M480 BSP V3.05.005
The Board Support Package for M480 Series
uac_parser.c
Go to the documentation of this file.
1/**************************************************************************/
10#include <stdio.h>
11#include <string.h>
12
13#include "NuMicro.h"
14
15#include "usb.h"
16#include "usbh_lib.h"
17#include "usbh_uac.h"
18#include "uac.h"
19
21
22static int uac_parse_ac_interface(UAC_DEV_T *uac, uint8_t *bptr)
23{
24 AC_IT_T *ac_itd;
25 AC_OT_T *ac_otd;
26
27 UAC_DBGMSG("Parse AC - [%d] [0x%x] [0x%x]\n", ((CS_HDR_T *)bptr)->bLength, ((CS_HDR_T *)bptr)->bDescriptorType, ((CS_HDR_T *)bptr)->bDescriptorSubtype);
28
29 switch (((CS_HDR_T *)bptr)->bDescriptorSubtype)
30 {
31 case AC_DESCRIPTOR_UNDEFINED: /* Not interested, discard it... */
32 UAC_DBGMSG("AC: AC_DESCRIPTOR_UNDEFINED\n");
33 break;
34
35 case HEADER:
36 /* Not interested, discard it... */
37 UAC_DBGMSG("AC: HEADER\n");
38 break;
39
40 case INPUT_TERMINAL:
41 ac_itd = (AC_IT_T *)bptr;
42 UAC_DBGMSG("AC: INPUT_TERMINAL\n");
43 if (ac_itd->wTerminalType == UAC_TT_USB_STREAMING)
44 {
45 UAC_DBGMSG("USB streaming terminal found, ID=0x%x\n", ac_itd->bTerminalID);
46 }
47 else if ((ac_itd->wTerminalType & 0x200) == 0x200)
48 {
49 UAC_DBGMSG("MICROPHONE input terminal found, ID=0x%x\n", ac_itd->bTerminalID);
50 uac->acif.mic_id = ac_itd->bTerminalID;
51 }
52 else
53 {
54 UAC_DBGMSG("Unsupported INPUT TERMINAL, ignore it!\n");
55 }
56 UAC_DBGMSG(" bTerminalID: 0%x\n", ac_itd->bTerminalID);
57 UAC_DBGMSG(" wTerminalType: 0%x\n", ac_itd->wTerminalType);
58 UAC_DBGMSG(" bAssocTerminal: 0%x\n", ac_itd->bAssocTerminal);
59 UAC_DBGMSG(" bNrChannels: 0%x\n", ac_itd->bNrChannels);
60 UAC_DBGMSG(" wChannelConfig: 0%x\n", ac_itd->wChannelConfig);
61 break;
62
63 case OUTPUT_TERMINAL:
64 ac_otd = (AC_OT_T *)bptr;
65 UAC_DBGMSG("AC: OUTPUT_TERMINAL\n");
66 if (ac_otd->wTerminalType == UAC_TT_USB_STREAMING)
67 {
68 UAC_DBGMSG("USB streaming terminal found, ID=0x%x\n", ac_otd->bTerminalID);
69 }
70 else if ((ac_otd->wTerminalType & 0x300) == 0x300)
71 {
72 UAC_DBGMSG("SPEAKER output terminal found, ID=0x%x\n", ac_otd->bTerminalID);
73 uac->acif.speaker_id = ac_otd->bTerminalID;
74 uac->acif.speaker_fuid = ac_otd->bSourceID;
75 }
76 else
77 {
78 UAC_DBGMSG("Unsupported OUTPUT TERMINAL, ignore it!\n");
79 }
80 UAC_DBGMSG(" bTerminalID: 0%x\n", ac_otd->bTerminalID);
81 UAC_DBGMSG(" wTerminalType: 0%x\n", ac_otd->wTerminalType);
82 UAC_DBGMSG(" bAssocTerminal: 0%x\n", ac_otd->bAssocTerminal);
83 UAC_DBGMSG(" bSourceID: 0%x\n", ac_otd->bSourceID);
84 break;
85
86 case MIXER_UNIT:
87#ifdef UAC_DEBUG
88 UAC_DBGMSG("AC: MIXER_UNIT\n");
89 UAC_DBGMSG(" bUnitID: 0%x\n", ((AC_MXR_T *)bptr)->bUnitID);
90 UAC_DBGMSG(" bNrInPins: 0%x\n", ((AC_MXR_T *)bptr)->bNrInPins);
91#endif
92 break;
93
94 case SELECTOR_UNIT:
95#ifdef UAC_DEBUG
96 UAC_DBGMSG("AC: SELECTOR_UNIT\n");
97 UAC_DBGMSG(" bUnitID: 0%x\n", ((AC_SU_T *)bptr)->bUnitID);
98 UAC_DBGMSG(" bNrInPins: 0%x\n", ((AC_SU_T *)bptr)->bNrInPins);
99#endif
100 break;
101
102 case FEATURE_UNIT:
103
104#ifdef UAC_DEBUG
105 UAC_DBGMSG("AC: FEATURE_UNIT\n");
106 UAC_DBGMSG(" bUnitID: 0%x\n", ((AC_FU_T *)bptr)->bUnitID);
107 UAC_DBGMSG(" bSourceID: 0%x\n", ((AC_FU_T *)bptr)->bSourceID);
108 UAC_DBGMSG(" bControlSize: 0%x\n", ((AC_FU_T *)bptr)->bControlSize);
109#endif
110 break;
111
112 case PROCESSING_UNIT:
113#ifdef UAC_DEBUG
114 UAC_DBGMSG("AC: PROCESSING_UNIT\n");
115 UAC_DBGMSG(" bUnitID: 0%x\n", ((AC_PU_T *)bptr)->bUnitID);
116 UAC_DBGMSG(" wProcessType: 0%x\n", ((AC_PU_T *)bptr)->wProcessType);
117 UAC_DBGMSG(" bNrInPins: 0%x\n", ((AC_PU_T *)bptr)->bNrInPins);
118#endif
119 break;
120
121 case EXTENSION_UNIT:
122 UAC_DBGMSG("AC: EXTENSION_UNIT\n");
123 break;
124
125 default:
126 UAC_ERRMSG("uac_parse_ac_interface - unrecognized bDescriptorSubtype 0x%x!\n", ((CS_HDR_T *)bptr)->bDescriptorSubtype);
127 return UAC_RET_PARSER;
128 }
129 return 0;
130}
131
132static int uac_set_microphone_feature_unit(UAC_DEV_T *uac)
133{
134 DESC_CONF_T *config;
135 AC_FU_T *hdr;
136 uint8_t *bptr;
137 uint8_t bTerminalID = uac->acif.mic_id;
138 int size;
139
140 bptr = uac->udev->cfd_buff;
141 config = (DESC_CONF_T *)bptr;
142
143 /* step over configuration descriptor */
144 bptr += config->bLength;
145 size = config->wTotalLength - config->bLength;
146
147 /*------------------------------------------------------------------------------------*/
148 /* Find the Terminal Descriptor */
149 /*------------------------------------------------------------------------------------*/
150 while (size >= sizeof(DESC_IF_T))
151 {
152 hdr = (AC_FU_T *)bptr;
153
154 if ((hdr->bDescriptorType == CS_INTERFACE) && (hdr->bDescriptorSubtype == FEATURE_UNIT) &&
155 (hdr->bSourceID == bTerminalID))
156 {
157 uac->acif.mic_fuid = hdr->bUnitID;
158 return 0;
159 }
160
161 if (hdr->bLength == 0)
162 return UAC_RET_PARSER; /* prevent infinite loop */
163
164 bptr += hdr->bLength;
165 size -= hdr->bLength;
166 }
167 return UAC_RET_PARSER; /* not found */
168}
169
178int uac_parse_control_interface(UAC_DEV_T *uac, IFACE_T *iface)
179{
180 DESC_CONF_T *config;
181 DESC_IF_T *ifd;
182 int if_num;
183 uint8_t *bptr;
184 int size, ret;
185
186 if_num = iface->if_num; /* interface number of AC interface */
187
188 UAC_DBGMSG("UAC parsing audio control (AC) interface %d...\n", if_num);
189
190 memset(&uac->acif, 0, sizeof(uac->acif)); /* clear AC information */
191 uac->acif.iface = iface;
192
193 bptr = uac->udev->cfd_buff;
194 config = (DESC_CONF_T *)bptr;
195
196 /* step over configuration descriptor */
197 bptr += config->bLength;
198 size = config->wTotalLength - config->bLength;
199
200 /*------------------------------------------------------------------------------------*/
201 /* Find the Standard AC Interface Descriptor */
202 /*------------------------------------------------------------------------------------*/
203 while (size >= sizeof(DESC_IF_T))
204 {
205 ifd = (DESC_IF_T *)bptr;
206
207 if ((ifd->bDescriptorType == USB_DT_INTERFACE) && (ifd->bInterfaceNumber == if_num) &&
208 (ifd->bInterfaceClass == USB_CLASS_AUDIO) && (ifd->bInterfaceSubClass == SUBCLS_AUDIOCONTROL))
209 break;
210
211 if (ifd->bLength == 0)
212 return UAC_RET_PARSER; /* prevent infinite loop */
213
214 bptr += ifd->bLength;
215 size -= ifd->bLength;
216 }
217
218 if (size < sizeof(DESC_IF_T)) /* cannot find the Standard AC descriptor */
219 {
220 UAC_ERRMSG("UAC_RET_PARSER! - AC standard not found!\n");
221 return UAC_RET_PARSER;
222 }
223
224 bptr += ifd->bLength;
225 size -= ifd->bLength;
226
227 /*------------------------------------------------------------------------------------*/
228 /* Walk though all Class-Specific AC Interface Descriptor (4.3.2) */
229 /*------------------------------------------------------------------------------------*/
230 while (size > sizeof(DESC_HDR_T))
231 {
232 ifd = (DESC_IF_T *)bptr;
233
234 if (ifd->bDescriptorType != CS_INTERFACE)
235 break;
236
237 ret = uac_parse_ac_interface(uac, bptr);
238 if (ret < 0)
239 {
240 UAC_ERRMSG("UAC_RET_PARSER! - parsing CS\n");
241 return UAC_RET_PARSER;
242 }
243
244 if (ifd->bLength == 0)
245 return UAC_RET_PARSER; /* prevent infinite loop */
246
247 bptr += ifd->bLength;
248 size -= ifd->bLength;
249 }
250
251 uac_set_microphone_feature_unit(uac);
252
253 UAC_DBGMSG(" Microphone Input Terminal ID: 0x%x\n", uac->acif.mic_id);
254 UAC_DBGMSG(" Microphone Feature Unit ID: 0x%x\n", uac->acif.mic_fuid);
255 UAC_DBGMSG(" Speaker Output Terminal ID: 0x%x\n", uac->acif.speaker_id);
256 UAC_DBGMSG(" Speaker Feature Unit ID: 0x%x\n", uac->acif.speaker_fuid);
257
258 return 0;
259}
260
261static int uac_parse_as_interface(AS_IF_T *asif, uint8_t *bptr)
262{
263 ALT_IFACE_T *aif = asif->iface->aif;
264 int i;
265
266 if (((CS_HDR_T *)bptr)->bDescriptorType == USB_DT_ENDPOINT)
267 {
268 for (i = 0; i < aif->ifd->bNumEndpoints; i++)
269 {
270 if (aif->ep[i].bEndpointAddress == ((DESC_EP_T *)bptr)->bEndpointAddress)
271 {
272 asif->ep = &(asif->iface->aif->ep[i]);
273 break;
274 }
275 }
276 if (i >= aif->ifd->bNumEndpoints)
277 {
278 UAC_ERRMSG("Endpoint 0x%x parsing error!\n", ((DESC_EP_T *)bptr)->bEndpointAddress);
279 return UAC_RET_PARSER;
280 }
281 return 0;
282 }
283
284 if (((CS_HDR_T *)bptr)->bDescriptorType == CS_ENDPOINT)
285 {
286 asif->cs_epd = (CS_EP_T *)bptr;
287 return 0;
288 }
289
290 switch (((CS_HDR_T *)bptr)->bDescriptorSubtype)
291 {
292 case AS_DESCRIPTOR_UNDEFINED:
293 UAC_DBGMSG("AS: AS_DESCRIPTOR_UNDEFINED\n");
294 break;
295
296 case AS_GENERAL:
297 asif->as_gen = (AS_GEN_T *)bptr;
298 UAC_DBGMSG("AS: AS_GENERAL\n");
299 UAC_DBGMSG(" bTerminalLink: 0%x\n", asif->as_gen->bTerminalLink);
300 UAC_DBGMSG(" wFormatTag: 0%x\n", asif->as_gen->wFormatTag);
301 break;
302
303 case FORMAT_TYPE:
304 asif->ft = (AS_FT1_T *)bptr;
305 UAC_DBGMSG("AS: FORMAT_TYPE\n");
306 break;
307
308 case FORMAT_SPECIFIC:
309 UAC_DBGMSG("AS: FORMAT_SPECIFIC\n");
310 break;
311
312 default:
313 UAC_ERRMSG("uac_parse_as_interface - unrecognized bDescriptorSubtype 0x%x!\n", ((CS_HDR_T *)bptr)->bDescriptorSubtype);
314 return UAC_RET_PARSER;
315 }
316
317 return 0;
318}
319
320static int iface_have_iso_in_ep(IFACE_T *iface)
321{
322 int i, j;
323 EP_INFO_T *ep;
324
325 for (i = 0; i < iface->num_alt; i++)
326 {
327 for (j = 0; j < iface->alt[i].ifd->bNumEndpoints; j++)
328 {
329 ep = &(iface->alt[i].ep[j]);
330 if (ep != NULL)
331 {
332 if (((ep->bmAttributes & EP_ATTR_TT_MASK) == EP_ATTR_TT_ISO) &&
333 ((ep->bEndpointAddress & EP_ADDR_DIR_MASK) == EP_ADDR_DIR_IN))
334 return 1;
335 }
336 }
337 }
338 return 0;
339}
340
341static int iface_have_iso_out_ep(IFACE_T *iface)
342{
343 int i, j;
344 EP_INFO_T *ep;
345
346 for (i = 0; i < iface->num_alt; i++)
347 {
348 for (j = 0; j < iface->alt[i].ifd->bNumEndpoints; j++)
349 {
350 ep = &(iface->alt[i].ep[j]);
351 if (ep != NULL)
352 {
353 if (((ep->bmAttributes & EP_ATTR_TT_MASK) == EP_ATTR_TT_ISO) &&
354 ((ep->bEndpointAddress & EP_ADDR_DIR_MASK) == EP_ADDR_DIR_OUT))
355 return 1;
356 }
357 }
358 }
359 return 0;
360}
361
362static void * uac_find_terminal(UAC_DEV_T *uac, uint8_t bTerminalID)
363{
364 DESC_CONF_T *config;
365 AC_OT_T *hdr;
366 uint8_t *bptr;
367 int size;
368
369 bptr = uac->udev->cfd_buff;
370 config = (DESC_CONF_T *)bptr;
371
372 /* step over configuration descriptor */
373 bptr += config->bLength;
374 size = config->wTotalLength - config->bLength;
375
376 /*------------------------------------------------------------------------------------*/
377 /* Find the Terminal Descriptor */
378 /*------------------------------------------------------------------------------------*/
379 while (size >= sizeof(DESC_IF_T))
380 {
381 hdr = (AC_OT_T *)bptr;
382
383 if ((hdr->bDescriptorType == CS_INTERFACE) &&
384 ((hdr->bDescriptorSubtype == INPUT_TERMINAL) || (hdr->bDescriptorSubtype == OUTPUT_TERMINAL)) &&
385 (hdr->bTerminalID == bTerminalID))
386 return (void *)hdr;
387
388 if (hdr->bLength == 0)
389 return NULL; /* prevent infinite loop */
390
391 bptr += hdr->bLength;
392 size -= hdr->bLength;
393 }
394 return NULL; /* not found */
395}
396
397#if 0
398static void * uac_find_feature_unit(UAC_DEV_T *uac, uint8_t bUnitID)
399{
400 DESC_CONF_T *config;
401 AC_FU_T *hdr;
402 uint8_t *bptr;
403 int size;
404
405 bptr = uac->udev->cfd_buff;
406 config = (DESC_CONF_T *)bptr;
407
408 /* step over configuration descriptor */
409 bptr += config->bLength;
410 size = config->wTotalLength - config->bLength;
411
412 /*------------------------------------------------------------------------------------*/
413 /* Find the Terminal Descriptor */
414 /*------------------------------------------------------------------------------------*/
415 while (size >= sizeof(DESC_IF_T))
416 {
417 hdr = (AC_FU_T *)bptr;
418
419 if ((hdr->bDescriptorType == CS_INTERFACE) && (hdr->bDescriptorSubtype == FEATURE_UNIT) &&
420 (hdr->bUnitID == bUnitID))
421 return (void *)hdr;
422
423 if (hdr->bLength == 0)
424 return NULL; /* prevent infinite loop */
425
426 bptr += hdr->bLength;
427 size -= hdr->bLength;
428 }
429 return NULL; /* not found */
430}
431#endif
432
442int uac_parse_streaming_interface(UAC_DEV_T *uac, IFACE_T *iface, uint8_t bAlternateSetting)
443{
444 DESC_CONF_T *config;
445 DESC_IF_T *ifd;
446 AS_IF_T asif;
447 int if_num;
448 uint8_t *bptr;
449 int size, ret;
450
451 if_num = iface->if_num; /* interface number of AC interface */
452
453 UAC_DBGMSG("UAC parsing audio stream (AS) interface %d, alt %d...\n", if_num, bAlternateSetting);
454
455 memset(&asif, 0, sizeof(asif)); /* clear AS information */
456 asif.iface = iface;
457
458 bptr = uac->udev->cfd_buff;
459 config = (DESC_CONF_T *)bptr;
460
461 /* step over configuration descriptor */
462 bptr += config->bLength;
463 size = config->wTotalLength - config->bLength;
464
465 /*------------------------------------------------------------------------------------*/
466 /* Find the Standard AS Interface Descriptor */
467 /*------------------------------------------------------------------------------------*/
468 while (size >= sizeof(DESC_IF_T))
469 {
470 ifd = (DESC_IF_T *)bptr;
471
472 if ((ifd->bDescriptorType == USB_DT_INTERFACE) &&
473 (ifd->bInterfaceNumber == if_num) && (ifd->bAlternateSetting == bAlternateSetting) &&
474 (ifd->bInterfaceClass == USB_CLASS_AUDIO) && (ifd->bInterfaceSubClass == SUBCLS_AUDIOSTREAMING))
475 break;
476
477 if (ifd->bLength == 0)
478 return UAC_RET_PARSER; /* prevent infinite loop */
479
480 bptr += ifd->bLength;
481 size -= ifd->bLength;
482 }
483
484 if (size < sizeof(DESC_IF_T)) /* cannot find the Standard AC descriptor */
485 {
486 UAC_ERRMSG("UAC_RET_PARSER! - AC standard not found!\n");
487 return UAC_RET_PARSER;
488 }
489
490 if (ifd->bNumEndpoints == 0)
491 {
492 UAC_DBGMSG("This alternative interface is an idle interface.\n");
493 return 0;
494 }
495
496 bptr += ifd->bLength;
497 size -= ifd->bLength;
498
499 /*------------------------------------------------------------------------------------*/
500 /* Walk though all Class-Specific AS Interface Descriptor (4.5.2) */
501 /*------------------------------------------------------------------------------------*/
502 while (size > sizeof(DESC_HDR_T))
503 {
504 ifd = (DESC_IF_T *)bptr;
505
506 //UAC_DBGMSG("Parse AS - [%d] [0x%x] [0x%x]\n", ((CS_HDR_T *)bptr)->bLength, ((CS_HDR_T *)bptr)->bDescriptorType, ((CS_HDR_T *)bptr)->bDescriptorSubtype);
507
508 if ((ifd->bDescriptorType != CS_INTERFACE) &&
509 (ifd->bDescriptorType != USB_DT_ENDPOINT) &&
510 (ifd->bDescriptorType != CS_ENDPOINT))
511 break;
512
513
514 ret = uac_parse_as_interface(&asif, bptr);
515 if (ret < 0)
516 {
517 UAC_ERRMSG("UAC_RET_PARSER! - parsing CS\n");
518 return UAC_RET_PARSER;
519 }
520
521 if (ifd->bLength == 0)
522 return UAC_RET_PARSER; /* prevent infinite loop */
523
524 bptr += ifd->bLength;
525 size -= ifd->bLength;
526 }
527
528 if (asif.as_gen == NULL)
529 {
530 UAC_ERRMSG("UAC_RET_PARSER! - AS_GEN not found!\n");
531 return UAC_RET_PARSER;
532 }
533
534 if (iface_have_iso_in_ep(iface))
535 {
536 /* Find microphone's output terminal by AS_GEN's bTerminalLink */
537 asif.ot = (AC_OT_T *)uac_find_terminal(uac, asif.as_gen->bTerminalLink);
538 if (asif.ot)
539 {
540 UAC_DBGMSG("Audio in Terminal ID: 0%x\n", asif.ot->bTerminalID);
541 UAC_DBGMSG(" bDescriptorSubtype: 0%x\n", asif.ot->bDescriptorSubtype);
542 UAC_DBGMSG(" wTerminalType: 0%x\n", asif.ot->wTerminalType);
543 UAC_DBGMSG(" bAssocTerminal: 0%x\n", asif.ot->bAssocTerminal);
544 UAC_DBGMSG(" bSourceID: 0%x\n", asif.ot->bSourceID);
545 }
546 else
547 {
548 UAC_ERRMSG("Cannot find audio in Output Terminal %d!\n", asif.as_gen->bTerminalLink);
549 }
550 memcpy(&uac->asif_in, &asif, sizeof(asif));
551 }
552 else if (iface_have_iso_out_ep(iface))
553 {
554 asif.it = (AC_IT_T *)uac_find_terminal(uac, asif.as_gen->bTerminalLink);
555 if (asif.it)
556 {
557 UAC_DBGMSG("Audio out Terminal ID: 0%x\n", asif.it->bTerminalID);
558 UAC_DBGMSG(" bDescriptorSubtype: 0%x\n", asif.it->bDescriptorSubtype);
559 UAC_DBGMSG(" wTerminalType: 0%x\n", asif.it->wTerminalType);
560 UAC_DBGMSG(" bAssocTerminal: 0%x\n", asif.it->bAssocTerminal);
561 }
562 else
563 {
564 UAC_ERRMSG("Cannot find audio in Output Terminal %d!\n", asif.as_gen->bTerminalLink);
565 }
566 memcpy(&uac->asif_out, &asif, sizeof(asif));
567 }
568 else
569 {
570 UAC_ERRMSG("Interface cannot find iso endpoints!\n");
571 return UAC_RET_PARSER;
572 }
573
574 UAC_DBGMSG("\n\nAudio stream interface parsing done =>\n");
575 UAC_DBGMSG(" Interface: %d, Alt: %d (iface = 0x%x)\n", if_num, bAlternateSetting, asif.iface);
576 if (asif.ep)
577 UAC_DBGMSG(" Endpoint: 0x%x, wMaxPacketSize: %d\n", asif.ep->bEndpointAddress, asif.ep->wMaxPacketSize);
578 UAC_DBGMSG(" as_gen: %s\n", (asif.as_gen == NULL) ? "Not Found" : "OK");
579 UAC_DBGMSG(" it: %s\n", (asif.it == NULL) ? "Not Found" : "OK");
580 UAC_DBGMSG(" ot: %s\n", (asif.ot == NULL) ? "Not Found" : "OK");
581 UAC_DBGMSG(" ft: %s\n", (asif.ft == NULL) ? "Not Found" : "OK");
582 UAC_DBGMSG(" cs_epd: %s\n", (asif.cs_epd == NULL) ? "Not Found" : "OK");
583
584 return 0;
585}
586
587
589
590/*** (C) COPYRIGHT 2016 Nuvoton Technology Corp. ***/
591
NuMicro peripheral access layer header file.
#define NULL
NULL pointer.
Definition: M480.h:605
#define UAC_RET_PARSER
Definition: usbh_lib.h:105
EP_INFO_T * ep
Definition: usbh_uac.h:95
uint8_t speaker_id
Definition: usbh_uac.h:85
AC_OT_T * ot
Definition: usbh_uac.h:99
CS_EP_T * cs_epd
Definition: usbh_uac.h:101
uint8_t mic_id
Definition: usbh_uac.h:83
uint8_t mic_fuid
Definition: usbh_uac.h:84
IFACE_T * iface
Definition: usbh_uac.h:82
AC_IF_T acif
Definition: usbh_uac.h:112
IFACE_T * iface
Definition: usbh_uac.h:94
AS_IF_T asif_in
Definition: usbh_uac.h:113
uint8_t speaker_fuid
Definition: usbh_uac.h:86
AS_GEN_T * as_gen
Definition: usbh_uac.h:97
UDEV_T * udev
Definition: usbh_uac.h:111
AS_FT1_T * ft
Definition: usbh_uac.h:100
AC_IT_T * it
Definition: usbh_uac.h:98
AS_IF_T asif_out
Definition: usbh_uac.h:114
M480 MCU USB Host Audio Class header file.
USB Host library header file.
USB Host library exported header file.
USB Host UAC class driver header file.