/* * Copyright (c) 2019 Actions Semiconductor Co., Ltd * * SPDX-License-Identifier: Apache-2.0 */ /** * @file * @brief OTA bluetooth SPP backend interface */ #include #include #include #include #include #include #include static struct spp_test_backend_t *g_test_backend; /* static void ttimer_handler(struct thread_timer *ttimer, void *expiry_fn_arg) { int count, ret; count = ring_buf_get(&g_test_backend->tx_ringbuf, g_test_backend->temp_buff, SPP_TX_RING_BUF_SIZE / 2); ret = stream_write(g_test_backend->sppble_stream, g_test_backend->temp_buff, count); if (count != ret) { SYS_LOG_ERR("SPP tx fail %d(%d)", ret, count); } thread_timer_start(ttimer, SPP_TRANSFER_TIMER_MS, 0); } */ void spp_test_backend_init(void *init_param) { g_test_backend->sppble_stream = sppble_stream_create(init_param); if (!g_test_backend->sppble_stream) { SYS_LOG_ERR("stream_create failed"); } } void spp_test_backend_exit(void) { SYS_LOG_DBG(""); if (g_test_backend->sppble_stream) { stream_destroy(g_test_backend->sppble_stream); } mem_free(g_test_backend); /* avoid connect again after exit */ g_test_backend = NULL; } int spp_test_backend_open(void) { int err = 0; SYS_LOG_DBG("open sppble_stream"); if (!g_test_backend->sppble_stream_opened) { err = stream_open(g_test_backend->sppble_stream, MODE_IN_OUT); if (err) { SYS_LOG_ERR("stream_open Failed"); } else { g_test_backend->sppble_stream_opened = 1; // g_test_backend->tx_buff = mem_malloc(SPP_TX_RING_BUF_SIZE); // g_test_backend->temp_buff = mem_malloc(SPP_TX_RING_BUF_SIZE / 2); // ring_buf_init(&g_test_backend->tx_ringbuf, SPP_TX_RING_BUF_SIZE, g_test_backend->tx_buff); // thread_timer_init(&g_test_backend->ttimer, ttimer_handler, NULL); // thread_timer_start(&g_test_backend->ttimer, SPP_TRANSFER_TIMER_MS, 0); } } return err; } int spp_test_backend_close(void) { int err = 0; SYS_LOG_DBG("close sppble_stream"); if (g_test_backend->sppble_stream_opened) { err = stream_close(g_test_backend->sppble_stream); if (err) { SYS_LOG_ERR("stream_close Failed"); } else { g_test_backend->sppble_stream_opened = 0; // thread_timer_stop(&g_test_backend->ttimer); // mem_free(g_test_backend->tx_buff); // mem_free(g_test_backend->temp_buff); } } return err; } int spp_test_backend_read(uint8_t *buf, uint32_t size, uint32_t timeout_ms) { int read_size, total_size = size; uint32_t prev_uptime, cur_uptime; uint8_t c; if (NULL == buf) { read_size = stream_tell(g_test_backend->sppble_stream); if (size > read_size) { size = read_size; } total_size = size; for (; 0 != size; size--) { stream_read(g_test_backend->sppble_stream, &c, 1); } } else { prev_uptime = k_uptime_get_32(); while (size > 0) { read_size = stream_read(g_test_backend->sppble_stream, buf, size); if (read_size > 0) { size -= read_size; buf += read_size; } cur_uptime = k_uptime_get_32(); if (cur_uptime - prev_uptime >= timeout_ms) break; os_sleep(1); } } if (size > 0) { read_size = total_size - size; SYS_LOG_DBG("need read %d bytes, but only got %d bytes", total_size, read_size); total_size = read_size; } return total_size; } int spp_test_backend_write(uint8_t *buf, uint32_t size, uint32_t timeout_ms) { int write_size, total_size = size; uint32_t prev_uptime, cur_uptime; prev_uptime = k_uptime_get_32(); while (size > 0) { write_size = stream_write(g_test_backend->sppble_stream, buf, size); if (write_size > 0) { size -= write_size; buf += write_size; } cur_uptime = k_uptime_get_32(); if (cur_uptime - prev_uptime >= timeout_ms) break; os_sleep(1); } if (size > 0) { write_size = total_size - size; SYS_LOG_ERR("write %d bytes, discard %d bytes", write_size, total_size - write_size); total_size = write_size; } return total_size; } int spp_test_backend_ioctl(int cmd, void *param0, void *param1) { return 0; } static void spp_test_connect_cb(int connected, uint8_t connect_type) { SYS_LOG_INF("connect: %d", connected); /* avoid connect again after exit */ if (g_test_backend) { if (g_test_backend->cb) { if (connected) { spp_test_backend_open(); } g_test_backend->cb(SPP_TEST_BACKEND_START_STATE, connected); if (!connected) { spp_test_backend_close(); } } } } bool spp_test_backend_load_bt_init(spp_test_notify_cb_t cb, struct ota_backend_bt_init_param *param) { struct sppble_stream_init_param init_param; if (!g_test_backend) { g_test_backend = mem_malloc(sizeof(struct spp_test_backend_t)); if (!g_test_backend) { SYS_LOG_ERR("malloc failed"); return false; } } memset(g_test_backend, 0x0, sizeof(struct spp_test_backend_t)); g_test_backend->type = OTA_BACKEND_TYPE_BLUETOOTH; g_test_backend->cb = cb; memset(&init_param, 0, sizeof(struct sppble_stream_init_param)); init_param.spp_uuid = (uint8_t *)param->spp_uuid; init_param.gatt_attr = param->gatt_attr; init_param.attr_size = param->attr_size; init_param.tx_chrc_attr = param->tx_chrc_attr; init_param.tx_attr = param->tx_attr; init_param.tx_ccc_attr = param->tx_ccc_attr; init_param.rx_attr = param->rx_attr; init_param.connect_cb = spp_test_connect_cb; init_param.read_timeout = param->read_timeout; /* K_FOREVER, K_NO_WAIT, K_MSEC(ms) */ init_param.write_timeout = param->write_timeout; /* Just call stream_create once, for register spp/ble service * not need call stream_destroy */ spp_test_backend_init(&init_param); return true; }