- Rewrite mixer enumeration functions

- WDMAUD should reports a mixer device each time it sees a KSNODETYPE_ADC / KSNODETYPE_DAC

svn path=/trunk/; revision=43129
This commit is contained in:
Johannes Anderwald 2009-09-24 14:54:58 +00:00
parent 5a4647d276
commit fee01ee6d4
2 changed files with 180 additions and 103 deletions

View file

@ -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

View file

@ -103,4 +103,9 @@ SetIrpIoStatus(
IN NTSTATUS Status,
IN ULONG Length);
NTSTATUS
WdmAudOpenSysAudioDevice(
IN LPWSTR DeviceName,
OUT PHANDLE Handle);
#endif