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
, &GUID_NULL
))
469 if (Property
->Flags
& KSPROPERTY_TYPE_SETSUPPORT
)
471 if (IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
< sizeof(GUID
))
473 /* buffer too small */
474 Irp
->IoStatus
.Status
= STATUS_BUFFER_OVERFLOW
;
475 Irp
->IoStatus
.Information
= sizeof(GUID
);
476 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
478 return STATUS_BUFFER_OVERFLOW
;
481 * KSPROPSETID_Audio when available
482 * KSPROPSETID_Sysaudio_Pin
484 RtlMoveMemory(Irp
->UserBuffer
, &KSPROPSETID_Connection
, sizeof(GUID
));
486 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
487 Irp
->IoStatus
.Information
= sizeof(GUID
);
488 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
490 return STATUS_SUCCESS
;
495 if (IsEqualGUIDAligned(&Property
->Set
, &KSPROPSETID_Connection
))
497 if (Property
->Id
== KSPROPERTY_CONNECTION_STATE
)
499 PKSSTATE State
= (PKSSTATE
)Irp
->UserBuffer
;
501 ASSERT_IRQL(DISPATCH_LEVEL
);
502 if (IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
< sizeof(KSSTATE
))
504 Irp
->IoStatus
.Information
= sizeof(KSSTATE
);
505 Irp
->IoStatus
.Status
= STATUS_BUFFER_TOO_SMALL
;
506 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
507 return STATUS_BUFFER_TOO_SMALL
;
510 if (Property
->Flags
& KSPROPERTY_TYPE_SET
)
512 Status
= STATUS_UNSUCCESSFUL
;
513 Irp
->IoStatus
.Information
= 0;
517 Status
= This
->Stream
->lpVtbl
->SetState(This
->Stream
, *State
);
519 DPRINT1("Setting state %u %x\n", *State
, Status
);
520 if (NT_SUCCESS(Status
))
522 This
->State
= *State
;
525 Irp
->IoStatus
.Status
= Status
;
526 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
529 else if (Property
->Flags
& KSPROPERTY_TYPE_GET
)
531 *State
= This
->State
;
532 Irp
->IoStatus
.Information
= sizeof(KSSTATE
);
533 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
534 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
535 return STATUS_SUCCESS
;
538 else if (Property
->Id
== KSPROPERTY_CONNECTION_DATAFORMAT
)
540 PKSDATAFORMAT DataFormat
= (PKSDATAFORMAT
)Irp
->UserBuffer
;
541 if (Property
->Flags
& KSPROPERTY_TYPE_SET
)
543 PKSDATAFORMAT NewDataFormat
;
544 if (!RtlCompareMemory(DataFormat
, This
->Format
, DataFormat
->FormatSize
))
546 Irp
->IoStatus
.Information
= DataFormat
->FormatSize
;
547 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
548 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
549 return STATUS_SUCCESS
;
552 NewDataFormat
= AllocateItem(NonPagedPool
, DataFormat
->FormatSize
, TAG_PORTCLASS
);
555 Irp
->IoStatus
.Information
= 0;
556 Irp
->IoStatus
.Status
= STATUS_NO_MEMORY
;
557 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
558 return STATUS_NO_MEMORY
;
560 RtlMoveMemory(NewDataFormat
, DataFormat
, DataFormat
->FormatSize
);
564 ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL
);
565 ASSERT(NewDataFormat
->FormatSize
== sizeof(KSDATAFORMAT_WAVEFORMATEX
));
566 ASSERT(IsEqualGUIDAligned(&((PKSDATAFORMAT_WAVEFORMATEX
)NewDataFormat
)->DataFormat
.MajorFormat
, &KSDATAFORMAT_TYPE_AUDIO
));
567 ASSERT(IsEqualGUIDAligned(&((PKSDATAFORMAT_WAVEFORMATEX
)NewDataFormat
)->DataFormat
.SubFormat
, &KSDATAFORMAT_SUBTYPE_PCM
));
568 ASSERT(IsEqualGUIDAligned(&((PKSDATAFORMAT_WAVEFORMATEX
)NewDataFormat
)->DataFormat
.Specifier
, &KSDATAFORMAT_SPECIFIER_WAVEFORMATEX
));
570 ASSERT(This
->State
== KSSTATE_STOP
);
571 DPRINT1("NewDataFormat: Channels %u Bits %u Samples %u\n", ((PKSDATAFORMAT_WAVEFORMATEX
)NewDataFormat
)->WaveFormatEx
.nChannels
,
572 ((PKSDATAFORMAT_WAVEFORMATEX
)NewDataFormat
)->WaveFormatEx
.wBitsPerSample
,
573 ((PKSDATAFORMAT_WAVEFORMATEX
)NewDataFormat
)->WaveFormatEx
.nSamplesPerSec
);
575 Status
= This
->Stream
->lpVtbl
->SetFormat(This
->Stream
, NewDataFormat
);
576 if (NT_SUCCESS(Status
))
579 ExFreePoolWithTag(This
->Format
, TAG_PORTCLASS
);
581 This
->IrpQueue
->lpVtbl
->UpdateFormat(This
->IrpQueue
, (PKSDATAFORMAT
)NewDataFormat
);
582 This
->Format
= NewDataFormat
;
583 Irp
->IoStatus
.Information
= DataFormat
->FormatSize
;
584 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
585 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
586 return STATUS_SUCCESS
;
589 DPRINT1("Failed to set format\n");
590 Irp
->IoStatus
.Information
= 0;
591 Irp
->IoStatus
.Status
= STATUS_UNSUCCESSFUL
;
592 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
593 return STATUS_UNSUCCESSFUL
;
595 else if (Property
->Flags
& KSPROPERTY_TYPE_GET
)
599 DPRINT1("No format\n");
600 Irp
->IoStatus
.Information
= 0;
601 Irp
->IoStatus
.Status
= STATUS_UNSUCCESSFUL
;
602 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
603 return STATUS_UNSUCCESSFUL
;
605 if (This
->Format
->FormatSize
> IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
)
607 Irp
->IoStatus
.Information
= This
->Format
->FormatSize
;
608 Irp
->IoStatus
.Status
= STATUS_BUFFER_TOO_SMALL
;
609 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
610 return STATUS_BUFFER_TOO_SMALL
;
613 RtlMoveMemory(DataFormat
, This
->Format
, This
->Format
->FormatSize
);
614 Irp
->IoStatus
.Information
= DataFormat
->FormatSize
;
615 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
616 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
617 return STATUS_SUCCESS
;
620 else if (Property
->Id
== KSPROPERTY_CONNECTION_ALLOCATORFRAMING
)
622 PKSALLOCATOR_FRAMING Framing
= (PKSALLOCATOR_FRAMING
)Irp
->UserBuffer
;
624 ASSERT_IRQL(DISPATCH_LEVEL
);
625 /* Validate input buffer */
626 if (IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
< sizeof(KSALLOCATOR_FRAMING
))
628 Irp
->IoStatus
.Information
= sizeof(KSALLOCATOR_FRAMING
);
629 Irp
->IoStatus
.Status
= STATUS_BUFFER_TOO_SMALL
;
630 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
631 return STATUS_BUFFER_TOO_SMALL
;
633 /* Clear frame structure */
634 RtlZeroMemory(Framing
, sizeof(KSALLOCATOR_FRAMING
));
635 /* store requested frame size */
636 Framing
->FrameSize
= This
->FrameSize
;
637 /* FIXME fill in struct */
639 Irp
->IoStatus
.Information
= sizeof(KSALLOCATOR_FRAMING
);
640 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
641 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
642 return STATUS_SUCCESS
;
646 RtlStringFromGUID(&Property
->Set
, &GuidString
);
647 DPRINT1("Unhandeled property Set |%S| Id %u Flags %x\n", GuidString
.Buffer
, Property
->Id
, Property
->Flags
);
648 RtlFreeUnicodeString(&GuidString
);
650 Irp
->IoStatus
.Status
= STATUS_NOT_IMPLEMENTED
;
651 Irp
->IoStatus
.Information
= 0;
652 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
653 return STATUS_NOT_IMPLEMENTED
;
658 IPortPinWaveCyclic_HandleKsStream(
659 IN IPortPinWaveCyclic
* iface
,
663 IPortPinWaveCyclicImpl
* This
= (IPortPinWaveCyclicImpl
*)iface
;
665 InterlockedIncrement((PLONG
)&This
->TotalPackets
);
667 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
));
669 Status
= This
->IrpQueue
->lpVtbl
->AddMapping(This
->IrpQueue
, NULL
, 0, Irp
);
671 return STATUS_PENDING
;
679 IPortPinWaveCyclic_fnDeviceIoControl(
680 IN IPortPinWaveCyclic
* iface
,
681 IN PDEVICE_OBJECT DeviceObject
,
684 PIO_STACK_LOCATION IoStack
;
686 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
689 if (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_KS_PROPERTY
)
691 return IPortPinWaveCyclic_HandleKsProperty(iface
, Irp
);
693 else if (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_KS_ENABLE_EVENT
)
696 /// handle enable event
698 else if (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_KS_DISABLE_EVENT
)
701 /// handle disable event
703 else if (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_KS_RESET_STATE
)
706 /// handle reset state
708 else if (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_KS_WRITE_STREAM
|| IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_KS_READ_STREAM
)
710 return IPortPinWaveCyclic_HandleKsStream(iface
, Irp
);
714 return KsDefaultDeviceIoCompletion(DeviceObject
, Irp
);
719 Irp
->IoStatus
.Information
= 0;
720 Irp
->IoStatus
.Status
= STATUS_UNSUCCESSFUL
;
721 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
723 return STATUS_UNSUCCESSFUL
;
731 IPortPinWaveCyclic_fnRead(
732 IN IPortPinWaveCyclic
* iface
,
733 IN PDEVICE_OBJECT DeviceObject
,
736 return KsDispatchInvalidDeviceRequest(DeviceObject
, Irp
);
744 IPortPinWaveCyclic_fnWrite(
745 IN IPortPinWaveCyclic
* iface
,
746 IN PDEVICE_OBJECT DeviceObject
,
749 return KsDispatchInvalidDeviceRequest(DeviceObject
, Irp
);
757 IPortPinWaveCyclic_fnFlush(
758 IN IPortPinWaveCyclic
* iface
,
759 IN PDEVICE_OBJECT DeviceObject
,
762 return KsDispatchInvalidDeviceRequest(DeviceObject
, Irp
);
768 IN PDEVICE_OBJECT DeviceObject
,
771 PMINIPORTWAVECYCLICSTREAM Stream
;
772 IPortPinWaveCyclicImpl
* This
;
774 PCLOSESTREAM_CONTEXT Ctx
= (PCLOSESTREAM_CONTEXT
)Context
;
776 This
= (IPortPinWaveCyclicImpl
*)Ctx
->Pin
;
778 if (This
->State
!= KSSTATE_STOP
)
780 /* stop stream in case it hasn't been */
781 Status
= This
->Stream
->lpVtbl
->SetState(This
->Stream
, KSSTATE_STOP
);
782 if (!NT_SUCCESS(Status
))
783 DPRINT1("Warning: failed to stop stream with %x\n", Status
);
785 This
->State
= KSSTATE_STOP
;
791 ExFreePool(This
->Format
);
797 This
->IrpQueue
->lpVtbl
->Release(This
->IrpQueue
);
800 /* complete the irp */
801 Ctx
->Irp
->IoStatus
.Information
= 0;
802 Ctx
->Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
803 IoCompleteRequest(Ctx
->Irp
, IO_NO_INCREMENT
);
805 /* free the work item */
806 IoFreeWorkItem(Ctx
->WorkItem
);
808 /* free work item ctx */
809 FreeItem(Ctx
, TAG_PORTCLASS
);
811 /* release reference to port driver */
812 This
->Port
->lpVtbl
->Release(This
->Port
);
814 /* release reference to filter instance */
815 This
->Filter
->lpVtbl
->Release(This
->Filter
);
819 Stream
= This
->Stream
;
821 This
->Filter
->lpVtbl
->FreePin(This
->Filter
, (IPortPinWaveCyclic
*)This
);
822 DPRINT1("Closing stream at Irql %u\n", KeGetCurrentIrql());
823 Stream
->lpVtbl
->Release(Stream
);
832 IPortPinWaveCyclic_fnClose(
833 IN IPortPinWaveCyclic
* iface
,
834 IN PDEVICE_OBJECT DeviceObject
,
837 PCLOSESTREAM_CONTEXT Ctx
;
838 IPortPinWaveCyclicImpl
* This
= (IPortPinWaveCyclicImpl
*)iface
;
842 /* allocate a close context */
843 Ctx
= AllocateItem(NonPagedPool
, sizeof(CLOSESTREAM_CONTEXT
), TAG_PORTCLASS
);
846 DPRINT1("Failed to allocate stream context\n");
849 /* allocate work context */
850 Ctx
->WorkItem
= IoAllocateWorkItem(DeviceObject
);
853 DPRINT1("Failed to allocate work item\n");
856 /* setup the close context */
858 Ctx
->Pin
= (PVOID
)This
;
860 IoMarkIrpPending(Irp
);
861 Irp
->IoStatus
.Information
= 0;
862 Irp
->IoStatus
.Status
= STATUS_PENDING
;
864 /* remove member from service group */
865 This
->ServiceGroup
->lpVtbl
->RemoveMember(This
->ServiceGroup
, (PSERVICESINK
)&This
->lpVtblServiceSink
);
867 /* defer work item */
868 IoQueueWorkItem(Ctx
->WorkItem
, CloseStreamRoutine
, DelayedWorkQueue
, (PVOID
)Ctx
);
870 return STATUS_PENDING
;
873 Irp
->IoStatus
.Information
= 0;
874 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
875 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
877 return STATUS_SUCCESS
;
882 FreeItem(Ctx
, TAG_PORTCLASS
);
884 Irp
->IoStatus
.Information
= 0;
885 Irp
->IoStatus
.Status
= STATUS_UNSUCCESSFUL
;
886 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
887 return STATUS_UNSUCCESSFUL
;
896 IPortPinWaveCyclic_fnQuerySecurity(
897 IN IPortPinWaveCyclic
* iface
,
898 IN PDEVICE_OBJECT DeviceObject
,
901 return KsDispatchInvalidDeviceRequest(DeviceObject
, Irp
);
909 IPortPinWaveCyclic_fnSetSecurity(
910 IN IPortPinWaveCyclic
* iface
,
911 IN PDEVICE_OBJECT DeviceObject
,
914 return KsDispatchInvalidDeviceRequest(DeviceObject
, Irp
);
922 IPortPinWaveCyclic_fnFastDeviceIoControl(
923 IN IPortPinWaveCyclic
* iface
,
924 IN PFILE_OBJECT FileObject
,
926 IN PVOID InputBuffer
,
927 IN ULONG InputBufferLength
,
928 OUT PVOID OutputBuffer
,
929 IN ULONG OutputBufferLength
,
930 IN ULONG IoControlCode
,
931 OUT PIO_STATUS_BLOCK StatusBlock
,
932 IN PDEVICE_OBJECT DeviceObject
)
934 return KsDispatchFastIoDeviceControlFailure(FileObject
, Wait
, InputBuffer
, InputBufferLength
, OutputBuffer
, OutputBufferLength
, IoControlCode
, StatusBlock
, DeviceObject
);
942 IPortPinWaveCyclic_fnFastRead(
943 IN IPortPinWaveCyclic
* iface
,
944 IN PFILE_OBJECT FileObject
,
945 IN PLARGE_INTEGER FileOffset
,
950 OUT PIO_STATUS_BLOCK StatusBlock
,
951 IN PDEVICE_OBJECT DeviceObject
)
954 PCONTEXT_WRITE Packet
;
956 IPortPinWaveCyclicImpl
* This
= (IPortPinWaveCyclicImpl
*)iface
;
958 /* HACK to be removed */
960 DPRINT("IPortPinWaveCyclic_fnFastRead entered\n");
962 Packet
= (PCONTEXT_WRITE
)Buffer
;
965 StatusBlock
->Status
= STATUS_PENDING
;
967 Status
= This
->IrpQueue
->lpVtbl
->AddMapping(This
->IrpQueue
, Buffer
, Length
, Irp
);
969 if (!NT_SUCCESS(Status
))
972 StatusBlock
->Status
= STATUS_PENDING
;
982 IPortPinWaveCyclic_fnFastWrite(
983 IN IPortPinWaveCyclic
* iface
,
984 IN PFILE_OBJECT FileObject
,
985 IN PLARGE_INTEGER FileOffset
,
990 OUT PIO_STATUS_BLOCK StatusBlock
,
991 IN PDEVICE_OBJECT DeviceObject
)
994 PCONTEXT_WRITE Packet
;
996 IPortPinWaveCyclicImpl
* This
= (IPortPinWaveCyclicImpl
*)iface
;
998 /* HACK to be removed */
1000 InterlockedIncrement((PLONG
)&This
->TotalPackets
);
1002 DPRINT("IPortPinWaveCyclic_fnFastWrite entered Total %u State %x MinData %u\n", This
->TotalPackets
, This
->State
, This
->IrpQueue
->lpVtbl
->NumData(This
->IrpQueue
));
1004 Packet
= (PCONTEXT_WRITE
)Buffer
;
1007 Status
= This
->IrpQueue
->lpVtbl
->AddMapping(This
->IrpQueue
, Buffer
, Length
, Irp
);
1009 if (!NT_SUCCESS(Status
))
1012 StatusBlock
->Status
= STATUS_PENDING
;
1022 IPortPinWaveCyclic_fnInit(
1023 IN IPortPinWaveCyclic
* iface
,
1024 IN PPORTWAVECYCLIC Port
,
1025 IN PPORTFILTERWAVECYCLIC Filter
,
1026 IN KSPIN_CONNECT
* ConnectDetails
,
1027 IN KSPIN_DESCRIPTOR
* KsPinDescriptor
)
1030 PKSDATAFORMAT DataFormat
;
1031 PDEVICE_OBJECT DeviceObject
;
1033 PVOID SilenceBuffer
;
1034 //IDrmAudioStream * DrmAudio = NULL;
1036 IPortPinWaveCyclicImpl
* This
= (IPortPinWaveCyclicImpl
*)iface
;
1038 This
->KsPinDescriptor
= KsPinDescriptor
;
1039 This
->ConnectDetails
= ConnectDetails
;
1040 This
->Miniport
= GetWaveCyclicMiniport(Port
);
1042 DeviceObject
= GetDeviceObject(Port
);
1044 DataFormat
= (PKSDATAFORMAT
)(ConnectDetails
+ 1);
1046 DPRINT("IPortPinWaveCyclic_fnInit entered\n");
1048 This
->Format
= ExAllocatePoolWithTag(NonPagedPool
, DataFormat
->FormatSize
, TAG_PORTCLASS
);
1050 return STATUS_INSUFFICIENT_RESOURCES
;
1052 RtlMoveMemory(This
->Format
, DataFormat
, DataFormat
->FormatSize
);
1054 Status
= NewIrpQueue(&This
->IrpQueue
);
1055 if (!NT_SUCCESS(Status
))
1058 if (KsPinDescriptor
->Communication
== KSPIN_COMMUNICATION_SINK
&& KsPinDescriptor
->DataFlow
== KSPIN_DATAFLOW_IN
)
1062 else if (KsPinDescriptor
->Communication
== KSPIN_COMMUNICATION_SINK
&& KsPinDescriptor
->DataFlow
== KSPIN_DATAFLOW_OUT
)
1068 DPRINT1("Unexpected Communication %u DataFlow %u\n", KsPinDescriptor
->Communication
, KsPinDescriptor
->DataFlow
);
1073 Status
= This
->Miniport
->lpVtbl
->NewStream(This
->Miniport
,
1077 ConnectDetails
->PinId
,
1081 &This
->ServiceGroup
);
1083 Status
= This
->Stream
->lpVtbl
->QueryInterface(This
->Stream
, &IID_IDrmAudioStream
, (PVOID
*)&DrmAudio
);
1084 if (NT_SUCCESS(Status
))
1086 DRMRIGHTS DrmRights
;
1087 DPRINT1("Got IID_IDrmAudioStream interface %p\n", DrmAudio
);
1089 DrmRights
.CopyProtect
= FALSE
;
1090 DrmRights
.Reserved
= 0;
1091 DrmRights
.DigitalOutputDisable
= FALSE
;
1093 Status
= DrmAudio
->lpVtbl
->SetContentId(DrmAudio
, 1, &DrmRights
);
1094 DPRINT("Status %x\n", Status
);
1098 DPRINT("IPortPinWaveCyclic_fnInit Status %x\n", Status
);
1100 if (!NT_SUCCESS(Status
))
1103 Status
= This
->ServiceGroup
->lpVtbl
->AddMember(This
->ServiceGroup
,
1104 (PSERVICESINK
)&This
->lpVtblServiceSink
);
1105 if (!NT_SUCCESS(Status
))
1107 DPRINT1("Failed to add pin to service group\n");
1111 This
->ServiceGroup
->lpVtbl
->SupportDelayedService(This
->ServiceGroup
);
1112 This
->Stream
->lpVtbl
->SetState(This
->Stream
, KSSTATE_STOP
);
1113 This
->State
= KSSTATE_STOP
;
1114 This
->CommonBufferOffset
= 0;
1115 This
->CommonBufferSize
= This
->DmaChannel
->lpVtbl
->AllocatedBufferSize(This
->DmaChannel
);
1116 This
->CommonBuffer
= This
->DmaChannel
->lpVtbl
->SystemAddress(This
->DmaChannel
);
1117 This
->Capture
= Capture
;
1118 /* delay of 10 milisec */
1119 This
->Delay
= Int32x32To64(10, -10000);
1121 Status
= This
->Stream
->lpVtbl
->SetNotificationFreq(This
->Stream
, 10, &This
->FrameSize
);
1123 SilenceBuffer
= AllocateItem(NonPagedPool
, This
->FrameSize
, TAG_PORTCLASS
);
1125 return STATUS_INSUFFICIENT_RESOURCES
;
1127 This
->Stream
->lpVtbl
->Silence(This
->Stream
, SilenceBuffer
, This
->FrameSize
);
1129 Status
= This
->IrpQueue
->lpVtbl
->Init(This
->IrpQueue
, ConnectDetails
, DataFormat
, DeviceObject
, This
->FrameSize
, 0, SilenceBuffer
);
1130 if (!NT_SUCCESS(Status
))
1132 This
->IrpQueue
->lpVtbl
->Release(This
->IrpQueue
);
1136 Port
->lpVtbl
->AddRef(Port
);
1137 Filter
->lpVtbl
->AddRef(Filter
);
1140 This
->Filter
= Filter
;
1142 //This->Stream->lpVtbl->SetFormat(This->Stream, (PKSDATAFORMAT)This->Format);
1143 DPRINT1("Setting state to acquire %x\n", This
->Stream
->lpVtbl
->SetState(This
->Stream
, KSSTATE_ACQUIRE
));
1144 DPRINT1("Setting state to pause %x\n", This
->Stream
->lpVtbl
->SetState(This
->Stream
, KSSTATE_PAUSE
));
1145 This
->State
= KSSTATE_PAUSE
;
1147 //This->ServiceGroup->lpVtbl->RequestDelayedService(This->ServiceGroup, This->Delay);
1149 return STATUS_SUCCESS
;
1157 IPortPinWaveCyclic_fnGetCompletedPosition(
1158 IN IPortPinWaveCyclic
* iface
)
1169 IPortPinWaveCyclic_fnGetCycleCount(
1170 IN IPortPinWaveCyclic
* iface
)
1181 IPortPinWaveCyclic_fnGetDeviceBufferSize(
1182 IN IPortPinWaveCyclic
* iface
)
1184 IPortPinWaveCyclicImpl
* This
= (IPortPinWaveCyclicImpl
*)iface
;
1186 return This
->CommonBufferSize
;
1194 IPortPinWaveCyclic_fnGetIrpStream(
1195 IN IPortPinWaveCyclic
* iface
)
1197 IPortPinWaveCyclicImpl
* This
= (IPortPinWaveCyclicImpl
*)iface
;
1199 return (PVOID
)This
->IrpQueue
;
1208 IPortPinWaveCyclic_fnGetMiniport(
1209 IN IPortPinWaveCyclic
* iface
)
1211 IPortPinWaveCyclicImpl
* This
= (IPortPinWaveCyclicImpl
*)iface
;
1213 return (PMINIPORT
)This
->Miniport
;
1216 static IPortPinWaveCyclicVtbl vt_IPortPinWaveCyclic
=
1218 IPortPinWaveCyclic_fnQueryInterface
,
1219 IPortPinWaveCyclic_fnAddRef
,
1220 IPortPinWaveCyclic_fnRelease
,
1221 IPortPinWaveCyclic_fnNewIrpTarget
,
1222 IPortPinWaveCyclic_fnDeviceIoControl
,
1223 IPortPinWaveCyclic_fnRead
,
1224 IPortPinWaveCyclic_fnWrite
,
1225 IPortPinWaveCyclic_fnFlush
,
1226 IPortPinWaveCyclic_fnClose
,
1227 IPortPinWaveCyclic_fnQuerySecurity
,
1228 IPortPinWaveCyclic_fnSetSecurity
,
1229 IPortPinWaveCyclic_fnFastDeviceIoControl
,
1230 IPortPinWaveCyclic_fnFastRead
,
1231 IPortPinWaveCyclic_fnFastWrite
,
1232 IPortPinWaveCyclic_fnInit
,
1233 IPortPinWaveCyclic_fnGetCompletedPosition
,
1234 IPortPinWaveCyclic_fnGetCycleCount
,
1235 IPortPinWaveCyclic_fnGetDeviceBufferSize
,
1236 IPortPinWaveCyclic_fnGetIrpStream
,
1237 IPortPinWaveCyclic_fnGetMiniport
1243 NTSTATUS
NewPortPinWaveCyclic(
1244 OUT IPortPinWaveCyclic
** OutPin
)
1246 IPortPinWaveCyclicImpl
* This
;
1248 This
= AllocateItem(NonPagedPool
, sizeof(IPortPinWaveCyclicImpl
), TAG_PORTCLASS
);
1250 return STATUS_INSUFFICIENT_RESOURCES
;
1252 /* initialize IPortPinWaveCyclic */
1254 This
->lpVtbl
= &vt_IPortPinWaveCyclic
;
1255 This
->lpVtblServiceSink
= &vt_IServiceSink
;
1259 *OutPin
= (IPortPinWaveCyclic
*)&This
->lpVtbl
;
1261 return STATUS_SUCCESS
;