From dac78ab19a698f3930dcbe53e36a1166e4898820 Mon Sep 17 00:00:00 2001 From: Johannes Anderwald Date: Fri, 17 Jul 2009 19:15:52 +0000 Subject: [PATCH] [WDMAUD.DRV] - Implement retrieving the preferred frame size - Set Maximum buffer limit to one second [PORTCLS] - Implement a dynamic buffer enlarging. In case a audio stream stops prematurely, increase the audio buffer limit by 1/3 - Implement KSPROPERTY_CONNECTION_ALLOCATORFRAMING for IPortPinWaveCyclic + IPortPinWavePci - Move IPortWavePciStream object to IPortPinWavePci, as IPrefetchOffset needs a tight integration (TBD) - Define pin property handler for IPortDMus (some audio devices may now show more than one waveout device) - Implement IPortEvents_fnAddEventToEventList for IPortWavePci [WDMAUD_KERNEL] - Implement IOCTL_GETFRAMESIZE [SYSAUDIO] - Fix a bug in the Pin_fnWrite, though code isnt used yet -? - Adobe Flash Player & Vlc may now have a better playback because the audio stream is now updated more often (because audio packet now use the preferred frame size which is in most cases 10ms). svn path=/trunk/; revision=42016 --- reactos/dll/win32/wdmaud.drv/wdmaud.c | 20 + .../wdm/audio/backpln/portcls/interfaces.h | 3 + .../wdm/audio/backpln/portcls/irpstream.c | 74 ++-- .../audio/backpln/portcls/pin_wavecyclic.c | 93 ++++- .../wdm/audio/backpln/portcls/pin_wavepci.c | 364 ++++++++++++++++-- .../wdm/audio/backpln/portcls/port_dmus.c | 26 +- .../wdm/audio/backpln/portcls/port_wavepci.c | 14 +- .../backpln/portcls/port_wavepcistream.c | 165 -------- .../wdm/audio/backpln/portcls/portcls.rbuild | 2 +- .../wdm/audio/backpln/portcls/private.h | 10 - .../drivers/wdm/audio/legacy/wdmaud/control.c | 47 ++- .../wdm/audio/legacy/wdmaud/interface.h | 20 +- reactos/drivers/wdm/audio/sysaudio/pin.c | 11 +- 13 files changed, 565 insertions(+), 284 deletions(-) delete mode 100644 reactos/drivers/wdm/audio/backpln/portcls/port_wavepcistream.c diff --git a/reactos/dll/win32/wdmaud.drv/wdmaud.c b/reactos/dll/win32/wdmaud.drv/wdmaud.c index bd710a316be..bcd34306ada 100644 --- a/reactos/dll/win32/wdmaud.drv/wdmaud.c +++ b/reactos/dll/win32/wdmaud.drv/wdmaud.c @@ -299,6 +299,26 @@ SetWdmWaveDeviceFormat( Instance->Handle = (PVOID)DeviceInfo.hDevice; + /* Now determine framing requirements */ + Result = SyncOverlappedDeviceIoControl(KernelHandle, + IOCTL_GETFRAMESIZE, + (LPVOID) &DeviceInfo, + sizeof(WDMAUD_DEVICE_INFO), + (LPVOID) &DeviceInfo, + sizeof(WDMAUD_DEVICE_INFO), + NULL); + + if ( MMSUCCESS(Result) ) + { + if (DeviceInfo.u.FrameSize) + { + Instance->FrameSize = DeviceInfo.u.FrameSize; + Instance->BufferCount = WaveFormat->nAvgBytesPerSec / Instance->FrameSize; + SND_TRACE(L"FrameSize %u BufferCount %u\n", Instance->FrameSize, Instance->BufferCount); + } + } + + return MMSYSERR_NOERROR; } diff --git a/reactos/drivers/wdm/audio/backpln/portcls/interfaces.h b/reactos/drivers/wdm/audio/backpln/portcls/interfaces.h index a80d92ec1e2..440680a2d28 100644 --- a/reactos/drivers/wdm/audio/backpln/portcls/interfaces.h +++ b/reactos/drivers/wdm/audio/backpln/portcls/interfaces.h @@ -234,6 +234,9 @@ DECLARE_INTERFACE_(IIrpQueue, IUnknown) STDMETHOD_(BOOL, HasLastMappingFailed)(THIS); STDMETHOD_(VOID, PrintQueueStatus)(THIS); + STDMETHOD_(VOID, SetMinimumDataThreshold)(THIS_ + IN ULONG MinimumDataThreshold); + STDMETHOD_(ULONG, GetMinimumDataThreshold)(THIS); }; diff --git a/reactos/drivers/wdm/audio/backpln/portcls/irpstream.c b/reactos/drivers/wdm/audio/backpln/portcls/irpstream.c index bd85582f9dd..f3e9a6d0038 100644 --- a/reactos/drivers/wdm/audio/backpln/portcls/irpstream.c +++ b/reactos/drivers/wdm/audio/backpln/portcls/irpstream.c @@ -40,6 +40,7 @@ typedef struct ULONG OutOfMapping; ULONG MaxFrameSize; ULONG Alignment; + ULONG MinimumDataThreshold; }IIrpQueueImpl; @@ -128,6 +129,7 @@ IIrpQueue_fnInit( This->DataFormat = (PKSDATAFORMAT_WAVEFORMATEX)DataFormat; This->MaxFrameSize = FrameSize; This->Alignment = Alignment; + This->MinimumDataThreshold = ((PKSDATAFORMAT_WAVEFORMATEX)DataFormat)->WaveFormatEx.nAvgBytesPerSec / 3; InitializeListHead(&This->ListHead); InitializeListHead(&This->FreeHead); @@ -315,7 +317,7 @@ IIrpQueue_fnMinimumDataAvailable( if (This->StartStream) return TRUE; - if (This->DataFormat->WaveFormatEx.nAvgBytesPerSec/3 < This->NumDataAvailable) + if (This->MinimumDataThreshold < This->NumDataAvailable) { This->StartStream = TRUE; Result = TRUE; @@ -346,9 +348,9 @@ IIrpQueue_fnUpdateFormat( { IIrpQueueImpl * This = (IIrpQueueImpl*)iface; This->DataFormat = (PKSDATAFORMAT_WAVEFORMATEX)DataFormat; + This->MinimumDataThreshold = This->DataFormat->WaveFormatEx.nAvgBytesPerSec / 3; This->StartStream = FALSE; This->NumDataAvailable = 0; - } NTSTATUS @@ -475,6 +477,27 @@ IIrpQueue_fnPrintQueueStatus( DPRINT("IIrpQueue_fnPrintQueueStatus ===============\n"); } +VOID +NTAPI +IIrpQueue_fnSetMinimumDataThreshold( + IN IIrpQueue *iface, + ULONG MinimumDataThreshold) +{ + IIrpQueueImpl * This = (IIrpQueueImpl*)iface; + + This->MinimumDataThreshold = MinimumDataThreshold; +} + +ULONG +NTAPI +IIrpQueue_fnGetMinimumDataThreshold( + IN IIrpQueue *iface) +{ + IIrpQueueImpl * This = (IIrpQueueImpl*)iface; + + return This->MinimumDataThreshold; +} + static IIrpQueueVtbl vt_IIrpQueue = { @@ -493,11 +516,11 @@ static IIrpQueueVtbl vt_IIrpQueue = IIrpQueue_fnGetMappingWithTag, IIrpQueue_fnReleaseMappingWithTag, IIrpQueue_fnHasLastMappingFailed, - IIrpQueue_fnPrintQueueStatus - + IIrpQueue_fnPrintQueueStatus, + IIrpQueue_fnSetMinimumDataThreshold, + IIrpQueue_fnGetMinimumDataThreshold }; - NTSTATUS NTAPI NewIrpQueue( @@ -515,44 +538,3 @@ NewIrpQueue( } -NTSTATUS -NewIrpStreamPhysical( - OUT IIrpStreamPhysical ** OutIIrpStreamPhysical, - IN IUnknown *OuterUnknown) -{ - return STATUS_UNSUCCESSFUL; -} - - -/* - * @implemented - */ - -NTSTATUS -NTAPI -PcNewIrpStreamPhysical( - OUT IIrpStreamPhysical ** OutIrpStreamPhysical, - IN IUnknown * OuterUnknown, - IN BOOLEAN Wait, - IN KSPIN_CONNECT *ConnectDetails, - IN PDEVICE_OBJECT DeviceObject, - IN PDMA_ADAPTER DmaAdapter) -{ - NTSTATUS Status; - IIrpStreamPhysical * Irp; - - Status = NewIrpStreamPhysical(&Irp, OuterUnknown); - if (!NT_SUCCESS(Status)) - return Status; - - - Status = Irp->lpVtbl->Init(Irp, Wait, ConnectDetails, DeviceObject, DmaAdapter); - if (!NT_SUCCESS(Status)) - { - Irp->lpVtbl->Release(Irp); - return Status; - } - - *OutIrpStreamPhysical = Irp; - return Status; -} diff --git a/reactos/drivers/wdm/audio/backpln/portcls/pin_wavecyclic.c b/reactos/drivers/wdm/audio/backpln/portcls/pin_wavecyclic.c index fdfc1860fb3..044784da1cd 100644 --- a/reactos/drivers/wdm/audio/backpln/portcls/pin_wavecyclic.c +++ b/reactos/drivers/wdm/audio/backpln/portcls/pin_wavecyclic.c @@ -37,6 +37,7 @@ typedef struct ULONG TotalPackets; ULONG PreCompleted; ULONG PostCompleted; + ULONG StopCount; ULONG Delay; }IPortPinWaveCyclicImpl; @@ -224,6 +225,8 @@ SetStreamWorkerRoutine( IPortPinWaveCyclicImpl * This; PSETSTREAM_CONTEXT Ctx = (PSETSTREAM_CONTEXT)Context; KSSTATE State; + ULONG MinimumDataThreshold; + ULONG MaximumDataThreshold; This = Ctx->Pin; State = Ctx->State; @@ -235,6 +238,10 @@ SetStreamWorkerRoutine( if (This->IrpQueue->lpVtbl->NumMappings(This->IrpQueue) && State == KSSTATE_STOP) return; + /* Has the audio state already been set? */ + if (This->State == State) + return; + /* Set the state */ if (NT_SUCCESS(This->Stream->lpVtbl->SetState(This->Stream, State))) { @@ -245,12 +252,26 @@ SetStreamWorkerRoutine( { /* reset start stream */ This->IrpQueue->lpVtbl->CancelBuffers(This->IrpQueue); //FIX function name - DPRINT1("Stopping PreCompleted %u PostCompleted %u\n", This->PreCompleted, This->PostCompleted); + + /* increase stop counter */ + This->StopCount++; + /* get current data threshold */ + MinimumDataThreshold = This->IrpQueue->lpVtbl->GetMinimumDataThreshold(This->IrpQueue); + /* get maximum data threshold */ + MaximumDataThreshold = ((PKSDATAFORMAT_WAVEFORMATEX)This->Format)->WaveFormatEx.nAvgBytesPerSec; + /* increase minimum data threshold by a third sec */ + MinimumDataThreshold += ((PKSDATAFORMAT_WAVEFORMATEX)This->Format)->WaveFormatEx.nAvgBytesPerSec / 3; + + /* assure it has not exceeded */ + MinimumDataThreshold = min(MinimumDataThreshold, MaximumDataThreshold); + /* store minimum data threshold */ + This->IrpQueue->lpVtbl->SetMinimumDataThreshold(This->IrpQueue, MinimumDataThreshold); + + DPRINT1("Stopping PreCompleted %u PostCompleted %u StopCount %u MinimumDataThreshold %u\n", This->PreCompleted, This->PostCompleted, This->StopCount, MinimumDataThreshold); } if (This->State == KSSTATE_RUN) { DPRINT1("State RUN %x MinAvailable %u\n", State, This->IrpQueue->lpVtbl->MinimumDataAvailable(This->IrpQueue)); - } } } @@ -570,11 +591,34 @@ IPortPinWaveCyclic_HandleKsProperty( return STATUS_SUCCESS; } } + else if (Property->Id == KSPROPERTY_CONNECTION_ALLOCATORFRAMING) + { + PKSALLOCATOR_FRAMING Framing = (PKSALLOCATOR_FRAMING)Irp->UserBuffer; + ASSERT_IRQL(DISPATCH_LEVEL); + /* Validate input buffer */ + if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(KSALLOCATOR_FRAMING)) + { + Irp->IoStatus.Information = sizeof(KSALLOCATOR_FRAMING); + Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + return STATUS_BUFFER_TOO_SMALL; + } + /* Clear frame structure */ + RtlZeroMemory(Framing, sizeof(KSALLOCATOR_FRAMING)); + /* store requested frame size */ + Framing->FrameSize = This->FrameSize; + /* FIXME fill in struct */ + + Irp->IoStatus.Information = sizeof(KSALLOCATOR_FRAMING); + Irp->IoStatus.Status = STATUS_SUCCESS; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + return STATUS_SUCCESS; + } } + RtlStringFromGUID(&Property->Set, &GuidString); DPRINT1("Unhandeled property Set |%S| Id %u Flags %x\n", GuidString.Buffer, Property->Id, Property->Flags); - DbgBreakPoint(); RtlFreeUnicodeString(&GuidString); Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED; @@ -640,7 +684,6 @@ IPortPinWaveCyclic_fnDeviceIoControl( } UNIMPLEMENTED - DbgBreakPoint(); Irp->IoStatus.Information = 0; Irp->IoStatus.Status = STATUS_UNSUCCESSFUL; @@ -696,21 +739,24 @@ CloseStreamRoutine( { PMINIPORTWAVECYCLICSTREAM Stream; IPortPinWaveCyclicImpl * This; + NTSTATUS Status; PCLOSESTREAM_CONTEXT Ctx = (PCLOSESTREAM_CONTEXT)Context; This = (IPortPinWaveCyclicImpl*)Ctx->Pin; - if (This->Stream) + if (This->State != KSSTATE_STOP) { - if (This->State != KSSTATE_STOP) - { - This->Stream->lpVtbl->SetState(This->Stream, KSSTATE_STOP); - KeStallExecutionProcessor(10); - } + /* stop stream in case it hasn't been */ + Status = This->Stream->lpVtbl->SetState(This->Stream, KSSTATE_STOP); + if (!NT_SUCCESS(Status)) + DPRINT1("Warning: failed to stop stream with %x\n", Status); + + This->State = KSSTATE_STOP; } if (This->Format) { + /* free format */ ExFreePool(This->Format); This->Format = NULL; } @@ -848,7 +894,7 @@ IPortPinWaveCyclic_fnFastDeviceIoControl( OUT PIO_STATUS_BLOCK StatusBlock, IN PDEVICE_OBJECT DeviceObject) { - UNIMPLEMENTED + //UNIMPLEMENTED return FALSE; } @@ -915,15 +961,19 @@ IPortPinWaveCyclic_fnFastWrite( NTSTATUS Status; PCONTEXT_WRITE Packet; PIRP Irp; + ULONG PrePostRatio; + ULONG MinData; IPortPinWaveCyclicImpl * This = (IPortPinWaveCyclicImpl*)iface; InterlockedIncrement((PLONG)&This->TotalPackets); - DPRINT("IPortPinWaveCyclic_fnFastWrite entered Total %u Pre %u Post %u State %x MinData %u\n", This->TotalPackets, This->PreCompleted, This->PostCompleted, This->State, This->IrpQueue->lpVtbl->NumData(This->IrpQueue)); + PrePostRatio = (This->PreCompleted * 100) / This->TotalPackets; + MinData = This->IrpQueue->lpVtbl->NumData(This->IrpQueue); + + DPRINT1("IPortPinWaveCyclic_fnFastWrite entered Total %u Pre %u Post %u State %x MinData %u Ratio %u\n", This->TotalPackets, This->PreCompleted, This->PostCompleted, This->State, This->IrpQueue->lpVtbl->NumData(This->IrpQueue), PrePostRatio); Packet = (PCONTEXT_WRITE)Buffer; - if (This->IrpQueue->lpVtbl->MinimumDataAvailable(This->IrpQueue)) { Irp = Packet->Irp; @@ -945,7 +995,7 @@ IPortPinWaveCyclic_fnFastWrite( if (!NT_SUCCESS(Status)) return FALSE; - if (This->IrpQueue->lpVtbl->MinimumDataAvailable(This->IrpQueue) == TRUE && This->State != KSSTATE_RUN) + if (This->State != KSSTATE_RUN && This->IrpQueue->lpVtbl->MinimumDataAvailable(This->IrpQueue) == TRUE) { SetStreamState(This, KSSTATE_RUN); /* some should initiate a state request but didnt do it */ @@ -1000,13 +1050,6 @@ IPortPinWaveCyclic_fnInit( if (!NT_SUCCESS(Status)) return Status; - Status = This->IrpQueue->lpVtbl->Init(This->IrpQueue, ConnectDetails, DataFormat, DeviceObject, 0, 0); - if (!NT_SUCCESS(Status)) - { - This->IrpQueue->lpVtbl->Release(This->IrpQueue); - return Status; - } - if (KsPinDescriptor->Communication == KSPIN_COMMUNICATION_SINK && KsPinDescriptor->DataFlow == KSPIN_DATAFLOW_IN) { Capture = FALSE; @@ -1071,6 +1114,14 @@ IPortPinWaveCyclic_fnInit( Status = This->Stream->lpVtbl->SetNotificationFreq(This->Stream, 10, &This->FrameSize); + Status = This->IrpQueue->lpVtbl->Init(This->IrpQueue, ConnectDetails, DataFormat, DeviceObject, This->FrameSize, 0); + if (!NT_SUCCESS(Status)) + { + This->IrpQueue->lpVtbl->Release(This->IrpQueue); + return Status; + } + + //This->Stream->lpVtbl->SetFormat(This->Stream, (PKSDATAFORMAT)This->Format); DPRINT1("Setting state to acquire %x\n", This->Stream->lpVtbl->SetState(This->Stream, KSSTATE_ACQUIRE)); DPRINT1("Setting state to pause %x\n", This->Stream->lpVtbl->SetState(This->Stream, KSSTATE_PAUSE)); diff --git a/reactos/drivers/wdm/audio/backpln/portcls/pin_wavepci.c b/reactos/drivers/wdm/audio/backpln/portcls/pin_wavepci.c index 87ecace3869..15aed30ab8b 100644 --- a/reactos/drivers/wdm/audio/backpln/portcls/pin_wavepci.c +++ b/reactos/drivers/wdm/audio/backpln/portcls/pin_wavepci.c @@ -12,6 +12,7 @@ typedef struct { IPortPinWavePciVtbl *lpVtbl; IServiceSinkVtbl *lpVtblServiceSink; + IPortWavePciStreamVtbl *lpVtblPortWavePciStream; LONG ref; IPortWavePci * Port; @@ -27,17 +28,21 @@ typedef struct BOOL Capture; PDEVICE_OBJECT DeviceObject; - PPORTWAVEPCISTREAM WaveStream; IIrpQueue * IrpQueue; ULONG TotalPackets; ULONG PreCompleted; ULONG PostCompleted; + ULONG StopCount; ULONG Delay; -}IPortPinWavePciImpl; + BOOL bUsePrefetch; + ULONG PrefetchOffset; + KSALLOCATOR_FRAMING AllocatorFraming; + +}IPortPinWavePciImpl; typedef struct { @@ -46,12 +51,110 @@ typedef struct KSSTATE State; }SETSTREAM_CONTEXT, *PSETSTREAM_CONTEXT; +//================================================================================================================================== +static NTSTATUS NTAPI -IPortWavePci_fnProcessNewIrp( - IPortPinWavePciImpl * This); +IPortWavePciStream_fnQueryInterface( + IPortWavePciStream* iface, + IN REFIID refiid, + OUT PVOID* Output) +{ + IPortPinWavePciImpl * This = (IPortPinWavePciImpl*)CONTAINING_RECORD(iface, IPortPinWavePciImpl, lpVtblPortWavePciStream); + + DPRINT("IPortWavePciStream_fnQueryInterface entered\n"); + + if (IsEqualGUIDAligned(refiid, &IID_IPortWavePciStream) || + IsEqualGUIDAligned(refiid, &IID_IUnknown)) + { + *Output = &This->lpVtbl; + InterlockedIncrement(&This->ref); + return STATUS_SUCCESS; + } + + return STATUS_UNSUCCESSFUL; +} + +static +ULONG +NTAPI +IPortWavePciStream_fnAddRef( + IPortWavePciStream* iface) +{ + IPortPinWavePciImpl * This = (IPortPinWavePciImpl*)CONTAINING_RECORD(iface, IPortPinWavePciImpl, lpVtblPortWavePciStream); + DPRINT("IPortWavePciStream_fnAddRef entered\n"); + + return InterlockedIncrement(&This->ref); +} + +static +ULONG +NTAPI +IPortWavePciStream_fnRelease( + IPortWavePciStream* iface) +{ + IPortPinWavePciImpl * This = (IPortPinWavePciImpl*)CONTAINING_RECORD(iface, IPortPinWavePciImpl, lpVtblPortWavePciStream); + + InterlockedDecrement(&This->ref); + + DPRINT("IPortWavePciStream_fnRelease entered %u\n", This->ref); + + /* Return new reference count */ + return This->ref; +} + +static +NTSTATUS +NTAPI +IPortWavePciStream_fnGetMapping( + IN IPortWavePciStream *iface, + IN PVOID Tag, + OUT PPHYSICAL_ADDRESS PhysicalAddress, + OUT PVOID *VirtualAddress, + OUT PULONG ByteCount, + OUT PULONG Flags) +{ + IPortPinWavePciImpl * This = (IPortPinWavePciImpl*)CONTAINING_RECORD(iface, IPortPinWavePciImpl, lpVtblPortWavePciStream); + + ASSERT_IRQL(DISPATCH_LEVEL); + return This->IrpQueue->lpVtbl->GetMappingWithTag(This->IrpQueue, Tag, PhysicalAddress, VirtualAddress, ByteCount, Flags); +} + +static +NTSTATUS +NTAPI +IPortWavePciStream_fnReleaseMapping( + IN IPortWavePciStream *iface, + IN PVOID Tag) +{ + IPortPinWavePciImpl * This = (IPortPinWavePciImpl*)CONTAINING_RECORD(iface, IPortPinWavePciImpl, lpVtblPortWavePciStream); + + ASSERT_IRQL(DISPATCH_LEVEL); + return This->IrpQueue->lpVtbl->ReleaseMappingWithTag(This->IrpQueue, Tag); +} + +static +NTSTATUS +NTAPI +IPortWavePciStream_fnTerminatePacket( + IN IPortWavePciStream *iface) +{ + UNIMPLEMENTED + ASSERT_IRQL(DISPATCH_LEVEL); + return STATUS_SUCCESS; +} + + +static IPortWavePciStreamVtbl vt_PortWavePciStream = +{ + IPortWavePciStream_fnQueryInterface, + IPortWavePciStream_fnAddRef, + IPortWavePciStream_fnRelease, + IPortWavePciStream_fnGetMapping, + IPortWavePciStream_fnReleaseMapping, + IPortWavePciStream_fnTerminatePacket +}; -//================================================================================================================================== static NTSTATUS @@ -117,6 +220,8 @@ SetStreamWorkerRoutine( IPortPinWavePciImpl * This; PSETSTREAM_CONTEXT Ctx = (PSETSTREAM_CONTEXT)Context; KSSTATE State; + ULONG MinimumDataThreshold; + ULONG MaximumDataThreshold; This = Ctx->Pin; State = Ctx->State; @@ -138,13 +243,27 @@ SetStreamWorkerRoutine( { /* reset start stream */ This->IrpQueue->lpVtbl->CancelBuffers(This->IrpQueue); //FIX function name - This->ServiceGroup->lpVtbl->CancelDelayedService(This->ServiceGroup); - DPRINT1("Stopping PreCompleted %u PostCompleted %u\n", This->PreCompleted, This->PostCompleted); + //This->ServiceGroup->lpVtbl->CancelDelayedService(This->ServiceGroup); + /* increase stop counter */ + This->StopCount++; + /* get current data threshold */ + MinimumDataThreshold = This->IrpQueue->lpVtbl->GetMinimumDataThreshold(This->IrpQueue); + /* get maximum data threshold */ + MaximumDataThreshold = ((PKSDATAFORMAT_WAVEFORMATEX)This->Format)->WaveFormatEx.nAvgBytesPerSec * 3; + /* increase minimum data threshold by a third sec */ + MinimumDataThreshold += ((PKSDATAFORMAT_WAVEFORMATEX)This->Format)->WaveFormatEx.nAvgBytesPerSec / 3; + + /* assure it has not exceeded */ + MinimumDataThreshold = min(MinimumDataThreshold, MaximumDataThreshold); + /* store minimum data threshold */ + This->IrpQueue->lpVtbl->SetMinimumDataThreshold(This->IrpQueue, MinimumDataThreshold); + + DPRINT1("Stopping PreCompleted %u PostCompleted %u StopCount %u MinimumDataThreshold %u\n", This->PreCompleted, This->PostCompleted, This->StopCount, MinimumDataThreshold); } if (This->State == KSSTATE_RUN) { /* start the notification timer */ - This->ServiceGroup->lpVtbl->RequestDelayedService(This->ServiceGroup, This->Delay); + //This->ServiceGroup->lpVtbl->RequestDelayedService(This->ServiceGroup, This->Delay); } } } @@ -201,26 +320,23 @@ NTAPI IServiceSink_fnRequestService( IServiceSink* iface) { - ULONGLONG Position; - NTSTATUS Status; IPortPinWavePciImpl * This = (IPortPinWavePciImpl*)CONTAINING_RECORD(iface, IPortPinWavePciImpl, lpVtblServiceSink); ASSERT_IRQL(DISPATCH_LEVEL); if (This->IrpQueue->lpVtbl->HasLastMappingFailed(This->IrpQueue)) { - This->IrpQueue->lpVtbl->PrintQueueStatus(This->IrpQueue); if (This->IrpQueue->lpVtbl->NumMappings(This->IrpQueue) == 0) { DPRINT("Stopping stream...\n"); SetStreamState(This, KSSTATE_STOP); + return; } } - Status = This->Stream->lpVtbl->GetPosition(This->Stream, &Position); - DPRINT("Position %lu Status %x\n", Position, Status); - This->Stream->lpVtbl->Service(This->Stream); + //TODO + //generate events } static IServiceSinkVtbl vt_IServiceSink = @@ -312,6 +428,191 @@ IPortPinWavePci_fnNewIrpTarget( return STATUS_UNSUCCESSFUL; } +NTSTATUS +NTAPI +IPortPinWavePci_HandleKsProperty( + IN IPortPinWavePci * iface, + IN PIRP Irp) +{ + PKSPROPERTY Property; + NTSTATUS Status; + UNICODE_STRING GuidString; + PIO_STACK_LOCATION IoStack; + + IPortPinWavePciImpl * This = (IPortPinWavePciImpl*)iface; + + IoStack = IoGetCurrentIrpStackLocation(Irp); + + DPRINT("IPortPinWavePci_HandleKsProperty entered\n"); + + if (IoStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(KSPROPERTY)) + { + Irp->IoStatus.Information = 0; + Irp->IoStatus.Status = STATUS_INVALID_PARAMETER; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + return STATUS_INVALID_PARAMETER; + } + + Property = (PKSPROPERTY)IoStack->Parameters.DeviceIoControl.Type3InputBuffer; + + if (IsEqualGUIDAligned(&Property->Set, &KSPROPSETID_Connection)) + { + if (Property->Id == KSPROPERTY_CONNECTION_STATE) + { + PKSSTATE State = (PKSSTATE)Irp->UserBuffer; + + ASSERT_IRQL(DISPATCH_LEVEL); + if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(KSSTATE)) + { + Irp->IoStatus.Information = sizeof(KSSTATE); + Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + return STATUS_BUFFER_TOO_SMALL; + } + + if (Property->Flags & KSPROPERTY_TYPE_SET) + { + Status = STATUS_UNSUCCESSFUL; + Irp->IoStatus.Information = 0; + + if (This->Stream) + { + Status = This->Stream->lpVtbl->SetState(This->Stream, *State); + + DPRINT1("Setting state %u %x\n", *State, Status); + if (NT_SUCCESS(Status)) + { + This->State = *State; + } + } + Irp->IoStatus.Status = Status; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + return Status; + } + else if (Property->Flags & KSPROPERTY_TYPE_GET) + { + *State = This->State; + Irp->IoStatus.Information = sizeof(KSSTATE); + Irp->IoStatus.Status = STATUS_SUCCESS; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + return STATUS_SUCCESS; + } + } + else if (Property->Id == KSPROPERTY_CONNECTION_DATAFORMAT) + { + PKSDATAFORMAT DataFormat = (PKSDATAFORMAT)Irp->UserBuffer; + if (Property->Flags & KSPROPERTY_TYPE_SET) + { + PKSDATAFORMAT NewDataFormat; + if (!RtlCompareMemory(DataFormat, This->Format, DataFormat->FormatSize)) + { + Irp->IoStatus.Information = DataFormat->FormatSize; + Irp->IoStatus.Status = STATUS_SUCCESS; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + return STATUS_SUCCESS; + } + + NewDataFormat = AllocateItem(NonPagedPool, DataFormat->FormatSize, TAG_PORTCLASS); + if (!NewDataFormat) + { + Irp->IoStatus.Information = 0; + Irp->IoStatus.Status = STATUS_NO_MEMORY; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + return STATUS_NO_MEMORY; + } + RtlMoveMemory(NewDataFormat, DataFormat, DataFormat->FormatSize); + + if (This->Stream) + { + ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL); + ASSERT(NewDataFormat->FormatSize == sizeof(KSDATAFORMAT_WAVEFORMATEX)); + ASSERT(IsEqualGUIDAligned(&((PKSDATAFORMAT_WAVEFORMATEX)NewDataFormat)->DataFormat.MajorFormat, &KSDATAFORMAT_TYPE_AUDIO)); + ASSERT(IsEqualGUIDAligned(&((PKSDATAFORMAT_WAVEFORMATEX)NewDataFormat)->DataFormat.SubFormat, &KSDATAFORMAT_SUBTYPE_PCM)); + ASSERT(IsEqualGUIDAligned(&((PKSDATAFORMAT_WAVEFORMATEX)NewDataFormat)->DataFormat.Specifier, &KSDATAFORMAT_SPECIFIER_WAVEFORMATEX)); + + ASSERT(This->State == KSSTATE_STOP); + DPRINT1("NewDataFormat: Channels %u Bits %u Samples %u\n", ((PKSDATAFORMAT_WAVEFORMATEX)NewDataFormat)->WaveFormatEx.nChannels, + ((PKSDATAFORMAT_WAVEFORMATEX)NewDataFormat)->WaveFormatEx.wBitsPerSample, + ((PKSDATAFORMAT_WAVEFORMATEX)NewDataFormat)->WaveFormatEx.nSamplesPerSec); + + Status = This->Stream->lpVtbl->SetFormat(This->Stream, NewDataFormat); + if (NT_SUCCESS(Status)) + { + if (This->Format) + ExFreePoolWithTag(This->Format, TAG_PORTCLASS); + + This->IrpQueue->lpVtbl->UpdateFormat(This->IrpQueue, (PKSDATAFORMAT)NewDataFormat); + This->Format = NewDataFormat; + Irp->IoStatus.Information = DataFormat->FormatSize; + Irp->IoStatus.Status = STATUS_SUCCESS; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + return STATUS_SUCCESS; + } + } + DPRINT1("Failed to set format\n"); + Irp->IoStatus.Information = 0; + Irp->IoStatus.Status = STATUS_UNSUCCESSFUL; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + return STATUS_UNSUCCESSFUL; + } + else if (Property->Flags & KSPROPERTY_TYPE_GET) + { + if (!This->Format) + { + DPRINT1("No format\n"); + Irp->IoStatus.Information = 0; + Irp->IoStatus.Status = STATUS_UNSUCCESSFUL; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + return STATUS_UNSUCCESSFUL; + } + if (This->Format->FormatSize > IoStack->Parameters.DeviceIoControl.OutputBufferLength) + { + Irp->IoStatus.Information = This->Format->FormatSize; + Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + return STATUS_BUFFER_TOO_SMALL; + } + + RtlMoveMemory(DataFormat, This->Format, This->Format->FormatSize); + Irp->IoStatus.Information = DataFormat->FormatSize; + Irp->IoStatus.Status = STATUS_SUCCESS; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + return STATUS_SUCCESS; + } + } + else if (Property->Id == KSPROPERTY_CONNECTION_ALLOCATORFRAMING) + { + PKSALLOCATOR_FRAMING Framing = (PKSALLOCATOR_FRAMING)Irp->UserBuffer; + + ASSERT_IRQL(DISPATCH_LEVEL); + /* Validate input buffer */ + if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(KSALLOCATOR_FRAMING)) + { + Irp->IoStatus.Information = sizeof(KSALLOCATOR_FRAMING); + Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + return STATUS_BUFFER_TOO_SMALL; + } + /* copy frame allocator struct */ + RtlMoveMemory(Framing, &This->AllocatorFraming, sizeof(KSALLOCATOR_FRAMING)); + + Irp->IoStatus.Information = sizeof(KSALLOCATOR_FRAMING); + Irp->IoStatus.Status = STATUS_SUCCESS; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + return STATUS_SUCCESS; + } + } + + RtlStringFromGUID(&Property->Set, &GuidString); + DPRINT1("Unhandeled property Set |%S| Id %u Flags %x\n", GuidString.Buffer, Property->Id, Property->Flags); + RtlFreeUnicodeString(&GuidString); + + Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED; + Irp->IoStatus.Information = 0; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + return STATUS_NOT_IMPLEMENTED; +} + /* * @unimplemented */ @@ -322,6 +623,16 @@ IPortPinWavePci_fnDeviceIoControl( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { + PIO_STACK_LOCATION IoStack; + + IoStack = IoGetCurrentIrpStackLocation(Irp); + + if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_PROPERTY) + { + return IPortPinWavePci_HandleKsProperty(iface, Irp); + } + + UNIMPLEMENTED Irp->IoStatus.Information = 0; @@ -614,7 +925,6 @@ IPortPinWavePci_fnFastWrite( Packet = (PCONTEXT_WRITE)Buffer; - if (This->IrpQueue->lpVtbl->MinimumDataAvailable(This->IrpQueue)) { Irp = Packet->Irp; @@ -669,7 +979,6 @@ IPortPinWavePci_fnInit( NTSTATUS Status; PKSDATAFORMAT DataFormat; BOOL Capture; - KSALLOCATOR_FRAMING AllocatorFraming; IPortPinWavePciImpl * This = (IPortPinWavePciImpl*)iface; @@ -693,14 +1002,6 @@ IPortPinWavePci_fnInit( RtlMoveMemory(This->Format, DataFormat, DataFormat->FormatSize); - Status = NewIPortWavePciStream(&This->WaveStream); - if (!NT_SUCCESS(Status)) - { - ExFreePool(This->Format); - This->Format = NULL; - return Status; - } - if (KsPinDescriptor->Communication == KSPIN_COMMUNICATION_SINK && KsPinDescriptor->DataFlow == KSPIN_DATAFLOW_IN) { Capture = FALSE; @@ -719,7 +1020,7 @@ IPortPinWavePci_fnInit( &This->Stream, NULL, NonPagedPool, - This->WaveStream, + (PPORTWAVEPCISTREAM)&This->lpVtblPortWavePciStream, ConnectDetails->PinId, Capture, This->Format, @@ -746,9 +1047,7 @@ IPortPinWavePci_fnInit( /* delay of 10 milisec */ This->Delay = Int32x32To64(10, -10000); - This->IrpQueue = IPortWavePciStream_GetIrpQueue(This->WaveStream); - - Status = This->Stream->lpVtbl->GetAllocatorFraming(This->Stream, &AllocatorFraming); + Status = This->Stream->lpVtbl->GetAllocatorFraming(This->Stream, &This->AllocatorFraming); if (!NT_SUCCESS(Status)) { DPRINT1("GetAllocatorFraming failed with %x\n", Status); @@ -756,9 +1055,13 @@ IPortPinWavePci_fnInit( } DPRINT("OptionFlags %x RequirementsFlag %x PoolType %x Frames %lu FrameSize %lu FileAlignment %lu\n", - AllocatorFraming.OptionsFlags, AllocatorFraming.RequirementsFlags, AllocatorFraming.PoolType, AllocatorFraming.Frames, AllocatorFraming.FrameSize, AllocatorFraming.FileAlignment); + This->AllocatorFraming.OptionsFlags, This->AllocatorFraming.RequirementsFlags, This->AllocatorFraming.PoolType, This->AllocatorFraming.Frames, This->AllocatorFraming.FrameSize, This->AllocatorFraming.FileAlignment); - Status = This->IrpQueue->lpVtbl->Init(This->IrpQueue, ConnectDetails, This->Format, DeviceObject, AllocatorFraming.FrameSize, AllocatorFraming.FileAlignment); + Status = NewIrpQueue(&This->IrpQueue); + if (!NT_SUCCESS(Status)) + return Status; + + Status = This->IrpQueue->lpVtbl->Init(This->IrpQueue, ConnectDetails, This->Format, DeviceObject, This->AllocatorFraming.FrameSize, This->AllocatorFraming.FileAlignment); if (!NT_SUCCESS(Status)) { DPRINT1("IrpQueue_Init failed with %x\n", Status); @@ -835,6 +1138,7 @@ NTSTATUS NewPortPinWavePci( This->ref = 1; This->lpVtbl = &vt_IPortPinWavePci; This->lpVtblServiceSink = &vt_IServiceSink; + This->lpVtblPortWavePciStream = &vt_PortWavePciStream; /* store result */ diff --git a/reactos/drivers/wdm/audio/backpln/portcls/port_dmus.c b/reactos/drivers/wdm/audio/backpln/portcls/port_dmus.c index c9910f81eb4..55eae19e285 100644 --- a/reactos/drivers/wdm/audio/backpln/portcls/port_dmus.c +++ b/reactos/drivers/wdm/audio/backpln/portcls/port_dmus.c @@ -45,6 +45,28 @@ static GUID InterfaceGuids[3] = } }; +DEFINE_KSPROPERTY_TOPOLOGYSET(PortFilterDMusTopologySet, TopologyPropertyHandler); +DEFINE_KSPROPERTY_PINPROPOSEDATAFORMAT(PortFilterDMusPinSet, PinPropertyHandler, PinPropertyHandler, PinPropertyHandler); + +KSPROPERTY_SET PortDMusPropertySet[] = +{ + { + &KSPROPSETID_Topology, + sizeof(PortFilterDMusTopologySet) / sizeof(KSPROPERTY_ITEM), + (const KSPROPERTY_ITEM*)&PortFilterDMusTopologySet, + 0, + NULL + }, + { + &KSPROPSETID_Pin, + sizeof(PortFilterDMusPinSet) / sizeof(KSPROPERTY_ITEM), + (const KSPROPERTY_ITEM*)&PortFilterDMusPinSet, + 0, + NULL + } +}; + + //--------------------------------------------------------------- // IUnknown interface functions // @@ -249,8 +271,8 @@ IPortDMus_fnInit( InterfaceGuids, 0, NULL, - 0, - NULL, + 2, + PortDMusPropertySet, 0, 0, 0, diff --git a/reactos/drivers/wdm/audio/backpln/portcls/port_wavepci.c b/reactos/drivers/wdm/audio/backpln/portcls/port_wavepci.c index c6d59d7d020..63ccedf0a1c 100644 --- a/reactos/drivers/wdm/audio/backpln/portcls/port_wavepci.c +++ b/reactos/drivers/wdm/audio/backpln/portcls/port_wavepci.c @@ -30,6 +30,10 @@ typedef struct PPCFILTER_DESCRIPTOR pDescriptor; PSUBDEVICE_DESCRIPTOR SubDeviceDescriptor; IPortFilterWavePci * Filter; + + LIST_ENTRY EventList; + KSPIN_LOCK EventListLock; + }IPortWavePciImpl; static GUID InterfaceGuids[3] = @@ -133,8 +137,14 @@ IPortEvents_fnAddEventToEventList( IPortEvents* iface, IN PKSEVENT_ENTRY EventEntry) { - UNIMPLEMENTED + KIRQL OldIrql; + IPortWavePciImpl * This = (IPortWavePciImpl*)CONTAINING_RECORD(iface, IPortWavePciImpl, lpVtblPortEvents); + ASSERT_IRQL_EQUAL(PASSIVE_LEVEL); + + KeAcquireSpinLock(&This->EventListLock, &OldIrql); + InsertTailList(&This->EventList, &EventEntry->ListEntry); + KeReleaseSpinLock(&This->EventListLock, OldIrql); } @@ -377,6 +387,8 @@ IPortWavePci_fnInit( This->pDeviceObject = DeviceObject; This->bInitialized = TRUE; This->pResourceList = ResourceList; + InitializeListHead(&This->EventList); + KeInitializeSpinLock(&This->EventListLock); /* increment reference on miniport adapter */ Miniport->lpVtbl->AddRef(Miniport); diff --git a/reactos/drivers/wdm/audio/backpln/portcls/port_wavepcistream.c b/reactos/drivers/wdm/audio/backpln/portcls/port_wavepcistream.c deleted file mode 100644 index 4e851d31e5a..00000000000 --- a/reactos/drivers/wdm/audio/backpln/portcls/port_wavepcistream.c +++ /dev/null @@ -1,165 +0,0 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Kernel Streaming - * FILE: drivers/wdm/audio/backpln/portcls/port_wavepcistream.c - * PURPOSE: Wave PCI Stream object - * PROGRAMMER: Johannes Anderwald - */ - -#include "private.h" - -typedef struct -{ - IPortWavePciStreamVtbl * lpVtbl; - IIrpQueue *Queue; - LONG ref; - - -}IPortWavePciStreamImpl; - -static -NTSTATUS -NTAPI -IPortWavePciStream_fnQueryInterface( - IPortWavePciStream* iface, - IN REFIID refiid, - OUT PVOID* Output) -{ - IPortWavePciStreamImpl * This = (IPortWavePciStreamImpl*)iface; - - DPRINT("IPortWavePciStream_fnQueryInterface entered\n"); - - if (IsEqualGUIDAligned(refiid, &IID_IPortWavePciStream) || - IsEqualGUIDAligned(refiid, &IID_IUnknown)) - { - *Output = &This->lpVtbl; - InterlockedIncrement(&This->ref); - return STATUS_SUCCESS; - } - - return STATUS_UNSUCCESSFUL; -} - -static -ULONG -NTAPI -IPortWavePciStream_fnAddRef( - IPortWavePciStream* iface) -{ - IPortWavePciStreamImpl * This = (IPortWavePciStreamImpl*)iface; - DPRINT("IPortWavePciStream_fnAddRef entered\n"); - - return InterlockedIncrement(&This->ref); -} - -static -ULONG -NTAPI -IPortWavePciStream_fnRelease( - IPortWavePciStream* iface) -{ - IPortWavePciStreamImpl * This = (IPortWavePciStreamImpl*)iface; - - InterlockedDecrement(&This->ref); - - DPRINT("IPortWavePciStream_fnRelease entered %u\n", This->ref); - - if (This->ref == 0) - { - This->Queue->lpVtbl->Release(This->Queue); - FreeItem(This, TAG_PORTCLASS); - return 0; - } - /* Return new reference count */ - return This->ref; -} - -static -NTSTATUS -NTAPI -IPortWavePciStream_fnGetMapping( - IN IPortWavePciStream *iface, - IN PVOID Tag, - OUT PPHYSICAL_ADDRESS PhysicalAddress, - OUT PVOID *VirtualAddress, - OUT PULONG ByteCount, - OUT PULONG Flags) -{ - IPortWavePciStreamImpl * This = (IPortWavePciStreamImpl*)iface; - - ASSERT_IRQL(DISPATCH_LEVEL); - return This->Queue->lpVtbl->GetMappingWithTag(This->Queue, Tag, PhysicalAddress, VirtualAddress, ByteCount, Flags); -} - -static -NTSTATUS -NTAPI -IPortWavePciStream_fnReleaseMapping( - IN IPortWavePciStream *iface, - IN PVOID Tag) -{ - IPortWavePciStreamImpl * This = (IPortWavePciStreamImpl*)iface; - - ASSERT_IRQL(DISPATCH_LEVEL); - return This->Queue->lpVtbl->ReleaseMappingWithTag(This->Queue, Tag); -} - -static -NTSTATUS -NTAPI -IPortWavePciStream_fnTerminatePacket( - IN IPortWavePciStream *iface) -{ - UNIMPLEMENTED - ASSERT_IRQL(DISPATCH_LEVEL); - return STATUS_SUCCESS; -} - - -static IPortWavePciStreamVtbl vt_PortWavePciStream = -{ - IPortWavePciStream_fnQueryInterface, - IPortWavePciStream_fnAddRef, - IPortWavePciStream_fnRelease, - IPortWavePciStream_fnGetMapping, - IPortWavePciStream_fnReleaseMapping, - IPortWavePciStream_fnTerminatePacket -}; - -NTSTATUS -NTAPI -NewIPortWavePciStream( - OUT PPORTWAVEPCISTREAM *Stream) -{ - IIrpQueue * Queue; - IPortWavePciStreamImpl * This; - NTSTATUS Status; - - Status = NewIrpQueue(&Queue); - if (!NT_SUCCESS(Status)) - return Status; - - This = AllocateItem(NonPagedPool, sizeof(IPortWavePciStreamImpl), TAG_PORTCLASS); - if (!This) - { - Queue->lpVtbl->Release(Queue); - return STATUS_INSUFFICIENT_RESOURCES; - } - - This->lpVtbl = &vt_PortWavePciStream; - This->ref = 1; - This->Queue = Queue; - - *Stream = (PPORTWAVEPCISTREAM)&This->lpVtbl; - return STATUS_SUCCESS; -} - -IIrpQueue* -NTAPI -IPortWavePciStream_GetIrpQueue( - IN IPortWavePciStream *iface) -{ - IPortWavePciStreamImpl * This = (IPortWavePciStreamImpl*)iface; - return This->Queue; -} - diff --git a/reactos/drivers/wdm/audio/backpln/portcls/portcls.rbuild b/reactos/drivers/wdm/audio/backpln/portcls/portcls.rbuild index 9ddd96b3311..ac75bc25911 100644 --- a/reactos/drivers/wdm/audio/backpln/portcls/portcls.rbuild +++ b/reactos/drivers/wdm/audio/backpln/portcls/portcls.rbuild @@ -10,6 +10,7 @@ drmk hal libcntpr + pseh adapter.c api.c connection.c @@ -40,7 +41,6 @@ port_topology.c port_wavecyclic.c port_wavepci.c - port_wavepcistream.c port_wavert.c port_wavertstream.c power.c diff --git a/reactos/drivers/wdm/audio/backpln/portcls/private.h b/reactos/drivers/wdm/audio/backpln/portcls/private.h index 445e5bc3b7d..5e0bb97b17f 100644 --- a/reactos/drivers/wdm/audio/backpln/portcls/private.h +++ b/reactos/drivers/wdm/audio/backpln/portcls/private.h @@ -279,16 +279,6 @@ PDEVICE_OBJECT GetDeviceObject( IPortWaveCyclic* iface); -IIrpQueue* -NTAPI -IPortWavePciStream_GetIrpQueue( - IN IPortWavePciStream *iface); - -NTSTATUS -NTAPI -NewIPortWavePciStream( - OUT PPORTWAVEPCISTREAM *Stream); - VOID NTAPI PcIoTimerRoutine( diff --git a/reactos/drivers/wdm/audio/legacy/wdmaud/control.c b/reactos/drivers/wdm/audio/legacy/wdmaud/control.c index ab86b087cfd..2f13fb7c9ec 100644 --- a/reactos/drivers/wdm/audio/legacy/wdmaud/control.c +++ b/reactos/drivers/wdm/audio/legacy/wdmaud/control.c @@ -595,6 +595,49 @@ WdmAudIoctlClose( return STATUS_INVALID_PARAMETER; } +NTSTATUS +NTAPI +WdmAudFrameSize( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp, + IN PWDMAUD_DEVICE_INFO DeviceInfo, + IN PWDMAUD_CLIENT ClientInfo) +{ + PFILE_OBJECT FileObject; + KSPROPERTY Property; + ULONG BytesReturned; + KSALLOCATOR_FRAMING Framing; + NTSTATUS Status; + + /* Get sysaudio pin file object */ + Status = ObReferenceObjectByHandle(DeviceInfo->hDevice, GENERIC_WRITE, IoFileObjectType, KernelMode, (PVOID*)&FileObject, NULL); + if (!NT_SUCCESS(Status)) + { + DPRINT1("Invalid buffer handle %x\n", DeviceInfo->hDevice); + return SetIrpIoStatus(Irp, Status, 0); + } + + /* Setup get framing request */ + Property.Id = KSPROPERTY_CONNECTION_ALLOCATORFRAMING; + Property.Flags = KSPROPERTY_TYPE_GET; + Property.Set = KSPROPSETID_Connection; + + Status = KsSynchronousIoControlDevice(FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)&Framing, sizeof(KSALLOCATOR_FRAMING), &BytesReturned); + /* Did we succeed */ + if (NT_SUCCESS(Status)) + { + /* Store framesize */ + DeviceInfo->u.FrameSize = Framing.FrameSize; + } + + /* Release file object */ + ObDereferenceObject(FileObject); + + return SetIrpIoStatus(Irp, Status, sizeof(WDMAUD_DEVICE_INFO)); + +} + + NTSTATUS NTAPI WdmAudDeviceControl( @@ -647,8 +690,9 @@ WdmAudDeviceControl( return WdmAudCapabilities(DeviceObject, Irp, DeviceInfo, ClientInfo); case IOCTL_CLOSE_WDMAUD: return WdmAudIoctlClose(DeviceObject, Irp, DeviceInfo, ClientInfo); + case IOCTL_GETFRAMESIZE: + return WdmAudFrameSize(DeviceObject, Irp, DeviceInfo, ClientInfo); case IOCTL_GETPOS: - DPRINT1("IOCTL_GETPOS\n"); case IOCTL_GETDEVID: case IOCTL_GETVOLUME: case IOCTL_SETVOLUME: @@ -793,4 +837,3 @@ WdmAudWrite( ObDereferenceObject(FileObject); return IoStatusBlock.Status; } - diff --git a/reactos/drivers/wdm/audio/legacy/wdmaud/interface.h b/reactos/drivers/wdm/audio/legacy/wdmaud/interface.h index 7221fc447cc..d3f5286b66e 100644 --- a/reactos/drivers/wdm/audio/legacy/wdmaud/interface.h +++ b/reactos/drivers/wdm/audio/legacy/wdmaud/interface.h @@ -43,6 +43,7 @@ typedef struct ULONGLONG Position; KSSTATE State; ULONG Volume; + ULONG FrameSize; }u; }WDMAUD_DEVICE_INFO, *PWDMAUD_DEVICE_INFO; @@ -212,7 +213,7 @@ typedef struct /// Arguments: InputBuffer is a pointer to a WDMAUD_DEVICE_INFO structure, /// InputBufferSize is size of WDMAUD_DEVICE_INFO structure /// Note: The DeviceType and hDevice must be set -/// Result: The result is returned in Volume +/// Result: The result is returned in Position /// ReturnCode: STATUS_SUCCESS indicates success /// Prequsites: opened device @@ -222,5 +223,22 @@ typedef struct METHOD_BUFFERED, \ FILE_CREATE_TREE_CONNECTION | FILE_ANY_ACCESS) +/// IOCTL_GETFRAMESIZE +/// +/// Description: This IOCTL retrieves the frame size requirements for an audio pin +/// +/// Arguments: InputBuffer is a pointer to a WDMAUD_DEVICE_INFO structure, +/// InputBufferSize is size of WDMAUD_DEVICE_INFO structure +/// Note: The DeviceType and hDevice must be set +/// Result: The result is returned in FrameSize +/// ReturnCode: STATUS_SUCCESS indicates success +/// Prequsites: opened device + +#define IOCTL_GETFRAMESIZE \ + CTL_CODE(FILE_DEVICE_SOUND, \ + 10, \ + METHOD_BUFFERED, \ + FILE_CREATE_TREE_CONNECTION | FILE_ANY_ACCESS) + #endif diff --git a/reactos/drivers/wdm/audio/sysaudio/pin.c b/reactos/drivers/wdm/audio/sysaudio/pin.c index 742d38b5bfd..63b6b0899fb 100644 --- a/reactos/drivers/wdm/audio/sysaudio/pin.c +++ b/reactos/drivers/wdm/audio/sysaudio/pin.c @@ -128,9 +128,9 @@ Pin_fnWrite( { PDISPATCH_CONTEXT Context; PIO_STACK_LOCATION IoStack; - ULONG BytesReturned; PFILE_OBJECT FileObject; NTSTATUS Status; + ULONG BytesReturned; /* Get current stack location */ IoStack = IoGetCurrentIrpStackLocation(Irp); @@ -159,20 +159,21 @@ Pin_fnWrite( return Status; } - /* Re-dispatch the request to the real target pin */ + /* call the portcls audio pin */ Status = KsSynchronousIoControlDevice(FileObject, KernelMode, IOCTL_KS_WRITE_STREAM, MmGetMdlVirtualAddress(Irp->MdlAddress), - IoStack->Parameters.Read.Length, + IoStack->Parameters.Write.Length, NULL, 0, &BytesReturned); - /* release file object */ + + /* Release file object */ ObDereferenceObject(FileObject); /* Save status and information */ Irp->IoStatus.Status = Status; - Irp->IoStatus.Information = 0; + Irp->IoStatus.Information = BytesReturned; /* Complete the irp */ IoCompleteRequest(Irp, IO_NO_INCREMENT); /* Done */