From 1cfbbff51a446468bbdfeb5ba3d2937f11c7fa39 Mon Sep 17 00:00:00 2001 From: Johannes Anderwald Date: Sun, 2 Oct 2016 13:08:23 +0000 Subject: [PATCH] [USBAUDIO] - edit allocator framing struct to match endpoint requirements - implement partly PinCaptureProcess, not yet working svn path=/trunk/; revision=72890 --- reactos/drivers/usb/usbaudio/pin.c | 309 +++++++++++++++++++++++- reactos/drivers/usb/usbaudio/usbaudio.h | 2 + 2 files changed, 308 insertions(+), 3 deletions(-) diff --git a/reactos/drivers/usb/usbaudio/pin.c b/reactos/drivers/usb/usbaudio/pin.c index c0a05d4ef64..c4a034d604c 100644 --- a/reactos/drivers/usb/usbaudio/pin.c +++ b/reactos/drivers/usb/usbaudio/pin.c @@ -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; } diff --git a/reactos/drivers/usb/usbaudio/usbaudio.h b/reactos/drivers/usb/usbaudio/usbaudio.h index 41daedef8ca..813ac59ffd4 100644 --- a/reactos/drivers/usb/usbaudio/usbaudio.h +++ b/reactos/drivers/usb/usbaudio/usbaudio.h @@ -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 */ -- 2.17.1