nrf_cli_ble_uart.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317
  1. /**
  2. * Copyright (c) 2016 - 2020, Nordic Semiconductor ASA
  3. *
  4. * All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without modification,
  7. * are permitted provided that the following conditions are met:
  8. *
  9. * 1. Redistributions of source code must retain the above copyright notice, this
  10. * list of conditions and the following disclaimer.
  11. *
  12. * 2. Redistributions in binary form, except as embedded into a Nordic
  13. * Semiconductor ASA integrated circuit in a product or a software update for
  14. * such product, must reproduce the above copyright notice, this list of
  15. * conditions and the following disclaimer in the documentation and/or other
  16. * materials provided with the distribution.
  17. *
  18. * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
  19. * contributors may be used to endorse or promote products derived from this
  20. * software without specific prior written permission.
  21. *
  22. * 4. This software, with or without modification, must only be used with a
  23. * Nordic Semiconductor ASA integrated circuit.
  24. *
  25. * 5. Any software provided in binary form under this license must not be reverse
  26. * engineered, decompiled, modified and/or disassembled.
  27. *
  28. * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
  29. * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  30. * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
  31. * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
  32. * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  33. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
  34. * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  35. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  36. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  37. * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  38. *
  39. */
  40. #include "sdk_common.h"
  41. #if NRF_MODULE_ENABLED(NRF_CLI_BLE_UART)
  42. #include "nrf_cli_ble_uart.h"
  43. #include "ble_nus.h"
  44. #include "nrf_ringbuf.h"
  45. #include "app_timer.h"
  46. #include "nrf_assert.h"
  47. #include "nrf_ble_gatt.h"
  48. #define NRF_LOG_MODULE_NAME cli_ble
  49. #if NRF_CLI_BLE_UART_CONFIG_LOG_ENABLED
  50. #define NRF_LOG_LEVEL NRF_CLI_BLE_UART_CONFIG_LOG_LEVEL
  51. #define NRF_LOG_INFO_COLOR NRF_CLI_BLE_UART_CONFIG_INFO_COLOR
  52. #define NRF_LOG_DEBUG_COLOR NRF_CLI_BLE_UART_CONFIG_DEBUG_COLOR
  53. #else //NRF_CLI_BLE_UART_CONFIG_LOG_ENABLED
  54. #define NRF_LOG_LEVEL 0
  55. #endif //NRF_CLI_BLE_UART_CONFIG_LOG_ENABLED
  56. #include "nrf_log.h"
  57. NRF_LOG_MODULE_REGISTER();
  58. #if NRF_CLI_BLE_UART_MAX_CLIENTS > NRF_SDH_BLE_TOTAL_LINK_COUNT
  59. #error "Too few BLE peripheral links are supported by the BLE SDH module for the maximal number \
  60. of BLE transport instances"
  61. #endif
  62. #define NRF_CLI_BLE_UART_TIMEOUT_MS 50
  63. #define OVERHEAD_LENGTH (OPCODE_LENGTH + HANDLE_LENGTH)
  64. BLE_NUS_DEF(m_nus, NRF_CLI_BLE_UART_MAX_CLIENTS);
  65. BLE_LINK_CTX_MANAGER_DEF(m_link_ctx_storage,
  66. NRF_CLI_BLE_UART_MAX_CLIENTS,
  67. sizeof(nrf_cli_ble_uart_internal_t *));
  68. static void tx_try(nrf_cli_ble_uart_internal_t * p_instance, uint32_t threshold)
  69. {
  70. uint8_t * p_out_data;
  71. size_t out_data_len =
  72. nrf_ble_gatt_eff_mtu_get(p_instance->p_gatt, p_instance->p_cb->conn_handle) -
  73. OVERHEAD_LENGTH;
  74. ret_code_t err_code = nrf_ringbuf_get(p_instance->p_tx_ringbuf,
  75. &p_out_data,
  76. &out_data_len,
  77. true);
  78. if (err_code == NRF_SUCCESS)
  79. {
  80. if (out_data_len >= threshold)
  81. {
  82. size_t req_data_len = out_data_len;
  83. err_code = ble_nus_data_send(&m_nus,
  84. p_out_data,
  85. (uint16_t*)&out_data_len,
  86. p_instance->p_cb->conn_handle);
  87. if ((err_code == NRF_ERROR_BUSY) || (err_code == NRF_ERROR_RESOURCES))
  88. {
  89. out_data_len = 0;
  90. }
  91. NRF_LOG_INFO("Conn_handle:%d TX req_len: %d, len: %d",
  92. p_instance->p_cb->conn_handle, req_data_len, out_data_len);
  93. NRF_LOG_HEXDUMP_DEBUG(p_out_data, out_data_len);
  94. err_code = nrf_ringbuf_free(p_instance->p_tx_ringbuf, out_data_len);
  95. ASSERT(err_code == NRF_SUCCESS);
  96. }
  97. else
  98. {
  99. err_code = nrf_ringbuf_free(p_instance->p_tx_ringbuf, 0);
  100. ASSERT(err_code == NRF_SUCCESS);
  101. }
  102. }
  103. }
  104. static void nus_data_handler(ble_nus_evt_t * p_nus_evt)
  105. {
  106. ret_code_t err_code = NRF_SUCCESS;
  107. nrf_cli_ble_uart_internal_t * p_instance;
  108. nrf_cli_ble_uart_internal_t ** pp_instance;
  109. err_code = blcm_link_ctx_get(&m_link_ctx_storage, p_nus_evt->conn_handle, (void *) &pp_instance);
  110. ASSERT(err_code == NRF_SUCCESS);
  111. p_instance = *pp_instance;
  112. switch (p_nus_evt->type)
  113. {
  114. case BLE_NUS_EVT_RX_DATA:
  115. {
  116. NRF_LOG_INFO("Conn_handle:%d, Received: %d",
  117. p_instance->p_cb->conn_handle, p_nus_evt->params.rx_data.length);
  118. NRF_LOG_HEXDUMP_DEBUG(p_nus_evt->params.rx_data.p_data, p_nus_evt->params.rx_data.length);
  119. size_t len = ((size_t) p_nus_evt->params.rx_data.length) & 0x0000FFFF;
  120. err_code = nrf_ringbuf_cpy_put(p_instance->p_rx_ringbuf,
  121. p_nus_evt->params.rx_data.p_data,
  122. (size_t *)&len);
  123. ASSERT(err_code == NRF_SUCCESS);
  124. p_instance->p_cb->handler(NRF_CLI_TRANSPORT_EVT_RX_RDY, p_instance->p_cb->p_context);
  125. break;
  126. }
  127. case BLE_NUS_EVT_TX_RDY:
  128. {
  129. //TX_Complete
  130. uint32_t max_tx_len = nrf_ble_gatt_eff_mtu_get(p_instance->p_gatt,
  131. p_instance->p_cb->conn_handle) -
  132. OVERHEAD_LENGTH;
  133. tx_try(p_instance, max_tx_len);
  134. p_instance->p_cb->handler(NRF_CLI_TRANSPORT_EVT_TX_RDY, p_instance->p_cb->p_context);
  135. break;
  136. }
  137. case BLE_NUS_EVT_COMM_STARTED:
  138. p_instance->p_cb->service_started = true;
  139. err_code = app_timer_start(*p_instance->p_timer,
  140. APP_TIMER_TICKS(NRF_CLI_BLE_UART_TIMEOUT_MS),
  141. p_instance);
  142. ASSERT(err_code == NRF_SUCCESS);
  143. NRF_LOG_INFO("Conn_handle:%d, communication started", p_instance->p_cb->conn_handle);
  144. break;
  145. case BLE_NUS_EVT_COMM_STOPPED:
  146. (void)app_timer_stop(*p_instance->p_timer);
  147. p_instance->p_cb->service_started = false;
  148. NRF_LOG_INFO("Conn_handle:%d, communication stopped", p_instance->p_cb->conn_handle);
  149. break;
  150. default:
  151. break;
  152. }
  153. }
  154. static void timer_handler(void * p_context)
  155. {
  156. nrf_cli_ble_uart_internal_t * p_instance = (nrf_cli_ble_uart_internal_t *) p_context;
  157. tx_try(p_instance, 1);
  158. ret_code_t err_code = app_timer_start(*p_instance->p_timer,
  159. APP_TIMER_TICKS(NRF_CLI_BLE_UART_TIMEOUT_MS), (void *)p_instance);
  160. ASSERT(err_code == NRF_SUCCESS);
  161. UNUSED_VARIABLE(err_code);
  162. UNUSED_PARAMETER(p_context);
  163. }
  164. ret_code_t nrf_cli_ble_uart_service_init(void)
  165. {
  166. ble_nus_init_t nus_init;
  167. memset(&nus_init, 0, sizeof(nus_init));
  168. nus_init.data_handler = nus_data_handler;
  169. return ble_nus_init(&m_nus, &nus_init);
  170. }
  171. static ret_code_t cli_ble_uart_init(nrf_cli_transport_t const * p_transport,
  172. void const * p_config,
  173. nrf_cli_transport_handler_t evt_handler,
  174. void * p_context)
  175. {
  176. ret_code_t err_code;
  177. nrf_cli_ble_uart_internal_t ** pp_instance;
  178. nrf_cli_ble_uart_internal_t * p_instance =
  179. CONTAINER_OF(p_transport, nrf_cli_ble_uart_internal_t, transport);
  180. nrf_cli_ble_uart_config_t * p_ble_uart_config = (nrf_cli_ble_uart_config_t *)p_config;
  181. p_instance->p_cb->handler = evt_handler;
  182. p_instance->p_cb->p_context = p_context;
  183. p_instance->p_cb->service_started = false;
  184. p_instance->p_cb->conn_handle = p_ble_uart_config->conn_handle;
  185. NRF_LOG_INFO("Conn_handle:%d init.", p_ble_uart_config->conn_handle);
  186. nrf_ringbuf_init(p_instance->p_rx_ringbuf);
  187. nrf_ringbuf_init(p_instance->p_tx_ringbuf);
  188. err_code = blcm_link_ctx_get(&m_link_ctx_storage,
  189. p_ble_uart_config->conn_handle,
  190. (void *) &pp_instance);
  191. VERIFY_SUCCESS(err_code);
  192. *pp_instance = p_instance;
  193. return NRF_SUCCESS;
  194. }
  195. static ret_code_t cli_ble_uart_uninit(nrf_cli_transport_t const * p_transport)
  196. {
  197. nrf_cli_ble_uart_internal_t * p_instance =
  198. CONTAINER_OF(p_transport, nrf_cli_ble_uart_internal_t, transport);
  199. NRF_LOG_INFO("Conn_handle:%d uninit.", p_instance->p_cb->conn_handle);
  200. ret_code_t ret = app_timer_stop(*p_instance->p_timer);
  201. return ret;
  202. }
  203. static ret_code_t cli_ble_uart_enable(nrf_cli_transport_t const * p_transport, bool blocking)
  204. {
  205. nrf_cli_ble_uart_internal_t * p_instance =
  206. CONTAINER_OF(p_transport, nrf_cli_ble_uart_internal_t, transport);
  207. NRF_LOG_INFO("Conn_handle:%d, enable blocking:%d", blocking, p_instance->p_cb->conn_handle);
  208. if (blocking)
  209. {
  210. return NRF_ERROR_NOT_SUPPORTED;
  211. }
  212. else
  213. {
  214. ret_code_t err_code = NRF_SUCCESS;
  215. if (!p_instance->p_cb->timer_created)
  216. {
  217. err_code = app_timer_create(p_instance->p_timer,
  218. APP_TIMER_MODE_SINGLE_SHOT,
  219. timer_handler);
  220. p_instance->p_cb->timer_created = true;
  221. }
  222. return err_code;
  223. }
  224. }
  225. static ret_code_t cli_ble_uart_read(nrf_cli_transport_t const * p_transport,
  226. void * p_data,
  227. size_t length,
  228. size_t * p_cnt)
  229. {
  230. ASSERT(p_cnt);
  231. nrf_cli_ble_uart_internal_t * p_instance =
  232. CONTAINER_OF(p_transport, nrf_cli_ble_uart_internal_t, transport);
  233. *p_cnt = length;
  234. ret_code_t err_code = nrf_ringbuf_cpy_get(p_instance->p_rx_ringbuf, p_data, p_cnt);
  235. if (*p_cnt)
  236. {
  237. NRF_LOG_INFO("Conn_handle:%d, read req_len:%d read_len: %d",
  238. p_instance->p_cb->conn_handle,
  239. length,
  240. *p_cnt);
  241. NRF_LOG_HEXDUMP_DEBUG(p_data, *p_cnt);
  242. }
  243. return err_code;
  244. }
  245. static ret_code_t cli_ble_uart_write(nrf_cli_transport_t const * p_transport,
  246. const void * p_data,
  247. size_t length,
  248. size_t * p_cnt)
  249. {
  250. ASSERT(p_cnt);
  251. nrf_cli_ble_uart_internal_t * p_instance =
  252. CONTAINER_OF(p_transport, nrf_cli_ble_uart_internal_t, transport);
  253. ret_code_t err_code = NRF_SUCCESS;
  254. if (p_instance->p_cb->service_started)
  255. {
  256. *p_cnt = length;
  257. err_code = nrf_ringbuf_cpy_put(p_instance->p_tx_ringbuf, p_data, p_cnt);
  258. NRF_LOG_INFO("Conn_handle:%d, write req:%d, buffered:%d",
  259. p_instance->p_cb->conn_handle, length, *p_cnt);
  260. NRF_LOG_HEXDUMP_DEBUG(p_data, *p_cnt);
  261. }
  262. else
  263. {
  264. NRF_LOG_INFO("Conn_handle:%d, write req:%d. Notifications not enabled",
  265. p_instance->p_cb->conn_handle, length);
  266. *p_cnt = length;
  267. p_instance->p_cb->handler(NRF_CLI_TRANSPORT_EVT_TX_RDY, p_instance->p_cb->p_context);
  268. }
  269. return err_code;
  270. }
  271. const nrf_cli_transport_api_t nrf_cli_ble_uart_transport_api = {
  272. .init = cli_ble_uart_init,
  273. .uninit = cli_ble_uart_uninit,
  274. .enable = cli_ble_uart_enable,
  275. .read = cli_ble_uart_read,
  276. .write = cli_ble_uart_write,
  277. };
  278. #endif //NRF_MODULE_ENABLED(NRF_CLI_BLE_UART)