From 347609e69110fcc6a463cc4f8ac9fd2d0daa2397 Mon Sep 17 00:00:00 2001 From: Johannes Anderwald Date: Fri, 2 Oct 2009 10:57:24 +0000 Subject: [PATCH] - Rewrite Wave API to enumerate wave out / in devices at startup - Improves speedup of application minus short delay in system boot - Enumerate controls for source and destination lines svn path=/trunk/; revision=43254 --- .../drivers/wdm/audio/legacy/wdmaud/control.c | 713 +---------------- .../drivers/wdm/audio/legacy/wdmaud/entry.c | 2 + .../drivers/wdm/audio/legacy/wdmaud/mixer.c | 422 ++++++++-- reactos/drivers/wdm/audio/legacy/wdmaud/sup.c | 300 +++++++ .../drivers/wdm/audio/legacy/wdmaud/wave.c | 756 ++++++++++++++++++ .../drivers/wdm/audio/legacy/wdmaud/wdmaud.h | 72 +- .../wdm/audio/legacy/wdmaud/wdmaud.rbuild | 3 + 7 files changed, 1503 insertions(+), 765 deletions(-) create mode 100644 reactos/drivers/wdm/audio/legacy/wdmaud/sup.c create mode 100644 reactos/drivers/wdm/audio/legacy/wdmaud/wave.c diff --git a/reactos/drivers/wdm/audio/legacy/wdmaud/control.c b/reactos/drivers/wdm/audio/legacy/wdmaud/control.c index b2a2cf535ba..ecf364514fe 100644 --- a/reactos/drivers/wdm/audio/legacy/wdmaud/control.c +++ b/reactos/drivers/wdm/audio/legacy/wdmaud/control.c @@ -19,114 +19,6 @@ const GUID KSDATAFORMAT_SUBTYPE_PCM = {0x00000001L, 0x0000, 0x0010, const GUID KSDATAFORMAT_SPECIFIER_WAVEFORMATEX = {0x05589f81L, 0xc356, 0x11ce, {0xbf, 0x01, 0x00, 0xaa, 0x00, 0x55, 0x59, 0x5a}}; const GUID KSPROPSETID_Topology = {0x720D4AC0L, 0x7533, 0x11D0, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}}; -NTSTATUS -SetIrpIoStatus( - IN PIRP Irp, - IN NTSTATUS Status, - IN ULONG Length) -{ - Irp->IoStatus.Information = Length; - Irp->IoStatus.Status = Status; - IoCompleteRequest(Irp, IO_NO_INCREMENT); - return Status; - -} - -NTSTATUS -GetFilterIdAndPinId( - IN PDEVICE_OBJECT DeviceObject, - IN PWDMAUD_DEVICE_INFO DeviceInfo, - IN PWDMAUD_CLIENT ClientInfo, - IN PULONG FilterId, - IN PULONG PinId) -{ - KSP_PIN Pin; - ULONG Count, BytesReturned, Index, SubIndex, Result, NumPins; - NTSTATUS Status; - KSPIN_COMMUNICATION Communication; - KSPIN_DATAFLOW DataFlow; - PWDMAUD_DEVICE_EXTENSION DeviceExtension; - - if (DeviceInfo->DeviceType != WAVE_OUT_DEVICE_TYPE && DeviceInfo->DeviceType != WAVE_IN_DEVICE_TYPE) - { - DPRINT1("FIXME: Unsupported device type %x\n", DeviceInfo->DeviceType); - return STATUS_UNSUCCESSFUL; - } - - Pin.Property.Set = KSPROPSETID_Sysaudio; - Pin.Property.Id = KSPROPERTY_SYSAUDIO_DEVICE_COUNT; - Pin.Property.Flags = KSPROPERTY_TYPE_GET; - - 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 STATUS_UNSUCCESSFUL; - - Result = 0; - for(Index = 0; Index < Count; Index++) - { - /* query number of pins */ - Pin.Reserved = Index; // 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)) - { - /* enumerate now all pins */ - for(SubIndex = 0; SubIndex < NumPins; SubIndex++) - { - Pin.PinId = SubIndex; - Pin.Property.Id = KSPROPERTY_PIN_COMMUNICATION; - Communication = KSPIN_COMMUNICATION_NONE; - - /* get pin communication type */ - KsSynchronousIoControlDevice(DeviceExtension->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&Pin, sizeof(KSP_PIN), (PVOID)&Communication, sizeof(KSPIN_COMMUNICATION), &BytesReturned); - - Pin.Property.Id = KSPROPERTY_PIN_DATAFLOW; - DataFlow = 0; - - /* get pin dataflow type */ - KsSynchronousIoControlDevice(DeviceExtension->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&Pin, sizeof(KSP_PIN), (PVOID)&DataFlow, sizeof(KSPIN_DATAFLOW), &BytesReturned); - - if (DeviceInfo->DeviceType == WAVE_OUT_DEVICE_TYPE) - { - if (Communication == KSPIN_COMMUNICATION_SINK && DataFlow == KSPIN_DATAFLOW_IN) - { - if(DeviceInfo->DeviceIndex == Result) - { - /* found the index */ - *FilterId = Index; - *PinId = SubIndex; - return STATUS_SUCCESS; - } - - Result++; - } - } - else if (DeviceInfo->DeviceType == WAVE_IN_DEVICE_TYPE) - { - if (Communication == KSPIN_COMMUNICATION_SINK && DataFlow == KSPIN_DATAFLOW_OUT) - { - if(DeviceInfo->DeviceIndex == Result) - { - /* found the index */ - *FilterId = Index; - *PinId = SubIndex; - return STATUS_SUCCESS; - } - Result++; - } - } - } - } - } - - return STATUS_UNSUCCESSFUL; -} NTSTATUS WdmAudControlOpen( @@ -135,174 +27,17 @@ WdmAudControlOpen( IN PWDMAUD_DEVICE_INFO DeviceInfo, IN PWDMAUD_CLIENT ClientInfo) { - SYSAUDIO_INSTANCE_INFO InstanceInfo; - PWDMAUD_DEVICE_EXTENSION DeviceExtension; - ULONG BytesReturned; - NTSTATUS Status; - ACCESS_MASK DesiredAccess = 0; - HANDLE PinHandle; - KSPIN_CONNECT * PinConnect; - ULONG Length, Index; - KSDATAFORMAT_WAVEFORMATEX * DataFormat; - ULONG FilterId; - ULONG PinId; - ULONG FreeIndex; - if (DeviceInfo->DeviceType == MIXER_DEVICE_TYPE) { return WdmAudControlOpenMixer(DeviceObject, Irp, DeviceInfo, ClientInfo); } - if (DeviceInfo->DeviceType != WAVE_OUT_DEVICE_TYPE && DeviceInfo->DeviceType != WAVE_IN_DEVICE_TYPE) + if (DeviceInfo->DeviceType == WAVE_OUT_DEVICE_TYPE || DeviceInfo->DeviceType == WAVE_IN_DEVICE_TYPE) { - DPRINT1("FIXME: only waveout / wavein devices are supported\n"); - return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, 0); + return WdmAudControlOpenWave(DeviceObject, Irp, DeviceInfo, ClientInfo); } - if (DeviceInfo->u.WaveFormatEx.wFormatTag != WAVE_FORMAT_PCM) - { - DPRINT("FIXME: Only WAVE_FORMAT_PCM is supported RequestFormat %x\n", DeviceInfo->u.WaveFormatEx.wFormatTag); - return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, 0); - } - - Status = GetFilterIdAndPinId(DeviceObject, DeviceInfo, ClientInfo, &FilterId, &PinId); - if (!NT_SUCCESS(Status)) - { - DPRINT1("Invalid device index %u\n", DeviceInfo->DeviceIndex); - return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, 0); - } - - /* close pin handle which uses same virtual audio device id and pin id */ - FreeIndex = MAXULONG; - for(Index = 0; Index < ClientInfo->NumPins; Index++) - { - if (ClientInfo->hPins[Index].FilterId == FilterId && ClientInfo->hPins[Index].PinId == PinId && ClientInfo->hPins[Index].Handle && ClientInfo->hPins[Index].Type == DeviceInfo->DeviceType) - { - ZwClose(ClientInfo->hPins[Index].Handle); - ClientInfo->hPins[Index].Handle = NULL; - FreeIndex = Index; - } - } - - - Length = sizeof(KSDATAFORMAT_WAVEFORMATEX) + sizeof(KSPIN_CONNECT); - PinConnect = ExAllocatePool(NonPagedPool, Length); - if (!PinConnect) - { - /* no memory */ - return SetIrpIoStatus(Irp, STATUS_NO_MEMORY, 0); - } - - DeviceExtension = (PWDMAUD_DEVICE_EXTENSION)DeviceObject->DeviceExtension; - - if (DeviceInfo->DeviceType == WAVE_IN_DEVICE_TYPE || - DeviceInfo->DeviceType == MIDI_IN_DEVICE_TYPE || - DeviceInfo->DeviceType == MIXER_DEVICE_TYPE) - { - DesiredAccess |= GENERIC_READ; - } - - if (DeviceInfo->DeviceType == WAVE_OUT_DEVICE_TYPE || - DeviceInfo->DeviceType == MIDI_OUT_DEVICE_TYPE || - DeviceInfo->DeviceType == AUX_DEVICE_TYPE || - DeviceInfo->DeviceType == MIXER_DEVICE_TYPE) - { - DesiredAccess |= GENERIC_WRITE; - } - - PinConnect->Interface.Set = KSINTERFACESETID_Standard; - PinConnect->Interface.Id = KSINTERFACE_STANDARD_STREAMING; - PinConnect->Interface.Flags = 0; - PinConnect->Medium.Set = KSMEDIUMSETID_Standard; - PinConnect->Medium.Id = KSMEDIUM_TYPE_ANYINSTANCE; - PinConnect->Medium.Flags = 0; - PinConnect->PinToHandle = NULL; - PinConnect->PinId = PinId; - PinConnect->Priority.PriorityClass = KSPRIORITY_NORMAL; - PinConnect->Priority.PrioritySubClass = 1; - - - DataFormat = (KSDATAFORMAT_WAVEFORMATEX*) (PinConnect + 1); - DataFormat->WaveFormatEx.wFormatTag = DeviceInfo->u.WaveFormatEx.wFormatTag; - DataFormat->WaveFormatEx.nChannels = DeviceInfo->u.WaveFormatEx.nChannels; - DataFormat->WaveFormatEx.nSamplesPerSec = DeviceInfo->u.WaveFormatEx.nSamplesPerSec; - DataFormat->WaveFormatEx.nBlockAlign = DeviceInfo->u.WaveFormatEx.nBlockAlign; - DataFormat->WaveFormatEx.nAvgBytesPerSec = DeviceInfo->u.WaveFormatEx.nAvgBytesPerSec; - DataFormat->WaveFormatEx.wBitsPerSample = DeviceInfo->u.WaveFormatEx.wBitsPerSample; - DataFormat->WaveFormatEx.cbSize = 0; - DataFormat->DataFormat.FormatSize = sizeof(KSDATAFORMAT) + sizeof(WAVEFORMATEX); - DataFormat->DataFormat.Flags = 0; - DataFormat->DataFormat.Reserved = 0; - DataFormat->DataFormat.MajorFormat = KSDATAFORMAT_TYPE_AUDIO; - - DataFormat->DataFormat.SubFormat = KSDATAFORMAT_SUBTYPE_PCM; - DataFormat->DataFormat.Specifier = KSDATAFORMAT_SPECIFIER_WAVEFORMATEX; - DataFormat->DataFormat.SampleSize = 4; - - /* setup property request */ - InstanceInfo.Property.Set = KSPROPSETID_Sysaudio; - InstanceInfo.Property.Id = KSPROPERTY_SYSAUDIO_INSTANCE_INFO; - InstanceInfo.Property.Flags = KSPROPERTY_TYPE_SET; - InstanceInfo.Flags = 0; - InstanceInfo.DeviceNumber = FilterId; - - /* first open the virtual device */ - Status = KsSynchronousIoControlDevice(DeviceExtension->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&InstanceInfo, sizeof(SYSAUDIO_INSTANCE_INFO), NULL, 0, &BytesReturned); - - if (!NT_SUCCESS(Status)) - { - /* failed */ - ExFreePool(PinConnect); - return SetIrpIoStatus(Irp, Status, sizeof(WDMAUD_DEVICE_INFO)); - } - - /* now create the pin */ - Status = KsCreatePin(DeviceExtension->hSysAudio, PinConnect, DesiredAccess, &PinHandle); - - /* free create info */ - ExFreePool(PinConnect); - - if (NT_SUCCESS(Status)) - { - PWDMAUD_HANDLE Handels; - - if (FreeIndex != MAXULONG) - { - /* re-use a free index */ - ClientInfo->hPins[Index].Handle = PinHandle; - ClientInfo->hPins[Index].FilterId = FilterId; - ClientInfo->hPins[Index].PinId = PinId; - ClientInfo->hPins[Index].Type = DeviceInfo->DeviceType; - - DeviceInfo->hDevice = PinHandle; - return SetIrpIoStatus(Irp, Status, sizeof(WDMAUD_DEVICE_INFO)); - } - - Handels = ExAllocatePool(NonPagedPool, sizeof(WDMAUD_HANDLE) * (ClientInfo->NumPins+1)); - - if (Handels) - { - if (ClientInfo->NumPins) - { - RtlMoveMemory(Handels, ClientInfo->hPins, sizeof(WDMAUD_HANDLE) * ClientInfo->NumPins); - ExFreePool(ClientInfo->hPins); - } - - ClientInfo->hPins = Handels; - ClientInfo->hPins[ClientInfo->NumPins].Handle = PinHandle; - ClientInfo->hPins[ClientInfo->NumPins].Type = DeviceInfo->DeviceType; - ClientInfo->hPins[ClientInfo->NumPins].FilterId = FilterId; - ClientInfo->hPins[ClientInfo->NumPins].PinId = PinId; - ClientInfo->NumPins++; - } - DeviceInfo->hDevice = PinHandle; - } - else - { - DeviceInfo->hDevice = NULL; - } - - return SetIrpIoStatus(Irp, Status, sizeof(WDMAUD_DEVICE_INFO)); + return SetIrpIoStatus(Irp, STATUS_NOT_SUPPORTED, sizeof(WDMAUD_DEVICE_INFO)); } NTSTATUS @@ -312,85 +47,23 @@ WdmAudControlDeviceType( IN PWDMAUD_DEVICE_INFO DeviceInfo, IN PWDMAUD_CLIENT ClientInfo) { - KSP_PIN Pin; - ULONG Count, BytesReturned, Index, SubIndex, Result, NumPins; + ULONG Result = 0; NTSTATUS Status; - KSPIN_COMMUNICATION Communication; - KSPIN_DATAFLOW DataFlow; PWDMAUD_DEVICE_EXTENSION DeviceExtension; DeviceExtension = (PWDMAUD_DEVICE_EXTENSION)DeviceObject->DeviceExtension; if (DeviceInfo->DeviceType == MIXER_DEVICE_TYPE) { - DeviceInfo->DeviceCount = DeviceExtension->MixerInfoCount; - return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO)); + Result = DeviceExtension->MixerInfoCount; } - - if (DeviceInfo->DeviceType != WAVE_OUT_DEVICE_TYPE && DeviceInfo->DeviceType != WAVE_IN_DEVICE_TYPE) + else if (DeviceInfo->DeviceType == WAVE_OUT_DEVICE_TYPE) { - DPRINT("FIXME: Unsupported device type %x\n", DeviceInfo->DeviceType); - DeviceInfo->DeviceCount = 0; - return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO)); + Result = DeviceExtension->WaveOutDeviceCount; } - - Pin.Property.Set = KSPROPSETID_Sysaudio; - Pin.Property.Id = KSPROPERTY_SYSAUDIO_DEVICE_COUNT; - Pin.Property.Flags = KSPROPERTY_TYPE_GET; - - - Status = KsSynchronousIoControlDevice(DeviceExtension->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&Pin, sizeof(KSPROPERTY), (PVOID)&Count, sizeof(ULONG), &BytesReturned); - if (!NT_SUCCESS(Status)) + else if (DeviceInfo->DeviceType == WAVE_IN_DEVICE_TYPE) { - DPRINT1("KSPROPERTY_SYSAUDIO_DEVICE_COUNT failed with %x\n", Status); - return SetIrpIoStatus(Irp, Status, sizeof(WDMAUD_DEVICE_INFO)); - } - Result = 0; - /* now enumerate all available filters */ - for(Index = 0; Index < Count; Index++) - { - /* query number of pins */ - Pin.Reserved = Index; // 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)) - { - /* enumerate now all pins */ - for(SubIndex = 0; SubIndex < NumPins; SubIndex++) - { - Pin.PinId = SubIndex; - 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)) - continue; - - Pin.Property.Id = KSPROPERTY_PIN_DATAFLOW; - DataFlow = 0; - - /* get pin dataflow type */ - Status = KsSynchronousIoControlDevice(DeviceExtension->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&Pin, sizeof(KSP_PIN), (PVOID)&DataFlow, sizeof(KSPIN_DATAFLOW), &BytesReturned); - if (!NT_SUCCESS(Status)) - continue; - - if (DeviceInfo->DeviceType == WAVE_OUT_DEVICE_TYPE) - { - if (Communication == KSPIN_COMMUNICATION_SINK && DataFlow == KSPIN_DATAFLOW_IN) - Result++; - } - else if (DeviceInfo->DeviceType == WAVE_IN_DEVICE_TYPE) - { - if (Communication == KSPIN_COMMUNICATION_SINK && DataFlow == KSPIN_DATAFLOW_OUT) - Result++; - } - } - } + Result = DeviceExtension->WaveInDeviceCount; } /* store result count */ @@ -436,253 +109,6 @@ WdmAudControlDeviceState( 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->MinimumBitsPerSample <= 16 && DataRangeAudio->MaximumBitsPerSample >= 16) - { - Result |= Mono16Bit; - if (DataRangeAudio->MaximumChannels >= 2) - { - Result |= Stereo8Bit; - } - } - } - return Result; - -} - -PKEY_VALUE_PARTIAL_INFORMATION -ReadKeyValue( - IN HANDLE hSubKey, - IN PUNICODE_STRING KeyName) -{ - NTSTATUS Status; - ULONG Length; - PKEY_VALUE_PARTIAL_INFORMATION PartialInformation; - - /* now query MatchingDeviceId key */ - Status = ZwQueryValueKey(hSubKey, KeyName, KeyValuePartialInformation, NULL, 0, &Length); - - /* check for success */ - if (Status != STATUS_BUFFER_TOO_SMALL) - return NULL; - - /* allocate a buffer for key data */ - PartialInformation = ExAllocatePool(NonPagedPool, Length); - - if (!PartialInformation) - return NULL; - - - /* now query MatchingDeviceId key */ - Status = ZwQueryValueKey(hSubKey, KeyName, KeyValuePartialInformation, PartialInformation, Length, &Length); - - /* check for success */ - if (!NT_SUCCESS(Status)) - { - ExFreePool(PartialInformation); - return NULL; - } - - if (PartialInformation->Type != REG_SZ) - { - /* invalid key type */ - ExFreePool(PartialInformation); - return NULL; - } - - return PartialInformation; -} - - -NTSTATUS -CompareProductName( - IN HANDLE hSubKey, - IN LPWSTR PnpName, - IN ULONG ProductNameSize, - OUT LPWSTR ProductName) -{ - PKEY_VALUE_PARTIAL_INFORMATION PartialInformation; - UNICODE_STRING DriverDescName = RTL_CONSTANT_STRING(L"DriverDesc"); - UNICODE_STRING MatchingDeviceIdName = RTL_CONSTANT_STRING(L"MatchingDeviceId"); - ULONG Length; - LPWSTR DeviceName; - - /* read MatchingDeviceId value */ - PartialInformation = ReadKeyValue(hSubKey, &MatchingDeviceIdName); - - if (!PartialInformation) - return STATUS_UNSUCCESSFUL; - - - /* extract last '&' */ - DeviceName = wcsrchr((LPWSTR)PartialInformation->Data, L'&'); - ASSERT(DeviceName); - /* terminate it */ - DeviceName[0] = L'\0'; - - Length = wcslen((LPWSTR)PartialInformation->Data); - - DPRINT("DeviceName %S PnpName %S Length %u\n", (LPWSTR)PartialInformation->Data, PnpName, Length); - - if (_wcsnicmp((LPWSTR)PartialInformation->Data, &PnpName[4], Length)) - { - ExFreePool(PartialInformation); - return STATUS_NO_MATCH; - } - - /* free buffer */ - ExFreePool(PartialInformation); - - /* read DriverDescName value */ - PartialInformation = ReadKeyValue(hSubKey, &DriverDescName); - - if (!PartialInformation) - { - /* failed to read driver desc key */ - return STATUS_UNSUCCESSFUL; - } - - /* copy key name */ - Length = min(ProductNameSize * sizeof(WCHAR), PartialInformation->DataLength); - RtlMoveMemory(ProductName, (PVOID)PartialInformation->Data, Length); - - /* zero terminate it */ - ProductName[ProductNameSize-1] = L'\0'; - - /* free buffer */ - ExFreePool(PartialInformation); - - return STATUS_SUCCESS; -} - - - -NTSTATUS -FindProductName( - IN LPWSTR PnpName, - IN ULONG ProductNameSize, - OUT LPWSTR ProductName) -{ - UNICODE_STRING KeyName = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Class\\{4D36E96C-E325-11CE-BFC1-08002BE10318}"); - - UNICODE_STRING SubKeyName; - WCHAR SubKey[20]; - OBJECT_ATTRIBUTES ObjectAttributes; - HANDLE hKey, hSubKey; - NTSTATUS Status; - ULONG Length, Index; - PKEY_FULL_INFORMATION KeyInformation; - - for(Index = 0; Index < wcslen(PnpName); Index++) - { - if (PnpName[Index] == '#') - PnpName[Index] = L'\\'; - } - - - /* initialize key attributes */ - InitializeObjectAttributes(&ObjectAttributes, &KeyName, OBJ_CASE_INSENSITIVE | OBJ_OPENIF, NULL, NULL); - - /* open the key */ - Status = ZwOpenKey(&hKey, GENERIC_READ, &ObjectAttributes); - - /* check for success */ - if (!NT_SUCCESS(Status)) - return Status; - - /* query num of subkeys */ - Status = ZwQueryKey(hKey, KeyFullInformation, NULL, 0, &Length); - - if (Status != STATUS_BUFFER_TOO_SMALL) - { - DPRINT1("ZwQueryKey failed with %x\n", Status); - /* failed */ - ZwClose(hKey); - return Status; - } - - /* allocate key information struct */ - KeyInformation = ExAllocatePool(NonPagedPool, Length); - if (!KeyInformation) - { - /* no memory */ - ZwClose(hKey); - return STATUS_INSUFFICIENT_RESOURCES; - } - - /* query num of subkeys */ - Status = ZwQueryKey(hKey, KeyFullInformation, (PVOID)KeyInformation, Length, &Length); - - if (!NT_SUCCESS(Status)) - { - DPRINT1("ZwQueryKey failed with %x\n", Status); - ExFreePool(KeyInformation); - ZwClose(hKey); - return Status; - } - - /* now iterate through all subkeys */ - for(Index = 0; Index < KeyInformation->SubKeys; Index++) - { - /* subkeys are always in the format 0000-XXXX */ - swprintf(SubKey, L"%04u", Index); - - /* initialize subkey name */ - RtlInitUnicodeString(&SubKeyName, SubKey); - - /* initialize key attributes */ - InitializeObjectAttributes(&ObjectAttributes, &SubKeyName, OBJ_CASE_INSENSITIVE | OBJ_OPENIF, hKey, NULL); - - /* open the sub key */ - Status = ZwOpenKey(&hSubKey, GENERIC_READ, &ObjectAttributes); - - /* check for success */ - if (NT_SUCCESS(Status)) - { - /* compare product name */ - Status = CompareProductName(hSubKey, PnpName, ProductNameSize, ProductName); - - /* close subkey */ - ZwClose(hSubKey); - - if (NT_SUCCESS(Status)) - break; - } - } - - /* free buffer */ - ExFreePool(KeyInformation); - - /* close key */ - ZwClose(hKey); - - /* no matching key found */ - return Status; -} - - - NTSTATUS WdmAudCapabilities( IN PDEVICE_OBJECT DeviceObject, @@ -692,19 +118,6 @@ WdmAudCapabilities( { PWDMAUD_DEVICE_EXTENSION DeviceExtension; NTSTATUS Status = STATUS_UNSUCCESSFUL; - KSP_PIN PinProperty; - KSCOMPONENTID ComponentId; - KSMULTIPLE_ITEM * MultipleItem; - ULONG BytesReturned; - PKSDATARANGE_AUDIO DataRangeAudio; - PKSDATARANGE DataRange; - ULONG Index; - ULONG wChannels = 0; - ULONG dwFormats = 0; - ULONG dwSupport = 0; - ULONG FilterId; - ULONG PinId; - WCHAR DeviceName[MAX_PATH]; DPRINT("WdmAudCapabilities entered\n"); @@ -713,115 +126,12 @@ WdmAudCapabilities( if (DeviceInfo->DeviceType == MIXER_DEVICE_TYPE) { Status = WdmAudMixerCapabilities(DeviceObject, DeviceInfo, ClientInfo, DeviceExtension); - return SetIrpIoStatus(Irp, Status, sizeof(WDMAUD_DEVICE_INFO)); } - - - Status = GetFilterIdAndPinId(DeviceObject, DeviceInfo, ClientInfo, &FilterId, &PinId); - if (!NT_SUCCESS(Status)) + else if (DeviceInfo->DeviceType == WAVE_IN_DEVICE_TYPE || DeviceInfo->DeviceType == WAVE_OUT_DEVICE_TYPE) { - DPRINT1("Invalid device index provided %u\n", DeviceInfo->DeviceIndex); - return SetIrpIoStatus(Irp, STATUS_INVALID_PARAMETER, 0); + Status = WdmAudWaveCapabilities(DeviceObject, DeviceInfo, ClientInfo, DeviceExtension); } - PinProperty.PinId = FilterId; - PinProperty.Property.Set = KSPROPSETID_Sysaudio; - PinProperty.Property.Id = KSPROPERTY_SYSAUDIO_COMPONENT_ID; - PinProperty.Property.Flags = KSPROPERTY_TYPE_GET; - - RtlZeroMemory(&ComponentId, sizeof(KSCOMPONENTID)); - - - Status = KsSynchronousIoControlDevice(DeviceExtension->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&PinProperty, sizeof(KSP_PIN), (PVOID)&ComponentId, sizeof(KSCOMPONENTID), &BytesReturned); - if (NT_SUCCESS(Status)) - { - DeviceInfo->u.WaveOutCaps.wMid = ComponentId.Manufacturer.Data1 - 0xd5a47fa7; - DeviceInfo->u.WaveOutCaps.vDriverVersion = MAKELONG(ComponentId.Version, ComponentId.Revision); - } - - /* retrieve pnp base name */ - PinProperty.PinId = FilterId; - PinProperty.Property.Set = KSPROPSETID_Sysaudio; - PinProperty.Property.Id = KSPROPERTY_SYSAUDIO_DEVICE_INTERFACE_NAME; - PinProperty.Property.Flags = KSPROPERTY_TYPE_GET; - - Status = KsSynchronousIoControlDevice(DeviceExtension->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&PinProperty, sizeof(KSP_PIN), (PVOID)DeviceName, sizeof(DeviceName), &BytesReturned); - if (NT_SUCCESS(Status)) - { - /* find product name */ - Status = FindProductName(DeviceName, MAXPNAMELEN, DeviceInfo->u.WaveOutCaps.szPname); - - /* check for success */ - if (!NT_SUCCESS(Status)) - { - DeviceInfo->u.WaveOutCaps.szPname[0] = L'\0'; - } - } - - PinProperty.Reserved = DeviceInfo->DeviceIndex; - PinProperty.PinId = PinId; - PinProperty.Property.Set = KSPROPSETID_Pin; - PinProperty.Property.Id = KSPROPERTY_PIN_DATARANGES; - PinProperty.Property.Flags = KSPROPERTY_TYPE_GET; - - BytesReturned = 0; - Status = KsSynchronousIoControlDevice(DeviceExtension->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&PinProperty, sizeof(KSP_PIN), (PVOID)NULL, 0, &BytesReturned); - if (Status != STATUS_BUFFER_TOO_SMALL) - { - return SetIrpIoStatus(Irp, Status, 0); - } - - MultipleItem = ExAllocatePool(NonPagedPool, BytesReturned); - if (!MultipleItem) - { - /* no memory */ - return SetIrpIoStatus(Irp, STATUS_NO_MEMORY, 0); - } - - Status = KsSynchronousIoControlDevice(DeviceExtension->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&PinProperty, sizeof(KSP_PIN), (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)) - { - DPRINT("Min Sample %u Max Sample %u Min Bits %u Max Bits %u Max Channel %u\n", DataRangeAudio->MinimumSampleFrequency, DataRangeAudio->MaximumSampleFrequency, - DataRangeAudio->MinimumBitsPerSample, DataRangeAudio->MaximumBitsPerSample, DataRangeAudio->MaximumChannels); - - 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 - } - } - } - DataRange = (PKSDATARANGE)((PUCHAR)DataRange + DataRange->FormatSize); - } - - DeviceInfo->u.WaveOutCaps.dwFormats = dwFormats; - DeviceInfo->u.WaveOutCaps.dwSupport = dwSupport; - DeviceInfo->u.WaveOutCaps.wChannels = wChannels; - - ExFreePool(MultipleItem); - return SetIrpIoStatus(Irp, Status, sizeof(WDMAUD_DEVICE_INFO)); } @@ -846,6 +156,7 @@ WdmAudIoctlClose( return STATUS_SUCCESS; } } + SetIrpIoStatus(Irp, STATUS_INVALID_PARAMETER, sizeof(WDMAUD_DEVICE_INFO)); return STATUS_INVALID_PARAMETER; } diff --git a/reactos/drivers/wdm/audio/legacy/wdmaud/entry.c b/reactos/drivers/wdm/audio/legacy/wdmaud/entry.c index 3e7bb58d6e3..a648315eb13 100644 --- a/reactos/drivers/wdm/audio/legacy/wdmaud/entry.c +++ b/reactos/drivers/wdm/audio/legacy/wdmaud/entry.c @@ -78,6 +78,8 @@ WdmAudInstallDevice( Status = WdmAudMixerInitialize(DeviceObject); DPRINT("WdmAudMixerInitialize Status %x\n", Status); + Status = WdmAudWaveInitialize(DeviceObject); + DPRINT("WdmAudWaveInitialize Status %x\n", Status); DeviceObject->Flags |= DO_DIRECT_IO | DO_POWER_PAGABLE; DeviceObject->Flags &= ~ DO_DEVICE_INITIALIZING; diff --git a/reactos/drivers/wdm/audio/legacy/wdmaud/mixer.c b/reactos/drivers/wdm/audio/legacy/wdmaud/mixer.c index 28cd154a5b8..b4d75181dd3 100644 --- a/reactos/drivers/wdm/audio/legacy/wdmaud/mixer.c +++ b/reactos/drivers/wdm/audio/legacy/wdmaud/mixer.c @@ -21,6 +21,7 @@ const GUID KSNODETYPE_STEREO_WIDE = {0xA9E69800L, 0xC558, 0x11D0, {0x8A, 0x2B, 0 const GUID KSNODETYPE_CHORUS = {0x20173F20L, 0xC559, 0x11D0, {0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1}}; const GUID KSNODETYPE_REVERB = {0xEF0328E0L, 0xC558, 0x11D0, {0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1}}; const GUID KSNODETYPE_SUPERMIX = {0xE573ADC0L, 0xC555, 0x11D0, {0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1}}; +const GUID KSNODETYPE_SUM = {0xDA441A60L, 0xC556, 0x11D0, {0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1}}; #define DESTINATION_LINE 0xFFFF0000 @@ -62,7 +63,7 @@ GetSourceMixerLineByLineId( while(Entry != &MixerInfo->LineList) { MixerLineSrc = (LPMIXERLINE_EXT)CONTAINING_RECORD(Entry, MIXERLINE_EXT, Entry); - DPRINT("dwLineID %x dwLineID %x\n", MixerLineSrc->Line.dwLineID, dwLineID); + DPRINT1("dwLineID %x dwLineID %x\n", MixerLineSrc->Line.dwLineID, dwLineID); if (MixerLineSrc->Line.dwLineID == dwLineID) return MixerLineSrc; @@ -719,67 +720,369 @@ AllocatePinArray( return Pins; } +PKSTOPOLOGY_CONNECTION +GetConnectionByIndex( + IN PKSMULTIPLE_ITEM MultipleItem, + IN ULONG Index) +{ + PKSTOPOLOGY_CONNECTION Descriptor; + + ASSERT(Index < MultipleItem->Count); + + Descriptor = (PKSTOPOLOGY_CONNECTION)(MultipleItem + 1); + return &Descriptor[Index]; +} + +LPGUID +GetNodeType( + IN PKSMULTIPLE_ITEM MultipleItem, + IN ULONG Index) +{ + LPGUID NodeType; + + ASSERT(Index < MultipleItem->Count); + + NodeType = (LPGUID)(MultipleItem + 1); + return &NodeType[Index]; +} + +NTSTATUS +GetControlsFromPinByConnectionIndex( + IN PKSMULTIPLE_ITEM NodeConnections, + IN PKSMULTIPLE_ITEM NodeTypes, + IN ULONG bUpDirection, + IN ULONG NodeConnectionIndex, + OUT PULONG Nodes) +{ + PKSTOPOLOGY_CONNECTION CurConnection; + LPGUID NodeType; + ULONG NodeIndex; + NTSTATUS Status; + ULONG NodeConnectionCount, Index; + PULONG NodeConnection; + + + /* get current connection */ + CurConnection = GetConnectionByIndex(NodeConnections, NodeConnectionIndex); + + if (bUpDirection) + NodeIndex = CurConnection->FromNode; + else + NodeIndex = CurConnection->ToNode; + + /* get target node type of current connection */ + NodeType = GetNodeType(NodeTypes, NodeIndex); + + if (IsEqualGUIDAligned(NodeType, &KSNODETYPE_SUM) || IsEqualGUIDAligned(NodeType, &KSNODETYPE_MUX)) + { + if (bUpDirection) + { + /* add the sum / mux node to destination line */ + //Nodes[NodeIndex] = TRUE; + } + + return STATUS_SUCCESS; + } + + /* now add the node */ + Nodes[NodeIndex] = TRUE; + + + /* get all node indexes referenced by that node */ + if (bUpDirection) + { + Status = GetNodeIndexes(NodeConnections, NodeIndex, TRUE, FALSE, &NodeConnectionCount, &NodeConnection); + } + else + { + Status = GetNodeIndexes(NodeConnections, NodeIndex, TRUE, TRUE, &NodeConnectionCount, &NodeConnection); + } + + if (NT_SUCCESS(Status)) + { + for(Index = 0; Index < NodeConnectionCount; Index++) + { + /* iterate recursively into the nodes */ + Status = GetControlsFromPinByConnectionIndex(NodeConnections, NodeTypes, bUpDirection, NodeConnection[Index], Nodes); + ASSERT(Status == STATUS_SUCCESS); + } + /* free node connection indexes */ + ExFreePool(NodeConnection); + } + + return Status; +} + +NTSTATUS +GetControlsFromPin( + IN PKSMULTIPLE_ITEM NodeConnections, + IN PKSMULTIPLE_ITEM NodeTypes, + IN ULONG PinId, + IN ULONG bUpDirection, + OUT PULONG Nodes) +{ + ULONG NodeConnectionCount, Index; + NTSTATUS Status; + PULONG NodeConnection; + + /* sanity check */ + ASSERT(PinId != (ULONG)-1); + + /* get all node indexes referenced by that pin */ + if (bUpDirection) + Status = GetNodeIndexes(NodeConnections, PinId, FALSE, FALSE, &NodeConnectionCount, &NodeConnection); + else + Status = GetNodeIndexes(NodeConnections, PinId, FALSE, TRUE, &NodeConnectionCount, &NodeConnection); + + for(Index = 0; Index < NodeConnectionCount; Index++) + { + /* get all associated controls */ + Status = GetControlsFromPinByConnectionIndex(NodeConnections, NodeTypes, bUpDirection, NodeConnection[Index], Nodes); + } + + ExFreePool(NodeConnection); + + return Status; +} + +NTSTATUS +AddMixerControl( + IN LPMIXER_INFO MixerInfo, + IN PFILE_OBJECT FileObject, + IN PKSMULTIPLE_ITEM NodeTypes, + IN ULONG NodeIndex, + OUT LPMIXERCONTROLW MixerControl) +{ + LPGUID NodeType; + KSP_NODE Node; + ULONG BytesReturned; + NTSTATUS Status; + LPWSTR Name; + + + /* initialize mixer control */ + MixerControl->cbStruct = sizeof(MIXERCONTROLW); + MixerControl->dwControlID = MixerInfo->ControlId; + + /* get node type */ + NodeType = GetNodeType(NodeTypes, NodeIndex); + /* store control type */ + MixerControl->dwControlType = GetControlTypeFromTopologyNode(NodeType); + + MixerControl->fdwControl = MIXERCONTROL_CONTROLF_UNIFORM; //FIXME + MixerControl->cMultipleItems = 0; //FIXME + + if (MixerControl->dwControlType == MIXERCONTROL_CONTROLTYPE_MUTE) + { + MixerControl->Bounds.dwMinimum = 0; + MixerControl->Bounds.dwMaximum = 1; + } + else if (MixerControl->dwControlType == MIXERCONTROL_CONTROLTYPE_VOLUME) + { + MixerControl->Bounds.dwMinimum = 0; + MixerControl->Bounds.dwMaximum = 0xFFFF; + MixerControl->Metrics.cSteps = 0xC0; //FIXME + } + + /* setup request to retrieve name */ + Node.NodeId = NodeIndex; + Node.Property.Id = KSPROPERTY_TOPOLOGY_NAME; + Node.Property.Flags = KSPROPERTY_TYPE_GET; + Node.Property.Set = KSPROPSETID_Topology; + Node.Reserved = 0; + + /* get node name size */ + Status = KsSynchronousIoControlDevice(FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&Node, sizeof(KSP_NODE), NULL, 0, &BytesReturned); + + if (Status == STATUS_BUFFER_TOO_SMALL) + { + ASSERT(BytesReturned != 0); + Name = ExAllocatePool(NonPagedPool, BytesReturned); + if (!Name) + { + /* not enough memory */ + return STATUS_INSUFFICIENT_RESOURCES; + } + + /* get node name */ + Status = KsSynchronousIoControlDevice(FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&Node, sizeof(KSP_NODE), (LPVOID)Name, BytesReturned, &BytesReturned); + if (NT_SUCCESS(Status)) + { + RtlMoveMemory(MixerControl->szShortName, Name, (min(MIXER_SHORT_NAME_CHARS, wcslen(Name)+1)) * sizeof(WCHAR)); + MixerControl->szShortName[MIXER_SHORT_NAME_CHARS-1] = L'\0'; + + RtlMoveMemory(MixerControl->szName, Name, (min(MIXER_LONG_NAME_CHARS, wcslen(Name)+1)) * sizeof(WCHAR)); + MixerControl->szName[MIXER_LONG_NAME_CHARS-1] = L'\0'; + } + + /* free name buffer */ + ExFreePool(Name); + } + + MixerInfo->ControlId++; + + DPRINT("Status %x Name %S\n", Status, MixerControl->szName); + return STATUS_SUCCESS; +} + NTSTATUS AddMixerSourceLine( IN OUT LPMIXER_INFO MixerInfo, IN PFILE_OBJECT FileObject, + IN PKSMULTIPLE_ITEM NodeConnections, + IN PKSMULTIPLE_ITEM NodeTypes, IN ULONG DeviceIndex, - IN ULONG PinId) + IN ULONG PinId, + IN ULONG bBridgePin, + IN ULONG bTargetPin) { LPMIXERLINE_EXT SrcLine, DstLine; NTSTATUS Status; KSP_PIN Pin; LPWSTR PinName; GUID NodeType; - ULONG BytesReturned; + ULONG BytesReturned, ControlCount, Index; + PULONG Nodes; - /* allocate src mixer line */ - SrcLine = (LPMIXERLINE_EXT)ExAllocatePool(NonPagedPool, sizeof(MIXERLINE_EXT)); - if (!SrcLine) - return STATUS_INSUFFICIENT_RESOURCES; + if (!bTargetPin) + { + /* allocate src mixer line */ + SrcLine = (LPMIXERLINE_EXT)ExAllocatePool(NonPagedPool, sizeof(MIXERLINE_EXT)); - /* zero struct */ - RtlZeroMemory(SrcLine, sizeof(MIXERLINE_EXT)); + if (!SrcLine) + return STATUS_INSUFFICIENT_RESOURCES; - /* initialize mixer src line */ - SrcLine->DeviceIndex = DeviceIndex; - SrcLine->PinId = PinId; - SrcLine->Line.cbStruct = sizeof(MIXERLINEW); + /* zero struct */ + RtlZeroMemory(SrcLine, sizeof(MIXERLINE_EXT)); + + } + else + { + ASSERT(!IsListEmpty(&MixerInfo->LineList)); + SrcLine = GetSourceMixerLineByLineId(MixerInfo, DESTINATION_LINE); + } /* get destination line */ DstLine = GetSourceMixerLineByLineId(MixerInfo, DESTINATION_LINE); + ASSERT(DstLine); - /* initialize mixer destination line */ - SrcLine->Line.cbStruct = sizeof(MIXERLINEW); - SrcLine->Line.dwDestination = 0; - SrcLine->Line.dwSource = DstLine->Line.cConnections; - SrcLine->Line.dwLineID = (DstLine->Line.cConnections * 0x10000); - SrcLine->Line.fdwLine = MIXERLINE_LINEF_ACTIVE | MIXERLINE_LINEF_SOURCE; - SrcLine->Line.dwUser = 0; - SrcLine->Line.cChannels = DstLine->Line.cChannels; - SrcLine->Line.cConnections = 0; - SrcLine->Line.cControls = 1; //FIXME - //HACK - SrcLine->LineControls = ExAllocatePool(NonPagedPool, SrcLine->Line.cControls * sizeof(MIXERCONTROLW)); - if (!SrcLine->LineControls) + if (!bTargetPin) + { + /* initialize mixer src line */ + SrcLine->DeviceIndex = DeviceIndex; + SrcLine->PinId = PinId; + SrcLine->Line.cbStruct = sizeof(MIXERLINEW); + + /* initialize mixer destination line */ + SrcLine->Line.cbStruct = sizeof(MIXERLINEW); + SrcLine->Line.dwDestination = 0; + SrcLine->Line.dwSource = DstLine->Line.cConnections; + SrcLine->Line.dwLineID = (DstLine->Line.cConnections * 0x10000); + SrcLine->Line.fdwLine = MIXERLINE_LINEF_ACTIVE | MIXERLINE_LINEF_SOURCE; + SrcLine->Line.dwUser = 0; + SrcLine->Line.cChannels = DstLine->Line.cChannels; + SrcLine->Line.cConnections = 0; + SrcLine->Line.Target.dwType = 1; + SrcLine->Line.Target.dwDeviceID = DstLine->Line.Target.dwDeviceID; + SrcLine->Line.Target.wMid = MixerInfo->MixCaps.wMid; + SrcLine->Line.Target.wPid = MixerInfo->MixCaps.wPid; + SrcLine->Line.Target.vDriverVersion = MixerInfo->MixCaps.vDriverVersion; + wcscpy(SrcLine->Line.Target.szPname, MixerInfo->MixCaps.szPname); + + } + + /* allocate a node arrary */ + Nodes = ExAllocatePool(NonPagedPool, sizeof(ULONG) * NodeTypes->Count); + + if (!Nodes) { /* not enough memory */ - ExFreePool(SrcLine); + if (!bTargetPin) + { + ExFreePool(SrcLine); + } return STATUS_INSUFFICIENT_RESOURCES; } - /* clear line controls */ - RtlZeroMemory(SrcLine->LineControls, sizeof(MIXERCONTROLW)); + /* clear nodes array */ + RtlZeroMemory(Nodes, sizeof(ULONG) * NodeTypes->Count); - /* fill in pseudo mixer control */ - SrcLine->LineControls->dwControlID = 1; //FIXME - SrcLine->LineControls->cbStruct = sizeof(MIXERCONTROLW); - SrcLine->LineControls->fdwControl = 0; - SrcLine->LineControls->cMultipleItems = 0; - wcscpy(SrcLine->LineControls->szName, L"test"); - wcscpy(SrcLine->LineControls->szShortName, L"test"); + Status = GetControlsFromPin(NodeConnections, NodeTypes, PinId, bTargetPin, Nodes); + if (!NT_SUCCESS(Status)) + { + /* something went wrong */ + if (!bTargetPin) + { + ExFreePool(SrcLine); + } + ExFreePool(Nodes); + return Status; + } + /* now count all nodes controlled by that pin */ + ControlCount = 0; + for(Index = 0; Index < NodeTypes->Count; Index++) + { + if (Nodes[Index]) + ControlCount++; + } + + /* now allocate the line controls */ + if (ControlCount) + { + SrcLine->LineControls = ExAllocatePool(NonPagedPool, sizeof(MIXERCONTROLW) * ControlCount); + + if (!SrcLine->LineControls) + { + /* no memory available */ + if (!bTargetPin) + { + ExFreePool(SrcLine); + } + ExFreePool(Nodes); + return STATUS_INSUFFICIENT_RESOURCES; + } + + SrcLine->NodeIds = ExAllocatePool(NonPagedPool, sizeof(ULONG) * ControlCount); + if (!SrcLine->NodeIds) + { + /* no memory available */ + ExFreePool(SrcLine->LineControls); + if (!bTargetPin) + { + ExFreePool(SrcLine); + } + ExFreePool(Nodes); + return STATUS_INSUFFICIENT_RESOURCES; + } + + /* zero line controls */ + RtlZeroMemory(SrcLine->LineControls, sizeof(MIXERCONTROLW) * ControlCount); + RtlZeroMemory(SrcLine->NodeIds, sizeof(ULONG) * ControlCount); + + ControlCount = 0; + for(Index = 0; Index < NodeTypes->Count; Index++) + { + if (Nodes[Index]) + { + /* store the node index for retrieving / setting details */ + SrcLine->NodeIds[ControlCount] = Index; + + Status = AddMixerControl(MixerInfo, FileObject, NodeTypes, Index, &SrcLine->LineControls[ControlCount]); + if (NT_SUCCESS(Status)) + { + /* increment control count on success */ + ControlCount++; + } + } + } + /* store control count */ + SrcLine->Line.cControls = ControlCount; + } + + /* release nodes array */ + ExFreePool(Nodes); /* get pin category */ Pin.PinId = PinId; @@ -831,17 +1134,12 @@ AddMixerSourceLine( } } - SrcLine->Line.Target.dwType = 1; - SrcLine->Line.Target.dwDeviceID = DstLine->Line.Target.dwDeviceID; - SrcLine->Line.Target.wMid = MixerInfo->MixCaps.wMid; - SrcLine->Line.Target.wPid = MixerInfo->MixCaps.wPid; - SrcLine->Line.Target.vDriverVersion = MixerInfo->MixCaps.vDriverVersion; - wcscpy(SrcLine->Line.Target.szPname, MixerInfo->MixCaps.szPname); - - /* insert src line */ - InsertTailList(&MixerInfo->LineList, &SrcLine->Entry); - DstLine->Line.cConnections++; + if (!bTargetPin) + { + InsertTailList(&MixerInfo->LineList, &SrcLine->Entry); + DstLine->Line.cConnections++; + } return STATUS_SUCCESS; } @@ -851,8 +1149,12 @@ NTSTATUS AddMixerSourceLines( IN OUT LPMIXER_INFO MixerInfo, IN PFILE_OBJECT FileObject, + IN PKSMULTIPLE_ITEM NodeConnections, + IN PKSMULTIPLE_ITEM NodeTypes, IN ULONG DeviceIndex, IN ULONG PinsCount, + IN ULONG BridgePinIndex, + IN ULONG TargetPinIndex, IN PULONG Pins) { ULONG Index; @@ -862,7 +1164,7 @@ AddMixerSourceLines( { if (Pins[Index-1]) { - AddMixerSourceLine(MixerInfo, FileObject, DeviceIndex, Index-1); + AddMixerSourceLine(MixerInfo, FileObject, NodeConnections, NodeTypes, DeviceIndex, Index-1, (Index -1 == BridgePinIndex), (Index -1 == TargetPinIndex)); } } return Status; @@ -987,7 +1289,7 @@ HandlePhysicalConnection( PinsSrcRef[OutConnection->Pin] = TRUE; } - Status = AddMixerSourceLines(MixerInfo, FileObject, DeviceIndex, PinsRefCount, PinsSrcRef); + Status = AddMixerSourceLines(MixerInfo, FileObject, NodeConnections, NodeTypes, DeviceIndex, PinsRefCount, OutConnection->Pin, Index, PinsSrcRef); ExFreePool(MixerControls); ExFreePool(PinsSrcRef); @@ -1045,10 +1347,6 @@ InitializeMixer( if (!DestinationLine) return STATUS_INSUFFICIENT_RESOURCES; - /* initialize mixer info */ - MixerInfo->hMixer = hDevice; - MixerInfo->MixerFileObject = FileObject; - /* intialize mixer caps */ MixerInfo->MixCaps.wMid = MM_MICROSOFT; //FIXME MixerInfo->MixCaps.wPid = MM_PID_UNMAPPED; //FIXME @@ -1083,7 +1381,6 @@ InitializeMixer( DestinationLine->Line.dwUser = 0; DestinationLine->Line.dwComponentType = (bInput == 0 ? MIXERLINE_COMPONENTTYPE_DST_SPEAKERS : MIXERLINE_COMPONENTTYPE_DST_WAVEIN); DestinationLine->Line.cChannels = 2; //FIXME - DestinationLine->Line.cControls = 0; //FIXME wcscpy(DestinationLine->Line.szShortName, L"Summe"); //FIXME wcscpy(DestinationLine->Line.szName, L"Summe"); //FIXME DestinationLine->Line.Target.dwType = (bInput == 0 ? MIXERLINE_TARGETTYPE_WAVEOUT : MIXERLINE_TARGETTYPE_WAVEIN); @@ -1411,6 +1708,7 @@ WdmAudGetLineControls( { LPMIXERLINE_EXT MixerLineSrc; PWDMAUD_DEVICE_EXTENSION DeviceExtension; + ULONG Index; /* get device extension */ DeviceExtension = (PWDMAUD_DEVICE_EXTENSION)DeviceObject->DeviceExtension; @@ -1427,15 +1725,12 @@ WdmAudGetLineControls( ASSERT(MixerLineSrc); if (MixerLineSrc) { - RtlMoveMemory(DeviceInfo->u.MixControls.pamxctrl, MixerLineSrc->LineControls, min(MixerLineSrc->Line.cControls, DeviceInfo->u.MixControls.cControls) * sizeof(MIXERLINECONTROLSW)); + RtlMoveMemory(DeviceInfo->u.MixControls.pamxctrl, MixerLineSrc->LineControls, min(MixerLineSrc->Line.cControls, DeviceInfo->u.MixControls.cControls) * sizeof(MIXERCONTROLW)); } return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO)); } else if (DeviceInfo->Flags == MIXER_GETLINECONTROLSF_ONEBYTYPE) { - DPRINT1("dwLineID %u\n",DeviceInfo->u.MixControls.dwLineID); - UNIMPLEMENTED - //HACK if ((ULONG)DeviceInfo->hDevice >= DeviceExtension->MixerInfoCount) { /* invalid parameter */ @@ -1444,11 +1739,18 @@ WdmAudGetLineControls( MixerLineSrc = GetSourceMixerLineByLineId(&DeviceExtension->MixerInfo[(ULONG)DeviceInfo->hDevice], DeviceInfo->u.MixControls.dwLineID); ASSERT(MixerLineSrc); - if (MixerLineSrc) + + Index = 0; + for(Index = 0; Index < MixerLineSrc->Line.cControls; Index++) { - RtlMoveMemory(DeviceInfo->u.MixControls.pamxctrl, MixerLineSrc->LineControls, min(MixerLineSrc->Line.cControls, DeviceInfo->u.MixControls.cControls) * sizeof(MIXERLINECONTROLSW)); + if (DeviceInfo->u.MixControls.dwControlType == MixerLineSrc->LineControls[Index].dwControlType) + { + RtlMoveMemory(DeviceInfo->u.MixControls.pamxctrl, &MixerLineSrc->LineControls[Index], sizeof(MIXERCONTROLW)); + return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO)); + } } - return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO)); + DPRINT1("DeviceInfo->u.MixControls.dwControlType %x not found in Line %x\n", DeviceInfo->u.MixControls.dwControlType, DeviceInfo->u.MixControls.dwLineID); + return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, sizeof(WDMAUD_DEVICE_INFO)); } UNIMPLEMENTED; diff --git a/reactos/drivers/wdm/audio/legacy/wdmaud/sup.c b/reactos/drivers/wdm/audio/legacy/wdmaud/sup.c new file mode 100644 index 00000000000..dd61c34f1f4 --- /dev/null +++ b/reactos/drivers/wdm/audio/legacy/wdmaud/sup.c @@ -0,0 +1,300 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Kernel Streaming + * FILE: drivers/wdm/audio/legacy/wdmaud/sup.c + * PURPOSE: System Audio graph builder + * PROGRAMMER: Andrew Greenwood + * Johannes Anderwald + */ +#include "wdmaud.h" + +NTSTATUS +SetIrpIoStatus( + IN PIRP Irp, + IN NTSTATUS Status, + IN ULONG Length) +{ + Irp->IoStatus.Information = Length; + Irp->IoStatus.Status = Status; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + return Status; + +} + +NTSTATUS +ClosePin( + IN PWDMAUD_CLIENT ClientInfo, + IN ULONG FilterId, + IN ULONG PinId, + IN SOUND_DEVICE_TYPE DeviceType) +{ + ULONG Index; + + for(Index = 0; Index < ClientInfo->NumPins; Index++) + { + if (ClientInfo->hPins[Index].FilterId == FilterId && ClientInfo->hPins[Index].PinId == PinId && ClientInfo->hPins[Index].Handle && ClientInfo->hPins[Index].Type == DeviceType) + { + if (ClientInfo->hPins[Index].Type != MIXER_DEVICE_TYPE) + { + ZwClose(ClientInfo->hPins[Index].Handle); + } + ClientInfo->hPins[Index].Handle = NULL; + return Index; + } + } + return MAXULONG; +} + +NTSTATUS +InsertPinHandle( + IN PWDMAUD_CLIENT ClientInfo, + IN ULONG FilterId, + IN ULONG PinId, + IN SOUND_DEVICE_TYPE DeviceType, + IN HANDLE PinHandle, + IN ULONG FreeIndex) +{ + PWDMAUD_HANDLE Handles; + + if (FreeIndex != MAXULONG) + { + /* re-use a free index */ + ClientInfo->hPins[FreeIndex].Handle = PinHandle; + ClientInfo->hPins[FreeIndex].FilterId = FilterId; + ClientInfo->hPins[FreeIndex].PinId = PinId; + ClientInfo->hPins[FreeIndex].Type = DeviceType; + + return STATUS_SUCCESS; + } + + Handles = ExAllocatePool(NonPagedPool, sizeof(WDMAUD_HANDLE) * (ClientInfo->NumPins+1)); + + if (!Handles) + return STATUS_INSUFFICIENT_RESOURCES; + + if (ClientInfo->NumPins) + { + RtlMoveMemory(Handles, ClientInfo->hPins, sizeof(WDMAUD_HANDLE) * ClientInfo->NumPins); + ExFreePool(ClientInfo->hPins); + } + + ClientInfo->hPins = Handles; + ClientInfo->hPins[ClientInfo->NumPins].Handle = PinHandle; + ClientInfo->hPins[ClientInfo->NumPins].Type = DeviceType; + ClientInfo->hPins[ClientInfo->NumPins].FilterId = FilterId; + ClientInfo->hPins[ClientInfo->NumPins].PinId = PinId; + ClientInfo->NumPins++; + + return STATUS_SUCCESS; +} + +PKEY_VALUE_PARTIAL_INFORMATION +ReadKeyValue( + IN HANDLE hSubKey, + IN PUNICODE_STRING KeyName) +{ + NTSTATUS Status; + ULONG Length; + PKEY_VALUE_PARTIAL_INFORMATION PartialInformation; + + /* now query MatchingDeviceId key */ + Status = ZwQueryValueKey(hSubKey, KeyName, KeyValuePartialInformation, NULL, 0, &Length); + + /* check for success */ + if (Status != STATUS_BUFFER_TOO_SMALL) + return NULL; + + /* allocate a buffer for key data */ + PartialInformation = ExAllocatePool(NonPagedPool, Length); + + if (!PartialInformation) + return NULL; + + + /* now query MatchingDeviceId key */ + Status = ZwQueryValueKey(hSubKey, KeyName, KeyValuePartialInformation, PartialInformation, Length, &Length); + + /* check for success */ + if (!NT_SUCCESS(Status)) + { + ExFreePool(PartialInformation); + return NULL; + } + + if (PartialInformation->Type != REG_SZ) + { + /* invalid key type */ + ExFreePool(PartialInformation); + return NULL; + } + + return PartialInformation; +} + + +NTSTATUS +CompareProductName( + IN HANDLE hSubKey, + IN LPWSTR PnpName, + IN ULONG ProductNameSize, + OUT LPWSTR ProductName) +{ + PKEY_VALUE_PARTIAL_INFORMATION PartialInformation; + UNICODE_STRING DriverDescName = RTL_CONSTANT_STRING(L"DriverDesc"); + UNICODE_STRING MatchingDeviceIdName = RTL_CONSTANT_STRING(L"MatchingDeviceId"); + ULONG Length; + LPWSTR DeviceName; + + /* read MatchingDeviceId value */ + PartialInformation = ReadKeyValue(hSubKey, &MatchingDeviceIdName); + + if (!PartialInformation) + return STATUS_UNSUCCESSFUL; + + + /* extract last '&' */ + DeviceName = wcsrchr((LPWSTR)PartialInformation->Data, L'&'); + ASSERT(DeviceName); + /* terminate it */ + DeviceName[0] = L'\0'; + + Length = wcslen((LPWSTR)PartialInformation->Data); + + DPRINT("DeviceName %S PnpName %S Length %u\n", (LPWSTR)PartialInformation->Data, PnpName, Length); + + if (_wcsnicmp((LPWSTR)PartialInformation->Data, &PnpName[4], Length)) + { + ExFreePool(PartialInformation); + return STATUS_NO_MATCH; + } + + /* free buffer */ + ExFreePool(PartialInformation); + + /* read DriverDescName value */ + PartialInformation = ReadKeyValue(hSubKey, &DriverDescName); + + if (!PartialInformation) + { + /* failed to read driver desc key */ + return STATUS_UNSUCCESSFUL; + } + + /* copy key name */ + Length = min(ProductNameSize * sizeof(WCHAR), PartialInformation->DataLength); + RtlMoveMemory(ProductName, (PVOID)PartialInformation->Data, Length); + + /* zero terminate it */ + ProductName[ProductNameSize-1] = L'\0'; + + /* free buffer */ + ExFreePool(PartialInformation); + + return STATUS_SUCCESS; +} + + + +NTSTATUS +FindProductName( + IN LPWSTR PnpName, + IN ULONG ProductNameSize, + OUT LPWSTR ProductName) +{ + UNICODE_STRING KeyName = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Class\\{4D36E96C-E325-11CE-BFC1-08002BE10318}"); + + UNICODE_STRING SubKeyName; + WCHAR SubKey[20]; + OBJECT_ATTRIBUTES ObjectAttributes; + HANDLE hKey, hSubKey; + NTSTATUS Status; + ULONG Length, Index; + PKEY_FULL_INFORMATION KeyInformation; + + for(Index = 0; Index < wcslen(PnpName); Index++) + { + if (PnpName[Index] == '#') + PnpName[Index] = L'\\'; + } + + + /* initialize key attributes */ + InitializeObjectAttributes(&ObjectAttributes, &KeyName, OBJ_CASE_INSENSITIVE | OBJ_OPENIF, NULL, NULL); + + /* open the key */ + Status = ZwOpenKey(&hKey, GENERIC_READ, &ObjectAttributes); + + /* check for success */ + if (!NT_SUCCESS(Status)) + return Status; + + /* query num of subkeys */ + Status = ZwQueryKey(hKey, KeyFullInformation, NULL, 0, &Length); + + if (Status != STATUS_BUFFER_TOO_SMALL) + { + DPRINT1("ZwQueryKey failed with %x\n", Status); + /* failed */ + ZwClose(hKey); + return Status; + } + + /* allocate key information struct */ + KeyInformation = ExAllocatePool(NonPagedPool, Length); + if (!KeyInformation) + { + /* no memory */ + ZwClose(hKey); + return STATUS_INSUFFICIENT_RESOURCES; + } + + /* query num of subkeys */ + Status = ZwQueryKey(hKey, KeyFullInformation, (PVOID)KeyInformation, Length, &Length); + + if (!NT_SUCCESS(Status)) + { + DPRINT1("ZwQueryKey failed with %x\n", Status); + ExFreePool(KeyInformation); + ZwClose(hKey); + return Status; + } + + /* now iterate through all subkeys */ + for(Index = 0; Index < KeyInformation->SubKeys; Index++) + { + /* subkeys are always in the format 0000-XXXX */ + swprintf(SubKey, L"%04u", Index); + + /* initialize subkey name */ + RtlInitUnicodeString(&SubKeyName, SubKey); + + /* initialize key attributes */ + InitializeObjectAttributes(&ObjectAttributes, &SubKeyName, OBJ_CASE_INSENSITIVE | OBJ_OPENIF, hKey, NULL); + + /* open the sub key */ + Status = ZwOpenKey(&hSubKey, GENERIC_READ, &ObjectAttributes); + + /* check for success */ + if (NT_SUCCESS(Status)) + { + /* compare product name */ + Status = CompareProductName(hSubKey, PnpName, ProductNameSize, ProductName); + + /* close subkey */ + ZwClose(hSubKey); + + if (NT_SUCCESS(Status)) + break; + } + } + + /* free buffer */ + ExFreePool(KeyInformation); + + /* close key */ + ZwClose(hKey); + + /* no matching key found */ + return Status; +} + diff --git a/reactos/drivers/wdm/audio/legacy/wdmaud/wave.c b/reactos/drivers/wdm/audio/legacy/wdmaud/wave.c new file mode 100644 index 00000000000..9aac7ffd12c --- /dev/null +++ b/reactos/drivers/wdm/audio/legacy/wdmaud/wave.c @@ -0,0 +1,756 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Kernel Streaming + * FILE: drivers/wdm/audio/legacy/wdmaud/wave.c + * PURPOSE: Wave Out enumeration + * PROGRAMMER: Andrew Greenwood + * Johannes Anderwald + */ +#include "wdmaud.h" + + +typedef struct +{ + ULONG SampleRate; + ULONG Bit8Mono; + ULONG Bit8Stereo; + ULONG Bit16Mono; + ULONG Bit16Stereo; +}AUDIO_RANGE; + +#define AUDIO_TEST_RANGE (5) + +static AUDIO_RANGE TestRange[AUDIO_TEST_RANGE] = +{ + { + 11025, + WAVE_FORMAT_1M08, + WAVE_FORMAT_1S08, + WAVE_FORMAT_1M16, + WAVE_FORMAT_1S16 + }, + { + 22050, + WAVE_FORMAT_2M08, + WAVE_FORMAT_2S08, + WAVE_FORMAT_2M16, + WAVE_FORMAT_2S16 + }, + { + 44100, + WAVE_FORMAT_4M08, + WAVE_FORMAT_4S08, + WAVE_FORMAT_4M16, + WAVE_FORMAT_4S16 + }, + { + 48000, + WAVE_FORMAT_48M08, + WAVE_FORMAT_48S08, + WAVE_FORMAT_48M16, + WAVE_FORMAT_48S16 + }, + { + 96000, + WAVE_FORMAT_96M08, + WAVE_FORMAT_96S08, + WAVE_FORMAT_96M16, + WAVE_FORMAT_96S16 + } +}; + +LPWAVE_INFO +AllocateWaveInfo() +{ + /* allocate wav info */ + LPWAVE_INFO WaveOutInfo = ExAllocatePool(NonPagedPool, sizeof(WAVE_INFO)); + if (!WaveOutInfo) + return NULL; + + /* zero wave info struct */ + RtlZeroMemory(WaveOutInfo, sizeof(WAVE_INFO)); + + return WaveOutInfo; +} + +PKSPIN_CONNECT +AllocatePinConnect( + ULONG DataFormatSize) +{ + PKSPIN_CONNECT Connect = ExAllocatePool(NonPagedPool, sizeof(KSPIN_CONNECT) + DataFormatSize); + if (!Connect) + return NULL; + + /* zero pin connect struct */ + RtlZeroMemory(Connect, sizeof(KSPIN_CONNECT) + DataFormatSize); + + return Connect; +} + +NTSTATUS +GetWaveInfoByIndexAndType( + IN PDEVICE_OBJECT DeviceObject, + IN ULONG DeviceIndex, + IN SOUND_DEVICE_TYPE DeviceType, + OUT LPWAVE_INFO *OutWaveInfo) +{ + PWDMAUD_DEVICE_EXTENSION DeviceExtension; + ULONG Index = 0; + PLIST_ENTRY Entry, ListHead; + LPWAVE_INFO WaveInfo; + + /* get device extension */ + DeviceExtension = (PWDMAUD_DEVICE_EXTENSION)DeviceObject->DeviceExtension; + + if (DeviceType == WAVE_IN_DEVICE_TYPE) + ListHead = &DeviceExtension->WaveInList; + else + ListHead = &DeviceExtension->WaveOutList; + + /* get first entry */ + Entry = ListHead->Flink; + + while(Entry != ListHead) + { + WaveInfo = (LPWAVE_INFO)CONTAINING_RECORD(Entry, WAVE_INFO, Entry); + + if (Index == DeviceIndex) + { + *OutWaveInfo = WaveInfo; + return STATUS_SUCCESS; + } + Index++; + Entry = Entry->Flink; + } + + return STATUS_NOT_FOUND; +} + + +VOID +InitializePinConnect( + IN OUT PKSPIN_CONNECT PinConnect, + IN ULONG PinId) +{ + PinConnect->Interface.Set = KSINTERFACESETID_Standard; + PinConnect->Interface.Id = KSINTERFACE_STANDARD_STREAMING; + PinConnect->Interface.Flags = 0; + PinConnect->Medium.Set = KSMEDIUMSETID_Standard; + PinConnect->Medium.Id = KSMEDIUM_TYPE_ANYINSTANCE; + PinConnect->Medium.Flags = 0; + PinConnect->PinToHandle = NULL; + PinConnect->PinId = PinId; + PinConnect->Priority.PriorityClass = KSPRIORITY_NORMAL; + PinConnect->Priority.PrioritySubClass = 1; +} + +VOID +InitializeDataFormat( + IN PKSDATAFORMAT_WAVEFORMATEX DataFormat, + LPWAVEFORMATEX WaveFormatEx) +{ + + DataFormat->WaveFormatEx.wFormatTag = WaveFormatEx->wFormatTag; + DataFormat->WaveFormatEx.nChannels = WaveFormatEx->nChannels; + DataFormat->WaveFormatEx.nSamplesPerSec = WaveFormatEx->nSamplesPerSec; + DataFormat->WaveFormatEx.nBlockAlign = WaveFormatEx->nBlockAlign; + DataFormat->WaveFormatEx.nAvgBytesPerSec = WaveFormatEx->nAvgBytesPerSec; + DataFormat->WaveFormatEx.wBitsPerSample = WaveFormatEx->wBitsPerSample; + DataFormat->WaveFormatEx.cbSize = 0; + DataFormat->DataFormat.FormatSize = sizeof(KSDATAFORMAT) + sizeof(WAVEFORMATEX); + DataFormat->DataFormat.Flags = 0; + DataFormat->DataFormat.Reserved = 0; + DataFormat->DataFormat.MajorFormat = KSDATAFORMAT_TYPE_AUDIO; + + DataFormat->DataFormat.SubFormat = KSDATAFORMAT_SUBTYPE_PCM; + DataFormat->DataFormat.Specifier = KSDATAFORMAT_SPECIFIER_WAVEFORMATEX; + DataFormat->DataFormat.SampleSize = 4; +} + + +NTSTATUS +AttachToVirtualAudioDevice( + IN PWDMAUD_DEVICE_EXTENSION DeviceExtension, + IN ULONG VirtualDeviceId) +{ + ULONG BytesReturned; + SYSAUDIO_INSTANCE_INFO InstanceInfo; + + /* setup property request */ + InstanceInfo.Property.Set = KSPROPSETID_Sysaudio; + InstanceInfo.Property.Id = KSPROPERTY_SYSAUDIO_INSTANCE_INFO; + InstanceInfo.Property.Flags = KSPROPERTY_TYPE_SET; + InstanceInfo.Flags = 0; + InstanceInfo.DeviceNumber = VirtualDeviceId; + + /* attach to virtual device */ + return KsSynchronousIoControlDevice(DeviceExtension->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&InstanceInfo, sizeof(SYSAUDIO_INSTANCE_INFO), NULL, 0, &BytesReturned); + +} + +NTSTATUS +GetAudioPinDataRanges( + IN PWDMAUD_DEVICE_EXTENSION DeviceExtension, + IN ULONG FilterId, + IN ULONG PinId, + IN OUT PKSMULTIPLE_ITEM * OutMultipleItem) +{ + KSP_PIN PinProperty; + ULONG BytesReturned = 0; + NTSTATUS Status; + PKSMULTIPLE_ITEM MultipleItem; + + /* retrieve size of data ranges buffer */ + PinProperty.Reserved = FilterId; + PinProperty.PinId = PinId; + PinProperty.Property.Set = KSPROPSETID_Pin; + PinProperty.Property.Id = KSPROPERTY_PIN_DATARANGES; + PinProperty.Property.Flags = KSPROPERTY_TYPE_GET; + + Status = KsSynchronousIoControlDevice(DeviceExtension->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&PinProperty, sizeof(KSP_PIN), (PVOID)NULL, 0, &BytesReturned); + if (Status != STATUS_MORE_ENTRIES) + { + return Status; + } + + MultipleItem = ExAllocatePool(NonPagedPool, BytesReturned); + if (!MultipleItem) + { + /* not enough memory */ + return STATUS_INSUFFICIENT_RESOURCES; + } + + Status = KsSynchronousIoControlDevice(DeviceExtension->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&PinProperty, sizeof(KSP_PIN), (PVOID)MultipleItem, BytesReturned, &BytesReturned); + if (!NT_SUCCESS(Status)) + { + /* failed */ + ExFreePool(MultipleItem); + return Status; + } + + /* save result */ + *OutMultipleItem = MultipleItem; + return Status; +} + +NTSTATUS +FindAudioDataRange( + PKSMULTIPLE_ITEM MultipleItem, + PKSDATARANGE_AUDIO * OutDataRangeAudio) +{ + ULONG Index; + PKSDATARANGE_AUDIO DataRangeAudio; + PKSDATARANGE DataRange; + + DataRange = (PKSDATARANGE) (MultipleItem + 1); + for(Index = 0; Index < MultipleItem->Count; Index++) + { + 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)) + { + DPRINT("Min Sample %u Max Sample %u Min Bits %u Max Bits %u Max Channel %u\n", DataRangeAudio->MinimumSampleFrequency, DataRangeAudio->MaximumSampleFrequency, + DataRangeAudio->MinimumBitsPerSample, DataRangeAudio->MaximumBitsPerSample, DataRangeAudio->MaximumChannels); + *OutDataRangeAudio = DataRangeAudio; + return STATUS_SUCCESS; + } + } + } + return STATUS_UNSUCCESSFUL; +} + +NTSTATUS +NTAPI +OpenWavePin( + IN PWDMAUD_DEVICE_EXTENSION DeviceExtension, + IN ULONG FilterId, + IN ULONG PinId, + IN LPWAVEFORMATEX WaveFormatEx, + IN ACCESS_MASK DesiredAccess, + OUT PHANDLE PinHandle) +{ + PKSPIN_CONNECT PinConnect; + PKSDATAFORMAT_WAVEFORMATEX DataFormat; + NTSTATUS Status; + + /* allocate pin connect */ + PinConnect = AllocatePinConnect(sizeof(KSDATAFORMAT_WAVEFORMATEX)); + if (!PinConnect) + { + /* no memory */ + return STATUS_INSUFFICIENT_RESOURCES; + } + + /* initialize pin connect struct */ + InitializePinConnect(PinConnect, PinId); + + /* get offset to dataformat */ + DataFormat = (PKSDATAFORMAT_WAVEFORMATEX) (PinConnect + 1); + /* initialize with requested wave format */ + InitializeDataFormat(DataFormat, WaveFormatEx); + + /* first attach to the virtual device */ + Status = AttachToVirtualAudioDevice(DeviceExtension, FilterId); + + if (!NT_SUCCESS(Status)) + { + /* failed */ + ExFreePool(PinConnect); + return Status; + } + + /* now create the pin */ + Status = KsCreatePin(DeviceExtension->hSysAudio, PinConnect, DesiredAccess, PinHandle); + + /* free create info */ + ExFreePool(PinConnect); + + return Status; +} + +ULONG +GetPinInstanceCount( + PWDMAUD_DEVICE_EXTENSION DeviceExtension, + ULONG FilterId, + ULONG PinId) +{ + KSP_PIN PinRequest; + KSPIN_CINSTANCES PinInstances; + ULONG BytesReturned; + NTSTATUS Status; + + /* query the instance count */ + PinRequest.Reserved = FilterId; + PinRequest.PinId = PinId; + PinRequest.Property.Set = KSPROPSETID_Pin; + PinRequest.Property.Flags = KSPROPERTY_TYPE_GET; + PinRequest.Property.Id = KSPROPERTY_PIN_CINSTANCES; + + Status = KsSynchronousIoControlDevice(DeviceExtension->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&PinRequest, sizeof(KSP_PIN), (PVOID)&PinInstances, sizeof(KSPIN_CINSTANCES), &BytesReturned); + ASSERT(Status == STATUS_SUCCESS); + return PinInstances.CurrentCount; +} + + +NTSTATUS +CheckSampleFormat( + PWDMAUD_DEVICE_EXTENSION DeviceExtension, + LPWAVE_INFO WaveInfo, + ULONG SampleRate, + ULONG NumChannels, + ULONG BitsPerSample) +{ + NTSTATUS Status = STATUS_SUCCESS; +#if 0 + + WAVEFORMATEX WaveFormat; + HANDLE PinHandle; + + /* clear wave format */ + RtlZeroMemory(&WaveFormat, sizeof(WAVEFORMATEX)); + + WaveFormat.wFormatTag = WAVE_FORMAT_PCM; + WaveFormat.nChannels = NumChannels; + WaveFormat.nSamplesPerSec = SampleRate; + WaveFormat.nAvgBytesPerSec = SampleRate * NumChannels * (BitsPerSample/8); + WaveFormat.nBlockAlign = (NumChannels * BitsPerSample) / 8; + WaveFormat.wBitsPerSample = BitsPerSample; + WaveFormat.cbSize = sizeof(WAVEFORMATEX); + + Status = OpenWavePin(DeviceExtension, WaveInfo->FilterId, WaveInfo->PinId, &WaveFormat, GENERIC_READ | GENERIC_WRITE, &PinHandle); + + if (NT_SUCCESS(Status)) + { + /* success */ + ZwClose(PinHandle); + + while(GetPinInstanceCount(DeviceExtension, WaveInfo->FilterId, WaveInfo->PinId)) + KeStallExecutionProcessor(5); + } + + DPRINT("SampleRate %u BitsPerSample %u NumChannels %u Status %x bInput %u\n", SampleRate, BitsPerSample, NumChannels, Status, WaveInfo->bInput); +#endif + + + return Status; +} + + +NTSTATUS +CheckFormat( + PWDMAUD_DEVICE_EXTENSION DeviceExtension, + PKSDATARANGE_AUDIO DataRangeAudio, + LPWAVE_INFO WaveInfo) +{ + ULONG Index, SampleFrequency; + ULONG Result = 0; + NTSTATUS Status; + + for(Index = 0; Index < AUDIO_TEST_RANGE; Index++) + { + SampleFrequency = TestRange[Index].SampleRate; + + if (DataRangeAudio->MinimumSampleFrequency <= SampleFrequency && DataRangeAudio->MaximumSampleFrequency >= SampleFrequency) + { + /* the audio adapter supports the sample frequency */ + if (DataRangeAudio->MinimumBitsPerSample <= 8 && DataRangeAudio->MaximumBitsPerSample >= 8) + { + /* check if pin supports the sample rate in 8-Bit Mono */ + Status = CheckSampleFormat(DeviceExtension, WaveInfo, SampleFrequency, 1, 8); + if (NT_SUCCESS(Status)) + { + Result |= TestRange[Index].Bit8Mono; + } + + if (DataRangeAudio->MaximumChannels > 1) + { + /* check if pin supports the sample rate in 8-Bit Stereo */ + Status = CheckSampleFormat(DeviceExtension, WaveInfo, SampleFrequency, 2, 8); + if (NT_SUCCESS(Status)) + { + Result |= TestRange[Index].Bit8Stereo; + } + } + } + + if (DataRangeAudio->MinimumBitsPerSample <= 16 && DataRangeAudio->MaximumBitsPerSample >= 16) + { + /* check if pin supports the sample rate in 16-Bit Mono */ + Status = CheckSampleFormat(DeviceExtension, WaveInfo, SampleFrequency, 1, 16); + if (NT_SUCCESS(Status)) + { + Result |= TestRange[Index].Bit16Mono; + } + + if (DataRangeAudio->MaximumChannels > 1) + { + /* check if pin supports the sample rate in 16-Bit Stereo */ + Status = CheckSampleFormat(DeviceExtension, WaveInfo, SampleFrequency, 2, 16); + if (NT_SUCCESS(Status)) + { + Result |= TestRange[Index].Bit16Stereo; + } + } + } + } + } + + + if (WaveInfo->bInput) + WaveInfo->u.InCaps.dwFormats = Result; + else + WaveInfo->u.OutCaps.dwFormats = Result; + + DPRINT("Format %x bInput %u\n", Result, WaveInfo->bInput); + + + return STATUS_SUCCESS; +} + +NTSTATUS +InitializeWaveInfo( + IN PDEVICE_OBJECT DeviceObject, + IN ULONG FilterId, + IN ULONG PinId, + IN ULONG bInput) +{ + KSP_PIN PinProperty; + KSCOMPONENTID ComponentId; + NTSTATUS Status; + ULONG BytesReturned; + WCHAR DeviceName[MAX_PATH]; + PWDMAUD_DEVICE_EXTENSION DeviceExtension; + PKSMULTIPLE_ITEM MultipleItem; + PKSDATARANGE_AUDIO DataRangeAudio; + LPWAVE_INFO WaveInfo = AllocateWaveInfo(); + + + if (!WaveInfo) + return STATUS_INSUFFICIENT_RESOURCES; + + /* initialize wave info */ + WaveInfo->bInput = bInput; + WaveInfo->FilterId = FilterId; + WaveInfo->PinId = PinId; + + /* setup request to return component id */ + PinProperty.PinId = FilterId; + PinProperty.Property.Set = KSPROPSETID_Sysaudio; + PinProperty.Property.Id = KSPROPERTY_SYSAUDIO_COMPONENT_ID; + PinProperty.Property.Flags = KSPROPERTY_TYPE_GET; + + /* get device extension */ + DeviceExtension = (PWDMAUD_DEVICE_EXTENSION)DeviceObject->DeviceExtension; + + /* query sysaudio for component id */ + Status = KsSynchronousIoControlDevice(DeviceExtension->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&PinProperty, sizeof(KSP_PIN), (PVOID)&ComponentId, sizeof(KSCOMPONENTID), &BytesReturned); + if (NT_SUCCESS(Status)) + { + if (bInput) + { + WaveInfo->u.InCaps.wMid = ComponentId.Manufacturer.Data1 - 0xd5a47fa7; + WaveInfo->u.InCaps.vDriverVersion = MAKELONG(ComponentId.Version, ComponentId.Revision); + } + else + { + WaveInfo->u.OutCaps.wMid = ComponentId.Manufacturer.Data1 - 0xd5a47fa7; + WaveInfo->u.OutCaps.vDriverVersion = MAKELONG(ComponentId.Version, ComponentId.Revision); + } + } + else + { + /* set up something useful */ + if (bInput) + { + WaveInfo->u.InCaps.wMid = MM_MICROSOFT; + WaveInfo->u.InCaps.wPid = MM_PID_UNMAPPED; + WaveInfo->u.InCaps.vDriverVersion = 1; + } + else + { + WaveInfo->u.OutCaps.wMid = MM_MICROSOFT; + WaveInfo->u.OutCaps.wPid = MM_PID_UNMAPPED; + WaveInfo->u.OutCaps.vDriverVersion = 1; + } + } + + /* retrieve pnp base name */ + PinProperty.PinId = FilterId; + PinProperty.Property.Set = KSPROPSETID_Sysaudio; + PinProperty.Property.Id = KSPROPERTY_SYSAUDIO_DEVICE_INTERFACE_NAME; + PinProperty.Property.Flags = KSPROPERTY_TYPE_GET; + + Status = KsSynchronousIoControlDevice(DeviceExtension->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&PinProperty, sizeof(KSP_PIN), (PVOID)DeviceName, sizeof(DeviceName), &BytesReturned); + if (NT_SUCCESS(Status)) + { + /* find product name */ + if (bInput) + Status = FindProductName(DeviceName, MAXPNAMELEN, WaveInfo->u.OutCaps.szPname); + else + Status = FindProductName(DeviceName, MAXPNAMELEN, WaveInfo->u.InCaps.szPname); + + /* check for success */ + if (!NT_SUCCESS(Status)) + { + if (bInput) + WaveInfo->u.OutCaps.szPname[0] = L'\0'; + else + WaveInfo->u.InCaps.szPname[0] = L'\0'; + } + } + + Status = GetAudioPinDataRanges(DeviceExtension, FilterId, PinId, &MultipleItem); + if (NT_SUCCESS(Status)) + { + /* find a audio data range */ + Status = FindAudioDataRange(MultipleItem, &DataRangeAudio); + + if (NT_SUCCESS(Status)) + { + if (bInput) + { + WaveInfo->u.InCaps.wChannels = DataRangeAudio->MaximumChannels; + } + else + { + WaveInfo->u.OutCaps.wChannels = DataRangeAudio->MaximumChannels; + } + CheckFormat(DeviceExtension, DataRangeAudio, WaveInfo); + } + ExFreePool(MultipleItem); + } + + if (bInput) + { + InsertTailList(&DeviceExtension->WaveInList, &WaveInfo->Entry); + DeviceExtension->WaveInDeviceCount++; + } + else + { + InsertTailList(&DeviceExtension->WaveOutList, &WaveInfo->Entry); + DeviceExtension->WaveOutDeviceCount++; + } + + + return STATUS_SUCCESS; +} + + +NTSTATUS +NTAPI +WdmAudWaveInitialize( + IN PDEVICE_OBJECT DeviceObject) +{ + KSP_PIN Pin; + ULONG Count, BytesReturned, Index, SubIndex, Result, NumPins; + NTSTATUS Status; + KSPIN_COMMUNICATION Communication; + KSPIN_DATAFLOW DataFlow; + 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; + + /* set wave count to zero */ + DeviceExtension->WaveInDeviceCount = 0; + DeviceExtension->WaveOutDeviceCount = 0; + + /* intialize list head */ + InitializeListHead(&DeviceExtension->WaveInList); + InitializeListHead(&DeviceExtension->WaveOutList); + + Status = KsSynchronousIoControlDevice(DeviceExtension->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&Pin, sizeof(KSPROPERTY), (PVOID)&Count, sizeof(ULONG), &BytesReturned); + if (!NT_SUCCESS(Status)) + return STATUS_UNSUCCESSFUL; + + Result = 0; + for(Index = 0; Index < Count; Index++) + { + /* query number of pins */ + Pin.Reserved = Index; // 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)) + { + /* enumerate now all pins */ + for(SubIndex = 0; SubIndex < NumPins; SubIndex++) + { + Pin.PinId = SubIndex; + Pin.Property.Id = KSPROPERTY_PIN_COMMUNICATION; + Communication = KSPIN_COMMUNICATION_NONE; + + /* get pin communication type */ + KsSynchronousIoControlDevice(DeviceExtension->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&Pin, sizeof(KSP_PIN), (PVOID)&Communication, sizeof(KSPIN_COMMUNICATION), &BytesReturned); + + Pin.Property.Id = KSPROPERTY_PIN_DATAFLOW; + DataFlow = 0; + + /* get pin dataflow type */ + KsSynchronousIoControlDevice(DeviceExtension->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&Pin, sizeof(KSP_PIN), (PVOID)&DataFlow, sizeof(KSPIN_DATAFLOW), &BytesReturned); + + if (Communication == KSPIN_COMMUNICATION_SINK && DataFlow == KSPIN_DATAFLOW_IN) + { + /* found a wave out device */ + InitializeWaveInfo(DeviceObject, Index, SubIndex, FALSE); + } + else if (Communication == KSPIN_COMMUNICATION_SINK && DataFlow == KSPIN_DATAFLOW_OUT) + { + /* found a wave in device */ + InitializeWaveInfo(DeviceObject, Index, SubIndex, TRUE); + } + } + } + } + + return STATUS_SUCCESS; +} + +NTSTATUS +WdmAudControlOpenWave( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp, + IN PWDMAUD_DEVICE_INFO DeviceInfo, + IN PWDMAUD_CLIENT ClientInfo) +{ + PWDMAUD_DEVICE_EXTENSION DeviceExtension; + LPWAVE_INFO WaveInfo; + NTSTATUS Status; + ACCESS_MASK DesiredAccess = 0; + HANDLE PinHandle; + ULONG FreeIndex; + + if (DeviceInfo->u.WaveFormatEx.wFormatTag != WAVE_FORMAT_PCM) + { + DPRINT("FIXME: Only WAVE_FORMAT_PCM is supported RequestFormat %x\n", DeviceInfo->u.WaveFormatEx.wFormatTag); + return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, 0); + } + + /* get device extension */ + DeviceExtension = (PWDMAUD_DEVICE_EXTENSION)DeviceObject->DeviceExtension; + + /* find destination wave */ + Status = GetWaveInfoByIndexAndType(DeviceObject, DeviceInfo->DeviceIndex, DeviceInfo->DeviceType, &WaveInfo); + if (!NT_SUCCESS(Status)) + { + /* failed to find wave info */ + DbgBreakPoint(); + return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, 0); + } + + /* close pin handle which uses same virtual audio device id and pin id */ + FreeIndex = ClosePin(ClientInfo, WaveInfo->FilterId, WaveInfo->PinId, DeviceInfo->DeviceType); + + /* get desired access */ + if (DeviceInfo->DeviceType == WAVE_IN_DEVICE_TYPE) + { + DesiredAccess |= GENERIC_READ; + } + else if (DeviceInfo->DeviceType == WAVE_OUT_DEVICE_TYPE) + { + DesiredAccess |= GENERIC_WRITE; + } + + /* now try open the pin */ + Status = OpenWavePin(DeviceExtension, WaveInfo->FilterId, WaveInfo->PinId, &DeviceInfo->u.WaveFormatEx, DesiredAccess, &PinHandle); + + if (!NT_SUCCESS(Status)) + { + /* failed to open the pin */ + return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, 0); + } + + /* store the handle */ + Status = InsertPinHandle(ClientInfo, WaveInfo->FilterId, WaveInfo->PinId, DeviceInfo->DeviceType, PinHandle, FreeIndex); + if (!NT_SUCCESS(Status)) + { + /* failed to insert handle */ + ZwClose(PinHandle); + return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, 0); + } + + /* store pin handle */ + DeviceInfo->hDevice = PinHandle; + return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO)); +} + +NTSTATUS +WdmAudWaveCapabilities( + IN PDEVICE_OBJECT DeviceObject, + IN PWDMAUD_DEVICE_INFO DeviceInfo, + IN PWDMAUD_CLIENT ClientInfo, + IN PWDMAUD_DEVICE_EXTENSION DeviceExtension) +{ + LPWAVE_INFO WaveInfo; + NTSTATUS Status; + + /* find destination wave */ + Status = GetWaveInfoByIndexAndType(DeviceObject, DeviceInfo->DeviceIndex, DeviceInfo->DeviceType, &WaveInfo); + if (!NT_SUCCESS(Status)) + { + /* failed to find wave info */ + DbgBreakPoint(); + return STATUS_UNSUCCESSFUL; + } + + if (DeviceInfo->DeviceType == WAVE_IN_DEVICE_TYPE) + { + RtlMoveMemory(&DeviceInfo->u.WaveInCaps, &WaveInfo->u.InCaps, sizeof(WAVEINCAPSW)); + } + else + { + RtlMoveMemory(&DeviceInfo->u.WaveOutCaps, &WaveInfo->u.OutCaps, sizeof(WAVEOUTCAPSW)); + } + + return STATUS_SUCCESS; +} + diff --git a/reactos/drivers/wdm/audio/legacy/wdmaud/wdmaud.h b/reactos/drivers/wdm/audio/legacy/wdmaud/wdmaud.h index 561336e2eb7..6941dcb53dd 100644 --- a/reactos/drivers/wdm/audio/legacy/wdmaud/wdmaud.h +++ b/reactos/drivers/wdm/audio/legacy/wdmaud/wdmaud.h @@ -40,21 +40,33 @@ typedef struct ULONG DeviceIndex; MIXERLINEW Line; LPMIXERCONTROLW LineControls; + PULONG NodeIds; }MIXERLINE_EXT, *LPMIXERLINE_EXT; typedef struct { - HANDLE hMixer; - PFILE_OBJECT MixerFileObject; - MIXERCAPSW MixCaps; LIST_ENTRY LineList; - + ULONG ControlId; }MIXER_INFO, *LPMIXER_INFO; +typedef struct +{ + LIST_ENTRY Entry; + ULONG FilterId; + ULONG PinId; + ULONG bInput; + union + { + WAVEOUTCAPSW OutCaps; + WAVEINCAPSW InCaps; + }u; +}WAVE_INFO, *LPWAVE_INFO; + + typedef struct { LIST_ENTRY Entry; @@ -77,6 +89,12 @@ typedef struct ULONG MixerInfoCount; LPMIXER_INFO MixerInfo; + ULONG WaveInDeviceCount; + LIST_ENTRY WaveInList; + + ULONG WaveOutDeviceCount; + LIST_ENTRY WaveOutList; + }WDMAUD_DEVICE_EXTENSION, *PWDMAUD_DEVICE_EXTENSION; @@ -86,6 +104,16 @@ typedef struct PIRP Irp; }CONTEXT_WRITE, *PCONTEXT_WRITE; +NTSTATUS +NTAPI +OpenWavePin( + IN PWDMAUD_DEVICE_EXTENSION DeviceExtension, + IN ULONG FilterId, + IN ULONG PinId, + IN LPWAVEFORMATEX WaveFormatEx, + IN ACCESS_MASK DesiredAccess, + OUT PHANDLE PinHandle); + NTSTATUS WdmAudRegisterDeviceInterface( IN PDEVICE_OBJECT PhysicalDeviceObject, @@ -120,6 +148,14 @@ WdmAudControlOpenMixer( IN PWDMAUD_DEVICE_INFO DeviceInfo, IN PWDMAUD_CLIENT ClientInfo); +NTSTATUS +WdmAudControlOpenWave( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp, + IN PWDMAUD_DEVICE_INFO DeviceInfo, + IN PWDMAUD_CLIENT ClientInfo); + + ULONG GetNumOfMixerDevices( IN PDEVICE_OBJECT DeviceObject); @@ -148,6 +184,13 @@ WdmAudMixerCapabilities( IN PWDMAUD_CLIENT ClientInfo, IN PWDMAUD_DEVICE_EXTENSION DeviceExtension); +NTSTATUS +WdmAudWaveCapabilities( + IN PDEVICE_OBJECT DeviceObject, + IN PWDMAUD_DEVICE_INFO DeviceInfo, + IN PWDMAUD_CLIENT ClientInfo, + IN PWDMAUD_DEVICE_EXTENSION DeviceExtension); + NTSTATUS NTAPI WdmAudFrameSize( @@ -192,5 +235,26 @@ NTSTATUS WdmAudMixerInitialize( IN PDEVICE_OBJECT DeviceObject); +NTSTATUS +NTAPI +WdmAudWaveInitialize( + IN PDEVICE_OBJECT DeviceObject); + +NTSTATUS +ClosePin( + IN PWDMAUD_CLIENT ClientInfo, + IN ULONG FilterId, + IN ULONG PinId, + IN SOUND_DEVICE_TYPE DeviceType); + +NTSTATUS +InsertPinHandle( + IN PWDMAUD_CLIENT ClientInfo, + IN ULONG FilterId, + IN ULONG PinId, + IN SOUND_DEVICE_TYPE DeviceType, + IN HANDLE PinHandle, + IN ULONG FreeIndex); + #endif diff --git a/reactos/drivers/wdm/audio/legacy/wdmaud/wdmaud.rbuild b/reactos/drivers/wdm/audio/legacy/wdmaud/wdmaud.rbuild index fda6c011d24..1b3acd12e84 100644 --- a/reactos/drivers/wdm/audio/legacy/wdmaud/wdmaud.rbuild +++ b/reactos/drivers/wdm/audio/legacy/wdmaud/wdmaud.rbuild @@ -7,9 +7,12 @@ ntoskrnl ks pseh + hal control.c deviface.c entry.c mixer.c + wave.c + sup.c wdmaud.rc