mirror of
https://github.com/reactos/reactos.git
synced 2025-07-27 07:41:51 +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
13 changed files with 565 additions and 284 deletions
|
@ -299,6 +299,26 @@ SetWdmWaveDeviceFormat(
|
||||||
|
|
||||||
Instance->Handle = (PVOID)DeviceInfo.hDevice;
|
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;
|
return MMSYSERR_NOERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -234,6 +234,9 @@ DECLARE_INTERFACE_(IIrpQueue, IUnknown)
|
||||||
|
|
||||||
STDMETHOD_(BOOL, HasLastMappingFailed)(THIS);
|
STDMETHOD_(BOOL, HasLastMappingFailed)(THIS);
|
||||||
STDMETHOD_(VOID, PrintQueueStatus)(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 OutOfMapping;
|
||||||
ULONG MaxFrameSize;
|
ULONG MaxFrameSize;
|
||||||
ULONG Alignment;
|
ULONG Alignment;
|
||||||
|
ULONG MinimumDataThreshold;
|
||||||
|
|
||||||
}IIrpQueueImpl;
|
}IIrpQueueImpl;
|
||||||
|
|
||||||
|
@ -128,6 +129,7 @@ IIrpQueue_fnInit(
|
||||||
This->DataFormat = (PKSDATAFORMAT_WAVEFORMATEX)DataFormat;
|
This->DataFormat = (PKSDATAFORMAT_WAVEFORMATEX)DataFormat;
|
||||||
This->MaxFrameSize = FrameSize;
|
This->MaxFrameSize = FrameSize;
|
||||||
This->Alignment = Alignment;
|
This->Alignment = Alignment;
|
||||||
|
This->MinimumDataThreshold = ((PKSDATAFORMAT_WAVEFORMATEX)DataFormat)->WaveFormatEx.nAvgBytesPerSec / 3;
|
||||||
|
|
||||||
InitializeListHead(&This->ListHead);
|
InitializeListHead(&This->ListHead);
|
||||||
InitializeListHead(&This->FreeHead);
|
InitializeListHead(&This->FreeHead);
|
||||||
|
@ -315,7 +317,7 @@ IIrpQueue_fnMinimumDataAvailable(
|
||||||
if (This->StartStream)
|
if (This->StartStream)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
if (This->DataFormat->WaveFormatEx.nAvgBytesPerSec/3 < This->NumDataAvailable)
|
if (This->MinimumDataThreshold < This->NumDataAvailable)
|
||||||
{
|
{
|
||||||
This->StartStream = TRUE;
|
This->StartStream = TRUE;
|
||||||
Result = TRUE;
|
Result = TRUE;
|
||||||
|
@ -346,9 +348,9 @@ IIrpQueue_fnUpdateFormat(
|
||||||
{
|
{
|
||||||
IIrpQueueImpl * This = (IIrpQueueImpl*)iface;
|
IIrpQueueImpl * This = (IIrpQueueImpl*)iface;
|
||||||
This->DataFormat = (PKSDATAFORMAT_WAVEFORMATEX)DataFormat;
|
This->DataFormat = (PKSDATAFORMAT_WAVEFORMATEX)DataFormat;
|
||||||
|
This->MinimumDataThreshold = This->DataFormat->WaveFormatEx.nAvgBytesPerSec / 3;
|
||||||
This->StartStream = FALSE;
|
This->StartStream = FALSE;
|
||||||
This->NumDataAvailable = 0;
|
This->NumDataAvailable = 0;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
|
@ -475,6 +477,27 @@ IIrpQueue_fnPrintQueueStatus(
|
||||||
DPRINT("IIrpQueue_fnPrintQueueStatus ===============\n");
|
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 =
|
static IIrpQueueVtbl vt_IIrpQueue =
|
||||||
{
|
{
|
||||||
|
@ -493,11 +516,11 @@ static IIrpQueueVtbl vt_IIrpQueue =
|
||||||
IIrpQueue_fnGetMappingWithTag,
|
IIrpQueue_fnGetMappingWithTag,
|
||||||
IIrpQueue_fnReleaseMappingWithTag,
|
IIrpQueue_fnReleaseMappingWithTag,
|
||||||
IIrpQueue_fnHasLastMappingFailed,
|
IIrpQueue_fnHasLastMappingFailed,
|
||||||
IIrpQueue_fnPrintQueueStatus
|
IIrpQueue_fnPrintQueueStatus,
|
||||||
|
IIrpQueue_fnSetMinimumDataThreshold,
|
||||||
|
IIrpQueue_fnGetMinimumDataThreshold
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
NTAPI
|
NTAPI
|
||||||
NewIrpQueue(
|
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 TotalPackets;
|
||||||
ULONG PreCompleted;
|
ULONG PreCompleted;
|
||||||
ULONG PostCompleted;
|
ULONG PostCompleted;
|
||||||
|
ULONG StopCount;
|
||||||
|
|
||||||
ULONG Delay;
|
ULONG Delay;
|
||||||
}IPortPinWaveCyclicImpl;
|
}IPortPinWaveCyclicImpl;
|
||||||
|
@ -224,6 +225,8 @@ SetStreamWorkerRoutine(
|
||||||
IPortPinWaveCyclicImpl * This;
|
IPortPinWaveCyclicImpl * This;
|
||||||
PSETSTREAM_CONTEXT Ctx = (PSETSTREAM_CONTEXT)Context;
|
PSETSTREAM_CONTEXT Ctx = (PSETSTREAM_CONTEXT)Context;
|
||||||
KSSTATE State;
|
KSSTATE State;
|
||||||
|
ULONG MinimumDataThreshold;
|
||||||
|
ULONG MaximumDataThreshold;
|
||||||
|
|
||||||
This = Ctx->Pin;
|
This = Ctx->Pin;
|
||||||
State = Ctx->State;
|
State = Ctx->State;
|
||||||
|
@ -235,6 +238,10 @@ SetStreamWorkerRoutine(
|
||||||
if (This->IrpQueue->lpVtbl->NumMappings(This->IrpQueue) && State == KSSTATE_STOP)
|
if (This->IrpQueue->lpVtbl->NumMappings(This->IrpQueue) && State == KSSTATE_STOP)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
/* Has the audio state already been set? */
|
||||||
|
if (This->State == State)
|
||||||
|
return;
|
||||||
|
|
||||||
/* Set the state */
|
/* Set the state */
|
||||||
if (NT_SUCCESS(This->Stream->lpVtbl->SetState(This->Stream, State)))
|
if (NT_SUCCESS(This->Stream->lpVtbl->SetState(This->Stream, State)))
|
||||||
{
|
{
|
||||||
|
@ -245,12 +252,26 @@ SetStreamWorkerRoutine(
|
||||||
{
|
{
|
||||||
/* reset start stream */
|
/* reset start stream */
|
||||||
This->IrpQueue->lpVtbl->CancelBuffers(This->IrpQueue); //FIX function name
|
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)
|
if (This->State == KSSTATE_RUN)
|
||||||
{
|
{
|
||||||
DPRINT1("State RUN %x MinAvailable %u\n", State, This->IrpQueue->lpVtbl->MinimumDataAvailable(This->IrpQueue));
|
DPRINT1("State RUN %x MinAvailable %u\n", State, This->IrpQueue->lpVtbl->MinimumDataAvailable(This->IrpQueue));
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -570,11 +591,34 @@ IPortPinWaveCyclic_HandleKsProperty(
|
||||||
return STATUS_SUCCESS;
|
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);
|
RtlStringFromGUID(&Property->Set, &GuidString);
|
||||||
DPRINT1("Unhandeled property Set |%S| Id %u Flags %x\n", GuidString.Buffer, Property->Id, Property->Flags);
|
DPRINT1("Unhandeled property Set |%S| Id %u Flags %x\n", GuidString.Buffer, Property->Id, Property->Flags);
|
||||||
DbgBreakPoint();
|
|
||||||
RtlFreeUnicodeString(&GuidString);
|
RtlFreeUnicodeString(&GuidString);
|
||||||
|
|
||||||
Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
|
Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
|
||||||
|
@ -640,7 +684,6 @@ IPortPinWaveCyclic_fnDeviceIoControl(
|
||||||
}
|
}
|
||||||
|
|
||||||
UNIMPLEMENTED
|
UNIMPLEMENTED
|
||||||
DbgBreakPoint();
|
|
||||||
|
|
||||||
Irp->IoStatus.Information = 0;
|
Irp->IoStatus.Information = 0;
|
||||||
Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
|
Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
|
||||||
|
@ -696,21 +739,24 @@ CloseStreamRoutine(
|
||||||
{
|
{
|
||||||
PMINIPORTWAVECYCLICSTREAM Stream;
|
PMINIPORTWAVECYCLICSTREAM Stream;
|
||||||
IPortPinWaveCyclicImpl * This;
|
IPortPinWaveCyclicImpl * This;
|
||||||
|
NTSTATUS Status;
|
||||||
PCLOSESTREAM_CONTEXT Ctx = (PCLOSESTREAM_CONTEXT)Context;
|
PCLOSESTREAM_CONTEXT Ctx = (PCLOSESTREAM_CONTEXT)Context;
|
||||||
|
|
||||||
This = (IPortPinWaveCyclicImpl*)Ctx->Pin;
|
This = (IPortPinWaveCyclicImpl*)Ctx->Pin;
|
||||||
|
|
||||||
if (This->Stream)
|
if (This->State != KSSTATE_STOP)
|
||||||
{
|
{
|
||||||
if (This->State != KSSTATE_STOP)
|
/* stop stream in case it hasn't been */
|
||||||
{
|
Status = This->Stream->lpVtbl->SetState(This->Stream, KSSTATE_STOP);
|
||||||
This->Stream->lpVtbl->SetState(This->Stream, KSSTATE_STOP);
|
if (!NT_SUCCESS(Status))
|
||||||
KeStallExecutionProcessor(10);
|
DPRINT1("Warning: failed to stop stream with %x\n", Status);
|
||||||
}
|
|
||||||
|
This->State = KSSTATE_STOP;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (This->Format)
|
if (This->Format)
|
||||||
{
|
{
|
||||||
|
/* free format */
|
||||||
ExFreePool(This->Format);
|
ExFreePool(This->Format);
|
||||||
This->Format = NULL;
|
This->Format = NULL;
|
||||||
}
|
}
|
||||||
|
@ -848,7 +894,7 @@ IPortPinWaveCyclic_fnFastDeviceIoControl(
|
||||||
OUT PIO_STATUS_BLOCK StatusBlock,
|
OUT PIO_STATUS_BLOCK StatusBlock,
|
||||||
IN PDEVICE_OBJECT DeviceObject)
|
IN PDEVICE_OBJECT DeviceObject)
|
||||||
{
|
{
|
||||||
UNIMPLEMENTED
|
//UNIMPLEMENTED
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -915,15 +961,19 @@ IPortPinWaveCyclic_fnFastWrite(
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
PCONTEXT_WRITE Packet;
|
PCONTEXT_WRITE Packet;
|
||||||
PIRP Irp;
|
PIRP Irp;
|
||||||
|
ULONG PrePostRatio;
|
||||||
|
ULONG MinData;
|
||||||
IPortPinWaveCyclicImpl * This = (IPortPinWaveCyclicImpl*)iface;
|
IPortPinWaveCyclicImpl * This = (IPortPinWaveCyclicImpl*)iface;
|
||||||
|
|
||||||
InterlockedIncrement((PLONG)&This->TotalPackets);
|
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;
|
Packet = (PCONTEXT_WRITE)Buffer;
|
||||||
|
|
||||||
|
|
||||||
if (This->IrpQueue->lpVtbl->MinimumDataAvailable(This->IrpQueue))
|
if (This->IrpQueue->lpVtbl->MinimumDataAvailable(This->IrpQueue))
|
||||||
{
|
{
|
||||||
Irp = Packet->Irp;
|
Irp = Packet->Irp;
|
||||||
|
@ -945,7 +995,7 @@ IPortPinWaveCyclic_fnFastWrite(
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
return FALSE;
|
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);
|
SetStreamState(This, KSSTATE_RUN);
|
||||||
/* some should initiate a state request but didnt do it */
|
/* some should initiate a state request but didnt do it */
|
||||||
|
@ -1000,13 +1050,6 @@ IPortPinWaveCyclic_fnInit(
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
return 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)
|
if (KsPinDescriptor->Communication == KSPIN_COMMUNICATION_SINK && KsPinDescriptor->DataFlow == KSPIN_DATAFLOW_IN)
|
||||||
{
|
{
|
||||||
Capture = FALSE;
|
Capture = FALSE;
|
||||||
|
@ -1071,6 +1114,14 @@ IPortPinWaveCyclic_fnInit(
|
||||||
|
|
||||||
Status = This->Stream->lpVtbl->SetNotificationFreq(This->Stream, 10, &This->FrameSize);
|
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);
|
//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 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));
|
DPRINT1("Setting state to pause %x\n", This->Stream->lpVtbl->SetState(This->Stream, KSSTATE_PAUSE));
|
||||||
|
|
|
@ -12,6 +12,7 @@ typedef struct
|
||||||
{
|
{
|
||||||
IPortPinWavePciVtbl *lpVtbl;
|
IPortPinWavePciVtbl *lpVtbl;
|
||||||
IServiceSinkVtbl *lpVtblServiceSink;
|
IServiceSinkVtbl *lpVtblServiceSink;
|
||||||
|
IPortWavePciStreamVtbl *lpVtblPortWavePciStream;
|
||||||
|
|
||||||
LONG ref;
|
LONG ref;
|
||||||
IPortWavePci * Port;
|
IPortWavePci * Port;
|
||||||
|
@ -27,17 +28,21 @@ typedef struct
|
||||||
|
|
||||||
BOOL Capture;
|
BOOL Capture;
|
||||||
PDEVICE_OBJECT DeviceObject;
|
PDEVICE_OBJECT DeviceObject;
|
||||||
PPORTWAVEPCISTREAM WaveStream;
|
|
||||||
IIrpQueue * IrpQueue;
|
IIrpQueue * IrpQueue;
|
||||||
|
|
||||||
ULONG TotalPackets;
|
ULONG TotalPackets;
|
||||||
ULONG PreCompleted;
|
ULONG PreCompleted;
|
||||||
ULONG PostCompleted;
|
ULONG PostCompleted;
|
||||||
|
ULONG StopCount;
|
||||||
|
|
||||||
ULONG Delay;
|
ULONG Delay;
|
||||||
|
|
||||||
}IPortPinWavePciImpl;
|
BOOL bUsePrefetch;
|
||||||
|
ULONG PrefetchOffset;
|
||||||
|
|
||||||
|
KSALLOCATOR_FRAMING AllocatorFraming;
|
||||||
|
|
||||||
|
}IPortPinWavePciImpl;
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
|
@ -46,12 +51,110 @@ typedef struct
|
||||||
KSSTATE State;
|
KSSTATE State;
|
||||||
}SETSTREAM_CONTEXT, *PSETSTREAM_CONTEXT;
|
}SETSTREAM_CONTEXT, *PSETSTREAM_CONTEXT;
|
||||||
|
|
||||||
|
//==================================================================================================================================
|
||||||
|
static
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
NTAPI
|
NTAPI
|
||||||
IPortWavePci_fnProcessNewIrp(
|
IPortWavePciStream_fnQueryInterface(
|
||||||
IPortPinWavePciImpl * This);
|
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
|
static
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
|
@ -117,6 +220,8 @@ SetStreamWorkerRoutine(
|
||||||
IPortPinWavePciImpl * This;
|
IPortPinWavePciImpl * This;
|
||||||
PSETSTREAM_CONTEXT Ctx = (PSETSTREAM_CONTEXT)Context;
|
PSETSTREAM_CONTEXT Ctx = (PSETSTREAM_CONTEXT)Context;
|
||||||
KSSTATE State;
|
KSSTATE State;
|
||||||
|
ULONG MinimumDataThreshold;
|
||||||
|
ULONG MaximumDataThreshold;
|
||||||
|
|
||||||
This = Ctx->Pin;
|
This = Ctx->Pin;
|
||||||
State = Ctx->State;
|
State = Ctx->State;
|
||||||
|
@ -138,13 +243,27 @@ SetStreamWorkerRoutine(
|
||||||
{
|
{
|
||||||
/* reset start stream */
|
/* reset start stream */
|
||||||
This->IrpQueue->lpVtbl->CancelBuffers(This->IrpQueue); //FIX function name
|
This->IrpQueue->lpVtbl->CancelBuffers(This->IrpQueue); //FIX function name
|
||||||
This->ServiceGroup->lpVtbl->CancelDelayedService(This->ServiceGroup);
|
//This->ServiceGroup->lpVtbl->CancelDelayedService(This->ServiceGroup);
|
||||||
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 * 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)
|
if (This->State == KSSTATE_RUN)
|
||||||
{
|
{
|
||||||
/* start the notification timer */
|
/* 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_fnRequestService(
|
||||||
IServiceSink* iface)
|
IServiceSink* iface)
|
||||||
{
|
{
|
||||||
ULONGLONG Position;
|
|
||||||
NTSTATUS Status;
|
|
||||||
IPortPinWavePciImpl * This = (IPortPinWavePciImpl*)CONTAINING_RECORD(iface, IPortPinWavePciImpl, lpVtblServiceSink);
|
IPortPinWavePciImpl * This = (IPortPinWavePciImpl*)CONTAINING_RECORD(iface, IPortPinWavePciImpl, lpVtblServiceSink);
|
||||||
|
|
||||||
ASSERT_IRQL(DISPATCH_LEVEL);
|
ASSERT_IRQL(DISPATCH_LEVEL);
|
||||||
|
|
||||||
if (This->IrpQueue->lpVtbl->HasLastMappingFailed(This->IrpQueue))
|
if (This->IrpQueue->lpVtbl->HasLastMappingFailed(This->IrpQueue))
|
||||||
{
|
{
|
||||||
This->IrpQueue->lpVtbl->PrintQueueStatus(This->IrpQueue);
|
|
||||||
if (This->IrpQueue->lpVtbl->NumMappings(This->IrpQueue) == 0)
|
if (This->IrpQueue->lpVtbl->NumMappings(This->IrpQueue) == 0)
|
||||||
{
|
{
|
||||||
DPRINT("Stopping stream...\n");
|
DPRINT("Stopping stream...\n");
|
||||||
SetStreamState(This, KSSTATE_STOP);
|
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);
|
This->Stream->lpVtbl->Service(This->Stream);
|
||||||
|
//TODO
|
||||||
|
//generate events
|
||||||
}
|
}
|
||||||
|
|
||||||
static IServiceSinkVtbl vt_IServiceSink =
|
static IServiceSinkVtbl vt_IServiceSink =
|
||||||
|
@ -312,6 +428,191 @@ IPortPinWavePci_fnNewIrpTarget(
|
||||||
return STATUS_UNSUCCESSFUL;
|
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
|
* @unimplemented
|
||||||
*/
|
*/
|
||||||
|
@ -322,6 +623,16 @@ IPortPinWavePci_fnDeviceIoControl(
|
||||||
IN PDEVICE_OBJECT DeviceObject,
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
IN PIRP Irp)
|
IN PIRP Irp)
|
||||||
{
|
{
|
||||||
|
PIO_STACK_LOCATION IoStack;
|
||||||
|
|
||||||
|
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
||||||
|
|
||||||
|
if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_PROPERTY)
|
||||||
|
{
|
||||||
|
return IPortPinWavePci_HandleKsProperty(iface, Irp);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
UNIMPLEMENTED
|
UNIMPLEMENTED
|
||||||
|
|
||||||
Irp->IoStatus.Information = 0;
|
Irp->IoStatus.Information = 0;
|
||||||
|
@ -614,7 +925,6 @@ IPortPinWavePci_fnFastWrite(
|
||||||
|
|
||||||
Packet = (PCONTEXT_WRITE)Buffer;
|
Packet = (PCONTEXT_WRITE)Buffer;
|
||||||
|
|
||||||
|
|
||||||
if (This->IrpQueue->lpVtbl->MinimumDataAvailable(This->IrpQueue))
|
if (This->IrpQueue->lpVtbl->MinimumDataAvailable(This->IrpQueue))
|
||||||
{
|
{
|
||||||
Irp = Packet->Irp;
|
Irp = Packet->Irp;
|
||||||
|
@ -669,7 +979,6 @@ IPortPinWavePci_fnInit(
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
PKSDATAFORMAT DataFormat;
|
PKSDATAFORMAT DataFormat;
|
||||||
BOOL Capture;
|
BOOL Capture;
|
||||||
KSALLOCATOR_FRAMING AllocatorFraming;
|
|
||||||
|
|
||||||
IPortPinWavePciImpl * This = (IPortPinWavePciImpl*)iface;
|
IPortPinWavePciImpl * This = (IPortPinWavePciImpl*)iface;
|
||||||
|
|
||||||
|
@ -693,14 +1002,6 @@ IPortPinWavePci_fnInit(
|
||||||
|
|
||||||
RtlMoveMemory(This->Format, DataFormat, DataFormat->FormatSize);
|
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)
|
if (KsPinDescriptor->Communication == KSPIN_COMMUNICATION_SINK && KsPinDescriptor->DataFlow == KSPIN_DATAFLOW_IN)
|
||||||
{
|
{
|
||||||
Capture = FALSE;
|
Capture = FALSE;
|
||||||
|
@ -719,7 +1020,7 @@ IPortPinWavePci_fnInit(
|
||||||
&This->Stream,
|
&This->Stream,
|
||||||
NULL,
|
NULL,
|
||||||
NonPagedPool,
|
NonPagedPool,
|
||||||
This->WaveStream,
|
(PPORTWAVEPCISTREAM)&This->lpVtblPortWavePciStream,
|
||||||
ConnectDetails->PinId,
|
ConnectDetails->PinId,
|
||||||
Capture,
|
Capture,
|
||||||
This->Format,
|
This->Format,
|
||||||
|
@ -746,9 +1047,7 @@ IPortPinWavePci_fnInit(
|
||||||
/* delay of 10 milisec */
|
/* delay of 10 milisec */
|
||||||
This->Delay = Int32x32To64(10, -10000);
|
This->Delay = Int32x32To64(10, -10000);
|
||||||
|
|
||||||
This->IrpQueue = IPortWavePciStream_GetIrpQueue(This->WaveStream);
|
Status = This->Stream->lpVtbl->GetAllocatorFraming(This->Stream, &This->AllocatorFraming);
|
||||||
|
|
||||||
Status = This->Stream->lpVtbl->GetAllocatorFraming(This->Stream, &AllocatorFraming);
|
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
DPRINT1("GetAllocatorFraming failed with %x\n", 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",
|
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))
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
DPRINT1("IrpQueue_Init failed with %x\n", Status);
|
DPRINT1("IrpQueue_Init failed with %x\n", Status);
|
||||||
|
@ -835,6 +1138,7 @@ NTSTATUS NewPortPinWavePci(
|
||||||
This->ref = 1;
|
This->ref = 1;
|
||||||
This->lpVtbl = &vt_IPortPinWavePci;
|
This->lpVtbl = &vt_IPortPinWavePci;
|
||||||
This->lpVtblServiceSink = &vt_IServiceSink;
|
This->lpVtblServiceSink = &vt_IServiceSink;
|
||||||
|
This->lpVtblPortWavePciStream = &vt_PortWavePciStream;
|
||||||
|
|
||||||
|
|
||||||
/* store result */
|
/* 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
|
// IUnknown interface functions
|
||||||
//
|
//
|
||||||
|
@ -249,8 +271,8 @@ IPortDMus_fnInit(
|
||||||
InterfaceGuids,
|
InterfaceGuids,
|
||||||
0,
|
0,
|
||||||
NULL,
|
NULL,
|
||||||
0,
|
2,
|
||||||
NULL,
|
PortDMusPropertySet,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
|
|
|
@ -30,6 +30,10 @@ typedef struct
|
||||||
PPCFILTER_DESCRIPTOR pDescriptor;
|
PPCFILTER_DESCRIPTOR pDescriptor;
|
||||||
PSUBDEVICE_DESCRIPTOR SubDeviceDescriptor;
|
PSUBDEVICE_DESCRIPTOR SubDeviceDescriptor;
|
||||||
IPortFilterWavePci * Filter;
|
IPortFilterWavePci * Filter;
|
||||||
|
|
||||||
|
LIST_ENTRY EventList;
|
||||||
|
KSPIN_LOCK EventListLock;
|
||||||
|
|
||||||
}IPortWavePciImpl;
|
}IPortWavePciImpl;
|
||||||
|
|
||||||
static GUID InterfaceGuids[3] =
|
static GUID InterfaceGuids[3] =
|
||||||
|
@ -133,8 +137,14 @@ IPortEvents_fnAddEventToEventList(
|
||||||
IPortEvents* iface,
|
IPortEvents* iface,
|
||||||
IN PKSEVENT_ENTRY EventEntry)
|
IN PKSEVENT_ENTRY EventEntry)
|
||||||
{
|
{
|
||||||
UNIMPLEMENTED
|
KIRQL OldIrql;
|
||||||
|
IPortWavePciImpl * This = (IPortWavePciImpl*)CONTAINING_RECORD(iface, IPortWavePciImpl, lpVtblPortEvents);
|
||||||
|
|
||||||
ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
|
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->pDeviceObject = DeviceObject;
|
||||||
This->bInitialized = TRUE;
|
This->bInitialized = TRUE;
|
||||||
This->pResourceList = ResourceList;
|
This->pResourceList = ResourceList;
|
||||||
|
InitializeListHead(&This->EventList);
|
||||||
|
KeInitializeSpinLock(&This->EventListLock);
|
||||||
|
|
||||||
/* increment reference on miniport adapter */
|
/* increment reference on miniport adapter */
|
||||||
Miniport->lpVtbl->AddRef(Miniport);
|
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>drmk</library>
|
||||||
<library>hal</library>
|
<library>hal</library>
|
||||||
<library>libcntpr</library>
|
<library>libcntpr</library>
|
||||||
|
<library>pseh</library>
|
||||||
<file>adapter.c</file>
|
<file>adapter.c</file>
|
||||||
<file>api.c</file>
|
<file>api.c</file>
|
||||||
<file>connection.c</file>
|
<file>connection.c</file>
|
||||||
|
@ -40,7 +41,6 @@
|
||||||
<file>port_topology.c</file>
|
<file>port_topology.c</file>
|
||||||
<file>port_wavecyclic.c</file>
|
<file>port_wavecyclic.c</file>
|
||||||
<file>port_wavepci.c</file>
|
<file>port_wavepci.c</file>
|
||||||
<file>port_wavepcistream.c</file>
|
|
||||||
<file>port_wavert.c</file>
|
<file>port_wavert.c</file>
|
||||||
<file>port_wavertstream.c</file>
|
<file>port_wavertstream.c</file>
|
||||||
<file>power.c</file>
|
<file>power.c</file>
|
||||||
|
|
|
@ -279,16 +279,6 @@ PDEVICE_OBJECT
|
||||||
GetDeviceObject(
|
GetDeviceObject(
|
||||||
IPortWaveCyclic* iface);
|
IPortWaveCyclic* iface);
|
||||||
|
|
||||||
IIrpQueue*
|
|
||||||
NTAPI
|
|
||||||
IPortWavePciStream_GetIrpQueue(
|
|
||||||
IN IPortWavePciStream *iface);
|
|
||||||
|
|
||||||
NTSTATUS
|
|
||||||
NTAPI
|
|
||||||
NewIPortWavePciStream(
|
|
||||||
OUT PPORTWAVEPCISTREAM *Stream);
|
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
NTAPI
|
NTAPI
|
||||||
PcIoTimerRoutine(
|
PcIoTimerRoutine(
|
||||||
|
|
|
@ -595,6 +595,49 @@ WdmAudIoctlClose(
|
||||||
return STATUS_INVALID_PARAMETER;
|
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
|
NTSTATUS
|
||||||
NTAPI
|
NTAPI
|
||||||
WdmAudDeviceControl(
|
WdmAudDeviceControl(
|
||||||
|
@ -647,8 +690,9 @@ WdmAudDeviceControl(
|
||||||
return WdmAudCapabilities(DeviceObject, Irp, DeviceInfo, ClientInfo);
|
return WdmAudCapabilities(DeviceObject, Irp, DeviceInfo, ClientInfo);
|
||||||
case IOCTL_CLOSE_WDMAUD:
|
case IOCTL_CLOSE_WDMAUD:
|
||||||
return WdmAudIoctlClose(DeviceObject, Irp, DeviceInfo, ClientInfo);
|
return WdmAudIoctlClose(DeviceObject, Irp, DeviceInfo, ClientInfo);
|
||||||
|
case IOCTL_GETFRAMESIZE:
|
||||||
|
return WdmAudFrameSize(DeviceObject, Irp, DeviceInfo, ClientInfo);
|
||||||
case IOCTL_GETPOS:
|
case IOCTL_GETPOS:
|
||||||
DPRINT1("IOCTL_GETPOS\n");
|
|
||||||
case IOCTL_GETDEVID:
|
case IOCTL_GETDEVID:
|
||||||
case IOCTL_GETVOLUME:
|
case IOCTL_GETVOLUME:
|
||||||
case IOCTL_SETVOLUME:
|
case IOCTL_SETVOLUME:
|
||||||
|
@ -793,4 +837,3 @@ WdmAudWrite(
|
||||||
ObDereferenceObject(FileObject);
|
ObDereferenceObject(FileObject);
|
||||||
return IoStatusBlock.Status;
|
return IoStatusBlock.Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -43,6 +43,7 @@ typedef struct
|
||||||
ULONGLONG Position;
|
ULONGLONG Position;
|
||||||
KSSTATE State;
|
KSSTATE State;
|
||||||
ULONG Volume;
|
ULONG Volume;
|
||||||
|
ULONG FrameSize;
|
||||||
}u;
|
}u;
|
||||||
|
|
||||||
}WDMAUD_DEVICE_INFO, *PWDMAUD_DEVICE_INFO;
|
}WDMAUD_DEVICE_INFO, *PWDMAUD_DEVICE_INFO;
|
||||||
|
@ -212,7 +213,7 @@ typedef struct
|
||||||
/// Arguments: InputBuffer is a pointer to a WDMAUD_DEVICE_INFO structure,
|
/// Arguments: InputBuffer is a pointer to a WDMAUD_DEVICE_INFO structure,
|
||||||
/// InputBufferSize is size of WDMAUD_DEVICE_INFO structure
|
/// InputBufferSize is size of WDMAUD_DEVICE_INFO structure
|
||||||
/// Note: The DeviceType and hDevice must be set
|
/// 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
|
/// ReturnCode: STATUS_SUCCESS indicates success
|
||||||
/// Prequsites: opened device
|
/// Prequsites: opened device
|
||||||
|
|
||||||
|
@ -222,5 +223,22 @@ typedef struct
|
||||||
METHOD_BUFFERED, \
|
METHOD_BUFFERED, \
|
||||||
FILE_CREATE_TREE_CONNECTION | FILE_ANY_ACCESS)
|
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
|
#endif
|
||||||
|
|
|
@ -128,9 +128,9 @@ Pin_fnWrite(
|
||||||
{
|
{
|
||||||
PDISPATCH_CONTEXT Context;
|
PDISPATCH_CONTEXT Context;
|
||||||
PIO_STACK_LOCATION IoStack;
|
PIO_STACK_LOCATION IoStack;
|
||||||
ULONG BytesReturned;
|
|
||||||
PFILE_OBJECT FileObject;
|
PFILE_OBJECT FileObject;
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
|
ULONG BytesReturned;
|
||||||
|
|
||||||
/* Get current stack location */
|
/* Get current stack location */
|
||||||
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
||||||
|
@ -159,20 +159,21 @@ Pin_fnWrite(
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Re-dispatch the request to the real target pin */
|
/* call the portcls audio pin */
|
||||||
Status = KsSynchronousIoControlDevice(FileObject, KernelMode, IOCTL_KS_WRITE_STREAM,
|
Status = KsSynchronousIoControlDevice(FileObject, KernelMode, IOCTL_KS_WRITE_STREAM,
|
||||||
MmGetMdlVirtualAddress(Irp->MdlAddress),
|
MmGetMdlVirtualAddress(Irp->MdlAddress),
|
||||||
IoStack->Parameters.Read.Length,
|
IoStack->Parameters.Write.Length,
|
||||||
NULL,
|
NULL,
|
||||||
0,
|
0,
|
||||||
&BytesReturned);
|
&BytesReturned);
|
||||||
|
|
||||||
/* release file object */
|
|
||||||
|
/* Release file object */
|
||||||
ObDereferenceObject(FileObject);
|
ObDereferenceObject(FileObject);
|
||||||
|
|
||||||
/* Save status and information */
|
/* Save status and information */
|
||||||
Irp->IoStatus.Status = Status;
|
Irp->IoStatus.Status = Status;
|
||||||
Irp->IoStatus.Information = 0;
|
Irp->IoStatus.Information = BytesReturned;
|
||||||
/* Complete the irp */
|
/* Complete the irp */
|
||||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
/* Done */
|
/* Done */
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue