1 /*
2  * Copyright (c) 2024, sakumisu
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 #include "usbd_core.h"
7 #include "usbd_audio.h"
8 
9 #define USING_FEEDBACK 0
10 
11 #define USBD_VID           0xffff
12 #define USBD_PID           0xffff
13 #define USBD_MAX_POWER     100
14 #define USBD_LANGID_STRING 1033
15 
16 #ifdef CONFIG_USB_HS
17 #define EP_INTERVAL               0x04
18 #define FEEDBACK_ENDP_PACKET_SIZE 0x04
19 #else
20 #define EP_INTERVAL               0x01
21 #define FEEDBACK_ENDP_PACKET_SIZE 0x03
22 #endif
23 
24 #define AUDIO_OUT_EP          0x02
25 #define AUDIO_IN_EP           0x81
26 #define AUDIO_OUT_FEEDBACK_EP 0x83
27 
28 #define AUDIO_OUT_CLOCK_ID 0x01
29 #define AUDIO_OUT_FU_ID    0x03
30 #define AUDIO_IN_CLOCK_ID  0x05
31 #define AUDIO_IN_FU_ID     0x07
32 
33 #define AUDIO_OUT_MAX_FREQ 96000
34 #define AUDIO_IN_MAX_FREQ  16000
35 
36 #define HALF_WORD_BYTES 2  //2 half word (one channel)
37 #define SAMPLE_BITS     16 //16 bit per channel
38 
39 #define BMCONTROL (AUDIO_V2_FU_CONTROL_MUTE | AUDIO_V2_FU_CONTROL_VOLUME)
40 
41 #define IN_CHANNEL_NUM 2
42 
43 #if IN_CHANNEL_NUM == 1
44 #define INPUT_CTRL      DBVAL(BMCONTROL), DBVAL(BMCONTROL)
45 #define INPUT_CH_ENABLE 0x00000000
46 #elif IN_CHANNEL_NUM == 2
47 #define INPUT_CTRL      DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
48 #define INPUT_CH_ENABLE 0x00000003
49 #elif IN_CHANNEL_NUM == 3
50 #define INPUT_CTRL      DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
51 #define INPUT_CH_ENABLE 0x00000007
52 #elif IN_CHANNEL_NUM == 4
53 #define INPUT_CTRL      DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
54 #define INPUT_CH_ENABLE 0x0000000f
55 #elif IN_CHANNEL_NUM == 5
56 #define INPUT_CTRL      DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
57 #define INPUT_CH_ENABLE 0x0000001f
58 #elif IN_CHANNEL_NUM == 6
59 #define INPUT_CTRL      DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
60 #define INPUT_CH_ENABLE 0x0000003F
61 #elif IN_CHANNEL_NUM == 7
62 #define INPUT_CTRL      DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
63 #define INPUT_CH_ENABLE 0x0000007f
64 #elif IN_CHANNEL_NUM == 8
65 #define INPUT_CTRL      DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
66 #define INPUT_CH_ENABLE 0x000000ff
67 #endif
68 
69 #define OUT_CHANNEL_NUM 2
70 
71 #if OUT_CHANNEL_NUM == 1
72 #define OUTPUT_CTRL      DBVAL(BMCONTROL), DBVAL(BMCONTROL)
73 #define OUTPUT_CH_ENABLE 0x00000000
74 #elif OUT_CHANNEL_NUM == 2
75 #define OUTPUT_CTRL      DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
76 #define OUTPUT_CH_ENABLE 0x00000003
77 #elif OUT_CHANNEL_NUM == 3
78 #define OUTPUT_CTRL      DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
79 #define OUTPUT_CH_ENABLE 0x00000007
80 #elif OUT_CHANNEL_NUM == 4
81 #define OUTPUT_CTRL      DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
82 #define OUTPUT_CH_ENABLE 0x0000000f
83 #elif OUT_CHANNEL_NUM == 5
84 #define OUTPUT_CTRL      DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
85 #define OUTPUT_CH_ENABLE 0x0000001f
86 #elif OUT_CHANNEL_NUM == 6
87 #define OUTPUT_CTRL      DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
88 #define OUTPUT_CH_ENABLE 0x0000003F
89 #elif OUT_CHANNEL_NUM == 7
90 #define OUTPUT_CTRL      DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
91 #define OUTPUT_CH_ENABLE 0x0000007f
92 #elif OUT_CHANNEL_NUM == 8
93 #define OUTPUT_CTRL      DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
94 #define OUTPUT_CH_ENABLE 0x000000ff
95 #endif
96 
97 /* AudioFreq * DataSize (2 bytes) * NumChannels */
98 #define AUDIO_OUT_PACKET ((uint32_t)((AUDIO_OUT_MAX_FREQ * HALF_WORD_BYTES * OUT_CHANNEL_NUM) / 1000))
99 #define AUDIO_IN_PACKET  ((uint32_t)((AUDIO_IN_MAX_FREQ * HALF_WORD_BYTES * IN_CHANNEL_NUM) / 1000))
100 
101 #if USING_FEEDBACK == 0
102 #define USB_AUDIO_CONFIG_DESC_SIZ (9 +                                                     \
103                                    AUDIO_V2_AC_DESCRIPTOR_INIT_LEN +                       \
104                                    AUDIO_V2_SIZEOF_AC_CLOCK_SOURCE_DESC +                  \
105                                    AUDIO_V2_SIZEOF_AC_INPUT_TERMINAL_DESC +                \
106                                    AUDIO_V2_SIZEOF_AC_FEATURE_UNIT_DESC(OUT_CHANNEL_NUM) + \
107                                    AUDIO_V2_SIZEOF_AC_OUTPUT_TERMINAL_DESC +               \
108                                    AUDIO_V2_SIZEOF_AC_CLOCK_SOURCE_DESC +                  \
109                                    AUDIO_V2_SIZEOF_AC_INPUT_TERMINAL_DESC +                \
110                                    AUDIO_V2_SIZEOF_AC_FEATURE_UNIT_DESC(IN_CHANNEL_NUM) +  \
111                                    AUDIO_V2_SIZEOF_AC_OUTPUT_TERMINAL_DESC +               \
112                                    AUDIO_V2_AS_DESCRIPTOR_INIT_LEN +                       \
113                                    AUDIO_V2_AS_DESCRIPTOR_INIT_LEN)
114 #else
115 #define USB_AUDIO_CONFIG_DESC_SIZ (9 +                                                     \
116                                    AUDIO_V2_AC_DESCRIPTOR_INIT_LEN +                       \
117                                    AUDIO_V2_SIZEOF_AC_CLOCK_SOURCE_DESC +                  \
118                                    AUDIO_V2_SIZEOF_AC_INPUT_TERMINAL_DESC +                \
119                                    AUDIO_V2_SIZEOF_AC_FEATURE_UNIT_DESC(OUT_CHANNEL_NUM) + \
120                                    AUDIO_V2_SIZEOF_AC_OUTPUT_TERMINAL_DESC +               \
121                                    AUDIO_V2_SIZEOF_AC_CLOCK_SOURCE_DESC +                  \
122                                    AUDIO_V2_SIZEOF_AC_INPUT_TERMINAL_DESC +                \
123                                    AUDIO_V2_SIZEOF_AC_FEATURE_UNIT_DESC(IN_CHANNEL_NUM) +  \
124                                    AUDIO_V2_SIZEOF_AC_OUTPUT_TERMINAL_DESC +               \
125                                    AUDIO_V2_AS_FEEDBACK_DESCRIPTOR_INIT_LEN +              \
126                                    AUDIO_V2_AS_DESCRIPTOR_INIT_LEN)
127 #endif
128 
129 #define AUDIO_AC_SIZ (AUDIO_V2_SIZEOF_AC_HEADER_DESC +                        \
130                       AUDIO_V2_SIZEOF_AC_CLOCK_SOURCE_DESC +                  \
131                       AUDIO_V2_SIZEOF_AC_INPUT_TERMINAL_DESC +                \
132                       AUDIO_V2_SIZEOF_AC_FEATURE_UNIT_DESC(OUT_CHANNEL_NUM) + \
133                       AUDIO_V2_SIZEOF_AC_OUTPUT_TERMINAL_DESC +               \
134                       AUDIO_V2_SIZEOF_AC_CLOCK_SOURCE_DESC +                  \
135                       AUDIO_V2_SIZEOF_AC_INPUT_TERMINAL_DESC +                \
136                       AUDIO_V2_SIZEOF_AC_FEATURE_UNIT_DESC(IN_CHANNEL_NUM) +  \
137                       AUDIO_V2_SIZEOF_AC_OUTPUT_TERMINAL_DESC)
138 
139 #ifdef CONFIG_USBDEV_ADVANCE_DESC
140 static const uint8_t device_descriptor[] = {
141     USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0x00, 0x00, 0x00, USBD_VID, USBD_PID, 0x0001, 0x01)
142 };
143 
144 static const uint8_t config_descriptor[] = {
145     USB_CONFIG_DESCRIPTOR_INIT(USB_AUDIO_CONFIG_DESC_SIZ, 0x03, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
146     AUDIO_V2_AC_DESCRIPTOR_INIT(0x00, 0x03, AUDIO_AC_SIZ, AUDIO_CATEGORY_UNDEF, 0x00, 0x00),
147     AUDIO_V2_AC_CLOCK_SOURCE_DESCRIPTOR_INIT(0x01, 0x03, 0x03),
148     AUDIO_V2_AC_INPUT_TERMINAL_DESCRIPTOR_INIT(0x02, AUDIO_TERMINAL_STREAMING, 0x01, OUT_CHANNEL_NUM, OUTPUT_CH_ENABLE, 0x0000),
149     AUDIO_V2_AC_FEATURE_UNIT_DESCRIPTOR_INIT(0x03, 0x02, OUTPUT_CTRL),
150     AUDIO_V2_AC_OUTPUT_TERMINAL_DESCRIPTOR_INIT(0x04, AUDIO_OUTTERM_SPEAKER, 0x03, 0x01, 0x0000),
151     AUDIO_V2_AC_CLOCK_SOURCE_DESCRIPTOR_INIT(0x05, 0x03, 0x03),
152     AUDIO_V2_AC_INPUT_TERMINAL_DESCRIPTOR_INIT(0x06, AUDIO_INTERM_MIC, 0x05, IN_CHANNEL_NUM, INPUT_CH_ENABLE, 0x0000),
153     AUDIO_V2_AC_FEATURE_UNIT_DESCRIPTOR_INIT(0x07, 0x06, INPUT_CTRL),
154     AUDIO_V2_AC_OUTPUT_TERMINAL_DESCRIPTOR_INIT(0x08, AUDIO_TERMINAL_STREAMING, 0x07, 0x05, 0x0000),
155 #if USING_FEEDBACK == 0
156     AUDIO_V2_AS_DESCRIPTOR_INIT(0x01, 0x02, OUT_CHANNEL_NUM, OUTPUT_CH_ENABLE, HALF_WORD_BYTES, SAMPLE_BITS, AUDIO_OUT_EP, 0x09, AUDIO_OUT_PACKET, EP_INTERVAL),
157 #else
158     AUDIO_V2_AS_FEEDBACK_DESCRIPTOR_INIT(0x01, 0x02, OUT_CHANNEL_NUM, OUTPUT_CH_ENABLE, HALF_WORD_BYTES, SAMPLE_BITS, AUDIO_OUT_EP, 0x09, AUDIO_OUT_PACKET, EP_INTERVAL, AUDIO_OUT_FEEDBACK_EP),
159 #endif
160     AUDIO_V2_AS_DESCRIPTOR_INIT(0x02, 0x08, IN_CHANNEL_NUM, INPUT_CH_ENABLE, HALF_WORD_BYTES, SAMPLE_BITS, AUDIO_IN_EP, 0x05, (AUDIO_IN_PACKET + 4), EP_INTERVAL)
161 };
162 
163 static const uint8_t device_quality_descriptor[] = {
164     ///////////////////////////////////////
165     /// device qualifier descriptor
166     ///////////////////////////////////////
167     0x0a,
168     USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
169     0x00,
170     0x02,
171     0x00,
172     0x00,
173     0x00,
174     0x40,
175     0x00,
176     0x00,
177 };
178 
179 static const char *string_descriptors[] = {
180     (const char[]){ 0x09, 0x04 }, /* Langid */
181     "CherryUSB",                  /* Manufacturer */
182     "CherryUSB UAC DEMO",         /* Product */
183     "2022123456",                 /* Serial Number */
184 };
185 
device_descriptor_callback(uint8_t speed)186 static const uint8_t *device_descriptor_callback(uint8_t speed)
187 {
188     return device_descriptor;
189 }
190 
config_descriptor_callback(uint8_t speed)191 static const uint8_t *config_descriptor_callback(uint8_t speed)
192 {
193     return config_descriptor;
194 }
195 
device_quality_descriptor_callback(uint8_t speed)196 static const uint8_t *device_quality_descriptor_callback(uint8_t speed)
197 {
198     return device_quality_descriptor;
199 }
200 
string_descriptor_callback(uint8_t speed,uint8_t index)201 static const char *string_descriptor_callback(uint8_t speed, uint8_t index)
202 {
203     if (index > 3) {
204         return NULL;
205     }
206     return string_descriptors[index];
207 }
208 
209 const struct usb_descriptor audio_v2_descriptor = {
210     .device_descriptor_callback = device_descriptor_callback,
211     .config_descriptor_callback = config_descriptor_callback,
212     .device_quality_descriptor_callback = device_quality_descriptor_callback,
213     .string_descriptor_callback = string_descriptor_callback
214 };
215 #else
216 uint8_t audio_v2_descriptor[] = {
217     USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0x00, 0x00, 0x00, USBD_VID, USBD_PID, 0x0001, 0x01),
218     USB_CONFIG_DESCRIPTOR_INIT(USB_AUDIO_CONFIG_DESC_SIZ, 0x03, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
219     AUDIO_V2_AC_DESCRIPTOR_INIT(0x00, 0x03, AUDIO_AC_SIZ, AUDIO_CATEGORY_UNDEF, 0x00, 0x00),
220     AUDIO_V2_AC_CLOCK_SOURCE_DESCRIPTOR_INIT(0x01, 0x03, 0x03),
221     AUDIO_V2_AC_INPUT_TERMINAL_DESCRIPTOR_INIT(0x02, AUDIO_TERMINAL_STREAMING, 0x01, OUT_CHANNEL_NUM, OUTPUT_CH_ENABLE, 0x0000),
222     AUDIO_V2_AC_FEATURE_UNIT_DESCRIPTOR_INIT(0x03, 0x02, OUTPUT_CTRL),
223     AUDIO_V2_AC_OUTPUT_TERMINAL_DESCRIPTOR_INIT(0x04, AUDIO_OUTTERM_SPEAKER, 0x03, 0x01, 0x0000),
224     AUDIO_V2_AC_CLOCK_SOURCE_DESCRIPTOR_INIT(0x05, 0x03, 0x03),
225     AUDIO_V2_AC_INPUT_TERMINAL_DESCRIPTOR_INIT(0x06, AUDIO_INTERM_MIC, 0x05, IN_CHANNEL_NUM, INPUT_CH_ENABLE, 0x0000),
226     AUDIO_V2_AC_FEATURE_UNIT_DESCRIPTOR_INIT(0x07, 0x06, INPUT_CTRL),
227     AUDIO_V2_AC_OUTPUT_TERMINAL_DESCRIPTOR_INIT(0x08, AUDIO_TERMINAL_STREAMING, 0x07, 0x05, 0x0000),
228 #if USING_FEEDBACK == 0
229     AUDIO_V2_AS_DESCRIPTOR_INIT(0x01, 0x02, OUT_CHANNEL_NUM, OUTPUT_CH_ENABLE, HALF_WORD_BYTES, SAMPLE_BITS, AUDIO_OUT_EP, 0x09, AUDIO_OUT_PACKET, EP_INTERVAL),
230 #else
231     AUDIO_V2_AS_FEEDBACK_DESCRIPTOR_INIT(0x01, 0x02, OUT_CHANNEL_NUM, OUTPUT_CH_ENABLE, HALF_WORD_BYTES, SAMPLE_BITS, AUDIO_OUT_EP, 0x09, AUDIO_OUT_PACKET, EP_INTERVAL, AUDIO_OUT_FEEDBACK_EP),
232 #endif
233     AUDIO_V2_AS_DESCRIPTOR_INIT(0x02, 0x08, IN_CHANNEL_NUM, INPUT_CH_ENABLE, HALF_WORD_BYTES, SAMPLE_BITS, AUDIO_IN_EP, 0x05, (AUDIO_IN_PACKET + 4), EP_INTERVAL),
234     ///////////////////////////////////////
235     /// string0 descriptor
236     ///////////////////////////////////////
237     USB_LANGID_INIT(USBD_LANGID_STRING),
238     ///////////////////////////////////////
239     /// string1 descriptor
240     ///////////////////////////////////////
241     0x14,                       /* bLength */
242     USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
243     'C', 0x00,                  /* wcChar0 */
244     'h', 0x00,                  /* wcChar1 */
245     'e', 0x00,                  /* wcChar2 */
246     'r', 0x00,                  /* wcChar3 */
247     'r', 0x00,                  /* wcChar4 */
248     'y', 0x00,                  /* wcChar5 */
249     'U', 0x00,                  /* wcChar6 */
250     'S', 0x00,                  /* wcChar7 */
251     'B', 0x00,                  /* wcChar8 */
252     ///////////////////////////////////////
253     /// string2 descriptor
254     ///////////////////////////////////////
255     0x26,                       /* bLength */
256     USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
257     'C', 0x00,                  /* wcChar0 */
258     'h', 0x00,                  /* wcChar1 */
259     'e', 0x00,                  /* wcChar2 */
260     'r', 0x00,                  /* wcChar3 */
261     'r', 0x00,                  /* wcChar4 */
262     'y', 0x00,                  /* wcChar5 */
263     'U', 0x00,                  /* wcChar6 */
264     'S', 0x00,                  /* wcChar7 */
265     'B', 0x00,                  /* wcChar8 */
266     ' ', 0x00,                  /* wcChar9 */
267     'U', 0x00,                  /* wcChar10 */
268     'A', 0x00,                  /* wcChar11 */
269     'C', 0x00,                  /* wcChar12 */
270     ' ', 0x00,                  /* wcChar13 */
271     'D', 0x00,                  /* wcChar14 */
272     'E', 0x00,                  /* wcChar15 */
273     'M', 0x00,                  /* wcChar16 */
274     'O', 0x00,                  /* wcChar17 */
275     ///////////////////////////////////////
276     /// string3 descriptor
277     ///////////////////////////////////////
278     0x16,                       /* bLength */
279     USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
280     '2', 0x00,                  /* wcChar0 */
281     '0', 0x00,                  /* wcChar1 */
282     '2', 0x00,                  /* wcChar2 */
283     '1', 0x00,                  /* wcChar3 */
284     '0', 0x00,                  /* wcChar4 */
285     '3', 0x00,                  /* wcChar5 */
286     '1', 0x00,                  /* wcChar6 */
287     '0', 0x00,                  /* wcChar7 */
288     '0', 0x00,                  /* wcChar8 */
289 #if USING_FEEDBACK == 0
290     '3', 0x00,                  /* wcChar9 */
291 #else
292     '4', 0x00, /* wcChar9 */
293 #endif
294 #ifdef CONFIG_USB_HS
295     ///////////////////////////////////////
296     /// device qualifier descriptor
297     ///////////////////////////////////////
298     0x0a,
299     USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
300     0x00,
301     0x02,
302     0x00,
303     0x00,
304     0x00,
305     0x40,
306     0x00,
307     0x00,
308 #endif
309     0x00
310 };
311 #endif
312 
313 static const uint8_t speaker_default_sampling_freq_table[] = {
314     AUDIO_SAMPLE_FREQ_NUM(5),
315     AUDIO_SAMPLE_FREQ_4B(8000),
316     AUDIO_SAMPLE_FREQ_4B(8000),
317     AUDIO_SAMPLE_FREQ_4B(0x00),
318     AUDIO_SAMPLE_FREQ_4B(16000),
319     AUDIO_SAMPLE_FREQ_4B(16000),
320     AUDIO_SAMPLE_FREQ_4B(0x00),
321     AUDIO_SAMPLE_FREQ_4B(32000),
322     AUDIO_SAMPLE_FREQ_4B(32000),
323     AUDIO_SAMPLE_FREQ_4B(0x00),
324     AUDIO_SAMPLE_FREQ_4B(48000),
325     AUDIO_SAMPLE_FREQ_4B(48000),
326     AUDIO_SAMPLE_FREQ_4B(0x00),
327     AUDIO_SAMPLE_FREQ_4B(96000),
328     AUDIO_SAMPLE_FREQ_4B(96000),
329     AUDIO_SAMPLE_FREQ_4B(0x00)
330 };
331 
332 static const uint8_t mic_default_sampling_freq_table[] = {
333     AUDIO_SAMPLE_FREQ_NUM(1),
334     AUDIO_SAMPLE_FREQ_4B(16000),
335     AUDIO_SAMPLE_FREQ_4B(16000),
336     AUDIO_SAMPLE_FREQ_4B(0x00)
337 };
338 
339 USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t read_buffer[AUDIO_OUT_PACKET];
340 USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t write_buffer[AUDIO_IN_PACKET];
341 
342 volatile bool tx_flag = 0;
343 volatile bool rx_flag = 0;
344 volatile bool ep_tx_busy_flag = false;
345 volatile uint32_t s_mic_sample_rate;
346 volatile uint32_t s_speaker_sample_rate;
347 
usbd_event_handler(uint8_t busid,uint8_t event)348 static void usbd_event_handler(uint8_t busid, uint8_t event)
349 {
350     switch (event) {
351         case USBD_EVENT_RESET:
352             break;
353         case USBD_EVENT_CONNECTED:
354             break;
355         case USBD_EVENT_DISCONNECTED:
356             break;
357         case USBD_EVENT_RESUME:
358             break;
359         case USBD_EVENT_SUSPEND:
360             break;
361         case USBD_EVENT_CONFIGURED:
362             break;
363         case USBD_EVENT_SET_REMOTE_WAKEUP:
364             break;
365         case USBD_EVENT_CLR_REMOTE_WAKEUP:
366             break;
367 
368         default:
369             break;
370     }
371 }
372 
usbd_audio_open(uint8_t busid,uint8_t intf)373 void usbd_audio_open(uint8_t busid, uint8_t intf)
374 {
375     if (intf == 1) {
376         rx_flag = 1;
377         /* setup first out ep read transfer */
378         usbd_ep_start_read(busid, AUDIO_OUT_EP, read_buffer, AUDIO_OUT_PACKET);
379 #if USING_FEEDBACK == 1
380 #ifdef CONFIG_USB_HS
381         uint32_t feedback_value = AUDIO_FREQ_TO_FEEDBACK_HS(AUDIO_FREQ);
382         AUDIO_FEEDBACK_TO_BUF_HS(s_speaker_feedback_buffer, feedback_value);
383 #else
384         uint32_t feedback_value = AUDIO_FREQ_TO_FEEDBACK_FS(AUDIO_FREQ);
385         AUDIO_FEEDBACK_TO_BUF_FS(s_speaker_feedback_buffer, feedback_value);
386 #endif
387         usbd_ep_start_write(busid, AUDIO_OUT_FEEDBACK_EP, s_speaker_feedback_buffer, FEEDBACK_ENDP_PACKET_SIZE);
388 #endif
389         USB_LOG_RAW("OPEN1\r\n");
390     } else {
391         tx_flag = 1;
392         USB_LOG_RAW("OPEN2\r\n");
393     }
394 }
395 
usbd_audio_close(uint8_t busid,uint8_t intf)396 void usbd_audio_close(uint8_t busid, uint8_t intf)
397 {
398     if (intf == 1) {
399         rx_flag = 0;
400         USB_LOG_RAW("CLOSE1\r\n");
401     } else {
402         tx_flag = 0;
403         USB_LOG_RAW("CLOSE2\r\n");
404     }
405 }
406 
usbd_audio_set_sampling_freq(uint8_t busid,uint8_t ep,uint32_t sampling_freq)407 void usbd_audio_set_sampling_freq(uint8_t busid, uint8_t ep, uint32_t sampling_freq)
408 {
409     if (ep == AUDIO_OUT_EP) {
410         s_speaker_sample_rate = sampling_freq;
411     } else if (ep == AUDIO_IN_EP) {
412         s_mic_sample_rate = sampling_freq;
413     }
414 }
415 
usbd_audio_get_sampling_freq(uint8_t busid,uint8_t ep)416 uint32_t usbd_audio_get_sampling_freq(uint8_t busid, uint8_t ep)
417 {
418     (void)busid;
419 
420     uint32_t freq = 0;
421 
422     if (ep == AUDIO_OUT_EP) {
423         freq = s_speaker_sample_rate;
424     } else if (ep == AUDIO_IN_EP) {
425         freq = s_mic_sample_rate;
426     }
427 
428     return freq;
429 }
430 
usbd_audio_get_sampling_freq_table(uint8_t busid,uint8_t ep,uint8_t ** sampling_freq_table)431 void usbd_audio_get_sampling_freq_table(uint8_t busid, uint8_t ep, uint8_t **sampling_freq_table)
432 {
433     if (ep == AUDIO_OUT_EP) {
434         *sampling_freq_table = (uint8_t *)speaker_default_sampling_freq_table;
435     } else if (ep == AUDIO_IN_EP) {
436         *sampling_freq_table = (uint8_t *)mic_default_sampling_freq_table;
437     } else {
438     }
439 }
440 
usbd_audio_iso_out_callback(uint8_t busid,uint8_t ep,uint32_t nbytes)441 void usbd_audio_iso_out_callback(uint8_t busid, uint8_t ep, uint32_t nbytes)
442 {
443     USB_LOG_RAW("actual out len:%d\r\n", (unsigned int)nbytes);
444     usbd_ep_start_read(busid, AUDIO_OUT_EP, read_buffer, AUDIO_OUT_PACKET);
445 }
446 
usbd_audio_iso_in_callback(uint8_t busid,uint8_t ep,uint32_t nbytes)447 void usbd_audio_iso_in_callback(uint8_t busid, uint8_t ep, uint32_t nbytes)
448 {
449     USB_LOG_RAW("actual in len:%d\r\n", (unsigned int)nbytes);
450     ep_tx_busy_flag = false;
451 }
452 
453 #if USING_FEEDBACK == 1
usbd_audio_iso_out_feedback_callback(uint8_t busid,uint8_t ep,uint32_t nbytes)454 void usbd_audio_iso_out_feedback_callback(uint8_t busid, uint8_t ep, uint32_t nbytes)
455 {
456     USB_LOG_RAW("actual feedback len:%d\r\n", nbytes);
457 #ifdef CONFIG_USB_HS
458     uint32_t feedback_value = AUDIO_FREQ_TO_FEEDBACK_HS(s_speaker_sample_rate);
459     AUDIO_FEEDBACK_TO_BUF_HS(s_speaker_feedback_buffer, feedback_value);
460 #else
461     uint32_t feedback_value = AUDIO_FREQ_TO_FEEDBACK_FS(s_speaker_sample_rate);
462     AUDIO_FEEDBACK_TO_BUF_FS(s_speaker_feedback_buffer, feedback_value);
463 #endif
464     usbd_ep_start_write(busid, AUDIO_OUT_FEEDBACK_EP, s_speaker_feedback_buffer, FEEDBACK_ENDP_PACKET_SIZE);
465 }
466 #endif
467 
468 static struct usbd_endpoint audio_out_ep = {
469     .ep_cb = usbd_audio_iso_out_callback,
470     .ep_addr = AUDIO_OUT_EP
471 };
472 
473 static struct usbd_endpoint audio_in_ep = {
474     .ep_cb = usbd_audio_iso_in_callback,
475     .ep_addr = AUDIO_IN_EP
476 };
477 
478 #if USING_FEEDBACK == 1
479 static struct usbd_endpoint audio_out_feedback_ep = {
480     .ep_cb = usbd_audio_iso_out_feedback_callback,
481     .ep_addr = AUDIO_OUT_FEEDBACK_EP
482 };
483 #endif
484 
485 struct usbd_interface intf0;
486 struct usbd_interface intf1;
487 struct usbd_interface intf2;
488 
489 struct audio_entity_info audio_entity_table[] = {
490     { .bEntityId = AUDIO_OUT_CLOCK_ID,
491       .bDescriptorSubtype = AUDIO_CONTROL_CLOCK_SOURCE,
492       .ep = AUDIO_OUT_EP },
493     { .bEntityId = AUDIO_OUT_FU_ID,
494       .bDescriptorSubtype = AUDIO_CONTROL_FEATURE_UNIT,
495       .ep = AUDIO_OUT_EP },
496     { .bEntityId = AUDIO_IN_CLOCK_ID,
497       .bDescriptorSubtype = AUDIO_CONTROL_CLOCK_SOURCE,
498       .ep = AUDIO_IN_EP },
499     { .bEntityId = AUDIO_IN_FU_ID,
500       .bDescriptorSubtype = AUDIO_CONTROL_FEATURE_UNIT,
501       .ep = AUDIO_IN_EP },
502 };
503 
audio_v2_init(uint8_t busid,uintptr_t reg_base)504 void audio_v2_init(uint8_t busid, uintptr_t reg_base)
505 {
506 #ifdef CONFIG_USBDEV_ADVANCE_DESC
507     usbd_desc_register(busid, &audio_v2_descriptor);
508 #else
509     usbd_desc_register(busid, audio_v2_descriptor);
510 #endif
511     usbd_add_interface(busid, usbd_audio_init_intf(busid, &intf0, 0x0200, audio_entity_table, 4));
512     usbd_add_interface(busid, usbd_audio_init_intf(busid, &intf1, 0x0200, audio_entity_table, 4));
513     usbd_add_interface(busid, usbd_audio_init_intf(busid, &intf2, 0x0200, audio_entity_table, 4));
514     usbd_add_endpoint(busid, &audio_in_ep);
515     usbd_add_endpoint(busid, &audio_out_ep);
516 #if USING_FEEDBACK == 1
517     usbd_add_endpoint(busid, &audio_out_feedback_ep);
518 #endif
519 
520     usbd_initialize(busid, reg_base, usbd_event_handler);
521 }
522 
audio_v2_test(uint8_t busid)523 void audio_v2_test(uint8_t busid)
524 {
525     if (tx_flag) {
526         memset(write_buffer, 'a', AUDIO_IN_PACKET);
527         ep_tx_busy_flag = true;
528         usbd_ep_start_write(busid, AUDIO_IN_EP, write_buffer, AUDIO_IN_PACKET);
529         while (ep_tx_busy_flag) {
530             if (tx_flag == false) {
531                 break;
532             }
533         }
534     }
535     if (rx_flag) {
536     }
537 }
538