[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:
Johannes Anderwald 2009-07-17 19:15:52 +00:00
parent 6d59a5cfa7
commit dac78ab19a
13 changed files with 565 additions and 284 deletions

View file

@ -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;
}

View file

@ -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);
};

View file

@ -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;
}

View file

@ -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));

View file

@ -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 */

View file

@ -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,

View file

@ -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);

View file

@ -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;
}

View file

@ -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>

View 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(

View file

@ -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;
}

View file

@ -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

View file

@ -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 */