cdc.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332
  1. /**************************************************************************/
  2. /*!
  3. @file cdc.c
  4. @author hathach (tinyusb.org)
  5. @section LICENSE
  6. Software License Agreement (BSD License)
  7. Copyright (c) 2013, hathach (tinyusb.org)
  8. All rights reserved.
  9. Redistribution and use in source and binary forms, with or without
  10. modification, are permitted provided that the following conditions are met:
  11. 1. Redistributions of source code must retain the above copyright
  12. notice, this list of conditions and the following disclaimer.
  13. 2. Redistributions in binary form must reproduce the above copyright
  14. notice, this list of conditions and the following disclaimer in the
  15. documentation and/or other materials provided with the distribution.
  16. 3. Neither the name of the copyright holders nor the
  17. names of its contributors may be used to endorse or promote products
  18. derived from this software without specific prior written permission.
  19. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
  20. EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  21. WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  22. DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
  23. DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  24. INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  25. LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION HOWEVER CAUSED AND
  26. ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  27. INCLUDING NEGLIGENCE OR OTHERWISE ARISING IN ANY WAY OUT OF THE USE OF THIS
  28. SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  29. This file is part of the tinyusb stack.
  30. */
  31. /**************************************************************************/
  32. #include "cdc.h"
  33. #include "common/fifo.h"
  34. #if defined TUSB_CFG_DEVICE_CDC && defined TUSB_CFG_DEVICE
  35. static USBD_HANDLE_T g_hCdc;
  36. static CDC_LINE_CODING line_coding;
  37. static uint8_t qBuffer[2][CDC_BUFFER_SIZE]; /* TX and RX buffers */
  38. static fifo_t ffTX, ffRX;
  39. void usb_cdc_recv_isr(void) ATTR_WEAK ATTR_ALIAS(usb_cdc_recv_isr_stub);
  40. /**************************************************************************/
  41. /*!
  42. @brief Stub for the optional CDC receive ISR that can be used
  43. to perform some action when data arrives via USB CDC
  44. */
  45. /**************************************************************************/
  46. void usb_cdc_recv_isr_stub (void)
  47. {
  48. return;
  49. }
  50. /**************************************************************************/
  51. /*!
  52. @brief Adds a single byte to the transmit buffer for USB CDC
  53. @param[in] c
  54. The byte to send
  55. @returns TRUE if the byte was successfully added to the TX buffer
  56. @note See example for tusb_cdc_getc
  57. */
  58. /**************************************************************************/
  59. bool tusb_cdc_putc (uint8_t c)
  60. {
  61. return fifo_write(&ffTX, c);
  62. }
  63. /**************************************************************************/
  64. /*!
  65. @brief Reads a single byte from the USB CDC buffer
  66. @param[in] c
  67. Pointer to the location where the byte should be written
  68. @returns TRUE if a byte was read from the buffer
  69. @section EXAMPLE
  70. @code
  71. // Convert incoming characters to upper case and send back via CDC
  72. if (usb_isConfigured())
  73. {
  74. uint8_t cdc_char;
  75. if( tusb_cdc_getc(&cdc_char) )
  76. {
  77. switch (cdc_char)
  78. {
  79. default :
  80. cdc_char = toupper(cdc_char);
  81. tusb_cdc_putc(cdc_char);
  82. break;
  83. }
  84. }
  85. }
  86. @endcode
  87. */
  88. /**************************************************************************/
  89. bool tusb_cdc_getc(uint8_t *c)
  90. {
  91. ASSERT(c, false); // not empty pointer
  92. return fifo_read(&ffRX, c);
  93. }
  94. /**************************************************************************/
  95. /*!
  96. @brief Writes the supplied buffer to the USB CDC device
  97. @param[in] buffer
  98. Pointer to the buffer that should be written via USB CDC
  99. @param[in] count
  100. The number of bytes to write
  101. @returns The actual number of bytes sent out via USB CDC
  102. @section EXAMPLE
  103. @code
  104. // Capture printf output (in Red Suite) and send it to USB CDC
  105. // (Note: With newlib this function should be renamed to _write)
  106. int __sys_write(int file, char *ptr, int len)
  107. {
  108. #ifdef CFG_PRINTF_USBCDC
  109. // Handle USB CDC output
  110. if (usb_isConfigured())
  111. {
  112. int length = len;
  113. while(length > 0)
  114. {
  115. uint16_t transferredCount;
  116. transferredCount = tusb_cdc_send( (uint8_t*) ptr, length);
  117. ptr += transferredCount;
  118. length -= transferredCount;
  119. }
  120. }
  121. #endif
  122. return len;
  123. }
  124. @endcode
  125. */
  126. /**************************************************************************/
  127. uint16_t tusb_cdc_send(uint8_t* buffer, uint16_t count)
  128. {
  129. uint16_t i=0;
  130. ASSERT(buffer && count, 0);
  131. while (i < count && fifo_write(&ffTX, buffer[i]) )
  132. {
  133. i++;
  134. }
  135. return i;
  136. }
  137. /**************************************************************************/
  138. /*!
  139. @brief Reads the incoming CDC buffer up to a maximum number of bytes
  140. @param[in] buffer
  141. Pointer to the buffer where data should be written
  142. @param[in] max
  143. The maximum number of bytes to read
  144. @returns The actual number of bytes received
  145. */
  146. /**************************************************************************/
  147. uint16_t tusb_cdc_recv(uint8_t* buffer, uint16_t max)
  148. {
  149. ASSERT(buffer && max, 0);
  150. return fifo_read_n(&ffRX, buffer, max);
  151. }
  152. #if 0
  153. // ROM driver bug: cannot hook this to CIC_GetRequest
  154. // Need this to implement GetLineCode & detect
  155. ErrorCode_t CDC_Control_GetRequest(USBD_HANDLE_T hUsb, USB_SETUP_PACKET *pSetup, uint8_t **pBuffer, uint16_t *length)
  156. {
  157. return LPC_OK;
  158. }
  159. #endif
  160. /**************************************************************************/
  161. /*!
  162. @brief TODO Add description
  163. */
  164. /**************************************************************************/
  165. ErrorCode_t CDC_SetLineCoding(USBD_HANDLE_T hUsb, CDC_LINE_CODING *lineCoding)
  166. {
  167. ASSERT(lineCoding, ERR_FAILED);
  168. memcpy(&line_coding, lineCoding, sizeof(CDC_LINE_CODING));
  169. return LPC_OK;
  170. }
  171. /**************************************************************************/
  172. /*!
  173. @brief TODO Add description
  174. */
  175. /**************************************************************************/
  176. ErrorCode_t CDC_SendBreak(USBD_HANDLE_T hCDC, uint16_t mstime)
  177. {
  178. return LPC_OK;
  179. }
  180. /**************************************************************************/
  181. /*!
  182. @brief Bulk Out handler for the USB ROM drivers (UART TX)
  183. */
  184. /**************************************************************************/
  185. ErrorCode_t CDC_BulkIn_Hdlr(USBD_HANDLE_T hUsb, void* data, uint32_t event)
  186. {
  187. if (USB_EVT_IN == event)
  188. {
  189. uint8_t buffer[CDC_DATA_EP_MAXPACKET_SIZE];
  190. uint16_t count;
  191. count = fifo_read_n(&ffTX, buffer, CDC_DATA_EP_MAXPACKET_SIZE);
  192. USBD_API->hw->WriteEP(hUsb, CDC_DATA_EP_IN, buffer, count); // write data to EP
  193. }
  194. return LPC_OK;
  195. }
  196. /**************************************************************************/
  197. /*!
  198. @brief Bulk Out handler for the USB ROM drivers (UART RX)
  199. */
  200. /**************************************************************************/
  201. ErrorCode_t CDC_BulkOut_Hdlr(USBD_HANDLE_T hUsb, void* data, uint32_t event)
  202. {
  203. if (USB_EVT_OUT == event)
  204. {
  205. uint16_t count, i;
  206. uint8_t buffer[CDC_DATA_EP_MAXPACKET_SIZE];
  207. count = USBD_API->hw->ReadEP(hUsb, CDC_DATA_EP_OUT, buffer);
  208. for (i=0; i<count; i++)
  209. {
  210. fifo_write(&ffRX, buffer[i]);
  211. }
  212. usb_cdc_recv_isr();
  213. }
  214. return LPC_OK;
  215. }
  216. /**************************************************************************/
  217. /*!
  218. @brief Initialises USB CDC using the ROM driver
  219. */
  220. /**************************************************************************/
  221. tusb_error_t tusb_cdc_init(USBD_HANDLE_T hUsb, USB_INTERFACE_DESCRIPTOR const *const pControlIntfDesc, USB_INTERFACE_DESCRIPTOR const *const pDataIntfDesc, uint32_t* mem_base, uint32_t* mem_size)
  222. {
  223. USBD_CDC_INIT_PARAM_T cdc_param =
  224. {
  225. .mem_base = *mem_base,
  226. .mem_size = *mem_size,
  227. .cif_intf_desc = (uint8_t*) pControlIntfDesc,
  228. .dif_intf_desc = (uint8_t*) pDataIntfDesc,
  229. .SetLineCode = CDC_SetLineCoding,
  230. .SendBreak = CDC_SendBreak,
  231. // .CIC_GetRequest = CDC_Control_GetRequest, // bug from romdrive cannot hook to this handler
  232. // Bug from ROM driver: can not hook bulk in & out handler here, must use USBD API register instead
  233. // .CDC_BulkIN_Hdlr = CDC_BulkIn_Hdlr,
  234. // .CDC_BulkOUT_Hdlr = CDC_BulkOut_Hdlr,
  235. };
  236. ASSERT (pControlIntfDesc && pDataIntfDesc, ERR_FAILED);
  237. /* register Bulk IN & OUT endpoint interrupt handler */
  238. ASSERT ( LPC_OK == USBD_API->core->RegisterEpHandler (hUsb , ((CDC_DATA_EP_IN & 0x0F) << 1) +1 , CDC_BulkIn_Hdlr , NULL), TUSB_ERROR_FAILED );
  239. ASSERT ( LPC_OK == USBD_API->core->RegisterEpHandler (hUsb , (CDC_DATA_EP_OUT & 0x0F) << 1 , CDC_BulkOut_Hdlr , NULL), TUSB_ERROR_FAILED );
  240. ASSERT ( LPC_OK == USBD_API->cdc->init(hUsb, &cdc_param, &g_hCdc), TUSB_ERROR_FAILED);
  241. /* update memory variables */
  242. *mem_base = cdc_param.mem_base;
  243. *mem_size = cdc_param.mem_size;
  244. return TUSB_ERROR_NONE;
  245. }
  246. /**************************************************************************/
  247. /*!
  248. @brief TODO Add description
  249. */
  250. /**************************************************************************/
  251. tusb_error_t tusb_cdc_configured(USBD_HANDLE_T hUsb)
  252. {
  253. uint8_t dummy=0;
  254. USBD_API->hw->WriteEP(hUsb, CDC_DATA_EP_IN, &dummy, 1); // initial packet for IN endpoint, will not work if omitted
  255. // FIXME abstract to hal
  256. #if MCU == MCU_LPC11UXX
  257. fifo_init (&ffTX, qBuffer[0], CDC_BUFFER_SIZE, false, USB_IRQn); // TX is non-overwritable
  258. fifo_init (&ffRX, qBuffer[1], CDC_BUFFER_SIZE, true, USB_IRQn); // RX is overwritable
  259. #elif MCU == MCU_LPC13UXX
  260. fifo_init (&ffTX, qBuffer[0], CDC_BUFFER_SIZE, false, USB_IRQ_IRQn); // TX is non-overwritable
  261. fifo_init (&ffRX, qBuffer[1], CDC_BUFFER_SIZE, true, USB_IRQ_IRQn); // RX is overwritable
  262. #elif MCU == MCU_LPC43XX
  263. fifo_init (&ffTX, qBuffer[0], CDC_BUFFER_SIZE, false, USB0_IRQn); // TODO USB1 TX is non-overwritable
  264. fifo_init (&ffRX, qBuffer[1], CDC_BUFFER_SIZE, true, USB0_IRQn); // RX is overwritable
  265. #else
  266. #error No MCU defined // TODO asbtract MCU
  267. #endif
  268. return TUSB_ERROR_NONE;
  269. }
  270. #endif