[LIBUSBAUDIO]

- Start implementing a library which is used to parse USB configuration descriptors and construct KSFILTER_DESCRIPTOR structure, which is used with the kernel streaming driver (ks.sys) 
- The library will be used in USBAUDIO driver

svn path=/trunk/; revision=58033
This commit is contained in:
Johannes Anderwald 2012-12-28 19:38:10 +00:00
parent 426a79eba3
commit d697105863
6 changed files with 1160 additions and 0 deletions

View file

@ -0,0 +1,13 @@
add_definitions(
-DUNICODE -D_UNICODE
-DNDEBUG=1)
list(APPEND SOURCE
libusbaudio.c
parser.c
format.c)
add_library(libusbaudio ${SOURCE})
add_dependencies(libusbaudio bugcodes)

View file

@ -0,0 +1,155 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Kernel Streaming
* FILE: lib/drivers/sound/libusbaudio/format.c
* PURPOSE: USB AUDIO Parser
* PROGRAMMER: Johannes Anderwald
*/
#include "priv.h"
KSDATARANGE StandardDataRange =
{
{
sizeof(KSDATARANGE),
0,
0,
0,
{STATIC_KSDATAFORMAT_TYPE_AUDIO},
{STATIC_KSDATAFORMAT_SUBTYPE_ANALOG},
{STATIC_KSDATAFORMAT_SPECIFIER_NONE}
}
};
GUID DataFormatTypeAudio = {STATIC_KSDATAFORMAT_TYPE_AUDIO};
GUID DataFormatSubTypePCM = {STATIC_KSDATAFORMAT_SUBTYPE_PCM};
GUID DataFormatSpecifierWaveFormat = {STATIC_KSDATAFORMAT_SPECIFIER_WAVEFORMATEX};
USBAUDIO_STATUS
UsbAudio_AssignDataRanges(
IN PUSBAUDIO_CONTEXT Context,
IN PUCHAR ConfigurationDescriptor,
IN ULONG ConfigurationDescriptorSize,
IN PKSFILTER_DESCRIPTOR FilterDescriptor,
IN PUSB_COMMON_DESCRIPTOR * InterfaceDescriptors,
IN ULONG InterfaceCount,
IN ULONG InterfaceIndex,
IN PULONG TerminalIds)
{
ULONG Count, Index;
USBAUDIO_STATUS Status;
PUSB_COMMON_DESCRIPTOR * Descriptors;
PUSB_AUDIO_STREAMING_INTERFACE_DESCRIPTOR HeaderDescriptor;
PKSDATAFORMAT_WAVEFORMATEX WaveFormat;
PKSDATARANGE *DataRanges;
PKSPIN_DESCRIPTOR PinDescriptor;
PUSB_AUDIO_STREAMING_FORMAT_TYPE_1 FormatType;
/* count audio descriptors */
Status = UsbAudio_CountAudioDescriptors(ConfigurationDescriptor, ConfigurationDescriptorSize, InterfaceDescriptors, InterfaceCount, InterfaceIndex, &Count);
if (Status != UA_STATUS_SUCCESS || Count < 2)
{
/* ignore failure */
DPRINT1("[LIBUSBAUDIO] Failed to count descriptors with %x Count %lx for InterfaceIndex %lx InterfaceCount %lx\n", Status, Count, InterfaceIndex, InterfaceCount);
return UA_STATUS_SUCCESS;
}
/* create descriptor array */
Status = UsbAudio_CreateAudioDescriptorArray(Context, ConfigurationDescriptor, ConfigurationDescriptorSize, InterfaceDescriptors, InterfaceCount, InterfaceIndex, Count, &Descriptors);
if (Status != UA_STATUS_SUCCESS)
{
/* ignore failure */
DPRINT1("[LIBUSBAUDIO] Failed to create audio descriptor array Count %lx Status %x\n", Count, Status);
return UA_STATUS_SUCCESS;
}
/* get header */
HeaderDescriptor = (PUSB_AUDIO_STREAMING_INTERFACE_DESCRIPTOR)Descriptors[0];
if (!HeaderDescriptor || HeaderDescriptor->bDescriptorType != USB_AUDIO_STREAMING_INTERFACE_INTERFACE_DESCRIPTOR_TYPE ||
HeaderDescriptor->bDescriptorSubtype != 0x01)
{
/* header missing or mis-aligned */
DPRINT1("[LIBUSBAUDIO] Failed to retrieve audio header %p\n", HeaderDescriptor);
return UA_STATUS_SUCCESS;
}
/* FIXME: only PCM is supported */
if (HeaderDescriptor->wFormatTag != WAVE_FORMAT_PCM)
{
/* not supported */
DPRINT1("[LIBUSBAUDIO] Only PCM is currenly supported wFormatTag %x\n", HTONS(HeaderDescriptor->wFormatTag));
return UA_STATUS_SUCCESS;
}
/* check format descriptor */
FormatType = (PUSB_AUDIO_STREAMING_FORMAT_TYPE_1)Descriptors[1];
if (!FormatType || FormatType->bDescriptorType != USB_AUDIO_STREAMING_INTERFACE_INTERFACE_DESCRIPTOR_TYPE ||
FormatType->bDescriptorSubtype != 0x02 || FormatType->bFormatType != 0x01 || FormatType->bSamFreqType != 1)
{
/* unexpected format descriptor */
DPRINT1("[LIBUSBAUDIO] Unexpected format descriptor %p bDescriptorType %x bDescriptorSubtype %x bFormatType %x bSamFreqType %x\n", FormatType,
FormatType->bDescriptorType, FormatType->bDescriptorSubtype, FormatType->bFormatType, FormatType->bSamFreqType);
return UA_STATUS_SUCCESS;
}
/* now search pin position */
for(Index = 0; Index < FilterDescriptor->PinDescriptorsCount; Index++)
{
//DPRINT("bTerminalLink %x Ids %lx\n", HeaderDescriptor->bTerminalLink, TerminalIds[Index]);
if (HeaderDescriptor->bTerminalLink == TerminalIds[Index])
{
/* alloc wave format */
WaveFormat = (PKSDATAFORMAT_WAVEFORMATEX)Context->Alloc(sizeof(KSDATAFORMAT_WAVEFORMATEX));
if (!WaveFormat)
return UA_STATUS_NO_MEMORY;
/* init wave format */
WaveFormat->WaveFormatEx.cbSize = sizeof(WAVEFORMATEX);
WaveFormat->WaveFormatEx.wFormatTag = WAVE_FORMAT_PCM;
WaveFormat->WaveFormatEx.nChannels = FormatType->bNrChannels;
WaveFormat->WaveFormatEx.wBitsPerSample = FormatType->bBitResolution;
WaveFormat->WaveFormatEx.nSamplesPerSec = ((FormatType->tSamFreq[2] & 0xFF) << 16) | ((FormatType->tSamFreq[1] & 0xFF)<< 8) | (FormatType->tSamFreq[0] & 0xFF);
WaveFormat->WaveFormatEx.nBlockAlign = (WaveFormat->WaveFormatEx.nChannels * WaveFormat->WaveFormatEx.wBitsPerSample) / 8;
WaveFormat->WaveFormatEx.nAvgBytesPerSec = WaveFormat->WaveFormatEx.nSamplesPerSec * WaveFormat->WaveFormatEx.nBlockAlign;
/* FIXME apply padding */
WaveFormat->DataFormat.FormatSize = sizeof(KSDATAFORMAT_WAVEFORMATEX);
Context->Copy(&WaveFormat->DataFormat.MajorFormat, &DataFormatTypeAudio, sizeof(GUID));
Context->Copy(&WaveFormat->DataFormat.SubFormat, &DataFormatSubTypePCM, sizeof(GUID));
Context->Copy(&WaveFormat->DataFormat.Specifier, &DataFormatSpecifierWaveFormat, sizeof(GUID));
//C_ASSERT(sizeof(WAVEFORMATEX) + sizeof(KSDATAFORMAT) == 82);
/* get corresponding pin descriptor */
PinDescriptor = (PKSPIN_DESCRIPTOR)&FilterDescriptor->PinDescriptors[Index].PinDescriptor;
/* alloc data range */
DataRanges = (PKSDATARANGE*)Context->Alloc(sizeof(PKSDATARANGE) * (PinDescriptor->DataRangesCount+1));
if (!DataRanges)
{
Context->Free(WaveFormat);
return UA_STATUS_NO_MEMORY;
}
if (PinDescriptor->DataRangesCount)
{
/* copy old range */
Context->Copy(DataRanges, (PVOID)PinDescriptor->DataRanges, sizeof(PKSDATARANGE) * PinDescriptor->DataRangesCount);
/* free old range */
Context->Free((PVOID)PinDescriptor->DataRanges);
}
/* assign new range */
PinDescriptor->DataRanges = DataRanges;
DataRanges[PinDescriptor->DataRangesCount] = (PKSDATARANGE)WaveFormat;
PinDescriptor->DataRangesCount++;
return UA_STATUS_SUCCESS;
}
}
return UA_STATUS_SUCCESS;
}

