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