- Extend test prog for quering capabilities

- Store PCFILTER in subdevice filter
- Call driver provided property request handlers
- partly implement waveout get capabilties (WIP)
- remove definitions for waveoutcaps, auxcaps, waveincaps, they are defined in mmsystem.h

svn path=/trunk/; revision=39719
This commit is contained in:
Johannes Anderwald 2009-02-23 11:13:35 +00:00
parent 2bf896ebe5
commit cb2ab2abe6
6 changed files with 194 additions and 69 deletions

View file

@ -47,6 +47,7 @@ main(int argc, char* argv[])
DeviceInfo.DeviceType = WAVE_OUT_DEVICE_TYPE;
Status = DeviceIoControl(hWdmAud, IOCTL_GETNUMDEVS_TYPE, (LPVOID)&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO), (LPVOID)&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO), &BytesReturned, &Overlapped);
if (!Status)
@ -74,6 +75,15 @@ main(int argc, char* argv[])
DeviceInfo.u.WaveFormatEx.nAvgBytesPerSec = 48000 * 4;
DeviceInfo.u.WaveFormatEx.wBitsPerSample = 16;
Status = DeviceIoControl(hWdmAud, IOCTL_GETCAPABILITIES, (LPVOID)&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO), (LPVOID)&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO), &BytesReturned, &Overlapped);
if (!Status)
{
if (WaitForSingleObject(&Overlapped.hEvent, 5000) != WAIT_OBJECT_0)
{
printf("Failed to get iocaps %lx\n", GetLastError());
}
}
Status = DeviceIoControl(hWdmAud, IOCTL_OPEN_WDMAUD, (LPVOID)&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO), &DeviceInfo, sizeof(WDMAUD_DEVICE_INFO), &BytesReturned, &Overlapped);
@ -87,6 +97,9 @@ main(int argc, char* argv[])
}
}
//
// Allocate a buffer for 1 second
//
@ -119,7 +132,7 @@ main(int argc, char* argv[])
return -1;
}
}
//
// Play our 1-second buffer
//
@ -136,6 +149,8 @@ main(int argc, char* argv[])
}
}
printf("WDMAUD: Played buffer\n");
DeviceInfo.State = KSSTATE_STOP;
Status = DeviceIoControl(hWdmAud, IOCTL_SETDEVICE_STATE, (LPVOID)&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO), &DeviceInfo, sizeof(WDMAUD_DEVICE_INFO), &BytesReturned, &Overlapped);
if (!Status)
@ -147,6 +162,9 @@ main(int argc, char* argv[])
return -1;
}
}
printf("WDMAUD: STOPPED\n");
CloseHandle(hWdmAud);
CloseHandle(&Overlapped.hEvent);
printf("WDMAUD: COMPLETE\n");
return 0;
}

View file

@ -128,6 +128,8 @@ typedef struct
GUID *Interfaces;
KSPIN_FACTORY Factory;
KSPROPERTY_SET_LIST FilterPropertySet;
PPCFILTER_DESCRIPTOR DeviceDescriptor;
}SUBDEVICE_DESCRIPTOR, *PSUBDEVICE_DESCRIPTOR;
#undef INTERFACE

View file

