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