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] =
68 /// KS_CATEGORY_TOPOLOGY
69 0xDDA54A40, 0x1E4C, 0x11D1, {0xA0, 0x50, 0x40, 0x57, 0x05, 0xC1, 0x00, 0x00}
73 0x6994AD04, 0x93EF, 0x11D0, {0xA3, 0xCC, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}
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 DPRINT1("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 DPRINT1("IPortTopology_Init called again\n");
223 return STATUS_SUCCESS
;
226 Status
= UnknownMiniport
->QueryInterface(IID_IMiniportTopology
, (PVOID
*)&Miniport
);
227 if (!NT_SUCCESS(Status
))
229 DPRINT1("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 DPRINT1("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 DPRINT1("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 return STATUS_SUCCESS
;
282 CPortTopology::NewRegistryKey(
283 OUT PREGISTRYKEY
*OutRegistryKey
,
284 IN PUNKNOWN OuterUnknown OPTIONAL
,
285 IN ULONG RegistryKeyType
,
286 IN ACCESS_MASK DesiredAccess
,
287 IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL
,
288 IN ULONG CreateOptions OPTIONAL
,
289 OUT PULONG Disposition OPTIONAL
)
291 PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL
);
295 DPRINT("IPortTopology_fnNewRegistryKey called w/o initialized\n");
296 return STATUS_UNSUCCESSFUL
;
298 return PcNewRegistryKey(OutRegistryKey
,
309 //---------------------------------------------------------------
310 // ISubdevice interface
315 CPortTopology::NewIrpTarget(
316 OUT
struct IIrpTarget
**OutTarget
,
319 IN POOL_TYPE PoolType
,
320 IN PDEVICE_OBJECT DeviceObject
,
322 IN KSOBJECT_CREATE
*CreateObject
)
325 IPortFilterTopology
* Filter
;
327 // is there already an instance of the filter
330 // it is, let's return the result
331 *OutTarget
= (IIrpTarget
*)m_Filter
;
333 // increment reference
335 return STATUS_SUCCESS
;
338 // create new instance of filter
339 Status
= NewPortFilterTopology(&Filter
);
340 if (!NT_SUCCESS(Status
))
346 // initialize the filter
347 Status
= Filter
->Init((IPortTopology
*)this);
348 if (!NT_SUCCESS(Status
))
357 *OutTarget
= (IIrpTarget
*)Filter
;
358 // store for later re-use
366 CPortTopology::ReleaseChildren()
368 DPRINT1("ISubDevice_fnReleaseChildren\n");
370 // release the filter
373 // release the miniport
374 DPRINT("Refs %u\n", m_pMiniport
->Release());
376 return STATUS_SUCCESS
;
381 CPortTopology::GetDescriptor(
382 IN SUBDEVICE_DESCRIPTOR
** Descriptor
)
384 DPRINT("ISubDevice_GetDescriptor this %p Descp %p\n", this, m_SubDeviceDescriptor
);
385 *Descriptor
= m_SubDeviceDescriptor
;
386 return STATUS_SUCCESS
;
391 CPortTopology::DataRangeIntersection(
393 IN PKSDATARANGE DataRange
,
394 IN PKSDATARANGE MatchingDataRange
,
395 IN ULONG OutputBufferLength
,
396 OUT PVOID ResultantFormat OPTIONAL
,
397 OUT PULONG ResultantFormatLength
)
399 DPRINT("ISubDevice_DataRangeIntersection this %p\n", this);
403 return m_pMiniport
->DataRangeIntersection (PinId
, DataRange
, MatchingDataRange
, OutputBufferLength
, ResultantFormat
, ResultantFormatLength
);
406 return STATUS_UNSUCCESSFUL
;
411 CPortTopology::PowerChangeNotify(
412 IN POWER_STATE PowerState
)
416 m_pPowerNotify
->PowerChangeNotify(PowerState
);
419 return STATUS_SUCCESS
;
424 CPortTopology::PinCount(
426 IN OUT PULONG FilterNecessary
,
427 IN OUT PULONG FilterCurrent
,
428 IN OUT PULONG FilterPossible
,
429 IN OUT PULONG GlobalCurrent
,
430 IN OUT PULONG GlobalPossible
)
434 m_pPinCount
->PinCount(PinId
, FilterNecessary
, FilterCurrent
, FilterPossible
, GlobalCurrent
, GlobalPossible
);
435 return STATUS_SUCCESS
;
439 // scan filter descriptor
441 return STATUS_UNSUCCESSFUL
;
447 CreatePinWorkerRoutine(
448 IN PDEVICE_OBJECT DeviceObject
,
453 PPIN_WORKER_CONTEXT WorkerContext
= (PPIN_WORKER_CONTEXT
)Context
;
455 DPRINT("CreatePinWorkerRoutine called\n");
457 Status
= WorkerContext
->Filter
->NewIrpTarget(&Pin
,
465 DPRINT1("CreatePinWorkerRoutine Status %x\n", Status
);
467 if (NT_SUCCESS(Status
))
469 // create the dispatch object
470 // FIXME need create item for clock
471 Status
= NewDispatchObject(WorkerContext
->Irp
, Pin
, 0, NULL
);
472 DPRINT("Pin %p\n", Pin
);
475 DPRINT("CreatePinWorkerRoutine completing irp %p\n", WorkerContext
->Irp
);
476 // save status in irp
477 WorkerContext
->Irp
->IoStatus
.Status
= Status
;
478 WorkerContext
->Irp
->IoStatus
.Information
= 0;
479 // complete the request
480 IoCompleteRequest(WorkerContext
->Irp
, IO_SOUND_INCREMENT
);
481 // free allocated work item
482 IoFreeWorkItem(WorkerContext
->WorkItem
);
484 FreeItem(WorkerContext
, TAG_PORTCLASS
);
490 IN PDEVICE_OBJECT DeviceObject
,
494 PKSOBJECT_CREATE_ITEM CreateItem
;
495 PPIN_WORKER_CONTEXT Context
;
497 // access the create item
498 CreateItem
= KSCREATE_ITEM_IRP_STORAGE(Irp
);
500 PC_ASSERT(CreateItem
);
502 DPRINT1("PcCreatePinDispatch called DeviceObject %p %S Name\n", DeviceObject
, CreateItem
->ObjectClass
.Buffer
);
504 Filter
= (IIrpTarget
*)CreateItem
->Context
;
507 PC_ASSERT(Filter
!= NULL
);
511 Status
= KsReferenceSoftwareBusObject(DeviceExt
->KsDeviceHeader
);
512 if (!NT_SUCCESS(Status
) && Status
!= STATUS_NOT_IMPLEMENTED
)
514 DPRINT1("PcCreatePinDispatch failed to reference device header\n");
516 FreeItem(Entry
, TAG_PORTCLASS
);
521 // new pins are instantiated at passive level,
522 // so allocate a work item and context for it
525 Context
= (PPIN_WORKER_CONTEXT
)AllocateItem(NonPagedPool
, sizeof(PIN_WORKER_CONTEXT
), TAG_PORTCLASS
);
528 DPRINT("Failed to allocate worker context\n");
529 Irp
->IoStatus
.Information
= 0;
530 Irp
->IoStatus
.Status
= STATUS_INSUFFICIENT_RESOURCES
;
531 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
532 return STATUS_INSUFFICIENT_RESOURCES
;
535 // allocate work item
536 Context
->WorkItem
= IoAllocateWorkItem(DeviceObject
);
537 if (!Context
->WorkItem
)
539 DPRINT("Failed to allocate workitem\n");
540 FreeItem(Context
, TAG_PORTCLASS
);
541 Irp
->IoStatus
.Information
= 0;
542 Irp
->IoStatus
.Status
= STATUS_INSUFFICIENT_RESOURCES
;
543 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
544 return STATUS_INSUFFICIENT_RESOURCES
;
547 Context
->Filter
= Filter
;
550 DPRINT("Queueing IRP %p Irql %u\n", Irp
, KeGetCurrentIrql());
551 Irp
->IoStatus
.Information
= 0;
552 Irp
->IoStatus
.Status
= STATUS_PENDING
;
553 IoMarkIrpPending(Irp
);
554 IoQueueWorkItem(Context
->WorkItem
, CreatePinWorkerRoutine
, DelayedWorkQueue
, (PVOID
)Context
);
555 return STATUS_PENDING
;
562 PcCreateItemDispatch(
563 IN PDEVICE_OBJECT DeviceObject
,
567 ISubdevice
* SubDevice
;
569 PKSOBJECT_CREATE_ITEM CreateItem
, PinCreateItem
;
571 // access the create item
572 CreateItem
= KSCREATE_ITEM_IRP_STORAGE(Irp
);
574 DPRINT1("PcCreateItemDispatch called DeviceObject %p %S Name\n", DeviceObject
, CreateItem
->ObjectClass
.Buffer
);
577 SubDevice
= (ISubdevice
*)CreateItem
->Context
;
580 PC_ASSERT(SubDevice
!= NULL
);
583 Status
= KsReferenceSoftwareBusObject(DeviceExt
->KsDeviceHeader
);
584 if (!NT_SUCCESS(Status
) && Status
!= STATUS_NOT_IMPLEMENTED
)
586 DPRINT1("PcCreateItemDispatch failed to reference device header\n");
588 FreeItem(Entry
, TAG_PORTCLASS
);
594 Status
= SubDevice
->NewIrpTarget(&Filter
,
601 if (!NT_SUCCESS(Status
))
603 DPRINT1("Failed to get filter object\n");
604 Irp
->IoStatus
.Status
= Status
;
605 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
609 // allocate pin create item
610 PinCreateItem
= (PKSOBJECT_CREATE_ITEM
)AllocateItem(NonPagedPool
, sizeof(KSOBJECT_CREATE_ITEM
), TAG_PORTCLASS
);
614 Irp
->IoStatus
.Status
= STATUS_INSUFFICIENT_RESOURCES
;
615 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
616 return STATUS_INSUFFICIENT_RESOURCES
;
619 // initialize pin create item
620 PinCreateItem
->Context
= (PVOID
)Filter
;
621 PinCreateItem
->Create
= PcCreatePinDispatch
;
622 RtlInitUnicodeString(&PinCreateItem
->ObjectClass
, KSSTRING_Pin
);
623 // FIXME copy security descriptor
625 // now allocate a dispatch object
626 Status
= NewDispatchObject(Irp
, Filter
, 1, PinCreateItem
);
629 Irp
->IoStatus
.Status
= Status
;
630 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
632 return STATUS_SUCCESS
;
640 CPortTopology
* This
;
643 This
= new(NonPagedPool
, TAG_PORTCLASS
) CPortTopology(NULL
);
645 return STATUS_INSUFFICIENT_RESOURCES
;
647 Status
= This
->QueryInterface(IID_IPort
, (PVOID
*)OutPort
);
649 if (!NT_SUCCESS(Status
))
654 DPRINT("NewPortTopology %p Status %x\n", *OutPort
, Status
);
663 CPortTopology
* This
= (CPortTopology
*)Port
;
664 return This
->m_pMiniport
;