nrf_cli_cdc_acm.c 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243
  1. /**
  2. * Copyright (c) 2017 - 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_CDC_ACM)
  42. #include "nrf_cli_cdc_acm.h"
  43. #include "nrf_queue.h"
  44. #include "app_error.h"
  45. #include "nrf_assert.h"
  46. #if APP_USBD_CONFIG_EVENT_QUEUE_ENABLE
  47. #error "Current CLI CDC implementation supports only USB with event queue disabled (see APP_USBD_CONFIG_EVENT_QUEUE_ENABLE)"
  48. #endif
  49. static void cdc_acm_user_ev_handler(app_usbd_class_inst_t const * p_inst,
  50. app_usbd_cdc_acm_user_event_t event);
  51. /*lint -save -e26 -e40 -e64 -e123 -e505 -e651*/
  52. /**
  53. * @brief CDC_ACM class instance.
  54. * */
  55. APP_USBD_CDC_ACM_GLOBAL_DEF(nrf_cli_cdc_acm,
  56. cdc_acm_user_ev_handler,
  57. NRF_CLI_CDC_ACM_COMM_INTERFACE,
  58. NRF_CLI_CDC_ACM_DATA_INTERFACE,
  59. NRF_CLI_CDC_ACM_COMM_EPIN,
  60. NRF_CLI_CDC_ACM_DATA_EPIN,
  61. NRF_CLI_CDC_ACM_DATA_EPOUT,
  62. APP_USBD_CDC_COMM_PROTOCOL_AT_V250
  63. );
  64. /*lint -restore*/
  65. NRF_QUEUE_DEF(uint8_t,
  66. m_rx_queue,
  67. 2*NRF_DRV_USBD_EPSIZE,
  68. NRF_QUEUE_MODE_OVERFLOW);
  69. static char m_rx_buffer[NRF_DRV_USBD_EPSIZE];
  70. static nrf_cli_cdc_acm_internal_t * mp_internal;
  71. /**
  72. * @brief Set new buffer and process any data if already present
  73. *
  74. * This is internal function.
  75. * The result of its execution is the library waiting for the event of the new data.
  76. * If there is already any data that was returned from the CDC internal buffer
  77. * it would be processed here.
  78. */
  79. static void cdc_acm_process_and_prepare_buffer(app_usbd_cdc_acm_t const * p_cdc_acm)
  80. {
  81. for (;;)
  82. {
  83. if (!nrf_queue_is_empty(&m_rx_queue))
  84. {
  85. mp_internal->p_cb->handler(NRF_CLI_TRANSPORT_EVT_RX_RDY, mp_internal->p_cb->p_context);
  86. }
  87. ret_code_t ret = app_usbd_cdc_acm_read_any(&nrf_cli_cdc_acm,
  88. m_rx_buffer,
  89. sizeof(m_rx_buffer));
  90. if (ret == NRF_SUCCESS)
  91. {
  92. size_t size = app_usbd_cdc_acm_rx_size(p_cdc_acm);
  93. size_t qsize = nrf_queue_in(&m_rx_queue, m_rx_buffer, size);
  94. ASSERT(size == qsize);
  95. UNUSED_VARIABLE(qsize);
  96. }
  97. else if (ret == NRF_ERROR_IO_PENDING)
  98. {
  99. break;
  100. }
  101. else
  102. {
  103. APP_ERROR_CHECK(ret);
  104. break;
  105. }
  106. }
  107. }
  108. /**
  109. * @brief User event handler.
  110. * */
  111. static void cdc_acm_user_ev_handler(app_usbd_class_inst_t const * p_inst,
  112. app_usbd_cdc_acm_user_event_t event)
  113. {
  114. app_usbd_cdc_acm_t const * p_cdc_acm = app_usbd_cdc_acm_class_get(p_inst);
  115. switch (event)
  116. {
  117. case APP_USBD_CDC_ACM_USER_EVT_PORT_OPEN:
  118. {
  119. /*Setup first transfer*/
  120. cdc_acm_process_and_prepare_buffer(p_cdc_acm);
  121. break;
  122. }
  123. case APP_USBD_CDC_ACM_USER_EVT_PORT_CLOSE:
  124. mp_internal->p_cb->handler(NRF_CLI_TRANSPORT_EVT_TX_RDY, mp_internal->p_cb->p_context);
  125. break;
  126. case APP_USBD_CDC_ACM_USER_EVT_TX_DONE:
  127. mp_internal->p_cb->handler(NRF_CLI_TRANSPORT_EVT_TX_RDY, mp_internal->p_cb->p_context);
  128. break;
  129. case APP_USBD_CDC_ACM_USER_EVT_RX_DONE:
  130. {
  131. /*Get amount of data transfered*/
  132. size_t size = app_usbd_cdc_acm_rx_size(p_cdc_acm);
  133. size_t qsize = nrf_queue_in(&m_rx_queue, m_rx_buffer, size);
  134. ASSERT(size == qsize);
  135. UNUSED_VARIABLE(qsize);
  136. /*Setup next transfer*/
  137. cdc_acm_process_and_prepare_buffer(p_cdc_acm);
  138. break;
  139. }
  140. default:
  141. break;
  142. }
  143. }
  144. static ret_code_t cli_cdc_acm_init(nrf_cli_transport_t const * p_transport,
  145. void const * p_config,
  146. nrf_cli_transport_handler_t evt_handler,
  147. void * p_context)
  148. {
  149. UNUSED_PARAMETER(p_config);
  150. nrf_cli_cdc_acm_internal_t * p_internal =
  151. CONTAINER_OF(p_transport, nrf_cli_cdc_acm_internal_t, transport);
  152. p_internal->p_cb->handler = evt_handler;
  153. p_internal->p_cb->p_context = p_context;
  154. mp_internal = p_internal;
  155. return NRF_SUCCESS;
  156. }
  157. static ret_code_t cli_cdc_acm_uninit(nrf_cli_transport_t const * p_transport)
  158. {
  159. UNUSED_PARAMETER(p_transport);
  160. return NRF_SUCCESS;
  161. }
  162. static ret_code_t cli_cdc_acm_enable(nrf_cli_transport_t const * p_transport,
  163. bool blocking)
  164. {
  165. UNUSED_PARAMETER(p_transport);
  166. if (blocking)
  167. {
  168. return NRF_ERROR_NOT_SUPPORTED;
  169. }
  170. else
  171. {
  172. return NRF_SUCCESS;
  173. }
  174. }
  175. static ret_code_t cli_cdc_acm_read(nrf_cli_transport_t const * p_transport,
  176. void * p_data,
  177. size_t length,
  178. size_t * p_cnt)
  179. {
  180. ASSERT(p_cnt);
  181. UNUSED_PARAMETER(p_transport);
  182. size_t size = nrf_queue_out(&m_rx_queue, p_data, length);
  183. *p_cnt = size;
  184. return NRF_SUCCESS;
  185. }
  186. static ret_code_t cli_cdc_acm_write(nrf_cli_transport_t const * p_transport,
  187. void const * p_data,
  188. size_t length,
  189. size_t * p_cnt)
  190. {
  191. ASSERT(p_cnt);
  192. UNUSED_PARAMETER(p_transport);
  193. ret_code_t ret;
  194. ret = app_usbd_cdc_acm_write(&nrf_cli_cdc_acm, p_data, length);
  195. if (ret == NRF_SUCCESS || ret == NRF_ERROR_INVALID_STATE)
  196. {
  197. *p_cnt = length;
  198. ret = NRF_SUCCESS;
  199. }
  200. else if (ret == NRF_ERROR_BUSY)
  201. {
  202. *p_cnt = 0;
  203. ret = NRF_SUCCESS;
  204. }
  205. else
  206. {
  207. /* Nothing to do */
  208. }
  209. return ret;
  210. }
  211. const nrf_cli_transport_api_t nrf_cli_cdc_acm_transport_api = {
  212. .init = cli_cdc_acm_init,
  213. .uninit = cli_cdc_acm_uninit,
  214. .enable = cli_cdc_acm_enable,
  215. .read = cli_cdc_acm_read,
  216. .write = cli_cdc_acm_write,
  217. };
  218. #endif // NRF_MODULE_ENABLED(NRF_CLI_CDC_ACM)