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