Author: janderwald Date: Thu Sep 24 16:54:58 2009 New Revision: 43129
URL: http://svn.reactos.org/svn/reactos?rev=43129&view=rev Log: - Rewrite mixer enumeration functions - WDMAUD should reports a mixer device each time it sees a KSNODETYPE_ADC / KSNODETYPE_DAC
Modified: trunk/reactos/drivers/wdm/audio/legacy/wdmaud/mixer.c trunk/reactos/drivers/wdm/audio/legacy/wdmaud/wdmaud.h
Modified: trunk/reactos/drivers/wdm/audio/legacy/wdmaud/mixer.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/wdm/audio/legacy/wd... ============================================================================== --- trunk/reactos/drivers/wdm/audio/legacy/wdmaud/mixer.c [iso-8859-1] (original) +++ trunk/reactos/drivers/wdm/audio/legacy/wdmaud/mixer.c [iso-8859-1] Thu Sep 24 16:54:58 2009 @@ -8,152 +8,224 @@ */ #include "wdmaud.h"
+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}}; + ULONG -IsVirtualDeviceATopologyFilter( +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 0; + + return Count; +} + +NTSTATUS +OpenSysAudioDeviceByIndex( IN PDEVICE_OBJECT DeviceObject, - ULONG VirtualDeviceId) -{ + IN ULONG DeviceIndex, + IN PHANDLE DeviceHandle, + IN PFILE_OBJECT * FileObject) +{ + LPWSTR Device; + HANDLE hDevice; + ULONG BytesReturned; KSP_PIN Pin; - ULONG Count, BytesReturned, Index, NumPins; - NTSTATUS Status; - KSPIN_COMMUNICATION Communication; + NTSTATUS Status; PWDMAUD_DEVICE_EXTENSION DeviceExtension; - ULONG MixerPinCount; - + + /* 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_COUNT; + Pin.Property.Id = KSPROPERTY_SYSAUDIO_DEVICE_INTERFACE_NAME; Pin.Property.Flags = KSPROPERTY_TYPE_GET; + Pin.PinId = DeviceIndex; +
DeviceExtension = (PWDMAUD_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
- Status = KsSynchronousIoControlDevice(DeviceExtension->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&Pin, sizeof(KSPROPERTY), (PVOID)&Count, sizeof(ULONG), &BytesReturned); - if (!NT_SUCCESS(Status)) - return FALSE; - - if (VirtualDeviceId >= Count) - return FALSE; - - /* query number of pins */ - Pin.Reserved = VirtualDeviceId; // see sysaudio - Pin.Property.Flags = KSPROPERTY_TYPE_GET; - Pin.Property.Set = KSPROPSETID_Pin; - Pin.Property.Id = KSPROPERTY_PIN_CTYPES; - Pin.PinId = 0; - - 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; - - /* 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)) - { - if (Communication == KSPIN_COMMUNICATION_NONE) - MixerPinCount++; - } - - } - - if (MixerPinCount == NumPins) - { - /* filter has no pins which can be instantiated -> topology filter */ - return TRUE; - } - - return FALSE; + /* 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); + + if (!NT_SUCCESS(Status)) + { + /* failed */ + ExFreePool(Device); + return 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)) + { + ZwClose(hDevice); + } + } + + 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)) + { + /* failed */ + ExFreePool(MultipleItem); + return Status; + } + + *Item = MultipleItem; + return Status; }
ULONG -GetNumOfMixerPinsFromTopologyFilter( - IN PDEVICE_OBJECT DeviceObject, - ULONG VirtualDeviceId) -{ - KSP_PIN Pin; - ULONG BytesReturned, Index, NumPins; - NTSTATUS Status; - PWDMAUD_DEVICE_EXTENSION DeviceExtension; - PKSMULTIPLE_ITEM MultipleItem; - PKSTOPOLOGY_CONNECTION Conn; - - Pin.PinId = 0; - Pin.Reserved = VirtualDeviceId; - Pin.Property.Set = KSPROPSETID_Topology; - Pin.Property.Id = KSPROPERTY_TOPOLOGY_CONNECTIONS; - Pin.Property.Flags = KSPROPERTY_TYPE_GET; - - 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)) - { - ExFreePool(MultipleItem); - return 0; - } - - Conn = (PKSTOPOLOGY_CONNECTION)(MultipleItem + 1); - NumPins = 0; - for (Index = 0; Index < MultipleItem->Count; Index++) - { - if (Conn[Index].ToNode == PCFILTER_NODE) - { - NumPins++; - } - } - - ExFreePool(MultipleItem); - return NumPins; +CountNodeType( + PKSMULTIPLE_ITEM MultipleItem, + LPGUID NodeType) +{ + ULONG Count; + ULONG Index; + LPGUID Guid; + + Count = 0; + Guid = (LPGUID)(MultipleItem+1); + + /* iterate through node type array */ + for(Index = 0; Index < MultipleItem->Count; Index++) + { + if (IsEqualGUIDAligned(NodeType, Guid)) + { + /* found matching guid */ + Count++; + } + Guid++; + } + return Count; }
ULONG GetNumOfMixerDevices( IN PDEVICE_OBJECT DeviceObject) { - KSP_PIN Pin; - ULONG Count, BytesReturned, Index, NumPins; - NTSTATUS Status; - PWDMAUD_DEVICE_EXTENSION DeviceExtension; - - Pin.Property.Set = KSPROPSETID_Sysaudio; - Pin.Property.Id = KSPROPERTY_SYSAUDIO_DEVICE_COUNT; - Pin.Property.Flags = KSPROPERTY_TYPE_GET; - - DeviceExtension = (PWDMAUD_DEVICE_EXTENSION)DeviceObject->DeviceExtension; - + ULONG DeviceCount, Index, Count; + NTSTATUS Status; + HANDLE hDevice; + PFILE_OBJECT FileObject; + PKSMULTIPLE_ITEM MultipleItem; + + /* get number of devices */ + DeviceCount = GetSysAudioDeviceCount(DeviceObject); + + if (!DeviceCount) + return 0; + + Index = 0; Count = 0; - Status = KsSynchronousIoControlDevice(DeviceExtension->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&Pin, sizeof(KSPROPERTY), (PVOID)&Count, sizeof(ULONG), &BytesReturned); - if (!NT_SUCCESS(Status) || !Count) - return 0; - - NumPins = 0; - for(Index = 0; Index < Count; Index++) - { - if (IsVirtualDeviceATopologyFilter(DeviceObject, Index)) - { - NumPins += GetNumOfMixerPinsFromTopologyFilter(DeviceObject, Index); - } - } - - return NumPins; + do + { + /* open the virtual audio device */ + Status = OpenSysAudioDeviceByIndex(DeviceObject, Index, &hDevice, &FileObject); + + 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
Modified: trunk/reactos/drivers/wdm/audio/legacy/wdmaud/wdmaud.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/wdm/audio/legacy/wd... ============================================================================== --- trunk/reactos/drivers/wdm/audio/legacy/wdmaud/wdmaud.h [iso-8859-1] (original) +++ trunk/reactos/drivers/wdm/audio/legacy/wdmaud/wdmaud.h [iso-8859-1] Thu Sep 24 16:54:58 2009 @@ -103,4 +103,9 @@ IN NTSTATUS Status, IN ULONG Length);
+NTSTATUS +WdmAudOpenSysAudioDevice( + IN LPWSTR DeviceName, + OUT PHANDLE Handle); + #endif