cdc_device.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484
  1. /*
  2. * The MIT License (MIT)
  3. *
  4. * Copyright (c) 2019 Ha Thach (tinyusb.org)
  5. *
  6. * Permission is hereby granted, free of charge, to any person obtaining a copy
  7. * of this software and associated documentation files (the "Software"), to deal
  8. * in the Software without restriction, including without limitation the rights
  9. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  10. * copies of the Software, and to permit persons to whom the Software is
  11. * furnished to do so, subject to the following conditions:
  12. *
  13. * The above copyright notice and this permission notice shall be included in
  14. * all copies or substantial portions of the Software.
  15. *
  16. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  19. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  21. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  22. * THE SOFTWARE.
  23. *
  24. * This file is part of the TinyUSB stack.
  25. */
  26. #include "tusb_option.h"
  27. #if (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_CDC)
  28. #include "cdc_device.h"
  29. #include "device/usbd_pvt.h"
  30. //--------------------------------------------------------------------+
  31. // MACRO CONSTANT TYPEDEF
  32. //--------------------------------------------------------------------+
  33. enum
  34. {
  35. BULK_PACKET_SIZE = (TUD_OPT_HIGH_SPEED ? 512 : 64)
  36. };
  37. typedef struct
  38. {
  39. uint8_t itf_num;
  40. uint8_t ep_notif;
  41. uint8_t ep_in;
  42. uint8_t ep_out;
  43. // Bit 0: DTR (Data Terminal Ready), Bit 1: RTS (Request to Send)
  44. uint8_t line_state;
  45. /*------------- From this point, data is not cleared by bus reset -------------*/
  46. char wanted_char;
  47. cdc_line_coding_t line_coding;
  48. // FIFO
  49. tu_fifo_t rx_ff;
  50. tu_fifo_t tx_ff;
  51. uint8_t rx_ff_buf[CFG_TUD_CDC_RX_BUFSIZE];
  52. uint8_t tx_ff_buf[CFG_TUD_CDC_TX_BUFSIZE];
  53. #if CFG_FIFO_MUTEX
  54. osal_mutex_def_t rx_ff_mutex;
  55. osal_mutex_def_t tx_ff_mutex;
  56. #endif
  57. // Endpoint Transfer buffer
  58. CFG_TUSB_MEM_ALIGN uint8_t epout_buf[CFG_TUD_CDC_EP_BUFSIZE];
  59. CFG_TUSB_MEM_ALIGN uint8_t epin_buf[CFG_TUD_CDC_EP_BUFSIZE];
  60. }cdcd_interface_t;
  61. #define ITF_MEM_RESET_SIZE offsetof(cdcd_interface_t, wanted_char)
  62. //--------------------------------------------------------------------+
  63. // INTERNAL OBJECT & FUNCTION DECLARATION
  64. //--------------------------------------------------------------------+
  65. CFG_TUSB_MEM_SECTION static cdcd_interface_t _cdcd_itf[CFG_TUD_CDC];
  66. static void _prep_out_transaction (cdcd_interface_t* p_cdc)
  67. {
  68. uint8_t const rhport = TUD_OPT_RHPORT;
  69. uint16_t available = tu_fifo_remaining(&p_cdc->rx_ff);
  70. // Prepare for incoming data but only allow what we can store in the ring buffer.
  71. // TODO Actually we can still carry out the transfer, keeping count of received bytes
  72. // and slowly move it to the FIFO when read().
  73. // This pre-check reduces endpoint claiming
  74. TU_VERIFY(available >= sizeof(p_cdc->epout_buf), );
  75. // claim endpoint
  76. TU_VERIFY(usbd_edpt_claim(rhport, p_cdc->ep_out), );
  77. // fifo can be changed before endpoint is claimed
  78. available = tu_fifo_remaining(&p_cdc->rx_ff);
  79. if ( available >= sizeof(p_cdc->epout_buf) )
  80. {
  81. usbd_edpt_xfer(rhport, p_cdc->ep_out, p_cdc->epout_buf, sizeof(p_cdc->epout_buf));
  82. }else
  83. {
  84. // Release endpoint since we don't make any transfer
  85. usbd_edpt_release(rhport, p_cdc->ep_out);
  86. }
  87. }
  88. //--------------------------------------------------------------------+
  89. // APPLICATION API
  90. //--------------------------------------------------------------------+
  91. bool tud_cdc_n_connected(uint8_t itf)
  92. {
  93. // DTR (bit 0) active is considered as connected
  94. return tud_ready() && tu_bit_test(_cdcd_itf[itf].line_state, 0);
  95. }
  96. uint8_t tud_cdc_n_get_line_state (uint8_t itf)
  97. {
  98. return _cdcd_itf[itf].line_state;
  99. }
  100. void tud_cdc_n_get_line_coding (uint8_t itf, cdc_line_coding_t* coding)
  101. {
  102. (*coding) = _cdcd_itf[itf].line_coding;
  103. }
  104. void tud_cdc_n_set_wanted_char (uint8_t itf, char wanted)
  105. {
  106. _cdcd_itf[itf].wanted_char = wanted;
  107. }
  108. //--------------------------------------------------------------------+
  109. // READ API
  110. //--------------------------------------------------------------------+
  111. uint32_t tud_cdc_n_available(uint8_t itf)
  112. {
  113. return tu_fifo_count(&_cdcd_itf[itf].rx_ff);
  114. }
  115. uint32_t tud_cdc_n_read(uint8_t itf, void* buffer, uint32_t bufsize)
  116. {
  117. cdcd_interface_t* p_cdc = &_cdcd_itf[itf];
  118. uint32_t num_read = tu_fifo_read_n(&p_cdc->rx_ff, buffer, bufsize);
  119. _prep_out_transaction(p_cdc);
  120. return num_read;
  121. }
  122. bool tud_cdc_n_peek(uint8_t itf, int pos, uint8_t* chr)
  123. {
  124. return tu_fifo_peek_at(&_cdcd_itf[itf].rx_ff, pos, chr);
  125. }
  126. void tud_cdc_n_read_flush (uint8_t itf)
  127. {
  128. cdcd_interface_t* p_cdc = &_cdcd_itf[itf];
  129. tu_fifo_clear(&p_cdc->rx_ff);
  130. _prep_out_transaction(p_cdc);
  131. }
  132. //--------------------------------------------------------------------+
  133. // WRITE API
  134. //--------------------------------------------------------------------+
  135. uint32_t tud_cdc_n_write(uint8_t itf, void const* buffer, uint32_t bufsize)
  136. {
  137. cdcd_interface_t* p_cdc = &_cdcd_itf[itf];
  138. uint16_t ret = tu_fifo_write_n(&p_cdc->tx_ff, buffer, bufsize);
  139. // flush if queue more than packet size
  140. if ( tu_fifo_count(&p_cdc->tx_ff) >= BULK_PACKET_SIZE )
  141. {
  142. tud_cdc_n_write_flush(itf);
  143. }
  144. return ret;
  145. }
  146. uint32_t tud_cdc_n_write_flush (uint8_t itf)
  147. {
  148. cdcd_interface_t* p_cdc = &_cdcd_itf[itf];
  149. // Skip if usb is not ready yet
  150. TU_VERIFY( tud_ready(), 0 );
  151. // No data to send
  152. if ( !tu_fifo_count(&p_cdc->tx_ff) ) return 0;
  153. uint8_t const rhport = TUD_OPT_RHPORT;
  154. // Claim the endpoint
  155. TU_VERIFY( usbd_edpt_claim(rhport, p_cdc->ep_in), 0 );
  156. // Pull data from FIFO
  157. uint16_t const count = tu_fifo_read_n(&p_cdc->tx_ff, p_cdc->epin_buf, sizeof(p_cdc->epin_buf));
  158. if ( count )
  159. {
  160. TU_ASSERT( usbd_edpt_xfer(rhport, p_cdc->ep_in, p_cdc->epin_buf, count), 0 );
  161. return count;
  162. }else
  163. {
  164. // Release endpoint since we don't make any transfer
  165. // Note: data is dropped if terminal is not connected
  166. usbd_edpt_release(rhport, p_cdc->ep_in);
  167. return 0;
  168. }
  169. }
  170. uint32_t tud_cdc_n_write_available (uint8_t itf)
  171. {
  172. return tu_fifo_remaining(&_cdcd_itf[itf].tx_ff);
  173. }
  174. bool tud_cdc_n_write_clear (uint8_t itf)
  175. {
  176. return tu_fifo_clear(&_cdcd_itf[itf].tx_ff);
  177. }
  178. //--------------------------------------------------------------------+
  179. // USBD Driver API
  180. //--------------------------------------------------------------------+
  181. void cdcd_init(void)
  182. {
  183. tu_memclr(_cdcd_itf, sizeof(_cdcd_itf));
  184. for(uint8_t i=0; i<CFG_TUD_CDC; i++)
  185. {
  186. cdcd_interface_t* p_cdc = &_cdcd_itf[i];
  187. p_cdc->wanted_char = -1;
  188. // default line coding is : stop bit = 1, parity = none, data bits = 8
  189. p_cdc->line_coding.bit_rate = 115200;
  190. p_cdc->line_coding.stop_bits = 0;
  191. p_cdc->line_coding.parity = 0;
  192. p_cdc->line_coding.data_bits = 8;
  193. // Config RX fifo
  194. tu_fifo_config(&p_cdc->rx_ff, p_cdc->rx_ff_buf, TU_ARRAY_SIZE(p_cdc->rx_ff_buf), 1, false);
  195. // Config TX fifo as overwritable at initialization and will be changed to non-overwritable
  196. // if terminal supports DTR bit. Without DTR we do not know if data is actually polled by terminal.
  197. // In this way, the most current data is prioritized.
  198. tu_fifo_config(&p_cdc->tx_ff, p_cdc->tx_ff_buf, TU_ARRAY_SIZE(p_cdc->tx_ff_buf), 1, true);
  199. #if CFG_FIFO_MUTEX
  200. tu_fifo_config_mutex(&p_cdc->rx_ff, osal_mutex_create(&p_cdc->rx_ff_mutex));
  201. tu_fifo_config_mutex(&p_cdc->tx_ff, osal_mutex_create(&p_cdc->tx_ff_mutex));
  202. #endif
  203. }
  204. }
  205. void cdcd_reset(uint8_t rhport)
  206. {
  207. (void) rhport;
  208. for(uint8_t i=0; i<CFG_TUD_CDC; i++)
  209. {
  210. cdcd_interface_t* p_cdc = &_cdcd_itf[i];
  211. tu_memclr(p_cdc, ITF_MEM_RESET_SIZE);
  212. tu_fifo_clear(&p_cdc->rx_ff);
  213. tu_fifo_clear(&p_cdc->tx_ff);
  214. tu_fifo_set_overwritable(&p_cdc->tx_ff, true);
  215. }
  216. }
  217. uint16_t cdcd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len)
  218. {
  219. // Only support ACM subclass
  220. TU_VERIFY( TUSB_CLASS_CDC == itf_desc->bInterfaceClass &&
  221. CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL == itf_desc->bInterfaceSubClass, 0);
  222. // Note: 0xFF can be used with RNDIS
  223. TU_VERIFY(tu_within(CDC_COMM_PROTOCOL_NONE, itf_desc->bInterfaceProtocol, CDC_COMM_PROTOCOL_ATCOMMAND_CDMA), 0);
  224. // Find available interface
  225. cdcd_interface_t * p_cdc = NULL;
  226. for(uint8_t cdc_id=0; cdc_id<CFG_TUD_CDC; cdc_id++)
  227. {
  228. if ( _cdcd_itf[cdc_id].ep_in == 0 )
  229. {
  230. p_cdc = &_cdcd_itf[cdc_id];
  231. break;
  232. }
  233. }
  234. TU_ASSERT(p_cdc, 0);
  235. //------------- Control Interface -------------//
  236. p_cdc->itf_num = itf_desc->bInterfaceNumber;
  237. uint16_t drv_len = sizeof(tusb_desc_interface_t);
  238. uint8_t const * p_desc = tu_desc_next( itf_desc );
  239. // Communication Functional Descriptors
  240. while ( TUSB_DESC_CS_INTERFACE == tu_desc_type(p_desc) && drv_len <= max_len )
  241. {
  242. drv_len += tu_desc_len(p_desc);
  243. p_desc = tu_desc_next(p_desc);
  244. }
  245. if ( TUSB_DESC_ENDPOINT == tu_desc_type(p_desc) )
  246. {
  247. // notification endpoint if any
  248. TU_ASSERT( usbd_edpt_open(rhport, (tusb_desc_endpoint_t const *) p_desc), 0 );
  249. p_cdc->ep_notif = ((tusb_desc_endpoint_t const *) p_desc)->bEndpointAddress;
  250. drv_len += tu_desc_len(p_desc);
  251. p_desc = tu_desc_next(p_desc);
  252. }
  253. //------------- Data Interface (if any) -------------//
  254. if ( (TUSB_DESC_INTERFACE == tu_desc_type(p_desc)) &&
  255. (TUSB_CLASS_CDC_DATA == ((tusb_desc_interface_t const *) p_desc)->bInterfaceClass) )
  256. {
  257. // next to endpoint descriptor
  258. drv_len += tu_desc_len(p_desc);
  259. p_desc = tu_desc_next(p_desc);
  260. // Open endpoint pair
  261. TU_ASSERT( usbd_open_edpt_pair(rhport, p_desc, 2, TUSB_XFER_BULK, &p_cdc->ep_out, &p_cdc->ep_in), 0 );
  262. drv_len += 2*sizeof(tusb_desc_endpoint_t);
  263. }
  264. // Prepare for incoming data
  265. _prep_out_transaction(p_cdc);
  266. return drv_len;
  267. }
  268. // Invoked when a control transfer occurred on an interface of this class
  269. // Driver response accordingly to the request and the transfer stage (setup/data/ack)
  270. // return false to stall control endpoint (e.g unsupported request)
  271. bool cdcd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request)
  272. {
  273. // Handle class request only
  274. TU_VERIFY(request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS);
  275. uint8_t itf = 0;
  276. cdcd_interface_t* p_cdc = _cdcd_itf;
  277. // Identify which interface to use
  278. for ( ; ; itf++, p_cdc++)
  279. {
  280. if (itf >= TU_ARRAY_SIZE(_cdcd_itf)) return false;
  281. if ( p_cdc->itf_num == request->wIndex ) break;
  282. }
  283. switch ( request->bRequest )
  284. {
  285. case CDC_REQUEST_SET_LINE_CODING:
  286. if (stage == CONTROL_STAGE_SETUP)
  287. {
  288. TU_LOG2(" Set Line Coding\r\n");
  289. tud_control_xfer(rhport, request, &p_cdc->line_coding, sizeof(cdc_line_coding_t));
  290. }
  291. else if ( stage == CONTROL_STAGE_ACK)
  292. {
  293. if ( tud_cdc_line_coding_cb ) tud_cdc_line_coding_cb(itf, &p_cdc->line_coding);
  294. }
  295. break;
  296. case CDC_REQUEST_GET_LINE_CODING:
  297. if (stage == CONTROL_STAGE_SETUP)
  298. {
  299. TU_LOG2(" Get Line Coding\r\n");
  300. tud_control_xfer(rhport, request, &p_cdc->line_coding, sizeof(cdc_line_coding_t));
  301. }
  302. break;
  303. case CDC_REQUEST_SET_CONTROL_LINE_STATE:
  304. if (stage == CONTROL_STAGE_SETUP)
  305. {
  306. tud_control_status(rhport, request);
  307. }
  308. else if (stage == CONTROL_STAGE_ACK)
  309. {
  310. // CDC PSTN v1.2 section 6.3.12
  311. // Bit 0: Indicates if DTE is present or not.
  312. // This signal corresponds to V.24 signal 108/2 and RS-232 signal DTR (Data Terminal Ready)
  313. // Bit 1: Carrier control for half-duplex modems.
  314. // This signal corresponds to V.24 signal 105 and RS-232 signal RTS (Request to Send)
  315. bool const dtr = tu_bit_test(request->wValue, 0);
  316. bool const rts = tu_bit_test(request->wValue, 1);
  317. p_cdc->line_state = (uint8_t) request->wValue;
  318. // Disable fifo overwriting if DTR bit is set
  319. tu_fifo_set_overwritable(&p_cdc->tx_ff, !dtr);
  320. TU_LOG2(" Set Control Line State: DTR = %d, RTS = %d\r\n", dtr, rts);
  321. // Invoke callback
  322. if ( tud_cdc_line_state_cb ) tud_cdc_line_state_cb(itf, dtr, rts);
  323. }
  324. break;
  325. case CDC_REQUEST_SEND_BREAK:
  326. if (stage == CONTROL_STAGE_SETUP)
  327. {
  328. tud_control_status(rhport, request);
  329. }
  330. else if (stage == CONTROL_STAGE_ACK)
  331. {
  332. TU_LOG2(" Send Break\r\n");
  333. if ( tud_cdc_send_break_cb ) tud_cdc_send_break_cb(itf, request->wValue);
  334. }
  335. break;
  336. default: return false; // stall unsupported request
  337. }
  338. return true;
  339. }
  340. bool cdcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes)
  341. {
  342. (void) result;
  343. uint8_t itf;
  344. cdcd_interface_t* p_cdc;
  345. // Identify which interface to use
  346. for (itf = 0; itf < CFG_TUD_CDC; itf++)
  347. {
  348. p_cdc = &_cdcd_itf[itf];
  349. if ( ( ep_addr == p_cdc->ep_out ) || ( ep_addr == p_cdc->ep_in ) ) break;
  350. }
  351. TU_ASSERT(itf < CFG_TUD_CDC);
  352. // Received new data
  353. if ( ep_addr == p_cdc->ep_out )
  354. {
  355. tu_fifo_write_n(&p_cdc->rx_ff, &p_cdc->epout_buf, xferred_bytes);
  356. // Check for wanted char and invoke callback if needed
  357. if ( tud_cdc_rx_wanted_cb && (((signed char) p_cdc->wanted_char) != -1) )
  358. {
  359. for ( uint32_t i = 0; i < xferred_bytes; i++ )
  360. {
  361. if ( (p_cdc->wanted_char == p_cdc->epout_buf[i]) && !tu_fifo_empty(&p_cdc->rx_ff) )
  362. {
  363. tud_cdc_rx_wanted_cb(itf, p_cdc->wanted_char);
  364. }
  365. }
  366. }
  367. // invoke receive callback (if there is still data)
  368. if (tud_cdc_rx_cb && !tu_fifo_empty(&p_cdc->rx_ff) ) tud_cdc_rx_cb(itf);
  369. // prepare for OUT transaction
  370. _prep_out_transaction(p_cdc);
  371. }
  372. // Data sent to host, we continue to fetch from tx fifo to send.
  373. // Note: This will cause incorrect baudrate set in line coding.
  374. // Though maybe the baudrate is not really important !!!
  375. if ( ep_addr == p_cdc->ep_in )
  376. {
  377. // invoke transmit callback to possibly refill tx fifo
  378. if ( tud_cdc_tx_complete_cb ) tud_cdc_tx_complete_cb(itf);
  379. if ( 0 == tud_cdc_n_write_flush(itf) )
  380. {
  381. // If there is no data left, a ZLP should be sent if
  382. // xferred_bytes is multiple of EP Packet size and not zero
  383. if ( !tu_fifo_count(&p_cdc->tx_ff) && xferred_bytes && (0 == (xferred_bytes & (BULK_PACKET_SIZE-1))) )
  384. {
  385. if ( usbd_edpt_claim(rhport, p_cdc->ep_in) )
  386. {
  387. usbd_edpt_xfer(rhport, p_cdc->ep_in, NULL, 0);
  388. }
  389. }
  390. }
  391. }
  392. // nothing to do with notif endpoint for now
  393. return true;
  394. }
  395. #endif