2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Kernel Streaming
4 * FILE: drivers/wdm/audio/backpln/portcls/pin_wavecyclic.c
5 * PURPOSE: WaveCyclic IRP Audio Pin
6 * PROGRAMMER: Johannes Anderwald
13 IPortPinWaveCyclicVtbl
*lpVtbl
;
14 IServiceSinkVtbl
*lpVtblServiceSink
;
17 IPortWaveCyclic
* Port
;
18 IPortFilterWaveCyclic
* Filter
;
19 KSPIN_DESCRIPTOR
* KsPinDescriptor
;
20 PMINIPORTWAVECYCLIC Miniport
;
21 PSERVICEGROUP ServiceGroup
;
22 PDMACHANNEL DmaChannel
;
23 PMINIPORTWAVECYCLICSTREAM Stream
;
26 KSPIN_CONNECT
* ConnectDetails
;
29 ULONG CommonBufferSize
;
30 ULONG CommonBufferOffset
;
41 }IPortPinWaveCyclicImpl
;
46 IPortPinWaveCyclicImpl
*Pin
;
47 PIO_WORKITEM WorkItem
;
49 }SETSTREAM_CONTEXT
, *PSETSTREAM_CONTEXT
;
53 IPortWaveCyclic_fnProcessNewIrp(
54 IPortPinWaveCyclicImpl
* This
);
56 //==================================================================================================================================
61 IServiceSink_fnQueryInterface(
66 IPortPinWaveCyclicImpl
* This
= (IPortPinWaveCyclicImpl
*)CONTAINING_RECORD(iface
, IPortPinWaveCyclicImpl
, lpVtblServiceSink
);
68 DPRINT("IServiceSink_fnQueryInterface entered\n");
70 if (IsEqualGUIDAligned(refiid
, &IID_IServiceSink
) ||
71 IsEqualGUIDAligned(refiid
, &IID_IUnknown
))
73 *Output
= &This
->lpVtblServiceSink
;
74 InterlockedIncrement(&This
->ref
);
75 return STATUS_SUCCESS
;
77 return STATUS_UNSUCCESSFUL
;
83 IServiceSink_fnAddRef(
86 IPortPinWaveCyclicImpl
* This
= (IPortPinWaveCyclicImpl
*)CONTAINING_RECORD(iface
, IPortPinWaveCyclicImpl
, lpVtblServiceSink
);
87 DPRINT("IServiceSink_fnAddRef entered\n");
89 return InterlockedIncrement(&This
->ref
);
95 IServiceSink_fnRelease(
98 IPortPinWaveCyclicImpl
* This
= (IPortPinWaveCyclicImpl
*)CONTAINING_RECORD(iface
, IPortPinWaveCyclicImpl
, lpVtblServiceSink
);
100 InterlockedDecrement(&This
->ref
);
102 DPRINT("IServiceSink_fnRelease entered %u\n", This
->ref
);
106 FreeItem(This
, TAG_PORTCLASS
);
109 /* Return new reference count */
116 IPortPinWaveCyclicImpl
* This
,
118 ULONG MaxTransferCount
)
126 BufferLength
= Position
- This
->CommonBufferOffset
;
127 BufferLength
= min(BufferLength
, MaxTransferCount
);
131 Status
= This
->IrpQueue
->lpVtbl
->GetMapping(This
->IrpQueue
, &Buffer
, &BufferSize
);
132 if (!NT_SUCCESS(Status
))
135 BytesToCopy
= min(BufferLength
, BufferSize
);
139 This
->DmaChannel
->lpVtbl
->CopyTo(This
->DmaChannel
,
141 (PUCHAR
)This
->CommonBuffer
+ This
->CommonBufferOffset
,
146 This
->DmaChannel
->lpVtbl
->CopyTo(This
->DmaChannel
,
147 (PUCHAR
)This
->CommonBuffer
+ This
->CommonBufferOffset
,
152 This
->IrpQueue
->lpVtbl
->UpdateMapping(This
->IrpQueue
, BytesToCopy
);
153 This
->CommonBufferOffset
+= BytesToCopy
;
155 BufferLength
= Position
- This
->CommonBufferOffset
;
161 UpdateCommonBufferOverlap(
162 IPortPinWaveCyclicImpl
* This
,
164 ULONG MaxTransferCount
)
166 ULONG BufferLength
, Length
, Gap
;
173 BufferLength
= Gap
= This
->CommonBufferSize
- This
->CommonBufferOffset
;
174 BufferLength
= Length
= min(BufferLength
, MaxTransferCount
);
177 Status
= This
->IrpQueue
->lpVtbl
->GetMapping(This
->IrpQueue
, &Buffer
, &BufferSize
);
178 if (!NT_SUCCESS(Status
))
181 BytesToCopy
= min(BufferLength
, BufferSize
);
185 This
->DmaChannel
->lpVtbl
->CopyTo(This
->DmaChannel
,
187 (PUCHAR
)This
->CommonBuffer
+ This
->CommonBufferOffset
,
192 This
->DmaChannel
->lpVtbl
->CopyTo(This
->DmaChannel
,
193 (PUCHAR
)This
->CommonBuffer
+ This
->CommonBufferOffset
,
198 This
->IrpQueue
->lpVtbl
->UpdateMapping(This
->IrpQueue
, BytesToCopy
);
199 This
->CommonBufferOffset
+= BytesToCopy
;
201 BufferLength
= This
->CommonBufferSize
- This
->CommonBufferOffset
;
206 This
->CommonBufferOffset
= 0;
208 MaxTransferCount
-= Length
;
210 if (MaxTransferCount
)
212 UpdateCommonBuffer(This
, Position
, MaxTransferCount
);
219 SetStreamWorkerRoutine(
220 IN PDEVICE_OBJECT DeviceObject
,
223 IPortPinWaveCyclicImpl
* This
;
224 PSETSTREAM_CONTEXT Ctx
= (PSETSTREAM_CONTEXT
)Context
;
226 ULONG MinimumDataThreshold
;
227 ULONG MaximumDataThreshold
;
232 IoFreeWorkItem(Ctx
->WorkItem
);
233 FreeItem(Ctx
, TAG_PORTCLASS
);
235 /* Has the audio stream resumed? */
236 if (This
->IrpQueue
->lpVtbl
->NumMappings(This
->IrpQueue
) && State
== KSSTATE_STOP
)
239 /* Has the audio state already been set? */
240 if (This
->State
== State
)
244 if (NT_SUCCESS(This
->Stream
->lpVtbl
->SetState(This
->Stream
, State
)))
246 /* Set internal state */
249 if (This
->State
== KSSTATE_STOP
)
251 /* reset start stream */
252 This
->IrpQueue
->lpVtbl
->CancelBuffers(This
->IrpQueue
); //FIX function name
254 /* increase stop counter */
256 /* get current data threshold */
257 MinimumDataThreshold
= This
->IrpQueue
->lpVtbl
->GetMinimumDataThreshold(This
->IrpQueue
);
258 /* get maximum data threshold */
259 MaximumDataThreshold
= ((PKSDATAFORMAT_WAVEFORMATEX
)This
->Format
)->WaveFormatEx
.nAvgBytesPerSec
;
260 /* increase minimum data threshold by a third sec */
261 MinimumDataThreshold
+= This
->FrameSize
* 10;
263 /* assure it has not exceeded */
264 MinimumDataThreshold
= min(MinimumDataThreshold
, MaximumDataThreshold
);
265 /* store minimum data threshold */
266 This
->IrpQueue
->lpVtbl
->SetMinimumDataThreshold(This
->IrpQueue
, MinimumDataThreshold
);
268 DPRINT1("Stopping TotalPackets %u StopCount %u\n", This
->TotalPackets
, This
->StopCount
);
270 if (This
->State
== KSSTATE_RUN
)
272 DPRINT1("State RUN %x MinAvailable %u CommonBufferSize %u Offset %u\n", State
, This
->IrpQueue
->lpVtbl
->MinimumDataAvailable(This
->IrpQueue
), This
->CommonBufferSize
, This
->CommonBufferOffset
);
280 IN IPortPinWaveCyclicImpl
* This
,
283 PDEVICE_OBJECT DeviceObject
;
284 PIO_WORKITEM WorkItem
;
285 PSETSTREAM_CONTEXT Context
;
287 ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL
);
289 /* Has the audio stream resumed? */
290 if (This
->IrpQueue
->lpVtbl
->NumMappings(This
->IrpQueue
) && State
== KSSTATE_STOP
)
293 /* Has the audio state already been set? */
294 if (This
->State
== State
)
297 /* Get device object */
298 DeviceObject
= GetDeviceObject(This
->Port
);
300 /* allocate set state context */
301 Context
= AllocateItem(NonPagedPool
, sizeof(SETSTREAM_CONTEXT
), TAG_PORTCLASS
);
306 /* allocate work item */
307 WorkItem
= IoAllocateWorkItem(DeviceObject
);
315 Context
->Pin
= (PVOID
)This
;
316 Context
->WorkItem
= WorkItem
;
317 Context
->State
= State
;
319 /* queue the work item */
320 IoQueueWorkItem(WorkItem
, SetStreamWorkerRoutine
, DelayedWorkQueue
, (PVOID
)Context
);
326 IServiceSink_fnRequestService(
333 IPortPinWaveCyclicImpl
* This
= (IPortPinWaveCyclicImpl
*)CONTAINING_RECORD(iface
, IPortPinWaveCyclicImpl
, lpVtblServiceSink
);
335 ASSERT_IRQL(DISPATCH_LEVEL
);
337 Status
= This
->IrpQueue
->lpVtbl
->GetMapping(This
->IrpQueue
, &Buffer
, &BufferSize
);
338 if (!NT_SUCCESS(Status
))
340 //SetStreamState(This, KSSTATE_STOP);
344 Status
= This
->Stream
->lpVtbl
->GetPosition(This
->Stream
, &Position
);
345 DPRINT("Position %u Buffer %p BufferSize %u ActiveIrpOffset %u\n", Position
, Buffer
, This
->CommonBufferSize
, BufferSize
);
347 if (Position
< This
->CommonBufferOffset
)
349 UpdateCommonBufferOverlap(This
, Position
, This
->FrameSize
);
351 else if (Position
>= This
->CommonBufferOffset
)
353 UpdateCommonBuffer(This
, Position
, This
->FrameSize
);
357 static IServiceSinkVtbl vt_IServiceSink
=
359 IServiceSink_fnQueryInterface
,
360 IServiceSink_fnAddRef
,
361 IServiceSink_fnRelease
,
362 IServiceSink_fnRequestService
365 //==================================================================================================================================
371 IPortPinWaveCyclic_fnQueryInterface(
372 IPortPinWaveCyclic
* iface
,
376 IPortPinWaveCyclicImpl
* This
= (IPortPinWaveCyclicImpl
*)iface
;
378 if (IsEqualGUIDAligned(refiid
, &IID_IIrpTarget
) ||
379 IsEqualGUIDAligned(refiid
, &IID_IUnknown
))
381 *Output
= &This
->lpVtbl
;
382 InterlockedIncrement(&This
->ref
);
383 return STATUS_SUCCESS
;
386 return STATUS_UNSUCCESSFUL
;
394 IPortPinWaveCyclic_fnAddRef(
395 IPortPinWaveCyclic
* iface
)
397 IPortPinWaveCyclicImpl
* This
= (IPortPinWaveCyclicImpl
*)iface
;
399 return InterlockedIncrement(&This
->ref
);
407 IPortPinWaveCyclic_fnRelease(
408 IPortPinWaveCyclic
* iface
)
410 IPortPinWaveCyclicImpl
* This
= (IPortPinWaveCyclicImpl
*)iface
;
412 InterlockedDecrement(&This
->ref
);
416 FreeItem(This
, TAG_PORTCLASS
);
427 IPortPinWaveCyclic_fnNewIrpTarget(
428 IN IPortPinWaveCyclic
* iface
,
429 OUT
struct IIrpTarget
**OutTarget
,
432 IN POOL_TYPE PoolType
,
433 IN PDEVICE_OBJECT DeviceObject
,
435 IN KSOBJECT_CREATE
*CreateObject
)
438 return STATUS_UNSUCCESSFUL
;
443 IPortPinWaveCyclic_HandleKsProperty(
444 IN IPortPinWaveCyclic
* iface
,
447 PKSPROPERTY Property
;
449 UNICODE_STRING GuidString
;
450 PIO_STACK_LOCATION IoStack
;
451 IPortPinWaveCyclicImpl
* This
= (IPortPinWaveCyclicImpl
*)iface
;
453 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
455 DPRINT("IPortPinWave_HandleKsProperty entered\n");
457 if (IoStack
->Parameters
.DeviceIoControl
.InputBufferLength
< sizeof(KSPROPERTY
))
459 Irp
->IoStatus
.Information
= 0;
460 Irp
->IoStatus
.Status
= STATUS_INVALID_PARAMETER
;
461 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
462 return STATUS_INVALID_PARAMETER
;
465 Property
= (PKSPROPERTY
)IoStack
->Parameters
.DeviceIoControl
.Type3InputBuffer
;
467 if (IsEqualGUIDAligned(&Property
->Set
, &KSPROPSETID_Connection
))
469 if (Property
->Id
== KSPROPERTY_CONNECTION_STATE
)
471 PKSSTATE State
= (PKSSTATE
)Irp
->UserBuffer
;
473 ASSERT_IRQL(DISPATCH_LEVEL
);
474 if (IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
< sizeof(KSSTATE
))
476 Irp
->IoStatus
.Information
= sizeof(KSSTATE
);
477 Irp
->IoStatus
.Status
= STATUS_BUFFER_TOO_SMALL
;
478 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
479 return STATUS_BUFFER_TOO_SMALL
;
482 if (Property
->Flags
& KSPROPERTY_TYPE_SET
)
484 Status
= STATUS_UNSUCCESSFUL
;
485 Irp
->IoStatus
.Information
= 0;
489 Status
= This
->Stream
->lpVtbl
->SetState(This
->Stream
, *State
);
491 DPRINT1("Setting state %u %x\n", *State
, Status
);
492 if (NT_SUCCESS(Status
))
494 This
->State
= *State
;
497 Irp
->IoStatus
.Status
= Status
;
498 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
501 else if (Property
->Flags
& KSPROPERTY_TYPE_GET
)
503 *State
= This
->State
;
504 Irp
->IoStatus
.Information
= sizeof(KSSTATE
);
505 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
506 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
507 return STATUS_SUCCESS
;
510 else if (Property
->Id
== KSPROPERTY_CONNECTION_DATAFORMAT
)
512 PKSDATAFORMAT DataFormat
= (PKSDATAFORMAT
)Irp
->UserBuffer
;
513 if (Property
->Flags
& KSPROPERTY_TYPE_SET
)
515 PKSDATAFORMAT NewDataFormat
;
516 if (!RtlCompareMemory(DataFormat
, This
->Format
, DataFormat
->FormatSize
))
518 Irp
->IoStatus
.Information
= DataFormat
->FormatSize
;
519 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
520 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
521 return STATUS_SUCCESS
;
524 NewDataFormat
= AllocateItem(NonPagedPool
, DataFormat
->FormatSize
, TAG_PORTCLASS
);
527 Irp
->IoStatus
.Information
= 0;
528 Irp
->IoStatus
.Status
= STATUS_NO_MEMORY
;
529 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
530 return STATUS_NO_MEMORY
;
532 RtlMoveMemory(NewDataFormat
, DataFormat
, DataFormat
->FormatSize
);
536 ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL
);
537 ASSERT(NewDataFormat
->FormatSize
== sizeof(KSDATAFORMAT_WAVEFORMATEX
));
538 ASSERT(IsEqualGUIDAligned(&((PKSDATAFORMAT_WAVEFORMATEX
)NewDataFormat
)->DataFormat
.MajorFormat
, &KSDATAFORMAT_TYPE_AUDIO
));
539 ASSERT(IsEqualGUIDAligned(&((PKSDATAFORMAT_WAVEFORMATEX
)NewDataFormat
)->DataFormat
.SubFormat
, &KSDATAFORMAT_SUBTYPE_PCM
));
540 ASSERT(IsEqualGUIDAligned(&((PKSDATAFORMAT_WAVEFORMATEX
)NewDataFormat
)->DataFormat
.Specifier
, &KSDATAFORMAT_SPECIFIER_WAVEFORMATEX
));
542 ASSERT(This
->State
== KSSTATE_STOP
);
543 DPRINT1("NewDataFormat: Channels %u Bits %u Samples %u\n", ((PKSDATAFORMAT_WAVEFORMATEX
)NewDataFormat
)->WaveFormatEx
.nChannels
,
544 ((PKSDATAFORMAT_WAVEFORMATEX
)NewDataFormat
)->WaveFormatEx
.wBitsPerSample
,
545 ((PKSDATAFORMAT_WAVEFORMATEX
)NewDataFormat
)->WaveFormatEx
.nSamplesPerSec
);
547 Status
= This
->Stream
->lpVtbl
->SetFormat(This
->Stream
, NewDataFormat
);
548 if (NT_SUCCESS(Status
))
551 ExFreePoolWithTag(This
->Format
, TAG_PORTCLASS
);
553 This
->IrpQueue
->lpVtbl
->UpdateFormat(This
->IrpQueue
, (PKSDATAFORMAT
)NewDataFormat
);
554 This
->Format
= NewDataFormat
;
555 Irp
->IoStatus
.Information
= DataFormat
->FormatSize
;
556 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
557 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
558 return STATUS_SUCCESS
;
561 DPRINT1("Failed to set format\n");
562 Irp
->IoStatus
.Information
= 0;
563 Irp
->IoStatus
.Status
= STATUS_UNSUCCESSFUL
;
564 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
565 return STATUS_UNSUCCESSFUL
;
567 else if (Property
->Flags
& KSPROPERTY_TYPE_GET
)
571 DPRINT1("No format\n");
572 Irp
->IoStatus
.Information
= 0;
573 Irp
->IoStatus
.Status
= STATUS_UNSUCCESSFUL
;
574 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
575 return STATUS_UNSUCCESSFUL
;
577 if (This
->Format
->FormatSize
> IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
)
579 Irp
->IoStatus
.Information
= This
->Format
->FormatSize
;
580 Irp
->IoStatus
.Status
= STATUS_BUFFER_TOO_SMALL
;
581 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
582 return STATUS_BUFFER_TOO_SMALL
;
585 RtlMoveMemory(DataFormat
, This
->Format
, This
->Format
->FormatSize
);
586 Irp
->IoStatus
.Information
= DataFormat
->FormatSize
;
587 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
588 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
589 return STATUS_SUCCESS
;
592 else if (Property
->Id
== KSPROPERTY_CONNECTION_ALLOCATORFRAMING
)
594 PKSALLOCATOR_FRAMING Framing
= (PKSALLOCATOR_FRAMING
)Irp
->UserBuffer
;
596 ASSERT_IRQL(DISPATCH_LEVEL
);
597 /* Validate input buffer */
598 if (IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
< sizeof(KSALLOCATOR_FRAMING
))
600 Irp
->IoStatus
.Information
= sizeof(KSALLOCATOR_FRAMING
);
601 Irp
->IoStatus
.Status
= STATUS_BUFFER_TOO_SMALL
;
602 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
603 return STATUS_BUFFER_TOO_SMALL
;
605 /* Clear frame structure */
606 RtlZeroMemory(Framing
, sizeof(KSALLOCATOR_FRAMING
));
607 /* store requested frame size */
608 Framing
->FrameSize
= This
->FrameSize
;
609 /* FIXME fill in struct */
611 Irp
->IoStatus
.Information
= sizeof(KSALLOCATOR_FRAMING
);
612 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
613 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
614 return STATUS_SUCCESS
;
618 RtlStringFromGUID(&Property
->Set
, &GuidString
);
619 DPRINT1("Unhandeled property Set |%S| Id %u Flags %x\n", GuidString
.Buffer
, Property
->Id
, Property
->Flags
);
620 RtlFreeUnicodeString(&GuidString
);
622 Irp
->IoStatus
.Status
= STATUS_NOT_IMPLEMENTED
;
623 Irp
->IoStatus
.Information
= 0;
624 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
625 return STATUS_NOT_IMPLEMENTED
;
630 IPortPinWaveCyclic_HandleKsStream(
631 IN IPortPinWaveCyclic
* iface
,
635 IPortPinWaveCyclicImpl
* This
= (IPortPinWaveCyclicImpl
*)iface
;
637 InterlockedIncrement((PLONG
)&This
->TotalPackets
);
639 DPRINT("IPortPinWaveCyclic_HandleKsStream entered Total %u Pre %u Post %u State %x MinData %u\n", This
->TotalPackets
, This
->State
, This
->IrpQueue
->lpVtbl
->NumData(This
->IrpQueue
));
641 Status
= This
->IrpQueue
->lpVtbl
->AddMapping(This
->IrpQueue
, NULL
, 0, Irp
);
643 return STATUS_PENDING
;
651 IPortPinWaveCyclic_fnDeviceIoControl(
652 IN IPortPinWaveCyclic
* iface
,
653 IN PDEVICE_OBJECT DeviceObject
,
656 PIO_STACK_LOCATION IoStack
;
658 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
661 if (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_KS_PROPERTY
)
663 return IPortPinWaveCyclic_HandleKsProperty(iface
, Irp
);
665 else if (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_KS_ENABLE_EVENT
)
668 /// handle enable event
670 else if (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_KS_DISABLE_EVENT
)
673 /// handle disable event
675 else if (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_KS_RESET_STATE
)
678 /// handle reset state
680 else if (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_KS_WRITE_STREAM
|| IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_KS_READ_STREAM
)
682 return IPortPinWaveCyclic_HandleKsStream(iface
, Irp
);
686 return KsDefaultDeviceIoCompletion(DeviceObject
, Irp
);
691 Irp
->IoStatus
.Information
= 0;
692 Irp
->IoStatus
.Status
= STATUS_UNSUCCESSFUL
;
693 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
695 return STATUS_UNSUCCESSFUL
;
703 IPortPinWaveCyclic_fnRead(
704 IN IPortPinWaveCyclic
* iface
,
705 IN PDEVICE_OBJECT DeviceObject
,
708 return KsDispatchInvalidDeviceRequest(DeviceObject
, Irp
);
716 IPortPinWaveCyclic_fnWrite(
717 IN IPortPinWaveCyclic
* iface
,
718 IN PDEVICE_OBJECT DeviceObject
,
721 return KsDispatchInvalidDeviceRequest(DeviceObject
, Irp
);
729 IPortPinWaveCyclic_fnFlush(
730 IN IPortPinWaveCyclic
* iface
,
731 IN PDEVICE_OBJECT DeviceObject
,
734 return KsDispatchInvalidDeviceRequest(DeviceObject
, Irp
);
740 IN PDEVICE_OBJECT DeviceObject
,
743 PMINIPORTWAVECYCLICSTREAM Stream
;
744 IPortPinWaveCyclicImpl
* This
;
746 PCLOSESTREAM_CONTEXT Ctx
= (PCLOSESTREAM_CONTEXT
)Context
;
748 This
= (IPortPinWaveCyclicImpl
*)Ctx
->Pin
;
750 if (This
->State
!= KSSTATE_STOP
)
752 /* stop stream in case it hasn't been */
753 Status
= This
->Stream
->lpVtbl
->SetState(This
->Stream
, KSSTATE_STOP
);
754 if (!NT_SUCCESS(Status
))
755 DPRINT1("Warning: failed to stop stream with %x\n", Status
);
757 This
->State
= KSSTATE_STOP
;
763 ExFreePool(This
->Format
);
769 This
->IrpQueue
->lpVtbl
->Release(This
->IrpQueue
);
772 /* complete the irp */
773 Ctx
->Irp
->IoStatus
.Information
= 0;
774 Ctx
->Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
775 IoCompleteRequest(Ctx
->Irp
, IO_NO_INCREMENT
);
777 /* free the work item */
778 IoFreeWorkItem(Ctx
->WorkItem
);
780 /* free work item ctx */
781 FreeItem(Ctx
, TAG_PORTCLASS
);
783 /* release reference to port driver */
784 This
->Port
->lpVtbl
->Release(This
->Port
);
786 /* release reference to filter instance */
787 This
->Filter
->lpVtbl
->Release(This
->Filter
);
791 Stream
= This
->Stream
;
793 This
->Filter
->lpVtbl
->FreePin(This
->Filter
, (IPortPinWaveCyclic
*)This
);
794 DPRINT1("Closing stream at Irql %u\n", KeGetCurrentIrql());
795 Stream
->lpVtbl
->Release(Stream
);
804 IPortPinWaveCyclic_fnClose(
805 IN IPortPinWaveCyclic
* iface
,
806 IN PDEVICE_OBJECT DeviceObject
,
809 PCLOSESTREAM_CONTEXT Ctx
;
810 IPortPinWaveCyclicImpl
* This
= (IPortPinWaveCyclicImpl
*)iface
;
814 /* allocate a close context */
815 Ctx
= AllocateItem(NonPagedPool
, sizeof(CLOSESTREAM_CONTEXT
), TAG_PORTCLASS
);
818 DPRINT1("Failed to allocate stream context\n");
821 /* allocate work context */
822 Ctx
->WorkItem
= IoAllocateWorkItem(DeviceObject
);
825 DPRINT1("Failed to allocate work item\n");
828 /* setup the close context */
830 Ctx
->Pin
= (PVOID
)This
;
832 IoMarkIrpPending(Irp
);
833 Irp
->IoStatus
.Information
= 0;
834 Irp
->IoStatus
.Status
= STATUS_PENDING
;
836 /* remove member from service group */
837 This
->ServiceGroup
->lpVtbl
->RemoveMember(This
->ServiceGroup
, (PSERVICESINK
)&This
->lpVtblServiceSink
);
839 /* defer work item */
840 IoQueueWorkItem(Ctx
->WorkItem
, CloseStreamRoutine
, DelayedWorkQueue
, (PVOID
)Ctx
);
842 return STATUS_PENDING
;
845 Irp
->IoStatus
.Information
= 0;
846 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
847 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
849 return STATUS_SUCCESS
;
854 FreeItem(Ctx
, TAG_PORTCLASS
);
856 Irp
->IoStatus
.Information
= 0;
857 Irp
->IoStatus
.Status
= STATUS_UNSUCCESSFUL
;
858 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
859 return STATUS_UNSUCCESSFUL
;
868 IPortPinWaveCyclic_fnQuerySecurity(
869 IN IPortPinWaveCyclic
* iface
,
870 IN PDEVICE_OBJECT DeviceObject
,
873 return KsDispatchInvalidDeviceRequest(DeviceObject
, Irp
);
881 IPortPinWaveCyclic_fnSetSecurity(
882 IN IPortPinWaveCyclic
* iface
,
883 IN PDEVICE_OBJECT DeviceObject
,
886 return KsDispatchInvalidDeviceRequest(DeviceObject
, Irp
);
894 IPortPinWaveCyclic_fnFastDeviceIoControl(
895 IN IPortPinWaveCyclic
* iface
,
896 IN PFILE_OBJECT FileObject
,
898 IN PVOID InputBuffer
,
899 IN ULONG InputBufferLength
,
900 OUT PVOID OutputBuffer
,
901 IN ULONG OutputBufferLength
,
902 IN ULONG IoControlCode
,
903 OUT PIO_STATUS_BLOCK StatusBlock
,
904 IN PDEVICE_OBJECT DeviceObject
)
906 return KsDispatchFastIoDeviceControlFailure(FileObject
, Wait
, InputBuffer
, InputBufferLength
, OutputBuffer
, OutputBufferLength
, IoControlCode
, StatusBlock
, DeviceObject
);
914 IPortPinWaveCyclic_fnFastRead(
915 IN IPortPinWaveCyclic
* iface
,
916 IN PFILE_OBJECT FileObject
,
917 IN PLARGE_INTEGER FileOffset
,
922 OUT PIO_STATUS_BLOCK StatusBlock
,
923 IN PDEVICE_OBJECT DeviceObject
)
926 PCONTEXT_WRITE Packet
;
928 IPortPinWaveCyclicImpl
* This
= (IPortPinWaveCyclicImpl
*)iface
;
930 /* HACK to be removed */
932 DPRINT("IPortPinWaveCyclic_fnFastRead entered\n");
934 Packet
= (PCONTEXT_WRITE
)Buffer
;
937 StatusBlock
->Status
= STATUS_PENDING
;
939 Status
= This
->IrpQueue
->lpVtbl
->AddMapping(This
->IrpQueue
, Buffer
, Length
, Irp
);
941 if (!NT_SUCCESS(Status
))
944 StatusBlock
->Status
= STATUS_PENDING
;
954 IPortPinWaveCyclic_fnFastWrite(
955 IN IPortPinWaveCyclic
* iface
,
956 IN PFILE_OBJECT FileObject
,
957 IN PLARGE_INTEGER FileOffset
,
962 OUT PIO_STATUS_BLOCK StatusBlock
,
963 IN PDEVICE_OBJECT DeviceObject
)
966 PCONTEXT_WRITE Packet
;
968 IPortPinWaveCyclicImpl
* This
= (IPortPinWaveCyclicImpl
*)iface
;
970 /* HACK to be removed */
972 InterlockedIncrement((PLONG
)&This
->TotalPackets
);
974 DPRINT("IPortPinWaveCyclic_fnFastWrite entered Total %u State %x MinData %u\n", This
->TotalPackets
, This
->State
, This
->IrpQueue
->lpVtbl
->NumData(This
->IrpQueue
));
976 Packet
= (PCONTEXT_WRITE
)Buffer
;
979 Status
= This
->IrpQueue
->lpVtbl
->AddMapping(This
->IrpQueue
, Buffer
, Length
, Irp
);
981 if (!NT_SUCCESS(Status
))
984 StatusBlock
->Status
= STATUS_PENDING
;
994 IPortPinWaveCyclic_fnInit(
995 IN IPortPinWaveCyclic
* iface
,
996 IN PPORTWAVECYCLIC Port
,
997 IN PPORTFILTERWAVECYCLIC Filter
,
998 IN KSPIN_CONNECT
* ConnectDetails
,
999 IN KSPIN_DESCRIPTOR
* KsPinDescriptor
)
1002 PKSDATAFORMAT DataFormat
;
1003 PDEVICE_OBJECT DeviceObject
;
1005 PVOID SilenceBuffer
;
1006 //IDrmAudioStream * DrmAudio = NULL;
1008 IPortPinWaveCyclicImpl
* This
= (IPortPinWaveCyclicImpl
*)iface
;
1010 This
->KsPinDescriptor
= KsPinDescriptor
;
1011 This
->ConnectDetails
= ConnectDetails
;
1012 This
->Miniport
= GetWaveCyclicMiniport(Port
);
1014 DeviceObject
= GetDeviceObject(Port
);
1016 DataFormat
= (PKSDATAFORMAT
)(ConnectDetails
+ 1);
1018 DPRINT("IPortPinWaveCyclic_fnInit entered\n");
1020 This
->Format
= ExAllocatePoolWithTag(NonPagedPool
, DataFormat
->FormatSize
, TAG_PORTCLASS
);
1022 return STATUS_INSUFFICIENT_RESOURCES
;
1024 RtlMoveMemory(This
->Format
, DataFormat
, DataFormat
->FormatSize
);
1026 Status
= NewIrpQueue(&This
->IrpQueue
);
1027 if (!NT_SUCCESS(Status
))
1030 if (KsPinDescriptor
->Communication
== KSPIN_COMMUNICATION_SINK
&& KsPinDescriptor
->DataFlow
== KSPIN_DATAFLOW_IN
)
1034 else if (KsPinDescriptor
->Communication
== KSPIN_COMMUNICATION_SINK
&& KsPinDescriptor
->DataFlow
== KSPIN_DATAFLOW_OUT
)
1040 DPRINT1("Unexpected Communication %u DataFlow %u\n", KsPinDescriptor
->Communication
, KsPinDescriptor
->DataFlow
);
1044 Status
= This
->Miniport
->lpVtbl
->NewStream(This
->Miniport
,
1048 ConnectDetails
->PinId
,
1052 &This
->ServiceGroup
);
1054 Status
= This
->Stream
->lpVtbl
->QueryInterface(This
->Stream
, &IID_IDrmAudioStream
, (PVOID
*)&DrmAudio
);
1055 if (NT_SUCCESS(Status
))
1057 DRMRIGHTS DrmRights
;
1058 DPRINT1("Got IID_IDrmAudioStream interface %p\n", DrmAudio
);
1060 DrmRights
.CopyProtect
= FALSE
;
1061 DrmRights
.Reserved
= 0;
1062 DrmRights
.DigitalOutputDisable
= FALSE
;
1064 Status
= DrmAudio
->lpVtbl
->SetContentId(DrmAudio
, 1, &DrmRights
);
1065 DPRINT("Status %x\n", Status
);
1069 DPRINT("IPortPinWaveCyclic_fnInit Status %x\n", Status
);
1071 if (!NT_SUCCESS(Status
))
1074 Status
= This
->ServiceGroup
->lpVtbl
->AddMember(This
->ServiceGroup
,
1075 (PSERVICESINK
)&This
->lpVtblServiceSink
);
1076 if (!NT_SUCCESS(Status
))
1078 DPRINT1("Failed to add pin to service group\n");
1082 This
->ServiceGroup
->lpVtbl
->SupportDelayedService(This
->ServiceGroup
);
1083 This
->Stream
->lpVtbl
->SetState(This
->Stream
, KSSTATE_STOP
);
1084 This
->State
= KSSTATE_STOP
;
1085 This
->CommonBufferOffset
= 0;
1086 This
->CommonBufferSize
= This
->DmaChannel
->lpVtbl
->AllocatedBufferSize(This
->DmaChannel
);
1087 This
->CommonBuffer
= This
->DmaChannel
->lpVtbl
->SystemAddress(This
->DmaChannel
);
1088 This
->Capture
= Capture
;
1089 /* delay of 10 milisec */
1090 This
->Delay
= Int32x32To64(10, -10000);
1092 Status
= This
->Stream
->lpVtbl
->SetNotificationFreq(This
->Stream
, 10, &This
->FrameSize
);
1094 SilenceBuffer
= AllocateItem(NonPagedPool
, This
->FrameSize
, TAG_PORTCLASS
);
1096 return STATUS_INSUFFICIENT_RESOURCES
;
1098 This
->Stream
->lpVtbl
->Silence(This
->Stream
, SilenceBuffer
, This
->FrameSize
);
1100 Status
= This
->IrpQueue
->lpVtbl
->Init(This
->IrpQueue
, ConnectDetails
, DataFormat
, DeviceObject
, This
->FrameSize
, 0, SilenceBuffer
);
1101 if (!NT_SUCCESS(Status
))
1103 This
->IrpQueue
->lpVtbl
->Release(This
->IrpQueue
);
1107 Port
->lpVtbl
->AddRef(Port
);
1108 Filter
->lpVtbl
->AddRef(Filter
);
1111 This
->Filter
= Filter
;
1113 //This->Stream->lpVtbl->SetFormat(This->Stream, (PKSDATAFORMAT)This->Format);
1114 DPRINT1("Setting state to acquire %x\n", This
->Stream
->lpVtbl
->SetState(This
->Stream
, KSSTATE_ACQUIRE
));
1115 DPRINT1("Setting state to pause %x\n", This
->Stream
->lpVtbl
->SetState(This
->Stream
, KSSTATE_PAUSE
));
1116 This
->State
= KSSTATE_PAUSE
;
1118 //This->ServiceGroup->lpVtbl->RequestDelayedService(This->ServiceGroup, This->Delay);
1120 return STATUS_SUCCESS
;
1128 IPortPinWaveCyclic_fnGetCompletedPosition(
1129 IN IPortPinWaveCyclic
* iface
)
1140 IPortPinWaveCyclic_fnGetCycleCount(
1141 IN IPortPinWaveCyclic
* iface
)
1152 IPortPinWaveCyclic_fnGetDeviceBufferSize(
1153 IN IPortPinWaveCyclic
* iface
)
1155 IPortPinWaveCyclicImpl
* This
= (IPortPinWaveCyclicImpl
*)iface
;
1157 return This
->CommonBufferSize
;
1165 IPortPinWaveCyclic_fnGetIrpStream(
1166 IN IPortPinWaveCyclic
* iface
)
1168 IPortPinWaveCyclicImpl
* This
= (IPortPinWaveCyclicImpl
*)iface
;
1170 return (PVOID
)This
->IrpQueue
;
1179 IPortPinWaveCyclic_fnGetMiniport(
1180 IN IPortPinWaveCyclic
* iface
)
1182 IPortPinWaveCyclicImpl
* This
= (IPortPinWaveCyclicImpl
*)iface
;
1184 return (PMINIPORT
)This
->Miniport
;
1187 static IPortPinWaveCyclicVtbl vt_IPortPinWaveCyclic
=
1189 IPortPinWaveCyclic_fnQueryInterface
,
1190 IPortPinWaveCyclic_fnAddRef
,
1191 IPortPinWaveCyclic_fnRelease
,
1192 IPortPinWaveCyclic_fnNewIrpTarget
,
1193 IPortPinWaveCyclic_fnDeviceIoControl
,
1194 IPortPinWaveCyclic_fnRead
,
1195 IPortPinWaveCyclic_fnWrite
,
1196 IPortPinWaveCyclic_fnFlush
,
1197 IPortPinWaveCyclic_fnClose
,
1198 IPortPinWaveCyclic_fnQuerySecurity
,
1199 IPortPinWaveCyclic_fnSetSecurity
,
1200 IPortPinWaveCyclic_fnFastDeviceIoControl
,
1201 IPortPinWaveCyclic_fnFastRead
,
1202 IPortPinWaveCyclic_fnFastWrite
,
1203 IPortPinWaveCyclic_fnInit
,
1204 IPortPinWaveCyclic_fnGetCompletedPosition
,
1205 IPortPinWaveCyclic_fnGetCycleCount
,
1206 IPortPinWaveCyclic_fnGetDeviceBufferSize
,
1207 IPortPinWaveCyclic_fnGetIrpStream
,
1208 IPortPinWaveCyclic_fnGetMiniport
1214 NTSTATUS
NewPortPinWaveCyclic(
1215 OUT IPortPinWaveCyclic
** OutPin
)
1217 IPortPinWaveCyclicImpl
* This
;
1219 This
= AllocateItem(NonPagedPool
, sizeof(IPortPinWaveCyclicImpl
), TAG_PORTCLASS
);
1221 return STATUS_INSUFFICIENT_RESOURCES
;
1223 /* initialize IPortPinWaveCyclic */
1225 This
->lpVtbl
= &vt_IPortPinWaveCyclic
;
1226 This
->lpVtblServiceSink
= &vt_IServiceSink
;
1230 *OutPin
= (IPortPinWaveCyclic
*)&This
->lpVtbl
;
1232 return STATUS_SUCCESS
;