winusb2.0_cdc_template.c 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268
  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. static const uint8_t device_descriptor[] = {
  43. USB_DEVICE_DESCRIPTOR_INIT(USB_2_1, 0xEF, 0x02, 0x01, USBD_VID, USBD_PID, 0x0100, 0x01)
  44. };
  45. static const uint8_t config_descriptor[] = {
  46. /* Configuration 0 */
  47. USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, INTF_NUM, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
  48. /* Interface 0 */
  49. USB_INTERFACE_DESCRIPTOR_INIT(0x00, 0x00, 0x02, 0xFF, 0x00, 0x00, 0x02),
  50. /* Endpoint OUT 2 */
  51. USB_ENDPOINT_DESCRIPTOR_INIT(WINUSB_OUT_EP, USB_ENDPOINT_TYPE_BULK, WINUSB_EP_MPS, 0x00),
  52. /* Endpoint IN 1 */
  53. USB_ENDPOINT_DESCRIPTOR_INIT(WINUSB_IN_EP, USB_ENDPOINT_TYPE_BULK, WINUSB_EP_MPS, 0x00),
  54. CDC_ACM_DESCRIPTOR_INIT(0x01, CDC_INT_EP, CDC_OUT_EP, CDC_IN_EP, WINUSB_EP_MPS, 0x00)
  55. };
  56. static const uint8_t device_quality_descriptor[] = {
  57. ///////////////////////////////////////
  58. /// device qualifier descriptor
  59. ///////////////////////////////////////
  60. 0x0a,
  61. USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
  62. 0x10,
  63. 0x02,
  64. 0x00,
  65. 0x00,
  66. 0x00,
  67. 0x40,
  68. 0x00,
  69. 0x00,
  70. };
  71. static const char *string_descriptors[] = {
  72. (const char[]){ 0x09, 0x04 }, /* Langid */
  73. "CherryUSB", /* Manufacturer */
  74. "CherryUSB WINUSB DEMO", /* Product */
  75. "2022123456", /* Serial Number */
  76. };
  77. static const uint8_t *device_descriptor_callback(uint8_t speed)
  78. {
  79. return device_descriptor;
  80. }
  81. static const uint8_t *config_descriptor_callback(uint8_t speed)
  82. {
  83. return config_descriptor;
  84. }
  85. static const uint8_t *device_quality_descriptor_callback(uint8_t speed)
  86. {
  87. return device_quality_descriptor;
  88. }
  89. static const char *string_descriptor_callback(uint8_t speed, uint8_t index)
  90. {
  91. if (index > 3) {
  92. return NULL;
  93. }
  94. return string_descriptors[index];
  95. }
  96. const struct usb_descriptor winusbv2_cdc_descriptor = {
  97. .device_descriptor_callback = device_descriptor_callback,
  98. .config_descriptor_callback = config_descriptor_callback,
  99. .device_quality_descriptor_callback = device_quality_descriptor_callback,
  100. .string_descriptor_callback = string_descriptor_callback,
  101. .msosv2_descriptor = &msosv2_desc,
  102. .bos_descriptor = &bos_desc
  103. };
  104. USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t read_buffer[2048];
  105. USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t write_buffer[2048];
  106. volatile bool ep_tx_busy_flag = false;
  107. static void usbd_event_handler(uint8_t busid, uint8_t event)
  108. {
  109. switch (event) {
  110. case USBD_EVENT_RESET:
  111. break;
  112. case USBD_EVENT_CONNECTED:
  113. break;
  114. case USBD_EVENT_DISCONNECTED:
  115. break;
  116. case USBD_EVENT_RESUME:
  117. break;
  118. case USBD_EVENT_SUSPEND:
  119. break;
  120. case USBD_EVENT_CONFIGURED:
  121. ep_tx_busy_flag = false;
  122. /* setup first out ep read transfer */
  123. usbd_ep_start_read(busid, WINUSB_OUT_EP, read_buffer, 2048);
  124. usbd_ep_start_read(busid, CDC_OUT_EP, read_buffer, 2048);
  125. break;
  126. case USBD_EVENT_SET_REMOTE_WAKEUP:
  127. break;
  128. case USBD_EVENT_CLR_REMOTE_WAKEUP:
  129. break;
  130. default:
  131. break;
  132. }
  133. }
  134. void usbd_winusb_out(uint8_t busid, uint8_t ep, uint32_t nbytes)
  135. {
  136. USB_LOG_RAW("actual out len:%d\r\n", (unsigned int)nbytes);
  137. // for (int i = 0; i < 100; i++) {
  138. // printf("%02x ", read_buffer[i]);
  139. // }
  140. // printf("\r\n");
  141. usbd_ep_start_write(busid, WINUSB_IN_EP, read_buffer, nbytes);
  142. /* setup next out ep read transfer */
  143. usbd_ep_start_read(busid, WINUSB_OUT_EP, read_buffer, 2048);
  144. }
  145. void usbd_winusb_in(uint8_t busid, uint8_t ep, uint32_t nbytes)
  146. {
  147. USB_LOG_RAW("actual in len:%d\r\n", (unsigned int)nbytes);
  148. if ((nbytes % usbd_get_ep_mps(busid, ep)) == 0 && nbytes) {
  149. /* send zlp */
  150. usbd_ep_start_write(busid, WINUSB_IN_EP, NULL, 0);
  151. } else {
  152. ep_tx_busy_flag = false;
  153. }
  154. }
  155. void usbd_cdc_acm_out(uint8_t busid, uint8_t ep, uint32_t nbytes)
  156. {
  157. USB_LOG_RAW("actual out len:%d\r\n", (unsigned int)nbytes);
  158. // for (int i = 0; i < 100; i++) {
  159. // printf("%02x ", read_buffer[i]);
  160. // }
  161. // printf("\r\n");
  162. usbd_ep_start_write(busid, CDC_IN_EP, read_buffer, nbytes);
  163. /* setup next out ep read transfer */
  164. usbd_ep_start_read(busid, CDC_OUT_EP, read_buffer, 2048);
  165. }
  166. void usbd_cdc_acm_in(uint8_t busid, uint8_t ep, uint32_t nbytes)
  167. {
  168. USB_LOG_RAW("actual in len:%d\r\n", (unsigned int)nbytes);
  169. if ((nbytes % usbd_get_ep_mps(busid, ep)) == 0 && nbytes) {
  170. /* send zlp */
  171. usbd_ep_start_write(busid, CDC_IN_EP, NULL, 0);
  172. } else {
  173. ep_tx_busy_flag = false;
  174. }
  175. }
  176. struct usbd_endpoint winusb_out_ep1 = {
  177. .ep_addr = WINUSB_OUT_EP,
  178. .ep_cb = usbd_winusb_out
  179. };
  180. struct usbd_endpoint winusb_in_ep1 = {
  181. .ep_addr = WINUSB_IN_EP,
  182. .ep_cb = usbd_winusb_in
  183. };
  184. static struct usbd_endpoint cdc_out_ep = {
  185. .ep_addr = CDC_OUT_EP,
  186. .ep_cb = usbd_cdc_acm_out
  187. };
  188. static struct usbd_endpoint cdc_in_ep = {
  189. .ep_addr = CDC_IN_EP,
  190. .ep_cb = usbd_cdc_acm_in
  191. };
  192. struct usbd_interface winusb_intf;
  193. struct usbd_interface intf1;
  194. struct usbd_interface intf2;
  195. void winusbv2_cdc_init(uint8_t busid, uintptr_t reg_base)
  196. {
  197. usbd_desc_register(busid, &winusbv2_cdc_descriptor);
  198. /*!< winusb */
  199. usbd_add_interface(busid, &winusb_intf);
  200. usbd_add_endpoint(busid, &winusb_out_ep1);
  201. usbd_add_endpoint(busid, &winusb_in_ep1);
  202. /*!< cdc acm */
  203. usbd_add_interface(busid, usbd_cdc_acm_init_intf(busid, &intf1));
  204. usbd_add_interface(busid, usbd_cdc_acm_init_intf(busid, &intf2));
  205. usbd_add_endpoint(busid, &cdc_out_ep);
  206. usbd_add_endpoint(busid, &cdc_in_ep);
  207. usbd_initialize(busid, reg_base, usbd_event_handler);
  208. }
  209. volatile uint8_t dtr_enable = 0;
  210. void usbd_cdc_acm_set_dtr(uint8_t busid, uint8_t intf, bool dtr)
  211. {
  212. if (dtr) {
  213. dtr_enable = 1;
  214. } else {
  215. dtr_enable = 0;
  216. }
  217. }
  218. void cdc_acm_data_send_with_dtr_test(uint8_t busid)
  219. {
  220. if (dtr_enable) {
  221. memset(&write_buffer[10], 'a', 2038);
  222. ep_tx_busy_flag = true;
  223. usbd_ep_start_write(busid, CDC_IN_EP, write_buffer, 2048);
  224. while (ep_tx_busy_flag) {
  225. }
  226. }
  227. }