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
11 class CPortPinWaveCyclic
: public IPortPinWaveCyclic
,
15 STDMETHODIMP
QueryInterface( REFIID InterfaceId
, PVOID
* Interface
);
17 STDMETHODIMP_(ULONG
) AddRef()
19 InterlockedIncrement(&m_Ref
);
22 STDMETHODIMP_(ULONG
) Release()
24 InterlockedDecrement(&m_Ref
);
33 IMP_IPortPinWaveCyclic
;
35 CPortPinWaveCyclic(IUnknown
*OuterUnknown
){}
36 virtual ~CPortPinWaveCyclic(){}
40 VOID
UpdateCommonBuffer(ULONG Position
, ULONG MaxTransferCount
);
41 VOID
UpdateCommonBufferOverlap(ULONG Position
, ULONG MaxTransferCount
);
42 VOID
GeneratePositionEvents(IN ULONGLONG OldOffset
, IN ULONGLONG NewOffset
);
44 friend NTSTATUS NTAPI
PinWaveCyclicState(IN PIRP Irp
, IN PKSIDENTIFIER Request
, IN OUT PVOID Data
);
45 friend NTSTATUS NTAPI
PinWaveCyclicDataFormat(IN PIRP Irp
, IN PKSIDENTIFIER Request
, IN OUT PVOID Data
);
46 friend NTSTATUS NTAPI
PinWaveCyclicAudioPosition(IN PIRP Irp
, IN PKSIDENTIFIER Request
, IN OUT PVOID Data
);
47 friend NTSTATUS NTAPI
PinWaveCyclicAllocatorFraming(IN PIRP Irp
, IN PKSIDENTIFIER Request
, IN OUT PVOID Data
);
48 friend NTSTATUS NTAPI
PinWaveCyclicAddEndOfStreamEvent(IN PIRP Irp
, IN PKSEVENTDATA EventData
, IN PKSEVENT_ENTRY EventEntry
);
49 friend NTSTATUS NTAPI
PinWaveCyclicAddLoopedStreamEvent(IN PIRP Irp
, IN PKSEVENTDATA EventData
, IN PKSEVENT_ENTRY EventEntry
);
50 friend VOID CALLBACK
PinSetStateWorkerRoutine(IN PDEVICE_OBJECT DeviceObject
, IN PVOID Context
);
52 IPortWaveCyclic
* m_Port
;
53 IPortFilterWaveCyclic
* m_Filter
;
54 KSPIN_DESCRIPTOR
* m_KsPinDescriptor
;
55 PMINIPORTWAVECYCLIC m_Miniport
;
56 PSERVICEGROUP m_ServiceGroup
;
57 PDMACHANNEL m_DmaChannel
;
58 PMINIPORTWAVECYCLICSTREAM m_Stream
;
60 PKSDATAFORMAT m_Format
;
61 PKSPIN_CONNECT m_ConnectDetails
;
64 ULONG m_CommonBufferSize
;
65 ULONG m_CommonBufferOffset
;
67 IIrpQueue
* m_IrpQueue
;
74 KSAUDIO_POSITION m_Position
;
75 KSALLOCATOR_FRAMING m_AllocatorFraming
;
76 PSUBDEVICE_DESCRIPTOR m_Descriptor
;
78 KSPIN_LOCK m_EventListLock
;
79 LIST_ENTRY m_EventList
;
91 ULONG bLoopedStreaming
;
93 }LOOPEDSTREAMING_EVENT_CONTEXT
, *PLOOPEDSTREAMING_EVENT_CONTEXT
;
97 ULONG bLoopedStreaming
;
98 }ENDOFSTREAM_EVENT_CONTEXT
, *PENDOFSTREAM_EVENT_CONTEXT
;
102 NTSTATUS NTAPI
PinWaveCyclicState(IN PIRP Irp
, IN PKSIDENTIFIER Request
, IN OUT PVOID Data
);
103 NTSTATUS NTAPI
PinWaveCyclicDataFormat(IN PIRP Irp
, IN PKSIDENTIFIER Request
, IN OUT PVOID Data
);
104 NTSTATUS NTAPI
PinWaveCyclicAudioPosition(IN PIRP Irp
, IN PKSIDENTIFIER Request
, IN OUT PVOID Data
);
105 NTSTATUS NTAPI
PinWaveCyclicAllocatorFraming(IN PIRP Irp
, IN PKSIDENTIFIER Request
, IN OUT PVOID Data
);
106 NTSTATUS NTAPI
PinWaveCyclicAddEndOfStreamEvent(IN PIRP Irp
, IN PKSEVENTDATA EventData
, IN PKSEVENT_ENTRY EventEntry
);
107 NTSTATUS NTAPI
PinWaveCyclicAddLoopedStreamEvent(IN PIRP Irp
, IN PKSEVENTDATA EventData
, IN PKSEVENT_ENTRY EventEntry
);
108 NTSTATUS NTAPI
PinWaveCyclicDRMHandler(IN PIRP Irp
, IN PKSIDENTIFIER Request
, IN OUT PVOID Data
);
111 DEFINE_KSPROPERTY_CONNECTIONSET(PinWaveCyclicConnectionSet
, PinWaveCyclicState
, PinWaveCyclicDataFormat
, PinWaveCyclicAllocatorFraming
);
112 DEFINE_KSPROPERTY_AUDIOSET(PinWaveCyclicAudioSet
, PinWaveCyclicAudioPosition
);
113 DEFINE_KSPROPERTY_DRMSET(PinWaveCyclicDRMSet
, PinWaveCyclicDRMHandler
);
115 KSEVENT_ITEM PinWaveCyclicConnectionEventSet
=
117 KSEVENT_CONNECTION_ENDOFSTREAM
,
119 sizeof(ENDOFSTREAM_EVENT_CONTEXT
),
120 PinWaveCyclicAddEndOfStreamEvent
,
125 KSEVENT_ITEM PinWaveCyclicStreamingEventSet
=
127 KSEVENT_LOOPEDSTREAMING_POSITION
,
128 sizeof(LOOPEDSTREAMING_POSITION_EVENT_DATA
),
129 sizeof(LOOPEDSTREAMING_EVENT_CONTEXT
),
130 PinWaveCyclicAddLoopedStreamEvent
,
136 KSPROPERTY_SET PinWaveCyclicPropertySet
[] =
139 &KSPROPSETID_Connection
,
140 sizeof(PinWaveCyclicConnectionSet
) / sizeof(KSPROPERTY_ITEM
),
141 (const KSPROPERTY_ITEM
*)&PinWaveCyclicConnectionSet
,
147 sizeof(PinWaveCyclicAudioSet
) / sizeof(KSPROPERTY_ITEM
),
148 (const KSPROPERTY_ITEM
*)&PinWaveCyclicAudioSet
,
153 &KSPROPSETID_DrmAudioStream
,
154 sizeof(PinWaveCyclicDRMSet
) / sizeof(KSPROPERTY_ITEM
),
155 (const KSPROPERTY_ITEM
*)&PinWaveCyclicDRMSet
,
161 KSEVENT_SET PinWaveCyclicEventSet
[] =
164 &KSEVENTSETID_LoopedStreaming
,
165 sizeof(PinWaveCyclicStreamingEventSet
) / sizeof(KSEVENT_ITEM
),
166 (const KSEVENT_ITEM
*)&PinWaveCyclicStreamingEventSet
169 &KSEVENTSETID_Connection
,
170 sizeof(PinWaveCyclicConnectionEventSet
) / sizeof(KSEVENT_ITEM
),
171 (const KSEVENT_ITEM
*)&PinWaveCyclicConnectionEventSet
176 //==================================================================================================================================
180 CPortPinWaveCyclic::QueryInterface(
184 DPRINT("IServiceSink_fnQueryInterface entered\n");
186 if (IsEqualGUIDAligned(refiid
, IID_IIrpTarget
) ||
187 IsEqualGUIDAligned(refiid
, IID_IUnknown
))
189 *Output
= PVOID(PUNKNOWN((IIrpTarget
*)this));
190 PUNKNOWN(*Output
)->AddRef();
191 return STATUS_SUCCESS
;
194 if (IsEqualGUIDAligned(refiid
, IID_IServiceSink
))
196 *Output
= PVOID(PUNKNOWN(PSERVICESINK(this)));
197 PUNKNOWN(*Output
)->AddRef();
198 return STATUS_SUCCESS
;
201 return STATUS_UNSUCCESSFUL
;
206 PinWaveCyclicDRMHandler(
208 IN PKSIDENTIFIER Request
,
211 DPRINT1("PinWaveCyclicDRMHandler\n");
213 return STATUS_INVALID_PARAMETER
;
219 PinWaveCyclicAddEndOfStreamEvent(
221 IN PKSEVENTDATA EventData
,
222 IN PKSEVENT_ENTRY EventEntry
)
224 PENDOFSTREAM_EVENT_CONTEXT Entry
;
225 PSUBDEVICE_DESCRIPTOR Descriptor
;
226 CPortPinWaveCyclic
*Pin
;
228 // get sub device descriptor
229 Descriptor
= (PSUBDEVICE_DESCRIPTOR
)KSPROPERTY_ITEM_IRP_STORAGE(Irp
);
232 PC_ASSERT(Descriptor
);
233 PC_ASSERT(Descriptor
->PortPin
);
234 PC_ASSERT_IRQL(DISPATCH_LEVEL
);
237 Pin
= (CPortPinWaveCyclic
*)Descriptor
->PortPin
;
240 Entry
= (PENDOFSTREAM_EVENT_CONTEXT
)(EventEntry
+ 1);
242 // not a looped event
243 Entry
->bLoopedStreaming
= FALSE
;
246 (void)ExInterlockedInsertTailList(&Pin
->m_EventList
, &EventEntry
->ListEntry
, &Pin
->m_EventListLock
);
249 return STATUS_SUCCESS
;
254 PinWaveCyclicAddLoopedStreamEvent(
256 IN PKSEVENTDATA EventData
,
257 IN PKSEVENT_ENTRY EventEntry
)
259 PLOOPEDSTREAMING_POSITION_EVENT_DATA Data
;
260 PLOOPEDSTREAMING_EVENT_CONTEXT Entry
;
261 PSUBDEVICE_DESCRIPTOR Descriptor
;
262 CPortPinWaveCyclic
*Pin
;
264 // get sub device descriptor
265 Descriptor
= (PSUBDEVICE_DESCRIPTOR
)KSEVENT_ITEM_IRP_STORAGE(Irp
);
268 PC_ASSERT(Descriptor
);
269 PC_ASSERT(Descriptor
->PortPin
);
270 PC_ASSERT_IRQL(DISPATCH_LEVEL
);
273 Pin
= (CPortPinWaveCyclic
*)Descriptor
->PortPin
;
275 // cast to looped event
276 Data
= (PLOOPEDSTREAMING_POSITION_EVENT_DATA
)EventData
;
279 Entry
= (PLOOPEDSTREAMING_EVENT_CONTEXT
)(EventEntry
+ 1);
281 Entry
->bLoopedStreaming
= TRUE
;
282 Entry
->Position
= Data
->Position
;
284 DPRINT1("Added event\n");
287 (void)ExInterlockedInsertTailList(&Pin
->m_EventList
, &EventEntry
->ListEntry
, &Pin
->m_EventListLock
);
290 return STATUS_SUCCESS
;
295 PinWaveCyclicAllocatorFraming(
297 IN PKSIDENTIFIER Request
,
300 CPortPinWaveCyclic
*Pin
;
301 PSUBDEVICE_DESCRIPTOR Descriptor
;
303 // get sub device descriptor
304 Descriptor
= (PSUBDEVICE_DESCRIPTOR
)KSEVENT_ITEM_IRP_STORAGE(Irp
);
307 PC_ASSERT(Descriptor
);
308 PC_ASSERT(Descriptor
->PortPin
);
309 PC_ASSERT_IRQL(DISPATCH_LEVEL
);
312 Pin
= (CPortPinWaveCyclic
*)Descriptor
->PortPin
;
315 if (Request
->Flags
& KSPROPERTY_TYPE_GET
)
318 RtlMoveMemory(Data
, &Pin
->m_AllocatorFraming
, sizeof(KSALLOCATOR_FRAMING
));
320 Irp
->IoStatus
.Information
= sizeof(KSALLOCATOR_FRAMING
);
321 return STATUS_SUCCESS
;
325 return STATUS_NOT_SUPPORTED
;
330 PinWaveCyclicAudioPosition(
332 IN PKSIDENTIFIER Request
,
335 CPortPinWaveCyclic
*Pin
;
336 PSUBDEVICE_DESCRIPTOR Descriptor
;
337 PKSAUDIO_POSITION Position
;
339 // get sub device descriptor
340 Descriptor
= (PSUBDEVICE_DESCRIPTOR
)KSPROPERTY_ITEM_IRP_STORAGE(Irp
);
343 PC_ASSERT(Descriptor
);
344 PC_ASSERT(Descriptor
->PortPin
);
345 PC_ASSERT_IRQL(DISPATCH_LEVEL
);
348 Pin
= (CPortPinWaveCyclic
*)Descriptor
->PortPin
;
351 PC_ASSERT(Pin
->m_Stream
);
353 if (Request
->Flags
& KSPROPERTY_TYPE_GET
)
355 // FIXME non multithreading-safe
356 // copy audio position
358 Position
= (PKSAUDIO_POSITION
)Data
;
360 if (Pin
->m_ConnectDetails
->Interface
.Id
== KSINTERFACE_STANDARD_STREAMING
)
362 RtlMoveMemory(Data
, &Pin
->m_Position
, sizeof(KSAUDIO_POSITION
));
363 DPRINT("Play %lu Record %lu\n", Pin
->m_Position
.PlayOffset
, Pin
->m_Position
.WriteOffset
);
365 else if (Pin
->m_ConnectDetails
->Interface
.Id
== KSINTERFACE_STANDARD_LOOPED_STREAMING
)
367 Position
->PlayOffset
= Pin
->m_Position
.PlayOffset
;
368 Position
->WriteOffset
= (ULONGLONG
)Pin
->m_IrpQueue
->GetCurrentIrpOffset();
369 DPRINT("Play %lu Write %lu\n", Position
->PlayOffset
, Position
->WriteOffset
);
372 Irp
->IoStatus
.Information
= sizeof(KSAUDIO_POSITION
);
373 return STATUS_SUCCESS
;
377 return STATUS_NOT_SUPPORTED
;
382 CPortPinWaveCyclic
*Pin
;
384 PIO_WORKITEM WorkItem
;
387 }SETPIN_CONTEXT
, *PSETPIN_CONTEXT
;
391 PinSetStateWorkerRoutine(
392 IN PDEVICE_OBJECT DeviceObject
,
395 PSETPIN_CONTEXT PinWorkContext
= (PSETPIN_CONTEXT
)Context
;
399 Status
= PinWorkContext
->Pin
->m_Stream
->SetState(PinWorkContext
->NewState
);
401 DPRINT1("Setting state %u %x\n", PinWorkContext
->NewState
, Status
);
402 if (NT_SUCCESS(Status
))
405 PinWorkContext
->Pin
->m_State
= PinWorkContext
->NewState
;
407 if (PinWorkContext
->Pin
->m_ConnectDetails
->Interface
.Id
== KSINTERFACE_STANDARD_LOOPED_STREAMING
&& PinWorkContext
->Pin
->m_State
== KSSTATE_STOP
)
409 /* FIXME complete pending irps with successfull state */
410 PinWorkContext
->Pin
->m_IrpQueue
->CancelBuffers();
413 //PinWorkContext->Pin->m_IrpQueue->CancelBuffers();
417 PinWorkContext
->Irp
->IoStatus
.Information
= sizeof(KSSTATE
);
418 PinWorkContext
->Irp
->IoStatus
.Status
= Status
;
421 IoCompleteRequest(PinWorkContext
->Irp
, IO_NO_INCREMENT
);
424 IoFreeWorkItem(PinWorkContext
->WorkItem
);
427 FreeItem(PinWorkContext
, TAG_PORTCLASS
);
436 IN PKSIDENTIFIER Request
,
439 NTSTATUS Status
= STATUS_UNSUCCESSFUL
;
440 CPortPinWaveCyclic
*Pin
;
441 PSUBDEVICE_DESCRIPTOR Descriptor
;
442 PKSSTATE State
= (PKSSTATE
)Data
;
444 // get sub device descriptor
445 Descriptor
= (PSUBDEVICE_DESCRIPTOR
)KSPROPERTY_ITEM_IRP_STORAGE(Irp
);
448 PC_ASSERT(Descriptor
);
449 PC_ASSERT(Descriptor
->PortPin
);
450 PC_ASSERT_IRQL(DISPATCH_LEVEL
);
453 Pin
= (CPortPinWaveCyclic
*)Descriptor
->PortPin
;
456 PC_ASSERT(Pin
->m_Stream
);
458 if (Request
->Flags
& KSPROPERTY_TYPE_SET
)
461 Status
= Pin
->m_Stream
->SetState(*State
);
463 DPRINT("Setting state %u %x\n", *State
, Status
);
464 if (NT_SUCCESS(Status
))
467 Pin
->m_State
= *State
;
469 if (Pin
->m_ConnectDetails
->Interface
.Id
== KSINTERFACE_STANDARD_LOOPED_STREAMING
&& Pin
->m_State
== KSSTATE_STOP
)
472 // complete with successful state
473 Pin
->m_Stream
->Silence(Pin
->m_CommonBuffer
, Pin
->m_CommonBufferSize
);
474 Pin
->m_IrpQueue
->CancelBuffers();
475 Pin
->m_Position
.PlayOffset
= 0;
476 Pin
->m_Position
.WriteOffset
= 0;
478 else if (Pin
->m_State
== KSSTATE_STOP
)
480 Pin
->m_Stream
->Silence(Pin
->m_CommonBuffer
, Pin
->m_CommonBufferSize
);
481 Pin
->m_IrpQueue
->CancelBuffers();
482 Pin
->m_Position
.PlayOffset
= 0;
483 Pin
->m_Position
.WriteOffset
= 0;
486 Irp
->IoStatus
.Information
= sizeof(KSSTATE
);
490 else if (Request
->Flags
& KSPROPERTY_TYPE_GET
)
492 // get current stream state
493 *State
= Pin
->m_State
;
495 Irp
->IoStatus
.Information
= sizeof(KSSTATE
);
497 return STATUS_SUCCESS
;
500 // unsupported request
501 return STATUS_NOT_SUPPORTED
;
506 PinWaveCyclicDataFormat(
508 IN PKSIDENTIFIER Request
,
511 NTSTATUS Status
= STATUS_UNSUCCESSFUL
;
512 CPortPinWaveCyclic
*Pin
;
513 PSUBDEVICE_DESCRIPTOR Descriptor
;
514 PIO_STACK_LOCATION IoStack
;
516 // get current irp stack location
517 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
519 // get sub device descriptor
520 Descriptor
= (PSUBDEVICE_DESCRIPTOR
)KSPROPERTY_ITEM_IRP_STORAGE(Irp
);
523 PC_ASSERT(Descriptor
);
524 PC_ASSERT(Descriptor
->PortPin
);
527 Pin
= (CPortPinWaveCyclic
*)Descriptor
->PortPin
;
530 PC_ASSERT(Pin
->m_Stream
);
531 PC_ASSERT(Pin
->m_Format
);
533 if (Request
->Flags
& KSPROPERTY_TYPE_SET
)
535 // try to change data format
536 PKSDATAFORMAT NewDataFormat
, DataFormat
= (PKSDATAFORMAT
)Irp
->UserBuffer
;
537 ULONG Size
= min(Pin
->m_Format
->FormatSize
, DataFormat
->FormatSize
);
539 if (RtlCompareMemory(DataFormat
, Pin
->m_Format
, Size
) == Size
)
541 // format is identical
542 Irp
->IoStatus
.Information
= DataFormat
->FormatSize
;
543 return STATUS_SUCCESS
;
546 // new change request
547 PC_ASSERT(Pin
->m_State
!= KSSTATE_RUN
);
548 // FIXME queue a work item when Irql != PASSIVE_LEVEL
549 PC_ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL
);
551 // allocate new data format
552 NewDataFormat
= (PKSDATAFORMAT
)AllocateItem(NonPagedPool
, DataFormat
->FormatSize
, TAG_PORTCLASS
);
556 return STATUS_NO_MEMORY
;
559 // copy new data format
560 RtlMoveMemory(NewDataFormat
, DataFormat
, DataFormat
->FormatSize
);
563 Status
= Pin
->m_Stream
->SetFormat(NewDataFormat
);
564 if (NT_SUCCESS(Status
))
567 FreeItem(Pin
->m_Format
, TAG_PORTCLASS
);
570 Pin
->m_Format
= NewDataFormat
;
571 Irp
->IoStatus
.Information
= NewDataFormat
->FormatSize
;
574 PC_ASSERT(NewDataFormat
->FormatSize
== sizeof(KSDATAFORMAT_WAVEFORMATEX
));
575 PC_ASSERT(IsEqualGUIDAligned(((PKSDATAFORMAT_WAVEFORMATEX
)NewDataFormat
)->DataFormat
.MajorFormat
, KSDATAFORMAT_TYPE_AUDIO
));
576 PC_ASSERT(IsEqualGUIDAligned(((PKSDATAFORMAT_WAVEFORMATEX
)NewDataFormat
)->DataFormat
.SubFormat
, KSDATAFORMAT_SUBTYPE_PCM
));
577 PC_ASSERT(IsEqualGUIDAligned(((PKSDATAFORMAT_WAVEFORMATEX
)NewDataFormat
)->DataFormat
.Specifier
, KSDATAFORMAT_SPECIFIER_WAVEFORMATEX
));
580 DPRINT("NewDataFormat: Channels %u Bits %u Samples %u\n", ((PKSDATAFORMAT_WAVEFORMATEX
)NewDataFormat
)->WaveFormatEx
.nChannels
,
581 ((PKSDATAFORMAT_WAVEFORMATEX
)NewDataFormat
)->WaveFormatEx
.wBitsPerSample
,
582 ((PKSDATAFORMAT_WAVEFORMATEX
)NewDataFormat
)->WaveFormatEx
.nSamplesPerSec
);
588 // failed to set format
589 FreeItem(NewDataFormat
, TAG_PORTCLASS
);
596 else if (Request
->Flags
& KSPROPERTY_TYPE_GET
)
598 // get current data format
599 PC_ASSERT(Pin
->m_Format
);
601 if (Pin
->m_Format
->FormatSize
> IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
)
604 Irp
->IoStatus
.Information
= Pin
->m_Format
->FormatSize
;
605 return STATUS_MORE_ENTRIES
;
608 RtlMoveMemory(Data
, Pin
->m_Format
, Pin
->m_Format
->FormatSize
);
610 Irp
->IoStatus
.Information
= Pin
->m_Format
->FormatSize
;
613 return STATUS_SUCCESS
;
616 // unsupported request
617 return STATUS_NOT_SUPPORTED
;
621 CPortPinWaveCyclic::GeneratePositionEvents(
622 IN ULONGLONG OldOffset
,
623 IN ULONGLONG NewOffset
)
626 PKSEVENT_ENTRY EventEntry
;
627 PLOOPEDSTREAMING_EVENT_CONTEXT Context
;
629 // acquire event lock
630 KeAcquireSpinLockAtDpcLevel(&m_EventListLock
);
632 // point to first entry
633 Entry
= m_EventList
.Flink
;
635 while(Entry
!= &m_EventList
)
638 EventEntry
= (PKSEVENT_ENTRY
)CONTAINING_RECORD(Entry
, KSEVENT_ENTRY
, ListEntry
);
640 // get event entry context
641 Context
= (PLOOPEDSTREAMING_EVENT_CONTEXT
)(EventEntry
+ 1);
643 if (Context
->bLoopedStreaming
== TRUE
)
645 if (NewOffset
> OldOffset
)
647 /* buffer progress no overlap */
648 if (OldOffset
< Context
->Position
&& Context
->Position
<= NewOffset
)
650 /* when someone eventually fixes sprintf... */
651 DPRINT("Generating event at OldOffset %I64u\n", OldOffset
);
652 DPRINT("Context->Position %I64u\n", Context
->Position
);
653 DPRINT("NewOffset %I64u\n", NewOffset
);
655 KsGenerateEvent(EventEntry
);
660 /* buffer wrap-arround */
661 if (OldOffset
< Context
->Position
|| NewOffset
> Context
->Position
)
663 /* when someone eventually fixes sprintf... */
664 DPRINT("Generating event at OldOffset %I64u\n", OldOffset
);
665 DPRINT("Context->Position %I64u\n", Context
->Position
);
666 DPRINT("NewOffset %I64u\n", NewOffset
);
668 KsGenerateEvent(EventEntry
);
673 // move to next entry
674 Entry
= Entry
->Flink
;
678 KeReleaseSpinLockFromDpcLevel(&m_EventListLock
);
682 CPortPinWaveCyclic::UpdateCommonBuffer(
684 ULONG MaxTransferCount
)
693 BufferLength
= Position
- m_CommonBufferOffset
;
694 BufferLength
= min(BufferLength
, MaxTransferCount
);
698 Status
= m_IrpQueue
->GetMapping(&Buffer
, &BufferSize
);
699 if (!NT_SUCCESS(Status
))
701 Gap
= Position
- m_CommonBufferOffset
;
702 if (Gap
> BufferLength
)
704 // insert silence samples
705 DPRINT("Inserting Silence Buffer Offset %lu GapLength %lu\n", m_CommonBufferOffset
, BufferLength
);
706 m_Stream
->Silence((PUCHAR
)m_CommonBuffer
+ m_CommonBufferOffset
, BufferLength
);
708 m_CommonBufferOffset
+= BufferLength
;
713 BytesToCopy
= min(BufferLength
, BufferSize
);
717 m_DmaChannel
->CopyFrom(Buffer
, (PUCHAR
)m_CommonBuffer
+ m_CommonBufferOffset
, BytesToCopy
);
721 m_DmaChannel
->CopyTo((PUCHAR
)m_CommonBuffer
+ m_CommonBufferOffset
, Buffer
, BytesToCopy
);
724 m_IrpQueue
->UpdateMapping(BytesToCopy
);
725 m_CommonBufferOffset
+= BytesToCopy
;
727 BufferLength
-= BytesToCopy
;
728 m_Position
.PlayOffset
+= BytesToCopy
;
730 if (m_ConnectDetails
->Interface
.Id
== KSINTERFACE_STANDARD_LOOPED_STREAMING
)
732 if (m_Position
.WriteOffset
)
734 // normalize position
735 m_Position
.PlayOffset
= m_Position
.PlayOffset
% m_Position
.WriteOffset
;
742 CPortPinWaveCyclic::UpdateCommonBufferOverlap(
744 ULONG MaxTransferCount
)
746 ULONG BufferLength
, Length
, Gap
;
753 BufferLength
= Gap
= m_CommonBufferSize
- m_CommonBufferOffset
;
754 BufferLength
= Length
= min(BufferLength
, MaxTransferCount
);
757 Status
= m_IrpQueue
->GetMapping(&Buffer
, &BufferSize
);
758 if (!NT_SUCCESS(Status
))
760 Gap
= m_CommonBufferSize
- m_CommonBufferOffset
+ Position
;
761 if (Gap
> BufferLength
)
763 // insert silence samples
764 DPRINT("Overlap Inserting Silence Buffer Size %lu Offset %lu Gap %lu Position %lu\n", m_CommonBufferSize
, m_CommonBufferOffset
, Gap
, Position
);
765 m_Stream
->Silence((PUCHAR
)m_CommonBuffer
+ m_CommonBufferOffset
, BufferLength
);
767 m_CommonBufferOffset
+= BufferLength
;
772 BytesToCopy
= min(BufferLength
, BufferSize
);
776 m_DmaChannel
->CopyFrom(Buffer
,
777 (PUCHAR
)m_CommonBuffer
+ m_CommonBufferOffset
,
782 m_DmaChannel
->CopyTo((PUCHAR
)m_CommonBuffer
+ m_CommonBufferOffset
,
787 m_IrpQueue
->UpdateMapping(BytesToCopy
);
788 m_CommonBufferOffset
+= BytesToCopy
;
789 m_Position
.PlayOffset
+= BytesToCopy
;
791 BufferLength
-=BytesToCopy
;
793 if (m_ConnectDetails
->Interface
.Id
== KSINTERFACE_STANDARD_LOOPED_STREAMING
)
795 if (m_Position
.WriteOffset
)
797 // normalize position
798 m_Position
.PlayOffset
= m_Position
.PlayOffset
% m_Position
.WriteOffset
;
805 m_CommonBufferOffset
= 0;
807 MaxTransferCount
-= Length
;
809 if (MaxTransferCount
)
811 UpdateCommonBuffer(Position
, MaxTransferCount
);
818 CPortPinWaveCyclic::RequestService()
822 ULONGLONG OldOffset
, NewOffset
;
824 PC_ASSERT_IRQL(DISPATCH_LEVEL
);
826 if (m_State
== KSSTATE_RUN
&& m_ResetState
== KSRESET_END
)
828 Status
= m_Stream
->GetPosition(&Position
);
830 OldOffset
= m_Position
.PlayOffset
;
832 if (Position
< m_CommonBufferOffset
)
834 UpdateCommonBufferOverlap(Position
, m_FrameSize
);
836 else if (Position
>= m_CommonBufferOffset
)
838 UpdateCommonBuffer(Position
, m_FrameSize
);
841 NewOffset
= m_Position
.PlayOffset
;
843 GeneratePositionEvents(OldOffset
, NewOffset
);
849 CPortPinWaveCyclic::NewIrpTarget(
850 OUT
struct IIrpTarget
**OutTarget
,
853 IN POOL_TYPE PoolType
,
854 IN PDEVICE_OBJECT DeviceObject
,
856 IN KSOBJECT_CREATE
*CreateObject
)
859 return STATUS_UNSUCCESSFUL
;
864 CPortPinWaveCyclic::DeviceIoControl(
865 IN PDEVICE_OBJECT DeviceObject
,
868 PIO_STACK_LOCATION IoStack
;
869 PKSPROPERTY Property
;
870 UNICODE_STRING GuidString
;
871 NTSTATUS Status
= STATUS_NOT_SUPPORTED
;
875 /* get current irp stack location */
876 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
878 if (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_KS_PROPERTY
)
880 /* handle property with subdevice descriptor */
881 Status
= PcHandlePropertyWithTable(Irp
, m_Descriptor
->FilterPropertySetCount
, m_Descriptor
->FilterPropertySet
, m_Descriptor
);
883 if (Status
== STATUS_NOT_FOUND
)
885 Property
= (PKSPROPERTY
)IoStack
->Parameters
.DeviceIoControl
.Type3InputBuffer
;
887 RtlStringFromGUID(Property
->Set
, &GuidString
);
888 DPRINT("Unhandeled property Set |%S| Id %u Flags %x\n", GuidString
.Buffer
, Property
->Id
, Property
->Flags
);
889 RtlFreeUnicodeString(&GuidString
);
892 else if (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_KS_ENABLE_EVENT
)
894 Status
= PcHandleEnableEventWithTable(Irp
, m_Descriptor
);
896 else if (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_KS_DISABLE_EVENT
)
898 Status
= PcHandleDisableEventWithTable(Irp
, m_Descriptor
);
900 else if (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_KS_RESET_STATE
)
902 Status
= KsAcquireResetValue(Irp
, &ResetValue
);
903 DPRINT("Status %x Value %u\n", Status
, ResetValue
);
904 /* check for success */
905 if (NT_SUCCESS(Status
))
907 //determine state of reset request
908 if (ResetValue
== KSRESET_BEGIN
)
910 // start reset procress
911 // incoming read/write requests will be rejected
912 m_ResetState
= KSRESET_BEGIN
;
914 // cancel existing buffers
915 m_IrpQueue
->CancelBuffers();
917 else if (ResetValue
== KSRESET_END
)
919 // end of reset process
920 m_ResetState
= KSRESET_END
;
924 else if (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_KS_WRITE_STREAM
|| IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_KS_READ_STREAM
)
926 /* increment total number of packets */
927 InterlockedIncrement((PLONG
)&m_TotalPackets
);
929 DPRINT("New Packet Total %u State %x MinData %u\n", m_TotalPackets
, m_State
, m_IrpQueue
->NumData());
931 /* is the device not currently reset */
932 if (m_ResetState
== KSRESET_END
)
934 /* add the mapping */
935 Status
= m_IrpQueue
->AddMapping(Irp
, &Data
);
937 /* check for success */
938 if (NT_SUCCESS(Status
))
940 m_Position
.WriteOffset
+= Data
;
941 Status
= STATUS_PENDING
;
946 /* reset request is currently in progress */
947 Status
= STATUS_DEVICE_NOT_READY
;
948 DPRINT1("NotReady\n");
953 return KsDefaultDeviceIoCompletion(DeviceObject
, Irp
);
956 if (Status
!= STATUS_PENDING
)
958 Irp
->IoStatus
.Status
= Status
;
959 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
967 CPortPinWaveCyclic::Read(
968 IN PDEVICE_OBJECT DeviceObject
,
971 return KsDispatchInvalidDeviceRequest(DeviceObject
, Irp
);
976 CPortPinWaveCyclic::Write(
977 IN PDEVICE_OBJECT DeviceObject
,
980 return KsDispatchInvalidDeviceRequest(DeviceObject
, Irp
);
985 CPortPinWaveCyclic::Flush(
986 IN PDEVICE_OBJECT DeviceObject
,
989 return KsDispatchInvalidDeviceRequest(DeviceObject
, Irp
);
994 CPortPinWaveCyclic::Close(
995 IN PDEVICE_OBJECT DeviceObject
,
998 DPRINT("CPortPinWaveCyclic::Close entered\n");
1000 PC_ASSERT_IRQL(PASSIVE_LEVEL
);
1005 FreeItem(m_Format
, TAG_PORTCLASS
);
1013 // cancel remaining irps
1014 m_IrpQueue
->CancelBuffers();
1016 // release irp queue
1017 m_IrpQueue
->Release();
1025 // remove member from service group
1026 m_ServiceGroup
->RemoveMember(PSERVICESINK(this));
1028 // do not release service group, it is released by the miniport object
1029 m_ServiceGroup
= NULL
;
1034 if (m_State
!= KSSTATE_STOP
)
1037 NTSTATUS Status
= m_Stream
->SetState(KSSTATE_STOP
);
1038 if (!NT_SUCCESS(Status
))
1040 DPRINT("Warning: failed to stop stream with %x\n", Status
);
1044 // set state to stop
1045 m_State
= KSSTATE_STOP
;
1047 DPRINT("Closing stream at Irql %u\n", KeGetCurrentIrql());
1050 m_Stream
->Release();
1052 // stream is now freed
1059 // disconnect pin from filter
1060 m_Filter
->FreePin((PPORTPINWAVECYCLIC
)this);
1062 // release filter reference
1063 m_Filter
->Release();
1065 // pin is done with filter
1071 // release reference to port driver
1074 // work is done for port
1078 Irp
->IoStatus
.Information
= 0;
1079 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
1080 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1084 return STATUS_SUCCESS
;
1089 CPortPinWaveCyclic::QuerySecurity(
1090 IN PDEVICE_OBJECT DeviceObject
,
1093 return KsDispatchInvalidDeviceRequest(DeviceObject
, Irp
);
1098 CPortPinWaveCyclic::SetSecurity(
1099 IN PDEVICE_OBJECT DeviceObject
,
1102 return KsDispatchInvalidDeviceRequest(DeviceObject
, Irp
);
1107 CPortPinWaveCyclic::FastDeviceIoControl(
1108 IN PFILE_OBJECT FileObject
,
1110 IN PVOID InputBuffer
,
1111 IN ULONG InputBufferLength
,
1112 OUT PVOID OutputBuffer
,
1113 IN ULONG OutputBufferLength
,
1114 IN ULONG IoControlCode
,
1115 OUT PIO_STATUS_BLOCK StatusBlock
,
1116 IN PDEVICE_OBJECT DeviceObject
)
1118 return KsDispatchFastIoDeviceControlFailure(FileObject
, Wait
, InputBuffer
, InputBufferLength
, OutputBuffer
, OutputBufferLength
, IoControlCode
, StatusBlock
, DeviceObject
);
1124 CPortPinWaveCyclic::FastRead(
1125 IN PFILE_OBJECT FileObject
,
1126 IN PLARGE_INTEGER FileOffset
,
1131 OUT PIO_STATUS_BLOCK StatusBlock
,
1132 IN PDEVICE_OBJECT DeviceObject
)
1134 return KsDispatchFastReadFailure(FileObject
, FileOffset
, Length
, Wait
, LockKey
, Buffer
, StatusBlock
, DeviceObject
);
1140 CPortPinWaveCyclic::FastWrite(
1141 IN PFILE_OBJECT FileObject
,
1142 IN PLARGE_INTEGER FileOffset
,
1147 OUT PIO_STATUS_BLOCK StatusBlock
,
1148 IN PDEVICE_OBJECT DeviceObject
)
1150 return KsDispatchFastReadFailure(FileObject
, FileOffset
, Length
, Wait
, LockKey
, Buffer
, StatusBlock
, DeviceObject
);
1156 CPortPinWaveCyclic::Init(
1157 IN PPORTWAVECYCLIC Port
,
1158 IN PPORTFILTERWAVECYCLIC Filter
,
1159 IN KSPIN_CONNECT
* ConnectDetails
,
1160 IN KSPIN_DESCRIPTOR
* KsPinDescriptor
)
1163 PKSDATAFORMAT DataFormat
;
1164 PDEVICE_OBJECT DeviceObject
;
1166 PSUBDEVICE_DESCRIPTOR SubDeviceDescriptor
= NULL
;
1167 //IDrmAudioStream * DrmAudio = NULL;
1169 m_KsPinDescriptor
= KsPinDescriptor
;
1170 m_ConnectDetails
= ConnectDetails
;
1171 m_Miniport
= GetWaveCyclicMiniport(Port
);
1173 DeviceObject
= GetDeviceObject(Port
);
1175 DataFormat
= (PKSDATAFORMAT
)(ConnectDetails
+ 1);
1177 DPRINT("CPortPinWaveCyclic::Init entered Size %u\n", DataFormat
->FormatSize
);
1179 Status
= NewIrpQueue(&m_IrpQueue
);
1180 if (!NT_SUCCESS(Status
))
1183 if (KsPinDescriptor
->Communication
== KSPIN_COMMUNICATION_SINK
&& KsPinDescriptor
->DataFlow
== KSPIN_DATAFLOW_IN
)
1187 else if (KsPinDescriptor
->Communication
== KSPIN_COMMUNICATION_SINK
&& KsPinDescriptor
->DataFlow
== KSPIN_DATAFLOW_OUT
)
1193 DPRINT("Unexpected Communication %u DataFlow %u\n", KsPinDescriptor
->Communication
, KsPinDescriptor
->DataFlow
);
1199 Status
= m_Miniport
->NewStream(&m_Stream
,
1202 ConnectDetails
->PinId
,
1208 Status
= m_Stream
->QueryInterface(IID_IDrmAudioStream
, (PVOID
*)&DrmAudio
);
1209 if (NT_SUCCESS(Status
))
1211 DRMRIGHTS DrmRights
;
1212 DPRINT("Got IID_IDrmAudioStream interface %p\n", DrmAudio
);
1214 DrmRights
.CopyProtect
= FALSE
;
1215 DrmRights
.Reserved
= 0;
1216 DrmRights
.DigitalOutputDisable
= FALSE
;
1218 Status
= DrmAudio
->SetContentId(1, &DrmRights
);
1219 DPRINT("Status %x\n", Status
);
1223 DPRINT1("CPortPinWaveCyclic::Init Status %x PinId %u Capture %u\n", Status
, ConnectDetails
->PinId
, Capture
);
1225 if (!NT_SUCCESS(Status
))
1228 ISubdevice
* Subdevice
= NULL
;
1229 // get subdevice interface
1230 Status
= Port
->QueryInterface(IID_ISubdevice
, (PVOID
*)&Subdevice
);
1232 if (!NT_SUCCESS(Status
))
1235 Status
= Subdevice
->GetDescriptor(&SubDeviceDescriptor
);
1236 if (!NT_SUCCESS(Status
))
1238 // failed to get descriptor
1239 Subdevice
->Release();
1243 /* initialize event management */
1244 InitializeListHead(&m_EventList
);
1245 KeInitializeSpinLock(&m_EventListLock
);
1247 Status
= PcCreateSubdeviceDescriptor(&m_Descriptor
,
1248 SubDeviceDescriptor
->InterfaceCount
,
1249 SubDeviceDescriptor
->Interfaces
,
1250 0, /* FIXME KSINTERFACE_STANDARD with KSINTERFACE_STANDARD_STREAMING / KSINTERFACE_STANDARD_LOOPED_STREAMING */
1252 sizeof(PinWaveCyclicPropertySet
) / sizeof(KSPROPERTY_SET
),
1253 PinWaveCyclicPropertySet
,
1258 sizeof(PinWaveCyclicEventSet
) / sizeof(KSEVENT_SET
),
1259 PinWaveCyclicEventSet
,
1260 SubDeviceDescriptor
->DeviceDescriptor
);
1262 m_Descriptor
->UnknownStream
= (PUNKNOWN
)m_Stream
;
1263 m_Descriptor
->UnknownMiniport
= SubDeviceDescriptor
->UnknownMiniport
;
1264 m_Descriptor
->PortPin
= (PVOID
)this;
1265 m_Descriptor
->EventList
= &m_EventList
;
1266 m_Descriptor
->EventListLock
= &m_EventListLock
;
1268 // initialize reset state
1269 m_ResetState
= KSRESET_END
;
1271 // release subdevice descriptor
1272 Subdevice
->Release();
1274 // add ourselves to service group
1275 Status
= m_ServiceGroup
->AddMember(PSERVICESINK(this));
1276 if (!NT_SUCCESS(Status
))
1278 DPRINT("Failed to add pin to service group\n");
1282 m_Stream
->SetState(KSSTATE_STOP
);
1283 m_State
= KSSTATE_STOP
;
1284 m_CommonBufferOffset
= 0;
1285 m_CommonBufferSize
= m_DmaChannel
->AllocatedBufferSize();
1286 m_CommonBuffer
= m_DmaChannel
->SystemAddress();
1287 m_Capture
= Capture
;
1288 // delay of 10 milisec
1289 m_Delay
= Int32x32To64(10, -10000);
1292 PC_ASSERT(m_CommonBufferSize
);
1293 PC_ASSERT(m_CommonBuffer
);
1295 Status
= m_Stream
->SetNotificationFreq(10, &m_FrameSize
);
1296 PC_ASSERT(NT_SUCCESS(Status
));
1297 PC_ASSERT(m_FrameSize
);
1299 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());
1302 /* set up allocator framing */
1303 m_AllocatorFraming
.RequirementsFlags
= KSALLOCATOR_REQUIREMENTF_SYSTEM_MEMORY
| KSALLOCATOR_REQUIREMENTF_PREFERENCES_ONLY
;
1304 m_AllocatorFraming
.PoolType
= NonPagedPool
;
1305 m_AllocatorFraming
.Frames
= 8;
1306 m_AllocatorFraming
.FileAlignment
= FILE_64_BYTE_ALIGNMENT
;
1307 m_AllocatorFraming
.Reserved
= 0;
1308 m_AllocatorFraming
.FrameSize
= m_FrameSize
;
1310 m_Stream
->Silence(m_CommonBuffer
, m_CommonBufferSize
);
1312 Status
= m_IrpQueue
->Init(ConnectDetails
, KsPinDescriptor
, m_FrameSize
, 0, FALSE
);
1313 if (!NT_SUCCESS(Status
))
1315 m_IrpQueue
->Release();
1319 m_Format
= (PKSDATAFORMAT
)AllocateItem(NonPagedPool
, DataFormat
->FormatSize
, TAG_PORTCLASS
);
1321 return STATUS_INSUFFICIENT_RESOURCES
;
1323 RtlMoveMemory(m_Format
, DataFormat
, DataFormat
->FormatSize
);
1331 return STATUS_SUCCESS
;
1337 CPortPinWaveCyclic::GetCompletedPosition()
1346 CPortPinWaveCyclic::GetCycleCount()
1355 CPortPinWaveCyclic::GetDeviceBufferSize()
1357 return m_CommonBufferSize
;
1363 CPortPinWaveCyclic::GetIrpStream()
1365 return (PVOID
)m_IrpQueue
;
1371 CPortPinWaveCyclic::GetMiniport()
1373 return (PMINIPORT
)m_Miniport
;
1378 NewPortPinWaveCyclic(
1379 OUT IPortPinWaveCyclic
** OutPin
)
1381 CPortPinWaveCyclic
* This
;
1383 This
= new(NonPagedPool
, TAG_PORTCLASS
)CPortPinWaveCyclic(NULL
);
1385 return STATUS_INSUFFICIENT_RESOURCES
;
1390 *OutPin
= (IPortPinWaveCyclic
*)This
;
1392 return STATUS_SUCCESS
;