2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Kernel Streaming
4 * FILE: drivers/wdm/audio/backpln/portcls/pin_WavePci.c
5 * PURPOSE: WavePci IRP Audio Pin
6 * PROGRAMMER: Johannes Anderwald
13 IPortPinWavePciVtbl
*lpVtbl
;
14 IServiceSinkVtbl
*lpVtblServiceSink
;
15 IPortWavePciStreamVtbl
*lpVtblPortWavePciStream
;
19 IPortFilterWavePci
* Filter
;
20 KSPIN_DESCRIPTOR
* KsPinDescriptor
;
21 PMINIPORTWAVEPCI Miniport
;
22 PSERVICEGROUP ServiceGroup
;
23 PDMACHANNEL DmaChannel
;
24 PMINIPORTWAVEPCISTREAM Stream
;
27 KSPIN_CONNECT
* ConnectDetails
;
30 PDEVICE_OBJECT DeviceObject
;
43 KSALLOCATOR_FRAMING AllocatorFraming
;
49 IPortPinWavePciImpl
*Pin
;
50 PIO_WORKITEM WorkItem
;
52 }SETSTREAM_CONTEXT
, *PSETSTREAM_CONTEXT
;
54 //==================================================================================================================================
58 IPortWavePciStream_fnQueryInterface(
59 IPortWavePciStream
* iface
,
63 IPortPinWavePciImpl
* This
= (IPortPinWavePciImpl
*)CONTAINING_RECORD(iface
, IPortPinWavePciImpl
, lpVtblPortWavePciStream
);
65 DPRINT("IPortWavePciStream_fnQueryInterface entered\n");
67 if (IsEqualGUIDAligned(refiid
, &IID_IPortWavePciStream
) ||
68 IsEqualGUIDAligned(refiid
, &IID_IUnknown
))
70 *Output
= &This
->lpVtbl
;
71 InterlockedIncrement(&This
->ref
);
72 return STATUS_SUCCESS
;
75 return STATUS_UNSUCCESSFUL
;
81 IPortWavePciStream_fnAddRef(
82 IPortWavePciStream
* iface
)
84 IPortPinWavePciImpl
* This
= (IPortPinWavePciImpl
*)CONTAINING_RECORD(iface
, IPortPinWavePciImpl
, lpVtblPortWavePciStream
);
85 DPRINT("IPortWavePciStream_fnAddRef entered\n");
87 return InterlockedIncrement(&This
->ref
);
93 IPortWavePciStream_fnRelease(
94 IPortWavePciStream
* iface
)
96 IPortPinWavePciImpl
* This
= (IPortPinWavePciImpl
*)CONTAINING_RECORD(iface
, IPortPinWavePciImpl
, lpVtblPortWavePciStream
);
98 InterlockedDecrement(&This
->ref
);
100 DPRINT("IPortWavePciStream_fnRelease entered %u\n", This
->ref
);
102 /* Return new reference count */
109 IPortWavePciStream_fnGetMapping(
110 IN IPortWavePciStream
*iface
,
112 OUT PPHYSICAL_ADDRESS PhysicalAddress
,
113 OUT PVOID
*VirtualAddress
,
114 OUT PULONG ByteCount
,
117 IPortPinWavePciImpl
* This
= (IPortPinWavePciImpl
*)CONTAINING_RECORD(iface
, IPortPinWavePciImpl
, lpVtblPortWavePciStream
);
119 ASSERT_IRQL(DISPATCH_LEVEL
);
120 return This
->IrpQueue
->lpVtbl
->GetMappingWithTag(This
->IrpQueue
, Tag
, PhysicalAddress
, VirtualAddress
, ByteCount
, Flags
);
126 IPortWavePciStream_fnReleaseMapping(
127 IN IPortWavePciStream
*iface
,
130 IPortPinWavePciImpl
* This
= (IPortPinWavePciImpl
*)CONTAINING_RECORD(iface
, IPortPinWavePciImpl
, lpVtblPortWavePciStream
);
132 ASSERT_IRQL(DISPATCH_LEVEL
);
133 return This
->IrpQueue
->lpVtbl
->ReleaseMappingWithTag(This
->IrpQueue
, Tag
);
139 IPortWavePciStream_fnTerminatePacket(
140 IN IPortWavePciStream
*iface
)
143 ASSERT_IRQL(DISPATCH_LEVEL
);
144 return STATUS_SUCCESS
;
148 static IPortWavePciStreamVtbl vt_PortWavePciStream
=
150 IPortWavePciStream_fnQueryInterface
,
151 IPortWavePciStream_fnAddRef
,
152 IPortWavePciStream_fnRelease
,
153 IPortWavePciStream_fnGetMapping
,
154 IPortWavePciStream_fnReleaseMapping
,
155 IPortWavePciStream_fnTerminatePacket
162 IServiceSink_fnQueryInterface(
167 IPortPinWavePciImpl
* This
= (IPortPinWavePciImpl
*)CONTAINING_RECORD(iface
, IPortPinWavePciImpl
, lpVtblServiceSink
);
169 DPRINT("IServiceSink_fnQueryInterface entered\n");
171 if (IsEqualGUIDAligned(refiid
, &IID_IServiceSink
) ||
172 IsEqualGUIDAligned(refiid
, &IID_IUnknown
))
174 *Output
= &This
->lpVtblServiceSink
;
175 InterlockedIncrement(&This
->ref
);
176 return STATUS_SUCCESS
;
178 return STATUS_UNSUCCESSFUL
;
184 IServiceSink_fnAddRef(
187 IPortPinWavePciImpl
* This
= (IPortPinWavePciImpl
*)CONTAINING_RECORD(iface
, IPortPinWavePciImpl
, lpVtblServiceSink
);
188 DPRINT("IServiceSink_fnAddRef entered\n");
190 return InterlockedIncrement(&This
->ref
);
196 IServiceSink_fnRelease(
199 IPortPinWavePciImpl
* This
= (IPortPinWavePciImpl
*)CONTAINING_RECORD(iface
, IPortPinWavePciImpl
, lpVtblServiceSink
);
201 InterlockedDecrement(&This
->ref
);
203 DPRINT("IServiceSink_fnRelease entered %u\n", This
->ref
);
207 FreeItem(This
, TAG_PORTCLASS
);
210 /* Return new reference count */
216 SetStreamWorkerRoutine(
217 IN PDEVICE_OBJECT DeviceObject
,
220 IPortPinWavePciImpl
* This
;
221 PSETSTREAM_CONTEXT Ctx
= (PSETSTREAM_CONTEXT
)Context
;
223 ULONG MinimumDataThreshold
;
224 ULONG MaximumDataThreshold
;
229 IoFreeWorkItem(Ctx
->WorkItem
);
230 FreeItem(Ctx
, TAG_PORTCLASS
);
232 /* Has the audio stream resumed? */
233 if (This
->IrpQueue
->lpVtbl
->NumMappings(This
->IrpQueue
) && State
== KSSTATE_STOP
)
237 if (NT_SUCCESS(This
->Stream
->lpVtbl
->SetState(This
->Stream
, State
)))
239 /* Set internal state to stop */
242 if (This
->State
== KSSTATE_STOP
)
244 /* reset start stream */
245 This
->IrpQueue
->lpVtbl
->CancelBuffers(This
->IrpQueue
); //FIX function name
246 //This->ServiceGroup->lpVtbl->CancelDelayedService(This->ServiceGroup);
247 /* increase stop counter */
249 /* get current data threshold */
250 MinimumDataThreshold
= This
->IrpQueue
->lpVtbl
->GetMinimumDataThreshold(This
->IrpQueue
);
251 /* get maximum data threshold */
252 MaximumDataThreshold
= ((PKSDATAFORMAT_WAVEFORMATEX
)This
->Format
)->WaveFormatEx
.nAvgBytesPerSec
;
253 /* increase minimum data threshold by 10 frames */
254 MinimumDataThreshold
+= This
->AllocatorFraming
.FrameSize
* 10;
256 /* assure it has not exceeded */
257 MinimumDataThreshold
= min(MinimumDataThreshold
, MaximumDataThreshold
);
258 /* store minimum data threshold */
259 This
->IrpQueue
->lpVtbl
->SetMinimumDataThreshold(This
->IrpQueue
, MinimumDataThreshold
);
261 DPRINT1("Stopping PreCompleted %u PostCompleted %u StopCount %u MinimumDataThreshold %u\n", This
->PreCompleted
, This
->PostCompleted
, This
->StopCount
, MinimumDataThreshold
);
263 if (This
->State
== KSSTATE_RUN
)
265 /* start the notification timer */
266 //This->ServiceGroup->lpVtbl->RequestDelayedService(This->ServiceGroup, This->Delay);
274 IN IPortPinWavePciImpl
* This
,
277 PDEVICE_OBJECT DeviceObject
;
278 PIO_WORKITEM WorkItem
;
279 PSETSTREAM_CONTEXT Context
;
281 ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL
);
283 /* Has the audio stream resumed? */
284 if (This
->IrpQueue
->lpVtbl
->NumMappings(This
->IrpQueue
) && State
== KSSTATE_STOP
)
287 /* Has the audio state already been set? */
288 if (This
->State
== State
)
291 /* Get device object */
292 DeviceObject
= GetDeviceObjectFromPortWavePci(This
->Port
);
294 /* allocate set state context */
295 Context
= AllocateItem(NonPagedPool
, sizeof(SETSTREAM_CONTEXT
), TAG_PORTCLASS
);
300 /* allocate work item */
301 WorkItem
= IoAllocateWorkItem(DeviceObject
);
309 Context
->Pin
= (PVOID
)This
;
310 Context
->WorkItem
= WorkItem
;
311 Context
->State
= State
;
313 /* queue the work item */
314 IoQueueWorkItem(WorkItem
, SetStreamWorkerRoutine
, DelayedWorkQueue
, (PVOID
)Context
);
320 IServiceSink_fnRequestService(
323 IPortPinWavePciImpl
* This
= (IPortPinWavePciImpl
*)CONTAINING_RECORD(iface
, IPortPinWavePciImpl
, lpVtblServiceSink
);
325 ASSERT_IRQL(DISPATCH_LEVEL
);
327 if (This
->IrpQueue
->lpVtbl
->HasLastMappingFailed(This
->IrpQueue
))
329 if (This
->IrpQueue
->lpVtbl
->NumMappings(This
->IrpQueue
) == 0)
331 DPRINT("Stopping stream...\n");
332 SetStreamState(This
, KSSTATE_STOP
);
337 This
->Stream
->lpVtbl
->Service(This
->Stream
);
342 static IServiceSinkVtbl vt_IServiceSink
=
344 IServiceSink_fnQueryInterface
,
345 IServiceSink_fnAddRef
,
346 IServiceSink_fnRelease
,
347 IServiceSink_fnRequestService
350 //==================================================================================================================================
356 IPortPinWavePci_fnQueryInterface(
357 IPortPinWavePci
* iface
,
361 IPortPinWavePciImpl
* This
= (IPortPinWavePciImpl
*)iface
;
363 if (IsEqualGUIDAligned(refiid
, &IID_IIrpTarget
) ||
364 IsEqualGUIDAligned(refiid
, &IID_IUnknown
))
366 *Output
= &This
->lpVtbl
;
367 InterlockedIncrement(&This
->ref
);
368 return STATUS_SUCCESS
;
371 return STATUS_UNSUCCESSFUL
;
379 IPortPinWavePci_fnAddRef(
380 IPortPinWavePci
* iface
)
382 IPortPinWavePciImpl
* This
= (IPortPinWavePciImpl
*)iface
;
384 return InterlockedIncrement(&This
->ref
);
392 IPortPinWavePci_fnRelease(
393 IPortPinWavePci
* iface
)
395 IPortPinWavePciImpl
* This
= (IPortPinWavePciImpl
*)iface
;
397 InterlockedDecrement(&This
->ref
);
401 FreeItem(This
, TAG_PORTCLASS
);
412 IPortPinWavePci_fnNewIrpTarget(
413 IN IPortPinWavePci
* iface
,
414 OUT
struct IIrpTarget
**OutTarget
,
417 IN POOL_TYPE PoolType
,
418 IN PDEVICE_OBJECT DeviceObject
,
420 IN KSOBJECT_CREATE
*CreateObject
)
424 Irp
->IoStatus
.Information
= 0;
425 Irp
->IoStatus
.Status
= STATUS_UNSUCCESSFUL
;
426 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
428 return STATUS_UNSUCCESSFUL
;
433 IPortPinWavePci_HandleKsProperty(
434 IN IPortPinWavePci
* iface
,
435 IN PVOID InputBuffer
,
436 IN ULONG InputBufferLength
,
437 IN PVOID OutputBuffer
,
438 IN ULONG OutputBufferLength
,
439 IN PIO_STATUS_BLOCK IoStatusBlock
)
441 PKSPROPERTY Property
;
443 UNICODE_STRING GuidString
;
445 IPortPinWavePciImpl
* This
= (IPortPinWavePciImpl
*)iface
;
448 DPRINT("IPortPinWavePci_HandleKsProperty entered\n");
450 if (InputBufferLength
< sizeof(KSPROPERTY
))
452 IoStatusBlock
->Information
= 0;
453 IoStatusBlock
->Status
= STATUS_INVALID_PARAMETER
;
454 return STATUS_INVALID_PARAMETER
;
457 Property
= (PKSPROPERTY
)InputBuffer
;
459 if (IsEqualGUIDAligned(&Property
->Set
, &KSPROPSETID_Connection
))
461 if (Property
->Id
== KSPROPERTY_CONNECTION_STATE
)
463 PKSSTATE State
= (PKSSTATE
)OutputBuffer
;
465 ASSERT_IRQL(DISPATCH_LEVEL
);
466 if (OutputBufferLength
< sizeof(KSSTATE
))
468 IoStatusBlock
->Information
= sizeof(KSSTATE
);
469 IoStatusBlock
->Status
= STATUS_BUFFER_TOO_SMALL
;
470 return STATUS_BUFFER_TOO_SMALL
;
473 if (Property
->Flags
& KSPROPERTY_TYPE_SET
)
475 Status
= STATUS_UNSUCCESSFUL
;
476 IoStatusBlock
->Information
= 0;
480 Status
= This
->Stream
->lpVtbl
->SetState(This
->Stream
, *State
);
482 DPRINT1("Setting state %u %x\n", *State
, Status
);
483 if (NT_SUCCESS(Status
))
485 This
->State
= *State
;
488 IoStatusBlock
->Status
= Status
;
491 else if (Property
->Flags
& KSPROPERTY_TYPE_GET
)
493 *State
= This
->State
;
494 IoStatusBlock
->Information
= sizeof(KSSTATE
);
495 IoStatusBlock
->Status
= STATUS_SUCCESS
;
496 return STATUS_SUCCESS
;
499 else if (Property
->Id
== KSPROPERTY_CONNECTION_DATAFORMAT
)
501 PKSDATAFORMAT DataFormat
= (PKSDATAFORMAT
)OutputBuffer
;
502 if (Property
->Flags
& KSPROPERTY_TYPE_SET
)
504 PKSDATAFORMAT NewDataFormat
;
505 if (!RtlCompareMemory(DataFormat
, This
->Format
, DataFormat
->FormatSize
))
507 IoStatusBlock
->Information
= DataFormat
->FormatSize
;
508 IoStatusBlock
->Status
= STATUS_SUCCESS
;
509 return STATUS_SUCCESS
;
512 NewDataFormat
= AllocateItem(NonPagedPool
, DataFormat
->FormatSize
, TAG_PORTCLASS
);
515 IoStatusBlock
->Information
= 0;
516 IoStatusBlock
->Status
= STATUS_NO_MEMORY
;
517 return STATUS_NO_MEMORY
;
519 RtlMoveMemory(NewDataFormat
, DataFormat
, DataFormat
->FormatSize
);
523 ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL
);
524 ASSERT(NewDataFormat
->FormatSize
== sizeof(KSDATAFORMAT_WAVEFORMATEX
));
525 ASSERT(IsEqualGUIDAligned(&((PKSDATAFORMAT_WAVEFORMATEX
)NewDataFormat
)->DataFormat
.MajorFormat
, &KSDATAFORMAT_TYPE_AUDIO
));
526 ASSERT(IsEqualGUIDAligned(&((PKSDATAFORMAT_WAVEFORMATEX
)NewDataFormat
)->DataFormat
.SubFormat
, &KSDATAFORMAT_SUBTYPE_PCM
));
527 ASSERT(IsEqualGUIDAligned(&((PKSDATAFORMAT_WAVEFORMATEX
)NewDataFormat
)->DataFormat
.Specifier
, &KSDATAFORMAT_SPECIFIER_WAVEFORMATEX
));
529 ASSERT(This
->State
== KSSTATE_STOP
);
530 DPRINT1("NewDataFormat: Channels %u Bits %u Samples %u\n", ((PKSDATAFORMAT_WAVEFORMATEX
)NewDataFormat
)->WaveFormatEx
.nChannels
,
531 ((PKSDATAFORMAT_WAVEFORMATEX
)NewDataFormat
)->WaveFormatEx
.wBitsPerSample
,
532 ((PKSDATAFORMAT_WAVEFORMATEX
)NewDataFormat
)->WaveFormatEx
.nSamplesPerSec
);
534 Status
= This
->Stream
->lpVtbl
->SetFormat(This
->Stream
, NewDataFormat
);
535 if (NT_SUCCESS(Status
))
538 ExFreePoolWithTag(This
->Format
, TAG_PORTCLASS
);
540 This
->IrpQueue
->lpVtbl
->UpdateFormat(This
->IrpQueue
, (PKSDATAFORMAT
)NewDataFormat
);
541 This
->Format
= NewDataFormat
;
542 IoStatusBlock
->Information
= DataFormat
->FormatSize
;
543 IoStatusBlock
->Status
= STATUS_SUCCESS
;
544 return STATUS_SUCCESS
;
547 DPRINT1("Failed to set format\n");
548 IoStatusBlock
->Information
= 0;
549 IoStatusBlock
->Status
= STATUS_UNSUCCESSFUL
;
550 return STATUS_UNSUCCESSFUL
;
552 else if (Property
->Flags
& KSPROPERTY_TYPE_GET
)
556 DPRINT1("No format\n");
557 IoStatusBlock
->Information
= 0;
558 IoStatusBlock
->Status
= STATUS_UNSUCCESSFUL
;
559 return STATUS_UNSUCCESSFUL
;
561 if (This
->Format
->FormatSize
> OutputBufferLength
)
563 IoStatusBlock
->Information
= This
->Format
->FormatSize
;
564 IoStatusBlock
->Status
= STATUS_BUFFER_TOO_SMALL
;
565 return STATUS_BUFFER_TOO_SMALL
;
568 RtlMoveMemory(DataFormat
, This
->Format
, This
->Format
->FormatSize
);
569 IoStatusBlock
->Information
= DataFormat
->FormatSize
;
570 IoStatusBlock
->Status
= STATUS_SUCCESS
;
571 return STATUS_SUCCESS
;
574 else if (Property
->Id
== KSPROPERTY_CONNECTION_ALLOCATORFRAMING
)
576 PKSALLOCATOR_FRAMING Framing
= (PKSALLOCATOR_FRAMING
)OutputBuffer
;
578 ASSERT_IRQL(DISPATCH_LEVEL
);
579 /* Validate input buffer */
580 if (OutputBufferLength
< sizeof(KSALLOCATOR_FRAMING
))
582 IoStatusBlock
->Information
= sizeof(KSALLOCATOR_FRAMING
);
583 IoStatusBlock
->Status
= STATUS_BUFFER_TOO_SMALL
;
584 return STATUS_BUFFER_TOO_SMALL
;
586 /* copy frame allocator struct */
587 RtlMoveMemory(Framing
, &This
->AllocatorFraming
, sizeof(KSALLOCATOR_FRAMING
));
589 IoStatusBlock
->Information
= sizeof(KSALLOCATOR_FRAMING
);
590 IoStatusBlock
->Status
= STATUS_SUCCESS
;
591 return STATUS_SUCCESS
;
595 RtlStringFromGUID(&Property
->Set
, &GuidString
);
596 DPRINT1("Unhandeled property Set |%S| Id %u Flags %x\n", GuidString
.Buffer
, Property
->Id
, Property
->Flags
);
597 RtlFreeUnicodeString(&GuidString
);
599 IoStatusBlock
->Status
= STATUS_NOT_IMPLEMENTED
;
600 IoStatusBlock
->Information
= 0;
601 return STATUS_NOT_IMPLEMENTED
;
609 IPortPinWavePci_fnDeviceIoControl(
610 IN IPortPinWavePci
* iface
,
611 IN PDEVICE_OBJECT DeviceObject
,
614 PIO_STACK_LOCATION IoStack
;
617 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
619 if (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_KS_PROPERTY
)
621 Status
= IPortPinWavePci_HandleKsProperty(iface
, IoStack
->Parameters
.DeviceIoControl
.Type3InputBuffer
, IoStack
->Parameters
.DeviceIoControl
.InputBufferLength
, Irp
->UserBuffer
, IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
, &Irp
->IoStatus
);
622 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
629 Irp
->IoStatus
.Information
= 0;
630 Irp
->IoStatus
.Status
= STATUS_UNSUCCESSFUL
;
631 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
633 return STATUS_UNSUCCESSFUL
;
641 IPortPinWavePci_fnRead(
642 IN IPortPinWavePci
* iface
,
643 IN PDEVICE_OBJECT DeviceObject
,
646 return KsDispatchInvalidDeviceRequest(DeviceObject
, Irp
);
654 IPortPinWavePci_fnWrite(
655 IN IPortPinWavePci
* iface
,
656 IN PDEVICE_OBJECT DeviceObject
,
659 return KsDispatchInvalidDeviceRequest(DeviceObject
, Irp
);
667 IPortPinWavePci_fnFlush(
668 IN IPortPinWavePci
* iface
,
669 IN PDEVICE_OBJECT DeviceObject
,
672 return KsDispatchInvalidDeviceRequest(DeviceObject
, Irp
);
679 IN PDEVICE_OBJECT DeviceObject
,
682 PMINIPORTWAVEPCISTREAM Stream
;
684 ISubdevice
*ISubDevice
;
685 PSUBDEVICE_DESCRIPTOR Descriptor
;
686 IPortPinWavePciImpl
* This
;
687 PCLOSESTREAM_CONTEXT Ctx
= (PCLOSESTREAM_CONTEXT
)Context
;
689 This
= (IPortPinWavePciImpl
*)Ctx
->Pin
;
693 if (This
->State
!= KSSTATE_STOP
)
695 This
->Stream
->lpVtbl
->SetState(This
->Stream
, KSSTATE_STOP
);
699 if (This
->ServiceGroup
)
701 This
->ServiceGroup
->lpVtbl
->RemoveMember(This
->ServiceGroup
, (PSERVICESINK
)&This
->lpVtblServiceSink
);
704 Status
= This
->Port
->lpVtbl
->QueryInterface(This
->Port
, &IID_ISubdevice
, (PVOID
*)&ISubDevice
);
705 if (NT_SUCCESS(Status
))
707 Status
= ISubDevice
->lpVtbl
->GetDescriptor(ISubDevice
, &Descriptor
);
708 if (NT_SUCCESS(Status
))
710 Descriptor
->Factory
.Instances
[This
->ConnectDetails
->PinId
].CurrentPinInstanceCount
--;
712 ISubDevice
->lpVtbl
->Release(ISubDevice
);
717 ExFreePool(This
->Format
);
721 /* complete the irp */
722 Ctx
->Irp
->IoStatus
.Information
= 0;
723 Ctx
->Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
724 IoCompleteRequest(Ctx
->Irp
, IO_NO_INCREMENT
);
726 /* free the work item */
727 IoFreeWorkItem(Ctx
->WorkItem
);
729 /* free work item ctx */
730 FreeItem(Ctx
, TAG_PORTCLASS
);
734 Stream
= This
->Stream
;
736 DPRINT1("Closing stream at Irql %u\n", KeGetCurrentIrql());
737 Stream
->lpVtbl
->Release(Stream
);
746 IPortPinWavePci_fnClose(
747 IN IPortPinWavePci
* iface
,
748 IN PDEVICE_OBJECT DeviceObject
,
751 PCLOSESTREAM_CONTEXT Ctx
;
752 IPortPinWavePciImpl
* This
= (IPortPinWavePciImpl
*)iface
;
756 Ctx
= AllocateItem(NonPagedPool
, sizeof(CLOSESTREAM_CONTEXT
), TAG_PORTCLASS
);
759 DPRINT1("Failed to allocate stream context\n");
763 Ctx
->WorkItem
= IoAllocateWorkItem(DeviceObject
);
766 DPRINT1("Failed to allocate work item\n");
771 Ctx
->Pin
= (PVOID
)This
;
773 IoMarkIrpPending(Irp
);
774 Irp
->IoStatus
.Information
= 0;
775 Irp
->IoStatus
.Status
= STATUS_PENDING
;
777 /* defer work item */
778 IoQueueWorkItem(Ctx
->WorkItem
, CloseStreamRoutine
, DelayedWorkQueue
, (PVOID
)Ctx
);
780 return STATUS_PENDING
;
783 Irp
->IoStatus
.Information
= 0;
784 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
785 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
787 return STATUS_SUCCESS
;
792 FreeItem(Ctx
, TAG_PORTCLASS
);
794 Irp
->IoStatus
.Information
= 0;
795 Irp
->IoStatus
.Status
= STATUS_UNSUCCESSFUL
;
796 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
797 return STATUS_UNSUCCESSFUL
;
806 IPortPinWavePci_fnQuerySecurity(
807 IN IPortPinWavePci
* iface
,
808 IN PDEVICE_OBJECT DeviceObject
,
811 return KsDispatchInvalidDeviceRequest(DeviceObject
, Irp
);
819 IPortPinWavePci_fnSetSecurity(
820 IN IPortPinWavePci
* iface
,
821 IN PDEVICE_OBJECT DeviceObject
,
824 return KsDispatchInvalidDeviceRequest(DeviceObject
, Irp
);
832 IPortPinWavePci_fnFastDeviceIoControl(
833 IN IPortPinWavePci
* iface
,
834 IN PFILE_OBJECT FileObject
,
836 IN PVOID InputBuffer
,
837 IN ULONG InputBufferLength
,
838 OUT PVOID OutputBuffer
,
839 IN ULONG OutputBufferLength
,
840 IN ULONG IoControlCode
,
841 OUT PIO_STATUS_BLOCK StatusBlock
,
842 IN PDEVICE_OBJECT DeviceObject
)
846 if (IoControlCode
== IOCTL_KS_PROPERTY
)
848 Status
= IPortPinWavePci_HandleKsProperty(iface
, InputBuffer
, InputBufferLength
, OutputBuffer
, OutputBufferLength
, StatusBlock
);
849 if (NT_SUCCESS(Status
))
863 IPortPinWavePci_fnFastRead(
864 IN IPortPinWavePci
* iface
,
865 IN PFILE_OBJECT FileObject
,
866 IN PLARGE_INTEGER FileOffset
,
871 OUT PIO_STATUS_BLOCK StatusBlock
,
872 IN PDEVICE_OBJECT DeviceObject
)
875 PCONTEXT_WRITE Packet
;
877 IPortPinWavePciImpl
* This
= (IPortPinWavePciImpl
*)iface
;
879 DPRINT("IPortPinWavePci_fnFastRead entered\n");
881 Packet
= (PCONTEXT_WRITE
)Buffer
;
884 StatusBlock
->Status
= STATUS_PENDING
;
886 Status
= This
->IrpQueue
->lpVtbl
->AddMapping(This
->IrpQueue
, Buffer
, Length
, Irp
);
888 if (!NT_SUCCESS(Status
))
891 /* set pending status as result */
892 StatusBlock
->Status
= STATUS_PENDING
;
901 IPortPinWavePci_fnFastWrite(
902 IN IPortPinWavePci
* iface
,
903 IN PFILE_OBJECT FileObject
,
904 IN PLARGE_INTEGER FileOffset
,
909 OUT PIO_STATUS_BLOCK StatusBlock
,
910 IN PDEVICE_OBJECT DeviceObject
)
913 PCONTEXT_WRITE Packet
;
915 ULONG MinimumDataThreshold
;
916 IPortPinWavePciImpl
* This
= (IPortPinWavePciImpl
*)iface
;
918 DPRINT("IPortPinWavePci_fnFastWrite entered Total %u Pre %u Post %u\n", This
->TotalPackets
, This
->PreCompleted
, This
->PostCompleted
);
920 InterlockedIncrement((PLONG
)&This
->TotalPackets
);
922 Packet
= (PCONTEXT_WRITE
)Buffer
;
924 if (This
->IrpQueue
->lpVtbl
->MinimumDataAvailable(This
->IrpQueue
))
927 StatusBlock
->Status
= STATUS_PENDING
;
928 InterlockedIncrement((PLONG
)&This
->PostCompleted
);
933 Packet
->Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
934 Packet
->Irp
->IoStatus
.Information
= Packet
->Header
.FrameExtent
;
935 IoCompleteRequest(Packet
->Irp
, IO_SOUND_INCREMENT
);
936 StatusBlock
->Status
= STATUS_SUCCESS
;
937 InterlockedIncrement((PLONG
)&This
->PreCompleted
);
940 Status
= This
->IrpQueue
->lpVtbl
->AddMapping(This
->IrpQueue
, Buffer
, Length
, Irp
);
942 if (!NT_SUCCESS(Status
))
945 StatusBlock
->Status
= STATUS_PENDING
;
947 if (This
->IrpQueue
->lpVtbl
->HasLastMappingFailed(This
->IrpQueue
))
949 /* get minimum data threshold */
950 MinimumDataThreshold
= This
->IrpQueue
->lpVtbl
->GetMinimumDataThreshold(This
->IrpQueue
);
952 if (MinimumDataThreshold
< This
->IrpQueue
->lpVtbl
->NumData(This
->IrpQueue
))
954 /* notify port driver that new mapping is available */
955 DPRINT("Notifying of new mapping\n");
956 This
->Stream
->lpVtbl
->MappingAvailable(This
->Stream
);
968 IPortPinWavePci_fnInit(
969 IN IPortPinWavePci
* iface
,
970 IN PPORTWAVEPCI Port
,
971 IN PPORTFILTERWAVEPCI Filter
,
972 IN KSPIN_CONNECT
* ConnectDetails
,
973 IN KSPIN_DESCRIPTOR
* KsPinDescriptor
,
974 IN PDEVICE_OBJECT DeviceObject
)
977 PKSDATAFORMAT DataFormat
;
980 IPortPinWavePciImpl
* This
= (IPortPinWavePciImpl
*)iface
;
982 Port
->lpVtbl
->AddRef(Port
);
983 Filter
->lpVtbl
->AddRef(Filter
);
986 This
->Filter
= Filter
;
987 This
->KsPinDescriptor
= KsPinDescriptor
;
988 This
->ConnectDetails
= ConnectDetails
;
989 This
->Miniport
= GetWavePciMiniport(Port
);
990 This
->DeviceObject
= DeviceObject
;
992 DataFormat
= (PKSDATAFORMAT
)(ConnectDetails
+ 1);
994 DPRINT("IPortPinWavePci_fnInit entered\n");
996 This
->Format
= ExAllocatePoolWithTag(NonPagedPool
, DataFormat
->FormatSize
, TAG_PORTCLASS
);
998 return STATUS_INSUFFICIENT_RESOURCES
;
1000 RtlMoveMemory(This
->Format
, DataFormat
, DataFormat
->FormatSize
);
1002 if (KsPinDescriptor
->Communication
== KSPIN_COMMUNICATION_SINK
&& KsPinDescriptor
->DataFlow
== KSPIN_DATAFLOW_IN
)
1006 else if (KsPinDescriptor
->Communication
== KSPIN_COMMUNICATION_SINK
&& KsPinDescriptor
->DataFlow
== KSPIN_DATAFLOW_OUT
)
1012 DPRINT1("Unexpected Communication %u DataFlow %u\n", KsPinDescriptor
->Communication
, KsPinDescriptor
->DataFlow
);
1016 Status
= This
->Miniport
->lpVtbl
->NewStream(This
->Miniport
,
1020 (PPORTWAVEPCISTREAM
)&This
->lpVtblPortWavePciStream
,
1021 ConnectDetails
->PinId
,
1025 &This
->ServiceGroup
);
1027 DPRINT("IPortPinWavePci_fnInit Status %x\n", Status
);
1029 if (!NT_SUCCESS(Status
))
1032 if (This
->ServiceGroup
)
1034 Status
= This
->ServiceGroup
->lpVtbl
->AddMember(This
->ServiceGroup
,
1035 (PSERVICESINK
)&This
->lpVtblServiceSink
);
1036 if (!NT_SUCCESS(Status
))
1038 DPRINT1("Failed to add pin to service group\n");
1041 This
->ServiceGroup
->lpVtbl
->SupportDelayedService(This
->ServiceGroup
);
1044 /* delay of 10 milisec */
1045 This
->Delay
= Int32x32To64(10, -10000);
1047 Status
= This
->Stream
->lpVtbl
->GetAllocatorFraming(This
->Stream
, &This
->AllocatorFraming
);
1048 if (!NT_SUCCESS(Status
))
1050 DPRINT1("GetAllocatorFraming failed with %x\n", Status
);
1054 DPRINT("OptionFlags %x RequirementsFlag %x PoolType %x Frames %lu FrameSize %lu FileAlignment %lu\n",
1055 This
->AllocatorFraming
.OptionsFlags
, This
->AllocatorFraming
.RequirementsFlags
, This
->AllocatorFraming
.PoolType
, This
->AllocatorFraming
.Frames
, This
->AllocatorFraming
.FrameSize
, This
->AllocatorFraming
.FileAlignment
);
1057 Status
= NewIrpQueue(&This
->IrpQueue
);
1058 if (!NT_SUCCESS(Status
))
1061 Status
= This
->IrpQueue
->lpVtbl
->Init(This
->IrpQueue
, ConnectDetails
, This
->Format
, DeviceObject
, This
->AllocatorFraming
.FrameSize
, This
->AllocatorFraming
.FileAlignment
, NULL
);
1062 if (!NT_SUCCESS(Status
))
1064 DPRINT1("IrpQueue_Init failed with %x\n", Status
);
1068 This
->State
= KSSTATE_STOP
;
1069 This
->Capture
= Capture
;
1071 return STATUS_SUCCESS
;
1079 IPortPinWavePci_fnGetIrpStream(
1080 IN IPortPinWavePci
* iface
)
1082 IPortPinWavePciImpl
* This
= (IPortPinWavePciImpl
*)iface
;
1084 return (PVOID
)This
->IrpQueue
;
1093 IPortPinWavePci_fnGetMiniport(
1094 IN IPortPinWavePci
* iface
)
1096 IPortPinWavePciImpl
* This
= (IPortPinWavePciImpl
*)iface
;
1098 return (PMINIPORT
)This
->Miniport
;
1101 static IPortPinWavePciVtbl vt_IPortPinWavePci
=
1103 IPortPinWavePci_fnQueryInterface
,
1104 IPortPinWavePci_fnAddRef
,
1105 IPortPinWavePci_fnRelease
,
1106 IPortPinWavePci_fnNewIrpTarget
,
1107 IPortPinWavePci_fnDeviceIoControl
,
1108 IPortPinWavePci_fnRead
,
1109 IPortPinWavePci_fnWrite
,
1110 IPortPinWavePci_fnFlush
,
1111 IPortPinWavePci_fnClose
,
1112 IPortPinWavePci_fnQuerySecurity
,
1113 IPortPinWavePci_fnSetSecurity
,
1114 IPortPinWavePci_fnFastDeviceIoControl
,
1115 IPortPinWavePci_fnFastRead
,
1116 IPortPinWavePci_fnFastWrite
,
1117 IPortPinWavePci_fnInit
,
1118 IPortPinWavePci_fnGetIrpStream
,
1119 IPortPinWavePci_fnGetMiniport
1125 NTSTATUS
NewPortPinWavePci(
1126 OUT IPortPinWavePci
** OutPin
)
1128 IPortPinWavePciImpl
* This
;
1130 This
= AllocateItem(NonPagedPool
, sizeof(IPortPinWavePciImpl
), TAG_PORTCLASS
);
1132 return STATUS_INSUFFICIENT_RESOURCES
;
1134 /* initialize IPortPinWavePci */
1136 This
->lpVtbl
= &vt_IPortPinWavePci
;
1137 This
->lpVtblServiceSink
= &vt_IServiceSink
;
1138 This
->lpVtblPortWavePciStream
= &vt_PortWavePciStream
;
1142 *OutPin
= (IPortPinWavePci
*)&This
->lpVtbl
;
1144 return STATUS_SUCCESS
;