[LIBUSBAUDIO]
authorJohannes Anderwald <johannes.anderwald@reactos.org>
Fri, 28 Dec 2012 19:38:10 +0000 (19:38 +0000)
committerJohannes Anderwald <johannes.anderwald@reactos.org>
Fri, 28 Dec 2012 19:38:10 +0000 (19:38 +0000)
- 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

reactos/lib/drivers/sound/libusbaudio/CMakeLists.txt [new file with mode: 0644]
reactos/lib/drivers/sound/libusbaudio/format.c [new file with mode: 0644]
reactos/lib/drivers/sound/libusbaudio/libusbaudio.c [new file with mode: 0644]
reactos/lib/drivers/sound/libusbaudio/libusbaudio.h [new file with mode: 0644]
reactos/lib/drivers/sound/libusbaudio/parser.c [new file with mode: 0644]
reactos/lib/drivers/sound/libusbaudio/priv.h [new file with mode: 0644]

diff --git a/reactos/lib/drivers/sound/libusbaudio/CMakeLists.txt b/reactos/lib/drivers/sound/libusbaudio/CMakeLists.txt
new file mode 100644 (file)
index 0000000..9e4851f
--- /dev/null
@@ -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)
+
diff --git a/reactos/lib/drivers/sound/libusbaudio/format.c b/reactos/lib/drivers/sound/libusbaudio/format.c
new file mode 100644 (file)
index 0000000..729113e
--- /dev/null
@@ -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;
+}
+
+
diff --git a/reactos/lib/drivers/sound/libusbaudio/libusbaudio.c b/reactos/lib/drivers/sound/libusbaudio/libusbaudio.c
new file mode 100644 (file)
index 0000000..92ace8b
--- /dev/null
@@ -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;
+}
\ No newline at end of file
diff --git a/reactos/lib/drivers/sound/libusbaudio/libusbaudio.h b/reactos/lib/drivers/sound/libusbaudio/libusbaudio.h
new file mode 100644 (file)
index 0000000..5d48c9f
--- /dev/null
@@ -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);
+
diff --git a/reactos/lib/drivers/sound/libusbaudio/parser.c b/reactos/lib/drivers/sound/libusbaudio/parser.c
new file mode 100644 (file)
index 0000000..0684b96
--- /dev/null
@@ -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;
+}
diff --git a/reactos/lib/drivers/sound/libusbaudio/priv.h b/reactos/lib/drivers/sound/libusbaudio/priv.h
new file mode 100644 (file)
index 0000000..4c90c38
--- /dev/null
@@ -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);
+