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