1 /* 2 * COPYRIGHT: See COPYING in the top level directory 3 * PROJECT: ReactOS Kernel Streaming 4 * FILE: drivers/wdm/audio/backpln/portcls/propertyhandler.cpp 5 * PURPOSE: Pin property handler 6 * PROGRAMMER: Johannes Anderwald 7 */ 8 9 #include "private.hpp" 10 11 #ifndef YDEBUG 12 #define NDEBUG 13 #endif 14 15 #include <debug.h> 16 17 NTSTATUS 18 HandlePropertyInstances( 19 IN PIO_STATUS_BLOCK IoStatus, 20 IN PKSIDENTIFIER Request, 21 IN OUT PVOID Data, 22 IN PSUBDEVICE_DESCRIPTOR Descriptor, 23 IN BOOL Global, 24 IN ISubdevice *SubDevice) 25 { 26 KSPIN_CINSTANCES * Instances; 27 KSP_PIN * Pin = (KSP_PIN*)Request; 28 ULONG FilterNecessary, FilterCurrent, FilterPossible, GlobalCurrent, GlobalPossible; 29 NTSTATUS Status; 30 31 if (Pin->PinId >= Descriptor->Factory.PinDescriptorCount) 32 { 33 IoStatus->Information = 0; 34 IoStatus->Status = STATUS_INVALID_PARAMETER; 35 return STATUS_INVALID_PARAMETER; 36 } 37 38 Instances = (KSPIN_CINSTANCES*)Data; 39 40 // check if the miniport supports the IPinCount interface 41 Status = SubDevice->PinCount(Pin->PinId, &FilterNecessary, &FilterCurrent, &FilterPossible, &GlobalCurrent, &GlobalPossible); 42 43 if (NT_SUCCESS(Status)) 44 { 45 if (Global) 46 { 47 Instances->PossibleCount = GlobalPossible; 48 Instances->CurrentCount = GlobalCurrent; 49 } 50 else 51 { 52 Instances->PossibleCount = FilterPossible; 53 Instances->CurrentCount = FilterCurrent; 54 } 55 } 56 else 57 { 58 if (Global) 59 Instances->PossibleCount = Descriptor->Factory.Instances[Pin->PinId].MaxGlobalInstanceCount; 60 else 61 Instances->PossibleCount = Descriptor->Factory.Instances[Pin->PinId].MaxFilterInstanceCount; 62 63 Instances->CurrentCount = Descriptor->Factory.Instances[Pin->PinId].CurrentPinInstanceCount; 64 } 65 66 IoStatus->Information = sizeof(KSPIN_CINSTANCES); 67 IoStatus->Status = STATUS_SUCCESS; 68 return STATUS_SUCCESS; 69 } 70 71 NTSTATUS 72 HandleNecessaryPropertyInstances( 73 IN PIO_STATUS_BLOCK IoStatus, 74 IN PKSIDENTIFIER Request, 75 IN OUT PVOID Data, 76 IN PSUBDEVICE_DESCRIPTOR Descriptor, 77 IN ISubdevice *SubDevice) 78 { 79 PULONG Result; 80 KSP_PIN * Pin = (KSP_PIN*)Request; 81 ULONG FilterNecessary, FilterCurrent, FilterPossible, GlobalCurrent, GlobalPossible; 82 NTSTATUS Status; 83 84 if (Pin->PinId >= Descriptor->Factory.PinDescriptorCount) 85 { 86 IoStatus->Information = 0; 87 IoStatus->Status = STATUS_INVALID_PARAMETER; 88 return STATUS_INVALID_PARAMETER; 89 } 90 91 Result = (PULONG)Data; 92 93 94 // check if the miniport supports the IPinCount interface 95 Status = SubDevice->PinCount(Pin->PinId, &FilterNecessary, &FilterCurrent, &FilterPossible, &GlobalCurrent, &GlobalPossible); 96 97 if (NT_SUCCESS(Status)) 98 { 99 *Result = FilterNecessary; 100 } 101 else 102 { 103 *Result = Descriptor->Factory.Instances[Pin->PinId].MinFilterInstanceCount; 104 } 105 106 IoStatus->Information = sizeof(ULONG); 107 IoStatus->Status = STATUS_SUCCESS; 108 return STATUS_SUCCESS; 109 } 110 111 NTSTATUS 112 HandleDataIntersection( 113 IN PIO_STATUS_BLOCK IoStatus, 114 IN PKSIDENTIFIER Request, 115 IN OUT PVOID Data, 116 IN ULONG DataLength, 117 IN PSUBDEVICE_DESCRIPTOR Descriptor, 118 IN ISubdevice *SubDevice) 119 { 120 KSP_PIN * Pin = (KSP_PIN*)Request; 121 PKSMULTIPLE_ITEM MultipleItem; 122 PKSDATARANGE DataRange; 123 NTSTATUS Status = STATUS_NO_MATCH; 124 ULONG Index, Length; 125 126 // Access parameters 127 MultipleItem = (PKSMULTIPLE_ITEM)(Pin + 1); 128 DataRange = (PKSDATARANGE)(MultipleItem + 1); 129 130 for(Index = 0; Index < MultipleItem->Count; Index++) 131 { 132 // Call miniport's proprietary handler 133 PC_ASSERT(Descriptor->Factory.KsPinDescriptor[Pin->PinId].DataRangesCount); 134 PC_ASSERT(Descriptor->Factory.KsPinDescriptor[Pin->PinId].DataRanges[0]); 135 Status = SubDevice->DataRangeIntersection(Pin->PinId, DataRange, (PKSDATARANGE)Descriptor->Factory.KsPinDescriptor[Pin->PinId].DataRanges[0], 136 DataLength, Data, &Length); 137 138 if (Status == STATUS_SUCCESS) 139 { 140 IoStatus->Information = Length; 141 break; 142 } 143 DataRange = (PKSDATARANGE)((PUCHAR)DataRange + DataRange->FormatSize); 144 } 145 146 IoStatus->Status = Status; 147 return Status; 148 } 149 150 NTSTATUS 151 HandlePhysicalConnection( 152 IN PIO_STATUS_BLOCK IoStatus, 153 IN PKSIDENTIFIER Request, 154 IN ULONG RequestLength, 155 IN OUT PVOID Data, 156 IN ULONG DataLength, 157 IN PSUBDEVICE_DESCRIPTOR Descriptor) 158 { 159 PKSP_PIN Pin; 160 PLIST_ENTRY Entry; 161 //PKSPIN_PHYSICALCONNECTION Connection; 162 PPHYSICAL_CONNECTION_ENTRY ConEntry; 163 164 // get pin 165 Pin = (PKSP_PIN)Request; 166 167 if (RequestLength < sizeof(KSP_PIN)) 168 { 169 // input buffer must be at least sizeof KSP_PIN 170 DPRINT("input length too small\n"); 171 return STATUS_INVALID_PARAMETER; 172 } 173 174 if (IsListEmpty(&Descriptor->PhysicalConnectionList)) 175 { 176 DPRINT("no connection\n"); 177 return STATUS_NOT_FOUND; 178 } 179 180 // get first item 181 Entry = Descriptor->PhysicalConnectionList.Flink; 182 183 do 184 { 185 ConEntry = (PPHYSICAL_CONNECTION_ENTRY)CONTAINING_RECORD(Entry, PHYSICAL_CONNECTION_ENTRY, Entry); 186 187 if (ConEntry->FromPin == Pin->PinId) 188 { 189 //Connection = (PKSPIN_PHYSICALCONNECTION)Data; 190 DPRINT("FoundEntry %S Size %u\n", ConEntry->Connection.SymbolicLinkName, ConEntry->Connection.Size); 191 IoStatus->Information = ConEntry->Connection.Size; 192 193 if (!DataLength) 194 { 195 IoStatus->Information = ConEntry->Connection.Size; 196 return STATUS_MORE_ENTRIES; 197 } 198 199 if (DataLength < ConEntry->Connection.Size) 200 { 201 return STATUS_BUFFER_TOO_SMALL; 202 } 203 204 RtlMoveMemory(Data, &ConEntry->Connection, ConEntry->Connection.Size); 205 return STATUS_SUCCESS; 206 } 207 208 // move to next item 209 Entry = Entry->Flink; 210 }while(Entry != &Descriptor->PhysicalConnectionList); 211 212 IoStatus->Information = 0; 213 return STATUS_NOT_FOUND; 214 } 215 216 NTSTATUS 217 NTAPI 218 PinPropertyHandler( 219 IN PIRP Irp, 220 IN PKSIDENTIFIER Request, 221 IN OUT PVOID Data) 222 { 223 PIO_STACK_LOCATION IoStack; 224 //PKSOBJECT_CREATE_ITEM CreateItem; 225 PSUBDEVICE_DESCRIPTOR Descriptor; 226 IIrpTarget * IrpTarget; 227 IPort *Port; 228 ISubdevice *SubDevice; 229 PDISPATCH_CONTEXT DispatchContext; 230 231 NTSTATUS Status = STATUS_UNSUCCESSFUL; 232 233 Descriptor = (PSUBDEVICE_DESCRIPTOR)KSPROPERTY_ITEM_IRP_STORAGE(Irp); 234 PC_ASSERT(Descriptor); 235 236 // get current irp stack 237 IoStack = IoGetCurrentIrpStackLocation(Irp); 238 239 // get dispatch context 240 DispatchContext = (PDISPATCH_CONTEXT)IoStack->FileObject->FsContext; 241 242 // Get the IrpTarget 243 IrpTarget = DispatchContext->Target; 244 PC_ASSERT(IrpTarget); 245 246 // Get the parent 247 Status = IrpTarget->QueryInterface(IID_IPort, (PVOID*)&Port); 248 if (!NT_SUCCESS(Status)) 249 { 250 DPRINT("Failed to obtain IPort interface from filter\n"); 251 Irp->IoStatus.Information = 0; 252 Irp->IoStatus.Status = STATUS_UNSUCCESSFUL; 253 return STATUS_UNSUCCESSFUL; 254 } 255 256 // Get private ISubdevice interface 257 Status = Port->QueryInterface(IID_ISubdevice, (PVOID*)&SubDevice); 258 if (!NT_SUCCESS(Status)) 259 { 260 DPRINT("Failed to obtain ISubdevice interface from port driver\n"); 261 DbgBreakPoint(); 262 while(TRUE); 263 } 264 265 // get current stack location 266 IoStack = IoGetCurrentIrpStackLocation(Irp); 267 268 switch(Request->Id) 269 { 270 case KSPROPERTY_PIN_CTYPES: 271 case KSPROPERTY_PIN_DATAFLOW: 272 case KSPROPERTY_PIN_DATARANGES: 273 case KSPROPERTY_PIN_INTERFACES: 274 case KSPROPERTY_PIN_MEDIUMS: 275 case KSPROPERTY_PIN_COMMUNICATION: 276 case KSPROPERTY_PIN_CATEGORY: 277 case KSPROPERTY_PIN_NAME: 278 case KSPROPERTY_PIN_PROPOSEDATAFORMAT: 279 Status = KsPinPropertyHandler(Irp, Request, Data, Descriptor->Factory.PinDescriptorCount, Descriptor->Factory.KsPinDescriptor); 280 break; 281 case KSPROPERTY_PIN_GLOBALCINSTANCES: 282 Status = HandlePropertyInstances(&Irp->IoStatus, Request, Data, Descriptor, TRUE, SubDevice); 283 break; 284 case KSPROPERTY_PIN_CINSTANCES: 285 Status = HandlePropertyInstances(&Irp->IoStatus, Request, Data, Descriptor, FALSE, SubDevice); 286 break; 287 case KSPROPERTY_PIN_NECESSARYINSTANCES: 288 Status = HandleNecessaryPropertyInstances(&Irp->IoStatus, Request, Data, Descriptor, SubDevice); 289 break; 290 291 case KSPROPERTY_PIN_DATAINTERSECTION: 292 Status = HandleDataIntersection(&Irp->IoStatus, Request, Data, IoStack->Parameters.DeviceIoControl.OutputBufferLength, Descriptor, SubDevice); 293 break; 294 case KSPROPERTY_PIN_PHYSICALCONNECTION: 295 Status = HandlePhysicalConnection(&Irp->IoStatus, Request, IoStack->Parameters.DeviceIoControl.InputBufferLength, Data, IoStack->Parameters.DeviceIoControl.OutputBufferLength, Descriptor); 296 break; 297 case KSPROPERTY_PIN_CONSTRAINEDDATARANGES: 298 UNIMPLEMENTED; 299 Status = STATUS_NOT_IMPLEMENTED; 300 break; 301 default: 302 UNIMPLEMENTED; 303 Status = STATUS_UNSUCCESSFUL; 304 } 305 306 // Release reference 307 Port->Release(); 308 309 // Release subdevice reference 310 SubDevice->Release(); 311 312 return Status; 313 } 314 315 NTSTATUS 316 NTAPI 317 TopologyPropertyHandler( 318 IN PIRP Irp, 319 IN PKSIDENTIFIER Request, 320 IN OUT PVOID Data) 321 { 322 PSUBDEVICE_DESCRIPTOR Descriptor; 323 324 Descriptor = (PSUBDEVICE_DESCRIPTOR)KSPROPERTY_ITEM_IRP_STORAGE(Irp); 325 326 return KsTopologyPropertyHandler(Irp, Request, Data, Descriptor->Topology); 327 } 328