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