The 'UNIMPLEMENTED' macro call should be followed explicitely by a semicolon.
[reactos.git] / reactos / drivers / wdm / audio / backpln / portcls / port_wavert.cpp
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Kernel Streaming
4 * FILE: drivers/wdm/audio/backpln/portcls/port_wavert.cpp
5 * PURPOSE: WaveRT Port Driver
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 class CPortWaveRT : public IPortWaveRT,
18 public IPortEvents,
19 public ISubdevice
20 {
21 public:
22 STDMETHODIMP QueryInterface( REFIID InterfaceId, PVOID* Interface);
23
24 STDMETHODIMP_(ULONG) AddRef()
25 {
26 InterlockedIncrement(&m_Ref);
27 return m_Ref;
28 }
29 STDMETHODIMP_(ULONG) Release()
30 {
31 InterlockedDecrement(&m_Ref);
32
33 if (!m_Ref)
34 {
35 delete this;
36 return 0;
37 }
38 return m_Ref;
39 }
40 IMP_IPortWaveRT;
41 IMP_ISubdevice;
42 IMP_IPortEvents;
43 CPortWaveRT(IUnknown *OuterUnknown) {}
44 virtual ~CPortWaveRT() {}
45
46 protected:
47
48 BOOL m_bInitialized;
49 PDEVICE_OBJECT m_pDeviceObject;
50 PMINIPORTWAVERT m_pMiniport;
51 PRESOURCELIST m_pResourceList;
52 PPINCOUNT m_pPinCount;
53 PPOWERNOTIFY m_pPowerNotify;
54 PPCFILTER_DESCRIPTOR m_pDescriptor;
55 PSUBDEVICE_DESCRIPTOR m_SubDeviceDescriptor;
56 IPortFilterWaveRT * m_Filter;
57
58 friend PMINIPORTWAVERT GetWaveRTMiniport(IN IPortWaveRT* iface);
59 friend PDEVICE_OBJECT GetDeviceObjectFromPortWaveRT(PPORTWAVERT iface);
60
61 LONG m_Ref;
62 };
63
64 static GUID InterfaceGuids[3] =
65 {
66 {
67 /// KS_CATEGORY_AUDIO
68 0x6994AD04, 0x93EF, 0x11D0, {0xA3, 0xCC, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}
69 },
70 {
71 /// KSCATEGORY_RENDER
72 0x65E8773EL, 0x8F56, 0x11D0, {0xA3, 0xB9, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}
73 },
74 {
75 /// KSCATEGORY_CAPTURE
76 0x65E8773DL, 0x8F56, 0x11D0, {0xA3, 0xB9, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}
77 }
78 };
79
80 DEFINE_KSPROPERTY_TOPOLOGYSET(PortFilterWaveRTTopologySet, TopologyPropertyHandler);
81 DEFINE_KSPROPERTY_PINPROPOSEDATAFORMAT(PortFilterWaveRTPinSet, PinPropertyHandler, PinPropertyHandler, PinPropertyHandler);
82
83 KSPROPERTY_SET WaveRTPropertySet[] =
84 {
85 {
86 &KSPROPSETID_Topology,
87 sizeof(PortFilterWaveRTTopologySet) / sizeof(KSPROPERTY_ITEM),
88 (const KSPROPERTY_ITEM*)&PortFilterWaveRTTopologySet,
89 0,
90 NULL
91 },
92 {
93 &KSPROPSETID_Pin,
94 sizeof(PortFilterWaveRTPinSet) / sizeof(KSPROPERTY_ITEM),
95 (const KSPROPERTY_ITEM*)&PortFilterWaveRTPinSet,
96 0,
97 NULL
98 }
99 };
100
101 //KSEVENTSETID_LoopedStreaming, Type = KSEVENT_LOOPEDSTREAMING_POSITION
102 //KSEVENTSETID_Connection, Type = KSEVENT_CONNECTION_ENDOFSTREAM,
103
104
105
106 //---------------------------------------------------------------
107 // IPortEvents
108 //
109
110 void
111 NTAPI
112 CPortWaveRT::AddEventToEventList(
113 IN PKSEVENT_ENTRY EventEntry)
114 {
115 UNIMPLEMENTED;
116 }
117
118
119 void
120 NTAPI
121 CPortWaveRT::GenerateEventList(
122 IN GUID* Set OPTIONAL,
123 IN ULONG EventId,
124 IN BOOL PinEvent,
125 IN ULONG PinId,
126 IN BOOL NodeEvent,
127 IN ULONG NodeId)
128 {
129 UNIMPLEMENTED;
130 }
131
132 //---------------------------------------------------------------
133 // IUnknown interface functions
134 //
135
136 NTSTATUS
137 NTAPI
138 CPortWaveRT::QueryInterface(
139 IN REFIID refiid,
140 OUT PVOID* Output)
141 {
142 UNICODE_STRING GuidString;
143
144 if (IsEqualGUIDAligned(refiid, IID_IPortWaveRT) ||
145 IsEqualGUIDAligned(refiid, IID_IUnknown))
146 {
147 *Output = PVOID(PPORTWAVERT(this));
148 PUNKNOWN(*Output)->AddRef();
149 return STATUS_SUCCESS;
150 }
151 else if (IsEqualGUIDAligned(refiid, IID_IPortEvents))
152 {
153 *Output = PVOID(PPORTEVENTS(this));
154 PUNKNOWN(*Output)->AddRef();
155 return STATUS_SUCCESS;
156 }
157 else if (IsEqualGUIDAligned(refiid, IID_ISubdevice))
158 {
159 *Output = PVOID(PSUBDEVICE(this));
160 PUNKNOWN(*Output)->AddRef();
161 return STATUS_SUCCESS;
162 }
163 else if (IsEqualGUIDAligned(refiid, IID_IPortClsVersion))
164 {
165 return NewPortClsVersion((PPORTCLSVERSION*)Output);
166 }
167 else if (IsEqualGUIDAligned(refiid, IID_IDrmPort) ||
168 IsEqualGUIDAligned(refiid, IID_IDrmPort2))
169 {
170 return NewIDrmPort((PDRMPORT2*)Output);
171 }
172 else if (IsEqualGUIDAligned(refiid, IID_IUnregisterSubdevice))
173 {
174 return NewIUnregisterSubdevice((PUNREGISTERSUBDEVICE*)Output);
175 }
176 else if (IsEqualGUIDAligned(refiid, IID_IUnregisterPhysicalConnection))
177 {
178 return NewIUnregisterPhysicalConnection((PUNREGISTERPHYSICALCONNECTION*)Output);
179 }
180
181 if (RtlStringFromGUID(refiid, &GuidString) == STATUS_SUCCESS)
182 {
183 DPRINT("IPortWaveRT_fnQueryInterface no interface!!! iface %S\n", GuidString.Buffer);
184 RtlFreeUnicodeString(&GuidString);
185 }
186
187 return STATUS_UNSUCCESSFUL;
188 }
189 //---------------------------------------------------------------
190 // IPort interface functions
191 //
192
193 NTSTATUS
194 NTAPI
195 CPortWaveRT::GetDeviceProperty(
196 IN DEVICE_REGISTRY_PROPERTY DeviceRegistryProperty,
197 IN ULONG BufferLength,
198 OUT PVOID PropertyBuffer,
199 OUT PULONG ReturnLength)
200 {
201 PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
202
203 if (!m_bInitialized)
204 {
205 DPRINT("IPortWaveRT_fnNewRegistryKey called w/o initialized\n");
206 return STATUS_UNSUCCESSFUL;
207 }
208
209 return IoGetDeviceProperty(m_pDeviceObject, DeviceRegistryProperty, BufferLength, PropertyBuffer, ReturnLength);
210 }
211
212 NTSTATUS
213 NTAPI
214 CPortWaveRT::Init(
215 IN PDEVICE_OBJECT DeviceObject,
216 IN PIRP Irp,
217 IN PUNKNOWN UnknownMiniport,
218 IN PUNKNOWN UnknownAdapter OPTIONAL,
219 IN PRESOURCELIST ResourceList)
220 {
221 IMiniportWaveRT * Miniport;
222 NTSTATUS Status;
223 PPINCOUNT PinCount;
224 PPOWERNOTIFY PowerNotify;
225
226 DPRINT("IPortWaveRT_Init entered %p\n", this);
227 PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
228
229 if (m_bInitialized)
230 {
231 DPRINT("IPortWaveRT_Init called again\n");
232 return STATUS_SUCCESS;
233 }
234
235 Status = UnknownMiniport->QueryInterface(IID_IMiniportWaveRT, (PVOID*)&Miniport);
236 if (!NT_SUCCESS(Status))
237 {
238 DPRINT("IPortWaveRT_Init called with invalid IMiniport adapter\n");
239 return STATUS_INVALID_PARAMETER;
240 }
241
242 // Initialize port object
243 m_pMiniport = Miniport;
244 m_pDeviceObject = DeviceObject;
245 m_bInitialized = TRUE;
246 m_pResourceList = ResourceList;
247
248 // increment reference on miniport adapter
249 Miniport->AddRef();
250
251 Status = Miniport->Init(UnknownAdapter, ResourceList, this);
252 if (!NT_SUCCESS(Status))
253 {
254 DPRINT("IMiniportWaveRT_Init failed with %x\n", Status);
255 Miniport->Release();
256 m_bInitialized = FALSE;
257 return Status;
258 }
259
260
261 // get the miniport device descriptor
262 Status = Miniport->GetDescription(&m_pDescriptor);
263 if (!NT_SUCCESS(Status))
264 {
265 DPRINT("failed to get description\n");
266 Miniport->Release();
267 m_bInitialized = FALSE;
268 return Status;
269 }
270
271 // create the subdevice descriptor
272 Status = PcCreateSubdeviceDescriptor(&m_SubDeviceDescriptor,
273 3,
274 InterfaceGuids,
275 0,
276 NULL,
277 2,
278 WaveRTPropertySet,
279 0,
280 0,
281 0,
282 NULL,
283 0,
284 NULL,
285 m_pDescriptor);
286
287 if (!NT_SUCCESS(Status))
288 {
289 DPRINT("PcCreateSubdeviceDescriptor failed with %x\n", Status);
290 Miniport->Release();
291 m_bInitialized = FALSE;
292 return Status;
293 }
294
295 // check if it supports IPinCount interface
296 Status = UnknownMiniport->QueryInterface(IID_IPinCount, (PVOID*)&PinCount);
297 if (NT_SUCCESS(Status))
298 {
299 // store IPinCount interface
300 m_pPinCount = PinCount;
301 }
302
303 // does the Miniport adapter support IPowerNotify interface*/
304 Status = UnknownMiniport->QueryInterface(IID_IPowerNotify, (PVOID*)&PowerNotify);
305 if (NT_SUCCESS(Status))
306 {
307 // store reference
308 m_pPowerNotify = PowerNotify;
309 }
310
311 // increment reference on resource list
312 ResourceList->AddRef();
313
314
315 DPRINT("IPortWaveRT successfully initialized\n");
316 return STATUS_SUCCESS;
317 }
318
319
320 NTSTATUS
321 NTAPI
322 CPortWaveRT::NewRegistryKey(
323 OUT PREGISTRYKEY *OutRegistryKey,
324 IN PUNKNOWN OuterUnknown OPTIONAL,
325 IN ULONG RegistryKeyType,
326 IN ACCESS_MASK DesiredAccess,
327 IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
328 IN ULONG CreateOptions OPTIONAL,
329 OUT PULONG Disposition OPTIONAL)
330 {
331 PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
332
333 if (!m_bInitialized)
334 {
335 DPRINT("IPortWaveRT_fnNewRegistryKey called w/o initialized\n");
336 return STATUS_UNSUCCESSFUL;
337 }
338 return PcNewRegistryKey(OutRegistryKey, OuterUnknown, RegistryKeyType, DesiredAccess, m_pDeviceObject, (ISubdevice*)this, ObjectAttributes, CreateOptions, Disposition);
339 }
340 //---------------------------------------------------------------
341 // ISubdevice interface
342 //
343
344 NTSTATUS
345 NTAPI
346 CPortWaveRT::NewIrpTarget(
347 OUT struct IIrpTarget **OutTarget,
348 IN PCWSTR Name,
349 IN PUNKNOWN Unknown,
350 IN POOL_TYPE PoolType,
351 IN PDEVICE_OBJECT DeviceObject,
352 IN PIRP Irp,
353 IN KSOBJECT_CREATE *CreateObject)
354 {
355 NTSTATUS Status;
356 IPortFilterWaveRT * Filter;
357
358 DPRINT("ISubDevice_NewIrpTarget this %p\n", this);
359
360 if (m_Filter)
361 {
362 *OutTarget = (IIrpTarget*)m_Filter;
363 return STATUS_SUCCESS;
364 }
365
366
367 Status = NewPortFilterWaveRT(&Filter);
368 if (!NT_SUCCESS(Status))
369 {
370 return Status;
371 }
372
373 Status = Filter->Init(this);
374 if (!NT_SUCCESS(Status))
375 {
376 Filter->Release();
377 return Status;
378 }
379
380 *OutTarget = (IIrpTarget*)Filter;
381 m_Filter = Filter;
382 return Status;
383 }
384
385 NTSTATUS
386 NTAPI
387 CPortWaveRT::ReleaseChildren()
388 {
389 UNIMPLEMENTED;
390 return STATUS_UNSUCCESSFUL;
391 }
392
393 NTSTATUS
394 NTAPI
395 CPortWaveRT::GetDescriptor(
396 IN SUBDEVICE_DESCRIPTOR ** Descriptor)
397 {
398 PC_ASSERT(m_SubDeviceDescriptor != NULL);
399
400 *Descriptor = m_SubDeviceDescriptor;
401
402 DPRINT("ISubDevice_GetDescriptor this %p desc %p\n", this, m_SubDeviceDescriptor);
403 return STATUS_SUCCESS;
404 }
405
406 NTSTATUS
407 NTAPI
408 CPortWaveRT::DataRangeIntersection(
409 IN ULONG PinId,
410 IN PKSDATARANGE DataRange,
411 IN PKSDATARANGE MatchingDataRange,
412 IN ULONG OutputBufferLength,
413 OUT PVOID ResultantFormat OPTIONAL,
414 OUT PULONG ResultantFormatLength)
415 {
416 DPRINT("ISubDevice_DataRangeIntersection this %p\n", this);
417
418 if (m_pMiniport)
419 {
420 return m_pMiniport->DataRangeIntersection (PinId, DataRange, MatchingDataRange, OutputBufferLength, ResultantFormat, ResultantFormatLength);
421 }
422
423 return STATUS_UNSUCCESSFUL;
424 }
425
426 NTSTATUS
427 NTAPI
428 CPortWaveRT::PowerChangeNotify(
429 IN POWER_STATE PowerState)
430 {
431 if (m_pPowerNotify)
432 {
433 m_pPowerNotify->PowerChangeNotify(PowerState);
434 }
435
436 return STATUS_SUCCESS;
437 }
438
439 NTSTATUS
440 NTAPI
441 CPortWaveRT::PinCount(
442 IN ULONG PinId,
443 IN OUT PULONG FilterNecessary,
444 IN OUT PULONG FilterCurrent,
445 IN OUT PULONG FilterPossible,
446 IN OUT PULONG GlobalCurrent,
447 IN OUT PULONG GlobalPossible)
448 {
449 if (m_pPinCount)
450 {
451 m_pPinCount->PinCount(PinId, FilterNecessary, FilterCurrent, FilterPossible, GlobalCurrent, GlobalPossible);
452 return STATUS_SUCCESS;
453 }
454
455 // FIXME
456 // scan filter descriptor
457
458 return STATUS_UNSUCCESSFUL;
459 }
460
461 ///--------------------------------------------------------------
462 PMINIPORTWAVERT
463 GetWaveRTMiniport(
464 IN IPortWaveRT* iface)
465 {
466 CPortWaveRT * This = (CPortWaveRT *)iface;
467 return This->m_pMiniport;
468 }
469
470 PDEVICE_OBJECT
471 GetDeviceObjectFromPortWaveRT(
472 PPORTWAVERT iface)
473 {
474 CPortWaveRT * This = (CPortWaveRT *)iface;
475 return This->m_pDeviceObject;
476 }
477
478 //---------------------------------------------------------------
479 // IPortWaveRT constructor
480 //
481
482
483 NTSTATUS
484 NewPortWaveRT(
485 OUT PPORT* OutPort)
486 {
487 CPortWaveRT * Port;
488 NTSTATUS Status;
489
490 Port = new(NonPagedPool, TAG_PORTCLASS) CPortWaveRT(NULL);
491 if (!Port)
492 return STATUS_INSUFFICIENT_RESOURCES;
493
494 Status = Port->QueryInterface(IID_IPort, (PVOID*)OutPort);
495
496 if (!NT_SUCCESS(Status))
497 {
498 delete Port;
499 }
500
501 DPRINT("NewPortWaveRT %p Status %u\n", Port, Status);
502 return Status;
503 }
504