[USBAUDIO]
[reactos.git] / reactos / drivers / usb / usbaudio / filter.c
index 062d0b5..93ad768 100644 (file)
@@ -43,13 +43,15 @@ KSPIN_MEDIUM StandardPinMedium =
 KSDATARANGE BridgePinAudioFormat[] =
 {
     {
-        sizeof(KSDATAFORMAT),
-        0,
-        0,
-        0,
-        {STATIC_KSDATAFORMAT_TYPE_AUDIO},
-        {STATIC_KSDATAFORMAT_SUBTYPE_ANALOG},
-        {STATIC_KSDATAFORMAT_SPECIFIER_NONE}
+        {
+            sizeof(KSDATAFORMAT),
+            0,
+            0,
+            0,
+            {STATIC_KSDATAFORMAT_TYPE_AUDIO},
+            {STATIC_KSDATAFORMAT_SUBTYPE_ANALOG},
+            {STATIC_KSDATAFORMAT_SPECIFIER_NONE}
+        }
     }
 };
 
@@ -74,6 +76,21 @@ static KSFILTER_DISPATCH USBAudioFilterDispatch =
     NULL
 };
 
+static KSPIN_DISPATCH UsbAudioPinDispatch =
+{
+    USBAudioPinCreate,
+    USBAudioPinClose,
+    USBAudioPinProcess,
+    USBAudioPinReset,
+    USBAudioPinSetDataFormat,
+    USBAudioPinSetDeviceState,
+    NULL,
+    NULL,
+    NULL,
+    NULL
+};
+
+
 NTSTATUS
 BuildUSBAudioFilterTopology(
     PKSDEVICE Device)
@@ -88,7 +105,39 @@ USBAudioFilterCreate(
     PKSFILTER Filter,
     PIRP Irp)
 {
-    UNIMPLEMENTED
+    PKSFILTERFACTORY FilterFactory;
+    PKSDEVICE Device;
+    PFILTER_CONTEXT FilterContext;
+
+    FilterFactory = KsGetParent(Filter);
+    if (FilterFactory == NULL)
+    {
+        /* invalid parameter */
+        return STATUS_INVALID_PARAMETER;
+    }
+
+    Device = KsGetParent(FilterFactory);
+    if (Device == NULL)
+    {
+        /* invalid parameter */
+        return STATUS_INVALID_PARAMETER;
+    }
+
+    /* alloc filter context */
+    FilterContext = AllocFunction(sizeof(FILTER_CONTEXT));
+    if (FilterContext == NULL)
+    {
+        /* no memory */
+        return STATUS_INSUFFICIENT_RESOURCES;
+    }
+
+    /* init context */
+    FilterContext->DeviceExtension = Device->Context;
+    FilterContext->LowerDevice = Device->NextDeviceObject;
+    Filter->Context = FilterContext;
+
+    DPRINT("USBAudioFilterCreate FilterContext %p LowerDevice %p DeviceExtension %p\n", FilterContext, FilterContext->LowerDevice, FilterContext->DeviceExtension);
+    KsAddItemToObjectBag(Filter->Bag, FilterContext, ExFreePool);
     return STATUS_SUCCESS;
 }
 
