[USBAUDIO]

- implement USBAudioSelectAudioStreamingInterface

svn path=/trunk/; revision=72843
This commit is contained in:
Johannes Anderwald 2016-09-28 20:31:32 +00:00
parent d1faa1a99f
commit ff46d90618
3 changed files with 187 additions and 70 deletions

View 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;
}

View 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;
/* TODO: verify connection format */
UNIMPLEMENTED
return STATUS_SUCCESS;
}
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;
}
/* 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

View 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;
}