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 SUBDEVICE_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
);
110 DEFINE_KSPROPERTY_CONNECTIONSET(PinWaveCyclicConnectionSet
, PinWaveCyclicState
, PinWaveCyclicDataFormat
, PinWaveCyclicAllocatorFraming
);
111 DEFINE_KSPROPERTY_AUDIOSET(PinWaveCyclicAudioSet
, PinWaveCyclicAudioPosition
);
113 KSEVENT_ITEM PinWaveCyclicConnectionEventSet
=
115 KSEVENT_CONNECTION_ENDOFSTREAM
,
117 sizeof(ENDOFSTREAM_EVENT_CONTEXT
),
118 PinWaveCyclicAddEndOfStreamEvent
,
123 KSEVENT_ITEM PinWaveCyclicStreamingEventSet
=
125 KSEVENT_LOOPEDSTREAMING_POSITION
,
126 sizeof(LOOPEDSTREAMING_POSITION_EVENT_DATA
),
127 sizeof(LOOPEDSTREAMING_EVENT_CONTEXT
),
128 PinWaveCyclicAddLoopedStreamEvent
,
134 KSPROPERTY_SET PinWaveCyclicPropertySet
[] =
137 &KSPROPSETID_Connection
,
138 sizeof(PinWaveCyclicConnectionSet
) / sizeof(KSPROPERTY_ITEM
),
139 (const KSPROPERTY_ITEM
*)&PinWaveCyclicConnectionSet
,
145 sizeof(PinWaveCyclicAudioSet
) / sizeof(KSPROPERTY_ITEM
),
146 (const KSPROPERTY_ITEM
*)&PinWaveCyclicAudioSet
,
152 KSEVENT_SET PinWaveCyclicEventSet
[] =
155 &KSEVENTSETID_LoopedStreaming
,
156 sizeof(PinWaveCyclicStreamingEventSet
) / sizeof(KSEVENT_ITEM
),
157 (const KSEVENT_ITEM
*)&PinWaveCyclicStreamingEventSet
160 &KSEVENTSETID_Connection
,
161 sizeof(PinWaveCyclicConnectionEventSet
) / sizeof(KSEVENT_ITEM
),
162 (const KSEVENT_ITEM
*)&PinWaveCyclicConnectionEventSet
167 //==================================================================================================================================
171 CPortPinWaveCyclic::QueryInterface(
175 DPRINT("IServiceSink_fnQueryInterface entered\n");
177 if (IsEqualGUIDAligned(refiid
, IID_IIrpTarget
) ||
178 IsEqualGUIDAligned(refiid
, IID_IUnknown
))
180 *Output
= PVOID(PUNKNOWN((IIrpTarget
*)this));
181 PUNKNOWN(*Output
)->AddRef();
182 return STATUS_SUCCESS
;
185 if (IsEqualGUIDAligned(refiid
, IID_IServiceSink
))
187 *Output
= PVOID(PUNKNOWN(PSERVICESINK(this)));
188 PUNKNOWN(*Output
)->AddRef();
189 return STATUS_SUCCESS
;
192 return STATUS_UNSUCCESSFUL
;
197 PinWaveCyclicAddEndOfStreamEvent(
199 IN PKSEVENTDATA EventData
,
200 IN PKSEVENT_ENTRY EventEntry
)
202 PENDOFSTREAM_EVENT_CONTEXT Entry
;
203 PSUBDEVICE_DESCRIPTOR Descriptor
;
204 CPortPinWaveCyclic
*Pin
;
206 // get sub device descriptor
207 Descriptor
= (PSUBDEVICE_DESCRIPTOR
)KSPROPERTY_ITEM_IRP_STORAGE(Irp
);
210 PC_ASSERT(Descriptor
);
211 PC_ASSERT(Descriptor
->PortPin
);
212 PC_ASSERT_IRQL(DISPATCH_LEVEL
);
215 Pin
= (CPortPinWaveCyclic
*)Descriptor
->PortPin
;
218 Entry
= (PENDOFSTREAM_EVENT_CONTEXT
)(EventEntry
+ 1);
220 // not a looped event
221 Entry
->bLoopedStreaming
= FALSE
;
224 (void)ExInterlockedInsertTailList(&Pin
->m_EventList
, &EventEntry
->ListEntry
, &Pin
->m_EventListLock
);
227 return STATUS_SUCCESS
;
232 PinWaveCyclicAddLoopedStreamEvent(
234 IN PKSEVENTDATA EventData
,
235 IN PKSEVENT_ENTRY EventEntry
)
237 PLOOPEDSTREAMING_POSITION_EVENT_DATA Data
;
238 PLOOPEDSTREAMING_EVENT_CONTEXT Entry
;
239 PSUBDEVICE_DESCRIPTOR Descriptor
;
240 CPortPinWaveCyclic
*Pin
;
242 // get sub device descriptor
243 Descriptor
= (PSUBDEVICE_DESCRIPTOR
)KSEVENT_ITEM_IRP_STORAGE(Irp
);
246 PC_ASSERT(Descriptor
);
247 PC_ASSERT(Descriptor
->PortPin
);
248 PC_ASSERT_IRQL(DISPATCH_LEVEL
);
251 Pin
= (CPortPinWaveCyclic
*)Descriptor
->PortPin
;
253 // cast to looped event
254 Data
= (PLOOPEDSTREAMING_POSITION_EVENT_DATA
)EventData
;
257 Entry
= (PLOOPEDSTREAMING_EVENT_CONTEXT
)(EventEntry
+ 1);
259 Entry
->bLoopedStreaming
= TRUE
;
260 Entry
->Position
= Data
->Position
;
262 DPRINT1("Added event\n");
265 (void)ExInterlockedInsertTailList(&Pin
->m_EventList
, &EventEntry
->ListEntry
, &Pin
->m_EventListLock
);
268 return STATUS_SUCCESS
;
273 PinWaveCyclicAllocatorFraming(
275 IN PKSIDENTIFIER Request
,
278 CPortPinWaveCyclic
*Pin
;
279 PSUBDEVICE_DESCRIPTOR Descriptor
;
281 // get sub device descriptor
282 Descriptor
= (PSUBDEVICE_DESCRIPTOR
)KSEVENT_ITEM_IRP_STORAGE(Irp
);
285 PC_ASSERT(Descriptor
);
286 PC_ASSERT(Descriptor
->PortPin
);
287 PC_ASSERT_IRQL(DISPATCH_LEVEL
);
290 Pin
= (CPortPinWaveCyclic
*)Descriptor
->PortPin
;
293 if (Request
->Flags
& KSPROPERTY_TYPE_GET
)
296 RtlMoveMemory(Data
, &Pin
->m_AllocatorFraming
, sizeof(KSALLOCATOR_FRAMING
));
298 Irp
->IoStatus
.Information
= sizeof(KSALLOCATOR_FRAMING
);
299 return STATUS_SUCCESS
;
303 return STATUS_NOT_SUPPORTED
;
308 PinWaveCyclicAudioPosition(
310 IN PKSIDENTIFIER Request
,
313 CPortPinWaveCyclic
*Pin
;
314 PSUBDEVICE_DESCRIPTOR Descriptor
;
315 PKSAUDIO_POSITION Position
;
317 // get sub device descriptor
318 Descriptor
= (PSUBDEVICE_DESCRIPTOR
)KSPROPERTY_ITEM_IRP_STORAGE(Irp
);
321 PC_ASSERT(Descriptor
);
322 PC_ASSERT(Descriptor
->PortPin
);
323 PC_ASSERT_IRQL(DISPATCH_LEVEL
);
326 Pin
= (CPortPinWaveCyclic
*)Descriptor
->PortPin
;
329 PC_ASSERT(Pin
->m_Stream
);
331 if (Request
->Flags
& KSPROPERTY_TYPE_GET
)
333 // FIXME non multithreading-safe
334 // copy audio position
336 Position
= (PKSAUDIO_POSITION
)Data
;
338 if (Pin
->m_ConnectDetails
->Interface
.Id
== KSINTERFACE_STANDARD_STREAMING
)
340 RtlMoveMemory(Data
, &Pin
->m_Position
, sizeof(KSAUDIO_POSITION
));
341 DPRINT("Play %lu Record %lu\n", Pin
->m_Position
.PlayOffset
, Pin
->m_Position
.WriteOffset
);
343 else if (Pin
->m_ConnectDetails
->Interface
.Id
== KSINTERFACE_STANDARD_LOOPED_STREAMING
)
345 Position
->PlayOffset
= Pin
->m_Position
.PlayOffset
;
346 Position
->WriteOffset
= (ULONGLONG
)Pin
->m_IrpQueue
->GetCurrentIrpOffset();
347 DPRINT("Play %lu Write %lu\n", Position
->PlayOffset
, Position
->WriteOffset
);
351 Irp
->IoStatus
.Information
= sizeof(KSAUDIO_POSITION
);
352 return STATUS_SUCCESS
;
356 return STATUS_NOT_SUPPORTED
;
361 CPortPinWaveCyclic
*Pin
;
363 PIO_WORKITEM WorkItem
;
366 }SETPIN_CONTEXT
, *PSETPIN_CONTEXT
;
370 PinSetStateWorkerRoutine(
371 IN PDEVICE_OBJECT DeviceObject
,
374 PSETPIN_CONTEXT PinWorkContext
= (PSETPIN_CONTEXT
)Context
;
378 Status
= PinWorkContext
->Pin
->m_Stream
->SetState(PinWorkContext
->NewState
);
380 DPRINT1("Setting state %u %x\n", PinWorkContext
->NewState
, Status
);
381 if (NT_SUCCESS(Status
))
384 PinWorkContext
->Pin
->m_State
= PinWorkContext
->NewState
;
386 if (PinWorkContext
->Pin
->m_ConnectDetails
->Interface
.Id
== KSINTERFACE_STANDARD_LOOPED_STREAMING
&& PinWorkContext
->Pin
->m_State
== KSSTATE_STOP
)
388 /* FIXME complete pending irps with successfull state */
389 PinWorkContext
->Pin
->m_IrpQueue
->CancelBuffers();
392 //PinWorkContext->Pin->m_IrpQueue->CancelBuffers();
396 PinWorkContext
->Irp
->IoStatus
.Information
= sizeof(KSSTATE
);
397 PinWorkContext
->Irp
->IoStatus
.Status
= Status
;
400 IoCompleteRequest(PinWorkContext
->Irp
, IO_NO_INCREMENT
);
403 IoFreeWorkItem(PinWorkContext
->WorkItem
);
406 FreeItem(PinWorkContext
, TAG_PORTCLASS
);
415 IN PKSIDENTIFIER Request
,
418 NTSTATUS Status
= STATUS_UNSUCCESSFUL
;
419 CPortPinWaveCyclic
*Pin
;
420 PSUBDEVICE_DESCRIPTOR Descriptor
;
421 PKSSTATE State
= (PKSSTATE
)Data
;
423 // get sub device descriptor
424 Descriptor
= (PSUBDEVICE_DESCRIPTOR
)KSPROPERTY_ITEM_IRP_STORAGE(Irp
);
427 PC_ASSERT(Descriptor
);
428 PC_ASSERT(Descriptor
->PortPin
);
429 PC_ASSERT_IRQL(DISPATCH_LEVEL
);
432 Pin
= (CPortPinWaveCyclic
*)Descriptor
->PortPin
;
435 PC_ASSERT(Pin
->m_Stream
);
437 if (Request
->Flags
& KSPROPERTY_TYPE_SET
)
440 Status
= Pin
->m_Stream
->SetState(*State
);
442 DPRINT("Setting state %u %x\n", *State
, Status
);
443 if (NT_SUCCESS(Status
))
446 Pin
->m_State
= *State
;
448 if (Pin
->m_ConnectDetails
->Interface
.Id
== KSINTERFACE_STANDARD_LOOPED_STREAMING
&& Pin
->m_State
== KSSTATE_STOP
)
451 // complete with successful state
452 Pin
->m_IrpQueue
->CancelBuffers();
454 else if (Pin
->m_State
== KSSTATE_STOP
)
456 Pin
->m_IrpQueue
->CancelBuffers();
459 Irp
->IoStatus
.Information
= sizeof(KSSTATE
);
463 else if (Request
->Flags
& KSPROPERTY_TYPE_GET
)
465 // get current stream state
466 *State
= Pin
->m_State
;
468 Irp
->IoStatus
.Information
= sizeof(KSSTATE
);
470 return STATUS_SUCCESS
;
473 // unsupported request
474 return STATUS_NOT_SUPPORTED
;
479 PinWaveCyclicDataFormat(
481 IN PKSIDENTIFIER Request
,
484 NTSTATUS Status
= STATUS_UNSUCCESSFUL
;
485 CPortPinWaveCyclic
*Pin
;
486 PSUBDEVICE_DESCRIPTOR Descriptor
;
487 PIO_STACK_LOCATION IoStack
;
489 // get current irp stack location
490 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
492 // get sub device descriptor
493 Descriptor
= (PSUBDEVICE_DESCRIPTOR
)KSPROPERTY_ITEM_IRP_STORAGE(Irp
);
496 PC_ASSERT(Descriptor
);
497 PC_ASSERT(Descriptor
->PortPin
);
500 Pin
= (CPortPinWaveCyclic
*)Descriptor
->PortPin
;
503 PC_ASSERT(Pin
->m_Stream
);
504 PC_ASSERT(Pin
->m_Format
);
506 if (Request
->Flags
& KSPROPERTY_TYPE_SET
)
508 // try to change data format
509 PKSDATAFORMAT NewDataFormat
, DataFormat
= (PKSDATAFORMAT
)Irp
->UserBuffer
;
510 ULONG Size
= min(Pin
->m_Format
->FormatSize
, DataFormat
->FormatSize
);
512 if (RtlCompareMemory(DataFormat
, Pin
->m_Format
, Size
) == Size
)
514 // format is identical
515 Irp
->IoStatus
.Information
= DataFormat
->FormatSize
;
516 return STATUS_SUCCESS
;
519 // new change request
520 PC_ASSERT(Pin
->m_State
!= KSSTATE_RUN
);
521 // FIXME queue a work item when Irql != PASSIVE_LEVEL
522 PC_ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL
);
524 // allocate new data format
525 NewDataFormat
= (PKSDATAFORMAT
)AllocateItem(NonPagedPool
, DataFormat
->FormatSize
, TAG_PORTCLASS
);
529 return STATUS_NO_MEMORY
;
532 // copy new data format
533 RtlMoveMemory(NewDataFormat
, DataFormat
, DataFormat
->FormatSize
);
536 Status
= Pin
->m_Stream
->SetFormat(NewDataFormat
);
537 if (NT_SUCCESS(Status
))
540 FreeItem(Pin
->m_Format
, TAG_PORTCLASS
);
542 // update irp queue with new format
543 Pin
->m_IrpQueue
->UpdateFormat((PKSDATAFORMAT
)NewDataFormat
);
546 Pin
->m_Format
= NewDataFormat
;
547 Irp
->IoStatus
.Information
= NewDataFormat
->FormatSize
;
550 PC_ASSERT(NewDataFormat
->FormatSize
== sizeof(KSDATAFORMAT_WAVEFORMATEX
));
551 PC_ASSERT(IsEqualGUIDAligned(((PKSDATAFORMAT_WAVEFORMATEX
)NewDataFormat
)->DataFormat
.MajorFormat
, KSDATAFORMAT_TYPE_AUDIO
));
552 PC_ASSERT(IsEqualGUIDAligned(((PKSDATAFORMAT_WAVEFORMATEX
)NewDataFormat
)->DataFormat
.SubFormat
, KSDATAFORMAT_SUBTYPE_PCM
));
553 PC_ASSERT(IsEqualGUIDAligned(((PKSDATAFORMAT_WAVEFORMATEX
)NewDataFormat
)->DataFormat
.Specifier
, KSDATAFORMAT_SPECIFIER_WAVEFORMATEX
));
556 DPRINT("NewDataFormat: Channels %u Bits %u Samples %u\n", ((PKSDATAFORMAT_WAVEFORMATEX
)NewDataFormat
)->WaveFormatEx
.nChannels
,
557 ((PKSDATAFORMAT_WAVEFORMATEX
)NewDataFormat
)->WaveFormatEx
.wBitsPerSample
,
558 ((PKSDATAFORMAT_WAVEFORMATEX
)NewDataFormat
)->WaveFormatEx
.nSamplesPerSec
);
564 // failed to set format
565 FreeItem(NewDataFormat
, TAG_PORTCLASS
);
572 else if (Request
->Flags
& KSPROPERTY_TYPE_GET
)
574 // get current data format
575 PC_ASSERT(Pin
->m_Format
);
577 if (Pin
->m_Format
->FormatSize
> IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
)
580 Irp
->IoStatus
.Information
= Pin
->m_Format
->FormatSize
;
581 return STATUS_MORE_ENTRIES
;
584 RtlMoveMemory(Data
, Pin
->m_Format
, Pin
->m_Format
->FormatSize
);
586 Irp
->IoStatus
.Information
= Pin
->m_Format
->FormatSize
;
589 return STATUS_SUCCESS
;
592 // unsupported request
593 return STATUS_NOT_SUPPORTED
;
597 CPortPinWaveCyclic::GeneratePositionEvents(
598 IN ULONGLONG OldOffset
,
599 IN ULONGLONG NewOffset
)
602 PKSEVENT_ENTRY EventEntry
;
603 PLOOPEDSTREAMING_EVENT_CONTEXT Context
;
605 // acquire event lock
606 KeAcquireSpinLockAtDpcLevel(&m_EventListLock
);
608 // point to first entry
609 Entry
= m_EventList
.Flink
;
611 while(Entry
!= &m_EventList
)
614 EventEntry
= (PKSEVENT_ENTRY
)CONTAINING_RECORD(Entry
, KSEVENT_ENTRY
, ListEntry
);
616 // get event entry context
617 Context
= (PLOOPEDSTREAMING_EVENT_CONTEXT
)(EventEntry
+ 1);
619 if (Context
->bLoopedStreaming
== TRUE
)
621 if (NewOffset
> OldOffset
)
623 /* buffer progress no overlap */
624 if (OldOffset
< Context
->Position
&& Context
->Position
<= NewOffset
)
626 /* when someone eventually fixes sprintf... */
627 DPRINT("Generating event at OldOffset %I64u\n", OldOffset
);
628 DPRINT("Context->Position %I64u\n", Context
->Position
);
629 DPRINT("NewOffset %I64u\n", NewOffset
);
631 KsGenerateEvent(EventEntry
);
636 /* buffer wrap-arround */
637 if (OldOffset
< Context
->Position
|| NewOffset
> Context
->Position
)
639 /* when someone eventually fixes sprintf... */
640 DPRINT("Generating event at OldOffset %I64u\n", OldOffset
);
641 DPRINT("Context->Position %I64u\n", Context
->Position
);
642 DPRINT("NewOffset %I64u\n", NewOffset
);
644 KsGenerateEvent(EventEntry
);
649 // move to next entry
650 Entry
= Entry
->Flink
;
654 KeReleaseSpinLockFromDpcLevel(&m_EventListLock
);
658 CPortPinWaveCyclic::UpdateCommonBuffer(
660 ULONG MaxTransferCount
)
668 BufferLength
= Position
- m_CommonBufferOffset
;
669 BufferLength
= min(BufferLength
, MaxTransferCount
);
673 Status
= m_IrpQueue
->GetMapping(&Buffer
, &BufferSize
);
674 if (!NT_SUCCESS(Status
))
677 BytesToCopy
= min(BufferLength
, BufferSize
);
681 m_DmaChannel
->CopyFrom(Buffer
, (PUCHAR
)m_CommonBuffer
+ m_CommonBufferOffset
, BytesToCopy
);
685 m_DmaChannel
->CopyTo((PUCHAR
)m_CommonBuffer
+ m_CommonBufferOffset
, Buffer
, BytesToCopy
);
688 m_IrpQueue
->UpdateMapping(BytesToCopy
);
689 m_CommonBufferOffset
+= BytesToCopy
;
691 BufferLength
= Position
- m_CommonBufferOffset
;
692 m_Position
.PlayOffset
+= BytesToCopy
;
694 if (m_ConnectDetails
->Interface
.Id
== KSINTERFACE_STANDARD_LOOPED_STREAMING
)
696 // normalize position
697 m_Position
.PlayOffset
= m_Position
.PlayOffset
% m_Position
.WriteOffset
;
703 CPortPinWaveCyclic::UpdateCommonBufferOverlap(
705 ULONG MaxTransferCount
)
707 ULONG BufferLength
, Length
, Gap
;
714 BufferLength
= Gap
= m_CommonBufferSize
- m_CommonBufferOffset
;
715 BufferLength
= Length
= min(BufferLength
, MaxTransferCount
);
718 Status
= m_IrpQueue
->GetMapping(&Buffer
, &BufferSize
);
719 if (!NT_SUCCESS(Status
))
722 BytesToCopy
= min(BufferLength
, BufferSize
);
726 m_DmaChannel
->CopyFrom(Buffer
,
727 (PUCHAR
)m_CommonBuffer
+ m_CommonBufferOffset
,
732 m_DmaChannel
->CopyTo((PUCHAR
)m_CommonBuffer
+ m_CommonBufferOffset
,
737 m_IrpQueue
->UpdateMapping(BytesToCopy
);
738 m_CommonBufferOffset
+= BytesToCopy
;
739 m_Position
.PlayOffset
+= BytesToCopy
;
741 BufferLength
= m_CommonBufferSize
- m_CommonBufferOffset
;
743 if (m_ConnectDetails
->Interface
.Id
== KSINTERFACE_STANDARD_LOOPED_STREAMING
)
745 // normalize position
746 m_Position
.PlayOffset
= m_Position
.PlayOffset
% m_Position
.WriteOffset
;
753 m_CommonBufferOffset
= 0;
755 MaxTransferCount
-= Length
;
757 if (MaxTransferCount
)
759 UpdateCommonBuffer(Position
, MaxTransferCount
);
766 CPortPinWaveCyclic::RequestService()
772 ULONGLONG OldOffset
, NewOffset
;
774 PC_ASSERT_IRQL(DISPATCH_LEVEL
);
776 Status
= m_IrpQueue
->GetMapping(&Buffer
, &BufferSize
);
777 if (!NT_SUCCESS(Status
))
782 Status
= m_Stream
->GetPosition(&Position
);
783 DPRINT("Position %u Buffer %p BufferSize %u ActiveIrpOffset %u Capture %u\n", Position
, Buffer
, m_CommonBufferSize
, BufferSize
, m_Capture
);
785 OldOffset
= m_Position
.PlayOffset
;
787 if (Position
< m_CommonBufferOffset
)
789 UpdateCommonBufferOverlap(Position
, m_FrameSize
);
791 else if (Position
>= m_CommonBufferOffset
)
793 UpdateCommonBuffer(Position
, m_FrameSize
);
796 NewOffset
= m_Position
.PlayOffset
;
798 GeneratePositionEvents(OldOffset
, NewOffset
);
803 CPortPinWaveCyclic::NewIrpTarget(
804 OUT
struct IIrpTarget
**OutTarget
,
807 IN POOL_TYPE PoolType
,
808 IN PDEVICE_OBJECT DeviceObject
,
810 IN KSOBJECT_CREATE
*CreateObject
)
813 return STATUS_UNSUCCESSFUL
;
818 CPortPinWaveCyclic::DeviceIoControl(
819 IN PDEVICE_OBJECT DeviceObject
,
822 PIO_STACK_LOCATION IoStack
;
823 PKSPROPERTY Property
;
824 UNICODE_STRING GuidString
;
825 NTSTATUS Status
= STATUS_NOT_SUPPORTED
;
829 /* get current irp stack location */
830 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
832 if (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_KS_PROPERTY
)
834 /* handle property with subdevice descriptor */
835 Status
= PcHandlePropertyWithTable(Irp
, m_Descriptor
.FilterPropertySetCount
, m_Descriptor
.FilterPropertySet
, &m_Descriptor
);
837 if (Status
== STATUS_NOT_FOUND
)
839 Property
= (PKSPROPERTY
)IoStack
->Parameters
.DeviceIoControl
.Type3InputBuffer
;
841 RtlStringFromGUID(Property
->Set
, &GuidString
);
842 DPRINT("Unhandeled property Set |%S| Id %u Flags %x\n", GuidString
.Buffer
, Property
->Id
, Property
->Flags
);
843 RtlFreeUnicodeString(&GuidString
);
846 else if (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_KS_ENABLE_EVENT
)
848 Status
= PcHandleEnableEventWithTable(Irp
, &m_Descriptor
);
850 else if (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_KS_DISABLE_EVENT
)
852 Status
= PcHandleDisableEventWithTable(Irp
, &m_Descriptor
);
854 else if (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_KS_RESET_STATE
)
856 Status
= KsAcquireResetValue(Irp
, &ResetValue
);
857 DPRINT("Status %x Value %u\n", Status
, ResetValue
);
858 /* check for success */
859 if (NT_SUCCESS(Status
))
861 if (ResetValue
== KSRESET_BEGIN
)
863 m_IrpQueue
->CancelBuffers();
864 m_ResetState
= KSRESET_BEGIN
;
866 else if (ResetValue
== KSRESET_END
)
868 m_ResetState
= KSRESET_END
;
872 else if (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_KS_WRITE_STREAM
|| IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_KS_READ_STREAM
)
874 /* increment total number of packets */
875 InterlockedIncrement((PLONG
)&m_TotalPackets
);
877 DPRINT("New Packet Total %u State %x MinData %u\n", m_TotalPackets
, m_State
, m_IrpQueue
->NumData());
879 /* is the device not currently reset */
880 if (m_ResetState
== KSRESET_END
)
882 /* add the mapping */
883 Status
= m_IrpQueue
->AddMapping(Irp
, &Data
);
885 /* check for success */
886 if (NT_SUCCESS(Status
))
888 m_Position
.WriteOffset
+= Data
;
889 Status
= STATUS_PENDING
;
894 /* reset request is currently in progress */
895 Status
= STATUS_DEVICE_NOT_READY
;
896 DPRINT1("NotReady\n");
901 return KsDefaultDeviceIoCompletion(DeviceObject
, Irp
);
904 if (Status
!= STATUS_PENDING
)
906 Irp
->IoStatus
.Status
= Status
;
907 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
915 CPortPinWaveCyclic::Read(
916 IN PDEVICE_OBJECT DeviceObject
,
919 return KsDispatchInvalidDeviceRequest(DeviceObject
, Irp
);
924 CPortPinWaveCyclic::Write(
925 IN PDEVICE_OBJECT DeviceObject
,
928 return KsDispatchInvalidDeviceRequest(DeviceObject
, Irp
);
933 CPortPinWaveCyclic::Flush(
934 IN PDEVICE_OBJECT DeviceObject
,
937 return KsDispatchInvalidDeviceRequest(DeviceObject
, Irp
);
942 CPortPinWaveCyclic::Close(
943 IN PDEVICE_OBJECT DeviceObject
,
946 DPRINT("CPortPinWaveCyclic::Close entered\n");
948 PC_ASSERT_IRQL(PASSIVE_LEVEL
);
953 ExFreePool(m_Format
);
960 m_IrpQueue
->Release();
966 // release reference to port driver
973 // remove member from service group
974 m_ServiceGroup
->RemoveMember(PSERVICESINK(this));
975 m_ServiceGroup
= NULL
;
980 if (m_State
!= KSSTATE_STOP
)
983 NTSTATUS Status
= m_Stream
->SetState(KSSTATE_STOP
);
984 if (!NT_SUCCESS(Status
))
986 DPRINT("Warning: failed to stop stream with %x\n", Status
);
991 m_State
= KSSTATE_STOP
;
994 DPRINT("Closing stream at Irql %u\n", KeGetCurrentIrql());
1003 // release reference to filter instance
1004 m_Filter
->FreePin((PPORTPINWAVECYCLIC
)this);
1005 m_Filter
->Release();
1009 Irp
->IoStatus
.Information
= 0;
1010 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
1011 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1015 return STATUS_SUCCESS
;
1020 CPortPinWaveCyclic::QuerySecurity(
1021 IN PDEVICE_OBJECT DeviceObject
,
1024 return KsDispatchInvalidDeviceRequest(DeviceObject
, Irp
);
1029 CPortPinWaveCyclic::SetSecurity(
1030 IN PDEVICE_OBJECT DeviceObject
,
1033 return KsDispatchInvalidDeviceRequest(DeviceObject
, Irp
);
1038 CPortPinWaveCyclic::FastDeviceIoControl(
1039 IN PFILE_OBJECT FileObject
,
1041 IN PVOID InputBuffer
,
1042 IN ULONG InputBufferLength
,
1043 OUT PVOID OutputBuffer
,
1044 IN ULONG OutputBufferLength
,
1045 IN ULONG IoControlCode
,
1046 OUT PIO_STATUS_BLOCK StatusBlock
,
1047 IN PDEVICE_OBJECT DeviceObject
)
1049 return KsDispatchFastIoDeviceControlFailure(FileObject
, Wait
, InputBuffer
, InputBufferLength
, OutputBuffer
, OutputBufferLength
, IoControlCode
, StatusBlock
, DeviceObject
);
1055 CPortPinWaveCyclic::FastRead(
1056 IN PFILE_OBJECT FileObject
,
1057 IN PLARGE_INTEGER FileOffset
,
1062 OUT PIO_STATUS_BLOCK StatusBlock
,
1063 IN PDEVICE_OBJECT DeviceObject
)
1065 return KsDispatchFastReadFailure(FileObject
, FileOffset
, Length
, Wait
, LockKey
, Buffer
, StatusBlock
, DeviceObject
);
1071 CPortPinWaveCyclic::FastWrite(
1072 IN PFILE_OBJECT FileObject
,
1073 IN PLARGE_INTEGER FileOffset
,
1078 OUT PIO_STATUS_BLOCK StatusBlock
,
1079 IN PDEVICE_OBJECT DeviceObject
)
1081 return KsDispatchFastReadFailure(FileObject
, FileOffset
, Length
, Wait
, LockKey
, Buffer
, StatusBlock
, DeviceObject
);
1087 CPortPinWaveCyclic::Init(
1088 IN PPORTWAVECYCLIC Port
,
1089 IN PPORTFILTERWAVECYCLIC Filter
,
1090 IN KSPIN_CONNECT
* ConnectDetails
,
1091 IN KSPIN_DESCRIPTOR
* KsPinDescriptor
)
1094 PKSDATAFORMAT DataFormat
;
1095 PDEVICE_OBJECT DeviceObject
;
1097 PVOID SilenceBuffer
;
1098 PSUBDEVICE_DESCRIPTOR SubDeviceDescriptor
= NULL
;
1099 //IDrmAudioStream * DrmAudio = NULL;
1101 m_KsPinDescriptor
= KsPinDescriptor
;
1102 m_ConnectDetails
= ConnectDetails
;
1103 m_Miniport
= GetWaveCyclicMiniport(Port
);
1105 DeviceObject
= GetDeviceObject(Port
);
1107 DataFormat
= (PKSDATAFORMAT
)(ConnectDetails
+ 1);
1109 DPRINT("CPortPinWaveCyclic::Init entered Size %u\n", DataFormat
->FormatSize
);
1111 Status
= NewIrpQueue(&m_IrpQueue
);
1112 if (!NT_SUCCESS(Status
))
1115 if (KsPinDescriptor
->Communication
== KSPIN_COMMUNICATION_SINK
&& KsPinDescriptor
->DataFlow
== KSPIN_DATAFLOW_IN
)
1119 else if (KsPinDescriptor
->Communication
== KSPIN_COMMUNICATION_SINK
&& KsPinDescriptor
->DataFlow
== KSPIN_DATAFLOW_OUT
)
1125 DPRINT("Unexpected Communication %u DataFlow %u\n", KsPinDescriptor
->Communication
, KsPinDescriptor
->DataFlow
);
1131 Status
= m_Miniport
->NewStream(&m_Stream
,
1134 ConnectDetails
->PinId
,
1140 Status
= m_Stream
->QueryInterface(IID_IDrmAudioStream
, (PVOID
*)&DrmAudio
);
1141 if (NT_SUCCESS(Status
))
1143 DRMRIGHTS DrmRights
;
1144 DPRINT("Got IID_IDrmAudioStream interface %p\n", DrmAudio
);
1146 DrmRights
.CopyProtect
= FALSE
;
1147 DrmRights
.Reserved
= 0;
1148 DrmRights
.DigitalOutputDisable
= FALSE
;
1150 Status
= DrmAudio
->SetContentId(1, &DrmRights
);
1151 DPRINT("Status %x\n", Status
);
1155 DPRINT1("CPortPinWaveCyclic::Init Status %x PinId %u Capture %u\n", Status
, ConnectDetails
->PinId
, Capture
);
1156 DPRINT1("Bits %u Samples %u Channels %u Tag %u FrameSize %u\n", ((PKSDATAFORMAT_WAVEFORMATEX
)(DataFormat
))->WaveFormatEx
.wBitsPerSample
, ((PKSDATAFORMAT_WAVEFORMATEX
)(DataFormat
))->WaveFormatEx
.nSamplesPerSec
, ((PKSDATAFORMAT_WAVEFORMATEX
)(DataFormat
))->WaveFormatEx
.nChannels
, ((PKSDATAFORMAT_WAVEFORMATEX
)(DataFormat
))->WaveFormatEx
.wFormatTag
, m_FrameSize
);
1158 if (!NT_SUCCESS(Status
))
1161 ISubdevice
* Subdevice
= NULL
;
1162 // get subdevice interface
1163 Status
= Port
->QueryInterface(IID_ISubdevice
, (PVOID
*)&Subdevice
);
1165 if (!NT_SUCCESS(Status
))
1168 Status
= Subdevice
->GetDescriptor(&SubDeviceDescriptor
);
1169 if (!NT_SUCCESS(Status
))
1171 // failed to get descriptor
1172 Subdevice
->Release();
1176 /* initialize event management */
1177 InitializeListHead(&m_EventList
);
1178 KeInitializeSpinLock(&m_EventListLock
);
1180 /* set up subdevice descriptor */
1181 RtlZeroMemory(&m_Descriptor
, sizeof(SUBDEVICE_DESCRIPTOR
));
1182 m_Descriptor
.FilterPropertySet
= PinWaveCyclicPropertySet
;
1183 m_Descriptor
.FilterPropertySetCount
= sizeof(PinWaveCyclicPropertySet
) / sizeof(KSPROPERTY_SET
);
1184 m_Descriptor
.UnknownStream
= (PUNKNOWN
)m_Stream
;
1185 m_Descriptor
.DeviceDescriptor
= SubDeviceDescriptor
->DeviceDescriptor
;
1186 m_Descriptor
.UnknownMiniport
= SubDeviceDescriptor
->UnknownMiniport
;
1187 m_Descriptor
.PortPin
= (PVOID
)this;
1188 m_Descriptor
.EventSetCount
= sizeof(PinWaveCyclicEventSet
) / sizeof(KSEVENT_SET
);
1189 m_Descriptor
.EventSet
= PinWaveCyclicEventSet
;
1190 m_Descriptor
.EventList
= &m_EventList
;
1191 m_Descriptor
.EventListLock
= &m_EventListLock
;
1193 // initialize reset state
1194 m_ResetState
= KSRESET_END
;
1196 // release subdevice descriptor
1197 Subdevice
->Release();
1199 // add ourselves to service group
1200 Status
= m_ServiceGroup
->AddMember(PSERVICESINK(this));
1201 if (!NT_SUCCESS(Status
))
1203 DPRINT("Failed to add pin to service group\n");
1207 m_ServiceGroup
->SupportDelayedService();
1208 m_Stream
->SetState(KSSTATE_STOP
);
1209 m_State
= KSSTATE_STOP
;
1210 m_CommonBufferOffset
= 0;
1211 m_CommonBufferSize
= m_DmaChannel
->AllocatedBufferSize();
1212 m_CommonBuffer
= m_DmaChannel
->SystemAddress();
1213 m_Capture
= Capture
;
1214 // delay of 10 milisec
1215 m_Delay
= Int32x32To64(10, -10000);
1217 Status
= m_Stream
->SetNotificationFreq(10, &m_FrameSize
);
1219 SilenceBuffer
= AllocateItem(NonPagedPool
, m_FrameSize
, TAG_PORTCLASS
);
1221 return STATUS_INSUFFICIENT_RESOURCES
;
1224 /* set up allocator framing */
1225 m_AllocatorFraming
.RequirementsFlags
= KSALLOCATOR_REQUIREMENTF_SYSTEM_MEMORY
| KSALLOCATOR_REQUIREMENTF_PREFERENCES_ONLY
;
1226 m_AllocatorFraming
.PoolType
= NonPagedPool
;
1227 m_AllocatorFraming
.Frames
= 8;
1228 m_AllocatorFraming
.FileAlignment
= FILE_64_BYTE_ALIGNMENT
;
1229 m_AllocatorFraming
.Reserved
= 0;
1230 m_AllocatorFraming
.FrameSize
= m_FrameSize
;
1232 m_Stream
->Silence(SilenceBuffer
, m_FrameSize
);
1233 m_Stream
->Silence(m_CommonBuffer
, m_CommonBufferSize
);
1235 Status
= m_IrpQueue
->Init(ConnectDetails
, DataFormat
, DeviceObject
, m_FrameSize
, 0, SilenceBuffer
);
1236 if (!NT_SUCCESS(Status
))
1238 m_IrpQueue
->Release();
1242 m_Format
= (PKSDATAFORMAT
)AllocateItem(NonPagedPool
, DataFormat
->FormatSize
, TAG_PORTCLASS
);
1244 return STATUS_INSUFFICIENT_RESOURCES
;
1246 RtlMoveMemory(m_Format
, DataFormat
, DataFormat
->FormatSize
);
1254 //DPRINT("Setting state to acquire %x\n", m_Stream->SetState(KSSTATE_ACQUIRE));
1255 //DPRINT("Setting state to pause %x\n", m_Stream->SetState(KSSTATE_PAUSE));
1257 return STATUS_SUCCESS
;
1263 CPortPinWaveCyclic::GetCompletedPosition()
1272 CPortPinWaveCyclic::GetCycleCount()
1281 CPortPinWaveCyclic::GetDeviceBufferSize()
1283 return m_CommonBufferSize
;
1289 CPortPinWaveCyclic::GetIrpStream()
1291 return (PVOID
)m_IrpQueue
;
1297 CPortPinWaveCyclic::GetMiniport()
1299 return (PMINIPORT
)m_Miniport
;
1304 NewPortPinWaveCyclic(
1305 OUT IPortPinWaveCyclic
** OutPin
)
1307 CPortPinWaveCyclic
* This
;
1309 This
= new(NonPagedPool
, TAG_PORTCLASS
)CPortPinWaveCyclic(NULL
);
1311 return STATUS_INSUFFICIENT_RESOURCES
;
1316 *OutPin
= (IPortPinWaveCyclic
*)This
;
1318 return STATUS_SUCCESS
;