@ -133,27 +133,55 @@ PcPropertyHandler(
PFNKSHANDLER PropertyHandler = NULL;
UNICODE_STRING GuidString;
NTSTATUS Status = STATUS_UNSUCCESSFUL;
PCPROPERTY_REQUEST PropertyRequest;
IoStack = IoGetCurrentIrpStackLocation(Irp);
Property = (PKSPROPERTY)IoStack->Parameters.DeviceIoControl.Type3InputBuffer;
ASSERT(Property);
DPRINT1("Num of Property Sets %u\n", Descriptor->FilterPropertySet.FreeKsPropertySetOffset);
/* check properties provided by the driver */
if (Descriptor->DeviceDescriptor->AutomationTable)
{
for(Index = 0; Index < Descriptor->DeviceDescriptor->AutomationTable->PropertyCount; Index++)
{
if (IsEqualGUID(&Descriptor->DeviceDescriptor->AutomationTable->Properties[Index].Set, &Property->Set))
{
if (Descriptor->DeviceDescriptor->AutomationTable->Properties[Index].Id == Property->Id)
{
if(Descriptor->DeviceDescriptor->AutomationTable->Properties[Index].Flags & Property->Flags)
{
RtlZeroMemory(&PropertyRequest, sizeof(PCPROPERTY_REQUEST));
PropertyRequest.PropertyItem = &Descriptor->DeviceDescriptor->AutomationTable->Properties[Index];
PropertyRequest.Verb = Property->Flags;
PropertyRequest.Value = Irp->UserBuffer;
PropertyRequest.ValueSize = IoStack->Parameters.DeviceIoControl.OutputBufferLength;
PropertyRequest.Irp = Irp;
DPRINT("Calling handler %p\n", Descriptor->DeviceDescriptor->AutomationTable->Properties[Index].Handler);
Status = Descriptor->DeviceDescriptor->AutomationTable->Properties[Index].Handler(&PropertyRequest);
Irp->IoStatus.Information = PropertyRequest.ValueSize;
Irp->IoStatus.Status = Status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return Status;
}
}
}
}
}
DPRINT("Num of Property Sets %u\n", Descriptor->FilterPropertySet.FreeKsPropertySetOffset);
for(Index = 0; Index < Descriptor->FilterPropertySet.FreeKsPropertySetOffset; Index++)
{
RtlStringFromGUID ((GUID*)Descriptor->FilterPropertySet.Properties[Index].Set, &GuidString);
DPRINT1("Current GUID %S\n", GuidString.Buffer);
RtlFreeUnicodeString(&GuidString);
if (IsEqualGUIDAligned(&Property->Set, Descriptor->FilterPropertySet.Properties[Index].Set))
{
DPRINT1("Found Property Set Properties %u\n", Descriptor->FilterPropertySet.Properties[Index].PropertiesCount);
DPRINT("Found Property Set Properties %u\n", Descriptor->FilterPropertySet.Properties[Index].PropertiesCount);
for(ItemIndex = 0; ItemIndex < Descriptor->FilterPropertySet.Properties[Index].PropertiesCount; ItemIndex++)
{
if (Descriptor->FilterPropertySet.Properties[Index].PropertyItem[ItemIndex].PropertyId == Property->Id)
{
DPRINT1("Found property set identifier %u\n", Property->Id);
DPRINT("Found property set identifier %u\n", Property->Id);
if (Property->Flags & KSPROPERTY_TYPE_SET)
PropertyHandler = Descriptor->FilterPropertySet.Properties[Index].PropertyItem[ItemIndex].SetPropertyHandler;
@ -165,6 +193,7 @@ PcPropertyHandler(
/* too small input buffer */
Irp->IoStatus.Information = Descriptor->FilterPropertySet.Properties[Index].PropertyItem[ItemIndex].MinProperty;
Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_BUFFER_TOO_SMALL;
}
@ -173,19 +202,20 @@ PcPropertyHandler(
/* too small output buffer */
Irp->IoStatus.Information = Descriptor->FilterPropertySet.Properties[Index].PropertyItem[ItemIndex].MinData;
Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_BUFFER_TOO_SMALL;
}
if (PropertyHandler)
{
KSPROPERTY_ITEM_IRP_STORAGE(Irp) = (PVOID)Descriptor;
DPRINT1("Calling property handler %p\n", PropertyHandler);
DPRINT("Calling property handler %p\n", PropertyHandler);
Status = PropertyHandler(Irp, Property, Irp->UserBuffer);
}
/* the information member is set by the handler */
Irp->IoStatus.Status = Status;
DPRINT1("Result %x\n", Status);
DPRINT("Result %x\n", Status);
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return Status;
}

View file

@ -204,7 +204,7 @@ PcCreateSubdeviceDescriptor(
Descriptor->Factory.Instances[Index].MinFilterInstanceCount = FilterDescription->Pins[Index].MinFilterInstanceCount;
}
}
Descriptor->DeviceDescriptor = FilterDescription;
*OutSubdeviceDescriptor = Descriptor;
return STATUS_SUCCESS;

View file

@ -17,7 +17,6 @@ const GUID KSDATAFORMAT_TYPE_AUDIO = {0x73647561L, 0x0000, 0x0010,
const GUID KSDATAFORMAT_SUBTYPE_PCM = {0x00000001L, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};
const GUID KSDATAFORMAT_SPECIFIER_WAVEFORMATEX = {0x05589f81L, 0xc356, 0x11ce, {0xbf, 0x01, 0x00, 0xaa, 0x00, 0x55, 0x59, 0x5a}};
NTSTATUS
SetIrpIoStatus(
IN PIRP Irp,
@ -324,17 +323,140 @@ WdmAudControlWriteData(
Status = KsSynchronousIoControlDevice(FileObject, KernelMode, IOCTL_KS_WRITE_STREAM, (PVOID)Packet, sizeof(KSSTREAM_HEADER), NULL, 0, &BytesReturned);
DPRINT1("KsSynchronousIoControlDevice result %x\n", Status);
IoMarkIrpPending(Irp);
Irp->IoStatus.Information = DeviceInfo->BufferSize;
Irp->IoStatus.Status = Status;
ExFreePool(Buffer);
return Status;
return SetIrpIoStatus(Irp, Status, sizeof(WDMAUD_DEVICE_INFO));
}
ULONG
CheckFormatSupport(
IN PKSDATARANGE_AUDIO DataRangeAudio,
ULONG SampleFrequency,
ULONG Mono8Bit,
ULONG Stereo8Bit,
ULONG Mono16Bit,
ULONG Stereo16Bit)
{
ULONG Result = 0;
if (DataRangeAudio->MinimumSampleFrequency <= SampleFrequency && DataRangeAudio->MaximumSampleFrequency >= SampleFrequency)
{
if (DataRangeAudio->MinimumBitsPerSample <= 8 && DataRangeAudio->MaximumBitsPerSample >= 8)
{
Result |= Mono8Bit;
if (DataRangeAudio->MaximumChannels >= 2)
{
Result |= Stereo8Bit;
}
}
if (DataRangeAudio->MaximumBitsPerSample <= 16 && DataRangeAudio->MaximumBitsPerSample >= 16)
{
Result |= Monot16;
if (DataRangeAudio->MaximumChannels >= 2)
{
Result |= Stereo8Bit;
}
}
}
return Result;
}
NTSTATUS
WdmAudCapabilities(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PWDMAUD_DEVICE_INFO DeviceInfo,
IN PWDMAUD_CLIENT ClientInfo)
{
KSP_PIN PinProperty;
KSPROPERTY Property;
KSCOMPONENTID ComponentId;
KSMULTIPLE_ITEM * MultipleItem;
ULONG BytesReturned;
PKSDATARANGE_AUDIO DataRangeAudio;
PKSDATARANGE DataRange;
NTSTATUS Status;
ULONG Index;
ULONG wChannels = 0;
ULONG dwFormats = 0;
ULONG dwSupport = 0;
Property.Set = KSPROPSETID_General;
Property.Id = KSPROPERTY_GENERAL_COMPONENTID;
Property.Flags = KSPROPERTY_TYPE_GET;
RtlZeroMemory(&ComponentId, sizeof(KSCOMPONENTID));
Status = KsSynchronousIoControlDevice(ClientInfo->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)&ComponentId, sizeof(KSCOMPONENTID), &BytesReturned);
if (!NT_SUCCESS(Status))
{
DPRINT1("KSPROPERTY_GENERAL_COMPONENTID failed with %x\n", Status);
return SetIrpIoStatus(Irp, Status, 0);
}
PinProperty.PinId = 0; //FIXME
PinProperty.Property.Set = KSPROPSETID_Pin;
PinProperty.Property.Id = KSPROPERTY_PIN_DATARANGES;
PinProperty.Property.Flags = KSPROPERTY_TYPE_GET;
Status = KsSynchronousIoControlDevice(ClientInfo->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)NULL, 0, &BytesReturned);
if (Status != STATUS_BUFFER_TOO_SMALL)
{
DPRINT1("KSPROPERTY_PIN_DATARANGES failed with %x\n", Status);
return SetIrpIoStatus(Irp, Status, 0);
}
MultipleItem = ExAllocatePool(NonPagedPool, BytesReturned);
if (!MultipleItem)
{
/* no memory */
return SetIrpIoStatus(Irp, STATUS_NO_MEMORY, 0);
}
Status = KsSynchronousIoControlDevice(ClientInfo->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)MultipleItem, BytesReturned, &BytesReturned);
if (!NT_SUCCESS(Status))
{
ExFreePool(MultipleItem);
return SetIrpIoStatus(Irp, Status, 0);
}
DataRange = (PKSDATARANGE) (MultipleItem + 1);
for(Index = 0; Index < MultipleItem->Count; Index++)
{
if (DeviceInfo->DeviceType == WAVE_OUT_DEVICE_TYPE || DeviceInfo->DeviceType == WAVE_IN_DEVICE_TYPE)
{
if (DataRange->FormatSize == sizeof(KSDATARANGE_AUDIO))
{
DataRangeAudio = (PKSDATARANGE_AUDIO)DataRange;
if (IsEqualGUIDAligned(&DataRangeAudio->DataRange.MajorFormat, &KSDATAFORMAT_TYPE_AUDIO) &&
IsEqualGUIDAligned(&DataRangeAudio->DataRange.SubFormat, &KSDATAFORMAT_SUBTYPE_PCM) &&
IsEqualGUIDAligned(&DataRangeAudio->DataRange.Specifier, &KSDATAFORMAT_SPECIFIER_WAVEFORMATEX))
{
dwFormats |= CheckFormatSupport(DataRangeAudio, 11025, WAVE_FORMAT_1M08, WAVE_FORMAT_1S08, WAVE_FORMAT_1M16, WAVE_FORMAT_1S16);
dwFormats |= CheckFormatSupport(DataRangeAudio, 22050, WAVE_FORMAT_2M08, WAVE_FORMAT_2S08, WAVE_FORMAT_2M16, WAVE_FORMAT_2S16);
dwFormats |= CheckFormatSupport(DataRangeAudio, 44100, WAVE_FORMAT_4M08, WAVE_FORMAT_4S08, WAVE_FORMAT_4M16, WAVE_FORMAT_4S16);
dwFormats |= CheckFormatSupport(DataRangeAudio, 48000, WAVE_FORMAT_48M08, WAVE_FORMAT_48S08, WAVE_FORMAT_48M16, WAVE_FORMAT_48S16);
dwFormats |= CheckFormatSupport(DataRangeAudio, 96000, WAVE_FORMAT_96M08, WAVE_FORMAT_96S08, WAVE_FORMAT_96M16, WAVE_FORMAT_96S16);
wChannels = DataRangeAudio->MaximumChannels;
dwSupport = WAVECAPS_VOLUME; //FIXME get info from nodes
}
}
}
}
DeviceInfo->u.WaveOutCaps.dwFormats = dwFormats;
DeviceInfo->u.WaveOutCaps.dwSupport = dwSupport;
DeviceInfo->u.WaveOutCaps.wChannels = wChannels;
DeviceInfo->u.WaveOutCaps.wMid = ComponentId.Manufacturer.Data1 - 0xd5a47fa7;
DeviceInfo->u.WaveOutCaps.vDriverVersion = MAKELONG(ComponentId.Version, ComponentId.Revision);
return SetIrpIoStatus(Irp, Status, sizeof(WDMAUD_DEVICE_INFO));
}
NTSTATUS
NTAPI
@ -386,12 +508,13 @@ WdmAudDeviceControl(
return WdmAudControlDeviceState(DeviceObject, Irp, DeviceInfo, ClientInfo);
case IOCTL_WRITEDATA:
return WdmAudControlWriteData(DeviceObject, Irp, DeviceInfo, ClientInfo);
case IOCTL_GETCAPABILITIES:
return WdmAudCapabilities(DeviceObject, Irp, DeviceInfo, ClientInfo);
case IOCTL_CLOSE_WDMAUD:
case IOCTL_GETDEVID:
case IOCTL_GETVOLUME:
case IOCTL_SETVOLUME:
case IOCTL_GETCAPABILITIES:
DPRINT1("Unhandeled %x\n", IoStack->Parameters.DeviceIoControl.IoControlCode);
break;
}

View file

@ -8,55 +8,7 @@
#define YDEBUG
#include <debug.h>
#include <ksmedia.h>
#ifndef MAXPNAMELEN
#define MAXPNAMELEN 32
#endif
#ifndef WAVEOUTCAPS
typedef struct
{
USHORT wMid;
USHORT wPid;
ULONG vDriverVersion;
WCHAR szPname[MAXPNAMELEN];
ULONG dwFormats;
USHORT wChannels;
USHORT wReserved1;
ULONG dwSupport;
} WAVEOUTCAPS;
#endif
#ifndef AUXCAPS
typedef struct {
USHORT wMid;
USHORT wPid;
ULONG vDriverVersion;
WCHAR szPname[MAXPNAMELEN];
USHORT wTechnology;
USHORT wReserved1;
ULONG dwSupport;
} AUXCAPS;
#endif
#ifndef WAVEINCAPS
typedef struct
{
USHORT wMid;
USHORT wPid;
ULONG vDriverVersion;
WCHAR szPname[MAXPNAMELEN];
ULONG dwFormats;
USHORT wChannels;
USHORT wReserved1;
} WAVEINCAPS;
#endif
#include <mmsystem.h>
#include "interface.h"