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