1 /* 2 * COPYRIGHT: See COPYING in the top level directory 3 * PROJECT: ReactOS Kernel Streaming 4 * FILE: drivers/wdm/audio/backpln/portcls/pin_wavepci.cpp 5 * PURPOSE: WavePci IRP Audio Pin 6 * PROGRAMMER: Johannes Anderwald 7 */ 8 9 #include "private.hpp" 10 11 #ifndef YDEBUG 12 #define NDEBUG 13 #endif 14 15 #include <debug.h> 16 17 class CPortPinWavePci : public IPortPinWavePci, 18 public IServiceSink, 19 public IPortWavePciStream 20 { 21 public: 22 STDMETHODIMP QueryInterface( REFIID InterfaceId, PVOID* Interface); 23 24 STDMETHODIMP_(ULONG) AddRef() 25 { 26 InterlockedIncrement(&m_Ref); 27 return m_Ref; 28 } 29 STDMETHODIMP_(ULONG) Release() 30 { 31 InterlockedDecrement(&m_Ref); 32 33 if (!m_Ref) 34 { 35 delete this; 36 return 0; 37 } 38 return m_Ref; 39 } 40 IMP_IPortPinWavePci; 41 IMP_IServiceSink; 42 IMP_IPortWavePciStream; 43 CPortPinWavePci(IUnknown *OuterUnknown) {} 44 virtual ~CPortPinWavePci(){} 45 protected: 46 47 friend NTSTATUS NTAPI PinWavePciState(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data); 48 friend NTSTATUS NTAPI PinWavePciDataFormat(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data); 49 friend NTSTATUS NTAPI PinWavePciAudioPosition(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data); 50 friend NTSTATUS NTAPI PinWavePciAllocatorFraming(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data); 51 52 IPortWavePci * m_Port; 53 IPortFilterWavePci * m_Filter; 54 KSPIN_DESCRIPTOR * m_KsPinDescriptor; 55 PMINIPORTWAVEPCI m_Miniport; 56 PSERVICEGROUP m_ServiceGroup; 57 PDMACHANNEL m_DmaChannel; 58 PMINIPORTWAVEPCISTREAM m_Stream; 59 KSSTATE m_State; 60 PKSDATAFORMAT m_Format; 61 KSPIN_CONNECT * m_ConnectDetails; 62 63 BOOL m_Capture; 64 PDEVICE_OBJECT m_DeviceObject; 65 IIrpQueue * m_IrpQueue; 66 67 ULONG m_TotalPackets; 68 KSAUDIO_POSITION m_Position; 69 ULONG m_StopCount; 70 71 BOOL m_bUsePrefetch; 72 ULONG m_PrefetchOffset; 73 SUBDEVICE_DESCRIPTOR m_Descriptor; 74 75 KSALLOCATOR_FRAMING m_AllocatorFraming; 76 77 LONG m_Ref; 78 79 NTSTATUS NTAPI HandleKsProperty(IN PIRP Irp); 80 NTSTATUS NTAPI HandleKsStream(IN PIRP Irp); 81 }; 82 83 typedef struct 84 { 85 CPortPinWavePci *Pin; 86 PIO_WORKITEM WorkItem; 87 KSSTATE State; 88 }SETSTREAM_CONTEXT, *PSETSTREAM_CONTEXT; 89 90 NTSTATUS NTAPI PinWavePciState(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data); 91 NTSTATUS NTAPI PinWavePciDataFormat(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data); 92 NTSTATUS NTAPI PinWavePciAudioPosition(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data); 93 NTSTATUS NTAPI PinWavePciAllocatorFraming(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data); 94 95 DEFINE_KSPROPERTY_CONNECTIONSET(PinWavePciConnectionSet, PinWavePciState, PinWavePciDataFormat, PinWavePciAllocatorFraming); 96 DEFINE_KSPROPERTY_AUDIOSET(PinWavePciAudioSet, PinWavePciAudioPosition); 97 98 KSPROPERTY_SET PinWavePciPropertySet[] = 99 { 100 { 101 &KSPROPSETID_Connection, 102 sizeof(PinWavePciConnectionSet) / sizeof(KSPROPERTY_ITEM), 103 (const KSPROPERTY_ITEM*)&PinWavePciConnectionSet, 104 0, 105 NULL 106 }, 107 { 108 &KSPROPSETID_Audio, 109 sizeof(PinWavePciAudioSet) / sizeof(KSPROPERTY_ITEM), 110 (const KSPROPERTY_ITEM*)&PinWavePciAudioSet, 111 0, 112 NULL 113 } 114 }; 115 116 117 NTSTATUS 118 NTAPI 119 PinWavePciAllocatorFraming( 120 IN PIRP Irp, 121 IN PKSIDENTIFIER Request, 122 IN OUT PVOID Data) 123 { 124 CPortPinWavePci *Pin; 125 PSUBDEVICE_DESCRIPTOR Descriptor; 126 127 // get sub device descriptor 128 Descriptor = (PSUBDEVICE_DESCRIPTOR)KSPROPERTY_ITEM_IRP_STORAGE(Irp); 129 130 // sanity check 131 PC_ASSERT(Descriptor); 132 PC_ASSERT(Descriptor->PortPin); 133 PC_ASSERT_IRQL(DISPATCH_LEVEL); 134 135 // cast to pin impl 136 Pin = (CPortPinWavePci*)Descriptor->PortPin; 137 138 139 if (Request->Flags & KSPROPERTY_TYPE_GET) 140 { 141 // copy pin framing 142 RtlMoveMemory(Data, &Pin->m_AllocatorFraming, sizeof(KSALLOCATOR_FRAMING)); 143 144 Irp->IoStatus.Information = sizeof(KSALLOCATOR_FRAMING); 145 return STATUS_SUCCESS; 146 } 147 148 // not supported 149 return STATUS_NOT_SUPPORTED; 150 } 151 152 NTSTATUS 153 NTAPI 154 PinWavePciAudioPosition( 155 IN PIRP Irp, 156 IN PKSIDENTIFIER Request, 157 IN OUT PVOID Data) 158 { 159 CPortPinWavePci *Pin; 160 PSUBDEVICE_DESCRIPTOR Descriptor; 161 162 // get sub device descriptor 163 Descriptor = (PSUBDEVICE_DESCRIPTOR)KSPROPERTY_ITEM_IRP_STORAGE(Irp); 164 165 // sanity check 166 PC_ASSERT(Descriptor); 167 PC_ASSERT(Descriptor->PortPin); 168 PC_ASSERT_IRQL(DISPATCH_LEVEL); 169 170 // cast to pin impl 171 Pin = (CPortPinWavePci*)Descriptor->PortPin; 172 173 //sanity check 174 PC_ASSERT(Pin->m_Stream); 175 176 if (Request->Flags & KSPROPERTY_TYPE_GET) 177 { 178 // FIXME non multithreading-safe 179 // copy audio position 180 RtlMoveMemory(Data, &Pin->m_Position, sizeof(KSAUDIO_POSITION)); 181 182 DPRINT("Play %lu Record %lu\n", Pin->m_Position.PlayOffset, Pin->m_Position.WriteOffset); 183 Irp->IoStatus.Information = sizeof(KSAUDIO_POSITION); 184 return STATUS_SUCCESS; 185 } 186 187 // not supported 188 return STATUS_NOT_SUPPORTED; 189 } 190 191 192 NTSTATUS 193 NTAPI 194 PinWavePciState( 195 IN PIRP Irp, 196 IN PKSIDENTIFIER Request, 197 IN OUT PVOID Data) 198 { 199 NTSTATUS Status = STATUS_UNSUCCESSFUL; 200 CPortPinWavePci *Pin; 201 PSUBDEVICE_DESCRIPTOR Descriptor; 202 PVOID FirstTag, LastTag; 203 ULONG MappingsRevoked; 204 PKSSTATE State = (PKSSTATE)Data; 205 206 // get sub device descriptor 207 Descriptor = (PSUBDEVICE_DESCRIPTOR)KSPROPERTY_ITEM_IRP_STORAGE(Irp); 208 209 // sanity check 210 PC_ASSERT(Descriptor); 211 PC_ASSERT(Descriptor->PortPin); 212 PC_ASSERT_IRQL(DISPATCH_LEVEL); 213 214 // cast to pin impl 215 Pin = (CPortPinWavePci*)Descriptor->PortPin; 216 217 //sanity check 218 PC_ASSERT(Pin->m_Stream); 219 220 if (Request->Flags & KSPROPERTY_TYPE_SET) 221 { 222 // try set stream 223 Status = Pin->m_Stream->SetState(*State); 224 225 DPRINT("Setting state %u %x\n", *State, Status); 226 if (NT_SUCCESS(Status)) 227 { 228 // store new state 229 Pin->m_State = *State; 230 if (Pin->m_ConnectDetails->Interface.Id == KSINTERFACE_STANDARD_LOOPED_STREAMING && Pin->m_State == KSSTATE_STOP) 231 { 232 // FIXME 233 // complete with successful state 234 Pin->m_IrpQueue->CancelBuffers(); 235 while(Pin->m_IrpQueue->GetAcquiredTagRange(&FirstTag, &LastTag)) 236 { 237 Status = Pin->m_Stream->RevokeMappings(FirstTag, LastTag, &MappingsRevoked); 238 DPRINT("RevokeMappings Status %lx MappingsRevoked: %lu\n", Status, MappingsRevoked); 239 KeStallExecutionProcessor(10); 240 } 241 Pin->m_Position.PlayOffset = 0; 242 Pin->m_Position.WriteOffset = 0; 243 } 244 else if (Pin->m_State == KSSTATE_STOP) 245 { 246 Pin->m_IrpQueue->CancelBuffers(); 247 while(Pin->m_IrpQueue->GetAcquiredTagRange(&FirstTag, &LastTag)) 248 { 249 Status = Pin->m_Stream->RevokeMappings(FirstTag, LastTag, &MappingsRevoked); 250 DPRINT("RevokeMappings Status %lx MappingsRevoked: %lu\n", Status, MappingsRevoked); 251 KeStallExecutionProcessor(10); 252 } 253 Pin->m_Position.PlayOffset = 0; 254 Pin->m_Position.WriteOffset = 0; 255 } 256 // store result 257 Irp->IoStatus.Information = sizeof(KSSTATE); 258 259 } 260 // store result 261 Irp->IoStatus.Information = sizeof(KSSTATE); 262 return Status; 263 } 264 else if (Request->Flags & KSPROPERTY_TYPE_GET) 265 { 266 // get current stream state 267 *State = Pin->m_State; 268 // store result 269 Irp->IoStatus.Information = sizeof(KSSTATE); 270 271 return STATUS_SUCCESS; 272 } 273 274 // unsupported request 275 return STATUS_NOT_SUPPORTED; 276 } 277 278 NTSTATUS 279 NTAPI 280 PinWavePciDataFormat( 281 IN PIRP Irp, 282 IN PKSIDENTIFIER Request, 283 IN OUT PVOID Data) 284 { 285 NTSTATUS Status = STATUS_UNSUCCESSFUL; 286 CPortPinWavePci *Pin; 287 PSUBDEVICE_DESCRIPTOR Descriptor; 288 PIO_STACK_LOCATION IoStack; 289 290 // get current irp stack location 291 IoStack = IoGetCurrentIrpStackLocation(Irp); 292 293 // get sub device descriptor 294 Descriptor = (PSUBDEVICE_DESCRIPTOR)KSPROPERTY_ITEM_IRP_STORAGE(Irp); 295 296 // sanity check 297 PC_ASSERT(Descriptor); 298 PC_ASSERT(Descriptor->PortPin); 299 300 // cast to pin impl 301 Pin = (CPortPinWavePci*)Descriptor->PortPin; 302 303 //sanity check 304 PC_ASSERT(Pin->m_Stream); 305 PC_ASSERT(Pin->m_Format); 306 307 if (Request->Flags & KSPROPERTY_TYPE_SET) 308 { 309 // try to change data format 310 PKSDATAFORMAT NewDataFormat, DataFormat = (PKSDATAFORMAT)Irp->UserBuffer; 311 ULONG Size = min(Pin->m_Format->FormatSize, DataFormat->FormatSize); 312 313 if (RtlCompareMemory(DataFormat, Pin->m_Format, Size) == Size) 314 { 315 // format is identical 316 Irp->IoStatus.Information = DataFormat->FormatSize; 317 return STATUS_SUCCESS; 318 } 319 320 // new change request 321 PC_ASSERT(Pin->m_State == KSSTATE_STOP); 322 // FIXME queue a work item when Irql != PASSIVE_LEVEL 323 PC_ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL); 324 325 // allocate new data format 326 NewDataFormat = (PKSDATAFORMAT)AllocateItem(NonPagedPool, DataFormat->FormatSize, TAG_PORTCLASS); 327 if (!NewDataFormat) 328 { 329 // not enough memory 330 return STATUS_NO_MEMORY; 331 } 332 333 // copy new data format 334 RtlMoveMemory(NewDataFormat, DataFormat, DataFormat->FormatSize); 335 336 // set new format 337 Status = Pin->m_Stream->SetFormat(NewDataFormat); 338 if (NT_SUCCESS(Status)) 339 { 340 // free old format 341 FreeItem(Pin->m_Format, TAG_PORTCLASS); 342 343 // store new format 344 Pin->m_Format = NewDataFormat; 345 Irp->IoStatus.Information = NewDataFormat->FormatSize; 346 347 #if 0 348 PC_ASSERT(NewDataFormat->FormatSize == sizeof(KSDATAFORMAT_WAVEFORMATEX)); 349 PC_ASSERT(IsEqualGUIDAligned(((PKSDATAFORMAT_WAVEFORMATEX)NewDataFormat)->DataFormat.MajorFormat, KSDATAFORMAT_TYPE_AUDIO)); 350 PC_ASSERT(IsEqualGUIDAligned(((PKSDATAFORMAT_WAVEFORMATEX)NewDataFormat)->DataFormat.SubFormat, KSDATAFORMAT_SUBTYPE_PCM)); 351 PC_ASSERT(IsEqualGUIDAligned(((PKSDATAFORMAT_WAVEFORMATEX)NewDataFormat)->DataFormat.Specifier, KSDATAFORMAT_SPECIFIER_WAVEFORMATEX)); 352 353 354 DPRINT("NewDataFormat: Channels %u Bits %u Samples %u\n", ((PKSDATAFORMAT_WAVEFORMATEX)NewDataFormat)->WaveFormatEx.nChannels, 355 ((PKSDATAFORMAT_WAVEFORMATEX)NewDataFormat)->WaveFormatEx.wBitsPerSample, 356 ((PKSDATAFORMAT_WAVEFORMATEX)NewDataFormat)->WaveFormatEx.nSamplesPerSec); 357 #endif 358 359 } 360 else 361 { 362 // failed to set format 363 FreeItem(NewDataFormat, TAG_PORTCLASS); 364 } 365 366 367 // done 368 return Status; 369 } 370 else if (Request->Flags & KSPROPERTY_TYPE_GET) 371 { 372 // get current data format 373 PC_ASSERT(Pin->m_Format); 374 375 if (Pin->m_Format->FormatSize > IoStack->Parameters.DeviceIoControl.OutputBufferLength) 376 { 377 // buffer too small 378 Irp->IoStatus.Information = Pin->m_Format->FormatSize; 379 return STATUS_MORE_ENTRIES; 380 } 381 // copy data format 382 RtlMoveMemory(Data, Pin->m_Format, Pin->m_Format->FormatSize); 383 // store result size 384 Irp->IoStatus.Information = Pin->m_Format->FormatSize; 385 386 // done 387 return STATUS_SUCCESS; 388 } 389 390 // unsupported request 391 return STATUS_NOT_SUPPORTED; 392 } 393 394 395 //================================================================================================================================== 396 NTSTATUS 397 NTAPI 398 CPortPinWavePci::QueryInterface( 399 IN REFIID refiid, 400 OUT PVOID* Output) 401 { 402 //DPRINT("CPortPinWavePci::QueryInterface entered\n"); 403 404 if (IsEqualGUIDAligned(refiid, IID_IIrpTarget) || 405 IsEqualGUIDAligned(refiid, IID_IUnknown)) 406 { 407 *Output = PVOID(PUNKNOWN((IIrpTarget*)this)); 408 PUNKNOWN(*Output)->AddRef(); 409 return STATUS_SUCCESS; 410 } 411 412 if (IsEqualGUIDAligned(refiid, IID_IServiceSink)) 413 { 414 *Output = PVOID(PSERVICESINK(this)); 415 PUNKNOWN(*Output)->AddRef(); 416 return STATUS_SUCCESS; 417 } 418 419 420 if (IsEqualGUIDAligned(refiid, IID_IPortWavePciStream)) 421 { 422 *Output = PVOID(PPORTWAVEPCISTREAM(this)); 423 PUNKNOWN(*Output)->AddRef(); 424 return STATUS_SUCCESS; 425 } 426 427 return STATUS_UNSUCCESSFUL; 428 } 429 430 NTSTATUS 431 NTAPI 432 CPortPinWavePci::GetMapping( 433 IN PVOID Tag, 434 OUT PPHYSICAL_ADDRESS PhysicalAddress, 435 OUT PVOID *VirtualAddress, 436 OUT PULONG ByteCount, 437 OUT PULONG Flags) 438 { 439 440 PC_ASSERT_IRQL(DISPATCH_LEVEL); 441 return m_IrpQueue->GetMappingWithTag(Tag, PhysicalAddress, VirtualAddress, ByteCount, Flags); 442 } 443 444 NTSTATUS 445 NTAPI 446 CPortPinWavePci::ReleaseMapping( 447 IN PVOID Tag) 448 { 449 450 PC_ASSERT_IRQL(DISPATCH_LEVEL); 451 return m_IrpQueue->ReleaseMappingWithTag(Tag); 452 } 453 454 NTSTATUS 455 NTAPI 456 CPortPinWavePci::TerminatePacket() 457 { 458 UNIMPLEMENTED; 459 PC_ASSERT_IRQL(DISPATCH_LEVEL); 460 return STATUS_SUCCESS; 461 } 462 463 464 VOID 465 NTAPI 466 CPortPinWavePci::RequestService() 467 { 468 PC_ASSERT_IRQL(DISPATCH_LEVEL); 469 470 if (m_State == KSSTATE_RUN) 471 { 472 m_Stream->Service(); 473 //TODO 474 //generate events 475 } 476 } 477 478 //================================================================================================================================== 479 480 NTSTATUS 481 NTAPI 482 CPortPinWavePci::NewIrpTarget( 483 OUT struct IIrpTarget **OutTarget, 484 IN PCWSTR Name, 485 IN PUNKNOWN Unknown, 486 IN POOL_TYPE PoolType, 487 IN PDEVICE_OBJECT DeviceObject, 488 IN PIRP Irp, 489 IN KSOBJECT_CREATE *CreateObject) 490 { 491 UNIMPLEMENTED; 492 493 Irp->IoStatus.Information = 0; 494 Irp->IoStatus.Status = STATUS_UNSUCCESSFUL; 495 IoCompleteRequest(Irp, IO_NO_INCREMENT); 496 497 return STATUS_UNSUCCESSFUL; 498 } 499 500 NTSTATUS 501 NTAPI 502 CPortPinWavePci::HandleKsProperty( 503 IN PIRP Irp) 504 { 505 //PKSPROPERTY Property; 506 NTSTATUS Status; 507 //UNICODE_STRING GuidString; 508 PIO_STACK_LOCATION IoStack; 509 510 //DPRINT("IPortPinWave_HandleKsProperty entered\n"); 511 512 IoStack = IoGetCurrentIrpStackLocation(Irp); 513 514 if (IoStack->Parameters.DeviceIoControl.IoControlCode != IOCTL_KS_PROPERTY) 515 { 516 //DPRINT("Unhandled function %lx Length %x\n", IoStack->Parameters.DeviceIoControl.IoControlCode, IoStack->Parameters.DeviceIoControl.InputBufferLength); 517 518 Irp->IoStatus.Status = STATUS_SUCCESS; 519 520 IoCompleteRequest(Irp, IO_NO_INCREMENT); 521 return STATUS_SUCCESS; 522 } 523 524 Status = PcHandlePropertyWithTable(Irp, m_Descriptor.FilterPropertySetCount, m_Descriptor.FilterPropertySet, &m_Descriptor); 525 526 if (Status == STATUS_NOT_FOUND) 527 { 528 //Property = (PKSPROPERTY)IoStack->Parameters.DeviceIoControl.Type3InputBuffer; 529 #if 0 530 RtlStringFromGUID(Property->Set, &GuidString); 531 //DPRINT("Unhandled property Set |%S| Id %u Flags %x\n", GuidString.Buffer, Property->Id, Property->Flags); 532 RtlFreeUnicodeString(&GuidString); 533 #endif 534 } 535 536 if (Status != STATUS_PENDING) 537 { 538 Irp->IoStatus.Status = Status; 539 IoCompleteRequest(Irp, IO_NO_INCREMENT); 540 } 541 542 return Status; 543 } 544 545 NTSTATUS 546 NTAPI 547 CPortPinWavePci::HandleKsStream( 548 IN PIRP Irp) 549 { 550 NTSTATUS Status; 551 ULONG Data = 0; 552 BOOLEAN bFailed; 553 InterlockedIncrement((PLONG)&m_TotalPackets); 554 555 DPRINT("IPortPinWaveCyclic_HandleKsStream entered Total %u State %x MinData %u\n", m_TotalPackets, m_State, m_IrpQueue->NumData()); 556 557 bFailed = m_IrpQueue->HasLastMappingFailed(); 558 559 Status = m_IrpQueue->AddMapping(Irp, &Data); 560 561 if (NT_SUCCESS(Status)) 562 { 563 if (m_Capture) 564 m_Position.WriteOffset += Data; 565 else 566 m_Position.PlayOffset += Data; 567 568 if (bFailed) 569 { 570 // notify stream of new mapping 571 m_Stream->MappingAvailable(); 572 } 573 574 return STATUS_PENDING; 575 } 576 577 return Status; 578 } 579 580 581 NTSTATUS 582 NTAPI 583 CPortPinWavePci::DeviceIoControl( 584 IN PDEVICE_OBJECT DeviceObject, 585 IN PIRP Irp) 586 { 587 PIO_STACK_LOCATION IoStack; 588 589 IoStack = IoGetCurrentIrpStackLocation(Irp); 590 591 if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_PROPERTY) 592 { 593 return HandleKsProperty(Irp); 594 } 595 else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_WRITE_STREAM || IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_READ_STREAM) 596 { 597 return HandleKsStream(Irp); 598 } 599 600 UNIMPLEMENTED; 601 602 Irp->IoStatus.Information = 0; 603 Irp->IoStatus.Status = STATUS_UNSUCCESSFUL; 604 IoCompleteRequest(Irp, IO_NO_INCREMENT); 605 606 return STATUS_UNSUCCESSFUL; 607 } 608 609 NTSTATUS 610 NTAPI 611 CPortPinWavePci::Read( 612 IN PDEVICE_OBJECT DeviceObject, 613 IN PIRP Irp) 614 { 615 return KsDispatchInvalidDeviceRequest(DeviceObject, Irp); 616 } 617 618 NTSTATUS 619 NTAPI 620 CPortPinWavePci::Write( 621 IN PDEVICE_OBJECT DeviceObject, 622 IN PIRP Irp) 623 { 624 return KsDispatchInvalidDeviceRequest(DeviceObject, Irp); 625 } 626 627 NTSTATUS 628 NTAPI 629 CPortPinWavePci::Flush( 630 IN PDEVICE_OBJECT DeviceObject, 631 IN PIRP Irp) 632 { 633 return KsDispatchInvalidDeviceRequest(DeviceObject, Irp); 634 } 635 636 NTSTATUS 637 NTAPI 638 CPortPinWavePci::Close( 639 IN PDEVICE_OBJECT DeviceObject, 640 IN PIRP Irp) 641 { 642 NTSTATUS Status; 643 644 if (m_Format) 645 { 646 // free format 647 FreeItem(m_Format, TAG_PORTCLASS); 648 649 // format is freed 650 m_Format = NULL; 651 } 652 653 if (m_IrpQueue) 654 { 655 // cancel remaining irps 656 m_IrpQueue->CancelBuffers(); 657 658 // release irp queue 659 m_IrpQueue->Release(); 660 661 // queue is freed 662 m_IrpQueue = NULL; 663 } 664 665 666 if (m_ServiceGroup) 667 { 668 // remove member from service group 669 m_ServiceGroup->RemoveMember(PSERVICESINK(this)); 670 671 // do not release service group, it is released by the miniport object 672 m_ServiceGroup = NULL; 673 } 674 675 if (m_Stream) 676 { 677 if (m_State != KSSTATE_STOP) 678 { 679 // stop stream 680 Status = m_Stream->SetState(KSSTATE_STOP); 681 if (!NT_SUCCESS(Status)) 682 { 683 DPRINT("Warning: failed to stop stream with %x\n", Status); 684 PC_ASSERT(0); 685 } 686 } 687 // set state to stop 688 m_State = KSSTATE_STOP; 689 690 DPRINT("Closing stream at Irql %u\n", KeGetCurrentIrql()); 691 692 // release stream 693 m_Stream->Release(); 694 695 // stream is now freed 696 m_Stream = NULL; 697 } 698 699 if (m_Filter) 700 { 701 // disconnect pin from filter 702 m_Filter->FreePin((PPORTPINWAVEPCI)this); 703 704 // release filter reference 705 m_Filter->Release(); 706 707 // pin is done with filter 708 m_Filter = NULL; 709 } 710 711 if (m_Port) 712 { 713 // release reference to port driver 714 m_Port->Release(); 715 716 // work is done for port 717 m_Port = NULL; 718 } 719 720 // successfully complete irp 721 Irp->IoStatus.Status = STATUS_SUCCESS; 722 Irp->IoStatus.Information = 0; 723 IoCompleteRequest(Irp, IO_NO_INCREMENT); 724 725 return STATUS_SUCCESS; 726 } 727 728 NTSTATUS 729 NTAPI 730 CPortPinWavePci::QuerySecurity( 731 IN PDEVICE_OBJECT DeviceObject, 732 IN PIRP Irp) 733 { 734 return KsDispatchInvalidDeviceRequest(DeviceObject, Irp); 735 } 736 737 NTSTATUS 738 NTAPI 739 CPortPinWavePci::SetSecurity( 740 IN PDEVICE_OBJECT DeviceObject, 741 IN PIRP Irp) 742 { 743 return KsDispatchInvalidDeviceRequest(DeviceObject, Irp); 744 } 745 746 BOOLEAN 747 NTAPI 748 CPortPinWavePci::FastDeviceIoControl( 749 IN PFILE_OBJECT FileObject, 750 IN BOOLEAN Wait, 751 IN PVOID InputBuffer, 752 IN ULONG InputBufferLength, 753 OUT PVOID OutputBuffer, 754 IN ULONG OutputBufferLength, 755 IN ULONG IoControlCode, 756 OUT PIO_STATUS_BLOCK StatusBlock, 757 IN PDEVICE_OBJECT DeviceObject) 758 { 759 return FALSE; 760 } 761 762 BOOLEAN 763 NTAPI 764 CPortPinWavePci::FastRead( 765 IN PFILE_OBJECT FileObject, 766 IN PLARGE_INTEGER FileOffset, 767 IN ULONG Length, 768 IN BOOLEAN Wait, 769 IN ULONG LockKey, 770 IN PVOID Buffer, 771 OUT PIO_STATUS_BLOCK StatusBlock, 772 IN PDEVICE_OBJECT DeviceObject) 773 { 774 return FALSE; 775 } 776 777 BOOLEAN 778 NTAPI 779 CPortPinWavePci::FastWrite( 780 IN PFILE_OBJECT FileObject, 781 IN PLARGE_INTEGER FileOffset, 782 IN ULONG Length, 783 IN BOOLEAN Wait, 784 IN ULONG LockKey, 785 IN PVOID Buffer, 786 OUT PIO_STATUS_BLOCK StatusBlock, 787 IN PDEVICE_OBJECT DeviceObject) 788 { 789 return FALSE; 790 } 791 792 793 NTSTATUS 794 NTAPI 795 CPortPinWavePci::Init( 796 IN PPORTWAVEPCI Port, 797 IN PPORTFILTERWAVEPCI Filter, 798 IN KSPIN_CONNECT * ConnectDetails, 799 IN KSPIN_DESCRIPTOR * KsPinDescriptor, 800 IN PDEVICE_OBJECT DeviceObject) 801 { 802 NTSTATUS Status; 803 PKSDATAFORMAT DataFormat; 804 BOOLEAN Capture; 805 ISubdevice * Subdevice = NULL; 806 PSUBDEVICE_DESCRIPTOR SubDeviceDescriptor = NULL; 807 808 // check if it is a source / sink pin 809 if (KsPinDescriptor->Communication == KSPIN_COMMUNICATION_SINK && KsPinDescriptor->DataFlow == KSPIN_DATAFLOW_IN) 810 { 811 // sink pin 812 Capture = FALSE; 813 } 814 else if (KsPinDescriptor->Communication == KSPIN_COMMUNICATION_SINK && KsPinDescriptor->DataFlow == KSPIN_DATAFLOW_OUT) 815 { 816 // source pin 817 Capture = TRUE; 818 } 819 else 820 { 821 DPRINT("Unexpected Communication %u DataFlow %u\n", KsPinDescriptor->Communication, KsPinDescriptor->DataFlow); 822 DbgBreakPoint(); 823 while(TRUE); 824 } 825 826 // add port / filter reference 827 Port->AddRef(); 828 Filter->AddRef(); 829 830 // initialize pin 831 m_Port = Port; 832 m_Filter = Filter; 833 m_KsPinDescriptor = KsPinDescriptor; 834 m_ConnectDetails = ConnectDetails; 835 m_Miniport = GetWavePciMiniport(Port); 836 m_DeviceObject = DeviceObject; 837 m_State = KSSTATE_STOP; 838 m_Capture = Capture; 839 840 DPRINT("IPortPinWavePci_fnInit entered\n"); 841 842 // get dataformat 843 DataFormat = (PKSDATAFORMAT)(ConnectDetails + 1); 844 845 // allocate data format 846 m_Format = (PKSDATAFORMAT)AllocateItem(NonPagedPool, DataFormat->FormatSize, TAG_PORTCLASS); 847 if (!m_Format) 848 { 849 // release references 850 m_Port->Release(); 851 m_Filter->Release(); 852 853 // no dangling pointers 854 Port = NULL; 855 Filter = NULL; 856 857 // failed to allocate data format 858 return STATUS_INSUFFICIENT_RESOURCES; 859 } 860 861 // copy data format 862 RtlMoveMemory(m_Format, DataFormat, DataFormat->FormatSize); 863 864 // allocate new stream 865 Status = m_Miniport->NewStream(&m_Stream, 866 NULL, 867 NonPagedPool, 868 PPORTWAVEPCISTREAM(this), 869 ConnectDetails->PinId, 870 Capture, 871 m_Format, 872 &m_DmaChannel, 873 &m_ServiceGroup); 874 875 DPRINT("IPortPinWavePci_fnInit Status %x\n", Status); 876 877 if (!NT_SUCCESS(Status)) 878 { 879 // free references 880 Port->Release(); 881 Filter->Release(); 882 883 // free data format 884 FreeItem(m_Format, TAG_PORTCLASS); 885 886 // no dangling pointers 887 m_Port = NULL; 888 m_Filter = NULL; 889 m_Format = NULL; 890 891 // failed to allocate stream 892 return Status; 893 } 894 895 // get allocator requirements for pin 896 Status = m_Stream->GetAllocatorFraming(&m_AllocatorFraming); 897 if (NT_SUCCESS(Status)) 898 { 899 DPRINT("OptionFlags %x RequirementsFlag %x PoolType %x Frames %lu FrameSize %lu FileAlignment %lu\n", 900 m_AllocatorFraming.OptionsFlags, m_AllocatorFraming.RequirementsFlags, m_AllocatorFraming.PoolType, m_AllocatorFraming.Frames, m_AllocatorFraming.FrameSize, m_AllocatorFraming.FileAlignment); 901 } 902 903 // allocate new irp queue 904 Status = NewIrpQueue(&m_IrpQueue); 905 if (!NT_SUCCESS(Status)) 906 { 907 // free references 908 Port->Release(); 909 Filter->Release(); 910 m_Stream->Release(); 911 912 // free data format 913 FreeItem(m_Format, TAG_PORTCLASS); 914 915 // no dangling pointers 916 m_Port = NULL; 917 m_Filter = NULL; 918 m_Format = NULL; 919 m_Stream = NULL; 920 921 // failed to allocate irp queue 922 return Status; 923 } 924 925 // initialize irp queue 926 Status = m_IrpQueue->Init(ConnectDetails, KsPinDescriptor, m_AllocatorFraming.FrameSize, m_AllocatorFraming.FileAlignment, TRUE); 927 if (!NT_SUCCESS(Status)) 928 { 929 // this should never happen 930 ASSERT(0); 931 } 932 933 // get subdevice interface 934 Status = Port->QueryInterface(IID_ISubdevice, (PVOID*)&Subdevice); 935 936 if (!NT_SUCCESS(Status)) 937 { 938 // this function should never fail 939 ASSERT(0); 940 } 941 942 // get subdevice descriptor 943 Status = Subdevice->GetDescriptor(&SubDeviceDescriptor); 944 if (!NT_SUCCESS(Status)) 945 { 946 // this function should never fail 947 ASSERT(0); 948 } 949 950 // release subdevice 951 Subdevice->Release(); 952 953 /* set up subdevice descriptor */ 954 RtlZeroMemory(&m_Descriptor, sizeof(SUBDEVICE_DESCRIPTOR)); 955 m_Descriptor.FilterPropertySet = PinWavePciPropertySet; 956 m_Descriptor.FilterPropertySetCount = sizeof(PinWavePciPropertySet) / sizeof(KSPROPERTY_SET); 957 m_Descriptor.UnknownStream = (PUNKNOWN)m_Stream; 958 m_Descriptor.DeviceDescriptor = SubDeviceDescriptor->DeviceDescriptor; 959 m_Descriptor.UnknownMiniport = SubDeviceDescriptor->UnknownMiniport; 960 m_Descriptor.PortPin = (PVOID)this; 961 962 if (m_ServiceGroup) 963 { 964 Status = m_ServiceGroup->AddMember(PSERVICESINK(this)); 965 if (!NT_SUCCESS(Status)) 966 { 967 // free references 968 m_Stream->Release(); 969 Port->Release(); 970 Filter->Release(); 971 972 // free data format 973 FreeItem(m_Format, TAG_PORTCLASS); 974 975 // no dangling pointers 976 m_Stream = NULL; 977 m_Port = NULL; 978 m_Filter = NULL; 979 m_Format = NULL; 980 981 // failed to add to service group 982 return Status; 983 } 984 } 985 986 987 return STATUS_SUCCESS; 988 } 989 990 PVOID 991 NTAPI 992 CPortPinWavePci::GetIrpStream() 993 { 994 return (PVOID)m_IrpQueue; 995 } 996 997 998 PMINIPORT 999 NTAPI 1000 CPortPinWavePci::GetMiniport() 1001 { 1002 return (PMINIPORT)m_Miniport; 1003 } 1004 1005 1006 NTSTATUS 1007 NewPortPinWavePci( 1008 OUT IPortPinWavePci ** OutPin) 1009 { 1010 CPortPinWavePci * This; 1011 1012 This = new(NonPagedPool, TAG_PORTCLASS) CPortPinWavePci(NULL); 1013 if (!This) 1014 return STATUS_INSUFFICIENT_RESOURCES; 1015 1016 This->AddRef(); 1017 1018 // store result 1019 *OutPin = (IPortPinWavePci*)This; 1020 1021 return STATUS_SUCCESS; 1022 } 1023 1024