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