- Experimental IPortPinWavePci implementation

- Refactor IPortWavePciStream initilization
- Add test code for IDrmAudioStream

svn path=/trunk/; revision=40712
This commit is contained in:
Johannes Anderwald 2009-04-27 00:33:49 +00:00
parent dc97dbb867
commit 86b82cf4d6
9 changed files with 907 additions and 43 deletions

View file

@ -131,7 +131,7 @@ IPortFilterWavePci_fnNewIrpTarget(
}
/* initialize the pin */
Status = Pin->lpVtbl->Init(Pin, This->Port, iface, ConnectDetails, &This->Descriptor->Factory.KsPinDescriptor[ConnectDetails->PinId], GetDeviceObjectFromWaveCyclic(This->Port));
Status = Pin->lpVtbl->Init(Pin, This->Port, iface, ConnectDetails, &This->Descriptor->Factory.KsPinDescriptor[ConnectDetails->PinId], GetDeviceObjectFromPortWavePci(This->Port));
if (!NT_SUCCESS(Status))
{
Pin->lpVtbl->Release(Pin);

View file

@ -51,7 +51,7 @@ const GUID IID_IUnknown = {0x00000000, 0x0000, 0x0000, {0x00, 0x00, 0xC0, 0x00,
const GUID IID_IPortEvents = {0xA80F29C4L, 0x5498, 0x11D2, {0x95, 0xD9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3}};
const GUID KSNAME_PIN = {0x146F1A80, 0x4791, 0x11D0, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}};
const GUID IID_IDrmAudioStream = {0x1915c967, 0x3299, 0x48cb, {0xa3, 0xe4, 0x69, 0xfd, 0x1d, 0x1b, 0x30, 0x6e}};
//FIXME
//

View file

@ -230,6 +230,7 @@ DECLARE_INTERFACE_(IIrpQueue, IUnknown)
STDMETHOD_(VOID, ReleaseMappingWithTag)(THIS_
IN PVOID Tag);
STDMETHOD_(BOOL, HasLastMappingFailed)(THIS);
};

View file

@ -43,6 +43,8 @@ typedef struct
BOOL OutOfMapping;
ULONG MaxFrameSize;
BOOL LastMappingFailed;
}IIrpQueueImpl;
VOID
@ -189,11 +191,14 @@ IIrpQueue_fnGetMapping(
IIrpQueueImpl * This = (IIrpQueueImpl*)iface;
if (!This->FirstMap)
{
This->LastMappingFailed = TRUE;
return STATUS_UNSUCCESSFUL;
}
*Buffer = (PUCHAR)This->FirstMap->Header->Data + This->CurrentOffset;
*BufferSize = This->FirstMap->Header->DataUsed - This->CurrentOffset;
This->LastMappingFailed = FALSE;
return STATUS_SUCCESS;
}
@ -365,13 +370,17 @@ IIrpQueue_fnGetMappingWithTag(
KeReleaseSpinLock(&This->Lock, OldIrql);
if (!Result)
{
This->LastMappingFailed = TRUE;
return STATUS_UNSUCCESSFUL;
}
Result->Tag = Tag;
*PhysicalAddress = MmGetPhysicalAddress(Result->Header->Data);
*VirtualAddress = Result->Header->Data;
*ByteCount = Result->Header->DataUsed;
This->LastTag = Tag;
This->LastMappingFailed = FALSE;
return STATUS_SUCCESS;
}
@ -421,6 +430,15 @@ IIrpQueue_fnReleaseMappingWithTag(
KeReleaseSpinLock(&This->Lock, OldIrql);
}
BOOL
NTAPI
IIrpQueue_fnHasLastMappingFailed(
IN IIrpQueue *iface)
{
IIrpQueueImpl * This = (IIrpQueueImpl*)iface;
return This->LastMappingFailed;
}
static IIrpQueueVtbl vt_IIrpQueue =
{
IIrpQueue_fnQueryInterface,
@ -436,7 +454,9 @@ static IIrpQueueVtbl vt_IIrpQueue =
IIrpQueue_fnCancelBuffers,
IIrpQueue_fnUpdateFormat,
IIrpQueue_fnGetMappingWithTag,
IIrpQueue_fnReleaseMappingWithTag
IIrpQueue_fnReleaseMappingWithTag,
IIrpQueue_fnHasLastMappingFailed
};

View file

