e32a2ad55a718a1f467a0cb0ea3d32acbe185bb7
[reactos.git] / reactos / drivers / wdm / audio / backpln / portcls / port_topology.c
1 #include "private.h"
2
3 typedef struct
4 {
5 IPortTopologyVtbl *lpVtbl;
6 ISubdeviceVtbl *lpVtblSubDevice;
7
8 LONG ref;
9 BOOL bInitialized;
10
11 PMINIPORTTOPOLOGY pMiniport;
12 PDEVICE_OBJECT pDeviceObject;
13 PPINCOUNT pPinCount;
14 PPOWERNOTIFY pPowerNotify;
15
16 }IPortTopologyImpl;
17
18
19 #if 0
20 static
21 KSPROPERTY_SET PinPropertySet =
22 {
23 &KSPROPSETID_Pin,
24 0,
25 NULL,
26 0,
27 NULL
28 };
29
30 static
31 KSPROPERTY_SET TopologyPropertySet =
32 {
33 &KSPROPSETID_Topology,
34 4,
35 NULL,
36 0,
37 NULL
38 };
39 #endif
40
41
42 //---------------------------------------------------------------
43 // IUnknown interface functions
44 //
45
46 NTSTATUS
47 NTAPI
48 IPortTopology_fnQueryInterface(
49 IPortTopology* iface,
50 IN REFIID refiid,
51 OUT PVOID* Output)
52 {
53 WCHAR Buffer[100];
54 IPortTopologyImpl * This = (IPortTopologyImpl*)iface;
55
56 DPRINT1("IPortTopology_fnQueryInterface\n");
57
58 if (IsEqualGUIDAligned(refiid, &IID_IPortTopology) ||
59 IsEqualGUIDAligned(refiid, &IID_IUnknown))
60 {
61 *Output = &This->lpVtbl;
62 InterlockedIncrement(&This->ref);
63 return STATUS_SUCCESS;
64 }
65 else if (IsEqualGUIDAligned(refiid, &IID_ISubdevice))
66 {
67 *Output = &This->lpVtblSubDevice;
68 InterlockedIncrement(&This->ref);
69 return STATUS_SUCCESS;
70 }
71 else if (IsEqualGUIDAligned(refiid, &IID_IPortClsVersion))
72 {
73 return NewPortClsVersion((PPORTCLSVERSION*)Output);
74 }
75 StringFromCLSID(refiid, Buffer);
76 DPRINT1("IPortTopology_fnQueryInterface no iface %S\n", Buffer);
77 StringFromCLSID(&IID_IUnknown, Buffer);
78 DPRINT1("IPortTopology_fnQueryInterface IUnknown %S\n", Buffer);
79
80 return STATUS_UNSUCCESSFUL;
81 }
82
83 ULONG
84 NTAPI
85 IPortTopology_fnAddRef(
86 IPortTopology* iface)
87 {
88 IPortTopologyImpl * This = (IPortTopologyImpl*)iface;
89
90 return InterlockedIncrement(&This->ref);
91 }
92
93 ULONG
94 NTAPI
95 IPortTopology_fnRelease(
96 IPortTopology* iface)
97 {
98 IPortTopologyImpl * This = (IPortTopologyImpl*)iface;
99
100 InterlockedDecrement(&This->ref);
101
102 if (This->ref == 0)
103 {
104 FreeItem(This, TAG_PORTCLASS);
105 return 0;
106 }
107 /* Return new reference count */
108 return This->ref;
109 }
110
111
112 //---------------------------------------------------------------
113 // IPort interface functions
114 //
115
116 NTSTATUS
117 NTAPI
118 IPortTopology_fnGetDeviceProperty(
119 IN IPortTopology * iface,
120 IN DEVICE_REGISTRY_PROPERTY DeviceRegistryProperty,
121 IN ULONG BufferLength,
122 OUT PVOID PropertyBuffer,
123 OUT PULONG ReturnLength)
124 {
125 IPortTopologyImpl * This = (IPortTopologyImpl*)iface;
126
127 if (!This->bInitialized)
128 {
129 DPRINT("IPortTopology_fnNewRegistryKey called w/o initiazed\n");
130 return STATUS_UNSUCCESSFUL;
131 }
132
133 return IoGetDeviceProperty(This->pDeviceObject, DeviceRegistryProperty, BufferLength, PropertyBuffer, ReturnLength);
134 }
135
136 NTSTATUS
137 NTAPI
138 IPortTopology_fnInit(
139 IN IPortTopology * iface,
140 IN PDEVICE_OBJECT DeviceObject,
141 IN PIRP Irp,
142 IN PUNKNOWN UnknownMiniport,
143 IN PUNKNOWN UnknownAdapter OPTIONAL,
144 IN PRESOURCELIST ResourceList)
145 {
146 IMiniportTopology * Miniport;
147 NTSTATUS Status;
148 IPortTopologyImpl * This = (IPortTopologyImpl*)iface;
149
150 DPRINT1("IPortTopology_fnInit entered This %p DeviceObject %p Irp %p UnknownMiniport %p UnknownAdapter %p ResourceList %p\n",
151 This, DeviceObject, Irp, UnknownMiniport, UnknownAdapter, ResourceList);
152
153 if (This->bInitialized)
154 {
155 DPRINT1("IPortTopology_Init called again\n");
156 return STATUS_SUCCESS;
157 }
158
159 Status = UnknownMiniport->lpVtbl->QueryInterface(UnknownMiniport, &IID_IMiniportTopology, (PVOID*)&Miniport);
160 if (!NT_SUCCESS(Status))
161 {
162 DPRINT1("IPortTopology_Init called with invalid IMiniport adapter\n");
163 return STATUS_INVALID_PARAMETER;
164 }
165
166 /* Initialize port object */
167 This->pMiniport = Miniport;
168 This->pDeviceObject = DeviceObject;
169 This->bInitialized = TRUE;
170
171 Status = Miniport->lpVtbl->Init(Miniport, UnknownAdapter, ResourceList, iface);
172 if (!NT_SUCCESS(Status))
173 {
174 DPRINT1("IPortTopology_Init failed with %x\n", Status);
175 This->bInitialized = FALSE;
176 return Status;
177 }
178
179 /* increment reference on miniport adapter */
180 Miniport->lpVtbl->AddRef(Miniport);
181
182
183 DPRINT1("IPortTopology_fnInit success\n");
184 return STATUS_SUCCESS;
185 }
186
187
188 NTSTATUS
189 NTAPI
190 IPortTopology_fnNewRegistryKey(
191 IN IPortTopology * iface,
192 OUT PREGISTRYKEY *OutRegistryKey,
193 IN PUNKNOWN OuterUnknown OPTIONAL,
194 IN ULONG RegistryKeyType,
195 IN ACCESS_MASK DesiredAccess,
196 IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
197 IN ULONG CreateOptions OPTIONAL,
198 OUT PULONG Disposition OPTIONAL)
199 {
200 IPortTopologyImpl * This = (IPortTopologyImpl*)iface;
201
202 if (!This->bInitialized)
203 {
204 DPRINT("IPortTopology_fnNewRegistryKey called w/o initialized\n");
205 return STATUS_UNSUCCESSFUL;
206 }
207 return PcNewRegistryKey(OutRegistryKey,
208 OuterUnknown,
209 RegistryKeyType,
210 DesiredAccess,
211 This->pDeviceObject,
212 NULL,//FIXME
213 ObjectAttributes,
214 CreateOptions,
215 Disposition);
216 }
217
218 static IPortTopologyVtbl vt_IPortTopology =
219 {
220 /* IUnknown methods */
221 IPortTopology_fnQueryInterface,
222 IPortTopology_fnAddRef,
223 IPortTopology_fnRelease,
224 /* IPort methods */
225 IPortTopology_fnInit,
226 IPortTopology_fnGetDeviceProperty,
227 IPortTopology_fnNewRegistryKey
228 };
229
230 //---------------------------------------------------------------
231 // ISubdevice interface
232 //
233
234 static
235 NTSTATUS
236 NTAPI
237 ISubDevice_fnQueryInterface(
238 IN ISubdevice *iface,
239 IN REFIID InterfaceId,
240 IN PVOID* Interface)
241 {
242 IPortTopologyImpl * This = (IPortTopologyImpl*)CONTAINING_RECORD(iface, IPortTopologyImpl, lpVtblSubDevice);
243
244 return IPortTopology_fnQueryInterface((IPortTopology*)This, InterfaceId, Interface);
245 }
246
247 static
248 ULONG
249 NTAPI
250 ISubDevice_fnAddRef(
251 IN ISubdevice *iface)
252 {
253 IPortTopologyImpl * This = (IPortTopologyImpl*)CONTAINING_RECORD(iface, IPortTopologyImpl, lpVtblSubDevice);
254
255 return IPortTopology_fnAddRef((IPortTopology*)This);
256 }
257
258 static
259 ULONG
260 NTAPI
261 ISubDevice_fnRelease(
262 IN ISubdevice *iface)
263 {
264 IPortTopologyImpl * This = (IPortTopologyImpl*)CONTAINING_RECORD(iface, IPortTopologyImpl, lpVtblSubDevice);
265
266 return IPortTopology_fnRelease((IPortTopology*)This);
267 }
268
269 static
270 NTSTATUS
271 NTAPI
272 ISubDevice_fnNewIrpTarget(
273 IN ISubdevice *iface,
274 OUT struct IIrpTarget **OutTarget,
275 IN WCHAR * Name,
276 IN PUNKNOWN Unknown,
277 IN POOL_TYPE PoolType,
278 IN PDEVICE_OBJECT * DeviceObject,
279 IN PIRP Irp,
280 IN KSOBJECT_CREATE *CreateObject)
281 {
282 IPortTopologyImpl * This = (IPortTopologyImpl*)CONTAINING_RECORD(iface, IPortTopologyImpl, lpVtblSubDevice);
283
284 DPRINT1("ISubDevice_NewIrpTarget this %p\n", This);
285 return STATUS_UNSUCCESSFUL;
286 }
287
288 static
289 NTSTATUS
290 NTAPI
291 ISubDevice_fnReleaseChildren(
292 IN ISubdevice *iface)
293 {
294 IPortTopologyImpl * This = (IPortTopologyImpl*)CONTAINING_RECORD(iface, IPortTopologyImpl, lpVtblSubDevice);
295
296 DPRINT1("ISubDevice_ReleaseChildren this %p\n", This);
297 return STATUS_UNSUCCESSFUL;
298 }
299
300 static
301 NTSTATUS
302 NTAPI
303 ISubDevice_fnGetDescriptor(
304 IN ISubdevice *iface,
305 IN struct SUBDEVICE_DESCRIPTOR ** Descriptor)
306 {
307 IPortTopologyImpl * This = (IPortTopologyImpl*)CONTAINING_RECORD(iface, IPortTopologyImpl, lpVtblSubDevice);
308
309 DPRINT1("ISubDevice_GetDescriptor this %p\n", This);
310 return STATUS_UNSUCCESSFUL;
311 }
312
313 static
314 NTSTATUS
315 NTAPI
316 ISubDevice_fnDataRangeIntersection(
317 IN ISubdevice *iface,
318 IN ULONG PinId,
319 IN PKSDATARANGE DataRange,
320 IN PKSDATARANGE MatchingDataRange,
321 IN ULONG OutputBufferLength,
322 OUT PVOID ResultantFormat OPTIONAL,
323 OUT PULONG ResultantFormatLength)
324 {
325 IPortTopologyImpl * This = (IPortTopologyImpl*)CONTAINING_RECORD(iface, IPortTopologyImpl, lpVtblSubDevice);
326
327 DPRINT("ISubDevice_DataRangeIntersection this %p\n", This);
328
329 if (This->pMiniport)
330 {
331 return This->pMiniport->lpVtbl->DataRangeIntersection (This->pMiniport, PinId, DataRange, MatchingDataRange, OutputBufferLength, ResultantFormat, ResultantFormatLength);
332 }
333
334 return STATUS_UNSUCCESSFUL;
335 }
336
337 static
338 NTSTATUS
339 NTAPI
340 ISubDevice_fnPowerChangeNotify(
341 IN ISubdevice *iface,
342 IN POWER_STATE PowerState)
343 {
344 IPortTopologyImpl * This = (IPortTopologyImpl*)CONTAINING_RECORD(iface, IPortTopologyImpl, lpVtblSubDevice);
345
346 if (This->pPowerNotify)
347 {
348 This->pPowerNotify->lpVtbl->PowerChangeNotify(This->pPowerNotify, PowerState);
349 }
350
351 return STATUS_SUCCESS;
352 }
353
354 static
355 NTSTATUS
356 NTAPI
357 ISubDevice_fnPinCount(
358 IN ISubdevice *iface,
359 IN ULONG PinId,
360 IN OUT PULONG FilterNecessary,
361 IN OUT PULONG FilterCurrent,
362 IN OUT PULONG FilterPossible,
363 IN OUT PULONG GlobalCurrent,
364 IN OUT PULONG GlobalPossible)
365 {
366 IPortTopologyImpl * This = (IPortTopologyImpl*)CONTAINING_RECORD(iface, IPortTopologyImpl, lpVtblSubDevice);
367
368 if (This->pPinCount)
369 {
370 This->pPinCount->lpVtbl->PinCount(This->pPinCount, PinId, FilterNecessary, FilterCurrent, FilterPossible, GlobalCurrent, GlobalPossible);
371 return STATUS_SUCCESS;
372 }
373
374 /* FIXME
375 * scan filter descriptor
376 */
377 return STATUS_UNSUCCESSFUL;
378 }
379
380 static ISubdeviceVtbl vt_ISubdeviceVtbl =
381 {
382 ISubDevice_fnQueryInterface,
383 ISubDevice_fnAddRef,
384 ISubDevice_fnRelease,
385 ISubDevice_fnNewIrpTarget,
386 ISubDevice_fnReleaseChildren,
387 ISubDevice_fnGetDescriptor,
388 ISubDevice_fnDataRangeIntersection,
389 ISubDevice_fnPowerChangeNotify,
390 ISubDevice_fnPinCount
391 };
392
393
394 NTSTATUS
395 NewPortTopology(
396 OUT PPORT* OutPort)
397 {
398 IPortTopologyImpl * This;
399
400 This = AllocateItem(NonPagedPool, sizeof(IPortTopologyImpl), TAG_PORTCLASS);
401 if (!This)
402 return STATUS_INSUFFICIENT_RESOURCES;
403
404 This->lpVtbl = &vt_IPortTopology;
405 This->lpVtblSubDevice = &vt_ISubdeviceVtbl;
406 This->ref = 1;
407 *OutPort = (PPORT)(&This->lpVtbl);
408 DPRINT1("NewPortTopology result %p\n", *OutPort);
409
410 return STATUS_SUCCESS;
411 }