1 /* 2 * COPYRIGHT: See COPYING in the top level directory 3 * PROJECT: ReactOS Kernel Streaming 4 * FILE: drivers/wdm/audio/backpln/portcls/pin_wavecyclic.cpp 5 * PURPOSE: WaveCyclic IRP Audio Pin 6 * PROGRAMMER: Johannes Anderwald 7 */ 8 9 #include "private.hpp" 10 11 #define NDEBUG 12 #include <debug.h> 13 14 class CPortPinWaveCyclic : public CUnknownImpl<IPortPinWaveCyclic, IServiceSink> 15 { 16 public: 17 inline 18 PVOID 19 operator new( 20 size_t Size, 21 POOL_TYPE PoolType, 22 ULONG Tag) 23 { 24 return ExAllocatePoolWithTag(PoolType, Size, Tag); 25 } 26 27 STDMETHODIMP QueryInterface( REFIID InterfaceId, PVOID* Interface); 28 29 IMP_IPortPinWaveCyclic; 30 IMP_IServiceSink; 31 CPortPinWaveCyclic(IUnknown *OuterUnknown) : 32 m_Port(nullptr), 33 m_Filter(nullptr), 34 m_KsPinDescriptor(nullptr), 35 m_Miniport(nullptr), 36 m_ServiceGroup(nullptr), 37 m_DmaChannel(nullptr), 38 m_Stream(nullptr), 39 m_State(KSSTATE_STOP), 40 m_Format(nullptr), 41 m_ConnectDetails(nullptr), 42 m_CommonBuffer(nullptr), 43 m_CommonBufferSize(0), 44 m_CommonBufferOffset(0), 45 m_IrpQueue(nullptr), 46 m_FrameSize(0), 47 m_Capture(FALSE), 48 m_TotalPackets(0), 49 m_StopCount(0), 50 m_Position({0}), 51 m_AllocatorFraming({{0}}), 52 m_Descriptor(nullptr), 53 m_EventListLock(0), 54 m_EventList({nullptr}), 55 m_ResetState(KSRESET_BEGIN), 56 m_Delay(0) 57 { 58 } 59 virtual ~CPortPinWaveCyclic(){} 60 61 protected: 62 63 VOID UpdateCommonBuffer(ULONG Position, ULONG MaxTransferCount); 64 VOID UpdateCommonBufferOverlap(ULONG Position, ULONG MaxTransferCount); 65 VOID GeneratePositionEvents(IN ULONGLONG OldOffset, IN ULONGLONG NewOffset); 66 67 friend NTSTATUS NTAPI PinWaveCyclicState(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data); 68 friend NTSTATUS NTAPI PinWaveCyclicDataFormat(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data); 69 friend NTSTATUS NTAPI PinWaveCyclicAudioPosition(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data); 70 friend NTSTATUS NTAPI PinWaveCyclicAllocatorFraming(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data); 71 friend NTSTATUS NTAPI PinWaveCyclicAddEndOfStreamEvent(IN PIRP Irp, IN PKSEVENTDATA EventData, IN PKSEVENT_ENTRY EventEntry); 72 friend NTSTATUS NTAPI PinWaveCyclicAddLoopedStreamEvent(IN PIRP Irp, IN PKSEVENTDATA EventData, IN PKSEVENT_ENTRY EventEntry); 73 friend VOID CALLBACK PinSetStateWorkerRoutine(IN PDEVICE_OBJECT DeviceObject, IN PVOID Context); 74 75 IPortWaveCyclic * m_Port; 76 IPortFilterWaveCyclic * m_Filter; 77 KSPIN_DESCRIPTOR * m_KsPinDescriptor; 78 PMINIPORTWAVECYCLIC m_Miniport; 79 PSERVICEGROUP m_ServiceGroup; 80 PDMACHANNEL m_DmaChannel; 81 PMINIPORTWAVECYCLICSTREAM m_Stream; 82 KSSTATE m_State; 83 PKSDATAFORMAT m_Format; 84 PKSPIN_CONNECT m_ConnectDetails; 85 86 PVOID m_CommonBuffer; 87 ULONG m_CommonBufferSize; 88 ULONG m_CommonBufferOffset; 89 90 IIrpQueue * m_IrpQueue; 91 92 ULONG m_FrameSize; 93 BOOL m_Capture; 94 95 ULONG m_TotalPackets; 96 ULONG m_StopCount; 97 KSAUDIO_POSITION m_Position; 98 KSALLOCATOR_FRAMING m_AllocatorFraming; 99 PSUBDEVICE_DESCRIPTOR m_Descriptor; 100 101 KSPIN_LOCK m_EventListLock; 102 LIST_ENTRY m_EventList; 103 104 KSRESET m_ResetState; 105 106 ULONG m_Delay; 107 }; 108 109 typedef struct 110 { 111 ULONG bLoopedStreaming; 112 ULONGLONG Position; 113 }LOOPEDSTREAMING_EVENT_CONTEXT, *PLOOPEDSTREAMING_EVENT_CONTEXT; 114 115 typedef struct 116 { 117 ULONG bLoopedStreaming; 118 }ENDOFSTREAM_EVENT_CONTEXT, *PENDOFSTREAM_EVENT_CONTEXT; 119 120 NTSTATUS NTAPI PinWaveCyclicState(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data); 121 NTSTATUS NTAPI PinWaveCyclicDataFormat(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data); 122 NTSTATUS NTAPI PinWaveCyclicAudioPosition(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data); 123 NTSTATUS NTAPI PinWaveCyclicAllocatorFraming(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data); 124 NTSTATUS NTAPI PinWaveCyclicAddEndOfStreamEvent(IN PIRP Irp, IN PKSEVENTDATA EventData, IN PKSEVENT_ENTRY EventEntry); 125 NTSTATUS NTAPI PinWaveCyclicAddLoopedStreamEvent(IN PIRP Irp, IN PKSEVENTDATA EventData, IN PKSEVENT_ENTRY EventEntry); 126 NTSTATUS NTAPI PinWaveCyclicDRMHandler(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data); 127 128 DEFINE_KSPROPERTY_CONNECTIONSET(PinWaveCyclicConnectionSet, PinWaveCyclicState, PinWaveCyclicDataFormat, PinWaveCyclicAllocatorFraming); 129 DEFINE_KSPROPERTY_AUDIOSET(PinWaveCyclicAudioSet, PinWaveCyclicAudioPosition); 130 DEFINE_KSPROPERTY_DRMSET(PinWaveCyclicDRMSet, PinWaveCyclicDRMHandler); 131 132 KSEVENT_ITEM PinWaveCyclicConnectionEventSet = 133 { 134 KSEVENT_CONNECTION_ENDOFSTREAM, 135 sizeof(KSEVENTDATA), 136 sizeof(ENDOFSTREAM_EVENT_CONTEXT), 137 PinWaveCyclicAddEndOfStreamEvent, 138 0, 139 0 140 }; 141 142 KSEVENT_ITEM PinWaveCyclicStreamingEventSet = 143 { 144 KSEVENT_LOOPEDSTREAMING_POSITION, 145 sizeof(LOOPEDSTREAMING_POSITION_EVENT_DATA), 146 sizeof(LOOPEDSTREAMING_EVENT_CONTEXT), 147 PinWaveCyclicAddLoopedStreamEvent, 148 0, 149 0 150 }; 151 152 KSPROPERTY_SET PinWaveCyclicPropertySet[] = 153 { 154 { 155 &KSPROPSETID_Connection, 156 sizeof(PinWaveCyclicConnectionSet) / sizeof(KSPROPERTY_ITEM), 157 (const KSPROPERTY_ITEM*)&PinWaveCyclicConnectionSet, 158 0, 159 NULL 160 }, 161 { 162 &KSPROPSETID_Audio, 163 sizeof(PinWaveCyclicAudioSet) / sizeof(KSPROPERTY_ITEM), 164 (const KSPROPERTY_ITEM*)&PinWaveCyclicAudioSet, 165 0, 166 NULL 167 }, 168 { 169 &KSPROPSETID_DrmAudioStream, 170 sizeof(PinWaveCyclicDRMSet) / sizeof(KSPROPERTY_ITEM), 171 (const KSPROPERTY_ITEM*)&PinWaveCyclicDRMSet, 172 0, 173 NULL 174 } 175 }; 176 177 KSEVENT_SET PinWaveCyclicEventSet[] = 178 { 179 { 180 &KSEVENTSETID_LoopedStreaming, 181 sizeof(PinWaveCyclicStreamingEventSet) / sizeof(KSEVENT_ITEM), 182 (const KSEVENT_ITEM*)&PinWaveCyclicStreamingEventSet 183 }, 184 { 185 &KSEVENTSETID_Connection, 186 sizeof(PinWaveCyclicConnectionEventSet) / sizeof(KSEVENT_ITEM), 187 (const KSEVENT_ITEM*)&PinWaveCyclicConnectionEventSet 188 } 189 }; 190 191 //================================================================================================================================== 192 193 NTSTATUS 194 NTAPI 195 CPortPinWaveCyclic::QueryInterface( 196 IN REFIID refiid, 197 OUT PVOID* Output) 198 { 199 DPRINT("IServiceSink_fnQueryInterface entered\n"); 200 201 if (IsEqualGUIDAligned(refiid, IID_IIrpTarget) || 202 IsEqualGUIDAligned(refiid, IID_IUnknown)) 203 { 204 *Output = PVOID(PUNKNOWN((IIrpTarget*)this)); 205 PUNKNOWN(*Output)->AddRef(); 206 return STATUS_SUCCESS; 207 } 208 209 if (IsEqualGUIDAligned(refiid, IID_IServiceSink)) 210 { 211 *Output = PVOID(PUNKNOWN(PSERVICESINK(this))); 212 PUNKNOWN(*Output)->AddRef(); 213 return STATUS_SUCCESS; 214 } 215 216 return STATUS_UNSUCCESSFUL; 217 } 218 219 NTSTATUS 220 NTAPI 221 PinWaveCyclicDRMHandler( 222 IN PIRP Irp, 223 IN PKSIDENTIFIER Request, 224 IN OUT PVOID Data) 225 { 226 DPRINT1("PinWaveCyclicDRMHandler\n"); 227 ASSERT(0); 228 return STATUS_INVALID_PARAMETER; 229 } 230 231 NTSTATUS 232 NTAPI 233 PinWaveCyclicAddEndOfStreamEvent( 234 IN PIRP Irp, 235 IN PKSEVENTDATA EventData, 236 IN PKSEVENT_ENTRY EventEntry) 237 { 238 PENDOFSTREAM_EVENT_CONTEXT Entry; 239 PSUBDEVICE_DESCRIPTOR Descriptor; 240 CPortPinWaveCyclic *Pin; 241 242 // get sub device descriptor 243 Descriptor = (PSUBDEVICE_DESCRIPTOR)KSPROPERTY_ITEM_IRP_STORAGE(Irp); 244 245 // sanity check 246 PC_ASSERT(Descriptor); 247 PC_ASSERT(Descriptor->PortPin); 248 PC_ASSERT_IRQL(DISPATCH_LEVEL); 249 250 // cast to pin impl 251 Pin = (CPortPinWaveCyclic*)Descriptor->PortPin; 252 253 // get extra size 254 Entry = (PENDOFSTREAM_EVENT_CONTEXT)(EventEntry + 1); 255 256 // not a looped event 257 Entry->bLoopedStreaming = FALSE; 258 259 // insert item 260 (void)ExInterlockedInsertTailList(&Pin->m_EventList, &EventEntry->ListEntry, &Pin->m_EventListLock); 261 262 // done 263 return STATUS_SUCCESS; 264 } 265 266 NTSTATUS 267 NTAPI 268 PinWaveCyclicAddLoopedStreamEvent( 269 IN PIRP Irp, 270 IN PKSEVENTDATA EventData, 271 IN PKSEVENT_ENTRY EventEntry) 272 { 273 PLOOPEDSTREAMING_POSITION_EVENT_DATA Data; 274 PLOOPEDSTREAMING_EVENT_CONTEXT Entry; 275 PSUBDEVICE_DESCRIPTOR Descriptor; 276 CPortPinWaveCyclic *Pin; 277 278 // get sub device descriptor 279 Descriptor = (PSUBDEVICE_DESCRIPTOR)KSEVENT_ITEM_IRP_STORAGE(Irp); 280 281 // sanity check 282 PC_ASSERT(Descriptor); 283 PC_ASSERT(Descriptor->PortPin); 284 PC_ASSERT_IRQL(DISPATCH_LEVEL); 285 286 // cast to pin impl 287 Pin = (CPortPinWaveCyclic*)Descriptor->PortPin; 288 289 // cast to looped event 290 Data = (PLOOPEDSTREAMING_POSITION_EVENT_DATA)EventData; 291 292 // get extra size 293 Entry = (PLOOPEDSTREAMING_EVENT_CONTEXT)(EventEntry + 1); 294 295 Entry->bLoopedStreaming = TRUE; 296 Entry->Position = Data->Position; 297 298 DPRINT1("Added event\n"); 299 300 // insert item 301 (void)ExInterlockedInsertTailList(&Pin->m_EventList, &EventEntry->ListEntry, &Pin->m_EventListLock); 302 303 // done 304 return STATUS_SUCCESS; 305 } 306 307 NTSTATUS 308 NTAPI 309 PinWaveCyclicAllocatorFraming( 310 IN PIRP Irp, 311 IN PKSIDENTIFIER Request, 312 IN OUT PVOID Data) 313 { 314 CPortPinWaveCyclic *Pin; 315 PSUBDEVICE_DESCRIPTOR Descriptor; 316 317 // get sub device descriptor 318 Descriptor = (PSUBDEVICE_DESCRIPTOR)KSEVENT_ITEM_IRP_STORAGE(Irp); 319 320 // sanity check 321 PC_ASSERT(Descriptor); 322 PC_ASSERT(Descriptor->PortPin); 323 PC_ASSERT_IRQL(DISPATCH_LEVEL); 324 325 // cast to pin impl 326 Pin = (CPortPinWaveCyclic*)Descriptor->PortPin; 327 328 if (Request->Flags & KSPROPERTY_TYPE_GET) 329 { 330 // copy pin framing 331 RtlMoveMemory(Data, &Pin->m_AllocatorFraming, sizeof(KSALLOCATOR_FRAMING)); 332 333 Irp->IoStatus.Information = sizeof(KSALLOCATOR_FRAMING); 334 return STATUS_SUCCESS; 335 } 336 337 // not supported 338 return STATUS_NOT_SUPPORTED; 339 } 340 341 NTSTATUS 342 NTAPI 343 PinWaveCyclicAudioPosition( 344 IN PIRP Irp, 345 IN PKSIDENTIFIER Request, 346 IN OUT PVOID Data) 347 { 348 CPortPinWaveCyclic *Pin; 349 PSUBDEVICE_DESCRIPTOR Descriptor; 350 PKSAUDIO_POSITION Position; 351 352 // get sub device descriptor 353 Descriptor = (PSUBDEVICE_DESCRIPTOR)KSPROPERTY_ITEM_IRP_STORAGE(Irp); 354 355 // sanity check 356 PC_ASSERT(Descriptor); 357 PC_ASSERT(Descriptor->PortPin); 358 PC_ASSERT_IRQL(DISPATCH_LEVEL); 359 360 // cast to pin impl 361 Pin = (CPortPinWaveCyclic*)Descriptor->PortPin; 362 363 //sanity check 364 PC_ASSERT(Pin->m_Stream); 365 366 if (Request->Flags & KSPROPERTY_TYPE_GET) 367 { 368 // FIXME non multithreading-safe 369 // copy audio position 370 371 Position = (PKSAUDIO_POSITION)Data; 372 373 if (Pin->m_ConnectDetails->Interface.Id == KSINTERFACE_STANDARD_STREAMING) 374 { 375 RtlMoveMemory(Data, &Pin->m_Position, sizeof(KSAUDIO_POSITION)); 376 DPRINT("Play %lu Record %lu\n", Pin->m_Position.PlayOffset, Pin->m_Position.WriteOffset); 377 } 378 else if (Pin->m_ConnectDetails->Interface.Id == KSINTERFACE_STANDARD_LOOPED_STREAMING) 379 { 380 Position->PlayOffset = Pin->m_Position.PlayOffset; 381 Position->WriteOffset = (ULONGLONG)Pin->m_IrpQueue->GetCurrentIrpOffset(); 382 DPRINT("Play %lu Write %lu\n", Position->PlayOffset, Position->WriteOffset); 383 } 384 385 Irp->IoStatus.Information = sizeof(KSAUDIO_POSITION); 386 return STATUS_SUCCESS; 387 } 388 389 // not supported 390 return STATUS_NOT_SUPPORTED; 391 } 392 393 typedef struct 394 { 395 CPortPinWaveCyclic *Pin; 396 KSSTATE NewState; 397 PIO_WORKITEM WorkItem; 398 PIRP Irp; 399 400 }SETPIN_CONTEXT, *PSETPIN_CONTEXT; 401 402 VOID 403 CALLBACK 404 PinSetStateWorkerRoutine( 405 IN PDEVICE_OBJECT DeviceObject, 406 IN PVOID Context) 407 { 408 PSETPIN_CONTEXT PinWorkContext = (PSETPIN_CONTEXT)Context; 409 NTSTATUS Status; 410 411 // try set stream 412 Status = PinWorkContext->Pin->m_Stream->SetState(PinWorkContext->NewState); 413 414 DPRINT1("Setting state %u %x\n", PinWorkContext->NewState, Status); 415 if (NT_SUCCESS(Status)) 416 { 417 // store new state 418 PinWorkContext->Pin->m_State = PinWorkContext->NewState; 419 420 if (PinWorkContext->Pin->m_ConnectDetails->Interface.Id == KSINTERFACE_STANDARD_LOOPED_STREAMING && PinWorkContext->Pin->m_State == KSSTATE_STOP) 421 { 422 /* FIXME complete pending irps with successful state */ 423 PinWorkContext->Pin->m_IrpQueue->CancelBuffers(); 424 } 425 //HACK 426 //PinWorkContext->Pin->m_IrpQueue->CancelBuffers(); 427 } 428 429 // store result 430 PinWorkContext->Irp->IoStatus.Information = sizeof(KSSTATE); 431 PinWorkContext->Irp->IoStatus.Status = Status; 432 433 // complete irp 434 IoCompleteRequest(PinWorkContext->Irp, IO_NO_INCREMENT); 435 436 // free work item 437 IoFreeWorkItem(PinWorkContext->WorkItem); 438 439 // free work context 440 FreeItem(PinWorkContext, TAG_PORTCLASS); 441 442 } 443 444 NTSTATUS 445 NTAPI 446 PinWaveCyclicState( 447 IN PIRP Irp, 448 IN PKSIDENTIFIER Request, 449 IN OUT PVOID Data) 450 { 451 NTSTATUS Status = STATUS_UNSUCCESSFUL; 452 CPortPinWaveCyclic *Pin; 453 PSUBDEVICE_DESCRIPTOR Descriptor; 454 PKSSTATE State = (PKSSTATE)Data; 455 456 // get sub device descriptor 457 Descriptor = (PSUBDEVICE_DESCRIPTOR)KSPROPERTY_ITEM_IRP_STORAGE(Irp); 458 459 // sanity check 460 PC_ASSERT(Descriptor); 461 PC_ASSERT(Descriptor->PortPin); 462 PC_ASSERT_IRQL(DISPATCH_LEVEL); 463 464 // cast to pin impl 465 Pin = (CPortPinWaveCyclic*)Descriptor->PortPin; 466 467 //sanity check 468 PC_ASSERT(Pin->m_Stream); 469 470 if (Request->Flags & KSPROPERTY_TYPE_SET) 471 { 472 // try set stream 473 Status = Pin->m_Stream->SetState(*State); 474 475 DPRINT("Setting state %u %x\n", *State, Status); 476 if (NT_SUCCESS(Status)) 477 { 478 // store new state 479 Pin->m_State = *State; 480 481 if (Pin->m_ConnectDetails->Interface.Id == KSINTERFACE_STANDARD_LOOPED_STREAMING && Pin->m_State == KSSTATE_STOP) 482 { 483 // FIXME 484 // complete with successful state 485 Pin->m_Stream->Silence(Pin->m_CommonBuffer, Pin->m_CommonBufferSize); 486 Pin->m_IrpQueue->CancelBuffers(); 487 Pin->m_Position.PlayOffset = 0; 488 Pin->m_Position.WriteOffset = 0; 489 } 490 else if (Pin->m_State == KSSTATE_STOP) 491 { 492 Pin->m_Stream->Silence(Pin->m_CommonBuffer, Pin->m_CommonBufferSize); 493 Pin->m_IrpQueue->CancelBuffers(); 494 Pin->m_Position.PlayOffset = 0; 495 Pin->m_Position.WriteOffset = 0; 496 } 497 // store result 498 Irp->IoStatus.Information = sizeof(KSSTATE); 499 } 500 return Status; 501 } 502 else if (Request->Flags & KSPROPERTY_TYPE_GET) 503 { 504 // get current stream state 505 *State = Pin->m_State; 506 // store result 507 Irp->IoStatus.Information = sizeof(KSSTATE); 508 509 return STATUS_SUCCESS; 510 } 511 512 // unsupported request 513 return STATUS_NOT_SUPPORTED; 514 } 515 516 NTSTATUS 517 NTAPI 518 PinWaveCyclicDataFormat( 519 IN PIRP Irp, 520 IN PKSIDENTIFIER Request, 521 IN OUT PVOID Data) 522 { 523 NTSTATUS Status = STATUS_UNSUCCESSFUL; 524 CPortPinWaveCyclic *Pin; 525 PSUBDEVICE_DESCRIPTOR Descriptor; 526 PIO_STACK_LOCATION IoStack; 527 528 // get current irp stack location 529 IoStack = IoGetCurrentIrpStackLocation(Irp); 530 531 // get sub device descriptor 532 Descriptor = (PSUBDEVICE_DESCRIPTOR)KSPROPERTY_ITEM_IRP_STORAGE(Irp); 533 534 // sanity check 535 PC_ASSERT(Descriptor); 536 PC_ASSERT(Descriptor->PortPin); 537 538 // cast to pin impl 539 Pin = (CPortPinWaveCyclic*)Descriptor->PortPin; 540 541 //sanity check 542 PC_ASSERT(Pin->m_Stream); 543 PC_ASSERT(Pin->m_Format); 544 545 if (Request->Flags & KSPROPERTY_TYPE_SET) 546 { 547 // try to change data format 548 PKSDATAFORMAT NewDataFormat, DataFormat = (PKSDATAFORMAT)Irp->UserBuffer; 549 ULONG Size = min(Pin->m_Format->FormatSize, DataFormat->FormatSize); 550 551 if (RtlCompareMemory(DataFormat, Pin->m_Format, Size) == Size) 552 { 553 // format is identical 554 Irp->IoStatus.Information = DataFormat->FormatSize; 555 return STATUS_SUCCESS; 556 } 557 558 // new change request 559 PC_ASSERT(Pin->m_State != KSSTATE_RUN); 560 // FIXME queue a work item when Irql != PASSIVE_LEVEL 561 PC_ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL); 562 563 // allocate new data format 564 NewDataFormat = (PKSDATAFORMAT)AllocateItem(NonPagedPool, DataFormat->FormatSize, TAG_PORTCLASS); 565 if (!NewDataFormat) 566 { 567 // not enough memory 568 return STATUS_NO_MEMORY; 569 } 570 571 // copy new data format 572 RtlMoveMemory(NewDataFormat, DataFormat, DataFormat->FormatSize); 573 574 // set new format 575 Status = Pin->m_Stream->SetFormat(NewDataFormat); 576 if (NT_SUCCESS(Status)) 577 { 578 // free old format 579 FreeItem(Pin->m_Format, TAG_PORTCLASS); 580 581 // store new format 582 Pin->m_Format = NewDataFormat; 583 Irp->IoStatus.Information = NewDataFormat->FormatSize; 584 585 #if 0 586 PC_ASSERT(NewDataFormat->FormatSize == sizeof(KSDATAFORMAT_WAVEFORMATEX)); 587 PC_ASSERT(IsEqualGUIDAligned(((PKSDATAFORMAT_WAVEFORMATEX)NewDataFormat)->DataFormat.MajorFormat, KSDATAFORMAT_TYPE_AUDIO)); 588 PC_ASSERT(IsEqualGUIDAligned(((PKSDATAFORMAT_WAVEFORMATEX)NewDataFormat)->DataFormat.SubFormat, KSDATAFORMAT_SUBTYPE_PCM)); 589 PC_ASSERT(IsEqualGUIDAligned(((PKSDATAFORMAT_WAVEFORMATEX)NewDataFormat)->DataFormat.Specifier, KSDATAFORMAT_SPECIFIER_WAVEFORMATEX)); 590 591 DPRINT("NewDataFormat: Channels %u Bits %u Samples %u\n", ((PKSDATAFORMAT_WAVEFORMATEX)NewDataFormat)->WaveFormatEx.nChannels, 592 ((PKSDATAFORMAT_WAVEFORMATEX)NewDataFormat)->WaveFormatEx.wBitsPerSample, 593 ((PKSDATAFORMAT_WAVEFORMATEX)NewDataFormat)->WaveFormatEx.nSamplesPerSec); 594 #endif 595 596 } 597 else 598 { 599 // failed to set format 600 FreeItem(NewDataFormat, TAG_PORTCLASS); 601 } 602 603 // done 604 return Status; 605 } 606 else if (Request->Flags & KSPROPERTY_TYPE_GET) 607 { 608 // get current data format 609 PC_ASSERT(Pin->m_Format); 610 611 if (Pin->m_Format->FormatSize > IoStack->Parameters.DeviceIoControl.OutputBufferLength) 612 { 613 // buffer too small 614 Irp->IoStatus.Information = Pin->m_Format->FormatSize; 615 return STATUS_MORE_ENTRIES; 616 } 617 // copy data format 618 RtlMoveMemory(Data, Pin->m_Format, Pin->m_Format->FormatSize); 619 // store result size 620 Irp->IoStatus.Information = Pin->m_Format->FormatSize; 621 622 // done 623 return STATUS_SUCCESS; 624 } 625 626 // unsupported request 627 return STATUS_NOT_SUPPORTED; 628 } 629 630 VOID 631 CPortPinWaveCyclic::GeneratePositionEvents( 632 IN ULONGLONG OldOffset, 633 IN ULONGLONG NewOffset) 634 { 635 PLIST_ENTRY Entry; 636 PKSEVENT_ENTRY EventEntry; 637 PLOOPEDSTREAMING_EVENT_CONTEXT Context; 638 639 // acquire event lock 640 KeAcquireSpinLockAtDpcLevel(&m_EventListLock); 641 642 // point to first entry 643 Entry = m_EventList.Flink; 644 645 while(Entry != &m_EventList) 646 { 647 // get event entry 648 EventEntry = (PKSEVENT_ENTRY)CONTAINING_RECORD(Entry, KSEVENT_ENTRY, ListEntry); 649 650 // get event entry context 651 Context = (PLOOPEDSTREAMING_EVENT_CONTEXT)(EventEntry + 1); 652 653 if (Context->bLoopedStreaming != FALSE) 654 { 655 if (NewOffset > OldOffset) 656 { 657 /* buffer progress no overlap */ 658 if (OldOffset < Context->Position && Context->Position <= NewOffset) 659 { 660 /* when someone eventually fixes sprintf... */ 661 DPRINT("Generating event at OldOffset %I64u\n", OldOffset); 662 DPRINT("Context->Position %I64u\n", Context->Position); 663 DPRINT("NewOffset %I64u\n", NewOffset); 664 /* generate event */ 665 KsGenerateEvent(EventEntry); 666 } 667 } 668 else 669 { 670 /* buffer wrap-arround */ 671 if (OldOffset < Context->Position || NewOffset > Context->Position) 672 { 673 /* when someone eventually fixes sprintf... */ 674 DPRINT("Generating event at OldOffset %I64u\n", OldOffset); 675 DPRINT("Context->Position %I64u\n", Context->Position); 676 DPRINT("NewOffset %I64u\n", NewOffset); 677 /* generate event */ 678 KsGenerateEvent(EventEntry); 679 } 680 } 681 } 682 683 // move to next entry 684 Entry = Entry->Flink; 685 } 686 687 // release lock 688 KeReleaseSpinLockFromDpcLevel(&m_EventListLock); 689 } 690 691 VOID 692 CPortPinWaveCyclic::UpdateCommonBuffer( 693 ULONG Position, 694 ULONG MaxTransferCount) 695 { 696 ULONG BufferLength; 697 ULONG BytesToCopy; 698 ULONG BufferSize; 699 ULONG Gap; 700 PUCHAR Buffer; 701 NTSTATUS Status; 702 703 BufferLength = Position - m_CommonBufferOffset; 704 BufferLength = min(BufferLength, MaxTransferCount); 705 706 while(BufferLength) 707 { 708 Status = m_IrpQueue->GetMapping(&Buffer, &BufferSize); 709 if (!NT_SUCCESS(Status)) 710 { 711 Gap = Position - m_CommonBufferOffset; 712 if (Gap > BufferLength) 713 { 714 // insert silence samples 715 DPRINT("Inserting Silence Buffer Offset %lu GapLength %lu\n", m_CommonBufferOffset, BufferLength); 716 m_Stream->Silence((PUCHAR)m_CommonBuffer + m_CommonBufferOffset, BufferLength); 717 718 m_CommonBufferOffset += BufferLength; 719 } 720 break; 721 } 722 723 BytesToCopy = min(BufferLength, BufferSize); 724 725 if (m_Capture) 726 { 727 m_DmaChannel->CopyFrom(Buffer, (PUCHAR)m_CommonBuffer + m_CommonBufferOffset, BytesToCopy); 728 } 729 else 730 { 731 m_DmaChannel->CopyTo((PUCHAR)m_CommonBuffer + m_CommonBufferOffset, Buffer, BytesToCopy); 732 } 733 734 m_IrpQueue->UpdateMapping(BytesToCopy); 735 m_CommonBufferOffset += BytesToCopy; 736 737 BufferLength -= BytesToCopy; 738 m_Position.PlayOffset += BytesToCopy; 739 740 if (m_ConnectDetails->Interface.Id == KSINTERFACE_STANDARD_LOOPED_STREAMING) 741 { 742 if (m_Position.WriteOffset) 743 { 744 // normalize position 745 m_Position.PlayOffset = m_Position.PlayOffset % m_Position.WriteOffset; 746 } 747 } 748 } 749 } 750 751 VOID 752 CPortPinWaveCyclic::UpdateCommonBufferOverlap( 753 ULONG Position, 754 ULONG MaxTransferCount) 755 { 756 ULONG BufferLength, Length, Gap; 757 ULONG BytesToCopy; 758 ULONG BufferSize; 759 PUCHAR Buffer; 760 NTSTATUS Status; 761 762 BufferLength = Gap = m_CommonBufferSize - m_CommonBufferOffset; 763 BufferLength = Length = min(BufferLength, MaxTransferCount); 764 while(BufferLength) 765 { 766 Status = m_IrpQueue->GetMapping(&Buffer, &BufferSize); 767 if (!NT_SUCCESS(Status)) 768 { 769 Gap = m_CommonBufferSize - m_CommonBufferOffset + Position; 770 if (Gap > BufferLength) 771 { 772 // insert silence samples 773 DPRINT("Overlap Inserting Silence Buffer Size %lu Offset %lu Gap %lu Position %lu\n", m_CommonBufferSize, m_CommonBufferOffset, Gap, Position); 774 m_Stream->Silence((PUCHAR)m_CommonBuffer + m_CommonBufferOffset, BufferLength); 775 776 m_CommonBufferOffset += BufferLength; 777 } 778 break; 779 } 780 781 BytesToCopy = min(BufferLength, BufferSize); 782 783 if (m_Capture) 784 { 785 m_DmaChannel->CopyFrom(Buffer, 786 (PUCHAR)m_CommonBuffer + m_CommonBufferOffset, 787 BytesToCopy); 788 } 789 else 790 { 791 m_DmaChannel->CopyTo((PUCHAR)m_CommonBuffer + m_CommonBufferOffset, 792 Buffer, 793 BytesToCopy); 794 } 795 796 m_IrpQueue->UpdateMapping(BytesToCopy); 797 m_CommonBufferOffset += BytesToCopy; 798 m_Position.PlayOffset += BytesToCopy; 799 800 BufferLength -=BytesToCopy; 801 802 if (m_ConnectDetails->Interface.Id == KSINTERFACE_STANDARD_LOOPED_STREAMING) 803 { 804 if (m_Position.WriteOffset) 805 { 806 // normalize position 807 m_Position.PlayOffset = m_Position.PlayOffset % m_Position.WriteOffset; 808 } 809 } 810 } 811 812 if (Gap == Length) 813 { 814 m_CommonBufferOffset = 0; 815 816 MaxTransferCount -= Length; 817 818 if (MaxTransferCount) 819 { 820 UpdateCommonBuffer(Position, MaxTransferCount); 821 } 822 } 823 } 824 825 VOID 826 NTAPI 827 CPortPinWaveCyclic::RequestService() 828 { 829 ULONG Position; 830 ULONGLONG OldOffset, NewOffset; 831 832 PC_ASSERT_IRQL(DISPATCH_LEVEL); 833 834 if (m_State == KSSTATE_RUN && m_ResetState == KSRESET_END) 835 { 836 m_Stream->GetPosition(&Position); 837 838 OldOffset = m_Position.PlayOffset; 839 840 if (Position < m_CommonBufferOffset) 841 { 842 UpdateCommonBufferOverlap(Position, m_FrameSize); 843 } 844 else if (Position >= m_CommonBufferOffset) 845 { 846 UpdateCommonBuffer(Position, m_FrameSize); 847 } 848 849 NewOffset = m_Position.PlayOffset; 850 851 GeneratePositionEvents(OldOffset, NewOffset); 852 } 853 } 854 855 NTSTATUS 856 NTAPI 857 CPortPinWaveCyclic::NewIrpTarget( 858 OUT struct IIrpTarget **OutTarget, 859 IN PCWSTR Name, 860 IN PUNKNOWN Unknown, 861 IN POOL_TYPE PoolType, 862 IN PDEVICE_OBJECT DeviceObject, 863 IN PIRP Irp, 864 IN KSOBJECT_CREATE *CreateObject) 865 { 866 UNIMPLEMENTED; 867 return STATUS_UNSUCCESSFUL; 868 } 869 870 NTSTATUS 871 NTAPI 872 CPortPinWaveCyclic::DeviceIoControl( 873 IN PDEVICE_OBJECT DeviceObject, 874 IN PIRP Irp) 875 { 876 PIO_STACK_LOCATION IoStack; 877 PKSPROPERTY Property; 878 UNICODE_STRING GuidString; 879 NTSTATUS Status = STATUS_NOT_SUPPORTED; 880 ULONG Data = 0; 881 KSRESET ResetValue; 882 883 /* get current irp stack location */ 884 IoStack = IoGetCurrentIrpStackLocation(Irp); 885 886 if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_PROPERTY) 887 { 888 /* handle property with subdevice descriptor */ 889 Status = PcHandlePropertyWithTable(Irp, m_Descriptor->FilterPropertySetCount, m_Descriptor->FilterPropertySet, m_Descriptor); 890 891 if (Status == STATUS_NOT_FOUND) 892 { 893 Property = (PKSPROPERTY)IoStack->Parameters.DeviceIoControl.Type3InputBuffer; 894 895 RtlStringFromGUID(Property->Set, &GuidString); 896 DPRINT("Unhandled property Set |%S| Id %u Flags %x\n", GuidString.Buffer, Property->Id, Property->Flags); 897 RtlFreeUnicodeString(&GuidString); 898 } 899 } 900 else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_ENABLE_EVENT) 901 { 902 Status = PcHandleEnableEventWithTable(Irp, m_Descriptor); 903 } 904 else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_DISABLE_EVENT) 905 { 906 Status = PcHandleDisableEventWithTable(Irp, m_Descriptor); 907 } 908 else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_RESET_STATE) 909 { 910 Status = KsAcquireResetValue(Irp, &ResetValue); 911 DPRINT("Status %x Value %u\n", Status, ResetValue); 912 /* check for success */ 913 if (NT_SUCCESS(Status)) 914 { 915 //determine state of reset request 916 if (ResetValue == KSRESET_BEGIN) 917 { 918 // start reset process 919 // incoming read/write requests will be rejected 920 m_ResetState = KSRESET_BEGIN; 921 922 // cancel existing buffers 923 m_IrpQueue->CancelBuffers(); 924 } 925 else if (ResetValue == KSRESET_END) 926 { 927 // end of reset process 928 m_ResetState = KSRESET_END; 929 } 930 } 931 } 932 else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_WRITE_STREAM || IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_READ_STREAM) 933 { 934 /* increment total number of packets */ 935 InterlockedIncrement((PLONG)&m_TotalPackets); 936 937 DPRINT("New Packet Total %u State %x MinData %u\n", m_TotalPackets, m_State, m_IrpQueue->NumData()); 938 939 /* is the device not currently reset */ 940 if (m_ResetState == KSRESET_END) 941 { 942 /* add the mapping */ 943 Status = m_IrpQueue->AddMapping(Irp, &Data); 944 945 /* check for success */ 946 if (NT_SUCCESS(Status)) 947 { 948 m_Position.WriteOffset += Data; 949 Status = STATUS_PENDING; 950 } 951 } 952 else 953 { 954 /* reset request is currently in progress */ 955 Status = STATUS_DEVICE_NOT_READY; 956 DPRINT1("NotReady\n"); 957 } 958 } 959 else 960 { 961 return KsDefaultDeviceIoCompletion(DeviceObject, Irp); 962 } 963 964 if (Status != STATUS_PENDING) 965 { 966 Irp->IoStatus.Status = Status; 967 IoCompleteRequest(Irp, IO_NO_INCREMENT); 968 } 969 970 return Status; 971 } 972 973 NTSTATUS 974 NTAPI 975 CPortPinWaveCyclic::Read( 976 IN PDEVICE_OBJECT DeviceObject, 977 IN PIRP Irp) 978 { 979 return KsDispatchInvalidDeviceRequest(DeviceObject, Irp); 980 } 981 982 NTSTATUS 983 NTAPI 984 CPortPinWaveCyclic::Write( 985 IN PDEVICE_OBJECT DeviceObject, 986 IN PIRP Irp) 987 { 988 return KsDispatchInvalidDeviceRequest(DeviceObject, Irp); 989 } 990 991 NTSTATUS 992 NTAPI 993 CPortPinWaveCyclic::Flush( 994 IN PDEVICE_OBJECT DeviceObject, 995 IN PIRP Irp) 996 { 997 return KsDispatchInvalidDeviceRequest(DeviceObject, Irp); 998 } 999 1000 NTSTATUS 1001 NTAPI 1002 CPortPinWaveCyclic::Close( 1003 IN PDEVICE_OBJECT DeviceObject, 1004 IN PIRP Irp) 1005 { 1006 DPRINT("CPortPinWaveCyclic::Close entered\n"); 1007 1008 PC_ASSERT_IRQL(PASSIVE_LEVEL); 1009 1010 if (m_Format) 1011 { 1012 // free format 1013 FreeItem(m_Format, TAG_PORTCLASS); 1014 1015 // format is freed 1016 m_Format = NULL; 1017 } 1018 1019 if (m_IrpQueue) 1020 { 1021 // cancel remaining irps 1022 m_IrpQueue->CancelBuffers(); 1023 1024 // release irp queue 1025 m_IrpQueue->Release(); 1026 1027 // queue is freed 1028 m_IrpQueue = NULL; 1029 } 1030 1031 if (m_ServiceGroup) 1032 { 1033 // remove member from service group 1034 m_ServiceGroup->RemoveMember(PSERVICESINK(this)); 1035 1036 // do not release service group, it is released by the miniport object 1037 m_ServiceGroup = NULL; 1038 } 1039 1040 if (m_Stream) 1041 { 1042 if (m_State != KSSTATE_STOP) 1043 { 1044 // stop stream 1045 NTSTATUS Status = m_Stream->SetState(KSSTATE_STOP); 1046 if (!NT_SUCCESS(Status)) 1047 { 1048 DPRINT("Warning: failed to stop stream with %x\n", Status); 1049 PC_ASSERT(0); 1050 } 1051 } 1052 // set state to stop 1053 m_State = KSSTATE_STOP; 1054 1055 DPRINT("Closing stream at Irql %u\n", KeGetCurrentIrql()); 1056 1057 // release stream 1058 m_Stream->Release(); 1059 1060 // stream is now freed 1061 m_Stream = NULL; 1062 } 1063 1064 if (m_Filter) 1065 { 1066 // disconnect pin from filter 1067 m_Filter->FreePin((PPORTPINWAVECYCLIC)this); 1068 1069 // release filter reference 1070 m_Filter->Release(); 1071 1072 // pin is done with filter 1073 m_Filter = NULL; 1074 } 1075 1076 if (m_Port) 1077 { 1078 // release reference to port driver 1079 m_Port->Release(); 1080 1081 // work is done for port 1082 m_Port = NULL; 1083 } 1084 1085 Irp->IoStatus.Information = 0; 1086 Irp->IoStatus.Status = STATUS_SUCCESS; 1087 IoCompleteRequest(Irp, IO_NO_INCREMENT); 1088 1089 delete this; 1090 1091 return STATUS_SUCCESS; 1092 } 1093 1094 NTSTATUS 1095 NTAPI 1096 CPortPinWaveCyclic::QuerySecurity( 1097 IN PDEVICE_OBJECT DeviceObject, 1098 IN PIRP Irp) 1099 { 1100 return KsDispatchInvalidDeviceRequest(DeviceObject, Irp); 1101 } 1102 1103 NTSTATUS 1104 NTAPI 1105 CPortPinWaveCyclic::SetSecurity( 1106 IN PDEVICE_OBJECT DeviceObject, 1107 IN PIRP Irp) 1108 { 1109 return KsDispatchInvalidDeviceRequest(DeviceObject, Irp); 1110 } 1111 1112 BOOLEAN 1113 NTAPI 1114 CPortPinWaveCyclic::FastDeviceIoControl( 1115 IN PFILE_OBJECT FileObject, 1116 IN BOOLEAN Wait, 1117 IN PVOID InputBuffer, 1118 IN ULONG InputBufferLength, 1119 OUT PVOID OutputBuffer, 1120 IN ULONG OutputBufferLength, 1121 IN ULONG IoControlCode, 1122 OUT PIO_STATUS_BLOCK StatusBlock, 1123 IN PDEVICE_OBJECT DeviceObject) 1124 { 1125 return KsDispatchFastIoDeviceControlFailure(FileObject, Wait, InputBuffer, InputBufferLength, OutputBuffer, OutputBufferLength, IoControlCode, StatusBlock, DeviceObject); 1126 } 1127 1128 BOOLEAN 1129 NTAPI 1130 CPortPinWaveCyclic::FastRead( 1131 IN PFILE_OBJECT FileObject, 1132 IN PLARGE_INTEGER FileOffset, 1133 IN ULONG Length, 1134 IN BOOLEAN Wait, 1135 IN ULONG LockKey, 1136 IN PVOID Buffer, 1137 OUT PIO_STATUS_BLOCK StatusBlock, 1138 IN PDEVICE_OBJECT DeviceObject) 1139 { 1140 return KsDispatchFastReadFailure(FileObject, FileOffset, Length, Wait, LockKey, Buffer, StatusBlock, DeviceObject); 1141 } 1142 1143 BOOLEAN 1144 NTAPI 1145 CPortPinWaveCyclic::FastWrite( 1146 IN PFILE_OBJECT FileObject, 1147 IN PLARGE_INTEGER FileOffset, 1148 IN ULONG Length, 1149 IN BOOLEAN Wait, 1150 IN ULONG LockKey, 1151 IN PVOID Buffer, 1152 OUT PIO_STATUS_BLOCK StatusBlock, 1153 IN PDEVICE_OBJECT DeviceObject) 1154 { 1155 return KsDispatchFastReadFailure(FileObject, FileOffset, Length, Wait, LockKey, Buffer, StatusBlock, DeviceObject); 1156 } 1157 1158 NTSTATUS 1159 NTAPI 1160 CPortPinWaveCyclic::Init( 1161 IN PPORTWAVECYCLIC Port, 1162 IN PPORTFILTERWAVECYCLIC Filter, 1163 IN KSPIN_CONNECT * ConnectDetails, 1164 IN KSPIN_DESCRIPTOR * KsPinDescriptor) 1165 { 1166 NTSTATUS Status; 1167 PKSDATAFORMAT DataFormat; 1168 //PDEVICE_OBJECT DeviceObject; 1169 BOOLEAN Capture; 1170 PSUBDEVICE_DESCRIPTOR SubDeviceDescriptor = NULL; 1171 //IDrmAudioStream * DrmAudio = NULL; 1172 1173 m_KsPinDescriptor = KsPinDescriptor; 1174 m_ConnectDetails = ConnectDetails; 1175 m_Miniport = GetWaveCyclicMiniport(Port); 1176 1177 //DeviceObject = GetDeviceObject(Port); 1178 1179 DataFormat = (PKSDATAFORMAT)(ConnectDetails + 1); 1180 1181 DPRINT("CPortPinWaveCyclic::Init entered Size %u\n", DataFormat->FormatSize); 1182 1183 Status = NewIrpQueue(&m_IrpQueue); 1184 if (!NT_SUCCESS(Status)) 1185 return Status; 1186 1187 if (KsPinDescriptor->Communication == KSPIN_COMMUNICATION_SINK && KsPinDescriptor->DataFlow == KSPIN_DATAFLOW_IN) 1188 { 1189 Capture = FALSE; 1190 } 1191 else if (KsPinDescriptor->Communication == KSPIN_COMMUNICATION_SINK && KsPinDescriptor->DataFlow == KSPIN_DATAFLOW_OUT) 1192 { 1193 Capture = TRUE; 1194 } 1195 else 1196 { 1197 DPRINT("Unexpected Communication %u DataFlow %u\n", KsPinDescriptor->Communication, KsPinDescriptor->DataFlow); 1198 DbgBreakPoint(); 1199 while(TRUE); 1200 } 1201 1202 Status = m_Miniport->NewStream(&m_Stream, 1203 NULL, 1204 NonPagedPool, 1205 ConnectDetails->PinId, 1206 Capture, 1207 DataFormat, 1208 &m_DmaChannel, 1209 &m_ServiceGroup); 1210 #if 0 1211 Status = m_Stream->QueryInterface(IID_IDrmAudioStream, (PVOID*)&DrmAudio); 1212 if (NT_SUCCESS(Status)) 1213 { 1214 DRMRIGHTS DrmRights; 1215 DPRINT("Got IID_IDrmAudioStream interface %p\n", DrmAudio); 1216 1217 DrmRights.CopyProtect = FALSE; 1218 DrmRights.Reserved = 0; 1219 DrmRights.DigitalOutputDisable = FALSE; 1220 1221 Status = DrmAudio->SetContentId(1, &DrmRights); 1222 DPRINT("Status %x\n", Status); 1223 } 1224 #endif 1225 1226 DPRINT1("CPortPinWaveCyclic::Init Status %x PinId %u Capture %u\n", Status, ConnectDetails->PinId, Capture); 1227 1228 if (!NT_SUCCESS(Status)) 1229 return Status; 1230 1231 ISubdevice * Subdevice = NULL; 1232 // get subdevice interface 1233 Status = Port->QueryInterface(IID_ISubdevice, (PVOID*)&Subdevice); 1234 1235 if (!NT_SUCCESS(Status)) 1236 return Status; 1237 1238 Status = Subdevice->GetDescriptor(&SubDeviceDescriptor); 1239 if (!NT_SUCCESS(Status)) 1240 { 1241 // failed to get descriptor 1242 Subdevice->Release(); 1243 return Status; 1244 } 1245 1246 /* initialize event management */ 1247 InitializeListHead(&m_EventList); 1248 KeInitializeSpinLock(&m_EventListLock); 1249 1250 Status = PcCreateSubdeviceDescriptor(&m_Descriptor, 1251 SubDeviceDescriptor->InterfaceCount, 1252 SubDeviceDescriptor->Interfaces, 1253 0, /* FIXME KSINTERFACE_STANDARD with KSINTERFACE_STANDARD_STREAMING / KSINTERFACE_STANDARD_LOOPED_STREAMING */ 1254 NULL, 1255 sizeof(PinWaveCyclicPropertySet) / sizeof(KSPROPERTY_SET), 1256 PinWaveCyclicPropertySet, 1257 0, 1258 0, 1259 0, 1260 NULL, 1261 sizeof(PinWaveCyclicEventSet) / sizeof(KSEVENT_SET), 1262 PinWaveCyclicEventSet, 1263 SubDeviceDescriptor->DeviceDescriptor); 1264 1265 m_Descriptor->UnknownStream = (PUNKNOWN)m_Stream; 1266 m_Descriptor->UnknownMiniport = SubDeviceDescriptor->UnknownMiniport; 1267 m_Descriptor->PortPin = (PVOID)this; 1268 m_Descriptor->EventList = &m_EventList; 1269 m_Descriptor->EventListLock = &m_EventListLock; 1270 1271 // initialize reset state 1272 m_ResetState = KSRESET_END; 1273 1274 // release subdevice descriptor 1275 Subdevice->Release(); 1276 1277 // add ourselves to service group 1278 Status = m_ServiceGroup->AddMember(PSERVICESINK(this)); 1279 if (!NT_SUCCESS(Status)) 1280 { 1281 DPRINT("Failed to add pin to service group\n"); 1282 return Status; 1283 } 1284 1285 m_Stream->SetState(KSSTATE_STOP); 1286 m_State = KSSTATE_STOP; 1287 m_CommonBufferOffset = 0; 1288 m_CommonBufferSize = m_DmaChannel->BufferSize(); 1289 m_CommonBuffer = m_DmaChannel->SystemAddress(); 1290 m_Capture = Capture; 1291 // delay of 10 millisec 1292 m_Delay = Int32x32To64(10, -10000); 1293 1294 // sanity checks 1295 PC_ASSERT(m_CommonBufferSize); 1296 PC_ASSERT(m_CommonBuffer); 1297 1298 Status = m_Stream->SetNotificationFreq(10, &m_FrameSize); 1299 PC_ASSERT(NT_SUCCESS(Status)); 1300 PC_ASSERT(m_FrameSize); 1301 1302 DPRINT1("Bits %u Samples %u Channels %u Tag %u FrameSize %u CommonBufferSize %lu, CommonBuffer %p\n", ((PKSDATAFORMAT_WAVEFORMATEX)(DataFormat))->WaveFormatEx.wBitsPerSample, ((PKSDATAFORMAT_WAVEFORMATEX)(DataFormat))->WaveFormatEx.nSamplesPerSec, ((PKSDATAFORMAT_WAVEFORMATEX)(DataFormat))->WaveFormatEx.nChannels, ((PKSDATAFORMAT_WAVEFORMATEX)(DataFormat))->WaveFormatEx.wFormatTag, m_FrameSize, m_CommonBufferSize, m_DmaChannel->SystemAddress()); 1303 1304 /* set up allocator framing */ 1305 m_AllocatorFraming.RequirementsFlags = KSALLOCATOR_REQUIREMENTF_SYSTEM_MEMORY | KSALLOCATOR_REQUIREMENTF_PREFERENCES_ONLY; 1306 m_AllocatorFraming.PoolType = NonPagedPool; 1307 m_AllocatorFraming.Frames = 8; 1308 m_AllocatorFraming.FileAlignment = FILE_64_BYTE_ALIGNMENT; 1309 m_AllocatorFraming.Reserved = 0; 1310 m_AllocatorFraming.FrameSize = m_FrameSize; 1311 1312 m_Stream->Silence(m_CommonBuffer, m_CommonBufferSize); 1313 1314 Status = m_IrpQueue->Init(ConnectDetails, KsPinDescriptor, m_FrameSize, 0, FALSE); 1315 if (!NT_SUCCESS(Status)) 1316 { 1317 m_IrpQueue->Release(); 1318 return Status; 1319 } 1320 1321 m_Format = (PKSDATAFORMAT)AllocateItem(NonPagedPool, DataFormat->FormatSize, TAG_PORTCLASS); 1322 if (!m_Format) 1323 return STATUS_INSUFFICIENT_RESOURCES; 1324 1325 RtlMoveMemory(m_Format, DataFormat, DataFormat->FormatSize); 1326 1327 Port->AddRef(); 1328 Filter->AddRef(); 1329 1330 m_Port = Port; 1331 m_Filter = Filter; 1332 1333 return STATUS_SUCCESS; 1334 } 1335 1336 ULONG 1337 NTAPI 1338 CPortPinWaveCyclic::GetCompletedPosition() 1339 { 1340 UNIMPLEMENTED; 1341 return 0; 1342 } 1343 1344 ULONG 1345 NTAPI 1346 CPortPinWaveCyclic::GetCycleCount() 1347 { 1348 UNIMPLEMENTED; 1349 return 0; 1350 } 1351 1352 ULONG 1353 NTAPI 1354 CPortPinWaveCyclic::GetDeviceBufferSize() 1355 { 1356 return m_CommonBufferSize; 1357 } 1358 1359 PVOID 1360 NTAPI 1361 CPortPinWaveCyclic::GetIrpStream() 1362 { 1363 return (PVOID)m_IrpQueue; 1364 } 1365 1366 PMINIPORT 1367 NTAPI 1368 CPortPinWaveCyclic::GetMiniport() 1369 { 1370 return (PMINIPORT)m_Miniport; 1371 } 1372 1373 NTSTATUS 1374 NewPortPinWaveCyclic( 1375 OUT IPortPinWaveCyclic ** OutPin) 1376 { 1377 CPortPinWaveCyclic * This; 1378 1379 This = new(NonPagedPool, TAG_PORTCLASS)CPortPinWaveCyclic(NULL); 1380 if (!This) 1381 return STATUS_INSUFFICIENT_RESOURCES; 1382 1383 This->AddRef(); 1384 1385 // store result 1386 *OutPin = (IPortPinWaveCyclic*)This; 1387 1388 return STATUS_SUCCESS; 1389 } 1390