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
);
350 Irp
->IoStatus
.Information
= sizeof(KSAUDIO_POSITION
);
351 return STATUS_SUCCESS
;
355 return STATUS_NOT_SUPPORTED
;
360 CPortPinWaveCyclic
*Pin
;
362 PIO_WORKITEM WorkItem
;
365 }SETPIN_CONTEXT
, *PSETPIN_CONTEXT
;
369 PinSetStateWorkerRoutine(
370 IN PDEVICE_OBJECT DeviceObject
,
373 PSETPIN_CONTEXT PinWorkContext
= (PSETPIN_CONTEXT
)Context
;
377 Status
= PinWorkContext
->Pin
->m_Stream
->SetState(PinWorkContext
->NewState
);
379 DPRINT1("Setting state %u %x\n", PinWorkContext
->NewState
, Status
);
380 if (NT_SUCCESS(Status
))
383 PinWorkContext
->Pin
->m_State
= PinWorkContext
->NewState
;
385 if (PinWorkContext
->Pin
->m_ConnectDetails
->Interface
.Id
== KSINTERFACE_STANDARD_LOOPED_STREAMING
&& PinWorkContext
->Pin
->m_State
== KSSTATE_STOP
)
387 /* FIXME complete pending irps with successfull state */
388 PinWorkContext
->Pin
->m_IrpQueue
->CancelBuffers();
391 //PinWorkContext->Pin->m_IrpQueue->CancelBuffers();
395 PinWorkContext
->Irp
->IoStatus
.Information
= sizeof(KSSTATE
);
396 PinWorkContext
->Irp
->IoStatus
.Status
= Status
;
399 IoCompleteRequest(PinWorkContext
->Irp
, IO_NO_INCREMENT
);
402 IoFreeWorkItem(PinWorkContext
->WorkItem
);
405 FreeItem(PinWorkContext
, TAG_PORTCLASS
);
414 IN PKSIDENTIFIER Request
,
417 NTSTATUS Status
= STATUS_UNSUCCESSFUL
;
418 CPortPinWaveCyclic
*Pin
;
419 PSUBDEVICE_DESCRIPTOR Descriptor
;
420 PKSSTATE State
= (PKSSTATE
)Data
;
422 // get sub device descriptor
423 Descriptor
= (PSUBDEVICE_DESCRIPTOR
)KSPROPERTY_ITEM_IRP_STORAGE(Irp
);
426 PC_ASSERT(Descriptor
);
427 PC_ASSERT(Descriptor
->PortPin
);
428 PC_ASSERT_IRQL(DISPATCH_LEVEL
);
431 Pin
= (CPortPinWaveCyclic
*)Descriptor
->PortPin
;
434 PC_ASSERT(Pin
->m_Stream
);
436 if (Request
->Flags
& KSPROPERTY_TYPE_SET
)
439 Status
= Pin
->m_Stream
->SetState(*State
);
441 DPRINT("Setting state %u %x\n", *State
, Status
);
442 if (NT_SUCCESS(Status
))
445 Pin
->m_State
= *State
;
447 if (Pin
->m_ConnectDetails
->Interface
.Id
== KSINTERFACE_STANDARD_LOOPED_STREAMING
&& Pin
->m_State
== KSSTATE_STOP
)
450 // complete with successful state
451 Pin
->m_IrpQueue
->CancelBuffers();
452 Pin
->m_Position
.PlayOffset
= 0;
453 Pin
->m_Position
.WriteOffset
= 0;
455 else if (Pin
->m_State
== KSSTATE_STOP
)
457 Pin
->m_IrpQueue
->CancelBuffers();
458 Pin
->m_Position
.PlayOffset
= 0;
459 Pin
->m_Position
.WriteOffset
= 0;
462 Irp
->IoStatus
.Information
= sizeof(KSSTATE
);
466 else if (Request
->Flags
& KSPROPERTY_TYPE_GET
)
468 // get current stream state
469 *State
= Pin
->m_State
;
471 Irp
->IoStatus
.Information
= sizeof(KSSTATE
);
473 return STATUS_SUCCESS
;
476 // unsupported request
477 return STATUS_NOT_SUPPORTED
;
482 PinWaveCyclicDataFormat(
484 IN PKSIDENTIFIER Request
,
487 NTSTATUS Status
= STATUS_UNSUCCESSFUL
;
488 CPortPinWaveCyclic
*Pin
;
489 PSUBDEVICE_DESCRIPTOR Descriptor
;
490 PIO_STACK_LOCATION IoStack
;
492 // get current irp stack location
493 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
495 // get sub device descriptor
496 Descriptor
= (PSUBDEVICE_DESCRIPTOR
)KSPROPERTY_ITEM_IRP_STORAGE(Irp
);
499 PC_ASSERT(Descriptor
);
500 PC_ASSERT(Descriptor
->PortPin
);
503 Pin
= (CPortPinWaveCyclic
*)Descriptor
->PortPin
;
506 PC_ASSERT(Pin
->m_Stream
);
507 PC_ASSERT(Pin
->m_Format
);
509 if (Request
->Flags
& KSPROPERTY_TYPE_SET
)
511 // try to change data format
512 PKSDATAFORMAT NewDataFormat
, DataFormat
= (PKSDATAFORMAT
)Irp
->UserBuffer
;
513 ULONG Size
= min(Pin
->m_Format
->FormatSize
, DataFormat
->FormatSize
);
515 if (RtlCompareMemory(DataFormat
, Pin
->m_Format
, Size
) == Size
)
517 // format is identical
518 Irp
->IoStatus
.Information
= DataFormat
->FormatSize
;
519 return STATUS_SUCCESS
;
522 // new change request
523 PC_ASSERT(Pin
->m_State
!= KSSTATE_RUN
);
524 // FIXME queue a work item when Irql != PASSIVE_LEVEL
525 PC_ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL
);
527 // allocate new data format
528 NewDataFormat
= (PKSDATAFORMAT
)AllocateItem(NonPagedPool
, DataFormat
->FormatSize
, TAG_PORTCLASS
);
532 return STATUS_NO_MEMORY
;
535 // copy new data format
536 RtlMoveMemory(NewDataFormat
, DataFormat
, DataFormat
->FormatSize
);
539 Status
= Pin
->m_Stream
->SetFormat(NewDataFormat
);
540 if (NT_SUCCESS(Status
))
543 FreeItem(Pin
->m_Format
, TAG_PORTCLASS
);
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 if (m_Position
.WriteOffset
)
698 // normalize position
699 m_Position
.PlayOffset
= m_Position
.PlayOffset
% m_Position
.WriteOffset
;
706 CPortPinWaveCyclic::UpdateCommonBufferOverlap(
708 ULONG MaxTransferCount
)
710 ULONG BufferLength
, Length
, Gap
;
717 BufferLength
= Gap
= m_CommonBufferSize
- m_CommonBufferOffset
;
718 BufferLength
= Length
= min(BufferLength
, MaxTransferCount
);
721 Status
= m_IrpQueue
->GetMapping(&Buffer
, &BufferSize
);
722 if (!NT_SUCCESS(Status
))
725 BytesToCopy
= min(BufferLength
, BufferSize
);
729 m_DmaChannel
->CopyFrom(Buffer
,
730 (PUCHAR
)m_CommonBuffer
+ m_CommonBufferOffset
,
735 m_DmaChannel
->CopyTo((PUCHAR
)m_CommonBuffer
+ m_CommonBufferOffset
,
740 m_IrpQueue
->UpdateMapping(BytesToCopy
);
741 m_CommonBufferOffset
+= BytesToCopy
;
742 m_Position
.PlayOffset
+= BytesToCopy
;
744 BufferLength
= m_CommonBufferSize
- m_CommonBufferOffset
;
746 if (m_ConnectDetails
->Interface
.Id
== KSINTERFACE_STANDARD_LOOPED_STREAMING
)
748 if (m_Position
.WriteOffset
)
750 // normalize position
751 m_Position
.PlayOffset
= m_Position
.PlayOffset
% m_Position
.WriteOffset
;
759 m_CommonBufferOffset
= 0;
761 MaxTransferCount
-= Length
;
763 if (MaxTransferCount
)
765 UpdateCommonBuffer(Position
, MaxTransferCount
);
772 CPortPinWaveCyclic::RequestService()
778 ULONGLONG OldOffset
, NewOffset
;
780 PC_ASSERT_IRQL(DISPATCH_LEVEL
);
782 if (m_State
== KSSTATE_RUN
)
784 Status
= m_IrpQueue
->GetMapping(&Buffer
, &BufferSize
);
785 if (!NT_SUCCESS(Status
))
790 Status
= m_Stream
->GetPosition(&Position
);
791 DPRINT("Position %u Buffer %p BufferSize %u ActiveIrpOffset %u Capture %u\n", Position
, Buffer
, m_CommonBufferSize
, BufferSize
, m_Capture
);
793 OldOffset
= m_Position
.PlayOffset
;
795 if (Position
< m_CommonBufferOffset
)
797 UpdateCommonBufferOverlap(Position
, m_FrameSize
);
799 else if (Position
>= m_CommonBufferOffset
)
801 UpdateCommonBuffer(Position
, m_FrameSize
);
804 NewOffset
= m_Position
.PlayOffset
;
806 GeneratePositionEvents(OldOffset
, NewOffset
);
812 CPortPinWaveCyclic::NewIrpTarget(
813 OUT
struct IIrpTarget
**OutTarget
,
816 IN POOL_TYPE PoolType
,
817 IN PDEVICE_OBJECT DeviceObject
,
819 IN KSOBJECT_CREATE
*CreateObject
)
822 return STATUS_UNSUCCESSFUL
;
827 CPortPinWaveCyclic::DeviceIoControl(
828 IN PDEVICE_OBJECT DeviceObject
,
831 PIO_STACK_LOCATION IoStack
;
832 PKSPROPERTY Property
;
833 UNICODE_STRING GuidString
;
834 NTSTATUS Status
= STATUS_NOT_SUPPORTED
;
838 /* get current irp stack location */
839 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
841 if (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_KS_PROPERTY
)
843 /* handle property with subdevice descriptor */
844 Status
= PcHandlePropertyWithTable(Irp
, m_Descriptor
.FilterPropertySetCount
, m_Descriptor
.FilterPropertySet
, &m_Descriptor
);
846 if (Status
== STATUS_NOT_FOUND
)
848 Property
= (PKSPROPERTY
)IoStack
->Parameters
.DeviceIoControl
.Type3InputBuffer
;
850 RtlStringFromGUID(Property
->Set
, &GuidString
);
851 DPRINT("Unhandeled property Set |%S| Id %u Flags %x\n", GuidString
.Buffer
, Property
->Id
, Property
->Flags
);
852 RtlFreeUnicodeString(&GuidString
);
855 else if (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_KS_ENABLE_EVENT
)
857 Status
= PcHandleEnableEventWithTable(Irp
, &m_Descriptor
);
859 else if (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_KS_DISABLE_EVENT
)
861 Status
= PcHandleDisableEventWithTable(Irp
, &m_Descriptor
);
863 else if (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_KS_RESET_STATE
)
865 Status
= KsAcquireResetValue(Irp
, &ResetValue
);
866 DPRINT("Status %x Value %u\n", Status
, ResetValue
);
867 /* check for success */
868 if (NT_SUCCESS(Status
))
870 if (ResetValue
== KSRESET_BEGIN
)
872 m_IrpQueue
->CancelBuffers();
873 m_ResetState
= KSRESET_BEGIN
;
875 else if (ResetValue
== KSRESET_END
)
877 m_ResetState
= KSRESET_END
;
881 else if (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_KS_WRITE_STREAM
|| IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_KS_READ_STREAM
)
883 /* increment total number of packets */
884 InterlockedIncrement((PLONG
)&m_TotalPackets
);
886 DPRINT("New Packet Total %u State %x MinData %u\n", m_TotalPackets
, m_State
, m_IrpQueue
->NumData());
888 /* is the device not currently reset */
889 if (m_ResetState
== KSRESET_END
)
891 /* add the mapping */
892 Status
= m_IrpQueue
->AddMapping(Irp
, &Data
);
894 /* check for success */
895 if (NT_SUCCESS(Status
))
897 m_Position
.WriteOffset
+= Data
;
898 Status
= STATUS_PENDING
;
903 /* reset request is currently in progress */
904 Status
= STATUS_DEVICE_NOT_READY
;
905 DPRINT1("NotReady\n");
910 return KsDefaultDeviceIoCompletion(DeviceObject
, Irp
);
913 if (Status
!= STATUS_PENDING
)
915 Irp
->IoStatus
.Status
= Status
;
916 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
924 CPortPinWaveCyclic::Read(
925 IN PDEVICE_OBJECT DeviceObject
,
928 return KsDispatchInvalidDeviceRequest(DeviceObject
, Irp
);
933 CPortPinWaveCyclic::Write(
934 IN PDEVICE_OBJECT DeviceObject
,
937 return KsDispatchInvalidDeviceRequest(DeviceObject
, Irp
);
942 CPortPinWaveCyclic::Flush(
943 IN PDEVICE_OBJECT DeviceObject
,
946 return KsDispatchInvalidDeviceRequest(DeviceObject
, Irp
);
951 CPortPinWaveCyclic::Close(
952 IN PDEVICE_OBJECT DeviceObject
,
955 DPRINT("CPortPinWaveCyclic::Close entered\n");
957 PC_ASSERT_IRQL(PASSIVE_LEVEL
);
962 ExFreePool(m_Format
);
969 m_IrpQueue
->Release();
975 // release reference to port driver
982 // remove member from service group
983 m_ServiceGroup
->RemoveMember(PSERVICESINK(this));
984 m_ServiceGroup
= NULL
;
989 if (m_State
!= KSSTATE_STOP
)
992 NTSTATUS Status
= m_Stream
->SetState(KSSTATE_STOP
);
993 if (!NT_SUCCESS(Status
))
995 DPRINT("Warning: failed to stop stream with %x\n", Status
);
1000 m_State
= KSSTATE_STOP
;
1003 DPRINT("Closing stream at Irql %u\n", KeGetCurrentIrql());
1005 m_Stream
->Release();
1012 // release reference to filter instance
1013 m_Filter
->FreePin((PPORTPINWAVECYCLIC
)this);
1014 m_Filter
->Release();
1018 Irp
->IoStatus
.Information
= 0;
1019 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
1020 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1024 return STATUS_SUCCESS
;
1029 CPortPinWaveCyclic::QuerySecurity(
1030 IN PDEVICE_OBJECT DeviceObject
,
1033 return KsDispatchInvalidDeviceRequest(DeviceObject
, Irp
);
1038 CPortPinWaveCyclic::SetSecurity(
1039 IN PDEVICE_OBJECT DeviceObject
,
1042 return KsDispatchInvalidDeviceRequest(DeviceObject
, Irp
);
1047 CPortPinWaveCyclic::FastDeviceIoControl(
1048 IN PFILE_OBJECT FileObject
,
1050 IN PVOID InputBuffer
,
1051 IN ULONG InputBufferLength
,
1052 OUT PVOID OutputBuffer
,
1053 IN ULONG OutputBufferLength
,
1054 IN ULONG IoControlCode
,
1055 OUT PIO_STATUS_BLOCK StatusBlock
,
1056 IN PDEVICE_OBJECT DeviceObject
)
1058 return KsDispatchFastIoDeviceControlFailure(FileObject
, Wait
, InputBuffer
, InputBufferLength
, OutputBuffer
, OutputBufferLength
, IoControlCode
, StatusBlock
, DeviceObject
);
1064 CPortPinWaveCyclic::FastRead(
1065 IN PFILE_OBJECT FileObject
,
1066 IN PLARGE_INTEGER FileOffset
,
1071 OUT PIO_STATUS_BLOCK StatusBlock
,
1072 IN PDEVICE_OBJECT DeviceObject
)
1074 return KsDispatchFastReadFailure(FileObject
, FileOffset
, Length
, Wait
, LockKey
, Buffer
, StatusBlock
, DeviceObject
);
1080 CPortPinWaveCyclic::FastWrite(
1081 IN PFILE_OBJECT FileObject
,
1082 IN PLARGE_INTEGER FileOffset
,
1087 OUT PIO_STATUS_BLOCK StatusBlock
,
1088 IN PDEVICE_OBJECT DeviceObject
)
1090 return KsDispatchFastReadFailure(FileObject
, FileOffset
, Length
, Wait
, LockKey
, Buffer
, StatusBlock
, DeviceObject
);
1096 CPortPinWaveCyclic::Init(
1097 IN PPORTWAVECYCLIC Port
,
1098 IN PPORTFILTERWAVECYCLIC Filter
,
1099 IN KSPIN_CONNECT
* ConnectDetails
,
1100 IN KSPIN_DESCRIPTOR
* KsPinDescriptor
)
1103 PKSDATAFORMAT DataFormat
;
1104 PDEVICE_OBJECT DeviceObject
;
1106 PVOID SilenceBuffer
;
1107 PSUBDEVICE_DESCRIPTOR SubDeviceDescriptor
= NULL
;
1108 //IDrmAudioStream * DrmAudio = NULL;
1110 m_KsPinDescriptor
= KsPinDescriptor
;
1111 m_ConnectDetails
= ConnectDetails
;
1112 m_Miniport
= GetWaveCyclicMiniport(Port
);
1114 DeviceObject
= GetDeviceObject(Port
);
1116 DataFormat
= (PKSDATAFORMAT
)(ConnectDetails
+ 1);
1118 DPRINT("CPortPinWaveCyclic::Init entered Size %u\n", DataFormat
->FormatSize
);
1120 Status
= NewIrpQueue(&m_IrpQueue
);
1121 if (!NT_SUCCESS(Status
))
1124 if (KsPinDescriptor
->Communication
== KSPIN_COMMUNICATION_SINK
&& KsPinDescriptor
->DataFlow
== KSPIN_DATAFLOW_IN
)
1128 else if (KsPinDescriptor
->Communication
== KSPIN_COMMUNICATION_SINK
&& KsPinDescriptor
->DataFlow
== KSPIN_DATAFLOW_OUT
)
1134 DPRINT("Unexpected Communication %u DataFlow %u\n", KsPinDescriptor
->Communication
, KsPinDescriptor
->DataFlow
);
1140 Status
= m_Miniport
->NewStream(&m_Stream
,
1143 ConnectDetails
->PinId
,
1149 Status
= m_Stream
->QueryInterface(IID_IDrmAudioStream
, (PVOID
*)&DrmAudio
);
1150 if (NT_SUCCESS(Status
))
1152 DRMRIGHTS DrmRights
;
1153 DPRINT("Got IID_IDrmAudioStream interface %p\n", DrmAudio
);
1155 DrmRights
.CopyProtect
= FALSE
;
1156 DrmRights
.Reserved
= 0;
1157 DrmRights
.DigitalOutputDisable
= FALSE
;
1159 Status
= DrmAudio
->SetContentId(1, &DrmRights
);
1160 DPRINT("Status %x\n", Status
);
1164 DPRINT1("CPortPinWaveCyclic::Init Status %x PinId %u Capture %u\n", Status
, ConnectDetails
->PinId
, Capture
);
1165 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
);
1167 if (!NT_SUCCESS(Status
))
1170 ISubdevice
* Subdevice
= NULL
;
1171 // get subdevice interface
1172 Status
= Port
->QueryInterface(IID_ISubdevice
, (PVOID
*)&Subdevice
);
1174 if (!NT_SUCCESS(Status
))
1177 Status
= Subdevice
->GetDescriptor(&SubDeviceDescriptor
);
1178 if (!NT_SUCCESS(Status
))
1180 // failed to get descriptor
1181 Subdevice
->Release();
1185 /* initialize event management */
1186 InitializeListHead(&m_EventList
);
1187 KeInitializeSpinLock(&m_EventListLock
);
1189 /* set up subdevice descriptor */
1190 RtlZeroMemory(&m_Descriptor
, sizeof(SUBDEVICE_DESCRIPTOR
));
1191 m_Descriptor
.FilterPropertySet
= PinWaveCyclicPropertySet
;
1192 m_Descriptor
.FilterPropertySetCount
= sizeof(PinWaveCyclicPropertySet
) / sizeof(KSPROPERTY_SET
);
1193 m_Descriptor
.UnknownStream
= (PUNKNOWN
)m_Stream
;
1194 m_Descriptor
.DeviceDescriptor
= SubDeviceDescriptor
->DeviceDescriptor
;
1195 m_Descriptor
.UnknownMiniport
= SubDeviceDescriptor
->UnknownMiniport
;
1196 m_Descriptor
.PortPin
= (PVOID
)this;
1197 m_Descriptor
.EventSetCount
= sizeof(PinWaveCyclicEventSet
) / sizeof(KSEVENT_SET
);
1198 m_Descriptor
.EventSet
= PinWaveCyclicEventSet
;
1199 m_Descriptor
.EventList
= &m_EventList
;
1200 m_Descriptor
.EventListLock
= &m_EventListLock
;
1202 // initialize reset state
1203 m_ResetState
= KSRESET_END
;
1205 // release subdevice descriptor
1206 Subdevice
->Release();
1208 // add ourselves to service group
1209 Status
= m_ServiceGroup
->AddMember(PSERVICESINK(this));
1210 if (!NT_SUCCESS(Status
))
1212 DPRINT("Failed to add pin to service group\n");
1216 m_Stream
->SetState(KSSTATE_STOP
);
1217 m_State
= KSSTATE_STOP
;
1218 m_CommonBufferOffset
= 0;
1219 m_CommonBufferSize
= m_DmaChannel
->AllocatedBufferSize();
1220 m_CommonBuffer
= m_DmaChannel
->SystemAddress();
1221 m_Capture
= Capture
;
1222 // delay of 10 milisec
1223 m_Delay
= Int32x32To64(10, -10000);
1225 Status
= m_Stream
->SetNotificationFreq(10, &m_FrameSize
);
1226 PC_ASSERT(NT_SUCCESS(Status
));
1227 PC_ASSERT(m_FrameSize
);
1229 SilenceBuffer
= AllocateItem(NonPagedPool
, m_FrameSize
, TAG_PORTCLASS
);
1231 return STATUS_INSUFFICIENT_RESOURCES
;
1234 /* set up allocator framing */
1235 m_AllocatorFraming
.RequirementsFlags
= KSALLOCATOR_REQUIREMENTF_SYSTEM_MEMORY
| KSALLOCATOR_REQUIREMENTF_PREFERENCES_ONLY
;
1236 m_AllocatorFraming
.PoolType
= NonPagedPool
;
1237 m_AllocatorFraming
.Frames
= 8;
1238 m_AllocatorFraming
.FileAlignment
= FILE_64_BYTE_ALIGNMENT
;
1239 m_AllocatorFraming
.Reserved
= 0;
1240 m_AllocatorFraming
.FrameSize
= m_FrameSize
;
1242 m_Stream
->Silence(SilenceBuffer
, m_FrameSize
);
1243 m_Stream
->Silence(m_CommonBuffer
, m_CommonBufferSize
);
1245 Status
= m_IrpQueue
->Init(ConnectDetails
, m_FrameSize
, 0, SilenceBuffer
);
1246 if (!NT_SUCCESS(Status
))
1248 m_IrpQueue
->Release();
1252 m_Format
= (PKSDATAFORMAT
)AllocateItem(NonPagedPool
, DataFormat
->FormatSize
, TAG_PORTCLASS
);
1254 return STATUS_INSUFFICIENT_RESOURCES
;
1256 RtlMoveMemory(m_Format
, DataFormat
, DataFormat
->FormatSize
);
1264 //DPRINT("Setting state to acquire %x\n", m_Stream->SetState(KSSTATE_ACQUIRE));
1265 //DPRINT("Setting state to pause %x\n", m_Stream->SetState(KSSTATE_PAUSE));
1267 return STATUS_SUCCESS
;
1273 CPortPinWaveCyclic::GetCompletedPosition()
1282 CPortPinWaveCyclic::GetCycleCount()
1291 CPortPinWaveCyclic::GetDeviceBufferSize()
1293 return m_CommonBufferSize
;
1299 CPortPinWaveCyclic::GetIrpStream()
1301 return (PVOID
)m_IrpQueue
;
1307 CPortPinWaveCyclic::GetMiniport()
1309 return (PMINIPORT
)m_Miniport
;
1314 NewPortPinWaveCyclic(
1315 OUT IPortPinWaveCyclic
** OutPin
)
1317 CPortPinWaveCyclic
* This
;
1319 This
= new(NonPagedPool
, TAG_PORTCLASS
)CPortPinWaveCyclic(NULL
);
1321 return STATUS_INSUFFICIENT_RESOURCES
;
1326 *OutPin
= (IPortPinWaveCyclic
*)This
;
1328 return STATUS_SUCCESS
;