mirror of
https://github.com/reactos/reactos.git
synced 2025-08-03 14:45:53 +00:00
[USBAUDIO]
- implement USBAudioSelectAudioStreamingInterface svn path=/trunk/; revision=72843
This commit is contained in:
parent
d1faa1a99f
commit
ff46d90618
3 changed files with 187 additions and 70 deletions
|
@ -136,6 +136,7 @@ USBAudioFilterCreate(
|
||||||
FilterContext->LowerDevice = Device->NextDeviceObject;
|
FilterContext->LowerDevice = Device->NextDeviceObject;
|
||||||
Filter->Context = FilterContext;
|
Filter->Context = FilterContext;
|
||||||
|
|
||||||
|
DPRINT("USBAudioFilterCreate FilterContext %p LowerDevice %p DeviceExtension %p\n", FilterContext, FilterContext->LowerDevice, FilterContext->DeviceExtension);
|
||||||
KsAddItemToObjectBag(Filter->Bag, FilterContext, ExFreePool);
|
KsAddItemToObjectBag(Filter->Bag, FilterContext, ExFreePool);
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,167 @@
|
||||||
|
|
||||||
#include "usbaudio.h"
|
#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
|
NTSTATUS
|
||||||
NTAPI
|
NTAPI
|
||||||
USBAudioPinCreate(
|
USBAudioPinCreate(
|
||||||
|
@ -18,6 +179,7 @@ USBAudioPinCreate(
|
||||||
PKSFILTER Filter;
|
PKSFILTER Filter;
|
||||||
PFILTER_CONTEXT FilterContext;
|
PFILTER_CONTEXT FilterContext;
|
||||||
PPIN_CONTEXT PinContext;
|
PPIN_CONTEXT PinContext;
|
||||||
|
NTSTATUS Status;
|
||||||
|
|
||||||
Filter = KsPinGetParentFilter(Pin);
|
Filter = KsPinGetParentFilter(Pin);
|
||||||
if (Filter == NULL)
|
if (Filter == NULL)
|
||||||
|
@ -44,6 +206,25 @@ USBAudioPinCreate(
|
||||||
/* store pin context*/
|
/* store pin context*/
|
||||||
Pin->Context = PinContext;
|
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;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -63,7 +244,6 @@ NTAPI
|
||||||
USBAudioPinProcess(
|
USBAudioPinProcess(
|
||||||
_In_ PKSPIN Pin)
|
_In_ PKSPIN Pin)
|
||||||
{
|
{
|
||||||
UNIMPLEMENTED
|
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -85,70 +265,14 @@ USBAudioPinSetDataFormat(
|
||||||
_In_ const KSDATARANGE* DataRange,
|
_In_ const KSDATARANGE* DataRange,
|
||||||
_In_opt_ const KSATTRIBUTE_LIST* AttributeRange)
|
_In_opt_ const KSATTRIBUTE_LIST* AttributeRange)
|
||||||
{
|
{
|
||||||
PURB Urb;
|
if (OldFormat == NULL)
|
||||||
PUCHAR SampleRateBuffer;
|
|
||||||
PPIN_CONTEXT PinContext;
|
|
||||||
NTSTATUS Status;
|
|
||||||
PKSDATAFORMAT_WAVEFORMATEX WaveFormatEx;
|
|
||||||
|
|
||||||
/* allocate sample rate buffer */
|
|
||||||
SampleRateBuffer = AllocFunction(sizeof(ULONG));
|
|
||||||
if (!SampleRateBuffer)
|
|
||||||
{
|
{
|
||||||
/* no memory */
|
/* TODO: verify connection format */
|
||||||
return STATUS_INSUFFICIENT_RESOURCES;
|
UNIMPLEMENTED
|
||||||
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IsEqualGUIDAligned(&Pin->ConnectionFormat->MajorFormat, &KSDATAFORMAT_TYPE_AUDIO) &&
|
return UsbAudioSetFormat(Pin);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
|
|
|
@ -79,14 +79,6 @@ SubmitUrbSync(
|
||||||
if (Status == STATUS_PENDING)
|
if (Status == STATUS_PENDING)
|
||||||
{
|
{
|
||||||
KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
|
KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
|
||||||
}
|
|
||||||
|
|
||||||
// complete request
|
|
||||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
||||||
|
|
||||||
if (Status == STATUS_PENDING)
|
|
||||||
{
|
|
||||||
// get final status
|
|
||||||
Status = IoStatus.Status;
|
Status = IoStatus.Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue