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 NTAPI
SetStreamState(IN KSSTATE State
);
45 NTSTATUS NTAPI
HandleKsStream(IN PIRP Irp
);
46 NTSTATUS NTAPI
HandleKsProperty(IN PIRP Irp
);
49 friend VOID NTAPI
CloseStreamRoutineWaveCyclic(IN PDEVICE_OBJECT DeviceObject
, IN PVOID Context
);
50 friend VOID NTAPI
SetStreamWorkerRoutineWaveCyclic(IN PDEVICE_OBJECT DeviceObject
, IN PVOID Context
);
51 friend NTSTATUS NTAPI
PinWaveCyclicState(IN PIRP Irp
, IN PKSIDENTIFIER Request
, IN OUT PVOID Data
);
52 friend NTSTATUS NTAPI
PinWaveCyclicDataFormat(IN PIRP Irp
, IN PKSIDENTIFIER Request
, IN OUT PVOID Data
);
53 friend NTSTATUS NTAPI
PinWaveCyclicAudioPosition(IN PIRP Irp
, IN PKSIDENTIFIER Request
, IN OUT PVOID Data
);
55 IPortWaveCyclic
* m_Port
;
56 IPortFilterWaveCyclic
* m_Filter
;
57 KSPIN_DESCRIPTOR
* m_KsPinDescriptor
;
58 PMINIPORTWAVECYCLIC m_Miniport
;
59 PSERVICEGROUP m_ServiceGroup
;
60 PDMACHANNEL m_DmaChannel
;
61 PMINIPORTWAVECYCLICSTREAM m_Stream
;
63 PKSDATAFORMAT m_Format
;
64 KSPIN_CONNECT
* m_ConnectDetails
;
67 ULONG m_CommonBufferSize
;
68 ULONG m_CommonBufferOffset
;
70 IIrpQueue
* m_IrpQueue
;
77 KSAUDIO_POSITION m_Position
;
78 SUBDEVICE_DESCRIPTOR m_Descriptor
;
88 CPortPinWaveCyclic
*Pin
;
89 PIO_WORKITEM WorkItem
;
91 }SETSTREAM_CONTEXT
, *PSETSTREAM_CONTEXT
;
93 NTSTATUS NTAPI
PinWaveCyclicState(IN PIRP Irp
, IN PKSIDENTIFIER Request
, IN OUT PVOID Data
);
94 NTSTATUS NTAPI
PinWaveCyclicDataFormat(IN PIRP Irp
, IN PKSIDENTIFIER Request
, IN OUT PVOID Data
);
95 NTSTATUS NTAPI
PinWaveCyclicAudioPosition(IN PIRP Irp
, IN PKSIDENTIFIER Request
, IN OUT PVOID Data
);
98 DEFINE_KSPROPERTY_CONNECTIONSET(PinWaveCyclicConnectionSet
, PinWaveCyclicState
, PinWaveCyclicDataFormat
);
99 DEFINE_KSPROPERTY_AUDIOSET(PinWaveCyclicAudioSet
, PinWaveCyclicAudioPosition
);
101 KSPROPERTY_SET PinWaveCyclicPropertySet
[] =
104 &KSPROPSETID_Connection
,
105 sizeof(PinWaveCyclicConnectionSet
) / sizeof(KSPROPERTY_ITEM
),
106 (const KSPROPERTY_ITEM
*)&PinWaveCyclicConnectionSet
,
112 sizeof(PinWaveCyclicAudioSet
) / sizeof(KSPROPERTY_ITEM
),
113 (const KSPROPERTY_ITEM
*)&PinWaveCyclicAudioSet
,
119 //==================================================================================================================================
123 CPortPinWaveCyclic::QueryInterface(
127 DPRINT("IServiceSink_fnQueryInterface entered\n");
129 if (IsEqualGUIDAligned(refiid
, IID_IIrpTarget
) ||
130 IsEqualGUIDAligned(refiid
, IID_IUnknown
))
132 *Output
= PVOID(PUNKNOWN((IIrpTarget
*)this));
133 PUNKNOWN(*Output
)->AddRef();
134 return STATUS_SUCCESS
;
137 if (IsEqualGUIDAligned(refiid
, IID_IServiceSink
))
139 *Output
= PVOID(PUNKNOWN(PSERVICESINK(this)));
140 PUNKNOWN(*Output
)->AddRef();
141 return STATUS_SUCCESS
;
144 return STATUS_UNSUCCESSFUL
;
151 PinWaveCyclicAudioPosition(
153 IN PKSIDENTIFIER Request
,
156 CPortPinWaveCyclic
*Pin
;
157 PSUBDEVICE_DESCRIPTOR Descriptor
;
159 // get sub device descriptor
160 Descriptor
= (PSUBDEVICE_DESCRIPTOR
)KSPROPERTY_ITEM_IRP_STORAGE(Irp
);
163 PC_ASSERT(Descriptor
);
164 PC_ASSERT(Descriptor
->PortPin
);
165 PC_ASSERT_IRQL(DISPATCH_LEVEL
);
168 Pin
= (CPortPinWaveCyclic
*)Descriptor
->PortPin
;
171 PC_ASSERT(Pin
->m_Stream
);
173 if (Request
->Flags
& KSPROPERTY_TYPE_GET
)
175 // FIXME non multithreading-safe
176 // copy audio position
177 RtlMoveMemory(Data
, &Pin
->m_Position
, sizeof(KSAUDIO_POSITION
));
179 DPRINT1("Play %lu Record %lu\n", Pin
->m_Position
.PlayOffset
, Pin
->m_Position
.WriteOffset
);
180 Irp
->IoStatus
.Information
= sizeof(KSAUDIO_POSITION
);
181 return STATUS_SUCCESS
;
185 return STATUS_NOT_SUPPORTED
;
193 IN PKSIDENTIFIER Request
,
196 NTSTATUS Status
= STATUS_UNSUCCESSFUL
;
197 CPortPinWaveCyclic
*Pin
;
198 PSUBDEVICE_DESCRIPTOR Descriptor
;
199 PKSSTATE State
= (PKSSTATE
)Data
;
201 // get sub device descriptor
202 Descriptor
= (PSUBDEVICE_DESCRIPTOR
)KSPROPERTY_ITEM_IRP_STORAGE(Irp
);
205 PC_ASSERT(Descriptor
);
206 PC_ASSERT(Descriptor
->PortPin
);
207 PC_ASSERT_IRQL(DISPATCH_LEVEL
);
210 Pin
= (CPortPinWaveCyclic
*)Descriptor
->PortPin
;
213 PC_ASSERT(Pin
->m_Stream
);
215 if (Request
->Flags
& KSPROPERTY_TYPE_SET
)
218 Status
= Pin
->m_Stream
->SetState(*State
);
220 DPRINT("Setting state %u %x\n", *State
, Status
);
221 if (NT_SUCCESS(Status
))
224 Pin
->m_State
= *State
;
227 Irp
->IoStatus
.Information
= sizeof(KSSTATE
);
230 else if (Request
->Flags
& KSPROPERTY_TYPE_GET
)
232 // get current stream state
233 *State
= Pin
->m_State
;
235 Irp
->IoStatus
.Information
= sizeof(KSSTATE
);
237 return STATUS_SUCCESS
;
240 // unsupported request
241 return STATUS_NOT_SUPPORTED
;
246 PinWaveCyclicDataFormat(
248 IN PKSIDENTIFIER Request
,
251 NTSTATUS Status
= STATUS_UNSUCCESSFUL
;
252 CPortPinWaveCyclic
*Pin
;
253 PSUBDEVICE_DESCRIPTOR Descriptor
;
254 PIO_STACK_LOCATION IoStack
;
256 // get current irp stack location
257 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
259 // get sub device descriptor
260 Descriptor
= (PSUBDEVICE_DESCRIPTOR
)KSPROPERTY_ITEM_IRP_STORAGE(Irp
);
263 PC_ASSERT(Descriptor
);
264 PC_ASSERT(Descriptor
->PortPin
);
267 Pin
= (CPortPinWaveCyclic
*)Descriptor
->PortPin
;
270 PC_ASSERT(Pin
->m_Stream
);
271 PC_ASSERT(Pin
->m_Format
);
273 if (Request
->Flags
& KSPROPERTY_TYPE_SET
)
275 // try to change data format
276 PKSDATAFORMAT NewDataFormat
, DataFormat
= (PKSDATAFORMAT
)Irp
->UserBuffer
;
277 ULONG Size
= min(Pin
->m_Format
->FormatSize
, DataFormat
->FormatSize
);
279 if (RtlCompareMemory(DataFormat
, Pin
->m_Format
, Size
) == Size
)
281 // format is identical
282 Irp
->IoStatus
.Information
= DataFormat
->FormatSize
;
283 return STATUS_SUCCESS
;
286 // new change request
287 PC_ASSERT(Pin
->m_State
== KSSTATE_STOP
);
288 // FIXME queue a work item when Irql != PASSIVE_LEVEL
289 PC_ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL
);
291 // allocate new data format
292 NewDataFormat
= (PKSDATAFORMAT
)AllocateItem(NonPagedPool
, DataFormat
->FormatSize
, TAG_PORTCLASS
);
296 return STATUS_NO_MEMORY
;
299 // copy new data format
300 RtlMoveMemory(NewDataFormat
, DataFormat
, DataFormat
->FormatSize
);
303 Status
= Pin
->m_Stream
->SetFormat(NewDataFormat
);
304 if (NT_SUCCESS(Status
))
307 FreeItem(Pin
->m_Format
, TAG_PORTCLASS
);
309 // update irp queue with new format
310 Pin
->m_IrpQueue
->UpdateFormat((PKSDATAFORMAT
)NewDataFormat
);
313 Pin
->m_Format
= NewDataFormat
;
314 Irp
->IoStatus
.Information
= NewDataFormat
->FormatSize
;
317 PC_ASSERT(NewDataFormat
->FormatSize
== sizeof(KSDATAFORMAT_WAVEFORMATEX
));
318 PC_ASSERT(IsEqualGUIDAligned(((PKSDATAFORMAT_WAVEFORMATEX
)NewDataFormat
)->DataFormat
.MajorFormat
, KSDATAFORMAT_TYPE_AUDIO
));
319 PC_ASSERT(IsEqualGUIDAligned(((PKSDATAFORMAT_WAVEFORMATEX
)NewDataFormat
)->DataFormat
.SubFormat
, KSDATAFORMAT_SUBTYPE_PCM
));
320 PC_ASSERT(IsEqualGUIDAligned(((PKSDATAFORMAT_WAVEFORMATEX
)NewDataFormat
)->DataFormat
.Specifier
, KSDATAFORMAT_SPECIFIER_WAVEFORMATEX
));
323 DPRINT1("NewDataFormat: Channels %u Bits %u Samples %u\n", ((PKSDATAFORMAT_WAVEFORMATEX
)NewDataFormat
)->WaveFormatEx
.nChannels
,
324 ((PKSDATAFORMAT_WAVEFORMATEX
)NewDataFormat
)->WaveFormatEx
.wBitsPerSample
,
325 ((PKSDATAFORMAT_WAVEFORMATEX
)NewDataFormat
)->WaveFormatEx
.nSamplesPerSec
);
331 // failed to set format
332 FreeItem(NewDataFormat
, TAG_PORTCLASS
);
339 else if (Request
->Flags
& KSPROPERTY_TYPE_GET
)
341 // get current data format
342 PC_ASSERT(Pin
->m_Format
);
344 if (Pin
->m_Format
->FormatSize
> IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
)
347 Irp
->IoStatus
.Information
= Pin
->m_Format
->FormatSize
;
348 return STATUS_MORE_ENTRIES
;
351 RtlMoveMemory(Data
, Pin
->m_Format
, Pin
->m_Format
->FormatSize
);
353 Irp
->IoStatus
.Information
= Pin
->m_Format
->FormatSize
;
356 return STATUS_SUCCESS
;
359 // unsupported request
360 return STATUS_NOT_SUPPORTED
;
365 CPortPinWaveCyclic::UpdateCommonBuffer(
367 ULONG MaxTransferCount
)
375 BufferLength
= Position
- m_CommonBufferOffset
;
376 BufferLength
= min(BufferLength
, MaxTransferCount
);
380 Status
= m_IrpQueue
->GetMapping(&Buffer
, &BufferSize
);
381 if (!NT_SUCCESS(Status
))
384 BytesToCopy
= min(BufferLength
, BufferSize
);
388 m_DmaChannel
->CopyFrom(Buffer
, (PUCHAR
)m_CommonBuffer
+ m_CommonBufferOffset
, BytesToCopy
);
392 m_DmaChannel
->CopyTo((PUCHAR
)m_CommonBuffer
+ m_CommonBufferOffset
, Buffer
, BytesToCopy
);
395 m_IrpQueue
->UpdateMapping(BytesToCopy
);
396 m_CommonBufferOffset
+= BytesToCopy
;
398 BufferLength
= Position
- m_CommonBufferOffset
;
399 m_Position
.PlayOffset
+= BytesToCopy
;
404 CPortPinWaveCyclic::UpdateCommonBufferOverlap(
406 ULONG MaxTransferCount
)
408 ULONG BufferLength
, Length
, Gap
;
415 BufferLength
= Gap
= m_CommonBufferSize
- m_CommonBufferOffset
;
416 BufferLength
= Length
= min(BufferLength
, MaxTransferCount
);
419 Status
= m_IrpQueue
->GetMapping(&Buffer
, &BufferSize
);
420 if (!NT_SUCCESS(Status
))
423 BytesToCopy
= min(BufferLength
, BufferSize
);
427 m_DmaChannel
->CopyFrom(Buffer
,
428 (PUCHAR
)m_CommonBuffer
+ m_CommonBufferOffset
,
433 m_DmaChannel
->CopyTo((PUCHAR
)m_CommonBuffer
+ m_CommonBufferOffset
,
438 m_IrpQueue
->UpdateMapping(BytesToCopy
);
439 m_CommonBufferOffset
+= BytesToCopy
;
440 m_Position
.PlayOffset
+= BytesToCopy
;
442 BufferLength
= m_CommonBufferSize
- m_CommonBufferOffset
;
447 m_CommonBufferOffset
= 0;
449 MaxTransferCount
-= Length
;
451 if (MaxTransferCount
)
453 UpdateCommonBuffer(Position
, MaxTransferCount
);
460 SetStreamWorkerRoutineWaveCyclic(
461 IN PDEVICE_OBJECT DeviceObject
,
464 CPortPinWaveCyclic
* This
;
465 PSETSTREAM_CONTEXT Ctx
= (PSETSTREAM_CONTEXT
)Context
;
467 ULONG MinimumDataThreshold
;
468 ULONG MaximumDataThreshold
;
473 IoFreeWorkItem(Ctx
->WorkItem
);
474 FreeItem(Ctx
, TAG_PORTCLASS
);
476 // Has the audio stream resumed?
477 if (This
->m_IrpQueue
->NumMappings() && State
== KSSTATE_STOP
)
480 // Has the audio state already been set?
481 if (This
->m_State
== State
)
485 if (NT_SUCCESS(This
->m_Stream
->SetState(State
)))
487 // Set internal state
488 This
->m_State
= State
;
490 if (This
->m_State
== KSSTATE_STOP
)
492 // reset start stream
493 This
->m_IrpQueue
->CancelBuffers(); //FIX function name
495 // increase stop counter
497 // get current data threshold
498 MinimumDataThreshold
= This
->m_IrpQueue
->GetMinimumDataThreshold();
499 // get maximum data threshold
500 MaximumDataThreshold
= ((PKSDATAFORMAT_WAVEFORMATEX
)This
->m_Format
)->WaveFormatEx
.nAvgBytesPerSec
;
501 // increase minimum data threshold by a third sec
502 MinimumDataThreshold
+= This
->m_FrameSize
* 10;
504 // assure it has not exceeded
505 MinimumDataThreshold
= min(MinimumDataThreshold
, MaximumDataThreshold
);
506 // store minimum data threshold
507 This
->m_IrpQueue
->SetMinimumDataThreshold(MinimumDataThreshold
);
509 DPRINT1("Stopping TotalPackets %u StopCount %u\n", This
->m_TotalPackets
, This
->m_StopCount
);
511 if (This
->m_State
== KSSTATE_RUN
)
513 DPRINT1("State RUN %x MinAvailable %u CommonBufferSize %u Offset %u\n", State
, This
->m_IrpQueue
->MinimumDataAvailable(), This
->m_CommonBufferSize
, This
->m_CommonBufferOffset
);
520 CPortPinWaveCyclic::SetStreamState(
523 PDEVICE_OBJECT DeviceObject
;
524 PIO_WORKITEM WorkItem
;
525 PSETSTREAM_CONTEXT Context
;
527 PC_ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL
);
529 // Has the audio stream resumed?
530 if (m_IrpQueue
->NumMappings() && State
== KSSTATE_STOP
)
533 // Has the audio state already been set?
534 if (m_State
== State
)
538 DeviceObject
= GetDeviceObject(m_Port
);
540 // allocate set state context
541 Context
= (PSETSTREAM_CONTEXT
)AllocateItem(NonPagedPool
, sizeof(SETSTREAM_CONTEXT
), TAG_PORTCLASS
);
546 // allocate work item
547 WorkItem
= IoAllocateWorkItem(DeviceObject
);
556 Context
->WorkItem
= WorkItem
;
557 Context
->State
= State
;
559 // queue the work item
560 IoQueueWorkItem(WorkItem
, SetStreamWorkerRoutineWaveCyclic
, DelayedWorkQueue
, (PVOID
)Context
);
565 CPortPinWaveCyclic::RequestService()
572 PC_ASSERT_IRQL(DISPATCH_LEVEL
);
574 Status
= m_IrpQueue
->GetMapping(&Buffer
, &BufferSize
);
575 if (!NT_SUCCESS(Status
))
577 //SetStreamState(This, KSSTATE_STOP);
581 Status
= m_Stream
->GetPosition(&Position
);
582 DPRINT1("Position %u Buffer %p BufferSize %u ActiveIrpOffset %u Capture %u\n", Position
, Buffer
, m_CommonBufferSize
, BufferSize
, m_Capture
);
584 if (Position
< m_CommonBufferOffset
)
586 UpdateCommonBufferOverlap(Position
, m_FrameSize
);
588 else if (Position
>= m_CommonBufferOffset
)
590 UpdateCommonBuffer(Position
, m_FrameSize
);
596 CPortPinWaveCyclic::NewIrpTarget(
597 OUT
struct IIrpTarget
**OutTarget
,
600 IN POOL_TYPE PoolType
,
601 IN PDEVICE_OBJECT DeviceObject
,
603 IN KSOBJECT_CREATE
*CreateObject
)
607 return STATUS_UNSUCCESSFUL
;
612 CPortPinWaveCyclic::HandleKsProperty(
615 PKSPROPERTY Property
;
617 UNICODE_STRING GuidString
;
618 PIO_STACK_LOCATION IoStack
;
620 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
622 DPRINT("IPortPinWave_HandleKsProperty entered\n");
624 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
626 if (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
!= IOCTL_KS_PROPERTY
)
628 DPRINT1("Unhandled function %lx Length %x\n", IoStack
->Parameters
.DeviceIoControl
.IoControlCode
, IoStack
->Parameters
.DeviceIoControl
.InputBufferLength
);
630 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
632 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
633 return STATUS_SUCCESS
;
636 Status
= PcHandlePropertyWithTable(Irp
, m_Descriptor
.FilterPropertySetCount
, m_Descriptor
.FilterPropertySet
, &m_Descriptor
);
638 if (Status
== STATUS_NOT_FOUND
)
640 Property
= (PKSPROPERTY
)IoStack
->Parameters
.DeviceIoControl
.Type3InputBuffer
;
642 RtlStringFromGUID(Property
->Set
, &GuidString
);
643 DPRINT1("Unhandeled property Set |%S| Id %u Flags %x\n", GuidString
.Buffer
, Property
->Id
, Property
->Flags
);
644 RtlFreeUnicodeString(&GuidString
);
647 if (Status
!= STATUS_PENDING
)
649 Irp
->IoStatus
.Status
= Status
;
650 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
658 CPortPinWaveCyclic::HandleKsStream(
662 InterlockedIncrement((PLONG
)&m_TotalPackets
);
664 DPRINT("IPortPinWaveCyclic_HandleKsStream entered Total %u State %x MinData %u\n", m_TotalPackets
, m_State
, m_IrpQueue
->NumData());
666 Status
= m_IrpQueue
->AddMapping(NULL
, 0, Irp
);
668 if (NT_SUCCESS(Status
))
671 PKSSTREAM_HEADER Header
= (PKSSTREAM_HEADER
)Irp
->AssociatedIrp
.SystemBuffer
;
675 m_Position
.WriteOffset
+= Header
->FrameExtent
;
677 m_Position
.WriteOffset
+= Header
->DataUsed
;
682 return STATUS_PENDING
;
687 CPortPinWaveCyclic::DeviceIoControl(
688 IN PDEVICE_OBJECT DeviceObject
,
691 PIO_STACK_LOCATION IoStack
;
693 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
696 if (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_KS_PROPERTY
)
698 return HandleKsProperty(Irp
);
700 else if (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_KS_ENABLE_EVENT
)
703 /// handle enable event
705 else if (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_KS_DISABLE_EVENT
)
708 /// handle disable event
710 else if (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_KS_RESET_STATE
)
713 /// handle reset state
715 else if (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_KS_WRITE_STREAM
|| IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_KS_READ_STREAM
)
717 return HandleKsStream(Irp
);
721 return KsDefaultDeviceIoCompletion(DeviceObject
, Irp
);
726 Irp
->IoStatus
.Information
= 0;
727 Irp
->IoStatus
.Status
= STATUS_UNSUCCESSFUL
;
728 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
730 return STATUS_UNSUCCESSFUL
;
735 CPortPinWaveCyclic::Read(
736 IN PDEVICE_OBJECT DeviceObject
,
739 return KsDispatchInvalidDeviceRequest(DeviceObject
, Irp
);
744 CPortPinWaveCyclic::Write(
745 IN PDEVICE_OBJECT DeviceObject
,
748 return KsDispatchInvalidDeviceRequest(DeviceObject
, Irp
);
753 CPortPinWaveCyclic::Flush(
754 IN PDEVICE_OBJECT DeviceObject
,
757 return KsDispatchInvalidDeviceRequest(DeviceObject
, Irp
);
762 CloseStreamRoutineWaveCyclic(
763 IN PDEVICE_OBJECT DeviceObject
,
766 PMINIPORTWAVECYCLICSTREAM Stream
;
767 CPortPinWaveCyclic
* This
;
769 PCLOSESTREAM_CONTEXT Ctx
= (PCLOSESTREAM_CONTEXT
)Context
;
771 This
= (CPortPinWaveCyclic
*)Ctx
->Pin
;
773 if (This
->m_State
!= KSSTATE_STOP
)
775 // stop stream in case it hasn't been
776 Status
= This
->m_Stream
->SetState(KSSTATE_STOP
);
777 if (!NT_SUCCESS(Status
))
778 DPRINT1("Warning: failed to stop stream with %x\n", Status
);
780 This
->m_State
= KSSTATE_STOP
;
786 ExFreePool(This
->m_Format
);
787 This
->m_Format
= NULL
;
790 if (This
->m_IrpQueue
)
792 This
->m_IrpQueue
->Release();
796 Ctx
->Irp
->IoStatus
.Information
= 0;
797 Ctx
->Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
798 IoCompleteRequest(Ctx
->Irp
, IO_NO_INCREMENT
);
800 // free the work item
801 IoFreeWorkItem(Ctx
->WorkItem
);
803 // free work item ctx
804 FreeItem(Ctx
, TAG_PORTCLASS
);
806 // release reference to port driver
807 This
->m_Port
->Release();
809 // release reference to filter instance
810 This
->m_Filter
->Release();
814 Stream
= This
->m_Stream
;
815 This
->m_Stream
= NULL
;
816 This
->m_Filter
->FreePin(This
);
817 DPRINT1("Closing stream at Irql %u\n", KeGetCurrentIrql());
824 CPortPinWaveCyclic::Close(
825 IN PDEVICE_OBJECT DeviceObject
,
828 PCLOSESTREAM_CONTEXT Ctx
;
830 DPRINT1("CPortPinWaveCyclic::Close entered\n");
834 // allocate a close context
835 Ctx
= (PCLOSESTREAM_CONTEXT
)AllocateItem(NonPagedPool
, sizeof(CLOSESTREAM_CONTEXT
), TAG_PORTCLASS
);
838 DPRINT1("Failed to allocate stream context\n");
841 // allocate work context
842 Ctx
->WorkItem
= IoAllocateWorkItem(DeviceObject
);
845 DPRINT1("Failed to allocate work item\n");
848 // setup the close context
852 IoMarkIrpPending(Irp
);
853 Irp
->IoStatus
.Information
= 0;
854 Irp
->IoStatus
.Status
= STATUS_PENDING
;
856 // remove member from service group
857 m_ServiceGroup
->RemoveMember(PSERVICESINK(this));
860 IoQueueWorkItem(Ctx
->WorkItem
, CloseStreamRoutineWaveCyclic
, DelayedWorkQueue
, (PVOID
)Ctx
);
862 return STATUS_PENDING
;
865 Irp
->IoStatus
.Information
= 0;
866 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
867 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
869 return STATUS_SUCCESS
;
874 FreeItem(Ctx
, TAG_PORTCLASS
);
876 Irp
->IoStatus
.Information
= 0;
877 Irp
->IoStatus
.Status
= STATUS_UNSUCCESSFUL
;
878 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
879 return STATUS_UNSUCCESSFUL
;
885 CPortPinWaveCyclic::QuerySecurity(
886 IN PDEVICE_OBJECT DeviceObject
,
889 return KsDispatchInvalidDeviceRequest(DeviceObject
, Irp
);
894 CPortPinWaveCyclic::SetSecurity(
895 IN PDEVICE_OBJECT DeviceObject
,
898 return KsDispatchInvalidDeviceRequest(DeviceObject
, Irp
);
903 CPortPinWaveCyclic::FastDeviceIoControl(
904 IN PFILE_OBJECT FileObject
,
906 IN PVOID InputBuffer
,
907 IN ULONG InputBufferLength
,
908 OUT PVOID OutputBuffer
,
909 IN ULONG OutputBufferLength
,
910 IN ULONG IoControlCode
,
911 OUT PIO_STATUS_BLOCK StatusBlock
,
912 IN PDEVICE_OBJECT DeviceObject
)
914 return KsDispatchFastIoDeviceControlFailure(FileObject
, Wait
, InputBuffer
, InputBufferLength
, OutputBuffer
, OutputBufferLength
, IoControlCode
, StatusBlock
, DeviceObject
);
920 CPortPinWaveCyclic::FastRead(
921 IN PFILE_OBJECT FileObject
,
922 IN PLARGE_INTEGER FileOffset
,
927 OUT PIO_STATUS_BLOCK StatusBlock
,
928 IN PDEVICE_OBJECT DeviceObject
)
930 return KsDispatchFastReadFailure(FileObject
, FileOffset
, Length
, Wait
, LockKey
, Buffer
, StatusBlock
, DeviceObject
);
936 CPortPinWaveCyclic::FastWrite(
937 IN PFILE_OBJECT FileObject
,
938 IN PLARGE_INTEGER FileOffset
,
943 OUT PIO_STATUS_BLOCK StatusBlock
,
944 IN PDEVICE_OBJECT DeviceObject
)
946 return KsDispatchFastReadFailure(FileObject
, FileOffset
, Length
, Wait
, LockKey
, Buffer
, StatusBlock
, DeviceObject
);
952 CPortPinWaveCyclic::Init(
953 IN PPORTWAVECYCLIC Port
,
954 IN PPORTFILTERWAVECYCLIC Filter
,
955 IN KSPIN_CONNECT
* ConnectDetails
,
956 IN KSPIN_DESCRIPTOR
* KsPinDescriptor
)
959 PKSDATAFORMAT DataFormat
;
960 PDEVICE_OBJECT DeviceObject
;
963 //IDrmAudioStream * DrmAudio = NULL;
965 m_KsPinDescriptor
= KsPinDescriptor
;
966 m_ConnectDetails
= ConnectDetails
;
967 m_Miniport
= GetWaveCyclicMiniport(Port
);
969 DeviceObject
= GetDeviceObject(Port
);
971 DataFormat
= (PKSDATAFORMAT
)(ConnectDetails
+ 1);
973 DPRINT("CPortPinWaveCyclic::Init entered Size %u\n", DataFormat
->FormatSize
);
975 Status
= NewIrpQueue(&m_IrpQueue
);
976 if (!NT_SUCCESS(Status
))
979 if (KsPinDescriptor
->Communication
== KSPIN_COMMUNICATION_SINK
&& KsPinDescriptor
->DataFlow
== KSPIN_DATAFLOW_IN
)
983 else if (KsPinDescriptor
->Communication
== KSPIN_COMMUNICATION_SINK
&& KsPinDescriptor
->DataFlow
== KSPIN_DATAFLOW_OUT
)
989 DPRINT1("Unexpected Communication %u DataFlow %u\n", KsPinDescriptor
->Communication
, KsPinDescriptor
->DataFlow
);
994 Status
= m_Miniport
->NewStream(&m_Stream
,
997 ConnectDetails
->PinId
,
1003 Status
= m_Stream
->QueryInterface(IID_IDrmAudioStream
, (PVOID
*)&DrmAudio
);
1004 if (NT_SUCCESS(Status
))
1006 DRMRIGHTS DrmRights
;
1007 DPRINT1("Got IID_IDrmAudioStream interface %p\n", DrmAudio
);
1009 DrmRights
.CopyProtect
= FALSE
;
1010 DrmRights
.Reserved
= 0;
1011 DrmRights
.DigitalOutputDisable
= FALSE
;
1013 Status
= DrmAudio
->SetContentId(1, &DrmRights
);
1014 DPRINT("Status %x\n", Status
);
1018 if (!NT_SUCCESS(Status
))
1021 ISubdevice
* Subdevice
= NULL
;
1022 // get subdevice interface
1023 Status
= Port
->QueryInterface(IID_ISubdevice
, (PVOID
*)&Subdevice
);
1025 if (!NT_SUCCESS(Status
))
1028 PSUBDEVICE_DESCRIPTOR SubDeviceDescriptor
= NULL
;
1030 Status
= Subdevice
->GetDescriptor(&SubDeviceDescriptor
);
1031 if (!NT_SUCCESS(Status
))
1033 // failed to get descriptor
1034 Subdevice
->Release();
1038 /* set up subdevice descriptor */
1039 RtlZeroMemory(&m_Descriptor
, sizeof(SUBDEVICE_DESCRIPTOR
));
1040 m_Descriptor
.FilterPropertySet
= PinWaveCyclicPropertySet
;
1041 m_Descriptor
.FilterPropertySetCount
= sizeof(PinWaveCyclicPropertySet
) / sizeof(KSPROPERTY_SET
);
1042 m_Descriptor
.UnknownStream
= (PUNKNOWN
)m_Stream
;
1043 m_Descriptor
.DeviceDescriptor
= SubDeviceDescriptor
->DeviceDescriptor
;
1044 m_Descriptor
.UnknownMiniport
= SubDeviceDescriptor
->UnknownMiniport
;
1045 m_Descriptor
.PortPin
= (PVOID
)this;
1047 DPRINT("CPortPinWaveCyclic::Init Status %x\n", Status
);
1049 // release subdevice descriptor
1050 Subdevice
->Release();
1052 Status
= m_ServiceGroup
->AddMember(PSERVICESINK(this));
1053 if (!NT_SUCCESS(Status
))
1055 DPRINT1("Failed to add pin to service group\n");
1059 m_ServiceGroup
->SupportDelayedService();
1060 m_Stream
->SetState(KSSTATE_STOP
);
1061 m_State
= KSSTATE_STOP
;
1062 m_CommonBufferOffset
= 0;
1063 m_CommonBufferSize
= m_DmaChannel
->AllocatedBufferSize();
1064 m_CommonBuffer
= m_DmaChannel
->SystemAddress();
1065 m_Capture
= Capture
;
1066 // delay of 10 milisec
1067 m_Delay
= Int32x32To64(10, -10000);
1069 Status
= m_Stream
->SetNotificationFreq(10, &m_FrameSize
);
1071 SilenceBuffer
= AllocateItem(NonPagedPool
, m_FrameSize
, TAG_PORTCLASS
);
1073 return STATUS_INSUFFICIENT_RESOURCES
;
1075 m_Stream
->Silence(SilenceBuffer
, m_FrameSize
);
1077 Status
= m_IrpQueue
->Init(ConnectDetails
, DataFormat
, DeviceObject
, m_FrameSize
, 0, SilenceBuffer
);
1078 if (!NT_SUCCESS(Status
))
1080 m_IrpQueue
->Release();
1084 m_Format
= (PKSDATAFORMAT
)AllocateItem(NonPagedPool
, DataFormat
->FormatSize
, TAG_PORTCLASS
);
1086 return STATUS_INSUFFICIENT_RESOURCES
;
1088 RtlMoveMemory(m_Format
, DataFormat
, DataFormat
->FormatSize
);
1097 DPRINT1("Setting state to acquire %x\n", m_Stream
->SetState(KSSTATE_ACQUIRE
));
1098 DPRINT1("Setting state to pause %x\n", m_Stream
->SetState(KSSTATE_PAUSE
));
1099 m_State
= KSSTATE_PAUSE
;
1102 return STATUS_SUCCESS
;
1108 CPortPinWaveCyclic::GetCompletedPosition()
1117 CPortPinWaveCyclic::GetCycleCount()
1126 CPortPinWaveCyclic::GetDeviceBufferSize()
1128 return m_CommonBufferSize
;
1134 CPortPinWaveCyclic::GetIrpStream()
1136 return (PVOID
)m_IrpQueue
;
1142 CPortPinWaveCyclic::GetMiniport()
1144 return (PMINIPORT
)m_Miniport
;
1149 NewPortPinWaveCyclic(
1150 OUT IPortPinWaveCyclic
** OutPin
)
1152 CPortPinWaveCyclic
* This
;
1154 This
= new(NonPagedPool
, TAG_PORTCLASS
)CPortPinWaveCyclic(NULL
);
1156 return STATUS_INSUFFICIENT_RESOURCES
;
1161 *OutPin
= (IPortPinWaveCyclic
*)This
;
1163 return STATUS_SUCCESS
;