winusb2.0_cdc_template.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466
  1. /*
  2. * Copyright (c) 2024, sakumisu
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. #include "usbd_core.h"
  7. #include "usbd_cdc_acm.h"
  8. #define WINUSB_IN_EP 0x81
  9. #define WINUSB_OUT_EP 0x02
  10. #define CDC_IN_EP 0x83
  11. #define CDC_OUT_EP 0x04
  12. #define CDC_INT_EP 0x85
  13. #define USBD_VID 0xFFFE
  14. #define USBD_PID 0xFFFF
  15. #define USBD_MAX_POWER 500
  16. #define USBD_LANGID_STRING 1033
  17. #define USB_CONFIG_SIZE (9 + 9 + 7 + 7 + CDC_ACM_DESCRIPTOR_LEN)
  18. #define INTF_NUM 3
  19. #ifdef CONFIG_USB_HS
  20. #define WINUSB_EP_MPS 512
  21. #else
  22. #define WINUSB_EP_MPS 64
  23. #endif
  24. #define USBD_WINUSB_VENDOR_CODE 0x20
  25. #define USBD_WEBUSB_ENABLE 0
  26. #define USBD_BULK_ENABLE 1
  27. #define USBD_WINUSB_ENABLE 1
  28. /* WinUSB Microsoft OS 2.0 descriptor sizes */
  29. #define WINUSB_DESCRIPTOR_SET_HEADER_SIZE 10
  30. #define WINUSB_FUNCTION_SUBSET_HEADER_SIZE 8
  31. #define WINUSB_FEATURE_COMPATIBLE_ID_SIZE 20
  32. #define FUNCTION_SUBSET_LEN 160
  33. #define DEVICE_INTERFACE_GUIDS_FEATURE_LEN 132
  34. #define USBD_WINUSB_DESC_SET_LEN (WINUSB_DESCRIPTOR_SET_HEADER_SIZE + USBD_WEBUSB_ENABLE * FUNCTION_SUBSET_LEN + USBD_BULK_ENABLE * FUNCTION_SUBSET_LEN)
  35. __ALIGN_BEGIN const uint8_t USBD_WinUSBDescriptorSetDescriptor[] = {
  36. WBVAL(WINUSB_DESCRIPTOR_SET_HEADER_SIZE), /* wLength */
  37. WBVAL(WINUSB_SET_HEADER_DESCRIPTOR_TYPE), /* wDescriptorType */
  38. 0x00, 0x00, 0x03, 0x06, /* >= Win 8.1 */ /* dwWindowsVersion*/
  39. WBVAL(USBD_WINUSB_DESC_SET_LEN), /* wDescriptorSetTotalLength */
  40. #if (USBD_WEBUSB_ENABLE)
  41. WBVAL(WINUSB_FUNCTION_SUBSET_HEADER_SIZE), // wLength
  42. WBVAL(WINUSB_SUBSET_HEADER_FUNCTION_TYPE), // wDescriptorType
  43. 0, // bFirstInterface USBD_WINUSB_IF_NUM
  44. 0, // bReserved
  45. WBVAL(FUNCTION_SUBSET_LEN), // wSubsetLength
  46. WBVAL(WINUSB_FEATURE_COMPATIBLE_ID_SIZE), // wLength
  47. WBVAL(WINUSB_FEATURE_COMPATIBLE_ID_TYPE), // wDescriptorType
  48. 'W', 'I', 'N', 'U', 'S', 'B', 0, 0, // CompatibleId
  49. 0, 0, 0, 0, 0, 0, 0, 0, // SubCompatibleId
  50. WBVAL(DEVICE_INTERFACE_GUIDS_FEATURE_LEN), // wLength
  51. WBVAL(WINUSB_FEATURE_REG_PROPERTY_TYPE), // wDescriptorType
  52. WBVAL(WINUSB_PROP_DATA_TYPE_REG_MULTI_SZ), // wPropertyDataType
  53. WBVAL(42), // wPropertyNameLength
  54. 'D', 0, 'e', 0, 'v', 0, 'i', 0, 'c', 0, 'e', 0,
  55. 'I', 0, 'n', 0, 't', 0, 'e', 0, 'r', 0, 'f', 0, 'a', 0, 'c', 0, 'e', 0,
  56. 'G', 0, 'U', 0, 'I', 0, 'D', 0, 's', 0, 0, 0,
  57. WBVAL(80), // wPropertyDataLength
  58. '{', 0,
  59. '9', 0, '2', 0, 'C', 0, 'E', 0, '6', 0, '4', 0, '6', 0, '2', 0, '-', 0,
  60. '9', 0, 'C', 0, '7', 0, '7', 0, '-', 0,
  61. '4', 0, '6', 0, 'F', 0, 'E', 0, '-', 0,
  62. '9', 0, '3', 0, '3', 0, 'B', 0, '-',
  63. 0, '3', 0, '1', 0, 'C', 0, 'B', 0, '9', 0, 'C', 0, '5', 0, 'A', 0, 'A', 0, '3', 0, 'B', 0, '9', 0,
  64. '}', 0, 0, 0, 0, 0
  65. #endif
  66. #if USBD_BULK_ENABLE
  67. WBVAL(WINUSB_FUNCTION_SUBSET_HEADER_SIZE), /* wLength */
  68. WBVAL(WINUSB_SUBSET_HEADER_FUNCTION_TYPE), /* wDescriptorType */
  69. 0, /* bFirstInterface USBD_BULK_IF_NUM*/
  70. 0, /* bReserved */
  71. WBVAL(FUNCTION_SUBSET_LEN), /* wSubsetLength */
  72. WBVAL(WINUSB_FEATURE_COMPATIBLE_ID_SIZE), /* wLength */
  73. WBVAL(WINUSB_FEATURE_COMPATIBLE_ID_TYPE), /* wDescriptorType */
  74. 'W', 'I', 'N', 'U', 'S', 'B', 0, 0, /* CompatibleId*/
  75. 0, 0, 0, 0, 0, 0, 0, 0, /* SubCompatibleId*/
  76. WBVAL(DEVICE_INTERFACE_GUIDS_FEATURE_LEN), /* wLength */
  77. WBVAL(WINUSB_FEATURE_REG_PROPERTY_TYPE), /* wDescriptorType */
  78. WBVAL(WINUSB_PROP_DATA_TYPE_REG_MULTI_SZ), /* wPropertyDataType */
  79. WBVAL(42), /* wPropertyNameLength */
  80. 'D', 0, 'e', 0, 'v', 0, 'i', 0, 'c', 0, 'e', 0,
  81. 'I', 0, 'n', 0, 't', 0, 'e', 0, 'r', 0, 'f', 0, 'a', 0, 'c', 0, 'e', 0,
  82. 'G', 0, 'U', 0, 'I', 0, 'D', 0, 's', 0, 0, 0,
  83. WBVAL(80), /* wPropertyDataLength */
  84. '{', 0,
  85. 'C', 0, 'D', 0, 'B', 0, '3', 0, 'B', 0, '5', 0, 'A', 0, 'D', 0, '-', 0,
  86. '2', 0, '9', 0, '3', 0, 'B', 0, '-', 0,
  87. '4', 0, '6', 0, '6', 0, '3', 0, '-', 0,
  88. 'A', 0, 'A', 0, '3', 0, '6', 0, '-',
  89. 0, '1', 0, 'A', 0, 'A', 0, 'E', 0, '4', 0, '6', 0, '4', 0, '6', 0, '3', 0, '7', 0, '7', 0, '6', 0,
  90. '}', 0, 0, 0, 0, 0
  91. #endif
  92. };
  93. #define USBD_NUM_DEV_CAPABILITIES (USBD_WEBUSB_ENABLE + USBD_WINUSB_ENABLE)
  94. #define USBD_WEBUSB_DESC_LEN 24
  95. #define USBD_WINUSB_DESC_LEN 28
  96. #define USBD_BOS_WTOTALLENGTH (0x05 + \
  97. USBD_WEBUSB_DESC_LEN * USBD_WEBUSB_ENABLE + \
  98. USBD_WINUSB_DESC_LEN * USBD_WINUSB_ENABLE)
  99. __ALIGN_BEGIN const uint8_t USBD_BinaryObjectStoreDescriptor[] = {
  100. 0x05, /* bLength */
  101. 0x0f, /* bDescriptorType */
  102. WBVAL(USBD_BOS_WTOTALLENGTH), /* wTotalLength */
  103. USBD_NUM_DEV_CAPABILITIES, /* bNumDeviceCaps */
  104. #if (USBD_WEBUSB_ENABLE)
  105. USBD_WEBUSB_DESC_LEN, /* bLength */
  106. 0x10, /* bDescriptorType */
  107. USB_DEVICE_CAPABILITY_PLATFORM, /* bDevCapabilityType */
  108. 0x00, /* bReserved */
  109. 0x38, 0xB6, 0x08, 0x34, /* PlatformCapabilityUUID */
  110. 0xA9, 0x09, 0xA0, 0x47,
  111. 0x8B, 0xFD, 0xA0, 0x76,
  112. 0x88, 0x15, 0xB6, 0x65,
  113. WBVAL(0x0100), /* 1.00 */ /* bcdVersion */
  114. USBD_WINUSB_VENDOR_CODE, /* bVendorCode */
  115. 0, /* iLandingPage */
  116. #endif
  117. #if (USBD_WINUSB_ENABLE)
  118. USBD_WINUSB_DESC_LEN, /* bLength */
  119. 0x10, /* bDescriptorType */
  120. USB_DEVICE_CAPABILITY_PLATFORM, /* bDevCapabilityType */
  121. 0x00, /* bReserved */
  122. 0xDF, 0x60, 0xDD, 0xD8, /* PlatformCapabilityUUID */
  123. 0x89, 0x45, 0xC7, 0x4C,
  124. 0x9C, 0xD2, 0x65, 0x9D,
  125. 0x9E, 0x64, 0x8A, 0x9F,
  126. 0x00, 0x00, 0x03, 0x06, /* >= Win 8.1 */ /* dwWindowsVersion*/
  127. WBVAL(USBD_WINUSB_DESC_SET_LEN), /* wDescriptorSetTotalLength */
  128. USBD_WINUSB_VENDOR_CODE, /* bVendorCode */
  129. 0, /* bAltEnumCode */
  130. #endif
  131. };
  132. struct usb_msosv2_descriptor msosv2_desc = {
  133. .vendor_code = USBD_WINUSB_VENDOR_CODE,
  134. .compat_id = USBD_WinUSBDescriptorSetDescriptor,
  135. .compat_id_len = USBD_WINUSB_DESC_SET_LEN,
  136. };
  137. struct usb_bos_descriptor bos_desc = {
  138. .string = USBD_BinaryObjectStoreDescriptor,
  139. .string_len = USBD_BOS_WTOTALLENGTH
  140. };
  141. #ifdef CONFIG_USBDEV_ADVANCE_DESC
  142. static const uint8_t device_descriptor[] = {
  143. USB_DEVICE_DESCRIPTOR_INIT(USB_2_1, 0xEF, 0x02, 0x01, USBD_VID, USBD_PID, 0x0100, 0x01)
  144. };
  145. static const uint8_t config_descriptor[] = {
  146. /* Configuration 0 */
  147. USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, INTF_NUM, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
  148. /* Interface 0 */
  149. USB_INTERFACE_DESCRIPTOR_INIT(0x00, 0x00, 0x02, 0xFF, 0x00, 0x00, 0x02),
  150. /* Endpoint OUT 2 */
  151. USB_ENDPOINT_DESCRIPTOR_INIT(WINUSB_OUT_EP, USB_ENDPOINT_TYPE_BULK, WINUSB_EP_MPS, 0x00),
  152. /* Endpoint IN 1 */
  153. USB_ENDPOINT_DESCRIPTOR_INIT(WINUSB_IN_EP, USB_ENDPOINT_TYPE_BULK, WINUSB_EP_MPS, 0x00),
  154. CDC_ACM_DESCRIPTOR_INIT(0x01, CDC_INT_EP, CDC_OUT_EP, CDC_IN_EP, WINUSB_EP_MPS, 0x00)
  155. };
  156. static const uint8_t device_quality_descriptor[] = {
  157. ///////////////////////////////////////
  158. /// device qualifier descriptor
  159. ///////////////////////////////////////
  160. 0x0a,
  161. USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
  162. 0x10,
  163. 0x02,
  164. 0x00,
  165. 0x00,
  166. 0x00,
  167. 0x40,
  168. 0x00,
  169. 0x00,
  170. };
  171. static const char *string_descriptors[] = {
  172. (const char[]){ 0x09, 0x04 }, /* Langid */
  173. "CherryUSB", /* Manufacturer */
  174. "CherryUSB WINUSB DEMO", /* Product */
  175. "2022123456", /* Serial Number */
  176. };
  177. static const uint8_t *device_descriptor_callback(uint8_t speed)
  178. {
  179. return device_descriptor;
  180. }
  181. static const uint8_t *config_descriptor_callback(uint8_t speed)
  182. {
  183. return config_descriptor;
  184. }
  185. static const uint8_t *device_quality_descriptor_callback(uint8_t speed)
  186. {
  187. return device_quality_descriptor;
  188. }
  189. static const char *string_descriptor_callback(uint8_t speed, uint8_t index)
  190. {
  191. if (index > 3) {
  192. return NULL;
  193. }
  194. return string_descriptors[index];
  195. }
  196. const struct usb_descriptor winusbv2_descriptor = {
  197. .device_descriptor_callback = device_descriptor_callback,
  198. .config_descriptor_callback = config_descriptor_callback,
  199. .device_quality_descriptor_callback = device_quality_descriptor_callback,
  200. .string_descriptor_callback = string_descriptor_callback,
  201. .msosv2_descriptor = &msosv2_desc,
  202. .bos_descriptor = &bos_desc
  203. };
  204. #else
  205. const uint8_t winusbv2_descriptor[] = {
  206. USB_DEVICE_DESCRIPTOR_INIT(USB_2_1, 0xEF, 0x02, 0x01, USBD_VID, USBD_PID, 0x0100, 0x01),
  207. /* Configuration 0 */
  208. USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, INTF_NUM, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
  209. /* Interface 0 */
  210. USB_INTERFACE_DESCRIPTOR_INIT(0x00, 0x00, 0x02, 0xFF, 0x00, 0x00, 0x02),
  211. /* Endpoint OUT 2 */
  212. USB_ENDPOINT_DESCRIPTOR_INIT(WINUSB_OUT_EP, USB_ENDPOINT_TYPE_BULK, WINUSB_EP_MPS, 0x00),
  213. /* Endpoint IN 1 */
  214. USB_ENDPOINT_DESCRIPTOR_INIT(WINUSB_IN_EP, USB_ENDPOINT_TYPE_BULK, WINUSB_EP_MPS, 0x00),
  215. CDC_ACM_DESCRIPTOR_INIT(0x01, CDC_INT_EP, CDC_OUT_EP, CDC_IN_EP, WINUSB_EP_MPS, 0x00),
  216. /* String 0 (LANGID) */
  217. USB_LANGID_INIT(USBD_LANGID_STRING),
  218. /* String 1 (Manufacturer) */
  219. 0x14, /* bLength */
  220. USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
  221. 'C', 0x00, /* wcChar0 */
  222. 'h', 0x00, /* wcChar1 */
  223. 'e', 0x00, /* wcChar2 */
  224. 'r', 0x00, /* wcChar3 */
  225. 'r', 0x00, /* wcChar4 */
  226. 'y', 0x00, /* wcChar5 */
  227. 'U', 0x00, /* wcChar6 */
  228. 'S', 0x00, /* wcChar7 */
  229. 'B', 0x00, /* wcChar8 */
  230. ///////////////////////////////////////
  231. /// string2 descriptor
  232. ///////////////////////////////////////
  233. 0x2C, /* bLength */
  234. USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
  235. 'C', 0x00, /* wcChar0 */
  236. 'h', 0x00, /* wcChar1 */
  237. 'e', 0x00, /* wcChar2 */
  238. 'r', 0x00, /* wcChar3 */
  239. 'r', 0x00, /* wcChar4 */
  240. 'y', 0x00, /* wcChar5 */
  241. 'U', 0x00, /* wcChar6 */
  242. 'S', 0x00, /* wcChar7 */
  243. 'B', 0x00, /* wcChar8 */
  244. ' ', 0x00, /* wcChar9 */
  245. 'W', 0x00, /* wcChar10 */
  246. 'I', 0x00, /* wcChar11 */
  247. 'N', 0x00, /* wcChar12 */
  248. 'U', 0x00, /* wcChar13 */
  249. 'S', 0x00, /* wcChar14 */
  250. 'B', 0x00, /* wcChar15 */
  251. ' ', 0x00, /* wcChar16 */
  252. 'D', 0x00, /* wcChar17 */
  253. 'E', 0x00, /* wcChar18 */
  254. 'M', 0x00, /* wcChar19 */
  255. 'O', 0x00, /* wcChar20 */
  256. ///////////////////////////////////////
  257. /// string3 descriptor
  258. ///////////////////////////////////////
  259. 0x16, /* bLength */
  260. USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
  261. '2', 0x00, /* wcChar0 */
  262. '0', 0x00, /* wcChar1 */
  263. '2', 0x00, /* wcChar2 */
  264. '2', 0x00, /* wcChar3 */
  265. '1', 0x00, /* wcChar4 */
  266. '2', 0x00, /* wcChar5 */
  267. '3', 0x00, /* wcChar6 */
  268. '4', 0x00, /* wcChar7 */
  269. '5', 0x00, /* wcChar8 */
  270. '6', 0x00, /* wcChar9 */
  271. #ifdef CONFIG_USB_HS
  272. /* Device Qualifier */
  273. 0x0a,
  274. USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
  275. 0x10,
  276. 0x02,
  277. 0x00,
  278. 0x00,
  279. 0x00,
  280. 0x40,
  281. 0x00,
  282. 0x00,
  283. #endif
  284. /* End */
  285. 0x00
  286. };
  287. #endif
  288. USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t read_buffer[2048];
  289. USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t write_buffer[2048];
  290. volatile bool ep_tx_busy_flag = false;
  291. static void usbd_event_handler(uint8_t busid, uint8_t event)
  292. {
  293. switch (event) {
  294. case USBD_EVENT_RESET:
  295. break;
  296. case USBD_EVENT_CONNECTED:
  297. break;
  298. case USBD_EVENT_DISCONNECTED:
  299. break;
  300. case USBD_EVENT_RESUME:
  301. break;
  302. case USBD_EVENT_SUSPEND:
  303. break;
  304. case USBD_EVENT_CONFIGURED:
  305. ep_tx_busy_flag = false;
  306. /* setup first out ep read transfer */
  307. usbd_ep_start_read(busid, WINUSB_OUT_EP, read_buffer, 2048);
  308. usbd_ep_start_read(busid, CDC_OUT_EP, read_buffer, 2048);
  309. break;
  310. case USBD_EVENT_SET_REMOTE_WAKEUP:
  311. break;
  312. case USBD_EVENT_CLR_REMOTE_WAKEUP:
  313. break;
  314. default:
  315. break;
  316. }
  317. }
  318. void usbd_winusb_out(uint8_t busid, uint8_t ep, uint32_t nbytes)
  319. {
  320. USB_LOG_RAW("actual out len:%d\r\n", nbytes);
  321. // for (int i = 0; i < 100; i++) {
  322. // printf("%02x ", read_buffer[i]);
  323. // }
  324. // printf("\r\n");
  325. usbd_ep_start_write(busid, WINUSB_IN_EP, read_buffer, nbytes);
  326. /* setup next out ep read transfer */
  327. usbd_ep_start_read(busid, WINUSB_OUT_EP, read_buffer, 2048);
  328. }
  329. void usbd_winusb_in(uint8_t busid, uint8_t ep, uint32_t nbytes)
  330. {
  331. USB_LOG_RAW("actual in len:%d\r\n", nbytes);
  332. if ((nbytes % usbd_get_ep_mps(busid, ep)) == 0 && nbytes) {
  333. /* send zlp */
  334. usbd_ep_start_write(busid, WINUSB_IN_EP, NULL, 0);
  335. } else {
  336. ep_tx_busy_flag = false;
  337. }
  338. }
  339. void usbd_cdc_acm_out(uint8_t busid, uint8_t ep, uint32_t nbytes)
  340. {
  341. USB_LOG_RAW("actual out len:%d\r\n", nbytes);
  342. // for (int i = 0; i < 100; i++) {
  343. // printf("%02x ", read_buffer[i]);
  344. // }
  345. // printf("\r\n");
  346. usbd_ep_start_write(busid, CDC_IN_EP, read_buffer, nbytes);
  347. /* setup next out ep read transfer */
  348. usbd_ep_start_read(busid, CDC_OUT_EP, read_buffer, 2048);
  349. }
  350. void usbd_cdc_acm_in(uint8_t busid, uint8_t ep, uint32_t nbytes)
  351. {
  352. USB_LOG_RAW("actual in len:%d\r\n", nbytes);
  353. if ((nbytes % usbd_get_ep_mps(busid, ep)) == 0 && nbytes) {
  354. /* send zlp */
  355. usbd_ep_start_write(busid, CDC_IN_EP, NULL, 0);
  356. } else {
  357. ep_tx_busy_flag = false;
  358. }
  359. }
  360. struct usbd_endpoint winusb_out_ep1 = {
  361. .ep_addr = WINUSB_OUT_EP,
  362. .ep_cb = usbd_winusb_out
  363. };
  364. struct usbd_endpoint winusb_in_ep1 = {
  365. .ep_addr = WINUSB_IN_EP,
  366. .ep_cb = usbd_winusb_in
  367. };
  368. static struct usbd_endpoint cdc_out_ep = {
  369. .ep_addr = CDC_OUT_EP,
  370. .ep_cb = usbd_cdc_acm_out
  371. };
  372. static struct usbd_endpoint cdc_in_ep = {
  373. .ep_addr = CDC_IN_EP,
  374. .ep_cb = usbd_cdc_acm_in
  375. };
  376. struct usbd_interface winusb_intf;
  377. struct usbd_interface intf1;
  378. struct usbd_interface intf2;
  379. void winusbv2_init(uint8_t busid, uintptr_t reg_base)
  380. {
  381. #ifdef CONFIG_USBDEV_ADVANCE_DESC
  382. usbd_desc_register(busid, &winusbv2_descriptor);
  383. #else
  384. usbd_desc_register(busid, winusbv2_descriptor);
  385. #endif
  386. #ifndef CONFIG_USBDEV_ADVANCE_DESC
  387. usbd_bos_desc_register(busid, &bos_desc);
  388. usbd_msosv2_desc_register(busid, &msosv2_desc);
  389. #endif
  390. /*!< winusb */
  391. usbd_add_interface(busid, &winusb_intf);
  392. usbd_add_endpoint(busid, &winusb_out_ep1);
  393. usbd_add_endpoint(busid, &winusb_in_ep1);
  394. /*!< cdc acm */
  395. usbd_add_interface(busid, usbd_cdc_acm_init_intf(busid, &intf1));
  396. usbd_add_interface(busid, usbd_cdc_acm_init_intf(busid, &intf2));
  397. usbd_add_endpoint(busid, &cdc_out_ep);
  398. usbd_add_endpoint(busid, &cdc_in_ep);
  399. usbd_initialize(busid, reg_base, usbd_event_handler);
  400. }
  401. volatile uint8_t dtr_enable = 0;
  402. void usbd_cdc_acm_set_dtr(uint8_t busid, uint8_t intf, bool dtr)
  403. {
  404. if (dtr) {
  405. dtr_enable = 1;
  406. } else {
  407. dtr_enable = 0;
  408. }
  409. }
  410. void cdc_acm_data_send_with_dtr_test(uint8_t busid)
  411. {
  412. if (dtr_enable) {
  413. memset(&write_buffer[10], 'a', 2038);
  414. ep_tx_busy_flag = true;
  415. usbd_ep_start_write(busid, CDC_IN_EP, write_buffer, 2048);
  416. while (ep_tx_busy_flag) {
  417. }
  418. }
  419. }