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