UAC音频控制接口头描述符bInCollection及baInterfaceNr字段分析
2023-01-13
2999
0
UAC1.0规范音频控制接口头描述符的定义如下:
typedef struct _USB_AC_HEADER
{
UINT8 bLength;
UINT8 bDescriptorType;
UINT8 bDescriptorSubType;
UINT16 bcdADC;
UINT16 wTotalLength;
UINT8 bInCollection;
UINT8 baInterfaceNr[bInCollection];
} USB_AC_HEADER;
其各字段的解释可详见:https://www.usbzh.com/article/detail-222.html
从这个结构来看,这是一个可变长的结构体,其变体主要是baInterfaceNr,是一个不定长的数组,其数组的大小由bInCollection。
这里我们先列出2个不同bInCollection的两种示例:
bInCollection为1时的示例:
------ Audio Control Interface Header Descriptor ------
bLength : 0x09 (9 bytes)
bDescriptorType : 0x24 (Audio Interface Descriptor)
bDescriptorSubtype : 0x01 (Header)
bcdADC : 0x0100
wTotalLength : 0x0028 (40 bytes)
bInCollection : 0x01
baInterfaceNr[1] : 0x01
Data (HexDump) : 09 24 01 00 01 28 00 01 01 .$...(...
baInterfaceNr为2时的示例:
------ Audio Control Interface Header Descriptor ------
bLength : 0x0A (10 bytes)
bDescriptorType : 0x24 (Audio Interface Descriptor)
bDescriptorSubtype : 0x01 (Header)
bcdADC : 0x0100
wTotalLength : 0x0041 (65 bytes)
bInCollection : 0x02
baInterfaceNr[1] : 0x01
baInterfaceNr[2] : 0x02
Data (HexDump) : 0A 24 01 00 01 41 00 02 01 02 .$...A....
bInCollection从规范上来讲,代表数据流的个数。
当为1时,代表只有1个数据流,只为2时代表有2个数据流。
所以我们上面为1时,是一个USB小音响的内容,由于其只有一个输出音频流,故为1。
当为2时,是我们的华为耳机的内容,由于我们既是一个麦克风同时也有一个耳机,故数据流为2。
baInterfaceNr数组中的内容代表的是音频流接口的索引。如为2时我们的华为耳机全部的配置描述符可参考:https://www.usbzh.com/article/detail-717.html
通过分析,其接口ID=1是的内容如下:
-------- Audio Streaming Interface Descriptor ---------
bLength : 0x07 (7 bytes)
bDescriptorType : 0x24 (Audio Interface Descriptor)
bDescriptorSubtype : 0x01 (AS_GENERAL)
bTerminalLink : 0x05 (Terminal ID 5)
bDelay : 0x00 (0 frames)
wFormatTag : 0x0001 (PCM)
Data (HexDump) : 07 24 01 05 00 01 00 .$.....
------- Audio Streaming Format Type Descriptor --------
bLength : 0x0B (11 bytes)
bDescriptorType : 0x24 (Audio Interface Descriptor)
bDescriptorSubtype : 0x02 (Format Type)
bFormatType : 0x01 (FORMAT_TYPE_I)
bNrChannels : 0x02 (2 channels)
bSubframeSize : 0x02 (2 bytes per subframe)
bBitResolution : 0x10 (16 bits per sample)
bSamFreqType : 0x01 (supports 1 sample frequence)
tSamFreq[1] : 0x0BB80 (48000 Hz)
Data (HexDump) : 0B 24 02 01 02 02 10 01 80 BB 00 .$.........
----------------- Endpoint Descriptor -----------------
bLength : 0x09 (9 bytes)
bDescriptorType : 0x05 (Endpoint Descriptor)
bEndpointAddress : 0x83 (Direction=IN EndpointID=3)
bmAttributes : 0x0D (TransferType=Isochronous SyncType=Synchronous EndpointType=Data)
wMaxPacketSize : 0x00C0 (192 bytes)
bInterval : 0x01 (1 ms)
bRefresh : 0x00
bSynchAddress : 0x00
Data (HexDump) : 09 05 83 0D C0 00 01 00 00 .........
----------- Audio Data Endpoint Descriptor ------------
bLength : 0x07 (7 bytes)
bDescriptorType : 0x25 (Audio Endpoint Descriptor)
bDescriptorSubtype : 0x01 (General)
bmAttributes : 0x01
D0 : Sampling Freq : 0x01 (supported)
D1 : Pitch : 0x00 (not supported)
D6..2: Reserved : 0x00
D7 : MaxPacketsOnly : 0x00 (no)
bLockDelayUnits : 0x00 (Undefined)
wLockDelay : 0x0000
Data (HexDump) : 07 25 01 01 00 00 00 .%.....
这是一个输入设备即麦克风音频流接描述符。
其接口为2时的:
---------------- Interface Descriptor -----------------
bLength : 0x09 (9 bytes)
bDescriptorType : 0x04 (Interface Descriptor)
bInterfaceNumber : 0x02 (Interface 2)
bAlternateSetting : 0x00
bNumEndpoints : 0x00 (Default Control Pipe only)
bInterfaceClass : 0x01 (Audio)
bInterfaceSubClass : 0x02 (Audio Streaming)
bInterfaceProtocol : 0x00
iInterface : 0x00 (No String Descriptor)
Data (HexDump) : 09 04 02 00 00 01 02 00 00 .........
---------------- Interface Descriptor -----------------
bLength : 0x09 (9 bytes)
bDescriptorType : 0x04 (Interface Descriptor)
bInterfaceNumber : 0x02 (Interface 2)
bAlternateSetting : 0x01
bNumEndpoints : 0x01 (1 Endpoint)
bInterfaceClass : 0x01 (Audio)
bInterfaceSubClass : 0x02 (Audio Streaming)
bInterfaceProtocol : 0x00
iInterface : 0x00 (No String Descriptor)
Data (HexDump) : 09 04 02 01 01 01 02 00 00 .........
-------- Audio Streaming Interface Descriptor ---------
bLength : 0x07 (7 bytes)
bDescriptorType : 0x24 (Audio Interface Descriptor)
bDescriptorSubtype : 0x01 (AS_GENERAL)
bTerminalLink : 0x01 (Terminal ID 1)
bDelay : 0x00 (0 frames)
wFormatTag : 0x0001 (PCM)
Data (HexDump) : 07 24 01 01 00 01 00 .$.....
------- Audio Streaming Format Type Descriptor --------
bLength : 0x11 (17 bytes)
bDescriptorType : 0x24 (Audio Interface Descriptor)
bDescriptorSubtype : 0x02 (Format Type)
bFormatType : 0x01 (FORMAT_TYPE_I)
bNrChannels : 0x02 (2 channels)
bSubframeSize : 0x02 (2 bytes per subframe)
bBitResolution : 0x10 (16 bits per sample)
bSamFreqType : 0x03 (supports 3 sample frequencies)
tSamFreq[1] : 0x0AC44 (44100 Hz)
tSamFreq[2] : 0x0BB80 (48000 Hz)
tSamFreq[3] : 0x17700 (96000 Hz)
Data (HexDump) : 11 24 02 01 02 02 10 03 44 AC 00 80 BB 00 00 77 .$......D......w
01 .
----------------- Endpoint Descriptor -----------------
bLength : 0x09 (9 bytes)
bDescriptorType : 0x05 (Endpoint Descriptor)
bEndpointAddress : 0x03 (Direction=OUT EndpointID=3)
bmAttributes : 0x0D (TransferType=Isochronous SyncType=Synchronous EndpointType=Data)
wMaxPacketSize : 0x0180 (384 bytes)
bInterval : 0x01 (1 ms)
bRefresh : 0x00
bSynchAddress : 0x00
Data (HexDump) : 09 05 03 0D 80 01 01 00 00 .........
----------- Audio Data Endpoint Descriptor ------------
bLength : 0x07 (7 bytes)
bDescriptorType : 0x25 (Audio Endpoint Descriptor)
bDescriptorSubtype : 0x01 (General)
bmAttributes : 0x01
D0 : Sampling Freq : 0x01 (supported)
D1 : Pitch : 0x00 (not supported)
D6..2: Reserved : 0x00
D7 : MaxPacketsOnly : 0x00 (no)
bLockDelayUnits : 0x00 (Undefined)
wLockDelay : 0x0000
Data (HexDump) : 07 25 01 01 00 00 00 .%.....
这是一个输出设备的,即USB耳机音频流接描述符。
我们再通过代码来更深层的理解一下音频流。
我们知道USB需要选择配置,选择配置之前需要解析各个USB接口述符的位置,所以对于UAC设备,可以采样如下的方式来解析音频流接口。即先获取到AC音频控制接口头描述符bInCollection,然后再循环解析配置描述符中各个音频流接口。
//首先获取UAC音频控制接口头描述符接针
pHeader = (PAUDIO_HEADER_UNIT)GetAudioSpecificInterface(pConfigurationDescriptor, pAudioInterface, HEADER_UNIT);
if (!pHeader)
{
FreeMem(pHwDevExt->pInterfaceList);
return STATUS_INVALID_PARAMETER;
}
//根据其接口描述符ID从配置描述符中获取对应的接口描述符指针
for (i = 0; i < pHeader->bInCollection; i++)
{
pAudioStreamingInterface = USBD_ParseConfigurationDescriptorEx(
pConfigurationDescriptor,
(PVOID)pConfigurationDescriptor,
(LONG)pHeader->baInterfaceNr[i], // Interface number
-1, // Alternate Setting
USB_DEVICE_CLASS_AUDIO, // Audio Class (Interface Class)
AUDIO_SUBCLASS_STREAMING, // Audio Streaming (Interface Sub-Class)
-1); // protocol don't care (InterfaceProtocol)
if (pAudioStreamingInterface)
{
pHwDevExt->pInterfaceList[j++].InterfaceDescriptor = pAudioStreamingInterface;
}
}
HID人机交互QQ群:564808376
UAC音频QQ群:218581009
UVC相机QQ群:331552032
BOT&UASP大容量存储QQ群:258159197
STC-USB单片机QQ群:315457461
USB技术交流QQ群2:580684376
USB技术交流QQ群:952873936