winusb2.0_cdc_template.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360
  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_VENDOR_CODE 0x17
  9. const uint8_t WINUSB_WCIDDescriptor[] = {
  10. USB_MSOSV2_COMP_ID_SET_HEADER_DESCRIPTOR_INIT(10 + USB_MSOSV2_COMP_ID_FUNCTION_WINUSB_MULTI_DESCRIPTOR_LEN),
  11. USB_MSOSV2_COMP_ID_FUNCTION_WINUSB_MULTI_DESCRIPTOR_INIT(0x00),
  12. };
  13. __ALIGN_BEGIN const uint8_t USBD_BinaryObjectStoreDescriptor[] = {
  14. USB_BOS_HEADER_DESCRIPTOR_INIT(5 + USB_BOS_CAP_PLATFORM_WINUSB_DESCRIPTOR_LEN, 1),
  15. USB_BOS_CAP_PLATFORM_WINUSB_DESCRIPTOR_INIT(WINUSB_VENDOR_CODE, sizeof(WINUSB_WCIDDescriptor)),
  16. };
  17. const struct usb_msosv2_descriptor msosv2_desc = {
  18. .vendor_code = WINUSB_VENDOR_CODE,
  19. .compat_id = WINUSB_WCIDDescriptor,
  20. .compat_id_len = sizeof(WINUSB_WCIDDescriptor),
  21. };
  22. const struct usb_bos_descriptor bos_desc = {
  23. .string = USBD_BinaryObjectStoreDescriptor,
  24. .string_len = sizeof(USBD_BinaryObjectStoreDescriptor),
  25. };
  26. #define WINUSB_IN_EP 0x81
  27. #define WINUSB_OUT_EP 0x02
  28. #define CDC_IN_EP 0x83
  29. #define CDC_OUT_EP 0x04
  30. #define CDC_INT_EP 0x85
  31. #define USBD_VID 0xFFFE
  32. #define USBD_PID 0xFFFF
  33. #define USBD_MAX_POWER 500
  34. #define USBD_LANGID_STRING 1033
  35. #define USB_CONFIG_SIZE (9 + 9 + 7 + 7 + CDC_ACM_DESCRIPTOR_LEN)
  36. #define INTF_NUM 3
  37. #ifdef CONFIG_USB_HS
  38. #define WINUSB_EP_MPS 512
  39. #else
  40. #define WINUSB_EP_MPS 64
  41. #endif
  42. #ifdef CONFIG_USBDEV_ADVANCE_DESC
  43. static const uint8_t device_descriptor[] = {
  44. USB_DEVICE_DESCRIPTOR_INIT(USB_2_1, 0xEF, 0x02, 0x01, USBD_VID, USBD_PID, 0x0100, 0x01)
  45. };
  46. static const uint8_t config_descriptor[] = {
  47. /* Configuration 0 */
  48. USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, INTF_NUM, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
  49. /* Interface 0 */
  50. USB_INTERFACE_DESCRIPTOR_INIT(0x00, 0x00, 0x02, 0xFF, 0x00, 0x00, 0x02),
  51. /* Endpoint OUT 2 */
  52. USB_ENDPOINT_DESCRIPTOR_INIT(WINUSB_OUT_EP, USB_ENDPOINT_TYPE_BULK, WINUSB_EP_MPS, 0x00),
  53. /* Endpoint IN 1 */
  54. USB_ENDPOINT_DESCRIPTOR_INIT(WINUSB_IN_EP, USB_ENDPOINT_TYPE_BULK, WINUSB_EP_MPS, 0x00),
  55. CDC_ACM_DESCRIPTOR_INIT(0x01, CDC_INT_EP, CDC_OUT_EP, CDC_IN_EP, WINUSB_EP_MPS, 0x00)
  56. };
  57. static const uint8_t device_quality_descriptor[] = {
  58. ///////////////////////////////////////
  59. /// device qualifier descriptor
  60. ///////////////////////////////////////
  61. 0x0a,
  62. USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
  63. 0x10,
  64. 0x02,
  65. 0x00,
  66. 0x00,
  67. 0x00,
  68. 0x40,
  69. 0x00,
  70. 0x00,
  71. };
  72. static const char *string_descriptors[] = {
  73. (const char[]){ 0x09, 0x04 }, /* Langid */
  74. "CherryUSB", /* Manufacturer */
  75. "CherryUSB WINUSB DEMO", /* Product */
  76. "2022123456", /* Serial Number */
  77. };
  78. static const uint8_t *device_descriptor_callback(uint8_t speed)
  79. {
  80. return device_descriptor;
  81. }
  82. static const uint8_t *config_descriptor_callback(uint8_t speed)
  83. {
  84. return config_descriptor;
  85. }
  86. static const uint8_t *device_quality_descriptor_callback(uint8_t speed)
  87. {
  88. return device_quality_descriptor;
  89. }
  90. static const char *string_descriptor_callback(uint8_t speed, uint8_t index)
  91. {
  92. if (index > 3) {
  93. return NULL;
  94. }
  95. return string_descriptors[index];
  96. }
  97. const struct usb_descriptor winusbv2_cdc_descriptor = {
  98. .device_descriptor_callback = device_descriptor_callback,
  99. .config_descriptor_callback = config_descriptor_callback,
  100. .device_quality_descriptor_callback = device_quality_descriptor_callback,
  101. .string_descriptor_callback = string_descriptor_callback,
  102. .msosv2_descriptor = &msosv2_desc,
  103. .bos_descriptor = &bos_desc
  104. };
  105. #else
  106. const uint8_t winusbv2_cdc_descriptor[] = {
  107. USB_DEVICE_DESCRIPTOR_INIT(USB_2_1, 0xEF, 0x02, 0x01, USBD_VID, USBD_PID, 0x0100, 0x01),
  108. /* Configuration 0 */
  109. USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, INTF_NUM, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
  110. /* Interface 0 */
  111. USB_INTERFACE_DESCRIPTOR_INIT(0x00, 0x00, 0x02, 0xFF, 0x00, 0x00, 0x02),
  112. /* Endpoint OUT 2 */
  113. USB_ENDPOINT_DESCRIPTOR_INIT(WINUSB_OUT_EP, USB_ENDPOINT_TYPE_BULK, WINUSB_EP_MPS, 0x00),
  114. /* Endpoint IN 1 */
  115. USB_ENDPOINT_DESCRIPTOR_INIT(WINUSB_IN_EP, USB_ENDPOINT_TYPE_BULK, WINUSB_EP_MPS, 0x00),
  116. CDC_ACM_DESCRIPTOR_INIT(0x01, CDC_INT_EP, CDC_OUT_EP, CDC_IN_EP, WINUSB_EP_MPS, 0x00),
  117. /* String 0 (LANGID) */
  118. USB_LANGID_INIT(USBD_LANGID_STRING),
  119. /* String 1 (Manufacturer) */
  120. 0x14, /* bLength */
  121. USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
  122. 'C', 0x00, /* wcChar0 */
  123. 'h', 0x00, /* wcChar1 */
  124. 'e', 0x00, /* wcChar2 */
  125. 'r', 0x00, /* wcChar3 */
  126. 'r', 0x00, /* wcChar4 */
  127. 'y', 0x00, /* wcChar5 */
  128. 'U', 0x00, /* wcChar6 */
  129. 'S', 0x00, /* wcChar7 */
  130. 'B', 0x00, /* wcChar8 */
  131. ///////////////////////////////////////
  132. /// string2 descriptor
  133. ///////////////////////////////////////
  134. 0x2C, /* bLength */
  135. USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
  136. 'C', 0x00, /* wcChar0 */
  137. 'h', 0x00, /* wcChar1 */
  138. 'e', 0x00, /* wcChar2 */
  139. 'r', 0x00, /* wcChar3 */
  140. 'r', 0x00, /* wcChar4 */
  141. 'y', 0x00, /* wcChar5 */
  142. 'U', 0x00, /* wcChar6 */
  143. 'S', 0x00, /* wcChar7 */
  144. 'B', 0x00, /* wcChar8 */
  145. ' ', 0x00, /* wcChar9 */
  146. 'W', 0x00, /* wcChar10 */
  147. 'I', 0x00, /* wcChar11 */
  148. 'N', 0x00, /* wcChar12 */
  149. 'U', 0x00, /* wcChar13 */
  150. 'S', 0x00, /* wcChar14 */
  151. 'B', 0x00, /* wcChar15 */
  152. ' ', 0x00, /* wcChar16 */
  153. 'D', 0x00, /* wcChar17 */
  154. 'E', 0x00, /* wcChar18 */
  155. 'M', 0x00, /* wcChar19 */
  156. 'O', 0x00, /* wcChar20 */
  157. ///////////////////////////////////////
  158. /// string3 descriptor
  159. ///////////////////////////////////////
  160. 0x16, /* bLength */
  161. USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
  162. '2', 0x00, /* wcChar0 */
  163. '0', 0x00, /* wcChar1 */
  164. '2', 0x00, /* wcChar2 */
  165. '2', 0x00, /* wcChar3 */
  166. '1', 0x00, /* wcChar4 */
  167. '2', 0x00, /* wcChar5 */
  168. '3', 0x00, /* wcChar6 */
  169. '4', 0x00, /* wcChar7 */
  170. '5', 0x00, /* wcChar8 */
  171. '6', 0x00, /* wcChar9 */
  172. #ifdef CONFIG_USB_HS
  173. /* Device Qualifier */
  174. 0x0a,
  175. USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
  176. 0x10,
  177. 0x02,
  178. 0x00,
  179. 0x00,
  180. 0x00,
  181. 0x40,
  182. 0x00,
  183. 0x00,
  184. #endif
  185. /* End */
  186. 0x00
  187. };
  188. #endif
  189. USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t read_buffer[2048];
  190. USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t write_buffer[2048];
  191. volatile bool ep_tx_busy_flag = false;
  192. static void usbd_event_handler(uint8_t busid, uint8_t event)
  193. {
  194. switch (event) {
  195. case USBD_EVENT_RESET:
  196. break;
  197. case USBD_EVENT_CONNECTED:
  198. break;
  199. case USBD_EVENT_DISCONNECTED:
  200. break;
  201. case USBD_EVENT_RESUME:
  202. break;
  203. case USBD_EVENT_SUSPEND:
  204. break;
  205. case USBD_EVENT_CONFIGURED:
  206. ep_tx_busy_flag = false;
  207. /* setup first out ep read transfer */
  208. usbd_ep_start_read(busid, WINUSB_OUT_EP, read_buffer, 2048);
  209. usbd_ep_start_read(busid, CDC_OUT_EP, read_buffer, 2048);
  210. break;
  211. case USBD_EVENT_SET_REMOTE_WAKEUP:
  212. break;
  213. case USBD_EVENT_CLR_REMOTE_WAKEUP:
  214. break;
  215. default:
  216. break;
  217. }
  218. }
  219. void usbd_winusb_out(uint8_t busid, uint8_t ep, uint32_t nbytes)
  220. {
  221. USB_LOG_RAW("actual out len:%d\r\n", (unsigned int)nbytes);
  222. // for (int i = 0; i < 100; i++) {
  223. // printf("%02x ", read_buffer[i]);
  224. // }
  225. // printf("\r\n");
  226. usbd_ep_start_write(busid, WINUSB_IN_EP, read_buffer, nbytes);
  227. /* setup next out ep read transfer */
  228. usbd_ep_start_read(busid, WINUSB_OUT_EP, read_buffer, 2048);
  229. }
  230. void usbd_winusb_in(uint8_t busid, uint8_t ep, uint32_t nbytes)
  231. {
  232. USB_LOG_RAW("actual in len:%d\r\n", (unsigned int)nbytes);
  233. if ((nbytes % usbd_get_ep_mps(busid, ep)) == 0 && nbytes) {
  234. /* send zlp */
  235. usbd_ep_start_write(busid, WINUSB_IN_EP, NULL, 0);
  236. } else {
  237. ep_tx_busy_flag = false;
  238. }
  239. }
  240. void usbd_cdc_acm_out(uint8_t busid, uint8_t ep, uint32_t nbytes)
  241. {
  242. USB_LOG_RAW("actual out len:%d\r\n", (unsigned int)nbytes);
  243. // for (int i = 0; i < 100; i++) {
  244. // printf("%02x ", read_buffer[i]);
  245. // }
  246. // printf("\r\n");
  247. usbd_ep_start_write(busid, CDC_IN_EP, read_buffer, nbytes);
  248. /* setup next out ep read transfer */
  249. usbd_ep_start_read(busid, CDC_OUT_EP, read_buffer, 2048);
  250. }
  251. void usbd_cdc_acm_in(uint8_t busid, uint8_t ep, uint32_t nbytes)
  252. {
  253. USB_LOG_RAW("actual in len:%d\r\n", (unsigned int)nbytes);
  254. if ((nbytes % usbd_get_ep_mps(busid, ep)) == 0 && nbytes) {
  255. /* send zlp */
  256. usbd_ep_start_write(busid, CDC_IN_EP, NULL, 0);
  257. } else {
  258. ep_tx_busy_flag = false;
  259. }
  260. }
  261. struct usbd_endpoint winusb_out_ep1 = {
  262. .ep_addr = WINUSB_OUT_EP,
  263. .ep_cb = usbd_winusb_out
  264. };
  265. struct usbd_endpoint winusb_in_ep1 = {
  266. .ep_addr = WINUSB_IN_EP,
  267. .ep_cb = usbd_winusb_in
  268. };
  269. static struct usbd_endpoint cdc_out_ep = {
  270. .ep_addr = CDC_OUT_EP,
  271. .ep_cb = usbd_cdc_acm_out
  272. };
  273. static struct usbd_endpoint cdc_in_ep = {
  274. .ep_addr = CDC_IN_EP,
  275. .ep_cb = usbd_cdc_acm_in
  276. };
  277. struct usbd_interface winusb_intf;
  278. struct usbd_interface intf1;
  279. struct usbd_interface intf2;
  280. void winusbv2_cdc_init(uint8_t busid, uintptr_t reg_base)
  281. {
  282. #ifdef CONFIG_USBDEV_ADVANCE_DESC
  283. usbd_desc_register(busid, &winusbv2_cdc_descriptor);
  284. #else
  285. usbd_desc_register(busid, winusbv2_cdc_descriptor);
  286. #endif
  287. #ifndef CONFIG_USBDEV_ADVANCE_DESC
  288. usbd_bos_desc_register(busid, &bos_desc);
  289. usbd_msosv2_desc_register(busid, &msosv2_desc);
  290. #endif
  291. /*!< winusb */
  292. usbd_add_interface(busid, &winusb_intf);
  293. usbd_add_endpoint(busid, &winusb_out_ep1);
  294. usbd_add_endpoint(busid, &winusb_in_ep1);
  295. /*!< cdc acm */
  296. usbd_add_interface(busid, usbd_cdc_acm_init_intf(busid, &intf1));
  297. usbd_add_interface(busid, usbd_cdc_acm_init_intf(busid, &intf2));
  298. usbd_add_endpoint(busid, &cdc_out_ep);
  299. usbd_add_endpoint(busid, &cdc_in_ep);
  300. usbd_initialize(busid, reg_base, usbd_event_handler);
  301. }
  302. volatile uint8_t dtr_enable = 0;
  303. void usbd_cdc_acm_set_dtr(uint8_t busid, uint8_t intf, bool dtr)
  304. {
  305. if (dtr) {
  306. dtr_enable = 1;
  307. } else {
  308. dtr_enable = 0;
  309. }
  310. }
  311. void cdc_acm_data_send_with_dtr_test(uint8_t busid)
  312. {
  313. if (dtr_enable) {
  314. memset(&write_buffer[10], 'a', 2038);
  315. ep_tx_busy_flag = true;
  316. usbd_ep_start_write(busid, CDC_IN_EP, write_buffer, 2048);
  317. while (ep_tx_busy_flag) {
  318. }
  319. }
  320. }