3262b5f64b0e4c60c446932ca736a23810c8c771
[reactos.git] / drivers / wdm / audio / backpln / portcls / port_wavecyclic.cpp
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Kernel Streaming
4 * FILE: drivers/wdm/audio/backpln/portcls/port_wavecyclic.cpp
5 * PURPOSE: WaveCyclic Port Driver
6 * PROGRAMMER: Johannes Anderwald
7 */
8
9 #include "private.hpp"
10
11 GUID IID_IDmaChannelSlave;
12
13 class CPortWaveCyclic : public IPortWaveCyclic,
14 public IPortEvents,
15 public ISubdevice
16 {
17 public:
18 STDMETHODIMP QueryInterface( REFIID InterfaceId, PVOID* Interface);
19
20 STDMETHODIMP_(ULONG) AddRef()
21 {
22 InterlockedIncrement(&m_Ref);
23 return m_Ref;
24 }
25 STDMETHODIMP_(ULONG) Release()
26 {
27 InterlockedDecrement(&m_Ref);
28 if (!m_Ref)
29 {
30 //delete this;
31 return 0;
32 }
33 return m_Ref;
34 }
35 IMP_IPortWaveCyclic;
36 IMP_ISubdevice;
37 IMP_IPortEvents;
38 CPortWaveCyclic(IUnknown *OuterUnknown){}
39 virtual ~CPortWaveCyclic(){}
40
41 protected:
42 PDEVICE_OBJECT m_pDeviceObject;
43 PMINIPORTWAVECYCLIC m_pMiniport;
44 PPINCOUNT m_pPinCount;
45 PPOWERNOTIFY m_pPowerNotify;
46 PPCFILTER_DESCRIPTOR m_pDescriptor;
47 PSUBDEVICE_DESCRIPTOR m_SubDeviceDescriptor;
48 IPortFilterWaveCyclic * m_Filter;
49
50 LONG m_Ref;
51
52 friend PMINIPORTWAVECYCLIC GetWaveCyclicMiniport(IN IPortWaveCyclic* iface);
53 friend PDEVICE_OBJECT GetDeviceObject(PPORTWAVECYCLIC iface);
54 };
55
56 GUID KSPROPERTY_SETID_Topology = {0x720D4AC0L, 0x7533, 0x11D0, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}};
57
58 static GUID InterfaceGuids[4] =
59 {
60 {
61 //KS_CATEGORY_AUDIO
62 0x6994AD04, 0x93EF, 0x11D0, {0xA3, 0xCC, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}
63 },
64 {
65 /// KSCATEGORY_RENDER
66 0x65E8773EL, 0x8F56, 0x11D0, {0xA3, 0xB9, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}
67 },
68 {
69 /// KSCATEGORY_CAPTURE
70 0x65E8773DL, 0x8F56, 0x11D0, {0xA3, 0xB9, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}
71 },
72 {
73 ///KSCATEGORY_AUDIO_DEVICE
74 0xFBF6F530L, 0x07B9, 0x11D2, {0xA7, 0x1E, 0x00, 0x00, 0xF8, 0x00, 0x47, 0x88}
75 }
76
77 };
78
79 DEFINE_KSPROPERTY_TOPOLOGYSET(PortFilterWaveCyclicTopologySet, TopologyPropertyHandler);
80 DEFINE_KSPROPERTY_PINPROPOSEDATAFORMAT(PortFilterWaveCyclicPinSet, PinPropertyHandler, PinPropertyHandler, PinPropertyHandler);
81
82 KSPROPERTY_SET WaveCyclicPropertySet[] =
83 {
84 {
85 &KSPROPSETID_Topology,
86 sizeof(PortFilterWaveCyclicTopologySet) / sizeof(KSPROPERTY_ITEM),
87 (const KSPROPERTY_ITEM*)&PortFilterWaveCyclicTopologySet,
88 0,
89 NULL
90 },
91 {
92 &KSPROPSETID_Pin,
93 sizeof(PortFilterWaveCyclicPinSet) / sizeof(KSPROPERTY_ITEM),
94 (const KSPROPERTY_ITEM*)&PortFilterWaveCyclicPinSet,
95 0,
96 NULL
97 }
98 };
99
100 //KSEVENTSETID_LoopedStreaming, Type = KSEVENT_LOOPEDSTREAMING_POSITION
101 //KSEVENTSETID_Connection, Type = KSEVENT_CONNECTION_ENDOFSTREAM,
102
103
104 //---------------------------------------------------------------
105 // IPortEvents
106 //
107
108 void
109 NTAPI
110 CPortWaveCyclic::AddEventToEventList(
111 IN PKSEVENT_ENTRY EventEntry)
112 {
113 UNIMPLEMENTED
114 }
115
116
117 void
118 NTAPI
119 CPortWaveCyclic::GenerateEventList(
120 IN GUID* Set OPTIONAL,
121 IN ULONG EventId,
122 IN BOOL PinEvent,
123 IN ULONG PinId,
124 IN BOOL NodeEvent,
125 IN ULONG NodeId)
126 {
127 UNIMPLEMENTED
128 }
129
130 //---------------------------------------------------------------
131 // IUnknown interface functions
132 //
133
134 NTSTATUS
135 NTAPI
136 CPortWaveCyclic::QueryInterface(
137 IN REFIID refiid,
138 OUT PVOID* Output)
139 {
140 UNICODE_STRING GuidString;
141
142 if (IsEqualGUIDAligned(refiid, IID_IPortWaveCyclic) ||
143 IsEqualGUIDAligned(refiid, IID_IPort) ||
144 IsEqualGUIDAligned(refiid, IID_IUnknown))
145 {
146 *Output = PVOID(PPORTWAVECYCLIC(this));
147 PUNKNOWN(*Output)->AddRef();
148 return STATUS_SUCCESS;
149 }
150 else if (IsEqualGUIDAligned(refiid, IID_IPortEvents))
151 {
152 *Output = PVOID(PPORTEVENTS(this));
153 PUNKNOWN(*Output)->AddRef();
154 return STATUS_SUCCESS;
155 }
156 else if (IsEqualGUIDAligned(refiid, IID_ISubdevice))
157 {
158 *Output = PVOID(PSUBDEVICE(this));
159 PUNKNOWN(*Output)->AddRef();
160 return STATUS_SUCCESS;
161 }
162 else if (IsEqualGUIDAligned(refiid, IID_IPortClsVersion))
163 {
164 return NewPortClsVersion((PPORTCLSVERSION*)Output);
165 }
166 else if (IsEqualGUIDAligned(refiid, IID_IDrmPort) ||
167 IsEqualGUIDAligned(refiid, IID_IDrmPort2))
168 {
169 return NewIDrmPort((PDRMPORT2*)Output);
170 }
171 else if (IsEqualGUIDAligned(refiid, IID_IUnregisterSubdevice))
172 {
173 return NewIUnregisterSubdevice((PUNREGISTERSUBDEVICE*)Output);
174 }
175 else if (IsEqualGUIDAligned(refiid, IID_IUnregisterPhysicalConnection))
176 {
177 return NewIUnregisterPhysicalConnection((PUNREGISTERPHYSICALCONNECTION*)Output);
178 }
179
180 if (RtlStringFromGUID(refiid, &GuidString) == STATUS_SUCCESS)
181 {
182 DPRINT("IPortWaveCyclic_fnQueryInterface no interface!!! iface %S\n", GuidString.Buffer);
183 RtlFreeUnicodeString(&GuidString);
184 }
185
186 return STATUS_UNSUCCESSFUL;
187 }
188
189 //---------------------------------------------------------------
190 // IPort interface functions
191 //
192
193 NTSTATUS
194 NTAPI
195 CPortWaveCyclic::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 return IoGetDeviceProperty(m_pDeviceObject, DeviceRegistryProperty, BufferLength, PropertyBuffer, ReturnLength);
204 }
205
206 NTSTATUS
207 NTAPI
208 CPortWaveCyclic::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 IMiniportWaveCyclic * Miniport;
216 NTSTATUS Status;
217 PPINCOUNT PinCount;
218 PPOWERNOTIFY PowerNotify;
219
220 DPRINT("IPortWaveCyclic_Init entered %p\n", this);
221 PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
222
223 Status = UnknownMiniport->QueryInterface(IID_IMiniportWaveCyclic, (PVOID*)&Miniport);
224 if (!NT_SUCCESS(Status))
225 {
226 DPRINT("IPortWaveCyclic_Init called with invalid IMiniport adapter\n");
227 return STATUS_INVALID_PARAMETER;
228 }
229
230 // Initialize port object
231 m_pMiniport = Miniport;
232 m_pDeviceObject = DeviceObject;
233
234 // initialize miniport
235 Status = Miniport->Init(UnknownAdapter, ResourceList, this);
236 if (!NT_SUCCESS(Status))
237 {
238 DPRINT("IMiniportWaveCyclic_Init failed with %x\n", Status);
239 Miniport->Release();
240 return Status;
241 }
242
243
244 // get the miniport device descriptor
245 Status = Miniport->GetDescription(&m_pDescriptor);
246 if (!NT_SUCCESS(Status))
247 {
248 DPRINT("failed to get description\n");
249 Miniport->Release();
250 return Status;
251 }
252
253 // create the subdevice descriptor
254 Status = PcCreateSubdeviceDescriptor(&m_SubDeviceDescriptor,
255 4,
256 InterfaceGuids,
257 0,
258 NULL,
259 2,
260 WaveCyclicPropertySet,
261 0,
262 0,
263 0,
264 NULL,
265 0,
266 NULL,
267 m_pDescriptor);
268
269 if (!NT_SUCCESS(Status))
270 {
271 DPRINT("PcCreateSubdeviceDescriptor failed with %x\n", Status);
272 Miniport->Release();
273 return Status;
274 }
275
276 // store for node property requests
277 m_SubDeviceDescriptor->UnknownMiniport = UnknownMiniport;
278
279 // check if it supports IPinCount interface
280 Status = UnknownMiniport->QueryInterface(IID_IPinCount, (PVOID*)&PinCount);
281 if (NT_SUCCESS(Status))
282 {
283 // store IPinCount interface
284 m_pPinCount = PinCount;
285 }
286
287 // does the Miniport adapter support IPowerNotify interface*/
288 Status = UnknownMiniport->QueryInterface(IID_IPowerNotify, (PVOID*)&PowerNotify);
289 if (NT_SUCCESS(Status))
290 {
291 // store reference
292 m_pPowerNotify = PowerNotify;
293 }
294
295 DPRINT("IPortWaveCyclic successfully initialized\n");
296 return STATUS_SUCCESS;
297 }
298
299
300 NTSTATUS
301 NTAPI
302 CPortWaveCyclic::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 return PcNewRegistryKey(OutRegistryKey, OuterUnknown, RegistryKeyType, DesiredAccess, m_pDeviceObject, (ISubdevice*)this, ObjectAttributes, CreateOptions, Disposition);
314 }
315
316
317 //---------------------------------------------------------------
318 // IPortWaveCyclic interface functions
319 //
320
321 NTSTATUS
322 NTAPI
323 CPortWaveCyclic::NewMasterDmaChannel(
324 OUT PDMACHANNEL* DmaChannel,
325 IN PUNKNOWN OuterUnknown,
326 IN PRESOURCELIST ResourceList OPTIONAL,
327 IN ULONG MaximumLength,
328 IN BOOLEAN Dma32BitAddresses,
329 IN BOOLEAN Dma64BitAddresses,
330 IN DMA_WIDTH DmaWidth,
331 IN DMA_SPEED DmaSpeed)
332 {
333 NTSTATUS Status;
334 DEVICE_DESCRIPTION DeviceDescription;
335
336 PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
337
338 Status = PcDmaMasterDescription(ResourceList, (Dma32BitAddresses | Dma64BitAddresses), Dma32BitAddresses, 0, Dma64BitAddresses, DmaWidth, DmaSpeed, MaximumLength, 0, &DeviceDescription);
339 if (NT_SUCCESS(Status))
340 {
341 return PcNewDmaChannel(DmaChannel, OuterUnknown, NonPagedPool, &DeviceDescription, m_pDeviceObject);
342 }
343
344 return Status;
345 }
346
347 NTSTATUS
348 NTAPI
349 CPortWaveCyclic::NewSlaveDmaChannel(
350 OUT PDMACHANNELSLAVE* OutDmaChannel,
351 IN PUNKNOWN OuterUnknown,
352 IN PRESOURCELIST ResourceList OPTIONAL,
353 IN ULONG DmaIndex,
354 IN ULONG MaximumLength,
355 IN BOOLEAN DemandMode,
356 IN DMA_SPEED DmaSpeed)
357 {
358 DEVICE_DESCRIPTION DeviceDescription;
359 PDMACHANNEL DmaChannel;
360 NTSTATUS Status;
361
362 PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
363
364 // FIXME
365 // Check for F-Type DMA Support
366 //
367
368 Status = PcDmaSlaveDescription(ResourceList, DmaIndex, DemandMode, TRUE, DmaSpeed, MaximumLength, 0, &DeviceDescription);
369 if (NT_SUCCESS(Status))
370 {
371 Status = PcNewDmaChannel(&DmaChannel, OuterUnknown, NonPagedPool, &DeviceDescription, m_pDeviceObject);
372 if (NT_SUCCESS(Status))
373 {
374 Status = DmaChannel->QueryInterface(IID_IDmaChannelSlave, (PVOID*)OutDmaChannel);
375 DmaChannel->Release();
376 }
377 }
378
379 return Status;
380 }
381
382 VOID
383 NTAPI
384 CPortWaveCyclic::Notify(
385 IN PSERVICEGROUP ServiceGroup)
386 {
387 ServiceGroup->RequestService ();
388 }
389
390 //---------------------------------------------------------------
391 // ISubdevice interface
392 //
393
394 NTSTATUS
395 NTAPI
396 CPortWaveCyclic::NewIrpTarget(
397 OUT struct IIrpTarget **OutTarget,
398 IN PCWSTR Name,
399 IN PUNKNOWN Unknown,
400 IN POOL_TYPE PoolType,
401 IN PDEVICE_OBJECT DeviceObject,
402 IN PIRP Irp,
403 IN KSOBJECT_CREATE *CreateObject)
404 {
405 NTSTATUS Status;
406 IPortFilterWaveCyclic * Filter;
407
408 DPRINT("ISubDevice_NewIrpTarget this %p\n", this);
409
410 // is there already an instance of the filter
411 if (m_Filter)
412 {
413 // it is, let's return the result
414 *OutTarget = (IIrpTarget*)m_Filter;
415
416 // increment reference
417 m_Filter->AddRef();
418 return STATUS_SUCCESS;
419 }
420
421 // create new instance of filter
422 Status = NewPortFilterWaveCyclic(&Filter);
423 if (!NT_SUCCESS(Status))
424 {
425 // not enough memory
426 return Status;
427 }
428
429 // initialize the filter
430 Status = Filter->Init((IPortWaveCyclic*)this);
431 if (!NT_SUCCESS(Status))
432 {
433 // destroy filter
434 Filter->Release();
435 // return status
436 return Status;
437 }
438
439 // store result
440 *OutTarget = (IIrpTarget*)Filter;
441 // store for later re-use
442 m_Filter = Filter;
443 // return status
444 return Status;
445 }
446
447
448 NTSTATUS
449 NTAPI
450 CPortWaveCyclic::ReleaseChildren()
451 {
452 DPRINT("ISubDevice_fnReleaseChildren\n");
453
454 // release the filter
455 m_Filter->Release();
456
457 if (m_pPinCount)
458 {
459 // release pincount interface
460 m_pPinCount->Release();
461 }
462
463 if (m_pPowerNotify)
464 {
465 // release power notify interface
466 m_pPowerNotify->Release();
467 }
468
469 // now release the miniport
470 m_pMiniport->Release();
471
472 return STATUS_SUCCESS;
473 }
474
475
476 NTSTATUS
477 NTAPI
478 CPortWaveCyclic::GetDescriptor(
479 IN SUBDEVICE_DESCRIPTOR ** Descriptor)
480 {
481 PC_ASSERT(m_SubDeviceDescriptor != NULL);
482
483 *Descriptor = m_SubDeviceDescriptor;
484
485 DPRINT("ISubDevice_GetDescriptor this %p desc %p\n", this, m_SubDeviceDescriptor);
486 return STATUS_SUCCESS;
487 }
488
489
490 NTSTATUS
491 NTAPI
492 CPortWaveCyclic::DataRangeIntersection(
493 IN ULONG PinId,
494 IN PKSDATARANGE DataRange,
495 IN PKSDATARANGE MatchingDataRange,
496 IN ULONG OutputBufferLength,
497 OUT PVOID ResultantFormat OPTIONAL,
498 OUT PULONG ResultantFormatLength)
499 {
500 DPRINT("ISubDevice_DataRangeIntersection this %p\n", this);
501
502 if (m_pMiniport)
503 {
504 return m_pMiniport->DataRangeIntersection (PinId, DataRange, MatchingDataRange, OutputBufferLength, ResultantFormat, ResultantFormatLength);
505 }
506
507 return STATUS_UNSUCCESSFUL;
508 }
509
510
511 NTSTATUS
512 NTAPI
513 CPortWaveCyclic::PowerChangeNotify(
514 IN POWER_STATE PowerState)
515 {
516 if (m_pPowerNotify)
517 {
518 m_pPowerNotify->PowerChangeNotify(PowerState);
519 }
520
521 return STATUS_SUCCESS;
522 }
523
524 NTSTATUS
525 NTAPI
526 CPortWaveCyclic::PinCount(
527 IN ULONG PinId,
528 IN OUT PULONG FilterNecessary,
529 IN OUT PULONG FilterCurrent,
530 IN OUT PULONG FilterPossible,
531 IN OUT PULONG GlobalCurrent,
532 IN OUT PULONG GlobalPossible)
533 {
534 if (m_pPinCount)
535 {
536 m_pPinCount->PinCount(PinId, FilterNecessary, FilterCurrent, FilterPossible, GlobalCurrent, GlobalPossible);
537 return STATUS_SUCCESS;
538 }
539
540 // FIXME
541 // scan filter descriptor
542
543 return STATUS_UNSUCCESSFUL;
544 }
545
546
547 ///--------------------------------------------------------------
548 PMINIPORTWAVECYCLIC
549 GetWaveCyclicMiniport(
550 IN IPortWaveCyclic* iface)
551 {
552 CPortWaveCyclic * This = (CPortWaveCyclic *)iface;
553 return This->m_pMiniport;
554 }
555
556 PDEVICE_OBJECT
557 GetDeviceObject(
558 PPORTWAVECYCLIC iface)
559 {
560 CPortWaveCyclic * This = (CPortWaveCyclic *)iface;
561 return This->m_pDeviceObject;
562 }
563
564 //---------------------------------------------------------------
565 // IPortWaveCyclic constructor
566 //
567
568 NTSTATUS
569 NewPortWaveCyclic(
570 OUT PPORT* OutPort)
571 {
572 NTSTATUS Status;
573 CPortWaveCyclic * Port;
574
575 Port = new(NonPagedPool, TAG_PORTCLASS)CPortWaveCyclic(NULL);
576 if (!Port)
577 return STATUS_INSUFFICIENT_RESOURCES;
578
579 Status = Port->QueryInterface(IID_IPort, (PVOID*)OutPort);
580
581 if (!NT_SUCCESS(Status))
582 {
583 delete Port;
584 }
585
586 DPRINT("NewPortWaveCyclic %p Status %u\n", Port, Status);
587 return Status;
588 }
589