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