[USBAUDIO]

- specify processings flags in filter descriptor
- implement processing workers
- move code for initializing irp & urb into single function
- usbaudio now successfully captures audio in win2k3.

svn path=/trunk/; revision=72969
This commit is contained in:
Johannes Anderwald 2016-10-14 10:35:19 +00:00
parent 25b64d3c35
commit 4b5428d521
3 changed files with 411 additions and 127 deletions

View file

@ -448,6 +448,9 @@ 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;

View file

@ -8,7 +8,9 @@
*/
#include "usbaudio.h"
#include <math.h>
#define PACKET_COUNT 10
NTSTATUS
GetMaxPacketSizeForInterface(
@ -55,15 +57,11 @@ UsbAudioAllocCaptureUrbIso(
OUT PURB * OutUrb)
{
PURB Urb;
ULONG PacketCount;
ULONG UrbSize;
ULONG Index;
/* calculate packet count */
PacketCount = BufferLength / MaxPacketSize;
/* calculate urb size*/
UrbSize = GET_ISO_URB_SIZE(PacketCount);
UrbSize = GET_ISO_URB_SIZE(PACKET_COUNT);
/* allocate urb */
Urb = AllocFunction(UrbSize);
@ -80,9 +78,9 @@ UsbAudioAllocCaptureUrbIso(
Urb->UrbIsochronousTransfer.TransferFlags = USBD_TRANSFER_DIRECTION_IN | USBD_START_ISO_TRANSFER_ASAP;
Urb->UrbIsochronousTransfer.TransferBufferLength = BufferLength;
Urb->UrbIsochronousTransfer.TransferBuffer = Buffer;
Urb->UrbIsochronousTransfer.NumberOfPackets = PacketCount;
Urb->UrbIsochronousTransfer.NumberOfPackets = PACKET_COUNT;
for (Index = 0; Index < PacketCount; Index++)
for (Index = 0; Index < PACKET_COUNT; Index++)
{
Urb->UrbIsochronousTransfer.IsoPacket[Index].Offset = Index * MaxPacketSize;
}
@ -92,7 +90,112 @@ UsbAudioAllocCaptureUrbIso(
}
NTSTATUS
UsbAudioSetMuteOff(
IN PKSPIN Pin)
{
PURB Urb;
PVOID SampleRateBuffer;
PPIN_CONTEXT PinContext;
NTSTATUS Status;
/* allocate sample rate buffer */
SampleRateBuffer = AllocFunction(sizeof(ULONG));
if (!SampleRateBuffer)
{
/* no memory */
return STATUS_INSUFFICIENT_RESOURCES;
}
/* allocate urb */
Urb = AllocFunction(sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST));
if (!Urb)
{
/* no memory */
FreeFunction(SampleRateBuffer);
return STATUS_INSUFFICIENT_RESOURCES;
}
/* FIXME: determine controls and format urb */
UsbBuildVendorRequest(Urb,
URB_FUNCTION_CLASS_INTERFACE,
sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST),
USBD_TRANSFER_DIRECTION_OUT,
0,
0x01,
0x100,
0x300,
SampleRateBuffer,
NULL,
1,
NULL);
/* get pin context */
PinContext = Pin->Context;
/* submit urb */
Status = SubmitUrbSync(PinContext->LowerDevice, Urb);
DPRINT1("UsbAudioSetMuteOff Pin %p Status %x\n", Pin, Status);
FreeFunction(Urb);
FreeFunction(SampleRateBuffer);
return Status;
}
NTSTATUS
UsbAudioSetVolume(
IN PKSPIN Pin)
{
PURB Urb;
PUCHAR SampleRateBuffer;
PPIN_CONTEXT PinContext;
NTSTATUS Status;
/* allocate sample rate buffer */
SampleRateBuffer = AllocFunction(sizeof(ULONG));
if (!SampleRateBuffer)
{
/* no memory */
return STATUS_INSUFFICIENT_RESOURCES;
}
/* allocate urb */
Urb = AllocFunction(sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST));
if (!Urb)
{
/* no memory */
FreeFunction(SampleRateBuffer);
return STATUS_INSUFFICIENT_RESOURCES;
}
/* FIXME: determine controls and format urb */
UsbBuildVendorRequest(Urb,
URB_FUNCTION_CLASS_INTERFACE,
sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST),
USBD_TRANSFER_DIRECTION_OUT,
0,
0x01,
0x200,
0x300,
SampleRateBuffer,
NULL,
2,
NULL);
/* get pin context */
PinContext = Pin->Context;
SampleRateBuffer[0] = 0xC2;
SampleRateBuffer[1] = 0xFE;
/* submit urb */
Status = SubmitUrbSync(PinContext->LowerDevice, Urb);
DPRINT1("UsbAudioSetVolume Pin %p Status %x\n", Pin, Status);
FreeFunction(Urb);
FreeFunction(SampleRateBuffer);
return Status;
}
NTSTATUS
UsbAudioSetFormat(
@ -140,13 +243,13 @@ UsbAudioSetFormat(
return STATUS_INSUFFICIENT_RESOURCES;
}
/* format urb */
/* FIXME: determine controls and format urb */
UsbBuildVendorRequest(Urb,
URB_FUNCTION_CLASS_ENDPOINT,
sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST),
USBD_TRANSFER_DIRECTION_OUT,
0,
0x01,
0x01, // SET_CUR
0x100,
0x81, //FIXME bEndpointAddress
SampleRateBuffer,
@ -244,6 +347,156 @@ USBAudioSelectAudioStreamingInterface(
return Status;
}
VOID
NTAPI
CaptureGateOnWorkItem(
_In_ PVOID Context)
{
PKSPIN Pin;
PPIN_CONTEXT PinContext;
PKSGATE Gate;
ULONG Count;
/* get pin */
Pin = Context;
/* get pin context */
PinContext = Pin->Context;
do
{
/* acquire processing mutex */
KsPinAcquireProcessingMutex(Pin);
/* get pin control gate */
Gate = KsPinGetAndGate(Pin);
/* turn input on */
KsGateTurnInputOn(Gate);
/* schedule processing */
KsPinAttemptProcessing(Pin, TRUE);
/* release processing mutex */
KsPinReleaseProcessingMutex(Pin);
/* decrement worker count */
Count = KsDecrementCountedWorker(PinContext->CaptureWorker);
} while (Count);
}
VOID
CaptureInitializeUrbAndIrp(
IN PKSPIN Pin,
IN PIRP Irp)
{
PIO_STACK_LOCATION IoStack;
PURB Urb;
PUCHAR TransferBuffer;
ULONG Index;
PPIN_CONTEXT PinContext;
/* get pin context */
PinContext = Pin->Context;
/* backup urb and transferbuffer */
Urb = Irp->Tail.Overlay.DriverContext[0];
TransferBuffer = Urb->UrbIsochronousTransfer.TransferBuffer;
/* 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;
Irp->Tail.Overlay.DriverContext[0] = Urb;
Irp->Tail.Overlay.DriverContext[1] = NULL;
/* init stack location */
IoStack = IoGetNextIrpStackLocation(Irp);
IoStack->DeviceObject = PinContext->DeviceExtension->LowerDevice;
IoStack->Parameters.Others.Argument1 = Urb;
IoStack->Parameters.Others.Argument2 = NULL;
IoStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
IoStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_SUBMIT_URB;
IoSetCompletionRoutine(Irp, UsbAudioCaptureComplete, Pin, TRUE, TRUE, TRUE);
RtlZeroMemory(Urb, GET_ISO_URB_SIZE(PACKET_COUNT));
/* init urb */
Urb->UrbIsochronousTransfer.Hdr.Function = URB_FUNCTION_ISOCH_TRANSFER;
Urb->UrbIsochronousTransfer.Hdr.Length = GET_ISO_URB_SIZE(10);
Urb->UrbIsochronousTransfer.PipeHandle = PinContext->DeviceExtension->InterfaceInfo->Pipes[0].PipeHandle;
Urb->UrbIsochronousTransfer.TransferFlags = USBD_TRANSFER_DIRECTION_IN | USBD_START_ISO_TRANSFER_ASAP;
Urb->UrbIsochronousTransfer.TransferBufferLength = PinContext->DeviceExtension->InterfaceInfo->Pipes[0].MaximumPacketSize * 10;
Urb->UrbIsochronousTransfer.TransferBuffer = TransferBuffer;
Urb->UrbIsochronousTransfer.NumberOfPackets = PACKET_COUNT;
Urb->UrbIsochronousTransfer.StartFrame = 0;
for (Index = 0; Index < PACKET_COUNT; Index++)
{
Urb->UrbIsochronousTransfer.IsoPacket[Index].Offset = Index * PinContext->DeviceExtension->InterfaceInfo->Pipes[0].MaximumPacketSize;
}
}
VOID
NTAPI
CaptureAvoidPipeStarvationWorker(
_In_ PVOID Context)
{
PKSPIN Pin;
PPIN_CONTEXT PinContext;
KIRQL OldLevel;
PLIST_ENTRY CurEntry;
PIRP Irp;
/* get pin */
Pin = Context;
/* get pin context */
PinContext = Pin->Context;
/* acquire spin lock */
KeAcquireSpinLock(&PinContext->IrpListLock, &OldLevel);
if (!IsListEmpty(&PinContext->IrpListHead))
{
/* sanity check */
ASSERT(!IsListEmpty(&PinContext->IrpListHead));
/* remove entry from list */
CurEntry = RemoveHeadList(&PinContext->IrpListHead);
/* release lock */
KeReleaseSpinLock(&PinContext->IrpListLock, OldLevel);
/* get irp offset */
Irp = (PIRP)CONTAINING_RECORD(CurEntry, IRP, Tail.Overlay.ListEntry);
/* reinitialize irp and urb */
CaptureInitializeUrbAndIrp(Pin, Irp);
KsDecrementCountedWorker(PinContext->StarvationWorker);
/* call driver */
IoCallDriver(PinContext->DeviceExtension->LowerDevice, Irp);
}
else
{
/* release lock */
KeReleaseSpinLock(&PinContext->IrpListLock, OldLevel);
KsDecrementCountedWorker(PinContext->StarvationWorker);
}
}
NTSTATUS
InitCapturePin(
IN PKSPIN Pin)
@ -257,6 +510,8 @@ InitCapturePin(
PPIN_CONTEXT PinContext;
PIO_STACK_LOCATION IoStack;
PKSALLOCATOR_FRAMING_EX Framing;
PKSGATE Gate;
/* set sample rate */
Status = UsbAudioSetFormat(Pin);
@ -272,6 +527,28 @@ InitCapturePin(
/* lets get maximum packet size */
MaximumPacketSize = GetMaxPacketSizeForInterface(PinContext->DeviceExtension->ConfigurationDescriptor, PinContext->InterfaceDescriptor, Pin->DataFlow);
/* initialize work item for capture worker */
ExInitializeWorkItem(&PinContext->CaptureWorkItem, CaptureGateOnWorkItem, (PVOID)Pin);
/* register worker */
Status = KsRegisterCountedWorker(CriticalWorkQueue, &PinContext->CaptureWorkItem, &PinContext->CaptureWorker);
if (!NT_SUCCESS(Status))
{
/* failed */
return Status;
}
/* initialize work item */
ExInitializeWorkItem(&PinContext->StarvationWorkItem, CaptureAvoidPipeStarvationWorker, (PVOID)Pin);
/* register worker */
Status = KsRegisterCountedWorker(CriticalWorkQueue, &PinContext->StarvationWorkItem, &PinContext->StarvationWorker);
if (!NT_SUCCESS(Status))
{
/* failed */
KsUnregisterWorker(PinContext->CaptureWorker);
}
/* lets edit framing struct */
Framing = (PKSALLOCATOR_FRAMING_EX)Pin->Descriptor->AllocatorFraming;
Framing->FramingItem[0].PhysicalRange.MinFrameSize =
@ -281,7 +558,7 @@ InitCapturePin(
MaximumPacketSize;
/* calculate buffer size 8 irps * 10 iso packets * max packet size */
BufferSize = 8 * 10 * MaximumPacketSize;
BufferSize = 8 * PACKET_COUNT * MaximumPacketSize;
/* allocate pin capture buffer */
PinContext->BufferSize = BufferSize;
@ -318,21 +595,23 @@ InitCapturePin(
IoStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
IoStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_SUBMIT_URB;
DPRINT1("InitCapturePin Irp %p\n", Irp);
IoSetCompletionRoutine(Irp, UsbAudioCaptureComplete, Pin, TRUE, TRUE, TRUE);
/* insert into irp list */
InsertTailList(&PinContext->IrpListHead, &Irp->Tail.Overlay.ListEntry);
/* add to object bag*/
KsAddItemToObjectBag(Pin->Bag, Irp, IoFreeIrp);
KsAddItemToObjectBag(Pin->Bag, Irp, ExFreePool);
/* FIXME select correct pipe handle */
Status = UsbAudioAllocCaptureUrbIso(PinContext->DeviceExtension->InterfaceInfo->Pipes[0].PipeHandle,
MaximumPacketSize,
&PinContext->Buffer[MaximumPacketSize * 10 * Index],
MaximumPacketSize * 10,
&PinContext->Buffer[MaximumPacketSize * PACKET_COUNT * Index],
MaximumPacketSize * PACKET_COUNT,
&Urb);
DPRINT1("InitCapturePin Irp %p Urb %p\n", Irp, Urb);
if (NT_SUCCESS(Status))
{
/* get next stack location */
@ -348,6 +627,13 @@ InitCapturePin(
return Status;
}
}
/* get process control gate */
Gate = KsPinGetAndGate(Pin);
/* turn input off */
KsGateTurnInputOff(Gate);
return Status;
}
@ -360,6 +646,8 @@ InitStreamPin(
}
NTSTATUS
NTAPI
USBAudioPinCreate(
@ -400,13 +688,16 @@ USBAudioPinCreate(
Pin->Context = PinContext;
/* lets edit allocator framing struct */
Status = _KsEdit(Pin->Bag, &Pin->Descriptor, sizeof(KSPIN_DESCRIPTOR_EX), sizeof(KSPIN_DESCRIPTOR_EX), USBAUDIO_TAG);
Status = _KsEdit(Pin->Bag, (PVOID*)&Pin->Descriptor, sizeof(KSPIN_DESCRIPTOR_EX), sizeof(KSPIN_DESCRIPTOR_EX), USBAUDIO_TAG);
if (NT_SUCCESS(Status))
{
Status = _KsEdit(Pin->Bag, &Pin->Descriptor->AllocatorFraming, sizeof(KSALLOCATOR_FRAMING_EX), sizeof(KSALLOCATOR_FRAMING_EX), USBAUDIO_TAG);
Status = _KsEdit(Pin->Bag, (PVOID*)&Pin->Descriptor->AllocatorFraming, sizeof(KSALLOCATOR_FRAMING_EX), sizeof(KSALLOCATOR_FRAMING_EX), USBAUDIO_TAG);
ASSERT(Status == STATUS_SUCCESS);
}
/* FIXME move to build filter topology*/
UsbAudioSetMuteOff(Pin);
UsbAudioSetVolume(Pin);
/* select streaming interface */
Status = USBAudioSelectAudioStreamingInterface(PinContext, PinContext->DeviceExtension, PinContext->DeviceExtension->ConfigurationDescriptor);
@ -451,29 +742,39 @@ UsbAudioCaptureComplete(
PPIN_CONTEXT PinContext;
KIRQL OldLevel;
PURB Urb;
PIO_STACK_LOCATION IoStack;
/* get pin context */
Pin = Context;
PinContext = Pin->Context;
/* get stack location */
IoStack = IoGetNextIrpStackLocation(Irp);
/* get urb */
Urb = Irp->Tail.Overlay.DriverContext[0];
//DPRINT("UsbAudioCaptureComplete Irp %p Urb %p\n", Irp, Urb);
/* acquire lock */
KeAcquireSpinLock(&PinContext->IrpListLock, &OldLevel);
/* insert entry into done list */
InsertTailList(&PinContext->DoneIrpListHead, &Irp->Tail.Overlay.ListEntry);
if (!NT_SUCCESS(Urb->UrbIsochronousTransfer.Hdr.Status))
{
//DPRINT("UsbAudioCaptureComplete Irp %p Urb %p Status %x Packet Status %x\n", Irp, Urb, Urb->UrbIsochronousTransfer.Hdr.Status, Urb->UrbIsochronousTransfer.IsoPacket[0].Status);
/* release lock */
KeReleaseSpinLock(&PinContext->IrpListLock, OldLevel);
/* insert entry into ready list */
InsertTailList(&PinContext->IrpListHead, &Irp->Tail.Overlay.ListEntry);
/* release lock */
KeReleaseSpinLock(&PinContext->IrpListLock, OldLevel);
KsIncrementCountedWorker(PinContext->StarvationWorker);
}
else
{
/* insert entry into done list */
InsertTailList(&PinContext->DoneIrpListHead, &Irp->Tail.Overlay.ListEntry);
/* release lock */
KeReleaseSpinLock(&PinContext->IrpListLock, OldLevel);
KsIncrementCountedWorker(PinContext->CaptureWorker);
}
/* done */
return STATUS_MORE_PROCESSING_REQUIRED;
@ -491,13 +792,22 @@ PinCaptureProcess(
PIO_STACK_LOCATION IoStack;
PURB Urb;
PUCHAR TransferBuffer, OutBuffer;
ULONG Index, Offset, MaximumPacketSize, Length;
ULONG Offset, Length;
NTSTATUS Status;
//PUSHORT SoundBuffer;
PKSGATE Gate;
//DPRINT1("PinCaptureProcess\n");
LeadingStreamPointer = KsPinGetLeadingEdgeStreamPointer(Pin, KSSTREAM_POINTER_STATE_LOCKED);
if (LeadingStreamPointer == NULL)
{
/* get process control gate */
Gate = KsPinGetAndGate(Pin);
/* shutdown processing */
KsGateTurnInputOff(Gate);
return STATUS_SUCCESS;
}
/* get pin context */
PinContext = Pin->Context;
@ -521,61 +831,65 @@ PinCaptureProcess(
Urb = (PURB)Irp->Tail.Overlay.DriverContext[0];
ASSERT(Urb);
Offset = 0;
for (Index = 0; Index < Urb->UrbIsochronousTransfer.NumberOfPackets; Index++)
Offset = PtrToUlong(Irp->Tail.Overlay.DriverContext[1]);
/* get transfer buffer */
TransferBuffer = Urb->UrbIsochronousTransfer.TransferBuffer;
/* get target buffer */
OutBuffer = (PUCHAR)LeadingStreamPointer->StreamHeader->Data;
/* calculate length */
Length = min(LeadingStreamPointer->OffsetOut.Count - LeadingStreamPointer->StreamHeader->DataUsed, Urb->UrbIsochronousTransfer.TransferBufferLength - Offset);
/* FIXME copy each packet extra */
/* copy audio bytes */
RtlCopyMemory((PUCHAR)&OutBuffer[LeadingStreamPointer->StreamHeader->DataUsed], &TransferBuffer[Offset], Length);
//DPRINT1("Irp %p Urb %p OutBuffer %p TransferBuffer %p Offset %lu Remaining %lu TransferBufferLength %lu Length %lu\n", Irp, Urb, OutBuffer, TransferBuffer, Offset, LeadingStreamPointer->OffsetOut.Remaining, Urb->UrbIsochronousTransfer.TransferBufferLength, Length);
/* adjust streampointer */
LeadingStreamPointer->StreamHeader->DataUsed += Length;
if (Length == LeadingStreamPointer->OffsetOut.Remaining)
{
/* add offset */
Offset += Urb->UrbIsochronousTransfer.IsoPacket[Index].Offset;
KsStreamPointerAdvanceOffsetsAndUnlock(LeadingStreamPointer, 0, Length, TRUE);
/* get transfer buffer */
TransferBuffer = Urb->UrbIsochronousTransfer.TransferBuffer;
/* acquire spin lock */
KeAcquireSpinLock(&PinContext->IrpListLock, &OldLevel);
/* get target buffer */
OutBuffer = (PUCHAR)LeadingStreamPointer->StreamHeader->Data;
/* adjust offset */
Irp->Tail.Overlay.DriverContext[1] = UlongToPtr(Length);
/* calculate length */
Length = min(LeadingStreamPointer->OffsetOut.Count - LeadingStreamPointer->StreamHeader->DataUsed, Urb->UrbIsochronousTransfer.IsoPacket[Index].Length);
/* reinsert into processed list */
InsertHeadList(&PinContext->DoneIrpListHead, &Irp->Tail.Overlay.ListEntry);
//DPRINT1("DataUsed %lu Count %lu Remaining %lu Copying %lu Data %p\n", LeadingStreamPointer->StreamHeader->DataUsed, LeadingStreamPointer->OffsetOut.Count, LeadingStreamPointer->OffsetOut.Remaining, Length, LeadingStreamPointer->OffsetOut.Data);
/* release lock */
KeReleaseSpinLock(&PinContext->IrpListLock, OldLevel);
/* copy buffer */
RtlCopyMemory((PUCHAR)&OutBuffer[LeadingStreamPointer->StreamHeader->DataUsed], &TransferBuffer[Offset], Length);
LeadingStreamPointer->StreamHeader->DataUsed += Length;
if (Length == LeadingStreamPointer->OffsetOut.Remaining) {
KsStreamPointerAdvanceOffsetsAndUnlock(LeadingStreamPointer, 0, Length, TRUE);
LeadingStreamPointer = KsPinGetLeadingEdgeStreamPointer(Pin, KSSTREAM_POINTER_STATE_LOCKED);
if (LeadingStreamPointer == NULL)
{
/* FIXME handle half processed packets */
//ASSERT(FALSE);
//DPRINT1("Warning: ignoring %lu packets\n", Urb->UrbIsochronousTransfer.NumberOfPackets - Index);
/* acquire spin lock */
KeAcquireSpinLock(&PinContext->IrpListLock, &OldLevel);
InsertTailList(&PinContext->IrpListHead, &Irp->Tail.Overlay.ListEntry);
KeReleaseSpinLock(&PinContext->IrpListLock, OldLevel);
return STATUS_SUCCESS;
}
LeadingStreamPointer = KsPinGetLeadingEdgeStreamPointer(Pin, KSSTREAM_POINTER_STATE_LOCKED);
if (LeadingStreamPointer == NULL)
{
/* no more work to be done*/
return STATUS_PENDING;
}
else
{
Status = KsStreamPointerAdvanceOffsets(LeadingStreamPointer, 0, Length, FALSE);
/* resume work on this irp */
continue;
}
}
else
{
Status = KsStreamPointerAdvanceOffsets(LeadingStreamPointer, 0, Length, FALSE);
ASSERT(Length == Urb->UrbIsochronousTransfer.TransferBufferLength - Offset);
}
/* acquire spin lock */
KeAcquireSpinLock(&PinContext->IrpListLock, &OldLevel);
InsertTailList(&PinContext->IrpListHead, &Irp->Tail.Overlay.ListEntry);
if (LeadingStreamPointer == NULL)
break;
}
while (!IsListEmpty(&PinContext->IrpListHead))
@ -589,44 +903,8 @@ PinCaptureProcess(
/* get irp offset */
Irp = (PIRP)CONTAINING_RECORD(CurEntry, IRP, Tail.Overlay.ListEntry);
/* backup urb and transferbuffer */
Urb = Irp->Tail.Overlay.DriverContext[0];
TransferBuffer = Urb->UrbIsochronousTransfer.TransferBuffer;
/* 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;
Irp->Tail.Overlay.DriverContext[0] = Urb;
/* init stack location */
IoStack = IoGetNextIrpStackLocation(Irp);
IoStack->DeviceObject = PinContext->DeviceExtension->LowerDevice;
IoStack->Parameters.Others.Argument1 = Urb;
IoStack->Parameters.Others.Argument2 = NULL;
IoStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
IoStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_SUBMIT_URB;
IoSetCompletionRoutine(Irp, UsbAudioCaptureComplete, Pin, TRUE, TRUE, TRUE);
RtlZeroMemory(Urb, GET_ISO_URB_SIZE(10));
/* init urb */
Urb->UrbIsochronousTransfer.Hdr.Function = URB_FUNCTION_ISOCH_TRANSFER;
Urb->UrbIsochronousTransfer.Hdr.Length = GET_ISO_URB_SIZE(10);
Urb->UrbIsochronousTransfer.PipeHandle = PinContext->DeviceExtension->InterfaceInfo->Pipes[0].PipeHandle;
Urb->UrbIsochronousTransfer.TransferFlags = USBD_TRANSFER_DIRECTION_IN | USBD_START_ISO_TRANSFER_ASAP;
Urb->UrbIsochronousTransfer.TransferBufferLength = PinContext->DeviceExtension->InterfaceInfo->Pipes[0].MaximumPacketSize * 10;
Urb->UrbIsochronousTransfer.TransferBuffer = TransferBuffer;
Urb->UrbIsochronousTransfer.NumberOfPackets = 10;
for (Index = 0; Index < 10; Index++)
{
Urb->UrbIsochronousTransfer.IsoPacket[Index].Offset = Index * 100;
}
/* reinitialize irp and urb */
CaptureInitializeUrbAndIrp(Pin, Irp);
IoCallDriver(PinContext->DeviceExtension->LowerDevice, Irp);
@ -641,7 +919,13 @@ PinCaptureProcess(
if (LeadingStreamPointer != NULL)
KsStreamPointerUnlock(LeadingStreamPointer, FALSE);
return STATUS_SUCCESS;
/* get process control gate */
Gate = KsPinGetAndGate(Pin);
/* shutdown processing */
KsGateTurnInputOff(Gate);
return STATUS_PENDING;
}
@ -700,9 +984,6 @@ StartCaptureIsocTransfer(
PPIN_CONTEXT PinContext;
PLIST_ENTRY CurEntry;
PIRP Irp;
PURB Urb;
PIO_STACK_LOCATION IoStack;
NTSTATUS Status;
KIRQL OldLevel;
/* get pin context */
@ -719,24 +1000,14 @@ StartCaptureIsocTransfer(
/* get irp offset */
Irp = (PIRP)CONTAINING_RECORD(CurEntry, IRP, Tail.Overlay.ListEntry);
/* get next stack location */
IoStack = IoGetNextIrpStackLocation(Irp);
/* init stack location */
IoStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
IoStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_SUBMIT_URB;
/* backup urb */
Urb = Irp->Tail.Overlay.DriverContext[0] = IoStack->Parameters.Others.Argument1;
IoSetCompletionRoutine(Irp, UsbAudioCaptureComplete, Pin, TRUE, TRUE, TRUE);
/* release lock */
KeReleaseSpinLock(&PinContext->IrpListLock, OldLevel);
DPRINT("StartCaptureIsocTransfer Irp %p Urb %p TransferBuffer %p\n", Irp, Urb, Urb->UrbIsochronousTransfer.TransferBuffer);
Status = IoCallDriver(PinContext->DeviceExtension->LowerDevice, Irp);
/* reinitialize irp and urb */
CaptureInitializeUrbAndIrp(Pin, Irp);
DPRINT("StartCaptureIsocTransfer Irp %p\n", Irp);
IoCallDriver(PinContext->DeviceExtension->LowerDevice, Irp);
/* acquire spin lock */
KeAcquireSpinLock(&PinContext->IrpListLock, &OldLevel);

View file

@ -127,7 +127,10 @@ typedef struct
PUCHAR Buffer; /* iso buffer*/
ULONG BufferSize; /* iso buffer size */
PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor; /* interface descriptor */
WORK_QUEUE_ITEM CaptureWorkItem; /* work item */
PKSWORKER CaptureWorker; /* capture worker */
WORK_QUEUE_ITEM StarvationWorkItem; /* work item */
PKSWORKER StarvationWorker; /* capture worker */
}PIN_CONTEXT, *PPIN_CONTEXT;
/* filter.c */
@ -250,6 +253,13 @@ USBAudioPnPSetPower(
/* pin.c*/
NTSTATUS
NTAPI
UsbAudioCaptureComplete(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context);
NTSTATUS
NTAPI
USBAudioPinCreate(