1 /*
2  * Copyright (c) 2024, sakumisu
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 #include "usbd_core.h"
7 #include "usbd_video.h"
8 #include "usbd_audio.h"
9 #include "usbd_hid.h"
10 #include "cherryusb_mjpeg.h"
11 
12 #define MAX_PACKETS_IN_ONE_TRANSFER 1
13 
14 #define VIDEO_IN_EP  0x81
15 #define VIDEO_INT_EP 0x86
16 
17 #ifdef CONFIG_USB_HS
18 #define MAX_PAYLOAD_SIZE  1024 // for high speed with one transcations every one micro frame
19 #define VIDEO_PACKET_SIZE (unsigned int)(((MAX_PAYLOAD_SIZE / 1)) | (0x00 << 11))
20 
21 // #define MAX_PAYLOAD_SIZE  2048 // for high speed with two transcations every one micro frame
22 // #define VIDEO_PACKET_SIZE (unsigned int)(((MAX_PAYLOAD_SIZE / 2)) | (0x01 << 11))
23 
24 // #define MAX_PAYLOAD_SIZE  3072 // for high speed with three transcations every one micro frame
25 // #define VIDEO_PACKET_SIZE (unsigned int)(((MAX_PAYLOAD_SIZE / 3)) | (0x02 << 11))
26 
27 #else
28 #define MAX_PAYLOAD_SIZE  1020
29 #define VIDEO_PACKET_SIZE (unsigned int)(((MAX_PAYLOAD_SIZE / 1)) | (0x00 << 11))
30 #endif
31 
32 #define WIDTH  (unsigned int)(640)
33 #define HEIGHT (unsigned int)(480)
34 
35 #define CAM_FPS        (30)
36 #define INTERVAL       (unsigned long)(10000000 / CAM_FPS)
37 #define MIN_BIT_RATE   (unsigned long)(WIDTH * HEIGHT * 16 * CAM_FPS) //16 bit
38 #define MAX_BIT_RATE   (unsigned long)(WIDTH * HEIGHT * 16 * CAM_FPS)
39 #define MAX_FRAME_SIZE (unsigned long)(WIDTH * HEIGHT * 2)
40 
41 #define VS_HEADER_SIZ (unsigned int)(VIDEO_SIZEOF_VS_INPUT_HEADER_DESC(1, 1) + VIDEO_SIZEOF_VS_FORMAT_MJPEG_DESC + VIDEO_SIZEOF_VS_FRAME_MJPEG_DESC(1))
42 
43 #define USB_VIDEO_DESC_SIZ (unsigned long)(9 +                                       \
44                                            VIDEO_VC_NOEP_DESCRIPTOR_LEN +            \
45                                            9 +                                       \
46                                            VS_HEADER_SIZ +                           \
47                                            9 +                                       \
48                                            7 +                                       \
49                                            AUDIO_AC_DESCRIPTOR_INIT_LEN(2) +         \
50                                            AUDIO_SIZEOF_AC_INPUT_TERMINAL_DESC +     \
51                                            AUDIO_SIZEOF_AC_FEATURE_UNIT_DESC(2, 1) + \
52                                            AUDIO_SIZEOF_AC_OUTPUT_TERMINAL_DESC +    \
53                                            AUDIO_SIZEOF_AC_INPUT_TERMINAL_DESC +     \
54                                            AUDIO_SIZEOF_AC_FEATURE_UNIT_DESC(2, 1) + \
55                                            AUDIO_SIZEOF_AC_OUTPUT_TERMINAL_DESC +    \
56                                            AUDIO_AS_DESCRIPTOR_INIT_LEN(1) +         \
57                                            AUDIO_AS_DESCRIPTOR_INIT_LEN(1) +         \
58                                            25)
59 
60 #define USBD_VID           0xffff
61 #define USBD_PID           0xffff
62 #define USBD_MAX_POWER     100
63 #define USBD_LANGID_STRING 1033
64 
65 #ifdef CONFIG_USB_HS
66 #define EP_INTERVAL 0x04
67 #else
68 #define EP_INTERVAL 0x01
69 #endif
70 
71 #define AUDIO_IN_EP  0x82
72 #define AUDIO_OUT_EP 0x03
73 
74 #define AUDIO_IN_FU_ID  0x02
75 #define AUDIO_OUT_FU_ID 0x05
76 
77 /* AUDIO Class Config */
78 #define AUDIO_SPEAKER_FREQ            16000U
79 #define AUDIO_SPEAKER_FRAME_SIZE_BYTE 2u
80 #define AUDIO_SPEAKER_RESOLUTION_BIT  16u
81 #define AUDIO_MIC_FREQ                16000U
82 #define AUDIO_MIC_FRAME_SIZE_BYTE     2u
83 #define AUDIO_MIC_RESOLUTION_BIT      16u
84 
85 #define AUDIO_SAMPLE_FREQ(frq) (uint8_t)(frq), (uint8_t)((frq >> 8)), (uint8_t)((frq >> 16))
86 
87 /* AudioFreq * DataSize (2 bytes) * NumChannels (Stereo: 2) */
88 #define AUDIO_OUT_PACKET ((uint32_t)((AUDIO_SPEAKER_FREQ * AUDIO_SPEAKER_FRAME_SIZE_BYTE * 2) / 1000))
89 /* 16bit(2 Bytes) 双声道(Mono:2) */
90 #define AUDIO_IN_PACKET ((uint32_t)((AUDIO_MIC_FREQ * AUDIO_MIC_FRAME_SIZE_BYTE * 2) / 1000))
91 
92 #define AUDIO_AC_SIZ (AUDIO_SIZEOF_AC_HEADER_DESC(2) +          \
93                       AUDIO_SIZEOF_AC_INPUT_TERMINAL_DESC +     \
94                       AUDIO_SIZEOF_AC_FEATURE_UNIT_DESC(2, 1) + \
95                       AUDIO_SIZEOF_AC_OUTPUT_TERMINAL_DESC +    \
96                       AUDIO_SIZEOF_AC_INPUT_TERMINAL_DESC +     \
97                       AUDIO_SIZEOF_AC_FEATURE_UNIT_DESC(2, 1) + \
98                       AUDIO_SIZEOF_AC_OUTPUT_TERMINAL_DESC)
99 
100 #define HID_INT_EP          0x84
101 #define HID_INT_EP_SIZE     8
102 #define HID_INT_EP_INTERVAL 10
103 
104 #define HID_KEYBOARD_REPORT_DESC_SIZE 63
105 
106 #ifdef CONFIG_USBDEV_ADVANCE_DESC
107 static const uint8_t device_descriptor[] = {
108     USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0xef, 0x02, 0x01, USBD_VID, USBD_PID, 0x0001, 0x01)
109 };
110 
111 static const uint8_t config_descriptor[] = {
112     USB_CONFIG_DESCRIPTOR_INIT(USB_VIDEO_DESC_SIZ, 0x06, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
113     //VIDEO_VC_DESCRIPTOR_INIT(0x00, VIDEO_INT_EP, 0x0100, VIDEO_VC_TERMINAL_LEN, 48000000, 0x02),
114     VIDEO_VC_NOEP_DESCRIPTOR_INIT(0x00, VIDEO_INT_EP, 0x0100, VIDEO_VC_TERMINAL_LEN, 48000000, 0x02),
115     VIDEO_VS_DESCRIPTOR_INIT(0x01, 0x00, 0x00),
116     VIDEO_VS_INPUT_HEADER_DESCRIPTOR_INIT(0x01, VS_HEADER_SIZ, VIDEO_IN_EP, 0x00),
117     VIDEO_VS_FORMAT_MJPEG_DESCRIPTOR_INIT(0x01, 0x01),
118     VIDEO_VS_FRAME_MJPEG_DESCRIPTOR_INIT(0x01, WIDTH, HEIGHT, MIN_BIT_RATE, MAX_BIT_RATE, MAX_FRAME_SIZE, DBVAL(INTERVAL), 0x01, DBVAL(INTERVAL)),
119     VIDEO_VS_DESCRIPTOR_INIT(0x01, 0x01, 0x01),
120     /* 1.2.2.2 Standard VideoStream Isochronous Video Data Endpoint Descriptor */
121     USB_ENDPOINT_DESCRIPTOR_INIT(VIDEO_IN_EP, 0x05, VIDEO_PACKET_SIZE, 0x01),
122     AUDIO_AC_DESCRIPTOR_INIT(0x02, 0x03, AUDIO_AC_SIZ, 0x00, 0x03, 0x04),
123     AUDIO_AC_INPUT_TERMINAL_DESCRIPTOR_INIT(0x01, AUDIO_INTERM_MIC, 0x02, 0x0003),
124     AUDIO_AC_FEATURE_UNIT_DESCRIPTOR_INIT(0x02, 0x01, 0x01, 0x03, 0x00, 0x00),
125     AUDIO_AC_OUTPUT_TERMINAL_DESCRIPTOR_INIT(0x03, AUDIO_TERMINAL_STREAMING, 0x02),
126     AUDIO_AC_INPUT_TERMINAL_DESCRIPTOR_INIT(0x04, AUDIO_TERMINAL_STREAMING, 0x02, 0x0003),
127     AUDIO_AC_FEATURE_UNIT_DESCRIPTOR_INIT(0x05, 0x04, 0x01, 0x03, 0x00, 0x00),
128     AUDIO_AC_OUTPUT_TERMINAL_DESCRIPTOR_INIT(0x06, AUDIO_OUTTERM_SPEAKER, 0x05),
129     AUDIO_AS_DESCRIPTOR_INIT(0x03, 0x04, 0x02, AUDIO_SPEAKER_FRAME_SIZE_BYTE, AUDIO_SPEAKER_RESOLUTION_BIT, AUDIO_OUT_EP, 0x09, AUDIO_OUT_PACKET,
130                              EP_INTERVAL, AUDIO_SAMPLE_FREQ_3B(AUDIO_SPEAKER_FREQ)),
131     AUDIO_AS_DESCRIPTOR_INIT(0x04, 0x03, 0x02, AUDIO_MIC_FRAME_SIZE_BYTE, AUDIO_MIC_RESOLUTION_BIT, AUDIO_IN_EP, 0x05, AUDIO_IN_PACKET,
132                              EP_INTERVAL, AUDIO_SAMPLE_FREQ_3B(AUDIO_MIC_FREQ)),
133     /************** Descriptor of Joystick Mouse interface ****************/
134     /* 09 */
135     0x09,                          /* bLength: Interface Descriptor size */
136     USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType: Interface descriptor type */
137     0x05,                          /* bInterfaceNumber: Number of Interface */
138     0x00,                          /* bAlternateSetting: Alternate setting */
139     0x01,                          /* bNumEndpoints */
140     0x03,                          /* bInterfaceClass: HID */
141     0x01,                          /* bInterfaceSubClass : 1=BOOT, 0=no boot */
142     0x01,                          /* nInterfaceProtocol : 0=none, 1=keyboard, 2=mouse */
143     0,                             /* iInterface: Index of string descriptor */
144     /******************** Descriptor of Joystick Mouse HID ********************/
145     /* 18 */
146     0x09,                    /* bLength: HID Descriptor size */
147     HID_DESCRIPTOR_TYPE_HID, /* bDescriptorType: HID */
148     0x11,                    /* bcdHID: HID Class Spec release number */
149     0x01,
150     0x00,                          /* bCountryCode: Hardware target country */
151     0x01,                          /* bNumDescriptors: Number of HID class descriptors to follow */
152     0x22,                          /* bDescriptorType */
153     HID_KEYBOARD_REPORT_DESC_SIZE, /* wItemLength: Total length of Report descriptor */
154     0x00,
155     /******************** Descriptor of Mouse endpoint ********************/
156     /* 27 */
157     0x07,                         /* bLength: Endpoint Descriptor size */
158     USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType: */
159     HID_INT_EP,                   /* bEndpointAddress: Endpoint Address (IN) */
160     0x03,                         /* bmAttributes: Interrupt endpoint */
161     HID_INT_EP_SIZE,              /* wMaxPacketSize: 4 Byte max */
162     0x00,
163     HID_INT_EP_INTERVAL, /* bInterval: Polling Interval */
164     /* 34 */
165 };
166 
167 static const uint8_t device_quality_descriptor[] = {
168     ///////////////////////////////////////
169     /// device qualifier descriptor
170     ///////////////////////////////////////
171     0x0a,
172     USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
173     0x00,
174     0x02,
175     0x00,
176     0x00,
177     0x00,
178     0x40,
179     0x00,
180     0x00,
181 };
182 
183 static const char *string_descriptors[] = {
184     (const char[]){ 0x09, 0x04 }, /* Langid */
185     "CherryUSB",                  /* Manufacturer */
186     "CherryUSB UVC UAC HID DEMO", /* Product */
187     "2022123456",                 /* Serial Number */
188 };
189 
device_descriptor_callback(uint8_t speed)190 static const uint8_t *device_descriptor_callback(uint8_t speed)
191 {
192     return device_descriptor;
193 }
194 
config_descriptor_callback(uint8_t speed)195 static const uint8_t *config_descriptor_callback(uint8_t speed)
196 {
197     return config_descriptor;
198 }
199 
device_quality_descriptor_callback(uint8_t speed)200 static const uint8_t *device_quality_descriptor_callback(uint8_t speed)
201 {
202     return device_quality_descriptor;
203 }
204 
string_descriptor_callback(uint8_t speed,uint8_t index)205 static const char *string_descriptor_callback(uint8_t speed, uint8_t index)
206 {
207     if (index > 3) {
208         return NULL;
209     }
210     return string_descriptors[index];
211 }
212 
213 const struct usb_descriptor video_audio_hid_descriptor = {
214     .device_descriptor_callback = device_descriptor_callback,
215     .config_descriptor_callback = config_descriptor_callback,
216     .device_quality_descriptor_callback = device_quality_descriptor_callback,
217     .string_descriptor_callback = string_descriptor_callback
218 };
219 #else
220 const uint8_t video_audio_hid_descriptor[] = {
221     USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0xef, 0x02, 0x01, USBD_VID, USBD_PID, 0x0001, 0x01),
222     USB_CONFIG_DESCRIPTOR_INIT(USB_VIDEO_DESC_SIZ, 0x06, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
223     //VIDEO_VC_DESCRIPTOR_INIT(0x00, VIDEO_INT_EP, 0x0100, VIDEO_VC_TERMINAL_LEN, 48000000, 0x02),
224     VIDEO_VC_NOEP_DESCRIPTOR_INIT(0x00, VIDEO_INT_EP, 0x0100, VIDEO_VC_TERMINAL_LEN, 48000000, 0x02),
225     VIDEO_VS_DESCRIPTOR_INIT(0x01, 0x00, 0x00),
226     VIDEO_VS_INPUT_HEADER_DESCRIPTOR_INIT(0x01, VS_HEADER_SIZ, VIDEO_IN_EP, 0x00),
227     VIDEO_VS_FORMAT_MJPEG_DESCRIPTOR_INIT(0x01, 0x01),
228     VIDEO_VS_FRAME_MJPEG_DESCRIPTOR_INIT(0x01, WIDTH, HEIGHT, MIN_BIT_RATE, MAX_BIT_RATE, MAX_FRAME_SIZE, DBVAL(INTERVAL), 0x01, DBVAL(INTERVAL)),
229     VIDEO_VS_DESCRIPTOR_INIT(0x01, 0x01, 0x01),
230     /* 1.2.2.2 Standard VideoStream Isochronous Video Data Endpoint Descriptor */
231     USB_ENDPOINT_DESCRIPTOR_INIT(VIDEO_IN_EP, 0x05, VIDEO_PACKET_SIZE, 0x01),
232     AUDIO_AC_DESCRIPTOR_INIT(0x02, 0x03, AUDIO_AC_SIZ, 0x00, 0x03, 0x04),
233     AUDIO_AC_INPUT_TERMINAL_DESCRIPTOR_INIT(0x01, AUDIO_INTERM_MIC, 0x02, 0x0003),
234     AUDIO_AC_FEATURE_UNIT_DESCRIPTOR_INIT(0x02, 0x01, 0x01, 0x03, 0x00, 0x00),
235     AUDIO_AC_OUTPUT_TERMINAL_DESCRIPTOR_INIT(0x03, AUDIO_TERMINAL_STREAMING, 0x02),
236     AUDIO_AC_INPUT_TERMINAL_DESCRIPTOR_INIT(0x04, AUDIO_TERMINAL_STREAMING, 0x02, 0x0003),
237     AUDIO_AC_FEATURE_UNIT_DESCRIPTOR_INIT(0x05, 0x04, 0x01, 0x03, 0x00, 0x00),
238     AUDIO_AC_OUTPUT_TERMINAL_DESCRIPTOR_INIT(0x06, AUDIO_OUTTERM_SPEAKER, 0x05),
239     AUDIO_AS_DESCRIPTOR_INIT(0x03, 0x04, 0x02, AUDIO_SPEAKER_FRAME_SIZE_BYTE, AUDIO_SPEAKER_RESOLUTION_BIT, AUDIO_OUT_EP, 0x09, AUDIO_OUT_PACKET,
240                              EP_INTERVAL, AUDIO_SAMPLE_FREQ_3B(AUDIO_SPEAKER_FREQ)),
241     AUDIO_AS_DESCRIPTOR_INIT(0x04, 0x03, 0x02, AUDIO_MIC_FRAME_SIZE_BYTE, AUDIO_MIC_RESOLUTION_BIT, AUDIO_IN_EP, 0x05, AUDIO_IN_PACKET,
242                              EP_INTERVAL, AUDIO_SAMPLE_FREQ_3B(AUDIO_MIC_FREQ)),
243     /************** Descriptor of Joystick Mouse interface ****************/
244     /* 09 */
245     0x09,                          /* bLength: Interface Descriptor size */
246     USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType: Interface descriptor type */
247     0x05,                          /* bInterfaceNumber: Number of Interface */
248     0x00,                          /* bAlternateSetting: Alternate setting */
249     0x01,                          /* bNumEndpoints */
250     0x03,                          /* bInterfaceClass: HID */
251     0x01,                          /* bInterfaceSubClass : 1=BOOT, 0=no boot */
252     0x01,                          /* nInterfaceProtocol : 0=none, 1=keyboard, 2=mouse */
253     0,                             /* iInterface: Index of string descriptor */
254     /******************** Descriptor of Joystick Mouse HID ********************/
255     /* 18 */
256     0x09,                    /* bLength: HID Descriptor size */
257     HID_DESCRIPTOR_TYPE_HID, /* bDescriptorType: HID */
258     0x11,                    /* bcdHID: HID Class Spec release number */
259     0x01,
260     0x00,                          /* bCountryCode: Hardware target country */
261     0x01,                          /* bNumDescriptors: Number of HID class descriptors to follow */
262     0x22,                          /* bDescriptorType */
263     HID_KEYBOARD_REPORT_DESC_SIZE, /* wItemLength: Total length of Report descriptor */
264     0x00,
265     /******************** Descriptor of Mouse endpoint ********************/
266     /* 27 */
267     0x07,                         /* bLength: Endpoint Descriptor size */
268     USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType: */
269     HID_INT_EP,                   /* bEndpointAddress: Endpoint Address (IN) */
270     0x03,                         /* bmAttributes: Interrupt endpoint */
271     HID_INT_EP_SIZE,              /* wMaxPacketSize: 4 Byte max */
272     0x00,
273     HID_INT_EP_INTERVAL, /* bInterval: Polling Interval */
274     /* 34 */
275     ///////////////////////////////////////
276     /// string0 descriptor
277     ///////////////////////////////////////
278     USB_LANGID_INIT(USBD_LANGID_STRING),
279     ///////////////////////////////////////
280     /// string1 descriptor
281     ///////////////////////////////////////
282     0x14,                       /* bLength */
283     USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
284     'C', 0x00,                  /* wcChar0 */
285     'h', 0x00,                  /* wcChar1 */
286     'e', 0x00,                  /* wcChar2 */
287     'r', 0x00,                  /* wcChar3 */
288     'r', 0x00,                  /* wcChar4 */
289     'y', 0x00,                  /* wcChar5 */
290     'U', 0x00,                  /* wcChar6 */
291     'S', 0x00,                  /* wcChar7 */
292     'B', 0x00,                  /* wcChar8 */
293     ///////////////////////////////////////
294     /// string2 descriptor
295     ///////////////////////////////////////
296     0x26,                       /* bLength */
297     USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
298     'C', 0x00,                  /* wcChar0 */
299     'h', 0x00,                  /* wcChar1 */
300     'e', 0x00,                  /* wcChar2 */
301     'r', 0x00,                  /* wcChar3 */
302     'r', 0x00,                  /* wcChar4 */
303     'y', 0x00,                  /* wcChar5 */
304     'U', 0x00,                  /* wcChar6 */
305     'S', 0x00,                  /* wcChar7 */
306     'B', 0x00,                  /* wcChar8 */
307     ' ', 0x00,                  /* wcChar9 */
308     'U', 0x00,                  /* wcChar10 */
309     'A', 0x00,                  /* wcChar11 */
310     'C', 0x00,                  /* wcChar12 */
311     ' ', 0x00,                  /* wcChar13 */
312     'D', 0x00,                  /* wcChar14 */
313     'E', 0x00,                  /* wcChar15 */
314     'M', 0x00,                  /* wcChar16 */
315     'O', 0x00,                  /* wcChar17 */
316     ///////////////////////////////////////
317     /// string3 descriptor
318     ///////////////////////////////////////
319     0x16,                       /* bLength */
320     USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
321     '2', 0x00,                  /* wcChar0 */
322     '0', 0x00,                  /* wcChar1 */
323     '2', 0x00,                  /* wcChar2 */
324     '4', 0x00,                  /* wcChar3 */
325     '0', 0x00,                  /* wcChar4 */
326     '3', 0x00,                  /* wcChar5 */
327     '1', 0x00,                  /* wcChar6 */
328     '0', 0x00,                  /* wcChar7 */
329     '0', 0x00,                  /* wcChar8 */
330     '0', 0x00,                  /* wcChar9 */
331 #ifdef CONFIG_USB_HS
332     ///////////////////////////////////////
333     /// device qualifier descriptor
334     ///////////////////////////////////////
335     0x0a,
336     USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
337     0x00,
338     0x02,
339     0x00,
340     0x00,
341     0x00,
342     0x40,
343     0x00,
344     0x00,
345 #endif
346     0x00
347 };
348 #endif
349 
350 static const uint8_t hid_keyboard_report_desc[HID_KEYBOARD_REPORT_DESC_SIZE] = {
351     0x05, 0x01, // USAGE_PAGE (Generic Desktop)
352     0x09, 0x06, // USAGE (Keyboard)
353     0xa1, 0x01, // COLLECTION (Application)
354     0x05, 0x07, // USAGE_PAGE (Keyboard)
355     0x19, 0xe0, // USAGE_MINIMUM (Keyboard LeftControl)
356     0x29, 0xe7, // USAGE_MAXIMUM (Keyboard Right GUI)
357     0x15, 0x00, // LOGICAL_MINIMUM (0)
358     0x25, 0x01, // LOGICAL_MAXIMUM (1)
359     0x75, 0x01, // REPORT_SIZE (1)
360     0x95, 0x08, // REPORT_COUNT (8)
361     0x81, 0x02, // INPUT (Data,Var,Abs)
362     0x95, 0x01, // REPORT_COUNT (1)
363     0x75, 0x08, // REPORT_SIZE (8)
364     0x81, 0x03, // INPUT (Cnst,Var,Abs)
365     0x95, 0x05, // REPORT_COUNT (5)
366     0x75, 0x01, // REPORT_SIZE (1)
367     0x05, 0x08, // USAGE_PAGE (LEDs)
368     0x19, 0x01, // USAGE_MINIMUM (Num Lock)
369     0x29, 0x05, // USAGE_MAXIMUM (Kana)
370     0x91, 0x02, // OUTPUT (Data,Var,Abs)
371     0x95, 0x01, // REPORT_COUNT (1)
372     0x75, 0x03, // REPORT_SIZE (3)
373     0x91, 0x03, // OUTPUT (Cnst,Var,Abs)
374     0x95, 0x06, // REPORT_COUNT (6)
375     0x75, 0x08, // REPORT_SIZE (8)
376     0x15, 0x00, // LOGICAL_MINIMUM (0)
377     0x25, 0xFF, // LOGICAL_MAXIMUM (255)
378     0x05, 0x07, // USAGE_PAGE (Keyboard)
379     0x19, 0x00, // USAGE_MINIMUM (Reserved (no event indicated))
380     0x29, 0x65, // USAGE_MAXIMUM (Keyboard Application)
381     0x81, 0x00, // INPUT (Data,Ary,Abs)
382     0xc0        // END_COLLECTION
383 };
384 
385 USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t audio_read_buffer[AUDIO_OUT_PACKET];
386 USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t audio_write_buffer[AUDIO_IN_PACKET];
387 USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t video_packet_buffer[2][MAX_PACKETS_IN_ONE_TRANSFER * MAX_PAYLOAD_SIZE];
388 
389 volatile bool video_tx_flag = 0;
390 volatile bool audio_tx_flag = 0;
391 volatile bool audio_rx_flag = 0;
392 volatile bool video_iso_tx_busy = false;
393 volatile bool audio_iso_tx_busy = false;
394 
395 #define HID_STATE_IDLE 0
396 #define HID_STATE_BUSY 1
397 
398 /*!< hid state ! Data can be sent only when state is idle  */
399 static volatile uint8_t hid_state = HID_STATE_IDLE;
400 
usbd_event_handler(uint8_t busid,uint8_t event)401 static void usbd_event_handler(uint8_t busid, uint8_t event)
402 {
403     switch (event) {
404         case USBD_EVENT_RESET:
405             break;
406         case USBD_EVENT_CONNECTED:
407             break;
408         case USBD_EVENT_DISCONNECTED:
409             break;
410         case USBD_EVENT_RESUME:
411             break;
412         case USBD_EVENT_SUSPEND:
413             break;
414         case USBD_EVENT_CONFIGURED:
415             video_tx_flag = 0;
416             audio_tx_flag = 0;
417             audio_rx_flag = 0;
418             video_iso_tx_busy = false;
419             audio_iso_tx_busy = false;
420             hid_state = HID_STATE_IDLE;
421             break;
422         case USBD_EVENT_SET_REMOTE_WAKEUP:
423             break;
424         case USBD_EVENT_CLR_REMOTE_WAKEUP:
425             break;
426 
427         default:
428             break;
429     }
430 }
431 
usbd_video_open(uint8_t busid,uint8_t intf)432 void usbd_video_open(uint8_t busid, uint8_t intf)
433 {
434     if (intf == 1) {
435         video_tx_flag = 1;
436         USB_LOG_RAW("OPEN\r\n");
437         video_iso_tx_busy = false;
438     }
439 }
usbd_video_close(uint8_t busid,uint8_t intf)440 void usbd_video_close(uint8_t busid, uint8_t intf)
441 {
442     if (intf == 1) {
443         USB_LOG_RAW("CLOSE\r\n");
444         video_tx_flag = 0;
445         video_iso_tx_busy = false;
446     }
447 }
448 
usbd_video_iso_callback(uint8_t busid,uint8_t ep,uint32_t nbytes)449 void usbd_video_iso_callback(uint8_t busid, uint8_t ep, uint32_t nbytes)
450 {
451     if (nbytes == 0) {
452         return;
453     }
454 
455     if (usbd_video_stream_split_transfer(busid, ep)) {
456         /* one frame has done */
457         video_iso_tx_busy = false;
458     }
459 }
460 
461 static struct usbd_endpoint video_in_ep = {
462     .ep_cb = usbd_video_iso_callback,
463     .ep_addr = VIDEO_IN_EP
464 };
465 
usbd_audio_open(uint8_t busid,uint8_t intf)466 void usbd_audio_open(uint8_t busid, uint8_t intf)
467 {
468     if (intf == 3) {
469         audio_rx_flag = 1;
470         /* setup first out ep read transfer */
471         usbd_ep_start_read(busid, AUDIO_OUT_EP, audio_read_buffer, AUDIO_OUT_PACKET);
472         printf("OPEN1\r\n");
473     } else if (intf == 4) {
474         audio_tx_flag = 1;
475         audio_iso_tx_busy = false;
476         printf("OPEN2\r\n");
477     }
478 }
479 
usbd_audio_close(uint8_t busid,uint8_t intf)480 void usbd_audio_close(uint8_t busid, uint8_t intf)
481 {
482     if (intf == 3) {
483         audio_rx_flag = 0;
484         printf("CLOSE1\r\n");
485     } else if (intf == 4) {
486         audio_tx_flag = 0;
487         audio_iso_tx_busy = false;
488         printf("CLOSE2\r\n");
489     }
490 }
491 
usbd_audio_out_callback(uint8_t busid,uint8_t ep,uint32_t nbytes)492 void usbd_audio_out_callback(uint8_t busid, uint8_t ep, uint32_t nbytes)
493 {
494     USB_LOG_RAW("actual out len:%d\r\n", (unsigned int)nbytes);
495     usbd_ep_start_read(busid, AUDIO_OUT_EP, audio_read_buffer, AUDIO_OUT_PACKET);
496 }
497 
usbd_audio_in_callback(uint8_t busid,uint8_t ep,uint32_t nbytes)498 void usbd_audio_in_callback(uint8_t busid, uint8_t ep, uint32_t nbytes)
499 {
500     USB_LOG_RAW("actual in len:%d\r\n", (unsigned int)nbytes);
501     audio_iso_tx_busy = false;
502 }
503 
504 static struct usbd_endpoint audio_in_ep = {
505     .ep_cb = usbd_audio_in_callback,
506     .ep_addr = AUDIO_IN_EP
507 };
508 
509 static struct usbd_endpoint audio_out_ep = {
510     .ep_cb = usbd_audio_out_callback,
511     .ep_addr = AUDIO_OUT_EP
512 };
513 
usbd_hid_int_callback(uint8_t busid,uint8_t ep,uint32_t nbytes)514 void usbd_hid_int_callback(uint8_t busid, uint8_t ep, uint32_t nbytes)
515 {
516     hid_state = HID_STATE_IDLE;
517 }
518 
519 static struct usbd_endpoint hid_in_ep = {
520     .ep_cb = usbd_hid_int_callback,
521     .ep_addr = HID_INT_EP
522 };
523 
524 struct usbd_interface intf0;
525 struct usbd_interface intf1;
526 
527 struct usbd_interface intf2;
528 struct usbd_interface intf3;
529 struct usbd_interface intf4;
530 
531 struct usbd_interface intf5;
532 
533 struct audio_entity_info audio_entity_table[] = {
534     { .bEntityId = AUDIO_IN_FU_ID,
535       .bDescriptorSubtype = AUDIO_CONTROL_FEATURE_UNIT,
536       .ep = AUDIO_IN_EP },
537     { .bEntityId = AUDIO_OUT_FU_ID,
538       .bDescriptorSubtype = AUDIO_CONTROL_FEATURE_UNIT,
539       .ep = AUDIO_OUT_EP },
540 };
541 
composite_init(uint8_t busid,uintptr_t reg_base)542 void composite_init(uint8_t busid, uintptr_t reg_base)
543 {
544 #ifdef CONFIG_USBDEV_ADVANCE_DESC
545     usbd_desc_register(busid, &video_audio_hid_descriptor);
546 #else
547     usbd_desc_register(busid, video_audio_hid_descriptor);
548 #endif
549     usbd_add_interface(busid, usbd_video_init_intf(busid, &intf0, INTERVAL, MAX_FRAME_SIZE, MAX_PAYLOAD_SIZE));
550     usbd_add_interface(busid, usbd_video_init_intf(busid, &intf1, INTERVAL, MAX_FRAME_SIZE, MAX_PAYLOAD_SIZE));
551     usbd_add_endpoint(busid, &video_in_ep);
552 
553     usbd_add_interface(busid, usbd_audio_init_intf(busid, &intf2, 0x0100, audio_entity_table, 2));
554     usbd_add_interface(busid, usbd_audio_init_intf(busid, &intf3, 0x0100, audio_entity_table, 2));
555     usbd_add_interface(busid, usbd_audio_init_intf(busid, &intf4, 0x0100, audio_entity_table, 2));
556     usbd_add_endpoint(busid, &audio_in_ep);
557     usbd_add_endpoint(busid, &audio_out_ep);
558 
559     usbd_add_interface(busid, usbd_hid_init_intf(busid, &intf0, hid_keyboard_report_desc, HID_KEYBOARD_REPORT_DESC_SIZE));
560     usbd_add_endpoint(busid, &hid_in_ep);
561 
562     usbd_initialize(busid, reg_base, usbd_event_handler);
563 }
564 
565 /* just for test, rewrite by yourself */
audio_test(uint8_t busid)566 void audio_test(uint8_t busid)
567 {
568     while (1) {
569         if (audio_tx_flag) {
570             memset(audio_write_buffer, 'a', AUDIO_IN_PACKET);
571             audio_iso_tx_busy = true;
572             usbd_ep_start_write(busid, AUDIO_IN_EP, audio_write_buffer, AUDIO_IN_PACKET);
573             while (audio_iso_tx_busy) {
574                 if (audio_tx_flag == false) {
575                     break;
576                 }
577             }
578         }
579     }
580 }
581 
582 USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t hid_write_buffer[64];
583 
hid_keyboard_test(uint8_t busid)584 void hid_keyboard_test(uint8_t busid)
585 {
586     const uint8_t sendbuffer[8] = { 0x00, 0x00, HID_KBD_USAGE_A, 0x00, 0x00, 0x00, 0x00, 0x00 };
587 
588     if(usb_device_is_configured(busid) == false) {
589         return;
590     }
591 
592     memcpy(hid_write_buffer, sendbuffer, 8);
593     hid_state = HID_STATE_BUSY;
594     usbd_ep_start_write(busid, HID_INT_EP, hid_write_buffer, 8);
595     while (hid_state == HID_STATE_BUSY) {
596     }
597 }
598 
video_test(uint8_t busid)599 void video_test(uint8_t busid)
600 {
601     memset(video_packet_buffer, 0, sizeof(video_packet_buffer));
602 
603     while (1) {
604         if (video_tx_flag) {
605             video_iso_tx_busy = true;
606             usbd_video_stream_start_write(busid, VIDEO_IN_EP, &video_packet_buffer[0][0], &video_packet_buffer[1][0], MAX_PACKETS_IN_ONE_TRANSFER * MAX_PAYLOAD_SIZE, (uint8_t *)cherryusb_mjpeg, sizeof(cherryusb_mjpeg));
607             while (video_iso_tx_busy) {
608                 if (video_tx_flag == 0) {
609                     break;
610                 }
611             }
612         }
613     }
614 }