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
);
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 KSPIN_CONNECT
* m_ConnectDetails
;
64 ULONG m_CommonBufferSize
;
65 ULONG m_CommonBufferOffset
;
67 IIrpQueue
* m_IrpQueue
;
83 CPortPinWaveCyclic
*Pin
;
84 PIO_WORKITEM WorkItem
;
86 }SETSTREAM_CONTEXT
, *PSETSTREAM_CONTEXT
;
88 //==================================================================================================================================
92 CPortPinWaveCyclic::QueryInterface(
96 DPRINT("IServiceSink_fnQueryInterface entered\n");
98 if (IsEqualGUIDAligned(refiid
, IID_IIrpTarget
) ||
99 IsEqualGUIDAligned(refiid
, IID_IUnknown
))
101 *Output
= PVOID(PUNKNOWN((IIrpTarget
*)this));
102 PUNKNOWN(*Output
)->AddRef();
103 return STATUS_SUCCESS
;
106 if (IsEqualGUIDAligned(refiid
, IID_IServiceSink
))
108 *Output
= PVOID(PUNKNOWN(PSERVICESINK(this)));
109 PUNKNOWN(*Output
)->AddRef();
110 return STATUS_SUCCESS
;
113 return STATUS_UNSUCCESSFUL
;
118 CPortPinWaveCyclic::UpdateCommonBuffer(
120 ULONG MaxTransferCount
)
128 BufferLength
= Position
- m_CommonBufferOffset
;
129 BufferLength
= min(BufferLength
, MaxTransferCount
);
133 Status
= m_IrpQueue
->GetMapping(&Buffer
, &BufferSize
);
134 if (!NT_SUCCESS(Status
))
137 BytesToCopy
= min(BufferLength
, BufferSize
);
141 m_DmaChannel
->CopyTo(Buffer
, (PUCHAR
)m_CommonBuffer
+ m_CommonBufferOffset
, BytesToCopy
);
145 m_DmaChannel
->CopyTo((PUCHAR
)m_CommonBuffer
+ m_CommonBufferOffset
, Buffer
, BytesToCopy
);
148 m_IrpQueue
->UpdateMapping(BytesToCopy
);
149 m_CommonBufferOffset
+= BytesToCopy
;
151 BufferLength
= Position
- m_CommonBufferOffset
;
156 CPortPinWaveCyclic::UpdateCommonBufferOverlap(
158 ULONG MaxTransferCount
)
160 ULONG BufferLength
, Length
, Gap
;
167 BufferLength
= Gap
= m_CommonBufferSize
- m_CommonBufferOffset
;
168 BufferLength
= Length
= min(BufferLength
, MaxTransferCount
);
171 Status
= m_IrpQueue
->GetMapping(&Buffer
, &BufferSize
);
172 if (!NT_SUCCESS(Status
))
175 BytesToCopy
= min(BufferLength
, BufferSize
);
179 m_DmaChannel
->CopyTo(Buffer
,
180 (PUCHAR
)m_CommonBuffer
+ m_CommonBufferOffset
,
185 m_DmaChannel
->CopyTo((PUCHAR
)m_CommonBuffer
+ m_CommonBufferOffset
,
190 m_IrpQueue
->UpdateMapping(BytesToCopy
);
191 m_CommonBufferOffset
+= BytesToCopy
;
193 BufferLength
= m_CommonBufferSize
- m_CommonBufferOffset
;
198 m_CommonBufferOffset
= 0;
200 MaxTransferCount
-= Length
;
202 if (MaxTransferCount
)
204 UpdateCommonBuffer(Position
, MaxTransferCount
);
211 SetStreamWorkerRoutineWaveCyclic(
212 IN PDEVICE_OBJECT DeviceObject
,
215 CPortPinWaveCyclic
* This
;
216 PSETSTREAM_CONTEXT Ctx
= (PSETSTREAM_CONTEXT
)Context
;
218 ULONG MinimumDataThreshold
;
219 ULONG MaximumDataThreshold
;
224 IoFreeWorkItem(Ctx
->WorkItem
);
225 FreeItem(Ctx
, TAG_PORTCLASS
);
227 // Has the audio stream resumed?
228 if (This
->m_IrpQueue
->NumMappings() && State
== KSSTATE_STOP
)
231 // Has the audio state already been set?
232 if (This
->m_State
== State
)
236 if (NT_SUCCESS(This
->m_Stream
->SetState(State
)))
238 // Set internal state
239 This
->m_State
= State
;
241 if (This
->m_State
== KSSTATE_STOP
)
243 // reset start stream
244 This
->m_IrpQueue
->CancelBuffers(); //FIX function name
246 // increase stop counter
248 // get current data threshold
249 MinimumDataThreshold
= This
->m_IrpQueue
->GetMinimumDataThreshold();
250 // get maximum data threshold
251 MaximumDataThreshold
= ((PKSDATAFORMAT_WAVEFORMATEX
)This
->m_Format
)->WaveFormatEx
.nAvgBytesPerSec
;
252 // increase minimum data threshold by a third sec
253 MinimumDataThreshold
+= This
->m_FrameSize
* 10;
255 // assure it has not exceeded
256 MinimumDataThreshold
= min(MinimumDataThreshold
, MaximumDataThreshold
);
257 // store minimum data threshold
258 This
->m_IrpQueue
->SetMinimumDataThreshold(MinimumDataThreshold
);
260 DPRINT1("Stopping TotalPackets %u StopCount %u\n", This
->m_TotalPackets
, This
->m_StopCount
);
262 if (This
->m_State
== KSSTATE_RUN
)
264 DPRINT1("State RUN %x MinAvailable %u CommonBufferSize %u Offset %u\n", State
, This
->m_IrpQueue
->MinimumDataAvailable(), This
->m_CommonBufferSize
, This
->m_CommonBufferOffset
);
271 CPortPinWaveCyclic::SetStreamState(
274 PDEVICE_OBJECT DeviceObject
;
275 PIO_WORKITEM WorkItem
;
276 PSETSTREAM_CONTEXT Context
;
278 PC_ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL
);
280 // Has the audio stream resumed?
281 if (m_IrpQueue
->NumMappings() && State
== KSSTATE_STOP
)
284 // Has the audio state already been set?
285 if (m_State
== State
)
289 DeviceObject
= GetDeviceObject(m_Port
);
291 // allocate set state context
292 Context
= (PSETSTREAM_CONTEXT
)AllocateItem(NonPagedPool
, sizeof(SETSTREAM_CONTEXT
), TAG_PORTCLASS
);
297 // allocate work item
298 WorkItem
= IoAllocateWorkItem(DeviceObject
);
307 Context
->WorkItem
= WorkItem
;
308 Context
->State
= State
;
310 // queue the work item
311 IoQueueWorkItem(WorkItem
, SetStreamWorkerRoutineWaveCyclic
, DelayedWorkQueue
, (PVOID
)Context
);
316 CPortPinWaveCyclic::RequestService()
323 PC_ASSERT_IRQL(DISPATCH_LEVEL
);
325 Status
= m_IrpQueue
->GetMapping(&Buffer
, &BufferSize
);
326 if (!NT_SUCCESS(Status
))
328 //SetStreamState(This, KSSTATE_STOP);
332 Status
= m_Stream
->GetPosition(&Position
);
333 DPRINT("Position %u Buffer %p BufferSize %u ActiveIrpOffset %u\n", Position
, Buffer
, m_CommonBufferSize
, BufferSize
);
335 if (Position
< m_CommonBufferOffset
)
337 UpdateCommonBufferOverlap(Position
, m_FrameSize
);
339 else if (Position
>= m_CommonBufferOffset
)
341 UpdateCommonBuffer(Position
, m_FrameSize
);
347 CPortPinWaveCyclic::NewIrpTarget(
348 OUT
struct IIrpTarget
**OutTarget
,
351 IN POOL_TYPE PoolType
,
352 IN PDEVICE_OBJECT DeviceObject
,
354 IN KSOBJECT_CREATE
*CreateObject
)
358 return STATUS_UNSUCCESSFUL
;
363 CPortPinWaveCyclic::HandleKsProperty(
366 PKSPROPERTY Property
;
368 UNICODE_STRING GuidString
;
369 PIO_STACK_LOCATION IoStack
;
371 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
373 DPRINT("IPortPinWave_HandleKsProperty entered\n");
375 if (IoStack
->Parameters
.DeviceIoControl
.InputBufferLength
< sizeof(KSPROPERTY
))
377 Irp
->IoStatus
.Information
= 0;
378 Irp
->IoStatus
.Status
= STATUS_INVALID_PARAMETER
;
379 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
380 return STATUS_INVALID_PARAMETER
;
383 Property
= (PKSPROPERTY
)IoStack
->Parameters
.DeviceIoControl
.Type3InputBuffer
;
385 if (IsEqualGUIDAligned(Property
->Set
, GUID_NULL
))
387 if (Property
->Flags
& KSPROPERTY_TYPE_SETSUPPORT
)
389 if (IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
< sizeof(GUID
))
392 Irp
->IoStatus
.Status
= STATUS_BUFFER_OVERFLOW
;
393 Irp
->IoStatus
.Information
= sizeof(GUID
);
394 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
396 return STATUS_BUFFER_OVERFLOW
;
399 // KSPROPSETID_Audio when available
400 // KSPROPSETID_Sysaudio_Pin
402 RtlMoveMemory(Irp
->UserBuffer
, &KSPROPSETID_Connection
, sizeof(GUID
));
404 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
405 Irp
->IoStatus
.Information
= sizeof(GUID
);
406 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
408 return STATUS_SUCCESS
;
413 if (IsEqualGUIDAligned(Property
->Set
, KSPROPSETID_Connection
))
415 if (Property
->Id
== KSPROPERTY_CONNECTION_STATE
)
417 PKSSTATE State
= (PKSSTATE
)Irp
->UserBuffer
;
419 PC_ASSERT_IRQL(DISPATCH_LEVEL
);
420 if (IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
< sizeof(KSSTATE
))
422 Irp
->IoStatus
.Information
= sizeof(KSSTATE
);
423 Irp
->IoStatus
.Status
= STATUS_BUFFER_TOO_SMALL
;
424 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
425 return STATUS_BUFFER_TOO_SMALL
;
428 if (Property
->Flags
& KSPROPERTY_TYPE_SET
)
430 Status
= STATUS_UNSUCCESSFUL
;
431 Irp
->IoStatus
.Information
= 0;
435 Status
= m_Stream
->SetState(*State
);
437 DPRINT1("Setting state %u %x\n", *State
, Status
);
438 if (NT_SUCCESS(Status
))
443 Irp
->IoStatus
.Status
= Status
;
444 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
447 else if (Property
->Flags
& KSPROPERTY_TYPE_GET
)
450 Irp
->IoStatus
.Information
= sizeof(KSSTATE
);
451 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
452 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
453 return STATUS_SUCCESS
;
456 else if (Property
->Id
== KSPROPERTY_CONNECTION_DATAFORMAT
)
458 PKSDATAFORMAT DataFormat
= (PKSDATAFORMAT
)Irp
->UserBuffer
;
459 if (Property
->Flags
& KSPROPERTY_TYPE_SET
)
461 PKSDATAFORMAT NewDataFormat
;
462 if (!RtlCompareMemory(DataFormat
, m_Format
, DataFormat
->FormatSize
))
464 Irp
->IoStatus
.Information
= DataFormat
->FormatSize
;
465 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
466 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
467 return STATUS_SUCCESS
;
470 NewDataFormat
= (PKSDATAFORMAT
)AllocateItem(NonPagedPool
, DataFormat
->FormatSize
, TAG_PORTCLASS
);
473 Irp
->IoStatus
.Information
= 0;
474 Irp
->IoStatus
.Status
= STATUS_NO_MEMORY
;
475 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
476 return STATUS_NO_MEMORY
;
478 RtlMoveMemory(NewDataFormat
, DataFormat
, DataFormat
->FormatSize
);
482 PC_ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL
);
483 PC_ASSERT(NewDataFormat
->FormatSize
== sizeof(KSDATAFORMAT_WAVEFORMATEX
));
484 PC_ASSERT(IsEqualGUIDAligned(((PKSDATAFORMAT_WAVEFORMATEX
)NewDataFormat
)->DataFormat
.MajorFormat
, KSDATAFORMAT_TYPE_AUDIO
));
485 PC_ASSERT(IsEqualGUIDAligned(((PKSDATAFORMAT_WAVEFORMATEX
)NewDataFormat
)->DataFormat
.SubFormat
, KSDATAFORMAT_SUBTYPE_PCM
));
486 PC_ASSERT(IsEqualGUIDAligned(((PKSDATAFORMAT_WAVEFORMATEX
)NewDataFormat
)->DataFormat
.Specifier
, KSDATAFORMAT_SPECIFIER_WAVEFORMATEX
));
488 PC_ASSERT(m_State
== KSSTATE_STOP
);
489 DPRINT1("NewDataFormat: Channels %u Bits %u Samples %u\n", ((PKSDATAFORMAT_WAVEFORMATEX
)NewDataFormat
)->WaveFormatEx
.nChannels
,
490 ((PKSDATAFORMAT_WAVEFORMATEX
)NewDataFormat
)->WaveFormatEx
.wBitsPerSample
,
491 ((PKSDATAFORMAT_WAVEFORMATEX
)NewDataFormat
)->WaveFormatEx
.nSamplesPerSec
);
493 Status
= m_Stream
->SetFormat(NewDataFormat
);
494 if (NT_SUCCESS(Status
))
497 ExFreePoolWithTag(m_Format
, TAG_PORTCLASS
);
499 m_IrpQueue
->UpdateFormat((PKSDATAFORMAT
)NewDataFormat
);
500 m_Format
= NewDataFormat
;
501 Irp
->IoStatus
.Information
= DataFormat
->FormatSize
;
502 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
503 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
504 return STATUS_SUCCESS
;
507 DPRINT1("Failed to set format\n");
508 Irp
->IoStatus
.Information
= 0;
509 Irp
->IoStatus
.Status
= STATUS_UNSUCCESSFUL
;
510 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
511 return STATUS_UNSUCCESSFUL
;
513 else if (Property
->Flags
& KSPROPERTY_TYPE_GET
)
517 DPRINT1("No format\n");
518 Irp
->IoStatus
.Information
= 0;
519 Irp
->IoStatus
.Status
= STATUS_UNSUCCESSFUL
;
520 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
521 return STATUS_UNSUCCESSFUL
;
523 if (m_Format
->FormatSize
> IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
)
525 Irp
->IoStatus
.Information
= m_Format
->FormatSize
;
526 Irp
->IoStatus
.Status
= STATUS_BUFFER_TOO_SMALL
;
527 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
528 return STATUS_BUFFER_TOO_SMALL
;
531 RtlMoveMemory(DataFormat
, m_Format
, m_Format
->FormatSize
);
532 Irp
->IoStatus
.Information
= DataFormat
->FormatSize
;
533 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
534 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
535 return STATUS_SUCCESS
;
538 else if (Property
->Id
== KSPROPERTY_CONNECTION_ALLOCATORFRAMING
)
540 PKSALLOCATOR_FRAMING Framing
= (PKSALLOCATOR_FRAMING
)Irp
->UserBuffer
;
542 PC_ASSERT_IRQL(DISPATCH_LEVEL
);
543 // Validate input buffer
544 if (IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
< sizeof(KSALLOCATOR_FRAMING
))
546 Irp
->IoStatus
.Information
= sizeof(KSALLOCATOR_FRAMING
);
547 Irp
->IoStatus
.Status
= STATUS_BUFFER_TOO_SMALL
;
548 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
549 return STATUS_BUFFER_TOO_SMALL
;
551 // Clear frame structure
552 RtlZeroMemory(Framing
, sizeof(KSALLOCATOR_FRAMING
));
553 // store requested frame size
554 Framing
->FrameSize
= m_FrameSize
;
555 // FIXME fill in struct
557 Irp
->IoStatus
.Information
= sizeof(KSALLOCATOR_FRAMING
);
558 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
559 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
560 return STATUS_SUCCESS
;
564 RtlStringFromGUID(Property
->Set
, &GuidString
);
565 DPRINT1("Unhandeled property Set |%S| Id %u Flags %x\n", GuidString
.Buffer
, Property
->Id
, Property
->Flags
);
566 RtlFreeUnicodeString(&GuidString
);
568 Irp
->IoStatus
.Status
= STATUS_NOT_IMPLEMENTED
;
569 Irp
->IoStatus
.Information
= 0;
570 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
571 return STATUS_NOT_IMPLEMENTED
;
576 CPortPinWaveCyclic::HandleKsStream(
579 InterlockedIncrement((PLONG
)&m_TotalPackets
);
581 DPRINT("IPortPinWaveCyclic_HandleKsStream entered Total %u Pre %u Post %u State %x MinData %u\n", m_TotalPackets
, m_State
, m_IrpQueue
->NumData());
583 m_IrpQueue
->AddMapping(NULL
, 0, Irp
);
585 return STATUS_PENDING
;
590 CPortPinWaveCyclic::DeviceIoControl(
591 IN PDEVICE_OBJECT DeviceObject
,
594 PIO_STACK_LOCATION IoStack
;
596 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
599 if (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_KS_PROPERTY
)
601 return HandleKsProperty(Irp
);
603 else if (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_KS_ENABLE_EVENT
)
606 /// handle enable event
608 else if (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_KS_DISABLE_EVENT
)
611 /// handle disable event
613 else if (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_KS_RESET_STATE
)
616 /// handle reset state
618 else if (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_KS_WRITE_STREAM
|| IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_KS_READ_STREAM
)
620 return HandleKsStream(Irp
);
624 return KsDefaultDeviceIoCompletion(DeviceObject
, Irp
);
629 Irp
->IoStatus
.Information
= 0;
630 Irp
->IoStatus
.Status
= STATUS_UNSUCCESSFUL
;
631 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
633 return STATUS_UNSUCCESSFUL
;
638 CPortPinWaveCyclic::Read(
639 IN PDEVICE_OBJECT DeviceObject
,
642 return KsDispatchInvalidDeviceRequest(DeviceObject
, Irp
);
647 CPortPinWaveCyclic::Write(
648 IN PDEVICE_OBJECT DeviceObject
,
651 return KsDispatchInvalidDeviceRequest(DeviceObject
, Irp
);
656 CPortPinWaveCyclic::Flush(
657 IN PDEVICE_OBJECT DeviceObject
,
660 return KsDispatchInvalidDeviceRequest(DeviceObject
, Irp
);
665 CloseStreamRoutineWaveCyclic(
666 IN PDEVICE_OBJECT DeviceObject
,
669 PMINIPORTWAVECYCLICSTREAM Stream
;
670 CPortPinWaveCyclic
* This
;
672 PCLOSESTREAM_CONTEXT Ctx
= (PCLOSESTREAM_CONTEXT
)Context
;
674 This
= (CPortPinWaveCyclic
*)Ctx
->Pin
;
676 if (This
->m_State
!= KSSTATE_STOP
)
678 // stop stream in case it hasn't been
679 Status
= This
->m_Stream
->SetState(KSSTATE_STOP
);
680 if (!NT_SUCCESS(Status
))
681 DPRINT1("Warning: failed to stop stream with %x\n", Status
);
683 This
->m_State
= KSSTATE_STOP
;
689 ExFreePool(This
->m_Format
);
690 This
->m_Format
= NULL
;
693 if (This
->m_IrpQueue
)
695 This
->m_IrpQueue
->Release();
699 Ctx
->Irp
->IoStatus
.Information
= 0;
700 Ctx
->Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
701 IoCompleteRequest(Ctx
->Irp
, IO_NO_INCREMENT
);
703 // free the work item
704 IoFreeWorkItem(Ctx
->WorkItem
);
706 // free work item ctx
707 FreeItem(Ctx
, TAG_PORTCLASS
);
709 // release reference to port driver
710 This
->m_Port
->Release();
712 // release reference to filter instance
713 This
->m_Filter
->Release();
717 Stream
= This
->m_Stream
;
718 This
->m_Stream
= NULL
;
719 This
->m_Filter
->FreePin(This
);
720 DPRINT1("Closing stream at Irql %u\n", KeGetCurrentIrql());
727 CPortPinWaveCyclic::Close(
728 IN PDEVICE_OBJECT DeviceObject
,
731 PCLOSESTREAM_CONTEXT Ctx
;
735 // allocate a close context
736 Ctx
= (PCLOSESTREAM_CONTEXT
)AllocateItem(NonPagedPool
, sizeof(CLOSESTREAM_CONTEXT
), TAG_PORTCLASS
);
739 DPRINT1("Failed to allocate stream context\n");
742 // allocate work context
743 Ctx
->WorkItem
= IoAllocateWorkItem(DeviceObject
);
746 DPRINT1("Failed to allocate work item\n");
749 // setup the close context
753 IoMarkIrpPending(Irp
);
754 Irp
->IoStatus
.Information
= 0;
755 Irp
->IoStatus
.Status
= STATUS_PENDING
;
757 // remove member from service group
758 m_ServiceGroup
->RemoveMember(PSERVICESINK(this));
761 IoQueueWorkItem(Ctx
->WorkItem
, CloseStreamRoutineWaveCyclic
, DelayedWorkQueue
, (PVOID
)Ctx
);
763 return STATUS_PENDING
;
766 Irp
->IoStatus
.Information
= 0;
767 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
768 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
770 return STATUS_SUCCESS
;
775 FreeItem(Ctx
, TAG_PORTCLASS
);
777 Irp
->IoStatus
.Information
= 0;
778 Irp
->IoStatus
.Status
= STATUS_UNSUCCESSFUL
;
779 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
780 return STATUS_UNSUCCESSFUL
;
786 CPortPinWaveCyclic::QuerySecurity(
787 IN PDEVICE_OBJECT DeviceObject
,
790 return KsDispatchInvalidDeviceRequest(DeviceObject
, Irp
);
795 CPortPinWaveCyclic::SetSecurity(
796 IN PDEVICE_OBJECT DeviceObject
,
799 return KsDispatchInvalidDeviceRequest(DeviceObject
, Irp
);
804 CPortPinWaveCyclic::FastDeviceIoControl(
805 IN PFILE_OBJECT FileObject
,
807 IN PVOID InputBuffer
,
808 IN ULONG InputBufferLength
,
809 OUT PVOID OutputBuffer
,
810 IN ULONG OutputBufferLength
,
811 IN ULONG IoControlCode
,
812 OUT PIO_STATUS_BLOCK StatusBlock
,
813 IN PDEVICE_OBJECT DeviceObject
)
815 return KsDispatchFastIoDeviceControlFailure(FileObject
, Wait
, InputBuffer
, InputBufferLength
, OutputBuffer
, OutputBufferLength
, IoControlCode
, StatusBlock
, DeviceObject
);
821 CPortPinWaveCyclic::FastRead(
822 IN PFILE_OBJECT FileObject
,
823 IN PLARGE_INTEGER FileOffset
,
828 OUT PIO_STATUS_BLOCK StatusBlock
,
829 IN PDEVICE_OBJECT DeviceObject
)
832 PCONTEXT_WRITE Packet
;
835 // HACK to be removed
837 DPRINT("CPortPinWaveCyclic::FastRead entered\n");
839 Packet
= (PCONTEXT_WRITE
)Buffer
;
842 StatusBlock
->Status
= STATUS_PENDING
;
844 Status
= m_IrpQueue
->AddMapping((PUCHAR
)Buffer
, Length
, Irp
);
846 if (!NT_SUCCESS(Status
))
849 StatusBlock
->Status
= STATUS_PENDING
;
857 CPortPinWaveCyclic::FastWrite(
858 IN PFILE_OBJECT FileObject
,
859 IN PLARGE_INTEGER FileOffset
,
864 OUT PIO_STATUS_BLOCK StatusBlock
,
865 IN PDEVICE_OBJECT DeviceObject
)
868 PCONTEXT_WRITE Packet
;
871 // HACK to be removed
873 InterlockedIncrement((PLONG
)&m_TotalPackets
);
875 DPRINT("CPortPinWaveCyclic::FastWrite entered Total %u State %x MinData %u\n", m_TotalPackets
, m_State
, m_IrpQueue
->NumData());
877 Packet
= (PCONTEXT_WRITE
)Buffer
;
880 Status
= m_IrpQueue
->AddMapping((PUCHAR
)Buffer
, Length
, Irp
);
882 if (!NT_SUCCESS(Status
))
885 StatusBlock
->Status
= STATUS_PENDING
;
893 CPortPinWaveCyclic::Init(
894 IN PPORTWAVECYCLIC Port
,
895 IN PPORTFILTERWAVECYCLIC Filter
,
896 IN KSPIN_CONNECT
* ConnectDetails
,
897 IN KSPIN_DESCRIPTOR
* KsPinDescriptor
)
900 PKSDATAFORMAT DataFormat
;
901 PDEVICE_OBJECT DeviceObject
;
904 //IDrmAudioStream * DrmAudio = NULL;
906 m_KsPinDescriptor
= KsPinDescriptor
;
907 m_ConnectDetails
= ConnectDetails
;
908 m_Miniport
= GetWaveCyclicMiniport(Port
);
910 DeviceObject
= GetDeviceObject(Port
);
912 DataFormat
= (PKSDATAFORMAT
)(ConnectDetails
+ 1);
914 DPRINT("CPortPinWaveCyclic::Init entered Size %u\n", DataFormat
->FormatSize
);
916 Status
= NewIrpQueue(&m_IrpQueue
);
917 if (!NT_SUCCESS(Status
))
920 if (KsPinDescriptor
->Communication
== KSPIN_COMMUNICATION_SINK
&& KsPinDescriptor
->DataFlow
== KSPIN_DATAFLOW_IN
)
924 else if (KsPinDescriptor
->Communication
== KSPIN_COMMUNICATION_SINK
&& KsPinDescriptor
->DataFlow
== KSPIN_DATAFLOW_OUT
)
930 DPRINT1("Unexpected Communication %u DataFlow %u\n", KsPinDescriptor
->Communication
, KsPinDescriptor
->DataFlow
);
935 Status
= m_Miniport
->NewStream(&m_Stream
,
938 ConnectDetails
->PinId
,
944 Status
= m_Stream
->QueryInterface(IID_IDrmAudioStream
, (PVOID
*)&DrmAudio
);
945 if (NT_SUCCESS(Status
))
948 DPRINT1("Got IID_IDrmAudioStream interface %p\n", DrmAudio
);
950 DrmRights
.CopyProtect
= FALSE
;
951 DrmRights
.Reserved
= 0;
952 DrmRights
.DigitalOutputDisable
= FALSE
;
954 Status
= DrmAudio
->SetContentId(1, &DrmRights
);
955 DPRINT("Status %x\n", Status
);
959 DPRINT("CPortPinWaveCyclic::Init Status %x\n", Status
);
961 if (!NT_SUCCESS(Status
))
964 Status
= m_ServiceGroup
->AddMember(PSERVICESINK(this));
965 if (!NT_SUCCESS(Status
))
967 DPRINT1("Failed to add pin to service group\n");
971 m_ServiceGroup
->SupportDelayedService();
972 m_Stream
->SetState(KSSTATE_STOP
);
973 m_State
= KSSTATE_STOP
;
974 m_CommonBufferOffset
= 0;
975 m_CommonBufferSize
= m_DmaChannel
->AllocatedBufferSize();
976 m_CommonBuffer
= m_DmaChannel
->SystemAddress();
978 // delay of 10 milisec
979 m_Delay
= Int32x32To64(10, -10000);
981 Status
= m_Stream
->SetNotificationFreq(10, &m_FrameSize
);
983 SilenceBuffer
= AllocateItem(NonPagedPool
, m_FrameSize
, TAG_PORTCLASS
);
985 return STATUS_INSUFFICIENT_RESOURCES
;
987 m_Stream
->Silence(SilenceBuffer
, m_FrameSize
);
989 Status
= m_IrpQueue
->Init(ConnectDetails
, DataFormat
, DeviceObject
, m_FrameSize
, 0, SilenceBuffer
);
990 if (!NT_SUCCESS(Status
))
992 m_IrpQueue
->Release();
996 m_Format
= (PKSDATAFORMAT
)ExAllocatePoolWithTag(NonPagedPool
, DataFormat
->FormatSize
, TAG_PORTCLASS
);
998 return STATUS_INSUFFICIENT_RESOURCES
;
1000 RtlMoveMemory(m_Format
, DataFormat
, DataFormat
->FormatSize
);
1009 DPRINT1("Setting state to acquire %x\n", m_Stream
->SetState(KSSTATE_ACQUIRE
));
1010 DPRINT1("Setting state to pause %x\n", m_Stream
->SetState(KSSTATE_PAUSE
));
1011 m_State
= KSSTATE_PAUSE
;
1013 //m_ServiceGroup->RequestDelayedService(m_Delay);
1015 return STATUS_SUCCESS
;
1021 CPortPinWaveCyclic::GetCompletedPosition()
1030 CPortPinWaveCyclic::GetCycleCount()
1039 CPortPinWaveCyclic::GetDeviceBufferSize()
1041 return m_CommonBufferSize
;
1047 CPortPinWaveCyclic::GetIrpStream()
1049 return (PVOID
)m_IrpQueue
;
1055 CPortPinWaveCyclic::GetMiniport()
1057 return (PMINIPORT
)m_Miniport
;
1062 NewPortPinWaveCyclic(
1063 OUT IPortPinWaveCyclic
** OutPin
)
1065 CPortPinWaveCyclic
* This
;
1067 This
= new(NonPagedPool
, TAG_PORTCLASS
)CPortPinWaveCyclic(NULL
);
1069 return STATUS_INSUFFICIENT_RESOURCES
;
1074 *OutPin
= (IPortPinWaveCyclic
*)This
;
1076 return STATUS_SUCCESS
;