mirror of
https://github.com/reactos/reactos.git
synced 2024-09-11 05:12:43 +00:00
328 lines
9.6 KiB
C++
328 lines
9.6 KiB
C++
/*
|
|
* COPYRIGHT: See COPYING in the top level directory
|
|
* PROJECT: ReactOS Kernel Streaming
|
|
* FILE: drivers/wdm/audio/backpln/portcls/propertyhandler.cpp
|
|
* PURPOSE: Pin property handler
|
|
* PROGRAMMER: Johannes Anderwald
|
|
*/
|
|
|
|
#include "private.hpp"
|
|
|
|
#ifndef YDEBUG
|
|
#define NDEBUG
|
|
#endif
|
|
|
|
#include <debug.h>
|
|
|
|
NTSTATUS
|
|
HandlePropertyInstances(
|
|
IN PIO_STATUS_BLOCK IoStatus,
|
|
IN PKSIDENTIFIER Request,
|
|
IN OUT PVOID Data,
|
|
IN PSUBDEVICE_DESCRIPTOR Descriptor,
|
|
IN BOOL Global,
|
|
IN ISubdevice *SubDevice)
|
|
{
|
|
KSPIN_CINSTANCES * Instances;
|
|
KSP_PIN * Pin = (KSP_PIN*)Request;
|
|
ULONG FilterNecessary, FilterCurrent, FilterPossible, GlobalCurrent, GlobalPossible;
|
|
NTSTATUS Status;
|
|
|
|
if (Pin->PinId >= Descriptor->Factory.PinDescriptorCount)
|
|
{
|
|
IoStatus->Information = 0;
|
|
IoStatus->Status = STATUS_INVALID_PARAMETER;
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
Instances = (KSPIN_CINSTANCES*)Data;
|
|
|
|
// check if the miniport supports the IPinCount interface
|
|
Status = SubDevice->PinCount(Pin->PinId, &FilterNecessary, &FilterCurrent, &FilterPossible, &GlobalCurrent, &GlobalPossible);
|
|
|
|
if (NT_SUCCESS(Status))
|
|
{
|
|
if (Global)
|
|
{
|
|
Instances->PossibleCount = GlobalPossible;
|
|
Instances->CurrentCount = GlobalCurrent;
|
|
}
|
|
else
|
|
{
|
|
Instances->PossibleCount = FilterPossible;
|
|
Instances->CurrentCount = FilterCurrent;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (Global)
|
|
Instances->PossibleCount = Descriptor->Factory.Instances[Pin->PinId].MaxGlobalInstanceCount;
|
|
else
|
|
Instances->PossibleCount = Descriptor->Factory.Instances[Pin->PinId].MaxFilterInstanceCount;
|
|
|
|
Instances->CurrentCount = Descriptor->Factory.Instances[Pin->PinId].CurrentPinInstanceCount;
|
|
}
|
|
|
|
IoStatus->Information = sizeof(KSPIN_CINSTANCES);
|
|
IoStatus->Status = STATUS_SUCCESS;
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
NTSTATUS
|
|
HandleNecessaryPropertyInstances(
|
|
IN PIO_STATUS_BLOCK IoStatus,
|
|
IN PKSIDENTIFIER Request,
|
|
IN OUT PVOID Data,
|
|
IN PSUBDEVICE_DESCRIPTOR Descriptor,
|
|
IN ISubdevice *SubDevice)
|
|
{
|
|
PULONG Result;
|
|
KSP_PIN * Pin = (KSP_PIN*)Request;
|
|
ULONG FilterNecessary, FilterCurrent, FilterPossible, GlobalCurrent, GlobalPossible;
|
|
NTSTATUS Status;
|
|
|
|
if (Pin->PinId >= Descriptor->Factory.PinDescriptorCount)
|
|
{
|
|
IoStatus->Information = 0;
|
|
IoStatus->Status = STATUS_INVALID_PARAMETER;
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
Result = (PULONG)Data;
|
|
|
|
|
|
// check if the miniport supports the IPinCount interface
|
|
Status = SubDevice->PinCount(Pin->PinId, &FilterNecessary, &FilterCurrent, &FilterPossible, &GlobalCurrent, &GlobalPossible);
|
|
|
|
if (NT_SUCCESS(Status))
|
|
{
|
|
*Result = FilterNecessary;
|
|
}
|
|
else
|
|
{
|
|
*Result = Descriptor->Factory.Instances[Pin->PinId].MinFilterInstanceCount;
|
|
}
|
|
|
|
IoStatus->Information = sizeof(ULONG);
|
|
IoStatus->Status = STATUS_SUCCESS;
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
NTSTATUS
|
|
HandleDataIntersection(
|
|
IN PIO_STATUS_BLOCK IoStatus,
|
|
IN PKSIDENTIFIER Request,
|
|
IN OUT PVOID Data,
|
|
IN ULONG DataLength,
|
|
IN PSUBDEVICE_DESCRIPTOR Descriptor,
|
|
IN ISubdevice *SubDevice)
|
|
{
|
|
KSP_PIN * Pin = (KSP_PIN*)Request;
|
|
PKSMULTIPLE_ITEM MultipleItem;
|
|
PKSDATARANGE DataRange;
|
|
NTSTATUS Status = STATUS_NO_MATCH;
|
|
ULONG Index, Length;
|
|
|
|
// Access parameters
|
|
MultipleItem = (PKSMULTIPLE_ITEM)(Pin + 1);
|
|
DataRange = (PKSDATARANGE)(MultipleItem + 1);
|
|
|
|
for(Index = 0; Index < MultipleItem->Count; Index++)
|
|
{
|
|
// Call miniport's proprietary handler
|
|
PC_ASSERT(Descriptor->Factory.KsPinDescriptor[Pin->PinId].DataRangesCount);
|
|
PC_ASSERT(Descriptor->Factory.KsPinDescriptor[Pin->PinId].DataRanges[0]);
|
|
Status = SubDevice->DataRangeIntersection(Pin->PinId, DataRange, (PKSDATARANGE)Descriptor->Factory.KsPinDescriptor[Pin->PinId].DataRanges[0],
|
|
DataLength, Data, &Length);
|
|
|
|
if (Status == STATUS_SUCCESS)
|
|
{
|
|
IoStatus->Information = Length;
|
|
break;
|
|
}
|
|
DataRange = (PKSDATARANGE)((PUCHAR)DataRange + DataRange->FormatSize);
|
|
}
|
|
|
|
IoStatus->Status = Status;
|
|
return Status;
|
|
}
|
|
|
|
NTSTATUS
|
|
HandlePhysicalConnection(
|
|
IN PIO_STATUS_BLOCK IoStatus,
|
|
IN PKSIDENTIFIER Request,
|
|
IN ULONG RequestLength,
|
|
IN OUT PVOID Data,
|
|
IN ULONG DataLength,
|
|
IN PSUBDEVICE_DESCRIPTOR Descriptor)
|
|
{
|
|
PKSP_PIN Pin;
|
|
PLIST_ENTRY Entry;
|
|
//PKSPIN_PHYSICALCONNECTION Connection;
|
|
PPHYSICAL_CONNECTION_ENTRY ConEntry;
|
|
|
|
// get pin
|
|
Pin = (PKSP_PIN)Request;
|
|
|
|
if (RequestLength < sizeof(KSP_PIN))
|
|
{
|
|
// input buffer must be at least sizeof KSP_PIN
|
|
DPRINT("input length too small\n");
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
if (IsListEmpty(&Descriptor->PhysicalConnectionList))
|
|
{
|
|
DPRINT("no connection\n");
|
|
return STATUS_NOT_FOUND;
|
|
}
|
|
|
|
// get first item
|
|
Entry = Descriptor->PhysicalConnectionList.Flink;
|
|
|
|
do
|
|
{
|
|
ConEntry = (PPHYSICAL_CONNECTION_ENTRY)CONTAINING_RECORD(Entry, PHYSICAL_CONNECTION_ENTRY, Entry);
|
|
|
|
if (ConEntry->FromPin == Pin->PinId)
|
|
{
|
|
//Connection = (PKSPIN_PHYSICALCONNECTION)Data;
|
|
DPRINT("FoundEntry %S Size %u\n", ConEntry->Connection.SymbolicLinkName, ConEntry->Connection.Size);
|
|
IoStatus->Information = ConEntry->Connection.Size;
|
|
|
|
if (!DataLength)
|
|
{
|
|
IoStatus->Information = ConEntry->Connection.Size;
|
|
return STATUS_MORE_ENTRIES;
|
|
}
|
|
|
|
if (DataLength < ConEntry->Connection.Size)
|
|
{
|
|
return STATUS_BUFFER_TOO_SMALL;
|
|
}
|
|
|
|
RtlMoveMemory(Data, &ConEntry->Connection, ConEntry->Connection.Size);
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
// move to next item
|
|
Entry = Entry->Flink;
|
|
}while(Entry != &Descriptor->PhysicalConnectionList);
|
|
|
|
IoStatus->Information = 0;
|
|
return STATUS_NOT_FOUND;
|
|
}
|
|
|
|
NTSTATUS
|
|
NTAPI
|
|
PinPropertyHandler(
|
|
IN PIRP Irp,
|
|
IN PKSIDENTIFIER Request,
|
|
IN OUT PVOID Data)
|
|
{
|
|
PIO_STACK_LOCATION IoStack;
|
|
//PKSOBJECT_CREATE_ITEM CreateItem;
|
|
PSUBDEVICE_DESCRIPTOR Descriptor;
|
|
IIrpTarget * IrpTarget;
|
|
IPort *Port;
|
|
ISubdevice *SubDevice;
|
|
PDISPATCH_CONTEXT DispatchContext;
|
|
|
|
NTSTATUS Status = STATUS_UNSUCCESSFUL;
|
|
|
|
Descriptor = (PSUBDEVICE_DESCRIPTOR)KSPROPERTY_ITEM_IRP_STORAGE(Irp);
|
|
PC_ASSERT(Descriptor);
|
|
|
|
// get current irp stack
|
|
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
|
|
|
// get dispatch context
|
|
DispatchContext = (PDISPATCH_CONTEXT)IoStack->FileObject->FsContext;
|
|
|
|
// Get the IrpTarget
|
|
IrpTarget = DispatchContext->Target;
|
|
PC_ASSERT(IrpTarget);
|
|
|
|
// Get the parent
|
|
Status = IrpTarget->QueryInterface(IID_IPort, (PVOID*)&Port);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
DPRINT("Failed to obtain IPort interface from filter\n");
|
|
Irp->IoStatus.Information = 0;
|
|
Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
|
|
return STATUS_UNSUCCESSFUL;
|
|
}
|
|
|
|
// Get private ISubdevice interface
|
|
Status = Port->QueryInterface(IID_ISubdevice, (PVOID*)&SubDevice);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
DPRINT("Failed to obtain ISubdevice interface from port driver\n");
|
|
DbgBreakPoint();
|
|
while(TRUE);
|
|
}
|
|
|
|
// get current stack location
|
|
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
|
|
|
switch(Request->Id)
|
|
{
|
|
case KSPROPERTY_PIN_CTYPES:
|
|
case KSPROPERTY_PIN_DATAFLOW:
|
|
case KSPROPERTY_PIN_DATARANGES:
|
|
case KSPROPERTY_PIN_INTERFACES:
|
|
case KSPROPERTY_PIN_MEDIUMS:
|
|
case KSPROPERTY_PIN_COMMUNICATION:
|
|
case KSPROPERTY_PIN_CATEGORY:
|
|
case KSPROPERTY_PIN_NAME:
|
|
case KSPROPERTY_PIN_PROPOSEDATAFORMAT:
|
|
Status = KsPinPropertyHandler(Irp, Request, Data, Descriptor->Factory.PinDescriptorCount, Descriptor->Factory.KsPinDescriptor);
|
|
break;
|
|
case KSPROPERTY_PIN_GLOBALCINSTANCES:
|
|
Status = HandlePropertyInstances(&Irp->IoStatus, Request, Data, Descriptor, TRUE, SubDevice);
|
|
break;
|
|
case KSPROPERTY_PIN_CINSTANCES:
|
|
Status = HandlePropertyInstances(&Irp->IoStatus, Request, Data, Descriptor, FALSE, SubDevice);
|
|
break;
|
|
case KSPROPERTY_PIN_NECESSARYINSTANCES:
|
|
Status = HandleNecessaryPropertyInstances(&Irp->IoStatus, Request, Data, Descriptor, SubDevice);
|
|
break;
|
|
|
|
case KSPROPERTY_PIN_DATAINTERSECTION:
|
|
Status = HandleDataIntersection(&Irp->IoStatus, Request, Data, IoStack->Parameters.DeviceIoControl.OutputBufferLength, Descriptor, SubDevice);
|
|
break;
|
|
case KSPROPERTY_PIN_PHYSICALCONNECTION:
|
|
Status = HandlePhysicalConnection(&Irp->IoStatus, Request, IoStack->Parameters.DeviceIoControl.InputBufferLength, Data, IoStack->Parameters.DeviceIoControl.OutputBufferLength, Descriptor);
|
|
break;
|
|
case KSPROPERTY_PIN_CONSTRAINEDDATARANGES:
|
|
UNIMPLEMENTED;
|
|
Status = STATUS_NOT_IMPLEMENTED;
|
|
break;
|
|
default:
|
|
UNIMPLEMENTED;
|
|
Status = STATUS_UNSUCCESSFUL;
|
|
}
|
|
|
|
// Release reference
|
|
Port->Release();
|
|
|
|
// Release subdevice reference
|
|
SubDevice->Release();
|
|
|
|
return Status;
|
|
}
|
|
|
|
NTSTATUS
|
|
NTAPI
|
|
TopologyPropertyHandler(
|
|
IN PIRP Irp,
|
|
IN PKSIDENTIFIER Request,
|
|
IN OUT PVOID Data)
|
|
{
|
|
PSUBDEVICE_DESCRIPTOR Descriptor;
|
|
|
|
Descriptor = (PSUBDEVICE_DESCRIPTOR)KSPROPERTY_ITEM_IRP_STORAGE(Irp);
|
|
|
|
return KsTopologyPropertyHandler(Irp, Request, Data, Descriptor->Topology);
|
|
}
|