1
0

cdc_loop.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332
  1. /* This file is the part of the Lightweight USB device Stack for STM32 microcontrollers
  2. *
  3. * Copyright ©2016 Dmitry Filimonchuk <dmitrystu[at]gmail[dot]com>
  4. *
  5. * Licensed under the Apache License, Version 2.0 (the "License");
  6. * you may not use this file except in compliance with the License.
  7. * You may obtain a copy of the License at
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. * Unless required by applicable law or agreed to in writing, software
  10. * distributed under the License is distributed on an "AS IS" BASIS,
  11. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. * See the License for the specific language governing permissions and
  13. * limitations under the License.
  14. */
  15. #include <stdint.h>
  16. #include <stdbool.h>
  17. #include <string.h>
  18. #include "stm32.h"
  19. #include "usb.h"
  20. #include "usb_cdc.h"
  21. #define CDC_EP0_SIZE 0x08
  22. #define CDC_RXD_EP 0x01
  23. #define CDC_TXD_EP 0x82
  24. #define CDC_DATA_SZ 0x40
  25. #define CDC_NTF_EP 0x83
  26. #define CDC_NTF_SZ 0x08
  27. #define CDC_LOOPBACK
  28. //#define CDC_USE_IRQ /* uncomment to build interrupt-based demo */
  29. struct cdc_config {
  30. struct usb_config_descriptor config;
  31. struct usb_interface_descriptor comm;
  32. struct usb_cdc_header_desc cdc_hdr;
  33. struct usb_cdc_call_mgmt_desc cdc_mgmt;
  34. struct usb_cdc_acm_desc cdc_acm;
  35. struct usb_cdc_union_desc cdc_union;
  36. struct usb_endpoint_descriptor comm_ep;
  37. struct usb_interface_descriptor data;
  38. struct usb_endpoint_descriptor data_eprx;
  39. struct usb_endpoint_descriptor data_eptx;
  40. } __attribute__((packed));
  41. static const struct usb_device_descriptor device_desc = {
  42. .bLength = sizeof(struct usb_device_descriptor),
  43. .bDescriptorType = USB_DTYPE_DEVICE,
  44. .bcdUSB = VERSION_BCD(2,0,0),
  45. .bDeviceClass = USB_CLASS_CDC,
  46. .bDeviceSubClass = USB_SUBCLASS_NONE,
  47. .bDeviceProtocol = USB_PROTO_NONE,
  48. .bMaxPacketSize0 = CDC_EP0_SIZE,
  49. .idVendor = 0x0483,
  50. .idProduct = 0x5740,
  51. .bcdDevice = VERSION_BCD(1,0,0),
  52. .iManufacturer = 1,
  53. .iProduct = 2,
  54. .iSerialNumber = INTSERIALNO_DESCRIPTOR,
  55. .bNumConfigurations = 1,
  56. };
  57. static const struct cdc_config config_desc = {
  58. .config = {
  59. .bLength = sizeof(struct usb_config_descriptor),
  60. .bDescriptorType = USB_DTYPE_CONFIGURATION,
  61. .wTotalLength = sizeof(struct cdc_config),
  62. .bNumInterfaces = 2,
  63. .bConfigurationValue = 1,
  64. .iConfiguration = NO_DESCRIPTOR,
  65. .bmAttributes = USB_CFG_ATTR_RESERVED | USB_CFG_ATTR_SELFPOWERED,
  66. .bMaxPower = USB_CFG_POWER_MA(100),
  67. },
  68. .comm = {
  69. .bLength = sizeof(struct usb_interface_descriptor),
  70. .bDescriptorType = USB_DTYPE_INTERFACE,
  71. .bInterfaceNumber = 0,
  72. .bAlternateSetting = 0,
  73. .bNumEndpoints = 1,
  74. .bInterfaceClass = USB_CLASS_CDC,
  75. .bInterfaceSubClass = USB_CDC_SUBCLASS_ACM,
  76. .bInterfaceProtocol = USB_CDC_PROTO_V25TER,
  77. .iInterface = NO_DESCRIPTOR,
  78. },
  79. .cdc_hdr = {
  80. .bFunctionLength = sizeof(struct usb_cdc_header_desc),
  81. .bDescriptorType = USB_DTYPE_CS_INTERFACE,
  82. .bDescriptorSubType = USB_DTYPE_CDC_HEADER,
  83. .bcdCDC = VERSION_BCD(1,1,0),
  84. },
  85. .cdc_mgmt = {
  86. .bFunctionLength = sizeof(struct usb_cdc_call_mgmt_desc),
  87. .bDescriptorType = USB_DTYPE_CS_INTERFACE,
  88. .bDescriptorSubType = USB_DTYPE_CDC_CALL_MANAGEMENT,
  89. .bmCapabilities = 0,
  90. .bDataInterface = 1,
  91. },
  92. .cdc_acm = {
  93. .bFunctionLength = sizeof(struct usb_cdc_acm_desc),
  94. .bDescriptorType = USB_DTYPE_CS_INTERFACE,
  95. .bDescriptorSubType = USB_DTYPE_CDC_ACM,
  96. .bmCapabilities = 0,
  97. },
  98. .cdc_union = {
  99. .bFunctionLength = sizeof(struct usb_cdc_union_desc),
  100. .bDescriptorType = USB_DTYPE_CS_INTERFACE,
  101. .bDescriptorSubType = USB_DTYPE_CDC_UNION,
  102. .bMasterInterface0 = 0,
  103. .bSlaveInterface0 = 1,
  104. },
  105. .comm_ep = {
  106. .bLength = sizeof(struct usb_endpoint_descriptor),
  107. .bDescriptorType = USB_DTYPE_ENDPOINT,
  108. .bEndpointAddress = CDC_NTF_EP,
  109. .bmAttributes = USB_EPTYPE_INTERRUPT,
  110. .wMaxPacketSize = CDC_NTF_SZ,
  111. .bInterval = 0xFF,
  112. },
  113. .data = {
  114. .bLength = sizeof(struct usb_interface_descriptor),
  115. .bDescriptorType = USB_DTYPE_INTERFACE,
  116. .bInterfaceNumber = 1,
  117. .bAlternateSetting = 0,
  118. .bNumEndpoints = 2,
  119. .bInterfaceClass = USB_CLASS_CDC_DATA,
  120. .bInterfaceSubClass = USB_SUBCLASS_NONE,
  121. .bInterfaceProtocol = USB_PROTO_NONE,
  122. .iInterface = NO_DESCRIPTOR,
  123. },
  124. .data_eprx = {
  125. .bLength = sizeof(struct usb_endpoint_descriptor),
  126. .bDescriptorType = USB_DTYPE_ENDPOINT,
  127. .bEndpointAddress = CDC_RXD_EP,
  128. .bmAttributes = USB_EPTYPE_BULK,
  129. .wMaxPacketSize = CDC_DATA_SZ,
  130. .bInterval = 0x01,
  131. },
  132. .data_eptx = {
  133. .bLength = sizeof(struct usb_endpoint_descriptor),
  134. .bDescriptorType = USB_DTYPE_ENDPOINT,
  135. .bEndpointAddress = CDC_TXD_EP,
  136. .bmAttributes = USB_EPTYPE_BULK,
  137. .wMaxPacketSize = CDC_DATA_SZ,
  138. .bInterval = 0x01,
  139. },
  140. };
  141. static const struct usb_string_descriptor lang_desc = USB_ARRAY_DESC(USB_LANGID_ENG_US);
  142. static const struct usb_string_descriptor manuf_desc_en = USB_STRING_DESC("Open source USB stack for STM32");
  143. static const struct usb_string_descriptor prod_desc_en = USB_STRING_DESC("CDC Loopback demo");
  144. static const struct usb_string_descriptor *const dtable[] = {
  145. &lang_desc,
  146. &manuf_desc_en,
  147. &prod_desc_en,
  148. };
  149. usbd_device udev;
  150. uint32_t ubuf[0x20];
  151. uint8_t fifo[0x200];
  152. uint32_t fpos = 0;
  153. static struct usb_cdc_line_coding cdc_line = {
  154. .dwDTERate = 38400,
  155. .bCharFormat = USB_CDC_1_STOP_BITS,
  156. .bParityType = USB_CDC_NO_PARITY,
  157. .bDataBits = 8,
  158. };
  159. static usbd_respond cdc_getdesc (usbd_ctlreq *req, void **address, uint16_t *length) {
  160. const uint8_t dtype = req->wValue >> 8;
  161. const uint8_t dnumber = req->wValue & 0xFF;
  162. const void* desc;
  163. uint16_t len = 0;
  164. switch (dtype) {
  165. case USB_DTYPE_DEVICE:
  166. desc = &device_desc;
  167. break;
  168. case USB_DTYPE_CONFIGURATION:
  169. desc = &config_desc;
  170. len = sizeof(config_desc);
  171. break;
  172. case USB_DTYPE_STRING:
  173. if (dnumber < 3) {
  174. desc = dtable[dnumber];
  175. } else {
  176. return usbd_fail;
  177. }
  178. break;
  179. default:
  180. return usbd_fail;
  181. }
  182. if (len == 0) {
  183. len = ((struct usb_header_descriptor*)desc)->bLength;
  184. }
  185. *address = (void*)desc;
  186. *length = len;
  187. return usbd_ack;
  188. };
  189. static usbd_respond cdc_control(usbd_device *dev, usbd_ctlreq *req, usbd_rqc_callback *callback) {
  190. if (((USB_REQ_RECIPIENT | USB_REQ_TYPE) & req->bmRequestType) != (USB_REQ_INTERFACE | USB_REQ_CLASS)) return usbd_fail;
  191. switch (req->bRequest) {
  192. case USB_CDC_SET_CONTROL_LINE_STATE:
  193. return usbd_ack;
  194. case USB_CDC_SET_LINE_CODING:
  195. memmove( req->data, &cdc_line, sizeof(cdc_line));
  196. return usbd_ack;
  197. case USB_CDC_GET_LINE_CODING:
  198. dev->status.data_ptr = &cdc_line;
  199. dev->status.data_count = sizeof(cdc_line);
  200. return usbd_ack;
  201. default:
  202. return usbd_fail;
  203. }
  204. }
  205. static void cdc_rxonly (usbd_device *dev, uint8_t event, uint8_t ep) {
  206. usbd_ep_read(dev, ep, fifo, CDC_DATA_SZ);
  207. }
  208. static void cdc_txonly(usbd_device *dev, uint8_t event, uint8_t ep) {
  209. uint8_t _t = dev->driver->frame_no();
  210. memset(fifo, _t, CDC_DATA_SZ);
  211. usbd_ep_write(dev, ep, fifo, CDC_DATA_SZ);
  212. }
  213. static void cdc_loopback(usbd_device *dev, uint8_t event, uint8_t ep) {
  214. int _t;
  215. switch (event) {
  216. case usbd_evt_eptx:
  217. _t = usbd_ep_write(dev, CDC_TXD_EP, &fifo[0], (fpos < CDC_DATA_SZ) ? fpos : CDC_DATA_SZ);
  218. if (_t > 0) {
  219. memmove(&fifo[0], &fifo[_t], fpos - _t);
  220. fpos -= _t;
  221. }
  222. case usbd_evt_eprx:
  223. if (fpos < (sizeof(fifo) - CDC_DATA_SZ)) {
  224. _t = usbd_ep_read(dev, CDC_RXD_EP, &fifo[fpos], CDC_DATA_SZ);
  225. if (_t > 0) {
  226. fpos += _t;
  227. }
  228. }
  229. default:
  230. break;
  231. }
  232. }
  233. static usbd_respond cdc_setconf (usbd_device *dev, uint8_t cfg) {
  234. switch (cfg) {
  235. case 0:
  236. /* deconfiguring device */
  237. usbd_ep_deconfig(dev, CDC_NTF_EP);
  238. usbd_ep_deconfig(dev, CDC_TXD_EP);
  239. usbd_ep_deconfig(dev, CDC_RXD_EP);
  240. usbd_reg_endpoint(dev, CDC_RXD_EP, 0);
  241. usbd_reg_endpoint(dev, CDC_TXD_EP, 0);
  242. return usbd_ack;
  243. case 1:
  244. /* configuring device */
  245. usbd_ep_config(dev, CDC_RXD_EP, USB_EPTYPE_BULK | USB_EPTYPE_DBLBUF, CDC_DATA_SZ);
  246. usbd_ep_config(dev, CDC_TXD_EP, USB_EPTYPE_BULK | USB_EPTYPE_DBLBUF, CDC_DATA_SZ);
  247. usbd_ep_config(dev, CDC_NTF_EP, USB_EPTYPE_INTERRUPT, CDC_NTF_SZ);
  248. #if defined(CDC_LOOPBACK)
  249. usbd_reg_endpoint(dev, CDC_RXD_EP, cdc_loopback);
  250. usbd_reg_endpoint(dev, CDC_TXD_EP, cdc_loopback);
  251. #else
  252. usbd_reg_endpoint(dev, CDC_RXD_EP, cdc_rxonly);
  253. usbd_reg_endpoint(dev, CDC_TXD_EP, cdc_txonly);
  254. #endif
  255. usbd_ep_write(dev, CDC_TXD_EP, 0, 0);
  256. return usbd_ack;
  257. default:
  258. return usbd_fail;
  259. }
  260. }
  261. static void cdc_init_usbd(void) {
  262. usbd_init(&udev, &usbd_hw, CDC_EP0_SIZE, ubuf, sizeof(ubuf));
  263. usbd_reg_config(&udev, cdc_setconf);
  264. usbd_reg_control(&udev, cdc_control);
  265. usbd_reg_descr(&udev, cdc_getdesc);
  266. }
  267. #if defined(CDC_USE_IRQ)
  268. #if defined(STM32L052xx)
  269. #define USB_HANDLER USB_IRQHandler
  270. #define USB_NVIC_IRQ USB_IRQn
  271. #elif defined(STM32L100xC)
  272. #define USB_HANDLER USB_LP_IRQHandler
  273. #define USB_NVIC_IRQ USB_LP_IRQn
  274. #elif defined(STM32L476xx)
  275. #define USB_HANDLER OTG_FS_IRQHandler
  276. #define USB_NVIC_IRQ OTG_FS_IRQn
  277. #elif defined(STM32F103x6)
  278. #define USB_HANDLER USB_LP_CAN1_RX0_IRQHandler
  279. #define USB_NVIC_IRQ USB_LP_CAN1_RX0_IRQn
  280. #elif defined(STM32F103xE)
  281. #define USB_HANDLER USB_LP_CAN1_RX0_IRQHandler
  282. #define USB_NVIC_IRQ USB_LP_CAN1_RX0_IRQn
  283. #elif defined(STM32F429xx) || defined(STM32F105xC) || defined(STM32F107xC)
  284. #define USB_HANDLER OTG_FS_IRQHandler
  285. #define USB_NVIC_IRQ OTG_FS_IRQn
  286. #else
  287. #error Not supported
  288. #endif
  289. void USB_HANDLER(void) {
  290. usbd_poll(&udev);
  291. }
  292. void main(void) {
  293. cdc_init_usbd();
  294. NVIC_EnableIRQ(USB_NVIC_IRQ);
  295. usbd_enable(&udev, true);
  296. usbd_connect(&udev, true);
  297. while(1) {
  298. __WFI();
  299. }
  300. }
  301. #else
  302. void main(void) {
  303. cdc_init_usbd();
  304. usbd_enable(&udev, true);
  305. usbd_connect(&udev, true);
  306. while(1) {
  307. usbd_poll(&udev);
  308. }
  309. }
  310. #endif