mirror of
https://github.com/reactos/reactos.git
synced 2024-08-05 02:50:55 +00:00
[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
This commit is contained in:
parent
6d59a5cfa7
commit
dac78ab19a
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -10,6 +10,7 @@
|
|||
<library>drmk</library>
|
||||
<library>hal</library>
|
||||
<library>libcntpr</library>
|
||||
<library>pseh</library>
|
||||
<file>adapter.c</file>
|
||||
<file>api.c</file>
|
||||
<file>connection.c</file>
|
||||
|
@ -40,7 +41,6 @@
|
|||
<file>port_topology.c</file>
|
||||
<file>port_wavecyclic.c</file>
|
||||
<file>port_wavepci.c</file>
|
||||
<file>port_wavepcistream.c</file>
|
||||
<file>port_wavert.c</file>
|
||||
<file>port_wavertstream.c</file>
|
||||
<file>power.c</file>
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 */
|
||||
|
|
Loading…
Reference in a new issue