2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Kernel Streaming
4 * FILE: drivers/wdm/audio/backpln/portcls/pin_wavert.c
5 * PURPOSE: WaveRT IRP Audio Pin
6 * PROGRAMMER: Johannes Anderwald
13 IPortPinWaveRTVtbl
*lpVtbl
;
14 IServiceSinkVtbl
*lpVtblServiceSink
;
18 IPortFilterWaveRT
* Filter
;
19 KSPIN_DESCRIPTOR
* KsPinDescriptor
;
20 PMINIPORTWAVERT Miniport
;
21 PMINIPORTWAVERTSTREAM Stream
;
22 PPORTWAVERTSTREAM PortStream
;
23 PSERVICEGROUP ServiceGroup
;
26 KSPIN_CONNECT
* ConnectDetails
;
29 ULONG CommonBufferSize
;
30 ULONG CommonBufferOffset
;
42 MEMORY_CACHING_TYPE CacheType
;
50 IPortPinWaveRTImpl
*Pin
;
51 PIO_WORKITEM WorkItem
;
53 }SETSTREAM_CONTEXT
, *PSETSTREAM_CONTEXT
;
59 IN IPortPinWaveRTImpl
* This
,
65 IPortPinWaveRTImpl
* This
,
74 BufferLength
= Position
- This
->CommonBufferOffset
;
77 Status
= This
->IrpQueue
->lpVtbl
->GetMapping(This
->IrpQueue
, &Buffer
, &BufferSize
);
78 if (!NT_SUCCESS(Status
))
81 BytesToCopy
= min(BufferLength
, BufferSize
);
85 RtlMoveMemory(Buffer
, (PUCHAR
)This
->CommonBuffer
+ This
->CommonBufferOffset
, BytesToCopy
);
89 RtlMoveMemory((PUCHAR
)This
->CommonBuffer
+ This
->CommonBufferOffset
, Buffer
, BytesToCopy
);
92 This
->IrpQueue
->lpVtbl
->UpdateMapping(This
->IrpQueue
, BytesToCopy
);
93 This
->CommonBufferOffset
+= BytesToCopy
;
95 BufferLength
= Position
- This
->CommonBufferOffset
;
101 UpdateCommonBufferOverlap(
102 IPortPinWaveRTImpl
* This
,
112 BufferLength
= This
->CommonBufferSize
- This
->CommonBufferOffset
;
115 Status
= This
->IrpQueue
->lpVtbl
->GetMapping(This
->IrpQueue
, &Buffer
, &BufferSize
);
116 if (!NT_SUCCESS(Status
))
119 BytesToCopy
= min(BufferLength
, BufferSize
);
123 RtlMoveMemory(Buffer
, (PUCHAR
)This
->CommonBuffer
+ This
->CommonBufferOffset
, BytesToCopy
);
127 RtlMoveMemory((PUCHAR
)This
->CommonBuffer
+ This
->CommonBufferOffset
, Buffer
, BytesToCopy
);
130 This
->IrpQueue
->lpVtbl
->UpdateMapping(This
->IrpQueue
, BytesToCopy
);
131 This
->CommonBufferOffset
+= BytesToCopy
;
133 BufferLength
= This
->CommonBufferSize
- This
->CommonBufferOffset
;
135 This
->CommonBufferOffset
= 0;
136 UpdateCommonBuffer(This
, Position
);
141 //==================================================================================================================================
145 IServiceSink_fnQueryInterface(
150 IPortPinWaveRTImpl
* This
= (IPortPinWaveRTImpl
*)CONTAINING_RECORD(iface
, IPortPinWaveRTImpl
, lpVtblServiceSink
);
152 DPRINT("IServiceSink_fnQueryInterface entered\n");
154 if (IsEqualGUIDAligned(refiid
, &IID_IServiceSink
) ||
155 IsEqualGUIDAligned(refiid
, &IID_IUnknown
))
157 *Output
= &This
->lpVtblServiceSink
;
158 InterlockedIncrement(&This
->ref
);
159 return STATUS_SUCCESS
;
161 return STATUS_UNSUCCESSFUL
;
167 IServiceSink_fnAddRef(
170 IPortPinWaveRTImpl
* This
= (IPortPinWaveRTImpl
*)CONTAINING_RECORD(iface
, IPortPinWaveRTImpl
, lpVtblServiceSink
);
171 DPRINT("IServiceSink_fnAddRef entered\n");
173 return InterlockedIncrement(&This
->ref
);
179 IServiceSink_fnRelease(
182 IPortPinWaveRTImpl
* This
= (IPortPinWaveRTImpl
*)CONTAINING_RECORD(iface
, IPortPinWaveRTImpl
, lpVtblServiceSink
);
184 InterlockedDecrement(&This
->ref
);
186 DPRINT("IServiceSink_fnRelease entered %u\n", This
->ref
);
190 FreeItem(This
, TAG_PORTCLASS
);
193 /* Return new reference count */
200 IServiceSink_fnRequestService(
203 KSAUDIO_POSITION Position
;
207 IPortPinWaveRTImpl
* This
= (IPortPinWaveRTImpl
*)CONTAINING_RECORD(iface
, IPortPinWaveRTImpl
, lpVtblServiceSink
);
209 ASSERT_IRQL(DISPATCH_LEVEL
);
211 Status
= This
->IrpQueue
->lpVtbl
->GetMapping(This
->IrpQueue
, &Buffer
, &BufferSize
);
212 if (!NT_SUCCESS(Status
))
214 SetStreamState(This
, KSSTATE_STOP
);
218 Status
= This
->Stream
->lpVtbl
->GetPosition(This
->Stream
, &Position
);
219 DPRINT("PlayOffset %lu WriteOffset %lu Buffer %p BufferSize %u CommonBufferSize %u\n", Position
.PlayOffset
, Position
.WriteOffset
, Buffer
, BufferSize
, This
->CommonBufferSize
);
221 if (Position
.PlayOffset
< This
->CommonBufferOffset
)
223 UpdateCommonBufferOverlap(This
, Position
.PlayOffset
);
225 else if (Position
.PlayOffset
>= This
->CommonBufferOffset
)
227 UpdateCommonBuffer(This
, Position
.PlayOffset
);
231 static IServiceSinkVtbl vt_IServiceSink
=
233 IServiceSink_fnQueryInterface
,
234 IServiceSink_fnAddRef
,
235 IServiceSink_fnRelease
,
236 IServiceSink_fnRequestService
243 SetStreamWorkerRoutine(
244 IN PDEVICE_OBJECT DeviceObject
,
247 IPortPinWaveRTImpl
* This
;
248 PSETSTREAM_CONTEXT Ctx
= (PSETSTREAM_CONTEXT
)Context
;
254 IoFreeWorkItem(Ctx
->WorkItem
);
255 FreeItem(Ctx
, TAG_PORTCLASS
);
257 /* Has the audio stream resumed? */
258 if (This
->IrpQueue
->lpVtbl
->NumMappings(This
->IrpQueue
) && State
== KSSTATE_STOP
)
262 if (NT_SUCCESS(This
->Stream
->lpVtbl
->SetState(This
->Stream
, State
)))
264 /* Set internal state to stop */
267 if (This
->State
== KSSTATE_STOP
)
269 /* reset start stream */
270 This
->IrpQueue
->lpVtbl
->CancelBuffers(This
->IrpQueue
); //FIX function name
271 This
->ServiceGroup
->lpVtbl
->CancelDelayedService(This
->ServiceGroup
);
272 DPRINT1("Stopping PreCompleted %u PostCompleted %u\n", This
->PreCompleted
, This
->PostCompleted
);
275 if (This
->State
== KSSTATE_RUN
)
277 /* start the notification timer */
278 This
->ServiceGroup
->lpVtbl
->RequestDelayedService(This
->ServiceGroup
, This
->Delay
);
287 IN IPortPinWaveRTImpl
* This
,
290 PDEVICE_OBJECT DeviceObject
;
291 PIO_WORKITEM WorkItem
;
292 PSETSTREAM_CONTEXT Context
;
294 ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL
);
296 /* Has the audio stream resumed? */
297 if (This
->IrpQueue
->lpVtbl
->NumMappings(This
->IrpQueue
) && State
== KSSTATE_STOP
)
300 /* Has the audio state already been set? */
301 if (This
->State
== State
)
304 /* Get device object */
305 DeviceObject
= GetDeviceObjectFromPortWaveRT(This
->Port
);
307 /* allocate set state context */
308 Context
= AllocateItem(NonPagedPool
, sizeof(SETSTREAM_CONTEXT
), TAG_PORTCLASS
);
313 /* allocate work item */
314 WorkItem
= IoAllocateWorkItem(DeviceObject
);
322 Context
->Pin
= (PVOID
)This
;
323 Context
->WorkItem
= WorkItem
;
324 Context
->State
= State
;
326 /* queue the work item */
327 IoQueueWorkItem(WorkItem
, SetStreamWorkerRoutine
, DelayedWorkQueue
, (PVOID
)Context
);
330 //==================================================================================================================================
336 IPortPinWaveRT_fnQueryInterface(
337 IPortPinWaveRT
* iface
,
341 IPortPinWaveRTImpl
* This
= (IPortPinWaveRTImpl
*)iface
;
343 if (IsEqualGUIDAligned(refiid
, &IID_IIrpTarget
) ||
344 IsEqualGUIDAligned(refiid
, &IID_IUnknown
))
346 *Output
= &This
->lpVtbl
;
347 InterlockedIncrement(&This
->ref
);
348 return STATUS_SUCCESS
;
351 return STATUS_UNSUCCESSFUL
;
359 IPortPinWaveRT_fnAddRef(
360 IPortPinWaveRT
* iface
)
362 IPortPinWaveRTImpl
* This
= (IPortPinWaveRTImpl
*)iface
;
364 return InterlockedIncrement(&This
->ref
);
372 IPortPinWaveRT_fnRelease(
373 IPortPinWaveRT
* iface
)
375 IPortPinWaveRTImpl
* This
= (IPortPinWaveRTImpl
*)iface
;
377 InterlockedDecrement(&This
->ref
);
381 FreeItem(This
, TAG_PORTCLASS
);
392 IPortPinWaveRT_fnNewIrpTarget(
393 IN IPortPinWaveRT
* iface
,
394 OUT
struct IIrpTarget
**OutTarget
,
397 IN POOL_TYPE PoolType
,
398 IN PDEVICE_OBJECT DeviceObject
,
400 IN KSOBJECT_CREATE
*CreateObject
)
403 return STATUS_UNSUCCESSFUL
;
408 IPortPinWaveRT_HandleKsProperty(
409 IN IPortPinWaveRT
* iface
,
412 PKSPROPERTY Property
;
414 UNICODE_STRING GuidString
;
415 PIO_STACK_LOCATION IoStack
;
416 IPortPinWaveRTImpl
* This
= (IPortPinWaveRTImpl
*)iface
;
418 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
420 DPRINT("IPortPinWave_HandleKsProperty entered\n");
422 if (IoStack
->Parameters
.DeviceIoControl
.InputBufferLength
< sizeof(KSPROPERTY
))
424 Irp
->IoStatus
.Information
= 0;
425 Irp
->IoStatus
.Status
= STATUS_INVALID_PARAMETER
;
426 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
427 return STATUS_INVALID_PARAMETER
;
430 Property
= (PKSPROPERTY
)IoStack
->Parameters
.DeviceIoControl
.Type3InputBuffer
;
432 if (IsEqualGUIDAligned(&Property
->Set
, &KSPROPSETID_Connection
))
434 if (Property
->Id
== KSPROPERTY_CONNECTION_STATE
)
436 PKSSTATE State
= (PKSSTATE
)Irp
->UserBuffer
;
438 if (IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
< sizeof(KSSTATE
))
440 Irp
->IoStatus
.Information
= sizeof(KSSTATE
);
441 Irp
->IoStatus
.Status
= STATUS_BUFFER_TOO_SMALL
;
442 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
443 return STATUS_BUFFER_TOO_SMALL
;
446 if (Property
->Flags
& KSPROPERTY_TYPE_SET
)
448 Status
= STATUS_UNSUCCESSFUL
;
449 Irp
->IoStatus
.Information
= 0;
453 Status
= This
->Stream
->lpVtbl
->SetState(This
->Stream
, *State
);
455 DPRINT1("Setting state %u %x\n", *State
, Status
);
456 if (NT_SUCCESS(Status
))
458 This
->State
= *State
;
461 Irp
->IoStatus
.Status
= Status
;
462 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
465 else if (Property
->Flags
& KSPROPERTY_TYPE_GET
)
467 *State
= This
->State
;
468 Irp
->IoStatus
.Information
= sizeof(KSSTATE
);
469 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
470 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
471 return STATUS_SUCCESS
;
474 else if (Property
->Id
== KSPROPERTY_CONNECTION_DATAFORMAT
)
476 PKSDATAFORMAT DataFormat
= (PKSDATAFORMAT
)Irp
->UserBuffer
;
477 if (Property
->Flags
& KSPROPERTY_TYPE_SET
)
479 PKSDATAFORMAT NewDataFormat
;
480 if (!RtlCompareMemory(DataFormat
, This
->Format
, DataFormat
->FormatSize
))
482 Irp
->IoStatus
.Information
= DataFormat
->FormatSize
;
483 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
484 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
485 return STATUS_SUCCESS
;
488 NewDataFormat
= AllocateItem(NonPagedPool
, DataFormat
->FormatSize
, TAG_PORTCLASS
);
491 Irp
->IoStatus
.Information
= 0;
492 Irp
->IoStatus
.Status
= STATUS_NO_MEMORY
;
493 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
494 return STATUS_NO_MEMORY
;
496 RtlMoveMemory(NewDataFormat
, DataFormat
, DataFormat
->FormatSize
);
500 ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL
);
501 ASSERT(NewDataFormat
->FormatSize
== sizeof(KSDATAFORMAT_WAVEFORMATEX
));
502 ASSERT(IsEqualGUIDAligned(&((PKSDATAFORMAT_WAVEFORMATEX
)NewDataFormat
)->DataFormat
.MajorFormat
, &KSDATAFORMAT_TYPE_AUDIO
));
503 ASSERT(IsEqualGUIDAligned(&((PKSDATAFORMAT_WAVEFORMATEX
)NewDataFormat
)->DataFormat
.SubFormat
, &KSDATAFORMAT_SUBTYPE_PCM
));
504 ASSERT(IsEqualGUIDAligned(&((PKSDATAFORMAT_WAVEFORMATEX
)NewDataFormat
)->DataFormat
.Specifier
, &KSDATAFORMAT_SPECIFIER_WAVEFORMATEX
));
506 ASSERT(This
->State
== KSSTATE_STOP
);
507 DPRINT1("NewDataFormat: Channels %u Bits %u Samples %u\n", ((PKSDATAFORMAT_WAVEFORMATEX
)NewDataFormat
)->WaveFormatEx
.nChannels
,
508 ((PKSDATAFORMAT_WAVEFORMATEX
)NewDataFormat
)->WaveFormatEx
.wBitsPerSample
,
509 ((PKSDATAFORMAT_WAVEFORMATEX
)NewDataFormat
)->WaveFormatEx
.nSamplesPerSec
);
511 Status
= This
->Stream
->lpVtbl
->SetFormat(This
->Stream
, NewDataFormat
);
512 if (NT_SUCCESS(Status
))
515 ExFreePoolWithTag(This
->Format
, TAG_PORTCLASS
);
517 This
->IrpQueue
->lpVtbl
->UpdateFormat(This
->IrpQueue
, (PKSDATAFORMAT
)NewDataFormat
);
518 This
->Format
= NewDataFormat
;
519 Irp
->IoStatus
.Information
= DataFormat
->FormatSize
;
520 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
521 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
522 return STATUS_SUCCESS
;
525 DPRINT1("Failed to set format\n");
526 Irp
->IoStatus
.Information
= 0;
527 Irp
->IoStatus
.Status
= STATUS_UNSUCCESSFUL
;
528 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
529 return STATUS_UNSUCCESSFUL
;
531 else if (Property
->Flags
& KSPROPERTY_TYPE_GET
)
535 DPRINT1("No format\n");
536 Irp
->IoStatus
.Information
= 0;
537 Irp
->IoStatus
.Status
= STATUS_UNSUCCESSFUL
;
538 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
539 return STATUS_UNSUCCESSFUL
;
541 if (This
->Format
->FormatSize
> IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
)
543 Irp
->IoStatus
.Information
= This
->Format
->FormatSize
;
544 Irp
->IoStatus
.Status
= STATUS_BUFFER_TOO_SMALL
;
545 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
546 return STATUS_BUFFER_TOO_SMALL
;
549 RtlMoveMemory(DataFormat
, This
->Format
, This
->Format
->FormatSize
);
550 Irp
->IoStatus
.Information
= DataFormat
->FormatSize
;
551 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
552 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
553 return STATUS_SUCCESS
;
558 RtlStringFromGUID(&Property
->Set
, &GuidString
);
559 DPRINT1("Unhandeled property Set |%S| Id %u Flags %x\n", GuidString
.Buffer
, Property
->Id
, Property
->Flags
);
561 RtlFreeUnicodeString(&GuidString
);
563 Irp
->IoStatus
.Status
= STATUS_NOT_IMPLEMENTED
;
564 Irp
->IoStatus
.Information
= 0;
565 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
566 return STATUS_NOT_IMPLEMENTED
;
571 IPortPinWaveRT_HandleKsStream(
572 IN IPortPinWaveRT
* iface
,
575 IPortPinWaveRTImpl
* This
= (IPortPinWaveRTImpl
*)iface
;
577 DPRINT("IPortPinWaveRT_HandleKsStream entered State %u Stream %p\n", This
->State
, This
->Stream
);
579 return STATUS_PENDING
;
587 IPortPinWaveRT_fnDeviceIoControl(
588 IN IPortPinWaveRT
* iface
,
589 IN PDEVICE_OBJECT DeviceObject
,
592 PIO_STACK_LOCATION IoStack
;
594 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
597 if (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_KS_PROPERTY
)
599 return IPortPinWaveRT_HandleKsProperty(iface
, Irp
);
601 else if (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_KS_ENABLE_EVENT
)
604 /// handle enable event
606 else if (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_KS_DISABLE_EVENT
)
609 /// handle disable event
611 else if (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_KS_RESET_STATE
)
614 /// handle reset state
616 else if (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_KS_WRITE_STREAM
|| IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_KS_READ_STREAM
)
618 return IPortPinWaveRT_HandleKsStream(iface
, Irp
);
622 return KsDefaultDeviceIoCompletion(DeviceObject
, Irp
);
628 Irp
->IoStatus
.Information
= 0;
629 Irp
->IoStatus
.Status
= STATUS_UNSUCCESSFUL
;
630 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
632 return STATUS_UNSUCCESSFUL
;
640 IPortPinWaveRT_fnRead(
641 IN IPortPinWaveRT
* iface
,
642 IN PDEVICE_OBJECT DeviceObject
,
645 return KsDispatchInvalidDeviceRequest(DeviceObject
, Irp
);
653 IPortPinWaveRT_fnWrite(
654 IN IPortPinWaveRT
* iface
,
655 IN PDEVICE_OBJECT DeviceObject
,
658 return KsDispatchInvalidDeviceRequest(DeviceObject
, Irp
);
666 IPortPinWaveRT_fnFlush(
667 IN IPortPinWaveRT
* iface
,
668 IN PDEVICE_OBJECT DeviceObject
,
671 return KsDispatchInvalidDeviceRequest(DeviceObject
, Irp
);
678 IN PDEVICE_OBJECT DeviceObject
,
681 PMINIPORTWAVERTSTREAM Stream
;
683 ISubdevice
*ISubDevice
;
684 PSUBDEVICE_DESCRIPTOR Descriptor
;
685 IPortPinWaveRTImpl
* This
;
686 PCLOSESTREAM_CONTEXT Ctx
= (PCLOSESTREAM_CONTEXT
)Context
;
688 This
= (IPortPinWaveRTImpl
*)Ctx
->Pin
;
692 if (This
->State
!= KSSTATE_STOP
)
694 This
->Stream
->lpVtbl
->SetState(This
->Stream
, KSSTATE_STOP
);
695 KeStallExecutionProcessor(10);
699 Status
= This
->Port
->lpVtbl
->QueryInterface(This
->Port
, &IID_ISubdevice
, (PVOID
*)&ISubDevice
);
700 if (NT_SUCCESS(Status
))
702 Status
= ISubDevice
->lpVtbl
->GetDescriptor(ISubDevice
, &Descriptor
);
703 if (NT_SUCCESS(Status
))
705 Descriptor
->Factory
.Instances
[This
->ConnectDetails
->PinId
].CurrentPinInstanceCount
--;
707 ISubDevice
->lpVtbl
->Release(ISubDevice
);
712 ExFreePool(This
->Format
);
718 This
->IrpQueue
->lpVtbl
->Release(This
->IrpQueue
);
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 IPortPinWaveRT_fnClose(
747 IN IPortPinWaveRT
* iface
,
748 IN PDEVICE_OBJECT DeviceObject
,
751 PCLOSESTREAM_CONTEXT Ctx
;
752 IPortPinWaveRTImpl
* This
= (IPortPinWaveRTImpl
*)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 IPortPinWaveRT_fnQuerySecurity(
807 IN IPortPinWaveRT
* iface
,
808 IN PDEVICE_OBJECT DeviceObject
,
811 return KsDispatchInvalidDeviceRequest(DeviceObject
, Irp
);
819 IPortPinWaveRT_fnSetSecurity(
820 IN IPortPinWaveRT
* iface
,
821 IN PDEVICE_OBJECT DeviceObject
,
824 return KsDispatchInvalidDeviceRequest(DeviceObject
, Irp
);
832 IPortPinWaveRT_fnFastDeviceIoControl(
833 IN IPortPinWaveRT
* 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
)
853 IPortPinWaveRT_fnFastRead(
854 IN IPortPinWaveRT
* iface
,
855 IN PFILE_OBJECT FileObject
,
856 IN PLARGE_INTEGER FileOffset
,
861 OUT PIO_STATUS_BLOCK StatusBlock
,
862 IN PDEVICE_OBJECT DeviceObject
)
865 PCONTEXT_WRITE Packet
;
867 IPortPinWaveRTImpl
* This
= (IPortPinWaveRTImpl
*)iface
;
869 DPRINT("IPortPinWaveRT_fnFastRead entered\n");
871 Packet
= (PCONTEXT_WRITE
)Buffer
;
874 StatusBlock
->Status
= STATUS_PENDING
;
876 Status
= This
->IrpQueue
->lpVtbl
->AddMapping(This
->IrpQueue
, Buffer
, Length
, Irp
);
878 if (!NT_SUCCESS(Status
))
881 StatusBlock
->Status
= STATUS_PENDING
;
890 IPortPinWaveRT_fnFastWrite(
891 IN IPortPinWaveRT
* iface
,
892 IN PFILE_OBJECT FileObject
,
893 IN PLARGE_INTEGER FileOffset
,
898 OUT PIO_STATUS_BLOCK StatusBlock
,
899 IN PDEVICE_OBJECT DeviceObject
)
902 PCONTEXT_WRITE Packet
;
904 IPortPinWaveRTImpl
* This
= (IPortPinWaveRTImpl
*)iface
;
906 InterlockedIncrement((PLONG
)&This
->TotalPackets
);
908 DPRINT("IPortPinWaveRT_fnFastWrite entered Total %u Pre %u Post %u\n", This
->TotalPackets
, This
->PreCompleted
, This
->PostCompleted
);
910 Packet
= (PCONTEXT_WRITE
)Buffer
;
913 if (This
->IrpQueue
->lpVtbl
->MinimumDataAvailable(This
->IrpQueue
))
916 StatusBlock
->Status
= STATUS_PENDING
;
917 InterlockedIncrement((PLONG
)&This
->PostCompleted
);
922 Packet
->Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
923 Packet
->Irp
->IoStatus
.Information
= Packet
->Header
.FrameExtent
;
924 IoCompleteRequest(Packet
->Irp
, IO_SOUND_INCREMENT
);
925 StatusBlock
->Status
= STATUS_SUCCESS
;
926 InterlockedIncrement((PLONG
)&This
->PreCompleted
);
929 Status
= This
->IrpQueue
->lpVtbl
->AddMapping(This
->IrpQueue
, Buffer
, Length
, Irp
);
931 if (!NT_SUCCESS(Status
))
934 StatusBlock
->Status
= STATUS_PENDING
;
943 IPortPinWaveRT_fnInit(
944 IN IPortPinWaveRT
* iface
,
946 IN PPORTFILTERWAVERT Filter
,
947 IN KSPIN_CONNECT
* ConnectDetails
,
948 IN KSPIN_DESCRIPTOR
* KsPinDescriptor
,
949 IN PDEVICE_OBJECT DeviceObject
)
952 PKSDATAFORMAT DataFormat
;
954 KSRTAUDIO_HWLATENCY Latency
;
955 IPortPinWaveRTImpl
* This
= (IPortPinWaveRTImpl
*)iface
;
957 Port
->lpVtbl
->AddRef(Port
);
958 Filter
->lpVtbl
->AddRef(Filter
);
961 This
->Filter
= Filter
;
962 This
->KsPinDescriptor
= KsPinDescriptor
;
963 This
->ConnectDetails
= ConnectDetails
;
964 This
->Miniport
= GetWaveRTMiniport(Port
);
966 DataFormat
= (PKSDATAFORMAT
)(ConnectDetails
+ 1);
968 DPRINT("IPortPinWaveRT_fnInit entered\n");
970 This
->Format
= AllocateItem(NonPagedPool
, DataFormat
->FormatSize
, TAG_PORTCLASS
);
972 return STATUS_INSUFFICIENT_RESOURCES
;
974 RtlMoveMemory(This
->Format
, DataFormat
, DataFormat
->FormatSize
);
976 Status
= NewIrpQueue(&This
->IrpQueue
);
977 if (!NT_SUCCESS(Status
))
982 Status
= This
->IrpQueue
->lpVtbl
->Init(This
->IrpQueue
, ConnectDetails
, DataFormat
, DeviceObject
, 0, 0, NULL
);
983 if (!NT_SUCCESS(Status
))
988 Status
= NewPortWaveRTStream(&This
->PortStream
);
989 if (!NT_SUCCESS(Status
))
994 Status
= PcNewServiceGroup(&This
->ServiceGroup
, NULL
);
995 if (!NT_SUCCESS(Status
))
1000 This
->ServiceGroup
->lpVtbl
->AddMember(This
->ServiceGroup
, (PSERVICESINK
)&This
->lpVtblServiceSink
);
1001 This
->ServiceGroup
->lpVtbl
->SupportDelayedService(This
->ServiceGroup
);
1003 if (KsPinDescriptor
->Communication
== KSPIN_COMMUNICATION_SINK
&& KsPinDescriptor
->DataFlow
== KSPIN_DATAFLOW_IN
)
1007 else if (KsPinDescriptor
->Communication
== KSPIN_COMMUNICATION_SINK
&& KsPinDescriptor
->DataFlow
== KSPIN_DATAFLOW_OUT
)
1013 DPRINT1("Unexpected Communication %u DataFlow %u\n", KsPinDescriptor
->Communication
, KsPinDescriptor
->DataFlow
);
1017 Status
= This
->Miniport
->lpVtbl
->NewStream(This
->Miniport
,
1020 ConnectDetails
->PinId
,
1023 DPRINT("IPortPinWaveRT_fnInit Status %x\n", Status
);
1025 if (!NT_SUCCESS(Status
))
1028 This
->Stream
->lpVtbl
->GetHWLatency(This
->Stream
, &Latency
);
1029 /* delay of 10 milisec */
1030 This
->Delay
= Int32x32To64(10, -10000);
1032 Status
= This
->Stream
->lpVtbl
->AllocateAudioBuffer(This
->Stream
, 16384 * 11, &This
->Mdl
, &This
->CommonBufferSize
, &This
->CommonBufferOffset
, &This
->CacheType
);
1033 if (!NT_SUCCESS(Status
))
1035 DPRINT1("AllocateAudioBuffer failed with %x\n", Status
);
1039 This
->CommonBuffer
= MmGetSystemAddressForMdlSafe(This
->Mdl
, NormalPagePriority
);
1040 if (!NT_SUCCESS(Status
))
1042 DPRINT1("Failed to get system address %x\n", Status
);
1043 IoFreeMdl(This
->Mdl
);
1048 DPRINT1("Setting state to acquire %x\n", This
->Stream
->lpVtbl
->SetState(This
->Stream
, KSSTATE_ACQUIRE
));
1049 DPRINT1("Setting state to pause %x\n", This
->Stream
->lpVtbl
->SetState(This
->Stream
, KSSTATE_PAUSE
));
1050 This
->State
= KSSTATE_PAUSE
;
1051 return STATUS_SUCCESS
;
1056 This
->IrpQueue
->lpVtbl
->Release(This
->IrpQueue
);
1057 This
->IrpQueue
= NULL
;
1062 FreeItem(This
->Format
, TAG_PORTCLASS
);
1063 This
->Format
= NULL
;
1066 if (This
->ServiceGroup
)
1068 This
->ServiceGroup
->lpVtbl
->Release(This
->ServiceGroup
);
1069 This
->ServiceGroup
= NULL
;
1074 This
->Stream
->lpVtbl
->Release(This
->Stream
);
1075 This
->Stream
= NULL
;
1079 if (This
->PortStream
)
1081 This
->PortStream
->lpVtbl
->Release(This
->PortStream
);
1082 This
->PortStream
= NULL
;
1089 static IPortPinWaveRTVtbl vt_IPortPinWaveRT
=
1091 IPortPinWaveRT_fnQueryInterface
,
1092 IPortPinWaveRT_fnAddRef
,
1093 IPortPinWaveRT_fnRelease
,
1094 IPortPinWaveRT_fnNewIrpTarget
,
1095 IPortPinWaveRT_fnDeviceIoControl
,
1096 IPortPinWaveRT_fnRead
,
1097 IPortPinWaveRT_fnWrite
,
1098 IPortPinWaveRT_fnFlush
,
1099 IPortPinWaveRT_fnClose
,
1100 IPortPinWaveRT_fnQuerySecurity
,
1101 IPortPinWaveRT_fnSetSecurity
,
1102 IPortPinWaveRT_fnFastDeviceIoControl
,
1103 IPortPinWaveRT_fnFastRead
,
1104 IPortPinWaveRT_fnFastWrite
,
1105 IPortPinWaveRT_fnInit
1108 NTSTATUS
NewPortPinWaveRT(
1109 OUT IPortPinWaveRT
** OutPin
)
1111 IPortPinWaveRTImpl
* This
;
1113 This
= AllocateItem(NonPagedPool
, sizeof(IPortPinWaveRTImpl
), TAG_PORTCLASS
);
1115 return STATUS_INSUFFICIENT_RESOURCES
;
1117 /* initialize IPortPinWaveRT */
1119 This
->lpVtbl
= &vt_IPortPinWaveRT
;
1120 This
->lpVtblServiceSink
= &vt_IServiceSink
;
1123 *OutPin
= (IPortPinWaveRT
*)&This
->lpVtbl
;
1125 return STATUS_SUCCESS
;