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