cdc_acm_hid_msc_template.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436
  1. /*
  2. * Copyright (c) 2024, sakumisu
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. #include "usbd_core.h"
  7. #include "usbd_msc.h"
  8. #include "usbd_cdc_acm.h"
  9. #include "usbd_hid.h"
  10. /*!< endpoint address */
  11. #define CDC_IN_EP 0x81
  12. #define CDC_OUT_EP 0x02
  13. #define CDC_INT_EP 0x83
  14. #define MSC_IN_EP 0x84
  15. #define MSC_OUT_EP 0x05
  16. /*!< endpoint address */
  17. #define HID_INT_EP 0x86
  18. #define HID_INT_EP_SIZE 4
  19. #define HID_INT_EP_INTERVAL 10
  20. #define USBD_VID 0xFFFF
  21. #define USBD_PID 0xFFFF
  22. #define USBD_MAX_POWER 100
  23. #define USBD_LANGID_STRING 1033
  24. /*!< report descriptor size */
  25. #define HID_MOUSE_REPORT_DESC_SIZE 74
  26. #define USB_CONFIG_SIZE (9 + CDC_ACM_DESCRIPTOR_LEN + MSC_DESCRIPTOR_LEN + 25)
  27. #ifdef CONFIG_USB_HS
  28. #define CDC_MAX_MPS 512
  29. #else
  30. #define CDC_MAX_MPS 64
  31. #endif
  32. #ifdef CONFIG_USB_HS
  33. #define MSC_MAX_MPS 512
  34. #else
  35. #define MSC_MAX_MPS 64
  36. #endif
  37. #ifdef CONFIG_USBDEV_ADVANCE_DESC
  38. static const uint8_t device_descriptor[] = {
  39. USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0x00, 0x00, 0x00, USBD_VID, USBD_PID, 0x0200, 0x01)
  40. };
  41. static const uint8_t config_descriptor[] = {
  42. USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, 0x04, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
  43. CDC_ACM_DESCRIPTOR_INIT(0x00, CDC_INT_EP, CDC_OUT_EP, CDC_IN_EP, CDC_MAX_MPS, 0x02),
  44. MSC_DESCRIPTOR_INIT(0x02, MSC_OUT_EP, MSC_IN_EP, MSC_MAX_MPS, 0x02),
  45. HID_MOUSE_DESCRIPTOR_INIT(0x03, 0x01, HID_MOUSE_REPORT_DESC_SIZE, HID_INT_EP, HID_INT_EP_SIZE, HID_INT_EP_INTERVAL),
  46. };
  47. static const uint8_t device_quality_descriptor[] = {
  48. ///////////////////////////////////////
  49. /// device qualifier descriptor
  50. ///////////////////////////////////////
  51. 0x0a,
  52. USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
  53. 0x00,
  54. 0x02,
  55. 0x00,
  56. 0x00,
  57. 0x00,
  58. 0x40,
  59. 0x00,
  60. 0x00,
  61. };
  62. static const char *string_descriptors[] = {
  63. (const char[]){ 0x09, 0x04 }, /* Langid */
  64. "CherryUSB", /* Manufacturer */
  65. "CherryUSB CDC MSC HID DEMO", /* Product */
  66. "2022123456", /* Serial Number */
  67. };
  68. static const uint8_t *device_descriptor_callback(uint8_t speed)
  69. {
  70. return device_descriptor;
  71. }
  72. static const uint8_t *config_descriptor_callback(uint8_t speed)
  73. {
  74. return config_descriptor;
  75. }
  76. static const uint8_t *device_quality_descriptor_callback(uint8_t speed)
  77. {
  78. return device_quality_descriptor;
  79. }
  80. static const char *string_descriptor_callback(uint8_t speed, uint8_t index)
  81. {
  82. if (index > 3) {
  83. return NULL;
  84. }
  85. return string_descriptors[index];
  86. }
  87. const struct usb_descriptor cdc_acm_hid_msc_descriptor = {
  88. .device_descriptor_callback = device_descriptor_callback,
  89. .config_descriptor_callback = config_descriptor_callback,
  90. .device_quality_descriptor_callback = device_quality_descriptor_callback,
  91. .string_descriptor_callback = string_descriptor_callback
  92. };
  93. #else
  94. const uint8_t cdc_acm_hid_msc_descriptor[] = {
  95. USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0x00, 0x00, 0x00, USBD_VID, USBD_PID, 0x0200, 0x01),
  96. USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, 0x04, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
  97. CDC_ACM_DESCRIPTOR_INIT(0x00, CDC_INT_EP, CDC_OUT_EP, CDC_IN_EP, CDC_MAX_MPS, 0x02),
  98. MSC_DESCRIPTOR_INIT(0x02, MSC_OUT_EP, MSC_IN_EP, MSC_MAX_MPS, 0x02),
  99. HID_MOUSE_DESCRIPTOR_INIT(0x03, 0x01, HID_MOUSE_REPORT_DESC_SIZE, HID_INT_EP, HID_INT_EP_SIZE, HID_INT_EP_INTERVAL),
  100. ///////////////////////////////////////
  101. /// string0 descriptor
  102. ///////////////////////////////////////
  103. USB_LANGID_INIT(USBD_LANGID_STRING),
  104. ///////////////////////////////////////
  105. /// string1 descriptor
  106. ///////////////////////////////////////
  107. 0x14, /* bLength */
  108. USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
  109. 'C', 0x00, /* wcChar0 */
  110. 'h', 0x00, /* wcChar1 */
  111. 'e', 0x00, /* wcChar2 */
  112. 'r', 0x00, /* wcChar3 */
  113. 'r', 0x00, /* wcChar4 */
  114. 'y', 0x00, /* wcChar5 */
  115. 'U', 0x00, /* wcChar6 */
  116. 'S', 0x00, /* wcChar7 */
  117. 'B', 0x00, /* wcChar8 */
  118. ///////////////////////////////////////
  119. /// string2 descriptor
  120. ///////////////////////////////////////
  121. 0x26, /* bLength */
  122. USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
  123. 'C', 0x00, /* wcChar0 */
  124. 'h', 0x00, /* wcChar1 */
  125. 'e', 0x00, /* wcChar2 */
  126. 'r', 0x00, /* wcChar3 */
  127. 'r', 0x00, /* wcChar4 */
  128. 'y', 0x00, /* wcChar5 */
  129. 'U', 0x00, /* wcChar6 */
  130. 'S', 0x00, /* wcChar7 */
  131. 'B', 0x00, /* wcChar8 */
  132. ' ', 0x00, /* wcChar9 */
  133. 'C', 0x00, /* wcChar10 */
  134. 'M', 0x00, /* wcChar11 */
  135. 'H', 0x00, /* wcChar12 */
  136. ' ', 0x00, /* wcChar13 */
  137. 'D', 0x00, /* wcChar14 */
  138. 'E', 0x00, /* wcChar15 */
  139. 'M', 0x00, /* wcChar16 */
  140. 'O', 0x00, /* wcChar17 */
  141. ///////////////////////////////////////
  142. /// string3 descriptor
  143. ///////////////////////////////////////
  144. 0x16, /* bLength */
  145. USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
  146. '2', 0x00, /* wcChar0 */
  147. '0', 0x00, /* wcChar1 */
  148. '2', 0x00, /* wcChar2 */
  149. '2', 0x00, /* wcChar3 */
  150. '1', 0x00, /* wcChar4 */
  151. '2', 0x00, /* wcChar5 */
  152. '3', 0x00, /* wcChar6 */
  153. '4', 0x00, /* wcChar7 */
  154. '5', 0x00, /* wcChar8 */
  155. '6', 0x00, /* wcChar9 */
  156. #ifdef CONFIG_USB_HS
  157. ///////////////////////////////////////
  158. /// device qualifier descriptor
  159. ///////////////////////////////////////
  160. 0x0a,
  161. USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
  162. 0x00,
  163. 0x02,
  164. 0x00,
  165. 0x00,
  166. 0x00,
  167. 0x40,
  168. 0x00,
  169. 0x00,
  170. #endif
  171. 0x00
  172. };
  173. #endif
  174. /*!< hid mouse report descriptor */
  175. static const uint8_t hid_mouse_report_desc[HID_MOUSE_REPORT_DESC_SIZE] = {
  176. 0x05, 0x01, // USAGE_PAGE (Generic Desktop)
  177. 0x09, 0x02, // USAGE (Mouse)
  178. 0xA1, 0x01, // COLLECTION (Application)
  179. 0x09, 0x01, // USAGE (Pointer)
  180. 0xA1, 0x00, // COLLECTION (Physical)
  181. 0x05, 0x09, // USAGE_PAGE (Button)
  182. 0x19, 0x01, // USAGE_MINIMUM (Button 1)
  183. 0x29, 0x03, // USAGE_MAXIMUM (Button 3)
  184. 0x15, 0x00, // LOGICAL_MINIMUM (0)
  185. 0x25, 0x01, // LOGICAL_MAXIMUM (1)
  186. 0x95, 0x03, // REPORT_COUNT (3)
  187. 0x75, 0x01, // REPORT_SIZE (1)
  188. 0x81, 0x02, // INPUT (Data,Var,Abs)
  189. 0x95, 0x01, // REPORT_COUNT (1)
  190. 0x75, 0x05, // REPORT_SIZE (5)
  191. 0x81, 0x01, // INPUT (Cnst,Var,Abs)
  192. 0x05, 0x01, // USAGE_PAGE (Generic Desktop)
  193. 0x09, 0x30, // USAGE (X)
  194. 0x09, 0x31, // USAGE (Y)
  195. 0x09, 0x38,
  196. 0x15, 0x81, // LOGICAL_MINIMUM (-127)
  197. 0x25, 0x7F, // LOGICAL_MAXIMUM (127)
  198. 0x75, 0x08, // REPORT_SIZE (8)
  199. 0x95, 0x03, // REPORT_COUNT (2)
  200. 0x81, 0x06, // INPUT (Data,Var,Rel)
  201. 0xC0, 0x09,
  202. 0x3c, 0x05,
  203. 0xff, 0x09,
  204. 0x01, 0x15,
  205. 0x00, 0x25,
  206. 0x01, 0x75,
  207. 0x01, 0x95,
  208. 0x02, 0xb1,
  209. 0x22, 0x75,
  210. 0x06, 0x95,
  211. 0x01, 0xb1,
  212. 0x01, 0xc0 // END_COLLECTION
  213. };
  214. /*!< mouse report struct */
  215. struct hid_mouse {
  216. uint8_t buttons;
  217. int8_t x;
  218. int8_t y;
  219. int8_t wheel;
  220. };
  221. /*!< mouse report */
  222. static struct hid_mouse mouse_cfg;
  223. #define HID_STATE_IDLE 0
  224. #define HID_STATE_BUSY 1
  225. /*!< hid state ! Data can be sent only when state is idle */
  226. static volatile uint8_t hid_state = HID_STATE_IDLE;
  227. /* function ------------------------------------------------------------------*/
  228. static void usbd_hid_int_callback(uint8_t busid, uint8_t ep, uint32_t nbytes)
  229. {
  230. hid_state = HID_STATE_IDLE;
  231. }
  232. /*!< endpoint call back */
  233. static struct usbd_endpoint hid_in_ep = {
  234. .ep_cb = usbd_hid_int_callback,
  235. .ep_addr = HID_INT_EP
  236. };
  237. USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t read_buffer[2048];
  238. USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t write_buffer[2048];
  239. volatile bool ep_tx_busy_flag = false;
  240. static void usbd_event_handler(uint8_t busid, uint8_t event)
  241. {
  242. switch (event) {
  243. case USBD_EVENT_RESET:
  244. break;
  245. case USBD_EVENT_CONNECTED:
  246. break;
  247. case USBD_EVENT_DISCONNECTED:
  248. break;
  249. case USBD_EVENT_RESUME:
  250. break;
  251. case USBD_EVENT_SUSPEND:
  252. break;
  253. case USBD_EVENT_CONFIGURED:
  254. ep_tx_busy_flag = false;
  255. hid_state = HID_STATE_IDLE;
  256. /* setup first out ep read transfer */
  257. usbd_ep_start_read(busid, CDC_OUT_EP, read_buffer, 2048);
  258. break;
  259. case USBD_EVENT_SET_REMOTE_WAKEUP:
  260. break;
  261. case USBD_EVENT_CLR_REMOTE_WAKEUP:
  262. break;
  263. default:
  264. break;
  265. }
  266. }
  267. void usbd_cdc_acm_bulk_out(uint8_t busid, uint8_t ep, uint32_t nbytes)
  268. {
  269. USB_LOG_RAW("actual out len:%d\r\n", (unsigned int)nbytes);
  270. /* setup next out ep read transfer */
  271. usbd_ep_start_read(busid, CDC_OUT_EP, read_buffer, 2048);
  272. }
  273. void usbd_cdc_acm_bulk_in(uint8_t busid, uint8_t ep, uint32_t nbytes)
  274. {
  275. USB_LOG_RAW("actual in len:%d\r\n", (unsigned int)nbytes);
  276. if ((nbytes % usbd_get_ep_mps(busid, ep)) == 0 && nbytes) {
  277. /* send zlp */
  278. usbd_ep_start_write(busid, CDC_IN_EP, NULL, 0);
  279. } else {
  280. ep_tx_busy_flag = false;
  281. }
  282. }
  283. /*!< endpoint call back */
  284. struct usbd_endpoint cdc_out_ep = {
  285. .ep_addr = CDC_OUT_EP,
  286. .ep_cb = usbd_cdc_acm_bulk_out
  287. };
  288. struct usbd_endpoint cdc_in_ep = {
  289. .ep_addr = CDC_IN_EP,
  290. .ep_cb = usbd_cdc_acm_bulk_in
  291. };
  292. struct usbd_interface intf0;
  293. struct usbd_interface intf1;
  294. struct usbd_interface intf2;
  295. struct usbd_interface intf3;
  296. void cdc_acm_hid_msc_descriptor_init(uint8_t busid, uintptr_t reg_base)
  297. {
  298. #ifdef CONFIG_USBDEV_ADVANCE_DESC
  299. usbd_desc_register(busid, &cdc_acm_hid_msc_descriptor);
  300. #else
  301. usbd_desc_register(busid, cdc_acm_hid_msc_descriptor);
  302. #endif
  303. usbd_add_interface(busid, usbd_cdc_acm_init_intf(busid, &intf0));
  304. usbd_add_interface(busid, usbd_cdc_acm_init_intf(busid, &intf1));
  305. usbd_add_endpoint(busid, &cdc_out_ep);
  306. usbd_add_endpoint(busid, &cdc_in_ep);
  307. usbd_add_interface(busid, usbd_msc_init_intf(busid, &intf2, MSC_OUT_EP, MSC_IN_EP));
  308. usbd_add_interface(busid, usbd_hid_init_intf(busid, &intf3, hid_mouse_report_desc, HID_MOUSE_REPORT_DESC_SIZE));
  309. usbd_add_endpoint(busid, &hid_in_ep);
  310. /*!< init mouse report data */
  311. mouse_cfg.buttons = 0;
  312. mouse_cfg.wheel = 0;
  313. mouse_cfg.x = 0;
  314. mouse_cfg.y = 0;
  315. usbd_initialize(busid, reg_base, usbd_event_handler);
  316. }
  317. /**
  318. * @brief hid mouse test
  319. * @pre none
  320. * @param[in] none
  321. * @retval none
  322. */
  323. void hid_mouse_test(uint8_t busid)
  324. {
  325. if(usb_device_is_configured(busid) == false) {
  326. return;
  327. }
  328. /*!< move mouse pointer */
  329. mouse_cfg.x += 10;
  330. mouse_cfg.y = 0;
  331. hid_state = HID_STATE_BUSY;
  332. usbd_ep_start_write(busid, HID_INT_EP, (uint8_t *)&mouse_cfg, 4);
  333. while (hid_state == HID_STATE_BUSY) {
  334. }
  335. }
  336. volatile uint8_t dtr_enable = 0;
  337. void usbd_cdc_acm_set_dtr(uint8_t busid, uint8_t intf, bool dtr)
  338. {
  339. if (dtr) {
  340. dtr_enable = 1;
  341. } else {
  342. dtr_enable = 0;
  343. }
  344. }
  345. void cdc_acm_data_send_with_dtr_test(uint8_t busid)
  346. {
  347. if (dtr_enable) {
  348. memset(&write_buffer[10], 'a', 2038);
  349. ep_tx_busy_flag = true;
  350. usbd_ep_start_write(busid, CDC_IN_EP, write_buffer, 2048);
  351. while (ep_tx_busy_flag) {
  352. }
  353. }
  354. }
  355. #define BLOCK_SIZE 512
  356. #define BLOCK_COUNT 10
  357. typedef struct
  358. {
  359. uint8_t BlockSpace[BLOCK_SIZE];
  360. } BLOCK_TYPE;
  361. BLOCK_TYPE mass_block[BLOCK_COUNT];
  362. void usbd_msc_get_cap(uint8_t busid, uint8_t lun, uint32_t *block_num, uint32_t *block_size)
  363. {
  364. *block_num = 1000; //Pretend having so many buffer,not has actually.
  365. *block_size = BLOCK_SIZE;
  366. }
  367. int usbd_msc_sector_read(uint8_t busid, uint8_t lun, uint32_t sector, uint8_t *buffer, uint32_t length)
  368. {
  369. if (sector < 10)
  370. memcpy(buffer, mass_block[sector].BlockSpace, length);
  371. return 0;
  372. }
  373. int usbd_msc_sector_write(uint8_t busid, uint8_t lun, uint32_t sector, uint8_t *buffer, uint32_t length)
  374. {
  375. if (sector < 10)
  376. memcpy(mass_block[sector].BlockSpace, buffer, length);
  377. return 0;
  378. }