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