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 
11 /*!< endpoint address */
12 #define CDC_IN_EP  0x81
13 #define CDC_OUT_EP 0x02
14 #define CDC_INT_EP 0x83
15 
16 #define MSC_IN_EP  0x84
17 #define MSC_OUT_EP 0x05
18 
19 /*!< endpoint address */
20 #define HID_INT_EP          0x86
21 #define HID_INT_EP_SIZE     4
22 #define HID_INT_EP_INTERVAL 10
23 
24 #define USBD_VID           0xFFFF
25 #define USBD_PID           0xFFFF
26 #define USBD_MAX_POWER     100
27 #define USBD_LANGID_STRING 1033
28 
29 /*!< report descriptor size */
30 #define HID_MOUSE_REPORT_DESC_SIZE 74
31 
32 #define USB_CONFIG_SIZE (9 + CDC_ACM_DESCRIPTOR_LEN + MSC_DESCRIPTOR_LEN + 25)
33 
34 #ifdef CONFIG_USB_HS
35 #define CDC_MAX_MPS 512
36 #else
37 #define CDC_MAX_MPS 64
38 #endif
39 
40 #ifdef CONFIG_USB_HS
41 #define MSC_MAX_MPS 512
42 #else
43 #define MSC_MAX_MPS 64
44 #endif
45 
46 #ifdef CONFIG_USBDEV_ADVANCE_DESC
47 static const uint8_t device_descriptor[] = {
48     USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0x00, 0x00, 0x00, USBD_VID, USBD_PID, 0x0200, 0x01)
49 };
50 
51 static const uint8_t config_descriptor[] = {
52     USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, 0x04, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
53     CDC_ACM_DESCRIPTOR_INIT(0x00, CDC_INT_EP, CDC_OUT_EP, CDC_IN_EP, CDC_MAX_MPS, 0x02),
54     MSC_DESCRIPTOR_INIT(0x02, MSC_OUT_EP, MSC_IN_EP, MSC_MAX_MPS, 0x02),
55     /************** Descriptor of Joystick Mouse interface ****************/
56     /* 09 */
57     0x09,                          /* bLength: Interface Descriptor size */
58     USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType: Interface descriptor type */
59     0x03,                          /* bInterfaceNumber: Number of Interface */
60     0x00,                          /* bAlternateSetting: Alternate setting */
61     0x01,                          /* bNumEndpoints */
62     0x03,                          /* bInterfaceClass: HID */
63     0x01,                          /* bInterfaceSubClass : 1=BOOT, 0=no boot */
64     0x02,                          /* nInterfaceProtocol : 0=none, 1=keyboard, 2=mouse */
65     0,                             /* iInterface: Index of string descriptor */
66     /******************** Descriptor of Joystick Mouse HID ********************/
67     /* 18 */
68     0x09,                    /* bLength: HID Descriptor size */
69     HID_DESCRIPTOR_TYPE_HID, /* bDescriptorType: HID */
70     0x11,                    /* bcdHID: HID Class Spec release number */
71     0x01,
72     0x00,                       /* bCountryCode: Hardware target country */
73     0x01,                       /* bNumDescriptors: Number of HID class descriptors to follow */
74     0x22,                       /* bDescriptorType */
75     HID_MOUSE_REPORT_DESC_SIZE, /* wItemLength: Total length of Report descriptor */
76     0x00,
77     /******************** Descriptor of Mouse endpoint ********************/
78     /* 27 */
79     0x07,                         /* bLength: Endpoint Descriptor size */
80     USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType: */
81     HID_INT_EP,                   /* bEndpointAddress: Endpoint Address (IN) */
82     0x03,                         /* bmAttributes: Interrupt endpoint */
83     HID_INT_EP_SIZE,              /* wMaxPacketSize: 4 Byte max */
84     0x00,
85     HID_INT_EP_INTERVAL, /* bInterval: Polling Interval */
86 };
87 
88 static const uint8_t device_quality_descriptor[] = {
89     ///////////////////////////////////////
90     /// device qualifier descriptor
91     ///////////////////////////////////////
92     0x0a,
93     USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
94     0x00,
95     0x02,
96     0x00,
97     0x00,
98     0x00,
99     0x40,
100     0x00,
101     0x00,
102 };
103 
104 static const char *string_descriptors[] = {
105     (const char[]){ 0x09, 0x04 }, /* Langid */
106     "CherryUSB",                  /* Manufacturer */
107     "CherryUSB CDC MSC HID DEMO", /* Product */
108     "2022123456",                 /* Serial Number */
109 };
110 
device_descriptor_callback(uint8_t speed)111 static const uint8_t *device_descriptor_callback(uint8_t speed)
112 {
113     return device_descriptor;
114 }
115 
config_descriptor_callback(uint8_t speed)116 static const uint8_t *config_descriptor_callback(uint8_t speed)
117 {
118     return config_descriptor;
119 }
120 
device_quality_descriptor_callback(uint8_t speed)121 static const uint8_t *device_quality_descriptor_callback(uint8_t speed)
122 {
123     return device_quality_descriptor;
124 }
125 
string_descriptor_callback(uint8_t speed,uint8_t index)126 static const char *string_descriptor_callback(uint8_t speed, uint8_t index)
127 {
128     if (index > 3) {
129         return NULL;
130     }
131     return string_descriptors[index];
132 }
133 
134 const struct usb_descriptor cdc_acm_hid_msc_descriptor = {
135     .device_descriptor_callback = device_descriptor_callback,
136     .config_descriptor_callback = config_descriptor_callback,
137     .device_quality_descriptor_callback = device_quality_descriptor_callback,
138     .string_descriptor_callback = string_descriptor_callback
139 };
140 #else
141 const uint8_t cdc_acm_hid_msc_descriptor[] = {
142     USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0x00, 0x00, 0x00, USBD_VID, USBD_PID, 0x0200, 0x01),
143     USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, 0x04, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
144     CDC_ACM_DESCRIPTOR_INIT(0x00, CDC_INT_EP, CDC_OUT_EP, CDC_IN_EP, CDC_MAX_MPS, 0x02),
145     MSC_DESCRIPTOR_INIT(0x02, MSC_OUT_EP, MSC_IN_EP, MSC_MAX_MPS, 0x02),
146     /************** Descriptor of Joystick Mouse interface ****************/
147     /* 09 */
148     0x09,                          /* bLength: Interface Descriptor size */
149     USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType: Interface descriptor type */
150     0x03,                          /* bInterfaceNumber: Number of Interface */
151     0x00,                          /* bAlternateSetting: Alternate setting */
152     0x01,                          /* bNumEndpoints */
153     0x03,                          /* bInterfaceClass: HID */
154     0x01,                          /* bInterfaceSubClass : 1=BOOT, 0=no boot */
155     0x02,                          /* nInterfaceProtocol : 0=none, 1=keyboard, 2=mouse */
156     0,                             /* iInterface: Index of string descriptor */
157     /******************** Descriptor of Joystick Mouse HID ********************/
158     /* 18 */
159     0x09,                    /* bLength: HID Descriptor size */
160     HID_DESCRIPTOR_TYPE_HID, /* bDescriptorType: HID */
161     0x11,                    /* bcdHID: HID Class Spec release number */
162     0x01,
163     0x00,                       /* bCountryCode: Hardware target country */
164     0x01,                       /* bNumDescriptors: Number of HID class descriptors to follow */
165     0x22,                       /* bDescriptorType */
166     HID_MOUSE_REPORT_DESC_SIZE, /* wItemLength: Total length of Report descriptor */
167     0x00,
168     /******************** Descriptor of Mouse endpoint ********************/
169     /* 27 */
170     0x07,                         /* bLength: Endpoint Descriptor size */
171     USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType: */
172     HID_INT_EP,                   /* bEndpointAddress: Endpoint Address (IN) */
173     0x03,                         /* bmAttributes: Interrupt endpoint */
174     HID_INT_EP_SIZE,              /* wMaxPacketSize: 4 Byte max */
175     0x00,
176     HID_INT_EP_INTERVAL, /* bInterval: Polling Interval */
177     ///////////////////////////////////////
178     /// string0 descriptor
179     ///////////////////////////////////////
180     USB_LANGID_INIT(USBD_LANGID_STRING),
181     ///////////////////////////////////////
182     /// string1 descriptor
183     ///////////////////////////////////////
184     0x14,                       /* bLength */
185     USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
186     'C', 0x00,                  /* wcChar0 */
187     'h', 0x00,                  /* wcChar1 */
188     'e', 0x00,                  /* wcChar2 */
189     'r', 0x00,                  /* wcChar3 */
190     'r', 0x00,                  /* wcChar4 */
191     'y', 0x00,                  /* wcChar5 */
192     'U', 0x00,                  /* wcChar6 */
193     'S', 0x00,                  /* wcChar7 */
194     'B', 0x00,                  /* wcChar8 */
195     ///////////////////////////////////////
196     /// string2 descriptor
197     ///////////////////////////////////////
198     0x26,                       /* bLength */
199     USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
200     'C', 0x00,                  /* wcChar0 */
201     'h', 0x00,                  /* wcChar1 */
202     'e', 0x00,                  /* wcChar2 */
203     'r', 0x00,                  /* wcChar3 */
204     'r', 0x00,                  /* wcChar4 */
205     'y', 0x00,                  /* wcChar5 */
206     'U', 0x00,                  /* wcChar6 */
207     'S', 0x00,                  /* wcChar7 */
208     'B', 0x00,                  /* wcChar8 */
209     ' ', 0x00,                  /* wcChar9 */
210     'C', 0x00,                  /* wcChar10 */
211     'M', 0x00,                  /* wcChar11 */
212     'H', 0x00,                  /* wcChar12 */
213     ' ', 0x00,                  /* wcChar13 */
214     'D', 0x00,                  /* wcChar14 */
215     'E', 0x00,                  /* wcChar15 */
216     'M', 0x00,                  /* wcChar16 */
217     'O', 0x00,                  /* wcChar17 */
218     ///////////////////////////////////////
219     /// string3 descriptor
220     ///////////////////////////////////////
221     0x16,                       /* bLength */
222     USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
223     '2', 0x00,                  /* wcChar0 */
224     '0', 0x00,                  /* wcChar1 */
225     '2', 0x00,                  /* wcChar2 */
226     '2', 0x00,                  /* wcChar3 */
227     '1', 0x00,                  /* wcChar4 */
228     '2', 0x00,                  /* wcChar5 */
229     '3', 0x00,                  /* wcChar6 */
230     '4', 0x00,                  /* wcChar7 */
231     '5', 0x00,                  /* wcChar8 */
232     '6', 0x00,                  /* wcChar9 */
233 #ifdef CONFIG_USB_HS
234     ///////////////////////////////////////
235     /// device qualifier descriptor
236     ///////////////////////////////////////
237     0x0a,
238     USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
239     0x00,
240     0x02,
241     0x00,
242     0x00,
243     0x00,
244     0x40,
245     0x00,
246     0x00,
247 #endif
248     0x00
249 };
250 #endif
251 
252 /*!< hid mouse report descriptor */
253 static const uint8_t hid_mouse_report_desc[HID_MOUSE_REPORT_DESC_SIZE] = {
254     0x05, 0x01, // USAGE_PAGE (Generic Desktop)
255     0x09, 0x02, // USAGE (Mouse)
256     0xA1, 0x01, // COLLECTION (Application)
257     0x09, 0x01, //   USAGE (Pointer)
258 
259     0xA1, 0x00, //   COLLECTION (Physical)
260     0x05, 0x09, //     USAGE_PAGE (Button)
261     0x19, 0x01, //     USAGE_MINIMUM (Button 1)
262     0x29, 0x03, //     USAGE_MAXIMUM (Button 3)
263 
264     0x15, 0x00, //     LOGICAL_MINIMUM (0)
265     0x25, 0x01, //     LOGICAL_MAXIMUM (1)
266     0x95, 0x03, //     REPORT_COUNT (3)
267     0x75, 0x01, //     REPORT_SIZE (1)
268 
269     0x81, 0x02, //     INPUT (Data,Var,Abs)
270     0x95, 0x01, //     REPORT_COUNT (1)
271     0x75, 0x05, //     REPORT_SIZE (5)
272     0x81, 0x01, //     INPUT (Cnst,Var,Abs)
273 
274     0x05, 0x01, //     USAGE_PAGE (Generic Desktop)
275     0x09, 0x30, //     USAGE (X)
276     0x09, 0x31, //     USAGE (Y)
277     0x09, 0x38,
278 
279     0x15, 0x81, //     LOGICAL_MINIMUM (-127)
280     0x25, 0x7F, //     LOGICAL_MAXIMUM (127)
281     0x75, 0x08, //     REPORT_SIZE (8)
282     0x95, 0x03, //     REPORT_COUNT (2)
283 
284     0x81, 0x06, //     INPUT (Data,Var,Rel)
285     0xC0, 0x09,
286     0x3c, 0x05,
287     0xff, 0x09,
288 
289     0x01, 0x15,
290     0x00, 0x25,
291     0x01, 0x75,
292     0x01, 0x95,
293 
294     0x02, 0xb1,
295     0x22, 0x75,
296     0x06, 0x95,
297     0x01, 0xb1,
298 
299     0x01, 0xc0 //   END_COLLECTION
300 };
301 
302 /*!< mouse report struct */
303 struct hid_mouse {
304     uint8_t buttons;
305     int8_t x;
306     int8_t y;
307     int8_t wheel;
308 };
309 
310 /*!< mouse report */
311 static struct hid_mouse mouse_cfg;
312 
313 #define HID_STATE_IDLE 0
314 #define HID_STATE_BUSY 1
315 
316 /*!< hid state ! Data can be sent only when state is idle  */
317 static volatile uint8_t hid_state = HID_STATE_IDLE;
318 
319 /* function ------------------------------------------------------------------*/
usbd_hid_int_callback(uint8_t busid,uint8_t ep,uint32_t nbytes)320 static void usbd_hid_int_callback(uint8_t busid, uint8_t ep, uint32_t nbytes)
321 {
322     hid_state = HID_STATE_IDLE;
323 }
324 
325 /*!< endpoint call back */
326 static struct usbd_endpoint hid_in_ep = {
327     .ep_cb = usbd_hid_int_callback,
328     .ep_addr = HID_INT_EP
329 };
330 
331 USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t read_buffer[2048];
332 USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t write_buffer[2048];
333 
334 volatile bool ep_tx_busy_flag = false;
335 
usbd_event_handler(uint8_t busid,uint8_t event)336 static void usbd_event_handler(uint8_t busid, uint8_t event)
337 {
338     switch (event) {
339         case USBD_EVENT_RESET:
340             break;
341         case USBD_EVENT_CONNECTED:
342             break;
343         case USBD_EVENT_DISCONNECTED:
344             break;
345         case USBD_EVENT_RESUME:
346             break;
347         case USBD_EVENT_SUSPEND:
348             break;
349         case USBD_EVENT_CONFIGURED:
350             ep_tx_busy_flag = false;
351             hid_state = HID_STATE_IDLE;
352             /* setup first out ep read transfer */
353             usbd_ep_start_read(busid, CDC_OUT_EP, read_buffer, 2048);
354             break;
355         case USBD_EVENT_SET_REMOTE_WAKEUP:
356             break;
357         case USBD_EVENT_CLR_REMOTE_WAKEUP:
358             break;
359 
360         default:
361             break;
362     }
363 }
364 
usbd_cdc_acm_bulk_out(uint8_t busid,uint8_t ep,uint32_t nbytes)365 void usbd_cdc_acm_bulk_out(uint8_t busid, uint8_t ep, uint32_t nbytes)
366 {
367     USB_LOG_RAW("actual out len:%d\r\n", (unsigned int)nbytes);
368     /* setup next out ep read transfer */
369     usbd_ep_start_read(busid, CDC_OUT_EP, read_buffer, 2048);
370 }
371 
usbd_cdc_acm_bulk_in(uint8_t busid,uint8_t ep,uint32_t nbytes)372 void usbd_cdc_acm_bulk_in(uint8_t busid, uint8_t ep, uint32_t nbytes)
373 {
374     USB_LOG_RAW("actual in len:%d\r\n", (unsigned int)nbytes);
375 
376     if ((nbytes % usbd_get_ep_mps(busid, ep)) == 0 && nbytes) {
377         /* send zlp */
378         usbd_ep_start_write(busid, CDC_IN_EP, NULL, 0);
379     } else {
380         ep_tx_busy_flag = false;
381     }
382 }
383 
384 /*!< endpoint call back */
385 struct usbd_endpoint cdc_out_ep = {
386     .ep_addr = CDC_OUT_EP,
387     .ep_cb = usbd_cdc_acm_bulk_out
388 };
389 
390 struct usbd_endpoint cdc_in_ep = {
391     .ep_addr = CDC_IN_EP,
392     .ep_cb = usbd_cdc_acm_bulk_in
393 };
394 
395 struct usbd_interface intf0;
396 struct usbd_interface intf1;
397 struct usbd_interface intf2;
398 struct usbd_interface intf3;
399 
cdc_acm_hid_msc_descriptor_init(uint8_t busid,uintptr_t reg_base)400 void cdc_acm_hid_msc_descriptor_init(uint8_t busid, uintptr_t reg_base)
401 {
402 #ifdef CONFIG_USBDEV_ADVANCE_DESC
403     usbd_desc_register(busid, &cdc_acm_hid_msc_descriptor);
404 #else
405     usbd_desc_register(busid, cdc_acm_hid_msc_descriptor);
406 #endif
407     usbd_add_interface(busid, usbd_cdc_acm_init_intf(busid, &intf0));
408     usbd_add_interface(busid, usbd_cdc_acm_init_intf(busid, &intf1));
409     usbd_add_endpoint(busid, &cdc_out_ep);
410     usbd_add_endpoint(busid, &cdc_in_ep);
411 
412     usbd_add_interface(busid, usbd_msc_init_intf(busid, &intf2, MSC_OUT_EP, MSC_IN_EP));
413 
414     usbd_add_interface(busid, usbd_hid_init_intf(busid, &intf3, hid_mouse_report_desc, HID_MOUSE_REPORT_DESC_SIZE));
415     usbd_add_endpoint(busid, &hid_in_ep);
416 
417     /*!< init mouse report data */
418     mouse_cfg.buttons = 0;
419     mouse_cfg.wheel = 0;
420     mouse_cfg.x = 0;
421     mouse_cfg.y = 0;
422 
423     usbd_initialize(busid, reg_base, usbd_event_handler);
424 }
425 
426 /**
427   * @brief            hid mouse test
428   * @pre              none
429   * @param[in]        none
430   * @retval           none
431   */
hid_mouse_test(uint8_t busid)432 void hid_mouse_test(uint8_t busid)
433 {
434     if(usb_device_is_configured(busid) == false) {
435         return;
436     }
437     /*!< move mouse pointer */
438     mouse_cfg.x += 10;
439     mouse_cfg.y = 0;
440 
441     hid_state = HID_STATE_BUSY;
442     usbd_ep_start_write(busid, HID_INT_EP, (uint8_t *)&mouse_cfg, 4);
443     while (hid_state == HID_STATE_BUSY) {
444     }
445 }
446 
447 volatile uint8_t dtr_enable = 0;
448 
usbd_cdc_acm_set_dtr(uint8_t busid,uint8_t intf,bool dtr)449 void usbd_cdc_acm_set_dtr(uint8_t busid, uint8_t intf, bool dtr)
450 {
451     if (dtr) {
452         dtr_enable = 1;
453     } else {
454         dtr_enable = 0;
455     }
456 }
457 
cdc_acm_data_send_with_dtr_test(uint8_t busid)458 void cdc_acm_data_send_with_dtr_test(uint8_t busid)
459 {
460     if (dtr_enable) {
461         memset(&write_buffer[10], 'a', 2038);
462         ep_tx_busy_flag = true;
463         usbd_ep_start_write(busid, CDC_IN_EP, write_buffer, 2048);
464         while (ep_tx_busy_flag) {
465         }
466     }
467 }
468 
469 #define BLOCK_SIZE  512
470 #define BLOCK_COUNT 10
471 
472 typedef struct
473 {
474     uint8_t BlockSpace[BLOCK_SIZE];
475 } BLOCK_TYPE;
476 
477 BLOCK_TYPE mass_block[BLOCK_COUNT];
478 
usbd_msc_get_cap(uint8_t busid,uint8_t lun,uint32_t * block_num,uint32_t * block_size)479 void usbd_msc_get_cap(uint8_t busid, uint8_t lun, uint32_t *block_num, uint32_t *block_size)
480 {
481     *block_num = 1000; //Pretend having so many buffer,not has actually.
482     *block_size = BLOCK_SIZE;
483 }
usbd_msc_sector_read(uint8_t busid,uint8_t lun,uint32_t sector,uint8_t * buffer,uint32_t length)484 int usbd_msc_sector_read(uint8_t busid, uint8_t lun, uint32_t sector, uint8_t *buffer, uint32_t length)
485 {
486     if (sector < 10)
487         memcpy(buffer, mass_block[sector].BlockSpace, length);
488     return 0;
489 }
490 
usbd_msc_sector_write(uint8_t busid,uint8_t lun,uint32_t sector,uint8_t * buffer,uint32_t length)491 int usbd_msc_sector_write(uint8_t busid, uint8_t lun, uint32_t sector, uint8_t *buffer, uint32_t length)
492 {
493     if (sector < 10)
494         memcpy(mass_block[sector].BlockSpace, buffer, length);
495     return 0;
496 }
497