cdc_loop.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543
  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_compat.h"
  19. #include "usb.h"
  20. #include "usb_cdc.h"
  21. #include "usb_hid.h"
  22. #include "hid_usage_desktop.h"
  23. #include "hid_usage_button.h"
  24. #define CDC_EP0_SIZE 0x08
  25. #define CDC_RXD_EP 0x01
  26. #define CDC_TXD_EP 0x81
  27. #define CDC_DATA_SZ 0x40
  28. #define CDC_NTF_EP 0x82
  29. #define CDC_NTF_SZ 0x08
  30. #define HID_RIN_EP 0x83
  31. #define HID_RIN_SZ 0x10
  32. #define CDC_LOOPBACK
  33. #define ENABLE_HID_COMBO
  34. //#define SIGNAL_MODEM /* uncomment to signal modem capabilities */
  35. //#define CDC_USE_IRQ /* uncomment to build interrupt-based demo */
  36. #if defined(SIGNAL_MODEM)
  37. #define CDC_PROTOCOL USB_CDC_PROTO_V25TER
  38. #else
  39. #define CDC_PROTOCOL USB_PROTO_NONE
  40. #endif
  41. /* Declaration of the report descriptor */
  42. struct cdc_config {
  43. struct usb_config_descriptor config;
  44. struct usb_iad_descriptor comm_iad;
  45. struct usb_interface_descriptor comm;
  46. struct usb_cdc_header_desc cdc_hdr;
  47. struct usb_cdc_call_mgmt_desc cdc_mgmt;
  48. struct usb_cdc_acm_desc cdc_acm;
  49. struct usb_cdc_union_desc cdc_union;
  50. struct usb_endpoint_descriptor comm_ep;
  51. struct usb_interface_descriptor data;
  52. struct usb_endpoint_descriptor data_eprx;
  53. struct usb_endpoint_descriptor data_eptx;
  54. #ifdef ENABLE_HID_COMBO
  55. struct usb_interface_descriptor hid;
  56. struct usb_hid_descriptor hid_desc;
  57. struct usb_endpoint_descriptor hid_ep;
  58. #endif //ENABLE_HID_COMBO
  59. } __attribute__((packed));
  60. /* HID mouse report desscriptor. 2 axis 5 buttons */
  61. static const uint8_t hid_report_desc[] = {
  62. HID_USAGE_PAGE(HID_PAGE_DESKTOP),
  63. HID_USAGE(HID_DESKTOP_MOUSE),
  64. HID_COLLECTION(HID_APPLICATION_COLLECTION),
  65. HID_USAGE(HID_DESKTOP_POINTER),
  66. HID_COLLECTION(HID_PHYSICAL_COLLECTION),
  67. HID_USAGE(HID_DESKTOP_X),
  68. HID_USAGE(HID_DESKTOP_Y),
  69. HID_LOGICAL_MINIMUM(-127),
  70. HID_LOGICAL_MAXIMUM(127),
  71. HID_REPORT_SIZE(8),
  72. HID_REPORT_COUNT(2),
  73. HID_INPUT(HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_RELATIVE ),
  74. HID_USAGE_PAGE(HID_PAGE_BUTTON),
  75. HID_USAGE_MINIMUM(1),
  76. HID_USAGE_MAXIMUM(5),
  77. HID_LOGICAL_MINIMUM(0),
  78. HID_LOGICAL_MAXIMUM(1),
  79. HID_REPORT_SIZE(1),
  80. HID_REPORT_COUNT(5),
  81. HID_INPUT(HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE ),
  82. HID_REPORT_SIZE(1),
  83. HID_REPORT_COUNT(3),
  84. HID_INPUT(HID_IOF_CONSTANT),
  85. HID_END_COLLECTION,
  86. HID_END_COLLECTION,
  87. };
  88. /* Device descriptor */
  89. static const struct usb_device_descriptor device_desc = {
  90. .bLength = sizeof(struct usb_device_descriptor),
  91. .bDescriptorType = USB_DTYPE_DEVICE,
  92. .bcdUSB = VERSION_BCD(2,0,0),
  93. .bDeviceClass = USB_CLASS_IAD,
  94. .bDeviceSubClass = USB_SUBCLASS_IAD,
  95. .bDeviceProtocol = USB_PROTO_IAD,
  96. .bMaxPacketSize0 = CDC_EP0_SIZE,
  97. .idVendor = 0x0483,
  98. .idProduct = 0x5740,
  99. .bcdDevice = VERSION_BCD(1,0,0),
  100. .iManufacturer = 1,
  101. .iProduct = 2,
  102. .iSerialNumber = INTSERIALNO_DESCRIPTOR,
  103. .bNumConfigurations = 1,
  104. };
  105. /* Device configuration descriptor */
  106. static const struct cdc_config config_desc = {
  107. .config = {
  108. .bLength = sizeof(struct usb_config_descriptor),
  109. .bDescriptorType = USB_DTYPE_CONFIGURATION,
  110. .wTotalLength = sizeof(struct cdc_config),
  111. #ifdef ENABLE_HID_COMBO
  112. .bNumInterfaces = 3,
  113. #else
  114. .bNumInterfaces = 2,
  115. #endif //ENABLE_HID_COMBO
  116. .bConfigurationValue = 1,
  117. .iConfiguration = NO_DESCRIPTOR,
  118. .bmAttributes = USB_CFG_ATTR_RESERVED | USB_CFG_ATTR_SELFPOWERED,
  119. .bMaxPower = USB_CFG_POWER_MA(100),
  120. },
  121. .comm_iad = {
  122. .bLength = sizeof(struct usb_iad_descriptor),
  123. .bDescriptorType = USB_DTYPE_INTERFASEASSOC,
  124. .bFirstInterface = 0,
  125. .bInterfaceCount = 2,
  126. .bFunctionClass = USB_CLASS_CDC,
  127. .bFunctionSubClass = USB_CDC_SUBCLASS_ACM,
  128. .bFunctionProtocol = CDC_PROTOCOL,
  129. .iFunction = NO_DESCRIPTOR,
  130. },
  131. .comm = {
  132. .bLength = sizeof(struct usb_interface_descriptor),
  133. .bDescriptorType = USB_DTYPE_INTERFACE,
  134. .bInterfaceNumber = 0,
  135. .bAlternateSetting = 0,
  136. .bNumEndpoints = 1,
  137. .bInterfaceClass = USB_CLASS_CDC,
  138. .bInterfaceSubClass = USB_CDC_SUBCLASS_ACM,
  139. .bInterfaceProtocol = CDC_PROTOCOL,
  140. .iInterface = NO_DESCRIPTOR,
  141. },
  142. .cdc_hdr = {
  143. .bFunctionLength = sizeof(struct usb_cdc_header_desc),
  144. .bDescriptorType = USB_DTYPE_CS_INTERFACE,
  145. .bDescriptorSubType = USB_DTYPE_CDC_HEADER,
  146. .bcdCDC = VERSION_BCD(1,1,0),
  147. },
  148. .cdc_mgmt = {
  149. .bFunctionLength = sizeof(struct usb_cdc_call_mgmt_desc),
  150. .bDescriptorType = USB_DTYPE_CS_INTERFACE,
  151. .bDescriptorSubType = USB_DTYPE_CDC_CALL_MANAGEMENT,
  152. .bmCapabilities = 0,
  153. .bDataInterface = 1,
  154. },
  155. .cdc_acm = {
  156. .bFunctionLength = sizeof(struct usb_cdc_acm_desc),
  157. .bDescriptorType = USB_DTYPE_CS_INTERFACE,
  158. .bDescriptorSubType = USB_DTYPE_CDC_ACM,
  159. .bmCapabilities = 0,
  160. },
  161. .cdc_union = {
  162. .bFunctionLength = sizeof(struct usb_cdc_union_desc),
  163. .bDescriptorType = USB_DTYPE_CS_INTERFACE,
  164. .bDescriptorSubType = USB_DTYPE_CDC_UNION,
  165. .bMasterInterface0 = 0,
  166. .bSlaveInterface0 = 1,
  167. },
  168. .comm_ep = {
  169. .bLength = sizeof(struct usb_endpoint_descriptor),
  170. .bDescriptorType = USB_DTYPE_ENDPOINT,
  171. .bEndpointAddress = CDC_NTF_EP,
  172. .bmAttributes = USB_EPTYPE_INTERRUPT,
  173. .wMaxPacketSize = CDC_NTF_SZ,
  174. .bInterval = 0xFF,
  175. },
  176. .data = {
  177. .bLength = sizeof(struct usb_interface_descriptor),
  178. .bDescriptorType = USB_DTYPE_INTERFACE,
  179. .bInterfaceNumber = 1,
  180. .bAlternateSetting = 0,
  181. .bNumEndpoints = 2,
  182. .bInterfaceClass = USB_CLASS_CDC_DATA,
  183. .bInterfaceSubClass = USB_SUBCLASS_NONE,
  184. .bInterfaceProtocol = USB_PROTO_NONE,
  185. .iInterface = NO_DESCRIPTOR,
  186. },
  187. .data_eprx = {
  188. .bLength = sizeof(struct usb_endpoint_descriptor),
  189. .bDescriptorType = USB_DTYPE_ENDPOINT,
  190. .bEndpointAddress = CDC_RXD_EP,
  191. .bmAttributes = USB_EPTYPE_BULK,
  192. .wMaxPacketSize = CDC_DATA_SZ,
  193. .bInterval = 0x01,
  194. },
  195. .data_eptx = {
  196. .bLength = sizeof(struct usb_endpoint_descriptor),
  197. .bDescriptorType = USB_DTYPE_ENDPOINT,
  198. .bEndpointAddress = CDC_TXD_EP,
  199. .bmAttributes = USB_EPTYPE_BULK,
  200. .wMaxPacketSize = CDC_DATA_SZ,
  201. .bInterval = 0x01,
  202. },
  203. #ifdef ENABLE_HID_COMBO
  204. .hid = {
  205. .bLength = sizeof(struct usb_interface_descriptor),
  206. .bDescriptorType = USB_DTYPE_INTERFACE,
  207. .bInterfaceNumber = 2,
  208. .bAlternateSetting = 0,
  209. .bNumEndpoints = 1,
  210. .bInterfaceClass = USB_CLASS_HID,
  211. .bInterfaceSubClass = USB_HID_SUBCLASS_NONBOOT,
  212. .bInterfaceProtocol = USB_HID_PROTO_NONBOOT,
  213. .iInterface = NO_DESCRIPTOR,
  214. },
  215. .hid_desc = {
  216. .bLength = sizeof(struct usb_hid_descriptor),
  217. .bDescriptorType = USB_DTYPE_HID,
  218. .bcdHID = VERSION_BCD(1,0,0),
  219. .bCountryCode = USB_HID_COUNTRY_NONE,
  220. .bNumDescriptors = 1,
  221. .bDescriptorType0 = USB_DTYPE_HID_REPORT,
  222. .wDescriptorLength0 = sizeof(hid_report_desc),
  223. },
  224. .hid_ep = {
  225. .bLength = sizeof(struct usb_endpoint_descriptor),
  226. .bDescriptorType = USB_DTYPE_ENDPOINT,
  227. .bEndpointAddress = HID_RIN_EP,
  228. .bmAttributes = USB_EPTYPE_INTERRUPT,
  229. .wMaxPacketSize = HID_RIN_SZ,
  230. .bInterval = 50,
  231. },
  232. #endif // ENABLE_HID_COMBO
  233. };
  234. static const struct usb_string_descriptor lang_desc = USB_ARRAY_DESC(USB_LANGID_ENG_US);
  235. static const struct usb_string_descriptor manuf_desc_en = USB_STRING_DESC("Open source USB stack for STM32");
  236. static const struct usb_string_descriptor prod_desc_en = USB_STRING_DESC("CDC Loopback demo");
  237. static const struct usb_string_descriptor *const dtable[] = {
  238. &lang_desc,
  239. &manuf_desc_en,
  240. &prod_desc_en,
  241. };
  242. usbd_device udev;
  243. uint32_t ubuf[0x20];
  244. uint8_t fifo[0x200];
  245. uint32_t fpos = 0;
  246. static struct usb_cdc_line_coding cdc_line = {
  247. .dwDTERate = 38400,
  248. .bCharFormat = USB_CDC_1_STOP_BITS,
  249. .bParityType = USB_CDC_NO_PARITY,
  250. .bDataBits = 8,
  251. };
  252. static struct {
  253. int8_t x;
  254. int8_t y;
  255. uint8_t buttons;
  256. } __attribute__((packed)) hid_report_data;
  257. static usbd_respond cdc_getdesc (usbd_ctlreq *req, void **address, uint16_t *length) {
  258. const uint8_t dtype = req->wValue >> 8;
  259. const uint8_t dnumber = req->wValue & 0xFF;
  260. const void* desc;
  261. uint16_t len = 0;
  262. switch (dtype) {
  263. case USB_DTYPE_DEVICE:
  264. desc = &device_desc;
  265. break;
  266. case USB_DTYPE_CONFIGURATION:
  267. desc = &config_desc;
  268. len = sizeof(config_desc);
  269. break;
  270. case USB_DTYPE_STRING:
  271. if (dnumber < 3) {
  272. desc = dtable[dnumber];
  273. } else {
  274. return usbd_fail;
  275. }
  276. break;
  277. default:
  278. return usbd_fail;
  279. }
  280. if (len == 0) {
  281. len = ((struct usb_header_descriptor*)desc)->bLength;
  282. }
  283. *address = (void*)desc;
  284. *length = len;
  285. return usbd_ack;
  286. }
  287. static usbd_respond cdc_control(usbd_device *dev, usbd_ctlreq *req, usbd_rqc_callback *callback) {
  288. if (((USB_REQ_RECIPIENT | USB_REQ_TYPE) & req->bmRequestType) == (USB_REQ_INTERFACE | USB_REQ_CLASS)
  289. && req->wIndex == 0 ) {
  290. switch (req->bRequest) {
  291. case USB_CDC_SET_CONTROL_LINE_STATE:
  292. return usbd_ack;
  293. case USB_CDC_SET_LINE_CODING:
  294. memcpy(&cdc_line, req->data, sizeof(cdc_line));
  295. return usbd_ack;
  296. case USB_CDC_GET_LINE_CODING:
  297. dev->status.data_ptr = &cdc_line;
  298. dev->status.data_count = sizeof(cdc_line);
  299. return usbd_ack;
  300. default:
  301. return usbd_fail;
  302. }
  303. }
  304. #ifdef ENABLE_HID_COMBO
  305. if (((USB_REQ_RECIPIENT | USB_REQ_TYPE) & req->bmRequestType) == (USB_REQ_INTERFACE | USB_REQ_CLASS)
  306. && req->wIndex == 2 ) {
  307. switch (req->bRequest) {
  308. case USB_HID_SETIDLE:
  309. return usbd_ack;
  310. case USB_HID_GETREPORT:
  311. dev->status.data_ptr = &hid_report_data;
  312. dev->status.data_count = sizeof(hid_report_data);
  313. return usbd_ack;
  314. default:
  315. return usbd_fail;
  316. }
  317. }
  318. if (((USB_REQ_RECIPIENT | USB_REQ_TYPE) & req->bmRequestType) == (USB_REQ_INTERFACE | USB_REQ_STANDARD)
  319. && req->wIndex == 2
  320. && req->bRequest == USB_STD_GET_DESCRIPTOR) {
  321. switch (req->wValue >> 8) {
  322. case USB_DTYPE_HID:
  323. dev->status.data_ptr = (uint8_t*)&(config_desc.hid_desc);
  324. dev->status.data_count = sizeof(config_desc.hid_desc);
  325. return usbd_ack;
  326. case USB_DTYPE_HID_REPORT:
  327. dev->status.data_ptr = (uint8_t*)hid_report_desc;
  328. dev->status.data_count = sizeof(hid_report_desc);
  329. return usbd_ack;
  330. default:
  331. return usbd_fail;
  332. }
  333. }
  334. #endif // ENABLE_HID_COMBO
  335. return usbd_fail;
  336. }
  337. static void cdc_rxonly (usbd_device *dev, uint8_t event, uint8_t ep) {
  338. usbd_ep_read(dev, ep, fifo, CDC_DATA_SZ);
  339. }
  340. static void cdc_txonly(usbd_device *dev, uint8_t event, uint8_t ep) {
  341. static uint8_t psize = 0x00U;
  342. static uint8_t remained = 0x00U;
  343. static uint8_t lastsym = 0x00U;
  344. uint8_t _t = (remained < CDC_DATA_SZ) ? remained : CDC_DATA_SZ;
  345. // fill buffer by sequental data
  346. for (size_t i = 0; i < _t; ++i) {
  347. fifo[i] = lastsym++;
  348. }
  349. usbd_ep_write(dev, ep, fifo, _t);
  350. if (remained < CDC_DATA_SZ) {
  351. // bulk xfer completed. increase bulk size
  352. remained = ++psize;
  353. } else {
  354. // continue to send remained data or ZLP
  355. remained -= _t;
  356. }
  357. }
  358. static void cdc_rxtx(usbd_device *dev, uint8_t event, uint8_t ep) {
  359. if (event == usbd_evt_eptx) {
  360. cdc_txonly(dev, event, ep);
  361. } else {
  362. cdc_rxonly(dev, event, ep);
  363. }
  364. }
  365. /* HID mouse IN endpoint callback */
  366. static void hid_mouse_move(usbd_device *dev, uint8_t event, uint8_t ep) {
  367. static uint8_t t = 0;
  368. if (t < 0x10) {
  369. hid_report_data.x = 1;
  370. hid_report_data.y = 0;
  371. } else if (t < 0x20) {
  372. hid_report_data.x = 1;
  373. hid_report_data.y = 1;
  374. } else if (t < 0x30) {
  375. hid_report_data.x = 0;
  376. hid_report_data.y = 1;
  377. } else if (t < 0x40) {
  378. hid_report_data.x = -1;
  379. hid_report_data.y = 1;
  380. } else if (t < 0x50) {
  381. hid_report_data.x = -1;
  382. hid_report_data.y = 0;
  383. } else if (t < 0x60) {
  384. hid_report_data.x = -1;
  385. hid_report_data.y = -1;
  386. } else if (t < 0x70) {
  387. hid_report_data.x = 0;
  388. hid_report_data.y = -1;
  389. } else {
  390. hid_report_data.x = 1;
  391. hid_report_data.y = -1;
  392. }
  393. t = (t + 1) & 0x7F;
  394. usbd_ep_write(dev, ep, &hid_report_data, sizeof(hid_report_data));
  395. }
  396. /* CDC loop callback. Both for the Data IN and Data OUT endpoint */
  397. static void cdc_loopback(usbd_device *dev, uint8_t event, uint8_t ep) {
  398. int _t;
  399. if (fpos <= (sizeof(fifo) - CDC_DATA_SZ)) {
  400. _t = usbd_ep_read(dev, CDC_RXD_EP, &fifo[fpos], CDC_DATA_SZ);
  401. if (_t > 0) {
  402. fpos += _t;
  403. }
  404. }
  405. if (fpos > 0) {
  406. _t = usbd_ep_write(dev, CDC_TXD_EP, &fifo[0], (fpos < CDC_DATA_SZ) ? fpos : CDC_DATA_SZ);
  407. if (_t > 0) {
  408. memmove(&fifo[0], &fifo[_t], fpos - _t);
  409. fpos -= _t;
  410. }
  411. }
  412. }
  413. static usbd_respond cdc_setconf (usbd_device *dev, uint8_t cfg) {
  414. switch (cfg) {
  415. case 0:
  416. /* deconfiguring device */
  417. #ifdef ENABLE_HID_COMBO
  418. usbd_ep_deconfig(dev, HID_RIN_EP);
  419. usbd_reg_endpoint(dev, HID_RIN_EP, 0);
  420. #endif // ENABLE_HID_COMBO
  421. usbd_ep_deconfig(dev, CDC_NTF_EP);
  422. usbd_ep_deconfig(dev, CDC_TXD_EP);
  423. usbd_ep_deconfig(dev, CDC_RXD_EP);
  424. usbd_reg_endpoint(dev, CDC_RXD_EP, 0);
  425. usbd_reg_endpoint(dev, CDC_TXD_EP, 0);
  426. return usbd_ack;
  427. case 1:
  428. /* configuring device */
  429. usbd_ep_config(dev, CDC_RXD_EP, USB_EPTYPE_BULK /*| USB_EPTYPE_DBLBUF*/, CDC_DATA_SZ);
  430. usbd_ep_config(dev, CDC_TXD_EP, USB_EPTYPE_BULK /*| USB_EPTYPE_DBLBUF*/, CDC_DATA_SZ);
  431. usbd_ep_config(dev, CDC_NTF_EP, USB_EPTYPE_INTERRUPT, CDC_NTF_SZ);
  432. #if defined(CDC_LOOPBACK)
  433. usbd_reg_endpoint(dev, CDC_RXD_EP, cdc_loopback);
  434. usbd_reg_endpoint(dev, CDC_TXD_EP, cdc_loopback);
  435. #elif ((CDC_TXD_EP & 0x7F) == (CDC_RXD_EP & 0x7F))
  436. usbd_reg_endpoint(dev, CDC_RXD_EP, cdc_rxtx);
  437. usbd_reg_endpoint(dev, CDC_TXD_EP, cdc_rxtx);
  438. #else
  439. usbd_reg_endpoint(dev, CDC_RXD_EP, cdc_rxonly);
  440. usbd_reg_endpoint(dev, CDC_TXD_EP, cdc_txonly);
  441. #endif
  442. #ifdef ENABLE_HID_COMBO
  443. usbd_ep_config(dev, HID_RIN_EP, USB_EPTYPE_INTERRUPT, HID_RIN_SZ);
  444. usbd_reg_endpoint(dev, HID_RIN_EP, hid_mouse_move);
  445. usbd_ep_write(dev, HID_RIN_EP, 0, 0);
  446. #endif // ENABLE_HID_COMBO
  447. usbd_ep_write(dev, CDC_TXD_EP, 0, 0);
  448. return usbd_ack;
  449. default:
  450. return usbd_fail;
  451. }
  452. }
  453. static void cdc_init_usbd(void) {
  454. usbd_init(&udev, &usbd_hw, CDC_EP0_SIZE, ubuf, sizeof(ubuf));
  455. usbd_reg_config(&udev, cdc_setconf);
  456. usbd_reg_control(&udev, cdc_control);
  457. usbd_reg_descr(&udev, cdc_getdesc);
  458. }
  459. #if defined(CDC_USE_IRQ)
  460. #if defined(STM32L052xx) || defined(STM32F070xB) || \
  461. defined(STM32F042x6)
  462. #define USB_HANDLER USB_IRQHandler
  463. #define USB_NVIC_IRQ USB_IRQn
  464. #elif defined(STM32L100xC) || defined(STM32G4)
  465. #define USB_HANDLER USB_LP_IRQHandler
  466. #define USB_NVIC_IRQ USB_LP_IRQn
  467. #elif defined(USBD_PRIMARY_OTGHS) && \
  468. (defined(STM32F446xx) || defined(STM32F429xx))
  469. #define USB_HANDLER OTG_HS_IRQHandler
  470. #define USB_NVIC_IRQ OTG_HS_IRQn
  471. /* WA. With __WFI/__WFE interrupt will not be fired
  472. * faced with F4 series and OTGHS only
  473. */
  474. #undef __WFI
  475. #define __WFI __NOP
  476. #elif defined(STM32L476xx) || defined(STM32F429xx) || \
  477. defined(STM32F105xC) || defined(STM32F107xC) || \
  478. defined(STM32F446xx) || defined(STM32F411xE) || \
  479. defined(STM32H743xx)
  480. #define USB_HANDLER OTG_FS_IRQHandler
  481. #define USB_NVIC_IRQ OTG_FS_IRQn
  482. #elif defined(STM32F103x6)
  483. #define USB_HANDLER USB_LP_CAN1_RX0_IRQHandler
  484. #define USB_NVIC_IRQ USB_LP_CAN1_RX0_IRQn
  485. #elif defined(STM32F103xE)
  486. #define USB_HANDLER USB_LP_CAN1_RX0_IRQHandler
  487. #define USB_NVIC_IRQ USB_LP_CAN1_RX0_IRQn
  488. #else
  489. #error Not supported
  490. #endif
  491. void USB_HANDLER(void) {
  492. usbd_poll(&udev);
  493. }
  494. void main(void) {
  495. cdc_init_usbd();
  496. NVIC_EnableIRQ(USB_NVIC_IRQ);
  497. usbd_enable(&udev, true);
  498. usbd_connect(&udev, true);
  499. while(1) {
  500. __WFI();
  501. }
  502. }
  503. #else
  504. int main(void) {
  505. cdc_init_usbd();
  506. usbd_enable(&udev, true);
  507. usbd_connect(&udev, true);
  508. while(1) {
  509. usbd_poll(&udev);
  510. }
  511. return 0;
  512. }
  513. #endif