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 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 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 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 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 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 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 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 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 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 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 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 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 843 USBAudioPinClose( 844 _In_ PKSPIN Pin, 845 _In_ PIRP Irp) 846 { 847 UNIMPLEMENTED; 848 return STATUS_NOT_IMPLEMENTED; 849 } 850 851 NTSTATUS 852 NTAPI 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 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 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 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 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 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 1290 USBAudioPinReset( 1291 _In_ PKSPIN Pin) 1292 { 1293 UNIMPLEMENTED; 1294 } 1295 1296 NTSTATUS 1297 NTAPI 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 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 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 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 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