/* * 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 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); }