mirror of
https://github.com/reactos/reactos.git
synced 2024-09-11 05:12:43 +00:00
702 lines
19 KiB
C++
702 lines
19 KiB
C++
/*
|
|
* COPYRIGHT: See COPYING in the top level directory
|
|
* PROJECT: ReactOS Kernel Streaming
|
|
* FILE: drivers/wdm/audio/backpln/portcls/pin_wavert.cpp
|
|
* PURPOSE: WaveRT IRP Audio Pin
|
|
* PROGRAMMER: Johannes Anderwald
|
|
*/
|
|
|
|
#include "private.hpp"
|
|
|
|
#ifndef YDEBUG
|
|
#define NDEBUG
|
|
#endif
|
|
|
|
#include <debug.h>
|
|
|
|
class CPortPinWaveRT : public IPortPinWaveRT
|
|
{
|
|
public:
|
|
STDMETHODIMP QueryInterface( REFIID InterfaceId, PVOID* Interface);
|
|
|
|
STDMETHODIMP_(ULONG) AddRef()
|
|
{
|
|
InterlockedIncrement(&m_Ref);
|
|
return m_Ref;
|
|
}
|
|
STDMETHODIMP_(ULONG) Release()
|
|
{
|
|
InterlockedDecrement(&m_Ref);
|
|
|
|
if (!m_Ref)
|
|
{
|
|
delete this;
|
|
return 0;
|
|
}
|
|
return m_Ref;
|
|
}
|
|
IMP_IPortPinWaveRT;
|
|
CPortPinWaveRT(IUnknown *OuterUnknown){}
|
|
virtual ~CPortPinWaveRT(){}
|
|
|
|
protected:
|
|
|
|
IPortWaveRT * m_Port;
|
|
IPortFilterWaveRT * m_Filter;
|
|
KSPIN_DESCRIPTOR * m_KsPinDescriptor;
|
|
PMINIPORTWAVERT m_Miniport;
|
|
PMINIPORTWAVERTSTREAM m_Stream;
|
|
PPORTWAVERTSTREAM m_PortStream;
|
|
KSSTATE m_State;
|
|
PKSDATAFORMAT m_Format;
|
|
KSPIN_CONNECT * m_ConnectDetails;
|
|
|
|
PVOID m_CommonBuffer;
|
|
ULONG m_CommonBufferSize;
|
|
ULONG m_CommonBufferOffset;
|
|
|
|
IIrpQueue * m_IrpQueue;
|
|
|
|
BOOL m_Capture;
|
|
|
|
ULONG m_TotalPackets;
|
|
ULONG m_PreCompleted;
|
|
ULONG m_PostCompleted;
|
|
|
|
ULONGLONG m_Delay;
|
|
|
|
MEMORY_CACHING_TYPE m_CacheType;
|
|
PMDL m_Mdl;
|
|
|
|
LONG m_Ref;
|
|
|
|
NTSTATUS NTAPI HandleKsProperty(IN PIRP Irp);
|
|
NTSTATUS NTAPI HandleKsStream(IN PIRP Irp);
|
|
VOID NTAPI SetStreamState(IN KSSTATE State);
|
|
friend VOID NTAPI SetStreamWorkerRoutine(IN PDEVICE_OBJECT DeviceObject, IN PVOID Context);
|
|
friend VOID NTAPI CloseStreamRoutine(IN PDEVICE_OBJECT DeviceObject, IN PVOID Context);
|
|
|
|
};
|
|
|
|
|
|
typedef struct
|
|
{
|
|
CPortPinWaveRT *Pin;
|
|
PIO_WORKITEM WorkItem;
|
|
KSSTATE State;
|
|
}SETSTREAM_CONTEXT, *PSETSTREAM_CONTEXT;
|
|
|
|
|
|
//==================================================================================================================================
|
|
NTSTATUS
|
|
NTAPI
|
|
CPortPinWaveRT::QueryInterface(
|
|
IN REFIID refiid,
|
|
OUT PVOID* Output)
|
|
{
|
|
DPRINT("IServiceSink_fnQueryInterface entered\n");
|
|
|
|
if (IsEqualGUIDAligned(refiid, IID_IIrpTarget) ||
|
|
IsEqualGUIDAligned(refiid, IID_IUnknown))
|
|
{
|
|
*Output = PVOID(PUNKNOWN((IIrpTarget*)this));
|
|
PUNKNOWN(*Output)->AddRef();
|
|
return STATUS_SUCCESS;
|
|
}
|
|
return STATUS_UNSUCCESSFUL;
|
|
}
|
|
|
|
//==================================================================================================================================
|
|
|
|
NTSTATUS
|
|
NTAPI
|
|
CPortPinWaveRT::NewIrpTarget(
|
|
OUT struct IIrpTarget **OutTarget,
|
|
IN PCWSTR Name,
|
|
IN PUNKNOWN Unknown,
|
|
IN POOL_TYPE PoolType,
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp,
|
|
IN KSOBJECT_CREATE *CreateObject)
|
|
{
|
|
UNIMPLEMENTED;
|
|
return STATUS_UNSUCCESSFUL;
|
|
}
|
|
|
|
NTSTATUS
|
|
NTAPI
|
|
CPortPinWaveRT::HandleKsProperty(
|
|
IN PIRP Irp)
|
|
{
|
|
PKSPROPERTY Property;
|
|
NTSTATUS Status;
|
|
UNICODE_STRING GuidString;
|
|
PIO_STACK_LOCATION IoStack;
|
|
|
|
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
|
|
|
DPRINT("IPortPinWave_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;
|
|
|
|
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 (m_Stream)
|
|
{
|
|
Status = m_Stream->SetState(*State);
|
|
|
|
DPRINT("Setting state %u %x\n", *State, Status);
|
|
if (NT_SUCCESS(Status))
|
|
{
|
|
m_State = *State;
|
|
}
|
|
}
|
|
Irp->IoStatus.Status = Status;
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
return Status;
|
|
}
|
|
else if (Property->Flags & KSPROPERTY_TYPE_GET)
|
|
{
|
|
*State = m_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, m_Format, DataFormat->FormatSize))
|
|
{
|
|
Irp->IoStatus.Information = DataFormat->FormatSize;
|
|
Irp->IoStatus.Status = STATUS_SUCCESS;
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
NewDataFormat = (PKSDATAFORMAT)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 (m_Stream)
|
|
{
|
|
#if 0
|
|
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(m_State == KSSTATE_STOP);
|
|
#endif
|
|
DPRINT("NewDataFormat: Channels %u Bits %u Samples %u\n", ((PKSDATAFORMAT_WAVEFORMATEX)NewDataFormat)->WaveFormatEx.nChannels,
|
|
((PKSDATAFORMAT_WAVEFORMATEX)NewDataFormat)->WaveFormatEx.wBitsPerSample,
|
|
((PKSDATAFORMAT_WAVEFORMATEX)NewDataFormat)->WaveFormatEx.nSamplesPerSec);
|
|
|
|
Status = m_Stream->SetFormat(NewDataFormat);
|
|
if (NT_SUCCESS(Status))
|
|
{
|
|
if (m_Format)
|
|
FreeItem(m_Format, TAG_PORTCLASS);
|
|
|
|
m_Format = NewDataFormat;
|
|
Irp->IoStatus.Information = DataFormat->FormatSize;
|
|
Irp->IoStatus.Status = STATUS_SUCCESS;
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
return STATUS_SUCCESS;
|
|
}
|
|
}
|
|
DPRINT("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 (!m_Format)
|
|
{
|
|
DPRINT("No format\n");
|
|
Irp->IoStatus.Information = 0;
|
|
Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
return STATUS_UNSUCCESSFUL;
|
|
}
|
|
if (m_Format->FormatSize > IoStack->Parameters.DeviceIoControl.OutputBufferLength)
|
|
{
|
|
Irp->IoStatus.Information = m_Format->FormatSize;
|
|
Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL;
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
return STATUS_BUFFER_TOO_SMALL;
|
|
}
|
|
|
|
RtlMoveMemory(DataFormat, m_Format, m_Format->FormatSize);
|
|
Irp->IoStatus.Information = DataFormat->FormatSize;
|
|
Irp->IoStatus.Status = STATUS_SUCCESS;
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
return STATUS_SUCCESS;
|
|
}
|
|
}
|
|
|
|
}
|
|
RtlStringFromGUID(Property->Set, &GuidString);
|
|
DPRINT("Unhandled 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;
|
|
}
|
|
|
|
NTSTATUS
|
|
NTAPI
|
|
CPortPinWaveRT::HandleKsStream(
|
|
IN PIRP Irp)
|
|
{
|
|
DPRINT("IPortPinWaveRT_HandleKsStream entered State %u Stream %p is UNIMPLEMENTED\n", m_State, m_Stream);
|
|
|
|
return STATUS_PENDING;
|
|
}
|
|
|
|
NTSTATUS
|
|
NTAPI
|
|
CPortPinWaveRT::DeviceIoControl(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp)
|
|
{
|
|
PIO_STACK_LOCATION IoStack;
|
|
|
|
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
|
|
|
|
|
if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_PROPERTY)
|
|
{
|
|
return HandleKsProperty(Irp);
|
|
}
|
|
else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_ENABLE_EVENT)
|
|
{
|
|
/// FIXME
|
|
/// handle enable event
|
|
}
|
|
else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_DISABLE_EVENT)
|
|
{
|
|
/// FIXME
|
|
/// handle disable event
|
|
}
|
|
else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_RESET_STATE)
|
|
{
|
|
/// FIXME
|
|
/// handle reset state
|
|
}
|
|
else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_WRITE_STREAM || IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_READ_STREAM)
|
|
{
|
|
return HandleKsStream(Irp);
|
|
}
|
|
else
|
|
{
|
|
return KsDefaultDeviceIoCompletion(DeviceObject, Irp);
|
|
}
|
|
|
|
UNIMPLEMENTED;
|
|
|
|
Irp->IoStatus.Information = 0;
|
|
Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
|
|
return STATUS_UNSUCCESSFUL;
|
|
}
|
|
|
|
NTSTATUS
|
|
NTAPI
|
|
CPortPinWaveRT::Read(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp)
|
|
{
|
|
return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
|
|
}
|
|
|
|
NTSTATUS
|
|
NTAPI
|
|
CPortPinWaveRT::Write(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp)
|
|
{
|
|
return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
|
|
}
|
|
|
|
NTSTATUS
|
|
NTAPI
|
|
CPortPinWaveRT::Flush(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp)
|
|
{
|
|
return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
|
|
}
|
|
|
|
VOID
|
|
NTAPI
|
|
CloseStreamRoutine(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PVOID Context)
|
|
{
|
|
PMINIPORTWAVERTSTREAM Stream;
|
|
NTSTATUS Status;
|
|
ISubdevice *ISubDevice;
|
|
PSUBDEVICE_DESCRIPTOR Descriptor;
|
|
CPortPinWaveRT * This;
|
|
PCLOSESTREAM_CONTEXT Ctx = (PCLOSESTREAM_CONTEXT)Context;
|
|
|
|
This = (CPortPinWaveRT*)Ctx->Pin;
|
|
|
|
if (This->m_Stream)
|
|
{
|
|
if (This->m_State != KSSTATE_STOP)
|
|
{
|
|
This->m_Stream->SetState(KSSTATE_STOP);
|
|
KeStallExecutionProcessor(10);
|
|
}
|
|
}
|
|
|
|
Status = This->m_Port->QueryInterface(IID_ISubdevice, (PVOID*)&ISubDevice);
|
|
if (NT_SUCCESS(Status))
|
|
{
|
|
Status = ISubDevice->GetDescriptor(&Descriptor);
|
|
if (NT_SUCCESS(Status))
|
|
{
|
|
Descriptor->Factory.Instances[This->m_ConnectDetails->PinId].CurrentPinInstanceCount--;
|
|
}
|
|
ISubDevice->Release();
|
|
}
|
|
|
|
if (This->m_Format)
|
|
{
|
|
FreeItem(This->m_Format, TAG_PORTCLASS);
|
|
This->m_Format = NULL;
|
|
}
|
|
|
|
if (This->m_IrpQueue)
|
|
{
|
|
This->m_IrpQueue->Release();
|
|
}
|
|
|
|
// 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->m_Stream)
|
|
{
|
|
Stream = This->m_Stream;
|
|
This->m_Stream = NULL;
|
|
DPRINT("Closing stream at Irql %u\n", KeGetCurrentIrql());
|
|
Stream->Release();
|
|
}
|
|
}
|
|
|
|
NTSTATUS
|
|
NTAPI
|
|
CPortPinWaveRT::Close(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp)
|
|
{
|
|
PCLOSESTREAM_CONTEXT Ctx;
|
|
|
|
if (m_Stream)
|
|
{
|
|
Ctx = (PCLOSESTREAM_CONTEXT)AllocateItem(NonPagedPool, sizeof(CLOSESTREAM_CONTEXT), TAG_PORTCLASS);
|
|
if (!Ctx)
|
|
{
|
|
DPRINT("Failed to allocate stream context\n");
|
|
goto cleanup;
|
|
}
|
|
|
|
Ctx->WorkItem = IoAllocateWorkItem(DeviceObject);
|
|
if (!Ctx->WorkItem)
|
|
{
|
|
DPRINT("Failed to allocate work item\n");
|
|
goto cleanup;
|
|
}
|
|
|
|
Ctx->Irp = Irp;
|
|
Ctx->Pin = 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;
|
|
|
|
}
|
|
|
|
NTSTATUS
|
|
NTAPI
|
|
CPortPinWaveRT::QuerySecurity(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp)
|
|
{
|
|
return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
|
|
}
|
|
|
|
NTSTATUS
|
|
NTAPI
|
|
CPortPinWaveRT::SetSecurity(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp)
|
|
{
|
|
return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
|
|
}
|
|
|
|
BOOLEAN
|
|
NTAPI
|
|
CPortPinWaveRT::FastDeviceIoControl(
|
|
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)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
BOOLEAN
|
|
NTAPI
|
|
CPortPinWaveRT::FastRead(
|
|
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)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
BOOLEAN
|
|
NTAPI
|
|
CPortPinWaveRT::FastWrite(
|
|
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)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
NTSTATUS
|
|
NTAPI
|
|
CPortPinWaveRT::Init(
|
|
IN PPORTWAVERT Port,
|
|
IN PPORTFILTERWAVERT Filter,
|
|
IN KSPIN_CONNECT * ConnectDetails,
|
|
IN KSPIN_DESCRIPTOR * KsPinDescriptor,
|
|
IN PDEVICE_OBJECT DeviceObject)
|
|
{
|
|
NTSTATUS Status;
|
|
PKSDATAFORMAT DataFormat;
|
|
BOOLEAN Capture;
|
|
KSRTAUDIO_HWLATENCY Latency;
|
|
|
|
Port->AddRef();
|
|
Filter->AddRef();
|
|
|
|
m_Port = Port;
|
|
m_Filter = Filter;
|
|
m_KsPinDescriptor = KsPinDescriptor;
|
|
m_ConnectDetails = ConnectDetails;
|
|
m_Miniport = GetWaveRTMiniport(Port);
|
|
|
|
DataFormat = (PKSDATAFORMAT)(ConnectDetails + 1);
|
|
|
|
DPRINT("CPortPinWaveRT::Init entered\n");
|
|
|
|
m_Format = (PKSDATAFORMAT)AllocateItem(NonPagedPool, DataFormat->FormatSize, TAG_PORTCLASS);
|
|
if (!m_Format)
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
RtlMoveMemory(m_Format, DataFormat, DataFormat->FormatSize);
|
|
|
|
Status = NewIrpQueue(&m_IrpQueue);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
goto cleanup;
|
|
}
|
|
|
|
Status = m_IrpQueue->Init(ConnectDetails, KsPinDescriptor, 0, 0, FALSE);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
goto cleanup;
|
|
}
|
|
|
|
Status = NewPortWaveRTStream(&m_PortStream);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
goto cleanup;
|
|
}
|
|
|
|
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
|
|
{
|
|
DPRINT("Unexpected Communication %u DataFlow %u\n", KsPinDescriptor->Communication, KsPinDescriptor->DataFlow);
|
|
KeBugCheck(0);
|
|
while(TRUE);
|
|
}
|
|
|
|
Status = m_Miniport->NewStream(&m_Stream, m_PortStream, ConnectDetails->PinId, Capture, m_Format);
|
|
DPRINT("CPortPinWaveRT::Init Status %x\n", Status);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
goto cleanup;
|
|
|
|
m_Stream->GetHWLatency(&Latency);
|
|
// delay of 10 millisec
|
|
m_Delay = Int32x32To64(10, -10000);
|
|
|
|
Status = m_Stream->AllocateAudioBuffer(16384 * 11, &m_Mdl, &m_CommonBufferSize, &m_CommonBufferOffset, &m_CacheType);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
DPRINT("AllocateAudioBuffer failed with %x\n", Status);
|
|
goto cleanup;
|
|
}
|
|
|
|
m_CommonBuffer = MmGetSystemAddressForMdlSafe(m_Mdl, NormalPagePriority);
|
|
if (!m_CommonBuffer)
|
|
{
|
|
DPRINT("Failed to get system address %x\n", Status);
|
|
IoFreeMdl(m_Mdl);
|
|
m_Mdl = NULL;
|
|
goto cleanup;
|
|
}
|
|
|
|
DPRINT("Setting state to acquire %x\n", m_Stream->SetState(KSSTATE_ACQUIRE));
|
|
DPRINT("Setting state to pause %x\n", m_Stream->SetState(KSSTATE_PAUSE));
|
|
m_State = KSSTATE_PAUSE;
|
|
return STATUS_SUCCESS;
|
|
|
|
cleanup:
|
|
if (m_IrpQueue)
|
|
{
|
|
m_IrpQueue->Release();
|
|
m_IrpQueue = NULL;
|
|
}
|
|
|
|
if (m_Format)
|
|
{
|
|
FreeItem(m_Format, TAG_PORTCLASS);
|
|
m_Format = NULL;
|
|
}
|
|
|
|
if (m_Stream)
|
|
{
|
|
m_Stream->Release();
|
|
m_Stream = NULL;
|
|
}
|
|
else
|
|
{
|
|
if (m_PortStream)
|
|
{
|
|
m_PortStream->Release();
|
|
m_PortStream = NULL;
|
|
}
|
|
|
|
}
|
|
return Status;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
NewPortPinWaveRT(
|
|
OUT IPortPinWaveRT ** OutPin)
|
|
{
|
|
CPortPinWaveRT * This;
|
|
|
|
This = new(NonPagedPool, TAG_PORTCLASS) CPortPinWaveRT(NULL);
|
|
if (!This)
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
This->AddRef();
|
|
|
|
// store result
|
|
*OutPin = (PPORTPINWAVERT)This;
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|