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 /* check if pin is in run state */
644 if (This
->State
!= KSSTATE_RUN
)
646 /* HACK set pin into run state if caller forgot it */
647 SetStreamState(This
, KSSTATE_RUN
);
648 DPRINT1("Starting stream with %lu mappings Status %x\n", This
->IrpQueue
->lpVtbl
->NumMappings(This
->IrpQueue
), Status
);
659 IPortPinWaveCyclic_fnDeviceIoControl(
660 IN IPortPinWaveCyclic
* iface
,
661 IN PDEVICE_OBJECT DeviceObject
,
664 PIO_STACK_LOCATION IoStack
;
666 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
669 if (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_KS_PROPERTY
)
671 return IPortPinWaveCyclic_HandleKsProperty(iface
, Irp
);
673 else if (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_KS_ENABLE_EVENT
)
676 /// handle enable event
678 else if (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_KS_DISABLE_EVENT
)
681 /// handle disable event
683 else if (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_KS_RESET_STATE
)
686 /// handle reset state
688 else if (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_KS_WRITE_STREAM
|| IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_KS_READ_STREAM
)
690 return IPortPinWaveCyclic_HandleKsStream(iface
, Irp
);
694 return KsDefaultDeviceIoCompletion(DeviceObject
, Irp
);
699 Irp
->IoStatus
.Information
= 0;
700 Irp
->IoStatus
.Status
= STATUS_UNSUCCESSFUL
;
701 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
703 return STATUS_UNSUCCESSFUL
;
711 IPortPinWaveCyclic_fnRead(
712 IN IPortPinWaveCyclic
* iface
,
713 IN PDEVICE_OBJECT DeviceObject
,
716 return KsDispatchInvalidDeviceRequest(DeviceObject
, Irp
);
724 IPortPinWaveCyclic_fnWrite(
725 IN IPortPinWaveCyclic
* iface
,
726 IN PDEVICE_OBJECT DeviceObject
,
729 return KsDispatchInvalidDeviceRequest(DeviceObject
, Irp
);
737 IPortPinWaveCyclic_fnFlush(
738 IN IPortPinWaveCyclic
* iface
,
739 IN PDEVICE_OBJECT DeviceObject
,
742 return KsDispatchInvalidDeviceRequest(DeviceObject
, Irp
);
748 IN PDEVICE_OBJECT DeviceObject
,
751 PMINIPORTWAVECYCLICSTREAM Stream
;
752 IPortPinWaveCyclicImpl
* This
;
754 PCLOSESTREAM_CONTEXT Ctx
= (PCLOSESTREAM_CONTEXT
)Context
;
756 This
= (IPortPinWaveCyclicImpl
*)Ctx
->Pin
;
758 if (This
->State
!= KSSTATE_STOP
)
760 /* stop stream in case it hasn't been */
761 Status
= This
->Stream
->lpVtbl
->SetState(This
->Stream
, KSSTATE_STOP
);
762 if (!NT_SUCCESS(Status
))
763 DPRINT1("Warning: failed to stop stream with %x\n", Status
);
765 This
->State
= KSSTATE_STOP
;
771 ExFreePool(This
->Format
);
777 This
->IrpQueue
->lpVtbl
->Release(This
->IrpQueue
);
780 /* complete the irp */
781 Ctx
->Irp
->IoStatus
.Information
= 0;
782 Ctx
->Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
783 IoCompleteRequest(Ctx
->Irp
, IO_NO_INCREMENT
);
785 /* free the work item */
786 IoFreeWorkItem(Ctx
->WorkItem
);
788 /* free work item ctx */
789 FreeItem(Ctx
, TAG_PORTCLASS
);
791 /* release reference to port driver */
792 This
->Port
->lpVtbl
->Release(This
->Port
);
794 /* release reference to filter instance */
795 This
->Filter
->lpVtbl
->Release(This
->Filter
);
799 Stream
= This
->Stream
;
801 This
->Filter
->lpVtbl
->FreePin(This
->Filter
, (IPortPinWaveCyclic
*)This
);
802 DPRINT1("Closing stream at Irql %u\n", KeGetCurrentIrql());
803 Stream
->lpVtbl
->Release(Stream
);
812 IPortPinWaveCyclic_fnClose(
813 IN IPortPinWaveCyclic
* iface
,
814 IN PDEVICE_OBJECT DeviceObject
,
817 PCLOSESTREAM_CONTEXT Ctx
;
818 IPortPinWaveCyclicImpl
* This
= (IPortPinWaveCyclicImpl
*)iface
;
822 /* allocate a close context */
823 Ctx
= AllocateItem(NonPagedPool
, sizeof(CLOSESTREAM_CONTEXT
), TAG_PORTCLASS
);
826 DPRINT1("Failed to allocate stream context\n");
829 /* allocate work context */
830 Ctx
->WorkItem
= IoAllocateWorkItem(DeviceObject
);
833 DPRINT1("Failed to allocate work item\n");
836 /* setup the close context */
838 Ctx
->Pin
= (PVOID
)This
;
840 IoMarkIrpPending(Irp
);
841 Irp
->IoStatus
.Information
= 0;
842 Irp
->IoStatus
.Status
= STATUS_PENDING
;
844 /* remove member from service group */
845 This
->ServiceGroup
->lpVtbl
->RemoveMember(This
->ServiceGroup
, (PSERVICESINK
)&This
->lpVtblServiceSink
);
847 /* defer work item */
848 IoQueueWorkItem(Ctx
->WorkItem
, CloseStreamRoutine
, DelayedWorkQueue
, (PVOID
)Ctx
);
850 return STATUS_PENDING
;
853 Irp
->IoStatus
.Information
= 0;
854 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
855 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
857 return STATUS_SUCCESS
;
862 FreeItem(Ctx
, TAG_PORTCLASS
);
864 Irp
->IoStatus
.Information
= 0;
865 Irp
->IoStatus
.Status
= STATUS_UNSUCCESSFUL
;
866 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
867 return STATUS_UNSUCCESSFUL
;
876 IPortPinWaveCyclic_fnQuerySecurity(
877 IN IPortPinWaveCyclic
* iface
,
878 IN PDEVICE_OBJECT DeviceObject
,
881 return KsDispatchInvalidDeviceRequest(DeviceObject
, Irp
);
889 IPortPinWaveCyclic_fnSetSecurity(
890 IN IPortPinWaveCyclic
* iface
,
891 IN PDEVICE_OBJECT DeviceObject
,
894 return KsDispatchInvalidDeviceRequest(DeviceObject
, Irp
);
902 IPortPinWaveCyclic_fnFastDeviceIoControl(
903 IN IPortPinWaveCyclic
* iface
,
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
)
922 IPortPinWaveCyclic_fnFastRead(
923 IN IPortPinWaveCyclic
* iface
,
924 IN PFILE_OBJECT FileObject
,
925 IN PLARGE_INTEGER FileOffset
,
930 OUT PIO_STATUS_BLOCK StatusBlock
,
931 IN PDEVICE_OBJECT DeviceObject
)
934 PCONTEXT_WRITE Packet
;
936 IPortPinWaveCyclicImpl
* This
= (IPortPinWaveCyclicImpl
*)iface
;
938 /* HACK to be removed */
940 DPRINT("IPortPinWaveCyclic_fnFastRead entered\n");
942 Packet
= (PCONTEXT_WRITE
)Buffer
;
945 StatusBlock
->Status
= STATUS_PENDING
;
947 Status
= This
->IrpQueue
->lpVtbl
->AddMapping(This
->IrpQueue
, Buffer
, Length
, Irp
);
949 if (!NT_SUCCESS(Status
))
952 StatusBlock
->Status
= STATUS_PENDING
;
962 IPortPinWaveCyclic_fnFastWrite(
963 IN IPortPinWaveCyclic
* iface
,
964 IN PFILE_OBJECT FileObject
,
965 IN PLARGE_INTEGER FileOffset
,
970 OUT PIO_STATUS_BLOCK StatusBlock
,
971 IN PDEVICE_OBJECT DeviceObject
)
974 PCONTEXT_WRITE Packet
;
976 IPortPinWaveCyclicImpl
* This
= (IPortPinWaveCyclicImpl
*)iface
;
978 /* HACK to be removed */
980 InterlockedIncrement((PLONG
)&This
->TotalPackets
);
982 DPRINT("IPortPinWaveCyclic_fnFastWrite entered Total %u State %x MinData %u\n", This
->TotalPackets
, This
->State
, This
->IrpQueue
->lpVtbl
->NumData(This
->IrpQueue
));
984 Packet
= (PCONTEXT_WRITE
)Buffer
;
987 Status
= This
->IrpQueue
->lpVtbl
->AddMapping(This
->IrpQueue
, Buffer
, Length
, Irp
);
989 if (!NT_SUCCESS(Status
))
992 StatusBlock
->Status
= STATUS_PENDING
;
1002 IPortPinWaveCyclic_fnInit(
1003 IN IPortPinWaveCyclic
* iface
,
1004 IN PPORTWAVECYCLIC Port
,
1005 IN PPORTFILTERWAVECYCLIC Filter
,
1006 IN KSPIN_CONNECT
* ConnectDetails
,
1007 IN KSPIN_DESCRIPTOR
* KsPinDescriptor
)
1010 PKSDATAFORMAT DataFormat
;
1011 PDEVICE_OBJECT DeviceObject
;
1013 PVOID SilenceBuffer
;
1014 //IDrmAudioStream * DrmAudio = NULL;
1016 IPortPinWaveCyclicImpl
* This
= (IPortPinWaveCyclicImpl
*)iface
;
1018 This
->KsPinDescriptor
= KsPinDescriptor
;
1019 This
->ConnectDetails
= ConnectDetails
;
1020 This
->Miniport
= GetWaveCyclicMiniport(Port
);
1022 DeviceObject
= GetDeviceObject(Port
);
1024 DataFormat
= (PKSDATAFORMAT
)(ConnectDetails
+ 1);
1026 DPRINT("IPortPinWaveCyclic_fnInit entered\n");
1028 This
->Format
= ExAllocatePoolWithTag(NonPagedPool
, DataFormat
->FormatSize
, TAG_PORTCLASS
);
1030 return STATUS_INSUFFICIENT_RESOURCES
;
1032 RtlMoveMemory(This
->Format
, DataFormat
, DataFormat
->FormatSize
);
1034 Status
= NewIrpQueue(&This
->IrpQueue
);
1035 if (!NT_SUCCESS(Status
))
1038 if (KsPinDescriptor
->Communication
== KSPIN_COMMUNICATION_SINK
&& KsPinDescriptor
->DataFlow
== KSPIN_DATAFLOW_IN
)
1042 else if (KsPinDescriptor
->Communication
== KSPIN_COMMUNICATION_SINK
&& KsPinDescriptor
->DataFlow
== KSPIN_DATAFLOW_OUT
)
1048 DPRINT1("Unexpected Communication %u DataFlow %u\n", KsPinDescriptor
->Communication
, KsPinDescriptor
->DataFlow
);
1052 Status
= This
->Miniport
->lpVtbl
->NewStream(This
->Miniport
,
1056 ConnectDetails
->PinId
,
1060 &This
->ServiceGroup
);
1062 Status
= This
->Stream
->lpVtbl
->QueryInterface(This
->Stream
, &IID_IDrmAudioStream
, (PVOID
*)&DrmAudio
);
1063 if (NT_SUCCESS(Status
))
1065 DRMRIGHTS DrmRights
;
1066 DPRINT1("Got IID_IDrmAudioStream interface %p\n", DrmAudio
);
1068 DrmRights
.CopyProtect
= FALSE
;
1069 DrmRights
.Reserved
= 0;
1070 DrmRights
.DigitalOutputDisable
= FALSE
;
1072 Status
= DrmAudio
->lpVtbl
->SetContentId(DrmAudio
, 1, &DrmRights
);
1073 DPRINT("Status %x\n", Status
);
1077 DPRINT("IPortPinWaveCyclic_fnInit Status %x\n", Status
);
1079 if (!NT_SUCCESS(Status
))
1082 Status
= This
->ServiceGroup
->lpVtbl
->AddMember(This
->ServiceGroup
,
1083 (PSERVICESINK
)&This
->lpVtblServiceSink
);
1084 if (!NT_SUCCESS(Status
))
1086 DPRINT1("Failed to add pin to service group\n");
1090 This
->ServiceGroup
->lpVtbl
->SupportDelayedService(This
->ServiceGroup
);
1091 This
->Stream
->lpVtbl
->SetState(This
->Stream
, KSSTATE_STOP
);
1092 This
->State
= KSSTATE_STOP
;
1093 This
->CommonBufferOffset
= 0;
1094 This
->CommonBufferSize
= This
->DmaChannel
->lpVtbl
->AllocatedBufferSize(This
->DmaChannel
);
1095 This
->CommonBuffer
= This
->DmaChannel
->lpVtbl
->SystemAddress(This
->DmaChannel
);
1096 This
->Capture
= Capture
;
1097 /* delay of 10 milisec */
1098 This
->Delay
= Int32x32To64(10, -10000);
1100 Status
= This
->Stream
->lpVtbl
->SetNotificationFreq(This
->Stream
, 10, &This
->FrameSize
);
1102 SilenceBuffer
= AllocateItem(NonPagedPool
, This
->FrameSize
, TAG_PORTCLASS
);
1104 return STATUS_INSUFFICIENT_RESOURCES
;
1106 This
->Stream
->lpVtbl
->Silence(This
->Stream
, SilenceBuffer
, This
->FrameSize
);
1108 Status
= This
->IrpQueue
->lpVtbl
->Init(This
->IrpQueue
, ConnectDetails
, DataFormat
, DeviceObject
, This
->FrameSize
, 0, SilenceBuffer
);
1109 if (!NT_SUCCESS(Status
))
1111 This
->IrpQueue
->lpVtbl
->Release(This
->IrpQueue
);
1115 Port
->lpVtbl
->AddRef(Port
);
1116 Filter
->lpVtbl
->AddRef(Filter
);
1119 This
->Filter
= Filter
;
1121 //This->Stream->lpVtbl->SetFormat(This->Stream, (PKSDATAFORMAT)This->Format);
1122 DPRINT1("Setting state to acquire %x\n", This
->Stream
->lpVtbl
->SetState(This
->Stream
, KSSTATE_ACQUIRE
));
1123 DPRINT1("Setting state to pause %x\n", This
->Stream
->lpVtbl
->SetState(This
->Stream
, KSSTATE_PAUSE
));
1124 This
->State
= KSSTATE_PAUSE
;
1126 //This->ServiceGroup->lpVtbl->RequestDelayedService(This->ServiceGroup, This->Delay);
1128 return STATUS_SUCCESS
;
1136 IPortPinWaveCyclic_fnGetCompletedPosition(
1137 IN IPortPinWaveCyclic
* iface
)
1148 IPortPinWaveCyclic_fnGetCycleCount(
1149 IN IPortPinWaveCyclic
* iface
)
1160 IPortPinWaveCyclic_fnGetDeviceBufferSize(
1161 IN IPortPinWaveCyclic
* iface
)
1163 IPortPinWaveCyclicImpl
* This
= (IPortPinWaveCyclicImpl
*)iface
;
1165 return This
->CommonBufferSize
;
1173 IPortPinWaveCyclic_fnGetIrpStream(
1174 IN IPortPinWaveCyclic
* iface
)
1176 IPortPinWaveCyclicImpl
* This
= (IPortPinWaveCyclicImpl
*)iface
;
1178 return (PVOID
)This
->IrpQueue
;
1187 IPortPinWaveCyclic_fnGetMiniport(
1188 IN IPortPinWaveCyclic
* iface
)
1190 IPortPinWaveCyclicImpl
* This
= (IPortPinWaveCyclicImpl
*)iface
;
1192 return (PMINIPORT
)This
->Miniport
;
1195 static IPortPinWaveCyclicVtbl vt_IPortPinWaveCyclic
=
1197 IPortPinWaveCyclic_fnQueryInterface
,
1198 IPortPinWaveCyclic_fnAddRef
,
1199 IPortPinWaveCyclic_fnRelease
,
1200 IPortPinWaveCyclic_fnNewIrpTarget
,
1201 IPortPinWaveCyclic_fnDeviceIoControl
,
1202 IPortPinWaveCyclic_fnRead
,
1203 IPortPinWaveCyclic_fnWrite
,
1204 IPortPinWaveCyclic_fnFlush
,
1205 IPortPinWaveCyclic_fnClose
,
1206 IPortPinWaveCyclic_fnQuerySecurity
,
1207 IPortPinWaveCyclic_fnSetSecurity
,
1208 IPortPinWaveCyclic_fnFastDeviceIoControl
,
1209 IPortPinWaveCyclic_fnFastRead
,
1210 IPortPinWaveCyclic_fnFastWrite
,
1211 IPortPinWaveCyclic_fnInit
,
1212 IPortPinWaveCyclic_fnGetCompletedPosition
,
1213 IPortPinWaveCyclic_fnGetCycleCount
,
1214 IPortPinWaveCyclic_fnGetDeviceBufferSize
,
1215 IPortPinWaveCyclic_fnGetIrpStream
,
1216 IPortPinWaveCyclic_fnGetMiniport
1222 NTSTATUS
NewPortPinWaveCyclic(
1223 OUT IPortPinWaveCyclic
** OutPin
)
1225 IPortPinWaveCyclicImpl
* This
;
1227 This
= AllocateItem(NonPagedPool
, sizeof(IPortPinWaveCyclicImpl
), TAG_PORTCLASS
);
1229 return STATUS_INSUFFICIENT_RESOURCES
;
1231 /* initialize IPortPinWaveCyclic */
1233 This
->lpVtbl
= &vt_IPortPinWaveCyclic
;
1234 This
->lpVtblServiceSink
= &vt_IServiceSink
;
1238 *OutPin
= (IPortPinWaveCyclic
*)&This
->lpVtbl
;
1240 return STATUS_SUCCESS
;