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();
455 Irp
->IoStatus
.Information
= sizeof(KSSTATE
);
458 else if (Request
->Flags
& KSPROPERTY_TYPE_GET
)
460 // get current stream state
461 *State
= Pin
->m_State
;
463 Irp
->IoStatus
.Information
= sizeof(KSSTATE
);
465 return STATUS_SUCCESS
;
468 // unsupported request
469 return STATUS_NOT_SUPPORTED
;
474 PinWaveCyclicDataFormat(
476 IN PKSIDENTIFIER Request
,
479 NTSTATUS Status
= STATUS_UNSUCCESSFUL
;
480 CPortPinWaveCyclic
*Pin
;
481 PSUBDEVICE_DESCRIPTOR Descriptor
;
482 PIO_STACK_LOCATION IoStack
;
484 // get current irp stack location
485 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
487 // get sub device descriptor
488 Descriptor
= (PSUBDEVICE_DESCRIPTOR
)KSPROPERTY_ITEM_IRP_STORAGE(Irp
);
491 PC_ASSERT(Descriptor
);
492 PC_ASSERT(Descriptor
->PortPin
);
495 Pin
= (CPortPinWaveCyclic
*)Descriptor
->PortPin
;
498 PC_ASSERT(Pin
->m_Stream
);
499 PC_ASSERT(Pin
->m_Format
);
501 if (Request
->Flags
& KSPROPERTY_TYPE_SET
)
503 // try to change data format
504 PKSDATAFORMAT NewDataFormat
, DataFormat
= (PKSDATAFORMAT
)Irp
->UserBuffer
;
505 ULONG Size
= min(Pin
->m_Format
->FormatSize
, DataFormat
->FormatSize
);
507 if (RtlCompareMemory(DataFormat
, Pin
->m_Format
, Size
) == Size
)
509 // format is identical
510 Irp
->IoStatus
.Information
= DataFormat
->FormatSize
;
511 return STATUS_SUCCESS
;
514 // new change request
515 PC_ASSERT(Pin
->m_State
!= KSSTATE_RUN
);
516 // FIXME queue a work item when Irql != PASSIVE_LEVEL
517 PC_ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL
);
519 // allocate new data format
520 NewDataFormat
= (PKSDATAFORMAT
)AllocateItem(NonPagedPool
, DataFormat
->FormatSize
, TAG_PORTCLASS
);
524 return STATUS_NO_MEMORY
;
527 // copy new data format
528 RtlMoveMemory(NewDataFormat
, DataFormat
, DataFormat
->FormatSize
);
531 Status
= Pin
->m_Stream
->SetFormat(NewDataFormat
);
532 if (NT_SUCCESS(Status
))
535 FreeItem(Pin
->m_Format
, TAG_PORTCLASS
);
537 // update irp queue with new format
538 Pin
->m_IrpQueue
->UpdateFormat((PKSDATAFORMAT
)NewDataFormat
);
541 Pin
->m_Format
= NewDataFormat
;
542 Irp
->IoStatus
.Information
= NewDataFormat
->FormatSize
;
545 PC_ASSERT(NewDataFormat
->FormatSize
== sizeof(KSDATAFORMAT_WAVEFORMATEX
));
546 PC_ASSERT(IsEqualGUIDAligned(((PKSDATAFORMAT_WAVEFORMATEX
)NewDataFormat
)->DataFormat
.MajorFormat
, KSDATAFORMAT_TYPE_AUDIO
));
547 PC_ASSERT(IsEqualGUIDAligned(((PKSDATAFORMAT_WAVEFORMATEX
)NewDataFormat
)->DataFormat
.SubFormat
, KSDATAFORMAT_SUBTYPE_PCM
));
548 PC_ASSERT(IsEqualGUIDAligned(((PKSDATAFORMAT_WAVEFORMATEX
)NewDataFormat
)->DataFormat
.Specifier
, KSDATAFORMAT_SPECIFIER_WAVEFORMATEX
));
551 DPRINT("NewDataFormat: Channels %u Bits %u Samples %u\n", ((PKSDATAFORMAT_WAVEFORMATEX
)NewDataFormat
)->WaveFormatEx
.nChannels
,
552 ((PKSDATAFORMAT_WAVEFORMATEX
)NewDataFormat
)->WaveFormatEx
.wBitsPerSample
,
553 ((PKSDATAFORMAT_WAVEFORMATEX
)NewDataFormat
)->WaveFormatEx
.nSamplesPerSec
);
559 // failed to set format
560 FreeItem(NewDataFormat
, TAG_PORTCLASS
);
567 else if (Request
->Flags
& KSPROPERTY_TYPE_GET
)
569 // get current data format
570 PC_ASSERT(Pin
->m_Format
);
572 if (Pin
->m_Format
->FormatSize
> IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
)
575 Irp
->IoStatus
.Information
= Pin
->m_Format
->FormatSize
;
576 return STATUS_MORE_ENTRIES
;
579 RtlMoveMemory(Data
, Pin
->m_Format
, Pin
->m_Format
->FormatSize
);
581 Irp
->IoStatus
.Information
= Pin
->m_Format
->FormatSize
;
584 return STATUS_SUCCESS
;
587 // unsupported request
588 return STATUS_NOT_SUPPORTED
;
592 CPortPinWaveCyclic::GeneratePositionEvents(
593 IN ULONGLONG OldOffset
,
594 IN ULONGLONG NewOffset
)
597 PKSEVENT_ENTRY EventEntry
;
598 PLOOPEDSTREAMING_EVENT_CONTEXT Context
;
600 // acquire event lock
601 KeAcquireSpinLockAtDpcLevel(&m_EventListLock
);
603 // point to first entry
604 Entry
= m_EventList
.Flink
;
606 while(Entry
!= &m_EventList
)
609 EventEntry
= (PKSEVENT_ENTRY
)CONTAINING_RECORD(Entry
, KSEVENT_ENTRY
, ListEntry
);
611 // get event entry context
612 Context
= (PLOOPEDSTREAMING_EVENT_CONTEXT
)(EventEntry
+ 1);
614 if (Context
->bLoopedStreaming
== TRUE
)
616 if (NewOffset
> OldOffset
)
618 /* buffer progress no overlap */
619 if (OldOffset
< Context
->Position
&& Context
->Position
<= NewOffset
)
621 /* when someone eventually fixes sprintf... */
622 DPRINT("Generating event at OldOffset %I64u\n", OldOffset
);
623 DPRINT("Context->Position %I64u\n", Context
->Position
);
624 DPRINT("NewOffset %I64u\n", NewOffset
);
626 KsGenerateEvent(EventEntry
);
631 /* buffer wrap-arround */
632 if (OldOffset
< Context
->Position
|| NewOffset
> Context
->Position
)
634 /* when someone eventually fixes sprintf... */
635 DPRINT("Generating event at OldOffset %I64u\n", OldOffset
);
636 DPRINT("Context->Position %I64u\n", Context
->Position
);
637 DPRINT("NewOffset %I64u\n", NewOffset
);
639 KsGenerateEvent(EventEntry
);
644 // move to next entry
645 Entry
= Entry
->Flink
;
649 KeReleaseSpinLockFromDpcLevel(&m_EventListLock
);
653 CPortPinWaveCyclic::UpdateCommonBuffer(
655 ULONG MaxTransferCount
)
663 BufferLength
= Position
- m_CommonBufferOffset
;
664 BufferLength
= min(BufferLength
, MaxTransferCount
);
668 Status
= m_IrpQueue
->GetMapping(&Buffer
, &BufferSize
);
669 if (!NT_SUCCESS(Status
))
672 BytesToCopy
= min(BufferLength
, BufferSize
);
676 m_DmaChannel
->CopyFrom(Buffer
, (PUCHAR
)m_CommonBuffer
+ m_CommonBufferOffset
, BytesToCopy
);
680 m_DmaChannel
->CopyTo((PUCHAR
)m_CommonBuffer
+ m_CommonBufferOffset
, Buffer
, BytesToCopy
);
683 m_IrpQueue
->UpdateMapping(BytesToCopy
);
684 m_CommonBufferOffset
+= BytesToCopy
;
686 BufferLength
= Position
- m_CommonBufferOffset
;
687 m_Position
.PlayOffset
+= BytesToCopy
;
689 if (m_ConnectDetails
->Interface
.Id
== KSINTERFACE_STANDARD_LOOPED_STREAMING
)
691 // normalize position
692 m_Position
.PlayOffset
= m_Position
.PlayOffset
% m_Position
.WriteOffset
;
698 CPortPinWaveCyclic::UpdateCommonBufferOverlap(
700 ULONG MaxTransferCount
)
702 ULONG BufferLength
, Length
, Gap
;
709 BufferLength
= Gap
= m_CommonBufferSize
- m_CommonBufferOffset
;
710 BufferLength
= Length
= min(BufferLength
, MaxTransferCount
);
713 Status
= m_IrpQueue
->GetMapping(&Buffer
, &BufferSize
);
714 if (!NT_SUCCESS(Status
))
717 BytesToCopy
= min(BufferLength
, BufferSize
);
721 m_DmaChannel
->CopyFrom(Buffer
,
722 (PUCHAR
)m_CommonBuffer
+ m_CommonBufferOffset
,
727 m_DmaChannel
->CopyTo((PUCHAR
)m_CommonBuffer
+ m_CommonBufferOffset
,
732 m_IrpQueue
->UpdateMapping(BytesToCopy
);
733 m_CommonBufferOffset
+= BytesToCopy
;
734 m_Position
.PlayOffset
+= BytesToCopy
;
736 BufferLength
= m_CommonBufferSize
- m_CommonBufferOffset
;
738 if (m_ConnectDetails
->Interface
.Id
== KSINTERFACE_STANDARD_LOOPED_STREAMING
)
740 // normalize position
741 m_Position
.PlayOffset
= m_Position
.PlayOffset
% m_Position
.WriteOffset
;
748 m_CommonBufferOffset
= 0;
750 MaxTransferCount
-= Length
;
752 if (MaxTransferCount
)
754 UpdateCommonBuffer(Position
, MaxTransferCount
);
761 CPortPinWaveCyclic::RequestService()
767 ULONGLONG OldOffset
, NewOffset
;
769 PC_ASSERT_IRQL(DISPATCH_LEVEL
);
771 Status
= m_IrpQueue
->GetMapping(&Buffer
, &BufferSize
);
772 if (!NT_SUCCESS(Status
))
777 Status
= m_Stream
->GetPosition(&Position
);
778 DPRINT("Position %u Buffer %p BufferSize %u ActiveIrpOffset %u Capture %u\n", Position
, Buffer
, m_CommonBufferSize
, BufferSize
, m_Capture
);
780 OldOffset
= m_Position
.PlayOffset
;
782 if (Position
< m_CommonBufferOffset
)
784 UpdateCommonBufferOverlap(Position
, m_FrameSize
);
786 else if (Position
>= m_CommonBufferOffset
)
788 UpdateCommonBuffer(Position
, m_FrameSize
);
791 NewOffset
= m_Position
.PlayOffset
;
793 GeneratePositionEvents(OldOffset
, NewOffset
);
798 CPortPinWaveCyclic::NewIrpTarget(
799 OUT
struct IIrpTarget
**OutTarget
,
802 IN POOL_TYPE PoolType
,
803 IN PDEVICE_OBJECT DeviceObject
,
805 IN KSOBJECT_CREATE
*CreateObject
)
808 return STATUS_UNSUCCESSFUL
;
813 CPortPinWaveCyclic::DeviceIoControl(
814 IN PDEVICE_OBJECT DeviceObject
,
817 PIO_STACK_LOCATION IoStack
;
818 PKSPROPERTY Property
;
819 UNICODE_STRING GuidString
;
820 NTSTATUS Status
= STATUS_NOT_SUPPORTED
;
824 /* get current irp stack location */
825 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
827 if (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_KS_PROPERTY
)
829 /* handle property with subdevice descriptor */
830 Status
= PcHandlePropertyWithTable(Irp
, m_Descriptor
.FilterPropertySetCount
, m_Descriptor
.FilterPropertySet
, &m_Descriptor
);
832 if (Status
== STATUS_NOT_FOUND
)
834 Property
= (PKSPROPERTY
)IoStack
->Parameters
.DeviceIoControl
.Type3InputBuffer
;
836 RtlStringFromGUID(Property
->Set
, &GuidString
);
837 DPRINT("Unhandeled property Set |%S| Id %u Flags %x\n", GuidString
.Buffer
, Property
->Id
, Property
->Flags
);
838 RtlFreeUnicodeString(&GuidString
);
841 else if (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_KS_ENABLE_EVENT
)
843 Status
= PcHandleEnableEventWithTable(Irp
, &m_Descriptor
);
845 else if (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_KS_DISABLE_EVENT
)
847 Status
= PcHandleDisableEventWithTable(Irp
, &m_Descriptor
);
849 else if (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_KS_RESET_STATE
)
852 Status
= KsAcquireResetValue(Irp
, &ResetValue
);
853 DPRINT("Status %x Value %u\n", Status
, ResetValue
);
854 /* check for success */
855 if (NT_SUCCESS(Status
))
857 if (ResetValue
== KSRESET_BEGIN
)
859 m_IrpQueue
->CancelBuffers();
860 m_ResetState
= KSRESET_BEGIN
;
862 else if (ResetValue
== KSRESET_END
)
864 m_ResetState
= KSRESET_END
;
868 else if (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_KS_WRITE_STREAM
|| IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_KS_READ_STREAM
)
870 /* increment total number of packets */
871 InterlockedIncrement((PLONG
)&m_TotalPackets
);
873 DPRINT("New Packet Total %u State %x MinData %u\n", m_TotalPackets
, m_State
, m_IrpQueue
->NumData());
875 /* is the device not currently reset */
876 if (m_ResetState
== KSRESET_END
)
878 /* add the mapping */
879 Status
= m_IrpQueue
->AddMapping(Irp
, &Data
);
881 /* check for success */
882 if (NT_SUCCESS(Status
))
884 m_Position
.WriteOffset
+= Data
;
885 Status
= STATUS_PENDING
;
890 /* reset request is currently in progress */
891 Status
= STATUS_DEVICE_NOT_READY
;
892 DPRINT1("NotReady\n");
897 return KsDefaultDeviceIoCompletion(DeviceObject
, Irp
);
900 if (Status
!= STATUS_PENDING
)
902 Irp
->IoStatus
.Status
= Status
;
903 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
911 CPortPinWaveCyclic::Read(
912 IN PDEVICE_OBJECT DeviceObject
,
915 return KsDispatchInvalidDeviceRequest(DeviceObject
, Irp
);
920 CPortPinWaveCyclic::Write(
921 IN PDEVICE_OBJECT DeviceObject
,
924 return KsDispatchInvalidDeviceRequest(DeviceObject
, Irp
);
929 CPortPinWaveCyclic::Flush(
930 IN PDEVICE_OBJECT DeviceObject
,
933 return KsDispatchInvalidDeviceRequest(DeviceObject
, Irp
);
938 CPortPinWaveCyclic::Close(
939 IN PDEVICE_OBJECT DeviceObject
,
942 DPRINT("CPortPinWaveCyclic::Close entered\n");
944 PC_ASSERT_IRQL(PASSIVE_LEVEL
);
949 ExFreePool(m_Format
);
956 m_IrpQueue
->Release();
962 // release reference to port driver
969 // remove member from service group
970 m_ServiceGroup
->RemoveMember(PSERVICESINK(this));
971 m_ServiceGroup
= NULL
;
976 if (m_State
!= KSSTATE_STOP
)
979 NTSTATUS Status
= m_Stream
->SetState(KSSTATE_STOP
);
980 if (!NT_SUCCESS(Status
))
982 DPRINT("Warning: failed to stop stream with %x\n", Status
);
987 m_State
= KSSTATE_STOP
;
990 DPRINT("Closing stream at Irql %u\n", KeGetCurrentIrql());
999 // release reference to filter instance
1000 m_Filter
->FreePin((PPORTPINWAVECYCLIC
)this);
1001 m_Filter
->Release();
1005 Irp
->IoStatus
.Information
= 0;
1006 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
1007 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1011 return STATUS_SUCCESS
;
1016 CPortPinWaveCyclic::QuerySecurity(
1017 IN PDEVICE_OBJECT DeviceObject
,
1020 return KsDispatchInvalidDeviceRequest(DeviceObject
, Irp
);
1025 CPortPinWaveCyclic::SetSecurity(
1026 IN PDEVICE_OBJECT DeviceObject
,
1029 return KsDispatchInvalidDeviceRequest(DeviceObject
, Irp
);
1034 CPortPinWaveCyclic::FastDeviceIoControl(
1035 IN PFILE_OBJECT FileObject
,
1037 IN PVOID InputBuffer
,
1038 IN ULONG InputBufferLength
,
1039 OUT PVOID OutputBuffer
,
1040 IN ULONG OutputBufferLength
,
1041 IN ULONG IoControlCode
,
1042 OUT PIO_STATUS_BLOCK StatusBlock
,
1043 IN PDEVICE_OBJECT DeviceObject
)
1045 return KsDispatchFastIoDeviceControlFailure(FileObject
, Wait
, InputBuffer
, InputBufferLength
, OutputBuffer
, OutputBufferLength
, IoControlCode
, StatusBlock
, DeviceObject
);
1051 CPortPinWaveCyclic::FastRead(
1052 IN PFILE_OBJECT FileObject
,
1053 IN PLARGE_INTEGER FileOffset
,
1058 OUT PIO_STATUS_BLOCK StatusBlock
,
1059 IN PDEVICE_OBJECT DeviceObject
)
1061 return KsDispatchFastReadFailure(FileObject
, FileOffset
, Length
, Wait
, LockKey
, Buffer
, StatusBlock
, DeviceObject
);
1067 CPortPinWaveCyclic::FastWrite(
1068 IN PFILE_OBJECT FileObject
,
1069 IN PLARGE_INTEGER FileOffset
,
1074 OUT PIO_STATUS_BLOCK StatusBlock
,
1075 IN PDEVICE_OBJECT DeviceObject
)
1077 return KsDispatchFastReadFailure(FileObject
, FileOffset
, Length
, Wait
, LockKey
, Buffer
, StatusBlock
, DeviceObject
);
1083 CPortPinWaveCyclic::Init(
1084 IN PPORTWAVECYCLIC Port
,
1085 IN PPORTFILTERWAVECYCLIC Filter
,
1086 IN KSPIN_CONNECT
* ConnectDetails
,
1087 IN KSPIN_DESCRIPTOR
* KsPinDescriptor
)
1090 PKSDATAFORMAT DataFormat
;
1091 PDEVICE_OBJECT DeviceObject
;
1093 PVOID SilenceBuffer
;
1094 PSUBDEVICE_DESCRIPTOR SubDeviceDescriptor
= NULL
;
1095 //IDrmAudioStream * DrmAudio = NULL;
1097 m_KsPinDescriptor
= KsPinDescriptor
;
1098 m_ConnectDetails
= ConnectDetails
;
1099 m_Miniport
= GetWaveCyclicMiniport(Port
);
1101 DeviceObject
= GetDeviceObject(Port
);
1103 DataFormat
= (PKSDATAFORMAT
)(ConnectDetails
+ 1);
1105 DPRINT("CPortPinWaveCyclic::Init entered Size %u\n", DataFormat
->FormatSize
);
1107 Status
= NewIrpQueue(&m_IrpQueue
);
1108 if (!NT_SUCCESS(Status
))
1111 if (KsPinDescriptor
->Communication
== KSPIN_COMMUNICATION_SINK
&& KsPinDescriptor
->DataFlow
== KSPIN_DATAFLOW_IN
)
1115 else if (KsPinDescriptor
->Communication
== KSPIN_COMMUNICATION_SINK
&& KsPinDescriptor
->DataFlow
== KSPIN_DATAFLOW_OUT
)
1121 DPRINT("Unexpected Communication %u DataFlow %u\n", KsPinDescriptor
->Communication
, KsPinDescriptor
->DataFlow
);
1127 Status
= m_Miniport
->NewStream(&m_Stream
,
1130 ConnectDetails
->PinId
,
1136 Status
= m_Stream
->QueryInterface(IID_IDrmAudioStream
, (PVOID
*)&DrmAudio
);
1137 if (NT_SUCCESS(Status
))
1139 DRMRIGHTS DrmRights
;
1140 DPRINT("Got IID_IDrmAudioStream interface %p\n", DrmAudio
);
1142 DrmRights
.CopyProtect
= FALSE
;
1143 DrmRights
.Reserved
= 0;
1144 DrmRights
.DigitalOutputDisable
= FALSE
;
1146 Status
= DrmAudio
->SetContentId(1, &DrmRights
);
1147 DPRINT("Status %x\n", Status
);
1151 DPRINT1("CPortPinWaveCyclic::Init Status %x PinId %u Capture %u\n", Status
, ConnectDetails
->PinId
, Capture
);
1152 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
);
1154 if (!NT_SUCCESS(Status
))
1157 ISubdevice
* Subdevice
= NULL
;
1158 // get subdevice interface
1159 Status
= Port
->QueryInterface(IID_ISubdevice
, (PVOID
*)&Subdevice
);
1161 if (!NT_SUCCESS(Status
))
1164 Status
= Subdevice
->GetDescriptor(&SubDeviceDescriptor
);
1165 if (!NT_SUCCESS(Status
))
1167 // failed to get descriptor
1168 Subdevice
->Release();
1172 /* initialize event management */
1173 InitializeListHead(&m_EventList
);
1174 KeInitializeSpinLock(&m_EventListLock
);
1176 /* set up subdevice descriptor */
1177 RtlZeroMemory(&m_Descriptor
, sizeof(SUBDEVICE_DESCRIPTOR
));
1178 m_Descriptor
.FilterPropertySet
= PinWaveCyclicPropertySet
;
1179 m_Descriptor
.FilterPropertySetCount
= sizeof(PinWaveCyclicPropertySet
) / sizeof(KSPROPERTY_SET
);
1180 m_Descriptor
.UnknownStream
= (PUNKNOWN
)m_Stream
;
1181 m_Descriptor
.DeviceDescriptor
= SubDeviceDescriptor
->DeviceDescriptor
;
1182 m_Descriptor
.UnknownMiniport
= SubDeviceDescriptor
->UnknownMiniport
;
1183 m_Descriptor
.PortPin
= (PVOID
)this;
1184 m_Descriptor
.EventSetCount
= sizeof(PinWaveCyclicEventSet
) / sizeof(KSEVENT_SET
);
1185 m_Descriptor
.EventSet
= PinWaveCyclicEventSet
;
1186 m_Descriptor
.EventList
= &m_EventList
;
1187 m_Descriptor
.EventListLock
= &m_EventListLock
;
1189 // initialize reset state
1190 m_ResetState
= KSRESET_END
;
1192 // release subdevice descriptor
1193 Subdevice
->Release();
1195 // add ourselves to service group
1196 Status
= m_ServiceGroup
->AddMember(PSERVICESINK(this));
1197 if (!NT_SUCCESS(Status
))
1199 DPRINT("Failed to add pin to service group\n");
1203 m_ServiceGroup
->SupportDelayedService();
1204 m_Stream
->SetState(KSSTATE_STOP
);
1205 m_State
= KSSTATE_STOP
;
1206 m_CommonBufferOffset
= 0;
1207 m_CommonBufferSize
= m_DmaChannel
->AllocatedBufferSize();
1208 m_CommonBuffer
= m_DmaChannel
->SystemAddress();
1209 m_Capture
= Capture
;
1210 // delay of 10 milisec
1211 m_Delay
= Int32x32To64(10, -10000);
1213 Status
= m_Stream
->SetNotificationFreq(10, &m_FrameSize
);
1215 SilenceBuffer
= AllocateItem(NonPagedPool
, m_FrameSize
, TAG_PORTCLASS
);
1217 return STATUS_INSUFFICIENT_RESOURCES
;
1220 /* set up allocator framing */
1221 m_AllocatorFraming
.RequirementsFlags
= KSALLOCATOR_REQUIREMENTF_SYSTEM_MEMORY
| KSALLOCATOR_REQUIREMENTF_PREFERENCES_ONLY
;
1222 m_AllocatorFraming
.PoolType
= NonPagedPool
;
1223 m_AllocatorFraming
.Frames
= 8;
1224 m_AllocatorFraming
.FileAlignment
= FILE_64_BYTE_ALIGNMENT
;
1225 m_AllocatorFraming
.Reserved
= 0;
1226 m_AllocatorFraming
.FrameSize
= m_FrameSize
;
1228 m_Stream
->Silence(SilenceBuffer
, m_FrameSize
);
1229 m_Stream
->Silence(m_CommonBuffer
, m_CommonBufferSize
);
1231 Status
= m_IrpQueue
->Init(ConnectDetails
, DataFormat
, DeviceObject
, m_FrameSize
, 0, SilenceBuffer
);
1232 if (!NT_SUCCESS(Status
))
1234 m_IrpQueue
->Release();
1238 m_Format
= (PKSDATAFORMAT
)AllocateItem(NonPagedPool
, DataFormat
->FormatSize
, TAG_PORTCLASS
);
1240 return STATUS_INSUFFICIENT_RESOURCES
;
1242 RtlMoveMemory(m_Format
, DataFormat
, DataFormat
->FormatSize
);
1250 //DPRINT("Setting state to acquire %x\n", m_Stream->SetState(KSSTATE_ACQUIRE));
1251 //DPRINT("Setting state to pause %x\n", m_Stream->SetState(KSSTATE_PAUSE));
1253 return STATUS_SUCCESS
;
1259 CPortPinWaveCyclic::GetCompletedPosition()
1268 CPortPinWaveCyclic::GetCycleCount()
1277 CPortPinWaveCyclic::GetDeviceBufferSize()
1279 return m_CommonBufferSize
;
1285 CPortPinWaveCyclic::GetIrpStream()
1287 return (PVOID
)m_IrpQueue
;
1293 CPortPinWaveCyclic::GetMiniport()
1295 return (PMINIPORT
)m_Miniport
;
1300 NewPortPinWaveCyclic(
1301 OUT IPortPinWaveCyclic
** OutPin
)
1303 CPortPinWaveCyclic
* This
;
1305 This
= new(NonPagedPool
, TAG_PORTCLASS
)CPortPinWaveCyclic(NULL
);
1307 return STATUS_INSUFFICIENT_RESOURCES
;
1312 *OutPin
= (IPortPinWaveCyclic
*)This
;
1314 return STATUS_SUCCESS
;