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)
14 GetMaxPacketSizeForInterface(
15 IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor
,
16 IN PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor
,
17 KSPIN_DATAFLOW DataFlow
)
19 PUSB_COMMON_DESCRIPTOR CommonDescriptor
;
20 PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor
;
22 /* loop descriptors */
23 CommonDescriptor
= (PUSB_COMMON_DESCRIPTOR
)((ULONG_PTR
)InterfaceDescriptor
+ InterfaceDescriptor
->bLength
);
24 ASSERT(InterfaceDescriptor
->bNumEndpoints
> 0);
25 while (CommonDescriptor
)
27 if (CommonDescriptor
->bDescriptorType
== USB_ENDPOINT_DESCRIPTOR_TYPE
)
29 EndpointDescriptor
= (PUSB_ENDPOINT_DESCRIPTOR
)CommonDescriptor
;
30 return EndpointDescriptor
->wMaxPacketSize
;
33 if (CommonDescriptor
->bDescriptorType
== USB_INTERFACE_DESCRIPTOR_TYPE
)
35 /* reached next interface descriptor */
39 if ((ULONG_PTR
)CommonDescriptor
+ CommonDescriptor
->bLength
>= ((ULONG_PTR
)ConfigurationDescriptor
+ ConfigurationDescriptor
->wTotalLength
))
42 CommonDescriptor
= (PUSB_COMMON_DESCRIPTOR
)((ULONG_PTR
)CommonDescriptor
+ CommonDescriptor
->bLength
);
50 UsbAudioAllocCaptureUrbIso(
51 IN USBD_PIPE_HANDLE PipeHandle
,
52 IN ULONG MaxPacketSize
,
54 IN ULONG BufferLength
,
62 /* calculate packet count */
63 PacketCount
= BufferLength
/ MaxPacketSize
;
65 /* calculate urb size*/
66 UrbSize
= GET_ISO_URB_SIZE(PacketCount
);
69 Urb
= AllocFunction(UrbSize
);
73 return STATUS_INSUFFICIENT_RESOURCES
;
77 Urb
->UrbIsochronousTransfer
.Hdr
.Function
= URB_FUNCTION_ISOCH_TRANSFER
;
78 Urb
->UrbIsochronousTransfer
.Hdr
.Length
= UrbSize
;
79 Urb
->UrbIsochronousTransfer
.PipeHandle
= PipeHandle
;
80 Urb
->UrbIsochronousTransfer
.TransferFlags
= USBD_TRANSFER_DIRECTION_IN
| USBD_START_ISO_TRANSFER_ASAP
;
81 Urb
->UrbIsochronousTransfer
.TransferBufferLength
= BufferLength
;
82 Urb
->UrbIsochronousTransfer
.TransferBuffer
= Buffer
;
83 Urb
->UrbIsochronousTransfer
.NumberOfPackets
= PacketCount
;
85 for (Index
= 0; Index
< PacketCount
; Index
++)
87 Urb
->UrbIsochronousTransfer
.IsoPacket
[Index
].Offset
= Index
* MaxPacketSize
;
91 return STATUS_SUCCESS
;
102 PUCHAR SampleRateBuffer
;
103 PPIN_CONTEXT PinContext
;
105 PKSDATAFORMAT_WAVEFORMATEX WaveFormatEx
;
107 /* allocate sample rate buffer */
108 SampleRateBuffer
= AllocFunction(sizeof(ULONG
));
109 if (!SampleRateBuffer
)
112 return STATUS_INSUFFICIENT_RESOURCES
;
115 if (IsEqualGUIDAligned(&Pin
->ConnectionFormat
->MajorFormat
, &KSDATAFORMAT_TYPE_AUDIO
) &&
116 IsEqualGUIDAligned(&Pin
->ConnectionFormat
->SubFormat
, &KSDATAFORMAT_SUBTYPE_PCM
) &&
117 IsEqualGUIDAligned(&Pin
->ConnectionFormat
->Specifier
, &KSDATAFORMAT_SPECIFIER_WAVEFORMATEX
))
119 WaveFormatEx
= (PKSDATAFORMAT_WAVEFORMATEX
)Pin
->ConnectionFormat
;
120 SampleRateBuffer
[2] = (WaveFormatEx
->WaveFormatEx
.nSamplesPerSec
>> 16) & 0xFF;
121 SampleRateBuffer
[1] = (WaveFormatEx
->WaveFormatEx
.nSamplesPerSec
>> 8) & 0xFF;
122 SampleRateBuffer
[0] = (WaveFormatEx
->WaveFormatEx
.nSamplesPerSec
>> 0) & 0xFF;
124 /* TODO: verify connection format */
128 /* not supported yet*/
130 FreeFunction(SampleRateBuffer
);
131 return STATUS_INVALID_PARAMETER
;
135 Urb
= AllocFunction(sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST
));
139 FreeFunction(SampleRateBuffer
);
140 return STATUS_INSUFFICIENT_RESOURCES
;
144 UsbBuildVendorRequest(Urb
,
145 URB_FUNCTION_CLASS_ENDPOINT
,
146 sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST
),
147 USBD_TRANSFER_DIRECTION_OUT
,
151 0x81, //FIXME bEndpointAddress
157 /* get pin context */
158 PinContext
= Pin
->Context
;
161 Status
= SubmitUrbSync(PinContext
->LowerDevice
, Urb
);
163 DPRINT1("USBAudioPinSetDataFormat Pin %p Status %x\n", Pin
, Status
);
165 FreeFunction(SampleRateBuffer
);
170 USBAudioSelectAudioStreamingInterface(
171 IN PPIN_CONTEXT PinContext
,
172 IN PDEVICE_EXTENSION DeviceExtension
,
173 IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor
)
176 PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor
;
179 /* grab interface descriptor */
180 InterfaceDescriptor
= USBD_ParseConfigurationDescriptorEx(ConfigurationDescriptor
, ConfigurationDescriptor
, -1, -1, USB_DEVICE_CLASS_AUDIO
, -1, -1);
181 if (!InterfaceDescriptor
)
183 /* no such interface */
184 return STATUS_INVALID_PARAMETER
;
187 /* FIXME selects the first interface with audio streaming and non zero num of endpoints */
188 while (InterfaceDescriptor
!= NULL
)
190 if (InterfaceDescriptor
->bInterfaceSubClass
== 0x02 /* AUDIO_STREAMING */ && InterfaceDescriptor
->bNumEndpoints
> 0)
194 InterfaceDescriptor
= USBD_ParseConfigurationDescriptorEx(ConfigurationDescriptor
, (PVOID
)((ULONG_PTR
)InterfaceDescriptor
+ InterfaceDescriptor
->bLength
), -1, -1, USB_DEVICE_CLASS_AUDIO
, -1, -1);
197 if (!InterfaceDescriptor
)
199 /* no such interface */
200 return STATUS_INVALID_PARAMETER
;
203 Urb
= AllocFunction(GET_SELECT_INTERFACE_REQUEST_SIZE(InterfaceDescriptor
->bNumEndpoints
));
207 return USBD_STATUS_INSUFFICIENT_RESOURCES
;
210 /* now prepare interface urb */
211 UsbBuildSelectInterfaceRequest(Urb
, GET_SELECT_INTERFACE_REQUEST_SIZE(InterfaceDescriptor
->bNumEndpoints
), DeviceExtension
->ConfigurationHandle
, InterfaceDescriptor
->bInterfaceNumber
, InterfaceDescriptor
->bAlternateSetting
);
213 /* now select the interface */
214 Status
= SubmitUrbSync(DeviceExtension
->LowerDevice
, Urb
);
216 DPRINT1("USBAudioSelectAudioStreamingInterface Status %x UrbStatus %x\n", Status
, Urb
->UrbSelectInterface
.Hdr
.Status
);
218 /* did it succeeed */
219 if (NT_SUCCESS(Status
))
221 /* free old interface info */
222 if (DeviceExtension
->InterfaceInfo
)
225 FreeFunction(DeviceExtension
->InterfaceInfo
);
228 /* alloc interface info */
229 DeviceExtension
->InterfaceInfo
= AllocFunction(Urb
->UrbSelectInterface
.Interface
.Length
);
230 if (DeviceExtension
->InterfaceInfo
== NULL
)
234 return STATUS_INSUFFICIENT_RESOURCES
;
237 /* copy interface info */
238 RtlCopyMemory(DeviceExtension
->InterfaceInfo
, &Urb
->UrbSelectInterface
.Interface
, Urb
->UrbSelectInterface
.Interface
.Length
);
239 PinContext
->InterfaceDescriptor
= InterfaceDescriptor
;
254 ULONG MaximumPacketSize
;
257 PPIN_CONTEXT PinContext
;
258 PIO_STACK_LOCATION IoStack
;
259 PKSALLOCATOR_FRAMING_EX Framing
;
261 /* set sample rate */
262 Status
= UsbAudioSetFormat(Pin
);
263 if (!NT_SUCCESS(Status
))
269 /* get pin context */
270 PinContext
= Pin
->Context
;
272 /* lets get maximum packet size */
273 MaximumPacketSize
= GetMaxPacketSizeForInterface(PinContext
->DeviceExtension
->ConfigurationDescriptor
, PinContext
->InterfaceDescriptor
, Pin
->DataFlow
);
275 /* lets edit framing struct */
276 Framing
= (PKSALLOCATOR_FRAMING_EX
)Pin
->Descriptor
->AllocatorFraming
;
277 Framing
->FramingItem
[0].PhysicalRange
.MinFrameSize
=
278 Framing
->FramingItem
[0].PhysicalRange
.MaxFrameSize
=
279 Framing
->FramingItem
[0].FramingRange
.Range
.MinFrameSize
=
280 Framing
->FramingItem
[0].FramingRange
.Range
.MaxFrameSize
=
283 /* calculate buffer size 8 irps * 10 iso packets * max packet size */
284 BufferSize
= 8 * 10 * MaximumPacketSize
;
286 /* allocate pin capture buffer */
287 PinContext
->BufferSize
= BufferSize
;
288 PinContext
->Buffer
= AllocFunction(BufferSize
);
289 if (!PinContext
->Buffer
)
292 return STATUS_INSUFFICIENT_RESOURCES
;
294 KsAddItemToObjectBag(Pin
->Bag
, PinContext
->Buffer
, ExFreePool
);
297 for (Index
= 0; Index
< 8; Index
++)
300 Irp
= AllocFunction(IoSizeOfIrp(PinContext
->DeviceExtension
->LowerDevice
->StackSize
));
304 return STATUS_INSUFFICIENT_RESOURCES
;
308 IoInitializeIrp(Irp
, IoSizeOfIrp(PinContext
->DeviceExtension
->LowerDevice
->StackSize
), PinContext
->DeviceExtension
->LowerDevice
->StackSize
);
310 Irp
->IoStatus
.Status
= STATUS_NOT_SUPPORTED
;
311 Irp
->IoStatus
.Information
= 0;
313 Irp
->UserBuffer
= NULL
;
315 IoStack
= IoGetNextIrpStackLocation(Irp
);
316 IoStack
->DeviceObject
= PinContext
->DeviceExtension
->LowerDevice
;
317 IoStack
->Parameters
.Others
.Argument2
= NULL
;
318 IoStack
->MajorFunction
= IRP_MJ_INTERNAL_DEVICE_CONTROL
;
319 IoStack
->Parameters
.DeviceIoControl
.IoControlCode
= IOCTL_INTERNAL_USB_SUBMIT_URB
;
322 DPRINT1("InitCapturePin Irp %p\n", Irp
);
323 /* insert into irp list */
324 InsertTailList(&PinContext
->IrpListHead
, &Irp
->Tail
.Overlay
.ListEntry
);
326 /* add to object bag*/
327 KsAddItemToObjectBag(Pin
->Bag
, Irp
, IoFreeIrp
);
329 /* FIXME select correct pipe handle */
330 Status
= UsbAudioAllocCaptureUrbIso(PinContext
->DeviceExtension
->InterfaceInfo
->Pipes
[0].PipeHandle
,
332 &PinContext
->Buffer
[MaximumPacketSize
* 10 * Index
],
333 MaximumPacketSize
* 10,
336 if (NT_SUCCESS(Status
))
338 /* get next stack location */
339 IoStack
= IoGetNextIrpStackLocation(Irp
);
342 IoStack
->Parameters
.Others
.Argument1
= Urb
;
343 Irp
->Tail
.Overlay
.DriverContext
[0] = Urb
;
359 return STATUS_NOT_IMPLEMENTED
;
370 PFILTER_CONTEXT FilterContext
;
371 PPIN_CONTEXT PinContext
;
374 Filter
= KsPinGetParentFilter(Pin
);
377 /* invalid parameter */
378 return STATUS_INVALID_PARAMETER
;
381 /* get filter context */
382 FilterContext
= Filter
->Context
;
384 /* allocate pin context */
385 PinContext
= AllocFunction(sizeof(PIN_CONTEXT
));
389 return STATUS_INSUFFICIENT_RESOURCES
;
392 /* init pin context */
393 PinContext
->DeviceExtension
= FilterContext
->DeviceExtension
;
394 PinContext
->LowerDevice
= FilterContext
->LowerDevice
;
395 InitializeListHead(&PinContext
->IrpListHead
);
396 InitializeListHead(&PinContext
->DoneIrpListHead
);
397 KeInitializeSpinLock(&PinContext
->IrpListLock
);
399 /* store pin context*/
400 Pin
->Context
= PinContext
;
402 /* lets edit allocator framing struct */
403 Status
= _KsEdit(Pin
->Bag
, &Pin
->Descriptor
, sizeof(KSPIN_DESCRIPTOR_EX
), sizeof(KSPIN_DESCRIPTOR_EX
), USBAUDIO_TAG
);
404 if (NT_SUCCESS(Status
))
406 Status
= _KsEdit(Pin
->Bag
, &Pin
->Descriptor
->AllocatorFraming
, sizeof(KSALLOCATOR_FRAMING_EX
), sizeof(KSALLOCATOR_FRAMING_EX
), USBAUDIO_TAG
);
407 ASSERT(Status
== STATUS_SUCCESS
);
411 /* select streaming interface */
412 Status
= USBAudioSelectAudioStreamingInterface(PinContext
, PinContext
->DeviceExtension
, PinContext
->DeviceExtension
->ConfigurationDescriptor
);
413 if (!NT_SUCCESS(Status
))
419 if (Pin
->DataFlow
== KSPIN_DATAFLOW_OUT
)
421 /* init capture pin */
422 Status
= InitCapturePin(Pin
);
426 /* audio streaming pin*/
427 Status
= InitStreamPin(Pin
);
430 return STATUS_SUCCESS
;
440 return STATUS_NOT_IMPLEMENTED
;
445 UsbAudioCaptureComplete(
446 IN PDEVICE_OBJECT DeviceObject
,
451 PPIN_CONTEXT PinContext
;
454 PIO_STACK_LOCATION IoStack
;
457 /* get pin context */
459 PinContext
= Pin
->Context
;
461 /* get stack location */
462 IoStack
= IoGetNextIrpStackLocation(Irp
);
465 Urb
= Irp
->Tail
.Overlay
.DriverContext
[0];
467 //DPRINT("UsbAudioCaptureComplete Irp %p Urb %p\n", Irp, Urb);
470 KeAcquireSpinLock(&PinContext
->IrpListLock
, &OldLevel
);
472 /* insert entry into done list */
473 InsertTailList(&PinContext
->DoneIrpListHead
, &Irp
->Tail
.Overlay
.ListEntry
);
476 KeReleaseSpinLock(&PinContext
->IrpListLock
, OldLevel
);
479 return STATUS_MORE_PROCESSING_REQUIRED
;
486 PKSSTREAM_POINTER LeadingStreamPointer
;
488 PPIN_CONTEXT PinContext
;
489 PLIST_ENTRY CurEntry
;
491 PIO_STACK_LOCATION IoStack
;
493 PUCHAR TransferBuffer
, OutBuffer
;
494 ULONG Index
, Offset
, MaximumPacketSize
, Length
;
496 //PUSHORT SoundBuffer;
498 LeadingStreamPointer
= KsPinGetLeadingEdgeStreamPointer(Pin
, KSSTREAM_POINTER_STATE_LOCKED
);
499 if (LeadingStreamPointer
== NULL
)
500 return STATUS_SUCCESS
;
502 /* get pin context */
503 PinContext
= Pin
->Context
;
505 /* acquire spin lock */
506 KeAcquireSpinLock(&PinContext
->IrpListLock
, &OldLevel
);
508 while (!IsListEmpty(&PinContext
->DoneIrpListHead
))
510 /* remove entry from list */
511 CurEntry
= RemoveHeadList(&PinContext
->DoneIrpListHead
);
514 KeReleaseSpinLock(&PinContext
->IrpListLock
, OldLevel
);
517 Irp
= (PIRP
)CONTAINING_RECORD(CurEntry
, IRP
, Tail
.Overlay
.ListEntry
);
519 /* get urb from irp */
520 IoStack
= IoGetNextIrpStackLocation(Irp
);
521 Urb
= (PURB
)Irp
->Tail
.Overlay
.DriverContext
[0];
525 for (Index
= 0; Index
< Urb
->UrbIsochronousTransfer
.NumberOfPackets
; Index
++)
528 Offset
+= Urb
->UrbIsochronousTransfer
.IsoPacket
[Index
].Offset
;
530 /* get transfer buffer */
531 TransferBuffer
= Urb
->UrbIsochronousTransfer
.TransferBuffer
;
533 /* get target buffer */
534 OutBuffer
= (PUCHAR
)LeadingStreamPointer
->StreamHeader
->Data
;
536 /* calculate length */
537 Length
= min(LeadingStreamPointer
->OffsetOut
.Count
- LeadingStreamPointer
->StreamHeader
->DataUsed
, Urb
->UrbIsochronousTransfer
.IsoPacket
[Index
].Length
);
539 //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);
542 RtlCopyMemory((PUCHAR
)&OutBuffer
[LeadingStreamPointer
->StreamHeader
->DataUsed
], &TransferBuffer
[Offset
], Length
);
544 LeadingStreamPointer
->StreamHeader
->DataUsed
+= Length
;
546 if (Length
== LeadingStreamPointer
->OffsetOut
.Remaining
) {
547 KsStreamPointerAdvanceOffsetsAndUnlock(LeadingStreamPointer
, 0, Length
, TRUE
);
549 LeadingStreamPointer
= KsPinGetLeadingEdgeStreamPointer(Pin
, KSSTREAM_POINTER_STATE_LOCKED
);
550 if (LeadingStreamPointer
== NULL
)
552 /* FIXME handle half processed packets */
554 //DPRINT1("Warning: ignoring %lu packets\n", Urb->UrbIsochronousTransfer.NumberOfPackets - Index);
556 /* acquire spin lock */
557 KeAcquireSpinLock(&PinContext
->IrpListLock
, &OldLevel
);
559 InsertTailList(&PinContext
->IrpListHead
, &Irp
->Tail
.Overlay
.ListEntry
);
561 KeReleaseSpinLock(&PinContext
->IrpListLock
, OldLevel
);
562 return STATUS_SUCCESS
;
567 Status
= KsStreamPointerAdvanceOffsets(LeadingStreamPointer
, 0, Length
, FALSE
);
572 /* acquire spin lock */
573 KeAcquireSpinLock(&PinContext
->IrpListLock
, &OldLevel
);
575 InsertTailList(&PinContext
->IrpListHead
, &Irp
->Tail
.Overlay
.ListEntry
);
577 if (LeadingStreamPointer
== NULL
)
581 while (!IsListEmpty(&PinContext
->IrpListHead
))
583 /* remove entry from list */
584 CurEntry
= RemoveHeadList(&PinContext
->IrpListHead
);
587 KeReleaseSpinLock(&PinContext
->IrpListLock
, OldLevel
);
590 Irp
= (PIRP
)CONTAINING_RECORD(CurEntry
, IRP
, Tail
.Overlay
.ListEntry
);
592 /* backup urb and transferbuffer */
593 Urb
= Irp
->Tail
.Overlay
.DriverContext
[0];
594 TransferBuffer
= Urb
->UrbIsochronousTransfer
.TransferBuffer
;
597 IoInitializeIrp(Irp
, IoSizeOfIrp(PinContext
->DeviceExtension
->LowerDevice
->StackSize
), PinContext
->DeviceExtension
->LowerDevice
->StackSize
);
599 Irp
->IoStatus
.Status
= STATUS_NOT_SUPPORTED
;
600 Irp
->IoStatus
.Information
= 0;
602 Irp
->UserBuffer
= NULL
;
603 Irp
->Tail
.Overlay
.DriverContext
[0] = Urb
;
605 /* init stack location */
606 IoStack
= IoGetNextIrpStackLocation(Irp
);
607 IoStack
->DeviceObject
= PinContext
->DeviceExtension
->LowerDevice
;
608 IoStack
->Parameters
.Others
.Argument1
= Urb
;
609 IoStack
->Parameters
.Others
.Argument2
= NULL
;
610 IoStack
->MajorFunction
= IRP_MJ_INTERNAL_DEVICE_CONTROL
;
611 IoStack
->Parameters
.DeviceIoControl
.IoControlCode
= IOCTL_INTERNAL_USB_SUBMIT_URB
;
613 IoSetCompletionRoutine(Irp
, UsbAudioCaptureComplete
, Pin
, TRUE
, TRUE
, TRUE
);
615 RtlZeroMemory(Urb
, GET_ISO_URB_SIZE(10));
618 Urb
->UrbIsochronousTransfer
.Hdr
.Function
= URB_FUNCTION_ISOCH_TRANSFER
;
619 Urb
->UrbIsochronousTransfer
.Hdr
.Length
= GET_ISO_URB_SIZE(10);
620 Urb
->UrbIsochronousTransfer
.PipeHandle
= PinContext
->DeviceExtension
->InterfaceInfo
->Pipes
[0].PipeHandle
;
621 Urb
->UrbIsochronousTransfer
.TransferFlags
= USBD_TRANSFER_DIRECTION_IN
| USBD_START_ISO_TRANSFER_ASAP
;
622 Urb
->UrbIsochronousTransfer
.TransferBufferLength
= PinContext
->DeviceExtension
->InterfaceInfo
->Pipes
[0].MaximumPacketSize
* 10;
623 Urb
->UrbIsochronousTransfer
.TransferBuffer
= TransferBuffer
;
624 Urb
->UrbIsochronousTransfer
.NumberOfPackets
= 10;
626 for (Index
= 0; Index
< 10; Index
++)
628 Urb
->UrbIsochronousTransfer
.IsoPacket
[Index
].Offset
= Index
* 100;
631 IoCallDriver(PinContext
->DeviceExtension
->LowerDevice
, Irp
);
633 /* acquire spin lock */
634 KeAcquireSpinLock(&PinContext
->IrpListLock
, &OldLevel
);
639 KeReleaseSpinLock(&PinContext
->IrpListLock
, OldLevel
);
641 if (LeadingStreamPointer
!= NULL
)
642 KsStreamPointerUnlock(LeadingStreamPointer
, FALSE
);
644 return STATUS_SUCCESS
;
655 if (Pin
->DataFlow
== KSPIN_DATAFLOW_OUT
)
657 Status
= PinCaptureProcess(Pin
);
662 Status
= STATUS_NOT_IMPLEMENTED
;
679 USBAudioPinSetDataFormat(
681 _In_opt_ PKSDATAFORMAT OldFormat
,
682 _In_opt_ PKSMULTIPLE_ITEM OldAttributeList
,
683 _In_
const KSDATARANGE
* DataRange
,
684 _In_opt_
const KSATTRIBUTE_LIST
* AttributeRange
)
686 if (OldFormat
== NULL
)
688 /* TODO: verify connection format */
690 return STATUS_SUCCESS
;
693 return UsbAudioSetFormat(Pin
);
697 StartCaptureIsocTransfer(
700 PPIN_CONTEXT PinContext
;
701 PLIST_ENTRY CurEntry
;
704 PIO_STACK_LOCATION IoStack
;
708 /* get pin context */
709 PinContext
= Pin
->Context
;
711 /* acquire spin lock */
712 KeAcquireSpinLock(&PinContext
->IrpListLock
, &OldLevel
);
714 while(!IsListEmpty(&PinContext
->IrpListHead
))
716 /* remove entry from list */
717 CurEntry
= RemoveHeadList(&PinContext
->IrpListHead
);
720 Irp
= (PIRP
)CONTAINING_RECORD(CurEntry
, IRP
, Tail
.Overlay
.ListEntry
);
723 /* get next stack location */
724 IoStack
= IoGetNextIrpStackLocation(Irp
);
726 /* init stack location */
727 IoStack
->MajorFunction
= IRP_MJ_INTERNAL_DEVICE_CONTROL
;
728 IoStack
->Parameters
.DeviceIoControl
.IoControlCode
= IOCTL_INTERNAL_USB_SUBMIT_URB
;
731 Urb
= Irp
->Tail
.Overlay
.DriverContext
[0] = IoStack
->Parameters
.Others
.Argument1
;
733 IoSetCompletionRoutine(Irp
, UsbAudioCaptureComplete
, Pin
, TRUE
, TRUE
, TRUE
);
736 KeReleaseSpinLock(&PinContext
->IrpListLock
, OldLevel
);
738 DPRINT("StartCaptureIsocTransfer Irp %p Urb %p TransferBuffer %p\n", Irp
, Urb
, Urb
->UrbIsochronousTransfer
.TransferBuffer
);
739 Status
= IoCallDriver(PinContext
->DeviceExtension
->LowerDevice
, Irp
);
741 /* acquire spin lock */
742 KeAcquireSpinLock(&PinContext
->IrpListLock
, &OldLevel
);
747 KeReleaseSpinLock(&PinContext
->IrpListLock
, OldLevel
);
749 return STATUS_SUCCESS
;
753 CapturePinStateChange(
755 _In_ KSSTATE ToState
,
756 _In_ KSSTATE FromState
)
760 if (FromState
!= ToState
)
764 if (ToState
== KSSTATE_PAUSE
)
766 if (FromState
== KSSTATE_RUN
)
768 /* wait until pin processing is finished*/
773 if (ToState
== KSSTATE_RUN
)
775 Status
= StartCaptureIsocTransfer(Pin
);
786 USBAudioPinSetDeviceState(
788 _In_ KSSTATE ToState
,
789 _In_ KSSTATE FromState
)
793 if (Pin
->DataFlow
== KSPIN_DATAFLOW_OUT
)
795 /* handle capture state changes */
796 Status
= CapturePinStateChange(Pin
, ToState
, FromState
);
801 Status
= STATUS_NOT_IMPLEMENTED
;