- Implement KSPROPERTY_CONNECTION_STATE & KSPROPERTY_CONNECTION_FORMAT for property set KSPROPSETID_Connection

- Queue a work item when Irql is above dispatch level
- Open the input / output stream when initializing the pin

svn path=/trunk/; revision=39671
This commit is contained in:
Johannes Anderwald 2009-02-18 23:27:10 +00:00
parent cbac26c676
commit c50d26f16b
7 changed files with 272 additions and 11 deletions

View file

@ -86,14 +86,14 @@ IPortFilterWaveCyclic_fnNewIrpTarget(
ISubdevice * ISubDevice;
NTSTATUS Status;
IPortPinWaveCyclic * Pin;
SUBDEVICE_DESCRIPTOR * Descriptor;
PKSPIN_CONNECT ConnectDetails;
IPortFilterWaveCyclicImpl * This = (IPortFilterWaveCyclicImpl *)iface;
ASSERT(This->Port);
DPRINT("IPortFilterWaveCyclic_fnNewIrpTarget entered\n");
Status = This->Port->lpVtbl->QueryInterface(This->Port, &IID_ISubdevice, (PVOID*)&ISubDevice);
if (!NT_SUCCESS(Status))
return STATUS_UNSUCCESSFUL;

View file

@ -60,6 +60,7 @@ const GUID KSDATAFORMAT_SPECIFIER_WAVEFORMATEX = {0x05589f81L, 0xc356, 0x11ce, {
const GUID KSPROPSETID_Topology = {0x720D4AC0L, 0x7533, 0x11D0, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}};
const GUID KSPROPSETID_Pin = {0x8C134960L, 0x51AD, 0x11CF, {0x87, 0x8A, 0x94, 0xF8, 0x01, 0xC1, 0x00, 0x00}};
const GUID KSPROPSETID_Connection = {0x1D58C920L, 0xAC9B, 0x11CF, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}};
///
/// undocumented guids

View file

@ -9,6 +9,12 @@ typedef struct
IPortWaveCyclic * Port;
IPortFilterWaveCyclic * Filter;
KSPIN_DESCRIPTOR * KsPinDescriptor;
PMINIPORTWAVECYCLIC Miniport;
PSERVICEGROUP ServiceGroup;
PDMACHANNEL DmaChannel;
PMINIPORTWAVECYCLICSTREAM Stream;
KSSTATE State;
PKSDATAFORMAT Format;
}IPortPinWaveCyclicImpl;
@ -165,6 +171,139 @@ IPortPinWaveCyclic_fnNewIrpTarget(
return STATUS_UNSUCCESSFUL;
}
NTSTATUS
NTAPI
IPortPinWaveCyclic_HandleKsProperty(
IN IPortPinWaveCyclic * iface,
IN PIRP Irp)
{
PKSPROPERTY Property;
NTSTATUS Status;
UNICODE_STRING GuidString;
PIO_STACK_LOCATION IoStack;
IPortPinWaveCyclicImpl * This = (IPortPinWaveCyclicImpl*)iface;
IoStack = IoGetCurrentIrpStackLocation(Irp);
DPRINT1("IPortPinWave_HandleKsProperty entered\n");
if (IoStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(KSPROPERTY))
{
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
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;
return STATUS_BUFFER_TOO_SMALL;
}
if (Property->Id & KSPROPERTY_TYPE_SET)
{
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
if (This->Stream)
{
Status = This->Stream->lpVtbl->SetState(This->Stream, *State);
DPRINT1("Setting state %x\n", Status);
if (NT_SUCCESS(Status))
{
This->State = *State;
Irp->IoStatus.Information = sizeof(KSSTATE);
Irp->IoStatus.Status = Status;
return Status;
}
Irp->IoStatus.Status = Status;
}
return Irp->IoStatus.Status;
}
else if (Property->Id & KSPROPERTY_TYPE_GET)
{
*State = This->State;
Irp->IoStatus.Information = sizeof(KSSTATE);
Irp->IoStatus.Status = STATUS_SUCCESS;
return STATUS_SUCCESS;
}
}
else if (Property->Id == KSPROPERTY_CONNECTION_DATAFORMAT)
{
PKSDATAFORMAT DataFormat = (PKSDATAFORMAT)Irp->UserBuffer;
if (Property->Id & KSPROPERTY_TYPE_SET)
{
PKSDATAFORMAT NewDataFormat = AllocateItem(NonPagedPool, DataFormat->FormatSize, TAG_PORTCLASS);
if (!NewDataFormat)
{
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = STATUS_NO_MEMORY;
return STATUS_NO_MEMORY;
}
RtlMoveMemory(NewDataFormat, DataFormat, DataFormat->FormatSize);
if (This->Stream)
{
Status = This->Stream->lpVtbl->SetFormat(This->Stream, DataFormat);
if (NT_SUCCESS(Status))
{
if (This->Format)
ExFreePoolWithTag(This->Format, TAG_PORTCLASS);
This->Format = NewDataFormat;
Irp->IoStatus.Information = DataFormat->FormatSize;
Irp->IoStatus.Status = STATUS_SUCCESS;
return STATUS_SUCCESS;
}
}
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
return STATUS_UNSUCCESSFUL;
}
else if (Property->Id & KSPROPERTY_TYPE_GET)
{
PKSDATAFORMAT DataFormat = (PKSDATAFORMAT)Irp->UserBuffer;
if (!This->Format)
{
DPRINT1("No format\n");
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
return STATUS_UNSUCCESSFUL;
}
if (This->Format->FormatSize > IoStack->Parameters.DeviceIoControl.OutputBufferLength)
{
Irp->IoStatus.Information = This->Format->FormatSize;
Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL;
return STATUS_BUFFER_TOO_SMALL;
}
RtlMoveMemory(DataFormat, This->Format, This->Format->FormatSize);
Irp->IoStatus.Information = DataFormat->FormatSize;
Irp->IoStatus.Status = STATUS_SUCCESS;
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;
Irp->IoStatus.Information = 0;
return STATUS_NOT_IMPLEMENTED;
}
/*
* @unimplemented
*/
@ -181,11 +320,10 @@ IPortPinWaveCyclic_fnDeviceIoControl(
IoStack = IoGetCurrentIrpStackLocation(Irp);
DPRINT1("IPortPinWaveCyclic_fnDeviceIoControl\n");
DPRINT1("IPortPinWaveCyclic_fnDeviceIoControl %x %x\n",IoStack->Parameters.DeviceIoControl.IoControlCode, IOCTL_KS_PROPERTY);
if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_PROPERTY)
{
/// FIXME
/// handle property event
return IPortPinWaveCyclic_HandleKsProperty(iface, Irp);
}
else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_ENABLE_EVENT)
{
@ -365,6 +503,8 @@ IPortPinWaveCyclic_fnInit(
IN KSPIN_CONNECT * ConnectDetails,
IN KSPIN_DESCRIPTOR * KsPinDescriptor)
{
NTSTATUS Status;
PKSDATAFORMAT DataFormat;
IPortPinWaveCyclicImpl * This = (IPortPinWaveCyclicImpl*)iface;
Port->lpVtbl->AddRef(Port);
@ -373,6 +513,42 @@ IPortPinWaveCyclic_fnInit(
This->Port = Port;
This->Filter = Filter;
This->KsPinDescriptor = KsPinDescriptor;
This->Miniport = GetWaveCyclicMiniport(Port);
DataFormat = (PKSDATAFORMAT)(ConnectDetails + 1);
DPRINT("IPortPinWaveCyclic_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 = This->Miniport->lpVtbl->NewStream(This->Miniport,
&This->Stream,
NULL,
NonPagedPool,
FALSE, //FIXME
ConnectDetails->PinId,
This->Format,
&This->DmaChannel,
&This->ServiceGroup);
DPRINT("IPortPinWaveCyclic_fnInit Status %x\n", Status);
if (!NT_SUCCESS(Status))
return Status;
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->State = KSSTATE_STOP;
return STATUS_SUCCESS;
}

View file

@ -172,7 +172,6 @@ IPortMidi_fnInit(
/* increment reference on miniport adapter */
Miniport->lpVtbl->AddRef(Miniport);
DbgBreakPoint();
Status = Miniport->lpVtbl->Init(Miniport, UnknownAdapter, ResourceList, iface, &ServiceGroup);
if (!NT_SUCCESS(Status))
{
@ -182,8 +181,6 @@ IPortMidi_fnInit(
return Status;
}
DPRINT1("IMiniportMidi sucessfully init\n");
/* get the miniport device descriptor */
Status = Miniport->lpVtbl->GetDescription(Miniport, &This->pDescriptor);
if (!NT_SUCCESS(Status))

View file

@ -17,6 +17,12 @@ typedef struct
PSUBDEVICE_DESCRIPTOR SubDeviceDescriptor;
}IPortTopologyImpl;
typedef struct
{
PIRP Irp;
IIrpTarget *Filter;
}PIN_WORKER_CONTEXT, *PPIN_WORKER_CONTEXT;
static GUID InterfaceGuids[2] =
{
@ -432,6 +438,43 @@ static ISubdeviceVtbl vt_ISubdeviceVtbl =
ISubDevice_fnPinCount
};
VOID
NTAPI
CreatePinWorkerRoutine(
IN PDEVICE_OBJECT DeviceObject,
IN PVOID Context)
{
NTSTATUS Status;
IIrpTarget *Pin;
PPIN_WORKER_CONTEXT WorkerContext = (PPIN_WORKER_CONTEXT)Context;
DPRINT("CreatePinWorkerRoutine called\n");
Status = WorkerContext->Filter->lpVtbl->NewIrpTarget(WorkerContext->Filter,
&Pin,
NULL,
NULL,
NonPagedPool,
DeviceObject,
WorkerContext->Irp,
NULL);
DPRINT("CreatePinWorkerRoutine Status %x\n", Status);
if (NT_SUCCESS(Status))
{
/* create the dispatch object */
Status = NewDispatchObject(WorkerContext->Irp, Pin);
DPRINT("Pin %p\n", Pin);
}
DPRINT1("CreatePinWorkerRoutine completing irp\n");
WorkerContext->Irp->IoStatus.Status = Status;
WorkerContext->Irp->IoStatus.Information = 0;
IoCompleteRequest(WorkerContext->Irp, IO_SOUND_INCREMENT);
}
NTSTATUS
NTAPI
PcCreateItemDispatch(
@ -521,7 +564,6 @@ PcCreateItemDispatch(
Status = NewDispatchObject(Irp, Filter);
DPRINT1("Filter %p\n", Filter);
DbgBreakPoint();
}
else
{
@ -534,6 +576,34 @@ PcCreateItemDispatch(
if (!wcsncmp(KS_NAME_PIN, Buffer, wcslen(KS_NAME_PIN)))
{
/* try to create new pin */
if (KeGetCurrentIrql() >= APC_LEVEL)
{
PPIN_WORKER_CONTEXT Context = AllocateItem(NonPagedPool, sizeof(PIN_WORKER_CONTEXT), TAG_PORTCLASS);
if (!Context)
{
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
return STATUS_INSUFFICIENT_RESOURCES;
}
Context->Filter = Filter;
Context->Irp = Irp;
PIO_WORKITEM WorkItem = IoAllocateWorkItem(DeviceObject);
if (!WorkItem)
{
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
return STATUS_INSUFFICIENT_RESOURCES;
}
IoQueueWorkItem(WorkItem, CreatePinWorkerRoutine, DelayedWorkQueue, (PVOID)Context);
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = STATUS_PENDING;
IoMarkIrpPending(Irp);
return STATUS_PENDING;
}
Create.CreateItemsCount = 1;
Create.CreateItemsList = (PKSOBJECT_CREATE_ITEM)(IoStack->FileObject->FileName.Buffer + (wcslen(KS_NAME_PIN) + 1));
@ -553,7 +623,8 @@ PcCreateItemDispatch(
}
}
}
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = Status;
return Status;
}

View file

@ -709,6 +709,14 @@ static ISubdeviceVtbl vt_ISubdeviceVtbl =
};
///--------------------------------------------------------------
PMINIPORTWAVECYCLIC
GetWaveCyclicMiniport(
IN IPortWaveCyclic* iface)
{
IPortWaveCyclicImpl * This = (IPortWaveCyclicImpl *)iface;
return This->pMiniport;
}
//---------------------------------------------------------------
// IPortWaveCyclic constructor

View file

@ -94,7 +94,15 @@ NewDispatchObject(
IN PIRP Irp,
IN IIrpTarget * Target);
PVOID AllocateItem(IN POOL_TYPE PoolType, IN SIZE_T NumberOfBytes, IN ULONG Tag);
PMINIPORTWAVECYCLIC
GetWaveCyclicMiniport(
IN IPortWaveCyclic* iface);
PVOID
AllocateItem(
IN POOL_TYPE PoolType,
IN SIZE_T NumberOfBytes,
IN ULONG Tag);
VOID
FreeItem(