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(){}
38 VOID
SetState(KSSTATE State
);
42 VOID
UpdateCommonBuffer(ULONG Position
, ULONG MaxTransferCount
);
43 VOID
UpdateCommonBufferOverlap(ULONG Position
, ULONG MaxTransferCount
);
44 VOID
GeneratePositionEvents(IN ULONG OldCommonBufferOffset
, IN ULONG NewCommonBufferOffset
);
45 NTSTATUS NTAPI
HandleKsStream(IN PIRP Irp
);
46 NTSTATUS NTAPI
HandleKsProperty(IN PIRP Irp
);
49 friend NTSTATUS NTAPI
PinWaveCyclicState(IN PIRP Irp
, IN PKSIDENTIFIER Request
, IN OUT PVOID Data
);
50 friend NTSTATUS NTAPI
PinWaveCyclicDataFormat(IN PIRP Irp
, IN PKSIDENTIFIER Request
, IN OUT PVOID Data
);
51 friend NTSTATUS NTAPI
PinWaveCyclicAudioPosition(IN PIRP Irp
, IN PKSIDENTIFIER Request
, IN OUT PVOID Data
);
52 friend NTSTATUS NTAPI
PinWaveCyclicAllocatorFraming(IN PIRP Irp
, IN PKSIDENTIFIER Request
, IN OUT PVOID Data
);
53 friend NTSTATUS NTAPI
PinWaveCyclicAddEndOfStreamEvent(IN PIRP Irp
, IN PKSEVENTDATA EventData
, IN PKSEVENT_ENTRY EventEntry
);
54 friend NTSTATUS NTAPI
PinWaveCyclicAddLoopedStreamEvent(IN PIRP Irp
, IN PKSEVENTDATA EventData
, IN PKSEVENT_ENTRY EventEntry
);
56 IPortWaveCyclic
* m_Port
;
57 IPortFilterWaveCyclic
* m_Filter
;
58 KSPIN_DESCRIPTOR
* m_KsPinDescriptor
;
59 PMINIPORTWAVECYCLIC m_Miniport
;
60 PSERVICEGROUP m_ServiceGroup
;
61 PDMACHANNEL m_DmaChannel
;
62 PMINIPORTWAVECYCLICSTREAM m_Stream
;
64 PKSDATAFORMAT m_Format
;
65 PKSPIN_CONNECT m_ConnectDetails
;
68 ULONG m_CommonBufferSize
;
69 ULONG m_CommonBufferOffset
;
71 IIrpQueue
* m_IrpQueue
;
78 KSAUDIO_POSITION m_Position
;
79 KSALLOCATOR_FRAMING m_AllocatorFraming
;
80 SUBDEVICE_DESCRIPTOR m_Descriptor
;
82 KSPIN_LOCK m_EventListLock
;
83 LIST_ENTRY m_EventList
;
93 ULONG bLoopedStreaming
;
95 }LOOPEDSTREAMING_EVENT_CONTEXT
, *PLOOPEDSTREAMING_EVENT_CONTEXT
;
99 ULONG bLoopedStreaming
;
100 }ENDOFSTREAM_EVENT_CONTEXT
, *PENDOFSTREAM_EVENT_CONTEXT
;
104 NTSTATUS NTAPI
PinWaveCyclicState(IN PIRP Irp
, IN PKSIDENTIFIER Request
, IN OUT PVOID Data
);
105 NTSTATUS NTAPI
PinWaveCyclicDataFormat(IN PIRP Irp
, IN PKSIDENTIFIER Request
, IN OUT PVOID Data
);
106 NTSTATUS NTAPI
PinWaveCyclicAudioPosition(IN PIRP Irp
, IN PKSIDENTIFIER Request
, IN OUT PVOID Data
);
107 NTSTATUS NTAPI
PinWaveCyclicAllocatorFraming(IN PIRP Irp
, IN PKSIDENTIFIER Request
, IN OUT PVOID Data
);
108 NTSTATUS NTAPI
PinWaveCyclicAddEndOfStreamEvent(IN PIRP Irp
, IN PKSEVENTDATA EventData
, IN PKSEVENT_ENTRY EventEntry
);
109 NTSTATUS NTAPI
PinWaveCyclicAddLoopedStreamEvent(IN PIRP Irp
, IN PKSEVENTDATA EventData
, IN PKSEVENT_ENTRY EventEntry
);
112 DEFINE_KSPROPERTY_CONNECTIONSET(PinWaveCyclicConnectionSet
, PinWaveCyclicState
, PinWaveCyclicDataFormat
, PinWaveCyclicAllocatorFraming
);
113 DEFINE_KSPROPERTY_AUDIOSET(PinWaveCyclicAudioSet
, PinWaveCyclicAudioPosition
);
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
,
154 KSEVENT_SET PinWaveCyclicEventSet
[] =
157 &KSEVENTSETID_LoopedStreaming
,
158 sizeof(PinWaveCyclicStreamingEventSet
) / sizeof(KSEVENT_ITEM
),
159 (const KSEVENT_ITEM
*)&PinWaveCyclicStreamingEventSet
162 &KSEVENTSETID_Connection
,
163 sizeof(PinWaveCyclicConnectionEventSet
) / sizeof(KSEVENT_ITEM
),
164 (const KSEVENT_ITEM
*)&PinWaveCyclicConnectionEventSet
169 //==================================================================================================================================
173 CPortPinWaveCyclic::QueryInterface(
177 DPRINT("IServiceSink_fnQueryInterface entered\n");
179 if (IsEqualGUIDAligned(refiid
, IID_IIrpTarget
) ||
180 IsEqualGUIDAligned(refiid
, IID_IUnknown
))
182 *Output
= PVOID(PUNKNOWN((IIrpTarget
*)this));
183 PUNKNOWN(*Output
)->AddRef();
184 return STATUS_SUCCESS
;
187 if (IsEqualGUIDAligned(refiid
, IID_IServiceSink
))
189 *Output
= PVOID(PUNKNOWN(PSERVICESINK(this)));
190 PUNKNOWN(*Output
)->AddRef();
191 return STATUS_SUCCESS
;
194 return STATUS_UNSUCCESSFUL
;
199 PinWaveCyclicAddEndOfStreamEvent(
201 IN PKSEVENTDATA EventData
,
202 IN PKSEVENT_ENTRY EventEntry
)
204 PENDOFSTREAM_EVENT_CONTEXT Entry
;
205 PSUBDEVICE_DESCRIPTOR Descriptor
;
206 CPortPinWaveCyclic
*Pin
;
208 // get sub device descriptor
209 Descriptor
= (PSUBDEVICE_DESCRIPTOR
)KSPROPERTY_ITEM_IRP_STORAGE(Irp
);
212 PC_ASSERT(Descriptor
);
213 PC_ASSERT(Descriptor
->PortPin
);
214 PC_ASSERT_IRQL(DISPATCH_LEVEL
);
217 Pin
= (CPortPinWaveCyclic
*)Descriptor
->PortPin
;
220 Entry
= (PENDOFSTREAM_EVENT_CONTEXT
)(EventEntry
+ 1);
222 // not a looped event
223 Entry
->bLoopedStreaming
= FALSE
;
226 (void)ExInterlockedInsertTailList(&Pin
->m_EventList
, &EventEntry
->ListEntry
, &Pin
->m_EventListLock
);
229 return STATUS_SUCCESS
;
234 PinWaveCyclicAddLoopedStreamEvent(
236 IN PKSEVENTDATA EventData
,
237 IN PKSEVENT_ENTRY EventEntry
)
239 PLOOPEDSTREAMING_POSITION_EVENT_DATA Data
;
240 PLOOPEDSTREAMING_EVENT_CONTEXT Entry
;
241 PSUBDEVICE_DESCRIPTOR Descriptor
;
242 CPortPinWaveCyclic
*Pin
;
244 // get sub device descriptor
245 Descriptor
= (PSUBDEVICE_DESCRIPTOR
)KSEVENT_ITEM_IRP_STORAGE(Irp
);
248 PC_ASSERT(Descriptor
);
249 PC_ASSERT(Descriptor
->PortPin
);
250 PC_ASSERT_IRQL(DISPATCH_LEVEL
);
253 Pin
= (CPortPinWaveCyclic
*)Descriptor
->PortPin
;
255 // cast to looped event
256 Data
= (PLOOPEDSTREAMING_POSITION_EVENT_DATA
)EventData
;
259 Entry
= (PLOOPEDSTREAMING_EVENT_CONTEXT
)(EventEntry
+ 1);
261 Entry
->bLoopedStreaming
= TRUE
;
262 Entry
->Position
= Data
->Position
;
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
% Pin
->m_Position
.WriteOffset
;
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
;
364 IN PKSIDENTIFIER Request
,
367 NTSTATUS Status
= STATUS_UNSUCCESSFUL
;
368 CPortPinWaveCyclic
*Pin
;
369 PSUBDEVICE_DESCRIPTOR Descriptor
;
370 PKSSTATE State
= (PKSSTATE
)Data
;
372 // get sub device descriptor
373 Descriptor
= (PSUBDEVICE_DESCRIPTOR
)KSPROPERTY_ITEM_IRP_STORAGE(Irp
);
376 PC_ASSERT(Descriptor
);
377 PC_ASSERT(Descriptor
->PortPin
);
378 PC_ASSERT_IRQL(DISPATCH_LEVEL
);
381 Pin
= (CPortPinWaveCyclic
*)Descriptor
->PortPin
;
384 PC_ASSERT(Pin
->m_Stream
);
386 if (Request
->Flags
& KSPROPERTY_TYPE_SET
)
389 Status
= Pin
->m_Stream
->SetState(*State
);
391 DPRINT("Setting state %u %x\n", *State
, Status
);
392 if (NT_SUCCESS(Status
))
395 Pin
->m_State
= *State
;
397 if (Pin
->m_ConnectDetails
->Interface
.Id
== KSINTERFACE_STANDARD_LOOPED_STREAMING
&& Pin
->m_State
== KSSTATE_STOP
)
399 /* FIXME complete pending irps with successfull state */
400 Pin
->m_IrpQueue
->CancelBuffers();
405 Irp
->IoStatus
.Information
= sizeof(KSSTATE
);
408 else if (Request
->Flags
& KSPROPERTY_TYPE_GET
)
410 // get current stream state
411 *State
= Pin
->m_State
;
413 Irp
->IoStatus
.Information
= sizeof(KSSTATE
);
415 return STATUS_SUCCESS
;
418 // unsupported request
419 return STATUS_NOT_SUPPORTED
;
424 PinWaveCyclicDataFormat(
426 IN PKSIDENTIFIER Request
,
429 NTSTATUS Status
= STATUS_UNSUCCESSFUL
;
430 CPortPinWaveCyclic
*Pin
;
431 PSUBDEVICE_DESCRIPTOR Descriptor
;
432 PIO_STACK_LOCATION IoStack
;
434 // get current irp stack location
435 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
437 // get sub device descriptor
438 Descriptor
= (PSUBDEVICE_DESCRIPTOR
)KSPROPERTY_ITEM_IRP_STORAGE(Irp
);
441 PC_ASSERT(Descriptor
);
442 PC_ASSERT(Descriptor
->PortPin
);
445 Pin
= (CPortPinWaveCyclic
*)Descriptor
->PortPin
;
448 PC_ASSERT(Pin
->m_Stream
);
449 PC_ASSERT(Pin
->m_Format
);
451 if (Request
->Flags
& KSPROPERTY_TYPE_SET
)
453 // try to change data format
454 PKSDATAFORMAT NewDataFormat
, DataFormat
= (PKSDATAFORMAT
)Irp
->UserBuffer
;
455 ULONG Size
= min(Pin
->m_Format
->FormatSize
, DataFormat
->FormatSize
);
457 if (RtlCompareMemory(DataFormat
, Pin
->m_Format
, Size
) == Size
)
459 // format is identical
460 Irp
->IoStatus
.Information
= DataFormat
->FormatSize
;
461 return STATUS_SUCCESS
;
464 // new change request
465 PC_ASSERT(Pin
->m_State
== KSSTATE_STOP
);
466 // FIXME queue a work item when Irql != PASSIVE_LEVEL
467 PC_ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL
);
469 // allocate new data format
470 NewDataFormat
= (PKSDATAFORMAT
)AllocateItem(NonPagedPool
, DataFormat
->FormatSize
, TAG_PORTCLASS
);
474 return STATUS_NO_MEMORY
;
477 // copy new data format
478 RtlMoveMemory(NewDataFormat
, DataFormat
, DataFormat
->FormatSize
);
481 Status
= Pin
->m_Stream
->SetFormat(NewDataFormat
);
482 if (NT_SUCCESS(Status
))
485 FreeItem(Pin
->m_Format
, TAG_PORTCLASS
);
487 // update irp queue with new format
488 Pin
->m_IrpQueue
->UpdateFormat((PKSDATAFORMAT
)NewDataFormat
);
491 Pin
->m_Format
= NewDataFormat
;
492 Irp
->IoStatus
.Information
= NewDataFormat
->FormatSize
;
495 PC_ASSERT(NewDataFormat
->FormatSize
== sizeof(KSDATAFORMAT_WAVEFORMATEX
));
496 PC_ASSERT(IsEqualGUIDAligned(((PKSDATAFORMAT_WAVEFORMATEX
)NewDataFormat
)->DataFormat
.MajorFormat
, KSDATAFORMAT_TYPE_AUDIO
));
497 PC_ASSERT(IsEqualGUIDAligned(((PKSDATAFORMAT_WAVEFORMATEX
)NewDataFormat
)->DataFormat
.SubFormat
, KSDATAFORMAT_SUBTYPE_PCM
));
498 PC_ASSERT(IsEqualGUIDAligned(((PKSDATAFORMAT_WAVEFORMATEX
)NewDataFormat
)->DataFormat
.Specifier
, KSDATAFORMAT_SPECIFIER_WAVEFORMATEX
));
501 DPRINT("NewDataFormat: Channels %u Bits %u Samples %u\n", ((PKSDATAFORMAT_WAVEFORMATEX
)NewDataFormat
)->WaveFormatEx
.nChannels
,
502 ((PKSDATAFORMAT_WAVEFORMATEX
)NewDataFormat
)->WaveFormatEx
.wBitsPerSample
,
503 ((PKSDATAFORMAT_WAVEFORMATEX
)NewDataFormat
)->WaveFormatEx
.nSamplesPerSec
);
509 // failed to set format
510 FreeItem(NewDataFormat
, TAG_PORTCLASS
);
517 else if (Request
->Flags
& KSPROPERTY_TYPE_GET
)
519 // get current data format
520 PC_ASSERT(Pin
->m_Format
);
522 if (Pin
->m_Format
->FormatSize
> IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
)
525 Irp
->IoStatus
.Information
= Pin
->m_Format
->FormatSize
;
526 return STATUS_MORE_ENTRIES
;
529 RtlMoveMemory(Data
, Pin
->m_Format
, Pin
->m_Format
->FormatSize
);
531 Irp
->IoStatus
.Information
= Pin
->m_Format
->FormatSize
;
534 return STATUS_SUCCESS
;
537 // unsupported request
538 return STATUS_NOT_SUPPORTED
;
542 CPortPinWaveCyclic::GeneratePositionEvents(
543 IN ULONG OldCommonBufferOffset
,
544 IN ULONG NewCommonBufferOffset
)
547 PKSEVENT_ENTRY EventEntry
;
548 PLOOPEDSTREAMING_EVENT_CONTEXT Context
;
550 // acquire event lock
551 KeAcquireSpinLockAtDpcLevel(&m_EventListLock
);
553 // point to first entry
554 Entry
= m_EventList
.Flink
;
556 while(Entry
!= &m_EventList
)
559 EventEntry
= (PKSEVENT_ENTRY
)CONTAINING_RECORD(Entry
, KSEVENT_ENTRY
, ListEntry
);
561 // get event entry context
562 Context
= (PLOOPEDSTREAMING_EVENT_CONTEXT
)(EventEntry
+ 1);
564 if (Context
->bLoopedStreaming
== TRUE
)
566 if (NewCommonBufferOffset
> OldCommonBufferOffset
)
568 /* buffer progress no overlap */
569 if (OldCommonBufferOffset
< Context
->Position
&& Context
->Position
<= NewCommonBufferOffset
)
572 KsGenerateEvent(EventEntry
);
577 /* buffer wrap-arround */
578 if (OldCommonBufferOffset
< Context
->Position
|| NewCommonBufferOffset
> Context
->Position
)
581 KsGenerateEvent(EventEntry
);
586 // move to next entry
587 Entry
= Entry
->Flink
;
591 KeReleaseSpinLockFromDpcLevel(&m_EventListLock
);
595 CPortPinWaveCyclic::UpdateCommonBuffer(
597 ULONG MaxTransferCount
)
605 BufferLength
= Position
- m_CommonBufferOffset
;
606 BufferLength
= min(BufferLength
, MaxTransferCount
);
610 Status
= m_IrpQueue
->GetMapping(&Buffer
, &BufferSize
);
611 if (!NT_SUCCESS(Status
))
614 BytesToCopy
= min(BufferLength
, BufferSize
);
618 m_DmaChannel
->CopyFrom(Buffer
, (PUCHAR
)m_CommonBuffer
+ m_CommonBufferOffset
, BytesToCopy
);
622 m_DmaChannel
->CopyTo((PUCHAR
)m_CommonBuffer
+ m_CommonBufferOffset
, Buffer
, BytesToCopy
);
625 m_IrpQueue
->UpdateMapping(BytesToCopy
);
626 m_CommonBufferOffset
+= BytesToCopy
;
628 BufferLength
= Position
- m_CommonBufferOffset
;
629 m_Position
.PlayOffset
+= BytesToCopy
;
634 CPortPinWaveCyclic::UpdateCommonBufferOverlap(
636 ULONG MaxTransferCount
)
638 ULONG BufferLength
, Length
, Gap
;
645 BufferLength
= Gap
= m_CommonBufferSize
- m_CommonBufferOffset
;
646 BufferLength
= Length
= min(BufferLength
, MaxTransferCount
);
649 Status
= m_IrpQueue
->GetMapping(&Buffer
, &BufferSize
);
650 if (!NT_SUCCESS(Status
))
653 BytesToCopy
= min(BufferLength
, BufferSize
);
657 m_DmaChannel
->CopyFrom(Buffer
,
658 (PUCHAR
)m_CommonBuffer
+ m_CommonBufferOffset
,
663 m_DmaChannel
->CopyTo((PUCHAR
)m_CommonBuffer
+ m_CommonBufferOffset
,
668 m_IrpQueue
->UpdateMapping(BytesToCopy
);
669 m_CommonBufferOffset
+= BytesToCopy
;
670 m_Position
.PlayOffset
+= BytesToCopy
;
672 BufferLength
= m_CommonBufferSize
- m_CommonBufferOffset
;
677 m_CommonBufferOffset
= 0;
679 MaxTransferCount
-= Length
;
681 if (MaxTransferCount
)
683 UpdateCommonBuffer(Position
, MaxTransferCount
);
690 CPortPinWaveCyclic::RequestService()
696 ULONG OldCommonBufferOffset
;
698 PC_ASSERT_IRQL(DISPATCH_LEVEL
);
700 Status
= m_IrpQueue
->GetMapping(&Buffer
, &BufferSize
);
701 if (!NT_SUCCESS(Status
))
706 Status
= m_Stream
->GetPosition(&Position
);
707 DPRINT("Position %u Buffer %p BufferSize %u ActiveIrpOffset %u Capture %u\n", Position
, Buffer
, m_CommonBufferSize
, BufferSize
, m_Capture
);
709 OldCommonBufferOffset
= m_CommonBufferOffset
;
711 if (Position
< m_CommonBufferOffset
)
713 UpdateCommonBufferOverlap(Position
, m_FrameSize
);
715 else if (Position
>= m_CommonBufferOffset
)
717 UpdateCommonBuffer(Position
, m_FrameSize
);
720 GeneratePositionEvents(OldCommonBufferOffset
, m_CommonBufferOffset
);
725 CPortPinWaveCyclic::NewIrpTarget(
726 OUT
struct IIrpTarget
**OutTarget
,
729 IN POOL_TYPE PoolType
,
730 IN PDEVICE_OBJECT DeviceObject
,
732 IN KSOBJECT_CREATE
*CreateObject
)
735 return STATUS_UNSUCCESSFUL
;
740 CPortPinWaveCyclic::HandleKsProperty(
743 PKSPROPERTY Property
;
745 UNICODE_STRING GuidString
;
746 PIO_STACK_LOCATION IoStack
;
748 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
750 DPRINT("IPortPinWave_HandleKsProperty entered\n");
752 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
754 Status
= PcHandlePropertyWithTable(Irp
, m_Descriptor
.FilterPropertySetCount
, m_Descriptor
.FilterPropertySet
, &m_Descriptor
);
756 if (Status
== STATUS_NOT_FOUND
)
758 Property
= (PKSPROPERTY
)IoStack
->Parameters
.DeviceIoControl
.Type3InputBuffer
;
760 RtlStringFromGUID(Property
->Set
, &GuidString
);
761 DPRINT("Unhandeled property Set |%S| Id %u Flags %x\n", GuidString
.Buffer
, Property
->Id
, Property
->Flags
);
762 RtlFreeUnicodeString(&GuidString
);
765 if (Status
!= STATUS_PENDING
)
767 Irp
->IoStatus
.Status
= Status
;
768 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
776 CPortPinWaveCyclic::HandleKsStream(
781 InterlockedIncrement((PLONG
)&m_TotalPackets
);
783 DPRINT("IPortPinWaveCyclic_HandleKsStream entered Total %u State %x MinData %u\n", m_TotalPackets
, m_State
, m_IrpQueue
->NumData());
785 Status
= m_IrpQueue
->AddMapping(Irp
, &Data
);
787 if (NT_SUCCESS(Status
))
789 m_Position
.WriteOffset
+= Data
;
791 return STATUS_PENDING
;
799 CPortPinWaveCyclic::DeviceIoControl(
800 IN PDEVICE_OBJECT DeviceObject
,
803 PIO_STACK_LOCATION IoStack
;
804 NTSTATUS Status
= STATUS_NOT_SUPPORTED
;
806 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
809 if (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_KS_PROPERTY
)
811 return HandleKsProperty(Irp
);
813 else if (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_KS_ENABLE_EVENT
)
815 Status
= PcHandleEnableEventWithTable(Irp
, &m_Descriptor
);
817 else if (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_KS_DISABLE_EVENT
)
819 Status
= PcHandleDisableEventWithTable(Irp
, &m_Descriptor
);
821 else if (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_KS_RESET_STATE
)
824 /// handle reset state
826 else if (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_KS_WRITE_STREAM
|| IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_KS_READ_STREAM
)
828 return HandleKsStream(Irp
);
832 return KsDefaultDeviceIoCompletion(DeviceObject
, Irp
);
835 if (Status
!= STATUS_PENDING
)
837 Irp
->IoStatus
.Status
= Status
;
838 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
846 CPortPinWaveCyclic::Read(
847 IN PDEVICE_OBJECT DeviceObject
,
850 return KsDispatchInvalidDeviceRequest(DeviceObject
, Irp
);
855 CPortPinWaveCyclic::Write(
856 IN PDEVICE_OBJECT DeviceObject
,
859 return KsDispatchInvalidDeviceRequest(DeviceObject
, Irp
);
864 CPortPinWaveCyclic::Flush(
865 IN PDEVICE_OBJECT DeviceObject
,
868 return KsDispatchInvalidDeviceRequest(DeviceObject
, Irp
);
873 CPortPinWaveCyclic::Close(
874 IN PDEVICE_OBJECT DeviceObject
,
877 DPRINT("CPortPinWaveCyclic::Close entered\n");
879 PC_ASSERT_IRQL(PASSIVE_LEVEL
);
884 ExFreePool(m_Format
);
891 m_IrpQueue
->Release();
897 // release reference to port driver
904 // remove member from service group
905 m_ServiceGroup
->RemoveMember(PSERVICESINK(this));
906 m_ServiceGroup
= NULL
;
911 if (m_State
!= KSSTATE_STOP
)
914 NTSTATUS Status
= m_Stream
->SetState(KSSTATE_STOP
);
915 if (!NT_SUCCESS(Status
))
917 DPRINT("Warning: failed to stop stream with %x\n", Status
);
922 m_State
= KSSTATE_STOP
;
925 DPRINT("Closing stream at Irql %u\n", KeGetCurrentIrql());
934 // release reference to filter instance
935 m_Filter
->FreePin((PPORTPINWAVECYCLIC
)this);
940 Irp
->IoStatus
.Information
= 0;
941 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
942 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
946 return STATUS_SUCCESS
;
951 CPortPinWaveCyclic::QuerySecurity(
952 IN PDEVICE_OBJECT DeviceObject
,
955 return KsDispatchInvalidDeviceRequest(DeviceObject
, Irp
);
960 CPortPinWaveCyclic::SetSecurity(
961 IN PDEVICE_OBJECT DeviceObject
,
964 return KsDispatchInvalidDeviceRequest(DeviceObject
, Irp
);
969 CPortPinWaveCyclic::FastDeviceIoControl(
970 IN PFILE_OBJECT FileObject
,
972 IN PVOID InputBuffer
,
973 IN ULONG InputBufferLength
,
974 OUT PVOID OutputBuffer
,
975 IN ULONG OutputBufferLength
,
976 IN ULONG IoControlCode
,
977 OUT PIO_STATUS_BLOCK StatusBlock
,
978 IN PDEVICE_OBJECT DeviceObject
)
980 return KsDispatchFastIoDeviceControlFailure(FileObject
, Wait
, InputBuffer
, InputBufferLength
, OutputBuffer
, OutputBufferLength
, IoControlCode
, StatusBlock
, DeviceObject
);
986 CPortPinWaveCyclic::FastRead(
987 IN PFILE_OBJECT FileObject
,
988 IN PLARGE_INTEGER FileOffset
,
993 OUT PIO_STATUS_BLOCK StatusBlock
,
994 IN PDEVICE_OBJECT DeviceObject
)
996 return KsDispatchFastReadFailure(FileObject
, FileOffset
, Length
, Wait
, LockKey
, Buffer
, StatusBlock
, DeviceObject
);
1002 CPortPinWaveCyclic::FastWrite(
1003 IN PFILE_OBJECT FileObject
,
1004 IN PLARGE_INTEGER FileOffset
,
1009 OUT PIO_STATUS_BLOCK StatusBlock
,
1010 IN PDEVICE_OBJECT DeviceObject
)
1012 return KsDispatchFastReadFailure(FileObject
, FileOffset
, Length
, Wait
, LockKey
, Buffer
, StatusBlock
, DeviceObject
);
1018 CPortPinWaveCyclic::Init(
1019 IN PPORTWAVECYCLIC Port
,
1020 IN PPORTFILTERWAVECYCLIC Filter
,
1021 IN KSPIN_CONNECT
* ConnectDetails
,
1022 IN KSPIN_DESCRIPTOR
* KsPinDescriptor
)
1025 PKSDATAFORMAT DataFormat
;
1026 PDEVICE_OBJECT DeviceObject
;
1028 PVOID SilenceBuffer
;
1029 PSUBDEVICE_DESCRIPTOR SubDeviceDescriptor
= NULL
;
1030 //IDrmAudioStream * DrmAudio = NULL;
1032 m_KsPinDescriptor
= KsPinDescriptor
;
1033 m_ConnectDetails
= ConnectDetails
;
1034 m_Miniport
= GetWaveCyclicMiniport(Port
);
1036 DeviceObject
= GetDeviceObject(Port
);
1038 DataFormat
= (PKSDATAFORMAT
)(ConnectDetails
+ 1);
1040 DPRINT("CPortPinWaveCyclic::Init entered Size %u\n", DataFormat
->FormatSize
);
1042 Status
= NewIrpQueue(&m_IrpQueue
);
1043 if (!NT_SUCCESS(Status
))
1046 if (KsPinDescriptor
->Communication
== KSPIN_COMMUNICATION_SINK
&& KsPinDescriptor
->DataFlow
== KSPIN_DATAFLOW_IN
)
1050 else if (KsPinDescriptor
->Communication
== KSPIN_COMMUNICATION_SINK
&& KsPinDescriptor
->DataFlow
== KSPIN_DATAFLOW_OUT
)
1056 DPRINT("Unexpected Communication %u DataFlow %u\n", KsPinDescriptor
->Communication
, KsPinDescriptor
->DataFlow
);
1062 Status
= m_Miniport
->NewStream(&m_Stream
,
1065 ConnectDetails
->PinId
,
1071 Status
= m_Stream
->QueryInterface(IID_IDrmAudioStream
, (PVOID
*)&DrmAudio
);
1072 if (NT_SUCCESS(Status
))
1074 DRMRIGHTS DrmRights
;
1075 DPRINT("Got IID_IDrmAudioStream interface %p\n", DrmAudio
);
1077 DrmRights
.CopyProtect
= FALSE
;
1078 DrmRights
.Reserved
= 0;
1079 DrmRights
.DigitalOutputDisable
= FALSE
;
1081 Status
= DrmAudio
->SetContentId(1, &DrmRights
);
1082 DPRINT("Status %x\n", Status
);
1086 DPRINT1("CPortPinWaveCyclic::Init Status %x PinId %u Capture %u\n", Status
, ConnectDetails
->PinId
, Capture
);
1087 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
);
1089 if (!NT_SUCCESS(Status
))
1092 ISubdevice
* Subdevice
= NULL
;
1093 // get subdevice interface
1094 Status
= Port
->QueryInterface(IID_ISubdevice
, (PVOID
*)&Subdevice
);
1096 if (!NT_SUCCESS(Status
))
1099 Status
= Subdevice
->GetDescriptor(&SubDeviceDescriptor
);
1100 if (!NT_SUCCESS(Status
))
1102 // failed to get descriptor
1103 Subdevice
->Release();
1107 /* initialize event management */
1108 InitializeListHead(&m_EventList
);
1109 KeInitializeSpinLock(&m_EventListLock
);
1111 /* set up subdevice descriptor */
1112 RtlZeroMemory(&m_Descriptor
, sizeof(SUBDEVICE_DESCRIPTOR
));
1113 m_Descriptor
.FilterPropertySet
= PinWaveCyclicPropertySet
;
1114 m_Descriptor
.FilterPropertySetCount
= sizeof(PinWaveCyclicPropertySet
) / sizeof(KSPROPERTY_SET
);
1115 m_Descriptor
.UnknownStream
= (PUNKNOWN
)m_Stream
;
1116 m_Descriptor
.DeviceDescriptor
= SubDeviceDescriptor
->DeviceDescriptor
;
1117 m_Descriptor
.UnknownMiniport
= SubDeviceDescriptor
->UnknownMiniport
;
1118 m_Descriptor
.PortPin
= (PVOID
)this;
1119 m_Descriptor
.EventSetCount
= sizeof(PinWaveCyclicEventSet
) / sizeof(KSEVENT_SET
);
1120 m_Descriptor
.EventSet
= PinWaveCyclicEventSet
;
1121 m_Descriptor
.EventList
= &m_EventList
;
1122 m_Descriptor
.EventListLock
= &m_EventListLock
;
1124 // release subdevice descriptor
1125 Subdevice
->Release();
1127 // add ourselves to service group
1128 Status
= m_ServiceGroup
->AddMember(PSERVICESINK(this));
1129 if (!NT_SUCCESS(Status
))
1131 DPRINT("Failed to add pin to service group\n");
1135 m_ServiceGroup
->SupportDelayedService();
1136 m_Stream
->SetState(KSSTATE_STOP
);
1137 m_State
= KSSTATE_STOP
;
1138 m_CommonBufferOffset
= 0;
1139 m_CommonBufferSize
= m_DmaChannel
->AllocatedBufferSize();
1140 m_CommonBuffer
= m_DmaChannel
->SystemAddress();
1141 m_Capture
= Capture
;
1142 // delay of 10 milisec
1143 m_Delay
= Int32x32To64(10, -10000);
1145 Status
= m_Stream
->SetNotificationFreq(10, &m_FrameSize
);
1147 SilenceBuffer
= AllocateItem(NonPagedPool
, m_FrameSize
, TAG_PORTCLASS
);
1149 return STATUS_INSUFFICIENT_RESOURCES
;
1152 /* set up allocator framing */
1153 m_AllocatorFraming
.RequirementsFlags
= KSALLOCATOR_REQUIREMENTF_SYSTEM_MEMORY
| KSALLOCATOR_REQUIREMENTF_PREFERENCES_ONLY
;
1154 m_AllocatorFraming
.PoolType
= NonPagedPool
;
1155 m_AllocatorFraming
.Frames
= 8;
1156 m_AllocatorFraming
.FileAlignment
= FILE_64_BYTE_ALIGNMENT
;
1157 m_AllocatorFraming
.Reserved
= 0;
1158 m_AllocatorFraming
.FrameSize
= m_FrameSize
;
1160 m_Stream
->Silence(SilenceBuffer
, m_FrameSize
);
1162 Status
= m_IrpQueue
->Init(ConnectDetails
, DataFormat
, DeviceObject
, m_FrameSize
, 0, SilenceBuffer
);
1163 if (!NT_SUCCESS(Status
))
1165 m_IrpQueue
->Release();
1169 m_Format
= (PKSDATAFORMAT
)AllocateItem(NonPagedPool
, DataFormat
->FormatSize
, TAG_PORTCLASS
);
1171 return STATUS_INSUFFICIENT_RESOURCES
;
1173 RtlMoveMemory(m_Format
, DataFormat
, DataFormat
->FormatSize
);
1181 DPRINT("Setting state to acquire %x\n", m_Stream
->SetState(KSSTATE_ACQUIRE
));
1182 DPRINT("Setting state to pause %x\n", m_Stream
->SetState(KSSTATE_PAUSE
));
1184 return STATUS_SUCCESS
;
1190 CPortPinWaveCyclic::GetCompletedPosition()
1199 CPortPinWaveCyclic::GetCycleCount()
1208 CPortPinWaveCyclic::GetDeviceBufferSize()
1210 return m_CommonBufferSize
;
1216 CPortPinWaveCyclic::GetIrpStream()
1218 return (PVOID
)m_IrpQueue
;
1224 CPortPinWaveCyclic::GetMiniport()
1226 return (PMINIPORT
)m_Miniport
;
1231 NewPortPinWaveCyclic(
1232 OUT IPortPinWaveCyclic
** OutPin
)
1234 CPortPinWaveCyclic
* This
;
1236 This
= new(NonPagedPool
, TAG_PORTCLASS
)CPortPinWaveCyclic(NULL
);
1238 return STATUS_INSUFFICIENT_RESOURCES
;
1243 *OutPin
= (IPortPinWaveCyclic
*)This
;
1245 return STATUS_SUCCESS
;