View file

@ -0,0 +1,364 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Kernel Streaming
* FILE: lib/drivers/sound/libusbaudio/libusbaudio.c
* PURPOSE: USB AUDIO Parser
* PROGRAMMER: Johannes Anderwald
*/
#include "priv.h"
GUID NodeTypeMicrophone = {STATIC_KSNODETYPE_MICROPHONE};
GUID NodeTypeDesktopMicrophone = {STATIC_KSNODETYPE_DESKTOP_MICROPHONE};
GUID NodeTypePersonalMicrophone = {STATIC_KSNODETYPE_PERSONAL_MICROPHONE};
GUID NodeTypeOmmniMicrophone = {STATIC_KSNODETYPE_OMNI_DIRECTIONAL_MICROPHONE};
GUID NodeTypeArrayMicrophone = {STATIC_KSNODETYPE_MICROPHONE_ARRAY};
GUID NodeTypeProcessingArrayMicrophone = {STATIC_KSNODETYPE_PROCESSING_MICROPHONE_ARRAY};
GUID NodeTypeSpeaker = {STATIC_KSNODETYPE_SPEAKER};
GUID NodeTypeHeadphonesSpeaker = {STATIC_KSNODETYPE_HEADPHONES};
GUID NodeTypeHMDA = {STATIC_KSNODETYPE_HEAD_MOUNTED_DISPLAY_AUDIO};
GUID NodeTypeDesktopSpeaker = {STATIC_KSNODETYPE_DESKTOP_SPEAKER};
GUID NodeTypeRoomSpeaker = {STATIC_KSNODETYPE_ROOM_SPEAKER};
GUID NodeTypeCommunicationSpeaker = {STATIC_KSNODETYPE_COMMUNICATION_SPEAKER};
GUID NodeTypeSubwoofer = {STATIC_KSNODETYPE_LOW_FREQUENCY_EFFECTS_SPEAKER};
GUID NodeTypeCapture = {STATIC_PINNAME_CAPTURE};
GUID NodeTypePlayback = {STATIC_KSCATEGORY_AUDIO};
KSPIN_INTERFACE StandardPinInterface =
{
{STATIC_KSINTERFACESETID_Standard},
KSINTERFACE_STANDARD_STREAMING,
0
};
KSPIN_MEDIUM StandardPinMedium =
{
{STATIC_KSMEDIUMSETID_Standard},
KSMEDIUM_TYPE_ANYINSTANCE,
0
};
USBAUDIO_STATUS
UsbAudio_InitializeContext(
IN PUSBAUDIO_CONTEXT Context,
IN PUSBAUDIO_ALLOC Alloc,
IN PUSBAUDIO_FREE Free,
IN PUSBAUDIO_COPY Copy)
{
/* verify parameters */
if (!Context || !Alloc || !Free || !Copy)
{
/* invalid parameter */
return UA_STATUS_INVALID_PARAMETER;
}
/* initialize context */
Context->Size = sizeof(USBAUDIO_CONTEXT);
Context->Alloc = Alloc;
Context->Free = Free;
Context->Copy = Copy;
/* done */
return UA_STATUS_SUCCESS;
}
LPGUID
UsbAudio_GetPinCategoryFromTerminalDescriptor(
IN PUSB_AUDIO_CONTROL_INPUT_TERMINAL_DESCRIPTOR TerminalDescriptor)
{
if (TerminalDescriptor->wTerminalType == USB_AUDIO_MICROPHONE_TERMINAL_TYPE)
return &NodeTypeMicrophone;
else if (TerminalDescriptor->wTerminalType == USB_AUDIO_DESKTOP_MICROPHONE_TERMINAL_TYPE)
return &NodeTypeDesktopMicrophone;
else if (TerminalDescriptor->wTerminalType == USB_AUDIO_PERSONAL_MICROPHONE_TERMINAL_TYPE)
return &NodeTypePersonalMicrophone;
else if (TerminalDescriptor->wTerminalType == USB_AUDIO_OMMNI_MICROPHONE_TERMINAL_TYPE)
return &NodeTypeOmmniMicrophone;
else if (TerminalDescriptor->wTerminalType == USB_AUDIO_ARRAY_MICROPHONE_TERMINAL_TYPE)
return &NodeTypeArrayMicrophone;
else if (TerminalDescriptor->wTerminalType == USB_AUDIO_ARRAY_PROCESSING_MICROPHONE_TERMINAL_TYPE)
return &NodeTypeProcessingArrayMicrophone;
/* playback types */
if (TerminalDescriptor->wTerminalType == USB_AUDIO_SPEAKER_TERMINAL_TYPE)
return &NodeTypeSpeaker;
else if (TerminalDescriptor->wTerminalType == USB_HEADPHONES_SPEAKER_TERMINAL_TYPE)
return &NodeTypeHeadphonesSpeaker;
else if (TerminalDescriptor->wTerminalType == USB_AUDIO_HMDA_TERMINAL_TYPE)
return &NodeTypeHMDA;
else if (TerminalDescriptor->wTerminalType == USB_AUDIO_DESKTOP_SPEAKER_TERMINAL_TYPE)
return &NodeTypeDesktopSpeaker;
else if (TerminalDescriptor->wTerminalType == USB_AUDIO_ROOM_SPEAKER_TERMINAL_TYPE)
return &NodeTypeRoomSpeaker;
else if (TerminalDescriptor->wTerminalType == USB_AUDIO_COMMUNICATION_SPEAKER_TERMINAL_TYPE)
return &NodeTypeCommunicationSpeaker;
else if (TerminalDescriptor->wTerminalType == USB_AUDIO_SUBWOOFER_TERMINAL_TYPE)
return &NodeTypeSubwoofer;
if (TerminalDescriptor->wTerminalType == USB_AUDIO_STREAMING_TERMINAL_TYPE)
{
if (TerminalDescriptor->bDescriptorSubtype == USB_AUDIO_OUTPUT_TERMINAL)
return &NodeTypeCapture;
else if (TerminalDescriptor->bDescriptorSubtype == USB_AUDIO_INPUT_TERMINAL)
return &NodeTypePlayback;
}
return NULL;
}
USBAUDIO_STATUS
UsbAudio_InitPinDescriptor(
IN PUCHAR ConfigurationDescriptor,
IN ULONG ConfigurationDescriptorLength,
IN PKSPIN_DESCRIPTOR_EX PinDescriptor,
IN ULONG TerminalCount,
IN PUSB_COMMON_DESCRIPTOR * Descriptors,
IN ULONG TerminalId)
{
PUSB_AUDIO_CONTROL_INPUT_TERMINAL_DESCRIPTOR TerminalDescriptor;
TerminalDescriptor = UsbAudio_GetTerminalDescriptorById(Descriptors, TerminalCount, TerminalId);
if (!TerminalDescriptor)
{
/* failed to find terminal descriptor */
return UA_STATUS_UNSUCCESSFUL;
}
/* init pin descriptor */
PinDescriptor->PinDescriptor.InterfacesCount = 1;
PinDescriptor->PinDescriptor.Interfaces = &StandardPinInterface;
PinDescriptor->PinDescriptor.MediumsCount = 1;
PinDescriptor->PinDescriptor.Mediums = &StandardPinMedium;
PinDescriptor->PinDescriptor.Category = UsbAudio_GetPinCategoryFromTerminalDescriptor(TerminalDescriptor);
if (TerminalDescriptor->wTerminalType == USB_AUDIO_STREAMING_TERMINAL_TYPE)
{
if (TerminalDescriptor->bDescriptorSubtype == USB_AUDIO_OUTPUT_TERMINAL)
{
PinDescriptor->PinDescriptor.Communication = KSPIN_COMMUNICATION_SINK;
PinDescriptor->PinDescriptor.DataFlow = KSPIN_DATAFLOW_OUT;
}
else if (TerminalDescriptor->bDescriptorSubtype == USB_AUDIO_INPUT_TERMINAL)
{
PinDescriptor->PinDescriptor.Communication = KSPIN_COMMUNICATION_SINK;
PinDescriptor->PinDescriptor.DataFlow = KSPIN_DATAFLOW_IN;
}
/* irp sinks / sources can be instantiated */
PinDescriptor->InstancesPossible = 1;
}
else if (TerminalDescriptor->bDescriptorSubtype == USB_AUDIO_INPUT_TERMINAL)
{
PinDescriptor->PinDescriptor.Communication = KSPIN_COMMUNICATION_BRIDGE;
PinDescriptor->PinDescriptor.DataFlow = KSPIN_DATAFLOW_IN;
}
else if (TerminalDescriptor->bDescriptorSubtype == USB_AUDIO_OUTPUT_TERMINAL)
{
PinDescriptor->PinDescriptor.Communication = KSPIN_COMMUNICATION_BRIDGE;
PinDescriptor->PinDescriptor.DataFlow = KSPIN_DATAFLOW_OUT;
}
return UA_STATUS_SUCCESS;
}
USBAUDIO_STATUS
UsbAudio_ParseConfigurationDescriptor(
IN PUSBAUDIO_CONTEXT Context,
IN PUCHAR ConfigurationDescriptor,
IN ULONG ConfigurationDescriptorSize)
{
USBAUDIO_STATUS Status;
PKSFILTER_DESCRIPTOR FilterDescriptor;
PUSB_COMMON_DESCRIPTOR * Descriptors;
PUSB_COMMON_DESCRIPTOR * InterfaceDescriptors;
PULONG TerminalIds;
ULONG Index, AudioControlInterfaceIndex;
ULONG InterfaceCount, DescriptorCount, NewDescriptorCount;
PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor;
if (!Context || !ConfigurationDescriptor || !ConfigurationDescriptorSize)
{
/* invalid parameter */
return UA_STATUS_INVALID_PARAMETER;
}
/* count usb interface descriptors */
Status = UsbAudio_CountInterfaceDescriptors(ConfigurationDescriptor, ConfigurationDescriptorSize, &InterfaceCount);
if (Status != UA_STATUS_SUCCESS || InterfaceCount == 0)
{
/* invalid parameter */
return UA_STATUS_INVALID_PARAMETER;
}
/* construct interface array */
Status = UsbAudio_CreateInterfaceDescriptorsArray(Context, ConfigurationDescriptor, ConfigurationDescriptorSize, InterfaceCount, &InterfaceDescriptors);
if (Status != UA_STATUS_SUCCESS)
{
/* invalid parameter */
return UA_STATUS_INVALID_PARAMETER;
}
/* get audio control interface index */
AudioControlInterfaceIndex = UsbAudio_GetAudioControlInterfaceIndex(InterfaceDescriptors, InterfaceCount);
if (AudioControlInterfaceIndex == MAXULONG)
{
/* invalid configuration descriptor */
Context->Free(InterfaceDescriptors);
return UA_STATUS_INVALID_PARAMETER;
}
/* count audio terminal descriptors */
Status = UsbAudio_CountAudioDescriptors(ConfigurationDescriptor, ConfigurationDescriptorSize, InterfaceDescriptors, InterfaceCount, AudioControlInterfaceIndex, &DescriptorCount);
if (Status != UA_STATUS_SUCCESS || DescriptorCount == 0)
{
/* invalid parameter */
Context->Free(InterfaceDescriptors);
return UA_STATUS_INVALID_PARAMETER;
}
/* construct terminal descriptor array */
Status = UsbAudio_CreateAudioDescriptorArray(Context, ConfigurationDescriptor, ConfigurationDescriptorSize, InterfaceDescriptors, InterfaceCount, AudioControlInterfaceIndex, DescriptorCount, &Descriptors);
if (Status != UA_STATUS_SUCCESS)
{
/* no memory */
Context->Free(InterfaceDescriptors);
//DPRINT("[LIBUSBAUDIO] Failed to create descriptor array with %x\n", Status);
return Status;
}
/* construct filter */
FilterDescriptor = (PKSFILTER_DESCRIPTOR)Context->Alloc(sizeof(KSFILTER_DESCRIPTOR));
if (!FilterDescriptor)
{
/* no memory */
Context->Free(InterfaceDescriptors);
Context->Free(Descriptors);
return UA_STATUS_NO_MEMORY;
}
/* construct pin id array */
TerminalIds = (PULONG)Context->Alloc(sizeof(ULONG) * DescriptorCount);
if (!TerminalIds)
{
/* no memory */
Context->Free(InterfaceDescriptors);
Context->Free(FilterDescriptor);
Context->Free(Descriptors);
return UA_STATUS_NO_MEMORY;
}
/* now assign terminal ids */
Status = UsbAudio_AssignTerminalIds(Context, DescriptorCount, Descriptors, TerminalIds, &NewDescriptorCount);
if(Status != UA_STATUS_SUCCESS || NewDescriptorCount == 0)
{
/* failed to initialize */
Context->Free(InterfaceDescriptors);
Context->Free(FilterDescriptor);
Context->Free(Descriptors);
Context->Free(TerminalIds);
DPRINT1("[LIBUSBAUDIO] Failed to assign terminal ids with %x DescriptorCount %lx\n", Status, DescriptorCount);
return UA_STATUS_UNSUCCESSFUL;
}
/* init filter */
FilterDescriptor->Version = KSFILTER_DESCRIPTOR_VERSION;
FilterDescriptor->Flags = 0; /* FIXME */
FilterDescriptor->PinDescriptorsCount = NewDescriptorCount;
FilterDescriptor->PinDescriptorSize = sizeof(KSPIN_DESCRIPTOR_EX);
FilterDescriptor->PinDescriptors = Context->Alloc(sizeof(KSPIN_DESCRIPTOR_EX) * FilterDescriptor->PinDescriptorsCount);
if (!FilterDescriptor->PinDescriptors)
{
/* no memory */
Context->Free(InterfaceDescriptors);
Context->Free(FilterDescriptor);
Context->Free(Descriptors);
Context->Free(TerminalIds);
return UA_STATUS_NO_MEMORY;
}
/* now init pin properties */
for(Index = 0; Index < FilterDescriptor->PinDescriptorsCount; Index++)
{
/* now init every pin descriptor */
Status = UsbAudio_InitPinDescriptor(ConfigurationDescriptor, ConfigurationDescriptorSize, (PKSPIN_DESCRIPTOR_EX)&FilterDescriptor->PinDescriptors[Index], DescriptorCount, Descriptors, TerminalIds[Index]);
if (Status != UA_STATUS_SUCCESS)
break;
}
if (Status != UA_STATUS_SUCCESS)
{
/* failed to init pin descriptor */
Context->Free(InterfaceDescriptors);
Context->Free((PVOID)FilterDescriptor->PinDescriptors);
Context->Free(FilterDescriptor);
Context->Free(Descriptors);
Context->Free(TerminalIds);
DPRINT1("[LIBUSBAUDIO] Failed to init pin with %x\n", Status);
return Status;
}
/* now assign data ranges to the pins */
for(Index = 0; Index < InterfaceCount; Index++)
{
/* get descriptor */
InterfaceDescriptor = (PUSB_INTERFACE_DESCRIPTOR)InterfaceDescriptors[Index];
/* sanity check */
ASSERT(InterfaceDescriptor->bDescriptorType == USB_INTERFACE_DESCRIPTOR_TYPE);
DPRINT1("InterfaceNumber %d bInterfaceClass %x bInterfaceSubClass %x\n", InterfaceDescriptor->bInterfaceNumber, InterfaceDescriptor->bInterfaceClass, InterfaceDescriptor->bInterfaceSubClass);
if (InterfaceDescriptor->bInterfaceClass != 0x01 && InterfaceDescriptor->bInterfaceSubClass != 0x02)
continue;
/* assign data ranges */
Status = UsbAudio_AssignDataRanges(Context, ConfigurationDescriptor, ConfigurationDescriptorSize, FilterDescriptor, InterfaceDescriptors, InterfaceCount, Index, TerminalIds);
if (Status != UA_STATUS_SUCCESS)
break;
}
if (Status != UA_STATUS_SUCCESS)
{
/* failed to init pin descriptor */
Context->Free(InterfaceDescriptors);
Context->Free((PVOID)FilterDescriptor->PinDescriptors);
Context->Free(FilterDescriptor);
Context->Free(Descriptors);
Context->Free(TerminalIds);
return Status;
}
if (Status != UA_STATUS_SUCCESS)
{
/* failed to init pin descriptor */
Context->Free(InterfaceDescriptors);
Context->Free((PVOID)FilterDescriptor->PinDescriptors);
Context->Free(FilterDescriptor);
Context->Free(Descriptors);
Context->Free(TerminalIds);
return Status;
}
Context->Context = FilterDescriptor;
return Status;
}
USBAUDIO_STATUS
UsbAudio_GetFilter(
IN PUSBAUDIO_CONTEXT Context,
OUT PVOID * OutFilterDescriptor)
{
if (!OutFilterDescriptor)
return UA_STATUS_INVALID_PARAMETER;
*OutFilterDescriptor = Context->Context;
return UA_STATUS_SUCCESS;
}