@ -37,6 +37,10 @@ typedef struct
ULONG FrameSize;
BOOL Capture;
ULONG TotalPackets;
ULONG PreCompleted;
ULONG PostCompleted;
}IPortPinWaveCyclicImpl;
@ -120,6 +124,8 @@ UpdateCommonBuffer(
ULONG BufferSize;
PUCHAR Buffer;
NTSTATUS Status;
PUSHORT Data;
ULONG Index;
BufferLength = Position - This->CommonBufferOffset;
while(BufferLength)
@ -140,6 +146,10 @@ UpdateCommonBuffer(
}
else
{
Data = (PUSHORT)Buffer;
for(Index = 0; Index < BytesToCopy / sizeof(USHORT); Index++)
Data[Index] = Data[Index] + 32768;
This->DmaChannel->lpVtbl->CopyTo(This->DmaChannel,
(PUCHAR)This->CommonBuffer + This->CommonBufferOffset,
Buffer,
@ -164,6 +174,8 @@ UpdateCommonBufferOverlap(
ULONG BufferSize;
PUCHAR Buffer;
NTSTATUS Status;
PUSHORT Data;
ULONG Index;
BufferLength = This->CommonBufferSize - This->CommonBufferOffset;
while(BufferLength)
@ -183,6 +195,10 @@ UpdateCommonBufferOverlap(
}
else
{
Data = (PUSHORT)Buffer;
for(Index = 0; Index < BytesToCopy / sizeof(USHORT); Index++)
Data[Index] = Data[Index] + 32768;
This->DmaChannel->lpVtbl->CopyTo(This->DmaChannel,
(PUCHAR)This->CommonBuffer + This->CommonBufferOffset,
Buffer,
@ -228,7 +244,7 @@ SetStreamWorkerRoutine(
{
/* reset start stream */
This->IrpQueue->lpVtbl->CancelBuffers(This->IrpQueue); //FIX function name
DPRINT1("Stopping %u Irql %u\n", This, This->IrpQueue->lpVtbl->NumMappings(This->IrpQueue), KeGetCurrentIrql());
DPRINT1("Stopping PreCompleted %u PostCompleted %u\n", This->PreCompleted, This->PostCompleted);
}
}
}
@ -908,7 +924,9 @@ IPortPinWaveCyclic_fnFastWrite(
PIRP Irp;
IPortPinWaveCyclicImpl * This = (IPortPinWaveCyclicImpl*)iface;
DPRINT("IPortPinWaveCyclic_fnFastWrite entered\n");
InterlockedIncrement((PLONG)&This->TotalPackets);
DPRINT("IPortPinWaveCyclic_fnFastWrite entered Total %u Pre %u Post %u\n", This->TotalPackets, This->PreCompleted, This->PostCompleted);
Packet = (PCONTEXT_WRITE)Buffer;
@ -917,6 +935,7 @@ IPortPinWaveCyclic_fnFastWrite(
{
Irp = Packet->Irp;
StatusBlock->Status = STATUS_PENDING;
InterlockedIncrement((PLONG)&This->PostCompleted);
}
else
{
@ -925,6 +944,7 @@ IPortPinWaveCyclic_fnFastWrite(
Packet->Irp->IoStatus.Information = Packet->Header.FrameExtent;
IoCompleteRequest(Packet->Irp, IO_SOUND_INCREMENT);
StatusBlock->Status = STATUS_SUCCESS;
InterlockedIncrement((PLONG)&This->PreCompleted);
}
Status = This->IrpQueue->lpVtbl->AddMapping(This->IrpQueue, Buffer, Length, Irp);
@ -958,6 +978,7 @@ IPortPinWaveCyclic_fnInit(
PKSDATAFORMAT DataFormat;
PDEVICE_OBJECT DeviceObject;
BOOL Capture;
//IDrmAudioStream * DrmAudio = NULL;
IPortPinWaveCyclicImpl * This = (IPortPinWaveCyclicImpl*)iface;
@ -1016,6 +1037,21 @@ IPortPinWaveCyclic_fnInit(
This->Format,
&This->DmaChannel,
&This->ServiceGroup);
#if 0
Status = This->Stream->lpVtbl->QueryInterface(This->Stream, &IID_IDrmAudioStream, (PVOID*)&DrmAudio);
if (NT_SUCCESS(Status))
{
DRMRIGHTS DrmRights;
DPRINT1("Got IID_IDrmAudioStream interface %p\n", DrmAudio);
DrmRights.CopyProtect = FALSE;
DrmRights.Reserved = 0;
DrmRights.DigitalOutputDisable = FALSE;
Status = DrmAudio->lpVtbl->SetContentId(DrmAudio, 1, &DrmRights);
DPRINT("Status %x\n", Status);
}
#endif
DPRINT("IPortPinWaveCyclic_fnInit Status %x\n", Status);
@ -1033,7 +1069,7 @@ IPortPinWaveCyclic_fnInit(
This->ServiceGroup->lpVtbl->SupportDelayedService(This->ServiceGroup);
//This->DmaChannel->lpVtbl->AddRef(This->DmaChannel);
This->Stream->lpVtbl->SetState(This->Stream, KSSTATE_STOP);
This->State = KSSTATE_STOP;
This->CommonBufferOffset = 0;
This->CommonBufferSize = This->DmaChannel->lpVtbl->AllocatedBufferSize(This->DmaChannel);

View file

@ -1,16 +1,829 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Kernel Streaming
* FILE: drivers/wdm/audio/backpln/portcls/pin_wavecyclic.c
* PURPOSE: WaveCyclic IRP Audio Pin
* FILE: drivers/wdm/audio/backpln/portcls/pin_WavePci.c
* PURPOSE: WavePci IRP Audio Pin
* PROGRAMMER: Johannes Anderwald
*/
#include "private.h"
NTSTATUS
NewPortPinWavePci(
OUT IPortPinWavePci ** OutPin)
#include "private.h"
typedef struct
{
IPortPinWavePciVtbl *lpVtbl;
IServiceSinkVtbl *lpVtblServiceSink;
LONG ref;
IPortWavePci * Port;
IPortFilterWavePci * Filter;
KSPIN_DESCRIPTOR * KsPinDescriptor;
PMINIPORTWAVEPCI Miniport;
PSERVICEGROUP ServiceGroup;
PDMACHANNEL DmaChannel;
PMINIPORTWAVEPCISTREAM Stream;
KSSTATE State;
PKSDATAFORMAT Format;
KSPIN_CONNECT * ConnectDetails;
BOOL Capture;
PDEVICE_OBJECT DeviceObject;
PPORTWAVEPCISTREAM WaveStream;
IIrpQueue * IrpQueue;
ULONG TotalPackets;
ULONG PreCompleted;
ULONG PostCompleted;
}IPortPinWavePciImpl;
typedef struct
{
IPortPinWavePciImpl *Pin;
PIO_WORKITEM WorkItem;
KSSTATE State;
}SETSTREAM_CONTEXT, *PSETSTREAM_CONTEXT;
NTSTATUS
NTAPI
IPortWavePci_fnProcessNewIrp(
IPortPinWavePciImpl * This);
//==================================================================================================================================
static
NTSTATUS
NTAPI
IServiceSink_fnQueryInterface(
IServiceSink* iface,
IN REFIID refiid,
OUT PVOID* Output)
{
IPortPinWavePciImpl * This = (IPortPinWavePciImpl*)CONTAINING_RECORD(iface, IPortPinWavePciImpl, lpVtblServiceSink);
DPRINT("IServiceSink_fnQueryInterface entered\n");
if (IsEqualGUIDAligned(refiid, &IID_IServiceSink) ||
IsEqualGUIDAligned(refiid, &IID_IUnknown))
{
*Output = &This->lpVtblServiceSink;
InterlockedIncrement(&This->ref);
return STATUS_SUCCESS;
}
return STATUS_UNSUCCESSFUL;
}
static
ULONG
NTAPI
IServiceSink_fnAddRef(
IServiceSink* iface)
{
IPortPinWavePciImpl * This = (IPortPinWavePciImpl*)CONTAINING_RECORD(iface, IPortPinWavePciImpl, lpVtblServiceSink);
DPRINT("IServiceSink_fnAddRef entered\n");
return InterlockedIncrement(&This->ref);
}
static
ULONG
NTAPI
IServiceSink_fnRelease(
IServiceSink* iface)
{
IPortPinWavePciImpl * This = (IPortPinWavePciImpl*)CONTAINING_RECORD(iface, IPortPinWavePciImpl, lpVtblServiceSink);
InterlockedDecrement(&This->ref);
DPRINT("IServiceSink_fnRelease entered %u\n", This->ref);
if (This->ref == 0)
{
FreeItem(This, TAG_PORTCLASS);
return 0;
}
/* Return new reference count */
return This->ref;
}
static
VOID
NTAPI
SetStreamWorkerRoutine(
IN PDEVICE_OBJECT DeviceObject,
IN PVOID Context)
{
IPortPinWavePciImpl * This;
PSETSTREAM_CONTEXT Ctx = (PSETSTREAM_CONTEXT)Context;
KSSTATE State;
This = Ctx->Pin;
State = Ctx->State;
IoFreeWorkItem(Ctx->WorkItem);
FreeItem(Ctx, TAG_PORTCLASS);
/* Has the audio stream resumed? */
if (This->IrpQueue->lpVtbl->NumMappings(This->IrpQueue) && State == KSSTATE_STOP)
return;
/* Set the state */
if (NT_SUCCESS(This->Stream->lpVtbl->SetState(This->Stream, State)))
{
/* Set internal state to stop */
This->State = State;
if (This->State == KSSTATE_STOP)
{
/* reset start stream */
This->IrpQueue->lpVtbl->CancelBuffers(This->IrpQueue); //FIX function name
DPRINT1("Stopping PreCompleted %u PostCompleted %u\n", This->PreCompleted, This->PostCompleted);
}
}
}
static
VOID
NTAPI
SetStreamState(
IN IPortPinWavePciImpl * This,
IN KSSTATE State)
{
PDEVICE_OBJECT DeviceObject;
PIO_WORKITEM WorkItem;
PSETSTREAM_CONTEXT Context;
ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
/* Has the audio stream resumed? */
if (This->IrpQueue->lpVtbl->NumMappings(This->IrpQueue) && State == KSSTATE_STOP)
return;
/* Has the audio state already been set? */
if (This->State == State)
return;
/* Get device object */
DeviceObject = GetDeviceObjectFromPortWavePci(This->Port);
/* allocate set state context */
Context = AllocateItem(NonPagedPool, sizeof(SETSTREAM_CONTEXT), TAG_PORTCLASS);
if (!Context)
return;
/* allocate work item */
WorkItem = IoAllocateWorkItem(DeviceObject);
if (!WorkItem)
{
ExFreePool(Context);
return;
}
Context->Pin = (PVOID)This;
Context->WorkItem = WorkItem;
Context->State = State;
/* queue the work item */
IoQueueWorkItem(WorkItem, SetStreamWorkerRoutine, DelayedWorkQueue, (PVOID)Context);
}
static
VOID
NTAPI
IServiceSink_fnRequestService(
IServiceSink* iface)
{
ULONGLONG Position;
NTSTATUS Status;
IPortPinWavePciImpl * This = (IPortPinWavePciImpl*)CONTAINING_RECORD(iface, IPortPinWavePciImpl, lpVtblServiceSink);
ASSERT_IRQL(DISPATCH_LEVEL);
Status = This->Stream->lpVtbl->GetPosition(This->Stream, &Position);
DPRINT("Position %llu Status %x\n", Position, Status);
This->Stream->lpVtbl->Service(This->Stream);
}
static IServiceSinkVtbl vt_IServiceSink =
{
IServiceSink_fnQueryInterface,
IServiceSink_fnAddRef,
IServiceSink_fnRelease,
IServiceSink_fnRequestService
};
//==================================================================================================================================
/*
* @implemented
*/
NTSTATUS
NTAPI
IPortPinWavePci_fnQueryInterface(
IPortPinWavePci* iface,
IN REFIID refiid,
OUT PVOID* Output)
{
IPortPinWavePciImpl * This = (IPortPinWavePciImpl*)iface;
if (IsEqualGUIDAligned(refiid, &IID_IIrpTarget) ||
IsEqualGUIDAligned(refiid, &IID_IUnknown))
{
*Output = &This->lpVtbl;
InterlockedIncrement(&This->ref);
return STATUS_SUCCESS;
}
return STATUS_UNSUCCESSFUL;
}
/*
* @implemented
*/
ULONG
NTAPI
IPortPinWavePci_fnAddRef(
IPortPinWavePci* iface)
{
IPortPinWavePciImpl * This = (IPortPinWavePciImpl*)iface;
return InterlockedIncrement(&This->ref);
}
/*
* @implemented
*/
ULONG
NTAPI
IPortPinWavePci_fnRelease(
IPortPinWavePci* iface)
{
IPortPinWavePciImpl * This = (IPortPinWavePciImpl*)iface;
InterlockedDecrement(&This->ref);
if (This->ref == 0)
{
FreeItem(This, TAG_PORTCLASS);
return 0;
}
return This->ref;
}
/*
* @unimplemented
*/
NTSTATUS
NTAPI
IPortPinWavePci_fnNewIrpTarget(
IN IPortPinWavePci* iface,
OUT struct IIrpTarget **OutTarget,
IN WCHAR * Name,
IN PUNKNOWN Unknown,
IN POOL_TYPE PoolType,
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN KSOBJECT_CREATE *CreateObject)
{
UNIMPLEMENTED
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_UNSUCCESSFUL;
}
/*
* @unimplemented
*/
NTSTATUS
NTAPI
IPortPinWavePci_fnDeviceIoControl(
IN IPortPinWavePci* iface,
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
UNIMPLEMENTED
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_UNSUCCESSFUL;
}
/*
* @implemented
*/
NTSTATUS
NTAPI
IPortPinWavePci_fnRead(
IN IPortPinWavePci* iface,
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
}
/*
* @implemented
*/
NTSTATUS
NTAPI
IPortPinWavePci_fnWrite(
IN IPortPinWavePci* iface,
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
}
/*
* @implemented
*/
NTSTATUS
NTAPI
IPortPinWavePci_fnFlush(
IN IPortPinWavePci* iface,
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
}
static
VOID
NTAPI
CloseStreamRoutine(
IN PDEVICE_OBJECT DeviceObject,
IN PVOID Context)
{
PMINIPORTWAVEPCISTREAM Stream;
NTSTATUS Status;
ISubdevice *ISubDevice;
PSUBDEVICE_DESCRIPTOR Descriptor;
IPortPinWavePciImpl * This;
PCLOSESTREAM_CONTEXT Ctx = (PCLOSESTREAM_CONTEXT)Context;
This = (IPortPinWavePciImpl*)Ctx->Pin;
if (This->Stream)
{
if (This->State != KSSTATE_STOP)
{
This->Stream->lpVtbl->SetState(This->Stream, KSSTATE_STOP);
KeStallExecutionProcessor(10);
}
}
if (This->ServiceGroup)
{
This->ServiceGroup->lpVtbl->RemoveMember(This->ServiceGroup, (PSERVICESINK)&This->lpVtblServiceSink);
This->ServiceGroup->lpVtbl->Release(This->ServiceGroup);
}
Status = This->Port->lpVtbl->QueryInterface(This->Port, &IID_ISubdevice, (PVOID*)&ISubDevice);
if (NT_SUCCESS(Status))
{
Status = ISubDevice->lpVtbl->GetDescriptor(ISubDevice, &Descriptor);
if (NT_SUCCESS(Status))
{
ISubDevice->lpVtbl->Release(ISubDevice);
Descriptor->Factory.Instances[This->ConnectDetails->PinId].CurrentPinInstanceCount--;
}
}
if (This->Format)
{
ExFreePool(This->Format);
This->Format = NULL;
}
if (This->WaveStream)
{
This->WaveStream->lpVtbl->Release(This->WaveStream);
}
/* complete the irp */
Ctx->Irp->IoStatus.Information = 0;
Ctx->Irp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest(Ctx->Irp, IO_NO_INCREMENT);
/* free the work item */
IoFreeWorkItem(Ctx->WorkItem);
/* free work item ctx */
FreeItem(Ctx, TAG_PORTCLASS);
if (This->Stream)
{
Stream = This->Stream;
This->Stream = NULL;
DPRINT1("Closing stream at Irql %u\n", KeGetCurrentIrql());
Stream->lpVtbl->Release(Stream);
/* this line is never reached */
}
}
/*
* @implemented
*/
NTSTATUS
NTAPI
IPortPinWavePci_fnClose(
IN IPortPinWavePci* iface,
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
PCLOSESTREAM_CONTEXT Ctx;
IPortPinWavePciImpl * This = (IPortPinWavePciImpl*)iface;
if (This->Stream)
{
Ctx = AllocateItem(NonPagedPool, sizeof(CLOSESTREAM_CONTEXT), TAG_PORTCLASS);
if (!Ctx)
{
DPRINT1("Failed to allocate stream context\n");
goto cleanup;
}
Ctx->WorkItem = IoAllocateWorkItem(DeviceObject);
if (!Ctx->WorkItem)
{
DPRINT1("Failed to allocate work item\n");
goto cleanup;
}
Ctx->Irp = Irp;
Ctx->Pin = (PVOID)This;
IoMarkIrpPending(Irp);
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = STATUS_PENDING;
/* defer work item */
IoQueueWorkItem(Ctx->WorkItem, CloseStreamRoutine, DelayedWorkQueue, (PVOID)Ctx);
/* Return result */
return STATUS_PENDING;
}
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
cleanup:
if (Ctx)
FreeItem(Ctx, TAG_PORTCLASS);
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_UNSUCCESSFUL;
}
/*
* @implemented
*/
NTSTATUS
NTAPI
IPortPinWavePci_fnQuerySecurity(
IN IPortPinWavePci* iface,
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
}
/*
* @implemented
*/
NTSTATUS
NTAPI
IPortPinWavePci_fnSetSecurity(
IN IPortPinWavePci* iface,
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
}
/*
* @implemented
*/
BOOLEAN
NTAPI
IPortPinWavePci_fnFastDeviceIoControl(
IN IPortPinWavePci* iface,
IN PFILE_OBJECT FileObject,
IN BOOLEAN Wait,
IN PVOID InputBuffer,
IN ULONG InputBufferLength,
OUT PVOID OutputBuffer,
IN ULONG OutputBufferLength,
IN ULONG IoControlCode,
OUT PIO_STATUS_BLOCK StatusBlock,
IN PDEVICE_OBJECT DeviceObject)
{
UNIMPLEMENTED
return FALSE;
}
/*
* @implemented
*/
BOOLEAN
NTAPI
IPortPinWavePci_fnFastRead(
IN IPortPinWavePci* iface,
IN PFILE_OBJECT FileObject,
IN PLARGE_INTEGER FileOffset,
IN ULONG Length,
IN BOOLEAN Wait,
IN ULONG LockKey,
IN PVOID Buffer,
OUT PIO_STATUS_BLOCK StatusBlock,
IN PDEVICE_OBJECT DeviceObject)
{
NTSTATUS Status;
PCONTEXT_WRITE Packet;
PIRP Irp;
IPortPinWavePciImpl * This = (IPortPinWavePciImpl*)iface;
DPRINT("IPortPinWavePci_fnFastRead entered\n");
Packet = (PCONTEXT_WRITE)Buffer;
Irp = Packet->Irp;
StatusBlock->Status = STATUS_PENDING;
Status = This->IrpQueue->lpVtbl->AddMapping(This->IrpQueue, Buffer, Length, Irp);
if (!NT_SUCCESS(Status))
return FALSE;
if (This->IrpQueue->lpVtbl->MinimumDataAvailable(This->IrpQueue) == TRUE && This->State != KSSTATE_RUN)
{
/* some should initiate a state request but didnt do it */
DPRINT1("Starting stream with %lu mappings\n", This->IrpQueue->lpVtbl->NumMappings(This->IrpQueue));
This->Stream->lpVtbl->SetState(This->Stream, KSSTATE_RUN);
This->State = KSSTATE_RUN;
}
return TRUE;
}
/*
* @implemented
*/
BOOLEAN
NTAPI
IPortPinWavePci_fnFastWrite(
IN IPortPinWavePci* iface,
IN PFILE_OBJECT FileObject,
IN PLARGE_INTEGER FileOffset,
IN ULONG Length,
IN BOOLEAN Wait,
IN ULONG LockKey,
IN PVOID Buffer,
OUT PIO_STATUS_BLOCK StatusBlock,
IN PDEVICE_OBJECT DeviceObject)
{
NTSTATUS Status;
PCONTEXT_WRITE Packet;
PIRP Irp;
IPortPinWavePciImpl * This = (IPortPinWavePciImpl*)iface;
InterlockedIncrement((PLONG)&This->TotalPackets);
DPRINT("IPortPinWavePci_fnFastWrite entered Total %u Pre %u Post %u\n", This->TotalPackets, This->PreCompleted, This->PostCompleted);
Packet = (PCONTEXT_WRITE)Buffer;
if (This->IrpQueue->lpVtbl->MinimumDataAvailable(This->IrpQueue))
{
Irp = Packet->Irp;
StatusBlock->Status = STATUS_PENDING;
InterlockedIncrement((PLONG)&This->PostCompleted);
}
else
{
Irp = NULL;
Packet->Irp->IoStatus.Status = STATUS_SUCCESS;
Packet->Irp->IoStatus.Information = Packet->Header.FrameExtent;
IoCompleteRequest(Packet->Irp, IO_SOUND_INCREMENT);
StatusBlock->Status = STATUS_SUCCESS;
InterlockedIncrement((PLONG)&This->PreCompleted);
}
Status = This->IrpQueue->lpVtbl->AddMapping(This->IrpQueue, Buffer, Length, Irp);
if (!NT_SUCCESS(Status))
return FALSE;
if (This->IrpQueue->lpVtbl->MinimumDataAvailable(This->IrpQueue) == TRUE && This->State != KSSTATE_RUN)
{
SetStreamState(This, KSSTATE_RUN);
/* some should initiate a state request but didnt do it */
DPRINT1("Starting stream with %lu mappings Status %x\n", This->IrpQueue->lpVtbl->NumMappings(This->IrpQueue), Status);
}
if (This->IrpQueue->lpVtbl->HasLastMappingFailed(This->IrpQueue))
{
/* notify port driver that new mapping is available */
This->Stream->lpVtbl->MappingAvailable(This->Stream);
}
return TRUE;
}
/*
* @unimplemented
*/
NTSTATUS
NTAPI
IPortPinWavePci_fnInit(
IN IPortPinWavePci* iface,
IN PPORTWAVEPCI Port,
IN PPORTFILTERWAVEPCI Filter,
IN KSPIN_CONNECT * ConnectDetails,
IN KSPIN_DESCRIPTOR * KsPinDescriptor,
IN PDEVICE_OBJECT DeviceObject)
{
NTSTATUS Status;
PKSDATAFORMAT DataFormat;
BOOL Capture;
KSALLOCATOR_FRAMING AllocatorFraming;
IPortPinWavePciImpl * This = (IPortPinWavePciImpl*)iface;
Port->lpVtbl->AddRef(Port);
Filter->lpVtbl->AddRef(Filter);
This->Port = Port;
This->Filter = Filter;
This->KsPinDescriptor = KsPinDescriptor;
This->ConnectDetails = ConnectDetails;
This->Miniport = GetWavePciMiniport(Port);
This->DeviceObject = DeviceObject;
DataFormat = (PKSDATAFORMAT)(ConnectDetails + 1);
DPRINT("IPortPinWavePci_fnInit entered\n");
This->Format = ExAllocatePoolWithTag(NonPagedPool, DataFormat->FormatSize, TAG_PORTCLASS);
if (!This->Format)
return STATUS_INSUFFICIENT_RESOURCES;
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;
}
else if (KsPinDescriptor->Communication == KSPIN_COMMUNICATION_SINK && KsPinDescriptor->DataFlow == KSPIN_DATAFLOW_OUT)
{
Capture = TRUE;
}
else
{
DPRINT1("Unexpected Communication %u DataFlow %u\n", KsPinDescriptor->Communication, KsPinDescriptor->DataFlow);
KeBugCheck(0);
}
Status = This->Miniport->lpVtbl->NewStream(This->Miniport,
&This->Stream,
NULL,
NonPagedPool,
This->WaveStream,
Capture,
ConnectDetails->PinId,
This->Format,
&This->DmaChannel,
&This->ServiceGroup);
DPRINT("IPortPinWavePci_fnInit Status %x\n", Status);
if (!NT_SUCCESS(Status))
return Status;
if (This->ServiceGroup)
{
Status = This->ServiceGroup->lpVtbl->AddMember(This->ServiceGroup,
(PSERVICESINK)&This->lpVtblServiceSink);
if (!NT_SUCCESS(Status))
{
DPRINT1("Failed to add pin to service group\n");
return Status;
}
This->ServiceGroup->lpVtbl->SupportDelayedService(This->ServiceGroup);
}
This->IrpQueue = IPortWavePciStream_GetIrpQueue(This->WaveStream);
Status = This->Stream->lpVtbl->GetAllocatorFraming(This->Stream, &AllocatorFraming);
if (!NT_SUCCESS(Status))
{
DPRINT1("GetAllocatorFraming failed with %x\n", Status);
return Status;
}
Status = This->IrpQueue->lpVtbl->Init(This->IrpQueue, ConnectDetails, This->Format, DeviceObject, AllocatorFraming.FrameSize);
if (!NT_SUCCESS(Status))
{
DPRINT1("IrpQueue_Init failed with %x\n", Status);
return Status;
}
This->State = KSSTATE_STOP;
This->Capture = Capture;
return STATUS_SUCCESS;
}
/*
* @implemented
*/
PVOID
NTAPI
IPortPinWavePci_fnGetIrpStream(
IN IPortPinWavePci* iface)
{
IPortPinWavePciImpl * This = (IPortPinWavePciImpl*)iface;
return (PVOID)This->IrpQueue;
}
/*
* @implemented
*/
PMINIPORT
NTAPI
IPortPinWavePci_fnGetMiniport(
IN IPortPinWavePci* iface)
{
IPortPinWavePciImpl * This = (IPortPinWavePciImpl*)iface;
return (PMINIPORT)This->Miniport;
}
static IPortPinWavePciVtbl vt_IPortPinWavePci =
{
IPortPinWavePci_fnQueryInterface,
IPortPinWavePci_fnAddRef,
IPortPinWavePci_fnRelease,
IPortPinWavePci_fnNewIrpTarget,
IPortPinWavePci_fnDeviceIoControl,
IPortPinWavePci_fnRead,
IPortPinWavePci_fnWrite,
IPortPinWavePci_fnFlush,
IPortPinWavePci_fnClose,
IPortPinWavePci_fnQuerySecurity,
IPortPinWavePci_fnSetSecurity,
IPortPinWavePci_fnFastDeviceIoControl,
IPortPinWavePci_fnFastRead,
IPortPinWavePci_fnFastWrite,
IPortPinWavePci_fnInit,
IPortPinWavePci_fnGetIrpStream,
IPortPinWavePci_fnGetMiniport
};
NTSTATUS NewPortPinWavePci(
OUT IPortPinWavePci ** OutPin)
{
IPortPinWavePciImpl * This;
This = AllocateItem(NonPagedPool, sizeof(IPortPinWavePciImpl), TAG_PORTCLASS);
if (!This)
return STATUS_INSUFFICIENT_RESOURCES;
/* initialize IPortPinWavePci */
This->ref = 1;
This->lpVtbl = &vt_IPortPinWavePci;
This->lpVtblServiceSink = &vt_IServiceSink;
/* store result */
*OutPin = (IPortPinWavePci*)&This->lpVtbl;
return STATUS_SUCCESS;
}

View file

@ -813,10 +813,17 @@ NewPortWavePci(
}
PDEVICE_OBJECT
GetDeviceObjectFromWaveCyclic(
GetDeviceObjectFromPortWavePci(
IPortWavePci* iface)
{
IPortWavePciImpl * This = (IPortWavePciImpl*)iface;
return This->pDeviceObject;
}
PMINIPORTWAVEPCI
GetWavePciMiniport(
PPORTWAVEPCI iface)
{
IPortWavePciImpl * This = (IPortWavePciImpl*)iface;
return This->Miniport;
}

View file

@ -66,6 +66,7 @@ IPortWavePciStream_fnRelease(
if (This->ref == 0)
{
This->Queue->lpVtbl->Release(This->Queue);
FreeItem(This, TAG_PORTCLASS);
return 0;
}
@ -131,11 +132,7 @@ static IPortWavePciStreamVtbl vt_PortWavePciStream =
NTSTATUS
NTAPI
NewIPortWavePciStream(
OUT PPORTWAVEPCISTREAM *Stream,
IN KSPIN_CONNECT *ConnectDetails,
IN PKSDATAFORMAT DataFormat,
IN PDEVICE_OBJECT DeviceObject,
IN ULONG FrameSize)
OUT PPORTWAVEPCISTREAM *Stream)
{
IIrpQueue * Queue;
IPortWavePciStreamImpl * This;
@ -145,13 +142,6 @@ NewIPortWavePciStream(
if (!NT_SUCCESS(Status))
return Status;
Status = Queue->lpVtbl->Init(Queue, ConnectDetails, DataFormat, DeviceObject, FrameSize);
if (!NT_SUCCESS(Status))
{
Queue->lpVtbl->Release(Queue);
return Status;
}
This = AllocateItem(NonPagedPool, sizeof(IPortWavePciStreamImpl), TAG_PORTCLASS);
if (!This)
{
@ -167,15 +157,12 @@ NewIPortWavePciStream(
return STATUS_SUCCESS;
}
NTSTATUS
IIrpQueue*
NTAPI
IPortWavePciStream_AddMapping(
IN IPortWavePciStream *iface,
IN PUCHAR Buffer,
IN ULONG BufferSize,
IN PIRP Irp)
IPortWavePciStream_GetIrpQueue(
IN IPortWavePciStream *iface)
{
IPortWavePciStreamImpl * This = (IPortWavePciStreamImpl*)iface;
return This->Queue->lpVtbl->AddMapping(This->Queue, Buffer, BufferSize, Irp);
return This->Queue;
}

View file

@ -101,6 +101,13 @@ PDEVICE_OBJECT
GetDeviceObjectFromWaveCyclic(
IPortWavePci* iface);
PDEVICE_OBJECT
GetDeviceObjectFromPortWavePci(
IPortWavePci* iface);
PMINIPORTWAVEPCI
GetWavePciMiniport(
PPORTWAVEPCI Port);
NTSTATUS
NTAPI
@ -272,22 +279,15 @@ PDEVICE_OBJECT
GetDeviceObject(
IPortWaveCyclic* iface);
NTSTATUS
IIrpQueue*
NTAPI
IPortWavePciStream_AddMapping(
IN IPortWavePciStream *iface,
IN PUCHAR Buffer,
IN ULONG BufferSize,
IN PIRP Irp);
IPortWavePciStream_GetIrpQueue(
IN IPortWavePciStream *iface);
NTSTATUS
NTAPI
NewIPortWavePciStream(
OUT PPORTWAVEPCISTREAM *Stream,
IN KSPIN_CONNECT *ConnectDetails,
IN PKSDATAFORMAT DataFormat,
IN PDEVICE_OBJECT DeviceObject,
IN ULONG FrameSize);
OUT PPORTWAVEPCISTREAM *Stream);
#define DEFINE_KSPROPERTY_PINPROPOSEDATAFORMAT(PinSet,\
PropGeneral, PropInstances, PropIntersection)\