2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Kernel Streaming
4 * FILE: drivers/wdm/audio/backpln/portcls/port_dmus.c
5 * PURPOSE: DirectMusic Port driver
6 * PROGRAMMER: Johannes Anderwald
13 IPortDMusVtbl
*lpVtbl
;
14 IServiceSinkVtbl
*lpVtblServiceSink
;
15 ISubdeviceVtbl
*lpVtblSubDevice
;
19 IMiniportDMus
*pMiniport
;
20 IMiniportMidi
*pMiniportMidi
;
21 DEVICE_OBJECT
*pDeviceObject
;
22 PSERVICEGROUP ServiceGroup
;
24 PPOWERNOTIFY pPowerNotify
;
25 PPORTFILTERDMUS Filter
;
27 PPCFILTER_DESCRIPTOR pDescriptor
;
28 PSUBDEVICE_DESCRIPTOR SubDeviceDescriptor
;
32 static GUID InterfaceGuids
[3] =
36 0x6994AD04, 0x93EF, 0x11D0, {0xA3, 0xCC, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}
39 /// KS_CATEGORY_RENDER
40 0x65E8773E, 0x8F56, 0x11D0, {0xA3, 0xB9, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}
43 /// KS_CATEGORY_CAPTURE
44 0x65E8773D, 0x8F56, 0x11D0, {0xA3, 0xB9, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}
48 DEFINE_KSPROPERTY_TOPOLOGYSET(PortFilterDMusTopologySet
, TopologyPropertyHandler
);
49 DEFINE_KSPROPERTY_PINPROPOSEDATAFORMAT(PortFilterDMusPinSet
, PinPropertyHandler
, PinPropertyHandler
, PinPropertyHandler
);
51 KSPROPERTY_SET PortDMusPropertySet
[] =
54 &KSPROPSETID_Topology
,
55 sizeof(PortFilterDMusTopologySet
) / sizeof(KSPROPERTY_ITEM
),
56 (const KSPROPERTY_ITEM
*)&PortFilterDMusTopologySet
,
62 sizeof(PortFilterDMusPinSet
) / sizeof(KSPROPERTY_ITEM
),
63 (const KSPROPERTY_ITEM
*)&PortFilterDMusPinSet
,
70 //---------------------------------------------------------------
71 // IUnknown interface functions
76 IPortDMus_fnQueryInterface(
81 UNICODE_STRING GuidString
;
82 IPortDMusImpl
* This
= (IPortDMusImpl
*)iface
;
85 if (IsEqualGUIDAligned(refiid
, &IID_IPortDMus
) ||
86 IsEqualGUIDAligned(refiid
, &IID_IPortMidi
) ||
87 IsEqualGUIDAligned(refiid
, &IID_IUnknown
))
89 *Output
= &This
->lpVtbl
;
90 InterlockedIncrement(&This
->ref
);
91 return STATUS_SUCCESS
;
93 else if (IsEqualGUIDAligned(refiid
, &IID_ISubdevice
))
95 *Output
= &This
->lpVtblSubDevice
;
96 InterlockedIncrement(&This
->ref
);
97 return STATUS_SUCCESS
;
99 else if (IsEqualGUIDAligned(refiid
, &IID_IDrmPort
) ||
100 IsEqualGUIDAligned(refiid
, &IID_IDrmPort2
))
102 return NewIDrmPort((PDRMPORT2
*)Output
);
104 else if (IsEqualGUIDAligned(refiid
, &IID_IPortClsVersion
))
106 return NewPortClsVersion((PPORTCLSVERSION
*)Output
);
108 else if (IsEqualGUIDAligned(refiid
, &IID_IUnregisterSubdevice
))
110 return NewIUnregisterSubdevice((PUNREGISTERSUBDEVICE
*)Output
);
112 else if (IsEqualGUIDAligned(refiid
, &IID_IUnregisterPhysicalConnection
))
114 return NewIUnregisterPhysicalConnection((PUNREGISTERPHYSICALCONNECTION
*)Output
);
117 if (RtlStringFromGUID(refiid
, &GuidString
) == STATUS_SUCCESS
)
119 DPRINT1("IPortMidi_fnQueryInterface no interface!!! iface %S\n", GuidString
.Buffer
);
120 RtlFreeUnicodeString(&GuidString
);
122 return STATUS_UNSUCCESSFUL
;
130 IPortDMusImpl
* This
= (IPortDMusImpl
*)iface
;
132 return _InterlockedIncrement(&This
->ref
);
140 IPortDMusImpl
* This
= (IPortDMusImpl
*)iface
;
142 _InterlockedDecrement(&This
->ref
);
146 if (This
->bInitialized
)
148 This
->pMiniport
->lpVtbl
->Release(This
->pMiniport
);
150 FreeItem(This
, TAG_PORTCLASS
);
153 /* Return new reference count */
158 //---------------------------------------------------------------
159 // IPort interface functions
164 IPortDMus_fnGetDeviceProperty(
165 IN IPortDMus
* iface
,
166 IN DEVICE_REGISTRY_PROPERTY DeviceRegistryProperty
,
167 IN ULONG BufferLength
,
168 OUT PVOID PropertyBuffer
,
169 OUT PULONG ReturnLength
)
171 IPortDMusImpl
* This
= (IPortDMusImpl
*)iface
;
173 ASSERT_IRQL_EQUAL(PASSIVE_LEVEL
);
175 if (!This
->bInitialized
)
177 DPRINT("IPortDMus_fnNewRegistryKey called w/o initiazed\n");
178 return STATUS_UNSUCCESSFUL
;
181 return IoGetDeviceProperty(This
->pDeviceObject
, DeviceRegistryProperty
, BufferLength
, PropertyBuffer
, ReturnLength
);
187 IN IPortDMus
* iface
,
188 IN PDEVICE_OBJECT DeviceObject
,
190 IN PUNKNOWN UnknownMiniport
,
191 IN PUNKNOWN UnknownAdapter OPTIONAL
,
192 IN PRESOURCELIST ResourceList
)
194 IMiniportDMus
* Miniport
= NULL
;
195 IMiniportMidi
* MidiMiniport
= NULL
;
197 PSERVICEGROUP ServiceGroup
= NULL
;
199 PPOWERNOTIFY PowerNotify
;
200 IPortDMusImpl
* This
= (IPortDMusImpl
*)iface
;
202 ASSERT_IRQL_EQUAL(PASSIVE_LEVEL
);
204 if (This
->bInitialized
)
206 DPRINT("IPortDMus_Init called again\n");
207 return STATUS_SUCCESS
;
210 Status
= UnknownMiniport
->lpVtbl
->QueryInterface(UnknownMiniport
, &IID_IMiniportDMus
, (PVOID
*)&Miniport
);
211 if (!NT_SUCCESS(Status
))
213 /* check for legacy interface */
214 Status
= UnknownMiniport
->lpVtbl
->QueryInterface(UnknownMiniport
, &IID_IMiniportMidi
, (PVOID
*)&MidiMiniport
);
215 if (!NT_SUCCESS(Status
))
217 DPRINT("IPortDMus_Init called with invalid IMiniport adapter\n");
218 return STATUS_INVALID_PARAMETER
;
222 /* Initialize port object */
223 This
->pMiniport
= Miniport
;
224 This
->pMiniportMidi
= MidiMiniport
;
225 This
->pDeviceObject
= DeviceObject
;
226 This
->bInitialized
= TRUE
;
230 /* initialize IMiniportDMus */
231 Status
= Miniport
->lpVtbl
->Init(Miniport
, UnknownAdapter
, ResourceList
, iface
, &ServiceGroup
);
232 if (!NT_SUCCESS(Status
))
234 DPRINT("IMiniportDMus_Init failed with %x\n", Status
);
235 This
->bInitialized
= FALSE
;
239 /* get the miniport device descriptor */
240 Status
= Miniport
->lpVtbl
->GetDescription(Miniport
, &This
->pDescriptor
);
241 if (!NT_SUCCESS(Status
))
243 DPRINT1("failed to get description\n");
244 Miniport
->lpVtbl
->Release(Miniport
);
245 This
->bInitialized
= FALSE
;
249 /* increment reference on miniport adapter */
250 Miniport
->lpVtbl
->AddRef(Miniport
);
255 /* initialize IMiniportMidi */
256 Status
= MidiMiniport
->lpVtbl
->Init(MidiMiniport
, UnknownAdapter
, ResourceList
, (IPortMidi
*)iface
, &ServiceGroup
);
257 if (!NT_SUCCESS(Status
))
259 DPRINT("IMiniportMidi_Init failed with %x\n", Status
);
260 This
->bInitialized
= FALSE
;
264 /* get the miniport device descriptor */
265 Status
= MidiMiniport
->lpVtbl
->GetDescription(MidiMiniport
, &This
->pDescriptor
);
266 if (!NT_SUCCESS(Status
))
268 DPRINT1("failed to get description\n");
269 MidiMiniport
->lpVtbl
->Release(MidiMiniport
);
270 This
->bInitialized
= FALSE
;
274 /* increment reference on miniport adapter */
275 MidiMiniport
->lpVtbl
->AddRef(MidiMiniport
);
278 /* create the subdevice descriptor */
279 Status
= PcCreateSubdeviceDescriptor(&This
->SubDeviceDescriptor
,
294 if (!NT_SUCCESS(Status
))
296 DPRINT1("Failed to create descriptior\n");
299 Miniport
->lpVtbl
->Release(Miniport
);
301 MidiMiniport
->lpVtbl
->Release(MidiMiniport
);
303 This
->bInitialized
= FALSE
;
307 if (This
->ServiceGroup
== NULL
&& ServiceGroup
)
309 /* register service group */
310 This
->ServiceGroup
= ServiceGroup
;
313 /* check if it supports IPinCount interface */
314 Status
= UnknownMiniport
->lpVtbl
->QueryInterface(UnknownMiniport
, &IID_IPinCount
, (PVOID
*)&PinCount
);
315 if (NT_SUCCESS(Status
))
317 /* store IPinCount interface */
318 This
->pPinCount
= PinCount
;
321 /* does the Miniport adapter support IPowerNotify interface*/
322 Status
= UnknownMiniport
->lpVtbl
->QueryInterface(UnknownMiniport
, &IID_IPowerNotify
, (PVOID
*)&PowerNotify
);
323 if (NT_SUCCESS(Status
))
325 /* store reference */
326 This
->pPowerNotify
= PowerNotify
;
329 return STATUS_SUCCESS
;
335 IPortDMus_fnNewRegistryKey(
336 IN IPortDMus
* iface
,
337 OUT PREGISTRYKEY
*OutRegistryKey
,
338 IN PUNKNOWN OuterUnknown OPTIONAL
,
339 IN ULONG RegistryKeyType
,
340 IN ACCESS_MASK DesiredAccess
,
341 IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL
,
342 IN ULONG CreateOptions OPTIONAL
,
343 OUT PULONG Disposition OPTIONAL
)
345 IPortDMusImpl
* This
= (IPortDMusImpl
*)iface
;
347 ASSERT_IRQL_EQUAL(PASSIVE_LEVEL
);
349 if (!This
->bInitialized
)
351 DPRINT("IPortDMus_fnNewRegistryKey called w/o initialized\n");
352 return STATUS_UNSUCCESSFUL
;
355 return PcNewRegistryKey(OutRegistryKey
,
369 IN IPortDMus
* iface
,
370 IN PSERVICEGROUP ServiceGroup OPTIONAL
)
372 IPortDMusImpl
* This
= (IPortDMusImpl
*)iface
;
376 ServiceGroup
->lpVtbl
->RequestService (ServiceGroup
);
380 ASSERT(This
->ServiceGroup
);
382 /* notify miniport service group */
383 This
->ServiceGroup
->lpVtbl
->RequestService(This
->ServiceGroup
);
385 /* notify stream miniport service group */
388 This
->Filter
->lpVtbl
->NotifyPins(This
->Filter
);
394 IPortDMus_fnRegisterServiceGroup(
395 IN IPortDMus
* iface
,
396 IN PSERVICEGROUP ServiceGroup
)
398 IPortDMusImpl
* This
= (IPortDMusImpl
*)iface
;
400 ASSERT_IRQL_EQUAL(PASSIVE_LEVEL
);
402 This
->ServiceGroup
= ServiceGroup
;
404 ServiceGroup
->lpVtbl
->AddRef(ServiceGroup
);
405 ServiceGroup
->lpVtbl
->AddMember(ServiceGroup
, (PSERVICESINK
)&This
->lpVtblServiceSink
);
408 static IPortDMusVtbl vt_IPortDMus
=
410 /* IUnknown methods */
411 IPortDMus_fnQueryInterface
,
416 IPortDMus_fnGetDeviceProperty
,
417 IPortDMus_fnNewRegistryKey
,
419 IPortDMus_fnRegisterServiceGroup
422 //---------------------------------------------------------------
423 // ISubdevice interface
429 ISubDevice_fnQueryInterface(
430 IN ISubdevice
*iface
,
431 IN REFIID InterfaceId
,
434 IPortDMusImpl
* This
= (IPortDMusImpl
*)CONTAINING_RECORD(iface
, IPortDMusImpl
, lpVtblSubDevice
);
436 return IPortDMus_fnQueryInterface((IPortDMus
*)This
, InterfaceId
, Interface
);
443 IN ISubdevice
*iface
)
445 IPortDMusImpl
* This
= (IPortDMusImpl
*)CONTAINING_RECORD(iface
, IPortDMusImpl
, lpVtblSubDevice
);
447 return IPortDMus_fnAddRef((IPortDMus
*)This
);
453 ISubDevice_fnRelease(
454 IN ISubdevice
*iface
)
456 IPortDMusImpl
* This
= (IPortDMusImpl
*)CONTAINING_RECORD(iface
, IPortDMusImpl
, lpVtblSubDevice
);
458 return IPortDMus_fnRelease((IPortDMus
*)This
);
464 ISubDevice_fnNewIrpTarget(
465 IN ISubdevice
*iface
,
466 OUT
struct IIrpTarget
**OutTarget
,
469 IN POOL_TYPE PoolType
,
470 IN PDEVICE_OBJECT DeviceObject
,
472 IN KSOBJECT_CREATE
*CreateObject
)
475 PPORTFILTERDMUS Filter
;
476 IPortDMusImpl
* This
= (IPortDMusImpl
*)CONTAINING_RECORD(iface
, IPortDMusImpl
, lpVtblSubDevice
);
478 DPRINT("ISubDevice_NewIrpTarget this %p\n", This
);
482 *OutTarget
= (IIrpTarget
*)This
->Filter
;
483 return STATUS_SUCCESS
;
487 Status
= NewPortFilterDMus(&Filter
);
488 if (!NT_SUCCESS(Status
))
493 Status
= Filter
->lpVtbl
->Init(Filter
, (PPORTDMUS
)This
);
494 if (!NT_SUCCESS(Status
))
496 Filter
->lpVtbl
->Release(Filter
);
500 *OutTarget
= (IIrpTarget
*)Filter
;
507 ISubDevice_fnReleaseChildren(
508 IN ISubdevice
*iface
)
510 //IPortDMusImpl * This = (IPortDMusImpl*)CONTAINING_RECORD(iface, IPortDMusImpl, lpVtblSubDevice);
513 return STATUS_UNSUCCESSFUL
;
519 ISubDevice_fnGetDescriptor(
520 IN ISubdevice
*iface
,
521 IN SUBDEVICE_DESCRIPTOR
** Descriptor
)
523 IPortDMusImpl
* This
= (IPortDMusImpl
*)CONTAINING_RECORD(iface
, IPortDMusImpl
, lpVtblSubDevice
);
525 DPRINT("ISubDevice_GetDescriptor this %p\n", This
);
526 *Descriptor
= This
->SubDeviceDescriptor
;
527 return STATUS_SUCCESS
;
533 ISubDevice_fnDataRangeIntersection(
534 IN ISubdevice
*iface
,
536 IN PKSDATARANGE DataRange
,
537 IN PKSDATARANGE MatchingDataRange
,
538 IN ULONG OutputBufferLength
,
539 OUT PVOID ResultantFormat OPTIONAL
,
540 OUT PULONG ResultantFormatLength
)
542 IPortDMusImpl
* This
= (IPortDMusImpl
*)CONTAINING_RECORD(iface
, IPortDMusImpl
, lpVtblSubDevice
);
544 DPRINT("ISubDevice_DataRangeIntersection this %p\n", This
);
548 return This
->pMiniport
->lpVtbl
->DataRangeIntersection (This
->pMiniport
, PinId
, DataRange
, MatchingDataRange
, OutputBufferLength
, ResultantFormat
, ResultantFormatLength
);
551 return STATUS_UNSUCCESSFUL
;
557 ISubDevice_fnPowerChangeNotify(
558 IN ISubdevice
*iface
,
559 IN POWER_STATE PowerState
)
561 IPortDMusImpl
* This
= (IPortDMusImpl
*)CONTAINING_RECORD(iface
, IPortDMusImpl
, lpVtblSubDevice
);
563 if (This
->pPowerNotify
)
565 This
->pPowerNotify
->lpVtbl
->PowerChangeNotify(This
->pPowerNotify
, PowerState
);
568 return STATUS_SUCCESS
;
574 ISubDevice_fnPinCount(
575 IN ISubdevice
*iface
,
577 IN OUT PULONG FilterNecessary
,
578 IN OUT PULONG FilterCurrent
,
579 IN OUT PULONG FilterPossible
,
580 IN OUT PULONG GlobalCurrent
,
581 IN OUT PULONG GlobalPossible
)
583 IPortDMusImpl
* This
= (IPortDMusImpl
*)CONTAINING_RECORD(iface
, IPortDMusImpl
, lpVtblSubDevice
);
587 This
->pPinCount
->lpVtbl
->PinCount(This
->pPinCount
, PinId
, FilterNecessary
, FilterCurrent
, FilterPossible
, GlobalCurrent
, GlobalPossible
);
588 return STATUS_SUCCESS
;
592 * scan filter descriptor
594 return STATUS_UNSUCCESSFUL
;
597 static ISubdeviceVtbl vt_ISubdevice
=
599 ISubDevice_fnQueryInterface
,
601 ISubDevice_fnRelease
,
602 ISubDevice_fnNewIrpTarget
,
603 ISubDevice_fnReleaseChildren
,
604 ISubDevice_fnGetDescriptor
,
605 ISubDevice_fnDataRangeIntersection
,
606 ISubDevice_fnPowerChangeNotify
,
607 ISubDevice_fnPinCount
614 IServiceSink_fnQueryInterface(
619 IPortDMusImpl
* This
= (IPortDMusImpl
*)CONTAINING_RECORD(iface
, IPortDMusImpl
, lpVtblServiceSink
);
621 if (IsEqualGUIDAligned(refiid
, &IID_IServiceSink
) ||
622 IsEqualGUIDAligned(refiid
, &IID_IUnknown
))
624 *Output
= &This
->lpVtblServiceSink
;
625 InterlockedIncrement(&This
->ref
);
626 return STATUS_SUCCESS
;
629 DPRINT("Unknown interface requested\n");
630 return STATUS_UNSUCCESSFUL
;
636 IServiceSink_fnAddRef(
639 IPortDMusImpl
* This
= (IPortDMusImpl
*)CONTAINING_RECORD(iface
, IPortDMusImpl
, lpVtblServiceSink
);
640 return IPortDMus_fnAddRef((IPortDMus
*)This
);
646 IServiceSink_fnRelease(
649 IPortDMusImpl
* This
= (IPortDMusImpl
*)CONTAINING_RECORD(iface
, IPortDMusImpl
, lpVtblServiceSink
);
650 return IPortDMus_fnRelease((IPortDMus
*)This
);
656 IServiceSink_fnRequestService(
662 static IServiceSinkVtbl vt_IServiceSink
=
664 IServiceSink_fnQueryInterface
,
665 IServiceSink_fnAddRef
,
666 IServiceSink_fnRelease
,
667 IServiceSink_fnRequestService
674 IPortDMusImpl
* This
= AllocateItem(NonPagedPool
, sizeof(IPortDMusImpl
), TAG_PORTCLASS
);
678 return STATUS_INSUFFICIENT_RESOURCES
;
682 This
->lpVtbl
= &vt_IPortDMus
;
683 This
->lpVtblServiceSink
= &vt_IServiceSink
;
684 This
->lpVtblSubDevice
= &vt_ISubdevice
;
686 *OutPort
= (PPORT
)&This
->lpVtbl
;
688 return STATUS_SUCCESS
;
693 IN IPortDMus
* iface
,
694 IN PMINIPORTDMUS
* Miniport
,
695 IN PMINIPORTMIDI
* MidiMiniport
)
697 IPortDMusImpl
* This
= (IPortDMusImpl
*)iface
;
699 *Miniport
= This
->pMiniport
;
700 *MidiMiniport
= This
->pMiniportMidi
;