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