@@ -112,7 +161,7 @@ CountTerminalUnits(
     {
         if (Descriptor->bInterfaceSubClass == 0x01) /* AUDIO_CONTROL */
         {
-            InterfaceHeaderDescriptor = USBD_ParseDescriptors(ConfigurationDescriptor, ConfigurationDescriptor->wTotalLength, Descriptor, USB_AUDIO_CONTROL_TERMINAL_DESCRIPTOR_TYPE);
+            InterfaceHeaderDescriptor = (PUSB_AUDIO_CONTROL_INTERFACE_HEADER_DESCRIPTOR)USBD_ParseDescriptors(ConfigurationDescriptor, ConfigurationDescriptor->wTotalLength, Descriptor, USB_AUDIO_CONTROL_TERMINAL_DESCRIPTOR_TYPE);
             if (InterfaceHeaderDescriptor != NULL)
             {
                 CommonDescriptor = USBD_ParseDescriptors(InterfaceHeaderDescriptor, InterfaceHeaderDescriptor->wTotalLength, (PVOID)((ULONG_PTR)InterfaceHeaderDescriptor + InterfaceHeaderDescriptor->bLength), USB_AUDIO_CONTROL_TERMINAL_DESCRIPTOR_TYPE);
@@ -127,7 +176,7 @@ CountTerminalUnits(
                         }
                         TotalTerminalCount++;
                     }
-                    CommonDescriptor = (PUSB_AUDIO_CONTROL_INPUT_TERMINAL_DESCRIPTOR)((ULONG_PTR)CommonDescriptor + CommonDescriptor->bLength);
+                    CommonDescriptor = (PUSB_COMMON_DESCRIPTOR)((ULONG_PTR)CommonDescriptor + CommonDescriptor->bLength);
                     if ((ULONG_PTR)CommonDescriptor >= ((ULONG_PTR)InterfaceHeaderDescriptor + InterfaceHeaderDescriptor->wTotalLength))
                         break;
                 }
@@ -203,7 +252,7 @@ UsbAudioGetStreamingTerminalDescriptorByIndex(
     {
         if (Descriptor->bInterfaceSubClass == 0x01) /* AUDIO_CONTROL */
         {
-            InterfaceHeaderDescriptor = USBD_ParseDescriptors(ConfigurationDescriptor, ConfigurationDescriptor->wTotalLength, Descriptor, USB_AUDIO_CONTROL_TERMINAL_DESCRIPTOR_TYPE);
+            InterfaceHeaderDescriptor = (PUSB_AUDIO_CONTROL_INTERFACE_HEADER_DESCRIPTOR)USBD_ParseDescriptors(ConfigurationDescriptor, ConfigurationDescriptor->wTotalLength, Descriptor, USB_AUDIO_CONTROL_TERMINAL_DESCRIPTOR_TYPE);
             if (InterfaceHeaderDescriptor != NULL)
             {
                 CommonDescriptor = USBD_ParseDescriptors(InterfaceHeaderDescriptor, InterfaceHeaderDescriptor->wTotalLength, (PVOID)((ULONG_PTR)InterfaceHeaderDescriptor + InterfaceHeaderDescriptor->bLength), USB_AUDIO_CONTROL_TERMINAL_DESCRIPTOR_TYPE);
@@ -221,7 +270,7 @@ UsbAudioGetStreamingTerminalDescriptorByIndex(
                             TerminalCount++;
                         }
                     }
-                    CommonDescriptor = (PUSB_AUDIO_CONTROL_INPUT_TERMINAL_DESCRIPTOR)((ULONG_PTR)CommonDescriptor + CommonDescriptor->bLength);
+                    CommonDescriptor = (PUSB_COMMON_DESCRIPTOR)((ULONG_PTR)CommonDescriptor + CommonDescriptor->bLength);
                     if ((ULONG_PTR)CommonDescriptor >= ((ULONG_PTR)InterfaceHeaderDescriptor + InterfaceHeaderDescriptor->wTotalLength))
                         break;
                 }
@@ -249,7 +298,7 @@ UsbAudioGetNonStreamingTerminalDescriptorByIndex(
     {
         if (Descriptor->bInterfaceSubClass == 0x01) /* AUDIO_CONTROL */
         {
-            InterfaceHeaderDescriptor = USBD_ParseDescriptors(ConfigurationDescriptor, ConfigurationDescriptor->wTotalLength, Descriptor, USB_AUDIO_CONTROL_TERMINAL_DESCRIPTOR_TYPE);
+            InterfaceHeaderDescriptor = (PUSB_AUDIO_CONTROL_INTERFACE_HEADER_DESCRIPTOR)USBD_ParseDescriptors(ConfigurationDescriptor, ConfigurationDescriptor->wTotalLength, Descriptor, USB_AUDIO_CONTROL_TERMINAL_DESCRIPTOR_TYPE);
             if (InterfaceHeaderDescriptor != NULL)
             {
                 CommonDescriptor = USBD_ParseDescriptors(InterfaceHeaderDescriptor, InterfaceHeaderDescriptor->wTotalLength, (PVOID)((ULONG_PTR)InterfaceHeaderDescriptor + InterfaceHeaderDescriptor->bLength), USB_AUDIO_CONTROL_TERMINAL_DESCRIPTOR_TYPE);
@@ -267,7 +316,7 @@ UsbAudioGetNonStreamingTerminalDescriptorByIndex(
                             TerminalCount++;
                         }
                     }
-                    CommonDescriptor = (PUSB_AUDIO_CONTROL_INPUT_TERMINAL_DESCRIPTOR)((ULONG_PTR)CommonDescriptor + CommonDescriptor->bLength);
+                    CommonDescriptor = (PUSB_COMMON_DESCRIPTOR)((ULONG_PTR)CommonDescriptor + CommonDescriptor->bLength);
                     if ((ULONG_PTR)CommonDescriptor >= ((ULONG_PTR)InterfaceHeaderDescriptor + InterfaceHeaderDescriptor->wTotalLength))
                         break;
                 }
@@ -277,6 +326,71 @@ UsbAudioGetNonStreamingTerminalDescriptorByIndex(
     return NULL;
 }
 
+VOID
+UsbAudioGetDataRanges(
+    IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor,
+    IN UCHAR bTerminalID,
+    OUT PKSDATARANGE** OutDataRanges,
+    OUT PULONG OutDataRangesCount)
+{
+    PUSB_AUDIO_STREAMING_INTERFACE_DESCRIPTOR StreamingInterfaceDescriptor;
+    PUSB_AUDIO_STREAMING_FORMAT_TYPE_DESCRIPTOR StreamingFormatDescriptor;
+    PUSB_INTERFACE_DESCRIPTOR Descriptor;
+    PKSDATARANGE_AUDIO DataRangeAudio;
+    PKSDATARANGE *DataRangeAudioArray;
+    ULONG NumFrequency;
+
+    for (Descriptor = USBD_ParseConfigurationDescriptorEx(ConfigurationDescriptor, ConfigurationDescriptor, -1, -1, USB_DEVICE_CLASS_AUDIO, -1, -1);
+    Descriptor != NULL;
+        Descriptor = USBD_ParseConfigurationDescriptorEx(ConfigurationDescriptor, (PVOID)((ULONG_PTR)Descriptor + Descriptor->bLength), -1, -1, USB_DEVICE_CLASS_AUDIO, -1, -1))
+    {
+        if (Descriptor->bInterfaceSubClass == 0x02) /* AUDIO_STREAMING */
+        {
+            StreamingInterfaceDescriptor = (PUSB_AUDIO_STREAMING_INTERFACE_DESCRIPTOR)USBD_ParseDescriptors(ConfigurationDescriptor, ConfigurationDescriptor->wTotalLength, Descriptor, USB_AUDIO_CONTROL_TERMINAL_DESCRIPTOR_TYPE);
+            if (StreamingInterfaceDescriptor != NULL)
+            {
+                ASSERT(StreamingInterfaceDescriptor->bDescriptorSubtype == 0x01);
+                ASSERT(StreamingInterfaceDescriptor->wFormatTag == WAVE_FORMAT_PCM);
+                if (StreamingInterfaceDescriptor->bTerminalLink == bTerminalID)
+                {
+                    StreamingFormatDescriptor = (PUSB_AUDIO_STREAMING_FORMAT_TYPE_DESCRIPTOR)((ULONG_PTR)StreamingInterfaceDescriptor + StreamingInterfaceDescriptor->bLength);
+                    ASSERT(StreamingFormatDescriptor->bDescriptorType == 0x24);
+                    ASSERT(StreamingFormatDescriptor->bDescriptorSubtype == 0x02);
+                    ASSERT(StreamingFormatDescriptor->bFormatType == 0x01);
+
+                    DataRangeAudio = AllocFunction(sizeof(KSDATARANGE_AUDIO));
+                    if (DataRangeAudio == NULL)
+                    {
+                        /* no memory*/
+                        return;
+                    }
+
+                    DataRangeAudio->DataRange.FormatSize = sizeof(KSDATARANGE_AUDIO);
+                    DataRangeAudio->DataRange.MajorFormat = KSDATAFORMAT_TYPE_AUDIO;
+                    DataRangeAudio->DataRange.SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
+                    DataRangeAudio->DataRange.Specifier = KSDATAFORMAT_SPECIFIER_WAVEFORMATEX;
+                    DataRangeAudio->MaximumChannels = 1;
+                    DataRangeAudio->MinimumBitsPerSample = StreamingFormatDescriptor->bBitResolution;
+                    DataRangeAudio->MaximumBitsPerSample = StreamingFormatDescriptor->bBitResolution;
+                    NumFrequency = StreamingFormatDescriptor->bSamFreqType - 1;
+                    DataRangeAudio->MinimumSampleFrequency = StreamingFormatDescriptor->tSamFreq[0] | StreamingFormatDescriptor->tSamFreq[1] << 8 | StreamingFormatDescriptor->tSamFreq[2] << 16;
+                    DataRangeAudio->MaximumSampleFrequency = StreamingFormatDescriptor->tSamFreq[NumFrequency*3] | StreamingFormatDescriptor->tSamFreq[NumFrequency * 3+1] << 8 | StreamingFormatDescriptor->tSamFreq[NumFrequency * 3+2]<<16;
+                    DataRangeAudioArray = AllocFunction(sizeof(PKSDATARANGE_AUDIO));
+                    if (DataRangeAudioArray == NULL)
+                    {
+                        /* no memory */
+                        FreeFunction(DataRangeAudio);
+                        return;
+                    }
+                    DataRangeAudioArray[0] = (PKSDATARANGE)DataRangeAudio;
+                    *OutDataRanges = DataRangeAudioArray;
+                    *OutDataRangesCount = 1;
+                    return;
+                }
+            }
+        }
+    }
+}
 
 
 NTSTATUS
@@ -313,11 +427,15 @@ USBAudioPinBuildDescriptors(
         {
             /* irp sink pins*/
             TerminalDescriptor = UsbAudioGetStreamingTerminalDescriptorByIndex(DeviceExtension->ConfigurationDescriptor, Index);
+            ASSERT(TerminalDescriptor != NULL);
+
+            Pins[Index].Dispatch = &UsbAudioPinDispatch;
             Pins[Index].PinDescriptor.InterfacesCount = 1;
             Pins[Index].PinDescriptor.Interfaces = &StandardPinInterface;
             Pins[Index].PinDescriptor.MediumsCount = 1;
             Pins[Index].PinDescriptor.Mediums = &StandardPinMedium;
             Pins[Index].PinDescriptor.Category = UsbAudioGetPinCategoryFromTerminalDescriptor(TerminalDescriptor);
+            UsbAudioGetDataRanges(DeviceExtension->ConfigurationDescriptor, TerminalDescriptor->bTerminalID, (PKSDATARANGE**)&Pins[Index].PinDescriptor.DataRanges, &Pins[Index].PinDescriptor.DataRangesCount);
 
             if (TerminalDescriptor->bDescriptorSubtype == USB_AUDIO_OUTPUT_TERMINAL)
             {
@@ -330,8 +448,12 @@ USBAudioPinBuildDescriptors(
                 Pins[Index].PinDescriptor.DataFlow = KSPIN_DATAFLOW_IN;
             }
 
+
+            Pins[Index].Flags = KSPIN_FLAG_PROCESS_IN_RUN_STATE_ONLY | KSFILTER_FLAG_CRITICAL_PROCESSING;
+
             /* irp sinks / sources can be instantiated */
             Pins[Index].InstancesPossible = 1;
+            Pins[Index].InstancesNecessary = 1;
         }
         else
         {
@@ -389,21 +511,25 @@ NTAPI
 USBAudioCreateFilterContext(
     PKSDEVICE Device)
 {
-    KSFILTER_DESCRIPTOR FilterDescriptor;
-    PDEVICE_EXTENSION DeviceExtension;
+    PKSFILTER_DESCRIPTOR FilterDescriptor;
     PKSCOMPONENTID ComponentId;
     NTSTATUS Status;
 
-    /* clear filter descriptor */
-    RtlZeroMemory(&FilterDescriptor, sizeof(KSFILTER_DESCRIPTOR));
+    /* allocate descriptor */
+    FilterDescriptor = AllocFunction(sizeof(KSFILTER_DESCRIPTOR));
+    if (!FilterDescriptor)
+    {
+        /* no memory */
+        return USBD_STATUS_INSUFFICIENT_RESOURCES;
+    }
 
     /* init filter descriptor*/
-    FilterDescriptor.Version = KSFILTER_DESCRIPTOR_VERSION;
-    FilterDescriptor.Flags = 0;
-    FilterDescriptor.ReferenceGuid = &KSNAME_Filter;
-    FilterDescriptor.Dispatch = &USBAudioFilterDispatch;
-    FilterDescriptor.CategoriesCount = 1;
-    FilterDescriptor.Categories = &GUID_KSCATEGORY_AUDIO;
+    FilterDescriptor->Version = KSFILTER_DESCRIPTOR_VERSION;
+    FilterDescriptor->Flags = 0;
+    FilterDescriptor->ReferenceGuid = &KSNAME_Filter;
+    FilterDescriptor->Dispatch = &USBAudioFilterDispatch;
+    FilterDescriptor->CategoriesCount = 1;
+    FilterDescriptor->Categories = &GUID_KSCATEGORY_AUDIO;
 
     /* init component id*/
     ComponentId = AllocFunction(sizeof(KSCOMPONENTID));
@@ -419,10 +545,10 @@ USBAudioCreateFilterContext(
         //FreeFunction(ComponentId);
         //return Status;
     }
-    FilterDescriptor.ComponentId = ComponentId;
+    FilterDescriptor->ComponentId = ComponentId;
 
     /* build pin descriptors */
-    Status = USBAudioPinBuildDescriptors(Device, (PKSPIN_DESCRIPTOR_EX *)&FilterDescriptor.PinDescriptors, &FilterDescriptor.PinDescriptorsCount, &FilterDescriptor.PinDescriptorSize);
+    Status = USBAudioPinBuildDescriptors(Device, (PKSPIN_DESCRIPTOR_EX *)&FilterDescriptor->PinDescriptors, &FilterDescriptor->PinDescriptorsCount, &FilterDescriptor->PinDescriptorSize);
     if (!NT_SUCCESS(Status))
     {
         /* failed*/
@@ -430,7 +556,6 @@ USBAudioCreateFilterContext(
         return Status;
     }
 
-    DbgBreakPoint();
     /* build topology */
     Status = BuildUSBAudioFilterTopology(Device);
     if (!NT_SUCCESS(Status))
@@ -441,8 +566,7 @@ USBAudioCreateFilterContext(
     }
 
     /* lets create the filter */
-    DeviceExtension = Device->Context;
-    Status = KsCreateFilterFactory(Device->FunctionalDeviceObject, &FilterDescriptor, ReferenceString, NULL, KSCREATE_ITEM_FREEONSTOP, NULL, NULL, NULL);
+    Status = KsCreateFilterFactory(Device->FunctionalDeviceObject, FilterDescriptor, ReferenceString, NULL, KSCREATE_ITEM_FREEONSTOP, NULL, NULL, NULL);
     DPRINT1("KsCreateFilterFactory: %x\n", Status);
 
     return Status;