2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Kernel Streaming
4 * FILE: drivers/wdm/audio/backpln/portcls/port_topology.cpp
5 * PURPOSE: Topology Port driver
6 * PROGRAMMER: Johannes Anderwald
11 class CPortTopology
: public IPortTopology
,
16 STDMETHODIMP
QueryInterface( REFIID InterfaceId
, PVOID
* Interface
);
18 STDMETHODIMP_(ULONG
) AddRef()
20 InterlockedIncrement(&m_Ref
);
23 STDMETHODIMP_(ULONG
) Release()
25 InterlockedDecrement(&m_Ref
);
37 CPortTopology(IUnknown
*OuterUnknown
){}
38 virtual ~CPortTopology(){}
43 PMINIPORTTOPOLOGY m_pMiniport
;
44 PDEVICE_OBJECT m_pDeviceObject
;
45 PPINCOUNT m_pPinCount
;
46 PPOWERNOTIFY m_pPowerNotify
;
48 PPCFILTER_DESCRIPTOR m_pDescriptor
;
49 PSUBDEVICE_DESCRIPTOR m_SubDeviceDescriptor
;
50 IPortFilterTopology
* m_Filter
;
54 friend PMINIPORTTOPOLOGY
GetTopologyMiniport(PPORTTOPOLOGY Port
);
62 PIO_WORKITEM WorkItem
;
63 }PIN_WORKER_CONTEXT
, *PPIN_WORKER_CONTEXT
;
65 static GUID InterfaceGuids
[2] =
69 0x6994AD04, 0x93EF, 0x11D0, {0xA3, 0xCC, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}
72 /// KS_CATEGORY_TOPOLOGY
73 0xDDA54A40, 0x1E4C, 0x11D1, {0xA0, 0x50, 0x40, 0x57, 0x05, 0xC1, 0x00, 0x00}
77 DEFINE_KSPROPERTY_TOPOLOGYSET(PortFilterTopologyTopologySet
, TopologyPropertyHandler
);
78 DEFINE_KSPROPERTY_PINPROPOSEDATAFORMAT(PortFilterTopologyPinSet
, PinPropertyHandler
, PinPropertyHandler
, PinPropertyHandler
);
80 KSPROPERTY_SET TopologyPropertySet
[] =
83 &KSPROPSETID_Topology
,
84 sizeof(PortFilterTopologyTopologySet
) / sizeof(KSPROPERTY_ITEM
),
85 (const KSPROPERTY_ITEM
*)&PortFilterTopologyTopologySet
,
91 sizeof(PortFilterTopologyPinSet
) / sizeof(KSPROPERTY_ITEM
),
92 (const KSPROPERTY_ITEM
*)&PortFilterTopologyPinSet
,
98 //---------------------------------------------------------------
105 CPortTopology::AddEventToEventList(
106 IN PKSEVENT_ENTRY EventEntry
)
113 CPortTopology::GenerateEventList(
114 IN GUID
* Set OPTIONAL
,
125 //---------------------------------------------------------------
126 // IUnknown interface functions
131 CPortTopology::QueryInterface(
135 UNICODE_STRING GuidString
;
137 DPRINT("IPortTopology_fnQueryInterface\n");
139 if (IsEqualGUIDAligned(refiid
, IID_IPortTopology
) ||
140 IsEqualGUIDAligned(refiid
, IID_IPort
) ||
141 IsEqualGUIDAligned(refiid
, IID_IUnknown
))
143 *Output
= PVOID(PUNKNOWN((IPortTopology
*)this));
144 PUNKNOWN(*Output
)->AddRef();
145 return STATUS_SUCCESS
;
147 else if (IsEqualGUIDAligned(refiid
, IID_ISubdevice
))
149 *Output
= PVOID(PSUBDEVICE(this));
150 PUNKNOWN(*Output
)->AddRef();
151 return STATUS_SUCCESS
;
153 else if (IsEqualGUIDAligned(refiid
, IID_IPortEvents
))
155 *Output
= PVOID(PPORTEVENTS(this));
156 PUNKNOWN(*Output
)->AddRef();
157 return STATUS_SUCCESS
;
159 else if (IsEqualGUIDAligned(refiid
, IID_IPortClsVersion
))
161 return NewPortClsVersion((PPORTCLSVERSION
*)Output
);
163 else if (IsEqualGUIDAligned(refiid
, IID_IUnregisterSubdevice
))
165 return NewIUnregisterSubdevice((PUNREGISTERSUBDEVICE
*)Output
);
167 else if (IsEqualGUIDAligned(refiid
, IID_IUnregisterPhysicalConnection
))
169 return NewIUnregisterPhysicalConnection((PUNREGISTERPHYSICALCONNECTION
*)Output
);
172 if (RtlStringFromGUID(refiid
, &GuidString
) == STATUS_SUCCESS
)
174 DPRINT("IPortTopology_fnQueryInterface no interface!!! iface %S\n", GuidString
.Buffer
);
175 RtlFreeUnicodeString(&GuidString
);
177 return STATUS_UNSUCCESSFUL
;
180 //---------------------------------------------------------------
181 // IPort interface functions
186 CPortTopology::GetDeviceProperty(
187 IN DEVICE_REGISTRY_PROPERTY DeviceRegistryProperty
,
188 IN ULONG BufferLength
,
189 OUT PVOID PropertyBuffer
,
190 OUT PULONG ReturnLength
)
192 PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL
);
196 DPRINT("IPortTopology_fnNewRegistryKey called w/o initiazed\n");
197 return STATUS_UNSUCCESSFUL
;
200 return IoGetDeviceProperty(m_pDeviceObject
, DeviceRegistryProperty
, BufferLength
, PropertyBuffer
, ReturnLength
);
206 IN PDEVICE_OBJECT DeviceObject
,
208 IN PUNKNOWN UnknownMiniport
,
209 IN PUNKNOWN UnknownAdapter OPTIONAL
,
210 IN PRESOURCELIST ResourceList
)
212 IMiniportTopology
* Miniport
;
215 DPRINT("IPortTopology_fnInit entered This %p DeviceObject %p Irp %p UnknownMiniport %p UnknownAdapter %p ResourceList %p\n",
216 this, DeviceObject
, Irp
, UnknownMiniport
, UnknownAdapter
, ResourceList
);
218 PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL
);
222 DPRINT("IPortTopology_Init called again\n");
223 return STATUS_SUCCESS
;
226 Status
= UnknownMiniport
->QueryInterface(IID_IMiniportTopology
, (PVOID
*)&Miniport
);
227 if (!NT_SUCCESS(Status
))
229 DPRINT("IPortTopology_Init called with invalid IMiniport adapter\n");
230 return STATUS_INVALID_PARAMETER
;
233 // Initialize port object
234 m_pMiniport
= Miniport
;
235 m_pDeviceObject
= DeviceObject
;
236 m_bInitialized
= TRUE
;
238 // now initialize the miniport driver
239 Status
= Miniport
->Init(UnknownAdapter
, ResourceList
, this);
240 if (!NT_SUCCESS(Status
))
242 DPRINT("IPortTopology_Init failed with %x\n", Status
);
243 m_bInitialized
= FALSE
;
248 // get the miniport device descriptor
249 Status
= Miniport
->GetDescription(&m_pDescriptor
);
250 if (!NT_SUCCESS(Status
))
252 DPRINT("failed to get description\n");
254 m_bInitialized
= FALSE
;
258 // create the subdevice descriptor
259 Status
= PcCreateSubdeviceDescriptor(&m_SubDeviceDescriptor
,
275 DPRINT("IPortTopology_fnInit success\n");
276 if (NT_SUCCESS(Status
))
278 // store for node property requests
279 m_SubDeviceDescriptor
->UnknownMiniport
= UnknownMiniport
;
282 return STATUS_SUCCESS
;
288 CPortTopology::NewRegistryKey(
289 OUT PREGISTRYKEY
*OutRegistryKey
,
290 IN PUNKNOWN OuterUnknown OPTIONAL
,
291 IN ULONG RegistryKeyType
,
292 IN ACCESS_MASK DesiredAccess
,
293 IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL
,
294 IN ULONG CreateOptions OPTIONAL
,
295 OUT PULONG Disposition OPTIONAL
)
297 PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL
);
301 DPRINT("IPortTopology_fnNewRegistryKey called w/o initialized\n");
302 return STATUS_UNSUCCESSFUL
;
304 return PcNewRegistryKey(OutRegistryKey
,
315 //---------------------------------------------------------------
316 // ISubdevice interface
321 CPortTopology::NewIrpTarget(
322 OUT
struct IIrpTarget
**OutTarget
,
325 IN POOL_TYPE PoolType
,
326 IN PDEVICE_OBJECT DeviceObject
,
328 IN KSOBJECT_CREATE
*CreateObject
)
331 IPortFilterTopology
* Filter
;
333 // is there already an instance of the filter
336 // it is, let's return the result
337 *OutTarget
= (IIrpTarget
*)m_Filter
;
339 // increment reference
341 return STATUS_SUCCESS
;
344 // create new instance of filter
345 Status
= NewPortFilterTopology(&Filter
);
346 if (!NT_SUCCESS(Status
))
352 // initialize the filter
353 Status
= Filter
->Init((IPortTopology
*)this);
354 if (!NT_SUCCESS(Status
))
363 *OutTarget
= (IIrpTarget
*)Filter
;
364 // store for later re-use
372 CPortTopology::ReleaseChildren()
374 DPRINT("ISubDevice_fnReleaseChildren\n");
376 // release the filter
379 // release the miniport
380 DPRINT("Refs %u\n", m_pMiniport
->Release());
382 return STATUS_SUCCESS
;
387 CPortTopology::GetDescriptor(
388 IN SUBDEVICE_DESCRIPTOR
** Descriptor
)
390 DPRINT("ISubDevice_GetDescriptor this %p Descp %p\n", this, m_SubDeviceDescriptor
);
391 *Descriptor
= m_SubDeviceDescriptor
;
392 return STATUS_SUCCESS
;
397 CPortTopology::DataRangeIntersection(
399 IN PKSDATARANGE DataRange
,
400 IN PKSDATARANGE MatchingDataRange
,
401 IN ULONG OutputBufferLength
,
402 OUT PVOID ResultantFormat OPTIONAL
,
403 OUT PULONG ResultantFormatLength
)
405 DPRINT("ISubDevice_DataRangeIntersection this %p\n", this);
409 return m_pMiniport
->DataRangeIntersection (PinId
, DataRange
, MatchingDataRange
, OutputBufferLength
, ResultantFormat
, ResultantFormatLength
);
412 return STATUS_UNSUCCESSFUL
;
417 CPortTopology::PowerChangeNotify(
418 IN POWER_STATE PowerState
)
422 m_pPowerNotify
->PowerChangeNotify(PowerState
);
425 return STATUS_SUCCESS
;
430 CPortTopology::PinCount(
432 IN OUT PULONG FilterNecessary
,
433 IN OUT PULONG FilterCurrent
,
434 IN OUT PULONG FilterPossible
,
435 IN OUT PULONG GlobalCurrent
,
436 IN OUT PULONG GlobalPossible
)
440 m_pPinCount
->PinCount(PinId
, FilterNecessary
, FilterCurrent
, FilterPossible
, GlobalCurrent
, GlobalPossible
);
441 return STATUS_SUCCESS
;
445 // scan filter descriptor
447 return STATUS_UNSUCCESSFUL
;
453 CreatePinWorkerRoutine(
454 IN PDEVICE_OBJECT DeviceObject
,
459 PPIN_WORKER_CONTEXT WorkerContext
= (PPIN_WORKER_CONTEXT
)Context
;
461 DPRINT("CreatePinWorkerRoutine called\n");
463 Status
= WorkerContext
->Filter
->NewIrpTarget(&Pin
,
471 DPRINT("CreatePinWorkerRoutine Status %x\n", Status
);
473 if (NT_SUCCESS(Status
))
475 // create the dispatch object
476 // FIXME need create item for clock
477 Status
= NewDispatchObject(WorkerContext
->Irp
, Pin
, 0, NULL
);
478 DPRINT("Pin %p\n", Pin
);
481 DPRINT("CreatePinWorkerRoutine completing irp %p\n", WorkerContext
->Irp
);
482 // save status in irp
483 WorkerContext
->Irp
->IoStatus
.Status
= Status
;
484 WorkerContext
->Irp
->IoStatus
.Information
= 0;
485 // complete the request
486 IoCompleteRequest(WorkerContext
->Irp
, IO_SOUND_INCREMENT
);
487 // free allocated work item
488 IoFreeWorkItem(WorkerContext
->WorkItem
);
490 FreeItem(WorkerContext
, TAG_PORTCLASS
);
496 IN PDEVICE_OBJECT DeviceObject
,
500 PKSOBJECT_CREATE_ITEM CreateItem
;
501 PPIN_WORKER_CONTEXT Context
;
503 // access the create item
504 CreateItem
= KSCREATE_ITEM_IRP_STORAGE(Irp
);
506 PC_ASSERT(CreateItem
);
508 DPRINT("PcCreatePinDispatch called DeviceObject %p %S Name\n", DeviceObject
, CreateItem
->ObjectClass
.Buffer
);
510 Filter
= (IIrpTarget
*)CreateItem
->Context
;
513 PC_ASSERT(Filter
!= NULL
);
517 Status
= KsReferenceSoftwareBusObject(DeviceExt
->KsDeviceHeader
);
518 if (!NT_SUCCESS(Status
) && Status
!= STATUS_NOT_IMPLEMENTED
)
520 DPRINT("PcCreatePinDispatch failed to reference device header\n");
522 FreeItem(Entry
, TAG_PORTCLASS
);
527 // new pins are instantiated at passive level,
528 // so allocate a work item and context for it
531 Context
= (PPIN_WORKER_CONTEXT
)AllocateItem(NonPagedPool
, sizeof(PIN_WORKER_CONTEXT
), TAG_PORTCLASS
);
534 DPRINT("Failed to allocate worker context\n");
535 Irp
->IoStatus
.Information
= 0;
536 Irp
->IoStatus
.Status
= STATUS_INSUFFICIENT_RESOURCES
;
537 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
538 return STATUS_INSUFFICIENT_RESOURCES
;
541 // allocate work item
542 Context
->WorkItem
= IoAllocateWorkItem(DeviceObject
);
543 if (!Context
->WorkItem
)
545 DPRINT("Failed to allocate workitem\n");
546 FreeItem(Context
, TAG_PORTCLASS
);
547 Irp
->IoStatus
.Information
= 0;
548 Irp
->IoStatus
.Status
= STATUS_INSUFFICIENT_RESOURCES
;
549 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
550 return STATUS_INSUFFICIENT_RESOURCES
;
553 Context
->Filter
= Filter
;
556 DPRINT("Queueing IRP %p Irql %u\n", Irp
, KeGetCurrentIrql());
557 Irp
->IoStatus
.Information
= 0;
558 Irp
->IoStatus
.Status
= STATUS_PENDING
;
559 IoMarkIrpPending(Irp
);
560 IoQueueWorkItem(Context
->WorkItem
, CreatePinWorkerRoutine
, DelayedWorkQueue
, (PVOID
)Context
);
561 return STATUS_PENDING
;
568 PcCreateItemDispatch(
569 IN PDEVICE_OBJECT DeviceObject
,
573 ISubdevice
* SubDevice
;
575 PKSOBJECT_CREATE_ITEM CreateItem
, PinCreateItem
;
577 // access the create item
578 CreateItem
= KSCREATE_ITEM_IRP_STORAGE(Irp
);
580 DPRINT("PcCreateItemDispatch called DeviceObject %p %S Name\n", DeviceObject
, CreateItem
->ObjectClass
.Buffer
);
583 SubDevice
= (ISubdevice
*)CreateItem
->Context
;
586 PC_ASSERT(SubDevice
!= NULL
);
589 Status
= KsReferenceSoftwareBusObject(DeviceExt
->KsDeviceHeader
);
590 if (!NT_SUCCESS(Status
) && Status
!= STATUS_NOT_IMPLEMENTED
)
592 DPRINT("PcCreateItemDispatch failed to reference device header\n");
594 FreeItem(Entry
, TAG_PORTCLASS
);
600 Status
= SubDevice
->NewIrpTarget(&Filter
,
607 if (!NT_SUCCESS(Status
))
609 DPRINT("Failed to get filter object\n");
610 Irp
->IoStatus
.Status
= Status
;
611 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
615 // allocate pin create item
616 PinCreateItem
= (PKSOBJECT_CREATE_ITEM
)AllocateItem(NonPagedPool
, sizeof(KSOBJECT_CREATE_ITEM
), TAG_PORTCLASS
);
620 Irp
->IoStatus
.Status
= STATUS_INSUFFICIENT_RESOURCES
;
621 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
622 return STATUS_INSUFFICIENT_RESOURCES
;
625 // initialize pin create item
626 PinCreateItem
->Context
= (PVOID
)Filter
;
627 PinCreateItem
->Create
= PcCreatePinDispatch
;
628 RtlInitUnicodeString(&PinCreateItem
->ObjectClass
, KSSTRING_Pin
);
629 // FIXME copy security descriptor
631 // now allocate a dispatch object
632 Status
= NewDispatchObject(Irp
, Filter
, 1, PinCreateItem
);
635 Irp
->IoStatus
.Status
= Status
;
636 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
638 return STATUS_SUCCESS
;
646 CPortTopology
* This
;
649 This
= new(NonPagedPool
, TAG_PORTCLASS
) CPortTopology(NULL
);
651 return STATUS_INSUFFICIENT_RESOURCES
;
653 Status
= This
->QueryInterface(IID_IPort
, (PVOID
*)OutPort
);
655 if (!NT_SUCCESS(Status
))
660 DPRINT("NewPortTopology %p Status %x\n", *OutPort
, Status
);
669 CPortTopology
* This
= (CPortTopology
*)Port
;
670 return This
->m_pMiniport
;