mirror of
https://github.com/reactos/reactos.git
synced 2025-02-22 08:25:03 +00:00
[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:
parent
426a79eba3
commit
d697105863
6 changed files with 1160 additions and 0 deletions
13
reactos/lib/drivers/sound/libusbaudio/CMakeLists.txt
Normal file
13
reactos/lib/drivers/sound/libusbaudio/CMakeLists.txt
Normal 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)
|
||||
|
155
reactos/lib/drivers/sound/libusbaudio/format.c
Normal file
155
reactos/lib/drivers/sound/libusbaudio/format.c
Normal 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;
|
||||
}
|
||||
|
||||
|
364
reactos/lib/drivers/sound/libusbaudio/libusbaudio.c
Normal file
364
reactos/lib/drivers/sound/libusbaudio/libusbaudio.c
Normal 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;
|
||||
}
|
56
reactos/lib/drivers/sound/libusbaudio/libusbaudio.h
Normal file
56
reactos/lib/drivers/sound/libusbaudio/libusbaudio.h
Normal 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);
|
||||
|
390
reactos/lib/drivers/sound/libusbaudio/parser.c
Normal file
390
reactos/lib/drivers/sound/libusbaudio/parser.c
Normal 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;
|
||||
}
|
182
reactos/lib/drivers/sound/libusbaudio/priv.h
Normal file
182
reactos/lib/drivers/sound/libusbaudio/priv.h
Normal 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);
|
||||
|
Loading…
Reference in a new issue