View file

@ -0,0 +1,56 @@
#pragma once
typedef enum
{
UA_STATUS_SUCCESS = 0,
UA_STATUS_NOTINITIALIZED,
UA_STATUS_NOT_IMPLEMENTED,
UA_STATUS_NO_MORE_DEVICES,
UA_STATUS_MORE_ENTRIES,
UA_STATUS_INVALID_PARAMETER,
UA_STATUS_UNSUCCESSFUL,
UA_STATUS_NO_MEMORY
}USBAUDIO_STATUS;
typedef PVOID (*PUSBAUDIO_ALLOC)(
IN ULONG NumberOfBytes);
typedef VOID (*PUSBAUDIO_FREE)(
IN PVOID Block);
typedef VOID (*PUSBAUDIO_COPY)(
IN PVOID Dst,
IN PVOID Src,
IN ULONG Length);
typedef struct
{
ULONG Size;
PVOID Context;
PUSBAUDIO_ALLOC Alloc;
PUSBAUDIO_FREE Free;
PUSBAUDIO_COPY Copy;
}USBAUDIO_CONTEXT, *PUSBAUDIO_CONTEXT;
USBAUDIO_STATUS
UsbAudio_InitializeContext(
IN PUSBAUDIO_CONTEXT Context,
IN PUSBAUDIO_ALLOC Alloc,
IN PUSBAUDIO_FREE Free,
IN PUSBAUDIO_COPY Copy);
USBAUDIO_STATUS
UsbAudio_ParseConfigurationDescriptor(
IN PUSBAUDIO_CONTEXT Context,
IN PUCHAR ConfigurationDescriptor,
IN ULONG ConfigurationDescriptorSize);
USBAUDIO_STATUS
UsbAudio_GetFilter(
IN PUSBAUDIO_CONTEXT Context,
OUT PVOID * OutFilterDescriptor);

