[USBAUDIO]
authorJohannes Anderwald <johannes.anderwald@reactos.org>
Wed, 28 Sep 2016 20:31:32 +0000 (20:31 +0000)
committerJohannes Anderwald <johannes.anderwald@reactos.org>
Wed, 28 Sep 2016 20:31:32 +0000 (20:31 +0000)
- implement USBAudioSelectAudioStreamingInterface

svn path=/trunk/; revision=72843

reactos/drivers/usb/usbaudio/filter.c
reactos/drivers/usb/usbaudio/pin.c
reactos/drivers/usb/usbaudio/usbaudio.c

index f270afc..fe76f55 100644 (file)
@@ -136,6 +136,7 @@ USBAudioFilterCreate(
     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;
 }
index e9d5c05..f0a50da 100644 (file)
@@ -9,6 +9,167 @@
 
 #include "usbaudio.h"
 
+NTSTATUS
+UsbAudioSetFormat(
+    IN PKSPIN Pin)
+{
+    PURB Urb;
+    PUCHAR SampleRateBuffer;
+    PPIN_CONTEXT PinContext;
+    NTSTATUS Status;
+    PKSDATAFORMAT_WAVEFORMATEX WaveFormatEx;
+
+    /* allocate sample rate buffer */
+    SampleRateBuffer = AllocFunction(sizeof(ULONG));
+    if (!SampleRateBuffer)
+    {
+        /* no memory */
+        return STATUS_INSUFFICIENT_RESOURCES;
+    }
+
+    if (IsEqualGUIDAligned(&Pin->ConnectionFormat->MajorFormat, &KSDATAFORMAT_TYPE_AUDIO) &&
+        IsEqualGUIDAligned(&Pin->ConnectionFormat->SubFormat, &KSDATAFORMAT_SUBTYPE_PCM) &&
+        IsEqualGUIDAligned(&Pin->ConnectionFormat->Specifier, &KSDATAFORMAT_SPECIFIER_WAVEFORMATEX))
+    {
+        WaveFormatEx = (PKSDATAFORMAT_WAVEFORMATEX)Pin->ConnectionFormat;
+        SampleRateBuffer[0] = (WaveFormatEx->WaveFormatEx.nSamplesPerSec >> 16) & 0xFF;
+        SampleRateBuffer[1] = (WaveFormatEx->WaveFormatEx.nSamplesPerSec >> 8) & 0xFF;
+        SampleRateBuffer[2] = (WaveFormatEx->WaveFormatEx.nSamplesPerSec >> 0) & 0xFF;
+
+        /* TODO: verify connection format */
+    }
+    else
+    {
+        /* not supported yet*/
+        UNIMPLEMENTED;
+        FreeFunction(SampleRateBuffer);
+        return STATUS_INVALID_PARAMETER;
+    }
+
+    /* allocate urb */
+    Urb = AllocFunction(sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST));
+    if (!Urb)
+    {
+        /* no memory */
+        FreeFunction(SampleRateBuffer);
+        return STATUS_INSUFFICIENT_RESOURCES;
+    }
+
+    /* format urb */
+    UsbBuildVendorRequest(Urb,
+        URB_FUNCTION_CLASS_ENDPOINT,
+        sizeof(URB),
+        USBD_TRANSFER_DIRECTION_OUT,
+        0,
+        0x01,
+        0x100,
+        0x81, //FIXME bEndpointAddress
+        SampleRateBuffer,
+        NULL,
+        3,
+        NULL);
+
+    /* get pin context */
+    PinContext = Pin->Context;
+    DbgBreakPoint();
+    /* submit urb */
+    Status = SubmitUrbSync(PinContext->LowerDevice, Urb);
+
+    DPRINT1("USBAudioPinSetDataFormat Pin %p Status %x\n", Pin, Status);
+    FreeFunction(Urb);
+    FreeFunction(SampleRateBuffer);
+    return Status;
+}
+
+NTSTATUS
+USBAudioSelectAudioStreamingInterface(
+    IN PDEVICE_EXTENSION DeviceExtension,
+    IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor)
+{
+    PURB Urb;
+    PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor;
+    NTSTATUS Status;
+
+    /* grab interface descriptor */
+    InterfaceDescriptor = USBD_ParseConfigurationDescriptorEx(ConfigurationDescriptor, ConfigurationDescriptor, -1, -1, USB_DEVICE_CLASS_AUDIO, -1, -1);
+    if (!InterfaceDescriptor)
+    {
+        /* no such interface */
+        return STATUS_INVALID_PARAMETER;
+    }
+
+    /* select the first interface with audio streaming and non zero num of endpoints */
+    while (InterfaceDescriptor != NULL)
+    {
+        if (InterfaceDescriptor->bInterfaceSubClass == 0x02 /* AUDIO_STREAMING */ && InterfaceDescriptor->bNumEndpoints > 0) 
+        {
+            break;
+        }
+        InterfaceDescriptor = USBD_ParseConfigurationDescriptorEx(ConfigurationDescriptor, (PVOID)((ULONG_PTR)InterfaceDescriptor + InterfaceDescriptor->bLength), -1, -1, USB_DEVICE_CLASS_AUDIO, -1, -1);
+    }
+
+    if (!InterfaceDescriptor)
+    {
+        /* no such interface */
+        return STATUS_INVALID_PARAMETER;
+    }
+
+    Urb = AllocFunction(GET_SELECT_INTERFACE_REQUEST_SIZE(InterfaceDescriptor->bNumEndpoints));
+    if (!Urb)
+    {
+        /* no memory */
+        return USBD_STATUS_INSUFFICIENT_RESOURCES;
+    }
+
+     /* now prepare interface urb */
+     UsbBuildSelectInterfaceRequest(Urb, GET_SELECT_INTERFACE_REQUEST_SIZE(InterfaceDescriptor->bNumEndpoints), DeviceExtension->ConfigurationHandle, InterfaceDescriptor->bInterfaceNumber, InterfaceDescriptor->bAlternateSetting);
+
+     /* copy interface information */
+     RtlCopyMemory(&Urb->UrbSelectInterface.Interface, DeviceExtension->InterfaceInfo, DeviceExtension->InterfaceInfo->Length);
+
+     /* set configuration handle */
+     Urb->UrbSelectInterface.ConfigurationHandle = DeviceExtension->ConfigurationHandle;
+
+     /* now select the interface */
+     Status = SubmitUrbSync(DeviceExtension->LowerDevice, Urb);
+
+     DPRINT1("USBAudioSelectAudioStreamingInterface Status %x UrbStatus %x\n", Status, Urb->UrbSelectInterface.Hdr.Status);
+
+     /* did it succeeed */
+     if (NT_SUCCESS(Status))
+     {
+         /* update configuration info */
+         ASSERT(Urb->UrbSelectInterface.Interface.Length == DeviceExtension->InterfaceInfo->Length);
+         RtlCopyMemory(DeviceExtension->InterfaceInfo, &Urb->UrbSelectInterface.Interface, Urb->UrbSelectInterface.Interface.Length);
+     }
+
+     /* free urb */
+     FreeFunction(Urb);
+     return Status;
+}
+
+NTSTATUS
+InitCapturePin(
+    IN PKSPIN Pin)
+{
+    NTSTATUS Status;
+
+    /* set sample rate */
+    Status = UsbAudioSetFormat(Pin);
+
+    /* TODO: init pin */
+    return Status;
+}
+
+NTSTATUS
+InitStreamPin(
+    IN PKSPIN Pin)
+{
+    UNIMPLEMENTED
+    return STATUS_NOT_IMPLEMENTED;
+}
+
+
 NTSTATUS
 NTAPI
 USBAudioPinCreate(
@@ -18,6 +179,7 @@ USBAudioPinCreate(
     PKSFILTER Filter;
     PFILTER_CONTEXT FilterContext;
     PPIN_CONTEXT PinContext;
+    NTSTATUS Status;
 
     Filter = KsPinGetParentFilter(Pin);
     if (Filter == NULL)
@@ -44,6 +206,25 @@ USBAudioPinCreate(
     /* store pin context*/
     Pin->Context = PinContext;
 
+    /* select streaming interface */
+    Status = USBAudioSelectAudioStreamingInterface(PinContext->DeviceExtension, PinContext->DeviceExtension->ConfigurationDescriptor);
+    if (!NT_SUCCESS(Status))
+    {
+        /* failed */
+        return Status;
+    }
+
+    if (Pin->DataFlow == KSPIN_DATAFLOW_OUT)
+    {
+        /* init capture pin */
+        Status = InitCapturePin(Pin);
+    }
+    else
+    {
+        /* audio streaming pin*/
+        Status = InitStreamPin(Pin);
+    }
+
     return STATUS_SUCCESS;
 }
 
@@ -63,7 +244,6 @@ NTAPI
 USBAudioPinProcess(
     _In_ PKSPIN Pin)
 {
-    UNIMPLEMENTED
     return STATUS_SUCCESS;
 }
 
@@ -85,70 +265,14 @@ USBAudioPinSetDataFormat(
     _In_ const KSDATARANGE* DataRange,
     _In_opt_ const KSATTRIBUTE_LIST* AttributeRange)
 {
-    PURB Urb;
-    PUCHAR SampleRateBuffer;
-    PPIN_CONTEXT PinContext;
-    NTSTATUS Status;
-    PKSDATAFORMAT_WAVEFORMATEX WaveFormatEx;
-
-    /* allocate sample rate buffer */
-    SampleRateBuffer = AllocFunction(sizeof(ULONG));
-    if (!SampleRateBuffer)
+    if (OldFormat == NULL)
     {
-        /* no memory */
-        return STATUS_INSUFFICIENT_RESOURCES;
-    }
-
-    if (IsEqualGUIDAligned(&Pin->ConnectionFormat->MajorFormat, &KSDATAFORMAT_TYPE_AUDIO) && 
-        IsEqualGUIDAligned(&Pin->ConnectionFormat->SubFormat,  &KSDATAFORMAT_SUBTYPE_PCM) &&
-        IsEqualGUIDAligned(&Pin->ConnectionFormat->Specifier, &KSDATAFORMAT_SPECIFIER_WAVEFORMATEX))
-    {
-        WaveFormatEx = (PKSDATAFORMAT_WAVEFORMATEX)Pin->ConnectionFormat;
-        SampleRateBuffer[0] = (WaveFormatEx->WaveFormatEx.nSamplesPerSec >> 16) & 0xFF;
-        SampleRateBuffer[1] = (WaveFormatEx->WaveFormatEx.nSamplesPerSec >> 8) & 0xFF;
-        SampleRateBuffer[2] = (WaveFormatEx->WaveFormatEx.nSamplesPerSec >> 0) & 0xFF;
-    }
-    else
-    {
-        /* not supported yet*/
-        UNIMPLEMENTED;
-        FreeFunction(SampleRateBuffer);
-        return STATUS_INVALID_PARAMETER;
+        /* TODO: verify connection format */
+        UNIMPLEMENTED
+        return STATUS_SUCCESS;
     }
 
-    /* allocate urb */
-    Urb = AllocFunction(sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST));
-    if (!Urb)
-    {
-        /* no memory */
-        FreeFunction(SampleRateBuffer);
-        return STATUS_INSUFFICIENT_RESOURCES;
-    }
-
-    /* format urb */
-    UsbBuildVendorRequest(Urb,
-                          URB_FUNCTION_CLASS_ENDPOINT,
-                          sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST),
-                          USBD_TRANSFER_DIRECTION_OUT,
-                          0,
-                          0x01,
-                          0x100,
-                          0x81, //bEndpointAddress
-                          SampleRateBuffer,
-                          NULL,
-                          3,
-                          NULL);
-
-    /* get pin context */
-    PinContext = Pin->Context;
-    DbgBreakPoint();
-    /* submit urb */
-    Status = SubmitUrbSync(PinContext->LowerDevice, Urb);
-
-    DPRINT1("USBAudioPinSetDataFormat Pin %p Status %x\n", Pin, Status);
-    FreeFunction(Urb);
-    FreeFunction(SampleRateBuffer);
-    return Status;
+    return UsbAudioSetFormat(Pin);
 }
 
 NTSTATUS
index 04619c1..01ac7d0 100644 (file)
@@ -79,14 +79,6 @@ SubmitUrbSync(
     if (Status == STATUS_PENDING)
     {
         KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
-    }
-
-    // complete request
-    IoCompleteRequest(Irp, IO_NO_INCREMENT);
-
-    if (Status == STATUS_PENDING)
-    {
-        // get final status
         Status = IoStatus.Status;
     }