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
17 class CPortPinWaveCyclic
: public IPortPinWaveCyclic
,
21 STDMETHODIMP
QueryInterface( REFIID InterfaceId
, PVOID
* Interface
);
23 STDMETHODIMP_(ULONG
) AddRef()
25 InterlockedIncrement(&m_Ref
);
28 STDMETHODIMP_(ULONG
) Release()
30 InterlockedDecrement(&m_Ref
);
39 IMP_IPortPinWaveCyclic
;
41 CPortPinWaveCyclic(IUnknown
*OuterUnknown
){}
42 virtual ~CPortPinWaveCyclic(){}
46 VOID
UpdateCommonBuffer(ULONG Position
, ULONG MaxTransferCount
);
47 VOID
UpdateCommonBufferOverlap(ULONG Position
, ULONG MaxTransferCount
);
48 VOID
GeneratePositionEvents(IN ULONGLONG OldOffset
, IN ULONGLONG NewOffset
);
50 friend NTSTATUS NTAPI
PinWaveCyclicState(IN PIRP Irp
, IN PKSIDENTIFIER Request
, IN OUT PVOID Data
);
51 friend NTSTATUS NTAPI
PinWaveCyclicDataFormat(IN PIRP Irp
, IN PKSIDENTIFIER Request
, IN OUT PVOID Data
);
52 friend NTSTATUS NTAPI
PinWaveCyclicAudioPosition(IN PIRP Irp
, IN PKSIDENTIFIER Request
, IN OUT PVOID Data
);
53 friend NTSTATUS NTAPI
PinWaveCyclicAllocatorFraming(IN PIRP Irp
, IN PKSIDENTIFIER Request
, IN OUT PVOID Data
);
54 friend NTSTATUS NTAPI
PinWaveCyclicAddEndOfStreamEvent(IN PIRP Irp
, IN PKSEVENTDATA EventData
, IN PKSEVENT_ENTRY EventEntry
);
55 friend NTSTATUS NTAPI
PinWaveCyclicAddLoopedStreamEvent(IN PIRP Irp
, IN PKSEVENTDATA EventData
, IN PKSEVENT_ENTRY EventEntry
);
56 friend VOID CALLBACK
PinSetStateWorkerRoutine(IN PDEVICE_OBJECT DeviceObject
, IN PVOID Context
);
58 IPortWaveCyclic
* m_Port
;
59 IPortFilterWaveCyclic
* m_Filter
;
60 KSPIN_DESCRIPTOR
* m_KsPinDescriptor
;
61 PMINIPORTWAVECYCLIC m_Miniport
;
62 PSERVICEGROUP m_ServiceGroup
;
63 PDMACHANNEL m_DmaChannel
;
64 PMINIPORTWAVECYCLICSTREAM m_Stream
;
66 PKSDATAFORMAT m_Format
;
67 PKSPIN_CONNECT m_ConnectDetails
;
70 ULONG m_CommonBufferSize
;
71 ULONG m_CommonBufferOffset
;
73 IIrpQueue
* m_IrpQueue
;
80 KSAUDIO_POSITION m_Position
;
81 KSALLOCATOR_FRAMING m_AllocatorFraming
;
82 PSUBDEVICE_DESCRIPTOR m_Descriptor
;
84 KSPIN_LOCK m_EventListLock
;
85 LIST_ENTRY m_EventList
;
97 ULONG bLoopedStreaming
;
99 }LOOPEDSTREAMING_EVENT_CONTEXT
, *PLOOPEDSTREAMING_EVENT_CONTEXT
;
103 ULONG bLoopedStreaming
;
104 }ENDOFSTREAM_EVENT_CONTEXT
, *PENDOFSTREAM_EVENT_CONTEXT
;
108 NTSTATUS NTAPI
PinWaveCyclicState(IN PIRP Irp
, IN PKSIDENTIFIER Request
, IN OUT PVOID Data
);
109 NTSTATUS NTAPI
PinWaveCyclicDataFormat(IN PIRP Irp
, IN PKSIDENTIFIER Request
, IN OUT PVOID Data
);
110 NTSTATUS NTAPI
PinWaveCyclicAudioPosition(IN PIRP Irp
, IN PKSIDENTIFIER Request
, IN OUT PVOID Data
);
111 NTSTATUS NTAPI
PinWaveCyclicAllocatorFraming(IN PIRP Irp
, IN PKSIDENTIFIER Request
, IN OUT PVOID Data
);
112 NTSTATUS NTAPI
PinWaveCyclicAddEndOfStreamEvent(IN PIRP Irp
, IN PKSEVENTDATA EventData
, IN PKSEVENT_ENTRY EventEntry
);
113 NTSTATUS NTAPI
PinWaveCyclicAddLoopedStreamEvent(IN PIRP Irp
, IN PKSEVENTDATA EventData
, IN PKSEVENT_ENTRY EventEntry
);
114 NTSTATUS NTAPI
PinWaveCyclicDRMHandler(IN PIRP Irp
, IN PKSIDENTIFIER Request
, IN OUT PVOID Data
);
117 DEFINE_KSPROPERTY_CONNECTIONSET(PinWaveCyclicConnectionSet
, PinWaveCyclicState
, PinWaveCyclicDataFormat
, PinWaveCyclicAllocatorFraming
);
118 DEFINE_KSPROPERTY_AUDIOSET(PinWaveCyclicAudioSet
, PinWaveCyclicAudioPosition
);
119 DEFINE_KSPROPERTY_DRMSET(PinWaveCyclicDRMSet
, PinWaveCyclicDRMHandler
);
121 KSEVENT_ITEM PinWaveCyclicConnectionEventSet
=
123 KSEVENT_CONNECTION_ENDOFSTREAM
,
125 sizeof(ENDOFSTREAM_EVENT_CONTEXT
),
126 PinWaveCyclicAddEndOfStreamEvent
,
131 KSEVENT_ITEM PinWaveCyclicStreamingEventSet
=
133 KSEVENT_LOOPEDSTREAMING_POSITION
,
134 sizeof(LOOPEDSTREAMING_POSITION_EVENT_DATA
),
135 sizeof(LOOPEDSTREAMING_EVENT_CONTEXT
),
136 PinWaveCyclicAddLoopedStreamEvent
,
142 KSPROPERTY_SET PinWaveCyclicPropertySet
[] =
145 &KSPROPSETID_Connection
,
146 sizeof(PinWaveCyclicConnectionSet
) / sizeof(KSPROPERTY_ITEM
),
147 (const KSPROPERTY_ITEM
*)&PinWaveCyclicConnectionSet
,
153 sizeof(PinWaveCyclicAudioSet
) / sizeof(KSPROPERTY_ITEM
),
154 (const KSPROPERTY_ITEM
*)&PinWaveCyclicAudioSet
,
159 &KSPROPSETID_DrmAudioStream
,
160 sizeof(PinWaveCyclicDRMSet
) / sizeof(KSPROPERTY_ITEM
),
161 (const KSPROPERTY_ITEM
*)&PinWaveCyclicDRMSet
,
167 KSEVENT_SET PinWaveCyclicEventSet
[] =
170 &KSEVENTSETID_LoopedStreaming
,
171 sizeof(PinWaveCyclicStreamingEventSet
) / sizeof(KSEVENT_ITEM
),
172 (const KSEVENT_ITEM
*)&PinWaveCyclicStreamingEventSet
175 &KSEVENTSETID_Connection
,
176 sizeof(PinWaveCyclicConnectionEventSet
) / sizeof(KSEVENT_ITEM
),
177 (const KSEVENT_ITEM
*)&PinWaveCyclicConnectionEventSet
182 //==================================================================================================================================
186 CPortPinWaveCyclic::QueryInterface(
190 DPRINT("IServiceSink_fnQueryInterface entered\n");
192 if (IsEqualGUIDAligned(refiid
, IID_IIrpTarget
) ||
193 IsEqualGUIDAligned(refiid
, IID_IUnknown
))
195 *Output
= PVOID(PUNKNOWN((IIrpTarget
*)this));
196 PUNKNOWN(*Output
)->AddRef();
197 return STATUS_SUCCESS
;
200 if (IsEqualGUIDAligned(refiid
, IID_IServiceSink
))
202 *Output
= PVOID(PUNKNOWN(PSERVICESINK(this)));
203 PUNKNOWN(*Output
)->AddRef();
204 return STATUS_SUCCESS
;
207 return STATUS_UNSUCCESSFUL
;
212 PinWaveCyclicDRMHandler(
214 IN PKSIDENTIFIER Request
,
217 DPRINT1("PinWaveCyclicDRMHandler\n");
219 return STATUS_INVALID_PARAMETER
;
225 PinWaveCyclicAddEndOfStreamEvent(
227 IN PKSEVENTDATA EventData
,
228 IN PKSEVENT_ENTRY EventEntry
)
230 PENDOFSTREAM_EVENT_CONTEXT Entry
;
231 PSUBDEVICE_DESCRIPTOR Descriptor
;
232 CPortPinWaveCyclic
*Pin
;
234 // get sub device descriptor
235 Descriptor
= (PSUBDEVICE_DESCRIPTOR
)KSPROPERTY_ITEM_IRP_STORAGE(Irp
);
238 PC_ASSERT(Descriptor
);
239 PC_ASSERT(Descriptor
->PortPin
);
240 PC_ASSERT_IRQL(DISPATCH_LEVEL
);
243 Pin
= (CPortPinWaveCyclic
*)Descriptor
->PortPin
;
246 Entry
= (PENDOFSTREAM_EVENT_CONTEXT
)(EventEntry
+ 1);
248 // not a looped event
249 Entry
->bLoopedStreaming
= FALSE
;
252 (void)ExInterlockedInsertTailList(&Pin
->m_EventList
, &EventEntry
->ListEntry
, &Pin
->m_EventListLock
);
255 return STATUS_SUCCESS
;
260 PinWaveCyclicAddLoopedStreamEvent(
262 IN PKSEVENTDATA EventData
,
263 IN PKSEVENT_ENTRY EventEntry
)
265 PLOOPEDSTREAMING_POSITION_EVENT_DATA Data
;
266 PLOOPEDSTREAMING_EVENT_CONTEXT Entry
;
267 PSUBDEVICE_DESCRIPTOR Descriptor
;
268 CPortPinWaveCyclic
*Pin
;
270 // get sub device descriptor
271 Descriptor
= (PSUBDEVICE_DESCRIPTOR
)KSEVENT_ITEM_IRP_STORAGE(Irp
);
274 PC_ASSERT(Descriptor
);
275 PC_ASSERT(Descriptor
->PortPin
);
276 PC_ASSERT_IRQL(DISPATCH_LEVEL
);
279 Pin
= (CPortPinWaveCyclic
*)Descriptor
->PortPin
;
281 // cast to looped event
282 Data
= (PLOOPEDSTREAMING_POSITION_EVENT_DATA
)EventData
;
285 Entry
= (PLOOPEDSTREAMING_EVENT_CONTEXT
)(EventEntry
+ 1);
287 Entry
->bLoopedStreaming
= TRUE
;
288 Entry
->Position
= Data
->Position
;
290 DPRINT1("Added event\n");
293 (void)ExInterlockedInsertTailList(&Pin
->m_EventList
, &EventEntry
->ListEntry
, &Pin
->m_EventListLock
);
296 return STATUS_SUCCESS
;
301 PinWaveCyclicAllocatorFraming(
303 IN PKSIDENTIFIER Request
,
306 CPortPinWaveCyclic
*Pin
;
307 PSUBDEVICE_DESCRIPTOR Descriptor
;
309 // get sub device descriptor
310 Descriptor
= (PSUBDEVICE_DESCRIPTOR
)KSEVENT_ITEM_IRP_STORAGE(Irp
);
313 PC_ASSERT(Descriptor
);
314 PC_ASSERT(Descriptor
->PortPin
);
315 PC_ASSERT_IRQL(DISPATCH_LEVEL
);
318 Pin
= (CPortPinWaveCyclic
*)Descriptor
->PortPin
;
321 if (Request
->Flags
& KSPROPERTY_TYPE_GET
)
324 RtlMoveMemory(Data
, &Pin
->m_AllocatorFraming
, sizeof(KSALLOCATOR_FRAMING
));
326 Irp
->IoStatus
.Information
= sizeof(KSALLOCATOR_FRAMING
);
327 return STATUS_SUCCESS
;
331 return STATUS_NOT_SUPPORTED
;
336 PinWaveCyclicAudioPosition(
338 IN PKSIDENTIFIER Request
,
341 CPortPinWaveCyclic
*Pin
;
342 PSUBDEVICE_DESCRIPTOR Descriptor
;
343 PKSAUDIO_POSITION Position
;
345 // get sub device descriptor
346 Descriptor
= (PSUBDEVICE_DESCRIPTOR
)KSPROPERTY_ITEM_IRP_STORAGE(Irp
);
349 PC_ASSERT(Descriptor
);
350 PC_ASSERT(Descriptor
->PortPin
);
351 PC_ASSERT_IRQL(DISPATCH_LEVEL
);
354 Pin
= (CPortPinWaveCyclic
*)Descriptor
->PortPin
;
357 PC_ASSERT(Pin
->m_Stream
);
359 if (Request
->Flags
& KSPROPERTY_TYPE_GET
)
361 // FIXME non multithreading-safe
362 // copy audio position
364 Position
= (PKSAUDIO_POSITION
)Data
;
366 if (Pin
->m_ConnectDetails
->Interface
.Id
== KSINTERFACE_STANDARD_STREAMING
)
368 RtlMoveMemory(Data
, &Pin
->m_Position
, sizeof(KSAUDIO_POSITION
));
369 DPRINT("Play %lu Record %lu\n", Pin
->m_Position
.PlayOffset
, Pin
->m_Position
.WriteOffset
);
371 else if (Pin
->m_ConnectDetails
->Interface
.Id
== KSINTERFACE_STANDARD_LOOPED_STREAMING
)
373 Position
->PlayOffset
= Pin
->m_Position
.PlayOffset
;
374 Position
->WriteOffset
= (ULONGLONG
)Pin
->m_IrpQueue
->GetCurrentIrpOffset();
375 DPRINT("Play %lu Write %lu\n", Position
->PlayOffset
, Position
->WriteOffset
);
378 Irp
->IoStatus
.Information
= sizeof(KSAUDIO_POSITION
);
379 return STATUS_SUCCESS
;
383 return STATUS_NOT_SUPPORTED
;
388 CPortPinWaveCyclic
*Pin
;
390 PIO_WORKITEM WorkItem
;
393 }SETPIN_CONTEXT
, *PSETPIN_CONTEXT
;
397 PinSetStateWorkerRoutine(
398 IN PDEVICE_OBJECT DeviceObject
,
401 PSETPIN_CONTEXT PinWorkContext
= (PSETPIN_CONTEXT
)Context
;
405 Status
= PinWorkContext
->Pin
->m_Stream
->SetState(PinWorkContext
->NewState
);
407 DPRINT1("Setting state %u %x\n", PinWorkContext
->NewState
, Status
);
408 if (NT_SUCCESS(Status
))
411 PinWorkContext
->Pin
->m_State
= PinWorkContext
->NewState
;
413 if (PinWorkContext
->Pin
->m_ConnectDetails
->Interface
.Id
== KSINTERFACE_STANDARD_LOOPED_STREAMING
&& PinWorkContext
->Pin
->m_State
== KSSTATE_STOP
)
415 /* FIXME complete pending irps with successful state */
416 PinWorkContext
->Pin
->m_IrpQueue
->CancelBuffers();
419 //PinWorkContext->Pin->m_IrpQueue->CancelBuffers();
423 PinWorkContext
->Irp
->IoStatus
.Information
= sizeof(KSSTATE
);
424 PinWorkContext
->Irp
->IoStatus
.Status
= Status
;
427 IoCompleteRequest(PinWorkContext
->Irp
, IO_NO_INCREMENT
);
430 IoFreeWorkItem(PinWorkContext
->WorkItem
);
433 FreeItem(PinWorkContext
, TAG_PORTCLASS
);
442 IN PKSIDENTIFIER Request
,
445 NTSTATUS Status
= STATUS_UNSUCCESSFUL
;
446 CPortPinWaveCyclic
*Pin
;
447 PSUBDEVICE_DESCRIPTOR Descriptor
;
448 PKSSTATE State
= (PKSSTATE
)Data
;
450 // get sub device descriptor
451 Descriptor
= (PSUBDEVICE_DESCRIPTOR
)KSPROPERTY_ITEM_IRP_STORAGE(Irp
);
454 PC_ASSERT(Descriptor
);
455 PC_ASSERT(Descriptor
->PortPin
);
456 PC_ASSERT_IRQL(DISPATCH_LEVEL
);
459 Pin
= (CPortPinWaveCyclic
*)Descriptor
->PortPin
;
462 PC_ASSERT(Pin
->m_Stream
);
464 if (Request
->Flags
& KSPROPERTY_TYPE_SET
)
467 Status
= Pin
->m_Stream
->SetState(*State
);
469 DPRINT("Setting state %u %x\n", *State
, Status
);
470 if (NT_SUCCESS(Status
))
473 Pin
->m_State
= *State
;
475 if (Pin
->m_ConnectDetails
->Interface
.Id
== KSINTERFACE_STANDARD_LOOPED_STREAMING
&& Pin
->m_State
== KSSTATE_STOP
)
478 // complete with successful state
479 Pin
->m_Stream
->Silence(Pin
->m_CommonBuffer
, Pin
->m_CommonBufferSize
);
480 Pin
->m_IrpQueue
->CancelBuffers();
481 Pin
->m_Position
.PlayOffset
= 0;
482 Pin
->m_Position
.WriteOffset
= 0;
484 else if (Pin
->m_State
== KSSTATE_STOP
)
486 Pin
->m_Stream
->Silence(Pin
->m_CommonBuffer
, Pin
->m_CommonBufferSize
);
487 Pin
->m_IrpQueue
->CancelBuffers();
488 Pin
->m_Position
.PlayOffset
= 0;
489 Pin
->m_Position
.WriteOffset
= 0;
492 Irp
->IoStatus
.Information
= sizeof(KSSTATE
);
496 else if (Request
->Flags
& KSPROPERTY_TYPE_GET
)
498 // get current stream state
499 *State
= Pin
->m_State
;
501 Irp
->IoStatus
.Information
= sizeof(KSSTATE
);
503 return STATUS_SUCCESS
;
506 // unsupported request
507 return STATUS_NOT_SUPPORTED
;
512 PinWaveCyclicDataFormat(
514 IN PKSIDENTIFIER Request
,
517 NTSTATUS Status
= STATUS_UNSUCCESSFUL
;
518 CPortPinWaveCyclic
*Pin
;
519 PSUBDEVICE_DESCRIPTOR Descriptor
;
520 PIO_STACK_LOCATION IoStack
;
522 // get current irp stack location
523 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
525 // get sub device descriptor
526 Descriptor
= (PSUBDEVICE_DESCRIPTOR
)KSPROPERTY_ITEM_IRP_STORAGE(Irp
);
529 PC_ASSERT(Descriptor
);
530 PC_ASSERT(Descriptor
->PortPin
);
533 Pin
= (CPortPinWaveCyclic
*)Descriptor
->PortPin
;
536 PC_ASSERT(Pin
->m_Stream
);
537 PC_ASSERT(Pin
->m_Format
);
539 if (Request
->Flags
& KSPROPERTY_TYPE_SET
)
541 // try to change data format
542 PKSDATAFORMAT NewDataFormat
, DataFormat
= (PKSDATAFORMAT
)Irp
->UserBuffer
;
543 ULONG Size
= min(Pin
->m_Format
->FormatSize
, DataFormat
->FormatSize
);
545 if (RtlCompareMemory(DataFormat
, Pin
->m_Format
, Size
) == Size
)
547 // format is identical
548 Irp
->IoStatus
.Information
= DataFormat
->FormatSize
;
549 return STATUS_SUCCESS
;
552 // new change request
553 PC_ASSERT(Pin
->m_State
!= KSSTATE_RUN
);
554 // FIXME queue a work item when Irql != PASSIVE_LEVEL
555 PC_ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL
);
557 // allocate new data format
558 NewDataFormat
= (PKSDATAFORMAT
)AllocateItem(NonPagedPool
, DataFormat
->FormatSize
, TAG_PORTCLASS
);
562 return STATUS_NO_MEMORY
;
565 // copy new data format
566 RtlMoveMemory(NewDataFormat
, DataFormat
, DataFormat
->FormatSize
);
569 Status
= Pin
->m_Stream
->SetFormat(NewDataFormat
);
570 if (NT_SUCCESS(Status
))
573 FreeItem(Pin
->m_Format
, TAG_PORTCLASS
);
576 Pin
->m_Format
= NewDataFormat
;
577 Irp
->IoStatus
.Information
= NewDataFormat
->FormatSize
;
580 PC_ASSERT(NewDataFormat
->FormatSize
== sizeof(KSDATAFORMAT_WAVEFORMATEX
));
581 PC_ASSERT(IsEqualGUIDAligned(((PKSDATAFORMAT_WAVEFORMATEX
)NewDataFormat
)->DataFormat
.MajorFormat
, KSDATAFORMAT_TYPE_AUDIO
));
582 PC_ASSERT(IsEqualGUIDAligned(((PKSDATAFORMAT_WAVEFORMATEX
)NewDataFormat
)->DataFormat
.SubFormat
, KSDATAFORMAT_SUBTYPE_PCM
));
583 PC_ASSERT(IsEqualGUIDAligned(((PKSDATAFORMAT_WAVEFORMATEX
)NewDataFormat
)->DataFormat
.Specifier
, KSDATAFORMAT_SPECIFIER_WAVEFORMATEX
));
586 DPRINT("NewDataFormat: Channels %u Bits %u Samples %u\n", ((PKSDATAFORMAT_WAVEFORMATEX
)NewDataFormat
)->WaveFormatEx
.nChannels
,
587 ((PKSDATAFORMAT_WAVEFORMATEX
)NewDataFormat
)->WaveFormatEx
.wBitsPerSample
,
588 ((PKSDATAFORMAT_WAVEFORMATEX
)NewDataFormat
)->WaveFormatEx
.nSamplesPerSec
);
594 // failed to set format
595 FreeItem(NewDataFormat
, TAG_PORTCLASS
);
602 else if (Request
->Flags
& KSPROPERTY_TYPE_GET
)
604 // get current data format
605 PC_ASSERT(Pin
->m_Format
);
607 if (Pin
->m_Format
->FormatSize
> IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
)
610 Irp
->IoStatus
.Information
= Pin
->m_Format
->FormatSize
;
611 return STATUS_MORE_ENTRIES
;
614 RtlMoveMemory(Data
, Pin
->m_Format
, Pin
->m_Format
->FormatSize
);
616 Irp
->IoStatus
.Information
= Pin
->m_Format
->FormatSize
;
619 return STATUS_SUCCESS
;
622 // unsupported request
623 return STATUS_NOT_SUPPORTED
;
627 CPortPinWaveCyclic::GeneratePositionEvents(
628 IN ULONGLONG OldOffset
,
629 IN ULONGLONG NewOffset
)
632 PKSEVENT_ENTRY EventEntry
;
633 PLOOPEDSTREAMING_EVENT_CONTEXT Context
;
635 // acquire event lock
636 KeAcquireSpinLockAtDpcLevel(&m_EventListLock
);
638 // point to first entry
639 Entry
= m_EventList
.Flink
;
641 while(Entry
!= &m_EventList
)
644 EventEntry
= (PKSEVENT_ENTRY
)CONTAINING_RECORD(Entry
, KSEVENT_ENTRY
, ListEntry
);
646 // get event entry context
647 Context
= (PLOOPEDSTREAMING_EVENT_CONTEXT
)(EventEntry
+ 1);
649 if (Context
->bLoopedStreaming
== TRUE
)
651 if (NewOffset
> OldOffset
)
653 /* buffer progress no overlap */
654 if (OldOffset
< Context
->Position
&& Context
->Position
<= NewOffset
)
656 /* when someone eventually fixes sprintf... */
657 DPRINT("Generating event at OldOffset %I64u\n", OldOffset
);
658 DPRINT("Context->Position %I64u\n", Context
->Position
);
659 DPRINT("NewOffset %I64u\n", NewOffset
);
661 KsGenerateEvent(EventEntry
);
666 /* buffer wrap-arround */
667 if (OldOffset
< Context
->Position
|| NewOffset
> Context
->Position
)
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
);
674 KsGenerateEvent(EventEntry
);
679 // move to next entry
680 Entry
= Entry
->Flink
;
684 KeReleaseSpinLockFromDpcLevel(&m_EventListLock
);
688 CPortPinWaveCyclic::UpdateCommonBuffer(
690 ULONG MaxTransferCount
)
699 BufferLength
= Position
- m_CommonBufferOffset
;
700 BufferLength
= min(BufferLength
, MaxTransferCount
);
704 Status
= m_IrpQueue
->GetMapping(&Buffer
, &BufferSize
);
705 if (!NT_SUCCESS(Status
))
707 Gap
= Position
- m_CommonBufferOffset
;
708 if (Gap
> BufferLength
)
710 // insert silence samples
711 DPRINT("Inserting Silence Buffer Offset %lu GapLength %lu\n", m_CommonBufferOffset
, BufferLength
);
712 m_Stream
->Silence((PUCHAR
)m_CommonBuffer
+ m_CommonBufferOffset
, BufferLength
);
714 m_CommonBufferOffset
+= BufferLength
;
719 BytesToCopy
= min(BufferLength
, BufferSize
);
723 m_DmaChannel
->CopyFrom(Buffer
, (PUCHAR
)m_CommonBuffer
+ m_CommonBufferOffset
, BytesToCopy
);
727 m_DmaChannel
->CopyTo((PUCHAR
)m_CommonBuffer
+ m_CommonBufferOffset
, Buffer
, BytesToCopy
);
730 m_IrpQueue
->UpdateMapping(BytesToCopy
);
731 m_CommonBufferOffset
+= BytesToCopy
;
733 BufferLength
-= BytesToCopy
;
734 m_Position
.PlayOffset
+= BytesToCopy
;
736 if (m_ConnectDetails
->Interface
.Id
== KSINTERFACE_STANDARD_LOOPED_STREAMING
)
738 if (m_Position
.WriteOffset
)
740 // normalize position
741 m_Position
.PlayOffset
= m_Position
.PlayOffset
% m_Position
.WriteOffset
;
748 CPortPinWaveCyclic::UpdateCommonBufferOverlap(
750 ULONG MaxTransferCount
)
752 ULONG BufferLength
, Length
, Gap
;
759 BufferLength
= Gap
= m_CommonBufferSize
- m_CommonBufferOffset
;
760 BufferLength
= Length
= min(BufferLength
, MaxTransferCount
);
763 Status
= m_IrpQueue
->GetMapping(&Buffer
, &BufferSize
);
764 if (!NT_SUCCESS(Status
))
766 Gap
= m_CommonBufferSize
- m_CommonBufferOffset
+ Position
;
767 if (Gap
> BufferLength
)
769 // insert silence samples
770 DPRINT("Overlap Inserting Silence Buffer Size %lu Offset %lu Gap %lu Position %lu\n", m_CommonBufferSize
, m_CommonBufferOffset
, Gap
, Position
);
771 m_Stream
->Silence((PUCHAR
)m_CommonBuffer
+ m_CommonBufferOffset
, BufferLength
);
773 m_CommonBufferOffset
+= BufferLength
;
778 BytesToCopy
= min(BufferLength
, BufferSize
);
782 m_DmaChannel
->CopyFrom(Buffer
,
783 (PUCHAR
)m_CommonBuffer
+ m_CommonBufferOffset
,
788 m_DmaChannel
->CopyTo((PUCHAR
)m_CommonBuffer
+ m_CommonBufferOffset
,
793 m_IrpQueue
->UpdateMapping(BytesToCopy
);
794 m_CommonBufferOffset
+= BytesToCopy
;
795 m_Position
.PlayOffset
+= BytesToCopy
;
797 BufferLength
-=BytesToCopy
;
799 if (m_ConnectDetails
->Interface
.Id
== KSINTERFACE_STANDARD_LOOPED_STREAMING
)
801 if (m_Position
.WriteOffset
)
803 // normalize position
804 m_Position
.PlayOffset
= m_Position
.PlayOffset
% m_Position
.WriteOffset
;
811 m_CommonBufferOffset
= 0;
813 MaxTransferCount
-= Length
;
815 if (MaxTransferCount
)
817 UpdateCommonBuffer(Position
, MaxTransferCount
);
824 CPortPinWaveCyclic::RequestService()
827 ULONGLONG OldOffset
, NewOffset
;
829 PC_ASSERT_IRQL(DISPATCH_LEVEL
);
831 if (m_State
== KSSTATE_RUN
&& m_ResetState
== KSRESET_END
)
833 m_Stream
->GetPosition(&Position
);
835 OldOffset
= m_Position
.PlayOffset
;
837 if (Position
< m_CommonBufferOffset
)
839 UpdateCommonBufferOverlap(Position
, m_FrameSize
);
841 else if (Position
>= m_CommonBufferOffset
)
843 UpdateCommonBuffer(Position
, m_FrameSize
);
846 NewOffset
= m_Position
.PlayOffset
;
848 GeneratePositionEvents(OldOffset
, NewOffset
);
854 CPortPinWaveCyclic::NewIrpTarget(
855 OUT
struct IIrpTarget
**OutTarget
,
858 IN POOL_TYPE PoolType
,
859 IN PDEVICE_OBJECT DeviceObject
,
861 IN KSOBJECT_CREATE
*CreateObject
)
864 return STATUS_UNSUCCESSFUL
;
869 CPortPinWaveCyclic::DeviceIoControl(
870 IN PDEVICE_OBJECT DeviceObject
,
873 PIO_STACK_LOCATION IoStack
;
874 PKSPROPERTY Property
;
875 UNICODE_STRING GuidString
;
876 NTSTATUS Status
= STATUS_NOT_SUPPORTED
;
880 /* get current irp stack location */
881 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
883 if (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_KS_PROPERTY
)
885 /* handle property with subdevice descriptor */
886 Status
= PcHandlePropertyWithTable(Irp
, m_Descriptor
->FilterPropertySetCount
, m_Descriptor
->FilterPropertySet
, m_Descriptor
);
888 if (Status
== STATUS_NOT_FOUND
)
890 Property
= (PKSPROPERTY
)IoStack
->Parameters
.DeviceIoControl
.Type3InputBuffer
;
892 RtlStringFromGUID(Property
->Set
, &GuidString
);
893 DPRINT("Unhandled property Set |%S| Id %u Flags %x\n", GuidString
.Buffer
, Property
->Id
, Property
->Flags
);
894 RtlFreeUnicodeString(&GuidString
);
897 else if (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_KS_ENABLE_EVENT
)
899 Status
= PcHandleEnableEventWithTable(Irp
, m_Descriptor
);
901 else if (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_KS_DISABLE_EVENT
)
903 Status
= PcHandleDisableEventWithTable(Irp
, m_Descriptor
);
905 else if (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_KS_RESET_STATE
)
907 Status
= KsAcquireResetValue(Irp
, &ResetValue
);
908 DPRINT("Status %x Value %u\n", Status
, ResetValue
);
909 /* check for success */
910 if (NT_SUCCESS(Status
))
912 //determine state of reset request
913 if (ResetValue
== KSRESET_BEGIN
)
915 // start reset process
916 // incoming read/write requests will be rejected
917 m_ResetState
= KSRESET_BEGIN
;
919 // cancel existing buffers
920 m_IrpQueue
->CancelBuffers();
922 else if (ResetValue
== KSRESET_END
)
924 // end of reset process
925 m_ResetState
= KSRESET_END
;
929 else if (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_KS_WRITE_STREAM
|| IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_KS_READ_STREAM
)
931 /* increment total number of packets */
932 InterlockedIncrement((PLONG
)&m_TotalPackets
);
934 DPRINT("New Packet Total %u State %x MinData %u\n", m_TotalPackets
, m_State
, m_IrpQueue
->NumData());
936 /* is the device not currently reset */
937 if (m_ResetState
== KSRESET_END
)
939 /* add the mapping */
940 Status
= m_IrpQueue
->AddMapping(Irp
, &Data
);
942 /* check for success */
943 if (NT_SUCCESS(Status
))
945 m_Position
.WriteOffset
+= Data
;
946 Status
= STATUS_PENDING
;
951 /* reset request is currently in progress */
952 Status
= STATUS_DEVICE_NOT_READY
;
953 DPRINT1("NotReady\n");
958 return KsDefaultDeviceIoCompletion(DeviceObject
, Irp
);
961 if (Status
!= STATUS_PENDING
)
963 Irp
->IoStatus
.Status
= Status
;
964 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
972 CPortPinWaveCyclic::Read(
973 IN PDEVICE_OBJECT DeviceObject
,
976 return KsDispatchInvalidDeviceRequest(DeviceObject
, Irp
);
981 CPortPinWaveCyclic::Write(
982 IN PDEVICE_OBJECT DeviceObject
,
985 return KsDispatchInvalidDeviceRequest(DeviceObject
, Irp
);
990 CPortPinWaveCyclic::Flush(
991 IN PDEVICE_OBJECT DeviceObject
,
994 return KsDispatchInvalidDeviceRequest(DeviceObject
, Irp
);
999 CPortPinWaveCyclic::Close(
1000 IN PDEVICE_OBJECT DeviceObject
,
1003 DPRINT("CPortPinWaveCyclic::Close entered\n");
1005 PC_ASSERT_IRQL(PASSIVE_LEVEL
);
1010 FreeItem(m_Format
, TAG_PORTCLASS
);
1018 // cancel remaining irps
1019 m_IrpQueue
->CancelBuffers();
1021 // release irp queue
1022 m_IrpQueue
->Release();
1030 // remove member from service group
1031 m_ServiceGroup
->RemoveMember(PSERVICESINK(this));
1033 // do not release service group, it is released by the miniport object
1034 m_ServiceGroup
= NULL
;
1039 if (m_State
!= KSSTATE_STOP
)
1042 NTSTATUS Status
= m_Stream
->SetState(KSSTATE_STOP
);
1043 if (!NT_SUCCESS(Status
))
1045 DPRINT("Warning: failed to stop stream with %x\n", Status
);
1049 // set state to stop
1050 m_State
= KSSTATE_STOP
;
1052 DPRINT("Closing stream at Irql %u\n", KeGetCurrentIrql());
1055 m_Stream
->Release();
1057 // stream is now freed
1064 // disconnect pin from filter
1065 m_Filter
->FreePin((PPORTPINWAVECYCLIC
)this);
1067 // release filter reference
1068 m_Filter
->Release();
1070 // pin is done with filter
1076 // release reference to port driver
1079 // work is done for port
1083 Irp
->IoStatus
.Information
= 0;
1084 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
1085 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1089 return STATUS_SUCCESS
;
1094 CPortPinWaveCyclic::QuerySecurity(
1095 IN PDEVICE_OBJECT DeviceObject
,
1098 return KsDispatchInvalidDeviceRequest(DeviceObject
, Irp
);
1103 CPortPinWaveCyclic::SetSecurity(
1104 IN PDEVICE_OBJECT DeviceObject
,
1107 return KsDispatchInvalidDeviceRequest(DeviceObject
, Irp
);
1112 CPortPinWaveCyclic::FastDeviceIoControl(
1113 IN PFILE_OBJECT FileObject
,
1115 IN PVOID InputBuffer
,
1116 IN ULONG InputBufferLength
,
1117 OUT PVOID OutputBuffer
,
1118 IN ULONG OutputBufferLength
,
1119 IN ULONG IoControlCode
,
1120 OUT PIO_STATUS_BLOCK StatusBlock
,
1121 IN PDEVICE_OBJECT DeviceObject
)
1123 return KsDispatchFastIoDeviceControlFailure(FileObject
, Wait
, InputBuffer
, InputBufferLength
, OutputBuffer
, OutputBufferLength
, IoControlCode
, StatusBlock
, DeviceObject
);
1129 CPortPinWaveCyclic::FastRead(
1130 IN PFILE_OBJECT FileObject
,
1131 IN PLARGE_INTEGER FileOffset
,
1136 OUT PIO_STATUS_BLOCK StatusBlock
,
1137 IN PDEVICE_OBJECT DeviceObject
)
1139 return KsDispatchFastReadFailure(FileObject
, FileOffset
, Length
, Wait
, LockKey
, Buffer
, StatusBlock
, DeviceObject
);
1145 CPortPinWaveCyclic::FastWrite(
1146 IN PFILE_OBJECT FileObject
,
1147 IN PLARGE_INTEGER FileOffset
,
1152 OUT PIO_STATUS_BLOCK StatusBlock
,
1153 IN PDEVICE_OBJECT DeviceObject
)
1155 return KsDispatchFastReadFailure(FileObject
, FileOffset
, Length
, Wait
, LockKey
, Buffer
, StatusBlock
, DeviceObject
);
1161 CPortPinWaveCyclic::Init(
1162 IN PPORTWAVECYCLIC Port
,
1163 IN PPORTFILTERWAVECYCLIC Filter
,
1164 IN KSPIN_CONNECT
* ConnectDetails
,
1165 IN KSPIN_DESCRIPTOR
* KsPinDescriptor
)
1168 PKSDATAFORMAT DataFormat
;
1169 //PDEVICE_OBJECT DeviceObject;
1171 PSUBDEVICE_DESCRIPTOR SubDeviceDescriptor
= NULL
;
1172 //IDrmAudioStream * DrmAudio = NULL;
1174 m_KsPinDescriptor
= KsPinDescriptor
;
1175 m_ConnectDetails
= ConnectDetails
;
1176 m_Miniport
= GetWaveCyclicMiniport(Port
);
1178 //DeviceObject = GetDeviceObject(Port);
1180 DataFormat
= (PKSDATAFORMAT
)(ConnectDetails
+ 1);
1182 DPRINT("CPortPinWaveCyclic::Init entered Size %u\n", DataFormat
->FormatSize
);
1184 Status
= NewIrpQueue(&m_IrpQueue
);
1185 if (!NT_SUCCESS(Status
))
1188 if (KsPinDescriptor
->Communication
== KSPIN_COMMUNICATION_SINK
&& KsPinDescriptor
->DataFlow
== KSPIN_DATAFLOW_IN
)
1192 else if (KsPinDescriptor
->Communication
== KSPIN_COMMUNICATION_SINK
&& KsPinDescriptor
->DataFlow
== KSPIN_DATAFLOW_OUT
)
1198 DPRINT("Unexpected Communication %u DataFlow %u\n", KsPinDescriptor
->Communication
, KsPinDescriptor
->DataFlow
);
1204 Status
= m_Miniport
->NewStream(&m_Stream
,
1207 ConnectDetails
->PinId
,
1213 Status
= m_Stream
->QueryInterface(IID_IDrmAudioStream
, (PVOID
*)&DrmAudio
);
1214 if (NT_SUCCESS(Status
))
1216 DRMRIGHTS DrmRights
;
1217 DPRINT("Got IID_IDrmAudioStream interface %p\n", DrmAudio
);
1219 DrmRights
.CopyProtect
= FALSE
;
1220 DrmRights
.Reserved
= 0;
1221 DrmRights
.DigitalOutputDisable
= FALSE
;
1223 Status
= DrmAudio
->SetContentId(1, &DrmRights
);
1224 DPRINT("Status %x\n", Status
);
1228 DPRINT1("CPortPinWaveCyclic::Init Status %x PinId %u Capture %u\n", Status
, ConnectDetails
->PinId
, Capture
);
1230 if (!NT_SUCCESS(Status
))
1233 ISubdevice
* Subdevice
= NULL
;
1234 // get subdevice interface
1235 Status
= Port
->QueryInterface(IID_ISubdevice
, (PVOID
*)&Subdevice
);
1237 if (!NT_SUCCESS(Status
))
1240 Status
= Subdevice
->GetDescriptor(&SubDeviceDescriptor
);
1241 if (!NT_SUCCESS(Status
))
1243 // failed to get descriptor
1244 Subdevice
->Release();
1248 /* initialize event management */
1249 InitializeListHead(&m_EventList
);
1250 KeInitializeSpinLock(&m_EventListLock
);
1252 Status
= PcCreateSubdeviceDescriptor(&m_Descriptor
,
1253 SubDeviceDescriptor
->InterfaceCount
,
1254 SubDeviceDescriptor
->Interfaces
,
1255 0, /* FIXME KSINTERFACE_STANDARD with KSINTERFACE_STANDARD_STREAMING / KSINTERFACE_STANDARD_LOOPED_STREAMING */
1257 sizeof(PinWaveCyclicPropertySet
) / sizeof(KSPROPERTY_SET
),
1258 PinWaveCyclicPropertySet
,
1263 sizeof(PinWaveCyclicEventSet
) / sizeof(KSEVENT_SET
),
1264 PinWaveCyclicEventSet
,
1265 SubDeviceDescriptor
->DeviceDescriptor
);
1267 m_Descriptor
->UnknownStream
= (PUNKNOWN
)m_Stream
;
1268 m_Descriptor
->UnknownMiniport
= SubDeviceDescriptor
->UnknownMiniport
;
1269 m_Descriptor
->PortPin
= (PVOID
)this;
1270 m_Descriptor
->EventList
= &m_EventList
;
1271 m_Descriptor
->EventListLock
= &m_EventListLock
;
1273 // initialize reset state
1274 m_ResetState
= KSRESET_END
;
1276 // release subdevice descriptor
1277 Subdevice
->Release();
1279 // add ourselves to service group
1280 Status
= m_ServiceGroup
->AddMember(PSERVICESINK(this));
1281 if (!NT_SUCCESS(Status
))
1283 DPRINT("Failed to add pin to service group\n");
1287 m_Stream
->SetState(KSSTATE_STOP
);
1288 m_State
= KSSTATE_STOP
;
1289 m_CommonBufferOffset
= 0;
1290 m_CommonBufferSize
= m_DmaChannel
->AllocatedBufferSize();
1291 m_CommonBuffer
= m_DmaChannel
->SystemAddress();
1292 m_Capture
= Capture
;
1293 // delay of 10 millisec
1294 m_Delay
= Int32x32To64(10, -10000);
1297 PC_ASSERT(m_CommonBufferSize
);
1298 PC_ASSERT(m_CommonBuffer
);
1300 Status
= m_Stream
->SetNotificationFreq(10, &m_FrameSize
);
1301 PC_ASSERT(NT_SUCCESS(Status
));
1302 PC_ASSERT(m_FrameSize
);
1304 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());
1307 /* set up allocator framing */
1308 m_AllocatorFraming
.RequirementsFlags
= KSALLOCATOR_REQUIREMENTF_SYSTEM_MEMORY
| KSALLOCATOR_REQUIREMENTF_PREFERENCES_ONLY
;
1309 m_AllocatorFraming
.PoolType
= NonPagedPool
;
1310 m_AllocatorFraming
.Frames
= 8;
1311 m_AllocatorFraming
.FileAlignment
= FILE_64_BYTE_ALIGNMENT
;
1312 m_AllocatorFraming
.Reserved
= 0;
1313 m_AllocatorFraming
.FrameSize
= m_FrameSize
;
1315 m_Stream
->Silence(m_CommonBuffer
, m_CommonBufferSize
);
1317 Status
= m_IrpQueue
->Init(ConnectDetails
, KsPinDescriptor
, m_FrameSize
, 0, FALSE
);
1318 if (!NT_SUCCESS(Status
))
1320 m_IrpQueue
->Release();
1324 m_Format
= (PKSDATAFORMAT
)AllocateItem(NonPagedPool
, DataFormat
->FormatSize
, TAG_PORTCLASS
);
1326 return STATUS_INSUFFICIENT_RESOURCES
;
1328 RtlMoveMemory(m_Format
, DataFormat
, DataFormat
->FormatSize
);
1336 return STATUS_SUCCESS
;
1342 CPortPinWaveCyclic::GetCompletedPosition()
1351 CPortPinWaveCyclic::GetCycleCount()
1360 CPortPinWaveCyclic::GetDeviceBufferSize()
1362 return m_CommonBufferSize
;
1368 CPortPinWaveCyclic::GetIrpStream()
1370 return (PVOID
)m_IrpQueue
;
1376 CPortPinWaveCyclic::GetMiniport()
1378 return (PMINIPORT
)m_Miniport
;
1383 NewPortPinWaveCyclic(
1384 OUT IPortPinWaveCyclic
** OutPin
)
1386 CPortPinWaveCyclic
* This
;
1388 This
= new(NonPagedPool
, TAG_PORTCLASS
)CPortPinWaveCyclic(NULL
);
1390 return STATUS_INSUFFICIENT_RESOURCES
;
1395 *OutPin
= (IPortPinWaveCyclic
*)This
;
1397 return STATUS_SUCCESS
;