From fee01ee6d46a5a558c282d527b0d3fb55c6bd145 Mon Sep 17 00:00:00 2001 From: Johannes Anderwald Date: Thu, 24 Sep 2009 14:54:58 +0000 Subject: [PATCH] - Rewrite mixer enumeration functions - WDMAUD should reports a mixer device each time it sees a KSNODETYPE_ADC / KSNODETYPE_DAC svn path=/trunk/; revision=43129 --- .../drivers/wdm/audio/legacy/wdmaud/mixer.c | 278 +++++++++++------- .../drivers/wdm/audio/legacy/wdmaud/wdmaud.h | 5 + 2 files changed, 180 insertions(+), 103 deletions(-) diff --git a/reactos/drivers/wdm/audio/legacy/wdmaud/mixer.c b/reactos/drivers/wdm/audio/legacy/wdmaud/mixer.c index 4cdc139c6d0..c8c239f817d 100644 --- a/reactos/drivers/wdm/audio/legacy/wdmaud/mixer.c +++ b/reactos/drivers/wdm/audio/legacy/wdmaud/mixer.c @@ -8,152 +8,224 @@ */ #include "wdmaud.h" -ULONG -IsVirtualDeviceATopologyFilter( - IN PDEVICE_OBJECT DeviceObject, - ULONG VirtualDeviceId) -{ - KSP_PIN Pin; - ULONG Count, BytesReturned, Index, NumPins; - NTSTATUS Status; - KSPIN_COMMUNICATION Communication; - PWDMAUD_DEVICE_EXTENSION DeviceExtension; - ULONG MixerPinCount; +const GUID KSNODETYPE_DAC = {0x507AE360L, 0xC554, 0x11D0, {0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1}}; +const GUID KSNODETYPE_ADC = {0x4D837FE0L, 0xC555, 0x11D0, {0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1}}; - Pin.Property.Set = KSPROPSETID_Sysaudio; - Pin.Property.Id = KSPROPERTY_SYSAUDIO_DEVICE_COUNT; - Pin.Property.Flags = KSPROPERTY_TYPE_GET; +ULONG +GetSysAudioDeviceCount( + IN PDEVICE_OBJECT DeviceObject) +{ + PWDMAUD_DEVICE_EXTENSION DeviceExtension; + KSPROPERTY Pin; + ULONG Count, BytesReturned; + NTSTATUS Status; + + /* setup the query request */ + Pin.Set = KSPROPSETID_Sysaudio; + Pin.Id = KSPROPERTY_SYSAUDIO_DEVICE_COUNT; + Pin.Flags = KSPROPERTY_TYPE_GET; DeviceExtension = (PWDMAUD_DEVICE_EXTENSION)DeviceObject->DeviceExtension; + /* query sysaudio for the device count */ Status = KsSynchronousIoControlDevice(DeviceExtension->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&Pin, sizeof(KSPROPERTY), (PVOID)&Count, sizeof(ULONG), &BytesReturned); if (!NT_SUCCESS(Status)) - return FALSE; + return 0; - if (VirtualDeviceId >= Count) - return FALSE; + return Count; +} - /* query number of pins */ - Pin.Reserved = VirtualDeviceId; // see sysaudio +NTSTATUS +OpenSysAudioDeviceByIndex( + IN PDEVICE_OBJECT DeviceObject, + IN ULONG DeviceIndex, + IN PHANDLE DeviceHandle, + IN PFILE_OBJECT * FileObject) +{ + LPWSTR Device; + HANDLE hDevice; + ULONG BytesReturned; + KSP_PIN Pin; + NTSTATUS Status; + PWDMAUD_DEVICE_EXTENSION DeviceExtension; + + /* first check if the device index is within bounds */ + if (DeviceIndex >= GetSysAudioDeviceCount(DeviceObject)) + return STATUS_INVALID_PARAMETER; + + /* setup the query request */ + Pin.Property.Set = KSPROPSETID_Sysaudio; + Pin.Property.Id = KSPROPERTY_SYSAUDIO_DEVICE_INTERFACE_NAME; Pin.Property.Flags = KSPROPERTY_TYPE_GET; - Pin.Property.Set = KSPROPSETID_Pin; - Pin.Property.Id = KSPROPERTY_PIN_CTYPES; - Pin.PinId = 0; + Pin.PinId = DeviceIndex; + + + DeviceExtension = (PWDMAUD_DEVICE_EXTENSION)DeviceObject->DeviceExtension; + + /* query sysaudio for the device path */ + Status = KsSynchronousIoControlDevice(DeviceExtension->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&Pin, sizeof(KSPROPERTY) + sizeof(ULONG), NULL, 0, &BytesReturned); + + /* check if the request failed */ + if (Status != STATUS_BUFFER_TOO_SMALL || BytesReturned == 0) + return STATUS_UNSUCCESSFUL; + + /* allocate buffer for the device */ + Device = ExAllocatePool(NonPagedPool, BytesReturned); + if (!Device) + return STATUS_INSUFFICIENT_RESOURCES; + + /* query sysaudio again for the device path */ + Status = KsSynchronousIoControlDevice(DeviceExtension->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&Pin, sizeof(KSPROPERTY) + sizeof(ULONG), (PVOID)Device, BytesReturned, &BytesReturned); - Status = KsSynchronousIoControlDevice(DeviceExtension->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&Pin, sizeof(KSP_PIN), (PVOID)&NumPins, sizeof(ULONG), &BytesReturned); if (!NT_SUCCESS(Status)) - return FALSE; - - /* enumerate now all pins */ - MixerPinCount = 0; - for(Index = 0; Index < NumPins; Index++) { - Pin.PinId = Index; - Pin.Property.Id = KSPROPERTY_PIN_COMMUNICATION; - Communication = KSPIN_COMMUNICATION_NONE; + /* failed */ + ExFreePool(Device); + return Status; + } - /* get pin communication type */ - Status = KsSynchronousIoControlDevice(DeviceExtension->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&Pin, sizeof(KSP_PIN), (PVOID)&Communication, sizeof(KSPIN_COMMUNICATION), &BytesReturned); - if (NT_SUCCESS(Status)) + /* now open the device */ + Status = WdmAudOpenSysAudioDevice(Device, &hDevice); + + /* free device buffer */ + ExFreePool(Device); + + if (!NT_SUCCESS(Status)) + { + return Status; + } + + *DeviceHandle = hDevice; + + if (FileObject) + { + Status = ObReferenceObjectByHandle(hDevice, FILE_READ_DATA | FILE_WRITE_DATA, IoFileObjectType, KernelMode, (PVOID*)FileObject, NULL); + + if (!NT_SUCCESS(Status)) { - if (Communication == KSPIN_COMMUNICATION_NONE) - MixerPinCount++; + ZwClose(hDevice); } - } - if (MixerPinCount == NumPins) + return Status; +} + +NTSTATUS +GetFilterNodeTypes( + PFILE_OBJECT FileObject, + PKSMULTIPLE_ITEM * Item) +{ + NTSTATUS Status; + ULONG BytesReturned; + PKSMULTIPLE_ITEM MultipleItem; + KSPROPERTY Property; + + /* setup query request */ + Property.Id = KSPROPERTY_TOPOLOGY_NODES; + Property.Flags = KSPROPERTY_TYPE_GET; + Property.Set = KSPROPSETID_Topology; + + /* query for required size */ + Status = KsSynchronousIoControlDevice(FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), NULL, 0, &BytesReturned); + + /* check for success */ + if (Status != STATUS_MORE_ENTRIES) + return Status; + + /* allocate buffer */ + MultipleItem = (PKSMULTIPLE_ITEM)ExAllocatePool(NonPagedPool, BytesReturned); + if (!MultipleItem) + return STATUS_INSUFFICIENT_RESOURCES; + + /* query for required size */ + Status = KsSynchronousIoControlDevice(FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)MultipleItem, BytesReturned, &BytesReturned); + + if (!NT_SUCCESS(Status)) { - /* filter has no pins which can be instantiated -> topology filter */ - return TRUE; + /* failed */ + ExFreePool(MultipleItem); + return Status; } - return FALSE; + *Item = MultipleItem; + return Status; } ULONG -GetNumOfMixerPinsFromTopologyFilter( - IN PDEVICE_OBJECT DeviceObject, - ULONG VirtualDeviceId) +CountNodeType( + PKSMULTIPLE_ITEM MultipleItem, + LPGUID NodeType) { - KSP_PIN Pin; - ULONG BytesReturned, Index, NumPins; - NTSTATUS Status; - PWDMAUD_DEVICE_EXTENSION DeviceExtension; - PKSMULTIPLE_ITEM MultipleItem; - PKSTOPOLOGY_CONNECTION Conn; + ULONG Count; + ULONG Index; + LPGUID Guid; - Pin.PinId = 0; - Pin.Reserved = VirtualDeviceId; - Pin.Property.Set = KSPROPSETID_Topology; - Pin.Property.Id = KSPROPERTY_TOPOLOGY_CONNECTIONS; - Pin.Property.Flags = KSPROPERTY_TYPE_GET; + Count = 0; + Guid = (LPGUID)(MultipleItem+1); - DeviceExtension = (PWDMAUD_DEVICE_EXTENSION)DeviceObject->DeviceExtension; - - BytesReturned = 0; - Status = KsSynchronousIoControlDevice(DeviceExtension->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&Pin, sizeof(KSP_PIN), (PVOID)NULL, 0, &BytesReturned); - - if (Status != STATUS_BUFFER_TOO_SMALL) - return 0; - - MultipleItem = ExAllocatePool(NonPagedPool, BytesReturned); - if (!MultipleItem) - return 0; - - RtlZeroMemory(MultipleItem, BytesReturned); - - Status = KsSynchronousIoControlDevice(DeviceExtension->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&Pin, sizeof(KSP_PIN), (PVOID)MultipleItem, BytesReturned, &BytesReturned); - if (!NT_SUCCESS(Status)) + /* iterate through node type array */ + for(Index = 0; Index < MultipleItem->Count; Index++) { - ExFreePool(MultipleItem); - return 0; - } - - Conn = (PKSTOPOLOGY_CONNECTION)(MultipleItem + 1); - NumPins = 0; - for (Index = 0; Index < MultipleItem->Count; Index++) - { - if (Conn[Index].ToNode == PCFILTER_NODE) + if (IsEqualGUIDAligned(NodeType, Guid)) { - NumPins++; + /* found matching guid */ + Count++; } + Guid++; } - - ExFreePool(MultipleItem); - return NumPins; + return Count; } ULONG GetNumOfMixerDevices( IN PDEVICE_OBJECT DeviceObject) { - KSP_PIN Pin; - ULONG Count, BytesReturned, Index, NumPins; + ULONG DeviceCount, Index, Count; NTSTATUS Status; - PWDMAUD_DEVICE_EXTENSION DeviceExtension; + HANDLE hDevice; + PFILE_OBJECT FileObject; + PKSMULTIPLE_ITEM MultipleItem; - Pin.Property.Set = KSPROPSETID_Sysaudio; - Pin.Property.Id = KSPROPERTY_SYSAUDIO_DEVICE_COUNT; - Pin.Property.Flags = KSPROPERTY_TYPE_GET; + /* get number of devices */ + DeviceCount = GetSysAudioDeviceCount(DeviceObject); - DeviceExtension = (PWDMAUD_DEVICE_EXTENSION)DeviceObject->DeviceExtension; - - Count = 0; - Status = KsSynchronousIoControlDevice(DeviceExtension->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&Pin, sizeof(KSPROPERTY), (PVOID)&Count, sizeof(ULONG), &BytesReturned); - if (!NT_SUCCESS(Status) || !Count) + if (!DeviceCount) return 0; - NumPins = 0; - for(Index = 0; Index < Count; Index++) + Index = 0; + Count = 0; + do { - if (IsVirtualDeviceATopologyFilter(DeviceObject, Index)) - { - NumPins += GetNumOfMixerPinsFromTopologyFilter(DeviceObject, Index); - } - } + /* open the virtual audio device */ + Status = OpenSysAudioDeviceByIndex(DeviceObject, Index, &hDevice, &FileObject); - return NumPins; + if (NT_SUCCESS(Status)) + { + /* retrieve all available node types */ + Status = GetFilterNodeTypes(FileObject, &MultipleItem); + if (NT_SUCCESS(Status)) + { + if (CountNodeType(MultipleItem, (LPGUID)&KSNODETYPE_DAC)) + { + /* increment (output) mixer count */ + Count++; + } + + if (CountNodeType(MultipleItem, (LPGUID)&KSNODETYPE_ADC)) + { + /* increment (input) mixer count */ + Count++; + } + ExFreePool(MultipleItem); + } + ObDereferenceObject(FileObject); + ZwClose(hDevice); + } + + Index++; + }while(Index < DeviceCount); + + return Count; } NTSTATUS diff --git a/reactos/drivers/wdm/audio/legacy/wdmaud/wdmaud.h b/reactos/drivers/wdm/audio/legacy/wdmaud/wdmaud.h index 13139d06c85..ae0b78220c1 100644 --- a/reactos/drivers/wdm/audio/legacy/wdmaud/wdmaud.h +++ b/reactos/drivers/wdm/audio/legacy/wdmaud/wdmaud.h @@ -103,4 +103,9 @@ SetIrpIoStatus( IN NTSTATUS Status, IN ULONG Length); +NTSTATUS +WdmAudOpenSysAudioDevice( + IN LPWSTR DeviceName, + OUT PHANDLE Handle); + #endif