1 /* 2 * COPYRIGHT: See COPYING in the top level directory 3 * PROJECT: ReactOS Kernel Streaming 4 * FILE: drivers/wdm/audio/backpln/portcls/port_wavecyclic.cpp 5 * PURPOSE: WaveCyclic 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 GUID IID_IDmaChannelSlave; 18 19 class CPortWaveCyclic : public IPortWaveCyclic, 20 public IPortEvents, 21 public ISubdevice 22 { 23 public: 24 STDMETHODIMP QueryInterface( REFIID InterfaceId, PVOID* Interface); 25 26 STDMETHODIMP_(ULONG) AddRef() 27 { 28 InterlockedIncrement(&m_Ref); 29 return m_Ref; 30 } 31 STDMETHODIMP_(ULONG) Release() 32 { 33 InterlockedDecrement(&m_Ref); 34 if (!m_Ref) 35 { 36 //delete this; 37 return 0; 38 } 39 return m_Ref; 40 } 41 IMP_IPortWaveCyclic; 42 IMP_ISubdevice; 43 IMP_IPortEvents; 44 CPortWaveCyclic(IUnknown *OuterUnknown){} 45 virtual ~CPortWaveCyclic(){} 46 47 protected: 48 PDEVICE_OBJECT m_pDeviceObject; 49 PMINIPORTWAVECYCLIC m_pMiniport; 50 PPINCOUNT m_pPinCount; 51 PPOWERNOTIFY m_pPowerNotify; 52 PPCFILTER_DESCRIPTOR m_pDescriptor; 53 PSUBDEVICE_DESCRIPTOR m_SubDeviceDescriptor; 54 IPortFilterWaveCyclic * m_Filter; 55 56 LONG m_Ref; 57 58 friend PMINIPORTWAVECYCLIC GetWaveCyclicMiniport(IN IPortWaveCyclic* iface); 59 friend PDEVICE_OBJECT GetDeviceObject(PPORTWAVECYCLIC iface); 60 }; 61 62 GUID KSPROPERTY_SETID_Topology = {0x720D4AC0L, 0x7533, 0x11D0, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}}; 63 64 static GUID InterfaceGuids[4] = 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 ///KSCATEGORY_AUDIO_DEVICE 80 0xFBF6F530L, 0x07B9, 0x11D2, {0xA7, 0x1E, 0x00, 0x00, 0xF8, 0x00, 0x47, 0x88} 81 } 82 83 }; 84 85 DEFINE_KSPROPERTY_TOPOLOGYSET(PortFilterWaveCyclicTopologySet, TopologyPropertyHandler); 86 DEFINE_KSPROPERTY_PINPROPOSEDATAFORMAT(PortFilterWaveCyclicPinSet, PinPropertyHandler, PinPropertyHandler, PinPropertyHandler); 87 88 KSPROPERTY_SET WaveCyclicPropertySet[] = 89 { 90 { 91 &KSPROPSETID_Topology, 92 sizeof(PortFilterWaveCyclicTopologySet) / sizeof(KSPROPERTY_ITEM), 93 (const KSPROPERTY_ITEM*)&PortFilterWaveCyclicTopologySet, 94 0, 95 NULL 96 }, 97 { 98 &KSPROPSETID_Pin, 99 sizeof(PortFilterWaveCyclicPinSet) / sizeof(KSPROPERTY_ITEM), 100 (const KSPROPERTY_ITEM*)&PortFilterWaveCyclicPinSet, 101 0, 102 NULL 103 } 104 }; 105 106 //KSEVENTSETID_LoopedStreaming, Type = KSEVENT_LOOPEDSTREAMING_POSITION 107 //KSEVENTSETID_Connection, Type = KSEVENT_CONNECTION_ENDOFSTREAM, 108 109 110 //--------------------------------------------------------------- 111 // IPortEvents 112 // 113 114 void 115 NTAPI 116 CPortWaveCyclic::AddEventToEventList( 117 IN PKSEVENT_ENTRY EventEntry) 118 { 119 UNIMPLEMENTED; 120 } 121 122 123 void 124 NTAPI 125 CPortWaveCyclic::GenerateEventList( 126 IN GUID* Set OPTIONAL, 127 IN ULONG EventId, 128 IN BOOL PinEvent, 129 IN ULONG PinId, 130 IN BOOL NodeEvent, 131 IN ULONG NodeId) 132 { 133 UNIMPLEMENTED; 134 } 135 136 //--------------------------------------------------------------- 137 // IUnknown interface functions 138 // 139 140 NTSTATUS 141 NTAPI 142 CPortWaveCyclic::QueryInterface( 143 IN REFIID refiid, 144 OUT PVOID* Output) 145 { 146 UNICODE_STRING GuidString; 147 148 if (IsEqualGUIDAligned(refiid, IID_IPortWaveCyclic) || 149 IsEqualGUIDAligned(refiid, IID_IPort) || 150 IsEqualGUIDAligned(refiid, IID_IUnknown)) 151 { 152 *Output = PVOID(PPORTWAVECYCLIC(this)); 153 PUNKNOWN(*Output)->AddRef(); 154 return STATUS_SUCCESS; 155 } 156 else if (IsEqualGUIDAligned(refiid, IID_IPortEvents)) 157 { 158 *Output = PVOID(PPORTEVENTS(this)); 159 PUNKNOWN(*Output)->AddRef(); 160 return STATUS_SUCCESS; 161 } 162 else if (IsEqualGUIDAligned(refiid, IID_ISubdevice)) 163 { 164 *Output = PVOID(PSUBDEVICE(this)); 165 PUNKNOWN(*Output)->AddRef(); 166 return STATUS_SUCCESS; 167 } 168 else if (IsEqualGUIDAligned(refiid, IID_IPortClsVersion)) 169 { 170 return NewPortClsVersion((PPORTCLSVERSION*)Output); 171 } 172 else if (IsEqualGUIDAligned(refiid, IID_IDrmPort) || 173 IsEqualGUIDAligned(refiid, IID_IDrmPort2)) 174 { 175 return NewIDrmPort((PDRMPORT2*)Output); 176 } 177 else if (IsEqualGUIDAligned(refiid, IID_IUnregisterSubdevice)) 178 { 179 return NewIUnregisterSubdevice((PUNREGISTERSUBDEVICE*)Output); 180 } 181 else if (IsEqualGUIDAligned(refiid, IID_IUnregisterPhysicalConnection)) 182 { 183 return NewIUnregisterPhysicalConnection((PUNREGISTERPHYSICALCONNECTION*)Output); 184 } 185 186 if (RtlStringFromGUID(refiid, &GuidString) == STATUS_SUCCESS) 187 { 188 DPRINT1("IPortWaveCyclic_fnQueryInterface no interface!!! iface %S\n", GuidString.Buffer); 189 RtlFreeUnicodeString(&GuidString); 190 } 191 192 return STATUS_UNSUCCESSFUL; 193 } 194 195 //--------------------------------------------------------------- 196 // IPort interface functions 197 // 198 199 NTSTATUS 200 NTAPI 201 CPortWaveCyclic::GetDeviceProperty( 202 IN DEVICE_REGISTRY_PROPERTY DeviceRegistryProperty, 203 IN ULONG BufferLength, 204 OUT PVOID PropertyBuffer, 205 OUT PULONG ReturnLength) 206 { 207 PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL); 208 209 return IoGetDeviceProperty(m_pDeviceObject, DeviceRegistryProperty, BufferLength, PropertyBuffer, ReturnLength); 210 } 211 212 NTSTATUS 213 NTAPI 214 CPortWaveCyclic::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 IMiniportWaveCyclic * Miniport; 222 NTSTATUS Status; 223 PPINCOUNT PinCount; 224 PPOWERNOTIFY PowerNotify; 225 226 DPRINT("IPortWaveCyclic_Init entered %p\n", this); 227 PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL); 228 229 Status = UnknownMiniport->QueryInterface(IID_IMiniportWaveCyclic, (PVOID*)&Miniport); 230 if (!NT_SUCCESS(Status)) 231 { 232 DPRINT("IPortWaveCyclic_Init called with invalid IMiniport adapter\n"); 233 return STATUS_INVALID_PARAMETER; 234 } 235 236 // Initialize port object 237 m_pMiniport = Miniport; 238 m_pDeviceObject = DeviceObject; 239 240 // initialize miniport 241 Status = Miniport->Init(UnknownAdapter, ResourceList, this); 242 if (!NT_SUCCESS(Status)) 243 { 244 DPRINT("IMiniportWaveCyclic_Init failed with %x\n", Status); 245 Miniport->Release(); 246 return Status; 247 } 248 249 250 // get the miniport device descriptor 251 Status = Miniport->GetDescription(&m_pDescriptor); 252 if (!NT_SUCCESS(Status)) 253 { 254 DPRINT("failed to get description\n"); 255 Miniport->Release(); 256 return Status; 257 } 258 259 // create the subdevice descriptor 260 Status = PcCreateSubdeviceDescriptor(&m_SubDeviceDescriptor, 261 4, 262 InterfaceGuids, 263 0, 264 NULL, 265 2, 266 WaveCyclicPropertySet, 267 0, 268 0, 269 0, 270 NULL, 271 0, 272 NULL, 273 m_pDescriptor); 274 275 if (!NT_SUCCESS(Status)) 276 { 277 DPRINT("PcCreateSubdeviceDescriptor failed with %x\n", Status); 278 Miniport->Release(); 279 return Status; 280 } 281 282 // store for node property requests 283 m_SubDeviceDescriptor->UnknownMiniport = UnknownMiniport; 284 285 // check if it supports IPinCount interface 286 Status = UnknownMiniport->QueryInterface(IID_IPinCount, (PVOID*)&PinCount); 287 if (NT_SUCCESS(Status)) 288 { 289 // store IPinCount interface 290 m_pPinCount = PinCount; 291 } 292 293 // does the Miniport adapter support IPowerNotify interface*/ 294 Status = UnknownMiniport->QueryInterface(IID_IPowerNotify, (PVOID*)&PowerNotify); 295 if (NT_SUCCESS(Status)) 296 { 297 // store reference 298 m_pPowerNotify = PowerNotify; 299 } 300 301 DPRINT("IPortWaveCyclic successfully initialized\n"); 302 return STATUS_SUCCESS; 303 } 304 305 306 NTSTATUS 307 NTAPI 308 CPortWaveCyclic::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 return PcNewRegistryKey(OutRegistryKey, OuterUnknown, RegistryKeyType, DesiredAccess, m_pDeviceObject, (ISubdevice*)this, ObjectAttributes, CreateOptions, Disposition); 320 } 321 322 323 //--------------------------------------------------------------- 324 // IPortWaveCyclic interface functions 325 // 326 327 NTSTATUS 328 NTAPI 329 CPortWaveCyclic::NewMasterDmaChannel( 330 OUT PDMACHANNEL* DmaChannel, 331 IN PUNKNOWN OuterUnknown, 332 IN PRESOURCELIST ResourceList OPTIONAL, 333 IN ULONG MaximumLength, 334 IN BOOLEAN Dma32BitAddresses, 335 IN BOOLEAN Dma64BitAddresses, 336 IN DMA_WIDTH DmaWidth, 337 IN DMA_SPEED DmaSpeed) 338 { 339 NTSTATUS Status; 340 DEVICE_DESCRIPTION DeviceDescription; 341 342 PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL); 343 344 Status = PcDmaMasterDescription(ResourceList, (Dma32BitAddresses | Dma64BitAddresses), Dma32BitAddresses, 0, Dma64BitAddresses, DmaWidth, DmaSpeed, MaximumLength, 0, &DeviceDescription); 345 if (NT_SUCCESS(Status)) 346 { 347 return PcNewDmaChannel(DmaChannel, OuterUnknown, NonPagedPool, &DeviceDescription, m_pDeviceObject); 348 } 349 350 return Status; 351 } 352 353 NTSTATUS 354 NTAPI 355 CPortWaveCyclic::NewSlaveDmaChannel( 356 OUT PDMACHANNELSLAVE* OutDmaChannel, 357 IN PUNKNOWN OuterUnknown, 358 IN PRESOURCELIST ResourceList OPTIONAL, 359 IN ULONG DmaIndex, 360 IN ULONG MaximumLength, 361 IN BOOLEAN DemandMode, 362 IN DMA_SPEED DmaSpeed) 363 { 364 DEVICE_DESCRIPTION DeviceDescription; 365 PDMACHANNEL DmaChannel; 366 NTSTATUS Status; 367 368 PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL); 369 370 // FIXME 371 // Check for F-Type DMA Support 372 // 373 374 Status = PcDmaSlaveDescription(ResourceList, DmaIndex, DemandMode, TRUE, DmaSpeed, MaximumLength, 0, &DeviceDescription); 375 if (NT_SUCCESS(Status)) 376 { 377 Status = PcNewDmaChannel(&DmaChannel, OuterUnknown, NonPagedPool, &DeviceDescription, m_pDeviceObject); 378 if (NT_SUCCESS(Status)) 379 { 380 Status = DmaChannel->QueryInterface(IID_IDmaChannelSlave, (PVOID*)OutDmaChannel); 381 DmaChannel->Release(); 382 } 383 } 384 385 return Status; 386 } 387 388 VOID 389 NTAPI 390 CPortWaveCyclic::Notify( 391 IN PSERVICEGROUP ServiceGroup) 392 { 393 ServiceGroup->RequestService (); 394 } 395 396 //--------------------------------------------------------------- 397 // ISubdevice interface 398 // 399 400 NTSTATUS 401 NTAPI 402 CPortWaveCyclic::NewIrpTarget( 403 OUT struct IIrpTarget **OutTarget, 404 IN PCWSTR Name, 405 IN PUNKNOWN Unknown, 406 IN POOL_TYPE PoolType, 407 IN PDEVICE_OBJECT DeviceObject, 408 IN PIRP Irp, 409 IN KSOBJECT_CREATE *CreateObject) 410 { 411 NTSTATUS Status; 412 IPortFilterWaveCyclic * Filter; 413 414 DPRINT("ISubDevice_NewIrpTarget this %p\n", this); 415 416 // is there already an instance of the filter 417 if (m_Filter) 418 { 419 // it is, let's return the result 420 *OutTarget = (IIrpTarget*)m_Filter; 421 422 // increment reference 423 m_Filter->AddRef(); 424 return STATUS_SUCCESS; 425 } 426 427 // create new instance of filter 428 Status = NewPortFilterWaveCyclic(&Filter); 429 if (!NT_SUCCESS(Status)) 430 { 431 // not enough memory 432 return Status; 433 } 434 435 // initialize the filter 436 Status = Filter->Init((IPortWaveCyclic*)this); 437 if (!NT_SUCCESS(Status)) 438 { 439 // destroy filter 440 Filter->Release(); 441 // return status 442 return Status; 443 } 444 445 // store result 446 *OutTarget = (IIrpTarget*)Filter; 447 // store for later re-use 448 m_Filter = Filter; 449 // return status 450 return Status; 451 } 452 453 454 NTSTATUS 455 NTAPI 456 CPortWaveCyclic::ReleaseChildren() 457 { 458 DPRINT("ISubDevice_fnReleaseChildren\n"); 459 460 // release the filter 461 m_Filter->Release(); 462 463 if (m_pPinCount) 464 { 465 // release pincount interface 466 m_pPinCount->Release(); 467 } 468 469 if (m_pPowerNotify) 470 { 471 // release power notify interface 472 m_pPowerNotify->Release(); 473 } 474 475 // now release the miniport 476 m_pMiniport->Release(); 477 478 return STATUS_SUCCESS; 479 } 480 481 482 NTSTATUS 483 NTAPI 484 CPortWaveCyclic::GetDescriptor( 485 IN SUBDEVICE_DESCRIPTOR ** Descriptor) 486 { 487 PC_ASSERT(m_SubDeviceDescriptor != NULL); 488 489 *Descriptor = m_SubDeviceDescriptor; 490 491 DPRINT("ISubDevice_GetDescriptor this %p desc %p\n", this, m_SubDeviceDescriptor); 492 return STATUS_SUCCESS; 493 } 494 495 496 NTSTATUS 497 NTAPI 498 CPortWaveCyclic::DataRangeIntersection( 499 IN ULONG PinId, 500 IN PKSDATARANGE DataRange, 501 IN PKSDATARANGE MatchingDataRange, 502 IN ULONG OutputBufferLength, 503 OUT PVOID ResultantFormat OPTIONAL, 504 OUT PULONG ResultantFormatLength) 505 { 506 DPRINT("ISubDevice_DataRangeIntersection this %p\n", this); 507 508 if (m_pMiniport) 509 { 510 return m_pMiniport->DataRangeIntersection (PinId, DataRange, MatchingDataRange, OutputBufferLength, ResultantFormat, ResultantFormatLength); 511 } 512 513 return STATUS_UNSUCCESSFUL; 514 } 515 516 517 NTSTATUS 518 NTAPI 519 CPortWaveCyclic::PowerChangeNotify( 520 IN POWER_STATE PowerState) 521 { 522 if (m_pPowerNotify) 523 { 524 m_pPowerNotify->PowerChangeNotify(PowerState); 525 } 526 527 return STATUS_SUCCESS; 528 } 529 530 NTSTATUS 531 NTAPI 532 CPortWaveCyclic::PinCount( 533 IN ULONG PinId, 534 IN OUT PULONG FilterNecessary, 535 IN OUT PULONG FilterCurrent, 536 IN OUT PULONG FilterPossible, 537 IN OUT PULONG GlobalCurrent, 538 IN OUT PULONG GlobalPossible) 539 { 540 if (m_pPinCount) 541 { 542 m_pPinCount->PinCount(PinId, FilterNecessary, FilterCurrent, FilterPossible, GlobalCurrent, GlobalPossible); 543 return STATUS_SUCCESS; 544 } 545 546 // FIXME 547 // scan filter descriptor 548 549 return STATUS_UNSUCCESSFUL; 550 } 551 552 553 ///-------------------------------------------------------------- 554 PMINIPORTWAVECYCLIC 555 GetWaveCyclicMiniport( 556 IN IPortWaveCyclic* iface) 557 { 558 CPortWaveCyclic * This = (CPortWaveCyclic *)iface; 559 return This->m_pMiniport; 560 } 561 562 PDEVICE_OBJECT 563 GetDeviceObject( 564 PPORTWAVECYCLIC iface) 565 { 566 CPortWaveCyclic * This = (CPortWaveCyclic *)iface; 567 return This->m_pDeviceObject; 568 } 569 570 //--------------------------------------------------------------- 571 // IPortWaveCyclic constructor 572 // 573 574 NTSTATUS 575 NewPortWaveCyclic( 576 OUT PPORT* OutPort) 577 { 578 NTSTATUS Status; 579 CPortWaveCyclic * Port; 580 581 Port = new(NonPagedPool, TAG_PORTCLASS)CPortWaveCyclic(NULL); 582 if (!Port) 583 return STATUS_INSUFFICIENT_RESOURCES; 584 585 Status = Port->QueryInterface(IID_IPort, (PVOID*)OutPort); 586 587 if (!NT_SUCCESS(Status)) 588 { 589 delete Port; 590 } 591 592 DPRINT("NewPortWaveCyclic %p Status %u\n", Port, Status); 593 return Status; 594 } 595 596