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