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