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 
505