1 /*
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.
6 * PROGRAMMERS:
7 * Johannes Anderwald (johannes.anderwald@reactos.org)
8 */
9
10 #include "usbaudio.h"
11
12 #define PACKET_COUNT 10
13
14
15 NTSTATUS
GetMaxPacketSizeForInterface(IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor,IN PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor,KSPIN_DATAFLOW DataFlow)16 GetMaxPacketSizeForInterface(
17 IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor,
18 IN PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor,
19 KSPIN_DATAFLOW DataFlow)
20 {
21 PUSB_COMMON_DESCRIPTOR CommonDescriptor;
22 PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor;
23
24 /* loop descriptors */
25 CommonDescriptor = (PUSB_COMMON_DESCRIPTOR)((ULONG_PTR)InterfaceDescriptor + InterfaceDescriptor->bLength);
26 ASSERT(InterfaceDescriptor->bNumEndpoints > 0);
27 while (CommonDescriptor)
28 {
29 if (CommonDescriptor->bDescriptorType == USB_ENDPOINT_DESCRIPTOR_TYPE)
30 {
31 EndpointDescriptor = (PUSB_ENDPOINT_DESCRIPTOR)CommonDescriptor;
32 return EndpointDescriptor->wMaxPacketSize;
33 }
34
35 if (CommonDescriptor->bDescriptorType == USB_INTERFACE_DESCRIPTOR_TYPE)
36 {
37 /* reached next interface descriptor */
38 break;
39 }
40
41 if ((ULONG_PTR)CommonDescriptor + CommonDescriptor->bLength >= ((ULONG_PTR)ConfigurationDescriptor + ConfigurationDescriptor->wTotalLength))
42 break;
43
44 CommonDescriptor = (PUSB_COMMON_DESCRIPTOR)((ULONG_PTR)CommonDescriptor + CommonDescriptor->bLength);
45 }
46
47 /* default to 100 */
48 return 100;
49 }
50
51 NTSTATUS
UsbAudioAllocCaptureUrbIso(IN USBD_PIPE_HANDLE PipeHandle,IN ULONG MaxPacketSize,IN PVOID Buffer,IN ULONG BufferLength,OUT PURB * OutUrb)52 UsbAudioAllocCaptureUrbIso(
53 IN USBD_PIPE_HANDLE PipeHandle,
54 IN ULONG MaxPacketSize,
55 IN PVOID Buffer,
56 IN ULONG BufferLength,
57 OUT PURB * OutUrb)
58 {
59 PURB Urb;
60 ULONG UrbSize;
61 ULONG Index;
62
63 /* calculate urb size*/
64 UrbSize = GET_ISO_URB_SIZE(PACKET_COUNT);
65
66 /* allocate urb */
67 Urb = AllocFunction(UrbSize);
68 if (!Urb)
69 {
70 /* no memory */
71 return STATUS_INSUFFICIENT_RESOURCES;
72 }
73
74 /* init urb */
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;
82
83 for (Index = 0; Index < PACKET_COUNT; Index++)
84 {
85 Urb->UrbIsochronousTransfer.IsoPacket[Index].Offset = Index * MaxPacketSize;
86 }
87
88 *OutUrb = Urb;
89 return STATUS_SUCCESS;
90
91 }
92
93 NTSTATUS
UsbAudioSetFormat(IN PKSPIN Pin)94 UsbAudioSetFormat(
95 IN PKSPIN Pin)
96 {
97 PURB Urb;
98 PUCHAR SampleRateBuffer;
99 PPIN_CONTEXT PinContext;
100 NTSTATUS Status;
101 PKSDATAFORMAT_WAVEFORMATEX WaveFormatEx;
102
103 /* allocate sample rate buffer */
104 SampleRateBuffer = AllocFunction(sizeof(ULONG));
105 if (!SampleRateBuffer)
106 {
107 /* no memory */
108 return STATUS_INSUFFICIENT_RESOURCES;
109 }
110
111 if (IsEqualGUIDAligned(&Pin->ConnectionFormat->MajorFormat, &KSDATAFORMAT_TYPE_AUDIO) &&
112 IsEqualGUIDAligned(&Pin->ConnectionFormat->SubFormat, &KSDATAFORMAT_SUBTYPE_PCM) &&
113 IsEqualGUIDAligned(&Pin->ConnectionFormat->Specifier, &KSDATAFORMAT_SPECIFIER_WAVEFORMATEX))
114 {
115 WaveFormatEx = (PKSDATAFORMAT_WAVEFORMATEX)Pin->ConnectionFormat;
116 SampleRateBuffer[2] = (WaveFormatEx->WaveFormatEx.nSamplesPerSec >> 16) & 0xFF;
117 SampleRateBuffer[1] = (WaveFormatEx->WaveFormatEx.nSamplesPerSec >> 8) & 0xFF;
118 SampleRateBuffer[0] = (WaveFormatEx->WaveFormatEx.nSamplesPerSec >> 0) & 0xFF;
119
120 /* TODO: verify connection format */
121 }
122 else
123 {
124 /* not supported yet*/
125 UNIMPLEMENTED;
126 FreeFunction(SampleRateBuffer);
127 return STATUS_INVALID_PARAMETER;
128 }
129
130 /* allocate urb */
131 Urb = AllocFunction(sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST));
132 if (!Urb)
133 {
134 /* no memory */
135 FreeFunction(SampleRateBuffer);
136 return STATUS_INSUFFICIENT_RESOURCES;
137 }
138
139 /* get pin context */
140 PinContext = Pin->Context;
141
142 /* FIXME: determine controls and format urb */
143 UsbBuildVendorRequest(Urb,
144 URB_FUNCTION_CLASS_ENDPOINT,
145 sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST),
146 USBD_TRANSFER_DIRECTION_OUT,
147 0,
148 0x01, // SET_CUR
149 0x100,
150 PinContext->DeviceExtension->InterfaceInfo->Pipes[0].EndpointAddress,
151 SampleRateBuffer,
152 NULL,
153 3,
154 NULL);
155
156
157
158 /* submit urb */
159 Status = SubmitUrbSync(PinContext->LowerDevice, Urb);
160
161 DPRINT1("USBAudioPinSetDataFormat Pin %p Status %x\n", Pin, Status);
162 FreeFunction(Urb);
163 FreeFunction(SampleRateBuffer);
164 return Status;
165 }
166
167 NTSTATUS
USBAudioSelectAudioStreamingInterface(IN PKSPIN Pin,IN PPIN_CONTEXT PinContext,IN PDEVICE_EXTENSION DeviceExtension,IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor,IN ULONG FormatDescriptorIndex)168 USBAudioSelectAudioStreamingInterface(
169 IN PKSPIN Pin,
170 IN PPIN_CONTEXT PinContext,
171 IN PDEVICE_EXTENSION DeviceExtension,
172 IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor,
173 IN ULONG FormatDescriptorIndex)
174 {
175 PURB Urb;
176 PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor;
177 NTSTATUS Status;
178 ULONG Found, Index;
179
180 PUSB_AUDIO_STREAMING_INTERFACE_DESCRIPTOR StreamingInterfaceDescriptor;
181 PUSB_AUDIO_CONTROL_INPUT_TERMINAL_DESCRIPTOR TerminalDescriptor = NULL;
182
183 /* search for terminal descriptor of that irp sink / irp source */
184 TerminalDescriptor = UsbAudioGetStreamingTerminalDescriptorByIndex(DeviceExtension->ConfigurationDescriptor, Pin->Id);
185 ASSERT(TerminalDescriptor != NULL);
186
187 /* grab interface descriptor */
188 InterfaceDescriptor = USBD_ParseConfigurationDescriptorEx(ConfigurationDescriptor, ConfigurationDescriptor, -1, -1, USB_DEVICE_CLASS_AUDIO, -1, -1);
189 if (!InterfaceDescriptor)
190 {
191 /* no such interface */
192 return STATUS_INVALID_PARAMETER;
193 }
194
195 Found = FALSE;
196 Index = 0;
197
198 /* selects the interface which has an audio streaming interface descriptor associated to the input / output terminal at the given format index */
199 while (InterfaceDescriptor != NULL)
200 {
201 if (InterfaceDescriptor->bInterfaceSubClass == 0x02 /* AUDIO_STREAMING */ && InterfaceDescriptor->bNumEndpoints > 0)
202 {
203 StreamingInterfaceDescriptor = (PUSB_AUDIO_STREAMING_INTERFACE_DESCRIPTOR)USBD_ParseDescriptors(ConfigurationDescriptor, ConfigurationDescriptor->wTotalLength, InterfaceDescriptor, USB_AUDIO_CONTROL_TERMINAL_DESCRIPTOR_TYPE);
204 if (StreamingInterfaceDescriptor != NULL)
205 {
206 ASSERT(StreamingInterfaceDescriptor->bDescriptorSubtype == 0x01);
207 ASSERT(StreamingInterfaceDescriptor->wFormatTag == WAVE_FORMAT_PCM);
208 if (StreamingInterfaceDescriptor->bTerminalLink == TerminalDescriptor->bTerminalID)
209 {
210 if (FormatDescriptorIndex == Index)
211 {
212 Found = TRUE;
213 break;
214 }
215 Index++;
216 }
217 }
218 }
219 InterfaceDescriptor = USBD_ParseConfigurationDescriptorEx(ConfigurationDescriptor, (PVOID)((ULONG_PTR)InterfaceDescriptor + InterfaceDescriptor->bLength), -1, -1, USB_DEVICE_CLASS_AUDIO, -1, -1);
220 }
221
222 if (!Found)
223 {
224 /* no such interface */
225 DPRINT1("No Interface found\n");
226 return STATUS_INVALID_PARAMETER;
227 }
228
229 Urb = AllocFunction(GET_SELECT_INTERFACE_REQUEST_SIZE(InterfaceDescriptor->bNumEndpoints));
230 if (!Urb)
231 {
232 /* no memory */
233 return STATUS_INSUFFICIENT_RESOURCES;
234 }
235
236 /* now prepare interface urb */
237 UsbBuildSelectInterfaceRequest(Urb, GET_SELECT_INTERFACE_REQUEST_SIZE(InterfaceDescriptor->bNumEndpoints), DeviceExtension->ConfigurationHandle, InterfaceDescriptor->bInterfaceNumber, InterfaceDescriptor->bAlternateSetting);
238
239 /* now select the interface */
240 Status = SubmitUrbSync(DeviceExtension->LowerDevice, Urb);
241
242 DPRINT1("USBAudioSelectAudioStreamingInterface Status %x UrbStatus %x InterfaceNumber %x AlternateSetting %x\n", Status, Urb->UrbSelectInterface.Hdr.Status, InterfaceDescriptor->bInterfaceNumber, InterfaceDescriptor->bAlternateSetting);
243
244 /* did it succeeed */
245 if (NT_SUCCESS(Status))
246 {
247 /* free old interface info */
248 if (DeviceExtension->InterfaceInfo)
249 {
250 /* free old info */
251 FreeFunction(DeviceExtension->InterfaceInfo);
252 }
253
254 /* alloc interface info */
255 DeviceExtension->InterfaceInfo = AllocFunction(Urb->UrbSelectInterface.Interface.Length);
256 if (DeviceExtension->InterfaceInfo == NULL)
257 {
258 /* no memory */
259 FreeFunction(Urb);
260 return STATUS_INSUFFICIENT_RESOURCES;
261 }
262
263 /* copy interface info */
264 RtlCopyMemory(DeviceExtension->InterfaceInfo, &Urb->UrbSelectInterface.Interface, Urb->UrbSelectInterface.Interface.Length);
265 PinContext->InterfaceDescriptor = InterfaceDescriptor;
266 }
267
268 /* free urb */
269 FreeFunction(Urb);
270 return Status;
271 }
272
273 VOID
274 NTAPI
CaptureGateOnWorkItem(_In_ PVOID Context)275 CaptureGateOnWorkItem(
276 _In_ PVOID Context)
277 {
278 PKSPIN Pin;
279 PPIN_CONTEXT PinContext;
280 PKSGATE Gate;
281 ULONG Count;
282
283 /* get pin */
284 Pin = Context;
285
286 /* get pin context */
287 PinContext = Pin->Context;
288
289 do
290 {
291 /* acquire processing mutex */
292 KsPinAcquireProcessingMutex(Pin);
293
294 /* get pin control gate */
295 Gate = KsPinGetAndGate(Pin);
296
297 /* turn input on */
298 KsGateTurnInputOn(Gate);
299
300 /* schedule processing */
301 KsPinAttemptProcessing(Pin, TRUE);
302
303 /* release processing mutex */
304 KsPinReleaseProcessingMutex(Pin);
305
306 /* decrement worker count */
307 Count = KsDecrementCountedWorker(PinContext->CaptureWorker);
308 } while (Count);
309 }
310
311 NTSTATUS
RenderInitializeUrbAndIrp(IN PKSPIN Pin,IN PPIN_CONTEXT PinContext,IN OUT PIRP Irp,IN PVOID TransferBuffer,IN ULONG TransferBufferSize,IN ULONG PacketSize)312 RenderInitializeUrbAndIrp(
313 IN PKSPIN Pin,
314 IN PPIN_CONTEXT PinContext,
315 IN OUT PIRP Irp,
316 IN PVOID TransferBuffer,
317 IN ULONG TransferBufferSize,
318 IN ULONG PacketSize)
319 {
320 ULONG Index, PacketCount;
321 PURB Urb;
322 PIO_STACK_LOCATION IoStack;
323
324 /* initialize irp */
325 IoInitializeIrp(Irp, IoSizeOfIrp(PinContext->DeviceExtension->LowerDevice->StackSize), PinContext->DeviceExtension->LowerDevice->StackSize);
326
327 /* set irp members */
328 Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
329 Irp->IoStatus.Information = 0;
330 Irp->Flags = 0;
331 Irp->UserBuffer = NULL;
332
333 /* init stack location */
334 IoStack = IoGetNextIrpStackLocation(Irp);
335 IoStack->DeviceObject = PinContext->DeviceExtension->LowerDevice;
336 IoStack->Parameters.Others.Argument2 = NULL;
337 IoStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
338 IoStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_SUBMIT_URB;
339
340 /* set completion routine */
341 IoSetCompletionRoutine(Irp, UsbAudioRenderComplete, Pin, TRUE, TRUE, TRUE);
342
343 /* calculate packet count */
344 PacketCount = TransferBufferSize / PacketSize;
345 ASSERT(TransferBufferSize % PacketSize == 0);
346
347 /* lets allocate urb */
348 Urb = (PURB)AllocFunction(GET_ISO_URB_SIZE(PacketCount));
349 if (!Urb)
350 {
351 /* no memory */
352 return STATUS_INSUFFICIENT_RESOURCES;
353 }
354
355 /* init urb */
356 Urb->UrbIsochronousTransfer.Hdr.Function = URB_FUNCTION_ISOCH_TRANSFER;
357 Urb->UrbIsochronousTransfer.Hdr.Length = GET_ISO_URB_SIZE(PacketCount);
358 Urb->UrbIsochronousTransfer.PipeHandle = PinContext->DeviceExtension->InterfaceInfo->Pipes[0].PipeHandle;
359 Urb->UrbIsochronousTransfer.TransferFlags = USBD_TRANSFER_DIRECTION_OUT | USBD_START_ISO_TRANSFER_ASAP;
360 Urb->UrbIsochronousTransfer.TransferBufferLength = TransferBufferSize;
361 Urb->UrbIsochronousTransfer.TransferBuffer = TransferBuffer;
362 Urb->UrbIsochronousTransfer.NumberOfPackets = PacketCount;
363 Urb->UrbIsochronousTransfer.StartFrame = 0;
364
365 for (Index = 0; Index < PacketCount; Index++)
366 {
367 Urb->UrbIsochronousTransfer.IsoPacket[Index].Offset = Index * PacketSize;
368 }
369
370 /* store urb */
371 IoStack->Parameters.Others.Argument1 = Urb;
372 Irp->Tail.Overlay.DriverContext[0] = Urb;
373
374
375 /* done */
376 return STATUS_SUCCESS;
377 }
378
379 VOID
CaptureInitializeUrbAndIrp(IN PKSPIN Pin,IN PIRP Irp)380 CaptureInitializeUrbAndIrp(
381 IN PKSPIN Pin,
382 IN PIRP Irp)
383 {
384 PIO_STACK_LOCATION IoStack;
385 PURB Urb;
386 PUCHAR TransferBuffer;
387 ULONG Index;
388 PPIN_CONTEXT PinContext;
389
390 /* get pin context */
391 PinContext = Pin->Context;
392
393 /* backup urb and transferbuffer */
394 Urb = Irp->Tail.Overlay.DriverContext[0];
395 TransferBuffer = Urb->UrbIsochronousTransfer.TransferBuffer;
396
397 /* initialize irp */
398 IoInitializeIrp(Irp, IoSizeOfIrp(PinContext->DeviceExtension->LowerDevice->StackSize), PinContext->DeviceExtension->LowerDevice->StackSize);
399
400 Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
401 Irp->IoStatus.Information = 0;
402 Irp->Flags = 0;
403 Irp->UserBuffer = NULL;
404 Irp->Tail.Overlay.DriverContext[0] = Urb;
405 Irp->Tail.Overlay.DriverContext[1] = NULL;
406
407 /* init stack location */
408 IoStack = IoGetNextIrpStackLocation(Irp);
409 IoStack->DeviceObject = PinContext->DeviceExtension->LowerDevice;
410 IoStack->Parameters.Others.Argument1 = Urb;
411 IoStack->Parameters.Others.Argument2 = NULL;
412 IoStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
413 IoStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_SUBMIT_URB;
414
415 IoSetCompletionRoutine(Irp, UsbAudioCaptureComplete, Pin, TRUE, TRUE, TRUE);
416
417 RtlZeroMemory(Urb, GET_ISO_URB_SIZE(PACKET_COUNT));
418
419 /* init urb */
420 Urb->UrbIsochronousTransfer.Hdr.Function = URB_FUNCTION_ISOCH_TRANSFER;
421 Urb->UrbIsochronousTransfer.Hdr.Length = GET_ISO_URB_SIZE(10);
422 Urb->UrbIsochronousTransfer.PipeHandle = PinContext->DeviceExtension->InterfaceInfo->Pipes[0].PipeHandle;
423 Urb->UrbIsochronousTransfer.TransferFlags = USBD_TRANSFER_DIRECTION_IN | USBD_START_ISO_TRANSFER_ASAP;
424 Urb->UrbIsochronousTransfer.TransferBufferLength = PinContext->DeviceExtension->InterfaceInfo->Pipes[0].MaximumPacketSize * 10;
425 Urb->UrbIsochronousTransfer.TransferBuffer = TransferBuffer;
426 Urb->UrbIsochronousTransfer.NumberOfPackets = PACKET_COUNT;
427 Urb->UrbIsochronousTransfer.StartFrame = 0;
428
429 for (Index = 0; Index < PACKET_COUNT; Index++)
430 {
431 Urb->UrbIsochronousTransfer.IsoPacket[Index].Offset = Index * PinContext->DeviceExtension->InterfaceInfo->Pipes[0].MaximumPacketSize;
432 }
433 }
434
435
436 VOID
437 NTAPI
CaptureAvoidPipeStarvationWorker(_In_ PVOID Context)438 CaptureAvoidPipeStarvationWorker(
439 _In_ PVOID Context)
440 {
441 PKSPIN Pin;
442 PPIN_CONTEXT PinContext;
443 KIRQL OldLevel;
444 PLIST_ENTRY CurEntry;
445 PIRP Irp;
446
447 /* get pin */
448 Pin = Context;
449
450 /* get pin context */
451 PinContext = Pin->Context;
452
453 /* acquire spin lock */
454 KeAcquireSpinLock(&PinContext->IrpListLock, &OldLevel);
455
456 if (!IsListEmpty(&PinContext->IrpListHead))
457 {
458 /* sanity check */
459 ASSERT(!IsListEmpty(&PinContext->IrpListHead));
460
461 /* remove entry from list */
462 CurEntry = RemoveHeadList(&PinContext->IrpListHead);
463
464 /* release lock */
465 KeReleaseSpinLock(&PinContext->IrpListLock, OldLevel);
466
467 /* get irp offset */
468 Irp = (PIRP)CONTAINING_RECORD(CurEntry, IRP, Tail.Overlay.ListEntry);
469
470 /* reinitialize irp and urb */
471 CaptureInitializeUrbAndIrp(Pin, Irp);
472
473 KsDecrementCountedWorker(PinContext->StarvationWorker);
474
475 /* call driver */
476 IoCallDriver(PinContext->DeviceExtension->LowerDevice, Irp);
477 }
478 else
479 {
480 /* release lock */
481 KeReleaseSpinLock(&PinContext->IrpListLock, OldLevel);
482
483 KsDecrementCountedWorker(PinContext->StarvationWorker);
484 }
485 }
486
487
488
489 NTSTATUS
InitCapturePin(IN PKSPIN Pin)490 InitCapturePin(
491 IN PKSPIN Pin)
492 {
493 NTSTATUS Status;
494 ULONG Index;
495 ULONG BufferSize;
496 ULONG MaximumPacketSize;
497 PIRP Irp;
498 PURB Urb;
499 PPIN_CONTEXT PinContext;
500 PIO_STACK_LOCATION IoStack;
501 PKSALLOCATOR_FRAMING_EX Framing;
502 PKSGATE Gate;
503
504
505 /* set sample rate */
506 Status = UsbAudioSetFormat(Pin);
507 if (!NT_SUCCESS(Status))
508 {
509 /* failed */
510 return Status;
511 }
512
513 /* get pin context */
514 PinContext = Pin->Context;
515
516 /* lets get maximum packet size */
517 MaximumPacketSize = GetMaxPacketSizeForInterface(PinContext->DeviceExtension->ConfigurationDescriptor, PinContext->InterfaceDescriptor, Pin->DataFlow);
518
519 /* initialize work item for capture worker */
520 ExInitializeWorkItem(&PinContext->CaptureWorkItem, CaptureGateOnWorkItem, (PVOID)Pin);
521
522 /* register worker */
523 Status = KsRegisterCountedWorker(CriticalWorkQueue, &PinContext->CaptureWorkItem, &PinContext->CaptureWorker);
524 if (!NT_SUCCESS(Status))
525 {
526 /* failed */
527 return Status;
528 }
529
530 /* initialize work item */
531 ExInitializeWorkItem(&PinContext->StarvationWorkItem, CaptureAvoidPipeStarvationWorker, (PVOID)Pin);
532
533 /* register worker */
534 Status = KsRegisterCountedWorker(CriticalWorkQueue, &PinContext->StarvationWorkItem, &PinContext->StarvationWorker);
535 if (!NT_SUCCESS(Status))
536 {
537 /* failed */
538 KsUnregisterWorker(PinContext->CaptureWorker);
539 }
540
541 /* lets edit framing struct */
542 Framing = (PKSALLOCATOR_FRAMING_EX)Pin->Descriptor->AllocatorFraming;
543 Framing->FramingItem[0].PhysicalRange.MinFrameSize =
544 Framing->FramingItem[0].PhysicalRange.MaxFrameSize =
545 Framing->FramingItem[0].FramingRange.Range.MinFrameSize =
546 Framing->FramingItem[0].FramingRange.Range.MaxFrameSize =
547 MaximumPacketSize;
548
549 /* calculate buffer size 8 irps * 10 iso packets * max packet size */
550 BufferSize = 8 * PACKET_COUNT * MaximumPacketSize;
551
552 /* allocate pin capture buffer */
553 PinContext->BufferSize = BufferSize;
554 PinContext->Buffer = AllocFunction(BufferSize);
555 if (!PinContext->Buffer)
556 {
557 /* no memory */
558 return STATUS_INSUFFICIENT_RESOURCES;
559 }
560 KsAddItemToObjectBag(Pin->Bag, PinContext->Buffer, ExFreePool);
561
562 /* init irps */
563 for (Index = 0; Index < 8; Index++)
564 {
565 /* allocate irp */
566 Irp = AllocFunction(IoSizeOfIrp(PinContext->DeviceExtension->LowerDevice->StackSize));
567 if (!Irp)
568 {
569 /* no memory */
570 return STATUS_INSUFFICIENT_RESOURCES;
571 }
572
573 /* initialize irp */
574 IoInitializeIrp(Irp, IoSizeOfIrp(PinContext->DeviceExtension->LowerDevice->StackSize), PinContext->DeviceExtension->LowerDevice->StackSize);
575
576 Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
577 Irp->IoStatus.Information = 0;
578 Irp->Flags = 0;
579 Irp->UserBuffer = NULL;
580
581 IoStack = IoGetNextIrpStackLocation(Irp);
582 IoStack->DeviceObject = PinContext->DeviceExtension->LowerDevice;
583 IoStack->Parameters.Others.Argument2 = NULL;
584 IoStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
585 IoStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_SUBMIT_URB;
586
587 IoSetCompletionRoutine(Irp, UsbAudioCaptureComplete, Pin, TRUE, TRUE, TRUE);
588
589 /* insert into irp list */
590 InsertTailList(&PinContext->IrpListHead, &Irp->Tail.Overlay.ListEntry);
591
592 /* add to object bag*/
593 KsAddItemToObjectBag(Pin->Bag, Irp, ExFreePool);
594
595 /* FIXME select correct pipe handle */
596 Status = UsbAudioAllocCaptureUrbIso(PinContext->DeviceExtension->InterfaceInfo->Pipes[0].PipeHandle,
597 MaximumPacketSize,
598 &PinContext->Buffer[MaximumPacketSize * PACKET_COUNT * Index],
599 MaximumPacketSize * PACKET_COUNT,
600 &Urb);
601
602 DPRINT1("InitCapturePin Irp %p Urb %p\n", Irp, Urb);
603
604 if (NT_SUCCESS(Status))
605 {
606 /* get next stack location */
607 IoStack = IoGetNextIrpStackLocation(Irp);
608
609 /* store urb */
610 IoStack->Parameters.Others.Argument1 = Urb;
611 Irp->Tail.Overlay.DriverContext[0] = Urb;
612 }
613 else
614 {
615 /* failed */
616 return Status;
617 }
618 }
619
620 /* get process control gate */
621 Gate = KsPinGetAndGate(Pin);
622
623 /* turn input off */
624 KsGateTurnInputOff(Gate);
625
626 return Status;
627 }
628
629 NTSTATUS
InitStreamPin(IN PKSPIN Pin)630 InitStreamPin(
631 IN PKSPIN Pin)
632 {
633 ULONG Index;
634 PIRP Irp;
635 PPIN_CONTEXT PinContext;
636 PKSDATAFORMAT_WAVEFORMATEX WaveFormatEx;
637 PIO_STACK_LOCATION IoStack;
638
639 DPRINT1("InitStreamPin\n");
640
641 /* get pin context */
642 PinContext = Pin->Context;
643
644 /* allocate 1 sec buffer */
645 WaveFormatEx = (PKSDATAFORMAT_WAVEFORMATEX)Pin->ConnectionFormat;
646 PinContext->Buffer = AllocFunction(WaveFormatEx->WaveFormatEx.nAvgBytesPerSec);
647 if (!PinContext->Buffer)
648 {
649 /* no memory */
650 return STATUS_INSUFFICIENT_RESOURCES;
651 }
652
653 /* init buffer size*/
654 PinContext->BufferSize = WaveFormatEx->WaveFormatEx.nAvgBytesPerSec;
655 PinContext->BufferOffset = 0;
656 PinContext->BufferLength = 0;
657
658 /* init irps */
659 for (Index = 0; Index < 12; Index++)
660 {
661 /* allocate irp */
662 Irp = AllocFunction(IoSizeOfIrp(PinContext->DeviceExtension->LowerDevice->StackSize));
663 if (!Irp)
664 {
665 /* no memory */
666 return STATUS_INSUFFICIENT_RESOURCES;
667 }
668
669 DPRINT1("InitStreamPin Irp %p\n", Irp);
670
671 /* initialize irp */
672 IoInitializeIrp(Irp, IoSizeOfIrp(PinContext->DeviceExtension->LowerDevice->StackSize), PinContext->DeviceExtension->LowerDevice->StackSize);
673
674 Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
675 Irp->IoStatus.Information = 0;
676 Irp->Flags = 0;
677 Irp->UserBuffer = NULL;
678
679 IoStack = IoGetNextIrpStackLocation(Irp);
680 IoStack->DeviceObject = PinContext->DeviceExtension->LowerDevice;
681 IoStack->Parameters.Others.Argument2 = NULL;
682 IoStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
683 IoStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_SUBMIT_URB;
684
685 IoSetCompletionRoutine(Irp, UsbAudioRenderComplete, Pin, TRUE, TRUE, TRUE);
686
687 /* insert into irp list */
688 InsertTailList(&PinContext->IrpListHead, &Irp->Tail.Overlay.ListEntry);
689
690 /* add to object bag*/
691 KsAddItemToObjectBag(Pin->Bag, Irp, ExFreePool);
692 }
693
694 return STATUS_SUCCESS;
695 }
696
697 ULONG
GetDataRangeIndexForFormat(IN PKSDATARANGE ConnectionFormat,IN const PKSDATARANGE * DataRanges,IN ULONG DataRangesCount)698 GetDataRangeIndexForFormat(
699 IN PKSDATARANGE ConnectionFormat,
700 IN const PKSDATARANGE * DataRanges,
701 IN ULONG DataRangesCount)
702 {
703 ULONG Index;
704 PKSDATARANGE CurrentDataRange;
705 PKSDATARANGE_AUDIO CurrentAudioDataRange;
706 PKSDATAFORMAT_WAVEFORMATEX ConnectionDataFormat;
707
708 if (ConnectionFormat->FormatSize != sizeof(KSDATAFORMAT) + sizeof(WAVEFORMATEX))
709 {
710 /* unsupported connection format */
711 DPRINT1("GetDataRangeIndexForFormat expected KSDATARANGE_AUDIO\n");
712 return MAXULONG;
713 }
714
715 /* cast to right type */
716 ConnectionDataFormat = (PKSDATAFORMAT_WAVEFORMATEX)ConnectionFormat;
717
718 for (Index = 0; Index < DataRangesCount; Index++)
719 {
720 /* get current data range */
721 CurrentDataRange = DataRanges[Index];
722
723 /* compare guids */
724 if (!IsEqualGUIDAligned(&CurrentDataRange->MajorFormat, &ConnectionFormat->MajorFormat) ||
725 !IsEqualGUIDAligned(&CurrentDataRange->SubFormat, &ConnectionFormat->SubFormat) ||
726 !IsEqualGUIDAligned(&CurrentDataRange->Specifier, &ConnectionFormat->Specifier))
727 {
728 /* no match */
729 continue;
730 }
731
732 /* all pin data ranges are KSDATARANGE_AUDIO */
733 CurrentAudioDataRange = (PKSDATARANGE_AUDIO)CurrentDataRange;
734
735 /* check if number of channel match */
736 if (CurrentAudioDataRange->MaximumChannels != ConnectionDataFormat->WaveFormatEx.nChannels)
737 {
738 /* number of channels mismatch */
739 continue;
740 }
741
742 if (CurrentAudioDataRange->MinimumSampleFrequency > ConnectionDataFormat->WaveFormatEx.nSamplesPerSec)
743 {
744 /* channel frequency too low */
745 continue;
746 }
747
748 if (CurrentAudioDataRange->MaximumSampleFrequency < ConnectionDataFormat->WaveFormatEx.nSamplesPerSec)
749 {
750 /* channel frequency too high */
751 continue;
752 }
753
754 /* FIXME add checks for bitrate / sample size etc */
755 return Index;
756 }
757
758 /* no datarange found */
759 return MAXULONG;
760 }
761
762 NTSTATUS
763 NTAPI
USBAudioPinCreate(_In_ PKSPIN Pin,_In_ PIRP Irp)764 USBAudioPinCreate(
765 _In_ PKSPIN Pin,
766 _In_ PIRP Irp)
767 {
768 PKSFILTER Filter;
769 PFILTER_CONTEXT FilterContext;
770 PPIN_CONTEXT PinContext;
771 NTSTATUS Status;
772 ULONG FormatIndex;
773
774 Filter = KsPinGetParentFilter(Pin);
775 if (Filter == NULL)
776 {
777 /* invalid parameter */
778 return STATUS_INVALID_PARAMETER;
779 }
780
781 /* get filter context */
782 FilterContext = Filter->Context;
783
784 /* allocate pin context */
785 PinContext = AllocFunction(sizeof(PIN_CONTEXT));
786 if (!PinContext)
787 {
788 /* no memory*/
789 return STATUS_INSUFFICIENT_RESOURCES;
790 }
791
792 /* init pin context */
793 PinContext->DeviceExtension = FilterContext->DeviceExtension;
794 PinContext->LowerDevice = FilterContext->LowerDevice;
795 InitializeListHead(&PinContext->IrpListHead);
796 InitializeListHead(&PinContext->DoneIrpListHead);
797 KeInitializeSpinLock(&PinContext->IrpListLock);
798
799 /* store pin context*/
800 Pin->Context = PinContext;
801
802 /* lets edit allocator framing struct */
803 Status = _KsEdit(Pin->Bag, (PVOID*)&Pin->Descriptor, sizeof(KSPIN_DESCRIPTOR_EX), sizeof(KSPIN_DESCRIPTOR_EX), USBAUDIO_TAG);
804 if (NT_SUCCESS(Status))
805 {
806 Status = _KsEdit(Pin->Bag, (PVOID*)&Pin->Descriptor->AllocatorFraming, sizeof(KSALLOCATOR_FRAMING_EX), sizeof(KSALLOCATOR_FRAMING_EX), USBAUDIO_TAG);
807 ASSERT(Status == STATUS_SUCCESS);
808 }
809
810 /* choose correct dataformat */
811 FormatIndex = GetDataRangeIndexForFormat(Pin->ConnectionFormat, Pin->Descriptor->PinDescriptor.DataRanges, Pin->Descriptor->PinDescriptor.DataRangesCount);
812 if (FormatIndex == MAXULONG)
813 {
814 /* no format match */
815 return STATUS_NO_MATCH;
816 }
817
818 /* select streaming interface */
819 Status = USBAudioSelectAudioStreamingInterface(Pin, PinContext, PinContext->DeviceExtension, PinContext->DeviceExtension->ConfigurationDescriptor, FormatIndex);
820 if (!NT_SUCCESS(Status))
821 {
822 /* failed */
823 DPRINT1("USBAudioSelectAudioStreamingInterface failed with %x\n", Status);
824 return Status;
825 }
826
827 if (Pin->DataFlow == KSPIN_DATAFLOW_OUT)
828 {
829 /* init capture pin */
830 Status = InitCapturePin(Pin);
831 }
832 else
833 {
834 /* audio streaming pin*/
835 Status = InitStreamPin(Pin);
836 }
837
838 return Status;
839 }
840
841 NTSTATUS
842 NTAPI
USBAudioPinClose(_In_ PKSPIN Pin,_In_ PIRP Irp)843 USBAudioPinClose(
844 _In_ PKSPIN Pin,
845 _In_ PIRP Irp)
846 {
847 UNIMPLEMENTED;
848 return STATUS_NOT_IMPLEMENTED;
849 }
850
851 NTSTATUS
852 NTAPI
UsbAudioRenderComplete(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp,IN PVOID Context)853 UsbAudioRenderComplete(
854 IN PDEVICE_OBJECT DeviceObject,
855 IN PIRP Irp,
856 IN PVOID Context)
857 {
858 PKSPIN Pin;
859 PPIN_CONTEXT PinContext;
860 KIRQL OldLevel;
861 PKSSTREAM_POINTER StreamPointerClone;
862 NTSTATUS Status;
863 PURB Urb;
864
865 /* get pin context */
866 Pin = Context;
867 PinContext = Pin->Context;
868
869 /* get status */
870 Status = Irp->IoStatus.Status;
871
872 /* get streampointer */
873 StreamPointerClone = Irp->Tail.Overlay.DriverContext[1];
874
875 /* get urb */
876 Urb = Irp->Tail.Overlay.DriverContext[0];
877
878 /* and free it */
879 FreeFunction(Urb);
880
881 /* acquire lock */
882 KeAcquireSpinLock(&PinContext->IrpListLock, &OldLevel);
883
884 /* insert entry into ready list */
885 InsertTailList(&PinContext->IrpListHead, &Irp->Tail.Overlay.ListEntry);
886
887 /* release lock */
888 KeReleaseSpinLock(&PinContext->IrpListLock, OldLevel);
889
890 if (!NT_SUCCESS(Status) && StreamPointerClone)
891 {
892 /* set status code because it failed */
893 KsStreamPointerSetStatusCode(StreamPointerClone, STATUS_DEVICE_DATA_ERROR);
894 DPRINT1("UsbAudioRenderComplete failed with %x\n", Status);
895 }
896
897 if (StreamPointerClone)
898 {
899 /* lets delete the stream pointer clone */
900 KsStreamPointerDelete(StreamPointerClone);
901 }
902
903 /* done */
904 return STATUS_MORE_PROCESSING_REQUIRED;
905 }
906
907 NTSTATUS
908 NTAPI
UsbAudioCaptureComplete(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp,IN PVOID Context)909 UsbAudioCaptureComplete(
910 IN PDEVICE_OBJECT DeviceObject,
911 IN PIRP Irp,
912 IN PVOID Context)
913 {
914 PKSPIN Pin;
915 PPIN_CONTEXT PinContext;
916 KIRQL OldLevel;
917 PURB Urb;
918
919 /* get pin context */
920 Pin = Context;
921 PinContext = Pin->Context;
922
923 /* get urb */
924 Urb = Irp->Tail.Overlay.DriverContext[0];
925
926 /* acquire lock */
927 KeAcquireSpinLock(&PinContext->IrpListLock, &OldLevel);
928
929 if (!NT_SUCCESS(Urb->UrbIsochronousTransfer.Hdr.Status))
930 {
931 //DPRINT("UsbAudioCaptureComplete Irp %p Urb %p Status %x Packet Status %x\n", Irp, Urb, Urb->UrbIsochronousTransfer.Hdr.Status, Urb->UrbIsochronousTransfer.IsoPacket[0].Status);
932
933 /* insert entry into ready list */
934 InsertTailList(&PinContext->IrpListHead, &Irp->Tail.Overlay.ListEntry);
935
936 /* release lock */
937 KeReleaseSpinLock(&PinContext->IrpListLock, OldLevel);
938
939 KsIncrementCountedWorker(PinContext->StarvationWorker);
940 }
941 else
942 {
943 /* insert entry into done list */
944 InsertTailList(&PinContext->DoneIrpListHead, &Irp->Tail.Overlay.ListEntry);
945
946 /* release lock */
947 KeReleaseSpinLock(&PinContext->IrpListLock, OldLevel);
948
949 KsIncrementCountedWorker(PinContext->CaptureWorker);
950 }
951
952 /* done */
953 return STATUS_MORE_PROCESSING_REQUIRED;
954 }
955
956 PIRP
PinGetIrpFromReadyList(IN PKSPIN Pin)957 PinGetIrpFromReadyList(
958 IN PKSPIN Pin)
959 {
960 PPIN_CONTEXT PinContext;
961 PLIST_ENTRY CurEntry;
962 KIRQL OldLevel;
963 PIRP Irp = NULL;
964
965 /* get pin context */
966 PinContext = Pin->Context;
967
968 /* acquire spin lock */
969 KeAcquireSpinLock(&PinContext->IrpListLock, &OldLevel);
970
971 if (!IsListEmpty(&PinContext->IrpListHead))
972 {
973 /* remove entry from list */
974 CurEntry = RemoveHeadList(&PinContext->IrpListHead);
975
976 /* get irp offset */
977 Irp = (PIRP)CONTAINING_RECORD(CurEntry, IRP, Tail.Overlay.ListEntry);
978 }
979
980 /* release lock */
981 KeReleaseSpinLock(&PinContext->IrpListLock, OldLevel);
982
983 return Irp;
984 }
985
986 NTSTATUS
PinRenderProcess(IN PKSPIN Pin)987 PinRenderProcess(
988 IN PKSPIN Pin)
989 {
990 PKSSTREAM_POINTER LeadingStreamPointer;
991 PKSSTREAM_POINTER CloneStreamPointer;
992 NTSTATUS Status;
993 PPIN_CONTEXT PinContext;
994 ULONG PacketCount, TotalPacketSize, Offset;
995 PKSDATAFORMAT_WAVEFORMATEX WaveFormatEx;
996 PUCHAR TransferBuffer;
997 PIRP Irp = NULL;
998
999 //DPRINT1("PinRenderProcess\n");
1000
1001 LeadingStreamPointer = KsPinGetLeadingEdgeStreamPointer(Pin, KSSTREAM_POINTER_STATE_LOCKED);
1002 if (LeadingStreamPointer == NULL)
1003 {
1004 return STATUS_SUCCESS;
1005 }
1006
1007 if (NULL == LeadingStreamPointer->StreamHeader->Data)
1008 {
1009 Status = KsStreamPointerAdvance(LeadingStreamPointer);
1010 DPRINT1("Advancing Streampointer\n");
1011 }
1012
1013
1014 /* get pin context */
1015 PinContext = Pin->Context;
1016
1017 /* get irp from ready list */
1018 Irp = PinGetIrpFromReadyList(Pin);
1019
1020 if (!Irp)
1021 {
1022 /* no irps available */
1023 DPRINT1("No irps available");
1024 KsStreamPointerUnlock(LeadingStreamPointer, TRUE);
1025 return STATUS_SUCCESS;
1026 }
1027
1028 /* clone stream pointer */
1029 Status = KsStreamPointerClone(LeadingStreamPointer, NULL, 0, &CloneStreamPointer);
1030 if (!NT_SUCCESS(Status))
1031 {
1032 /* failed */
1033 KsStreamPointerUnlock(LeadingStreamPointer, TRUE);
1034 DPRINT1("Leaking Irp %p\n", Irp);
1035 return STATUS_SUCCESS;
1036 }
1037
1038 /* calculate packet count */
1039 /* FIXME support various sample rates */
1040 WaveFormatEx = (PKSDATAFORMAT_WAVEFORMATEX)Pin->ConnectionFormat;
1041 TotalPacketSize = WaveFormatEx->WaveFormatEx.nAvgBytesPerSec / 1000;
1042
1043 /* init transfer buffer*/
1044 TransferBuffer = CloneStreamPointer->StreamHeader->Data;
1045
1046 Offset = 0;
1047
1048 /* are there bytes from previous request*/
1049 if (PinContext->BufferLength)
1050 {
1051 ASSERT(PinContext->BufferLength < TotalPacketSize);
1052
1053 /* calculate offset*/
1054 Offset = TotalPacketSize - PinContext->BufferLength;
1055
1056 if (PinContext->BufferOffset + TotalPacketSize >= PinContext->BufferSize)
1057 {
1058 RtlMoveMemory(PinContext->Buffer, &PinContext->Buffer[PinContext->BufferOffset - PinContext->BufferLength], PinContext->BufferLength);
1059 PinContext->BufferOffset = PinContext->BufferLength;
1060 }
1061
1062 /* copy audio bytes */
1063 RtlCopyMemory(&PinContext->Buffer[PinContext->BufferOffset], TransferBuffer, Offset);
1064
1065 /* init irp*/
1066 Status = RenderInitializeUrbAndIrp(Pin, PinContext, Irp, &PinContext->Buffer[PinContext->BufferOffset-PinContext->BufferLength], TotalPacketSize, TotalPacketSize);
1067 if (NT_SUCCESS(Status))
1068 {
1069 /* render audio bytes */
1070 Status = IoCallDriver(PinContext->LowerDevice, Irp);
1071 }
1072 else
1073 {
1074 ASSERT(FALSE);
1075 }
1076
1077 PinContext->BufferLength = 0;
1078 PinContext->BufferOffset += Offset;
1079
1080 /* get new irp from ready list */
1081 Irp = PinGetIrpFromReadyList(Pin);
1082 ASSERT(Irp);
1083
1084 }
1085
1086 /* FIXME correct MaximumPacketSize ? */
1087 PacketCount = (CloneStreamPointer->OffsetIn.Remaining - Offset) / TotalPacketSize;
1088
1089 Status = RenderInitializeUrbAndIrp(Pin, PinContext, Irp, &TransferBuffer[Offset], PacketCount * TotalPacketSize, TotalPacketSize);
1090 if (NT_SUCCESS(Status))
1091 {
1092 /* store in irp context */
1093 Irp->Tail.Overlay.DriverContext[1] = CloneStreamPointer;
1094
1095 if ((PacketCount * TotalPacketSize) + Offset < CloneStreamPointer->OffsetIn.Remaining)
1096 {
1097 /* calculate remaining buffer bytes */
1098 PinContext->BufferLength = CloneStreamPointer->OffsetIn.Remaining - ((PacketCount * TotalPacketSize) + Offset);
1099
1100 /* check for overflow */
1101 if (PinContext->BufferOffset + TotalPacketSize >= PinContext->BufferSize)
1102 {
1103 /* reset buffer offset*/
1104 PinContext->BufferOffset = 0;
1105 }
1106 RtlCopyMemory(&PinContext->Buffer[PinContext->BufferOffset], &TransferBuffer[(PacketCount * TotalPacketSize) + Offset], PinContext->BufferLength);
1107 PinContext->BufferOffset += PinContext->BufferLength;
1108 }
1109
1110 /* render audio bytes */
1111 Status = IoCallDriver(PinContext->LowerDevice, Irp);
1112 }
1113
1114
1115 /* unlock stream pointer and finish*/
1116 KsStreamPointerUnlock(LeadingStreamPointer, TRUE);
1117 return STATUS_PENDING;
1118 }
1119
1120 NTSTATUS
PinCaptureProcess(IN PKSPIN Pin)1121 PinCaptureProcess(
1122 IN PKSPIN Pin)
1123 {
1124 PKSSTREAM_POINTER LeadingStreamPointer;
1125 KIRQL OldLevel;
1126 PPIN_CONTEXT PinContext;
1127 PLIST_ENTRY CurEntry;
1128 PIRP Irp;
1129 PURB Urb;
1130 PUCHAR TransferBuffer, OutBuffer;
1131 ULONG Offset, Length;
1132 NTSTATUS Status;
1133 PKSGATE Gate;
1134
1135 //DPRINT1("PinCaptureProcess\n");
1136 LeadingStreamPointer = KsPinGetLeadingEdgeStreamPointer(Pin, KSSTREAM_POINTER_STATE_LOCKED);
1137 if (LeadingStreamPointer == NULL)
1138 {
1139 /* get process control gate */
1140 Gate = KsPinGetAndGate(Pin);
1141
1142 /* shutdown processing */
1143 KsGateTurnInputOff(Gate);
1144
1145 return STATUS_SUCCESS;
1146 }
1147
1148 /* get pin context */
1149 PinContext = Pin->Context;
1150
1151 /* acquire spin lock */
1152 KeAcquireSpinLock(&PinContext->IrpListLock, &OldLevel);
1153
1154 while (!IsListEmpty(&PinContext->DoneIrpListHead))
1155 {
1156 /* remove entry from list */
1157 CurEntry = RemoveHeadList(&PinContext->DoneIrpListHead);
1158
1159 /* release lock */
1160 KeReleaseSpinLock(&PinContext->IrpListLock, OldLevel);
1161
1162 /* get irp offset */
1163 Irp = (PIRP)CONTAINING_RECORD(CurEntry, IRP, Tail.Overlay.ListEntry);
1164
1165 /* get urb from irp */
1166 Urb = (PURB)Irp->Tail.Overlay.DriverContext[0];
1167 ASSERT(Urb);
1168
1169 Offset = PtrToUlong(Irp->Tail.Overlay.DriverContext[1]);
1170
1171 /* get transfer buffer */
1172 TransferBuffer = Urb->UrbIsochronousTransfer.TransferBuffer;
1173
1174 /* get target buffer */
1175 OutBuffer = (PUCHAR)LeadingStreamPointer->StreamHeader->Data;
1176
1177 /* calculate length */
1178 Length = min(LeadingStreamPointer->OffsetOut.Count - LeadingStreamPointer->StreamHeader->DataUsed, Urb->UrbIsochronousTransfer.TransferBufferLength - Offset);
1179
1180 /* FIXME copy each packet extra */
1181 /* copy audio bytes */
1182 RtlCopyMemory((PUCHAR)&OutBuffer[LeadingStreamPointer->StreamHeader->DataUsed], &TransferBuffer[Offset], Length);
1183
1184 //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);
1185
1186 /* adjust streampointer */
1187 LeadingStreamPointer->StreamHeader->DataUsed += Length;
1188
1189 if (Length == LeadingStreamPointer->OffsetOut.Remaining)
1190 {
1191 KsStreamPointerAdvanceOffsetsAndUnlock(LeadingStreamPointer, 0, Length, TRUE);
1192
1193 /* acquire spin lock */
1194 KeAcquireSpinLock(&PinContext->IrpListLock, &OldLevel);
1195
1196 /* adjust offset */
1197 Irp->Tail.Overlay.DriverContext[1] = UlongToPtr(Length);
1198
1199 /* reinsert into processed list */
1200 InsertHeadList(&PinContext->DoneIrpListHead, &Irp->Tail.Overlay.ListEntry);
1201
1202 /* release lock */
1203 KeReleaseSpinLock(&PinContext->IrpListLock, OldLevel);
1204
1205 LeadingStreamPointer = KsPinGetLeadingEdgeStreamPointer(Pin, KSSTREAM_POINTER_STATE_LOCKED);
1206 if (LeadingStreamPointer == NULL)
1207 {
1208 /* no more work to be done*/
1209 return STATUS_PENDING;
1210 }
1211 else
1212 {
1213 /* resume work on this irp */
1214 continue;
1215 }
1216 }
1217 else
1218 {
1219 Status = KsStreamPointerAdvanceOffsets(LeadingStreamPointer, 0, Length, FALSE);
1220 NT_ASSERT(NT_SUCCESS(Status));
1221 ASSERT(Length == Urb->UrbIsochronousTransfer.TransferBufferLength - Offset);
1222 }
1223
1224
1225 /* acquire spin lock */
1226 KeAcquireSpinLock(&PinContext->IrpListLock, &OldLevel);
1227
1228 InsertTailList(&PinContext->IrpListHead, &Irp->Tail.Overlay.ListEntry);
1229 }
1230
1231 while (!IsListEmpty(&PinContext->IrpListHead))
1232 {
1233 /* remove entry from list */
1234 CurEntry = RemoveHeadList(&PinContext->IrpListHead);
1235
1236 /* release lock */
1237 KeReleaseSpinLock(&PinContext->IrpListLock, OldLevel);
1238
1239 /* get irp offset */
1240 Irp = (PIRP)CONTAINING_RECORD(CurEntry, IRP, Tail.Overlay.ListEntry);
1241
1242 /* reinitialize irp and urb */
1243 CaptureInitializeUrbAndIrp(Pin, Irp);
1244
1245 IoCallDriver(PinContext->DeviceExtension->LowerDevice, Irp);
1246
1247 /* acquire spin lock */
1248 KeAcquireSpinLock(&PinContext->IrpListLock, &OldLevel);
1249
1250 }
1251
1252 /* release lock */
1253 KeReleaseSpinLock(&PinContext->IrpListLock, OldLevel);
1254
1255 if (LeadingStreamPointer != NULL)
1256 KsStreamPointerUnlock(LeadingStreamPointer, FALSE);
1257
1258 /* get process control gate */
1259 Gate = KsPinGetAndGate(Pin);
1260
1261 /* shutdown processing */
1262 KsGateTurnInputOff(Gate);
1263
1264 return STATUS_PENDING;
1265 }
1266
1267
1268 NTSTATUS
1269 NTAPI
USBAudioPinProcess(_In_ PKSPIN Pin)1270 USBAudioPinProcess(
1271 _In_ PKSPIN Pin)
1272 {
1273 NTSTATUS Status;
1274
1275 if (Pin->DataFlow == KSPIN_DATAFLOW_OUT)
1276 {
1277 Status = PinCaptureProcess(Pin);
1278 }
1279 else
1280 {
1281 Status = PinRenderProcess(Pin);
1282 }
1283
1284 return Status;
1285 }
1286
1287
1288 VOID
1289 NTAPI
USBAudioPinReset(_In_ PKSPIN Pin)1290 USBAudioPinReset(
1291 _In_ PKSPIN Pin)
1292 {
1293 UNIMPLEMENTED;
1294 }
1295
1296 NTSTATUS
1297 NTAPI
USBAudioPinSetDataFormat(_In_ PKSPIN Pin,_In_opt_ PKSDATAFORMAT OldFormat,_In_opt_ PKSMULTIPLE_ITEM OldAttributeList,_In_ const KSDATARANGE * DataRange,_In_opt_ const KSATTRIBUTE_LIST * AttributeRange)1298 USBAudioPinSetDataFormat(
1299 _In_ PKSPIN Pin,
1300 _In_opt_ PKSDATAFORMAT OldFormat,
1301 _In_opt_ PKSMULTIPLE_ITEM OldAttributeList,
1302 _In_ const KSDATARANGE* DataRange,
1303 _In_opt_ const KSATTRIBUTE_LIST* AttributeRange)
1304 {
1305 if (OldFormat == NULL)
1306 {
1307 /* TODO: verify connection format */
1308 UNIMPLEMENTED;
1309 return STATUS_SUCCESS;
1310 }
1311
1312 return UsbAudioSetFormat(Pin);
1313 }
1314
1315 NTSTATUS
StartCaptureIsocTransfer(IN PKSPIN Pin)1316 StartCaptureIsocTransfer(
1317 IN PKSPIN Pin)
1318 {
1319 PPIN_CONTEXT PinContext;
1320 PLIST_ENTRY CurEntry;
1321 PIRP Irp;
1322 KIRQL OldLevel;
1323
1324 /* get pin context */
1325 PinContext = Pin->Context;
1326
1327 /* acquire spin lock */
1328 KeAcquireSpinLock(&PinContext->IrpListLock, &OldLevel);
1329
1330 while(!IsListEmpty(&PinContext->IrpListHead))
1331 {
1332 /* remove entry from list */
1333 CurEntry = RemoveHeadList(&PinContext->IrpListHead);
1334
1335 /* get irp offset */
1336 Irp = (PIRP)CONTAINING_RECORD(CurEntry, IRP, Tail.Overlay.ListEntry);
1337
1338 /* release lock */
1339 KeReleaseSpinLock(&PinContext->IrpListLock, OldLevel);
1340
1341 /* reinitialize irp and urb */
1342 CaptureInitializeUrbAndIrp(Pin, Irp);
1343
1344 DPRINT("StartCaptureIsocTransfer Irp %p\n", Irp);
1345 IoCallDriver(PinContext->DeviceExtension->LowerDevice, Irp);
1346
1347 /* acquire spin lock */
1348 KeAcquireSpinLock(&PinContext->IrpListLock, &OldLevel);
1349
1350 }
1351
1352 /* release lock */
1353 KeReleaseSpinLock(&PinContext->IrpListLock, OldLevel);
1354
1355 return STATUS_SUCCESS;
1356 }
1357
1358 NTSTATUS
CapturePinStateChange(_In_ PKSPIN Pin,_In_ KSSTATE ToState,_In_ KSSTATE FromState)1359 CapturePinStateChange(
1360 _In_ PKSPIN Pin,
1361 _In_ KSSTATE ToState,
1362 _In_ KSSTATE FromState)
1363 {
1364 NTSTATUS Status = STATUS_SUCCESS;
1365
1366 if (FromState != ToState)
1367 {
1368 if (ToState)
1369 {
1370 if (ToState == KSSTATE_PAUSE)
1371 {
1372 if (FromState == KSSTATE_RUN)
1373 {
1374 /* wait until pin processing is finished*/
1375 }
1376 }
1377 else
1378 {
1379 if (ToState == KSSTATE_RUN)
1380 {
1381 Status = StartCaptureIsocTransfer(Pin);
1382 }
1383 }
1384 }
1385 }
1386 return Status;
1387 }
1388
1389
1390 NTSTATUS
1391 NTAPI
USBAudioPinSetDeviceState(_In_ PKSPIN Pin,_In_ KSSTATE ToState,_In_ KSSTATE FromState)1392 USBAudioPinSetDeviceState(
1393 _In_ PKSPIN Pin,
1394 _In_ KSSTATE ToState,
1395 _In_ KSSTATE FromState)
1396 {
1397 NTSTATUS Status;
1398
1399 if (Pin->DataFlow == KSPIN_DATAFLOW_OUT)
1400 {
1401 /* handle capture state changes */
1402 Status = CapturePinStateChange(Pin, ToState, FromState);
1403 }
1404 else
1405 {
1406 UNIMPLEMENTED;
1407 Status = STATUS_SUCCESS;
1408 }
1409
1410 return Status;
1411 }
1412
1413
1414 NTSTATUS
1415 NTAPI
UsbAudioPinDataIntersect(_In_ PVOID Context,_In_ PIRP Irp,_In_ PKSP_PIN Pin,_In_ PKSDATARANGE DataRange,_In_ PKSDATARANGE MatchingDataRange,_In_ ULONG DataBufferSize,_Out_ PVOID Data,_Out_ PULONG DataSize)1416 UsbAudioPinDataIntersect(
1417 _In_ PVOID Context,
1418 _In_ PIRP Irp,
1419 _In_ PKSP_PIN Pin,
1420 _In_ PKSDATARANGE DataRange,
1421 _In_ PKSDATARANGE MatchingDataRange,
1422 _In_ ULONG DataBufferSize,
1423 _Out_ PVOID Data,
1424 _Out_ PULONG DataSize)
1425 {
1426 PKSFILTER Filter;
1427 PKSPIN_DESCRIPTOR_EX PinDescriptor;
1428 PKSDATAFORMAT_WAVEFORMATEX DataFormat;
1429 PKSDATARANGE_AUDIO DataRangeAudio;
1430
1431 /* get filter from irp*/
1432 Filter = KsGetFilterFromIrp(Irp);
1433 if (!Filter)
1434 {
1435 /* no match*/
1436 return STATUS_NO_MATCH;
1437 }
1438
1439 /* get pin descriptor */
1440 PinDescriptor = (PKSPIN_DESCRIPTOR_EX)&Filter->Descriptor->PinDescriptors[Pin->PinId];
1441
1442 *DataSize = sizeof(KSDATAFORMAT_WAVEFORMATEX);
1443 if (DataBufferSize == 0)
1444 {
1445 /* buffer too small */
1446 return STATUS_BUFFER_OVERFLOW;
1447 }
1448
1449 /* sanity checks*/
1450 ASSERT(PinDescriptor->PinDescriptor.DataRangesCount >= 0);
1451 ASSERT(PinDescriptor->PinDescriptor.DataRanges[0]->FormatSize == sizeof(KSDATARANGE_AUDIO));
1452
1453 DataRangeAudio = (PKSDATARANGE_AUDIO)PinDescriptor->PinDescriptor.DataRanges[0];
1454
1455 DataFormat = Data;
1456 DataFormat->WaveFormatEx.wFormatTag = WAVE_FORMAT_PCM;
1457 DataFormat->WaveFormatEx.nChannels = DataRangeAudio->MaximumChannels;
1458 DataFormat->WaveFormatEx.nSamplesPerSec = DataRangeAudio->MaximumSampleFrequency;
1459 DataFormat->WaveFormatEx.nAvgBytesPerSec = DataRangeAudio->MaximumSampleFrequency * (DataRangeAudio->MaximumBitsPerSample / 8) * DataRangeAudio->MaximumChannels;
1460 DataFormat->WaveFormatEx.nBlockAlign = (DataRangeAudio->MaximumBitsPerSample / 8) * DataRangeAudio->MaximumChannels;
1461 DataFormat->WaveFormatEx.wBitsPerSample = DataRangeAudio->MaximumBitsPerSample;
1462 DataFormat->WaveFormatEx.cbSize = 0;
1463
1464 DataFormat->DataFormat.FormatSize = sizeof(KSDATAFORMAT) + sizeof(WAVEFORMATEX);
1465 DataFormat->DataFormat.Flags = 0;
1466 DataFormat->DataFormat.Reserved = 0;
1467 DataFormat->DataFormat.MajorFormat = KSDATAFORMAT_TYPE_AUDIO;
1468 DataFormat->DataFormat.SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
1469 DataFormat->DataFormat.Specifier = KSDATAFORMAT_SPECIFIER_WAVEFORMATEX;
1470 DataFormat->DataFormat.SampleSize = (DataRangeAudio->MaximumBitsPerSample / 8) * DataRangeAudio->MaximumChannels;
1471
1472 return STATUS_SUCCESS;
1473 }
1474