Sync up to trunk head.
[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 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 //KS_CATEGORY_AUDIO
64 0x6994AD04, 0x93EF, 0x11D0, {0xA3, 0xCC, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}
65 },
66 {
67 /// KSCATEGORY_RENDER
68 0x65E8773EL, 0x8F56, 0x11D0, {0xA3, 0xB9, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}
69 },
70 {
71 /// KSCATEGORY_CAPTURE
72 0x65E8773DL, 0x8F56, 0x11D0, {0xA3, 0xB9, 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 DPRINT("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 DPRINT("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 DPRINT("PcCreateSubdeviceDescriptor failed with %x\n", Status);
296 Miniport->Release();
297 m_bInitialized = FALSE;
298 return Status;
299 }
300
301 // store for node property requests
302 m_SubDeviceDescriptor->UnknownMiniport = UnknownMiniport;
303
304 // check if it supports IPinCount interface
305 Status = UnknownMiniport->QueryInterface(IID_IPinCount, (PVOID*)&PinCount);
306 if (NT_SUCCESS(Status))
307 {
308 // store IPinCount interface
309 m_pPinCount = PinCount;
310 }
311
312 // does the Miniport adapter support IPowerNotify interface*/
313 Status = UnknownMiniport->QueryInterface(IID_IPowerNotify, (PVOID*)&PowerNotify);
314 if (NT_SUCCESS(Status))
315 {
316 // store reference
317 m_pPowerNotify = PowerNotify;
318 }
319
320 DPRINT("IPortWaveCyclic successfully initialized\n");
321 return STATUS_SUCCESS;
322 }
323
324
325 NTSTATUS
326 NTAPI
327 CPortWaveCyclic::NewRegistryKey(
328 OUT PREGISTRYKEY *OutRegistryKey,
329 IN PUNKNOWN OuterUnknown OPTIONAL,
330 IN ULONG RegistryKeyType,
331 IN ACCESS_MASK DesiredAccess,
332 IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
333 IN ULONG CreateOptions OPTIONAL,
334 OUT PULONG Disposition OPTIONAL)
335 {
336 PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
337
338 if (!m_bInitialized)
339 {
340 DPRINT("IPortWaveCyclic_fnNewRegistryKey called w/o initialized\n");
341 return STATUS_UNSUCCESSFUL;
342 }
343 return PcNewRegistryKey(OutRegistryKey, OuterUnknown, RegistryKeyType, DesiredAccess, m_pDeviceObject, (ISubdevice*)this, ObjectAttributes, CreateOptions, Disposition);
344 }
345
346
347 //---------------------------------------------------------------
348 // IPortWaveCyclic interface functions
349 //
350
351 NTSTATUS
352 NTAPI
353 CPortWaveCyclic::NewMasterDmaChannel(
354 OUT PDMACHANNEL* DmaChannel,
355 IN PUNKNOWN OuterUnknown,
356 IN PRESOURCELIST ResourceList OPTIONAL,
357 IN ULONG MaximumLength,
358 IN BOOLEAN Dma32BitAddresses,
359 IN BOOLEAN Dma64BitAddresses,
360 IN DMA_WIDTH DmaWidth,
361 IN DMA_SPEED DmaSpeed)
362 {
363 NTSTATUS Status;
364 DEVICE_DESCRIPTION DeviceDescription;
365
366 PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
367
368 if (!m_bInitialized)
369 {
370 DPRINT("IPortWaveCyclic_fnNewSlaveDmaChannel called w/o initialized\n");
371 return STATUS_UNSUCCESSFUL;
372 }
373
374 Status = PcDmaMasterDescription(ResourceList, (Dma32BitAddresses | Dma64BitAddresses), Dma32BitAddresses, 0, Dma64BitAddresses, DmaWidth, DmaSpeed, MaximumLength, 0, &DeviceDescription);
375 if (NT_SUCCESS(Status))
376 {
377 return PcNewDmaChannel(DmaChannel, OuterUnknown, NonPagedPool, &DeviceDescription, m_pDeviceObject);
378 }
379
380 return Status;
381 }
382
383 NTSTATUS
384 NTAPI
385 CPortWaveCyclic::NewSlaveDmaChannel(
386 OUT PDMACHANNELSLAVE* OutDmaChannel,
387 IN PUNKNOWN OuterUnknown,
388 IN PRESOURCELIST ResourceList OPTIONAL,
389 IN ULONG DmaIndex,
390 IN ULONG MaximumLength,
391 IN BOOLEAN DemandMode,
392 IN DMA_SPEED DmaSpeed)
393 {
394 DEVICE_DESCRIPTION DeviceDescription;
395 PDMACHANNEL DmaChannel;
396 NTSTATUS Status;
397
398 PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
399
400 if (!m_bInitialized)
401 {
402 DPRINT("IPortWaveCyclic_fnNewSlaveDmaChannel called w/o initialized\n");
403 return STATUS_UNSUCCESSFUL;
404 }
405
406 // FIXME
407 // Check for F-Type DMA Support
408 //
409
410 Status = PcDmaSlaveDescription(ResourceList, DmaIndex, DemandMode, TRUE, DmaSpeed, MaximumLength, 0, &DeviceDescription);
411 if (NT_SUCCESS(Status))
412 {
413 Status = PcNewDmaChannel(&DmaChannel, OuterUnknown, NonPagedPool, &DeviceDescription, m_pDeviceObject);
414 if (NT_SUCCESS(Status))
415 {
416 Status = DmaChannel->QueryInterface(IID_IDmaChannelSlave, (PVOID*)OutDmaChannel);
417 DmaChannel->Release();
418 }
419 }
420
421 return Status;
422 }
423
424 VOID
425 NTAPI
426 CPortWaveCyclic::Notify(
427 IN PSERVICEGROUP ServiceGroup)
428 {
429 ServiceGroup->RequestService ();
430 }
431
432 //---------------------------------------------------------------
433 // ISubdevice interface
434 //
435
436 NTSTATUS
437 NTAPI
438 CPortWaveCyclic::NewIrpTarget(
439 OUT struct IIrpTarget **OutTarget,
440 IN PCWSTR Name,
441 IN PUNKNOWN Unknown,
442 IN POOL_TYPE PoolType,
443 IN PDEVICE_OBJECT DeviceObject,
444 IN PIRP Irp,
445 IN KSOBJECT_CREATE *CreateObject)
446 {
447 NTSTATUS Status;
448 IPortFilterWaveCyclic * Filter;
449
450 DPRINT("ISubDevice_NewIrpTarget this %p\n", this);
451
452 // is there already an instance of the filter
453 if (m_Filter)
454 {
455 // it is, let's return the result
456 *OutTarget = (IIrpTarget*)m_Filter;
457
458 // increment reference
459 m_Filter->AddRef();
460 return STATUS_SUCCESS;
461 }
462
463 // create new instance of filter
464 Status = NewPortFilterWaveCyclic(&Filter);
465 if (!NT_SUCCESS(Status))
466 {
467 // not enough memory
468 return Status;
469 }
470
471 // initialize the filter
472 Status = Filter->Init((IPortWaveCyclic*)this);
473 if (!NT_SUCCESS(Status))
474 {
475 // destroy filter
476 Filter->Release();
477 // return status
478 return Status;
479 }
480
481 // store result
482 *OutTarget = (IIrpTarget*)Filter;
483 // store for later re-use
484 m_Filter = Filter;
485 // return status
486 return Status;
487 }
488
489
490 NTSTATUS
491 NTAPI
492 CPortWaveCyclic::ReleaseChildren()
493 {
494 DPRINT("ISubDevice_fnReleaseChildren\n");
495
496 // release the filter
497 m_Filter->Release();
498
499 if (m_pPinCount)
500 {
501 // release pincount interface
502 m_pPinCount->Release();
503 }
504
505 if (m_pPowerNotify)
506 {
507 // release power notify interface
508 m_pPowerNotify->Release();
509 }
510
511 // now release the miniport
512 m_pMiniport->Release();
513
514 return STATUS_SUCCESS;
515 }
516
517
518 NTSTATUS
519 NTAPI
520 CPortWaveCyclic::GetDescriptor(
521 IN SUBDEVICE_DESCRIPTOR ** Descriptor)
522 {
523 PC_ASSERT(m_SubDeviceDescriptor != NULL);
524
525 *Descriptor = m_SubDeviceDescriptor;
526
527 DPRINT("ISubDevice_GetDescriptor this %p desc %p\n", this, m_SubDeviceDescriptor);
528 return STATUS_SUCCESS;
529 }
530
531
532 NTSTATUS
533 NTAPI
534 CPortWaveCyclic::DataRangeIntersection(
535 IN ULONG PinId,
536 IN PKSDATARANGE DataRange,
537 IN PKSDATARANGE MatchingDataRange,
538 IN ULONG OutputBufferLength,
539 OUT PVOID ResultantFormat OPTIONAL,
540 OUT PULONG ResultantFormatLength)
541 {
542 DPRINT("ISubDevice_DataRangeIntersection this %p\n", this);
543
544 if (m_pMiniport)
545 {
546 return m_pMiniport->DataRangeIntersection (PinId, DataRange, MatchingDataRange, OutputBufferLength, ResultantFormat, ResultantFormatLength);
547 }
548
549 return STATUS_UNSUCCESSFUL;
550 }
551
552
553 NTSTATUS
554 NTAPI
555 CPortWaveCyclic::PowerChangeNotify(
556 IN POWER_STATE PowerState)
557 {
558 if (m_pPowerNotify)
559 {
560 m_pPowerNotify->PowerChangeNotify(PowerState);
561 }
562
563 return STATUS_SUCCESS;
564 }
565
566 NTSTATUS
567 NTAPI
568 CPortWaveCyclic::PinCount(
569 IN ULONG PinId,
570 IN OUT PULONG FilterNecessary,
571 IN OUT PULONG FilterCurrent,
572 IN OUT PULONG FilterPossible,
573 IN OUT PULONG GlobalCurrent,
574 IN OUT PULONG GlobalPossible)
575 {
576 if (m_pPinCount)
577 {
578 m_pPinCount->PinCount(PinId, FilterNecessary, FilterCurrent, FilterPossible, GlobalCurrent, GlobalPossible);
579 return STATUS_SUCCESS;
580 }
581
582 // FIXME
583 // scan filter descriptor
584
585 return STATUS_UNSUCCESSFUL;
586 }
587
588
589 ///--------------------------------------------------------------
590 PMINIPORTWAVECYCLIC
591 GetWaveCyclicMiniport(
592 IN IPortWaveCyclic* iface)
593 {
594 CPortWaveCyclic * This = (CPortWaveCyclic *)iface;
595 return This->m_pMiniport;
596 }
597
598 PDEVICE_OBJECT
599 GetDeviceObject(
600 PPORTWAVECYCLIC iface)
601 {
602 CPortWaveCyclic * This = (CPortWaveCyclic *)iface;
603 return This->m_pDeviceObject;
604 }
605
606 //---------------------------------------------------------------
607 // IPortWaveCyclic constructor
608 //
609
610 NTSTATUS
611 NewPortWaveCyclic(
612 OUT PPORT* OutPort)
613 {
614 NTSTATUS Status;
615 CPortWaveCyclic * Port;
616
617 Port = new(NonPagedPool, TAG_PORTCLASS)CPortWaveCyclic(NULL);
618 if (!Port)
619 return STATUS_INSUFFICIENT_RESOURCES;
620
621 Status = Port->QueryInterface(IID_IPort, (PVOID*)OutPort);
622
623 if (!NT_SUCCESS(Status))
624 {
625 delete Port;
626 }
627
628 DPRINT("NewPortWaveCyclic %p Status %u\n", Port, Status);
629 return Status;
630 }
631