mirror of
https://github.com/reactos/reactos.git
synced 2025-05-29 22:18:13 +00:00
[USBAUDIO]
- remove setting InstancesNecessary as it causes problems with KsStudio - start implementing support for usb headsets - use endpoint address in UsbAudioSetFormat - rewrite USBAudioSelectAudioStreamingInterface to select the interface based on the format index chosen svn path=/trunk/; revision=73094
This commit is contained in:
parent
79e0de2faf
commit
2a33de20a4
3 changed files with 280 additions and 21 deletions
|
@ -1258,7 +1258,6 @@ USBAudioPinBuildDescriptors(
|
|||
|
||||
/* irp sinks / sources can be instantiated */
|
||||
Pins[Index].InstancesPossible = 1;
|
||||
Pins[Index].InstancesNecessary = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -136,6 +136,9 @@ UsbAudioSetFormat(
|
|||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
/* get pin context */
|
||||
PinContext = Pin->Context;
|
||||
|
||||
/* FIXME: determine controls and format urb */
|
||||
UsbBuildVendorRequest(Urb,
|
||||
URB_FUNCTION_CLASS_ENDPOINT,
|
||||
|
@ -144,14 +147,13 @@ UsbAudioSetFormat(
|
|||
0,
|
||||
0x01, // SET_CUR
|
||||
0x100,
|
||||
0x81, //FIXME bEndpointAddress
|
||||
PinContext->DeviceExtension->InterfaceInfo->Pipes[0].EndpointAddress,
|
||||
SampleRateBuffer,
|
||||
NULL,
|
||||
3,
|
||||
NULL);
|
||||
|
||||
/* get pin context */
|
||||
PinContext = Pin->Context;
|
||||
|
||||
|
||||
/* submit urb */
|
||||
Status = SubmitUrbSync(PinContext->LowerDevice, Urb);
|
||||
|
@ -164,13 +166,23 @@ UsbAudioSetFormat(
|
|||
|
||||
NTSTATUS
|
||||
USBAudioSelectAudioStreamingInterface(
|
||||
IN PKSPIN Pin,
|
||||
IN PPIN_CONTEXT PinContext,
|
||||
IN PDEVICE_EXTENSION DeviceExtension,
|
||||
IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor)
|
||||
IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor,
|
||||
IN ULONG FormatDescriptorIndex)
|
||||
{
|
||||
PURB Urb;
|
||||
PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor;
|
||||
NTSTATUS Status;
|
||||
ULONG Found, Index;
|
||||
|
||||
PUSB_AUDIO_STREAMING_INTERFACE_DESCRIPTOR StreamingInterfaceDescriptor;
|
||||
PUSB_AUDIO_CONTROL_INPUT_TERMINAL_DESCRIPTOR TerminalDescriptor = NULL;
|
||||
|
||||
/* search for terminal descriptor of that irp sink / irp source */
|
||||
TerminalDescriptor = UsbAudioGetStreamingTerminalDescriptorByIndex(DeviceExtension->ConfigurationDescriptor, Pin->Id);
|
||||
ASSERT(TerminalDescriptor != NULL);
|
||||
|
||||
/* grab interface descriptor */
|
||||
InterfaceDescriptor = USBD_ParseConfigurationDescriptorEx(ConfigurationDescriptor, ConfigurationDescriptor, -1, -1, USB_DEVICE_CLASS_AUDIO, -1, -1);
|
||||
|
@ -180,19 +192,37 @@ USBAudioSelectAudioStreamingInterface(
|
|||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
/* FIXME selects the first interface with audio streaming and non zero num of endpoints */
|
||||
Found = FALSE;
|
||||
Index = 0;
|
||||
|
||||
/* selects the interface which has an audio streaming interface descriptor associated to the input / output terminal at the given format index */
|
||||
while (InterfaceDescriptor != NULL)
|
||||
{
|
||||
if (InterfaceDescriptor->bInterfaceSubClass == 0x02 /* AUDIO_STREAMING */ && InterfaceDescriptor->bNumEndpoints > 0)
|
||||
{
|
||||
break;
|
||||
StreamingInterfaceDescriptor = (PUSB_AUDIO_STREAMING_INTERFACE_DESCRIPTOR)USBD_ParseDescriptors(ConfigurationDescriptor, ConfigurationDescriptor->wTotalLength, InterfaceDescriptor, USB_AUDIO_CONTROL_TERMINAL_DESCRIPTOR_TYPE);
|
||||
if (StreamingInterfaceDescriptor != NULL)
|
||||
{
|
||||
ASSERT(StreamingInterfaceDescriptor->bDescriptorSubtype == 0x01);
|
||||
ASSERT(StreamingInterfaceDescriptor->wFormatTag == WAVE_FORMAT_PCM);
|
||||
if (StreamingInterfaceDescriptor->bTerminalLink == TerminalDescriptor->bTerminalID)
|
||||
{
|
||||
if (FormatDescriptorIndex == Index)
|
||||
{
|
||||
Found = TRUE;
|
||||
break;
|
||||
}
|
||||
Index++;
|
||||
}
|
||||
}
|
||||
}
|
||||
InterfaceDescriptor = USBD_ParseConfigurationDescriptorEx(ConfigurationDescriptor, (PVOID)((ULONG_PTR)InterfaceDescriptor + InterfaceDescriptor->bLength), -1, -1, USB_DEVICE_CLASS_AUDIO, -1, -1);
|
||||
}
|
||||
|
||||
if (!InterfaceDescriptor)
|
||||
if (!Found)
|
||||
{
|
||||
/* no such interface */
|
||||
DPRINT1("No Interface found\n");
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
|
@ -200,7 +230,7 @@ USBAudioSelectAudioStreamingInterface(
|
|||
if (!Urb)
|
||||
{
|
||||
/* no memory */
|
||||
return USBD_STATUS_INSUFFICIENT_RESOURCES;
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
/* now prepare interface urb */
|
||||
|
@ -209,7 +239,7 @@ USBAudioSelectAudioStreamingInterface(
|
|||
/* now select the interface */
|
||||
Status = SubmitUrbSync(DeviceExtension->LowerDevice, Urb);
|
||||
|
||||
DPRINT1("USBAudioSelectAudioStreamingInterface Status %x UrbStatus %x\n", Status, Urb->UrbSelectInterface.Hdr.Status);
|
||||
DPRINT1("USBAudioSelectAudioStreamingInterface Status %x UrbStatus %x InterfaceNumber %x AlternateSetting %x\n", Status, Urb->UrbSelectInterface.Hdr.Status, InterfaceDescriptor->bInterfaceNumber, InterfaceDescriptor->bAlternateSetting);
|
||||
|
||||
/* did it succeeed */
|
||||
if (NT_SUCCESS(Status))
|
||||
|
@ -534,13 +564,55 @@ NTSTATUS
|
|||
InitStreamPin(
|
||||
IN PKSPIN Pin)
|
||||
{
|
||||
UNIMPLEMENTED
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
ULONG Index;
|
||||
PIRP Irp;
|
||||
PPIN_CONTEXT PinContext;
|
||||
PIO_STACK_LOCATION IoStack;
|
||||
|
||||
DPRINT1("InitStreamPin\n");
|
||||
|
||||
/* get pin context */
|
||||
PinContext = Pin->Context;
|
||||
|
||||
/* init irps */
|
||||
for (Index = 0; Index < 12; Index++)
|
||||
{
|
||||
/* allocate irp */
|
||||
Irp = AllocFunction(IoSizeOfIrp(PinContext->DeviceExtension->LowerDevice->StackSize));
|
||||
if (!Irp)
|
||||
{
|
||||
/* no memory */
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
DPRINT1("InitStreamPin Irp %p\n", Irp);
|
||||
|
||||
/* initialize irp */
|
||||
IoInitializeIrp(Irp, IoSizeOfIrp(PinContext->DeviceExtension->LowerDevice->StackSize), PinContext->DeviceExtension->LowerDevice->StackSize);
|
||||
|
||||
Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
|
||||
Irp->IoStatus.Information = 0;
|
||||
Irp->Flags = 0;
|
||||
Irp->UserBuffer = NULL;
|
||||
|
||||
IoStack = IoGetNextIrpStackLocation(Irp);
|
||||
IoStack->DeviceObject = PinContext->DeviceExtension->LowerDevice;
|
||||
IoStack->Parameters.Others.Argument2 = NULL;
|
||||
IoStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
|
||||
IoStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_SUBMIT_URB;
|
||||
|
||||
IoSetCompletionRoutine(Irp, UsbAudioRenderComplete, Pin, TRUE, TRUE, TRUE);
|
||||
|
||||
/* insert into irp list */
|
||||
InsertTailList(&PinContext->IrpListHead, &Irp->Tail.Overlay.ListEntry);
|
||||
|
||||
/* add to object bag*/
|
||||
KsAddItemToObjectBag(Pin->Bag, Irp, ExFreePool);
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
USBAudioPinCreate(
|
||||
|
@ -589,10 +661,12 @@ USBAudioPinCreate(
|
|||
}
|
||||
|
||||
/* select streaming interface */
|
||||
Status = USBAudioSelectAudioStreamingInterface(PinContext, PinContext->DeviceExtension, PinContext->DeviceExtension->ConfigurationDescriptor);
|
||||
/* FIXME choose correct dataformat */
|
||||
Status = USBAudioSelectAudioStreamingInterface(Pin, PinContext, PinContext->DeviceExtension, PinContext->DeviceExtension->ConfigurationDescriptor, 0);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
/* failed */
|
||||
DPRINT1("USBAudioSelectAudioStreamingInterface failed with %x\n", Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
@ -607,7 +681,7 @@ USBAudioPinCreate(
|
|||
Status = InitStreamPin(Pin);
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
|
@ -620,6 +694,52 @@ USBAudioPinClose(
|
|||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
UsbAudioRenderComplete(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp,
|
||||
IN PVOID Context)
|
||||
{
|
||||
PKSPIN Pin;
|
||||
PPIN_CONTEXT PinContext;
|
||||
KIRQL OldLevel;
|
||||
PKSSTREAM_POINTER StreamPointerClone;
|
||||
NTSTATUS Status;
|
||||
|
||||
/* get pin context */
|
||||
Pin = Context;
|
||||
PinContext = Pin->Context;
|
||||
|
||||
/* get status */
|
||||
Status = Irp->IoStatus.Status;
|
||||
|
||||
/* get streampointer */
|
||||
StreamPointerClone = Irp->Tail.Overlay.DriverContext[1];
|
||||
|
||||
/* acquire lock */
|
||||
KeAcquireSpinLock(&PinContext->IrpListLock, &OldLevel);
|
||||
|
||||
/* insert entry into ready list */
|
||||
InsertTailList(&PinContext->IrpListHead, &Irp->Tail.Overlay.ListEntry);
|
||||
|
||||
/* release lock */
|
||||
KeReleaseSpinLock(&PinContext->IrpListLock, OldLevel);
|
||||
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
/* set status code because it failed */
|
||||
//KsStreamPointerSetStatusCode(StreamPointerClone, STATUS_DEVICE_DATA_ERROR);
|
||||
DPRINT1("UsbAudioRenderComplete failed with %x\n", Status);
|
||||
}
|
||||
|
||||
/* lets delete the stream pointer clone */
|
||||
KsStreamPointerDelete(StreamPointerClone);
|
||||
|
||||
/* done */
|
||||
return STATUS_MORE_PROCESSING_REQUIRED;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
UsbAudioCaptureComplete(
|
||||
|
@ -669,6 +789,135 @@ UsbAudioCaptureComplete(
|
|||
return STATUS_MORE_PROCESSING_REQUIRED;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
PinRenderProcess(
|
||||
IN PKSPIN Pin)
|
||||
{
|
||||
PKSSTREAM_POINTER LeadingStreamPointer;
|
||||
PKSSTREAM_POINTER CloneStreamPointer;
|
||||
NTSTATUS Status;
|
||||
KIRQL OldLevel;
|
||||
PPIN_CONTEXT PinContext;
|
||||
PURB Urb;
|
||||
ULONG PacketCount, TotalPacketSize, Index;
|
||||
PKSDATAFORMAT_WAVEFORMATEX WaveFormatEx;
|
||||
PIO_STACK_LOCATION IoStack;
|
||||
PLIST_ENTRY CurEntry;
|
||||
PIRP Irp = NULL;
|
||||
|
||||
//DPRINT1("PinRenderProcess\n");
|
||||
|
||||
LeadingStreamPointer = KsPinGetLeadingEdgeStreamPointer(Pin, KSSTREAM_POINTER_STATE_LOCKED);
|
||||
if (LeadingStreamPointer == NULL)
|
||||
{
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
if (NULL == LeadingStreamPointer->StreamHeader->Data)
|
||||
{
|
||||
Status = KsStreamPointerAdvance(LeadingStreamPointer);
|
||||
DPRINT1("Advancing Streampointer\n");
|
||||
}
|
||||
|
||||
|
||||
/* get pin context */
|
||||
PinContext = Pin->Context;
|
||||
|
||||
/* acquire spin lock */
|
||||
KeAcquireSpinLock(&PinContext->IrpListLock, &OldLevel);
|
||||
|
||||
if (!IsListEmpty(&PinContext->IrpListHead))
|
||||
{
|
||||
/* remove entry from list */
|
||||
CurEntry = RemoveHeadList(&PinContext->IrpListHead);
|
||||
|
||||
/* get irp offset */
|
||||
Irp = (PIRP)CONTAINING_RECORD(CurEntry, IRP, Tail.Overlay.ListEntry);
|
||||
}
|
||||
|
||||
/* release lock */
|
||||
KeReleaseSpinLock(&PinContext->IrpListLock, OldLevel);
|
||||
|
||||
if (!Irp)
|
||||
{
|
||||
/* no irps available */
|
||||
DPRINT1("No irps available");
|
||||
KsStreamPointerUnlock(LeadingStreamPointer, TRUE);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/* clone stream pointer */
|
||||
Status = KsStreamPointerClone(LeadingStreamPointer, NULL, 0, &CloneStreamPointer);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
/* failed */
|
||||
KsStreamPointerUnlock(LeadingStreamPointer, TRUE);
|
||||
DPRINT1("Leaking Irp %p\n", Irp);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/* initialize irp */
|
||||
IoInitializeIrp(Irp, IoSizeOfIrp(PinContext->DeviceExtension->LowerDevice->StackSize), PinContext->DeviceExtension->LowerDevice->StackSize);
|
||||
|
||||
Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
|
||||
Irp->IoStatus.Information = 0;
|
||||
Irp->Flags = 0;
|
||||
Irp->UserBuffer = NULL;
|
||||
|
||||
IoStack = IoGetNextIrpStackLocation(Irp);
|
||||
IoStack->DeviceObject = PinContext->DeviceExtension->LowerDevice;
|
||||
IoStack->Parameters.Others.Argument2 = NULL;
|
||||
IoStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
|
||||
IoStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_SUBMIT_URB;
|
||||
|
||||
IoSetCompletionRoutine(Irp, UsbAudioRenderComplete, Pin, TRUE, TRUE, TRUE);
|
||||
|
||||
/* calculate packet count */
|
||||
WaveFormatEx = (PKSDATAFORMAT_WAVEFORMATEX)Pin->ConnectionFormat;
|
||||
TotalPacketSize = WaveFormatEx->WaveFormatEx.nAvgBytesPerSec / 1000;
|
||||
ASSERT(TotalPacketSize <= PinContext->DeviceExtension->InterfaceInfo->Pipes[0].MaximumPacketSize);
|
||||
|
||||
/* FIXME correct MaximumPacketSize ? */
|
||||
PacketCount = CloneStreamPointer->OffsetIn.Remaining / TotalPacketSize;
|
||||
|
||||
ASSERT(PacketCount < 255);
|
||||
|
||||
//DPRINT1("PinRenderProcess Irp %p TotalPacketSize %lu MaximumPacketSize %lu PacketCount %lu Count %lu Data %p\n", Irp, TotalPacketSize, PinContext->DeviceExtension->InterfaceInfo->Pipes[0].MaximumPacketSize, PacketCount, CloneStreamPointer->OffsetIn.Count, CloneStreamPointer->OffsetIn.Data);
|
||||
|
||||
Urb = (PURB)AllocFunction(GET_ISO_URB_SIZE(PacketCount));
|
||||
ASSERT(Urb);
|
||||
|
||||
/* init urb */
|
||||
Urb->UrbIsochronousTransfer.Hdr.Function = URB_FUNCTION_ISOCH_TRANSFER;
|
||||
Urb->UrbIsochronousTransfer.Hdr.Length = GET_ISO_URB_SIZE(PacketCount);
|
||||
Urb->UrbIsochronousTransfer.PipeHandle = PinContext->DeviceExtension->InterfaceInfo->Pipes[0].PipeHandle;
|
||||
Urb->UrbIsochronousTransfer.TransferFlags = USBD_TRANSFER_DIRECTION_OUT | USBD_START_ISO_TRANSFER_ASAP;
|
||||
Urb->UrbIsochronousTransfer.TransferBufferLength = CloneStreamPointer->OffsetIn.Remaining;
|
||||
Urb->UrbIsochronousTransfer.TransferBuffer = CloneStreamPointer->OffsetIn.Data;
|
||||
Urb->UrbIsochronousTransfer.NumberOfPackets = PacketCount;
|
||||
Urb->UrbIsochronousTransfer.StartFrame = 0;
|
||||
|
||||
for (Index = 0; Index < PacketCount; Index++)
|
||||
{
|
||||
Urb->UrbIsochronousTransfer.IsoPacket[Index].Offset = Index * TotalPacketSize;
|
||||
}
|
||||
|
||||
/* store urb */
|
||||
IoStack = IoGetNextIrpStackLocation(Irp);
|
||||
IoStack->Parameters.Others.Argument1 = Urb;
|
||||
|
||||
/* store in irp context */
|
||||
Irp->Tail.Overlay.DriverContext[0] = Urb;
|
||||
Irp->Tail.Overlay.DriverContext[1] = CloneStreamPointer;
|
||||
|
||||
Status = IoCallDriver(PinContext->LowerDevice, Irp);
|
||||
|
||||
/* unlock stream pointer and finish*/
|
||||
KsStreamPointerUnlock(LeadingStreamPointer, TRUE);
|
||||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
PinCaptureProcess(
|
||||
IN PKSPIN Pin)
|
||||
|
@ -830,8 +1079,7 @@ USBAudioPinProcess(
|
|||
}
|
||||
else
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
Status = STATUS_NOT_IMPLEMENTED;
|
||||
Status = PinRenderProcess(Pin);
|
||||
}
|
||||
|
||||
return Status;
|
||||
|
@ -914,7 +1162,7 @@ CapturePinStateChange(
|
|||
_In_ KSSTATE ToState,
|
||||
_In_ KSSTATE FromState)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
|
||||
if (FromState != ToState)
|
||||
{
|
||||
|
@ -957,7 +1205,7 @@ USBAudioPinSetDeviceState(
|
|||
else
|
||||
{
|
||||
UNIMPLEMENTED
|
||||
Status = STATUS_NOT_IMPLEMENTED;
|
||||
Status = STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
return Status;
|
||||
|
|
|
@ -203,6 +203,11 @@ NTAPI
|
|||
USBAudioCreateFilterContext(
|
||||
PKSDEVICE Device);
|
||||
|
||||
PUSB_AUDIO_CONTROL_INPUT_TERMINAL_DESCRIPTOR
|
||||
UsbAudioGetStreamingTerminalDescriptorByIndex(
|
||||
IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor,
|
||||
IN ULONG Index);
|
||||
|
||||
/* pool.c */
|
||||
PVOID
|
||||
NTAPI
|
||||
|
@ -342,6 +347,13 @@ UsbAudioCaptureComplete(
|
|||
IN PIRP Irp,
|
||||
IN PVOID Context);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
UsbAudioRenderComplete(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp,
|
||||
IN PVOID Context);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
USBAudioPinCreate(
|
||||
|
|
Loading…
Reference in a new issue