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