2 * PROJECT: ReactOS Universal Audio Class Driver
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: drivers/usb/usbaudio/pin.c
5 * PURPOSE: USB Audio device driver.
7 * Johannes Anderwald (johannes.anderwald@reactos.org)
12 #define PACKET_COUNT 10
16 GetMaxPacketSizeForInterface(
17 IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor
,
18 IN PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor
,
19 KSPIN_DATAFLOW DataFlow
)
21 PUSB_COMMON_DESCRIPTOR CommonDescriptor
;
22 PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor
;
24 /* loop descriptors */
25 CommonDescriptor
= (PUSB_COMMON_DESCRIPTOR
)((ULONG_PTR
)InterfaceDescriptor
+ InterfaceDescriptor
->bLength
);
26 ASSERT(InterfaceDescriptor
->bNumEndpoints
> 0);
27 while (CommonDescriptor
)
29 if (CommonDescriptor
->bDescriptorType
== USB_ENDPOINT_DESCRIPTOR_TYPE
)
31 EndpointDescriptor
= (PUSB_ENDPOINT_DESCRIPTOR
)CommonDescriptor
;
32 return EndpointDescriptor
->wMaxPacketSize
;
35 if (CommonDescriptor
->bDescriptorType
== USB_INTERFACE_DESCRIPTOR_TYPE
)
37 /* reached next interface descriptor */
41 if ((ULONG_PTR
)CommonDescriptor
+ CommonDescriptor
->bLength
>= ((ULONG_PTR
)ConfigurationDescriptor
+ ConfigurationDescriptor
->wTotalLength
))
44 CommonDescriptor
= (PUSB_COMMON_DESCRIPTOR
)((ULONG_PTR
)CommonDescriptor
+ CommonDescriptor
->bLength
);
52 UsbAudioAllocCaptureUrbIso(
53 IN USBD_PIPE_HANDLE PipeHandle
,
54 IN ULONG MaxPacketSize
,
56 IN ULONG BufferLength
,
63 /* calculate urb size*/
64 UrbSize
= GET_ISO_URB_SIZE(PACKET_COUNT
);
67 Urb
= AllocFunction(UrbSize
);
71 return STATUS_INSUFFICIENT_RESOURCES
;
75 Urb
->UrbIsochronousTransfer
.Hdr
.Function
= URB_FUNCTION_ISOCH_TRANSFER
;
76 Urb
->UrbIsochronousTransfer
.Hdr
.Length
= UrbSize
;
77 Urb
->UrbIsochronousTransfer
.PipeHandle
= PipeHandle
;
78 Urb
->UrbIsochronousTransfer
.TransferFlags
= USBD_TRANSFER_DIRECTION_IN
| USBD_START_ISO_TRANSFER_ASAP
;
79 Urb
->UrbIsochronousTransfer
.TransferBufferLength
= BufferLength
;
80 Urb
->UrbIsochronousTransfer
.TransferBuffer
= Buffer
;
81 Urb
->UrbIsochronousTransfer
.NumberOfPackets
= PACKET_COUNT
;
83 for (Index
= 0; Index
< PACKET_COUNT
; Index
++)
85 Urb
->UrbIsochronousTransfer
.IsoPacket
[Index
].Offset
= Index
* MaxPacketSize
;
89 return STATUS_SUCCESS
;
98 PVOID SampleRateBuffer
;
99 PPIN_CONTEXT PinContext
;
102 /* allocate sample rate buffer */
103 SampleRateBuffer
= AllocFunction(sizeof(ULONG
));
104 if (!SampleRateBuffer
)
107 return STATUS_INSUFFICIENT_RESOURCES
;
111 Urb
= AllocFunction(sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST
));
115 FreeFunction(SampleRateBuffer
);
116 return STATUS_INSUFFICIENT_RESOURCES
;
119 /* FIXME: determine controls and format urb */
120 UsbBuildVendorRequest(Urb
,
121 URB_FUNCTION_CLASS_INTERFACE
,
122 sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST
),
123 USBD_TRANSFER_DIRECTION_OUT
,
133 /* get pin context */
134 PinContext
= Pin
->Context
;
137 Status
= SubmitUrbSync(PinContext
->LowerDevice
, Urb
);
139 DPRINT1("UsbAudioSetMuteOff Pin %p Status %x\n", Pin
, Status
);
141 FreeFunction(SampleRateBuffer
);
150 PUCHAR SampleRateBuffer
;
151 PPIN_CONTEXT PinContext
;
154 /* allocate sample rate buffer */
155 SampleRateBuffer
= AllocFunction(sizeof(ULONG
));
156 if (!SampleRateBuffer
)
159 return STATUS_INSUFFICIENT_RESOURCES
;
163 Urb
= AllocFunction(sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST
));
167 FreeFunction(SampleRateBuffer
);
168 return STATUS_INSUFFICIENT_RESOURCES
;
171 /* FIXME: determine controls and format urb */
172 UsbBuildVendorRequest(Urb
,
173 URB_FUNCTION_CLASS_INTERFACE
,
174 sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST
),
175 USBD_TRANSFER_DIRECTION_OUT
,
185 /* get pin context */
186 PinContext
= Pin
->Context
;
188 SampleRateBuffer
[0] = 0xC2;
189 SampleRateBuffer
[1] = 0xFE;
192 Status
= SubmitUrbSync(PinContext
->LowerDevice
, Urb
);
194 DPRINT1("UsbAudioSetVolume Pin %p Status %x\n", Pin
, Status
);
196 FreeFunction(SampleRateBuffer
);
205 PUCHAR SampleRateBuffer
;
206 PPIN_CONTEXT PinContext
;
208 PKSDATAFORMAT_WAVEFORMATEX WaveFormatEx
;
210 /* allocate sample rate buffer */
211 SampleRateBuffer
= AllocFunction(sizeof(ULONG
));
212 if (!SampleRateBuffer
)
215 return STATUS_INSUFFICIENT_RESOURCES
;
218 if (IsEqualGUIDAligned(&Pin
->ConnectionFormat
->MajorFormat
, &KSDATAFORMAT_TYPE_AUDIO
) &&
219 IsEqualGUIDAligned(&Pin
->ConnectionFormat
->SubFormat
, &KSDATAFORMAT_SUBTYPE_PCM
) &&
220 IsEqualGUIDAligned(&Pin
->ConnectionFormat
->Specifier
, &KSDATAFORMAT_SPECIFIER_WAVEFORMATEX
))
222 WaveFormatEx
= (PKSDATAFORMAT_WAVEFORMATEX
)Pin
->ConnectionFormat
;
223 SampleRateBuffer
[2] = (WaveFormatEx
->WaveFormatEx
.nSamplesPerSec
>> 16) & 0xFF;
224 SampleRateBuffer
[1] = (WaveFormatEx
->WaveFormatEx
.nSamplesPerSec
>> 8) & 0xFF;
225 SampleRateBuffer
[0] = (WaveFormatEx
->WaveFormatEx
.nSamplesPerSec
>> 0) & 0xFF;
227 /* TODO: verify connection format */
231 /* not supported yet*/
233 FreeFunction(SampleRateBuffer
);
234 return STATUS_INVALID_PARAMETER
;
238 Urb
= AllocFunction(sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST
));
242 FreeFunction(SampleRateBuffer
);
243 return STATUS_INSUFFICIENT_RESOURCES
;
246 /* FIXME: determine controls and format urb */
247 UsbBuildVendorRequest(Urb
,
248 URB_FUNCTION_CLASS_ENDPOINT
,
249 sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST
),
250 USBD_TRANSFER_DIRECTION_OUT
,
254 0x81, //FIXME bEndpointAddress
260 /* get pin context */
261 PinContext
= Pin
->Context
;
264 Status
= SubmitUrbSync(PinContext
->LowerDevice
, Urb
);
266 DPRINT1("USBAudioPinSetDataFormat Pin %p Status %x\n", Pin
, Status
);
268 FreeFunction(SampleRateBuffer
);
273 USBAudioSelectAudioStreamingInterface(
274 IN PPIN_CONTEXT PinContext
,
275 IN PDEVICE_EXTENSION DeviceExtension
,
276 IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor
)
279 PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor
;
282 /* grab interface descriptor */
283 InterfaceDescriptor
= USBD_ParseConfigurationDescriptorEx(ConfigurationDescriptor
, ConfigurationDescriptor
, -1, -1, USB_DEVICE_CLASS_AUDIO
, -1, -1);
284 if (!InterfaceDescriptor
)
286 /* no such interface */
287 return STATUS_INVALID_PARAMETER
;
290 /* FIXME selects the first interface with audio streaming and non zero num of endpoints */
291 while (InterfaceDescriptor
!= NULL
)
293 if (InterfaceDescriptor
->bInterfaceSubClass
== 0x02 /* AUDIO_STREAMING */ && InterfaceDescriptor
->bNumEndpoints
> 0)
297 InterfaceDescriptor
= USBD_ParseConfigurationDescriptorEx(ConfigurationDescriptor
, (PVOID
)((ULONG_PTR
)InterfaceDescriptor
+ InterfaceDescriptor
->bLength
), -1, -1, USB_DEVICE_CLASS_AUDIO
, -1, -1);
300 if (!InterfaceDescriptor
)
302 /* no such interface */
303 return STATUS_INVALID_PARAMETER
;
306 Urb
= AllocFunction(GET_SELECT_INTERFACE_REQUEST_SIZE(InterfaceDescriptor
->bNumEndpoints
));
310 return USBD_STATUS_INSUFFICIENT_RESOURCES
;
313 /* now prepare interface urb */
314 UsbBuildSelectInterfaceRequest(Urb
, GET_SELECT_INTERFACE_REQUEST_SIZE(InterfaceDescriptor
->bNumEndpoints
), DeviceExtension
->ConfigurationHandle
, InterfaceDescriptor
->bInterfaceNumber
, InterfaceDescriptor
->bAlternateSetting
);
316 /* now select the interface */
317 Status
= SubmitUrbSync(DeviceExtension
->LowerDevice
, Urb
);
319 DPRINT1("USBAudioSelectAudioStreamingInterface Status %x UrbStatus %x\n", Status
, Urb
->UrbSelectInterface
.Hdr
.Status
);
321 /* did it succeeed */
322 if (NT_SUCCESS(Status
))
324 /* free old interface info */
325 if (DeviceExtension
->InterfaceInfo
)
328 FreeFunction(DeviceExtension
->InterfaceInfo
);
331 /* alloc interface info */
332 DeviceExtension
->InterfaceInfo
= AllocFunction(Urb
->UrbSelectInterface
.Interface
.Length
);
333 if (DeviceExtension
->InterfaceInfo
== NULL
)
337 return STATUS_INSUFFICIENT_RESOURCES
;
340 /* copy interface info */
341 RtlCopyMemory(DeviceExtension
->InterfaceInfo
, &Urb
->UrbSelectInterface
.Interface
, Urb
->UrbSelectInterface
.Interface
.Length
);
342 PinContext
->InterfaceDescriptor
= InterfaceDescriptor
;
352 CaptureGateOnWorkItem(
356 PPIN_CONTEXT PinContext
;
363 /* get pin context */
364 PinContext
= Pin
->Context
;
368 /* acquire processing mutex */
369 KsPinAcquireProcessingMutex(Pin
);
371 /* get pin control gate */
372 Gate
= KsPinGetAndGate(Pin
);
375 KsGateTurnInputOn(Gate
);
377 /* schedule processing */
378 KsPinAttemptProcessing(Pin
, TRUE
);
380 /* release processing mutex */
381 KsPinReleaseProcessingMutex(Pin
);
383 /* decrement worker count */
384 Count
= KsDecrementCountedWorker(PinContext
->CaptureWorker
);
391 CaptureInitializeUrbAndIrp(
395 PIO_STACK_LOCATION IoStack
;
397 PUCHAR TransferBuffer
;
399 PPIN_CONTEXT PinContext
;
401 /* get pin context */
402 PinContext
= Pin
->Context
;
404 /* backup urb and transferbuffer */
405 Urb
= Irp
->Tail
.Overlay
.DriverContext
[0];
406 TransferBuffer
= Urb
->UrbIsochronousTransfer
.TransferBuffer
;
409 IoInitializeIrp(Irp
, IoSizeOfIrp(PinContext
->DeviceExtension
->LowerDevice
->StackSize
), PinContext
->DeviceExtension
->LowerDevice
->StackSize
);
411 Irp
->IoStatus
.Status
= STATUS_NOT_SUPPORTED
;
412 Irp
->IoStatus
.Information
= 0;
414 Irp
->UserBuffer
= NULL
;
415 Irp
->Tail
.Overlay
.DriverContext
[0] = Urb
;
416 Irp
->Tail
.Overlay
.DriverContext
[1] = NULL
;
418 /* init stack location */
419 IoStack
= IoGetNextIrpStackLocation(Irp
);
420 IoStack
->DeviceObject
= PinContext
->DeviceExtension
->LowerDevice
;
421 IoStack
->Parameters
.Others
.Argument1
= Urb
;
422 IoStack
->Parameters
.Others
.Argument2
= NULL
;
423 IoStack
->MajorFunction
= IRP_MJ_INTERNAL_DEVICE_CONTROL
;
424 IoStack
->Parameters
.DeviceIoControl
.IoControlCode
= IOCTL_INTERNAL_USB_SUBMIT_URB
;
426 IoSetCompletionRoutine(Irp
, UsbAudioCaptureComplete
, Pin
, TRUE
, TRUE
, TRUE
);
428 RtlZeroMemory(Urb
, GET_ISO_URB_SIZE(PACKET_COUNT
));
431 Urb
->UrbIsochronousTransfer
.Hdr
.Function
= URB_FUNCTION_ISOCH_TRANSFER
;
432 Urb
->UrbIsochronousTransfer
.Hdr
.Length
= GET_ISO_URB_SIZE(10);
433 Urb
->UrbIsochronousTransfer
.PipeHandle
= PinContext
->DeviceExtension
->InterfaceInfo
->Pipes
[0].PipeHandle
;
434 Urb
->UrbIsochronousTransfer
.TransferFlags
= USBD_TRANSFER_DIRECTION_IN
| USBD_START_ISO_TRANSFER_ASAP
;
435 Urb
->UrbIsochronousTransfer
.TransferBufferLength
= PinContext
->DeviceExtension
->InterfaceInfo
->Pipes
[0].MaximumPacketSize
* 10;
436 Urb
->UrbIsochronousTransfer
.TransferBuffer
= TransferBuffer
;
437 Urb
->UrbIsochronousTransfer
.NumberOfPackets
= PACKET_COUNT
;
438 Urb
->UrbIsochronousTransfer
.StartFrame
= 0;
440 for (Index
= 0; Index
< PACKET_COUNT
; Index
++)
442 Urb
->UrbIsochronousTransfer
.IsoPacket
[Index
].Offset
= Index
* PinContext
->DeviceExtension
->InterfaceInfo
->Pipes
[0].MaximumPacketSize
;
449 CaptureAvoidPipeStarvationWorker(
453 PPIN_CONTEXT PinContext
;
455 PLIST_ENTRY CurEntry
;
461 /* get pin context */
462 PinContext
= Pin
->Context
;
464 /* acquire spin lock */
465 KeAcquireSpinLock(&PinContext
->IrpListLock
, &OldLevel
);
467 if (!IsListEmpty(&PinContext
->IrpListHead
))
470 ASSERT(!IsListEmpty(&PinContext
->IrpListHead
));
472 /* remove entry from list */
473 CurEntry
= RemoveHeadList(&PinContext
->IrpListHead
);
476 KeReleaseSpinLock(&PinContext
->IrpListLock
, OldLevel
);
479 Irp
= (PIRP
)CONTAINING_RECORD(CurEntry
, IRP
, Tail
.Overlay
.ListEntry
);
481 /* reinitialize irp and urb */
482 CaptureInitializeUrbAndIrp(Pin
, Irp
);
484 KsDecrementCountedWorker(PinContext
->StarvationWorker
);
487 IoCallDriver(PinContext
->DeviceExtension
->LowerDevice
, Irp
);
492 KeReleaseSpinLock(&PinContext
->IrpListLock
, OldLevel
);
494 KsDecrementCountedWorker(PinContext
->StarvationWorker
);
507 ULONG MaximumPacketSize
;
510 PPIN_CONTEXT PinContext
;
511 PIO_STACK_LOCATION IoStack
;
512 PKSALLOCATOR_FRAMING_EX Framing
;
516 /* set sample rate */
517 Status
= UsbAudioSetFormat(Pin
);
518 if (!NT_SUCCESS(Status
))
524 /* get pin context */
525 PinContext
= Pin
->Context
;
527 /* lets get maximum packet size */
528 MaximumPacketSize
= GetMaxPacketSizeForInterface(PinContext
->DeviceExtension
->ConfigurationDescriptor
, PinContext
->InterfaceDescriptor
, Pin
->DataFlow
);
530 /* initialize work item for capture worker */
531 ExInitializeWorkItem(&PinContext
->CaptureWorkItem
, CaptureGateOnWorkItem
, (PVOID
)Pin
);
533 /* register worker */
534 Status
= KsRegisterCountedWorker(CriticalWorkQueue
, &PinContext
->CaptureWorkItem
, &PinContext
->CaptureWorker
);
535 if (!NT_SUCCESS(Status
))
541 /* initialize work item */
542 ExInitializeWorkItem(&PinContext
->StarvationWorkItem
, CaptureAvoidPipeStarvationWorker
, (PVOID
)Pin
);
544 /* register worker */
545 Status
= KsRegisterCountedWorker(CriticalWorkQueue
, &PinContext
->StarvationWorkItem
, &PinContext
->StarvationWorker
);
546 if (!NT_SUCCESS(Status
))
549 KsUnregisterWorker(PinContext
->CaptureWorker
);
552 /* lets edit framing struct */
553 Framing
= (PKSALLOCATOR_FRAMING_EX
)Pin
->Descriptor
->AllocatorFraming
;
554 Framing
->FramingItem
[0].PhysicalRange
.MinFrameSize
=
555 Framing
->FramingItem
[0].PhysicalRange
.MaxFrameSize
=
556 Framing
->FramingItem
[0].FramingRange
.Range
.MinFrameSize
=
557 Framing
->FramingItem
[0].FramingRange
.Range
.MaxFrameSize
=
560 /* calculate buffer size 8 irps * 10 iso packets * max packet size */
561 BufferSize
= 8 * PACKET_COUNT
* MaximumPacketSize
;
563 /* allocate pin capture buffer */
564 PinContext
->BufferSize
= BufferSize
;
565 PinContext
->Buffer
= AllocFunction(BufferSize
);
566 if (!PinContext
->Buffer
)
569 return STATUS_INSUFFICIENT_RESOURCES
;
571 KsAddItemToObjectBag(Pin
->Bag
, PinContext
->Buffer
, ExFreePool
);
574 for (Index
= 0; Index
< 8; Index
++)
577 Irp
= AllocFunction(IoSizeOfIrp(PinContext
->DeviceExtension
->LowerDevice
->StackSize
));
581 return STATUS_INSUFFICIENT_RESOURCES
;
585 IoInitializeIrp(Irp
, IoSizeOfIrp(PinContext
->DeviceExtension
->LowerDevice
->StackSize
), PinContext
->DeviceExtension
->LowerDevice
->StackSize
);
587 Irp
->IoStatus
.Status
= STATUS_NOT_SUPPORTED
;
588 Irp
->IoStatus
.Information
= 0;
590 Irp
->UserBuffer
= NULL
;
592 IoStack
= IoGetNextIrpStackLocation(Irp
);
593 IoStack
->DeviceObject
= PinContext
->DeviceExtension
->LowerDevice
;
594 IoStack
->Parameters
.Others
.Argument2
= NULL
;
595 IoStack
->MajorFunction
= IRP_MJ_INTERNAL_DEVICE_CONTROL
;
596 IoStack
->Parameters
.DeviceIoControl
.IoControlCode
= IOCTL_INTERNAL_USB_SUBMIT_URB
;
598 IoSetCompletionRoutine(Irp
, UsbAudioCaptureComplete
, Pin
, TRUE
, TRUE
, TRUE
);
600 /* insert into irp list */
601 InsertTailList(&PinContext
->IrpListHead
, &Irp
->Tail
.Overlay
.ListEntry
);
603 /* add to object bag*/
604 KsAddItemToObjectBag(Pin
->Bag
, Irp
, ExFreePool
);
606 /* FIXME select correct pipe handle */
607 Status
= UsbAudioAllocCaptureUrbIso(PinContext
->DeviceExtension
->InterfaceInfo
->Pipes
[0].PipeHandle
,
609 &PinContext
->Buffer
[MaximumPacketSize
* PACKET_COUNT
* Index
],
610 MaximumPacketSize
* PACKET_COUNT
,
613 DPRINT1("InitCapturePin Irp %p Urb %p\n", Irp
, Urb
);
615 if (NT_SUCCESS(Status
))
617 /* get next stack location */
618 IoStack
= IoGetNextIrpStackLocation(Irp
);
621 IoStack
->Parameters
.Others
.Argument1
= Urb
;
622 Irp
->Tail
.Overlay
.DriverContext
[0] = Urb
;
631 /* get process control gate */
632 Gate
= KsPinGetAndGate(Pin
);
635 KsGateTurnInputOff(Gate
);
645 return STATUS_NOT_IMPLEMENTED
;
658 PFILTER_CONTEXT FilterContext
;
659 PPIN_CONTEXT PinContext
;
662 Filter
= KsPinGetParentFilter(Pin
);
665 /* invalid parameter */
666 return STATUS_INVALID_PARAMETER
;
669 /* get filter context */
670 FilterContext
= Filter
->Context
;
672 /* allocate pin context */
673 PinContext
= AllocFunction(sizeof(PIN_CONTEXT
));
677 return STATUS_INSUFFICIENT_RESOURCES
;
680 /* init pin context */
681 PinContext
->DeviceExtension
= FilterContext
->DeviceExtension
;
682 PinContext
->LowerDevice
= FilterContext
->LowerDevice
;
683 InitializeListHead(&PinContext
->IrpListHead
);
684 InitializeListHead(&PinContext
->DoneIrpListHead
);
685 KeInitializeSpinLock(&PinContext
->IrpListLock
);
687 /* store pin context*/
688 Pin
->Context
= PinContext
;
690 /* lets edit allocator framing struct */
691 Status
= _KsEdit(Pin
->Bag
, (PVOID
*)&Pin
->Descriptor
, sizeof(KSPIN_DESCRIPTOR_EX
), sizeof(KSPIN_DESCRIPTOR_EX
), USBAUDIO_TAG
);
692 if (NT_SUCCESS(Status
))
694 Status
= _KsEdit(Pin
->Bag
, (PVOID
*)&Pin
->Descriptor
->AllocatorFraming
, sizeof(KSALLOCATOR_FRAMING_EX
), sizeof(KSALLOCATOR_FRAMING_EX
), USBAUDIO_TAG
);
695 ASSERT(Status
== STATUS_SUCCESS
);
698 /* FIXME move to build filter topology*/
699 UsbAudioSetMuteOff(Pin
);
700 UsbAudioSetVolume(Pin
);
702 /* select streaming interface */
703 Status
= USBAudioSelectAudioStreamingInterface(PinContext
, PinContext
->DeviceExtension
, PinContext
->DeviceExtension
->ConfigurationDescriptor
);
704 if (!NT_SUCCESS(Status
))
710 if (Pin
->DataFlow
== KSPIN_DATAFLOW_OUT
)
712 /* init capture pin */
713 Status
= InitCapturePin(Pin
);
717 /* audio streaming pin*/
718 Status
= InitStreamPin(Pin
);
721 return STATUS_SUCCESS
;
731 return STATUS_NOT_IMPLEMENTED
;
736 UsbAudioCaptureComplete(
737 IN PDEVICE_OBJECT DeviceObject
,
742 PPIN_CONTEXT PinContext
;
746 /* get pin context */
748 PinContext
= Pin
->Context
;
751 Urb
= Irp
->Tail
.Overlay
.DriverContext
[0];
754 KeAcquireSpinLock(&PinContext
->IrpListLock
, &OldLevel
);
756 if (!NT_SUCCESS(Urb
->UrbIsochronousTransfer
.Hdr
.Status
))
758 //DPRINT("UsbAudioCaptureComplete Irp %p Urb %p Status %x Packet Status %x\n", Irp, Urb, Urb->UrbIsochronousTransfer.Hdr.Status, Urb->UrbIsochronousTransfer.IsoPacket[0].Status);
760 /* insert entry into ready list */
761 InsertTailList(&PinContext
->IrpListHead
, &Irp
->Tail
.Overlay
.ListEntry
);
764 KeReleaseSpinLock(&PinContext
->IrpListLock
, OldLevel
);
766 KsIncrementCountedWorker(PinContext
->StarvationWorker
);
770 /* insert entry into done list */
771 InsertTailList(&PinContext
->DoneIrpListHead
, &Irp
->Tail
.Overlay
.ListEntry
);
774 KeReleaseSpinLock(&PinContext
->IrpListLock
, OldLevel
);
776 KsIncrementCountedWorker(PinContext
->CaptureWorker
);
780 return STATUS_MORE_PROCESSING_REQUIRED
;
787 PKSSTREAM_POINTER LeadingStreamPointer
;
789 PPIN_CONTEXT PinContext
;
790 PLIST_ENTRY CurEntry
;
792 PIO_STACK_LOCATION IoStack
;
794 PUCHAR TransferBuffer
, OutBuffer
;
795 ULONG Offset
, Length
;
799 //DPRINT1("PinCaptureProcess\n");
800 LeadingStreamPointer
= KsPinGetLeadingEdgeStreamPointer(Pin
, KSSTREAM_POINTER_STATE_LOCKED
);
801 if (LeadingStreamPointer
== NULL
)
803 /* get process control gate */
804 Gate
= KsPinGetAndGate(Pin
);
806 /* shutdown processing */
807 KsGateTurnInputOff(Gate
);
809 return STATUS_SUCCESS
;
812 /* get pin context */
813 PinContext
= Pin
->Context
;
815 /* acquire spin lock */
816 KeAcquireSpinLock(&PinContext
->IrpListLock
, &OldLevel
);
818 while (!IsListEmpty(&PinContext
->DoneIrpListHead
))
820 /* remove entry from list */
821 CurEntry
= RemoveHeadList(&PinContext
->DoneIrpListHead
);
824 KeReleaseSpinLock(&PinContext
->IrpListLock
, OldLevel
);
827 Irp
= (PIRP
)CONTAINING_RECORD(CurEntry
, IRP
, Tail
.Overlay
.ListEntry
);
829 /* get urb from irp */
830 IoStack
= IoGetNextIrpStackLocation(Irp
);
831 Urb
= (PURB
)Irp
->Tail
.Overlay
.DriverContext
[0];
834 Offset
= PtrToUlong(Irp
->Tail
.Overlay
.DriverContext
[1]);
836 /* get transfer buffer */
837 TransferBuffer
= Urb
->UrbIsochronousTransfer
.TransferBuffer
;
839 /* get target buffer */
840 OutBuffer
= (PUCHAR
)LeadingStreamPointer
->StreamHeader
->Data
;
842 /* calculate length */
843 Length
= min(LeadingStreamPointer
->OffsetOut
.Count
- LeadingStreamPointer
->StreamHeader
->DataUsed
, Urb
->UrbIsochronousTransfer
.TransferBufferLength
- Offset
);
845 /* FIXME copy each packet extra */
846 /* copy audio bytes */
847 RtlCopyMemory((PUCHAR
)&OutBuffer
[LeadingStreamPointer
->StreamHeader
->DataUsed
], &TransferBuffer
[Offset
], Length
);
849 //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);
851 /* adjust streampointer */
852 LeadingStreamPointer
->StreamHeader
->DataUsed
+= Length
;
854 if (Length
== LeadingStreamPointer
->OffsetOut
.Remaining
)
856 KsStreamPointerAdvanceOffsetsAndUnlock(LeadingStreamPointer
, 0, Length
, TRUE
);
858 /* acquire spin lock */
859 KeAcquireSpinLock(&PinContext
->IrpListLock
, &OldLevel
);
862 Irp
->Tail
.Overlay
.DriverContext
[1] = UlongToPtr(Length
);
864 /* reinsert into processed list */
865 InsertHeadList(&PinContext
->DoneIrpListHead
, &Irp
->Tail
.Overlay
.ListEntry
);
868 KeReleaseSpinLock(&PinContext
->IrpListLock
, OldLevel
);
870 LeadingStreamPointer
= KsPinGetLeadingEdgeStreamPointer(Pin
, KSSTREAM_POINTER_STATE_LOCKED
);
871 if (LeadingStreamPointer
== NULL
)
873 /* no more work to be done*/
874 return STATUS_PENDING
;
878 /* resume work on this irp */
884 Status
= KsStreamPointerAdvanceOffsets(LeadingStreamPointer
, 0, Length
, FALSE
);
885 ASSERT(Length
== Urb
->UrbIsochronousTransfer
.TransferBufferLength
- Offset
);
889 /* acquire spin lock */
890 KeAcquireSpinLock(&PinContext
->IrpListLock
, &OldLevel
);
892 InsertTailList(&PinContext
->IrpListHead
, &Irp
->Tail
.Overlay
.ListEntry
);
895 while (!IsListEmpty(&PinContext
->IrpListHead
))
897 /* remove entry from list */
898 CurEntry
= RemoveHeadList(&PinContext
->IrpListHead
);
901 KeReleaseSpinLock(&PinContext
->IrpListLock
, OldLevel
);
904 Irp
= (PIRP
)CONTAINING_RECORD(CurEntry
, IRP
, Tail
.Overlay
.ListEntry
);
906 /* reinitialize irp and urb */
907 CaptureInitializeUrbAndIrp(Pin
, Irp
);
909 IoCallDriver(PinContext
->DeviceExtension
->LowerDevice
, Irp
);
911 /* acquire spin lock */
912 KeAcquireSpinLock(&PinContext
->IrpListLock
, &OldLevel
);
917 KeReleaseSpinLock(&PinContext
->IrpListLock
, OldLevel
);
919 if (LeadingStreamPointer
!= NULL
)
920 KsStreamPointerUnlock(LeadingStreamPointer
, FALSE
);
922 /* get process control gate */
923 Gate
= KsPinGetAndGate(Pin
);
925 /* shutdown processing */
926 KsGateTurnInputOff(Gate
);
928 return STATUS_PENDING
;
939 if (Pin
->DataFlow
== KSPIN_DATAFLOW_OUT
)
941 Status
= PinCaptureProcess(Pin
);
946 Status
= STATUS_NOT_IMPLEMENTED
;
963 USBAudioPinSetDataFormat(
965 _In_opt_ PKSDATAFORMAT OldFormat
,
966 _In_opt_ PKSMULTIPLE_ITEM OldAttributeList
,
967 _In_
const KSDATARANGE
* DataRange
,
968 _In_opt_
const KSATTRIBUTE_LIST
* AttributeRange
)
970 if (OldFormat
== NULL
)
972 /* TODO: verify connection format */
974 return STATUS_SUCCESS
;
977 return UsbAudioSetFormat(Pin
);
981 StartCaptureIsocTransfer(
984 PPIN_CONTEXT PinContext
;
985 PLIST_ENTRY CurEntry
;
989 /* get pin context */
990 PinContext
= Pin
->Context
;
992 /* acquire spin lock */
993 KeAcquireSpinLock(&PinContext
->IrpListLock
, &OldLevel
);
995 while(!IsListEmpty(&PinContext
->IrpListHead
))
997 /* remove entry from list */
998 CurEntry
= RemoveHeadList(&PinContext
->IrpListHead
);
1000 /* get irp offset */
1001 Irp
= (PIRP
)CONTAINING_RECORD(CurEntry
, IRP
, Tail
.Overlay
.ListEntry
);
1004 KeReleaseSpinLock(&PinContext
->IrpListLock
, OldLevel
);
1006 /* reinitialize irp and urb */
1007 CaptureInitializeUrbAndIrp(Pin
, Irp
);
1009 DPRINT("StartCaptureIsocTransfer Irp %p\n", Irp
);
1010 IoCallDriver(PinContext
->DeviceExtension
->LowerDevice
, Irp
);
1012 /* acquire spin lock */
1013 KeAcquireSpinLock(&PinContext
->IrpListLock
, &OldLevel
);
1018 KeReleaseSpinLock(&PinContext
->IrpListLock
, OldLevel
);
1020 return STATUS_SUCCESS
;
1024 CapturePinStateChange(
1026 _In_ KSSTATE ToState
,
1027 _In_ KSSTATE FromState
)
1031 if (FromState
!= ToState
)
1035 if (ToState
== KSSTATE_PAUSE
)
1037 if (FromState
== KSSTATE_RUN
)
1039 /* wait until pin processing is finished*/
1044 if (ToState
== KSSTATE_RUN
)
1046 Status
= StartCaptureIsocTransfer(Pin
);
1057 USBAudioPinSetDeviceState(
1059 _In_ KSSTATE ToState
,
1060 _In_ KSSTATE FromState
)
1064 if (Pin
->DataFlow
== KSPIN_DATAFLOW_OUT
)
1066 /* handle capture state changes */
1067 Status
= CapturePinStateChange(Pin
, ToState
, FromState
);
1072 Status
= STATUS_NOT_IMPLEMENTED
;
1081 UsbAudioPinDataIntersect(
1085 _In_ PKSDATARANGE DataRange
,
1086 _In_ PKSDATARANGE MatchingDataRange
,
1087 _In_ ULONG DataBufferSize
,
1089 _Out_ PULONG DataSize
)
1092 PKSPIN_DESCRIPTOR_EX PinDescriptor
;
1093 PKSDATAFORMAT_WAVEFORMATEX DataFormat
;
1094 PKSDATARANGE_AUDIO DataRangeAudio
;
1096 /* get filter from irp*/
1097 Filter
= KsGetFilterFromIrp(Irp
);
1101 return STATUS_NO_MATCH
;
1104 /* get pin descriptor */
1105 PinDescriptor
= &Filter
->Descriptor
->PinDescriptors
[Pin
->PinId
];
1107 *DataSize
= sizeof(KSDATAFORMAT_WAVEFORMATEX
);
1108 if (DataBufferSize
== 0)
1110 /* buffer too small */
1111 return STATUS_BUFFER_OVERFLOW
;
1115 ASSERT(PinDescriptor
->PinDescriptor
.DataRangesCount
>= 0);
1116 ASSERT(PinDescriptor
->PinDescriptor
.DataRanges
[0]->FormatSize
== sizeof(KSDATARANGE_AUDIO
));
1118 DataRangeAudio
= (PKSDATARANGE_AUDIO
)PinDescriptor
->PinDescriptor
.DataRanges
[0];
1121 DataFormat
->WaveFormatEx
.wFormatTag
= WAVE_FORMAT_PCM
;
1122 DataFormat
->WaveFormatEx
.nChannels
= DataRangeAudio
->MaximumChannels
;
1123 DataFormat
->WaveFormatEx
.nSamplesPerSec
= DataRangeAudio
->MaximumSampleFrequency
;
1124 DataFormat
->WaveFormatEx
.nAvgBytesPerSec
= DataRangeAudio
->MaximumSampleFrequency
* (DataRangeAudio
->MaximumBitsPerSample
/ 8) * DataRangeAudio
->MaximumChannels
;
1125 DataFormat
->WaveFormatEx
.nBlockAlign
= (DataRangeAudio
->MaximumBitsPerSample
/ 8) * DataRangeAudio
->MaximumChannels
;
1126 DataFormat
->WaveFormatEx
.wBitsPerSample
= DataRangeAudio
->MaximumBitsPerSample
;
1127 DataFormat
->WaveFormatEx
.cbSize
= 0;
1129 DataFormat
->DataFormat
.FormatSize
= sizeof(KSDATAFORMAT
) + sizeof(WAVEFORMATEX
);
1130 DataFormat
->DataFormat
.Flags
= 0;
1131 DataFormat
->DataFormat
.Reserved
= 0;
1132 DataFormat
->DataFormat
.MajorFormat
= KSDATAFORMAT_TYPE_AUDIO
;
1133 DataFormat
->DataFormat
.SubFormat
= KSDATAFORMAT_SUBTYPE_PCM
;
1134 DataFormat
->DataFormat
.Specifier
= KSDATAFORMAT_SPECIFIER_WAVEFORMATEX
;
1135 DataFormat
->DataFormat
.SampleSize
= (DataRangeAudio
->MaximumBitsPerSample
/ 8) * DataRangeAudio
->MaximumChannels
;
1137 return STATUS_SUCCESS
;