app_usbd_cdc_acm.c 42 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200
  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(APP_USBD_CDC_ACM)
  42. #include "app_usbd_cdc_acm.h"
  43. #include <inttypes.h>
  44. /**
  45. * @defgroup app_usbd_cdc_acm_internal CDC ACM internals
  46. * @{
  47. * @ingroup app_usbd_cdc
  48. * @internal
  49. */
  50. #define NRF_LOG_MODULE_NAME cdc_acm
  51. #if APP_USBD_CDC_ACM_CONFIG_LOG_ENABLED
  52. #define NRF_LOG_LEVEL APP_USBD_CDC_ACM_CONFIG_LOG_LEVEL
  53. #define NRF_LOG_INFO_COLOR APP_USBD_CDC_ACM_CONFIG_INFO_COLOR
  54. #define NRF_LOG_DEBUG_COLOR APP_USBD_CDC_ACM_CONFIG_DEBUG_COLOR
  55. #else //APP_USBD_CDC_ACM_CONFIG_LOG_ENABLED
  56. #define NRF_LOG_LEVEL 0
  57. #endif //APP_USBD_CDC_ACM_CONFIG_LOG_ENABLED
  58. #include "nrf_log.h"
  59. NRF_LOG_MODULE_REGISTER();
  60. #define APP_USBD_CDC_ACM_COMM_IFACE_IDX 0 /**< CDC ACM class comm interface index. */
  61. #define APP_USBD_CDC_ACM_DATA_IFACE_IDX 1 /**< CDC ACM class data interface index. */
  62. #define APP_USBD_CDC_ACM_COMM_EPIN_IDX 0 /**< CDC ACM comm class endpoint IN index. */
  63. #define APP_USBD_CDC_ACM_DATA_EPIN_IDX 0 /**< CDC ACM data class endpoint IN index. */
  64. #define APP_USBD_CDC_ACM_DATA_EPOUT_IDX 1 /**< CDC ACM data class endpoint OUT index. */
  65. /**
  66. * @brief Auxiliary function to access cdc_acm class instance data.
  67. *
  68. * @param[in] p_inst Class instance data.
  69. *
  70. * @return CDC ACM class instance.
  71. */
  72. static inline app_usbd_cdc_acm_t const * cdc_acm_get(app_usbd_class_inst_t const * p_inst)
  73. {
  74. ASSERT(p_inst != NULL);
  75. return (app_usbd_cdc_acm_t const *)p_inst;
  76. }
  77. /**
  78. * @brief Auxiliary function to access cdc_acm class context data.
  79. *
  80. * @param[in] p_cdc_acm CDC ACM class instance data.
  81. *
  82. * @return CDC ACM class instance context.
  83. */
  84. static inline app_usbd_cdc_acm_ctx_t * cdc_acm_ctx_get(app_usbd_cdc_acm_t const * p_cdc_acm)
  85. {
  86. ASSERT(p_cdc_acm != NULL);
  87. ASSERT(p_cdc_acm->specific.p_data != NULL);
  88. return &p_cdc_acm->specific.p_data->ctx;
  89. }
  90. /**
  91. * @brief User event handler.
  92. *
  93. * @param[in] p_inst Class instance.
  94. * @param[in] event user Event type.
  95. */
  96. static inline void user_event_handler(app_usbd_class_inst_t const * p_inst,
  97. app_usbd_cdc_acm_user_event_t event)
  98. {
  99. app_usbd_cdc_acm_t const * p_cdc_acm = cdc_acm_get(p_inst);
  100. if (p_cdc_acm->specific.inst.user_ev_handler != NULL)
  101. {
  102. p_cdc_acm->specific.inst.user_ev_handler(p_inst, event);
  103. }
  104. }
  105. /**
  106. * @brief Auxiliary function to access CDC ACM COMM IN endpoint address.
  107. *
  108. * @param[in] p_inst Class instance data.
  109. *
  110. * @return IN endpoint address.
  111. */
  112. static inline nrf_drv_usbd_ep_t comm_ep_in_addr_get(app_usbd_class_inst_t const * p_inst)
  113. {
  114. app_usbd_class_iface_conf_t const * class_iface;
  115. class_iface = app_usbd_class_iface_get(p_inst, APP_USBD_CDC_ACM_COMM_IFACE_IDX);
  116. app_usbd_class_ep_conf_t const * ep_cfg;
  117. ep_cfg = app_usbd_class_iface_ep_get(class_iface, APP_USBD_CDC_ACM_COMM_EPIN_IDX);
  118. return app_usbd_class_ep_address_get(ep_cfg);
  119. }
  120. /**
  121. * @brief Auxiliary function to access CDC ACM DATA IN endpoint address.
  122. *
  123. * @param[in] p_inst Class instance data.
  124. *
  125. * @return IN endpoint address.
  126. */
  127. static inline nrf_drv_usbd_ep_t data_ep_in_addr_get(app_usbd_class_inst_t const * p_inst)
  128. {
  129. app_usbd_class_iface_conf_t const * class_iface;
  130. class_iface = app_usbd_class_iface_get(p_inst, APP_USBD_CDC_ACM_DATA_IFACE_IDX);
  131. app_usbd_class_ep_conf_t const * ep_cfg;
  132. ep_cfg = app_usbd_class_iface_ep_get(class_iface, APP_USBD_CDC_ACM_DATA_EPIN_IDX);
  133. return app_usbd_class_ep_address_get(ep_cfg);
  134. }
  135. /**
  136. * @brief Auxiliary function to access CDC ACM DATA OUT endpoint address.
  137. *
  138. * @param[in] p_inst Class instance data.
  139. *
  140. * @return OUT endpoint address.
  141. */
  142. static inline nrf_drv_usbd_ep_t data_ep_out_addr_get(app_usbd_class_inst_t const * p_inst)
  143. {
  144. app_usbd_class_iface_conf_t const * class_iface;
  145. class_iface = app_usbd_class_iface_get(p_inst, APP_USBD_CDC_ACM_DATA_IFACE_IDX);
  146. app_usbd_class_ep_conf_t const * ep_cfg;
  147. ep_cfg = app_usbd_class_iface_ep_get(class_iface, APP_USBD_CDC_ACM_DATA_EPOUT_IDX);
  148. return app_usbd_class_ep_address_get(ep_cfg);
  149. }
  150. /**
  151. * @brief Internal SETUP standard IN request handler.
  152. *
  153. * @param[in] p_inst Generic class instance.
  154. * @param[in] p_setup_ev Setup event.
  155. *
  156. * @return Standard error code.
  157. */
  158. static ret_code_t setup_req_std_in(app_usbd_class_inst_t const * p_inst,
  159. app_usbd_setup_evt_t const * p_setup_ev)
  160. {
  161. /* Only Get Descriptor standard IN request is supported by CDC class */
  162. if ((app_usbd_setup_req_rec(p_setup_ev->setup.bmRequestType) == APP_USBD_SETUP_REQREC_INTERFACE)
  163. &&
  164. (p_setup_ev->setup.bRequest == APP_USBD_SETUP_STDREQ_GET_DESCRIPTOR))
  165. {
  166. size_t dsc_len = 0;
  167. size_t max_size;
  168. uint8_t * p_trans_buff = app_usbd_core_setup_transfer_buff_get(&max_size);
  169. /* Try to find descriptor in class internals*/
  170. ret_code_t ret = app_usbd_class_descriptor_find(
  171. p_inst,
  172. p_setup_ev->setup.wValue.hb,
  173. p_setup_ev->setup.wValue.lb,
  174. p_trans_buff,
  175. &dsc_len);
  176. if (ret != NRF_ERROR_NOT_FOUND)
  177. {
  178. ASSERT(dsc_len < NRF_DRV_USBD_EPSIZE);
  179. return app_usbd_core_setup_rsp(&(p_setup_ev->setup), p_trans_buff, dsc_len);
  180. }
  181. }
  182. return NRF_ERROR_NOT_SUPPORTED;
  183. }
  184. /**
  185. * @brief Internal SETUP standard OUT request handler.
  186. *
  187. * @param[in] p_inst Generic class instance.
  188. * @param[in] p_setup_ev Setup event.
  189. *
  190. * @return Standard error code.
  191. */
  192. static ret_code_t setup_req_std_out(app_usbd_class_inst_t const * p_inst,
  193. app_usbd_setup_evt_t const * p_setup_ev)
  194. {
  195. switch (p_setup_ev->setup.bRequest)
  196. {
  197. default:
  198. break;
  199. }
  200. return NRF_ERROR_NOT_SUPPORTED;
  201. }
  202. /**
  203. * @brief Internal SETUP class IN request handler.
  204. *
  205. * @param[in] p_inst Generic class instance.
  206. * @param[in] p_setup_ev Setup event.
  207. *
  208. * @return Standard error code.
  209. */
  210. static ret_code_t setup_req_class_in(app_usbd_class_inst_t const * p_inst,
  211. app_usbd_setup_evt_t const * p_setup_ev)
  212. {
  213. app_usbd_cdc_acm_t const * p_cdc_acm = cdc_acm_get(p_inst);
  214. app_usbd_cdc_acm_ctx_t * p_cdc_acm_ctx = cdc_acm_ctx_get(p_cdc_acm);
  215. switch (p_setup_ev->setup.bRequest)
  216. {
  217. case APP_USBD_CDC_REQ_GET_LINE_CODING:
  218. {
  219. if (p_setup_ev->setup.wLength.w != sizeof(app_usbd_cdc_line_coding_t))
  220. {
  221. return NRF_ERROR_NOT_SUPPORTED;
  222. }
  223. return app_usbd_core_setup_rsp(&p_setup_ev->setup,
  224. &p_cdc_acm_ctx->line_coding,
  225. sizeof(app_usbd_cdc_line_coding_t));
  226. }
  227. default:
  228. break;
  229. }
  230. return NRF_ERROR_NOT_SUPPORTED;
  231. }
  232. /**
  233. * @brief Class specific OUT request data callback.
  234. *
  235. * @param status Endpoint status.
  236. * @param p_context Context of transfer (set by @ref app_usbd_core_setup_data_handler_set).
  237. *
  238. * @return Standard error code.
  239. */
  240. static ret_code_t cdc_acm_req_out_data_cb(nrf_drv_usbd_ep_status_t status, void * p_context)
  241. {
  242. if (status != NRF_USBD_EP_OK)
  243. {
  244. return NRF_ERROR_INTERNAL;
  245. }
  246. app_usbd_cdc_acm_t const * p_cdc_acm = p_context;
  247. app_usbd_cdc_acm_ctx_t * p_cdc_acm_ctx = cdc_acm_ctx_get(p_cdc_acm);
  248. switch (p_cdc_acm_ctx->request.type)
  249. {
  250. case APP_USBD_CDC_REQ_SET_LINE_CODING:
  251. {
  252. memcpy(&p_cdc_acm_ctx->line_coding,
  253. &p_cdc_acm_ctx->request.payload.line_coding,
  254. sizeof(app_usbd_cdc_line_coding_t));
  255. NRF_LOG_INFO("REQ_SET_LINE_CODING: baudrate: %"PRIu32", databits: %u, "
  256. "format: %u, parity: %u",
  257. uint32_decode(p_cdc_acm_ctx->line_coding.dwDTERate),
  258. p_cdc_acm_ctx->line_coding.bDataBits,
  259. p_cdc_acm_ctx->line_coding.bCharFormat,
  260. p_cdc_acm_ctx->line_coding.bParityType);
  261. break;
  262. }
  263. default:
  264. return NRF_ERROR_NOT_SUPPORTED;
  265. }
  266. return NRF_SUCCESS;
  267. }
  268. /**
  269. * @brief Class specific request data stage setup.
  270. *
  271. * @param[in] p_inst Generic class instance.
  272. * @param[in] p_setup_ev Setup event.
  273. *
  274. * @return Standard error code.
  275. */
  276. static ret_code_t cdc_acm_req_out_datastage(app_usbd_class_inst_t const * p_inst,
  277. app_usbd_setup_evt_t const * p_setup_ev)
  278. {
  279. app_usbd_cdc_acm_t const * p_cdc_acm = cdc_acm_get(p_inst);
  280. app_usbd_cdc_acm_ctx_t * p_cdc_acm_ctx = cdc_acm_ctx_get(p_cdc_acm);
  281. p_cdc_acm_ctx->request.type = p_setup_ev->setup.bRequest;
  282. p_cdc_acm_ctx->request.len = p_setup_ev->setup.wLength.w;
  283. /*Request setup data*/
  284. NRF_DRV_USBD_TRANSFER_OUT(transfer,
  285. &p_cdc_acm_ctx->request.payload,
  286. p_cdc_acm_ctx->request.len);
  287. ret_code_t ret;
  288. CRITICAL_REGION_ENTER();
  289. ret = app_usbd_ep_transfer(NRF_DRV_USBD_EPOUT0, &transfer);
  290. if (ret == NRF_SUCCESS)
  291. {
  292. const app_usbd_core_setup_data_handler_desc_t desc = {
  293. .handler = cdc_acm_req_out_data_cb,
  294. .p_context = (void*)p_cdc_acm
  295. };
  296. ret = app_usbd_core_setup_data_handler_set(NRF_DRV_USBD_EPOUT0, &desc);
  297. }
  298. CRITICAL_REGION_EXIT();
  299. return ret;
  300. }
  301. /**
  302. * @brief Reset port to default state.
  303. *
  304. * @param p_inst Generic class instance.
  305. */
  306. static void cdc_acm_reset_port(app_usbd_class_inst_t const * p_inst)
  307. {
  308. app_usbd_cdc_acm_t const * p_cdc_acm = cdc_acm_get(p_inst);
  309. app_usbd_cdc_acm_ctx_t * p_cdc_acm_ctx = cdc_acm_ctx_get(p_cdc_acm);
  310. p_cdc_acm_ctx->line_state = 0;
  311. // Set rx transfers configuration to default state.
  312. p_cdc_acm_ctx->rx_transfer[0].p_buf = NULL;
  313. p_cdc_acm_ctx->rx_transfer[1].p_buf = NULL;
  314. p_cdc_acm_ctx->bytes_left = 0;
  315. p_cdc_acm_ctx->bytes_read = 0;
  316. p_cdc_acm_ctx->last_read = 0;
  317. p_cdc_acm_ctx->cur_read = 0;
  318. p_cdc_acm_ctx->p_copy_pos = p_cdc_acm_ctx->internal_rx_buf;
  319. }
  320. /**
  321. * @brief Internal SETUP class OUT request handler.
  322. *
  323. * @param[in] p_inst Generic class instance.
  324. * @param[in] p_setup_ev Setup event.
  325. *
  326. * @return Standard error code.
  327. */
  328. static ret_code_t setup_req_class_out(app_usbd_class_inst_t const * p_inst,
  329. app_usbd_setup_evt_t const * p_setup_ev)
  330. {
  331. app_usbd_cdc_acm_t const * p_cdc_acm = cdc_acm_get(p_inst);
  332. app_usbd_cdc_acm_ctx_t * p_cdc_acm_ctx = cdc_acm_ctx_get(p_cdc_acm);
  333. switch (p_setup_ev->setup.bRequest)
  334. {
  335. case APP_USBD_CDC_REQ_SET_LINE_CODING:
  336. {
  337. if (p_setup_ev->setup.wLength.w != sizeof(app_usbd_cdc_line_coding_t))
  338. {
  339. return NRF_ERROR_NOT_SUPPORTED;
  340. }
  341. return cdc_acm_req_out_datastage(p_inst, p_setup_ev);
  342. }
  343. case APP_USBD_CDC_REQ_SET_CONTROL_LINE_STATE:
  344. {
  345. if (p_setup_ev->setup.wLength.w != 0)
  346. {
  347. return NRF_ERROR_NOT_SUPPORTED;
  348. }
  349. NRF_LOG_INFO("REQ_SET_CONTROL_LINE_STATE: 0x%x", p_setup_ev->setup.wValue.w);
  350. bool old_dtr = (p_cdc_acm_ctx->line_state & APP_USBD_CDC_ACM_LINE_STATE_DTR) ?
  351. true : false;
  352. p_cdc_acm_ctx->line_state = p_setup_ev->setup.wValue.w;
  353. bool new_dtr = (p_cdc_acm_ctx->line_state & APP_USBD_CDC_ACM_LINE_STATE_DTR) ?
  354. true : false;
  355. if (old_dtr == new_dtr)
  356. {
  357. return NRF_SUCCESS;
  358. }
  359. const app_usbd_cdc_acm_user_event_t ev = new_dtr ?
  360. APP_USBD_CDC_ACM_USER_EVT_PORT_OPEN : APP_USBD_CDC_ACM_USER_EVT_PORT_CLOSE;
  361. user_event_handler(p_inst, ev);
  362. if (!new_dtr)
  363. {
  364. /*Abort DATA endpoints on port close */
  365. nrf_drv_usbd_ep_t ep;
  366. ep = data_ep_in_addr_get(p_inst);
  367. nrf_drv_usbd_ep_abort(ep);
  368. ep = data_ep_out_addr_get(p_inst);
  369. nrf_drv_usbd_ep_abort(ep);
  370. // Set rx transfers configuration to default state.
  371. p_cdc_acm_ctx->rx_transfer[0].p_buf = NULL;
  372. p_cdc_acm_ctx->rx_transfer[1].p_buf = NULL;
  373. p_cdc_acm_ctx->bytes_left = 0;
  374. p_cdc_acm_ctx->bytes_read = 0;
  375. p_cdc_acm_ctx->last_read = 0;
  376. p_cdc_acm_ctx->cur_read = 0;
  377. p_cdc_acm_ctx->p_copy_pos = p_cdc_acm_ctx->internal_rx_buf;
  378. }
  379. return NRF_SUCCESS;
  380. }
  381. default:
  382. break;
  383. }
  384. return NRF_ERROR_NOT_SUPPORTED;
  385. }
  386. /**
  387. * @brief Control endpoint handler.
  388. *
  389. * @param[in] p_inst Generic class instance.
  390. * @param[in] p_setup_ev Setup event.
  391. *
  392. * @return Standard error code.
  393. */
  394. static ret_code_t setup_event_handler(app_usbd_class_inst_t const * p_inst,
  395. app_usbd_setup_evt_t const * p_setup_ev)
  396. {
  397. ASSERT(p_inst != NULL);
  398. ASSERT(p_setup_ev != NULL);
  399. if (app_usbd_setup_req_dir(p_setup_ev->setup.bmRequestType) == APP_USBD_SETUP_REQDIR_IN)
  400. {
  401. switch (app_usbd_setup_req_typ(p_setup_ev->setup.bmRequestType))
  402. {
  403. case APP_USBD_SETUP_REQTYPE_STD:
  404. return setup_req_std_in(p_inst, p_setup_ev);
  405. case APP_USBD_SETUP_REQTYPE_CLASS:
  406. return setup_req_class_in(p_inst, p_setup_ev);
  407. default:
  408. break;
  409. }
  410. }
  411. else /*APP_USBD_SETUP_REQDIR_OUT*/
  412. {
  413. switch (app_usbd_setup_req_typ(p_setup_ev->setup.bmRequestType))
  414. {
  415. case APP_USBD_SETUP_REQTYPE_STD:
  416. return setup_req_std_out(p_inst, p_setup_ev);
  417. case APP_USBD_SETUP_REQTYPE_CLASS:
  418. return setup_req_class_out(p_inst, p_setup_ev);
  419. default:
  420. break;
  421. }
  422. }
  423. return NRF_ERROR_NOT_SUPPORTED;
  424. }
  425. /**
  426. * @brief CDC ACM consumer.
  427. *
  428. * @note See @ref nrf_drv_usbd_consumer_t
  429. */
  430. static bool cdc_acm_consumer(nrf_drv_usbd_ep_transfer_t * p_next,
  431. void * p_context,
  432. size_t ep_size,
  433. size_t data_size)
  434. {
  435. app_usbd_cdc_acm_ctx_t * p_cdc_acm_ctx = (app_usbd_cdc_acm_ctx_t *) p_context;
  436. p_next->size = data_size;
  437. if (data_size <= p_cdc_acm_ctx->rx_transfer[0].read_left)
  438. {
  439. p_next->p_data.rx = p_cdc_acm_ctx->rx_transfer[0].p_buf;
  440. p_cdc_acm_ctx->rx_transfer[0].p_buf += data_size;
  441. p_cdc_acm_ctx->bytes_read += data_size;
  442. p_cdc_acm_ctx->rx_transfer[0].read_left -= data_size;
  443. NRF_LOG_DEBUG("Received %d bytes. Space left in user buffer: %d bytes.",
  444. data_size,
  445. p_cdc_acm_ctx->rx_transfer[0].read_left);
  446. return (p_cdc_acm_ctx->rx_transfer[0].read_left) != 0;
  447. }
  448. else
  449. {
  450. p_next->p_data.rx = p_cdc_acm_ctx->internal_rx_buf;
  451. p_cdc_acm_ctx->cur_read = data_size;
  452. NRF_LOG_DEBUG("Received %d bytes. Stored in internal buffer.", data_size);
  453. return false;
  454. }
  455. }
  456. /**
  457. * @brief CDC ACM single transfer consumer.
  458. *
  459. * This function finalizes transfer after any received block.
  460. *
  461. * @note See @ref nrf_drv_usbd_consumer_t
  462. */
  463. static bool cdc_acm_single_shoot_consumer(nrf_drv_usbd_ep_transfer_t * p_next,
  464. void * p_context,
  465. size_t ep_size,
  466. size_t data_size)
  467. {
  468. app_usbd_cdc_acm_ctx_t * p_cdc_acm_ctx = (app_usbd_cdc_acm_ctx_t *) p_context;
  469. p_next->size = data_size;
  470. if (data_size <= p_cdc_acm_ctx->rx_transfer[0].read_left)
  471. {
  472. p_next->p_data.rx = p_cdc_acm_ctx->rx_transfer[0].p_buf;
  473. p_cdc_acm_ctx->bytes_read = data_size;
  474. p_cdc_acm_ctx->rx_transfer[0].read_left = data_size;
  475. NRF_LOG_DEBUG("Received %d bytes. Space left in user buffer: %d bytes.",
  476. data_size,
  477. p_cdc_acm_ctx->rx_transfer[0].read_left);
  478. }
  479. else
  480. {
  481. p_next->p_data.rx = p_cdc_acm_ctx->internal_rx_buf;
  482. p_cdc_acm_ctx->cur_read = data_size;
  483. NRF_LOG_DEBUG("Received %d bytes. Stored in internal buffer.", data_size);
  484. }
  485. return false;
  486. }
  487. /**
  488. * @brief Manage switching between user buffers and copying data from internal buffer.
  489. *
  490. * @param p_inst Generic USB class instance.
  491. *
  492. * @return Standard error code.
  493. */
  494. static ret_code_t cdc_acm_rx_block_finished(app_usbd_class_inst_t const * p_inst)
  495. {
  496. app_usbd_cdc_acm_t const * p_cdc_acm = cdc_acm_get(p_inst);
  497. app_usbd_cdc_acm_ctx_t * p_cdc_acm_ctx = cdc_acm_ctx_get(p_cdc_acm);
  498. nrf_drv_usbd_ep_t ep = data_ep_out_addr_get(p_inst);
  499. nrf_drv_usbd_handler_desc_t handler_desc = {
  500. .handler.consumer = cdc_acm_consumer,
  501. .p_context = p_cdc_acm_ctx
  502. };
  503. if (p_cdc_acm_ctx->rx_transfer[0].read_left == 0) // Buffer completely filled by consumer
  504. {
  505. p_cdc_acm_ctx->last_read = p_cdc_acm_ctx->bytes_read;
  506. p_cdc_acm_ctx->bytes_read = 0;
  507. p_cdc_acm_ctx->bytes_left = 0;
  508. if (p_cdc_acm_ctx->rx_transfer[1].p_buf != NULL)
  509. {
  510. p_cdc_acm_ctx->rx_transfer[0] = p_cdc_acm_ctx->rx_transfer[1];
  511. p_cdc_acm_ctx->rx_transfer[1].p_buf = NULL;
  512. return app_usbd_ep_handled_transfer(ep, &handler_desc);
  513. }
  514. else
  515. {
  516. p_cdc_acm_ctx->rx_transfer[0].p_buf = NULL;
  517. return NRF_SUCCESS;
  518. }
  519. }
  520. size_t bytes_read = p_cdc_acm_ctx->cur_read;
  521. size_t bytes_to_cpy = bytes_read;
  522. if (bytes_read > p_cdc_acm_ctx->rx_transfer[0].read_left)
  523. {
  524. bytes_to_cpy = p_cdc_acm_ctx->rx_transfer[0].read_left;
  525. }
  526. memcpy(p_cdc_acm_ctx->rx_transfer[0].p_buf,
  527. p_cdc_acm_ctx->internal_rx_buf,
  528. bytes_to_cpy);
  529. // First buffer is full
  530. p_cdc_acm_ctx->last_read = p_cdc_acm_ctx->bytes_read + bytes_to_cpy;
  531. p_cdc_acm_ctx->bytes_read = 0;
  532. p_cdc_acm_ctx->bytes_left = bytes_read - bytes_to_cpy;
  533. p_cdc_acm_ctx->p_copy_pos = p_cdc_acm_ctx->internal_rx_buf + bytes_to_cpy;
  534. if (p_cdc_acm_ctx->rx_transfer[1].p_buf != NULL)
  535. {
  536. // If there is second transfer, copy it to first
  537. p_cdc_acm_ctx->rx_transfer[0] = p_cdc_acm_ctx->rx_transfer[1];
  538. p_cdc_acm_ctx->rx_transfer[1].p_buf = NULL;
  539. while (p_cdc_acm_ctx->bytes_left > 0)
  540. {
  541. if (p_cdc_acm_ctx->bytes_left >= p_cdc_acm_ctx->rx_transfer[0].read_left)
  542. {
  543. // If there are enough bytes left in internal buffer to completely fill next transfer,
  544. // we call user event handler to obtain next buffer and continue double buffering.
  545. memcpy(p_cdc_acm_ctx->rx_transfer[0].p_buf,
  546. p_cdc_acm_ctx->p_copy_pos,
  547. p_cdc_acm_ctx->rx_transfer[0].read_left);
  548. p_cdc_acm_ctx->bytes_left -= p_cdc_acm_ctx->rx_transfer[0].read_left;
  549. p_cdc_acm_ctx->p_copy_pos += p_cdc_acm_ctx->rx_transfer[0].read_left;
  550. p_cdc_acm_ctx->last_read = p_cdc_acm_ctx->rx_transfer[0].read_left;
  551. user_event_handler(p_inst, APP_USBD_CDC_ACM_USER_EVT_RX_DONE);
  552. if (p_cdc_acm_ctx->rx_transfer[1].p_buf != NULL)
  553. {
  554. p_cdc_acm_ctx->rx_transfer[0] = p_cdc_acm_ctx->rx_transfer[1];
  555. p_cdc_acm_ctx->rx_transfer[1].p_buf = NULL;
  556. }
  557. else
  558. {
  559. // If user does not specify a second buffer, all data transfers are done
  560. // and data left in internal buffer is lost.
  561. p_cdc_acm_ctx->rx_transfer[0].p_buf = NULL;
  562. break;
  563. }
  564. }
  565. else
  566. {
  567. memcpy(p_cdc_acm_ctx->rx_transfer[0].p_buf,
  568. p_cdc_acm_ctx->p_copy_pos,
  569. p_cdc_acm_ctx->bytes_left);
  570. p_cdc_acm_ctx->bytes_read = p_cdc_acm_ctx->bytes_left;
  571. p_cdc_acm_ctx->rx_transfer[0].read_left -= p_cdc_acm_ctx->bytes_left;
  572. p_cdc_acm_ctx->rx_transfer[0].p_buf += p_cdc_acm_ctx->bytes_left;
  573. break;
  574. }
  575. }
  576. }
  577. else
  578. {
  579. p_cdc_acm_ctx->rx_transfer[0].p_buf = NULL;
  580. }
  581. if (p_cdc_acm_ctx->rx_transfer[0].p_buf != NULL)
  582. {
  583. return app_usbd_ep_handled_transfer(ep, &handler_desc);
  584. }
  585. return NRF_SUCCESS;
  586. }
  587. /**
  588. * @brief Class specific endpoint transfer handler.
  589. *
  590. * @param[in] p_inst Generic class instance.
  591. * @param[in] p_setup_ev Setup event.
  592. *
  593. * @return Standard error code.
  594. */
  595. static ret_code_t cdc_acm_endpoint_ev(app_usbd_class_inst_t const * p_inst,
  596. app_usbd_complex_evt_t const * p_event)
  597. {
  598. if (comm_ep_in_addr_get(p_inst) == p_event->drv_evt.data.eptransfer.ep)
  599. {
  600. NRF_LOG_INFO("EPIN_COMM: notify");
  601. return NRF_SUCCESS;
  602. }
  603. ret_code_t ret;
  604. if (NRF_USBD_EPIN_CHECK(p_event->drv_evt.data.eptransfer.ep))
  605. {
  606. switch (p_event->drv_evt.data.eptransfer.status)
  607. {
  608. case NRF_USBD_EP_OK:
  609. NRF_LOG_INFO("EPIN_DATA: %02x done", p_event->drv_evt.data.eptransfer.ep);
  610. user_event_handler(p_inst, APP_USBD_CDC_ACM_USER_EVT_TX_DONE);
  611. return NRF_SUCCESS;
  612. case NRF_USBD_EP_ABORTED:
  613. return NRF_SUCCESS;
  614. default:
  615. return NRF_ERROR_INTERNAL;
  616. }
  617. }
  618. if (NRF_USBD_EPOUT_CHECK(p_event->drv_evt.data.eptransfer.ep))
  619. {
  620. switch (p_event->drv_evt.data.eptransfer.status)
  621. {
  622. case NRF_USBD_EP_OK:
  623. ret = cdc_acm_rx_block_finished(p_inst);
  624. NRF_LOG_INFO("EPOUT_DATA: %02x done", p_event->drv_evt.data.eptransfer.ep);
  625. user_event_handler(p_inst, APP_USBD_CDC_ACM_USER_EVT_RX_DONE);
  626. return ret;
  627. case NRF_USBD_EP_WAITING:
  628. case NRF_USBD_EP_ABORTED:
  629. return NRF_SUCCESS;
  630. default:
  631. return NRF_ERROR_INTERNAL;
  632. }
  633. }
  634. return NRF_ERROR_NOT_SUPPORTED;
  635. }
  636. /**
  637. * @brief @ref app_usbd_class_methods_t::event_handler
  638. */
  639. static ret_code_t cdc_acm_event_handler(app_usbd_class_inst_t const * p_inst,
  640. app_usbd_complex_evt_t const * p_event)
  641. {
  642. ASSERT(p_inst != NULL);
  643. ASSERT(p_event != NULL);
  644. ret_code_t ret = NRF_SUCCESS;
  645. switch (p_event->app_evt.type)
  646. {
  647. case APP_USBD_EVT_DRV_SOF:
  648. break;
  649. case APP_USBD_EVT_DRV_RESET:
  650. cdc_acm_reset_port(p_inst);
  651. break;
  652. case APP_USBD_EVT_DRV_SETUP:
  653. ret = setup_event_handler(p_inst, (app_usbd_setup_evt_t const *)p_event);
  654. break;
  655. case APP_USBD_EVT_DRV_EPTRANSFER:
  656. ret = cdc_acm_endpoint_ev(p_inst, p_event);
  657. break;
  658. case APP_USBD_EVT_DRV_SUSPEND:
  659. break;
  660. case APP_USBD_EVT_DRV_RESUME:
  661. break;
  662. case APP_USBD_EVT_INST_APPEND:
  663. break;
  664. case APP_USBD_EVT_INST_REMOVE:
  665. break;
  666. case APP_USBD_EVT_STARTED:
  667. break;
  668. case APP_USBD_EVT_STOPPED:
  669. break;
  670. case APP_USBD_EVT_POWER_REMOVED:
  671. user_event_handler(p_inst, APP_USBD_CDC_ACM_USER_EVT_PORT_CLOSE);
  672. cdc_acm_reset_port(p_inst);
  673. break;
  674. default:
  675. ret = NRF_ERROR_NOT_SUPPORTED;
  676. break;
  677. }
  678. return ret;
  679. }
  680. static bool cdc_acm_feed_descriptors(app_usbd_class_descriptor_ctx_t * p_ctx,
  681. app_usbd_class_inst_t const * p_inst,
  682. uint8_t * p_buff,
  683. size_t max_size)
  684. {
  685. static uint8_t ifaces = 0;
  686. ifaces = app_usbd_class_iface_count_get(p_inst);
  687. app_usbd_cdc_acm_t const * p_cdc_acm = cdc_acm_get(p_inst);
  688. APP_USBD_CLASS_DESCRIPTOR_BEGIN(p_ctx, p_buff, max_size);
  689. /* INTERFACE ASSOCIATION DESCRIPTOR */
  690. APP_USBD_CLASS_DESCRIPTOR_WRITE(0x08); // bLength
  691. APP_USBD_CLASS_DESCRIPTOR_WRITE(APP_USBD_DESCRIPTOR_INTERFACE_ASSOCIATION); // bDescriptorType = Interface Association
  692. APP_USBD_CLASS_DESCRIPTOR_WRITE(p_cdc_acm->specific.inst.comm_interface); // bFirstInterface
  693. APP_USBD_CLASS_DESCRIPTOR_WRITE(0x02); // bInterfaceCount
  694. APP_USBD_CLASS_DESCRIPTOR_WRITE(APP_USBD_CDC_COMM_CLASS); // bFunctionClass
  695. APP_USBD_CLASS_DESCRIPTOR_WRITE(APP_USBD_CDC_SUBCLASS_ACM); // bFunctionSubClass
  696. APP_USBD_CLASS_DESCRIPTOR_WRITE(p_cdc_acm->specific.inst.protocol); // bFunctionProtocol
  697. APP_USBD_CLASS_DESCRIPTOR_WRITE(0x00); // iFunction
  698. static uint8_t i = 0;
  699. for (i = 0; i < ifaces; i++)
  700. {
  701. /* INTERFACE DESCRIPTOR */
  702. APP_USBD_CLASS_DESCRIPTOR_WRITE(0x09); // bLength
  703. APP_USBD_CLASS_DESCRIPTOR_WRITE(APP_USBD_DESCRIPTOR_INTERFACE); // bDescriptorType = Interface
  704. static app_usbd_class_iface_conf_t const * p_cur_iface = NULL;
  705. p_cur_iface = app_usbd_class_iface_get(p_inst, i);
  706. APP_USBD_CLASS_DESCRIPTOR_WRITE(app_usbd_class_iface_number_get(p_cur_iface)); // bInterfaceNumber
  707. APP_USBD_CLASS_DESCRIPTOR_WRITE(0x00); // bAlternateSetting
  708. APP_USBD_CLASS_DESCRIPTOR_WRITE(app_usbd_class_iface_ep_count_get(p_cur_iface)); // bNumEndpoints
  709. if (p_cdc_acm->specific.inst.comm_interface == app_usbd_class_iface_number_get(p_cur_iface))
  710. {
  711. APP_USBD_CLASS_DESCRIPTOR_WRITE(APP_USBD_CDC_COMM_CLASS); // bInterfaceClass = CDC COMM
  712. APP_USBD_CLASS_DESCRIPTOR_WRITE(APP_USBD_CDC_SUBCLASS_ACM); // bInterfaceSubclass
  713. APP_USBD_CLASS_DESCRIPTOR_WRITE(p_cdc_acm->specific.inst.protocol); // bInterfaceProtocol
  714. }
  715. else if (p_cdc_acm->specific.inst.data_interface ==
  716. app_usbd_class_iface_number_get(p_cur_iface))
  717. {
  718. APP_USBD_CLASS_DESCRIPTOR_WRITE(APP_USBD_CDC_DATA_CLASS); // bInterfaceClass = CDC DATA
  719. APP_USBD_CLASS_DESCRIPTOR_WRITE(0x00); // bInterfaceSubclass
  720. APP_USBD_CLASS_DESCRIPTOR_WRITE(0x00); // bInterfaceProtocol
  721. }
  722. else
  723. {
  724. ASSERT(0);
  725. }
  726. APP_USBD_CLASS_DESCRIPTOR_WRITE(0x00); // iInterface
  727. if (p_cdc_acm->specific.inst.comm_interface == app_usbd_class_iface_number_get(p_cur_iface))
  728. {
  729. /* HEADER DESCRIPTOR */
  730. APP_USBD_CLASS_DESCRIPTOR_WRITE(0x05); // bLength
  731. APP_USBD_CLASS_DESCRIPTOR_WRITE(APP_USBD_CDC_CS_INTERFACE); // bDescriptorType = Class Specific Interface
  732. APP_USBD_CLASS_DESCRIPTOR_WRITE(APP_USBD_CDC_SCS_HEADER); // bDescriptorSubtype = Header Functional Descriptor
  733. APP_USBD_CLASS_DESCRIPTOR_WRITE(0x10); // bcdCDC LSB
  734. APP_USBD_CLASS_DESCRIPTOR_WRITE(0x01); // bcdCDC MSB
  735. /* CALL MANAGEMENT DESCRIPTOR */
  736. APP_USBD_CLASS_DESCRIPTOR_WRITE(0x05); // bLength
  737. APP_USBD_CLASS_DESCRIPTOR_WRITE(APP_USBD_CDC_CS_INTERFACE); // bDescriptorType = Class Specific Interface
  738. APP_USBD_CLASS_DESCRIPTOR_WRITE(APP_USBD_CDC_SCS_CALL_MGMT); // bDescriptorSubtype = Call Management Functional Descriptor
  739. APP_USBD_CLASS_DESCRIPTOR_WRITE(0x03); // bmCapabilities
  740. APP_USBD_CLASS_DESCRIPTOR_WRITE(p_cdc_acm->specific.inst.data_interface); // bDataInterface
  741. /* ABSTRACT CONTROL MANAGEMENT DESCRIPTOR */
  742. APP_USBD_CLASS_DESCRIPTOR_WRITE(0x04); // bLength
  743. APP_USBD_CLASS_DESCRIPTOR_WRITE(APP_USBD_CDC_CS_INTERFACE); // bDescriptorType = Class Specific Interface
  744. APP_USBD_CLASS_DESCRIPTOR_WRITE(APP_USBD_CDC_SCS_ACM); // bDescriptorSubtype = Abstract Control Management Functional Descriptor
  745. APP_USBD_CLASS_DESCRIPTOR_WRITE(0x02); // bmCapabilities
  746. /* UNION DESCRIPTOR */
  747. APP_USBD_CLASS_DESCRIPTOR_WRITE(0x05);
  748. APP_USBD_CLASS_DESCRIPTOR_WRITE(APP_USBD_CDC_CS_INTERFACE); // bDescriptorType = Class Specific Interface
  749. APP_USBD_CLASS_DESCRIPTOR_WRITE(APP_USBD_CDC_SCS_UNION); // bDescriptorSubtype = Union Functional Descriptor
  750. APP_USBD_CLASS_DESCRIPTOR_WRITE(p_cdc_acm->specific.inst.comm_interface); // bControlInterface
  751. APP_USBD_CLASS_DESCRIPTOR_WRITE(p_cdc_acm->specific.inst.data_interface); // bSubordinateInterface
  752. }
  753. else if (p_cdc_acm->specific.inst.data_interface ==
  754. app_usbd_class_iface_number_get(p_cur_iface))
  755. {
  756. ;
  757. }
  758. else
  759. {
  760. ASSERT(0);
  761. }
  762. /* ENDPOINT DESCRIPTORS */
  763. static uint8_t endpoints = 0;
  764. endpoints = app_usbd_class_iface_ep_count_get(p_cur_iface);
  765. static uint8_t j = 0;
  766. for (j = 0; j < endpoints; j++)
  767. {
  768. APP_USBD_CLASS_DESCRIPTOR_WRITE(0x07); // bLength
  769. APP_USBD_CLASS_DESCRIPTOR_WRITE(APP_USBD_DESCRIPTOR_ENDPOINT); // bDescriptorType = Endpoint
  770. static app_usbd_class_ep_conf_t const * p_cur_ep = NULL;
  771. p_cur_ep = app_usbd_class_iface_ep_get(p_cur_iface, j);
  772. APP_USBD_CLASS_DESCRIPTOR_WRITE(app_usbd_class_ep_address_get(p_cur_ep)); // bEndpointAddress
  773. if (p_cdc_acm->specific.inst.comm_interface ==
  774. app_usbd_class_iface_number_get(p_cur_iface))
  775. {
  776. APP_USBD_CLASS_DESCRIPTOR_WRITE(APP_USBD_DESCRIPTOR_EP_ATTR_TYPE_INTERRUPT); // bmAttributes
  777. }
  778. else if (p_cdc_acm->specific.inst.data_interface ==
  779. app_usbd_class_iface_number_get(p_cur_iface))
  780. {
  781. APP_USBD_CLASS_DESCRIPTOR_WRITE(APP_USBD_DESCRIPTOR_EP_ATTR_TYPE_BULK); // bmAttributes
  782. }
  783. else
  784. {
  785. ASSERT(0);
  786. }
  787. APP_USBD_CLASS_DESCRIPTOR_WRITE(LSB_16(NRF_DRV_USBD_EPSIZE)); // wMaxPacketSize LSB
  788. APP_USBD_CLASS_DESCRIPTOR_WRITE(MSB_16(NRF_DRV_USBD_EPSIZE)); // wMaxPacketSize MSB
  789. if (p_cdc_acm->specific.inst.comm_interface ==
  790. app_usbd_class_iface_number_get(p_cur_iface))
  791. {
  792. APP_USBD_CLASS_DESCRIPTOR_WRITE(p_cdc_acm->specific.inst.p_ep_interval[0]); // bInterval
  793. }
  794. else if (p_cdc_acm->specific.inst.data_interface ==
  795. app_usbd_class_iface_number_get(p_cur_iface))
  796. {
  797. APP_USBD_CLASS_DESCRIPTOR_WRITE(0x00); // bInterval
  798. }
  799. else
  800. {
  801. ASSERT(0);
  802. }
  803. }
  804. }
  805. APP_USBD_CLASS_DESCRIPTOR_END();
  806. }
  807. /**
  808. * @brief Public cdc_acm class interface.
  809. *
  810. */
  811. const app_usbd_class_methods_t app_usbd_cdc_acm_class_methods = {
  812. .event_handler = cdc_acm_event_handler,
  813. .feed_descriptors = cdc_acm_feed_descriptors,
  814. };
  815. /** @} */
  816. ret_code_t app_usbd_cdc_acm_write(app_usbd_cdc_acm_t const * p_cdc_acm,
  817. const void * p_buf,
  818. size_t length)
  819. {
  820. app_usbd_class_inst_t const * p_inst = app_usbd_cdc_acm_class_inst_get(p_cdc_acm);
  821. app_usbd_cdc_acm_ctx_t * p_cdc_acm_ctx = cdc_acm_ctx_get(p_cdc_acm);
  822. bool dtr_state = (p_cdc_acm_ctx->line_state & APP_USBD_CDC_ACM_LINE_STATE_DTR) ?
  823. true : false;
  824. if (!dtr_state)
  825. {
  826. /*Port is not opened*/
  827. return NRF_ERROR_INVALID_STATE;
  828. }
  829. nrf_drv_usbd_ep_t ep = data_ep_in_addr_get(p_inst);
  830. if (APP_USBD_CDC_ACM_ZLP_ON_EPSIZE_WRITE && ((length % NRF_DRV_USBD_EPSIZE) == 0))
  831. {
  832. NRF_DRV_USBD_TRANSFER_IN_ZLP(transfer, p_buf, length);
  833. return app_usbd_ep_transfer(ep, &transfer);
  834. }
  835. else
  836. {
  837. NRF_DRV_USBD_TRANSFER_IN(transfer, p_buf, length);
  838. return app_usbd_ep_transfer(ep, &transfer);
  839. }
  840. }
  841. size_t app_usbd_cdc_acm_rx_size(app_usbd_cdc_acm_t const * p_cdc_acm)
  842. {
  843. app_usbd_cdc_acm_ctx_t * p_cdc_acm_ctx = cdc_acm_ctx_get(p_cdc_acm);
  844. return p_cdc_acm_ctx->last_read;
  845. }
  846. size_t app_usbd_cdc_acm_bytes_stored(app_usbd_cdc_acm_t const * p_cdc_acm)
  847. {
  848. app_usbd_cdc_acm_ctx_t * p_cdc_acm_ctx = cdc_acm_ctx_get(p_cdc_acm);
  849. return p_cdc_acm_ctx->bytes_left;
  850. }
  851. ret_code_t app_usbd_cdc_acm_read(app_usbd_cdc_acm_t const * p_cdc_acm,
  852. void * p_buf,
  853. size_t length)
  854. {
  855. ASSERT(p_buf != NULL);
  856. ret_code_t ret;
  857. app_usbd_cdc_acm_ctx_t * p_cdc_acm_ctx = cdc_acm_ctx_get(p_cdc_acm);
  858. if (0U == (p_cdc_acm_ctx->line_state & APP_USBD_CDC_ACM_LINE_STATE_DTR))
  859. {
  860. /*Port is not opened*/
  861. return NRF_ERROR_INVALID_STATE;
  862. }
  863. #if (APP_USBD_CONFIG_EVENT_QUEUE_ENABLE == 0)
  864. CRITICAL_REGION_ENTER();
  865. #endif // (APP_USBD_CONFIG_EVENT_QUEUE_ENABLE == 0)
  866. if (p_cdc_acm_ctx->rx_transfer[0].p_buf == NULL)
  867. {
  868. if (p_cdc_acm_ctx->bytes_left >= length)
  869. {
  870. memcpy(p_buf, p_cdc_acm_ctx->p_copy_pos, length);
  871. p_cdc_acm_ctx->bytes_left -= length;
  872. p_cdc_acm_ctx->p_copy_pos += length;
  873. p_cdc_acm_ctx->last_read = length;
  874. ret = NRF_SUCCESS;
  875. }
  876. else
  877. {
  878. p_cdc_acm_ctx->rx_transfer[0].p_buf = p_buf;
  879. p_cdc_acm_ctx->rx_transfer[0].read_left = length;
  880. nrf_drv_usbd_ep_t ep = data_ep_out_addr_get(app_usbd_cdc_acm_class_inst_get(p_cdc_acm));
  881. nrf_drv_usbd_handler_desc_t const handler_desc = {
  882. .handler.consumer = cdc_acm_consumer,
  883. .p_context = p_cdc_acm_ctx
  884. };
  885. if (p_cdc_acm_ctx->bytes_left > 0)
  886. {
  887. memcpy(p_cdc_acm_ctx->rx_transfer[0].p_buf,
  888. p_cdc_acm_ctx->p_copy_pos,
  889. p_cdc_acm_ctx->bytes_left);
  890. p_cdc_acm_ctx->rx_transfer[0].read_left -= p_cdc_acm_ctx->bytes_left;
  891. p_cdc_acm_ctx->rx_transfer[0].p_buf += p_cdc_acm_ctx->bytes_left;
  892. p_cdc_acm_ctx->bytes_read = p_cdc_acm_ctx->bytes_left;
  893. p_cdc_acm_ctx->bytes_left = 0;
  894. }
  895. ret = app_usbd_ep_handled_transfer(ep, &handler_desc);
  896. if (ret == NRF_SUCCESS)
  897. {
  898. ret = NRF_ERROR_IO_PENDING;
  899. }
  900. }
  901. }
  902. else if (p_cdc_acm_ctx->rx_transfer[1].p_buf == NULL)
  903. {
  904. p_cdc_acm_ctx->rx_transfer[1].p_buf = p_buf;
  905. p_cdc_acm_ctx->rx_transfer[1].read_left = length;
  906. ret = NRF_ERROR_IO_PENDING;
  907. }
  908. else
  909. {
  910. ret = NRF_ERROR_BUSY;
  911. }
  912. #if (APP_USBD_CONFIG_EVENT_QUEUE_ENABLE == 0)
  913. CRITICAL_REGION_EXIT();
  914. #endif // (APP_USBD_CONFIG_EVENT_QUEUE_ENABLE == 0)
  915. return ret;
  916. }
  917. ret_code_t app_usbd_cdc_acm_read_any(app_usbd_cdc_acm_t const * p_cdc_acm,
  918. void * p_buf,
  919. size_t length)
  920. {
  921. ASSERT(p_buf != NULL);
  922. ret_code_t ret;
  923. app_usbd_cdc_acm_ctx_t * p_cdc_acm_ctx = cdc_acm_ctx_get(p_cdc_acm);
  924. if (0U == (p_cdc_acm_ctx->line_state & APP_USBD_CDC_ACM_LINE_STATE_DTR))
  925. {
  926. /*Port is not opened*/
  927. return NRF_ERROR_INVALID_STATE;
  928. }
  929. #if (APP_USBD_CONFIG_EVENT_QUEUE_ENABLE == 0)
  930. CRITICAL_REGION_ENTER();
  931. #endif // (APP_USBD_CONFIG_EVENT_QUEUE_ENABLE == 0)
  932. if (p_cdc_acm_ctx->bytes_left > 0)
  933. {
  934. size_t to_copy = MIN(length, p_cdc_acm_ctx->bytes_left);
  935. memcpy(p_buf, p_cdc_acm_ctx->p_copy_pos, to_copy);
  936. p_cdc_acm_ctx->bytes_left -= to_copy;
  937. p_cdc_acm_ctx->p_copy_pos += to_copy;
  938. p_cdc_acm_ctx->last_read = to_copy;
  939. ret = NRF_SUCCESS;
  940. }
  941. else
  942. {
  943. if (p_cdc_acm_ctx->rx_transfer[0].p_buf == NULL)
  944. {
  945. p_cdc_acm_ctx->rx_transfer[0].p_buf = p_buf;
  946. p_cdc_acm_ctx->rx_transfer[0].read_left = length;
  947. nrf_drv_usbd_ep_t ep = data_ep_out_addr_get(app_usbd_cdc_acm_class_inst_get(p_cdc_acm));
  948. nrf_drv_usbd_handler_desc_t const handler_desc = {
  949. .handler.consumer = cdc_acm_single_shoot_consumer,
  950. .p_context = p_cdc_acm_ctx
  951. };
  952. ret = app_usbd_ep_handled_transfer(ep, &handler_desc);
  953. if (ret == NRF_SUCCESS)
  954. {
  955. ret = NRF_ERROR_IO_PENDING;
  956. }
  957. }
  958. else
  959. {
  960. ret = NRF_ERROR_BUSY;
  961. }
  962. }
  963. #if (APP_USBD_CONFIG_EVENT_QUEUE_ENABLE == 0)
  964. CRITICAL_REGION_EXIT();
  965. #endif // (APP_USBD_CONFIG_EVENT_QUEUE_ENABLE == 0)
  966. return ret;
  967. }
  968. static ret_code_t cdc_acm_serial_state_notify(app_usbd_cdc_acm_t const * p_cdc_acm)
  969. {
  970. app_usbd_class_inst_t const * p_inst = app_usbd_cdc_acm_class_inst_get(p_cdc_acm);
  971. app_usbd_cdc_acm_ctx_t * p_cdc_acm_ctx = cdc_acm_ctx_get(p_cdc_acm);
  972. nrf_drv_usbd_ep_t ep = comm_ep_in_addr_get(p_inst);
  973. NRF_DRV_USBD_TRANSFER_OUT(transfer,
  974. &p_cdc_acm_ctx->request.payload,
  975. sizeof(app_usbd_cdc_acm_notify_t));
  976. return app_usbd_ep_transfer(ep, &transfer);
  977. }
  978. ret_code_t app_usbd_cdc_acm_serial_state_notify(app_usbd_cdc_acm_t const * p_cdc_acm,
  979. app_usbd_cdc_acm_serial_state_t serial_state,
  980. bool value)
  981. {
  982. app_usbd_cdc_acm_ctx_t * p_cdc_acm_ctx = cdc_acm_ctx_get(p_cdc_acm);
  983. ret_code_t ret;
  984. CRITICAL_REGION_ENTER();
  985. ret = NRF_SUCCESS;
  986. switch (serial_state)
  987. {
  988. case APP_USBD_CDC_ACM_SERIAL_STATE_DCD:
  989. case APP_USBD_CDC_ACM_SERIAL_STATE_DSR:
  990. case APP_USBD_CDC_ACM_SERIAL_STATE_BREAK:
  991. case APP_USBD_CDC_ACM_SERIAL_STATE_RING:
  992. case APP_USBD_CDC_ACM_SERIAL_STATE_FRAMING:
  993. case APP_USBD_CDC_ACM_SERIAL_STATE_PARITY:
  994. case APP_USBD_CDC_ACM_SERIAL_STATE_OVERRUN:
  995. if (value)
  996. {
  997. p_cdc_acm_ctx->serial_state |= serial_state;
  998. }
  999. else
  1000. {
  1001. p_cdc_acm_ctx->serial_state &= ~serial_state;
  1002. }
  1003. break;
  1004. default:
  1005. ret = NRF_ERROR_NOT_SUPPORTED;
  1006. break;
  1007. }
  1008. if (ret == NRF_SUCCESS)
  1009. {
  1010. app_usbd_cdc_acm_notify_t * notify = &p_cdc_acm_ctx->request.payload.notify;
  1011. notify->cdc_notify.bmRequestType = app_usbd_setup_req_val(APP_USBD_SETUP_REQREC_INTERFACE,
  1012. APP_USBD_SETUP_REQTYPE_CLASS,
  1013. APP_USBD_SETUP_REQDIR_IN);
  1014. notify->cdc_notify.bRequest = APP_USBD_CDC_NOTIF_SERIAL_STATE;
  1015. notify->cdc_notify.wValue = 0;
  1016. notify->cdc_notify.wIndex = 0;
  1017. notify->cdc_notify.wLength = sizeof(notify->serial_state);
  1018. notify->serial_state = p_cdc_acm_ctx->serial_state;
  1019. ret = cdc_acm_serial_state_notify(p_cdc_acm);
  1020. }
  1021. CRITICAL_REGION_EXIT();
  1022. return ret;
  1023. }
  1024. ret_code_t app_usbd_cdc_acm_line_state_get(app_usbd_cdc_acm_t const * p_cdc_acm,
  1025. app_usbd_cdc_acm_line_state_t line_state,
  1026. uint32_t * value)
  1027. {
  1028. app_usbd_cdc_acm_ctx_t * p_cdc_acm_ctx = cdc_acm_ctx_get(p_cdc_acm);
  1029. ret_code_t ret;
  1030. CRITICAL_REGION_ENTER();
  1031. ret = NRF_SUCCESS;
  1032. switch (line_state)
  1033. {
  1034. case APP_USBD_CDC_ACM_LINE_STATE_DTR:
  1035. case APP_USBD_CDC_ACM_LINE_STATE_RTS:
  1036. *value = (p_cdc_acm_ctx->line_state & line_state) != 0;
  1037. break;
  1038. default:
  1039. ret = NRF_ERROR_NOT_SUPPORTED;
  1040. break;
  1041. }
  1042. CRITICAL_REGION_EXIT();
  1043. return ret;
  1044. }
  1045. #endif //NRF_MODULE_ENABLED(APP_USBD_CDC_ACM)