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
);
54 friend NTSTATUS NTAPI
PinWaveCyclicAllocatorFraming(IN PIRP Irp
, IN PKSIDENTIFIER Request
, IN OUT PVOID Data
);
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 KSPIN_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
;
90 CPortPinWaveCyclic
*Pin
;
91 PIO_WORKITEM WorkItem
;
93 }SETSTREAM_CONTEXT
, *PSETSTREAM_CONTEXT
;
95 NTSTATUS NTAPI
PinWaveCyclicState(IN PIRP Irp
, IN PKSIDENTIFIER Request
, IN OUT PVOID Data
);
96 NTSTATUS NTAPI
PinWaveCyclicDataFormat(IN PIRP Irp
, IN PKSIDENTIFIER Request
, IN OUT PVOID Data
);
97 NTSTATUS NTAPI
PinWaveCyclicAudioPosition(IN PIRP Irp
, IN PKSIDENTIFIER Request
, IN OUT PVOID Data
);
98 NTSTATUS NTAPI
PinWaveCyclicAllocatorFraming(IN PIRP Irp
, IN PKSIDENTIFIER Request
, IN OUT PVOID Data
);
100 DEFINE_KSPROPERTY_CONNECTIONSET(PinWaveCyclicConnectionSet
, PinWaveCyclicState
, PinWaveCyclicDataFormat
, PinWaveCyclicAllocatorFraming
);
101 DEFINE_KSPROPERTY_AUDIOSET(PinWaveCyclicAudioSet
, PinWaveCyclicAudioPosition
);
103 KSPROPERTY_SET PinWaveCyclicPropertySet
[] =
106 &KSPROPSETID_Connection
,
107 sizeof(PinWaveCyclicConnectionSet
) / sizeof(KSPROPERTY_ITEM
),
108 (const KSPROPERTY_ITEM
*)&PinWaveCyclicConnectionSet
,
114 sizeof(PinWaveCyclicAudioSet
) / sizeof(KSPROPERTY_ITEM
),
115 (const KSPROPERTY_ITEM
*)&PinWaveCyclicAudioSet
,
121 //==================================================================================================================================
125 CPortPinWaveCyclic::QueryInterface(
129 DPRINT("IServiceSink_fnQueryInterface entered\n");
131 if (IsEqualGUIDAligned(refiid
, IID_IIrpTarget
) ||
132 IsEqualGUIDAligned(refiid
, IID_IUnknown
))
134 *Output
= PVOID(PUNKNOWN((IIrpTarget
*)this));
135 PUNKNOWN(*Output
)->AddRef();
136 return STATUS_SUCCESS
;
139 if (IsEqualGUIDAligned(refiid
, IID_IServiceSink
))
141 *Output
= PVOID(PUNKNOWN(PSERVICESINK(this)));
142 PUNKNOWN(*Output
)->AddRef();
143 return STATUS_SUCCESS
;
146 return STATUS_UNSUCCESSFUL
;
151 PinWaveCyclicAllocatorFraming(
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 if (Request
->Flags
& KSPROPERTY_TYPE_GET
)
174 RtlMoveMemory(Data
, &Pin
->m_AllocatorFraming
, sizeof(KSALLOCATOR_FRAMING
));
176 Irp
->IoStatus
.Information
= sizeof(KSALLOCATOR_FRAMING
);
177 return STATUS_SUCCESS
;
181 return STATUS_NOT_SUPPORTED
;
186 PinWaveCyclicAudioPosition(
188 IN PKSIDENTIFIER Request
,
191 CPortPinWaveCyclic
*Pin
;
192 PSUBDEVICE_DESCRIPTOR Descriptor
;
194 // get sub device descriptor
195 Descriptor
= (PSUBDEVICE_DESCRIPTOR
)KSPROPERTY_ITEM_IRP_STORAGE(Irp
);
198 PC_ASSERT(Descriptor
);
199 PC_ASSERT(Descriptor
->PortPin
);
200 PC_ASSERT_IRQL(DISPATCH_LEVEL
);
203 Pin
= (CPortPinWaveCyclic
*)Descriptor
->PortPin
;
206 PC_ASSERT(Pin
->m_Stream
);
208 if (Request
->Flags
& KSPROPERTY_TYPE_GET
)
210 // FIXME non multithreading-safe
211 // copy audio position
212 RtlMoveMemory(Data
, &Pin
->m_Position
, sizeof(KSAUDIO_POSITION
));
214 DPRINT1("Play %lu Record %lu\n", Pin
->m_Position
.PlayOffset
, Pin
->m_Position
.WriteOffset
);
215 Irp
->IoStatus
.Information
= sizeof(KSAUDIO_POSITION
);
216 return STATUS_SUCCESS
;
220 return STATUS_NOT_SUPPORTED
;
228 IN PKSIDENTIFIER Request
,
231 NTSTATUS Status
= STATUS_UNSUCCESSFUL
;
232 CPortPinWaveCyclic
*Pin
;
233 PSUBDEVICE_DESCRIPTOR Descriptor
;
234 PKSSTATE State
= (PKSSTATE
)Data
;
236 // get sub device descriptor
237 Descriptor
= (PSUBDEVICE_DESCRIPTOR
)KSPROPERTY_ITEM_IRP_STORAGE(Irp
);
240 PC_ASSERT(Descriptor
);
241 PC_ASSERT(Descriptor
->PortPin
);
242 PC_ASSERT_IRQL(DISPATCH_LEVEL
);
245 Pin
= (CPortPinWaveCyclic
*)Descriptor
->PortPin
;
248 PC_ASSERT(Pin
->m_Stream
);
250 if (Request
->Flags
& KSPROPERTY_TYPE_SET
)
253 Status
= Pin
->m_Stream
->SetState(*State
);
255 DPRINT("Setting state %u %x\n", *State
, Status
);
256 if (NT_SUCCESS(Status
))
259 Pin
->m_State
= *State
;
262 Irp
->IoStatus
.Information
= sizeof(KSSTATE
);
265 else if (Request
->Flags
& KSPROPERTY_TYPE_GET
)
267 // get current stream state
268 *State
= Pin
->m_State
;
270 Irp
->IoStatus
.Information
= sizeof(KSSTATE
);
272 return STATUS_SUCCESS
;
275 // unsupported request
276 return STATUS_NOT_SUPPORTED
;
281 PinWaveCyclicDataFormat(
283 IN PKSIDENTIFIER Request
,
286 NTSTATUS Status
= STATUS_UNSUCCESSFUL
;
287 CPortPinWaveCyclic
*Pin
;
288 PSUBDEVICE_DESCRIPTOR Descriptor
;
289 PIO_STACK_LOCATION IoStack
;
291 // get current irp stack location
292 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
294 // get sub device descriptor
295 Descriptor
= (PSUBDEVICE_DESCRIPTOR
)KSPROPERTY_ITEM_IRP_STORAGE(Irp
);
298 PC_ASSERT(Descriptor
);
299 PC_ASSERT(Descriptor
->PortPin
);
302 Pin
= (CPortPinWaveCyclic
*)Descriptor
->PortPin
;
305 PC_ASSERT(Pin
->m_Stream
);
306 PC_ASSERT(Pin
->m_Format
);
308 if (Request
->Flags
& KSPROPERTY_TYPE_SET
)
310 // try to change data format
311 PKSDATAFORMAT NewDataFormat
, DataFormat
= (PKSDATAFORMAT
)Irp
->UserBuffer
;
312 ULONG Size
= min(Pin
->m_Format
->FormatSize
, DataFormat
->FormatSize
);
314 if (RtlCompareMemory(DataFormat
, Pin
->m_Format
, Size
) == Size
)
316 // format is identical
317 Irp
->IoStatus
.Information
= DataFormat
->FormatSize
;
318 return STATUS_SUCCESS
;
321 // new change request
322 PC_ASSERT(Pin
->m_State
== KSSTATE_STOP
);
323 // FIXME queue a work item when Irql != PASSIVE_LEVEL
324 PC_ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL
);
326 // allocate new data format
327 NewDataFormat
= (PKSDATAFORMAT
)AllocateItem(NonPagedPool
, DataFormat
->FormatSize
, TAG_PORTCLASS
);
331 return STATUS_NO_MEMORY
;
334 // copy new data format
335 RtlMoveMemory(NewDataFormat
, DataFormat
, DataFormat
->FormatSize
);
338 Status
= Pin
->m_Stream
->SetFormat(NewDataFormat
);
339 if (NT_SUCCESS(Status
))
342 FreeItem(Pin
->m_Format
, TAG_PORTCLASS
);
344 // update irp queue with new format
345 Pin
->m_IrpQueue
->UpdateFormat((PKSDATAFORMAT
)NewDataFormat
);
348 Pin
->m_Format
= NewDataFormat
;
349 Irp
->IoStatus
.Information
= NewDataFormat
->FormatSize
;
352 PC_ASSERT(NewDataFormat
->FormatSize
== sizeof(KSDATAFORMAT_WAVEFORMATEX
));
353 PC_ASSERT(IsEqualGUIDAligned(((PKSDATAFORMAT_WAVEFORMATEX
)NewDataFormat
)->DataFormat
.MajorFormat
, KSDATAFORMAT_TYPE_AUDIO
));
354 PC_ASSERT(IsEqualGUIDAligned(((PKSDATAFORMAT_WAVEFORMATEX
)NewDataFormat
)->DataFormat
.SubFormat
, KSDATAFORMAT_SUBTYPE_PCM
));
355 PC_ASSERT(IsEqualGUIDAligned(((PKSDATAFORMAT_WAVEFORMATEX
)NewDataFormat
)->DataFormat
.Specifier
, KSDATAFORMAT_SPECIFIER_WAVEFORMATEX
));
358 DPRINT1("NewDataFormat: Channels %u Bits %u Samples %u\n", ((PKSDATAFORMAT_WAVEFORMATEX
)NewDataFormat
)->WaveFormatEx
.nChannels
,
359 ((PKSDATAFORMAT_WAVEFORMATEX
)NewDataFormat
)->WaveFormatEx
.wBitsPerSample
,
360 ((PKSDATAFORMAT_WAVEFORMATEX
)NewDataFormat
)->WaveFormatEx
.nSamplesPerSec
);
366 // failed to set format
367 FreeItem(NewDataFormat
, TAG_PORTCLASS
);
374 else if (Request
->Flags
& KSPROPERTY_TYPE_GET
)
376 // get current data format
377 PC_ASSERT(Pin
->m_Format
);
379 if (Pin
->m_Format
->FormatSize
> IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
)
382 Irp
->IoStatus
.Information
= Pin
->m_Format
->FormatSize
;
383 return STATUS_MORE_ENTRIES
;
386 RtlMoveMemory(Data
, Pin
->m_Format
, Pin
->m_Format
->FormatSize
);
388 Irp
->IoStatus
.Information
= Pin
->m_Format
->FormatSize
;
391 return STATUS_SUCCESS
;
394 // unsupported request
395 return STATUS_NOT_SUPPORTED
;
400 CPortPinWaveCyclic::UpdateCommonBuffer(
402 ULONG MaxTransferCount
)
410 BufferLength
= Position
- m_CommonBufferOffset
;
411 BufferLength
= min(BufferLength
, MaxTransferCount
);
415 Status
= m_IrpQueue
->GetMapping(&Buffer
, &BufferSize
);
416 if (!NT_SUCCESS(Status
))
419 BytesToCopy
= min(BufferLength
, BufferSize
);
423 m_DmaChannel
->CopyFrom(Buffer
, (PUCHAR
)m_CommonBuffer
+ m_CommonBufferOffset
, BytesToCopy
);
427 m_DmaChannel
->CopyTo((PUCHAR
)m_CommonBuffer
+ m_CommonBufferOffset
, Buffer
, BytesToCopy
);
430 m_IrpQueue
->UpdateMapping(BytesToCopy
);
431 m_CommonBufferOffset
+= BytesToCopy
;
433 BufferLength
= Position
- m_CommonBufferOffset
;
434 m_Position
.PlayOffset
+= BytesToCopy
;
439 CPortPinWaveCyclic::UpdateCommonBufferOverlap(
441 ULONG MaxTransferCount
)
443 ULONG BufferLength
, Length
, Gap
;
450 BufferLength
= Gap
= m_CommonBufferSize
- m_CommonBufferOffset
;
451 BufferLength
= Length
= min(BufferLength
, MaxTransferCount
);
454 Status
= m_IrpQueue
->GetMapping(&Buffer
, &BufferSize
);
455 if (!NT_SUCCESS(Status
))
458 BytesToCopy
= min(BufferLength
, BufferSize
);
462 m_DmaChannel
->CopyFrom(Buffer
,
463 (PUCHAR
)m_CommonBuffer
+ m_CommonBufferOffset
,
468 m_DmaChannel
->CopyTo((PUCHAR
)m_CommonBuffer
+ m_CommonBufferOffset
,
473 m_IrpQueue
->UpdateMapping(BytesToCopy
);
474 m_CommonBufferOffset
+= BytesToCopy
;
475 m_Position
.PlayOffset
+= BytesToCopy
;
477 BufferLength
= m_CommonBufferSize
- m_CommonBufferOffset
;
482 m_CommonBufferOffset
= 0;
484 MaxTransferCount
-= Length
;
486 if (MaxTransferCount
)
488 UpdateCommonBuffer(Position
, MaxTransferCount
);
495 SetStreamWorkerRoutineWaveCyclic(
496 IN PDEVICE_OBJECT DeviceObject
,
499 CPortPinWaveCyclic
* This
;
500 PSETSTREAM_CONTEXT Ctx
= (PSETSTREAM_CONTEXT
)Context
;
502 ULONG MinimumDataThreshold
;
503 ULONG MaximumDataThreshold
;
508 IoFreeWorkItem(Ctx
->WorkItem
);
509 FreeItem(Ctx
, TAG_PORTCLASS
);
511 // Has the audio stream resumed?
512 if (This
->m_IrpQueue
->NumMappings() && State
== KSSTATE_STOP
)
515 // Has the audio state already been set?
516 if (This
->m_State
== State
)
520 if (NT_SUCCESS(This
->m_Stream
->SetState(State
)))
522 // Set internal state
523 This
->m_State
= State
;
525 if (This
->m_State
== KSSTATE_STOP
)
527 // reset start stream
528 This
->m_IrpQueue
->CancelBuffers(); //FIX function name
530 // increase stop counter
532 // get current data threshold
533 MinimumDataThreshold
= This
->m_IrpQueue
->GetMinimumDataThreshold();
534 // get maximum data threshold
535 MaximumDataThreshold
= ((PKSDATAFORMAT_WAVEFORMATEX
)This
->m_Format
)->WaveFormatEx
.nAvgBytesPerSec
;
536 // increase minimum data threshold by a third sec
537 MinimumDataThreshold
+= This
->m_FrameSize
* 10;
539 // assure it has not exceeded
540 MinimumDataThreshold
= min(MinimumDataThreshold
, MaximumDataThreshold
);
541 // store minimum data threshold
542 This
->m_IrpQueue
->SetMinimumDataThreshold(MinimumDataThreshold
);
544 DPRINT1("Stopping TotalPackets %u StopCount %u\n", This
->m_TotalPackets
, This
->m_StopCount
);
546 if (This
->m_State
== KSSTATE_RUN
)
548 DPRINT1("State RUN %x MinAvailable %u CommonBufferSize %u Offset %u\n", State
, This
->m_IrpQueue
->MinimumDataAvailable(), This
->m_CommonBufferSize
, This
->m_CommonBufferOffset
);
555 CPortPinWaveCyclic::SetStreamState(
558 PDEVICE_OBJECT DeviceObject
;
559 PIO_WORKITEM WorkItem
;
560 PSETSTREAM_CONTEXT Context
;
562 PC_ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL
);
564 // Has the audio stream resumed?
565 if (m_IrpQueue
->NumMappings() && State
== KSSTATE_STOP
)
568 // Has the audio state already been set?
569 if (m_State
== State
)
573 DeviceObject
= GetDeviceObject(m_Port
);
575 // allocate set state context
576 Context
= (PSETSTREAM_CONTEXT
)AllocateItem(NonPagedPool
, sizeof(SETSTREAM_CONTEXT
), TAG_PORTCLASS
);
581 // allocate work item
582 WorkItem
= IoAllocateWorkItem(DeviceObject
);
591 Context
->WorkItem
= WorkItem
;
592 Context
->State
= State
;
594 // queue the work item
595 IoQueueWorkItem(WorkItem
, SetStreamWorkerRoutineWaveCyclic
, DelayedWorkQueue
, (PVOID
)Context
);
600 CPortPinWaveCyclic::RequestService()
607 PC_ASSERT_IRQL(DISPATCH_LEVEL
);
609 Status
= m_IrpQueue
->GetMapping(&Buffer
, &BufferSize
);
610 if (!NT_SUCCESS(Status
))
612 //SetStreamState(This, KSSTATE_STOP);
616 Status
= m_Stream
->GetPosition(&Position
);
617 DPRINT("Position %u Buffer %p BufferSize %u ActiveIrpOffset %u Capture %u\n", Position
, Buffer
, m_CommonBufferSize
, BufferSize
, m_Capture
);
619 if (Position
< m_CommonBufferOffset
)
621 UpdateCommonBufferOverlap(Position
, m_FrameSize
);
623 else if (Position
>= m_CommonBufferOffset
)
625 UpdateCommonBuffer(Position
, m_FrameSize
);
631 CPortPinWaveCyclic::NewIrpTarget(
632 OUT
struct IIrpTarget
**OutTarget
,
635 IN POOL_TYPE PoolType
,
636 IN PDEVICE_OBJECT DeviceObject
,
638 IN KSOBJECT_CREATE
*CreateObject
)
642 return STATUS_UNSUCCESSFUL
;
647 CPortPinWaveCyclic::HandleKsProperty(
650 PKSPROPERTY Property
;
652 UNICODE_STRING GuidString
;
653 PIO_STACK_LOCATION IoStack
;
655 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
657 DPRINT("IPortPinWave_HandleKsProperty entered\n");
659 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
661 if (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
!= IOCTL_KS_PROPERTY
)
663 DPRINT1("Unhandled function %lx Length %x\n", IoStack
->Parameters
.DeviceIoControl
.IoControlCode
, IoStack
->Parameters
.DeviceIoControl
.InputBufferLength
);
665 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
667 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
668 return STATUS_SUCCESS
;
671 Status
= PcHandlePropertyWithTable(Irp
, m_Descriptor
.FilterPropertySetCount
, m_Descriptor
.FilterPropertySet
, &m_Descriptor
);
673 if (Status
== STATUS_NOT_FOUND
)
675 Property
= (PKSPROPERTY
)IoStack
->Parameters
.DeviceIoControl
.Type3InputBuffer
;
677 RtlStringFromGUID(Property
->Set
, &GuidString
);
678 DPRINT1("Unhandeled property Set |%S| Id %u Flags %x\n", GuidString
.Buffer
, Property
->Id
, Property
->Flags
);
679 RtlFreeUnicodeString(&GuidString
);
682 if (Status
!= STATUS_PENDING
)
684 Irp
->IoStatus
.Status
= Status
;
685 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
693 CPortPinWaveCyclic::HandleKsStream(
697 InterlockedIncrement((PLONG
)&m_TotalPackets
);
699 DPRINT("IPortPinWaveCyclic_HandleKsStream entered Total %u State %x MinData %u\n", m_TotalPackets
, m_State
, m_IrpQueue
->NumData());
701 Status
= m_IrpQueue
->AddMapping(NULL
, 0, Irp
);
703 if (NT_SUCCESS(Status
))
706 PKSSTREAM_HEADER Header
= (PKSSTREAM_HEADER
)Irp
->AssociatedIrp
.SystemBuffer
;
710 m_Position
.WriteOffset
+= Header
->FrameExtent
;
712 m_Position
.WriteOffset
+= Header
->DataUsed
;
717 return STATUS_PENDING
;
722 CPortPinWaveCyclic::DeviceIoControl(
723 IN PDEVICE_OBJECT DeviceObject
,
726 PIO_STACK_LOCATION IoStack
;
728 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
731 if (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_KS_PROPERTY
)
733 return HandleKsProperty(Irp
);
735 else if (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_KS_ENABLE_EVENT
)
738 /// handle enable event
740 else if (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_KS_DISABLE_EVENT
)
743 /// handle disable event
745 else if (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_KS_RESET_STATE
)
748 /// handle reset state
750 else if (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_KS_WRITE_STREAM
|| IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_KS_READ_STREAM
)
752 return HandleKsStream(Irp
);
756 return KsDefaultDeviceIoCompletion(DeviceObject
, Irp
);
761 Irp
->IoStatus
.Information
= 0;
762 Irp
->IoStatus
.Status
= STATUS_UNSUCCESSFUL
;
763 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
765 return STATUS_UNSUCCESSFUL
;
770 CPortPinWaveCyclic::Read(
771 IN PDEVICE_OBJECT DeviceObject
,
774 return KsDispatchInvalidDeviceRequest(DeviceObject
, Irp
);
779 CPortPinWaveCyclic::Write(
780 IN PDEVICE_OBJECT DeviceObject
,
783 return KsDispatchInvalidDeviceRequest(DeviceObject
, Irp
);
788 CPortPinWaveCyclic::Flush(
789 IN PDEVICE_OBJECT DeviceObject
,
792 return KsDispatchInvalidDeviceRequest(DeviceObject
, Irp
);
797 CloseStreamRoutineWaveCyclic(
798 IN PDEVICE_OBJECT DeviceObject
,
801 PMINIPORTWAVECYCLICSTREAM Stream
;
802 CPortPinWaveCyclic
* This
;
804 PCLOSESTREAM_CONTEXT Ctx
= (PCLOSESTREAM_CONTEXT
)Context
;
806 This
= (CPortPinWaveCyclic
*)Ctx
->Pin
;
808 if (This
->m_State
!= KSSTATE_STOP
)
810 // stop stream in case it hasn't been
811 Status
= This
->m_Stream
->SetState(KSSTATE_STOP
);
812 if (!NT_SUCCESS(Status
))
813 DPRINT1("Warning: failed to stop stream with %x\n", Status
);
815 This
->m_State
= KSSTATE_STOP
;
821 ExFreePool(This
->m_Format
);
822 This
->m_Format
= NULL
;
825 if (This
->m_IrpQueue
)
827 This
->m_IrpQueue
->Release();
831 Ctx
->Irp
->IoStatus
.Information
= 0;
832 Ctx
->Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
833 IoCompleteRequest(Ctx
->Irp
, IO_NO_INCREMENT
);
835 // free the work item
836 IoFreeWorkItem(Ctx
->WorkItem
);
838 // free work item ctx
839 FreeItem(Ctx
, TAG_PORTCLASS
);
841 // release reference to port driver
842 This
->m_Port
->Release();
844 // release reference to filter instance
845 This
->m_Filter
->Release();
849 Stream
= This
->m_Stream
;
850 This
->m_Stream
= NULL
;
851 This
->m_Filter
->FreePin(This
);
852 DPRINT1("Closing stream at Irql %u\n", KeGetCurrentIrql());
859 CPortPinWaveCyclic::Close(
860 IN PDEVICE_OBJECT DeviceObject
,
863 PCLOSESTREAM_CONTEXT Ctx
;
865 DPRINT1("CPortPinWaveCyclic::Close entered\n");
869 // allocate a close context
870 Ctx
= (PCLOSESTREAM_CONTEXT
)AllocateItem(NonPagedPool
, sizeof(CLOSESTREAM_CONTEXT
), TAG_PORTCLASS
);
873 DPRINT1("Failed to allocate stream context\n");
876 // allocate work context
877 Ctx
->WorkItem
= IoAllocateWorkItem(DeviceObject
);
880 DPRINT1("Failed to allocate work item\n");
883 // setup the close context
887 IoMarkIrpPending(Irp
);
888 Irp
->IoStatus
.Information
= 0;
889 Irp
->IoStatus
.Status
= STATUS_PENDING
;
891 // remove member from service group
892 m_ServiceGroup
->RemoveMember(PSERVICESINK(this));
895 IoQueueWorkItem(Ctx
->WorkItem
, CloseStreamRoutineWaveCyclic
, DelayedWorkQueue
, (PVOID
)Ctx
);
897 return STATUS_PENDING
;
900 Irp
->IoStatus
.Information
= 0;
901 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
902 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
904 return STATUS_SUCCESS
;
909 FreeItem(Ctx
, TAG_PORTCLASS
);
911 Irp
->IoStatus
.Information
= 0;
912 Irp
->IoStatus
.Status
= STATUS_UNSUCCESSFUL
;
913 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
914 return STATUS_UNSUCCESSFUL
;
920 CPortPinWaveCyclic::QuerySecurity(
921 IN PDEVICE_OBJECT DeviceObject
,
924 return KsDispatchInvalidDeviceRequest(DeviceObject
, Irp
);
929 CPortPinWaveCyclic::SetSecurity(
930 IN PDEVICE_OBJECT DeviceObject
,
933 return KsDispatchInvalidDeviceRequest(DeviceObject
, Irp
);
938 CPortPinWaveCyclic::FastDeviceIoControl(
939 IN PFILE_OBJECT FileObject
,
941 IN PVOID InputBuffer
,
942 IN ULONG InputBufferLength
,
943 OUT PVOID OutputBuffer
,
944 IN ULONG OutputBufferLength
,
945 IN ULONG IoControlCode
,
946 OUT PIO_STATUS_BLOCK StatusBlock
,
947 IN PDEVICE_OBJECT DeviceObject
)
949 return KsDispatchFastIoDeviceControlFailure(FileObject
, Wait
, InputBuffer
, InputBufferLength
, OutputBuffer
, OutputBufferLength
, IoControlCode
, StatusBlock
, DeviceObject
);
955 CPortPinWaveCyclic::FastRead(
956 IN PFILE_OBJECT FileObject
,
957 IN PLARGE_INTEGER FileOffset
,
962 OUT PIO_STATUS_BLOCK StatusBlock
,
963 IN PDEVICE_OBJECT DeviceObject
)
965 return KsDispatchFastReadFailure(FileObject
, FileOffset
, Length
, Wait
, LockKey
, Buffer
, StatusBlock
, DeviceObject
);
971 CPortPinWaveCyclic::FastWrite(
972 IN PFILE_OBJECT FileObject
,
973 IN PLARGE_INTEGER FileOffset
,
978 OUT PIO_STATUS_BLOCK StatusBlock
,
979 IN PDEVICE_OBJECT DeviceObject
)
981 return KsDispatchFastReadFailure(FileObject
, FileOffset
, Length
, Wait
, LockKey
, Buffer
, StatusBlock
, DeviceObject
);
987 CPortPinWaveCyclic::Init(
988 IN PPORTWAVECYCLIC Port
,
989 IN PPORTFILTERWAVECYCLIC Filter
,
990 IN KSPIN_CONNECT
* ConnectDetails
,
991 IN KSPIN_DESCRIPTOR
* KsPinDescriptor
)
994 PKSDATAFORMAT DataFormat
;
995 PDEVICE_OBJECT DeviceObject
;
998 PSUBDEVICE_DESCRIPTOR SubDeviceDescriptor
= NULL
;
999 //IDrmAudioStream * DrmAudio = NULL;
1001 m_KsPinDescriptor
= KsPinDescriptor
;
1002 m_ConnectDetails
= ConnectDetails
;
1003 m_Miniport
= GetWaveCyclicMiniport(Port
);
1005 DeviceObject
= GetDeviceObject(Port
);
1007 DataFormat
= (PKSDATAFORMAT
)(ConnectDetails
+ 1);
1009 DPRINT("CPortPinWaveCyclic::Init entered Size %u\n", DataFormat
->FormatSize
);
1011 Status
= NewIrpQueue(&m_IrpQueue
);
1012 if (!NT_SUCCESS(Status
))
1015 if (KsPinDescriptor
->Communication
== KSPIN_COMMUNICATION_SINK
&& KsPinDescriptor
->DataFlow
== KSPIN_DATAFLOW_IN
)
1019 else if (KsPinDescriptor
->Communication
== KSPIN_COMMUNICATION_SINK
&& KsPinDescriptor
->DataFlow
== KSPIN_DATAFLOW_OUT
)
1025 DPRINT1("Unexpected Communication %u DataFlow %u\n", KsPinDescriptor
->Communication
, KsPinDescriptor
->DataFlow
);
1030 Status
= m_Miniport
->NewStream(&m_Stream
,
1033 ConnectDetails
->PinId
,
1039 Status
= m_Stream
->QueryInterface(IID_IDrmAudioStream
, (PVOID
*)&DrmAudio
);
1040 if (NT_SUCCESS(Status
))
1042 DRMRIGHTS DrmRights
;
1043 DPRINT1("Got IID_IDrmAudioStream interface %p\n", DrmAudio
);
1045 DrmRights
.CopyProtect
= FALSE
;
1046 DrmRights
.Reserved
= 0;
1047 DrmRights
.DigitalOutputDisable
= FALSE
;
1049 Status
= DrmAudio
->SetContentId(1, &DrmRights
);
1050 DPRINT("Status %x\n", Status
);
1054 DPRINT("CPortPinWaveCyclic::Init Status %x\n", Status
);
1056 if (!NT_SUCCESS(Status
))
1059 ISubdevice
* Subdevice
= NULL
;
1060 // get subdevice interface
1061 Status
= Port
->QueryInterface(IID_ISubdevice
, (PVOID
*)&Subdevice
);
1063 if (!NT_SUCCESS(Status
))
1066 Status
= Subdevice
->GetDescriptor(&SubDeviceDescriptor
);
1067 if (!NT_SUCCESS(Status
))
1069 // failed to get descriptor
1070 Subdevice
->Release();
1074 /* set up subdevice descriptor */
1075 RtlZeroMemory(&m_Descriptor
, sizeof(SUBDEVICE_DESCRIPTOR
));
1076 m_Descriptor
.FilterPropertySet
= PinWaveCyclicPropertySet
;
1077 m_Descriptor
.FilterPropertySetCount
= sizeof(PinWaveCyclicPropertySet
) / sizeof(KSPROPERTY_SET
);
1078 m_Descriptor
.UnknownStream
= (PUNKNOWN
)m_Stream
;
1079 m_Descriptor
.DeviceDescriptor
= SubDeviceDescriptor
->DeviceDescriptor
;
1080 m_Descriptor
.UnknownMiniport
= SubDeviceDescriptor
->UnknownMiniport
;
1081 m_Descriptor
.PortPin
= (PVOID
)this;
1083 // release subdevice descriptor
1084 Subdevice
->Release();
1086 // add ourselves to service group
1087 Status
= m_ServiceGroup
->AddMember(PSERVICESINK(this));
1088 if (!NT_SUCCESS(Status
))
1090 DPRINT1("Failed to add pin to service group\n");
1094 m_ServiceGroup
->SupportDelayedService();
1095 m_Stream
->SetState(KSSTATE_STOP
);
1096 m_State
= KSSTATE_STOP
;
1097 m_CommonBufferOffset
= 0;
1098 m_CommonBufferSize
= m_DmaChannel
->AllocatedBufferSize();
1099 m_CommonBuffer
= m_DmaChannel
->SystemAddress();
1100 m_Capture
= Capture
;
1101 // delay of 10 milisec
1102 m_Delay
= Int32x32To64(10, -10000);
1104 Status
= m_Stream
->SetNotificationFreq(10, &m_FrameSize
);
1106 SilenceBuffer
= AllocateItem(NonPagedPool
, m_FrameSize
, TAG_PORTCLASS
);
1108 return STATUS_INSUFFICIENT_RESOURCES
;
1111 /* set up allocator framing */
1112 m_AllocatorFraming
.RequirementsFlags
= KSALLOCATOR_REQUIREMENTF_SYSTEM_MEMORY
| KSALLOCATOR_REQUIREMENTF_PREFERENCES_ONLY
;
1113 m_AllocatorFraming
.PoolType
= NonPagedPool
;
1114 m_AllocatorFraming
.Frames
= 8;
1115 m_AllocatorFraming
.FileAlignment
= FILE_64_BYTE_ALIGNMENT
;
1116 m_AllocatorFraming
.Reserved
= 0;
1117 m_AllocatorFraming
.FrameSize
= m_FrameSize
;
1119 m_Stream
->Silence(SilenceBuffer
, m_FrameSize
);
1121 Status
= m_IrpQueue
->Init(ConnectDetails
, DataFormat
, DeviceObject
, m_FrameSize
, 0, SilenceBuffer
);
1122 if (!NT_SUCCESS(Status
))
1124 m_IrpQueue
->Release();
1128 m_Format
= (PKSDATAFORMAT
)AllocateItem(NonPagedPool
, DataFormat
->FormatSize
, TAG_PORTCLASS
);
1130 return STATUS_INSUFFICIENT_RESOURCES
;
1132 RtlMoveMemory(m_Format
, DataFormat
, DataFormat
->FormatSize
);
1141 DPRINT1("Setting state to acquire %x\n", m_Stream
->SetState(KSSTATE_ACQUIRE
));
1142 DPRINT1("Setting state to pause %x\n", m_Stream
->SetState(KSSTATE_PAUSE
));
1143 m_State
= KSSTATE_PAUSE
;
1146 return STATUS_SUCCESS
;
1152 CPortPinWaveCyclic::GetCompletedPosition()
1161 CPortPinWaveCyclic::GetCycleCount()
1170 CPortPinWaveCyclic::GetDeviceBufferSize()
1172 return m_CommonBufferSize
;
1178 CPortPinWaveCyclic::GetIrpStream()
1180 return (PVOID
)m_IrpQueue
;
1186 CPortPinWaveCyclic::GetMiniport()
1188 return (PMINIPORT
)m_Miniport
;
1193 NewPortPinWaveCyclic(
1194 OUT IPortPinWaveCyclic
** OutPin
)
1196 CPortPinWaveCyclic
* This
;
1198 This
= new(NonPagedPool
, TAG_PORTCLASS
)CPortPinWaveCyclic(NULL
);
1200 return STATUS_INSUFFICIENT_RESOURCES
;
1205 *OutPin
= (IPortPinWaveCyclic
*)This
;
1207 return STATUS_SUCCESS
;