1 /* 2 * COPYRIGHT: See COPYING in the top level directory 3 * PROJECT: ReactOS Kernel Streaming 4 * FILE: drivers/wdm/audio/backpln/portcls/port_dmus.cpp 5 * PURPOSE: DirectMusic Port driver 6 * PROGRAMMER: Johannes Anderwald 7 */ 8 9 #include "private.hpp" 10 11 #define NDEBUG 12 #include <debug.h> 13 14 class CPortDMus : public CUnknownImpl<IPortDMus, ISubdevice> 15 { 16 public: 17 STDMETHODIMP QueryInterface( REFIID InterfaceId, PVOID* Interface); 18 19 IMP_IPortDMus; 20 IMP_ISubdevice; 21 CPortDMus(IUnknown *OuterUnknown){} 22 virtual ~CPortDMus(){} 23 24 protected: 25 26 BOOL m_bInitialized; 27 IMiniportDMus * m_pMiniport; 28 IMiniportMidi * m_pMiniportMidi; 29 DEVICE_OBJECT * m_pDeviceObject; 30 PSERVICEGROUP m_ServiceGroup; 31 PPINCOUNT m_pPinCount; 32 PPOWERNOTIFY m_pPowerNotify; 33 PPORTFILTERDMUS m_Filter; 34 35 PPCFILTER_DESCRIPTOR m_pDescriptor; 36 PSUBDEVICE_DESCRIPTOR m_SubDeviceDescriptor; 37 38 friend VOID GetDMusMiniport(IN IPortDMus * iface, IN PMINIPORTDMUS * Miniport, IN PMINIPORTMIDI * MidiMiniport); 39 40 }; 41 42 static GUID InterfaceGuids[3] = 43 { 44 { 45 /// KS_CATEGORY_AUDIO 46 0x6994AD04, 0x93EF, 0x11D0, {0xA3, 0xCC, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96} 47 }, 48 { 49 /// KS_CATEGORY_RENDER 50 0x65E8773E, 0x8F56, 0x11D0, {0xA3, 0xB9, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96} 51 }, 52 { 53 /// KS_CATEGORY_CAPTURE 54 0x65E8773D, 0x8F56, 0x11D0, {0xA3, 0xB9, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96} 55 } 56 }; 57 58 DEFINE_KSPROPERTY_TOPOLOGYSET(PortFilterDMusTopologySet, TopologyPropertyHandler); 59 DEFINE_KSPROPERTY_PINPROPOSEDATAFORMAT(PortFilterDMusPinSet, PinPropertyHandler, PinPropertyHandler, PinPropertyHandler); 60 61 KSPROPERTY_SET PortDMusPropertySet[] = 62 { 63 { 64 &KSPROPSETID_Topology, 65 sizeof(PortFilterDMusTopologySet) / sizeof(KSPROPERTY_ITEM), 66 (const KSPROPERTY_ITEM*)&PortFilterDMusTopologySet, 67 0, 68 NULL 69 }, 70 { 71 &KSPROPSETID_Pin, 72 sizeof(PortFilterDMusPinSet) / sizeof(KSPROPERTY_ITEM), 73 (const KSPROPERTY_ITEM*)&PortFilterDMusPinSet, 74 0, 75 NULL 76 } 77 }; 78 79 //--------------------------------------------------------------- 80 // IUnknown interface functions 81 // 82 83 NTSTATUS 84 NTAPI 85 CPortDMus::QueryInterface( 86 IN REFIID refiid, 87 OUT PVOID* Output) 88 { 89 UNICODE_STRING GuidString; 90 91 if (IsEqualGUIDAligned(refiid, IID_IPortDMus) || 92 IsEqualGUIDAligned(refiid, IID_IPortMidi) || 93 IsEqualGUIDAligned(refiid, IID_IPort) || 94 IsEqualGUIDAligned(refiid, IID_IUnknown)) 95 { 96 *Output = PVOID(PUNKNOWN((IPortDMus*)this)); 97 PUNKNOWN(*Output)->AddRef(); 98 return STATUS_SUCCESS; 99 } 100 else if (IsEqualGUIDAligned(refiid, IID_ISubdevice)) 101 { 102 *Output = PVOID(PSUBDEVICE(this)); 103 PUNKNOWN(*Output)->AddRef(); 104 return STATUS_SUCCESS; 105 } 106 else if (IsEqualGUIDAligned(refiid, IID_IDrmPort) || 107 IsEqualGUIDAligned(refiid, IID_IDrmPort2)) 108 { 109 return NewIDrmPort((PDRMPORT2*)Output); 110 } 111 else if (IsEqualGUIDAligned(refiid, IID_IPortClsVersion)) 112 { 113 return NewPortClsVersion((PPORTCLSVERSION*)Output); 114 } 115 else if (IsEqualGUIDAligned(refiid, IID_IUnregisterSubdevice)) 116 { 117 return NewIUnregisterSubdevice((PUNREGISTERSUBDEVICE*)Output); 118 } 119 else if (IsEqualGUIDAligned(refiid, IID_IUnregisterPhysicalConnection)) 120 { 121 return NewIUnregisterPhysicalConnection((PUNREGISTERPHYSICALCONNECTION*)Output); 122 } 123 124 if (RtlStringFromGUID(refiid, &GuidString) == STATUS_SUCCESS) 125 { 126 DPRINT("IPortMidi_fnQueryInterface no interface!!! iface %S\n", GuidString.Buffer); 127 RtlFreeUnicodeString(&GuidString); 128 } 129 return STATUS_UNSUCCESSFUL; 130 } 131 132 //--------------------------------------------------------------- 133 // IPort interface functions 134 // 135 136 NTSTATUS 137 NTAPI 138 CPortDMus::GetDeviceProperty( 139 IN DEVICE_REGISTRY_PROPERTY DeviceRegistryProperty, 140 IN ULONG BufferLength, 141 OUT PVOID PropertyBuffer, 142 OUT PULONG ReturnLength) 143 { 144 PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL); 145 146 if (!m_bInitialized) 147 { 148 DPRINT("IPortDMus_fnNewRegistryKey called w/o initialized\n"); 149 return STATUS_UNSUCCESSFUL; 150 } 151 152 return IoGetDeviceProperty(m_pDeviceObject, DeviceRegistryProperty, BufferLength, PropertyBuffer, ReturnLength); 153 } 154 155 NTSTATUS 156 NTAPI 157 CPortDMus::Init( 158 IN PDEVICE_OBJECT DeviceObject, 159 IN PIRP Irp, 160 IN PUNKNOWN UnknownMiniport, 161 IN PUNKNOWN UnknownAdapter OPTIONAL, 162 IN PRESOURCELIST ResourceList) 163 { 164 IMiniportDMus * Miniport = NULL; 165 IMiniportMidi * MidiMiniport = NULL; 166 NTSTATUS Status; 167 PSERVICEGROUP ServiceGroup = NULL; 168 PPINCOUNT PinCount; 169 PPOWERNOTIFY PowerNotify; 170 171 PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL); 172 173 if (m_bInitialized) 174 { 175 DPRINT("IPortDMus_Init called again\n"); 176 return STATUS_SUCCESS; 177 } 178 179 Status = UnknownMiniport->QueryInterface(IID_IMiniportDMus, (PVOID*)&Miniport); 180 if (!NT_SUCCESS(Status)) 181 { 182 // check for legacy interface 183 Status = UnknownMiniport->QueryInterface(IID_IMiniportMidi, (PVOID*)&MidiMiniport); 184 if (!NT_SUCCESS(Status)) 185 { 186 DPRINT("IPortDMus_Init called with invalid IMiniport adapter\n"); 187 return STATUS_INVALID_PARAMETER; 188 } 189 } 190 191 // Initialize port object 192 m_pMiniport = Miniport; 193 m_pMiniportMidi = MidiMiniport; 194 m_pDeviceObject = DeviceObject; 195 m_bInitialized = TRUE; 196 197 if (Miniport) 198 { 199 // initialize IMiniportDMus 200 Status = Miniport->Init(UnknownAdapter, ResourceList, this, &ServiceGroup); 201 if (!NT_SUCCESS(Status)) 202 { 203 DPRINT("IMiniportDMus_Init failed with %x\n", Status); 204 m_bInitialized = FALSE; 205 return Status; 206 } 207 208 // get the miniport device descriptor 209 Status = Miniport->GetDescription(&m_pDescriptor); 210 if (!NT_SUCCESS(Status)) 211 { 212 DPRINT("failed to get description\n"); 213 Miniport->Release(); 214 m_bInitialized = FALSE; 215 return Status; 216 } 217 218 // increment reference on miniport adapter 219 Miniport->AddRef(); 220 221 } 222 else 223 { 224 // initialize IMiniportMidi 225 Status = MidiMiniport->Init(UnknownAdapter, ResourceList, (IPortMidi*)this, &ServiceGroup); 226 if (!NT_SUCCESS(Status)) 227 { 228 DPRINT("IMiniportMidi_Init failed with %x\n", Status); 229 m_bInitialized = FALSE; 230 return Status; 231 } 232 233 // get the miniport device descriptor 234 Status = MidiMiniport->GetDescription(&m_pDescriptor); 235 if (!NT_SUCCESS(Status)) 236 { 237 DPRINT("failed to get description\n"); 238 MidiMiniport->Release(); 239 m_bInitialized = FALSE; 240 return Status; 241 } 242 243 // increment reference on miniport adapter 244 MidiMiniport->AddRef(); 245 } 246 247 // create the subdevice descriptor 248 Status = PcCreateSubdeviceDescriptor(&m_SubDeviceDescriptor, 249 3, 250 InterfaceGuids, 251 0, 252 NULL, 253 2, 254 PortDMusPropertySet, 255 0, 256 0, 257 0, 258 NULL, 259 0, 260 NULL, 261 m_pDescriptor); 262 263 if (!NT_SUCCESS(Status)) 264 { 265 DPRINT("Failed to create descriptor\n"); 266 267 if (Miniport) 268 Miniport->Release(); 269 else 270 MidiMiniport->Release(); 271 272 m_bInitialized = FALSE; 273 return Status; 274 } 275 276 if (m_ServiceGroup == NULL && ServiceGroup) 277 { 278 // register service group 279 m_ServiceGroup = ServiceGroup; 280 } 281 282 // check if it supports IPinCount interface 283 Status = UnknownMiniport->QueryInterface(IID_IPinCount, (PVOID*)&PinCount); 284 if (NT_SUCCESS(Status)) 285 { 286 // store IPinCount interface 287 m_pPinCount = PinCount; 288 } 289 290 // does the Miniport adapter support IPowerNotify interface*/ 291 Status = UnknownMiniport->QueryInterface(IID_IPowerNotify, (PVOID*)&PowerNotify); 292 if (NT_SUCCESS(Status)) 293 { 294 // store reference 295 m_pPowerNotify = PowerNotify; 296 } 297 298 return STATUS_SUCCESS; 299 } 300 301 NTSTATUS 302 NTAPI 303 CPortDMus::NewRegistryKey( 304 OUT PREGISTRYKEY *OutRegistryKey, 305 IN PUNKNOWN OuterUnknown OPTIONAL, 306 IN ULONG RegistryKeyType, 307 IN ACCESS_MASK DesiredAccess, 308 IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, 309 IN ULONG CreateOptions OPTIONAL, 310 OUT PULONG Disposition OPTIONAL) 311 { 312 PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL); 313 314 if (!m_bInitialized) 315 { 316 DPRINT("IPortDMus_fnNewRegistryKey called w/o initialized\n"); 317 return STATUS_UNSUCCESSFUL; 318 } 319 320 return PcNewRegistryKey(OutRegistryKey, 321 OuterUnknown, 322 RegistryKeyType, 323 DesiredAccess, 324 m_pDeviceObject, 325 (ISubdevice*)this, 326 ObjectAttributes, 327 CreateOptions, 328 Disposition); 329 } 330 331 VOID 332 NTAPI 333 CPortDMus::Notify( 334 IN PSERVICEGROUP ServiceGroup OPTIONAL) 335 { 336 if (ServiceGroup) 337 { 338 ServiceGroup->RequestService (); 339 return; 340 } 341 342 PC_ASSERT(m_ServiceGroup); 343 344 // notify miniport service group 345 m_ServiceGroup->RequestService(); 346 347 // notify stream miniport service group 348 if (m_Filter) 349 { 350 m_Filter->NotifyPins(); 351 } 352 } 353 354 VOID 355 NTAPI 356 CPortDMus::RegisterServiceGroup( 357 IN PSERVICEGROUP ServiceGroup) 358 { 359 PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL); 360 361 m_ServiceGroup = ServiceGroup; 362 363 ServiceGroup->AddMember(PSERVICESINK(this)); 364 } 365 //--------------------------------------------------------------- 366 // ISubdevice interface 367 // 368 369 NTSTATUS 370 NTAPI 371 CPortDMus::NewIrpTarget( 372 OUT struct IIrpTarget **OutTarget, 373 IN PCWSTR Name, 374 IN PUNKNOWN Unknown, 375 IN POOL_TYPE PoolType, 376 IN PDEVICE_OBJECT DeviceObject, 377 IN PIRP Irp, 378 IN KSOBJECT_CREATE *CreateObject) 379 { 380 NTSTATUS Status; 381 PPORTFILTERDMUS Filter; 382 383 DPRINT("ISubDevice_NewIrpTarget this %p\n", this); 384 385 if (m_Filter) 386 { 387 *OutTarget = (IIrpTarget*)m_Filter; 388 return STATUS_SUCCESS; 389 } 390 391 Status = NewPortFilterDMus(&Filter); 392 if (!NT_SUCCESS(Status)) 393 { 394 return Status; 395 } 396 397 Status = Filter->Init(PPORTDMUS(this)); 398 if (!NT_SUCCESS(Status)) 399 { 400 Filter->Release(); 401 return Status; 402 } 403 404 *OutTarget = (IIrpTarget*)Filter; 405 return Status; 406 } 407 408 NTSTATUS 409 NTAPI 410 CPortDMus::ReleaseChildren() 411 { 412 UNIMPLEMENTED; 413 return STATUS_UNSUCCESSFUL; 414 } 415 416 NTSTATUS 417 NTAPI 418 CPortDMus::GetDescriptor( 419 IN SUBDEVICE_DESCRIPTOR ** Descriptor) 420 { 421 DPRINT("ISubDevice_GetDescriptor this %p\n", this); 422 *Descriptor = m_SubDeviceDescriptor; 423 return STATUS_SUCCESS; 424 } 425 426 NTSTATUS 427 NTAPI 428 CPortDMus::DataRangeIntersection( 429 IN ULONG PinId, 430 IN PKSDATARANGE DataRange, 431 IN PKSDATARANGE MatchingDataRange, 432 IN ULONG OutputBufferLength, 433 OUT PVOID ResultantFormat OPTIONAL, 434 OUT PULONG ResultantFormatLength) 435 { 436 DPRINT("ISubDevice_DataRangeIntersection this %p\n", this); 437 438 if (m_pMiniport) 439 { 440 return m_pMiniport->DataRangeIntersection (PinId, DataRange, MatchingDataRange, OutputBufferLength, ResultantFormat, ResultantFormatLength); 441 } 442 443 return STATUS_UNSUCCESSFUL; 444 } 445 446 NTSTATUS 447 NTAPI 448 CPortDMus::PowerChangeNotify( 449 IN POWER_STATE PowerState) 450 { 451 if (m_pPowerNotify) 452 { 453 m_pPowerNotify->PowerChangeNotify(PowerState); 454 } 455 456 return STATUS_SUCCESS; 457 } 458 459 NTSTATUS 460 NTAPI 461 CPortDMus::PinCount( 462 IN ULONG PinId, 463 IN OUT PULONG FilterNecessary, 464 IN OUT PULONG FilterCurrent, 465 IN OUT PULONG FilterPossible, 466 IN OUT PULONG GlobalCurrent, 467 IN OUT PULONG GlobalPossible) 468 { 469 if (m_pPinCount) 470 { 471 m_pPinCount->PinCount(PinId, FilterNecessary, FilterCurrent, FilterPossible, GlobalCurrent, GlobalPossible); 472 return STATUS_SUCCESS; 473 } 474 475 // FIXME 476 // scan filter descriptor 477 478 return STATUS_UNSUCCESSFUL; 479 } 480 481 NTSTATUS 482 NewPortDMus( 483 OUT PPORT* OutPort) 484 { 485 NTSTATUS Status; 486 CPortDMus * Port = new(NonPagedPool, TAG_PORTCLASS) CPortDMus(NULL); 487 if (!Port) 488 return STATUS_INSUFFICIENT_RESOURCES; 489 490 Status = Port->QueryInterface(IID_IPort, (PVOID*)OutPort); 491 492 if (!NT_SUCCESS(Status)) 493 { 494 delete Port; 495 } 496 497 DPRINT("NewPortDMus %p Status %u\n", Port, Status); 498 return Status; 499 500 } 501 502 VOID 503 GetDMusMiniport( 504 IN IPortDMus * iface, 505 IN PMINIPORTDMUS * Miniport, 506 IN PMINIPORTMIDI * MidiMiniport) 507 { 508 CPortDMus * This = (CPortDMus*)iface; 509 510 *Miniport = This->m_pMiniport; 511 *MidiMiniport = This->m_pMiniportMidi; 512 } 513