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