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