View file

@ -0,0 +1,390 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Kernel Streaming
* FILE: lib/drivers/sound/libusbaudio/libusbaudio.c
* PURPOSE: USB AUDIO Parser
* PROGRAMMER: Johannes Anderwald
*/
#include "priv.h"
USBAUDIO_STATUS
UsbAudio_CountDescriptors(
IN PUCHAR ConfigurationDescriptor,
IN ULONG ConfigurationDescriptorLength,
IN UCHAR DescriptorType,
IN PUSB_COMMON_DESCRIPTOR StartPosition,
IN PUSB_COMMON_DESCRIPTOR EndPosition,
OUT PULONG DescriptorCount)
{
PUSB_COMMON_DESCRIPTOR Descriptor;
ULONG Count = 0;
/* init result */
*DescriptorCount = 0;
/* enumerate descriptors */
Descriptor = StartPosition;
if (Descriptor == NULL)
Descriptor = (PUSB_COMMON_DESCRIPTOR)ConfigurationDescriptor;
if (EndPosition == NULL)
EndPosition = (PUSB_COMMON_DESCRIPTOR)((ULONG_PTR)ConfigurationDescriptor + ConfigurationDescriptorLength);
while((ULONG_PTR)Descriptor < ((ULONG_PTR)EndPosition))
{
if (!Descriptor->bLength || !Descriptor->bDescriptorType)
{
/* bogus descriptor */
return UA_STATUS_UNSUCCESSFUL;
}
if (Descriptor->bDescriptorType == DescriptorType)
{
/* found descriptor */
Count++;
}
/* move to next descriptor */
Descriptor = (PUSB_COMMON_DESCRIPTOR)((ULONG_PTR)Descriptor + Descriptor->bLength);
}
/* store result */
*DescriptorCount = Count;
return UA_STATUS_SUCCESS;
}
USBAUDIO_STATUS
UsbAudio_GetDescriptors(
IN PUCHAR ConfigurationDescriptor,
IN ULONG ConfigurationDescriptorLength,
IN UCHAR DescriptorType,
IN ULONG DescriptorCount,
IN PUSB_COMMON_DESCRIPTOR StartPosition,
IN PUSB_COMMON_DESCRIPTOR EndPosition,
OUT PUSB_COMMON_DESCRIPTOR *Descriptors)
{
PUSB_COMMON_DESCRIPTOR Descriptor;
ULONG Count = 0;
/* enumerate descriptors */
Descriptor = StartPosition;
if (Descriptor == NULL)
Descriptor = (PUSB_COMMON_DESCRIPTOR)ConfigurationDescriptor;
if (EndPosition == NULL)
EndPosition = (PUSB_COMMON_DESCRIPTOR)((ULONG_PTR)ConfigurationDescriptor + ConfigurationDescriptorLength);
while((ULONG_PTR)Descriptor < ((ULONG_PTR)EndPosition))
{
if (!Descriptor->bLength || !Descriptor->bDescriptorType)
{
/* bogus descriptor */
return UA_STATUS_UNSUCCESSFUL;
}
if (Descriptor->bDescriptorType == DescriptorType)
{
/* found descriptor */
if (Count >= DescriptorCount)
break;
/* store result */
Descriptors[Count] = Descriptor;
Count++;
}
/* move to next descriptor */
Descriptor = (PUSB_COMMON_DESCRIPTOR)((ULONG_PTR)Descriptor + Descriptor->bLength);
}
/* done */
return UA_STATUS_SUCCESS;
}
USBAUDIO_STATUS
UsbAudio_CountInterfaceDescriptors(
IN PUCHAR ConfigurationDescriptor,
IN ULONG ConfigurationDescriptorLength,
OUT PULONG DescriptorCount)
{
return UsbAudio_CountDescriptors(ConfigurationDescriptor, ConfigurationDescriptorLength, USB_INTERFACE_DESCRIPTOR_TYPE, NULL, NULL, DescriptorCount);
}
USBAUDIO_STATUS
UsbAudio_CreateDescriptorArray(
IN PUSBAUDIO_CONTEXT Context,
IN PUCHAR ConfigurationDescriptor,
IN ULONG ConfigurationDescriptorLength,
IN ULONG ArrayLength,
IN ULONG DescriptorType,
IN PUSB_COMMON_DESCRIPTOR StartPosition,
IN PUSB_COMMON_DESCRIPTOR EndPosition,
OUT PUSB_COMMON_DESCRIPTOR ** Array)
{
USBAUDIO_STATUS Status;
PUSB_COMMON_DESCRIPTOR * Descriptors;
/* zero result */
*Array = NULL;
/* first allocate descriptor array */
Descriptors = (PUSB_COMMON_DESCRIPTOR*)Context->Alloc(sizeof(PUSB_COMMON_DESCRIPTOR) * ArrayLength);
if (!Descriptors)
{
/* no memory */
return UA_STATUS_NO_MEMORY;
}
/* extract control terminal descriptors */
Status = UsbAudio_GetDescriptors(ConfigurationDescriptor, ConfigurationDescriptorLength, DescriptorType, ArrayLength, StartPosition, EndPosition, Descriptors);
if (Status != UA_STATUS_SUCCESS)
{
/* failed */
Context->Free(Descriptors);
return Status;
}
/* store result */
*Array = Descriptors;
return UA_STATUS_SUCCESS;
}
USBAUDIO_STATUS
UsbAudio_CountAudioDescriptors(
IN PUCHAR ConfigurationDescriptor,
IN ULONG ConfigurationDescriptorLength,
IN PUSB_COMMON_DESCRIPTOR * InterfaceDescriptors,
IN ULONG InterfaceDescriptorCount,
IN ULONG InterfaceDescriptorIndex,
OUT PULONG DescriptorCount)
{
if (InterfaceDescriptorIndex + 1 == InterfaceDescriptorCount)
return UsbAudio_CountDescriptors(ConfigurationDescriptor, ConfigurationDescriptorLength, USB_AUDIO_CONTROL_TERMINAL_DESCRIPTOR_TYPE, InterfaceDescriptors[InterfaceDescriptorIndex], NULL, DescriptorCount);
else
return UsbAudio_CountDescriptors(ConfigurationDescriptor, ConfigurationDescriptorLength, USB_AUDIO_CONTROL_TERMINAL_DESCRIPTOR_TYPE, InterfaceDescriptors[InterfaceDescriptorIndex], InterfaceDescriptors[InterfaceDescriptorIndex + 1], DescriptorCount);
}
USBAUDIO_STATUS
UsbAudio_CreateInterfaceDescriptorsArray(
IN PUSBAUDIO_CONTEXT Context,
IN PUCHAR ConfigurationDescriptor,
IN ULONG ConfigurationDescriptorLength,
IN ULONG ArrayLength,
OUT PUSB_COMMON_DESCRIPTOR ** Array)
{
return UsbAudio_CreateDescriptorArray(Context, ConfigurationDescriptor, ConfigurationDescriptorLength, ArrayLength, USB_INTERFACE_DESCRIPTOR_TYPE, NULL, NULL, Array);
}
USBAUDIO_STATUS
UsbAudio_CreateAudioDescriptorArray(
IN PUSBAUDIO_CONTEXT Context,
IN PUCHAR ConfigurationDescriptor,
IN ULONG ConfigurationDescriptorLength,
IN PUSB_COMMON_DESCRIPTOR * InterfaceDescriptors,
IN ULONG InterfaceDescriptorCount,
IN ULONG InterfaceDescriptorIndex,
IN ULONG ArrayLength,
OUT PUSB_COMMON_DESCRIPTOR ** Array)
{
if (InterfaceDescriptorIndex + 1 == InterfaceDescriptorCount)
return UsbAudio_CreateDescriptorArray(Context, ConfigurationDescriptor, ConfigurationDescriptorLength, ArrayLength, USB_AUDIO_CONTROL_TERMINAL_DESCRIPTOR_TYPE, InterfaceDescriptors[InterfaceDescriptorIndex], NULL, Array);
else
return UsbAudio_CreateDescriptorArray(Context, ConfigurationDescriptor, ConfigurationDescriptorLength, ArrayLength, USB_AUDIO_CONTROL_TERMINAL_DESCRIPTOR_TYPE,
InterfaceDescriptors[InterfaceDescriptorIndex], InterfaceDescriptors[InterfaceDescriptorIndex + 1], Array);
}
PUSB_AUDIO_CONTROL_INPUT_TERMINAL_DESCRIPTOR
UsbAudio_GetTerminalDescriptorById(
IN PUSB_COMMON_DESCRIPTOR *Descriptors,
IN ULONG DescriptorCount,
IN ULONG TerminalId)
{
ULONG Index;
PUSB_AUDIO_CONTROL_INPUT_TERMINAL_DESCRIPTOR Descriptor;
for(Index = 0; Index < DescriptorCount; Index++)
{
/* get descriptor */
Descriptor = (PUSB_AUDIO_CONTROL_INPUT_TERMINAL_DESCRIPTOR)Descriptors[Index];
/* is it an input / output terminal */
DPRINT("Descriptor %p Type %x SubType %x TerminalID %x\n", Descriptor, Descriptor->bDescriptorType, Descriptor->bDescriptorSubtype, Descriptor->bTerminalID);
if (Descriptor->bDescriptorSubtype != USB_AUDIO_INPUT_TERMINAL && Descriptor->bDescriptorSubtype != USB_AUDIO_OUTPUT_TERMINAL)
continue;
if (Descriptor->bTerminalID == TerminalId)
return Descriptor;
}
return NULL;
}
ULONG
UsbAudio_GetAudioControlInterfaceIndex(
IN PUSB_COMMON_DESCRIPTOR * InterfaceDescriptors,
IN ULONG DescriptorCount)
{
ULONG Index;
PUSB_INTERFACE_DESCRIPTOR Descriptor;
for(Index = 0; Index < DescriptorCount; Index++)
{
/* get descriptor */
Descriptor = (PUSB_INTERFACE_DESCRIPTOR)InterfaceDescriptors[Index];
ASSERT(Descriptor->bDescriptorType == USB_INTERFACE_DESCRIPTOR_TYPE);
ASSERT(Descriptor->bLength == sizeof(USB_INTERFACE_DESCRIPTOR));
/* compare interface class */
if (Descriptor->bInterfaceClass == 0x01 && Descriptor->bInterfaceSubClass == 0x01)
{
/* found audio control class */
return Index;
}
}
/* not found */
return MAXULONG;
}
USBAUDIO_STATUS
UsbAudio_FindTerminalDescriptorAtIndexWithSubtypeAndTerminalType(
IN ULONG DescriptorCount,
IN PUSB_COMMON_DESCRIPTOR *Descriptors,
IN ULONG DescriptorIndex,
IN UCHAR Subtype,
IN USHORT TerminalType,
OUT PUSB_AUDIO_CONTROL_INPUT_TERMINAL_DESCRIPTOR * OutDescriptor,
OUT PULONG OutDescriptorIndex)
{
ULONG Index;
ULONG Count = 0;
PUSB_AUDIO_CONTROL_INPUT_TERMINAL_DESCRIPTOR CurrentDescriptor;
for(Index = 0; Index < DescriptorCount; Index++)
{
/* get current descriptor */
CurrentDescriptor = (PUSB_AUDIO_CONTROL_INPUT_TERMINAL_DESCRIPTOR)Descriptors[Index];
ASSERT(CurrentDescriptor->bDescriptorType == USB_AUDIO_CONTROL_TERMINAL_DESCRIPTOR_TYPE);
if (CurrentDescriptor->bDescriptorSubtype == Subtype &&
(TerminalType == USB_AUDIO_UNDEFINED_TERMINAL_TYPE || CurrentDescriptor->wTerminalType == TerminalType))
{
/* found descriptor */
if (Count == DescriptorIndex)
{
/* store result */
*OutDescriptor = CurrentDescriptor;
*OutDescriptorIndex = Index;
return UA_STATUS_SUCCESS;
}
Count++;
}
}
/* not found */
return UA_STATUS_UNSUCCESSFUL;
}
USBAUDIO_STATUS
UsbAudio_AssignTerminalIds(
IN PUSBAUDIO_CONTEXT Context,
IN ULONG TerminalIdsLength,
IN PUSB_COMMON_DESCRIPTOR * TerminalIds,
OUT PULONG PinArray,
OUT PULONG PinArrayCount)
{
ULONG Consumed = 0;
ULONG PinIndex = 0;
ULONG Index, DescriptorIndex;
PUSB_AUDIO_CONTROL_INPUT_TERMINAL_DESCRIPTOR Descriptor;
USBAUDIO_STATUS Status;
/* FIXME: support more than 32 terminals */
ASSERT(TerminalIdsLength <= 32);
/* first search for an output terminal with streaming type */
Status = UsbAudio_FindTerminalDescriptorAtIndexWithSubtypeAndTerminalType(TerminalIdsLength, TerminalIds, 0, USB_AUDIO_OUTPUT_TERMINAL, USB_AUDIO_STREAMING_TERMINAL_TYPE, &Descriptor, &DescriptorIndex);
if (Status == UA_STATUS_SUCCESS)
{
/* found output terminal */
PinArray[PinIndex] = Descriptor->bTerminalID;
Consumed |= 1 << DescriptorIndex;
DPRINT("Assigned TerminalId %x to PinIndex %lx Consumed %lx DescriptorIndex %lx\n", Descriptor->bTerminalID, PinIndex, Consumed, DescriptorIndex);
PinIndex++;
}
/* now search for an input terminal with streaming type */
Status = UsbAudio_FindTerminalDescriptorAtIndexWithSubtypeAndTerminalType(TerminalIdsLength, TerminalIds, 0, USB_AUDIO_INPUT_TERMINAL, USB_AUDIO_STREAMING_TERMINAL_TYPE, &Descriptor, &DescriptorIndex);
if (Status == UA_STATUS_SUCCESS)
{
/* found output terminal */
PinArray[PinIndex] = Descriptor->bTerminalID;
Consumed |= 1 << DescriptorIndex;
PinIndex++;
}
/* now assign all other input terminals */
Index = 0;
do
{
/* find an input terminal */
Status = UsbAudio_FindTerminalDescriptorAtIndexWithSubtypeAndTerminalType(TerminalIdsLength, TerminalIds, Index, USB_AUDIO_INPUT_TERMINAL, USB_AUDIO_UNDEFINED_TERMINAL_TYPE, &Descriptor, &DescriptorIndex);
if (Status != UA_STATUS_SUCCESS)
{
/* no more items */
break;
}
if (Consumed & (1 << DescriptorIndex))
{
/* terminal has already been assigned to an pin */
Index++;
continue;
}
/* assign terminal */
PinArray[PinIndex] = Descriptor->bTerminalID;
Consumed |= 1 << DescriptorIndex;
PinIndex++;
Index++;
}while(Status == UA_STATUS_SUCCESS);
/* now assign all other output terminals */
Index = 0;
do
{
/* find an input terminal */
Status = UsbAudio_FindTerminalDescriptorAtIndexWithSubtypeAndTerminalType(TerminalIdsLength, TerminalIds, Index, USB_AUDIO_OUTPUT_TERMINAL, USB_AUDIO_UNDEFINED_TERMINAL_TYPE, &Descriptor, &DescriptorIndex);
if (Status != UA_STATUS_SUCCESS)
{
/* no more items */
break;
}
if (Consumed & (1 << DescriptorIndex))
{
/* terminal has already been assigned to an pin */
Index++;
continue;
}
/* assign terminal */
PinArray[PinIndex] = Descriptor->bTerminalID;
Consumed |= 1 << DescriptorIndex;
PinIndex++;
Index++;
}while(Status == UA_STATUS_SUCCESS);
/* store pin count */
DPRINT("Consumed %lx PinIndex %lu\n", Consumed, PinIndex);
*PinArrayCount = PinIndex;
return UA_STATUS_SUCCESS;
}

