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