[USBAUDIO]

- edit allocator framing struct to match endpoint requirements
- implement partly PinCaptureProcess, not yet working

svn path=/trunk/; revision=72890
This commit is contained in:
Johannes Anderwald 2016-10-02 13:08:23 +00:00
parent 160d7c5b1e
commit 1cfbbff51a
2 changed files with 308 additions and 3 deletions

View file

@ -255,6 +255,7 @@ InitCapturePin(
PURB Urb;
PPIN_CONTEXT PinContext;
PIO_STACK_LOCATION IoStack;
PKSALLOCATOR_FRAMING_EX Framing;
/* set sample rate */
Status = UsbAudioSetFormat(Pin);
@ -267,8 +268,17 @@ InitCapturePin(
/* get pin context */
PinContext = Pin->Context;
/* lets get maximum packet size */
MaximumPacketSize = GetMaxPacketSizeForInterface(PinContext->DeviceExtension->ConfigurationDescriptor, PinContext->InterfaceDescriptor, Pin->DataFlow);
/* lets edit framing struct */
Framing = (PKSALLOCATOR_FRAMING_EX)Pin->Descriptor->AllocatorFraming;
Framing->FramingItem[0].PhysicalRange.MinFrameSize =
Framing->FramingItem[0].PhysicalRange.MaxFrameSize =
Framing->FramingItem[0].FramingRange.Range.MinFrameSize =
Framing->FramingItem[0].FramingRange.Range.MaxFrameSize =
MaximumPacketSize;
/* calculate buffer size 8 irps * 10 iso packets * max packet size */
BufferSize = 8 * 10 * MaximumPacketSize;
@ -292,6 +302,7 @@ InitCapturePin(
return STATUS_INSUFFICIENT_RESOURCES;
}
DPRINT1("InitCapturePin Irp %p\n", Irp);
/* insert into irp list */
InsertTailList(&PinContext->IrpListHead, &Irp->Tail.Overlay.ListEntry);
@ -312,6 +323,7 @@ InitCapturePin(
/* store urb */
IoStack->Parameters.Others.Argument1 = Urb;
Irp->Tail.Overlay.DriverContext[0] = Urb;
}
else
{
@ -364,10 +376,21 @@ USBAudioPinCreate(
PinContext->DeviceExtension = FilterContext->DeviceExtension;
PinContext->LowerDevice = FilterContext->LowerDevice;
InitializeListHead(&PinContext->IrpListHead);
InitializeListHead(&PinContext->DoneIrpListHead);
KeInitializeSpinLock(&PinContext->IrpListLock);
/* store pin context*/
Pin->Context = PinContext;
/* lets edit allocator framing struct */
Status = _KsEdit(Pin->Bag, &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);
ASSERT(Status == STATUS_SUCCESS);
}
/* select streaming interface */
Status = USBAudioSelectAudioStreamingInterface(PinContext, PinContext->DeviceExtension, PinContext->DeviceExtension->ConfigurationDescriptor);
if (!NT_SUCCESS(Status))
@ -400,13 +423,197 @@ USBAudioPinClose(
return STATUS_NOT_IMPLEMENTED;
}
NTSTATUS
NTAPI
UsbAudioCaptureComplete(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context)
{
PKSPIN Pin;
PPIN_CONTEXT PinContext;
KIRQL OldLevel;
/* get pin context */
Pin = Context;
PinContext = Pin->Context;
/* acquire lock */
KeAcquireSpinLock(&PinContext->IrpListLock, &OldLevel);
/* insert entry into done list */
InsertTailList(&PinContext->DoneIrpListHead, &Irp->Tail.Overlay.ListEntry);
/* release lock */
KeReleaseSpinLock(&PinContext->IrpListLock, OldLevel);
DPRINT1("UsbAudioCaptureComplete Irp %p\n", Irp);
/* done */
return STATUS_MORE_PROCESSING_REQUIRED;
}
NTSTATUS
PinCaptureProcess(
IN PKSPIN Pin)
{
PKSSTREAM_POINTER LeadingStreamPointer;
KIRQL OldLevel;
PPIN_CONTEXT PinContext;
PLIST_ENTRY CurEntry;
PIRP Irp;
PIO_STACK_LOCATION IoStack;
PURB Urb;
PUCHAR TransferBuffer;
ULONG Index, Offset;
LeadingStreamPointer = KsPinGetLeadingEdgeStreamPointer(Pin, KSSTREAM_POINTER_STATE_LOCKED);
if (LeadingStreamPointer == NULL)
return STATUS_SUCCESS;
/* get pin context */
PinContext = Pin->Context;
/* acquire spin lock */
KeAcquireSpinLock(&PinContext->IrpListLock, &OldLevel);
while (!IsListEmpty(&PinContext->DoneIrpListHead))
{
/* remove entry from list */
CurEntry = RemoveHeadList(&PinContext->DoneIrpListHead);
/* release lock */
KeReleaseSpinLock(&PinContext->IrpListLock, OldLevel);
/* get irp offset */
Irp = (PIRP)CONTAINING_RECORD(CurEntry, IRP, Tail.Overlay.ListEntry);
/* get urb from irp */
IoStack = IoGetNextIrpStackLocation(Irp);
Urb = (PURB)Irp->Tail.Overlay.DriverContext[0];
ASSERT(Urb);
Offset = 0;
for (Index = 0; Index < Urb->UrbIsochronousTransfer.NumberOfPackets; Index++)
{
/* add offset */
Offset += Urb->UrbIsochronousTransfer.IsoPacket[Index].Offset;
/* get transfer buffer */
TransferBuffer = Urb->UrbIsochronousTransfer.TransferBuffer;
/* copy data */
if (LeadingStreamPointer->OffsetOut.Remaining >= Urb->UrbIsochronousTransfer.IsoPacket[Index].Length)
{
/* copy buffer */
RtlCopyMemory((PUCHAR)LeadingStreamPointer->OffsetOut.Data, &TransferBuffer[Offset], Urb->UrbIsochronousTransfer.IsoPacket[Index].Length);
}
else
{
/* advance to next frame */
KsStreamPointerAdvanceOffsetsAndUnlock(LeadingStreamPointer, 0, 0, TRUE);
LeadingStreamPointer = KsPinGetLeadingEdgeStreamPointer(Pin, KSSTREAM_POINTER_STATE_LOCKED);
if (LeadingStreamPointer == NULL)
{
/* FIXME handle half processed packets */
//ASSERT(FALSE);
break;
}
ASSERT(LeadingStreamPointer->OffsetOut.Remaining >= Urb->UrbIsochronousTransfer.IsoPacket[Index].Length);
/* copy buffer */
RtlCopyMemory((PUCHAR)LeadingStreamPointer->OffsetOut.Data, &TransferBuffer[Offset], Urb->UrbIsochronousTransfer.IsoPacket[Index].Length);
}
if (LeadingStreamPointer->OffsetOut.Remaining == Urb->UrbIsochronousTransfer.IsoPacket[Index].Length)
{
KsStreamPointerAdvanceOffsetsAndUnlock(LeadingStreamPointer, 0, Urb->UrbIsochronousTransfer.IsoPacket[Index].Length, TRUE);
LeadingStreamPointer = KsPinGetLeadingEdgeStreamPointer(Pin, KSSTREAM_POINTER_STATE_LOCKED);
if (LeadingStreamPointer == NULL)
break;
}
else
{
KsStreamPointerAdvanceOffsets(LeadingStreamPointer, 0, Urb->UrbIsochronousTransfer.IsoPacket[Index].Length, FALSE);
}
}
/* acquire spin lock */
KeAcquireSpinLock(&PinContext->IrpListLock, &OldLevel);
/* get next stack location */
IoStack = IoGetNextIrpStackLocation(Irp);
/* init stack location */
IoStack->Parameters.Others.Argument1 = Urb;
IoStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
IoStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_SUBMIT_URB;
IoSetCompletionRoutine(Irp, UsbAudioCaptureComplete, Pin, TRUE, TRUE, TRUE);
InsertTailList(&PinContext->IrpListHead, &Irp->Tail.Overlay.ListEntry);
if (LeadingStreamPointer == NULL)
break;
}
while (!IsListEmpty(&PinContext->IrpListHead))
{
/* remove entry from list */
CurEntry = RemoveHeadList(&PinContext->IrpListHead);
/* 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;
IoSetCompletionRoutine(Irp, UsbAudioCaptureComplete, Pin, TRUE, TRUE, TRUE);
/* release lock */
KeReleaseSpinLock(&PinContext->IrpListLock, OldLevel);
DPRINT1("PinCaptureProcess Irp %p\n", Irp);
IoCallDriver(PinContext->DeviceExtension->LowerDevice, Irp);
/* acquire spin lock */
KeAcquireSpinLock(&PinContext->IrpListLock, &OldLevel);
}
/* release lock */
KeReleaseSpinLock(&PinContext->IrpListLock, OldLevel);
if (LeadingStreamPointer != NULL)
KsStreamPointerUnlock(LeadingStreamPointer, FALSE);
return STATUS_SUCCESS;
}
NTSTATUS
NTAPI
USBAudioPinProcess(
_In_ PKSPIN Pin)
{
return STATUS_SUCCESS;
NTSTATUS Status;
if (Pin->DataFlow == KSPIN_DATAFLOW_OUT)
{
Status = PinCaptureProcess(Pin);
}
else
{
UNIMPLEMENTED;
Status = STATUS_NOT_IMPLEMENTED;
}
return Status;
}
@ -437,6 +644,90 @@ USBAudioPinSetDataFormat(
return UsbAudioSetFormat(Pin);
}
NTSTATUS
StartCaptureIsocTransfer(
IN PKSPIN Pin)
{
PPIN_CONTEXT PinContext;
PLIST_ENTRY CurEntry;
PIRP Irp;
PIO_STACK_LOCATION IoStack;
NTSTATUS Status;
KIRQL OldLevel;
/* get pin context */
PinContext = Pin->Context;
/* acquire spin lock */
KeAcquireSpinLock(&PinContext->IrpListLock, &OldLevel);
while(!IsListEmpty(&PinContext->IrpListHead))
{
/* remove entry from list */
CurEntry = RemoveHeadList(&PinContext->IrpListHead);
/* 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;
IoSetCompletionRoutine(Irp, UsbAudioCaptureComplete, Pin, TRUE, TRUE, TRUE);
/* release lock */
KeReleaseSpinLock(&PinContext->IrpListLock, OldLevel);
DPRINT1("StartCaptureIsocTransfer Irp %p\n", Irp);
Status = IoCallDriver(PinContext->DeviceExtension->LowerDevice, Irp);
/* acquire spin lock */
KeAcquireSpinLock(&PinContext->IrpListLock, &OldLevel);
}
/* release lock */
KeReleaseSpinLock(&PinContext->IrpListLock, OldLevel);
return STATUS_SUCCESS;
}
NTSTATUS
CapturePinStateChange(
_In_ PKSPIN Pin,
_In_ KSSTATE ToState,
_In_ KSSTATE FromState)
{
NTSTATUS Status;
if (FromState != ToState)
{
if (ToState)
{
if (ToState == KSSTATE_PAUSE)
{
if (FromState == KSSTATE_RUN)
{
/* wait until pin processing is finished*/
}
}
else
{
if (ToState == KSSTATE_RUN)
{
Status = StartCaptureIsocTransfer(Pin);
}
}
}
}
return Status;
}
NTSTATUS
NTAPI
USBAudioPinSetDeviceState(
@ -444,6 +735,18 @@ USBAudioPinSetDeviceState(
_In_ KSSTATE ToState,
_In_ KSSTATE FromState)
{
UNIMPLEMENTED
return STATUS_SUCCESS;
NTSTATUS Status;
if (Pin->DataFlow == KSPIN_DATAFLOW_OUT)
{
/* handle capture state changes */
Status = CapturePinStateChange(Pin, ToState, FromState);
}
else
{
UNIMPLEMENTED
Status = STATUS_NOT_IMPLEMENTED;
}
return Status;
}

View file

@ -122,6 +122,8 @@ typedef struct
PDEVICE_EXTENSION DeviceExtension; /* device extension */
PDEVICE_OBJECT LowerDevice; /* lower device*/
LIST_ENTRY IrpListHead; /* irp list*/
LIST_ENTRY DoneIrpListHead; /* irp done list head */
KSPIN_LOCK IrpListLock; /* irp list lock*/
PUCHAR Buffer; /* iso buffer*/
ULONG BufferSize; /* iso buffer size */
PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor; /* interface descriptor */