View file

@ -0,0 +1,182 @@
#pragma once
#include <pseh/pseh2.h>
#include <ntddk.h>
#include <windef.h>
#define NOBITMAP
#include <mmreg.h>
#include <ks.h>
#include <ksmedia.h>
#include <mmreg.h>
#include <mmsystem.h>
#include "Usb100.h"
#include <debug.h>
#include "libusbaudio.h"
#define USB_AUDIO_CONTROL_TERMINAL_DESCRIPTOR_TYPE (0x24)
#define USB_AUDIO_STREAMING_INTERFACE_INTERFACE_DESCRIPTOR_TYPE (0x24)
#define USB_AUDIO_INPUT_TERMINAL (0x02)
#define USB_AUDIO_OUTPUT_TERMINAL (0x03)
/* Universal Serial Bus Device Class Definition for Terminal Types Section A 1.1 */
#define USB_AUDIO_PCM_DATA_FORMAT (0x01)
#define USB_AUDIO_PCM8_DATA_FORMAT (0x02)
#define USB_AUDIO_IEEE_FLOAT_DATA_FORMAT (0x03)
#define USB_AUDIO_ALAW_DATA_FORMAT (0x04)
#define USB_AUDIO_MULAW_DATA_FORMAT (0x05)
/* Universal Serial Bus Device Class Definition for Terminal Types Section A 1.1 */
#define USB_AUDIO_DATA_FORMAT_TYPE_1 (0x01)
#define USB_AUDIO_DATA_FORMAT_TYPE_2 (0x02)
#define USB_AUDIO_DATA_FORMAT_TYPE_3 (0x03)
/* Universal Serial Bus Device Class Definition for Terminal Types Section 2.2 */
#define USB_AUDIO_STREAMING_TERMINAL_TYPE (0x0101)
#define USB_AUDIO_MICROPHONE_TERMINAL_TYPE (0x0201)
#define USB_AUDIO_DESKTOP_MICROPHONE_TERMINAL_TYPE (0x0202)
#define USB_AUDIO_PERSONAL_MICROPHONE_TERMINAL_TYPE (0x0203)
#define USB_AUDIO_OMMNI_MICROPHONE_TERMINAL_TYPE (0x0204)
#define USB_AUDIO_ARRAY_MICROPHONE_TERMINAL_TYPE (0x0205)
#define USB_AUDIO_ARRAY_PROCESSING_MICROPHONE_TERMINAL_TYPE (0x0206)
#define USB_AUDIO_SPEAKER_TERMINAL_TYPE (0x0301)
#define USB_HEADPHONES_SPEAKER_TERMINAL_TYPE (0x0302)
#define USB_AUDIO_HMDA_TERMINAL_TYPE (0x0303)
#define USB_AUDIO_DESKTOP_SPEAKER_TERMINAL_TYPE (0x0304)
#define USB_AUDIO_ROOM_SPEAKER_TERMINAL_TYPE (0x0305)
#define USB_AUDIO_COMMUNICATION_SPEAKER_TERMINAL_TYPE (0x0306)
#define USB_AUDIO_SUBWOOFER_TERMINAL_TYPE (0x0307)
#define USB_AUDIO_UNDEFINED_TERMINAL_TYPE (0xFFFF)
#define HTONS(x) ( ( (((unsigned short)(x)) >>8) & 0xff) | \
((((unsigned short)(x)) & 0xff)<<8) )
#include <pshpack1.h>
typedef struct
{
UCHAR bLength;
UCHAR bDescriptorType;
UCHAR bDescriptorSubtype;
UCHAR bTerminalID;
USHORT wTerminalType;
UCHAR bAssocTerminal;
UCHAR bSourceID;
UCHAR iTerminal;
}USB_AUDIO_CONTROL_OUTPUT_TERMINAL_DESCRIPTOR, *PUSB_AUDIO_CONTROL_OUTPUT_TERMINAL_DESCRIPTOR;
typedef struct
{
UCHAR bLength;
UCHAR bDescriptorType;
UCHAR bDescriptorSubtype;
UCHAR bTerminalID;
USHORT wTerminalType;
UCHAR bAssocTerminal;
UCHAR bNrChannels;
USHORT wChannelConfig;
UCHAR iChannelNames;
UCHAR iTerminal;
}USB_AUDIO_CONTROL_INPUT_TERMINAL_DESCRIPTOR, *PUSB_AUDIO_CONTROL_INPUT_TERMINAL_DESCRIPTOR;
typedef struct
{
UCHAR bLength;
UCHAR bDescriptorType;
UCHAR bDescriptorSubtype;
UCHAR bTerminalLink;
UCHAR bDelay;
USHORT wFormatTag;
}USB_AUDIO_STREAMING_INTERFACE_DESCRIPTOR, *PUSB_AUDIO_STREAMING_INTERFACE_DESCRIPTOR;
C_ASSERT(sizeof(USB_AUDIO_STREAMING_INTERFACE_DESCRIPTOR) == 0x07);
typedef struct
{
UCHAR bLength;
UCHAR bDescriptorType;
UCHAR bDescriptorSubtype;
UCHAR bFormatType;
UCHAR bNrChannels;
UCHAR bSubframeSize;
UCHAR bBitResolution;
UCHAR bSamFreqType;
UCHAR tSamFreq[3];
}USB_AUDIO_STREAMING_FORMAT_TYPE_1, *PUSB_AUDIO_STREAMING_FORMAT_TYPE_1;
C_ASSERT(sizeof(USB_AUDIO_STREAMING_FORMAT_TYPE_1) == 0x0B);
/* format.c */
USBAUDIO_STATUS
UsbAudio_AssignDataRanges(
IN PUSBAUDIO_CONTEXT Context,
IN PUCHAR ConfigurationDescriptor,
IN ULONG ConfigurationDescriptorSize,
IN PKSFILTER_DESCRIPTOR FilterDescriptor,
IN PUSB_COMMON_DESCRIPTOR * InterfaceDescriptors,
IN ULONG InterfaceCount,
IN ULONG InterfaceIndex,
IN PULONG TerminalIds);
/* parser.c */
USBAUDIO_STATUS
UsbAudio_CountInterfaceDescriptors(
IN PUCHAR ConfigurationDescriptor,
IN ULONG ConfigurationDescriptorLength,
OUT PULONG DescriptorCount);
USBAUDIO_STATUS
UsbAudio_CreateInterfaceDescriptorsArray(
IN PUSBAUDIO_CONTEXT Context,
IN PUCHAR ConfigurationDescriptor,
IN ULONG ConfigurationDescriptorLength,
IN ULONG ArrayLength,
OUT PUSB_COMMON_DESCRIPTOR ** Array);
ULONG
UsbAudio_GetAudioControlInterfaceIndex(
IN PUSB_COMMON_DESCRIPTOR * InterfaceDescriptors,
IN ULONG DescriptorCount);
USBAUDIO_STATUS
UsbAudio_CountAudioDescriptors(
IN PUCHAR ConfigurationDescriptor,
IN ULONG ConfigurationDescriptorLength,
IN PUSB_COMMON_DESCRIPTOR * InterfaceDescriptors,
IN ULONG InterfaceDescriptorCount,
IN ULONG InterfaceDescriptorIndex,
OUT PULONG DescriptorCount);
USBAUDIO_STATUS
UsbAudio_CreateAudioDescriptorArray(
IN PUSBAUDIO_CONTEXT Context,
IN PUCHAR ConfigurationDescriptor,
IN ULONG ConfigurationDescriptorLength,
IN PUSB_COMMON_DESCRIPTOR * InterfaceDescriptors,
IN ULONG InterfaceDescriptorCount,
IN ULONG InterfaceDescriptorIndex,
IN ULONG ArrayLength,
OUT PUSB_COMMON_DESCRIPTOR ** Array);
USBAUDIO_STATUS
UsbAudio_AssignTerminalIds(
IN PUSBAUDIO_CONTEXT Context,
IN ULONG TerminalIdsLength,
IN PUSB_COMMON_DESCRIPTOR * TerminalIds,
OUT PULONG PinArray,
OUT PULONG PinArrayCount);
PUSB_AUDIO_CONTROL_INPUT_TERMINAL_DESCRIPTOR
UsbAudio_GetTerminalDescriptorById(
IN PUSB_COMMON_DESCRIPTOR *Descriptors,
IN ULONG DescriptorCount,
IN ULONG TerminalId);