From 7dd79b9a785d0866966de68a8ac69e30794dfd48 Mon Sep 17 00:00:00 2001 From: Oleg Dubinskiy Date: Fri, 2 Sep 2022 20:07:43 +0200 Subject: [PATCH] [AUDIO] Device management code refactoring [WDMAUD.DRV] Completely rewrite Legacy and MMixer routines, to make them more compatible with Windows. - Make it independent from MMEBuddy library and make it using its own MME routines instead of MMEBuddy's. - Get rid from SOUND_DEVICE_INSTANCE structure usage, use WDMAUD_DEVICE_INFO instead. SOUND_DEVICE_INSTANCE has the same purpose as WDMAUD_DEVICE_INFO, and Windows does not use multiple structures, so we also don't need that, to be more compatible with MS. Separate all device state related stuff into WDMAUD_DEVICE_STATE structure. Rework them t the look similar to Windows's (based on analysis). Set alignment 1 for both of them, to make it of the same size as in Windows XP/2003. This gets us better compatibility (and therefore ability to work together) between our/MS wdmaud.drv/sys ring. Although it still doesn't work, but the major steps are done. - Rewrite all Legacy rotines to make them more similar to MS. Add their own WdmAudIoControl, and don't use SyncOverlappedDeviceIoControl from MMEBuddy. - Don't use separate members for each data buffer in WDMAUD_DEVICE_INFO structure, declare one buffer member, which can store several types of data passed by the caller (as in Windows). Add a second member which indicates the size of passed data. - Adapt all MMixer routines to other changes. Use WDMAUD_DEVICE_INFO structure for all of them too, instead of SOUND_DEVICE_INSTANCE. - Implement proper resampling support. Rename WriteFileEx_Remixer to WdmAudResampleStream, and rewrite it to only do the resampling, remove all streaming code from it, which is buggy anyway. Call it in WdmAudSubmitWaveHeader (reworked from WdmAudCommitWaveBuffer), to properly resample wave header data before sending it. Add RESAMPLING_ENABLED define which allows to enable/disable resampling support. - Don't use MMFUNCTION_TABLE structure from MMEBuddy, extend usage of FUNC_NAME macro instead, which redirects to Legacy or MMixer API appropriatedly, depending on USE_MMIXER_LIB define. - Remove WdmAudQueryDeviceInterfaceString, since it does not exist in Windows. The device interface string is already received by calling SetupApi routines and is stored in WDMAUD_DEVICE_INFO structure. - Refactor opening audio device mechanism. Add WdmAudOpenKernelSoundDevice (previously WdmAudOpenSoundDevice), which does the initial initialization of Wdm Audio driver mapper, and WdmAudOpenSoundDevice, which opens the device itself (previously SetWaveDeviceFormat). This is more similar to Windows. - Completely rewrite Wave Header extension management. In Windows, header extension has two members: streaming device info pointer (aka sound private handle), allocated and used by SubmitWaveHeader for I/O operations, and a pointer to OVERLAPPED structure which contains steaming event handle. There is no committed and completed bytes counts. [WDMAUD] Fix all kernel-mode routines, whose are used by Legacy APIs. Adapt them to current changes also. - Fix all IOCTL declarations. Add new/update existing IOCTLs to Windows-compatible state. I investigated them by the following way: 1. Analyze them via debugger, when they are passed to DeviceIoControl. 2. Copy their handle and paste it to any IOCTL decoder (I used OSR online IOCTL Decoder for example). 3. Decode them ang get their actual declarations, those can be used by us. - Use Buffer member of WDMAUD_DEVICE_INFO when possible for storing user data received from/passed to the caller. - Implement some more IOCTLs whose exist in Windows. Add initialization code, and rewrite streaming routine. Use KsStreamIo for that, instead of dumb calling the driver via IoCallDriver. That KS routine is buggy, so it also needs a fix, which I will send in a a separate PR. - Extend usage of MMixer library. Implement MMixerGetWavePosition, and use it for both Legacy and MMixer routines (in wdmaud.sys and wdmaud.drv appropriately). [MMIXER] - Add support for WAVE_FORMAT_EXTENSIBLE audio format. Don't fail when it is requested. Initialize required structure fields for it. It already is supported properly by us, since it is just and extended representation of WAVE_FORMAT_PCM. - Handle some more Mixer control types, to fix sndvol32.exe Mixer open failures after my changes. Remove unneeded duplicating of MIXERCONTROL_CONTROLTYPE_MUX handling. - Implement MMixerGetWavePosition. [KS] - Fix bug in KsStreamIo Properly set output buffer length in IO Stack Location of the current IRP, since it is passed to KsProbeStreamIrp when calling KsStreamIo, so it fails if the length isn't set properly. Don't set an input buffer length and the buffer itself, since it isn't passed anywhere, so setting it makes no sense. Moreover, MSDN says that for IOCTL_KS_READ/WRITE_STREAM, only output buffer (and its length) is needed to be set, but not an input one. So it indeed is more correct. It fixes buffer overflow in KsProbeStreamIrp when attempting to perform the streaming via KsStreamIo. I discovered this bug during my audio refactoring from PR #4660. - Restore old hack for MS portcls. --- dll/directx/wine/dsound/dsound_main.c | 43 +- dll/directx/wine/dsound/primary.c | 20 +- dll/win32/wdmaud.drv/CMakeLists.txt | 19 +- dll/win32/wdmaud.drv/auxiliary/auxMessage.c | 71 + dll/win32/wdmaud.drv/legacy.c | 1183 +++++++---------- dll/win32/wdmaud.drv/midi/midMessage.c | 99 ++ dll/win32/wdmaud.drv/midi/modMessage.c | 89 ++ dll/win32/wdmaud.drv/mixer/mxdMessage.c | 164 +++ dll/win32/wdmaud.drv/mmewrap.c | 335 +++++ dll/win32/wdmaud.drv/mmixer.c | 619 ++++----- dll/win32/wdmaud.drv/reentrancy.c | 106 ++ dll/win32/wdmaud.drv/{mixer.c => resample.c} | 136 +- dll/win32/wdmaud.drv/result.c | 74 ++ dll/win32/wdmaud.drv/wave/header.c | 207 +++ dll/win32/wdmaud.drv/wave/streaming.c | 89 ++ dll/win32/wdmaud.drv/wave/widMessage.c | 134 ++ dll/win32/wdmaud.drv/wave/wodMessage.c | 134 ++ dll/win32/wdmaud.drv/wdmaud.c | 190 +-- dll/win32/wdmaud.drv/wdmaud.h | 351 +++-- dll/win32/wdmaud.drv/wdmaud.spec | 1 + drivers/ksfilter/ks/allocators.c | 7 +- drivers/ksfilter/ks/api.c | 3 +- drivers/ksfilter/ks/clocks.c | 1 + drivers/ksfilter/ks/connectivity.c | 152 ++- drivers/ksfilter/ks/device.c | 4 +- drivers/ksfilter/ks/filter.c | 2 +- drivers/ksfilter/ks/filterfactory.c | 1 + drivers/ksfilter/ks/irp.c | 44 +- drivers/ksfilter/ks/pin.c | 5 +- drivers/ksfilter/ks/swenum.c | 4 +- drivers/ksfilter/ks/topology.c | 3 +- drivers/wdm/audio/backpln/CMakeLists.txt | 2 +- .../wdm/audio/backpln/portcls/irpstream.cpp | 5 +- .../audio/backpln/portcls/pin_wavecyclic.cpp | 5 +- .../audio/backpln/portcls/port_wavecyclic.cpp | 2 +- .../audio/backpln/portcls/propertyhandler.cpp | 7 +- drivers/wdm/audio/drivers/ac97/debug.h | 2 +- drivers/wdm/audio/drivers/ac97/miniport.cpp | 4 + .../wdm/audio/filters/kmixer/CMakeLists.txt | 3 +- drivers/wdm/audio/filters/kmixer/filter.c | 10 - drivers/wdm/audio/filters/kmixer/kmixer.h | 1 + drivers/wdm/audio/filters/kmixer/pin.c | 198 +-- .../wdm/audio/legacy/wdmaud/CMakeLists.txt | 2 +- drivers/wdm/audio/legacy/wdmaud/control.c | 554 ++++---- drivers/wdm/audio/legacy/wdmaud/deviface.c | 184 +-- drivers/wdm/audio/legacy/wdmaud/entry.c | 35 +- drivers/wdm/audio/legacy/wdmaud/interface.h | 512 ++++--- drivers/wdm/audio/legacy/wdmaud/mmixer.c | 188 ++- drivers/wdm/audio/legacy/wdmaud/sup.c | 106 +- drivers/wdm/audio/legacy/wdmaud/wdmaud.h | 81 +- drivers/wdm/audio/sysaudio/control.c | 192 +-- drivers/wdm/audio/sysaudio/deviface.c | 17 +- drivers/wdm/audio/sysaudio/dispatcher.c | 39 +- drivers/wdm/audio/sysaudio/main.c | 10 +- drivers/wdm/audio/sysaudio/pin.c | 221 +-- drivers/wdm/audio/sysaudio/sysaudio.h | 5 +- sdk/include/psdk/ks.h | 17 + sdk/include/psdk/ksmedia.h | 11 + sdk/include/psdk/mmddk.h | 5 + sdk/include/reactos/libs/sound/sndtypes.h | 16 +- sdk/lib/drivers/sound/mmixer/controls.c | 5 +- sdk/lib/drivers/sound/mmixer/filter.c | 5 - sdk/lib/drivers/sound/mmixer/midi.c | 76 +- sdk/lib/drivers/sound/mmixer/mixer.c | 78 +- sdk/lib/drivers/sound/mmixer/mmixer.h | 8 +- sdk/lib/drivers/sound/mmixer/precomp.h | 15 +- sdk/lib/drivers/sound/mmixer/wave.c | 174 ++- 67 files changed, 4406 insertions(+), 2679 deletions(-) create mode 100644 dll/win32/wdmaud.drv/auxiliary/auxMessage.c create mode 100644 dll/win32/wdmaud.drv/midi/midMessage.c create mode 100644 dll/win32/wdmaud.drv/midi/modMessage.c create mode 100644 dll/win32/wdmaud.drv/mixer/mxdMessage.c create mode 100644 dll/win32/wdmaud.drv/mmewrap.c create mode 100644 dll/win32/wdmaud.drv/reentrancy.c rename dll/win32/wdmaud.drv/{mixer.c => resample.c} (76%) create mode 100644 dll/win32/wdmaud.drv/result.c create mode 100644 dll/win32/wdmaud.drv/wave/header.c create mode 100644 dll/win32/wdmaud.drv/wave/streaming.c create mode 100644 dll/win32/wdmaud.drv/wave/widMessage.c create mode 100644 dll/win32/wdmaud.drv/wave/wodMessage.c diff --git a/dll/directx/wine/dsound/dsound_main.c b/dll/directx/wine/dsound/dsound_main.c index f37ab4178c087..c5e36b06b071b 100644 --- a/dll/directx/wine/dsound/dsound_main.c +++ b/dll/directx/wine/dsound/dsound_main.c @@ -319,7 +319,7 @@ HRESULT WINAPI DirectSoundEnumerateW( LPVOID lpContext ) { unsigned devs, wod; - WAVEOUTCAPSW capsW; + LPWAVEOUTCAPSW capsW; GUID guid; int err; @@ -333,16 +333,21 @@ HRESULT WINAPI DirectSoundEnumerateW( setup_dsound_options(); + capsW = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WAVEOUTCAPSW)); + if (!capsW) { + return DSERR_OUTOFMEMORY; + } + devs = waveOutGetNumDevs(); if (devs > 0) { if (GetDeviceID(&DSDEVID_DefaultPlayback, &guid) == DS_OK) { for (wod = 0; wod < devs; ++wod) { if (IsEqualGUID( &guid, &DSOUND_renderer_guids[wod] ) ) { - err = mmErr(waveOutGetDevCapsW(wod, &capsW, sizeof(WAVEOUTCAPSW))); + err = mmErr(waveOutGetDevCapsW(wod, capsW, sizeof(WAVEOUTCAPSW))); if (err == DS_OK) { TRACE("calling lpDSEnumCallback(NULL,\"%ls\",\"%ls\",%p)\n", - capsW.szPname,L"Primary Sound Driver",lpContext); - if (lpDSEnumCallback(NULL, capsW.szPname, L"Primary Sound Driver", lpContext) == FALSE) + capsW->szPname,L"Primary Sound Driver",lpContext); + if (lpDSEnumCallback(NULL, capsW->szPname, L"Primary Sound Driver", lpContext) == FALSE) return DS_OK; } } @@ -351,14 +356,17 @@ HRESULT WINAPI DirectSoundEnumerateW( } for (wod = 0; wod < devs; ++wod) { - err = mmErr(waveOutGetDevCapsW(wod, &capsW, sizeof(WAVEOUTCAPSW))); + err = mmErr(waveOutGetDevCapsW(wod, capsW, sizeof(WAVEOUTCAPSW))); if (err == DS_OK) { TRACE("calling lpDSEnumCallback(%s,\"%ls\",\"%ls\",%p)\n", - debugstr_guid(&DSOUND_renderer_guids[wod]),capsW.szPname,L"Primary Sound Driver",lpContext); - if (lpDSEnumCallback(&DSOUND_renderer_guids[wod], capsW.szPname, L"Primary Sound Driver", lpContext) == FALSE) + debugstr_guid(&DSOUND_renderer_guids[wod]),capsW->szPname,L"Primary Sound Driver",lpContext); + if (lpDSEnumCallback(&DSOUND_renderer_guids[wod], capsW->szPname, L"Primary Sound Driver", lpContext) == FALSE) return DS_OK; } } + + HeapFree(GetProcessHeap(), 0, capsW); + return DS_OK; } @@ -411,7 +419,7 @@ DirectSoundCaptureEnumerateW( LPVOID lpContext) { unsigned devs, wid; - WAVEINCAPSW capsW; + LPWAVEINCAPSW capsW; GUID guid; int err; @@ -424,16 +432,21 @@ DirectSoundCaptureEnumerateW( setup_dsound_options(); + capsW = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WAVEINCAPSW)); + if (!capsW) { + return DSERR_OUTOFMEMORY; + } + devs = waveInGetNumDevs(); if (devs > 0) { if (GetDeviceID(&DSDEVID_DefaultCapture, &guid) == DS_OK) { for (wid = 0; wid < devs; ++wid) { if (IsEqualGUID( &guid, &DSOUND_capture_guids[wid] ) ) { - err = mmErr(waveInGetDevCapsW(wid, &capsW, sizeof(WAVEINCAPSW))); + err = mmErr(waveInGetDevCapsW(wid, capsW, sizeof(WAVEINCAPSW))); if (err == DS_OK) { TRACE("calling lpDSEnumCallback(NULL,\"%ls\",\"%ls\",%p)\n", - capsW.szPname,L"Primary Sound Capture Driver",lpContext); - if (lpDSEnumCallback(NULL, capsW.szPname, L"Primary Sound Capture Driver", lpContext) == FALSE) + capsW->szPname,L"Primary Sound Capture Driver",lpContext); + if (lpDSEnumCallback(NULL, capsW->szPname, L"Primary Sound Capture Driver", lpContext) == FALSE) return DS_OK; } } @@ -442,15 +455,17 @@ DirectSoundCaptureEnumerateW( } for (wid = 0; wid < devs; ++wid) { - err = mmErr(waveInGetDevCapsW(wid, &capsW, sizeof(WAVEINCAPSW))); + err = mmErr(waveInGetDevCapsW(wid, capsW, sizeof(WAVEINCAPSW))); if (err == DS_OK) { TRACE("calling lpDSEnumCallback(%s,\"%ls\",\"%ls\",%p)\n", - debugstr_guid(&DSOUND_capture_guids[wid]),capsW.szPname,L"Primary Sound Capture Driver",lpContext); - if (lpDSEnumCallback(&DSOUND_capture_guids[wid], capsW.szPname, L"Primary Sound Capture Driver", lpContext) == FALSE) + debugstr_guid(&DSOUND_capture_guids[wid]),capsW->szPname,L"Primary Sound Capture Driver",lpContext); + if (lpDSEnumCallback(&DSOUND_capture_guids[wid], capsW->szPname, L"Primary Sound Capture Driver", lpContext) == FALSE) return DS_OK; } } + HeapFree(GetProcessHeap(), 0, capsW); + return DS_OK; } diff --git a/dll/directx/wine/dsound/primary.c b/dll/directx/wine/dsound/primary.c index b04a526929e4e..ac57ce3632ae7 100644 --- a/dll/directx/wine/dsound/primary.c +++ b/dll/directx/wine/dsound/primary.c @@ -465,19 +465,19 @@ HRESULT primarybuffer_SetFormat(DirectSoundDevice *device, LPCWAVEFORMATEX wfex) LPWAVEFORMATEX oldpwfx; BOOL forced = device->priolevel == DSSCL_WRITEPRIMARY; - TRACE("(%p,%p)\n", device, wfex); - + ERR("(%p,%p)\n", device, wfex); + ERR("forced %x\n", forced); if (device->priolevel == DSSCL_NORMAL) { - WARN("failed priority check!\n"); + ERR("failed priority check!\n"); return DSERR_PRIOLEVELNEEDED; } /* Let's be pedantic! */ if (wfex == NULL) { - WARN("invalid parameter: wfex==NULL!\n"); + ERR("invalid parameter: wfex==NULL!\n"); return DSERR_INVALIDPARAM; } - TRACE("(formattag=0x%04x,chans=%d,samplerate=%d," + ERR("(formattag=0x%04x,chans=%d,samplerate=%d," "bytespersec=%d,blockalign=%d,bitspersamp=%d,cbSize=%d)\n", wfex->wFormatTag, wfex->nChannels, wfex->nSamplesPerSec, wfex->nAvgBytesPerSec, wfex->nBlockAlign, @@ -514,7 +514,7 @@ HRESULT primarybuffer_SetFormat(DirectSoundDevice *device, LPCWAVEFORMATEX wfex) if (err != DSERR_BUFFERLOST && FAILED(err)) { DWORD size = DSOUND_GetFormatSize(oldpwfx); - WARN("IDsDriverBuffer_SetFormat failed\n"); + ERR("IDsDriverBuffer_SetFormat failed\n"); if (!forced) { CopyMemory(device->pwfx, oldpwfx, size); err = DS_OK; @@ -547,12 +547,12 @@ HRESULT primarybuffer_SetFormat(DirectSoundDevice *device, LPCWAVEFORMATEX wfex) err = DSOUND_ReopenDevice(device, FALSE); if (FAILED(err)) { - WARN("DSOUND_ReopenDevice failed: %08x\n", err); + ERR("DSOUND_ReopenDevice failed: %08x\n", err); goto done; } err = DSOUND_PrimaryOpen(device); if (err != DS_OK) { - WARN("DSOUND_PrimaryOpen failed\n"); + ERR("DSOUND_PrimaryOpen failed\n"); goto done; } @@ -562,9 +562,9 @@ HRESULT primarybuffer_SetFormat(DirectSoundDevice *device, LPCWAVEFORMATEX wfex) device->pwfx->nSamplesPerSec = wfex->nSamplesPerSec; err = DSOUND_ReopenDevice(device, TRUE); if (FAILED(err)) - WARN("DSOUND_ReopenDevice(2) failed: %08x\n", err); + ERR("DSOUND_ReopenDevice(2) failed: %08x\n", err); else if (FAILED((err = DSOUND_PrimaryOpen(device)))) - WARN("DSOUND_PrimaryOpen(2) failed: %08x\n", err); + ERR("DSOUND_PrimaryOpen(2) failed: %08x\n", err); } } diff --git a/dll/win32/wdmaud.drv/CMakeLists.txt b/dll/win32/wdmaud.drv/CMakeLists.txt index 16703b0d0fd4d..0bc70205c4047 100644 --- a/dll/win32/wdmaud.drv/CMakeLists.txt +++ b/dll/win32/wdmaud.drv/CMakeLists.txt @@ -8,10 +8,21 @@ include_directories( spec2def(wdmaud.drv wdmaud.spec) list(APPEND SOURCE - wdmaud.c - mixer.c - mmixer.c legacy.c + mmewrap.c + mmixer.c + reentrancy.c + resample.c + result.c + wdmaud.c + auxiliary/auxMessage.c + midi/midMessage.c + midi/modMessage.c + mixer/mxdMessage.c + wave/header.c + wave/streaming.c + wave/widMessage.c + wave/wodMessage.c wdmaud.h) add_library(wdmaud.drv MODULE @@ -21,7 +32,7 @@ add_library(wdmaud.drv MODULE set_module_type(wdmaud.drv win32dll UNICODE) set_target_properties(wdmaud.drv PROPERTIES SUFFIX "") -target_link_libraries(wdmaud.drv mmebuddy libsamplerate mmixer) +target_link_libraries(wdmaud.drv libsamplerate mmixer) add_importlibs(wdmaud.drv user32 winmm advapi32 msvcrt setupapi ksuser kernel32 ntdll) add_pch(wdmaud.drv wdmaud.h SOURCE) add_cd_file(TARGET wdmaud.drv DESTINATION reactos/system32 FOR all) diff --git a/dll/win32/wdmaud.drv/auxiliary/auxMessage.c b/dll/win32/wdmaud.drv/auxiliary/auxMessage.c new file mode 100644 index 0000000000000..01b154785161b --- /dev/null +++ b/dll/win32/wdmaud.drv/auxiliary/auxMessage.c @@ -0,0 +1,71 @@ +/* + * PROJECT: ReactOS Sound System "MME Buddy" Library + * LICENSE: GPL - See COPYING in the top level directory + * FILE: lib/sound/mmebuddy/auxiliary/auxMessage.c + * + * PURPOSE: Provides the auxMessage exported function, as required by + * the MME API, for auxiliary device support. + * + * PROGRAMMERS: Andrew Greenwood (silverblade@reactos.org) +*/ + +#include "wdmaud.h" + +#define YDEBUG +#include + +/* + Standard MME driver entry-point for messages relating to auxiliary devices. +*/ +DWORD +APIENTRY +auxMessage( + UINT DeviceId, + UINT Message, + DWORD_PTR PrivateHandle, + DWORD_PTR Parameter1, + DWORD_PTR Parameter2) +{ + MMRESULT Result = MMSYSERR_NOTSUPPORTED; + + AcquireEntrypointMutex(AUX_DEVICE_TYPE); + + DPRINT("auxMessage - Message type %d\n", Message); + + switch ( Message ) + { +#ifndef USE_MMIXER_LIB + case AUXM_INIT: + { + Result = WdmAudAddRemoveDeviceNode(AUX_DEVICE_TYPE, TRUE); + break; + } + + case DRVM_EXIT: + { + Result = WdmAudAddRemoveDeviceNode(AUX_DEVICE_TYPE, FALSE); + break; + } +#endif + + case AUXDM_GETNUMDEVS : + { + Result = MmeGetNumDevs(AUX_DEVICE_TYPE); + break; + } + + case AUXDM_GETDEVCAPS : + { + Result = MmeGetSoundDeviceCapabilities(AUX_DEVICE_TYPE, + DeviceId, + (MDEVICECAPSEX*)&Parameter1); + break; + } + } + + DPRINT("auxMessage returning MMRESULT %d\n", Result); + + ReleaseEntrypointMutex(AUX_DEVICE_TYPE); + + return Result; +} diff --git a/dll/win32/wdmaud.drv/legacy.c b/dll/win32/wdmaud.drv/legacy.c index 00c9507341d8e..39c02e8eb19ac 100644 --- a/dll/win32/wdmaud.drv/legacy.c +++ b/dll/win32/wdmaud.drv/legacy.c @@ -1,89 +1,257 @@ /* - * PROJECT: ReactOS Sound System - * LICENSE: GPL - See COPYING in the top level directory - * FILE: dll/win32/wdmaud.drv/wdmaud.c - * - * PURPOSE: WDM Audio Driver (User-mode part) - * PROGRAMMERS: Andrew Greenwood (silverblade@reactos.org) - Johannes Anderwald - * - * NOTES: Looking for wodMessage & co? You won't find them here. Try - * the MME Buddy library, which is where these routines are - * actually implemented. - * + * PROJECT: ReactOS Audio Subsystem + * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later) + * PURPOSE: WDM Audio Driver Mapper (User-mode part) + * COPYRIGHT: Copyright 2007-2008 Andrew Greenwood (silverblade@reactos.org) + * Copyright 2009-2010 Johannes Anderwald + * Copyright 2022 Oleg Dubinskiy (oleg.dubinskij30@gmail.com) */ #include "wdmaud.h" -#define NDEBUG -#include -#include +#include -#define KERNEL_DEVICE_NAME L"\\\\.\\wdmaud" +#define YDEBUG +#include +extern MIXER_CONTEXT MixerContext; HANDLE KernelHandle = INVALID_HANDLE_VALUE; DWORD OpenCount = 0; +/* + This is a wrapper around DeviceIoControl which provides control over + instantiated sound devices. It waits for I/O to complete (since an + instantiated sound device is opened _In_ overlapped mode, this is necessary). +*/ +MMRESULT +WdmAudIoControl( + _In_ PWDMAUD_DEVICE_INFO DeviceInfo, + _In_opt_ ULONG BufferSize, + _In_opt_ PVOID Buffer, + _In_ DWORD IoControlCode) +{ + MMRESULT Result = MMSYSERR_NOERROR; + OVERLAPPED Overlapped; + DWORD Transferred = 0; + BOOL IoResult; + + /* Overlapped I/O is done here - this is used for waiting for completion */ + ZeroMemory(&Overlapped, sizeof(OVERLAPPED)); + Overlapped.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL); + + if ( ! Overlapped.hEvent ) + return Win32ErrorToMmResult(GetLastError()); + + /* Store input data */ + DeviceInfo->BufferSize = BufferSize; + DeviceInfo->Buffer = Buffer; + + /* Talk to the device */ + IoResult = DeviceIoControl(KernelHandle, + IoControlCode, + DeviceInfo, + sizeof(WDMAUD_DEVICE_INFO), + DeviceInfo, + sizeof(WDMAUD_DEVICE_INFO), + &Transferred, + &Overlapped); + + /* If failure occurs, make sure it's not just due to the overlapped I/O */ + if ( ! IoResult ) + { + if (GetLastError() == ERROR_IO_PENDING) + { + /* Wait for I/O complete */ + WaitForSingleObject(Overlapped.hEvent, INFINITE); + } + Result = Win32ErrorToMmResult(GetLastError()); + } + + /* Don't need this any more */ + CloseHandle(Overlapped.hEvent); + + DPRINT("Transferred %d bytes in Sync overlapped I/O\n", Transferred); + + return Result; +} + DWORD WINAPI -MixerEventThreadRoutine( +WaveThreadRoutine( LPVOID Parameter) { - HANDLE WaitObjects[2]; - DWORD dwResult; + PWDMAUD_DEVICE_INFO DeviceInfo = (PWDMAUD_DEVICE_INFO)Parameter; + PWAVEHDR_EXTENSION HeaderExtension; + DWORD dwResult = WAIT_FAILED; + PWAVEHDR WaveHeader; +#ifndef USE_MMIXER_LIB MMRESULT Result; - WDMAUD_DEVICE_INFO DeviceInfo; - PSOUND_DEVICE_INSTANCE Instance = (PSOUND_DEVICE_INSTANCE)Parameter; +#endif + HANDLE hEvent; - /* setup wait objects */ - WaitObjects[0] = Instance->hNotifyEvent; - WaitObjects[1] = Instance->hStopEvent; + while (TRUE) + { + DPRINT("WaveQueue %p\n", DeviceInfo->DeviceState->WaveQueue); + WaveHeader = DeviceInfo->DeviceState->WaveQueue; + if (WaveHeader) + { + DPRINT("1\n"); + HeaderExtension = (PWAVEHDR_EXTENSION)WaveHeader->reserved; + if (HeaderExtension) + { + hEvent = HeaderExtension->Overlapped.hEvent; + DPRINT("2\n"); + + if (hEvent) + { + /* Wait for I/O complete */ + dwResult = WaitForSingleObject(hEvent, INFINITE); + DPRINT("dwResult %d\n", dwResult); + } + + DPRINT("3\n"); + if (DeviceInfo) + { + /* Complete current header */ + CompleteWaveHeader(DeviceInfo); + } + else + { + DPRINT1("Invalid device info data %p\n", DeviceInfo); + break; + } + } + else + { + /* Failed, move to the next header */ + DPRINT("4\n"); + DeviceInfo->DeviceState->WaveQueue = DeviceInfo->DeviceState->WaveQueue->lpNext; + } + } + else + { + DPRINT("6\n"); +#ifdef USE_MMIXER_LIB + /* make sure the pin is stopped */ + MMixerSetWaveStatus(&MixerContext, DeviceInfo->hDevice, KSSTATE_STOP); +#else + /* Stop streaming if no more data to stream */ + Result = WdmAudIoControl(DeviceInfo, + 0, + NULL, + DeviceInfo->DeviceType == WAVE_OUT_DEVICE_TYPE ? + IOCTL_PAUSE_PLAYBACK : IOCTL_PAUSE_CAPTURE); + if (!MMSUCCESS(Result)) + { + DPRINT1("Call to %s failed with %d\n", + DeviceInfo->DeviceType == WAVE_OUT_DEVICE_TYPE ? + "IOCTL_PAUSE_PLAYBACK" : "IOCTL_PAUSE_CAPTURE", + GetLastError()); + break; + } +#endif - /* zero device info */ - ZeroMemory(&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO)); + /* Wait for stop event complete */ + WaitForSingleObject(DeviceInfo->DeviceState->hNotifyEvent, INFINITE); - DeviceInfo.hDevice = Instance->Handle; - DeviceInfo.DeviceType = MIXER_DEVICE_TYPE; + /* Done */ + break; + } + } - do + CloseHandle(DeviceInfo->DeviceState->hNotifyEvent); + SetEvent(DeviceInfo->DeviceState->hStopEvent); + + /* Done */ + return 0; +} + +MMRESULT +WdmAudCreateCompletionThread( + _In_ PWDMAUD_DEVICE_INFO DeviceInfo) +{ + if (!DeviceInfo->DeviceState->hThread) { - dwResult = WaitForMultipleObjects(2, WaitObjects, FALSE, INFINITE); + if (!DeviceInfo->DeviceState->hNotifyEvent) + { + DeviceInfo->DeviceState->hNotifyEvent = CreateEventW(NULL, FALSE, FALSE, NULL); + if (!DeviceInfo->DeviceState->hNotifyEvent) + { + DPRINT1("CreateEventW failed with %d\n", GetLastError()); + DeviceInfo->DeviceState->bStartInThread = FALSE; + return Win32ErrorToMmResult(GetLastError()); + } + } - if (dwResult == WAIT_OBJECT_0 + 1) + if (!DeviceInfo->DeviceState->hStopEvent) { - /* stop event was signalled */ - break; + DeviceInfo->DeviceState->hStopEvent = CreateEventW(NULL, FALSE, FALSE, NULL); + if (!DeviceInfo->DeviceState->hStopEvent) + { + DPRINT1("CreateEventW failed with %d\n", GetLastError()); + DeviceInfo->DeviceState->bStartInThread = FALSE; + /* Close previous handle */ + CloseHandle(DeviceInfo->DeviceState->hNotifyEvent); + return Win32ErrorToMmResult(GetLastError()); + } } - do + DeviceInfo->DeviceState->hThread = CreateThread(NULL, + 0, + WaveThreadRoutine, + DeviceInfo, + 0, + NULL); + if (!DeviceInfo->DeviceState->hThread) { - Result = SyncOverlappedDeviceIoControl(KernelHandle, - IOCTL_GET_MIXER_EVENT, - (LPVOID) &DeviceInfo, - sizeof(WDMAUD_DEVICE_INFO), - (LPVOID) &DeviceInfo, - sizeof(WDMAUD_DEVICE_INFO), - NULL); - - if (Result == MMSYSERR_NOERROR) + DPRINT1("CreateThread failed with %d\n", GetLastError()); + DeviceInfo->DeviceState->bStartInThread = FALSE; + /* Close previous handles */ + CloseHandle(DeviceInfo->DeviceState->hNotifyEvent); + CloseHandle(DeviceInfo->DeviceState->hStopEvent); + return Win32ErrorToMmResult(GetLastError()); + } + SetThreadPriority(DeviceInfo->DeviceState->hThread, THREAD_PRIORITY_TIME_CRITICAL); + } + + DeviceInfo->DeviceState->bStartInThread = TRUE; + + return MMSYSERR_NOERROR; +} + +MMRESULT +WdmAudDestroyCompletionThread( + _In_ PWDMAUD_DEVICE_INFO DeviceInfo) +{ + if (DeviceInfo->DeviceState->hThread) + { + if (DeviceInfo->DeviceState->hNotifyEvent) + { + if (DeviceInfo->DeviceState->bStartInThread) { - DriverCallback(Instance->WinMM.ClientCallback, - HIWORD(Instance->WinMM.Flags), - Instance->WinMM.Handle, - DeviceInfo.u.MixerEvent.NotificationType, - Instance->WinMM.ClientCallbackInstanceData, - (DWORD_PTR)DeviceInfo.u.MixerEvent.Value, - 0); + SetEvent(DeviceInfo->DeviceState->hNotifyEvent); + DeviceInfo->DeviceState->bStartInThread = FALSE; } - }while(Result == MMSYSERR_NOERROR); - }while(TRUE); + } - /* done */ - return 0; + if (DeviceInfo->DeviceState->hStopEvent) + { + WaitForSingleObject(DeviceInfo->DeviceState->hStopEvent, INFINITE); + } + + CloseHandle(DeviceInfo->DeviceState->hThread); + + if (DeviceInfo->DeviceState->hStopEvent) + { + CloseHandle(DeviceInfo->DeviceState->hStopEvent); + } + } + + return MMSYSERR_NOERROR; } MMRESULT -WdmAudCleanupByLegacy() +WdmAudCleanupByLegacy(VOID) { if (KernelHandle != INVALID_HANDLE_VALUE) { @@ -95,167 +263,119 @@ WdmAudCleanupByLegacy() } MMRESULT -WdmAudGetNumWdmDevsByLegacy( - IN MMDEVICE_TYPE DeviceType, - OUT DWORD* DeviceCount) +WdmAudAddRemoveDeviceNode( + _In_ SOUND_DEVICE_TYPE DeviceType, + _In_ BOOL bAdd) { MMRESULT Result; - WDMAUD_DEVICE_INFO DeviceInfo; + PWDMAUD_DEVICE_INFO DeviceInfo; - VALIDATE_MMSYS_PARAMETER( KernelHandle != INVALID_HANDLE_VALUE ); VALIDATE_MMSYS_PARAMETER( IS_VALID_SOUND_DEVICE_TYPE(DeviceType) ); - VALIDATE_MMSYS_PARAMETER( DeviceCount ); - ZeroMemory(&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO)); - DeviceInfo.DeviceType = DeviceType; + DPRINT("WDMAUD - AddRemoveDeviceNode DeviceType %u\n", DeviceType); - Result = SyncOverlappedDeviceIoControl(KernelHandle, - IOCTL_GETNUMDEVS_TYPE, - (LPVOID) &DeviceInfo, - sizeof(WDMAUD_DEVICE_INFO), - (LPVOID) &DeviceInfo, - sizeof(WDMAUD_DEVICE_INFO), - NULL); + DeviceInfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WDMAUD_DEVICE_INFO)); + if (!DeviceInfo) + { + /* No memory */ + DPRINT1("Failed to allocate WDMAUD_DEVICE_INFO structure\n"); + return MMSYSERR_NOMEM; + } + + DeviceInfo->DeviceType = DeviceType; + + Result = WdmAudIoControl(DeviceInfo, + 0, + NULL, + bAdd ? + IOCTL_ADD_DEVNODE : + IOCTL_REMOVE_DEVNODE); + + HeapFree(GetProcessHeap(), 0, DeviceInfo); if ( ! MMSUCCESS( Result ) ) { - SND_ERR(L"Call to IOCTL_GETNUMDEVS_TYPE failed\n"); - *DeviceCount = 0; + DPRINT1("Call to %ls failed with %d\n", + bAdd ? L"IOCTL_ADD_DEVNODE" : L"IOCTL_REMOVE_DEVNODE", + GetLastError()); return TranslateInternalMmResult(Result); } - *DeviceCount = DeviceInfo.DeviceCount; - return MMSYSERR_NOERROR; } MMRESULT -WdmAudGetCapabilitiesByLegacy( - IN PSOUND_DEVICE SoundDevice, - IN DWORD DeviceId, - OUT PVOID Capabilities, - IN DWORD CapabilitiesSize) +WdmAudGetNumWdmDevsByLegacy( + _In_ SOUND_DEVICE_TYPE DeviceType, + _Out_ DWORD* DeviceCount) { MMRESULT Result; - MMDEVICE_TYPE DeviceType; - WDMAUD_DEVICE_INFO DeviceInfo; + PWDMAUD_DEVICE_INFO DeviceInfo; - SND_ASSERT( SoundDevice ); - SND_ASSERT( Capabilities ); + VALIDATE_MMSYS_PARAMETER( KernelHandle != INVALID_HANDLE_VALUE ); + VALIDATE_MMSYS_PARAMETER( IS_VALID_SOUND_DEVICE_TYPE(DeviceType) ); + VALIDATE_MMSYS_PARAMETER( DeviceCount ); - Result = GetSoundDeviceType(SoundDevice, &DeviceType); - SND_ASSERT( Result == MMSYSERR_NOERROR ); + DPRINT("WDMAUD - GetNumWdmDevs DeviceType %u\n", DeviceType); - if ( ! MMSUCCESS(Result) ) - return Result; - - SND_TRACE(L"WDMAUD - GetWdmDeviceCapabilities DeviceType %u DeviceId %u\n", DeviceType, DeviceId); + DeviceInfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WDMAUD_DEVICE_INFO)); + if (!DeviceInfo) + { + /* No memory */ + DPRINT1("Failed to allocate WDMAUD_DEVICE_INFO structure\n"); + return MMSYSERR_NOMEM; + } - ZeroMemory(&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO)); - DeviceInfo.DeviceType = DeviceType; - DeviceInfo.DeviceIndex = DeviceId; + DeviceInfo->DeviceType = DeviceType; - Result = SyncOverlappedDeviceIoControl(KernelHandle, - IOCTL_GETCAPABILITIES, - (LPVOID) &DeviceInfo, - sizeof(WDMAUD_DEVICE_INFO), - (LPVOID) &DeviceInfo, - sizeof(WDMAUD_DEVICE_INFO), - NULL); + Result = WdmAudIoControl(DeviceInfo, + 0, + NULL, + IOCTL_GETNUMDEVS_TYPE); - if ( ! MMSUCCESS(Result) ) + if ( ! MMSUCCESS( Result ) ) { + DPRINT1("Call to IOCTL_GETNUMDEVS_TYPE failed with %d\n", GetLastError()); + *DeviceCount = 0; + HeapFree(GetProcessHeap(), 0, DeviceInfo); return TranslateInternalMmResult(Result); } - /* This is pretty much a big hack right now */ - switch ( DeviceType ) - { - case MIXER_DEVICE_TYPE: - { - LPMIXERCAPSW MixerCaps = (LPMIXERCAPSW) Capabilities; - - DeviceInfo.u.MixCaps.szPname[MAXPNAMELEN-1] = L'\0'; - CopyWideString(MixerCaps->szPname, DeviceInfo.u.MixCaps.szPname); - - MixerCaps->cDestinations = DeviceInfo.u.MixCaps.cDestinations; - MixerCaps->fdwSupport = DeviceInfo.u.MixCaps.fdwSupport; - MixerCaps->vDriverVersion = DeviceInfo.u.MixCaps.vDriverVersion; - MixerCaps->wMid = DeviceInfo.u.MixCaps.wMid; - MixerCaps->wPid = DeviceInfo.u.MixCaps.wPid; - break; - } - case WAVE_OUT_DEVICE_TYPE : - { - LPWAVEOUTCAPSW WaveOutCaps = (LPWAVEOUTCAPSW) Capabilities; - - DeviceInfo.u.WaveOutCaps.szPname[MAXPNAMELEN-1] = L'\0'; - WaveOutCaps->wMid = DeviceInfo.u.WaveOutCaps.wMid; - WaveOutCaps->wPid = DeviceInfo.u.WaveOutCaps.wPid; - - WaveOutCaps->vDriverVersion = DeviceInfo.u.WaveOutCaps.vDriverVersion; - CopyWideString(WaveOutCaps->szPname, DeviceInfo.u.WaveOutCaps.szPname); + *DeviceCount = DeviceInfo->DeviceIndex; - WaveOutCaps->dwFormats = DeviceInfo.u.WaveOutCaps.dwFormats; - WaveOutCaps->wChannels = DeviceInfo.u.WaveOutCaps.wChannels; - WaveOutCaps->dwSupport = DeviceInfo.u.WaveOutCaps.dwSupport; - break; - } - case WAVE_IN_DEVICE_TYPE : - { - LPWAVEINCAPSW WaveInCaps = (LPWAVEINCAPSW) Capabilities; - - DeviceInfo.u.WaveInCaps.szPname[MAXPNAMELEN-1] = L'\0'; - - WaveInCaps->wMid = DeviceInfo.u.WaveInCaps.wMid; - WaveInCaps->wPid = DeviceInfo.u.WaveInCaps.wPid; - - WaveInCaps->vDriverVersion = DeviceInfo.u.WaveInCaps.vDriverVersion; - CopyWideString(WaveInCaps->szPname, DeviceInfo.u.WaveInCaps.szPname); - - WaveInCaps->dwFormats = DeviceInfo.u.WaveInCaps.dwFormats; - WaveInCaps->wChannels = DeviceInfo.u.WaveInCaps.wChannels; - WaveInCaps->wReserved1 = 0; - break; - } - case MIDI_IN_DEVICE_TYPE : - { - LPMIDIINCAPSW MidiInCaps = (LPMIDIINCAPSW)Capabilities; + HeapFree(GetProcessHeap(), 0, DeviceInfo); - DeviceInfo.u.MidiInCaps.szPname[MAXPNAMELEN-1] = L'\0'; + return MMSYSERR_NOERROR; +} - MidiInCaps->vDriverVersion = DeviceInfo.u.MidiInCaps.vDriverVersion; - MidiInCaps->wMid = DeviceInfo.u.MidiInCaps.wMid; - MidiInCaps->wPid = DeviceInfo.u.MidiInCaps.wPid; - MidiInCaps->dwSupport = DeviceInfo.u.MidiInCaps.dwSupport; +MMRESULT +WdmAudGetCapabilitiesByLegacy( + _In_ PWDMAUD_DEVICE_INFO DeviceInfo, + _Out_ MDEVICECAPSEX* Capabilities) +{ + MMRESULT Result; - CopyWideString(MidiInCaps->szPname, DeviceInfo.u.MidiInCaps.szPname); - break; - } - case MIDI_OUT_DEVICE_TYPE : - { - LPMIDIOUTCAPSW MidiOutCaps = (LPMIDIOUTCAPSW)Capabilities; + ASSERT( Capabilities ); - DeviceInfo.u.MidiOutCaps.szPname[MAXPNAMELEN-1] = L'\0'; + DPRINT("WDMAUD - GetWdmDeviceCapabilities DeviceType %u DeviceId %u\n", DeviceInfo->DeviceType, DeviceInfo->DeviceIndex); - MidiOutCaps->vDriverVersion = DeviceInfo.u.MidiOutCaps.vDriverVersion; - MidiOutCaps->wMid = DeviceInfo.u.MidiOutCaps.wMid; - MidiOutCaps->wPid = DeviceInfo.u.MidiOutCaps.wPid; - MidiOutCaps->dwSupport = DeviceInfo.u.MidiOutCaps.dwSupport; + Result = WdmAudIoControl(DeviceInfo, + Capabilities->cbSize, + Capabilities->pCaps, + IOCTL_GETCAPABILITIES); - CopyWideString(MidiOutCaps->szPname, DeviceInfo.u.MidiOutCaps.szPname); - break; - } + if ( ! MMSUCCESS(Result) ) + { + DPRINT1("Call to IOCTL_GETCAPABILITIES failed with %d\n", GetLastError()); } - return MMSYSERR_NOERROR; + return Result; } MMRESULT -WdmAudOpenSoundDeviceByLegacy( - IN PSOUND_DEVICE SoundDevice, - OUT PVOID *Handle) +WdmAudOpenKernelSoundDeviceByLegacy(VOID) { + DWORD dwSize; HDEVINFO hDevInfo; SP_DEVICE_INTERFACE_DATA DeviceInterfaceData; GUID SWBusGuid = {STATIC_KSCATEGORY_WDMAUD}; @@ -263,7 +383,7 @@ WdmAudOpenSoundDeviceByLegacy( if ( KernelHandle == INVALID_HANDLE_VALUE ) { - hDevInfo = SetupDiGetClassDevsW(&SWBusGuid, NULL, NULL, DIGCF_DEVICEINTERFACE| DIGCF_PRESENT); + hDevInfo = SetupDiGetClassDevsW(&SWBusGuid, NULL, NULL, DIGCF_DEVICEINTERFACE | DIGCF_PRESENT); if (!hDevInfo) { // failed @@ -278,7 +398,9 @@ WdmAudOpenSoundDeviceByLegacy( return MMSYSERR_ERROR; } - DeviceInterfaceDetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA_W)HeapAlloc(GetProcessHeap(), 0, MAX_PATH * sizeof(WCHAR) + sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W)); + SetupDiGetDeviceInterfaceDetailW(hDevInfo, &DeviceInterfaceData, NULL, 0, &dwSize, NULL); + + DeviceInterfaceDetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA_W)HeapAlloc(GetProcessHeap(), 0, dwSize); if (!DeviceInterfaceDetailData) { // failed @@ -287,21 +409,22 @@ WdmAudOpenSoundDeviceByLegacy( } DeviceInterfaceDetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W); - if (!SetupDiGetDeviceInterfaceDetailW(hDevInfo, &DeviceInterfaceData, DeviceInterfaceDetailData,MAX_PATH * sizeof(WCHAR) + sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W), NULL, NULL)) + if (!SetupDiGetDeviceInterfaceDetailW(hDevInfo, &DeviceInterfaceData, DeviceInterfaceDetailData, dwSize, &dwSize, NULL)) { // failed HeapFree(GetProcessHeap(), 0, DeviceInterfaceDetailData); SetupDiDestroyDeviceInfoList(hDevInfo); return MMSYSERR_ERROR; } - SND_TRACE(L"Opening wdmaud device '%s'\n",DeviceInterfaceDetailData->DevicePath); + + DPRINT("Opening wdmaud device '%ls'\n", DeviceInterfaceDetailData->DevicePath); KernelHandle = CreateFileW(DeviceInterfaceDetailData->DevicePath, - GENERIC_READ | GENERIC_WRITE, - 0, - NULL, - OPEN_EXISTING, - FILE_FLAG_OVERLAPPED, - NULL); + GENERIC_READ | GENERIC_WRITE, + 0, + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, + NULL); HeapFree(GetProcessHeap(), 0, DeviceInterfaceDetailData); SetupDiDestroyDeviceInfoList(hDevInfo); @@ -317,643 +440,335 @@ WdmAudOpenSoundDeviceByLegacy( } MMRESULT -WdmAudCloseSoundDeviceByLegacy( - IN struct _SOUND_DEVICE_INSTANCE* SoundDeviceInstance, - IN PVOID Handle) +WdmAudOpenSoundDeviceByLegacy( + _In_ PWDMAUD_DEVICE_INFO DeviceInfo, + _In_ PWAVEFORMATEX WaveFormat) { - WDMAUD_DEVICE_INFO DeviceInfo; MMRESULT Result; - MMDEVICE_TYPE DeviceType; - PSOUND_DEVICE SoundDevice; - - Result = GetSoundDeviceFromInstance(SoundDeviceInstance, &SoundDevice); - - if ( ! MMSUCCESS(Result) ) - { - return TranslateInternalMmResult(Result); - } if ( OpenCount == 0 ) { return MMSYSERR_NOERROR; } - SND_ASSERT( KernelHandle != INVALID_HANDLE_VALUE ); + ASSERT( KernelHandle != INVALID_HANDLE_VALUE ); - Result = GetSoundDeviceType(SoundDevice, &DeviceType); - SND_ASSERT( Result == MMSYSERR_NOERROR ); + DPRINT("WDMAUD - OpenWdmSoundDevice DeviceType %u\n", DeviceInfo->DeviceType); - if (SoundDeviceInstance->Handle != (PVOID)KernelHandle) - { - ZeroMemory(&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO)); - - DeviceInfo.DeviceType = DeviceType; - DeviceInfo.hDevice = SoundDeviceInstance->Handle; - - /* First stop the stream */ - if (DeviceType != MIXER_DEVICE_TYPE) - { - DeviceInfo.u.State = KSSTATE_PAUSE; - SyncOverlappedDeviceIoControl(KernelHandle, - IOCTL_SETDEVICE_STATE, - (LPVOID) &DeviceInfo, - sizeof(WDMAUD_DEVICE_INFO), - (LPVOID) &DeviceInfo, - sizeof(WDMAUD_DEVICE_INFO), - NULL); - - DeviceInfo.u.State = KSSTATE_ACQUIRE; - SyncOverlappedDeviceIoControl(KernelHandle, - IOCTL_SETDEVICE_STATE, - (LPVOID) &DeviceInfo, - sizeof(WDMAUD_DEVICE_INFO), - (LPVOID) &DeviceInfo, - sizeof(WDMAUD_DEVICE_INFO), - NULL); - - - DeviceInfo.u.State = KSSTATE_STOP; - SyncOverlappedDeviceIoControl(KernelHandle, - IOCTL_SETDEVICE_STATE, - (LPVOID) &DeviceInfo, - sizeof(WDMAUD_DEVICE_INFO), - (LPVOID) &DeviceInfo, - sizeof(WDMAUD_DEVICE_INFO), - NULL); - } - - SyncOverlappedDeviceIoControl(KernelHandle, - IOCTL_CLOSE_WDMAUD, - (LPVOID) &DeviceInfo, - sizeof(WDMAUD_DEVICE_INFO), - (LPVOID) &DeviceInfo, - sizeof(WDMAUD_DEVICE_INFO), - NULL); - } + /* Open device handle */ + Result = WdmAudIoControl(DeviceInfo, + sizeof(WAVEFORMATEX), + WaveFormat, + IOCTL_OPEN_WDMAUD); - if (DeviceType == MIXER_DEVICE_TYPE) + if ( ! MMSUCCESS( Result ) ) { - SetEvent(SoundDeviceInstance->hStopEvent); - CloseHandle(SoundDeviceInstance->hStopEvent); - CloseHandle(SoundDeviceInstance->hNotifyEvent); + DPRINT1("Call to IOCTL_OPEN_WDMAUD failed with %d\n", GetLastError()); + return TranslateInternalMmResult(Result); } - --OpenCount; - - if ( OpenCount < 1 ) - { - CloseHandle(KernelHandle); - KernelHandle = INVALID_HANDLE_VALUE; - } +#ifdef RESAMPLING_ENABLED + DeviceInfo->Buffer = WaveFormat; + DeviceInfo->BufferSize = sizeof(WAVEFORMATEX); +#endif return MMSYSERR_NOERROR; } MMRESULT -WdmAudSetMixerDeviceFormatByLegacy( - IN PSOUND_DEVICE_INSTANCE Instance, - IN DWORD DeviceId, - IN PWAVEFORMATEX WaveFormat, - IN DWORD WaveFormatSize) +WdmAudCloseSoundDeviceByLegacy( + _In_ PWDMAUD_DEVICE_INFO DeviceInfo, + _In_ PVOID Handle) { MMRESULT Result; - WDMAUD_DEVICE_INFO DeviceInfo; - HANDLE hThread; - Instance->hNotifyEvent = CreateEventW(NULL, FALSE, FALSE, NULL); - if ( ! Instance->hNotifyEvent ) - return MMSYSERR_NOMEM; - - if (Instance->Handle != NULL) + if ( OpenCount == 0 ) { - /* device is already open */ return MMSYSERR_NOERROR; } - Instance->hStopEvent = CreateEventW(NULL, FALSE, FALSE, NULL); - if ( ! Instance->hStopEvent ) - return MMSYSERR_NOMEM; - - ZeroMemory(&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO)); - DeviceInfo.DeviceType = MIXER_DEVICE_TYPE; - DeviceInfo.DeviceIndex = DeviceId; - DeviceInfo.u.hNotifyEvent = Instance->hNotifyEvent; + ASSERT( KernelHandle != INVALID_HANDLE_VALUE ); - Result = SyncOverlappedDeviceIoControl(KernelHandle, - IOCTL_OPEN_WDMAUD, - (LPVOID) &DeviceInfo, - sizeof(WDMAUD_DEVICE_INFO), - (LPVOID) &DeviceInfo, - sizeof(WDMAUD_DEVICE_INFO), - NULL); + DPRINT("WDMAUD - CloseWdmSoundDevice DeviceType %u\n", DeviceInfo->DeviceType); - if ( ! MMSUCCESS(Result) ) + if (DeviceInfo->hDevice != KernelHandle) { - CloseHandle(Instance->hNotifyEvent); - CloseHandle(Instance->hStopEvent); - return TranslateInternalMmResult(Result); + if (DeviceInfo->DeviceType == WAVE_IN_DEVICE_TYPE || DeviceInfo->DeviceType == WAVE_OUT_DEVICE_TYPE) + { + /* Is stream still in use? */ + if (DeviceInfo->DeviceState->WaveQueue) + { + DPRINT1("Stream is still in progress!\n"); + return WAVERR_STILLPLAYING; + } + + /* Destroy I/O thread */ + Result = WdmAudDestroyCompletionThread(DeviceInfo); + ASSERT(Result == MMSYSERR_NOERROR); + } + + /* Close device handle */ + Result = WdmAudIoControl(DeviceInfo, + 0, + NULL, + IOCTL_CLOSE_WDMAUD); + + if ( ! MMSUCCESS(Result) ) + { + DPRINT1("Call to IOCTL_CLOSE_WDMAUD failed with %d\n", GetLastError()); + return TranslateInternalMmResult(Result); + } } - hThread = CreateThread(NULL, 0, MixerEventThreadRoutine, (LPVOID)Instance, 0, NULL); - if ( hThread ) + --OpenCount; + + if ( OpenCount < 1 ) { - CloseHandle(hThread); + CloseHandle(KernelHandle); + KernelHandle = INVALID_HANDLE_VALUE; } - /* Store sound device handle instance handle */ - Instance->Handle = (PVOID)DeviceInfo.hDevice; - return MMSYSERR_NOERROR; } MMRESULT -WdmAudSetWaveDeviceFormatByLegacy( - IN PSOUND_DEVICE_INSTANCE Instance, - IN DWORD DeviceId, - IN PWAVEFORMATEX WaveFormat, - IN DWORD WaveFormatSize) +WdmAudSubmitWaveHeaderByLegacy( + _In_ PWDMAUD_DEVICE_INFO DeviceInfo, + _In_ PWAVEHDR WaveHeader) { - MMRESULT Result; - PSOUND_DEVICE SoundDevice; - PVOID Identifier; - WDMAUD_DEVICE_INFO DeviceInfo; - MMDEVICE_TYPE DeviceType; - - Result = GetSoundDeviceFromInstance(Instance, &SoundDevice); + PWDMAUD_DEVICE_INFO LocalDeviceInfo; + PWAVEHDR_EXTENSION HeaderExtension; + MMRESULT Result = MMSYSERR_NOERROR; + DWORD Transferred = 0; + BOOL IoResult; + DWORD IoCtl; - if ( ! MMSUCCESS(Result) ) - { - return TranslateInternalMmResult(Result); - } - - Result = GetSoundDeviceIdentifier(SoundDevice, &Identifier); - - if ( ! MMSUCCESS(Result) ) - { - return TranslateInternalMmResult(Result); - } + VALIDATE_MMSYS_PARAMETER( DeviceInfo ); - if (Instance->Handle != NULL) - { - /* device is already open */ - return MMSYSERR_NOERROR; - } + DPRINT("WDMAUD - SubmitWaveHeader DeviceType %u\n", DeviceInfo->DeviceType); - Result = GetSoundDeviceType(SoundDevice, &DeviceType); - - SND_ASSERT( Result == MMSYSERR_NOERROR ); - - ZeroMemory(&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO)); - DeviceInfo.DeviceType = DeviceType; - DeviceInfo.DeviceIndex = DeviceId; - DeviceInfo.u.WaveFormatEx.cbSize = sizeof(WAVEFORMATEX); //WaveFormat->cbSize; - DeviceInfo.u.WaveFormatEx.wFormatTag = WaveFormat->wFormatTag; -#ifdef USERMODE_MIXER - DeviceInfo.u.WaveFormatEx.nChannels = 2; - DeviceInfo.u.WaveFormatEx.nSamplesPerSec = 44100; - DeviceInfo.u.WaveFormatEx.nBlockAlign = 4; - DeviceInfo.u.WaveFormatEx.nAvgBytesPerSec = 176400; - DeviceInfo.u.WaveFormatEx.wBitsPerSample = 16; -#else - DeviceInfo.u.WaveFormatEx.nChannels = WaveFormat->nChannels; - DeviceInfo.u.WaveFormatEx.nSamplesPerSec = WaveFormat->nSamplesPerSec; - DeviceInfo.u.WaveFormatEx.nBlockAlign = WaveFormat->nBlockAlign; - DeviceInfo.u.WaveFormatEx.nAvgBytesPerSec = WaveFormat->nAvgBytesPerSec; - DeviceInfo.u.WaveFormatEx.wBitsPerSample = (DeviceInfo.u.WaveFormatEx.nAvgBytesPerSec * 8) / (DeviceInfo.u.WaveFormatEx.nSamplesPerSec * DeviceInfo.u.WaveFormatEx.nChannels); +#ifdef RESAMPLING_ENABLED + /* Resample the stream */ + Result = WdmAudResampleStream(DeviceInfo, WaveHeader); + ASSERT( Result == MMSYSERR_NOERROR ); #endif - Result = SyncOverlappedDeviceIoControl(KernelHandle, - IOCTL_OPEN_WDMAUD, - (LPVOID) &DeviceInfo, - sizeof(WDMAUD_DEVICE_INFO), - (LPVOID) &DeviceInfo, - sizeof(WDMAUD_DEVICE_INFO), - NULL); - - if ( ! MMSUCCESS(Result) ) + LocalDeviceInfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WDMAUD_DEVICE_INFO)); + if (!LocalDeviceInfo) { - return TranslateInternalMmResult(Result); + /* No memory */ + DPRINT1("Failed to allocate WDMAUD_DEVICE_INFO structure\n"); + return MMSYSERR_NOMEM; } - if (WaveFormatSize >= sizeof(WAVEFORMAT)) - { - /* Store format */ - Instance->WaveFormatEx.wFormatTag = WaveFormat->wFormatTag; - Instance->WaveFormatEx.nChannels = WaveFormat->nChannels; - Instance->WaveFormatEx.nSamplesPerSec = WaveFormat->nSamplesPerSec; - Instance->WaveFormatEx.nBlockAlign = WaveFormat->nBlockAlign; - Instance->WaveFormatEx.nAvgBytesPerSec = WaveFormat->nAvgBytesPerSec; - } + HeaderExtension = (PWAVEHDR_EXTENSION)WaveHeader->reserved; + HeaderExtension->DeviceInfo = LocalDeviceInfo; // Will be freed on wave header completion. - /* store details */ - Instance->WaveFormatEx.cbSize = sizeof(WAVEFORMATEX); - Instance->WaveFormatEx.wBitsPerSample = (DeviceInfo.u.WaveFormatEx.nAvgBytesPerSec * 8) / (DeviceInfo.u.WaveFormatEx.nSamplesPerSec * DeviceInfo.u.WaveFormatEx.nChannels); + LocalDeviceInfo->DeviceType = DeviceInfo->DeviceType; + LocalDeviceInfo->DeviceIndex = DeviceInfo->DeviceIndex; + LocalDeviceInfo->hDevice = DeviceInfo->hDevice; + LocalDeviceInfo->Buffer = WaveHeader; + LocalDeviceInfo->BufferSize = sizeof(WAVEHDR); - /* Store sound device handle instance handle */ - Instance->Handle = (PVOID)DeviceInfo.hDevice; + if (DeviceInfo->DeviceType == WAVE_OUT_DEVICE_TYPE) + IoCtl = IOCTL_WRITEDATA; + else if (DeviceInfo->DeviceType == WAVE_IN_DEVICE_TYPE) + IoCtl = IOCTL_READDATA; - /* Now determine framing requirements */ - Result = SyncOverlappedDeviceIoControl(KernelHandle, - IOCTL_GETFRAMESIZE, - (LPVOID) &DeviceInfo, - sizeof(WDMAUD_DEVICE_INFO), - (LPVOID) &DeviceInfo, - sizeof(WDMAUD_DEVICE_INFO), - NULL); + IoResult = DeviceIoControl(KernelHandle, + IoCtl, + LocalDeviceInfo, + sizeof(WDMAUD_DEVICE_INFO), + LocalDeviceInfo, + sizeof(WDMAUD_DEVICE_INFO), + &Transferred, + &HeaderExtension->Overlapped); - if ( MMSUCCESS(Result) ) + if (!IoResult) { - if (DeviceInfo.u.FrameSize) + if (GetLastError() != ERROR_IO_PENDING) { - Instance->FrameSize = DeviceInfo.u.FrameSize * 2; - Instance->BufferCount = WaveFormat->nAvgBytesPerSec / Instance->FrameSize; - SND_TRACE(L"FrameSize %u BufferCount %u\n", Instance->FrameSize, Instance->BufferCount); + DPRINT1("Call to %s failed with %d\n", + DeviceInfo->DeviceType == WAVE_OUT_DEVICE_TYPE ? + "IOCTL_WRITEDATA" : "IOCTL_READDATA", + GetLastError()); } + Result = Win32ErrorToMmResult(GetLastError()); } - else + + if (MMSUCCESS(Result)) { - // use a default of 100 buffers - Instance->BufferCount = 100; + /* Create I/O thread */ + Result = WdmAudCreateCompletionThread(DeviceInfo); + if (!MMSUCCESS(Result)) + { + /* Failed */ + DPRINT1("Failed to create sound thread with error %d\n", GetLastError()); + return TranslateInternalMmResult(Result); + } } - /* Now acquire resources */ - DeviceInfo.u.State = KSSTATE_ACQUIRE; - SyncOverlappedDeviceIoControl(KernelHandle, IOCTL_SETDEVICE_STATE, (LPVOID) &DeviceInfo, sizeof(WDMAUD_DEVICE_INFO), (LPVOID) &DeviceInfo, sizeof(WDMAUD_DEVICE_INFO), NULL); - - /* pause the pin */ - DeviceInfo.u.State = KSSTATE_PAUSE; - SyncOverlappedDeviceIoControl(KernelHandle, IOCTL_SETDEVICE_STATE, (LPVOID) &DeviceInfo, sizeof(WDMAUD_DEVICE_INFO), (LPVOID) &DeviceInfo, sizeof(WDMAUD_DEVICE_INFO), NULL); - - /* start the pin */ - DeviceInfo.u.State = KSSTATE_RUN; - SyncOverlappedDeviceIoControl(KernelHandle, IOCTL_SETDEVICE_STATE, (LPVOID) &DeviceInfo, sizeof(WDMAUD_DEVICE_INFO), (LPVOID) &DeviceInfo, sizeof(WDMAUD_DEVICE_INFO), NULL); - - - return MMSYSERR_NOERROR; -} - -VOID -CALLBACK -LegacyCompletionRoutine( - IN DWORD dwErrorCode, - IN DWORD dwNumberOfBytesTransferred, - IN LPOVERLAPPED lpOverlapped) -{ - PSOUND_OVERLAPPED Overlap; - PWDMAUD_DEVICE_INFO DeviceInfo; - - Overlap = (PSOUND_OVERLAPPED)lpOverlapped; - DeviceInfo = (PWDMAUD_DEVICE_INFO)Overlap->CompletionContext; + DPRINT("Transferred %d bytes in Sync overlapped I/O\n", Transferred); - /* Call mmebuddy overlap routine */ - Overlap->OriginalCompletionRoutine(dwErrorCode, DeviceInfo->Header.DataUsed, lpOverlapped); - - HeapFree(GetProcessHeap(), 0, DeviceInfo); + return Result; } MMRESULT -WdmAudCommitWaveBufferByLegacy( - IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance, - IN PVOID OffsetPtr, - IN DWORD Length, - IN PSOUND_OVERLAPPED Overlap, - IN LPOVERLAPPED_COMPLETION_ROUTINE CompletionRoutine) +WdmAudSetWaveStateByLegacy( + _In_ PWDMAUD_DEVICE_INFO DeviceInfo, + _In_ BOOL bStart) { - HANDLE Handle; MMRESULT Result; - PWDMAUD_DEVICE_INFO DeviceInfo; - PSOUND_DEVICE SoundDevice; - MMDEVICE_TYPE DeviceType; - BOOL Ret; - - VALIDATE_MMSYS_PARAMETER( SoundDeviceInstance ); - VALIDATE_MMSYS_PARAMETER( OffsetPtr ); - VALIDATE_MMSYS_PARAMETER( Overlap ); - VALIDATE_MMSYS_PARAMETER( CompletionRoutine ); - - GetSoundDeviceInstanceHandle(SoundDeviceInstance, &Handle); - SND_ASSERT(Handle); - - Result = GetSoundDeviceFromInstance(SoundDeviceInstance, &SoundDevice); - - if ( ! MMSUCCESS(Result) ) - { - return TranslateInternalMmResult(Result); - } - - Result = GetSoundDeviceType(SoundDevice, &DeviceType); - SND_ASSERT( Result == MMSYSERR_NOERROR ); + DWORD IoCtl; - DeviceInfo = (PWDMAUD_DEVICE_INFO)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WDMAUD_DEVICE_INFO)); - if (!DeviceInfo) - { - // no memory - return MMSYSERR_NOMEM; - } - - DeviceInfo->Header.FrameExtent = Length; - if (DeviceType == WAVE_OUT_DEVICE_TYPE) - { - DeviceInfo->Header.DataUsed = Length; - } - DeviceInfo->Header.Data = OffsetPtr; - DeviceInfo->Header.Size = sizeof(WDMAUD_DEVICE_INFO); - DeviceInfo->Header.PresentationTime.Numerator = 1; - DeviceInfo->Header.PresentationTime.Denominator = 1; - DeviceInfo->hDevice = Handle; - DeviceInfo->DeviceType = DeviceType; + DPRINT("WDMAUD - SetWaveState DeviceType %u\n", DeviceInfo->DeviceType); + DeviceInfo->DeviceState->bStart = bStart; - // create completion event - Overlap->Standard.hEvent = Handle = CreateEventW(NULL, FALSE, FALSE, NULL); - if (Overlap->Standard.hEvent == NULL) + if (DeviceInfo->DeviceType == WAVE_IN_DEVICE_TYPE) { - // no memory - HeapFree(GetProcessHeap(), 0, DeviceInfo); - return MMSYSERR_NOMEM; + IoCtl = bStart ? IOCTL_START_CAPTURE : IOCTL_PAUSE_CAPTURE; } - - Overlap->OriginalCompletionRoutine = CompletionRoutine; - Overlap->CompletionContext = (PVOID)DeviceInfo; - - if (DeviceType == WAVE_OUT_DEVICE_TYPE) + else if (DeviceInfo->DeviceType == WAVE_OUT_DEVICE_TYPE) { - Ret = WriteFileEx(KernelHandle, DeviceInfo, sizeof(WDMAUD_DEVICE_INFO), (LPOVERLAPPED)Overlap, LegacyCompletionRoutine); - if (Ret) - WaitForSingleObjectEx (KernelHandle, INFINITE, TRUE); + IoCtl = bStart ? IOCTL_START_PLAYBACK : IOCTL_PAUSE_PLAYBACK; } - else if (DeviceType == WAVE_IN_DEVICE_TYPE) - { - Ret = ReadFileEx(KernelHandle, DeviceInfo, sizeof(WDMAUD_DEVICE_INFO), (LPOVERLAPPED)Overlap, LegacyCompletionRoutine); - if (Ret) - WaitForSingleObjectEx (KernelHandle, INFINITE, TRUE); - } - - // close event handle - CloseHandle(Handle); - - return MMSYSERR_NOERROR; -} - -MMRESULT -WdmAudSetWaveStateByLegacy( - IN struct _SOUND_DEVICE_INSTANCE* SoundDeviceInstance, - IN BOOL bStart) -{ - MMRESULT Result; - PSOUND_DEVICE SoundDevice; - WDMAUD_DEVICE_INFO DeviceInfo; - MMDEVICE_TYPE DeviceType; - HANDLE Handle; - Result = GetSoundDeviceFromInstance(SoundDeviceInstance, &SoundDevice); + Result = WdmAudIoControl(DeviceInfo, + 0, + NULL, + IoCtl); - if ( ! MMSUCCESS(Result) ) + if ( ! MMSUCCESS( Result ) ) { + DPRINT1("Call to %s failed with %d\n", + DeviceInfo->DeviceType == WAVE_OUT_DEVICE_TYPE ? + (bStart ? "IOCTL_START_PLAYBACK" : "IOCTL_PAUSE_PLAYBACK") : + (bStart ? "IOCTL_START_CAPTURE" : "IOCTL_PAUSE_CAPTURE"), + GetLastError()); return TranslateInternalMmResult(Result); } - Result = GetSoundDeviceType(SoundDevice, &DeviceType); - SND_ASSERT( Result == MMSYSERR_NOERROR ); - - Result = GetSoundDeviceInstanceHandle(SoundDeviceInstance, &Handle); - SND_ASSERT( Result == MMSYSERR_NOERROR ); - - ZeroMemory(&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO)); - DeviceInfo.hDevice = Handle; - DeviceInfo.DeviceType = DeviceType; - - if (bStart) - DeviceInfo.u.State = KSSTATE_RUN; - else - DeviceInfo.u.State = KSSTATE_PAUSE; - Result = SyncOverlappedDeviceIoControl(KernelHandle, - IOCTL_SETDEVICE_STATE, - (LPVOID) &DeviceInfo, - sizeof(WDMAUD_DEVICE_INFO), - (LPVOID) &DeviceInfo, - sizeof(WDMAUD_DEVICE_INFO), - NULL); - - return Result; + return MMSYSERR_NOERROR; } MMRESULT -WdmAudGetDeviceInterfaceStringByLegacy( - IN MMDEVICE_TYPE DeviceType, - IN DWORD DeviceId, - IN LPWSTR Interface, - IN DWORD InterfaceLength, - OUT DWORD * InterfaceSize) +WdmAudResetStreamByLegacy( + _In_ PWDMAUD_DEVICE_INFO DeviceInfo, + _In_ BOOL bStartReset) { - WDMAUD_DEVICE_INFO DeviceInfo; MMRESULT Result; + DWORD IoCtl; - ZeroMemory(&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO)); - DeviceInfo.DeviceType = DeviceType; - DeviceInfo.DeviceIndex = DeviceId; + DPRINT("WDMAUD - ResetWaveStream DeviceType %u\n", DeviceInfo->DeviceType); + DeviceInfo->DeviceState->bReset = bStartReset; + DeviceInfo->DeviceState->bStart = FALSE; - Result = SyncOverlappedDeviceIoControl(KernelHandle, - IOCTL_QUERYDEVICEINTERFACESTRING, - (LPVOID) &DeviceInfo, - sizeof(WDMAUD_DEVICE_INFO), - (LPVOID) &DeviceInfo, - sizeof(WDMAUD_DEVICE_INFO), - NULL); + IoCtl = DeviceInfo->DeviceType == WAVE_OUT_DEVICE_TYPE ? + IOCTL_RESET_PLAYBACK : IOCTL_RESET_CAPTURE; + Result = WdmAudIoControl(DeviceInfo, + 0, + NULL, + IoCtl); if ( ! MMSUCCESS(Result) ) { + DPRINT1("Call to %s failed with %d\n", + DeviceInfo->DeviceType == WAVE_OUT_DEVICE_TYPE ? + "IOCTL_RESET_PLAYBACK" : "IOCTL_RESET_CAPTURE", + GetLastError()); return TranslateInternalMmResult(Result); } + Result = WdmAudDestroyCompletionThread(DeviceInfo); + ASSERT(Result == MMSYSERR_NOERROR); - if (!Interface) - { - SND_ASSERT(InterfaceSize); - - *InterfaceSize = DeviceInfo.u.Interface.DeviceInterfaceStringSize; - return MMSYSERR_NOERROR; - } - - if (InterfaceLength < DeviceInfo.u.Interface.DeviceInterfaceStringSize) - { - /* buffer is too small */ - return MMSYSERR_MOREDATA; - } - - DeviceInfo.u.Interface.DeviceInterfaceStringSize = InterfaceLength; - DeviceInfo.u.Interface.DeviceInterfaceString = Interface; - - Result = SyncOverlappedDeviceIoControl(KernelHandle, - IOCTL_QUERYDEVICEINTERFACESTRING, - (LPVOID) &DeviceInfo, - sizeof(WDMAUD_DEVICE_INFO), - (LPVOID) &DeviceInfo, - sizeof(WDMAUD_DEVICE_INFO), - NULL); - - if ( MMSUCCESS(Result) && InterfaceLength > 2) - { - Interface[1] = L'\\'; - Interface[InterfaceLength-1] = L'\0'; - } - - return Result; + return MMSYSERR_NOERROR; } MMRESULT WdmAudGetWavePositionByLegacy( - IN struct _SOUND_DEVICE_INSTANCE* SoundDeviceInstance, - IN MMTIME* Time) + _In_ PWDMAUD_DEVICE_INFO DeviceInfo, + _In_ MMTIME* Time) { MMRESULT Result; - PSOUND_DEVICE SoundDevice; - WDMAUD_DEVICE_INFO DeviceInfo; - MMDEVICE_TYPE DeviceType; - HANDLE Handle; + DWORD Position; + DWORD IoCtl; - Result = GetSoundDeviceFromInstance(SoundDeviceInstance, &SoundDevice); + DPRINT("WDMAUD - GetWavePosition DeviceType %u\n", DeviceInfo->DeviceType); - if ( ! MMSUCCESS(Result) ) - { - return TranslateInternalMmResult(Result); - } - - Result = GetSoundDeviceType(SoundDevice, &DeviceType); - SND_ASSERT( Result == MMSYSERR_NOERROR ); - - Result = GetSoundDeviceInstanceHandle(SoundDeviceInstance, &Handle); - SND_ASSERT( Result == MMSYSERR_NOERROR ); + IoCtl = DeviceInfo->DeviceType == WAVE_OUT_DEVICE_TYPE ? + IOCTL_GETOUTPOS : IOCTL_GETINPOS; - ZeroMemory(&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO)); - DeviceInfo.hDevice = Handle; - DeviceInfo.DeviceType = DeviceType; - - Result = SyncOverlappedDeviceIoControl(KernelHandle, - IOCTL_OPEN_WDMAUD, - (LPVOID) &DeviceInfo, - sizeof(WDMAUD_DEVICE_INFO), - (LPVOID) &DeviceInfo, - sizeof(WDMAUD_DEVICE_INFO), - NULL); + Result = WdmAudIoControl(DeviceInfo, + sizeof(DWORD), + &Position, + IoCtl); if ( ! MMSUCCESS(Result) ) { + DPRINT1("Call to %s failed with %d\n", + DeviceInfo->DeviceType == WAVE_OUT_DEVICE_TYPE ? + "IOCTL_GETOUTPOS" : "IOCTL_GETINPOS", + GetLastError()); return TranslateInternalMmResult(Result); } + /* Store position */ Time->wType = TIME_BYTES; - Time->u.cb = (DWORD)DeviceInfo.u.Position; + Time->u.cb = Position; return MMSYSERR_NOERROR; } - -MMRESULT -WdmAudResetStreamByLegacy( - IN struct _SOUND_DEVICE_INSTANCE* SoundDeviceInstance, - IN MMDEVICE_TYPE DeviceType, - IN BOOLEAN bStartReset) -{ - MMRESULT Result; - HANDLE Handle; - WDMAUD_DEVICE_INFO DeviceInfo; - - Result = GetSoundDeviceInstanceHandle(SoundDeviceInstance, &Handle); - SND_ASSERT( Result == MMSYSERR_NOERROR ); - - ZeroMemory(&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO)); - DeviceInfo.hDevice = Handle; - DeviceInfo.DeviceType = DeviceType; - DeviceInfo.u.ResetStream = (bStartReset ? KSRESET_BEGIN : KSRESET_END); - - Result = SyncOverlappedDeviceIoControl(KernelHandle, - IOCTL_RESET_STREAM, - (LPVOID) &DeviceInfo, - sizeof(WDMAUD_DEVICE_INFO), - (LPVOID) &DeviceInfo, - sizeof(WDMAUD_DEVICE_INFO), - NULL); - return Result; -} - MMRESULT WdmAudQueryMixerInfoByLegacy( - IN struct _SOUND_DEVICE_INSTANCE* SoundDeviceInstance, - IN DWORD DeviceId, - IN UINT uMsg, - IN LPVOID Parameter, - IN DWORD Flags) + _In_ PWDMAUD_DEVICE_INFO DeviceInfo, + _In_ DWORD DeviceId, + _In_ UINT uMsg, + _In_ LPVOID Parameter, + _In_ DWORD Flags) { MMRESULT Result; - WDMAUD_DEVICE_INFO DeviceInfo; - HANDLE Handle; DWORD IoControlCode; - LPMIXERLINEW MixLine; - LPMIXERLINECONTROLSW MixControls; - LPMIXERCONTROLDETAILS MixDetails; - SND_TRACE(L"uMsg %x Flags %x\n", uMsg, Flags); + DPRINT("WDMAUD - QueryMixerInfo: uMsg %x Flags %x\n", uMsg, Flags); - Result = GetSoundDeviceInstanceHandle(SoundDeviceInstance, &Handle); - SND_ASSERT( Result == MMSYSERR_NOERROR ); - - ZeroMemory(&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO)); - DeviceInfo.hDevice = Handle; - DeviceInfo.DeviceIndex = DeviceId; - DeviceInfo.DeviceType = MIXER_DEVICE_TYPE; - DeviceInfo.Flags = Flags; - - MixLine = (LPMIXERLINEW)Parameter; - MixControls = (LPMIXERLINECONTROLSW)Parameter; - MixDetails = (LPMIXERCONTROLDETAILS)Parameter; + DeviceInfo->DeviceIndex = DeviceId; + DeviceInfo->DeviceType = MIXER_DEVICE_TYPE; + DeviceInfo->Flags = Flags; switch(uMsg) { case MXDM_GETLINEINFO: - RtlCopyMemory(&DeviceInfo.u.MixLine, MixLine, sizeof(MIXERLINEW)); IoControlCode = IOCTL_GETLINEINFO; break; case MXDM_GETLINECONTROLS: - RtlCopyMemory(&DeviceInfo.u.MixControls, MixControls, sizeof(MIXERLINECONTROLSW)); IoControlCode = IOCTL_GETLINECONTROLS; break; - case MXDM_SETCONTROLDETAILS: - RtlCopyMemory(&DeviceInfo.u.MixDetails, MixDetails, sizeof(MIXERCONTROLDETAILS)); + case MXDM_SETCONTROLDETAILS: IoControlCode = IOCTL_SETCONTROLDETAILS; break; - case MXDM_GETCONTROLDETAILS: - RtlCopyMemory(&DeviceInfo.u.MixDetails, MixDetails, sizeof(MIXERCONTROLDETAILS)); + case MXDM_GETCONTROLDETAILS: IoControlCode = IOCTL_GETCONTROLDETAILS; break; - default: - SND_ASSERT(0); - return MMSYSERR_NOTSUPPORTED; + default: + ASSERT(0); + break; } - Result = SyncOverlappedDeviceIoControl(KernelHandle, - IoControlCode, - (LPVOID) &DeviceInfo, - sizeof(WDMAUD_DEVICE_INFO), - (LPVOID) &DeviceInfo, - sizeof(WDMAUD_DEVICE_INFO), - NULL); + Result = WdmAudIoControl(DeviceInfo, + sizeof(Parameter), + Parameter, + IoControlCode); if ( ! MMSUCCESS(Result) ) { - return Result; - } - - switch(uMsg) - { - case MXDM_GETLINEINFO: - { - RtlCopyMemory(MixLine, &DeviceInfo.u.MixLine, sizeof(MIXERLINEW)); - break; - } + DPRINT1("Call to 0x%lx failed with %d\n", IoControlCode, GetLastError()); + return TranslateInternalMmResult(Result); } - return Result; + return MMSYSERR_NOERROR; } diff --git a/dll/win32/wdmaud.drv/midi/midMessage.c b/dll/win32/wdmaud.drv/midi/midMessage.c new file mode 100644 index 0000000000000..d49548ed44091 --- /dev/null +++ b/dll/win32/wdmaud.drv/midi/midMessage.c @@ -0,0 +1,99 @@ +/* + * PROJECT: ReactOS Sound System "MME Buddy" Library + * LICENSE: GPL - See COPYING in the top level directory + * FILE: lib/sound/mmebuddy/midi/midMessage.c + * + * PURPOSE: Provides the midMessage exported function, as required by + * the MME API, for MIDI input device support. + * + * PROGRAMMERS: Andrew Greenwood (silverblade@reactos.org) +*/ + +#include "wdmaud.h" + +#define YDEBUG +#include + +/* + Standard MME driver entry-point for messages relating to MIDI input. +*/ +DWORD +APIENTRY +midMessage( + UINT DeviceId, + UINT Message, + DWORD_PTR PrivateHandle, + DWORD_PTR Parameter1, + DWORD_PTR Parameter2) +{ + MMRESULT Result = MMSYSERR_NOTSUPPORTED; + + AcquireEntrypointMutex(MIDI_IN_DEVICE_TYPE); + + DPRINT("midMessage - Message type %d\n", Message); + + switch ( Message ) + { +#ifndef USE_MMIXER_LIB + case MIDM_INIT: + { + Result = WdmAudAddRemoveDeviceNode(MIDI_IN_DEVICE_TYPE, TRUE); + break; + } + + case DRVM_EXIT: + { + Result = WdmAudAddRemoveDeviceNode(MIDI_IN_DEVICE_TYPE, FALSE); + break; + } +#endif + + case MIDM_GETNUMDEVS : + { + Result = MmeGetNumDevs(MIDI_IN_DEVICE_TYPE); + break; + } + + case MIDM_GETDEVCAPS : + { + Result = MmeGetSoundDeviceCapabilities(MIDI_IN_DEVICE_TYPE, + DeviceId, + (MDEVICECAPSEX*)Parameter1); + break; + } + + case MIDM_OPEN : + { + Result = MmeOpenDevice(MIDI_IN_DEVICE_TYPE, + DeviceId, + (LPWAVEOPENDESC)Parameter1, + Parameter2, + (DWORD_PTR*) PrivateHandle); + break; + } + + case MIDM_CLOSE : + { + Result = MmeCloseDevice(PrivateHandle); + break; + } + + case MIDM_START : + { + Result = MmeSetState(PrivateHandle, TRUE); + break; + } + + case MIDM_STOP : + { + Result = MmeSetState(PrivateHandle, FALSE); + break; + } + } + + DPRINT("midMessage returning MMRESULT %d\n", Result); + + ReleaseEntrypointMutex(MIDI_IN_DEVICE_TYPE); + + return Result; +} diff --git a/dll/win32/wdmaud.drv/midi/modMessage.c b/dll/win32/wdmaud.drv/midi/modMessage.c new file mode 100644 index 0000000000000..72a5abe2f853c --- /dev/null +++ b/dll/win32/wdmaud.drv/midi/modMessage.c @@ -0,0 +1,89 @@ +/* + * PROJECT: ReactOS Sound System "MME Buddy" Library + * LICENSE: GPL - See COPYING in the top level directory + * FILE: lib/sound/mmebuddy/midi/modMessage.c + * + * PURPOSE: Provides the modMessage exported function, as required by + * the MME API, for MIDI output device support. + * + * PROGRAMMERS: Andrew Greenwood (silverblade@reactos.org) +*/ + +#include "wdmaud.h" + +#define YDEBUG +#include + +/* + Standard MME driver entry-point for messages relating to MIDI output. +*/ +DWORD +APIENTRY +modMessage( + UINT DeviceId, + UINT Message, + DWORD_PTR PrivateHandle, + DWORD_PTR Parameter1, + DWORD_PTR Parameter2) +{ + MMRESULT Result = MMSYSERR_NOTSUPPORTED; + + AcquireEntrypointMutex(MIDI_OUT_DEVICE_TYPE); + + DPRINT("modMessage - Message type %d\n", Message); + + switch ( Message ) + { +#ifndef USE_MMIXER_LIB + case MODM_INIT: + { + Result = WdmAudAddRemoveDeviceNode(MIDI_OUT_DEVICE_TYPE, TRUE); + break; + } + + case DRVM_EXIT: + { + Result = WdmAudAddRemoveDeviceNode(MIDI_OUT_DEVICE_TYPE, FALSE); + break; + } +#endif + + case MODM_GETNUMDEVS : + { + Result = MmeGetNumDevs(MIDI_OUT_DEVICE_TYPE); + break; + } + + case MODM_GETDEVCAPS : + { + Result = MmeGetSoundDeviceCapabilities(MIDI_OUT_DEVICE_TYPE, + DeviceId, + (MDEVICECAPSEX*)Parameter1); + break; + } + + case MODM_OPEN : + { + Result = MmeOpenDevice(MIDI_OUT_DEVICE_TYPE, + DeviceId, + (LPWAVEOPENDESC)Parameter1, + Parameter2, + (DWORD_PTR*)PrivateHandle); + break; + } + + case MODM_CLOSE : + { + Result = MmeCloseDevice(PrivateHandle); + + break; + } + + } + + DPRINT("modMessage returning MMRESULT %d\n", Result); + + ReleaseEntrypointMutex(MIDI_OUT_DEVICE_TYPE); + + return Result; +} diff --git a/dll/win32/wdmaud.drv/mixer/mxdMessage.c b/dll/win32/wdmaud.drv/mixer/mxdMessage.c new file mode 100644 index 0000000000000..70593f7ea8f48 --- /dev/null +++ b/dll/win32/wdmaud.drv/mixer/mxdMessage.c @@ -0,0 +1,164 @@ +/* + * PROJECT: ReactOS Sound System "MME Buddy" Library + * LICENSE: GPL - See COPYING in the top level directory + * FILE: lib/sound/mmebuddy/mixer/mxdMessage.c + * + * PURPOSE: Provides the mxdMessage exported function, as required by + * the MME API, for mixer device support. + * + * PROGRAMMERS: Andrew Greenwood (silverblade@reactos.org) +*/ + +#include "wdmaud.h" + +#define YDEBUG +#include + +MMRESULT +MmeGetLineInfo( + IN UINT DeviceId, + IN UINT Message, + IN DWORD_PTR PrivateHandle, + IN DWORD_PTR Parameter1, + IN DWORD_PTR Parameter2) +{ + PWDMAUD_DEVICE_INFO DeviceInfo; + MMRESULT Result; + + DPRINT("Getting mixer info %u\n", Message); + + if ( PrivateHandle == 0 ) + { + DeviceInfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WDMAUD_DEVICE_INFO)); + if (DeviceInfo) + { + Result = FUNC_NAME(WdmAudQueryMixerInfo)(DeviceInfo, DeviceId, Message, (LPVOID)Parameter1, Parameter2); + HeapFree(GetProcessHeap(), 0, DeviceInfo); + return TranslateInternalMmResult(Result); + } + } + + VALIDATE_MMSYS_PARAMETER( PrivateHandle ); + DeviceInfo = (PWDMAUD_DEVICE_INFO) PrivateHandle; + + return FUNC_NAME(WdmAudQueryMixerInfo)(DeviceInfo, DeviceId, Message, (LPVOID)Parameter1, Parameter2); +} + + +/* + Standard MME driver entry-point for messages relating to mixers. +*/ +DWORD +APIENTRY +mxdMessage( + UINT DeviceId, + UINT Message, + DWORD_PTR PrivateHandle, + DWORD_PTR Parameter1, + DWORD_PTR Parameter2) +{ + MMRESULT Result = MMSYSERR_NOTSUPPORTED; + + AcquireEntrypointMutex(MIXER_DEVICE_TYPE); + + DPRINT("mxdMessage - Message type %d\n", Message); + + switch ( Message ) + { +#ifndef USE_MMIXER_LIB + case MXDM_INIT: + { + Result = WdmAudAddRemoveDeviceNode(MIXER_DEVICE_TYPE, TRUE); + break; + } + + case DRVM_EXIT: + { + Result = WdmAudAddRemoveDeviceNode(MIXER_DEVICE_TYPE, FALSE); + break; + } +#endif + + case MXDM_GETNUMDEVS : + { + Result = MmeGetNumDevs(MIXER_DEVICE_TYPE); + break; + } + + case MXDM_GETDEVCAPS : + { + Result = MmeGetSoundDeviceCapabilities(MIXER_DEVICE_TYPE, + DeviceId, + (MDEVICECAPSEX*)Parameter1); + break; + } + + case MXDM_OPEN : + { + Result = MmeOpenDevice(MIXER_DEVICE_TYPE, + DeviceId, + (LPWAVEOPENDESC)Parameter1, + Parameter2, + (DWORD_PTR*) PrivateHandle); + + break; + } + + case MXDM_CLOSE : + { + Result = MmeCloseDevice(PrivateHandle); + + break; + } + + case MXDM_GETCONTROLDETAILS : + { + Result = MmeGetLineInfo(DeviceId, + Message, + PrivateHandle, + Parameter1, + Parameter2); + + break; + } + + case MXDM_SETCONTROLDETAILS : + { + Result = MmeGetLineInfo(DeviceId, + Message, + PrivateHandle, + Parameter1, + Parameter2); + + break; + } + + case MXDM_GETLINECONTROLS : + { + Result = MmeGetLineInfo(DeviceId, + Message, + PrivateHandle, + Parameter1, + Parameter2); + + break; + } + + case MXDM_GETLINEINFO : + { + Result = MmeGetLineInfo(DeviceId, + Message, + PrivateHandle, + Parameter1, + Parameter2); + + break; + } + } + + DPRINT("mxdMessage returning MMRESULT %d\n", Result); + + ReleaseEntrypointMutex(MIXER_DEVICE_TYPE); + + return Result; +} diff --git a/dll/win32/wdmaud.drv/mmewrap.c b/dll/win32/wdmaud.drv/mmewrap.c new file mode 100644 index 0000000000000..5d2d7b866044f --- /dev/null +++ b/dll/win32/wdmaud.drv/mmewrap.c @@ -0,0 +1,335 @@ +/* + * PROJECT: ReactOS Sound System "MME Buddy" Library + * LICENSE: GPL - See COPYING in the top level directory + * FILE: lib/drivers/sound/mmebuddy/mmewrap.c + * + * PURPOSE: Interface between MME functions and MME Buddy's own. + * + * PROGRAMMERS: Andrew Greenwood (silverblade@reactos.org) +*/ + +#include "wdmaud.h" + +#define YDEBUG +#include + +/* + Sets the device into running or stopped state +*/ + +MMRESULT +MmeSetState( + IN DWORD_PTR PrivateHandle, + IN BOOL bStart) +{ + PWDMAUD_DEVICE_INFO DeviceInfo; + + VALIDATE_MMSYS_PARAMETER( PrivateHandle ); + DeviceInfo = (PWDMAUD_DEVICE_INFO)PrivateHandle; + + VALIDATE_MMSYS_PARAMETER( DeviceInfo ); + + /* Try change state */ + return FUNC_NAME(WdmAudSetWaveState)(DeviceInfo, bStart); +} + +/* + Call the client application when something interesting happens (MME API + defines "interesting things" as device open, close, and buffer + completion.) +*/ +VOID +NotifyMmeClient( + IN PWDMAUD_DEVICE_INFO DeviceInfo, + IN UINT Message, + IN DWORD_PTR Parameter) +{ + ASSERT( DeviceInfo ); + + DPRINT("MME client callback - message %d, parameter %d\n", + (int) Message, + (int) Parameter); + + if ( DeviceInfo->dwCallback ) + { + DriverCallback(DeviceInfo->dwCallback, + HIWORD(DeviceInfo->Flags), + DeviceInfo->hDevice, + Message, + DeviceInfo->dwInstance, + Parameter, + 0); + } +} + +DWORD +MmeGetNumDevs( + IN SOUND_DEVICE_TYPE DeviceType) +{ + MMRESULT Result; + DWORD DeviceCount; + + VALIDATE_MMSYS_PARAMETER( IS_VALID_SOUND_DEVICE_TYPE(DeviceType) ); + + Result = FUNC_NAME(WdmAudGetNumWdmDevs)(DeviceType, &DeviceCount); + + if ( ! MMSUCCESS(Result) ) + { + DPRINT1("Error %d while obtaining number of devices\n", GetLastError()); + return 0; + } + + DPRINT("%d devices of type %d found\n", DeviceCount, DeviceType); + + return DeviceCount; +} + +/* + Obtains the capabilities of a sound device. This routine ensures that the + supplied CapabilitiesSize parameter at least meets the minimum size of the + relevant capabilities structure. + + Ultimately, it will call the GetCapabilities function specified in the + sound device's function table. Note that there are several of these, in a + union. This is simply to avoid manually typecasting when implementing the + functions. +*/ +MMRESULT +MmeGetSoundDeviceCapabilities( + IN SOUND_DEVICE_TYPE DeviceType, + IN DWORD DeviceId, + OUT MDEVICECAPSEX* Capabilities) +{ + PWDMAUD_DEVICE_INFO DeviceInfo; + MMRESULT Result; + + DPRINT("MME *_GETCAPS for device %d of type %d\n", DeviceId, DeviceType); + + /* FIXME: Validate device ID */ + VALIDATE_MMSYS_PARAMETER( Capabilities ); + VALIDATE_MMSYS_PARAMETER( IS_VALID_SOUND_DEVICE_TYPE(DeviceType) ); + + DeviceInfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WDMAUD_DEVICE_INFO)); + if (!DeviceInfo) + { + /* No memory */ + return MMSYSERR_NOMEM; + } + + DeviceInfo->DeviceType = DeviceType; + DeviceInfo->DeviceIndex = DeviceId; + + Result = FUNC_NAME(WdmAudGetCapabilities)(DeviceInfo, + Capabilities); + + HeapFree(GetProcessHeap(), 0, DeviceInfo); + + return Result; +} + +MMRESULT +MmeOpenDevice( + IN SOUND_DEVICE_TYPE DeviceType, + IN UINT DeviceId, + IN LPWAVEOPENDESC OpenParameters, + IN DWORD Flags, + OUT DWORD_PTR* PrivateHandle) +{ + MMRESULT Result; + UINT Message; + PWDMAUD_DEVICE_INFO DeviceInfo; + + DPRINT("Opening device\n"); + + VALIDATE_MMSYS_PARAMETER( IS_WAVE_DEVICE_TYPE(DeviceType) || IS_MIXER_DEVICE_TYPE(DeviceType) || IS_MIDI_DEVICE_TYPE(DeviceType) ); /* FIXME? wave in too? */ + VALIDATE_MMSYS_PARAMETER( OpenParameters ); + + /* Check that winmm gave us a private handle to fill */ + VALIDATE_MMSYS_PARAMETER( PrivateHandle ); + + /* Allocate a new WDMAUD_DEVICE_INFO structure */ + DeviceInfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WDMAUD_DEVICE_INFO)); + if (!DeviceInfo) + { + /* No memory */ + return MMSYSERR_NOMEM; + } + + /* Allocate a new WDMAUD_DEVICE_STATE structure */ + DeviceInfo->DeviceState = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WDMAUD_DEVICE_STATE)); + if (!DeviceInfo->DeviceState) + { + /* No memory */ + HeapFree(GetProcessHeap(), 0, DeviceInfo); + return MMSYSERR_NOMEM; + } + + if (DeviceType == WAVE_IN_DEVICE_TYPE || DeviceType == WAVE_OUT_DEVICE_TYPE) + { + /* Check if the caller just wanted to know if a format is supported */ + if ( Flags & WAVE_FORMAT_QUERY ) + { +#if 0 + DeviceInfo->DeviceType = DeviceType; + DeviceInfo->DeviceIndex = DeviceId; + DeviceInfo->Flags = Flags; + + Result = FUNC_NAME(WdmAudOpenSoundDevice)(DeviceInfo, OpenParameters->lpFormat); + if (!MMSUCCESS(Result)) + { + DPRINT1("Audio format is not supported\n"); + Result = WAVERR_BADFORMAT; + } + + HeapFree(GetProcessHeap(), 0, DeviceInfo->DeviceState); + HeapFree(GetProcessHeap(), 0, DeviceInfo); + return Result; +#else + return MMSYSERR_NOERROR; +#endif + } + } + + DeviceInfo->DeviceType = DeviceType; + DeviceInfo->DeviceIndex = DeviceId; + DeviceInfo->hDevice = OpenParameters->hWave; + DeviceInfo->dwCallback = OpenParameters->dwCallback; + DeviceInfo->dwInstance = OpenParameters->dwInstance; + DeviceInfo->Flags = Flags; + DeviceInfo->hMixer = NULL; + DeviceInfo->NotificationType = 0; + DeviceInfo->Value = 0; + DeviceInfo->DeviceState->WaveQueue = NULL; + DeviceInfo->DeviceState->bStart = FALSE; + DeviceInfo->DeviceState->bStartInThread = FALSE; + DeviceInfo->DeviceState->hNotifyEvent = NULL; + DeviceInfo->DeviceState->hStopEvent = NULL; + DeviceInfo->DeviceState->hThread = NULL; + + /* Open sound device */ + Result = FUNC_NAME(WdmAudOpenSoundDevice)(DeviceInfo, OpenParameters->lpFormat); + if ( ! MMSUCCESS(Result) ) + { + HeapFree(GetProcessHeap(), 0, DeviceInfo->DeviceState); + HeapFree(GetProcessHeap(), 0, DeviceInfo); + return TranslateInternalMmResult(Result); + } + + /* Store the device info pointer in the private handle */ + *PrivateHandle = (DWORD_PTR)DeviceInfo; + + if (DeviceType == WAVE_OUT_DEVICE_TYPE || DeviceType == WAVE_IN_DEVICE_TYPE || + DeviceType == MIDI_OUT_DEVICE_TYPE || DeviceType == MIDI_IN_DEVICE_TYPE) + { + /* Let the application know the device is open */ + + if (DeviceInfo->DeviceType == WAVE_OUT_DEVICE_TYPE) + Message = WOM_OPEN; + else if (DeviceInfo->DeviceType == WAVE_IN_DEVICE_TYPE) + Message = WIM_OPEN; + else if (DeviceInfo->DeviceType == MIDI_IN_DEVICE_TYPE) + Message = MIM_OPEN; + else if (DeviceInfo->DeviceType == MIDI_OUT_DEVICE_TYPE) + Message = MOM_OPEN; + + ReleaseEntrypointMutex(DeviceType); + + NotifyMmeClient(DeviceInfo, + Message, + 0); + + AcquireEntrypointMutex(DeviceType); + } + + DPRINT("Device is now opened\n"); + + return MMSYSERR_NOERROR; +} + +MMRESULT +MmeCloseDevice( + IN DWORD_PTR PrivateHandle) +{ + MMRESULT Result; + PWDMAUD_DEVICE_INFO DeviceInfo; + UINT Message = 0; + + DPRINT("Closing wave device (WIDM_CLOSE / WODM_CLOSE)\n"); + + VALIDATE_MMSYS_PARAMETER( PrivateHandle ); + DeviceInfo = (PWDMAUD_DEVICE_INFO)PrivateHandle; + + if ( ! DeviceInfo ) + return MMSYSERR_INVALHANDLE; + + /* TODO: Check device is stopped! */ + + if (DeviceInfo->DeviceType != MIXER_DEVICE_TYPE) + { + ReleaseEntrypointMutex(DeviceInfo->DeviceType); + + if (DeviceInfo->DeviceType == WAVE_OUT_DEVICE_TYPE) + Message = WOM_CLOSE; + else if (DeviceInfo->DeviceType == WAVE_IN_DEVICE_TYPE) + Message = WIM_CLOSE; + else if (DeviceInfo->DeviceType == MIDI_IN_DEVICE_TYPE) + Message = MIM_CLOSE; + else if (DeviceInfo->DeviceType == MIDI_OUT_DEVICE_TYPE) + Message = MOM_CLOSE; + + /* TODO: Work with MIDI devices too */ + NotifyMmeClient(DeviceInfo, + Message, + 0); + + AcquireEntrypointMutex(DeviceInfo->DeviceType); + } + + /* Clode sound device */ + Result = FUNC_NAME(WdmAudCloseSoundDevice)(DeviceInfo, DeviceInfo->hDevice); + + /* Free device state */ + HeapFree(GetProcessHeap(), 0, DeviceInfo->DeviceState); + + /* Free device info */ + HeapFree(GetProcessHeap(), 0, DeviceInfo); + + return Result; +} + +MMRESULT +MmeResetWavePlayback( + IN DWORD_PTR PrivateHandle) +{ + PWDMAUD_DEVICE_INFO DeviceInfo; + + DPRINT("Resetting wave device (WODM_RESET)\n"); + + VALIDATE_MMSYS_PARAMETER( PrivateHandle ); + DeviceInfo = (PWDMAUD_DEVICE_INFO) PrivateHandle; + + return StopStreaming(DeviceInfo); +} + + +MMRESULT +MmeGetPosition( + IN DWORD_PTR PrivateHandle, + IN MMTIME* Time, + IN DWORD Size) +{ + PWDMAUD_DEVICE_INFO DeviceInfo; + + VALIDATE_MMSYS_PARAMETER( PrivateHandle ); + DeviceInfo = (PWDMAUD_DEVICE_INFO) PrivateHandle; + + if ( ! DeviceInfo ) + return MMSYSERR_INVALHANDLE; + + if ( Size != sizeof(MMTIME) ) + return MMSYSERR_INVALPARAM; + + /* Call the driver */ + return FUNC_NAME(WdmAudGetWavePosition)(DeviceInfo, Time); +} + diff --git a/dll/win32/wdmaud.drv/mmixer.c b/dll/win32/wdmaud.drv/mmixer.c index 8fc2ed6309c9b..531808c4c9f3e 100644 --- a/dll/win32/wdmaud.drv/mmixer.c +++ b/dll/win32/wdmaud.drv/mmixer.c @@ -1,10 +1,9 @@ /* - * PROJECT: ReactOS Sound System - * LICENSE: GPL - See COPYING in the top level directory - * FILE: dll/win32/wdmaud.drv/mmixer.c - * + * PROJECT: ReactOS Audio Subsystem + * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later) * PURPOSE: WDM Audio Mixer API (User-mode part) - * PROGRAMMERS: Johannes Anderwald + * COPYRIGHT: Copyright 2009-2010 Johannes Anderwald + * Copyright 2022 Oleg Dubinskiy (oleg.dubinskij30@gmail.com) */ #include "wdmaud.h" @@ -12,31 +11,25 @@ #include #include #include -#define NTOS_MODE_USER -#include -#include -#define NDEBUG +#define YDEBUG #include -#include BOOL MMixerLibraryInitialized = FALSE; - - PVOID Alloc(ULONG NumBytes); MIXER_STATUS Close(HANDLE hDevice); VOID Free(PVOID Block); VOID Copy(PVOID Src, PVOID Dst, ULONG NumBytes); -MIXER_STATUS Open(IN LPWSTR DevicePath, OUT PHANDLE hDevice); -MIXER_STATUS Control(IN HANDLE hMixer, IN ULONG dwIoControlCode, IN PVOID lpInBuffer, IN ULONG nInBufferSize, OUT PVOID lpOutBuffer, ULONG nOutBufferSize, PULONG lpBytesReturned); -MIXER_STATUS Enum(IN PVOID EnumContext, IN ULONG DeviceIndex, OUT LPWSTR * DeviceName, OUT PHANDLE OutHandle, OUT PHANDLE OutKey); -MIXER_STATUS OpenKey(IN HANDLE hKey, IN LPWSTR SubKey, IN ULONG DesiredAccess, OUT PHANDLE OutKey); -MIXER_STATUS CloseKey(IN HANDLE hKey); -MIXER_STATUS QueryKeyValue(IN HANDLE hKey, IN LPWSTR KeyName, OUT PVOID * ResultBuffer, OUT PULONG ResultLength, OUT PULONG KeyType); -PVOID AllocEventData(IN ULONG ExtraSize); -VOID FreeEventData(IN PVOID EventData); +MIXER_STATUS Open(_In_ LPWSTR DevicePath, _Out_ PHANDLE hDevice); +MIXER_STATUS Control(_In_ HANDLE hMixer, _In_ ULONG dwIoControlCode, _In_ PVOID lpInBuffer, _In_ ULONG nInBufferSize, _Out_ PVOID lpOutBuffer, ULONG nOutBufferSize, PULONG lpBytesReturned); +MIXER_STATUS Enum(_In_ PVOID EnumContext, _In_ ULONG DeviceIndex, _Out_ LPWSTR * DeviceName, _Out_ PHANDLE OutHandle, _Out_ PHANDLE OutKey); +MIXER_STATUS OpenKey(_In_ HANDLE hKey, _In_ LPWSTR SubKey, _In_ ULONG DesiredAccess, _Out_ PHANDLE OutKey); +MIXER_STATUS CloseKey(_In_ HANDLE hKey); +MIXER_STATUS QueryKeyValue(_In_ HANDLE hKey, _In_ LPWSTR KeyName, _Out_ PVOID * ResultBuffer, _Out_ PULONG ResultLength, _Out_ PULONG KeyType); +PVOID AllocEventData(_In_ ULONG ExtraSize); +VOID FreeEventData(_In_ PVOID EventData); MIXER_CONTEXT MixerContext = { @@ -59,11 +52,11 @@ GUID CategoryGuid = {STATIC_KSCATEGORY_AUDIO}; MIXER_STATUS QueryKeyValue( - IN HANDLE hKey, - IN LPWSTR KeyName, - OUT PVOID * ResultBuffer, - OUT PULONG ResultLength, - OUT PULONG KeyType) + _In_ HANDLE hKey, + _In_ LPWSTR KeyName, + _Out_ PVOID * ResultBuffer, + _Out_ PULONG ResultLength, + _Out_ PULONG KeyType) { if (RegQueryValueExW((HKEY)hKey, KeyName, NULL, KeyType, NULL, ResultLength) == ERROR_FILE_NOT_FOUND) return MM_STATUS_UNSUCCESSFUL; @@ -82,10 +75,10 @@ QueryKeyValue( MIXER_STATUS OpenKey( - IN HANDLE hKey, - IN LPWSTR SubKey, - IN ULONG DesiredAccess, - OUT PHANDLE OutKey) + _In_ HANDLE hKey, + _In_ LPWSTR SubKey, + _In_ ULONG DesiredAccess, + _Out_ PHANDLE OutKey) { if (RegOpenKeyExW((HKEY)hKey, SubKey, 0, DesiredAccess, (PHKEY)OutKey) == ERROR_SUCCESS) return MM_STATUS_SUCCESS; @@ -95,7 +88,7 @@ OpenKey( MIXER_STATUS CloseKey( - IN HANDLE hKey) + _In_ HANDLE hKey) { RegCloseKey((HKEY)hKey); return MM_STATUS_SUCCESS; @@ -130,8 +123,8 @@ Copy(PVOID Src, PVOID Dst, ULONG NumBytes) MIXER_STATUS Open( - IN LPWSTR DevicePath, - OUT PHANDLE hDevice) + _In_ LPWSTR DevicePath, + _Out_ PHANDLE hDevice) { DevicePath[1] = L'\\'; *hDevice = CreateFileW(DevicePath, @@ -139,7 +132,7 @@ Open( 0, NULL, OPEN_EXISTING, - FILE_FLAG_OVERLAPPED, + FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL); if (*hDevice == INVALID_HANDLE_VALUE) { @@ -151,11 +144,11 @@ Open( MIXER_STATUS Control( - IN HANDLE hMixer, - IN ULONG dwIoControlCode, - IN PVOID lpInBuffer, - IN ULONG nInBufferSize, - OUT PVOID lpOutBuffer, + _In_ HANDLE hMixer, + _In_ ULONG dwIoControlCode, + _In_ PVOID lpInBuffer, + _In_ ULONG nInBufferSize, + _Out_ PVOID lpOutBuffer, ULONG nOutBufferSize, PULONG lpBytesReturned) { @@ -196,6 +189,11 @@ Control( return MM_STATUS_UNSUCCESSFUL; } + else + { + DPRINT("Waiting...\n"); + WaitForSingleObject(Overlapped.hEvent, INFINITE); + } } /* Wait for the I/O to complete */ @@ -218,11 +216,11 @@ Control( MIXER_STATUS Enum( - IN PVOID EnumContext, - IN ULONG DeviceIndex, - OUT LPWSTR * DeviceName, - OUT PHANDLE OutHandle, - OUT PHANDLE OutKey) + _In_ PVOID EnumContext, + _In_ ULONG DeviceIndex, + _Out_ LPWSTR * DeviceName, + _Out_ PHANDLE OutHandle, + _Out_ PHANDLE OutKey) { SP_DEVICE_INTERFACE_DATA InterfaceData; SP_DEVINFO_DATA DeviceData; @@ -237,10 +235,10 @@ Enum( InterfaceData.Reserved = 0; Result = SetupDiEnumDeviceInterfaces(EnumContext, - NULL, - &CategoryGuid, - DeviceIndex, - &InterfaceData); + NULL, + &CategoryGuid, + DeviceIndex, + &InterfaceData); if (!Result) { @@ -305,7 +303,7 @@ Enum( PVOID AllocEventData( - IN ULONG ExtraSize) + _In_ ULONG ExtraSize) { PKSEVENTDATA Data = (PKSEVENTDATA)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(KSEVENTDATA) + ExtraSize); if (!Data) @@ -323,7 +321,7 @@ AllocEventData( } VOID -FreeEventData(IN PVOID EventData) +FreeEventData(_In_ PVOID EventData) { PKSEVENTDATA Data = (PKSEVENTDATA)EventData; @@ -349,7 +347,7 @@ WdmAudInitUserModeMixer() DeviceHandle = SetupDiGetClassDevs(&CategoryGuid, NULL, NULL, - DIGCF_DEVICEINTERFACE/* FIXME |DIGCF_PRESENT*/); + DIGCF_DEVICEINTERFACE | DIGCF_PRESENT); if (DeviceHandle == INVALID_HANDLE_VALUE) { @@ -379,7 +377,7 @@ WdmAudInitUserModeMixer() } MMRESULT -WdmAudCleanupByMMixer() +WdmAudCleanupByMMixer(VOID) { /* TODO */ return MMSYSERR_NOERROR; @@ -387,8 +385,8 @@ WdmAudCleanupByMMixer() MMRESULT WdmAudGetMixerCapabilities( - IN ULONG DeviceId, - LPMIXERCAPSW Capabilities) + _In_ ULONG DeviceId, + _Out_ LPMIXERCAPSW Capabilities) { if (MMixerGetCapabilities(&MixerContext, DeviceId, Capabilities) == MM_STATUS_SUCCESS) return MMSYSERR_NOERROR; @@ -398,10 +396,10 @@ WdmAudGetMixerCapabilities( MMRESULT WdmAudGetLineInfo( - IN HANDLE hMixer, - IN DWORD MixerId, - IN LPMIXERLINEW MixLine, - IN ULONG Flags) + _In_ HANDLE hMixer, + _In_ DWORD MixerId, + _In_ LPMIXERLINEW MixLine, + _In_ ULONG Flags) { if (MMixerGetLineInfo(&MixerContext, hMixer, MixerId, Flags, MixLine) == MM_STATUS_SUCCESS) return MMSYSERR_NOERROR; @@ -411,10 +409,10 @@ WdmAudGetLineInfo( MMRESULT WdmAudGetLineControls( - IN HANDLE hMixer, - IN DWORD MixerId, - IN LPMIXERLINECONTROLSW MixControls, - IN ULONG Flags) + _In_ HANDLE hMixer, + _In_ DWORD MixerId, + _In_ LPMIXERLINECONTROLSW MixControls, + _In_ ULONG Flags) { if (MMixerGetLineControls(&MixerContext, hMixer, MixerId, Flags, MixControls) == MM_STATUS_SUCCESS) return MMSYSERR_NOERROR; @@ -424,10 +422,10 @@ WdmAudGetLineControls( MMRESULT WdmAudSetControlDetails( - IN HANDLE hMixer, - IN DWORD MixerId, - IN LPMIXERCONTROLDETAILS MixDetails, - IN ULONG Flags) + _In_ HANDLE hMixer, + _In_ DWORD MixerId, + _In_ LPMIXERCONTROLDETAILS MixDetails, + _In_ ULONG Flags) { if (MMixerSetControlDetails(&MixerContext, hMixer, MixerId, Flags, MixDetails) == MM_STATUS_SUCCESS) return MMSYSERR_NOERROR; @@ -438,10 +436,10 @@ WdmAudSetControlDetails( MMRESULT WdmAudGetControlDetails( - IN HANDLE hMixer, - IN DWORD MixerId, - IN LPMIXERCONTROLDETAILS MixDetails, - IN ULONG Flags) + _In_ HANDLE hMixer, + _In_ DWORD MixerId, + _In_ LPMIXERCONTROLDETAILS MixDetails, + _In_ ULONG Flags) { if (MMixerGetControlDetails(&MixerContext, hMixer, MixerId, Flags, MixDetails) == MM_STATUS_SUCCESS) return MMSYSERR_NOERROR; @@ -449,10 +447,34 @@ WdmAudGetControlDetails( return MMSYSERR_ERROR; } +MMRESULT +WdmAudGetMidiOutCapabilities( + _In_ ULONG DeviceId, + _Out_ LPMIDIOUTCAPSW Capabilities) +{ + if (MMixerMidiOutCapabilities(&MixerContext, DeviceId, Capabilities) == MM_STATUS_SUCCESS) + return MMSYSERR_NOERROR; + + return MMSYSERR_ERROR; + +} + +MMRESULT +WdmAudGetMidiInCapabilities( + _In_ ULONG DeviceId, + _Out_ LPMIDIINCAPSW Capabilities) +{ + if (MMixerMidiInCapabilities(&MixerContext, DeviceId, Capabilities) == MM_STATUS_SUCCESS) + return MMSYSERR_NOERROR; + + return MMSYSERR_ERROR; +} + + MMRESULT WdmAudGetWaveOutCapabilities( - IN ULONG DeviceId, - LPWAVEOUTCAPSW Capabilities) + _In_ ULONG DeviceId, + _Out_ LPWAVEOUTCAPSW Capabilities) { if (MMixerWaveOutCapabilities(&MixerContext, DeviceId, Capabilities) == MM_STATUS_SUCCESS) return MMSYSERR_NOERROR; @@ -463,8 +485,8 @@ WdmAudGetWaveOutCapabilities( MMRESULT WdmAudGetWaveInCapabilities( - IN ULONG DeviceId, - LPWAVEINCAPSW Capabilities) + _In_ ULONG DeviceId, + _Out_ LPWAVEINCAPSW Capabilities) { if (MMixerWaveInCapabilities(&MixerContext, DeviceId, Capabilities) == MM_STATUS_SUCCESS) return MMSYSERR_NOERROR; @@ -472,80 +494,104 @@ WdmAudGetWaveInCapabilities( return MMSYSERR_ERROR; } -MMRESULT -WdmAudSetWaveDeviceFormatByMMixer( - IN PSOUND_DEVICE_INSTANCE Instance, - IN DWORD DeviceId, - IN PWAVEFORMATEX WaveFormat, - IN DWORD WaveFormatSize) -{ - MMDEVICE_TYPE DeviceType; - PSOUND_DEVICE SoundDevice; - MMRESULT Result; - BOOL bWaveIn; - Result = GetSoundDeviceFromInstance(Instance, &SoundDevice); +VOID +CALLBACK +MixerEventCallback( + _In_ PVOID MixerEventContext, + _In_ HANDLE hMixer, + _In_ ULONG NotificationType, + _In_ ULONG Value) +{ + PWDMAUD_DEVICE_INFO DeviceInfo = (PWDMAUD_DEVICE_INFO)MixerEventContext; - if ( ! MMSUCCESS(Result) ) - { - return TranslateInternalMmResult(Result); - } + DriverCallback(DeviceInfo->dwCallback, + HIWORD(DeviceInfo->Flags), + DeviceInfo->hDevice, + NotificationType, + DeviceInfo->dwInstance, + (DWORD_PTR)Value, + 0); +} - Result = GetSoundDeviceType(SoundDevice, &DeviceType); - SND_ASSERT( Result == MMSYSERR_NOERROR ); +MMRESULT +WdmAudOpenSoundDeviceByMMixer( + _In_ PWDMAUD_DEVICE_INFO DeviceInfo, + _In_ PWAVEFORMATEX WaveFormat) +{ + BOOL bInput; - bWaveIn = (DeviceType == WAVE_IN_DEVICE_TYPE ? TRUE : FALSE); + if (DeviceInfo->DeviceType == MIXER_DEVICE_TYPE) + { + if (MMixerOpen(&MixerContext, DeviceInfo->DeviceIndex, (PVOID)DeviceInfo, MixerEventCallback, &DeviceInfo->hDevice) == MM_STATUS_SUCCESS) + { + return MMSYSERR_NOERROR; + } + } + else if (DeviceInfo->DeviceType == MIDI_IN_DEVICE_TYPE || DeviceInfo->DeviceType == MIDI_OUT_DEVICE_TYPE) + { + bInput = DeviceInfo->DeviceType == MIDI_IN_DEVICE_TYPE; - if (MMixerOpenWave(&MixerContext, DeviceId, bWaveIn, WaveFormat, NULL, NULL, &Instance->Handle) == MM_STATUS_SUCCESS) + if (MMixerOpenMidi(&MixerContext, DeviceInfo->DeviceIndex, bInput, NULL, NULL, &DeviceInfo->hDevice) == MM_STATUS_SUCCESS) + { + return MMSYSERR_NOERROR; + } + } + else if (DeviceInfo->DeviceType == WAVE_IN_DEVICE_TYPE || DeviceInfo->DeviceType == WAVE_OUT_DEVICE_TYPE) { - if (DeviceType == WAVE_OUT_DEVICE_TYPE) + bInput = DeviceInfo->DeviceType == WAVE_IN_DEVICE_TYPE; + + if (MMixerOpenWave(&MixerContext, DeviceInfo->DeviceIndex, bInput, WaveFormat, NULL, NULL, &DeviceInfo->hDevice) == MM_STATUS_SUCCESS) { - MMixerSetWaveStatus(&MixerContext, Instance->Handle, KSSTATE_ACQUIRE); - MMixerSetWaveStatus(&MixerContext, Instance->Handle, KSSTATE_PAUSE); - MMixerSetWaveStatus(&MixerContext, Instance->Handle, KSSTATE_RUN); + MMixerSetWaveStatus(&MixerContext, DeviceInfo->hDevice, KSSTATE_ACQUIRE); + MMixerSetWaveStatus(&MixerContext, DeviceInfo->hDevice, KSSTATE_PAUSE); + MMixerSetWaveStatus(&MixerContext, DeviceInfo->hDevice, KSSTATE_RUN); + +#ifdef RESAMPLING_ENABLED + DeviceInfo->Buffer = WaveFormat; + DeviceInfo->BufferSize = sizeof(WAVEFORMATEX); +#endif + + return MMSYSERR_NOERROR; } - return MMSYSERR_NOERROR; } return MMSYSERR_ERROR; } - MMRESULT WdmAudGetCapabilitiesByMMixer( - IN PSOUND_DEVICE SoundDevice, - IN DWORD DeviceId, - OUT PVOID Capabilities, - IN DWORD CapabilitiesSize) + _In_ PWDMAUD_DEVICE_INFO DeviceInfo, + _Out_ MDEVICECAPSEX* Capabilities) { - MMDEVICE_TYPE DeviceType; - MMRESULT Result; - - Result = GetSoundDeviceType(SoundDevice, &DeviceType); - SND_ASSERT( Result == MMSYSERR_NOERROR ); - - if (DeviceType == MIXER_DEVICE_TYPE) + if (DeviceInfo->DeviceType == MIXER_DEVICE_TYPE) { - return WdmAudGetMixerCapabilities(DeviceId, (LPMIXERCAPSW)Capabilities); + return WdmAudGetMixerCapabilities(DeviceInfo->DeviceIndex, (LPMIXERCAPSW)Capabilities); } - else if (DeviceType == WAVE_OUT_DEVICE_TYPE) + else if (DeviceInfo->DeviceType == MIDI_OUT_DEVICE_TYPE) { - return WdmAudGetWaveOutCapabilities(DeviceId, (LPWAVEOUTCAPSW)Capabilities); + return WdmAudGetMidiOutCapabilities(DeviceInfo->DeviceIndex, (LPMIDIOUTCAPSW)Capabilities); } - else if (DeviceType == WAVE_IN_DEVICE_TYPE) + else if (DeviceInfo->DeviceType == MIDI_IN_DEVICE_TYPE) { - return WdmAudGetWaveInCapabilities(DeviceId, (LPWAVEINCAPSW)Capabilities); + return WdmAudGetMidiInCapabilities(DeviceInfo->DeviceIndex, (LPMIDIINCAPSW)Capabilities); + } + else if (DeviceInfo->DeviceType == WAVE_OUT_DEVICE_TYPE) + { + return WdmAudGetWaveOutCapabilities(DeviceInfo->DeviceIndex, (LPWAVEOUTCAPSW)Capabilities); + } + else if (DeviceInfo->DeviceType == WAVE_IN_DEVICE_TYPE) + { + return WdmAudGetWaveInCapabilities(DeviceInfo->DeviceIndex, (LPWAVEINCAPSW)Capabilities); } else { // not supported - return MMSYSERR_ERROR; + return MMSYSERR_NOTSUPPORTED; } } MMRESULT -WdmAudOpenSoundDeviceByMMixer( - IN struct _SOUND_DEVICE* SoundDevice, - OUT PVOID* Handle) +WdmAudOpenKernelSoundDeviceByMMixer(VOID) { if (WdmAudInitUserModeMixer()) return MMSYSERR_NOERROR; @@ -555,36 +601,28 @@ WdmAudOpenSoundDeviceByMMixer( MMRESULT WdmAudCloseSoundDeviceByMMixer( - IN struct _SOUND_DEVICE_INSTANCE* SoundDeviceInstance, - IN PVOID Handle) + _In_ PWDMAUD_DEVICE_INFO DeviceInfo, + _In_ PVOID Handle) { - MMDEVICE_TYPE DeviceType; - PSOUND_DEVICE SoundDevice; MMRESULT Result; - Result = GetSoundDeviceFromInstance(SoundDeviceInstance, &SoundDevice); - - if ( ! MMSUCCESS(Result) ) + if (DeviceInfo->DeviceType == MIXER_DEVICE_TYPE) { - return TranslateInternalMmResult(Result); - } - - Result = GetSoundDeviceType(SoundDevice, &DeviceType); - SND_ASSERT( Result == MMSYSERR_NOERROR ); - - if (DeviceType == MIXER_DEVICE_TYPE) - { - /* no op */ + CloseHandle(DeviceInfo->hDevice); return MMSYSERR_NOERROR; } - else if (DeviceType == WAVE_IN_DEVICE_TYPE || DeviceType == WAVE_OUT_DEVICE_TYPE) + else if (DeviceInfo->DeviceType == WAVE_IN_DEVICE_TYPE || DeviceInfo->DeviceType == WAVE_OUT_DEVICE_TYPE) { + /* Destroy I/O thread */ + Result = WdmAudDestroyCompletionThread(DeviceInfo); + ASSERT(Result == MMSYSERR_NOERROR); + /* make sure the pin is stopped */ - MMixerSetWaveStatus(&MixerContext, SoundDeviceInstance->Handle, KSSTATE_PAUSE); - MMixerSetWaveStatus(&MixerContext, SoundDeviceInstance->Handle, KSSTATE_ACQUIRE); - MMixerSetWaveStatus(&MixerContext, SoundDeviceInstance->Handle, KSSTATE_STOP); + MMixerSetWaveStatus(&MixerContext, DeviceInfo->hDevice, KSSTATE_PAUSE); + MMixerSetWaveStatus(&MixerContext, DeviceInfo->hDevice, KSSTATE_ACQUIRE); + MMixerSetWaveStatus(&MixerContext, DeviceInfo->hDevice, KSSTATE_STOP); - CloseHandle(Handle); + CloseHandle(DeviceInfo->hDevice); return MMSYSERR_NOERROR; } @@ -594,8 +632,8 @@ WdmAudCloseSoundDeviceByMMixer( MMRESULT WdmAudGetNumWdmDevsByMMixer( - IN MMDEVICE_TYPE DeviceType, - OUT DWORD* DeviceCount) + _In_ SOUND_DEVICE_TYPE DeviceType, + _Out_ DWORD* DeviceCount) { switch(DeviceType) { @@ -616,16 +654,15 @@ WdmAudGetNumWdmDevsByMMixer( MMRESULT WdmAudQueryMixerInfoByMMixer( - IN struct _SOUND_DEVICE_INSTANCE* SoundDeviceInstance, - IN DWORD MixerId, - IN UINT uMsg, - IN LPVOID Parameter, - IN DWORD Flags) + _In_ PWDMAUD_DEVICE_INFO DeviceInfo, + _In_ DWORD MixerId, + _In_ UINT uMsg, + _In_ LPVOID Parameter, + _In_ DWORD Flags) { LPMIXERLINEW MixLine; LPMIXERLINECONTROLSW MixControls; LPMIXERCONTROLDETAILS MixDetails; - HANDLE hMixer = NULL; MixLine = (LPMIXERLINEW)Parameter; MixControls = (LPMIXERLINECONTROLSW)Parameter; @@ -633,116 +670,58 @@ WdmAudQueryMixerInfoByMMixer( /* FIXME param checks */ - if (SoundDeviceInstance) - { - hMixer = SoundDeviceInstance->Handle; - } - switch(uMsg) { case MXDM_GETLINEINFO: - return WdmAudGetLineInfo(hMixer, MixerId, MixLine, Flags); + return WdmAudGetLineInfo(DeviceInfo->hDevice, MixerId, MixLine, Flags); case MXDM_GETLINECONTROLS: - return WdmAudGetLineControls(hMixer, MixerId, MixControls, Flags); - case MXDM_SETCONTROLDETAILS: - return WdmAudSetControlDetails(hMixer, MixerId, MixDetails, Flags); - case MXDM_GETCONTROLDETAILS: - return WdmAudGetControlDetails(hMixer, MixerId, MixDetails, Flags); - default: - DPRINT1("MixerId %lu, uMsg %lu, Parameter %p, Flags %lu\n", MixerId, uMsg, Parameter, Flags); - SND_ASSERT(0); - return MMSYSERR_NOTSUPPORTED; + return WdmAudGetLineControls(DeviceInfo->hDevice, MixerId, MixControls, Flags); + case MXDM_SETCONTROLDETAILS: + return WdmAudSetControlDetails(DeviceInfo->hDevice, MixerId, MixDetails, Flags); + case MXDM_GETCONTROLDETAILS: + return WdmAudGetControlDetails(DeviceInfo->hDevice, MixerId, MixDetails, Flags); + default: + DPRINT1("MixerId %lu, uMsg %lu, Parameter %p, Flags %lu\n", MixerId, uMsg, Parameter, Flags); + ASSERT(0); + return MMSYSERR_NOTSUPPORTED; } } -MMRESULT -WdmAudGetDeviceInterfaceStringByMMixer( - IN MMDEVICE_TYPE DeviceType, - IN DWORD DeviceId, - IN LPWSTR Interface, - IN DWORD InterfaceLength, - OUT DWORD * InterfaceSize) -{ - /* FIXME */ - return MMSYSERR_NOTSUPPORTED; -} - -VOID -CALLBACK -MixerEventCallback( - IN PVOID MixerEventContext, - IN HANDLE hMixer, - IN ULONG NotificationType, - IN ULONG Value) -{ - PSOUND_DEVICE_INSTANCE Instance = (PSOUND_DEVICE_INSTANCE)MixerEventContext; - - DriverCallback(Instance->WinMM.ClientCallback, - HIWORD(Instance->WinMM.Flags), - Instance->WinMM.Handle, - NotificationType, - Instance->WinMM.ClientCallbackInstanceData, - (DWORD_PTR)Value, - 0); -} - -MMRESULT -WdmAudSetMixerDeviceFormatByMMixer( - IN PSOUND_DEVICE_INSTANCE Instance, - IN DWORD DeviceId, - IN PWAVEFORMATEX WaveFormat, - IN DWORD WaveFormatSize) -{ - if (MMixerOpen(&MixerContext, DeviceId, (PVOID)Instance, MixerEventCallback, &Instance->Handle) == MM_STATUS_SUCCESS) - return MMSYSERR_NOERROR; - - return MMSYSERR_BADDEVICEID; -} - MMRESULT WdmAudSetWaveStateByMMixer( - IN struct _SOUND_DEVICE_INSTANCE* SoundDeviceInstance, - IN BOOL bStart) + _In_ PWDMAUD_DEVICE_INFO DeviceInfo, + _In_ BOOL bStart) { - MMDEVICE_TYPE DeviceType; - PSOUND_DEVICE SoundDevice; - MMRESULT Result; + DeviceInfo->DeviceState->bStart = bStart; - Result = GetSoundDeviceFromInstance(SoundDeviceInstance, &SoundDevice); - SND_ASSERT( Result == MMSYSERR_NOERROR ); - - - Result = GetSoundDeviceType(SoundDevice, &DeviceType); - SND_ASSERT( Result == MMSYSERR_NOERROR ); - - if (DeviceType == WAVE_IN_DEVICE_TYPE || DeviceType == WAVE_OUT_DEVICE_TYPE) + if (DeviceInfo->DeviceType == WAVE_IN_DEVICE_TYPE || DeviceInfo->DeviceType == WAVE_OUT_DEVICE_TYPE) { if (bStart) { - MMixerSetWaveStatus(&MixerContext, SoundDeviceInstance->Handle, KSSTATE_ACQUIRE); - MMixerSetWaveStatus(&MixerContext, SoundDeviceInstance->Handle, KSSTATE_PAUSE); - MMixerSetWaveStatus(&MixerContext, SoundDeviceInstance->Handle, KSSTATE_RUN); + MMixerSetWaveStatus(&MixerContext, DeviceInfo->hDevice, KSSTATE_ACQUIRE); + MMixerSetWaveStatus(&MixerContext, DeviceInfo->hDevice, KSSTATE_PAUSE); + MMixerSetWaveStatus(&MixerContext, DeviceInfo->hDevice, KSSTATE_RUN); } else { - MMixerSetWaveStatus(&MixerContext, SoundDeviceInstance->Handle, KSSTATE_PAUSE); - MMixerSetWaveStatus(&MixerContext, SoundDeviceInstance->Handle, KSSTATE_ACQUIRE); - MMixerSetWaveStatus(&MixerContext, SoundDeviceInstance->Handle, KSSTATE_STOP); + MMixerSetWaveStatus(&MixerContext, DeviceInfo->hDevice, KSSTATE_PAUSE); + MMixerSetWaveStatus(&MixerContext, DeviceInfo->hDevice, KSSTATE_ACQUIRE); + MMixerSetWaveStatus(&MixerContext, DeviceInfo->hDevice, KSSTATE_STOP); } } - else if (DeviceType == MIDI_IN_DEVICE_TYPE || DeviceType == MIDI_OUT_DEVICE_TYPE) + else if (DeviceInfo->DeviceType == MIDI_IN_DEVICE_TYPE || DeviceInfo->DeviceType == MIDI_OUT_DEVICE_TYPE) { if (bStart) { - MMixerSetMidiStatus(&MixerContext, SoundDeviceInstance->Handle, KSSTATE_ACQUIRE); - MMixerSetMidiStatus(&MixerContext, SoundDeviceInstance->Handle, KSSTATE_PAUSE); - MMixerSetMidiStatus(&MixerContext, SoundDeviceInstance->Handle, KSSTATE_RUN); + MMixerSetMidiStatus(&MixerContext, DeviceInfo->hDevice, KSSTATE_ACQUIRE); + MMixerSetMidiStatus(&MixerContext, DeviceInfo->hDevice, KSSTATE_PAUSE); + MMixerSetMidiStatus(&MixerContext, DeviceInfo->hDevice, KSSTATE_RUN); } else { - MMixerSetMidiStatus(&MixerContext, SoundDeviceInstance->Handle, KSSTATE_PAUSE); - MMixerSetMidiStatus(&MixerContext, SoundDeviceInstance->Handle, KSSTATE_ACQUIRE); - MMixerSetMidiStatus(&MixerContext, SoundDeviceInstance->Handle, KSSTATE_STOP); + MMixerSetMidiStatus(&MixerContext, DeviceInfo->hDevice, KSSTATE_PAUSE); + MMixerSetMidiStatus(&MixerContext, DeviceInfo->hDevice, KSSTATE_ACQUIRE); + MMixerSetMidiStatus(&MixerContext, DeviceInfo->hDevice, KSSTATE_STOP); } } @@ -751,119 +730,143 @@ WdmAudSetWaveStateByMMixer( MMRESULT WdmAudResetStreamByMMixer( - IN struct _SOUND_DEVICE_INSTANCE* SoundDeviceInstance, - IN MMDEVICE_TYPE DeviceType, - IN BOOLEAN bStartReset) + _In_ PWDMAUD_DEVICE_INFO DeviceInfo, + _In_ BOOL bStartReset) { MIXER_STATUS Status; + MMRESULT Result; - if (DeviceType == WAVE_IN_DEVICE_TYPE || DeviceType == WAVE_OUT_DEVICE_TYPE) + DeviceInfo->DeviceState->bReset = bStartReset; + + if (DeviceInfo->DeviceType == WAVE_IN_DEVICE_TYPE || DeviceInfo->DeviceType == WAVE_OUT_DEVICE_TYPE) { - Status = MMixerSetWaveResetState(&MixerContext, SoundDeviceInstance->Handle, bStartReset); + Status = MMixerSetWaveResetState(&MixerContext, DeviceInfo->hDevice, bStartReset); if (Status == MM_STATUS_SUCCESS) { - /* completed successfully */ + /* Destroy I/O thread */ + Result = WdmAudDestroyCompletionThread(DeviceInfo); + ASSERT(Result == MMSYSERR_NOERROR); + + /* Completed successfully */ return MMSYSERR_NOERROR; } } - return MMSYSERR_NOTSUPPORTED; } MMRESULT WdmAudGetWavePositionByMMixer( - IN struct _SOUND_DEVICE_INSTANCE* SoundDeviceInstance, - IN MMTIME* Time) -{ - /* FIXME */ - return MMSYSERR_NOTSUPPORTED; -} - -static -VOID WINAPI -CommitWaveBufferApc(PVOID ApcContext, - PIO_STATUS_BLOCK IoStatusBlock, - ULONG Reserved) + _In_ PWDMAUD_DEVICE_INFO DeviceInfo, + _In_ MMTIME* Time) { - DWORD dwErrorCode; - PSOUND_OVERLAPPED Overlap; - KSSTREAM_HEADER* lpHeader; - - dwErrorCode = RtlNtStatusToDosError(IoStatusBlock->Status); - Overlap = (PSOUND_OVERLAPPED)IoStatusBlock; - lpHeader = Overlap->CompletionContext; + MIXER_STATUS Status; + DWORD Position; + DPRINT("wType %u\n", Time->wType); + if (DeviceInfo->DeviceType == WAVE_IN_DEVICE_TYPE || DeviceInfo->DeviceType == WAVE_OUT_DEVICE_TYPE) + { + Status = MMixerGetWavePosition(&MixerContext, DeviceInfo->hDevice, &Position); + if (Status == MM_STATUS_SUCCESS) + { + /* Store position */ + Time->wType = TIME_BYTES; + Time->u.cb = Position; - /* Call mmebuddy overlap routine */ - Overlap->OriginalCompletionRoutine(dwErrorCode, - lpHeader->DataUsed, &Overlap->Standard); + /* Completed successfully */ + return MMSYSERR_NOERROR; + } + } - HeapFree(GetProcessHeap(), 0, lpHeader); + return MMSYSERR_NOTSUPPORTED; } MMRESULT -WdmAudCommitWaveBufferByMMixer( - IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance, - IN PVOID OffsetPtr, - IN DWORD Length, - IN PSOUND_OVERLAPPED Overlap, - IN LPOVERLAPPED_COMPLETION_ROUTINE CompletionRoutine) -{ - PSOUND_DEVICE SoundDevice; - MMDEVICE_TYPE DeviceType; - MMRESULT Result; - ULONG IoCtl; - KSSTREAM_HEADER* lpHeader; - NTSTATUS Status; - - Result = GetSoundDeviceFromInstance(SoundDeviceInstance, &SoundDevice); - - if ( ! MMSUCCESS(Result) ) - { - return TranslateInternalMmResult(Result); - } +WdmAudSubmitWaveHeaderByMMixer( + _In_ PWDMAUD_DEVICE_INFO DeviceInfo, + _In_ PWAVEHDR WaveHeader) +{ + MMRESULT Result = MMSYSERR_NOERROR; + PWAVEHDR_EXTENSION HeaderExtension; + PKSSTREAM_HEADER lpHeader; + DWORD Transferred = 0; + BOOL IoResult; + DWORD IoCtl; - Result = GetSoundDeviceType(SoundDevice, &DeviceType); - SND_ASSERT( Result == MMSYSERR_NOERROR ); +#ifdef RESAMPLING_ENABLED + /* Resample the stream */ + Result = WdmAudResampleStream(DeviceInfo, WaveHeader); + ASSERT( Result == MMSYSERR_NOERROR ); +#endif lpHeader = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(KSSTREAM_HEADER)); if ( ! lpHeader ) { - /* no memory */ + /* No memory */ return MMSYSERR_NOMEM; } - /* setup stream packet */ + HeaderExtension = (PWAVEHDR_EXTENSION)WaveHeader->reserved; + HeaderExtension->DeviceInfo = NULL; + + /* Setup stream header */ lpHeader->Size = sizeof(KSSTREAM_HEADER); lpHeader->PresentationTime.Numerator = 1; lpHeader->PresentationTime.Denominator = 1; - lpHeader->Data = OffsetPtr; - lpHeader->FrameExtent = Length; - Overlap->CompletionContext = lpHeader; - Overlap->OriginalCompletionRoutine = CompletionRoutine; - IoCtl = (DeviceType == WAVE_OUT_DEVICE_TYPE ? IOCTL_KS_WRITE_STREAM : IOCTL_KS_READ_STREAM); + lpHeader->Data = WaveHeader->lpData; + lpHeader->FrameExtent = WaveHeader->dwBufferLength; - if (DeviceType == WAVE_OUT_DEVICE_TYPE) + if (DeviceInfo->DeviceType == WAVE_OUT_DEVICE_TYPE) { - lpHeader->DataUsed = Length; + lpHeader->DataUsed = WaveHeader->dwBufferLength; + } + else + { + lpHeader->DataUsed = 0; } - Status = NtDeviceIoControlFile(SoundDeviceInstance->Handle, - NULL, - CommitWaveBufferApc, - NULL, - (PIO_STATUS_BLOCK)Overlap, - IoCtl, - NULL, - 0, - lpHeader, - sizeof(KSSTREAM_HEADER)); + /* Set IOCTL */ + if (DeviceInfo->DeviceType == WAVE_OUT_DEVICE_TYPE) + IoCtl = IOCTL_KS_WRITE_STREAM; + else if (DeviceInfo->DeviceType == WAVE_IN_DEVICE_TYPE) + IoCtl = IOCTL_KS_READ_STREAM; - if (!NT_SUCCESS(Status)) + /* Talk to the device */ + IoResult = DeviceIoControl(DeviceInfo->hDevice, + IoCtl, + NULL, + 0, + lpHeader, + sizeof(KSSTREAM_HEADER), + &Transferred, + &HeaderExtension->Overlapped); + HeapFree(GetProcessHeap(), 0, lpHeader); + + /* If failure occurs, make sure it's not just due to the overlapped I/O */ + if (!IoResult) { - DPRINT1("NtDeviceIoControlFile() failed with status %08lx\n", Status); - return MMSYSERR_ERROR; + if (GetLastError() != ERROR_IO_PENDING) + { + DPRINT1("Call to %s failed with %d\n", + DeviceInfo->DeviceType == WAVE_OUT_DEVICE_TYPE ? + "IOCTL_KS_WRITE_STREAM" : "IOCTL_KS_READ_STREAM", + GetLastError()); + } + Result = Win32ErrorToMmResult(GetLastError()); } - return MMSYSERR_NOERROR; + if (MMSUCCESS(Result)) + { + /* Create I/O thread */ + Result = WdmAudCreateCompletionThread(DeviceInfo); + if (!MMSUCCESS(Result)) + { + /* Failed */ + DPRINT1("Failed to create sound thread with error %d\n", GetLastError()); + return TranslateInternalMmResult(Result); + } + } + + DPRINT("Transferred %d bytes in Sync overlapped I/O\n", Transferred); + + return Result; } diff --git a/dll/win32/wdmaud.drv/reentrancy.c b/dll/win32/wdmaud.drv/reentrancy.c new file mode 100644 index 0000000000000..0725cdf2bc7cb --- /dev/null +++ b/dll/win32/wdmaud.drv/reentrancy.c @@ -0,0 +1,106 @@ +/* + * PROJECT: ReactOS Sound System "MME Buddy" Library + * LICENSE: GPL - See COPYING in the top level directory + * FILE: lib/sound/mmebuddy/reentrancy.c + * + * PURPOSE: Provides entry-point mutex guards. + * + * PROGRAMMERS: Andrew Greenwood (silverblade@reactos.org) +*/ + +#include "wdmaud.h" + +#define YDEBUG +#include + +HANDLE EntrypointMutexes[SOUND_DEVICE_TYPES]; + +/* + Creates a set of mutexes which are used for the purpose of guarding the + device-type specific module entry-points. If any of these fail creation, + all of them will be destroyed and the failure reported. +*/ +MMRESULT +InitEntrypointMutexes() +{ + UCHAR i; + MMRESULT Result = MMSYSERR_NOERROR; + + /* Blank all entries ni the table first */ + for ( i = 0; i < SOUND_DEVICE_TYPES; ++ i ) + { + EntrypointMutexes[i] = NULL; + } + + /* Now create the mutexes */ + for ( i = 0; i < SOUND_DEVICE_TYPES; ++ i ) + { + EntrypointMutexes[i] = CreateMutex(NULL, FALSE, NULL); + + if ( ! EntrypointMutexes[i] ) + { + Result = Win32ErrorToMmResult(GetLastError()); + + /* Clean up any mutexes we successfully created */ + CleanupEntrypointMutexes(); + break; + } + } + + return Result; +} + +/* + Cleans up any of the entry-point guard mutexes. This will only close the + handles of mutexes which have been created, making it safe for use as a + cleanup routine even within the InitEntrypointMutexes routine above. +*/ +VOID +CleanupEntrypointMutexes() +{ + UCHAR i; + + /* Only clean up a mutex if it actually exists */ + for ( i = 0; i < SOUND_DEVICE_TYPES; ++ i ) + { + if ( EntrypointMutexes[i] ) + { + CloseHandle(EntrypointMutexes[i]); + EntrypointMutexes[i] = NULL; + } + } +} + +/* + Grabs an entry-point mutex. +*/ +VOID +AcquireEntrypointMutex( + IN SOUND_DEVICE_TYPE DeviceType) +{ + UCHAR i; + + ASSERT( IS_VALID_SOUND_DEVICE_TYPE(DeviceType) ); + i = SOUND_DEVICE_TYPE_TO_INDEX(DeviceType); + + ASSERT( EntrypointMutexes[i] ); + + WaitForSingleObject(EntrypointMutexes[i], INFINITE); +} + +/* + Releases an entry-point mutex. +*/ +VOID +ReleaseEntrypointMutex( + IN SOUND_DEVICE_TYPE DeviceType) +{ + UCHAR i; + + ASSERT( IS_VALID_SOUND_DEVICE_TYPE(DeviceType) ); + i = SOUND_DEVICE_TYPE_TO_INDEX(DeviceType); + + ASSERT( EntrypointMutexes[i] ); + + ReleaseMutex(EntrypointMutexes[i]); +} diff --git a/dll/win32/wdmaud.drv/mixer.c b/dll/win32/wdmaud.drv/resample.c similarity index 76% rename from dll/win32/wdmaud.drv/mixer.c rename to dll/win32/wdmaud.drv/resample.c index 73cd376277e18..e572af747da55 100644 --- a/dll/win32/wdmaud.drv/mixer.c +++ b/dll/win32/wdmaud.drv/resample.c @@ -1,10 +1,9 @@ /* - * PROJECT: ReactOS Sound System - * LICENSE: GPL - See COPYING in the top level directory - * FILE: dll/win32/wdmaud.drv/mixer.c - * - * PURPOSE: WDM Audio Driver (User-mode part) - * PROGRAMMERS: Johannes Anderwald + * PROJECT: ReactOS Sound Subsystem + * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later) + * PURPOSE: WDM Audio Driver resampling routines + * COPYRIGHT: Copyright 2009-2010 Johannes Anderwald + * Copyright 2022 Oleg Dubinskiy (oleg.dubinskij30@gmail.com) */ #include "wdmaud.h" @@ -12,11 +11,9 @@ #include #include -#define NDEBUG +#define YDEBUG #include -#include -extern HANDLE KernelHandle; DWORD PerformSampleRateConversion( @@ -38,7 +35,7 @@ PerformSampleRateConversion( ULONG NumSamples; ULONG NewSamples; - //SND_TRACE(L"PerformSampleRateConversion OldRate %u NewRate %u BytesPerSample %u NumChannels %u\n", OldRate, NewRate, BytesPerSample, NumChannels); + DPRINT("PerformSampleRateConversion OldRate %u NewRate %u BytesPerSample %u NumChannels %u\n", OldRate, NewRate, BytesPerSample, NumChannels); ASSERT(BytesPerSample == 1 || BytesPerSample == 2 || BytesPerSample == 4); @@ -151,7 +148,7 @@ PerformChannelConversion( Samples = BufferLength / (BitsPerSample / 8) / OldChannels; - SND_TRACE(L"PerformChannelConversion OldChannels %u NewChannels %u\n", OldChannels, NewChannels); + DPRINT("PerformChannelConversion OldChannels %u NewChannels %u\n", OldChannels, NewChannels); if (NewChannels > OldChannels) { @@ -258,7 +255,6 @@ PerformChannelConversion( return ERROR_SUCCESS; } - DWORD PerformQualityConversion( PUCHAR Buffer, @@ -274,9 +270,9 @@ PerformQualityConversion( ASSERT(OldWidth != NewWidth); Samples = BufferLength / (OldWidth / 8); - //DPRINT("Samples %u BufferLength %u\n", Samples, BufferLength); - //SND_TRACE(L"PerformQualityConversion OldWidth %u NewWidth %u\n", OldWidth, NewWidth); + DPRINT("PerformQualityConversion OldWidth %u NewWidth %u\n", OldWidth, NewWidth); + DPRINT("Samples %u BufferLength %u\n", Samples, BufferLength); if (OldWidth == 8 && NewWidth == 16) { @@ -406,79 +402,55 @@ PerformQualityConversion( return ERROR_SUCCESS; } -VOID -CALLBACK -MixerCompletionRoutine( - IN DWORD dwErrorCode, - IN DWORD dwNumberOfBytesTransferred, - IN LPOVERLAPPED lpOverlapped) -{ - PSOUND_OVERLAPPED Overlap = (PSOUND_OVERLAPPED)lpOverlapped; - - /* Call mmebuddy overlap routine */ - Overlap->OriginalCompletionRoutine(dwErrorCode, PtrToUlong(Overlap->CompletionContext), lpOverlapped); -} MMRESULT -WriteFileEx_Remixer( - IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance, - IN PVOID OffsetPtr, - IN DWORD Length, - IN PSOUND_OVERLAPPED Overlap, - IN LPOVERLAPPED_COMPLETION_ROUTINE CompletionRoutine) +WdmAudResampleStream( + _In_ PWDMAUD_DEVICE_INFO DeviceInfo, + _Inout_ PWAVEHDR WaveHeader) { - HANDLE Handle; - WDMAUD_DEVICE_INFO DeviceInfo; DWORD BufferLength, BufferLengthTemp; PVOID BufferOut, BufferOutTemp; + PWAVEFORMATEX WaveFormatEx; DWORD Status; - BOOL Result; - - VALIDATE_MMSYS_PARAMETER( SoundDeviceInstance ); - VALIDATE_MMSYS_PARAMETER( OffsetPtr ); - VALIDATE_MMSYS_PARAMETER( Overlap ); - VALIDATE_MMSYS_PARAMETER( CompletionRoutine ); - GetSoundDeviceInstanceHandle(SoundDeviceInstance, &Handle); + VALIDATE_MMSYS_PARAMETER( DeviceInfo ); - SND_ASSERT(Handle); + /* Get wave format */ + WaveFormatEx = (PWAVEFORMATEX)DeviceInfo->Buffer; - BufferOut = OffsetPtr; - BufferLength = Length; + /* Get input data */ + BufferOut = WaveHeader->lpData; + BufferLength = WaveHeader->dwBufferLength; - if (SoundDeviceInstance->WaveFormatEx.wBitsPerSample != 16) + /* Do the resampling */ + if (WaveFormatEx->wBitsPerSample > 16) { - Status = PerformQualityConversion(OffsetPtr, - Length, - SoundDeviceInstance->WaveFormatEx.wBitsPerSample, + Status = PerformQualityConversion((PUCHAR)WaveHeader->lpData, + WaveHeader->dwBufferLength, + WaveFormatEx->wBitsPerSample, 16, &BufferOut, &BufferLength); if (Status) { - SND_TRACE(L"PerformQualityConversion failed\n"); + DPRINT("PerformQualityConversion failed\n"); return MMSYSERR_NOERROR; } } - if (SoundDeviceInstance->WaveFormatEx.nChannels != 2) + if (WaveFormatEx->nChannels > 2) { Status = PerformChannelConversion(BufferOut, BufferLength, - SoundDeviceInstance->WaveFormatEx.nChannels, + WaveFormatEx->nChannels, 2, 16, &BufferOutTemp, &BufferLengthTemp); - if (BufferOut != OffsetPtr) - { - HeapFree(GetProcessHeap(), 0, BufferOut); - } - if (Status) { - SND_TRACE(L"PerformChannelConversion failed\n"); + DPRINT("PerformChannelConversion failed\n"); return MMSYSERR_NOERROR; } @@ -486,25 +458,20 @@ WriteFileEx_Remixer( BufferLength = BufferLengthTemp; } - if (SoundDeviceInstance->WaveFormatEx.nSamplesPerSec != 44100) + if (WaveFormatEx->nSamplesPerSec > 48000) { Status = PerformSampleRateConversion(BufferOut, BufferLength, - SoundDeviceInstance->WaveFormatEx.nSamplesPerSec, + WaveFormatEx->nSamplesPerSec, 44100, 2, 2, &BufferOutTemp, &BufferLengthTemp); - if (BufferOut != OffsetPtr) - { - HeapFree(GetProcessHeap(), 0, BufferOut); - } - if (Status) { - SND_TRACE(L"PerformSampleRateConversion failed\n"); + DPRINT("PerformSampleRateConversion failed\n"); return MMSYSERR_NOERROR; } @@ -512,42 +479,11 @@ WriteFileEx_Remixer( BufferLength = BufferLengthTemp; } - ZeroMemory(&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO)); - DeviceInfo.hDevice = Handle; - DeviceInfo.DeviceType = WAVE_OUT_DEVICE_TYPE; //FIXME - DeviceInfo.Header.FrameExtent = BufferLength; - DeviceInfo.Header.DataUsed = BufferLength; - DeviceInfo.Header.Data = BufferOut; - DeviceInfo.Header.Size = sizeof(KSSTREAM_HEADER); - DeviceInfo.Header.PresentationTime.Numerator = 1; - DeviceInfo.Header.PresentationTime.Denominator = 1; - - Overlap->CompletionContext = UlongToPtr(Length); - Overlap->OriginalCompletionRoutine = CompletionRoutine; - - Overlap->Standard.hEvent = CreateEventW(NULL, FALSE, FALSE, NULL); - - //SND_TRACE(L"OriginalLength %u NewLength %u\n", Length, BufferLength); - -#if 0 - Result = WriteFileEx(KernelHandle, &DeviceInfo, sizeof(WDMAUD_DEVICE_INFO), (LPOVERLAPPED)Overlap, CompletionRoutine); -#else - Result = WriteFileEx(KernelHandle, &DeviceInfo, sizeof(WDMAUD_DEVICE_INFO), (LPOVERLAPPED)Overlap, MixerCompletionRoutine); -#endif - - if ( ! Result ) - { - SND_TRACE(L"WriteFileEx failed with %x\n", GetLastError()); - return MMSYSERR_NOERROR; - } - - WaitForSingleObjectEx (KernelHandle, INFINITE, TRUE); - -#ifdef USERMODE_MIXER - // if (BufferOut != OffsetPtr) - // HeapFree(GetProcessHeap(), 0, BufferOut); -#endif + DPRINT("OriginalLength %u NewLength %u\n", WaveHeader->dwBufferLength, BufferLength); + /* Set output data */ + WaveHeader->lpData = BufferOut; + WaveHeader->dwBufferLength = BufferLength; return MMSYSERR_NOERROR; } diff --git a/dll/win32/wdmaud.drv/result.c b/dll/win32/wdmaud.drv/result.c new file mode 100644 index 0000000000000..698d918a0dbe9 --- /dev/null +++ b/dll/win32/wdmaud.drv/result.c @@ -0,0 +1,74 @@ +/* + * PROJECT: ReactOS Sound Subsystem + * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later) + * PURPOSE: WDM Audio Driver MMRESULT return code routines + * COPYRIGHT: Copyright 2009-2010 Johannes Anderwald + * Copyright 2022 Oleg Dubinskiy (oleg.dubinskij30@gmail.com) + */ + +#include + +/* + Translate a Win32 error code into an MMRESULT code. +*/ +MMRESULT +Win32ErrorToMmResult( + IN UINT ErrorCode) +{ + switch ( ErrorCode ) + { + case NO_ERROR : + case ERROR_IO_PENDING : + return MMSYSERR_NOERROR; + + case ERROR_BUSY : + return MMSYSERR_ALLOCATED; + + case ERROR_NOT_SUPPORTED : + case ERROR_INVALID_FUNCTION : + return MMSYSERR_NOTSUPPORTED; + + case ERROR_NOT_ENOUGH_MEMORY : + return MMSYSERR_NOMEM; + + case ERROR_ACCESS_DENIED : + return MMSYSERR_BADDEVICEID; + + case ERROR_INSUFFICIENT_BUFFER : + return MMSYSERR_INVALPARAM; + + case ERROR_INVALID_PARAMETER : + return MMSYSERR_INVALPARAM; + + + default : + return MMSYSERR_ERROR; + } +} + +/* + If a function invokes another function, this aids in translating the + result code so that it is applicable in the context of the original caller. + For example, specifying that an invalid parameter was passed probably does + not make much sense if the parameter wasn't passed by the original caller! + + This could potentially highlight internal logic problems. + + However, things like MMSYSERR_NOMEM make sense to return to the caller. +*/ +MMRESULT +TranslateInternalMmResult( + IN MMRESULT Result) +{ + switch ( Result ) + { + case MMSYSERR_INVALPARAM : + case MMSYSERR_INVALFLAG : + { + return MMSYSERR_ERROR; + } + } + + return Result; +} + diff --git a/dll/win32/wdmaud.drv/wave/header.c b/dll/win32/wdmaud.drv/wave/header.c new file mode 100644 index 0000000000000..84ffcf3a3649b --- /dev/null +++ b/dll/win32/wdmaud.drv/wave/header.c @@ -0,0 +1,207 @@ +/* + * PROJECT: ReactOS Sound System "MME Buddy" Library + * LICENSE: GPL - See COPYING in the top level directory + * FILE: lib/drivers/sound/mmebuddy/wave/header.c + * + * PURPOSE: Wave header preparation and submission routines + * + * PROGRAMMERS: Andrew Greenwood (silverblade@reactos.org) +*/ + +#include "wdmaud.h" + +#define YDEBUG +#include + + +/* + The following routines are basically handlers for: + - WODM_PREPARE + - WODM_UNPREPARE + - WODM_WRITE + + All of these calls are ultimately dealt with in the context of the + appropriate sound thread, so the implementation should expect itself to + be running in this other thread when any of these operations take place. +*/ + +MMRESULT +PrepareWaveHeader( + IN PWDMAUD_DEVICE_INFO DeviceInfo, + IN PWAVEHDR Header) +{ + PWAVEHDR_EXTENSION HeaderExtension; + + VALIDATE_MMSYS_PARAMETER( DeviceInfo ); + VALIDATE_MMSYS_PARAMETER( Header ); + + DPRINT("Preparing wave header\n"); + + /* Initialize fields for new header */ + Header->lpNext = NULL; + Header->reserved = 0; + + /* Allocate header extension */ + HeaderExtension = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WAVEHDR_EXTENSION)); + if (!HeaderExtension) + { + /* No memory */ + return MMSYSERR_NOMEM; + } + + /* Create stream event */ + HeaderExtension->Overlapped.hEvent = CreateEventW(NULL, FALSE, FALSE, NULL); + if (!HeaderExtension->Overlapped.hEvent) + { + /* No memory */ + HeapFree(GetProcessHeap(), 0, HeaderExtension); + return MMSYSERR_NOMEM; + } + + Header->reserved = (DWORD_PTR)HeaderExtension; + + /* This is what winmm expects to be returned */ + return MMSYSERR_NOTSUPPORTED; +} + +MMRESULT +UnprepareWaveHeader( + IN PWDMAUD_DEVICE_INFO DeviceInfo, + IN PWAVEHDR Header) +{ + PWAVEHDR_EXTENSION HeaderExtension; + + VALIDATE_MMSYS_PARAMETER( DeviceInfo ); + VALIDATE_MMSYS_PARAMETER( Header ); + + DPRINT("Un-preparing wave header\n"); + + HeaderExtension = (PWAVEHDR_EXTENSION)Header->reserved; + + Header->reserved = 0; + + /* Destroy stream event */ + CloseHandle(HeaderExtension->Overlapped.hEvent); + + /* Free header extension */ + HeapFree(GetProcessHeap(), 0, HeaderExtension); + + /* This is what winmm expects to be returned */ + return MMSYSERR_NOTSUPPORTED; +} + +MMRESULT +WriteWaveHeader( + IN PWDMAUD_DEVICE_INFO DeviceInfo, + IN PWAVEHDR Header) +{ + VALIDATE_MMSYS_PARAMETER( DeviceInfo ); + VALIDATE_MMSYS_PARAMETER( Header ); + + DPRINT("Submitting wave header\n"); + + /* + A few minor sanity checks - any custom checks should've been carried + out during wave header preparation etc. + */ + VALIDATE_MMSYS_PARAMETER( Header->lpData != NULL ); + VALIDATE_MMSYS_PARAMETER( Header->dwBufferLength > 0 ); + VALIDATE_MMSYS_PARAMETER( Header->dwFlags & WHDR_PREPARED ); + VALIDATE_MMSYS_PARAMETER( ! (Header->dwFlags & WHDR_INQUEUE) ); + + return EnqueueWaveHeader(DeviceInfo, Header); +} + + +/* + EnqueueWaveHeader + Put the header in the record/playback queue. This is performed within + the context of the sound thread, it must NEVER be called from another + thread. + + CompleteWaveHeader + Set the header information to indicate that it has finished playing, + and return it to the client application. This again must be called + within the context of the sound thread. +*/ + +MMRESULT +EnqueueWaveHeader( + IN PWDMAUD_DEVICE_INFO DeviceInfo, + IN PWAVEHDR Header) +{ + VALIDATE_MMSYS_PARAMETER( DeviceInfo ); + VALIDATE_MMSYS_PARAMETER( Header ); + + /* Set the "in queue" flag */ + Header->dwFlags |= WHDR_INQUEUE; + + /* Clear the "done" flag for the buffer */ + Header->dwFlags &= ~WHDR_DONE; + + if (!DeviceInfo->DeviceState->WaveQueue) + { + /* This is the first header in the queue */ + DPRINT("Enqueued first wave header\n"); + DeviceInfo->DeviceState->WaveQueue = Header; + + if (DeviceInfo->DeviceState->hNotifyEvent) + { + /* Set queue event */ + SetEvent(DeviceInfo->DeviceState->hNotifyEvent); + } + } + else + { + /* This is the 2nd or another header */ + DPRINT("Enqueued next wave header\n"); + + /* Insert the header in the end of the queue */ + while (DeviceInfo->DeviceState->WaveQueue->lpNext) + { + DPRINT("WaveQueue %p\n", DeviceInfo->DeviceState->WaveQueue); + DeviceInfo->DeviceState->WaveQueue = DeviceInfo->DeviceState->WaveQueue->lpNext; + } + DeviceInfo->DeviceState->WaveQueue->lpNext = Header; + } + + /* Do wave streaming */ + return DoWaveStreaming(DeviceInfo, Header); +} + +VOID +CompleteWaveHeader( + IN PWDMAUD_DEVICE_INFO DeviceInfo) +{ + PWAVEHDR_EXTENSION HeaderExtension; + PWAVEHDR Header; + + Header = DeviceInfo->DeviceState->WaveQueue; + + DPRINT("Completing wave header\n"); + + if (Header) + { + /* Move to the next header */ + DeviceInfo->DeviceState->WaveQueue = DeviceInfo->DeviceState->WaveQueue->lpNext; + + DPRINT("Returning buffer to client...\n"); + + /* Free header's device info */ + HeaderExtension = (PWAVEHDR_EXTENSION)Header->reserved; + if (HeaderExtension->DeviceInfo) + { + HeapFree(GetProcessHeap(), 0, HeaderExtension->DeviceInfo); + } + + /* Update the header */ + Header->lpNext = NULL; + Header->dwFlags &= ~WHDR_INQUEUE; + Header->dwFlags |= WHDR_DONE; + + /* Safe to do this without thread protection, as we're done with the header */ + NotifyMmeClient(DeviceInfo, + DeviceInfo->DeviceType == WAVE_OUT_DEVICE_TYPE ? WOM_DONE : WIM_DATA, + (DWORD_PTR)Header); + } +} diff --git a/dll/win32/wdmaud.drv/wave/streaming.c b/dll/win32/wdmaud.drv/wave/streaming.c new file mode 100644 index 0000000000000..4e7122215d561 --- /dev/null +++ b/dll/win32/wdmaud.drv/wave/streaming.c @@ -0,0 +1,89 @@ +/* + * PROJECT: ReactOS Sound System "MME Buddy" Library + * LICENSE: GPL - See COPYING in the top level directory + * FILE: lib/drivers/sound/mmebuddy/wave/streaming.c + * + * PURPOSE: Wave streaming + * + * PROGRAMMERS: Andrew Greenwood (silverblade@reactos.org) +*/ + +#include "wdmaud.h" + +#define YDEBUG +#include + + +/* + DoWaveStreaming + Check if there is streaming to be done, and if so, do it. +*/ + +MMRESULT +DoWaveStreaming( + IN PWDMAUD_DEVICE_INFO DeviceInfo, + IN PWAVEHDR Header) +{ + MMRESULT Result; + + /* Is there any work to do? */ + if (!Header) + { + DPRINT("DoWaveStreaming: No work to do - doing nothing\n"); + return MMSYSERR_NOMEM; + } + + /* Sanity checks */ + ASSERT(Header->dwFlags & WHDR_PREPARED); + ASSERT(Header->dwFlags & WHDR_INQUEUE); + + /* Submit wave header */ + Result = FUNC_NAME(WdmAudSubmitWaveHeader)(DeviceInfo, Header); + if (!MMSUCCESS(Result)) + { + DPRINT1("WdmAudSubmitWaveHeader failed with error %d\n", GetLastError()); + Header->dwFlags &= ~WHDR_INQUEUE; + return TranslateInternalMmResult(Result); + } + + /* Done */ + return MMSYSERR_NOERROR; +} + +/* + Stream control functions + (External/internal thread pairs) + + TODO - Move elsewhere as these shouldn't be wave specific! +*/ + +MMRESULT +StopStreamingInSoundThread( + IN PWDMAUD_DEVICE_INFO DeviceInfo) +{ + MMRESULT Result; + + /* Reset the stream */ + Result = FUNC_NAME(WdmAudResetStream)(DeviceInfo, FALSE); + + if ( ! MMSUCCESS(Result) ) + { + /* Failed */ + return TranslateInternalMmResult(Result); + } + + return MMSYSERR_NOERROR; +} + +MMRESULT +StopStreaming( + IN PWDMAUD_DEVICE_INFO DeviceInfo) +{ + if ( ! DeviceInfo ) + return MMSYSERR_INVALHANDLE; + + if ( DeviceInfo->DeviceType != WAVE_OUT_DEVICE_TYPE && DeviceInfo->DeviceType != WAVE_IN_DEVICE_TYPE ) + return MMSYSERR_NOTSUPPORTED; + + return StopStreamingInSoundThread(DeviceInfo); +} diff --git a/dll/win32/wdmaud.drv/wave/widMessage.c b/dll/win32/wdmaud.drv/wave/widMessage.c new file mode 100644 index 0000000000000..808006133e9a4 --- /dev/null +++ b/dll/win32/wdmaud.drv/wave/widMessage.c @@ -0,0 +1,134 @@ +/* + * PROJECT: ReactOS Sound System "MME Buddy" Library + * LICENSE: GPL - See COPYING in the top level directory + * FILE: lib/sound/mmebuddy/wave/widMessage.c + * + * PURPOSE: Provides the widMessage exported function, as required by + * the MME API, for wave input device support. + * + * PROGRAMMERS: Andrew Greenwood (silverblade@reactos.org) +*/ + +#include "wdmaud.h" + +#define YDEBUG +#include + +/* + Standard MME driver entry-point for messages relating to wave audio + input. +*/ +DWORD +APIENTRY +widMessage( + UINT DeviceId, + UINT Message, + DWORD_PTR PrivateHandle, + DWORD_PTR Parameter1, + DWORD_PTR Parameter2) +{ + MMRESULT Result = MMSYSERR_NOTSUPPORTED; + + AcquireEntrypointMutex(WAVE_IN_DEVICE_TYPE); + + DPRINT("widMessage - Message type %d\n", Message); + + switch ( Message ) + { +#ifndef USE_MMIXER_LIB + case WIDM_INIT: + { + Result = WdmAudAddRemoveDeviceNode(WAVE_IN_DEVICE_TYPE, TRUE); + break; + } + + case DRVM_EXIT: + { + Result = WdmAudAddRemoveDeviceNode(WAVE_IN_DEVICE_TYPE, FALSE); + break; + } +#endif + case WIDM_GETNUMDEVS : + { + Result = MmeGetNumDevs(WAVE_IN_DEVICE_TYPE); + break; + } + + case WIDM_START : + { + Result = MmeSetState(PrivateHandle, TRUE); + break; + } + + case WIDM_STOP : + { + Result = MmeSetState(PrivateHandle, FALSE); + break; + } + + case WIDM_GETDEVCAPS : + { + + Result = MmeGetSoundDeviceCapabilities(WAVE_IN_DEVICE_TYPE, + DeviceId, + (MDEVICECAPSEX*)Parameter1); + break; + } + case WIDM_OPEN : + { + + /* Do sanity checks for 'recording' SamplesPerSec value */ + LPWAVEOPENDESC OpenParameters = (LPWAVEOPENDESC)Parameter1; + if (OpenParameters->lpFormat->nSamplesPerSec > 100000) + OpenParameters->lpFormat->nSamplesPerSec = 100000; + if (OpenParameters->lpFormat->nSamplesPerSec < 5000) + OpenParameters->lpFormat->nSamplesPerSec = 5000; + + Result = MmeOpenDevice(WAVE_IN_DEVICE_TYPE, + DeviceId, + (LPWAVEOPENDESC)Parameter1, + Parameter2, + (DWORD_PTR*) PrivateHandle); + break; + } + + case WIDM_CLOSE : + { + Result = MmeCloseDevice(PrivateHandle); + + break; + } + + case WIDM_PREPARE : + { + /* TODO: Do we need to pass 2nd parameter? */ + Result = MmePrepareWaveHeader(PrivateHandle, Parameter1); + break; + } + + case WIDM_UNPREPARE : + { + Result = MmeUnprepareWaveHeader(PrivateHandle, Parameter1); + break; + } + + case WIDM_RESET : + { + /* Stop playback, reset position to zero */ + Result = MmeResetWavePlayback(PrivateHandle); + break; + } + + case WIDM_ADDBUFFER : + { + Result = MmeWriteWaveHeader(PrivateHandle, Parameter1); + break; + } + } + + DPRINT("widMessage returning MMRESULT %d\n", Result); + + ReleaseEntrypointMutex(WAVE_IN_DEVICE_TYPE); + + return Result; +} diff --git a/dll/win32/wdmaud.drv/wave/wodMessage.c b/dll/win32/wdmaud.drv/wave/wodMessage.c new file mode 100644 index 0000000000000..a22dc5e7341ee --- /dev/null +++ b/dll/win32/wdmaud.drv/wave/wodMessage.c @@ -0,0 +1,134 @@ +/* + * PROJECT: ReactOS Sound System "MME Buddy" Library + * LICENSE: GPL - See COPYING in the top level directory + * FILE: lib/drivers/sound/mmebuddy/wave/wodMessage.c + * + * PURPOSE: Provides the wodMessage exported function, as required by + * the MME API, for wave output device support. + * + * PROGRAMMERS: Andrew Greenwood (silverblade@reactos.org) +*/ + +#include "wdmaud.h" + +#define YDEBUG +#include + +/* + Standard MME driver entry-point for messages relating to wave audio + output. +*/ +DWORD +APIENTRY +wodMessage( + UINT DeviceId, + UINT Message, + DWORD_PTR PrivateHandle, + DWORD_PTR Parameter1, + DWORD_PTR Parameter2) +{ + MMRESULT Result = MMSYSERR_NOTSUPPORTED; + + AcquireEntrypointMutex(WAVE_OUT_DEVICE_TYPE); + + DPRINT("wodMessage - Message type %d\n", Message); + + switch ( Message ) + { +#ifndef USE_MMIXER_LIB + case WODM_INIT: + { + Result = WdmAudAddRemoveDeviceNode(WAVE_OUT_DEVICE_TYPE, TRUE); + break; + } + + case DRVM_EXIT: + { + Result = WdmAudAddRemoveDeviceNode(WAVE_OUT_DEVICE_TYPE, FALSE); + break; + } +#endif + + case WODM_GETNUMDEVS : + { + Result = MmeGetNumDevs(WAVE_OUT_DEVICE_TYPE); + break; + } + + case WODM_GETDEVCAPS : + { + Result = MmeGetSoundDeviceCapabilities(WAVE_OUT_DEVICE_TYPE, + DeviceId, + (MDEVICECAPSEX*)Parameter1); + break; + } + + case WODM_OPEN : + { + Result = MmeOpenDevice(WAVE_OUT_DEVICE_TYPE, + DeviceId, + (LPWAVEOPENDESC)Parameter1, + Parameter2, + (DWORD_PTR*)PrivateHandle); + break; + } + + case WODM_CLOSE : + { + Result = MmeCloseDevice(PrivateHandle); + + break; + } + + case WODM_PREPARE : + { + /* TODO: Do we need to pass 2nd parameter? */ + Result = MmePrepareWaveHeader(PrivateHandle, Parameter1); + break; + } + + case WODM_UNPREPARE : + { + Result = MmeUnprepareWaveHeader(PrivateHandle, Parameter1); + break; + } + + case WODM_WRITE : + { + Result = MmeWriteWaveHeader(PrivateHandle, Parameter1); + break; + } + + case WODM_RESET : + { + /* Stop playback, reset position to zero */ + Result = MmeResetWavePlayback(PrivateHandle); + break; + } + + case WODM_RESTART : + { + /* Continue playback when paused */ + Result = MmeSetState(PrivateHandle, TRUE); + break; + } + case WODM_PAUSE : + { + /* Pause playback */ + Result = MmeSetState(PrivateHandle, FALSE); + break; + } + + case WODM_GETPOS : + { + Result = MmeGetPosition(PrivateHandle, (MMTIME*)Parameter1, Parameter2); + break; + } + } + + DPRINT("wodMessage returning MMRESULT %d\n", Result); + + ReleaseEntrypointMutex(WAVE_OUT_DEVICE_TYPE); + + return Result; +} diff --git a/dll/win32/wdmaud.drv/wdmaud.c b/dll/win32/wdmaud.drv/wdmaud.c index 45308b3aff24e..ec3bb59fea0e3 100644 --- a/dll/win32/wdmaud.drv/wdmaud.c +++ b/dll/win32/wdmaud.drv/wdmaud.c @@ -5,109 +5,12 @@ * * PURPOSE: WDM Audio Driver (User-mode part) * PROGRAMMERS: Andrew Greenwood (silverblade@reactos.org) - * - * NOTES: Looking for wodMessage & co? You won't find them here. Try - * the MME Buddy library, which is where these routines are - * actually implemented. - * */ #include "wdmaud.h" -#define NDEBUG +#define YDEBUG #include -#include - -#define USE_MMIXER_LIB -#ifndef USE_MMIXER_LIB -#define FUNC_NAME(x) x##ByLegacy -#else -#define FUNC_NAME(x) x##ByMMixer -#endif - -MMRESULT -QueryWdmWaveDeviceFormatSupport( - IN PSOUND_DEVICE Device, - IN PWAVEFORMATEX WaveFormat, - IN DWORD WaveFormatSize) -{ - /* Whatever... */ - return MMSYSERR_NOERROR; -} - -MMRESULT -PopulateWdmDeviceList( - MMDEVICE_TYPE DeviceType) -{ - MMRESULT Result; - DWORD DeviceCount = 0; - PSOUND_DEVICE SoundDevice = NULL; - MMFUNCTION_TABLE FuncTable; - DWORD i; - - VALIDATE_MMSYS_PARAMETER( IS_VALID_SOUND_DEVICE_TYPE(DeviceType) ); - - Result = FUNC_NAME(WdmAudGetNumWdmDevs)(DeviceType, &DeviceCount); - - if ( ! MMSUCCESS(Result) ) - { - SND_ERR(L"Error %d while obtaining number of devices\n", Result); - return TranslateInternalMmResult(Result); - } - - SND_TRACE(L"%d devices of type %d found\n", DeviceCount, DeviceType); - - - for ( i = 0; i < DeviceCount; ++ i ) - { - Result = ListSoundDevice(DeviceType, UlongToPtr(i), &SoundDevice); - - if ( ! MMSUCCESS(Result) ) - { - SND_ERR(L"Failed to list sound device - error %d\n", Result); - return TranslateInternalMmResult(Result); - } - - /* Set up our function table */ - ZeroMemory(&FuncTable, sizeof(MMFUNCTION_TABLE)); - FuncTable.GetCapabilities = FUNC_NAME(WdmAudGetCapabilities); - FuncTable.QueryWaveFormatSupport = QueryWdmWaveDeviceFormatSupport; //FIXME - FuncTable.Open = FUNC_NAME(WdmAudOpenSoundDevice); - FuncTable.Close = FUNC_NAME(WdmAudCloseSoundDevice); - FuncTable.GetDeviceInterfaceString = FUNC_NAME(WdmAudGetDeviceInterfaceString); - - if (DeviceType == MIXER_DEVICE_TYPE) - { - FuncTable.SetWaveFormat = FUNC_NAME(WdmAudSetMixerDeviceFormat); - FuncTable.QueryMixerInfo = FUNC_NAME(WdmAudQueryMixerInfo); - } - else if (DeviceType == WAVE_IN_DEVICE_TYPE || DeviceType == WAVE_OUT_DEVICE_TYPE) - { - FuncTable.SetWaveFormat = FUNC_NAME(WdmAudSetWaveDeviceFormat); - FuncTable.SetState = FUNC_NAME(WdmAudSetWaveState); - FuncTable.ResetStream = FUNC_NAME(WdmAudResetStream); - FuncTable.GetPos = FUNC_NAME(WdmAudGetWavePosition); - -#ifndef USERMODE_MIXER - FuncTable.CommitWaveBuffer = FUNC_NAME(WdmAudCommitWaveBuffer); -#else - FuncTable.CommitWaveBuffer = WriteFileEx_Remixer; -#endif - } - else if (DeviceType == MIDI_IN_DEVICE_TYPE || DeviceType == MIDI_OUT_DEVICE_TYPE) - { - FuncTable.SetWaveFormat = FUNC_NAME(WdmAudSetMixerDeviceFormat); - FuncTable.SetState = FUNC_NAME(WdmAudSetWaveState); - FuncTable.GetPos = FUNC_NAME(WdmAudGetWavePosition); - } - - SetSoundDeviceFunctionTable(SoundDevice, &FuncTable); - } - - return MMSYSERR_NOERROR; -} - - LONG APIENTRY @@ -122,52 +25,85 @@ DriverProc( { case DRV_LOAD : { - HANDLE Handle; MMRESULT Result; - SND_TRACE(L"DRV_LOAD\n"); +#ifndef USE_MMIXER_LIB + PWDMAUD_DEVICE_INFO DeviceInfo; +#endif + DPRINT("DRV_LOAD\n"); Result = InitEntrypointMutexes(); if ( ! MMSUCCESS(Result) ) return 0L; - Result = FUNC_NAME(WdmAudOpenSoundDevice)(NULL, &Handle); + Result = FUNC_NAME(WdmAudOpenKernelSoundDevice)(); if ( Result != MMSYSERR_NOERROR ) { - SND_ERR(L"Failed to open \\\\.\\wdmaud\n"); - //UnlistAllSoundDevices(); + DPRINT1("Failed to open \\\\.\\wdmaud with %d\n", GetLastError()); return 0L; } - /* Populate the device lists */ - SND_TRACE(L"Populating device lists\n"); - PopulateWdmDeviceList(WAVE_OUT_DEVICE_TYPE); - PopulateWdmDeviceList(WAVE_IN_DEVICE_TYPE); - PopulateWdmDeviceList(MIDI_OUT_DEVICE_TYPE); - PopulateWdmDeviceList(MIDI_IN_DEVICE_TYPE); - PopulateWdmDeviceList(AUX_DEVICE_TYPE); - PopulateWdmDeviceList(MIXER_DEVICE_TYPE); +#ifndef USE_MMIXER_LIB + DeviceInfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WDMAUD_DEVICE_INFO)); + if (!DeviceInfo) + { + /* No memory */ + DPRINT1("Failed to allocate WDMAUD_DEVICE_INFO structure\n"); + return 0L; + } + + /* Initialize wdmaud.sys */ + DeviceInfo->DeviceType = AUX_DEVICE_TYPE; + + Result = WdmAudIoControl(DeviceInfo, 0, NULL, IOCTL_INIT_WDMAUD); + HeapFree(GetProcessHeap(), 0, DeviceInfo); + if ( ! MMSUCCESS( Result ) ) + { + DPRINT1("Call to IOCTL_INIT_WDMAUD failed with %d\n", GetLastError()); + + return 0L; + } +#endif - SND_TRACE(L"Initialisation complete\n"); + DPRINT("Initialization completed\n"); return 1L; } case DRV_FREE : { - SND_TRACE(L"DRV_FREE\n"); +#ifndef USE_MMIXER_LIB + MMRESULT Result; + PWDMAUD_DEVICE_INFO DeviceInfo; +#endif + DPRINT("DRV_FREE\n"); +#ifndef USE_MMIXER_LIB + DeviceInfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WDMAUD_DEVICE_INFO)); + if (!DeviceInfo) + { + /* No memory */ + DPRINT1("Failed to allocate WDMAUD_DEVICE_INFO structure\n"); + return 0L; + } - FUNC_NAME(WdmAudCleanup)(); + /* Unload wdmaud.sys */ + DeviceInfo->DeviceType = AUX_DEVICE_TYPE; - /* TODO: Clean up the path names! */ - UnlistAllSoundDevices(); + Result = WdmAudIoControl(DeviceInfo, 0, NULL, IOCTL_EXIT_WDMAUD); + HeapFree(GetProcessHeap(), 0, DeviceInfo); + if ( ! MMSUCCESS( Result ) ) + { + DPRINT1("Call to IOCTL_EXIT_WDMAUD failed with %d\n", GetLastError()); - CleanupEntrypointMutexes(); + return 0L; + } +#endif + + FUNC_NAME(WdmAudCleanup)(); - SND_TRACE(L"Unfreed memory blocks: %d\n", - GetMemoryAllocationCount()); + CleanupEntrypointMutexes(); return 1L; } @@ -175,27 +111,27 @@ DriverProc( case DRV_ENABLE : case DRV_DISABLE : { - SND_TRACE(L"DRV_ENABLE / DRV_DISABLE\n"); + DPRINT("DRV_ENABLE / DRV_DISABLE\n"); return 1L; } case DRV_OPEN : case DRV_CLOSE : { - SND_TRACE(L"DRV_OPEN / DRV_CLOSE\n"); + DPRINT("DRV_OPEN / DRV_CLOSE\n"); return 1L; } case DRV_QUERYCONFIGURE : { - SND_TRACE(L"DRV_QUERYCONFIGURE\n"); + DPRINT("DRV_QUERYCONFIGURE\n"); return 0L; } case DRV_CONFIGURE : return DRVCNF_OK; default : - SND_TRACE(L"Unhandled message %d\n", Message); + DPRINT("Unhandled message %d\n", Message); return DefDriverProc(DriverId, DriverHandle, Message, @@ -213,16 +149,16 @@ BOOL WINAPI DllMain( switch ( fdwReason ) { case DLL_PROCESS_ATTACH : - SND_TRACE(L"WDMAUD.DRV - Process attached\n"); + DPRINT("WDMAUD.DRV - Process attached\n"); break; case DLL_PROCESS_DETACH : - SND_TRACE(L"WDMAUD.DRV - Process detached\n"); + DPRINT("WDMAUD.DRV - Process detached\n"); break; case DLL_THREAD_ATTACH : - SND_TRACE(L"WDMAUD.DRV - Thread attached\n"); + DPRINT("WDMAUD.DRV - Thread attached\n"); break; case DLL_THREAD_DETACH : - SND_TRACE(L"WDMAUD.DRV - Thread detached\n"); + DPRINT("WDMAUD.DRV - Thread detached\n"); break; } diff --git a/dll/win32/wdmaud.drv/wdmaud.h b/dll/win32/wdmaud.drv/wdmaud.h index d3900b3adfa7f..4a8a7dae594ab 100644 --- a/dll/win32/wdmaud.drv/wdmaud.h +++ b/dll/win32/wdmaud.drv/wdmaud.h @@ -13,13 +13,39 @@ #include #include -#include #include #include #include #include #include +/* + * Enables user-mode stream resampling support. + * Resampling is required by some legacy devices + * those don't support modern audio formats. + * They're only able to use standard 44100 KHz sample rate, + * 2 (stereo) channels and 16 BPS quality. + * For example, Intel AC97 driver, + * which is used in VirtualBox by default. + */ +//#define RESAMPLING_ENABLED + +//#define USE_MMIXER_LIB +#ifndef USE_MMIXER_LIB +#define FUNC_NAME(x) x##ByLegacy +#else +#define FUNC_NAME(x) x##ByMMixer +#endif + +/* This lives in WAVEHDR.reserved */ +typedef struct +{ + PWDMAUD_DEVICE_INFO DeviceInfo; + OVERLAPPED Overlapped; +} WAVEHDR_EXTENSION, *PWAVEHDR_EXTENSION; + +/* mmixer.c */ + BOOL WdmAudInitUserModeMixer(VOID); @@ -32,214 +58,245 @@ WdmAudGetWaveInCount(VOID); ULONG WdmAudGetMixerCount(VOID); -MMRESULT -WdmAudGetNumWdmDevsByMMixer( - IN MMDEVICE_TYPE DeviceType, - OUT DWORD* DeviceCount); +/* resample.c */ MMRESULT -WdmAudCommitWaveBufferByLegacy( - IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance, - IN PVOID OffsetPtr, - IN DWORD Length, - IN PSOUND_OVERLAPPED Overlap, - IN LPOVERLAPPED_COMPLETION_ROUTINE CompletionRoutine); +WdmAudResampleStream( + _In_ PWDMAUD_DEVICE_INFO DeviceInfo, + _In_ _Out_ PWAVEHDR WaveHeader); -MMRESULT -WriteFileEx_Remixer( - IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance, - IN PVOID OffsetPtr, - IN DWORD Length, - IN PSOUND_OVERLAPPED Overlap, - IN LPOVERLAPPED_COMPLETION_ROUTINE CompletionRoutine); +/* legacy.c */ MMRESULT -WdmAudGetCapabilitiesByMMixer( - IN PSOUND_DEVICE SoundDevice, - IN DWORD DeviceId, - OUT PVOID Capabilities, - IN DWORD CapabilitiesSize); +WdmAudIoControl( + _In_ PWDMAUD_DEVICE_INFO DeviceInfo, + _In_opt_ ULONG DataBufferSize, + _In_opt_ PVOID Buffer, + _In_ DWORD IoControlCode); MMRESULT -WdmAudOpenSoundDeviceByMMixer( - IN struct _SOUND_DEVICE* SoundDevice, - OUT PVOID* Handle); +WdmAudCreateCompletionThread( + _In_ PWDMAUD_DEVICE_INFO DeviceInfo); MMRESULT -WdmAudCloseSoundDeviceByMMixer( - IN struct _SOUND_DEVICE_INSTANCE* SoundDeviceInstance, - IN PVOID Handle); +WdmAudDestroyCompletionThread( + _In_ PWDMAUD_DEVICE_INFO DeviceInfo); MMRESULT -WdmAudGetLineInfo( - IN HANDLE hMixer, - IN DWORD MixerId, - IN LPMIXERLINEW MixLine, - IN ULONG Flags); +WdmAudAddRemoveDeviceNode( + _In_ SOUND_DEVICE_TYPE DeviceType, + _In_ BOOL bAdd); + +/* Shared functions for legacy.c and mmixer.c */ MMRESULT -WdmAudGetLineControls( - IN HANDLE hMixer, - IN DWORD MixerId, - IN LPMIXERLINECONTROLSW MixControls, - IN ULONG Flags); +FUNC_NAME(WdmAudOpenKernelSoundDevice)(VOID); MMRESULT -WdmAudSetControlDetails( - IN HANDLE hMixer, - IN DWORD MixerId, - IN LPMIXERCONTROLDETAILS MixDetails, - IN ULONG Flags); +FUNC_NAME(WdmAudCleanup)(VOID); MMRESULT -WdmAudGetControlDetails( - IN HANDLE hMixer, - IN DWORD MixerId, - IN LPMIXERCONTROLDETAILS MixDetails, - IN ULONG Flags); +FUNC_NAME(WdmAudGetCapabilities)( + _In_ PWDMAUD_DEVICE_INFO DeviceInfo, + _Out_ MDEVICECAPSEX* Capabilities); MMRESULT -WdmAudSetWaveDeviceFormatByMMixer( - IN PSOUND_DEVICE_INSTANCE Instance, - IN DWORD DeviceId, - IN PWAVEFORMATEX WaveFormat, - IN DWORD WaveFormatSize); +FUNC_NAME(WdmAudOpenSoundDevice)( + _In_ PWDMAUD_DEVICE_INFO DeviceInfo, + _In_ PWAVEFORMATEX WaveFormat); MMRESULT -WdmAudGetDeviceInterfaceStringByMMixer( - IN MMDEVICE_TYPE DeviceType, - IN DWORD DeviceId, - IN LPWSTR Interface, - IN DWORD InterfaceLength, - OUT DWORD * InterfaceSize); +FUNC_NAME(WdmAudCloseSoundDevice)( + _In_ PWDMAUD_DEVICE_INFO DeviceInfo, + _In_ PVOID Handle); MMRESULT -WdmAudSetMixerDeviceFormatByMMixer( - IN PSOUND_DEVICE_INSTANCE Instance, - IN DWORD DeviceId, - IN PWAVEFORMATEX WaveFormat, - IN DWORD WaveFormatSize); +FUNC_NAME(WdmAudQueryMixerInfo)( + _In_ PWDMAUD_DEVICE_INFO DeviceInfo, + _In_ DWORD DeviceId, + _In_ UINT uMsg, + _In_ LPVOID Parameter, + _In_ DWORD Flags); MMRESULT -WdmAudQueryMixerInfoByMMixer( - IN struct _SOUND_DEVICE_INSTANCE* SoundDeviceInstance, - IN DWORD DeviceId, - IN UINT uMsg, - IN LPVOID Parameter, - IN DWORD Flags); +FUNC_NAME(WdmAudSetWaveState)( + _In_ PWDMAUD_DEVICE_INFO DeviceInfo, + _In_ BOOL bStart); MMRESULT -WdmAudSetWaveStateByMMixer( - IN struct _SOUND_DEVICE_INSTANCE* SoundDeviceInstance, - IN BOOL bStart); +FUNC_NAME(WdmAudSubmitWaveHeader)( + _In_ PWDMAUD_DEVICE_INFO DeviceInfo, + _In_ PWAVEHDR WaveHeader); MMRESULT -WdmAudResetStreamByMMixer( - IN struct _SOUND_DEVICE_INSTANCE* SoundDeviceInstance, - IN MMDEVICE_TYPE DeviceType, - IN BOOLEAN bStartReset); +FUNC_NAME(WdmAudResetStream)( + _In_ PWDMAUD_DEVICE_INFO DeviceInfo, + _In_ BOOL bStartReset); MMRESULT -WdmAudGetWavePositionByMMixer( - IN struct _SOUND_DEVICE_INSTANCE* SoundDeviceInstance, - IN MMTIME* Time); +FUNC_NAME(WdmAudGetWavePosition)( + _In_ PWDMAUD_DEVICE_INFO DeviceInfo, + _In_ MMTIME* Time); MMRESULT -WdmAudCommitWaveBufferByMMixer( - IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance, - IN PVOID OffsetPtr, - IN DWORD Length, - IN PSOUND_OVERLAPPED Overlap, - IN LPOVERLAPPED_COMPLETION_ROUTINE CompletionRoutine); +FUNC_NAME(WdmAudGetNumWdmDevs)( + _In_ SOUND_DEVICE_TYPE DeviceType, + _Out_ DWORD* DeviceCount); + +/* + reentrancy.c +*/ MMRESULT -WdmAudCleanupByMMixer(VOID); +InitEntrypointMutexes(VOID); -/* legacy.c */ +VOID +CleanupEntrypointMutexes(VOID); + +VOID +AcquireEntrypointMutex( + _In_ SOUND_DEVICE_TYPE DeviceType); + +VOID +ReleaseEntrypointMutex( + _In_ SOUND_DEVICE_TYPE DeviceType); + +/* + mmewrap.c +*/ + +VOID +NotifyMmeClient( + _In_ PWDMAUD_DEVICE_INFO DeviceInfo, + _In_ UINT Message, + _In_ DWORD_PTR Parameter); + +DWORD +MmeGetNumDevs( + _In_ SOUND_DEVICE_TYPE DeviceType); MMRESULT -WdmAudCleanupByLegacy(VOID); +MmeGetSoundDeviceCapabilities( + _In_ SOUND_DEVICE_TYPE DeviceType, + _In_ DWORD DeviceId, + _Out_ MDEVICECAPSEX* Capabilities); MMRESULT -WdmAudGetCapabilitiesByLegacy( - IN PSOUND_DEVICE SoundDevice, - IN DWORD DeviceId, - OUT PVOID Capabilities, - IN DWORD CapabilitiesSize); +MmeOpenDevice( + _In_ SOUND_DEVICE_TYPE DeviceType, + _In_ UINT DeviceId, + _In_ LPWAVEOPENDESC OpenParameters, + _In_ DWORD Flags, + _Out_ DWORD_PTR* PrivateHandle); MMRESULT -WdmAudOpenSoundDeviceByLegacy( - IN PSOUND_DEVICE SoundDevice, - OUT PVOID *Handle -); +MmeCloseDevice( + _In_ DWORD_PTR PrivateHandle); MMRESULT -WdmAudCloseSoundDeviceByLegacy( - IN struct _SOUND_DEVICE_INSTANCE* SoundDeviceInstance, - IN PVOID Handle); +MmeGetPosition( + _In_ DWORD_PTR PrivateHandle, + _In_ MMTIME* Time, + _In_ DWORD Size); MMRESULT -WdmAudGetDeviceInterfaceStringByLegacy( - IN MMDEVICE_TYPE DeviceType, - IN DWORD DeviceId, - IN LPWSTR Interface, - IN DWORD InterfaceLength, - OUT DWORD * InterfaceSize); +MmeSetState( + _In_ DWORD_PTR PrivateHandle, + _In_ BOOL bStart); + + +#define MmePrepareWaveHeader(private_handle, header) \ + PrepareWaveHeader((PWDMAUD_DEVICE_INFO)private_handle, (PWAVEHDR)header) + +#define MmeUnprepareWaveHeader(private_handle, header) \ + UnprepareWaveHeader((PWDMAUD_DEVICE_INFO)private_handle, (PWAVEHDR)header) + +#define MmeWriteWaveHeader(private_handle, header) \ + WriteWaveHeader((PWDMAUD_DEVICE_INFO)private_handle, (PWAVEHDR)header) + +MMRESULT +MmeResetWavePlayback( + _In_ DWORD_PTR PrivateHandle); + +/* + result.c +*/ MMRESULT -WdmAudSetMixerDeviceFormatByLegacy( - IN PSOUND_DEVICE_INSTANCE Instance, - IN DWORD DeviceId, - IN PWAVEFORMATEX WaveFormat, - IN DWORD WaveFormatSize); +Win32ErrorToMmResult( + _In_ UINT ErrorCode); MMRESULT -WdmAudQueryMixerInfoByLegacy( - IN struct _SOUND_DEVICE_INSTANCE* SoundDeviceInstance, - IN DWORD DeviceId, - IN UINT uMsg, - IN LPVOID Parameter, - IN DWORD Flags); +TranslateInternalMmResult( + _In_ MMRESULT Result); + +/* + header.c +*/ MMRESULT -WdmAudSetWaveDeviceFormatByLegacy( - IN PSOUND_DEVICE_INSTANCE Instance, - IN DWORD DeviceId, - IN PWAVEFORMATEX WaveFormat, - IN DWORD WaveFormatSize); +EnqueueWaveHeader( + _In_ PWDMAUD_DEVICE_INFO DeviceInfo, + _In_ PWAVEHDR Header); + +VOID +CompleteWaveHeader( + _In_ PWDMAUD_DEVICE_INFO DeviceInfo); MMRESULT -WdmAudSetWaveStateByLegacy( - IN struct _SOUND_DEVICE_INSTANCE* SoundDeviceInstance, - IN BOOL bStart); +PrepareWaveHeader( + _In_ PWDMAUD_DEVICE_INFO DeviceInfo, + _In_ PWAVEHDR Header); MMRESULT -WdmAudResetStreamByLegacy( - IN struct _SOUND_DEVICE_INSTANCE* SoundDeviceInstance, - IN MMDEVICE_TYPE DeviceType, - IN BOOLEAN bStartReset); +UnprepareWaveHeader( + _In_ PWDMAUD_DEVICE_INFO DeviceInfo, + _In_ PWAVEHDR Header); MMRESULT -WdmAudGetWavePositionByLegacy( - IN struct _SOUND_DEVICE_INSTANCE* SoundDeviceInstance, - IN MMTIME* Time); +WriteWaveHeader( + _In_ PWDMAUD_DEVICE_INFO DeviceInfo, + _In_ PWAVEHDR Header); + +/* + streaming.c +*/ MMRESULT -WriteFileEx_Committer2( - IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance, - IN PVOID OffsetPtr, - IN DWORD Length, - IN PSOUND_OVERLAPPED Overlap, - IN LPOVERLAPPED_COMPLETION_ROUTINE CompletionRoutine); +DoWaveStreaming( + _In_ PWDMAUD_DEVICE_INFO DeviceInfo, + _In_ PWAVEHDR Header); MMRESULT -WdmAudGetNumWdmDevsByLegacy( - IN MMDEVICE_TYPE DeviceType, - OUT DWORD* DeviceCount); +StopStreaming( + _In_ PWDMAUD_DEVICE_INFO DeviceInfo); + + +/* + Convert a device type into a zero-based array index + */ + +#define SOUND_DEVICE_TYPE_TO_INDEX(x) \ + ( x - MIN_SOUND_DEVICE_TYPE ) + +#define INDEX_TO_SOUND_DEVICE_TYPE(x) \ + ( x + MIN_SOUND_DEVICE_TYPE ) + +/* + Validation +*/ + +#define VALIDATE_MMSYS_PARAMETER(parameter_condition) \ + { \ + if ( ! (parameter_condition) ) \ + { \ + DPRINT1("FAILED parameter check: %hS at File %S Line %lu\n", #parameter_condition, __FILE__, __LINE__); \ + return MMSYSERR_INVALPARAM; \ + } \ + } + +#define MMSUCCESS(result) \ + ( result == MMSYSERR_NOERROR ) -DWORD -WINAPI -MixerEventThreadRoutine( - LPVOID Parameter); #endif /* __WDMAUD_H__ */ diff --git a/dll/win32/wdmaud.drv/wdmaud.spec b/dll/win32/wdmaud.drv/wdmaud.spec index d6195cce4a3eb..81b24e86d9fa1 100644 --- a/dll/win32/wdmaud.drv/wdmaud.spec +++ b/dll/win32/wdmaud.drv/wdmaud.spec @@ -4,3 +4,4 @@ @ stdcall wodMessage(long long long long long) @ stdcall widMessage(long long long long long) @ stdcall modMessage(long long long long long) +@ stdcall midMessage(long long long long long) diff --git a/drivers/ksfilter/ks/allocators.c b/drivers/ksfilter/ks/allocators.c index a265f04837273..661479040d887 100644 --- a/drivers/ksfilter/ks/allocators.c +++ b/drivers/ksfilter/ks/allocators.c @@ -175,7 +175,7 @@ IKsAllocator_fnDeviceIoControl( /* invalid request */ Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST; CompleteRequest(Irp, IO_NO_INCREMENT); - + DPRINT1("1\n"); return STATUS_INVALID_DEVICE_REQUEST; } @@ -674,7 +674,10 @@ KsValidateAllocatorFramingEx( IN const KSALLOCATOR_FRAMING_EX* PinFraming) { if (BufferSize < sizeof(KSALLOCATOR_FRAMING_EX)) - return STATUS_INVALID_DEVICE_REQUEST; + { + DPRINT1("2\n"); + return STATUS_INVALID_DEVICE_REQUEST; + } /* verify framing */ if ((Framing->FramingItem[0].Flags & KSALLOCATOR_FLAG_PARTIAL_READ_SUPPORT) && diff --git a/drivers/ksfilter/ks/api.c b/drivers/ksfilter/ks/api.c index d32b54e253597..cc8238fe75780 100644 --- a/drivers/ksfilter/ks/api.c +++ b/drivers/ksfilter/ks/api.c @@ -691,6 +691,7 @@ KsAllocateObjectHeader( } /* store the object in the file object */ IoStack->FileObject->FsContext2 = ObjectHeader; + IoStack->FileObject->FsContext = ObjectHeader; /* store parent device */ ObjectHeader->ParentDeviceObject = IoGetRelatedDeviceObject(IoStack->FileObject); @@ -1159,7 +1160,7 @@ KsSynchronousIoControlDevice( } - /* Store Fileobject */ + /* Prepare stack location */ IoStack = IoGetNextIrpStackLocation(Irp); IoStack->FileObject = FileObject; diff --git a/drivers/ksfilter/ks/clocks.c b/drivers/ksfilter/ks/clocks.c index 730748b2343ae..05559f4cf6e93 100644 --- a/drivers/ksfilter/ks/clocks.c +++ b/drivers/ksfilter/ks/clocks.c @@ -299,6 +299,7 @@ KsValidateClockCreateRequest( if (ClockCreate->CreateFlags != 0) { /* flags must be zero */ + DPRINT1("CLockCreate->CreateFlags %d\n", ClockCreate->CreateFlags); FreeItem(ClockCreate); return STATUS_INVALID_PARAMETER; } diff --git a/drivers/ksfilter/ks/connectivity.c b/drivers/ksfilter/ks/connectivity.c index ba7db56d8b5c2..3c3c6f21e494d 100644 --- a/drivers/ksfilter/ks/connectivity.c +++ b/drivers/ksfilter/ks/connectivity.c @@ -43,7 +43,7 @@ KsCreatePin( PKSDATAFORMAT_WAVEFORMATEX Format = (PKSDATAFORMAT_WAVEFORMATEX)(Connect + 1); if (Format->DataFormat.FormatSize == sizeof(KSDATAFORMAT) || - Format->DataFormat.FormatSize == sizeof(KSDATAFORMAT) + sizeof(WAVEFORMATEX)) + Format->DataFormat.FormatSize == sizeof(KSDATAFORMAT) + sizeof(WAVEFORMATEX) + Format->WaveFormatEx.cbSize) { ConnectSize += Format->DataFormat.FormatSize; } @@ -110,7 +110,6 @@ KspValidateConnectRequest( Descriptor = &((PKSPIN_DESCRIPTOR_EX)((ULONG_PTR)Descriptors + DescriptorSize * ConnectDetails->PinId))->PinDescriptor; } - /* does the pin have interface details filled in */ if (Descriptor->InterfacesCount && Descriptor->Interfaces) { @@ -209,6 +208,16 @@ KspValidateConnectRequest( /// FIXME /// implement format checking + /* HACK for MS sysaudio */ + /* For some reason it returns wrong PinId (2 instead of 0) + * and KSPIN_DATAFLOW_OUT DataFlow (which is used for WaveIn). + * While the actual source of problem isn't figured out yet, + * force this to correct data here. + */ + DPRINT1("DataFlow %d PinId %d\n", Descriptor->DataFlow, ConnectDetails->PinId); + //Descriptor->DataFlow = KSPIN_DATAFLOW_IN; + //ConnectDetails->PinId = 0; + *Connect = ConnectDetails; return STATUS_SUCCESS; } @@ -346,7 +355,7 @@ KspPinPropertyHandler( IoStack = IoGetCurrentIrpStackLocation(Irp); Buffer = Data; - //DPRINT("KsPinPropertyHandler Irp %p Property %p Data %p DescriptorsCount %u Descriptor %p OutputLength %u Id %u\n", Irp, Property, Data, DescriptorsCount, Descriptor, IoStack->Parameters.DeviceIoControl.OutputBufferLength, Property->Id); + DPRINT("KsPinPropertyHandler Irp %p Property %p Data %p DescriptorsCount %u Descriptor %p OutputLength %u Id %u\n", Irp, Property, Data, DescriptorsCount, Descriptors, IoStack->Parameters.DeviceIoControl.OutputBufferLength, Property->Id); /* convert to PKSP_PIN */ Pin = (KSP_PIN*)Property; @@ -356,6 +365,7 @@ KspPinPropertyHandler( if (Pin->PinId >= DescriptorsCount) { /* invalid parameter */ + DPRINT1("Pin->PinId %d is our of range, DescriptorsCount %d\n", Pin->PinId, DescriptorsCount); return STATUS_INVALID_PARAMETER; } } @@ -420,6 +430,7 @@ KspPinPropertyHandler( if (IoStack->Parameters.DeviceIoControl.OutputBufferLength == 0) { /* buffer too small */ + DPRINT1("1\n"); Irp->IoStatus.Information = Size; Status = STATUS_BUFFER_OVERFLOW; break; @@ -430,6 +441,7 @@ KspPinPropertyHandler( if (IoStack->Parameters.DeviceIoControl.OutputBufferLength == sizeof(ULONG)) { /* store the result size */ + DPRINT1("2\n"); Item->Size = Size; Irp->IoStatus.Information = sizeof(ULONG); Status = STATUS_SUCCESS; @@ -442,6 +454,7 @@ KspPinPropertyHandler( if (IoStack->Parameters.DeviceIoControl.OutputBufferLength == sizeof(KSMULTIPLE_ITEM)) { + DPRINT1("3\n"); Irp->IoStatus.Information = sizeof(KSMULTIPLE_ITEM); Status = STATUS_SUCCESS; break; @@ -674,7 +687,7 @@ KsPinPropertyHandler( } /* - @unimplemented + @implemented */ KSDDKAPI NTSTATUS NTAPI KsPinDataIntersectionEx( @@ -687,28 +700,11 @@ KsPinDataIntersectionEx( IN PFNKSINTERSECTHANDLEREX IntersectHandler OPTIONAL, IN PVOID HandlerContext OPTIONAL) { - UNIMPLEMENTED; - return STATUS_UNSUCCESSFUL; -} - -/* - @implemented -*/ -KSDDKAPI -NTSTATUS -NTAPI -KsPinDataIntersection( - IN PIRP Irp, - IN PKSP_PIN Pin, - OUT PVOID Data, - IN ULONG DescriptorsCount, - IN const KSPIN_DESCRIPTOR* Descriptor, - IN PFNKSINTERSECTHANDLER IntersectHandler) -{ - KSMULTIPLE_ITEM * Item; - KSDATARANGE * DataRange; + PKSMULTIPLE_ITEM MultipleItem; + PKSDATARANGE DataRange; PIO_STACK_LOCATION IoStack; - ULONG Size; + ULONG OutputBufferLength; + ULONG DataSize, Size; ULONG Index; NTSTATUS Status; @@ -728,35 +724,66 @@ KsPinDataIntersection( if (Pin->PinId >= DescriptorsCount) { /* it is */ + DPRINT1("PinId %d is out of range, DescriptorsCount %d\n", Pin->PinId, DescriptorsCount); Irp->IoStatus.Status = STATUS_INVALID_PARAMETER; Irp->IoStatus.Information = 0; return STATUS_INVALID_PARAMETER; } + /* get output buffer length */ + OutputBufferLength = IoStack->Parameters.DeviceIoControl.OutputBufferLength; + /* get start item */ - Item = (KSMULTIPLE_ITEM*)(Pin + 1); + MultipleItem = (KSMULTIPLE_ITEM*)(Pin + 1); + /* get first data range */ - DataRange = (KSDATARANGE*)(Item + 1); + DataRange = (PKSDATARANGE)(MultipleItem + 1); + + /* FIXME make sure its 64 bit aligned */ + ASSERT(((ULONG_PTR)DataRange & 0x7) == 0); + /* iterate through all data ranges */ - for(Index = 0; Index < Item->Count; Index++, DataRange++) + for (Index = 0; Index < Descriptor->DataRangesCount; Index++) { - /* call intersect handler */ - Status = IntersectHandler(Irp, Pin, DataRange, Data); - if (NT_SUCCESS(Status)) + /* check matching of the data range */ + if (IsEqualGUIDAligned(&Descriptor->DataRanges[0]->MajorFormat, &DataRange->MajorFormat) || + IsEqualGUIDAligned(&Descriptor->DataRanges[0]->SubFormat, &DataRange->SubFormat) || + IsEqualGUIDAligned(&Descriptor->DataRanges[0]->Specifier, &DataRange->Specifier)) { - if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < DataRange->FormatSize) + /* call intersect handler */ + Status = IntersectHandler(HandlerContext, + Irp, + Pin, + DataRange, + Descriptor->DataRanges[0], + OutputBufferLength, + Data, + &DataSize); + DPRINT1("IntersectHandler status 0x%lx\n", Status); + if (NT_SUCCESS(Status) || Status == STATUS_BUFFER_OVERFLOW || Status == STATUS_BUFFER_TOO_SMALL) { - /* buffer is too small */ - Irp->IoStatus.Information = DataRange->FormatSize; - Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL; - return STATUS_BUFFER_TOO_SMALL; + Irp->IoStatus.Information = DataSize; + if (OutputBufferLength == 0) + { + /* buffer overflow */ + Irp->IoStatus.Status = STATUS_BUFFER_OVERFLOW; + return STATUS_BUFFER_OVERFLOW; + } + else if (OutputBufferLength < sizeof(KSDATARANGE)) + { + /* buffer is too small */ + Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL; + return STATUS_BUFFER_TOO_SMALL; + } + RtlMoveMemory(Irp->UserBuffer, DataRange, sizeof(KSDATARANGE)); + Irp->IoStatus.Status = STATUS_SUCCESS; + return STATUS_SUCCESS; } - RtlMoveMemory(Irp->UserBuffer, DataRange, sizeof(KSDATARANGE)); - Irp->IoStatus.Information = sizeof(KSDATARANGE); - Irp->IoStatus.Status = STATUS_SUCCESS; - return STATUS_SUCCESS; - } + } + DataRange = (PKSDATARANGE)((PUCHAR)DataRange + DataRange->FormatSize); + /* FIXME make sure its 64 bit aligned */ + ASSERT(((ULONG_PTR)DataRange & 0x7) == 0); } Irp->IoStatus.Information = 0; @@ -764,6 +791,49 @@ KsPinDataIntersection( return STATUS_NO_MATCH; } +NTSTATUS +KspPinIntersectHandlerEx( + IN PVOID Context, + IN PIRP Irp, + IN PKSP_PIN Pin, + IN PKSDATARANGE DataRange, + IN PKSDATARANGE MatchingDataRange, + IN ULONG DataBufferSize, + OUT PVOID Data, + OUT PULONG DataSize) +{ + PFNKSINTERSECTHANDLER IntersectHandler = (PFNKSINTERSECTHANDLER)Context; + NTSTATUS Status; + + Status = IntersectHandler(Irp, Pin, DataRange, Data); + *DataSize = (ULONG)Irp->IoStatus.Information; + return Status; +} + +/* + @implemented +*/ +KSDDKAPI +NTSTATUS +NTAPI +KsPinDataIntersection( + IN PIRP Irp, + IN PKSP_PIN Pin, + OUT PVOID Data, + IN ULONG DescriptorsCount, + IN const KSPIN_DESCRIPTOR* Descriptor, + IN PFNKSINTERSECTHANDLER IntersectHandler) +{ + return KsPinDataIntersectionEx(Irp, + Pin, + Data, + DescriptorsCount, + Descriptor, + sizeof(KSPIN_DESCRIPTOR), + (PFNKSINTERSECTHANDLEREX)KspPinIntersectHandlerEx, + IntersectHandler); +} + /* @implemented */ diff --git a/drivers/ksfilter/ks/device.c b/drivers/ksfilter/ks/device.c index 5c3e528b3ca65..f9084310a3a91 100644 --- a/drivers/ksfilter/ks/device.c +++ b/drivers/ksfilter/ks/device.c @@ -554,11 +554,11 @@ IKsDevice_Power( /* TODO */ - Irp->IoStatus.Status = STATUS_SUCCESS; + Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED; Irp->IoStatus.Information = 0; CompleteRequest(Irp, IO_NO_INCREMENT); - return STATUS_SUCCESS; + return STATUS_NOT_IMPLEMENTED; } NTSTATUS diff --git a/drivers/ksfilter/ks/filter.c b/drivers/ksfilter/ks/filter.c index 59bc676745d07..7d431e1c994ba 100644 --- a/drivers/ksfilter/ks/filter.c +++ b/drivers/ksfilter/ks/filter.c @@ -774,7 +774,7 @@ KspHandlePropertyInstances( Instances->PossibleCount = This->Filter.Descriptor->PinDescriptors[Pin->PinId].InstancesPossible; /* current instance count */ Instances->CurrentCount = This->PinInstanceCount[Pin->PinId]; - + DPRINT1("CurrentCount %d, PossibleCount %d\n", Instances->CurrentCount, Instances->PossibleCount); IoStatus->Information = sizeof(KSPIN_CINSTANCES); IoStatus->Status = STATUS_SUCCESS; return STATUS_SUCCESS; diff --git a/drivers/ksfilter/ks/filterfactory.c b/drivers/ksfilter/ks/filterfactory.c index be907d8df9c00..4b7579411494e 100644 --- a/drivers/ksfilter/ks/filterfactory.c +++ b/drivers/ksfilter/ks/filterfactory.c @@ -721,6 +721,7 @@ KsFilterFactoryUpdateCacheData( if (!Found) { /* filter category is not present */ + DPRINT1("Failed to find filter category\n"); Status = STATUS_INVALID_PARAMETER; break; } diff --git a/drivers/ksfilter/ks/irp.c b/drivers/ksfilter/ks/irp.c index 01ee18c283273..b590e8a53fa10 100644 --- a/drivers/ksfilter/ks/irp.c +++ b/drivers/ksfilter/ks/irp.c @@ -656,6 +656,10 @@ KsStreamIo( IoStack = IoGetNextIrpStackLocation(Irp); /* setup stack parameters */ IoStack->FileObject = FileObject; + + IoStack->MajorFunction = IRP_MJ_DEVICE_CONTROL; + IoStack->Parameters.DeviceIoControl.Type3InputBuffer = StreamHeaders; + IoStack->Parameters.DeviceIoControl.InputBufferLength = Length; IoStack->Parameters.DeviceIoControl.OutputBufferLength = Length; IoStack->Parameters.DeviceIoControl.IoControlCode = (Flags == KSSTREAM_READ ? IOCTL_KS_READ_STREAM : IOCTL_KS_WRITE_STREAM); @@ -667,6 +671,7 @@ KsStreamIo( /* now call the driver */ Status = IoCallDriver(DeviceObject, Irp); + DPRINT1("Status 0x%lx\n", Status); /* done */ return Status; } @@ -834,6 +839,7 @@ KsProbeStreamIrp( if (StreamHeader->Size != HeaderSize && !(StreamHeader->OptionsFlags & KSSTREAM_HEADER_OPTIONSF_TYPECHANGED)) { /* invalid stream header */ + DPRINT1("1\n"); ExRaiseStatus(STATUS_INVALID_BUFFER_SIZE); } } @@ -843,6 +849,7 @@ KsProbeStreamIrp( if (StreamHeader->Size < sizeof(KSSTREAM_HEADER) || (StreamHeader->Size & 7)) { /* invalid stream header */ + DPRINT1("2\n"); ExRaiseStatus(STATUS_INVALID_BUFFER_SIZE); } } @@ -850,6 +857,7 @@ KsProbeStreamIrp( if (Length < StreamHeader->Size) { /* length is too short */ + DPRINT1("3\n"); ExRaiseStatus(STATUS_INVALID_BUFFER_SIZE); } @@ -858,6 +866,7 @@ KsProbeStreamIrp( if (StreamHeader->DataUsed > StreamHeader->FrameExtent) { /* frame extend can never be smaller */ + DPRINT1("4\n"); ExRaiseStatus(STATUS_INVALID_BUFFER_SIZE); } @@ -867,6 +876,7 @@ KsProbeStreamIrp( if (Length != sizeof(KSSTREAM_HEADER) || (PVOID)StreamHeader != Irp->AssociatedIrp.SystemBuffer) { /* stream changed - must be send in a single packet */ + DPRINT1("5\n"); ExRaiseStatus(STATUS_INVALID_BUFFER_SIZE); } @@ -897,6 +907,7 @@ KsProbeStreamIrp( if (StreamHeader->DataUsed) { /* DataUsed must be zero for stream read operation */ + DPRINT1("6\n"); ExRaiseStatus(STATUS_INVALID_BUFFER_SIZE); } @@ -940,6 +951,9 @@ KsProbeStreamIrp( goto ProbeMdl; } + // HACK for MS portcls + //HeaderSize = Length; + /* probe user mode buffers */ if (Length && ( (!HeaderSize) || (Length % HeaderSize == 0) || ((ProbeFlags & KSPROBE_ALLOWFORMATCHANGE) && (Length == sizeof(KSSTREAM_HEADER))) ) ) { @@ -1007,6 +1021,7 @@ KsProbeStreamIrp( if (StreamHeader->Size != HeaderSize && !(StreamHeader->OptionsFlags & KSSTREAM_HEADER_OPTIONSF_TYPECHANGED)) { /* invalid stream header */ + DPRINT1("7\n"); ExRaiseStatus(STATUS_INVALID_BUFFER_SIZE); } } @@ -1016,6 +1031,7 @@ KsProbeStreamIrp( if (StreamHeader->Size < sizeof(KSSTREAM_HEADER) || (StreamHeader->Size & 7)) { /* invalid stream header */ + DPRINT1("8\n"); ExRaiseStatus(STATUS_INVALID_BUFFER_SIZE); } } @@ -1023,6 +1039,7 @@ KsProbeStreamIrp( if (Length < StreamHeader->Size) { /* length is too short */ + DPRINT1("9\n"); ExRaiseStatus(STATUS_INVALID_BUFFER_SIZE); } @@ -1031,6 +1048,7 @@ KsProbeStreamIrp( if (StreamHeader->DataUsed > StreamHeader->FrameExtent) { /* frame extend can never be smaller */ + DPRINT1("10\n"); ExRaiseStatus(STATUS_INVALID_BUFFER_SIZE); } @@ -1040,6 +1058,7 @@ KsProbeStreamIrp( if (Length != sizeof(KSSTREAM_HEADER) || (PVOID)StreamHeader != Irp->AssociatedIrp.SystemBuffer) { /* stream changed - must be send in a single packet */ + DPRINT1("11\n"); ExRaiseStatus(STATUS_INVALID_BUFFER_SIZE); } @@ -1071,6 +1090,7 @@ KsProbeStreamIrp( if (StreamHeader->DataUsed) { /* DataUsed must be zero for stream read operation */ + DPRINT1("13\n"); ExRaiseStatus(STATUS_INVALID_BUFFER_SIZE); } @@ -1099,6 +1119,7 @@ KsProbeStreamIrp( return Status; } + DPRINT1("14\n"); return STATUS_INVALID_BUFFER_SIZE; } @@ -1190,6 +1211,9 @@ KsDispatchInvalidDeviceRequest( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { + DPRINT1("KsDispatchInvalidDeviceRequest called: DeviceObject %p, Irp %p\n", + DeviceObject, Irp); + Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST; CompleteRequest(Irp, IO_NO_INCREMENT); @@ -1209,6 +1233,9 @@ KsDefaultDeviceIoCompletion( PIO_STACK_LOCATION IoStack; NTSTATUS Status; + DPRINT1("KsDefaultDeviceIoCompletion called: DeviceObject %p, Irp %p\n", + DeviceObject, Irp); + /* get current irp stack */ IoStack = IoGetCurrentIrpStackLocation(Irp); @@ -1683,18 +1710,6 @@ KsAddIrpToCancelableQueue( DPRINT("KsAddIrpToCancelableQueue QueueHead %p SpinLock %p Irp %p ListLocation %x DriverCancel %p\n", QueueHead, SpinLock, Irp, ListLocation, DriverCancel); - // HACK for ms portcls - if (IoStack->MajorFunction == IRP_MJ_CREATE) - { - // complete the request - DPRINT1("MS HACK\n"); - Irp->IoStatus.Status = STATUS_SUCCESS; - CompleteRequest(Irp, IO_NO_INCREMENT); - - return; - } - - if (!DriverCancel) { /* default to KsCancelRoutine */ @@ -1898,7 +1913,7 @@ KspCreate( DeviceHeader = DeviceExtension->DeviceHeader; - if (IoStack->FileObject->FileName.Buffer == NULL) + if (IoStack->FileObject == NULL) { /* FIXME Pnp-Issue */ DPRINT("Using reference string hack\n"); @@ -2053,6 +2068,9 @@ KsSetMajorFunctionHandler( { DPRINT("KsSetMajorFunctionHandler Function %x\n", MajorFunction); + // HACK for MS portcls + DriverObject->MajorFunction[IRP_MJ_CREATE] = KspCreate; + switch ( MajorFunction ) { case IRP_MJ_CREATE: diff --git a/drivers/ksfilter/ks/pin.c b/drivers/ksfilter/ks/pin.c index b35caf76e852b..38486d93e4918 100644 --- a/drivers/ksfilter/ks/pin.c +++ b/drivers/ksfilter/ks/pin.c @@ -420,7 +420,7 @@ IKsPin_PinDataFormatPropertyHandler( /* get current irp stack */ IoStack = IoGetCurrentIrpStackLocation(Irp); - DPRINT("IKsPin_PinDataFormatPropertyHandler\n"); + DPRINT1("IKsPin_PinDataFormatPropertyHandler\n"); /* sanity check */ ASSERT(IoStack->FileObject); @@ -455,6 +455,7 @@ IKsPin_PinDataFormatPropertyHandler( if (This->Pin.Descriptor->Flags & KSPIN_FLAG_FIXED_FORMAT) { /* format cannot be changed */ + DPRINT1("3\n"); Status = STATUS_INVALID_DEVICE_REQUEST; } else @@ -473,7 +474,7 @@ IKsPin_PinDataFormatPropertyHandler( /* release processing mutex */ KeReleaseMutex(This->BasicHeader.ControlMutex, FALSE); - DPRINT("IKsPin_PinDataFormatPropertyHandler Status %lx\n", Status); + DPRINT1("IKsPin_PinDataFormatPropertyHandler Status %lx\n", Status); return Status; } diff --git a/drivers/ksfilter/ks/swenum.c b/drivers/ksfilter/ks/swenum.c index 1e5738f85817d..ea41973404fdb 100644 --- a/drivers/ksfilter/ks/swenum.c +++ b/drivers/ksfilter/ks/swenum.c @@ -812,7 +812,7 @@ KspStartBusDevice( DPRINT1("KspStartBusDevice Name %S DeviceName %S Instance %S Started\n", Name, DeviceEntry->DeviceName, DeviceEntry->Instance); /* enable device classes */ - //KspEnableBusDeviceInterface(DeviceEntry, TRUE); + KspEnableBusDeviceInterface(DeviceEntry, TRUE); /* done */ return STATUS_SUCCESS; @@ -1227,7 +1227,7 @@ KspBusWorkerRoutine( Diff.QuadPart); /* deactivate interfaces */ - //KspEnableBusDeviceInterface(DeviceEntry, FALSE); + KspEnableBusDeviceInterface(DeviceEntry, FALSE); /* re-acquire lock */ KeAcquireSpinLock(&BusDeviceExtension->Lock, &OldLevel); diff --git a/drivers/ksfilter/ks/topology.c b/drivers/ksfilter/ks/topology.c index 4a241209f2b36..aebb109bb46b3 100644 --- a/drivers/ksfilter/ks/topology.c +++ b/drivers/ksfilter/ks/topology.c @@ -105,7 +105,7 @@ KsValidateTopologyNodeCreateRequest( PKSNODE_CREATE NodeCreate; ULONG Size; NTSTATUS Status; - + DPRINT1("Topology %p\n", Topology); /* did the caller miss the topology */ if (!Topology) return STATUS_INVALID_PARAMETER; @@ -182,6 +182,7 @@ KsTopologyPropertyHandler( if (Node->NodeId >= Topology->TopologyNodesCount) { /* invalid node id */ + DPRINT1("Node->NodeId %d is out of range, Topology->TopologyNodesCount %d\n", Node->NodeId, Topology->TopologyNodesCount); Irp->IoStatus.Information = 0; Status = STATUS_INVALID_PARAMETER; break; diff --git a/drivers/wdm/audio/backpln/CMakeLists.txt b/drivers/wdm/audio/backpln/CMakeLists.txt index 867bad2f9c56b..970243d9bc47a 100644 --- a/drivers/wdm/audio/backpln/CMakeLists.txt +++ b/drivers/wdm/audio/backpln/CMakeLists.txt @@ -1,3 +1,3 @@ -add_subdirectory(audio_test) +#add_subdirectory(audio_test) add_subdirectory(portcls) diff --git a/drivers/wdm/audio/backpln/portcls/irpstream.cpp b/drivers/wdm/audio/backpln/portcls/irpstream.cpp index a79259fa0828d..5964318b5694c 100644 --- a/drivers/wdm/audio/backpln/portcls/irpstream.cpp +++ b/drivers/wdm/audio/backpln/portcls/irpstream.cpp @@ -194,11 +194,13 @@ CIrpQueue::AddMapping( if (m_Descriptor->DataFlow == KSPIN_DATAFLOW_IN) { // irp sink + DPRINT("Header->DataUsed %d\n", Header->DataUsed); HeaderLength = Header->DataUsed; } else { // irp source + DPRINT("Header->FrameExtent %d\n", Header->FrameExtent); HeaderLength = Header->FrameExtent; } @@ -300,10 +302,11 @@ CIrpQueue::GetMapping( PIRP Irp; ULONG Offset; PKSSTREAM_DATA StreamData; - + DPRINT("Irp %p\n", m_Irp); // check if there is an irp in the partially processed if (m_Irp) { + DPRINT("Irp->Cancel %x\n", m_Irp->Cancel); // use last irp if (m_Irp->Cancel == FALSE) { diff --git a/drivers/wdm/audio/backpln/portcls/pin_wavecyclic.cpp b/drivers/wdm/audio/backpln/portcls/pin_wavecyclic.cpp index 15495d2aeefb5..9f8430e07ce89 100644 --- a/drivers/wdm/audio/backpln/portcls/pin_wavecyclic.cpp +++ b/drivers/wdm/audio/backpln/portcls/pin_wavecyclic.cpp @@ -587,11 +587,12 @@ PinWaveCyclicDataFormat( PC_ASSERT(IsEqualGUIDAligned(((PKSDATAFORMAT_WAVEFORMATEX)NewDataFormat)->DataFormat.MajorFormat, KSDATAFORMAT_TYPE_AUDIO)); PC_ASSERT(IsEqualGUIDAligned(((PKSDATAFORMAT_WAVEFORMATEX)NewDataFormat)->DataFormat.SubFormat, KSDATAFORMAT_SUBTYPE_PCM)); PC_ASSERT(IsEqualGUIDAligned(((PKSDATAFORMAT_WAVEFORMATEX)NewDataFormat)->DataFormat.Specifier, KSDATAFORMAT_SPECIFIER_WAVEFORMATEX)); +#endif DPRINT("NewDataFormat: Channels %u Bits %u Samples %u\n", ((PKSDATAFORMAT_WAVEFORMATEX)NewDataFormat)->WaveFormatEx.nChannels, ((PKSDATAFORMAT_WAVEFORMATEX)NewDataFormat)->WaveFormatEx.wBitsPerSample, ((PKSDATAFORMAT_WAVEFORMATEX)NewDataFormat)->WaveFormatEx.nSamplesPerSec); -#endif + } else @@ -1223,7 +1224,7 @@ CPortPinWaveCyclic::Init( } #endif - DPRINT1("CPortPinWaveCyclic::Init Status %x PinId %u Capture %u\n", Status, ConnectDetails->PinId, Capture); + DPRINT1("CPortPinWaveCyclic::Init Status %x PinId %u Capture %u\n", Status, ConnectDetails->PinId, KsPinDescriptor->DataFlow == KSPIN_DATAFLOW_OUT); if (!NT_SUCCESS(Status)) return Status; diff --git a/drivers/wdm/audio/backpln/portcls/port_wavecyclic.cpp b/drivers/wdm/audio/backpln/portcls/port_wavecyclic.cpp index 04525ab53f8c7..f5245e065f09f 100644 --- a/drivers/wdm/audio/backpln/portcls/port_wavecyclic.cpp +++ b/drivers/wdm/audio/backpln/portcls/port_wavecyclic.cpp @@ -205,7 +205,7 @@ CPortWaveCyclic::Init( Status = UnknownMiniport->QueryInterface(IID_IMiniportWaveCyclic, (PVOID*)&Miniport); if (!NT_SUCCESS(Status)) { - DPRINT("IPortWaveCyclic_Init called with invalid IMiniport adapter\n"); + DPRINT1("IPortWaveCyclic_Init called with invalid IMiniport adapter\n"); return STATUS_INVALID_PARAMETER; } diff --git a/drivers/wdm/audio/backpln/portcls/propertyhandler.cpp b/drivers/wdm/audio/backpln/portcls/propertyhandler.cpp index 5aa07fcf998df..b6b6a99348295 100644 --- a/drivers/wdm/audio/backpln/portcls/propertyhandler.cpp +++ b/drivers/wdm/audio/backpln/portcls/propertyhandler.cpp @@ -33,7 +33,7 @@ HandlePropertyInstances( } Instances = (KSPIN_CINSTANCES*)Data; - + DPRINT1("PinId %d\n", Pin->PinId); // check if the miniport supports the IPinCount interface Status = SubDevice->PinCount(Pin->PinId, &FilterNecessary, &FilterCurrent, &FilterPossible, &GlobalCurrent, &GlobalPossible); @@ -59,7 +59,7 @@ HandlePropertyInstances( Instances->CurrentCount = Descriptor->Factory.Instances[Pin->PinId].CurrentPinInstanceCount; } - + DPRINT1("CurrentCount %d, PossibleCount %d\n", Instances->CurrentCount, Instances->PossibleCount); IoStatus->Information = sizeof(KSPIN_CINSTANCES); IoStatus->Status = STATUS_SUCCESS; return STATUS_SUCCESS; @@ -131,8 +131,9 @@ HandleDataIntersection( Status = SubDevice->DataRangeIntersection(Pin->PinId, DataRange, (PKSDATARANGE)Descriptor->Factory.KsPinDescriptor[Pin->PinId].DataRanges[0], DataLength, Data, &Length); - if (Status == STATUS_SUCCESS) + if (Status == STATUS_SUCCESS || Status == STATUS_BUFFER_OVERFLOW || Status == STATUS_BUFFER_TOO_SMALL) { + ASSERT(Length); IoStatus->Information = Length; break; } diff --git a/drivers/wdm/audio/drivers/ac97/debug.h b/drivers/wdm/audio/drivers/ac97/debug.h index 78c5335c16dd9..f14e22f459d01 100644 --- a/drivers/wdm/audio/drivers/ac97/debug.h +++ b/drivers/wdm/audio/drivers/ac97/debug.h @@ -38,7 +38,7 @@ const int DBG_ALL = 0xFFFFFFFF; // The default statements that will print are warnings (DBG_WARNING) and // errors (DBG_ERROR). // -const int DBG_DEFAULT = 0x00000004; // Errors only. +const int DBG_DEFAULT = 0x00000002; // Errors only. // diff --git a/drivers/wdm/audio/drivers/ac97/miniport.cpp b/drivers/wdm/audio/drivers/ac97/miniport.cpp index 83bb53d9d3c2e..e5199b735db71 100644 --- a/drivers/wdm/audio/drivers/ac97/miniport.cpp +++ b/drivers/wdm/audio/drivers/ac97/miniport.cpp @@ -673,7 +673,10 @@ STDMETHODIMP_(NTSTATUS) CMiniport::DataRangeIntersection nMaxChannels--; // ... and also 0 channels wouldn't be a good request. if (!nMaxChannels) + { + DOUT (DBG_WARNING, ("[DataRangeIntersection] No valid channels found")); return STATUS_NO_MATCH; + } WaveFormat->Format.nChannels = (WORD)nMaxChannels; } @@ -704,6 +707,7 @@ STDMETHODIMP_(NTSTATUS) CMiniport::DataRangeIntersection if ((((PKSDATARANGE_AUDIO)ClientsDataRange)->MaximumSampleFrequency < ulFrequency) || (((PKSDATARANGE_AUDIO)ClientsDataRange)->MinimumSampleFrequency > ulFrequency)) { + DOUT (DBG_WARNING, ("[DataRangeIntersection] Invalid sample frequency")); return STATUS_NO_MATCH; } diff --git a/drivers/wdm/audio/filters/kmixer/CMakeLists.txt b/drivers/wdm/audio/filters/kmixer/CMakeLists.txt index 6d6b8fc55fb2a..5dfb252b9fcec 100644 --- a/drivers/wdm/audio/filters/kmixer/CMakeLists.txt +++ b/drivers/wdm/audio/filters/kmixer/CMakeLists.txt @@ -1,5 +1,6 @@ -include_directories(${REACTOS_SOURCE_DIR}/sdk/lib/3rdparty/libsamplerate) +include_directories(${REACTOS_SOURCE_DIR}/sdk/lib/3rdparty/libsamplerate + ${REACTOS_SOURCE_DIR}/sdk/lib/3rdparty/resampler) list(APPEND SOURCE kmixer.c diff --git a/drivers/wdm/audio/filters/kmixer/filter.c b/drivers/wdm/audio/filters/kmixer/filter.c index f2112b758b1d3..eb28138646169 100644 --- a/drivers/wdm/audio/filters/kmixer/filter.c +++ b/drivers/wdm/audio/filters/kmixer/filter.c @@ -109,16 +109,6 @@ DispatchCreateKMix( DPRINT("DispatchCreateKMix entered\n"); - /* check if the request was from usermode */ - if (Irp->RequestorMode == UserMode) - { - /* deny access from usermode */ - Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST; - Irp->IoStatus.Information = 0; - IoCompleteRequest(Irp, IO_NO_INCREMENT); - return STATUS_INVALID_DEVICE_REQUEST; - } - /* get device extension */ DeviceExtension = (PKMIXER_DEVICE_EXT)DeviceObject->DeviceExtension; diff --git a/drivers/wdm/audio/filters/kmixer/kmixer.h b/drivers/wdm/audio/filters/kmixer/kmixer.h index 934158ed6d75f..93014250b371f 100644 --- a/drivers/wdm/audio/filters/kmixer/kmixer.h +++ b/drivers/wdm/audio/filters/kmixer/kmixer.h @@ -3,6 +3,7 @@ #include #include +#include typedef struct { diff --git a/drivers/wdm/audio/filters/kmixer/pin.c b/drivers/wdm/audio/filters/kmixer/pin.c index eb2196c358533..634581dc7e25e 100644 --- a/drivers/wdm/audio/filters/kmixer/pin.c +++ b/drivers/wdm/audio/filters/kmixer/pin.c @@ -10,11 +10,12 @@ #include -#define NDEBUG +#define YDEBUG #include const GUID KSPROPSETID_Connection = {0x1D58C920L, 0xAC9B, 0x11CF, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}}; + NTSTATUS PerformSampleRateConversion( PUCHAR Buffer, @@ -130,15 +131,11 @@ PerformSampleRateConversion( } else if (BytesPerSample == 2) { - PUSHORT Res = (PUSHORT)ResultOut; - - src_float_to_short_array(FloatOut, (short*)Res, Data.output_frames_gen * NumChannels); + src_float_to_short_array(FloatOut, (short*)ResultOut, Data.output_frames_gen * NumChannels); } else if (BytesPerSample == 4) { - PULONG Res = (PULONG)ResultOut; - - src_float_to_int_array(FloatOut, (int*)Res, Data.output_frames_gen * NumChannels); + src_float_to_int_array(FloatOut, (int*)ResultOut, Data.output_frames_gen * NumChannels); } @@ -287,7 +284,7 @@ PerformQualityConversion( ASSERT(OldWidth != NewWidth); Samples = BufferLength / (OldWidth / 8); - //DPRINT("Samples %u BufferLength %u\n", Samples, BufferLength); + DPRINT("PerformQualityConversion Samples %u BufferLength %u\n", Samples, BufferLength); if (OldWidth == 8 && NewWidth == 16) { @@ -426,11 +423,11 @@ Pin_fnDeviceIoControl( { PIO_STACK_LOCATION IoStack; PKSP_PIN Property; - //DPRINT1("Pin_fnDeviceIoControl called DeviceObject %p Irp %p\n", DeviceObject); + DPRINT("Pin_fnDeviceIoControl called DeviceObject %p Irp %p\n", DeviceObject, Irp); IoStack = IoGetCurrentIrpStackLocation(Irp); - if (IoStack->Parameters.DeviceIoControl.InputBufferLength == sizeof(KSP_PIN) && IoStack->Parameters.DeviceIoControl.OutputBufferLength == sizeof(KSDATAFORMAT_WAVEFORMATEX)) + if (IoStack->Parameters.DeviceIoControl.InputBufferLength == sizeof(KSP_PIN) && IoStack->Parameters.DeviceIoControl.OutputBufferLength >= sizeof(KSDATAFORMAT_WAVEFORMATEX)) { Property = (PKSP_PIN)IoStack->Parameters.DeviceIoControl.Type3InputBuffer; @@ -451,6 +448,8 @@ Pin_fnDeviceIoControl( Formats[Property->PinId].WaveFormatEx.nChannels = WaveFormat->WaveFormatEx.nChannels; Formats[Property->PinId].WaveFormatEx.wBitsPerSample = WaveFormat->WaveFormatEx.wBitsPerSample; Formats[Property->PinId].WaveFormatEx.nSamplesPerSec = WaveFormat->WaveFormatEx.nSamplesPerSec; + Formats[Property->PinId].WaveFormatEx.nBlockAlign = WaveFormat->WaveFormatEx.nBlockAlign; + Formats[Property->PinId].WaveFormatEx.nAvgBytesPerSec = WaveFormat->WaveFormatEx.nAvgBytesPerSec; Irp->IoStatus.Information = 0; Irp->IoStatus.Status = STATUS_SUCCESS; @@ -486,12 +485,98 @@ Pin_fnWrite( PDEVICE_OBJECT DeviceObject, PIRP Irp) { - UNIMPLEMENTED; + PIO_STACK_LOCATION IoStack; + PKSSTREAM_HEADER StreamHeader; + PVOID BufferOut, BufferOutTemp; + ULONG BufferLength, BufferLengthTemp; + NTSTATUS Status = STATUS_SUCCESS; + PKSDATAFORMAT_WAVEFORMATEX Formats; + PKSDATAFORMAT_WAVEFORMATEX InputFormat, OutputFormat; - Irp->IoStatus.Information = 0; - Irp->IoStatus.Status = STATUS_SUCCESS; - IoCompleteRequest(Irp, IO_NO_INCREMENT); - return STATUS_SUCCESS; + DPRINT("Pin_fnWrite called DeviceObject %p Irp %p\n", DeviceObject, Irp); + + IoStack = IoGetCurrentIrpStackLocation(Irp); + + Formats = (PKSDATAFORMAT_WAVEFORMATEX)IoStack->FileObject->FsContext2; + + InputFormat = Formats; + OutputFormat = (Formats + 1); + + Status = KsProbeStreamIrp(Irp, KSPROBE_STREAMWRITE | KSPROBE_ALLOCATEMDL | KSPROBE_PROBEANDLOCK, sizeof(KSSTREAM_HEADER)); + if (!NT_SUCCESS(Status)) + { + DPRINT1("KsProbeStreamIrp failed with Status 0x%lx Cancel %u\n", Status, Irp->Cancel); + return Status; + } + + StreamHeader = (PKSSTREAM_HEADER)Irp->AssociatedIrp.SystemBuffer; + + BufferOut = StreamHeader->Data; + BufferLength = StreamHeader->DataUsed; + + DPRINT("\n Old Channels %u Num Channels %u\n Old SampleRate %u SampleRate %u\n Old BitsPerSample %u BitsPerSample %u\n", + InputFormat->WaveFormatEx.nChannels, OutputFormat->WaveFormatEx.nChannels, + InputFormat->WaveFormatEx.nSamplesPerSec, OutputFormat->WaveFormatEx.nSamplesPerSec, + InputFormat->WaveFormatEx.wBitsPerSample, OutputFormat->WaveFormatEx.wBitsPerSample); + + if (InputFormat->WaveFormatEx.wBitsPerSample != 16) + { + Status = PerformQualityConversion(StreamHeader->Data, + StreamHeader->DataUsed, + InputFormat->WaveFormatEx.wBitsPerSample, + 16, + &BufferOut, + &BufferLength); + if (NT_SUCCESS(Status)) + { + StreamHeader->Data = BufferOut; + StreamHeader->DataUsed = BufferLength; + } + } + + if (InputFormat->WaveFormatEx.nChannels != 2) + { + Status = PerformChannelConversion(BufferOut, + BufferLength, + InputFormat->WaveFormatEx.nChannels, + 2, + 16, + &BufferOutTemp, + &BufferLengthTemp); + + BufferOut = BufferOutTemp; + BufferLength = BufferLengthTemp; + + if (NT_SUCCESS(Status)) + { + StreamHeader->Data = BufferOut; + StreamHeader->DataUsed = BufferLength; + } + } + + if (InputFormat->WaveFormatEx.nSamplesPerSec != 44100) + { + Status = PerformSampleRateConversion(BufferOut, + BufferLength, + InputFormat->WaveFormatEx.nSamplesPerSec, + 44100, + 2, + 2, + &BufferOutTemp, + &BufferLengthTemp); + + BufferOut = BufferOutTemp; + BufferLength = BufferLengthTemp; + + if (NT_SUCCESS(Status)) + { + StreamHeader->Data = BufferOut; + StreamHeader->DataUsed = BufferLength; + } + } + + Irp->IoStatus.Status = Status; + return Status; } NTSTATUS @@ -565,8 +650,6 @@ Pin_fnFastDeviceIoControl( PDEVICE_OBJECT DeviceObject) { UNIMPLEMENTED; - - return FALSE; } @@ -600,85 +683,8 @@ Pin_fnFastWrite( PIO_STATUS_BLOCK IoStatus, PDEVICE_OBJECT DeviceObject) { - PKSSTREAM_HEADER StreamHeader; - PVOID BufferOut; - ULONG BufferLength; - NTSTATUS Status = STATUS_SUCCESS; - PKSDATAFORMAT_WAVEFORMATEX Formats; - PKSDATAFORMAT_WAVEFORMATEX InputFormat, OutputFormat; - - DPRINT("Pin_fnFastWrite called DeviceObject %p Irp %p\n", DeviceObject); - - Formats = (PKSDATAFORMAT_WAVEFORMATEX)FileObject->FsContext2; - - InputFormat = Formats; - OutputFormat = (Formats + 1); - StreamHeader = (PKSSTREAM_HEADER)Buffer; - - - DPRINT("Num Channels %u Old Channels %u\n SampleRate %u Old SampleRate %u\n BitsPerSample %u Old BitsPerSample %u\n", - InputFormat->WaveFormatEx.nChannels, OutputFormat->WaveFormatEx.nChannels, - InputFormat->WaveFormatEx.nSamplesPerSec, OutputFormat->WaveFormatEx.nSamplesPerSec, - InputFormat->WaveFormatEx.wBitsPerSample, OutputFormat->WaveFormatEx.wBitsPerSample); - - if (InputFormat->WaveFormatEx.wBitsPerSample != OutputFormat->WaveFormatEx.wBitsPerSample) - { - Status = PerformQualityConversion(StreamHeader->Data, - StreamHeader->DataUsed, - InputFormat->WaveFormatEx.wBitsPerSample, - OutputFormat->WaveFormatEx.wBitsPerSample, - &BufferOut, - &BufferLength); - if (NT_SUCCESS(Status)) - { - ExFreePool(StreamHeader->Data); - StreamHeader->Data = BufferOut; - StreamHeader->DataUsed = BufferLength; - } - } - - if (InputFormat->WaveFormatEx.nChannels != OutputFormat->WaveFormatEx.nChannels) - { - Status = PerformChannelConversion(StreamHeader->Data, - StreamHeader->DataUsed, - InputFormat->WaveFormatEx.nChannels, - OutputFormat->WaveFormatEx.nChannels, - OutputFormat->WaveFormatEx.wBitsPerSample, - &BufferOut, - &BufferLength); - - if (NT_SUCCESS(Status)) - { - ExFreePool(StreamHeader->Data); - StreamHeader->Data = BufferOut; - StreamHeader->DataUsed = BufferLength; - } - } - - if (InputFormat->WaveFormatEx.nSamplesPerSec != OutputFormat->WaveFormatEx.nSamplesPerSec) - { - Status = PerformSampleRateConversion(StreamHeader->Data, - StreamHeader->DataUsed, - InputFormat->WaveFormatEx.nSamplesPerSec, - OutputFormat->WaveFormatEx.nSamplesPerSec, - OutputFormat->WaveFormatEx.wBitsPerSample / 8, - OutputFormat->WaveFormatEx.nChannels, - &BufferOut, - &BufferLength); - if (NT_SUCCESS(Status)) - { - ExFreePool(StreamHeader->Data); - StreamHeader->Data = BufferOut; - StreamHeader->DataUsed = BufferLength; - } - } - - IoStatus->Status = Status; - - if (NT_SUCCESS(Status)) - return TRUE; - else - return FALSE; + UNIMPLEMENTED; + return FALSE; } static KSDISPATCH_TABLE PinTable = diff --git a/drivers/wdm/audio/legacy/wdmaud/CMakeLists.txt b/drivers/wdm/audio/legacy/wdmaud/CMakeLists.txt index c088ebf6460f4..a5ff17c43dfbb 100644 --- a/drivers/wdm/audio/legacy/wdmaud/CMakeLists.txt +++ b/drivers/wdm/audio/legacy/wdmaud/CMakeLists.txt @@ -15,7 +15,7 @@ list(APPEND SOURCE add_library(wdmaud MODULE ${SOURCE} wdmaud.rc) set_module_type(wdmaud kernelmodedriver) -target_link_libraries(wdmaud mmixer libcntpr) +target_link_libraries(wdmaud mmixer libcntpr ${PSEH_LIB}) add_pch(wdmaud wdmaud.h SOURCE) add_importlibs(wdmaud ntoskrnl ks hal) add_cd_file(TARGET wdmaud DESTINATION reactos/system32/drivers FOR all) diff --git a/drivers/wdm/audio/legacy/wdmaud/control.c b/drivers/wdm/audio/legacy/wdmaud/control.c index f9ae9a323396b..0adfac5d07854 100644 --- a/drivers/wdm/audio/legacy/wdmaud/control.c +++ b/drivers/wdm/audio/legacy/wdmaud/control.c @@ -9,11 +9,40 @@ #include "wdmaud.h" -#define NDEBUG +#define YDEBUG #include const GUID KSPROPSETID_Sysaudio = {0xCBE3FAA0L, 0xCC75, 0x11D0, {0xB4, 0x65, 0x00, 0x00, 0x1A, 0x18, 0x18, 0xE6}}; +NTSTATUS +WdmAudControlInitialize( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) +{ + NTSTATUS Status; + LPWSTR SymbolicLinkList; + PWDMAUD_DEVICE_EXTENSION DeviceExtension; + + /* Get device extension */ + DeviceExtension = (PWDMAUD_DEVICE_EXTENSION)DeviceObject->DeviceExtension; + + /* Get SysAudio device interface */ + Status = GetSysAudioDeviceInterface(&SymbolicLinkList); + if (NT_SUCCESS(Status)) + { + /* Wait for initialization finishing */ + KeWaitForSingleObject(&DeviceExtension->InitializationCompletionEvent, + Executive, + KernelMode, + FALSE, + NULL); + } + + ExFreePool(SymbolicLinkList); + + return SetIrpIoStatus(Irp, Status, sizeof(WDMAUD_DEVICE_INFO)); +} + NTSTATUS WdmAudControlOpen( IN PDEVICE_OBJECT DeviceObject, @@ -21,23 +50,28 @@ WdmAudControlOpen( IN PWDMAUD_DEVICE_INFO DeviceInfo, IN PWDMAUD_CLIENT ClientInfo) { + NTSTATUS Status; + if (DeviceInfo->DeviceType == MIXER_DEVICE_TYPE) { - return WdmAudControlOpenMixer(DeviceObject, Irp, DeviceInfo, ClientInfo); + Status = WdmAudControlOpenMixer(DeviceObject, Irp, DeviceInfo, ClientInfo); } - - if (DeviceInfo->DeviceType == WAVE_OUT_DEVICE_TYPE || DeviceInfo->DeviceType == WAVE_IN_DEVICE_TYPE) + else if (DeviceInfo->DeviceType == WAVE_OUT_DEVICE_TYPE || DeviceInfo->DeviceType == WAVE_IN_DEVICE_TYPE) { - return WdmAudControlOpenWave(DeviceObject, Irp, DeviceInfo, ClientInfo); + Status = WdmAudControlOpenWave(DeviceObject, Irp, DeviceInfo, ClientInfo); } - - if (DeviceInfo->DeviceType == MIDI_OUT_DEVICE_TYPE || DeviceInfo->DeviceType == MIDI_IN_DEVICE_TYPE) + else if (DeviceInfo->DeviceType == MIDI_OUT_DEVICE_TYPE || DeviceInfo->DeviceType == MIDI_IN_DEVICE_TYPE) { - return WdmAudControlOpenMidi(DeviceObject, Irp, DeviceInfo, ClientInfo); + Status = WdmAudControlOpenMidi(DeviceObject, Irp, DeviceInfo, ClientInfo); } + if (NT_SUCCESS(Status) && DeviceInfo->DeviceType != MIXER_DEVICE_TYPE) + { + /* Start audio device after opening */ + WdmAudSetDeviceState(DeviceObject, Irp, DeviceInfo, KSSTATE_RUN, FALSE); + } - return SetIrpIoStatus(Irp, STATUS_NOT_SUPPORTED, sizeof(WDMAUD_DEVICE_INFO)); + return SetIrpIoStatus(Irp, Status, sizeof(WDMAUD_DEVICE_INFO)); } NTSTATUS @@ -72,48 +106,12 @@ WdmAudControlDeviceType( /* store result count */ - DeviceInfo->DeviceCount = Result; + DeviceInfo->DeviceIndex = Result; - DPRINT("WdmAudControlDeviceType Devices %u\n", DeviceInfo->DeviceCount); + DPRINT("WdmAudControlDeviceType Devices %u\n", DeviceInfo->DeviceIndex); return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO)); } -NTSTATUS -WdmAudControlDeviceState( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp, - IN PWDMAUD_DEVICE_INFO DeviceInfo, - IN PWDMAUD_CLIENT ClientInfo) -{ - KSPROPERTY Property; - KSSTATE State; - NTSTATUS Status; - ULONG BytesReturned; - PFILE_OBJECT FileObject; - - DPRINT("WdmAudControlDeviceState\n"); - - Status = ObReferenceObjectByHandle(DeviceInfo->hDevice, GENERIC_READ | GENERIC_WRITE, *IoFileObjectType, KernelMode, (PVOID*)&FileObject, NULL); - if (!NT_SUCCESS(Status)) - { - DPRINT1("Error: invalid device handle provided %p Type %x\n", DeviceInfo->hDevice, DeviceInfo->DeviceType); - return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, 0); - } - - Property.Set = KSPROPSETID_Connection; - Property.Id = KSPROPERTY_CONNECTION_STATE; - Property.Flags = KSPROPERTY_TYPE_SET; - - State = DeviceInfo->u.State; - - Status = KsSynchronousIoControlDevice(FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)&State, sizeof(KSSTATE), &BytesReturned); - - ObDereferenceObject(FileObject); - - DPRINT("WdmAudControlDeviceState Status %x\n", Status); - return SetIrpIoStatus(Irp, Status, sizeof(WDMAUD_DEVICE_INFO)); -} - NTSTATUS WdmAudCapabilities( IN PDEVICE_OBJECT DeviceObject, @@ -130,15 +128,15 @@ WdmAudCapabilities( if (DeviceInfo->DeviceType == MIXER_DEVICE_TYPE) { - Status = WdmAudMixerCapabilities(DeviceObject, DeviceInfo, ClientInfo, DeviceExtension); + Status = WdmAudMixerCapabilities(DeviceObject, Irp, DeviceInfo, ClientInfo, DeviceExtension); } else if (DeviceInfo->DeviceType == WAVE_IN_DEVICE_TYPE || DeviceInfo->DeviceType == WAVE_OUT_DEVICE_TYPE) { - Status = WdmAudWaveCapabilities(DeviceObject, DeviceInfo, ClientInfo, DeviceExtension); + Status = WdmAudWaveCapabilities(DeviceObject, Irp, DeviceInfo, ClientInfo, DeviceExtension); } else if (DeviceInfo->DeviceType == MIDI_IN_DEVICE_TYPE || DeviceInfo->DeviceType == MIDI_OUT_DEVICE_TYPE) { - Status = WdmAudMidiCapabilities(DeviceObject, DeviceInfo, ClientInfo, DeviceExtension); + Status = WdmAudMidiCapabilities(DeviceObject, Irp, DeviceInfo, ClientInfo, DeviceExtension); } return SetIrpIoStatus(Irp, Status, sizeof(WDMAUD_DEVICE_INFO)); @@ -154,15 +152,20 @@ WdmAudIoctlClose( { ULONG Index; + if (DeviceInfo->DeviceType != MIXER_DEVICE_TYPE) + { + /* Stop audio device before closing */ + WdmAudSetDeviceState(DeviceObject, Irp, DeviceInfo, KSSTATE_STOP, FALSE); + } + for(Index = 0; Index < ClientInfo->NumPins; Index++) { if (ClientInfo->hPins[Index].Handle == DeviceInfo->hDevice && ClientInfo->hPins[Index].Type != MIXER_DEVICE_TYPE) { DPRINT1("Closing device %p\n", DeviceInfo->hDevice); - ZwClose(DeviceInfo->hDevice); - ClientInfo->hPins[Index].Handle = NULL; - SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO)); - return STATUS_SUCCESS; + ClosePin(ClientInfo, Index); + DeviceInfo->hDevice = NULL; + return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO)); } else if (ClientInfo->hPins[Index].Handle == DeviceInfo->hDevice && ClientInfo->hPins[Index].Type == MIXER_DEVICE_TYPE) { @@ -171,98 +174,48 @@ WdmAudIoctlClose( } } - SetIrpIoStatus(Irp, STATUS_INVALID_PARAMETER, sizeof(WDMAUD_DEVICE_INFO)); - return STATUS_INVALID_PARAMETER; + return SetIrpIoStatus(Irp, STATUS_INVALID_PARAMETER, sizeof(WDMAUD_DEVICE_INFO)); } NTSTATUS -NTAPI -WdmAudFrameSize( +WdmAudSetDeviceState( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PWDMAUD_DEVICE_INFO DeviceInfo, - IN PWDMAUD_CLIENT ClientInfo) + IN KSSTATE State, + IN BOOL CompleteIrp) // Avoids multiple IRP complete requests + // when calling internally from wdmaud. { - PFILE_OBJECT FileObject; + NTSTATUS Status; KSPROPERTY Property; ULONG BytesReturned; - KSALLOCATOR_FRAMING Framing; - NTSTATUS Status; + PFILE_OBJECT FileObject; + + DPRINT("WdmAudControlDeviceState\n"); - /* Get sysaudio pin file object */ - Status = ObReferenceObjectByHandle(DeviceInfo->hDevice, GENERIC_WRITE, *IoFileObjectType, KernelMode, (PVOID*)&FileObject, NULL); + Status = ObReferenceObjectByHandle(DeviceInfo->hDevice, GENERIC_READ | GENERIC_WRITE, *IoFileObjectType, KernelMode, (PVOID*)&FileObject, NULL); if (!NT_SUCCESS(Status)) { - DPRINT1("Invalid buffer handle %p\n", DeviceInfo->hDevice); - return SetIrpIoStatus(Irp, Status, 0); + DPRINT1("Error: invalid device handle provided %p Type %x\n", DeviceInfo->hDevice, DeviceInfo->DeviceType); + return CompleteIrp ? SetIrpIoStatus(Irp, Status, 0) : Status; } - /* Setup get framing request */ - Property.Id = KSPROPERTY_CONNECTION_ALLOCATORFRAMING; - Property.Flags = KSPROPERTY_TYPE_GET; Property.Set = KSPROPSETID_Connection; + Property.Id = KSPROPERTY_CONNECTION_STATE; + Property.Flags = KSPROPERTY_TYPE_SET; - Status = KsSynchronousIoControlDevice(FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)&Framing, sizeof(KSALLOCATOR_FRAMING), &BytesReturned); - /* Did we succeed */ - if (NT_SUCCESS(Status)) + Status = KsSynchronousIoControlDevice(FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)&State, sizeof(KSSTATE), &BytesReturned); + if (!NT_SUCCESS(Status)) { - /* Store framesize */ - DeviceInfo->u.FrameSize = Framing.FrameSize; + DPRINT1("%x failed with status 0x%lx\n", State, Status); + ObDereferenceObject(FileObject); + return CompleteIrp ? SetIrpIoStatus(Irp, Status, 0) : Status; } - /* Release file object */ ObDereferenceObject(FileObject); - return SetIrpIoStatus(Irp, Status, sizeof(WDMAUD_DEVICE_INFO)); - -} - -NTSTATUS -NTAPI -WdmAudGetDeviceInterface( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp, - IN PWDMAUD_DEVICE_INFO DeviceInfo) -{ - NTSTATUS Status; - LPWSTR Device; - ULONG Size, Length; - - /* get device interface string input length */ - Size = DeviceInfo->u.Interface.DeviceInterfaceStringSize; - - /* get mixer info */ - Status = WdmAudGetPnpNameByIndexAndType(DeviceInfo->DeviceIndex, DeviceInfo->DeviceType, &Device); - - /* check for success */ - if (!NT_SUCCESS(Status)) - { - /* invalid device id */ - return SetIrpIoStatus(Irp, Status, sizeof(WDMAUD_DEVICE_INFO)); - } - - /* calculate length */ - Length = (wcslen(Device)+1) * sizeof(WCHAR); - - if (!Size) - { - /* store device interface size */ - DeviceInfo->u.Interface.DeviceInterfaceStringSize = Length; - } - else if (Size < Length) - { - /* buffer too small */ - DeviceInfo->u.Interface.DeviceInterfaceStringSize = Length; - return SetIrpIoStatus(Irp, STATUS_BUFFER_OVERFLOW, sizeof(WDMAUD_DEVICE_INFO)); - } - else - { - //FIXME SEH - RtlMoveMemory(DeviceInfo->u.Interface.DeviceInterfaceString, Device, Length); - } - - FreeItem(Device); - return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO)); + DPRINT("WdmAudControlDeviceState Status 0x%lx BytesReturned %lu\n", Status, BytesReturned); + return CompleteIrp ? SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO)) : STATUS_SUCCESS; } NTSTATUS @@ -270,10 +223,14 @@ NTAPI WdmAudResetStream( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, - IN PWDMAUD_DEVICE_INFO DeviceInfo) + IN PWDMAUD_DEVICE_INFO DeviceInfo, + IN BOOL CompleteIrp) // Avoids multiple IRP complete requests + // when calling internally from wdmaud. { - KSRESET ResetStream; + KSSTATE State; NTSTATUS Status; + KSRESET ResetStream; + KSPROPERTY Property; ULONG BytesReturned; PFILE_OBJECT FileObject; @@ -283,103 +240,55 @@ WdmAudResetStream( if (!NT_SUCCESS(Status)) { DPRINT1("Error: invalid device handle provided %p Type %x\n", DeviceInfo->hDevice, DeviceInfo->DeviceType); - return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, 0); + return CompleteIrp ? SetIrpIoStatus(Irp, Status, 0) : Status; } - ResetStream = DeviceInfo->u.ResetStream; - ASSERT(ResetStream == KSRESET_BEGIN || ResetStream == KSRESET_END); - - Status = KsSynchronousIoControlDevice(FileObject, KernelMode, IOCTL_KS_RESET_STATE, (PVOID)&ResetStream, sizeof(KSRESET), NULL, 0, &BytesReturned); - - ObDereferenceObject(FileObject); - - DPRINT("WdmAudResetStream Status %x\n", Status); - return SetIrpIoStatus(Irp, Status, sizeof(WDMAUD_DEVICE_INFO)); -} - -NTSTATUS -NTAPI -WdmAudDeviceControl( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp) -{ - PIO_STACK_LOCATION IoStack; - PWDMAUD_DEVICE_INFO DeviceInfo; - PWDMAUD_CLIENT ClientInfo; - - IoStack = IoGetCurrentIrpStackLocation(Irp); - - DPRINT("WdmAudDeviceControl entered\n"); - - if (IoStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(WDMAUD_DEVICE_INFO)) - { - /* invalid parameter */ - DPRINT1("Input buffer too small size %u expected %u\n", IoStack->Parameters.DeviceIoControl.InputBufferLength, sizeof(WDMAUD_DEVICE_INFO)); - return SetIrpIoStatus(Irp, STATUS_INVALID_PARAMETER, 0); - } + Property.Set = KSPROPSETID_Connection; + Property.Id = KSPROPERTY_CONNECTION_STATE; + Property.Flags = KSPROPERTY_TYPE_SET; - DeviceInfo = (PWDMAUD_DEVICE_INFO)Irp->AssociatedIrp.SystemBuffer; + State = DeviceInfo->DeviceType == WAVE_OUT_DEVICE_TYPE ? KSSTATE_PAUSE : KSSTATE_STOP; - if (DeviceInfo->DeviceType < MIN_SOUND_DEVICE_TYPE || DeviceInfo->DeviceType > MAX_SOUND_DEVICE_TYPE) + Status = KsSynchronousIoControlDevice(FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)&State, sizeof(KSSTATE), &BytesReturned); + if (!NT_SUCCESS(Status)) { - /* invalid parameter */ - DPRINT1("Error: device type not set\n"); - return SetIrpIoStatus(Irp, STATUS_INVALID_PARAMETER, 0); + DPRINT1("%ls failed with status 0x%lx\n", + DeviceInfo->DeviceType == WAVE_OUT_DEVICE_TYPE ? + L"KSSTATE_PAUSE" : L"KSSTATE_STOP", + Status); + ObDereferenceObject(FileObject); + return CompleteIrp ? SetIrpIoStatus(Irp, Status, 0) : Status; } - if (!IoStack->FileObject || !IoStack->FileObject->FsContext) + if (DeviceInfo->DeviceType == WAVE_OUT_DEVICE_TYPE) { - /* file object parameter */ - DPRINT1("Error: file object is not attached\n"); - return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, 0); + ResetStream = KSRESET_BEGIN; + Status = KsSynchronousIoControlDevice(FileObject, KernelMode, IOCTL_KS_RESET_STATE, (PVOID)&ResetStream, sizeof(KSRESET), NULL, 0, &BytesReturned); + if (!NT_SUCCESS(Status)) + { + DPRINT1("KSRESET_BEGIN failed with status 0x%lx\n", Status); + ObDereferenceObject(FileObject); + return CompleteIrp ? SetIrpIoStatus(Irp, Status, 0) : Status; + } + ResetStream = KSRESET_END; + Status = KsSynchronousIoControlDevice(FileObject, KernelMode, IOCTL_KS_RESET_STATE, (PVOID)&ResetStream, sizeof(KSRESET), NULL, 0, &BytesReturned); + if (!NT_SUCCESS(Status)) + { + DPRINT1("KSRESET_END failed with status 0x%lx\n", Status); + ObDereferenceObject(FileObject); + return CompleteIrp ? SetIrpIoStatus(Irp, Status, 0) : Status; + } } - ClientInfo = (PWDMAUD_CLIENT)IoStack->FileObject->FsContext; - - DPRINT("WdmAudDeviceControl entered\n"); - switch(IoStack->Parameters.DeviceIoControl.IoControlCode) - { - case IOCTL_OPEN_WDMAUD: - return WdmAudControlOpen(DeviceObject, Irp, DeviceInfo, ClientInfo); - case IOCTL_GETNUMDEVS_TYPE: - return WdmAudControlDeviceType(DeviceObject, Irp, DeviceInfo, ClientInfo); - case IOCTL_SETDEVICE_STATE: - return WdmAudControlDeviceState(DeviceObject, Irp, DeviceInfo, ClientInfo); - case IOCTL_GETCAPABILITIES: - return WdmAudCapabilities(DeviceObject, Irp, DeviceInfo, ClientInfo); - case IOCTL_CLOSE_WDMAUD: - return WdmAudIoctlClose(DeviceObject, Irp, DeviceInfo, ClientInfo); - case IOCTL_GETFRAMESIZE: - return WdmAudFrameSize(DeviceObject, Irp, DeviceInfo, ClientInfo); - case IOCTL_GETLINEINFO: - return WdmAudGetLineInfo(DeviceObject, Irp, DeviceInfo, ClientInfo); - case IOCTL_GETLINECONTROLS: - return WdmAudGetLineControls(DeviceObject, Irp, DeviceInfo, ClientInfo); - case IOCTL_SETCONTROLDETAILS: - return WdmAudSetControlDetails(DeviceObject, Irp, DeviceInfo, ClientInfo); - case IOCTL_GETCONTROLDETAILS: - return WdmAudGetControlDetails(DeviceObject, Irp, DeviceInfo, ClientInfo); - case IOCTL_QUERYDEVICEINTERFACESTRING: - return WdmAudGetDeviceInterface(DeviceObject, Irp, DeviceInfo); - case IOCTL_GET_MIXER_EVENT: - return WdmAudGetMixerEvent(DeviceObject, Irp, DeviceInfo, ClientInfo); - case IOCTL_RESET_STREAM: - return WdmAudResetStream(DeviceObject, Irp, DeviceInfo); - case IOCTL_GETPOS: - case IOCTL_GETDEVID: - case IOCTL_GETVOLUME: - case IOCTL_SETVOLUME: - - DPRINT1("Unhandled %x\n", IoStack->Parameters.DeviceIoControl.IoControlCode); - break; - } + ObDereferenceObject(FileObject); - return SetIrpIoStatus(Irp, STATUS_NOT_IMPLEMENTED, 0); + DPRINT("WdmAudResetStream Status 0x%lx BytesReturned %lu\n", Status, BytesReturned); + return CompleteIrp ? SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO)) : STATUS_SUCCESS; } NTSTATUS NTAPI -IoCompletion ( +IoCompletion( PDEVICE_OBJECT DeviceObject, PIRP Irp, PVOID Ctx) @@ -388,31 +297,29 @@ IoCompletion ( PMDL Mdl, NextMdl; PWDMAUD_COMPLETION_CONTEXT Context = (PWDMAUD_COMPLETION_CONTEXT)Ctx; - /* get stream header */ - Header = (PKSSTREAM_HEADER)Irp->AssociatedIrp.SystemBuffer; + /* Get stream header */ + Header = (PKSSTREAM_HEADER)Irp->UserBuffer; - /* sanity check */ + /* Sanity check */ ASSERT(Header); - /* time to free all allocated mdls */ + /* Time to free all allocated mdls */ Mdl = Irp->MdlAddress; while(Mdl) { - /* get next mdl */ + /* Get next mdl */ NextMdl = Mdl->Next; - /* unlock pages */ + /* Unlock pages */ MmUnlockPages(Mdl); - /* grab next mdl */ + /* Grab next mdl */ Mdl = NextMdl; } - //IoFreeMdl(Mdl); - /* clear mdl list */ - Irp->MdlAddress = Context->Mdl; - + /* Clear mdl list */ + Irp->MdlAddress = Context->Mdl; DPRINT("IoCompletion Irp %p IoStatus %lx Information %lx\n", Irp, Irp->IoStatus.Status, Irp->IoStatus.Information); @@ -422,12 +329,6 @@ IoCompletion ( Irp->IoStatus.Information = 0; } - /* dereference file object */ - ObDereferenceObject(Context->FileObject); - - /* free context */ - FreeItem(Context); - return STATUS_SUCCESS; } @@ -437,58 +338,101 @@ WdmAudReadWrite( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { - NTSTATUS Status; + PWDMAUD_COMPLETION_CONTEXT Context; PWDMAUD_DEVICE_INFO DeviceInfo; + PWDMAUD_CLIENT ClientInfo; + PKSSTREAM_HEADER StreamHeader; PFILE_OBJECT FileObject; PIO_STACK_LOCATION IoStack; + PWAVEHDR WaveHeader; + NTSTATUS Status; ULONG Length; + ULONG PinId; PMDL Mdl; - BOOLEAN Read = TRUE; - PWDMAUD_COMPLETION_CONTEXT Context; - /* allocate completion context */ - Context = AllocateItem(NonPagedPool, sizeof(WDMAUD_COMPLETION_CONTEXT)); + /* get device info */ + DeviceInfo = (PWDMAUD_DEVICE_INFO)Irp->AssociatedIrp.SystemBuffer; + ASSERT(DeviceInfo); - if (!Context) + /* Get wave header passed by the caller */ + WaveHeader = (PWAVEHDR)DeviceInfo->Buffer; + ASSERT(WaveHeader); + + /* get current irp stack location */ + IoStack = IoGetCurrentIrpStackLocation(Irp); + ASSERT(IoStack->FileObject); + + /* get client context struct */ + ClientInfo = (PWDMAUD_CLIENT)IoStack->FileObject->FsContext; + ASSERT(ClientInfo); + + /* get active pin */ + PinId = GetActivePin(ClientInfo); + ASSERT(PinId != MAXULONG); + + /* get pin file object */ + FileObject = ClientInfo->hPins[PinId].FileObject; + ASSERT(FileObject); + + /* allocate stream header */ + StreamHeader = AllocateItem(NonPagedPool, sizeof(KSSTREAM_HEADER)); + if (!StreamHeader) { /* not enough memory */ - Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; - IoCompleteRequest(Irp, IO_NO_INCREMENT); - - /* done */ return STATUS_INSUFFICIENT_RESOURCES; } - /* get current irp stack location */ - IoStack = IoGetCurrentIrpStackLocation(Irp); + StreamHeader->Size = sizeof(KSSTREAM_HEADER); + StreamHeader->PresentationTime.Numerator = 1; + StreamHeader->PresentationTime.Denominator = 1; + StreamHeader->Data = WaveHeader->lpData; + StreamHeader->FrameExtent = WaveHeader->dwBufferLength; + + if (DeviceInfo->DeviceType == WAVE_OUT_DEVICE_TYPE) + { + StreamHeader->DataUsed = WaveHeader->dwBufferLength; + } + else + { + StreamHeader->DataUsed = 0; + } - /* store the input buffer in UserBuffer - as KsProbeStreamIrp operates on IRP_MJ_DEVICE_CONTROL */ - Irp->UserBuffer = MmGetMdlVirtualAddress(Irp->MdlAddress); + /* store the input buffer in SystemBuffer - as KsProbeStreamIrp operates on IRP_MJ_DEVICE_CONTROL */ + Irp->AssociatedIrp.SystemBuffer = StreamHeader; /* sanity check */ ASSERT(Irp->UserBuffer); /* get the length of the request length */ - Length = IoStack->Parameters.Write.Length; + Length = StreamHeader->Size; /* store outputbuffer length */ IoStack->Parameters.DeviceIoControl.OutputBufferLength = Length; + /* allocate completion context */ + Context = AllocateItem(NonPagedPool, sizeof(WDMAUD_COMPLETION_CONTEXT)); + + if (!Context) + { + /* not enough memory */ + FreeItem(StreamHeader); + return STATUS_INSUFFICIENT_RESOURCES; + } + /* setup context */ - Context->Length = Length; - Context->Function = (IoStack->MajorFunction == IRP_MJ_WRITE ? IOCTL_KS_WRITE_STREAM : IOCTL_KS_READ_STREAM); + Context->Length = sizeof(KSSTREAM_HEADER); + Context->Function = DeviceInfo->DeviceType == WAVE_IN_DEVICE_TYPE ? IOCTL_KS_READ_STREAM : IOCTL_KS_WRITE_STREAM; Context->Mdl = Irp->MdlAddress; /* store mdl address */ Mdl = Irp->MdlAddress; - /* remove mdladdress as KsProbeStreamIrp will interpret it as an already probed audio buffer */ + /* clear mdl address */ Irp->MdlAddress = NULL; - if (IoStack->MajorFunction == IRP_MJ_WRITE) + if (DeviceInfo->DeviceType == WAVE_OUT_DEVICE_TYPE) { /* probe the write stream irp */ - Read = FALSE; Status = KsProbeStreamIrp(Irp, KSPROBE_STREAMWRITE | KSPROBE_ALLOCATEMDL | KSPROBE_PROBEANDLOCK, Length); } else @@ -499,23 +443,10 @@ WdmAudReadWrite( if (!NT_SUCCESS(Status)) { - DPRINT1("KsProbeStreamIrp failed with Status %x Cancel %u\n", Status, Irp->Cancel); - Irp->MdlAddress = Mdl; - FreeItem(Context); - return SetIrpIoStatus(Irp, Status, 0); - } - - /* get device info */ - DeviceInfo = (PWDMAUD_DEVICE_INFO)Irp->AssociatedIrp.SystemBuffer; - ASSERT(DeviceInfo); - - /* now get sysaudio file object */ - Status = ObReferenceObjectByHandle(DeviceInfo->hDevice, GENERIC_WRITE, *IoFileObjectType, KernelMode, (PVOID*)&FileObject, NULL); - if (!NT_SUCCESS(Status)) - { - DPRINT1("Invalid pin handle %p\n", DeviceInfo->hDevice); + DPRINT1("KsProbeStreamIrp failed with Status 0x%lx Cancel %u\n", Status, Irp->Cancel); Irp->MdlAddress = Mdl; FreeItem(Context); + FreeItem(StreamHeader); return SetIrpIoStatus(Irp, Status, 0); } @@ -530,14 +461,101 @@ WdmAudReadWrite( /* prepare stack location */ IoStack->FileObject = FileObject; - IoStack->Parameters.Write.Length = Length; - IoStack->MajorFunction = IRP_MJ_WRITE; - IoStack->Parameters.DeviceIoControl.IoControlCode = (Read ? IOCTL_KS_READ_STREAM : IOCTL_KS_WRITE_STREAM); + IoStack->MajorFunction = IRP_MJ_DEVICE_CONTROL; + IoStack->Parameters.DeviceIoControl.OutputBufferLength = Length; + IoStack->Parameters.DeviceIoControl.IoControlCode = (DeviceInfo->DeviceType == WAVE_IN_DEVICE_TYPE) ? IOCTL_KS_READ_STREAM : IOCTL_KS_WRITE_STREAM; IoSetCompletionRoutine(Irp, IoCompletion, (PVOID)Context, TRUE, TRUE, TRUE); - /* mark irp as pending */ -// IoMarkIrpPending(Irp); /* call the driver */ - Status = IoCallDriver(IoGetRelatedDeviceObject(FileObject), Irp); - return Status; + IoCallDriver(IoGetRelatedDeviceObject(FileObject), Irp); + + /* done */ + return STATUS_PENDING; +} + +NTSTATUS +NTAPI +WdmAudDeviceControl( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) +{ + PIO_STACK_LOCATION IoStack; + PWDMAUD_DEVICE_INFO DeviceInfo; + PWDMAUD_CLIENT ClientInfo; + + IoStack = IoGetCurrentIrpStackLocation(Irp); + + DPRINT("WdmAudDeviceControl entered\n"); + DPRINT("IOCTL 0x%lx\n", IoStack->Parameters.DeviceIoControl.IoControlCode); + + DeviceInfo = (PWDMAUD_DEVICE_INFO)Irp->AssociatedIrp.SystemBuffer; + if (DeviceInfo->DeviceType < MIN_SOUND_DEVICE_TYPE || DeviceInfo->DeviceType > MAX_SOUND_DEVICE_TYPE) + { + /* invalid parameter */ + DPRINT1("Error: device type not set\n"); + return SetIrpIoStatus(Irp, STATUS_INVALID_PARAMETER, 0); + } + + if (!IoStack->FileObject || !IoStack->FileObject->FsContext) + { + /* file object parameter */ + DPRINT1("Error: file object is not attached\n"); + return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, 0); + } + ClientInfo = (PWDMAUD_CLIENT)IoStack->FileObject->FsContext; + + switch(IoStack->Parameters.DeviceIoControl.IoControlCode) + { + case IOCTL_INIT_WDMAUD: + return WdmAudControlInitialize(DeviceObject, Irp); + case IOCTL_EXIT_WDMAUD: + /* No op */ + return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO)); + case IOCTL_OPEN_WDMAUD: + case IOCTL_OPEN_MIXER: + return WdmAudControlOpen(DeviceObject, Irp, DeviceInfo, ClientInfo); + case IOCTL_GETNUMDEVS_TYPE: + return WdmAudControlDeviceType(DeviceObject, Irp, DeviceInfo, ClientInfo); + case IOCTL_GETCAPABILITIES: + return WdmAudCapabilities(DeviceObject, Irp, DeviceInfo, ClientInfo); + case IOCTL_CLOSE_WDMAUD: + return WdmAudIoctlClose(DeviceObject, Irp, DeviceInfo, ClientInfo); + case IOCTL_GET_MIXER_EVENT: + return WdmAudGetMixerEvent(DeviceObject, Irp, DeviceInfo, ClientInfo); + case IOCTL_GETLINEINFO: + return WdmAudGetLineInfo(DeviceObject, Irp, DeviceInfo, ClientInfo); + case IOCTL_GETLINECONTROLS: + return WdmAudGetLineControls(DeviceObject, Irp, DeviceInfo, ClientInfo); + case IOCTL_SETCONTROLDETAILS: + return WdmAudSetControlDetails(DeviceObject, Irp, DeviceInfo, ClientInfo); + case IOCTL_GETCONTROLDETAILS: + return WdmAudGetControlDetails(DeviceObject, Irp, DeviceInfo, ClientInfo); + case IOCTL_RESET_CAPTURE: + return WdmAudSetDeviceState(DeviceObject, Irp, DeviceInfo, KSSTATE_STOP, TRUE); + case IOCTL_RESET_PLAYBACK: + return WdmAudResetStream(DeviceObject, Irp, DeviceInfo, TRUE); + case IOCTL_GETINPOS: + case IOCTL_GETOUTPOS: + return WdmAudGetPosition(DeviceObject, Irp, DeviceInfo); + case IOCTL_PAUSE_CAPTURE: + return WdmAudSetDeviceState(DeviceObject, Irp, DeviceInfo, KSSTATE_STOP, TRUE); + case IOCTL_PAUSE_PLAYBACK: + return WdmAudSetDeviceState(DeviceObject, Irp, DeviceInfo, KSSTATE_PAUSE, TRUE); + case IOCTL_START_CAPTURE: + case IOCTL_START_PLAYBACK: + return WdmAudSetDeviceState(DeviceObject, Irp, DeviceInfo, KSSTATE_RUN, TRUE); + case IOCTL_READDATA: + case IOCTL_WRITEDATA: + return WdmAudReadWrite(DeviceObject, Irp); + case IOCTL_ADD_DEVNODE: + case IOCTL_REMOVE_DEVNODE: + case IOCTL_GETVOLUME: + case IOCTL_SETVOLUME: + + default: + DPRINT1("Unhandled 0x%x\n", IoStack->Parameters.DeviceIoControl.IoControlCode); + break; + } + + return SetIrpIoStatus(Irp, STATUS_NOT_IMPLEMENTED, 0); } diff --git a/drivers/wdm/audio/legacy/wdmaud/deviface.c b/drivers/wdm/audio/legacy/wdmaud/deviface.c index 8fafcfd8257a7..f7d6be6ade7a9 100644 --- a/drivers/wdm/audio/legacy/wdmaud/deviface.c +++ b/drivers/wdm/audio/legacy/wdmaud/deviface.c @@ -9,9 +9,10 @@ #include "wdmaud.h" -#define NDEBUG +#define YDEBUG #include + NTSTATUS WdmAudOpenSysAudioDevice( IN LPWSTR DeviceName, @@ -39,147 +40,86 @@ WdmAudOpenSysAudioDevice( CreateFileTypeNone, NULL, IO_NO_PARAMETER_CHECKING | IO_FORCE_ACCESS_CHECK); - + DPRINT("IoCreateFile status 0x%lx\n", Status); return Status; } NTSTATUS -NTAPI -DeviceInterfaceChangeCallback( - IN PVOID NotificationStructure, - IN PVOID Context) +WdmAudOpenSysAudioDevices( + IN PWDMAUD_DEVICE_EXTENSION DeviceExtension) { - DEVICE_INTERFACE_CHANGE_NOTIFICATION * Event = (DEVICE_INTERFACE_CHANGE_NOTIFICATION*)NotificationStructure; - - DPRINT1("DeviceInterfaceChangeCallback called %p\n", Event); - DbgBreakPoint(); - return STATUS_SUCCESS; -} + NTSTATUS Status = STATUS_SUCCESS; + LPWSTR SymbolicLinkList, SymbolicLink; + HANDLE hSysAudio; + PFILE_OBJECT FileObject; -NTSTATUS -WdmAudOpenSysAudioDeviceInterfaces( - IN PWDMAUD_DEVICE_EXTENSION DeviceExtension, - IN LPWSTR SymbolicLinkList) -{ - SYSAUDIO_ENTRY * Entry; - ULONG Length; + Status = IoGetDeviceInterfaces(&KSCATEGORY_SYSAUDIO, + NULL, + 0, + &SymbolicLinkList); - DPRINT1("WdmAudOpenSysAudioDeviceInterfaces called\n"); + if (!NT_SUCCESS(Status)) + { + return Status; + } - while(*SymbolicLinkList) + for (SymbolicLink = SymbolicLinkList; + *SymbolicLink != UNICODE_NULL; + SymbolicLink += wcslen(SymbolicLink) + 1) { - Length = wcslen(SymbolicLinkList) + 1; - Entry = (SYSAUDIO_ENTRY*)AllocateItem(NonPagedPool, sizeof(SYSAUDIO_ENTRY) + Length * sizeof(WCHAR)); - if (!Entry) + DPRINT("Opening device %S\n", SymbolicLink); + Status = WdmAudOpenSysAudioDevice(SymbolicLink, &hSysAudio); + if (NT_SUCCESS(Status)) { - return STATUS_INSUFFICIENT_RESOURCES; + DPRINT("Successfully opened %S, handle %p\n", SymbolicLink, hSysAudio); + break; } + } - Entry->SymbolicLink.Length = Length * sizeof(WCHAR); - Entry->SymbolicLink.MaximumLength = Length * sizeof(WCHAR); - Entry->SymbolicLink.Buffer = (LPWSTR) (Entry + 1); - wcscpy(Entry->SymbolicLink.Buffer, SymbolicLinkList); - - InsertTailList(&DeviceExtension->SysAudioDeviceList, &Entry->Entry); + if (!hSysAudio) + { + DPRINT1("Failed to find sysaudio devices 0x%lx\n", Status); + FreeItem(SymbolicLinkList); + return Status; + } - DeviceExtension->NumSysAudioDevices++; - SymbolicLinkList += Length; + /* get the file object */ + Status = ObReferenceObjectByHandle(hSysAudio, + FILE_READ_DATA | FILE_WRITE_DATA, + *IoFileObjectType, + KernelMode, + (PVOID*)&FileObject, + NULL); + if (!NT_SUCCESS(Status)) + { + DPRINT1("Failed to reference FileObject 0x%lx\n", Status); + FreeItem(SymbolicLinkList); + return Status; } + + DeviceExtension->NumSysAudioDevices++; + DeviceExtension->hSysAudio = hSysAudio; + DeviceExtension->FileObject = FileObject; + return STATUS_SUCCESS; } - NTSTATUS -WdmAudOpenSysAudioDevices( - IN PDEVICE_OBJECT DeviceObject, - IN PWDMAUD_DEVICE_EXTENSION DeviceExtension) +GetSysAudioDeviceInterface( + OUT LPWSTR* SymbolicLinkList) { - NTSTATUS Status = STATUS_SUCCESS; - LPWSTR SymbolicLinkList; - SYSAUDIO_ENTRY * Entry; - ULONG Length; - HANDLE hSysAudio; - PFILE_OBJECT FileObject; - UNICODE_STRING DeviceName = RTL_CONSTANT_STRING(L"\\Device\\sysaudio\\GLOBAL"); - - if (DeviceExtension->DeviceInterfaceSupport) - { - Status = IoGetDeviceInterfaces(&KSCATEGORY_SYSAUDIO, - NULL, - 0, - &SymbolicLinkList); - - if (NT_SUCCESS(Status)) - { - WdmAudOpenSysAudioDeviceInterfaces(DeviceExtension, SymbolicLinkList); - FreeItem(SymbolicLinkList); - } - + NTSTATUS Status; - Status = IoRegisterPlugPlayNotification(EventCategoryDeviceInterfaceChange, - PNPNOTIFY_DEVICE_INTERFACE_INCLUDE_EXISTING_INTERFACES, - (PVOID)&KSCATEGORY_SYSAUDIO, - DeviceObject->DriverObject, - DeviceInterfaceChangeCallback, - (PVOID)DeviceExtension, - &DeviceExtension->SysAudioNotification); - } - else + /* Get SysAudio device interface */ + Status = IoGetDeviceInterfaces(&KSCATEGORY_SYSAUDIO, NULL, 0, SymbolicLinkList); + if (!NT_SUCCESS(Status)) { - Entry = (SYSAUDIO_ENTRY*)AllocateItem(NonPagedPool, sizeof(SYSAUDIO_ENTRY)); - if (!Entry) - { - return STATUS_INSUFFICIENT_RESOURCES; - } - - - Length = wcslen(DeviceName.Buffer) + 1; - Entry->SymbolicLink.Length = 0; - Entry->SymbolicLink.MaximumLength = Length * sizeof(WCHAR); - Entry->SymbolicLink.Buffer = AllocateItem(NonPagedPool, Entry->SymbolicLink.MaximumLength); - - if (!Entry->SymbolicLink.Buffer) - { - FreeItem(Entry); - return STATUS_INSUFFICIENT_RESOURCES; - } - - Status = RtlAppendUnicodeStringToString(&Entry->SymbolicLink, &DeviceName); - - if (!NT_SUCCESS(Status)) - { - FreeItem(Entry->SymbolicLink.Buffer); - FreeItem(Entry); - return Status; - } - - DPRINT("Opening device %S\n", Entry->SymbolicLink.Buffer); - Status = WdmAudOpenSysAudioDevice(Entry->SymbolicLink.Buffer, &hSysAudio); - if (!NT_SUCCESS(Status)) - { - DPRINT1("Failed to open sysaudio %x\n", Status); - FreeItem(Entry->SymbolicLink.Buffer); - FreeItem(Entry); - return Status; - } - - InsertTailList(&DeviceExtension->SysAudioDeviceList, &Entry->Entry); - DeviceExtension->NumSysAudioDevices++; - - /* get the file object */ - Status = ObReferenceObjectByHandle(hSysAudio, FILE_READ_DATA | FILE_WRITE_DATA, *IoFileObjectType, KernelMode, (PVOID*)&FileObject, NULL); - if (!NT_SUCCESS(Status)) - { - DPRINT1("Failed to reference FileObject %x\n", Status); - ZwClose(hSysAudio); - return Status; - } - DeviceExtension = (PWDMAUD_DEVICE_EXTENSION)DeviceObject->DeviceExtension; - DeviceExtension->hSysAudio = hSysAudio; - DeviceExtension->FileObject = FileObject; + DPRINT1("IoGetDeviceInterfaces failed with 0x%lx\n", Status); + return Status; } - return Status; + DPRINT("Got SysAudio device interface %ls\n", *SymbolicLinkList); + return STATUS_SUCCESS; } NTSTATUS @@ -195,7 +135,6 @@ WdmAudRegisterDeviceInterface( { IoSetDeviceInterfaceState(&SymbolicLinkName, TRUE); RtlFreeUnicodeString(&SymbolicLinkName); - //DeviceExtension->DeviceInterfaceSupport = TRUE; return Status; } @@ -203,7 +142,7 @@ WdmAudRegisterDeviceInterface( } NTSTATUS -WdmAudOpenSysaudio( +WdmAudAllocateContext( IN PDEVICE_OBJECT DeviceObject, IN PWDMAUD_CLIENT *pClient) { @@ -219,9 +158,6 @@ WdmAudOpenSysaudio( return STATUS_UNSUCCESSFUL; } - /* sanity check */ - ASSERT(!IsListEmpty(&DeviceExtension->SysAudioDeviceList)); - /* allocate client context struct */ Client = AllocateItem(NonPagedPool, sizeof(WDMAUD_CLIENT)); diff --git a/drivers/wdm/audio/legacy/wdmaud/entry.c b/drivers/wdm/audio/legacy/wdmaud/entry.c index 158fe92a5a10a..3ccd223b0f38a 100644 --- a/drivers/wdm/audio/legacy/wdmaud/entry.c +++ b/drivers/wdm/audio/legacy/wdmaud/entry.c @@ -9,7 +9,7 @@ #include "wdmaud.h" -#define NDEBUG +#define YDEBUG #include const GUID KSCATEGORY_SYSAUDIO = {0xA7C7A5B1L, 0x5AF3, 0x11D1, {0x9C, 0xED, 0x00, 0xA0, 0x24, 0xBF, 0x04, 0x07}}; @@ -26,16 +26,15 @@ WdmAudInitWorkerRoutine( { NTSTATUS Status; PWDMAUD_DEVICE_EXTENSION DeviceExtension; - ULONG DeviceCount; + ULONG DeviceCount, DeviceIndex; /* get device extension */ DeviceExtension = (PWDMAUD_DEVICE_EXTENSION)DeviceObject->DeviceExtension; - if (DeviceExtension->FileObject == NULL) { /* find available sysaudio devices */ - Status = WdmAudOpenSysAudioDevices(DeviceObject, DeviceExtension); + Status = WdmAudOpenSysAudioDevices(DeviceExtension); if (!NT_SUCCESS(Status)) { DPRINT1("WdmAudOpenSysAudioDevices failed with %x\n", Status); @@ -43,7 +42,6 @@ WdmAudInitWorkerRoutine( } } - /* get device count */ DeviceCount = GetSysAudioDeviceCount(DeviceObject); @@ -58,6 +56,17 @@ WdmAudInitWorkerRoutine( /* store sysaudio device count */ DeviceExtension->SysAudioDeviceCount = DeviceCount; + + /* set index for all device instances */ + for (DeviceIndex = 0; DeviceIndex < DeviceCount; DeviceIndex++) + { + Status = SetSysAudioDeviceInstance(DeviceExtension, DeviceIndex); + if (!NT_SUCCESS(Status)) + { + /* failed, move to the next instance */ + continue; + } + } } /* signal completion */ @@ -133,9 +142,6 @@ WdmaudAddDevice( return Status; } - /* initialize sysaudio device list */ - InitializeListHead(&DeviceExtension->SysAudioDeviceList); - /* initialize client context device list */ InitializeListHead(&DeviceExtension->WdmAudClientList); @@ -165,7 +171,7 @@ WdmaudAddDevice( /* start the timer */ IoStartTimer(DeviceObject); - DeviceObject->Flags |= DO_DIRECT_IO | DO_POWER_PAGABLE; + DeviceObject->Flags |= DO_BUFFERED_IO | DO_POWER_PAGABLE; DeviceObject->Flags &= ~ DO_DEVICE_INITIALIZING; return STATUS_SUCCESS; @@ -229,17 +235,16 @@ WdmAudCreate( WdmAudInitWorkerRoutine(DeviceObject, NULL); } - - Status = WdmAudOpenSysaudio(DeviceObject, &pClient); + Status = WdmAudAllocateContext(DeviceObject, &pClient); if (!NT_SUCCESS(Status)) { - DPRINT1("Failed to open sysaudio!\n"); + DPRINT1("Failed to allocate context, status 0x%lx!\n", Status); /* complete and forget */ - Irp->IoStatus.Status = STATUS_UNSUCCESSFUL; + Irp->IoStatus.Status = Status; IoCompleteRequest(Irp, IO_NO_INCREMENT); /* done */ - return STATUS_UNSUCCESSFUL; + return Status; } IoStack = IoGetCurrentIrpStackLocation(Irp); @@ -324,7 +329,7 @@ WdmAudCleanup( if (pClient->hPins[Index].Handle && pClient->hPins[Index].Type != MIXER_DEVICE_TYPE) { /* found an still open audio pin */ - ZwClose(pClient->hPins[Index].Handle); + ClosePin(pClient, Index); } WdmAudCloseAllMixers(DeviceObject, pClient, Index); } diff --git a/drivers/wdm/audio/legacy/wdmaud/interface.h b/drivers/wdm/audio/legacy/wdmaud/interface.h index a6877e3dd8c3a..62f644ae52294 100644 --- a/drivers/wdm/audio/legacy/wdmaud/interface.h +++ b/drivers/wdm/audio/legacy/wdmaud/interface.h @@ -5,110 +5,144 @@ /// /// History: 12/02/2008 Created -// These are now in sndtypes.h -/* -typedef enum +#include + +/* Fixing alignment is needed to make the struct size compatible with MS */ +#pragma pack(1) + +/* Contains device state management related stuff */ +typedef struct { - DEVICE_TYPE_NONE = 0, - DEVICE_TYPE_WAVE_OUT, - DEVICE_TYPE_WAVE_IN, - DEVICE_TYPE_MIDI_IN, - DEVICE_TYPE_MIDI_OUT, - DEVICE_TYPE_AUX_IN, - DEVICE_TYPE_AUX_OUT + DWORD unk1; + HANDLE hThread; // Verified to match Windows XP/2003, the sound thread handle. + DWORD unk2; -}AUDIO_DEVICE_TYPE; -*/ + LPWAVEHDR WaveQueue; // Verified to match Windows XP/2003, wave queue header. + LPMIDIHDR MidiQueue; // Verified to match Windows XP/2003, midi queue header. -#include + DWORD unk3; + DWORD unk4; + + HANDLE hNotifyEvent; // Verified to match Windows XP/2003, queue notification event. + HANDLE hStopEvent; // Verified to match Windows XP/2003, queue stop event. + BOOL unk5; + BOOL bReset; // Verified to match Windows XP/2003, indicates whether device is starting to be reset. + BOOL bStart; // Verified to match Windows XP/2003, indicates whether device is to be started. + BOOL bStartInThread; // Verified to match Windows XP/2003, indicates whether the sound is started in thread. + + char unk6; + char unk7; + +}WDMAUD_DEVICE_STATE, *PWDMAUD_DEVICE_STATE; + +/* Contains the main information about a sound device */ typedef struct { - KSSTREAM_HEADER Header; - SOUND_DEVICE_TYPE DeviceType; - ULONG_PTR DeviceIndex; - - HANDLE hDevice; - ULONG DeviceCount; - ULONG Flags; - - union - { - MIXERCAPSW MixCaps; - MIXERCONTROLDETAILS MixDetails; - MIXERLINECONTROLSW MixControls; - MIXERLINEW MixLine; - WAVEFORMATEX WaveFormatEx; - WAVEOUTCAPSW WaveOutCaps; - AUXCAPSW AuxCaps; - WAVEINCAPSW WaveInCaps; - MIDIINCAPSW MidiInCaps; - MIDIOUTCAPSW MidiOutCaps; - ULONGLONG Position; - struct - { - LPWSTR DeviceInterfaceString; - ULONG DeviceInterfaceStringSize; - }Interface; - - struct - { - HANDLE hMixer; - ULONG NotificationType; - ULONG Value; - }MixerEvent; - KSSTATE State; - KSRESET ResetStream; - ULONG Volume; - ULONG FrameSize; - HANDLE hNotifyEvent; - }u; + PVOID unk1; + DWORD DeviceIndex; // Verified to match Windows XP/2003, indicates the ordering number of device. + SOUND_DEVICE_TYPE DeviceType; // Verified to match Windows XP/2003, indicates the type of the sound device, from 0 to 5. + HANDLE hDevice; // Verified to match Windows XP/2003, a handle to an opened audio device. + + DWORD_PTR dwInstance; // Verified to match Windows XP/2003, WinMM client callback's instance from the caller's WAVEOPENDESC structure. + DWORD_PTR dwCallback; // Verified to match Windows XP/2003, WinMM client callback from the caller's WAVEOPENDESC structure. + + DWORD unk2; + + DWORD Flags; // Verified to match Windows XP/2003, wave open flags passed in by the caller. + + PVOID Buffer; // Verified to match Windows XP/2003, optional buffer containing an additional data passed by the caller. It's different for different device management actions. + DWORD BufferSize; // Verified to match Windows XP/2003, the size, in bytes, of optional buffer passed by the caller. + + DWORD unk3; + DWORD unk4; + + HANDLE hMixer; + DWORD NotificationType; + DWORD Value; + + DWORD unk5; + DWORD unk6; + DWORD unk7; + INT unk8; + + PWDMAUD_DEVICE_STATE DeviceState; // Verified to match Windows XP/2003, WDMAUD_DEVICE_STATE structure for this device. + + LPCWSTR DeviceInterfaceString; // Verified to match Windows XP/2003, device interface string for this device. }WDMAUD_DEVICE_INFO, *PWDMAUD_DEVICE_INFO; +#pragma pack() + +/// IOCTL_INIT_WDMAUD +/// +/// Description: This IOCTL does the initialization of wdmaud.sys +/// +/// Arguments: Buffer is NULL, +/// BufferSize is zero +/// Return Code: STATUS_SUCCESS indicates success, otherwise appropriate error code +/// Prerequisites: none +#define IOCTL_INIT_WDMAUD \ + CTL_CODE(FILE_DEVICE_SOUND, \ + 0x0000, \ + METHOD_BUFFERED, \ + FILE_WRITE_ACCESS) -/// IOCTL_OPEN_WDMAUD +/// IOCTL_ADD_DEVNODE /// -/// Description: This IOCTL informs wdmaud that an application whats to use wdmsys for a waveOut / waveIn / aux operation +/// Description: This IOCTL adds a new device node /// -/// Arguments: InputBuffer is a pointer to a WDMAUD_DEVICE_INFO structure, -/// InputBufferSize is size of WDMAUD_DEVICE_INFO structure -/// Note: DeviceType identifies the device type, DeviceIndex the index, WaveFormatEx the device details -/// Result: is returned in hDevice +/// Arguments: Buffer is NULL, +/// BufferSize is zero +/// Note: DeviceType identifies the device type, DeviceIndex the index, WaveFormat the device details /// Return Code: STATUS_SUCCESS indicates success, otherwise appropriate error code /// Prerequisites: none -#define IOCTL_OPEN_WDMAUD \ +#define IOCTL_ADD_DEVNODE \ CTL_CODE(FILE_DEVICE_SOUND, \ - 0, \ + 0x0001, \ METHOD_BUFFERED, \ - FILE_CREATE_TREE_CONNECTION | FILE_ANY_ACCESS) + FILE_WRITE_ACCESS) + +/// IOCTL_REMOVE_DEVNODE +/// +/// Description: This IOCTL removes an existing device node +/// +/// Arguments: Buffer is NULL, +/// BufferSize is zero +/// Note: DeviceType identifies the device type, DeviceIndex the index, WaveFormat the device details +/// Return Code: STATUS_SUCCESS indicates success, otherwise appropriate error code +/// Prerequisites: none +#define IOCTL_REMOVE_DEVNODE \ + CTL_CODE(FILE_DEVICE_SOUND, \ + 0x0002, \ + METHOD_BUFFERED, \ + FILE_WRITE_ACCESS) -/// IOCTL_CLOSE_WDMAUD +/// IOCTL_GETCAPABILITIES /// -/// Description: This IOCTL informs that an application has finished with wdmsys and closes the connection +/// Description: This IOCTL retrieves the capabilities of an specific wave out device /// -/// Arguments: InputBuffer is a pointer to a WDMAUD_DEVICE_INFO structure, -/// InputBufferSize is size of WDMAUD_DEVICE_INFO structure -/// Note: DeviceType, DeviceIndex and hDevice must be set +/// Arguments: Buffer is a pointer to a capabilities data, +/// BufferSize is size of capabilities data +/// Note: The DeviceType and DeviceIndex must be set /// ReturnCode: STATUS_SUCCESS indicates success -/// Prerequisites: openend device +/// Prerequisites: none -#define IOCTL_CLOSE_WDMAUD \ +#define IOCTL_GETCAPABILITIES \ CTL_CODE(FILE_DEVICE_SOUND, \ - 1, \ + 0x0003, \ METHOD_BUFFERED, \ - FILE_CREATE_TREE_CONNECTION | FILE_ANY_ACCESS) \ - + FILE_WRITE_ACCESS) /// IOCTL_GETNUMDEVS_TYPE /// -/// Description: This IOCTL queries the number of devices currently present of a specific type. The caller passes a WDMAUD_DEVICE_INFO structure. +/// Description: This IOCTL queries the number of devices currently present of a specific type. /// -/// Arguments: InputBuffer is a pointer to a WDMAUD_DEVICE_INFO structure, -/// InputBufferSize is size of WDMAUD_DEVICE_INFO structure +/// Arguments: Buffer is NULL, +/// BufferSize is zero /// Note: The DeviceType contains the requested device type. /// Result: The result is returned in DeviceCount /// ReturnCode: STATUS_SUCCESS indicates success @@ -116,263 +150,355 @@ typedef struct #define IOCTL_GETNUMDEVS_TYPE \ CTL_CODE(FILE_DEVICE_SOUND, \ - 2, \ + 0x0004, \ METHOD_BUFFERED, \ - FILE_CREATE_TREE_CONNECTION | FILE_ANY_ACCESS) + FILE_WRITE_ACCESS) -/// IOCTL_SETDEVICE_STATE +/// IOCTL_OPEN_WDMAUD /// -/// Description: This IOCTL sets an opened waveOut / waveIn / midiIn / midiOut / aux device to specific state +/// Description: This IOCTL informs wdmaud that an application whats to use wdmsys for a waveOut / waveIn / aux operation /// -/// Arguments: InputBuffer is a pointer to a WDMAUD_DEVICE_INFO structure, -/// InputBufferSize is size of WDMAUD_DEVICE_INFO structure -/// Note: The DeviceType, DeviceIndex, hDevice and State member must be set. State determines the new state -/// ReturnCode: STATUS_SUCCESS indicates success -/// Prerequisites: opened device +/// Arguments: Buffer is a pointer to the WAVEFORMATEX structure, +/// BufferSize is size of the WAVEFORMATEX structure +/// Note: DeviceType identifies the device type, DeviceIndex the index, WaveFormat the device details +/// Result: is returned in hDevice +/// Return Code: STATUS_SUCCESS indicates success, otherwise appropriate error code +/// Prerequisites: none -#define IOCTL_SETDEVICE_STATE \ +#define IOCTL_OPEN_WDMAUD \ CTL_CODE(FILE_DEVICE_SOUND, \ - 3, \ + 0x0005, \ METHOD_BUFFERED, \ - FILE_CREATE_TREE_CONNECTION | FILE_ANY_ACCESS) - + FILE_WRITE_ACCESS) -/// IOCTL_GETDEVID +/// IOCTL_CLOSE_WDMAUD /// -/// Description: This IOCTL returns the device index by its provided handle +/// Description: This IOCTL informs that an application has finished with wdmsys and closes the connection /// -/// Arguments: InputBuffer is a pointer to a WDMAUD_DEVICE_INFO structure, -/// InputBufferSize is size of WDMAUD_DEVICE_INFO structure -/// Note: The DeviceType and hDevice must be set -/// Result: The result is returned in DeviceIndex +/// Arguments: Buffer is NULL, +/// BufferSize is zero +/// Note: DeviceType, DeviceIndex and hDevice must be set /// ReturnCode: STATUS_SUCCESS indicates success -/// Prerequisites: opened device +/// Prerequisites: Openend device -#define IOCTL_GETDEVID \ +#define IOCTL_CLOSE_WDMAUD \ CTL_CODE(FILE_DEVICE_SOUND, \ - 4, \ + 0x0006, \ METHOD_BUFFERED, \ - FILE_CREATE_TREE_CONNECTION | FILE_ANY_ACCESS) - + FILE_WRITE_ACCESS) /// IOCTL_GETVOLUME /// -/// Description: This IOCTL returns the volume a device +/// Description: This IOCTL returns the volume to a device /// /// Arguments: InputBuffer is a pointer to a WDMAUD_DEVICE_INFO structure, /// InputBufferSize is size of WDMAUD_DEVICE_INFO structure /// Note: The DeviceType and hDevice must be set -/// Result: The result is returned in Volume /// ReturnCode: STATUS_SUCCESS indicates success -/// Prerequisites: opened device +/// Prerequisites: Opened device #define IOCTL_GETVOLUME \ CTL_CODE(FILE_DEVICE_SOUND, \ - 5, \ + 0x0007, \ METHOD_BUFFERED, \ - FILE_CREATE_TREE_CONNECTION | FILE_ANY_ACCESS) + FILE_WRITE_ACCESS) /// IOCTL_SETVOLUME /// -/// Description: This IOCTL sets the volume a device +/// Description: This IOCTL sets the volume for a device /// /// Arguments: InputBuffer is a pointer to a WDMAUD_DEVICE_INFO structure, /// InputBufferSize is size of WDMAUD_DEVICE_INFO structure /// Note: The DeviceType, hDevice and Volume must be set /// ReturnCode: STATUS_SUCCESS indicates success -/// Prerequisites: opened device +/// Prerequisites: Opened device #define IOCTL_SETVOLUME \ CTL_CODE(FILE_DEVICE_SOUND, \ - 6, \ + 0x0008, \ METHOD_BUFFERED, \ - FILE_CREATE_TREE_CONNECTION | FILE_ANY_ACCESS) + FILE_WRITE_ACCESS) -/// IOCTL_GETCAPABILITIES +/// IOCTL_SETVOLUME /// -/// Description: This IOCTL retrieves the capabilities of an specific device +/// Description: This IOCTL does unloading of wdmaud.sys /// -/// Arguments: InputBuffer is a pointer to a WDMAUD_DEVICE_INFO structure, -/// InputBufferSize is size of WDMAUD_DEVICE_INFO structure -/// Note: The DeviceType and DeviceIndex must be set +/// Arguments: InputBuffer is NULL, +/// InputBufferSize is zero /// ReturnCode: STATUS_SUCCESS indicates success -/// Prerequisites: none +/// Prerequisites: Initialized device -#define IOCTL_GETCAPABILITIES \ +#define IOCTL_EXIT_WDMAUD \ CTL_CODE(FILE_DEVICE_SOUND, \ - 7, \ + 0x0009, \ METHOD_BUFFERED, \ - FILE_CREATE_TREE_CONNECTION | FILE_ANY_ACCESS) + FILE_WRITE_ACCESS) +/// IOCTL_PAUSE_PLAYBACK +/// +/// Description: This IOCTL pauses playback of an opened waveOut device +/// +/// Arguments: Buffer is NULL, +/// BufferSize is zero +/// Note: The DeviceType and hDevice members must be set. State determines the new state +/// ReturnCode: STATUS_SUCCESS indicates success +/// Prerequisites: Opened device -/// IOCTL_WRITEDATA +#define IOCTL_PAUSE_PLAYBACK \ + CTL_CODE(FILE_DEVICE_SOUND, \ + 0x0040, \ + METHOD_BUFFERED, \ + FILE_WRITE_ACCESS) + +/// IOCTL_START_PLAYBACK /// -/// Description: This IOCTL writes data to specified device +/// Description: This IOCTL starts playback for an opened waveOut device /// -/// Arguments: InputBuffer is a pointer to a WDMAUD_DEVICE_INFO structure, -/// InputBufferSize is size of WDMAUD_DEVICE_INFO structure -/// Note: The DeviceType, DeviceIndex, hDevice, BufferSize and Buffer must be set +/// Arguments: Buffer is NULL, +/// BufferSize is zero +/// Note: The DeviceType and hDevice members must be set. State determines the new state /// ReturnCode: STATUS_SUCCESS indicates success -/// Prerequisites: opened device +/// Prerequisites: Opened device -#define IOCTL_WRITEDATA \ +#define IOCTL_START_PLAYBACK \ + CTL_CODE(FILE_DEVICE_SOUND, \ + 0x0041, \ + METHOD_BUFFERED, \ + FILE_WRITE_ACCESS) + +/// IOCTL_RESET_PLAYBACK +/// +/// Description: This IOCTL resets the stream for an opened waveOut device to default state +/// +/// Arguments: Buffer is NULL, +/// BufferSize is zero +/// Note: The DeviceType and hDevice members must be set. State determines the new state +/// ReturnCode: STATUS_SUCCESS indicates success +/// Prerequisites: Opened device + +#define IOCTL_RESET_PLAYBACK \ CTL_CODE(FILE_DEVICE_SOUND, \ - 8, \ + 0x0042, \ METHOD_BUFFERED, \ - FILE_CREATE_TREE_CONNECTION | FILE_ANY_ACCESS) + FILE_WRITE_ACCESS) -/// IOCTL_GETPOS +/// IOCTL_GETOUTPOS /// /// Description: This IOCTL retrieves the current playback / write position /// -/// Arguments: InputBuffer is a pointer to a WDMAUD_DEVICE_INFO structure, -/// InputBufferSize is size of WDMAUD_DEVICE_INFO structure +/// Arguments: Buffer is a pointer to a variable that receives playback / write position, +/// BufferSize is set to size of DWORD /// Note: The DeviceType and hDevice must be set /// Result: The result is returned in Position /// ReturnCode: STATUS_SUCCESS indicates success -/// Prerequisites: opened device +/// Prerequisites: Opened device -#define IOCTL_GETPOS \ +#define IOCTL_GETOUTPOS \ CTL_CODE(FILE_DEVICE_SOUND, \ - 9, \ + 0x0044, \ METHOD_BUFFERED, \ - FILE_CREATE_TREE_CONNECTION | FILE_ANY_ACCESS) + FILE_WRITE_ACCESS) -/// IOCTL_GETFRAMESIZE +/// IOCTL_WRITEDATA /// -/// Description: This IOCTL retrieves the frame size requirements for an audio pin +/// Description: This IOCTL writes data to the specified WaveOut device /// -/// Arguments: InputBuffer is a pointer to a WDMAUD_DEVICE_INFO structure, -/// InputBufferSize is size of WDMAUD_DEVICE_INFO structure +/// Arguments: Buffer is a pointer to a WAVEHDR structure, +/// BufferSize is size of WAVEHDR structure /// Note: The DeviceType and hDevice must be set -/// Result: The result is returned in FrameSize /// ReturnCode: STATUS_SUCCESS indicates success -/// Prerequisites: opened device +/// Prerequisites: Opened device -#define IOCTL_GETFRAMESIZE \ +#define IOCTL_WRITEDATA \ CTL_CODE(FILE_DEVICE_SOUND, \ - 10, \ + 0x0047, \ METHOD_BUFFERED, \ - FILE_CREATE_TREE_CONNECTION | FILE_ANY_ACCESS) + FILE_WRITE_ACCESS) -/// IOCTL_GETLINEINFO +/// IOCTL_PAUSE_CAPTURE /// -/// Description: This IOCTL retrieves information on a mixerline +/// Description: This IOCTL pauses capture of an opened waveIn device /// -/// Arguments: InputBuffer is a pointer to a WDMAUD_DEVICE_INFO structure, -/// InputBufferSize is size of WDMAUD_DEVICE_INFO structure -/// Note: The hDevice member must be set -/// Result: The result is returned in MixLine +/// Arguments: Buffer is NULL, +/// BufferSize is zero +/// Note: The DeviceType and hDevice members must be set. State determines the new state /// ReturnCode: STATUS_SUCCESS indicates success -/// Prerequisites: opened device +/// Prerequisites: Opened device -#define IOCTL_GETLINEINFO \ +#define IOCTL_PAUSE_CAPTURE \ CTL_CODE(FILE_DEVICE_SOUND, \ - 11, \ + 0x0050, \ METHOD_BUFFERED, \ - FILE_CREATE_TREE_CONNECTION | FILE_ANY_ACCESS) + FILE_WRITE_ACCESS) +/// IOCTL_START_CAPTURE +/// +/// Description: This IOCTL starts capture for an opened waveIn device +/// +/// Arguments: Buffer is NULL, +/// BufferSize is zero +/// Note: The DeviceType and hDevice members must be set. State determines the new state +/// ReturnCode: STATUS_SUCCESS indicates success +/// Prerequisites: Opened device -/// IOCTL_GETLINECONTROLS +#define IOCTL_START_CAPTURE \ + CTL_CODE(FILE_DEVICE_SOUND, \ + 0x0051, \ + METHOD_BUFFERED, \ + FILE_WRITE_ACCESS) + +/// IOCTL_RESET_CAPTURE /// -/// Description: This IOCTL retrieves controls of a mixerline +/// Description: This IOCTL resets the stream for an opened waveIn device to default state +/// +/// Arguments: Buffer is NULL, +/// BufferSize is zero +/// Note: The DeviceType and hDevice members must be set. State determines the new state +/// ReturnCode: STATUS_SUCCESS indicates success +/// Prerequisites: Opened device + +#define IOCTL_RESET_CAPTURE \ + CTL_CODE(FILE_DEVICE_SOUND, \ + 0x0052, \ + METHOD_BUFFERED, \ + FILE_WRITE_ACCESS) + +/// IOCTL_GETINPOS +/// +/// Description: This IOCTL retrieves the current capture / read position +/// +/// Arguments: Buffer is a pointer to a variable that receives playback / write position, +/// BufferSize is set to size of DWORD +/// Note: The DeviceType and hDevice must be set +/// Result: The result is returned in Position +/// ReturnCode: STATUS_SUCCESS indicates success +/// Prerequisites: Opened device + +#define IOCTL_GETINPOS \ + CTL_CODE(FILE_DEVICE_SOUND, \ + 0x0053, \ + METHOD_BUFFERED, \ + FILE_WRITE_ACCESS) + +/// IOCTL_READDATA +/// +/// Description: This IOCTL reads data from the specified WaveIn device +/// +/// Arguments: Buffer is a pointer to a WAVEHDR structure, +/// BufferSize is size of WAVEHDR structure +/// Note: The DeviceType and hDevice must be set +/// ReturnCode: STATUS_SUCCESS indicates success +/// Prerequisites: Opened device + +#define IOCTL_READDATA \ + CTL_CODE(FILE_DEVICE_SOUND, \ + 0x0054, \ + METHOD_BUFFERED, \ + FILE_WRITE_ACCESS) + +/// IOCTL_OPEN_MIXER +/// +/// Description: This IOCTL opens mixer device /// /// Arguments: InputBuffer is a pointer to a WDMAUD_DEVICE_INFO structure, /// InputBufferSize is size of WDMAUD_DEVICE_INFO structure /// Note: The hDevice member must be set -/// Result: The result is returned in MixControls +/// Result: The result is returned in MixLine /// ReturnCode: STATUS_SUCCESS indicates success -/// Prerequisites: opened device +/// Prerequisites: Opened device -#define IOCTL_GETLINECONTROLS \ +#define IOCTL_OPEN_MIXER \ CTL_CODE(FILE_DEVICE_SOUND, \ - 12, \ + 0x00C0, \ METHOD_BUFFERED, \ - FILE_CREATE_TREE_CONNECTION | FILE_ANY_ACCESS) + FILE_WRITE_ACCESS) - -/// IOCTL_SETCONTROLDETAILS +/// IOCTL_GET_MIXER_EVENT /// -/// Description: This IOCTL sets details of a control of a mixerline +/// Description: This IOCTL queries for wdmaud driver if there any new kernel streaming events available /// /// Arguments: InputBuffer is a pointer to a WDMAUD_DEVICE_INFO structure, /// InputBufferSize is size of WDMAUD_DEVICE_INFO structure /// Note: The hDevice member must be set +/// Result: The result is returned in the struct MixerInfo /// ReturnCode: STATUS_SUCCESS indicates success -/// Prerequisites: opened device -#define IOCTL_SETCONTROLDETAILS \ +#define IOCTL_GET_MIXER_EVENT \ CTL_CODE(FILE_DEVICE_SOUND, \ - 13, \ + 0x00C6, \ METHOD_BUFFERED, \ - FILE_CREATE_TREE_CONNECTION | FILE_ANY_ACCESS) + FILE_WRITE_ACCESS) - -/// IOCTL_GETCONTROLDETAILS +/// IOCTL_GETLINEINFO /// -/// Description: This IOCTL gets details of a control of a mixerline +/// Description: This IOCTL retrieves information on a mixerline /// /// Arguments: InputBuffer is a pointer to a WDMAUD_DEVICE_INFO structure, /// InputBufferSize is size of WDMAUD_DEVICE_INFO structure /// Note: The hDevice member must be set -/// Result: The result is returned in MixDetails +/// Result: The result is returned in MixLine /// ReturnCode: STATUS_SUCCESS indicates success -/// Prerequisites: opened device +/// Prerequisites: Opened device -#define IOCTL_GETCONTROLDETAILS \ +#define IOCTL_GETLINEINFO \ CTL_CODE(FILE_DEVICE_SOUND, \ - 14, \ + 0x00C2, \ METHOD_BUFFERED, \ - FILE_CREATE_TREE_CONNECTION | FILE_ANY_ACCESS) + FILE_WRITE_ACCESS) -/// IOCTL_QUERYDEVICEINTERFACESTRING +/// IOCTL_GETLINECONTROLS /// -/// Description: This IOCTL queries the mixer / playback / recording device for its device interface string +/// Description: This IOCTL retrieves controls of a mixerline /// /// Arguments: InputBuffer is a pointer to a WDMAUD_DEVICE_INFO structure, /// InputBufferSize is size of WDMAUD_DEVICE_INFO structure -/// Note: The DeviceType, DeviceIndex must be set -/// Result: The size is returned in Interface.DeviceInterfaceStringSize and if a buffer is supplied in Interface.DeviceInterfaceString -/// the device interface string is stored +/// Note: The hDevice member must be set +/// Result: The result is returned in MixControls /// ReturnCode: STATUS_SUCCESS indicates success +/// Prerequisites: Opened device -#define IOCTL_QUERYDEVICEINTERFACESTRING \ +#define IOCTL_GETLINECONTROLS \ CTL_CODE(FILE_DEVICE_SOUND, \ - 15, \ + 0x00C3, \ METHOD_BUFFERED, \ - FILE_CREATE_TREE_CONNECTION | FILE_ANY_ACCESS) + FILE_WRITE_ACCESS) -/// IOCTL_GET_MIXER_EVENT + +/// IOCTL_SETCONTROLDETAILS /// -/// Description: This IOCTL queries for wdmaud driver if there any new kernel streaming events available +/// Description: This IOCTL sets details of a control of a mixerline /// /// Arguments: InputBuffer is a pointer to a WDMAUD_DEVICE_INFO structure, /// InputBufferSize is size of WDMAUD_DEVICE_INFO structure /// Note: The hDevice member must be set -/// Result: The result is returned in the struct MixerInfo /// ReturnCode: STATUS_SUCCESS indicates success +/// Prerequisites: Opened device -#define IOCTL_GET_MIXER_EVENT \ +#define IOCTL_SETCONTROLDETAILS \ CTL_CODE(FILE_DEVICE_SOUND, \ - 16, \ + 0x00C4, \ METHOD_BUFFERED, \ - FILE_CREATE_TREE_CONNECTION | FILE_ANY_ACCESS) + FILE_WRITE_ACCESS) -/// IOCTL_RESET_STREAM + +/// IOCTL_GETCONTROLDETAILS /// -/// Description: This IOCTL instructs wdmaud to reset a stream +/// Description: This IOCTL gets details of a control of a mixerline /// /// Arguments: InputBuffer is a pointer to a WDMAUD_DEVICE_INFO structure, /// InputBufferSize is size of WDMAUD_DEVICE_INFO structure -/// Note: The hDevice member must be set and DeviceType +/// Note: The hDevice member must be set +/// Result: The result is returned in MixDetails /// ReturnCode: STATUS_SUCCESS indicates success +/// Prerequisites: Opened device -#define IOCTL_RESET_STREAM \ +#define IOCTL_GETCONTROLDETAILS \ CTL_CODE(FILE_DEVICE_SOUND, \ - 17, \ + 0x00C5, \ METHOD_BUFFERED, \ - FILE_CREATE_TREE_CONNECTION | FILE_ANY_ACCESS) + FILE_WRITE_ACCESS) + diff --git a/drivers/wdm/audio/legacy/wdmaud/mmixer.c b/drivers/wdm/audio/legacy/wdmaud/mmixer.c index dbf97ba56081d..ace798410fe5b 100644 --- a/drivers/wdm/audio/legacy/wdmaud/mmixer.c +++ b/drivers/wdm/audio/legacy/wdmaud/mmixer.c @@ -10,7 +10,7 @@ #include -#define NDEBUG +#define YDEBUG #include PVOID Alloc(ULONG NumBytes); @@ -202,10 +202,10 @@ Control( PFILE_OBJECT FileObject; /* get file object */ - Status = ObReferenceObjectByHandle(hMixer, GENERIC_READ | GENERIC_WRITE, *IoFileObjectType, KernelMode, (PVOID*)&FileObject, NULL); + Status = ObReferenceObjectByHandle(hMixer, GENERIC_READ | GENERIC_WRITE, NULL, KernelMode, (PVOID*)&FileObject, NULL); if (!NT_SUCCESS(Status)) { - DPRINT("failed to reference %p with %lx\n", hMixer, Status); + DPRINT("failed to reference %p with 0x%lx\n", hMixer, Status); return MM_STATUS_UNSUCCESSFUL; } @@ -227,7 +227,7 @@ Control( } else { - DPRINT("Failed with %lx\n", Status); + DPRINT("KsSynchronousIoControlDevice failed with 0x%lx\n", Status); return MM_STATUS_UNSUCCESSFUL; } } @@ -263,6 +263,7 @@ Enum( if (!NT_SUCCESS(Status)) { /* failed to retrieve device name */ + DPRINT1("Status 0x%lx\n", Status); return MM_STATUS_UNSUCCESSFUL; } @@ -375,7 +376,6 @@ EventCallback( } } - NTSTATUS WdmAudMixerInitialize( IN PDEVICE_OBJECT DeviceObject) @@ -389,22 +389,28 @@ WdmAudMixerInitialize( { /* failed to initialize mmixer library */ DPRINT("MMixerInitialize failed with %lx\n", Status); + return STATUS_UNSUCCESSFUL; } - return Status; + return STATUS_SUCCESS; } NTSTATUS WdmAudMixerCapabilities( IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp, IN PWDMAUD_DEVICE_INFO DeviceInfo, IN PWDMAUD_CLIENT ClientInfo, IN PWDMAUD_DEVICE_EXTENSION DeviceExtension) { - if (MMixerGetCapabilities(&MixerContext, DeviceInfo->DeviceIndex, &DeviceInfo->u.MixCaps) == MM_STATUS_SUCCESS) - return STATUS_SUCCESS; + MIXER_STATUS Status = MM_STATUS_UNSUCCESSFUL; + + Status = MMixerGetCapabilities(&MixerContext, DeviceInfo->DeviceIndex, (LPMIXERCAPSW)DeviceInfo->Buffer); - return STATUS_INVALID_PARAMETER; + if (Status == MM_STATUS_SUCCESS) + return STATUS_SUCCESS; + else + return STATUS_UNSUCCESSFUL; } NTSTATUS @@ -414,61 +420,15 @@ WdmAudControlOpenMixer( IN PWDMAUD_DEVICE_INFO DeviceInfo, IN PWDMAUD_CLIENT ClientInfo) { - HANDLE hMixer; - PWDMAUD_HANDLE Handles; - //PWDMAUD_DEVICE_EXTENSION DeviceExtension; - NTSTATUS Status; - PKEVENT EventObject = NULL; - DPRINT("WdmAudControlOpenMixer\n"); - //DeviceExtension = (PWDMAUD_DEVICE_EXTENSION)DeviceObject->DeviceExtension; - - if (DeviceInfo->u.hNotifyEvent) - { - Status = ObReferenceObjectByHandle(DeviceInfo->u.hNotifyEvent, EVENT_MODIFY_STATE, *ExEventObjectType, UserMode, (LPVOID*)&EventObject, NULL); - - if (!NT_SUCCESS(Status)) - { - DPRINT1("Invalid notify event passed %p from client %p\n", DeviceInfo->u.hNotifyEvent, ClientInfo); - DbgBreakPoint(); - return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, 0); - } - } - - if (MMixerOpen(&MixerContext, DeviceInfo->DeviceIndex, ClientInfo, EventCallback, &hMixer) != MM_STATUS_SUCCESS) + if (MMixerOpen(&MixerContext, DeviceInfo->DeviceIndex, ClientInfo, EventCallback, &DeviceInfo->hDevice) != MM_STATUS_SUCCESS) { - ObDereferenceObject(EventObject); DPRINT1("Failed to open mixer\n"); - return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, 0); - } - - - Handles = AllocateItem(NonPagedPool, sizeof(WDMAUD_HANDLE) * (ClientInfo->NumPins+1)); - - if (Handles) - { - if (ClientInfo->NumPins) - { - RtlMoveMemory(Handles, ClientInfo->hPins, sizeof(WDMAUD_HANDLE) * ClientInfo->NumPins); - FreeItem(ClientInfo->hPins); - } - - ClientInfo->hPins = Handles; - ClientInfo->hPins[ClientInfo->NumPins].Handle = hMixer; - ClientInfo->hPins[ClientInfo->NumPins].Type = MIXER_DEVICE_TYPE; - ClientInfo->hPins[ClientInfo->NumPins].NotifyEvent = EventObject; - ClientInfo->NumPins++; - } - else - { - ObDereferenceObject(EventObject); - return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, sizeof(WDMAUD_DEVICE_INFO)); + return STATUS_UNSUCCESSFUL; } - DeviceInfo->hDevice = hMixer; - - return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO)); + return STATUS_SUCCESS; } NTSTATUS @@ -503,13 +463,10 @@ WdmAudCloseAllMixers( IN PWDMAUD_CLIENT ClientInfo, IN ULONG Index) { - ULONG DeviceCount, DeviceIndex; - - /* Get all mixers */ - DeviceCount = GetSysAudioDeviceCount(DeviceObject); + ULONG DeviceIndex; /* Close every mixer attached to the device */ - for (DeviceIndex = 0; DeviceIndex < DeviceCount; DeviceIndex++) + for (DeviceIndex = 0; DeviceIndex < Index; DeviceIndex++) { if (MMixerClose(&MixerContext, DeviceIndex, ClientInfo, EventCallback) != MM_STATUS_SUCCESS) { @@ -539,7 +496,7 @@ WdmAudGetControlDetails( DeviceInfo->Flags &= ~MIXER_OBJECTF_HMIXER; /* query mmixer library */ - Status = MMixerGetControlDetails(&MixerContext, DeviceInfo->hDevice, DeviceInfo->DeviceIndex, DeviceInfo->Flags, &DeviceInfo->u.MixDetails); + Status = MMixerGetControlDetails(&MixerContext, DeviceInfo->hDevice, DeviceInfo->DeviceIndex, DeviceInfo->Flags, (LPMIXERCONTROLDETAILS)DeviceInfo->Buffer); if (Status == MM_STATUS_SUCCESS) return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO)); @@ -561,7 +518,7 @@ WdmAudGetLineInfo( DeviceInfo->Flags &= ~MIXER_OBJECTF_HMIXER; /* query mixer library */ - Status = MMixerGetLineInfo(&MixerContext, DeviceInfo->hDevice, DeviceInfo->DeviceIndex, DeviceInfo->Flags, &DeviceInfo->u.MixLine); + Status = MMixerGetLineInfo(&MixerContext, DeviceInfo->hDevice, DeviceInfo->DeviceIndex, DeviceInfo->Flags, (LPMIXERLINEW)DeviceInfo->Buffer); if (Status == MM_STATUS_SUCCESS) return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO)); @@ -583,7 +540,7 @@ WdmAudGetLineControls( DeviceInfo->Flags &= ~MIXER_OBJECTF_HMIXER; /* query mixer library */ - Status = MMixerGetLineControls(&MixerContext, DeviceInfo->hDevice, DeviceInfo->DeviceIndex, DeviceInfo->Flags, &DeviceInfo->u.MixControls); + Status = MMixerGetLineControls(&MixerContext, DeviceInfo->hDevice, DeviceInfo->DeviceIndex, DeviceInfo->Flags, (LPMIXERLINECONTROLSW)DeviceInfo->Buffer); if (Status == MM_STATUS_SUCCESS) return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO)); @@ -607,7 +564,7 @@ WdmAudSetControlDetails( DeviceInfo->Flags &= ~MIXER_OBJECTF_HMIXER; /* query mixer library */ - Status = MMixerSetControlDetails(&MixerContext, DeviceInfo->hDevice, DeviceInfo->DeviceIndex, DeviceInfo->Flags, &DeviceInfo->u.MixDetails); + Status = MMixerSetControlDetails(&MixerContext, DeviceInfo->hDevice, DeviceInfo->DeviceIndex, DeviceInfo->Flags, (LPMIXERCONTROLDETAILS)DeviceInfo->Buffer); if (Status == MM_STATUS_SUCCESS) return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO)); @@ -637,9 +594,9 @@ WdmAudGetMixerEvent( if (EventEntry->hMixer == DeviceInfo->hDevice) { /* found an entry */ - DeviceInfo->u.MixerEvent.hMixer = EventEntry->hMixer; - DeviceInfo->u.MixerEvent.NotificationType = EventEntry->NotificationType; - DeviceInfo->u.MixerEvent.Value = EventEntry->Value; + DeviceInfo->hMixer = EventEntry->hMixer; + DeviceInfo->NotificationType = EventEntry->NotificationType; + DeviceInfo->Value = EventEntry->Value; /* remove entry from list */ RemoveEntryList(&EventEntry->Entry); @@ -720,6 +677,7 @@ WdmAudGetPnpNameByIndexAndType( NTSTATUS WdmAudWaveCapabilities( IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp, IN PWDMAUD_DEVICE_INFO DeviceInfo, IN PWDMAUD_CLIENT ClientInfo, IN PWDMAUD_DEVICE_EXTENSION DeviceExtension) @@ -729,23 +687,24 @@ WdmAudWaveCapabilities( if (DeviceInfo->DeviceType == WAVE_IN_DEVICE_TYPE) { /* get capabilities */ - Status = MMixerWaveInCapabilities(&MixerContext, DeviceInfo->DeviceIndex, &DeviceInfo->u.WaveInCaps); + Status = MMixerWaveInCapabilities(&MixerContext, DeviceInfo->DeviceIndex, (LPWAVEINCAPSW)DeviceInfo->Buffer); } else if (DeviceInfo->DeviceType == WAVE_OUT_DEVICE_TYPE) { /* get capabilities */ - Status = MMixerWaveOutCapabilities(&MixerContext, DeviceInfo->DeviceIndex, &DeviceInfo->u.WaveOutCaps); + Status = MMixerWaveOutCapabilities(&MixerContext, DeviceInfo->DeviceIndex, (LPWAVEOUTCAPSW)DeviceInfo->Buffer); } if (Status == MM_STATUS_SUCCESS) return STATUS_SUCCESS; else - return Status; + return STATUS_UNSUCCESSFUL; } NTSTATUS WdmAudMidiCapabilities( IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp, IN PWDMAUD_DEVICE_INFO DeviceInfo, IN PWDMAUD_CLIENT ClientInfo, IN PWDMAUD_DEVICE_EXTENSION DeviceExtension) @@ -755,12 +714,12 @@ WdmAudMidiCapabilities( if (DeviceInfo->DeviceType == MIDI_IN_DEVICE_TYPE) { /* get capabilities */ - Status = MMixerMidiInCapabilities(&MixerContext, DeviceInfo->DeviceIndex, &DeviceInfo->u.MidiInCaps); + Status = MMixerMidiInCapabilities(&MixerContext, DeviceInfo->DeviceIndex, (LPMIDIINCAPSW)DeviceInfo->Buffer); } - else if (DeviceInfo->DeviceType == WAVE_OUT_DEVICE_TYPE) + else if (DeviceInfo->DeviceType == MIDI_OUT_DEVICE_TYPE) { /* get capabilities */ - Status = MMixerMidiOutCapabilities(&MixerContext, DeviceInfo->DeviceIndex, &DeviceInfo->u.MidiOutCaps); + Status = MMixerMidiOutCapabilities(&MixerContext, DeviceInfo->DeviceIndex, (LPMIDIOUTCAPSW)DeviceInfo->Buffer); } if (Status == MM_STATUS_SUCCESS) @@ -769,6 +728,26 @@ WdmAudMidiCapabilities( return STATUS_UNSUCCESSFUL; } +NTSTATUS +NTAPI +WdmAudGetPosition( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp, + IN PWDMAUD_DEVICE_INFO DeviceInfo) +{ + MIXER_STATUS Status; + DWORD Position; + + Status = MMixerGetWavePosition(&MixerContext, DeviceInfo->hDevice, &Position); + + DeviceInfo->Buffer = (PVOID)&Position; + + DPRINT("Success %x\n", Status == MM_STATUS_SUCCESS); + if (Status == MM_STATUS_SUCCESS) + return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO)); + else + return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, sizeof(WDMAUD_DEVICE_INFO)); +} MIXER_STATUS CreatePinCallback( @@ -780,40 +759,59 @@ CreatePinCallback( IN ACCESS_MASK DesiredAccess, OUT PHANDLE PinHandle) { - ULONG BytesReturned; - SYSAUDIO_INSTANCE_INFO InstanceInfo; NTSTATUS Status; ULONG FreeIndex; + PFILE_OBJECT PinFileObject; PPIN_CREATE_CONTEXT Context = (PPIN_CREATE_CONTEXT)Ctx; - /* 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 */ - Status = KsSynchronousIoControlDevice(Context->DeviceExtension->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&InstanceInfo, sizeof(SYSAUDIO_INSTANCE_INFO), NULL, 0, &BytesReturned); + /* find available sysaudio devices */ + Status = WdmAudOpenSysAudioDevices(Context->DeviceExtension); + if (!NT_SUCCESS(Status)) + { + DPRINT1("WdmAudOpenSysAudioDevices failed with 0x%lx\n", Status); + return MM_STATUS_UNSUCCESSFUL; + } + /* set current device instance */ + Status = SetSysAudioDeviceInstance(Context->DeviceExtension, VirtualDeviceId); if (!NT_SUCCESS(Status)) + { + DPRINT1("KSPROPERTY_SYSAUDIO_DEVICE_INSTANCE failed with status 0x%lx\n", Status); return MM_STATUS_UNSUCCESSFUL; + } /* close existing pin */ - FreeIndex = ClosePin(Context->ClientInfo, VirtualDeviceId, PinId, Context->DeviceType); + FreeIndex = ClosePinByIndex(Context->ClientInfo, VirtualDeviceId, PinId, Context->DeviceType); /* now create the pin */ Status = KsCreatePin(Context->DeviceExtension->hSysAudio, PinConnect, DesiredAccess, PinHandle); + if (!NT_SUCCESS(Status)) + { + /* failed to create the pin */ + DPRINT1("KsCreatePin failed with status 0x%lx\n", Status); + return MM_STATUS_UNSUCCESSFUL; + } - /* check for success */ + /* get pin file object */ + Status = ObReferenceObjectByHandle(*PinHandle, + FILE_READ_DATA | FILE_WRITE_DATA, + *IoFileObjectType, + KernelMode, + (PVOID*)&PinFileObject, + NULL); if (!NT_SUCCESS(Status)) + { + DPRINT1("ObReferenceObjectByHandle failed with 0x%lx for %p\n", Status, *PinHandle); + ZwClose(*PinHandle); return MM_STATUS_UNSUCCESSFUL; + } /* store the handle */ - Status = InsertPinHandle(Context->ClientInfo, VirtualDeviceId, PinId, Context->DeviceType, *PinHandle, FreeIndex); + Status = InsertPinHandle(Context->ClientInfo, VirtualDeviceId, PinId, Context->DeviceType, *PinHandle, PinFileObject, FreeIndex); if (!NT_SUCCESS(Status)) { /* failed to insert handle */ + ObDereferenceObject(PinFileObject); ZwClose(*PinHandle); return MM_STATUS_UNSUCCESSFUL; } @@ -835,12 +833,12 @@ WdmAudControlOpenWave( Context.DeviceExtension = (PWDMAUD_DEVICE_EXTENSION)DeviceObject->DeviceExtension; Context.DeviceType = DeviceInfo->DeviceType; - Status = MMixerOpenWave(&MixerContext, DeviceInfo->DeviceIndex, DeviceInfo->DeviceType == WAVE_IN_DEVICE_TYPE, &DeviceInfo->u.WaveFormatEx, CreatePinCallback, &Context, &DeviceInfo->hDevice); + Status = MMixerOpenWave(&MixerContext, DeviceInfo->DeviceIndex, DeviceInfo->DeviceType == WAVE_IN_DEVICE_TYPE, (LPWAVEFORMATEX)DeviceInfo->Buffer, CreatePinCallback, &Context, &DeviceInfo->hDevice); if (Status == MM_STATUS_SUCCESS) - return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO)); + return STATUS_SUCCESS; else - return SetIrpIoStatus(Irp, STATUS_NOT_SUPPORTED, sizeof(WDMAUD_DEVICE_INFO)); + return STATUS_NOT_SUPPORTED; } NTSTATUS @@ -860,7 +858,7 @@ WdmAudControlOpenMidi( Status = MMixerOpenMidi(&MixerContext, DeviceInfo->DeviceIndex, DeviceInfo->DeviceType == MIDI_IN_DEVICE_TYPE, CreatePinCallback, &Context, &DeviceInfo->hDevice); if (Status == MM_STATUS_SUCCESS) - return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO)); + return STATUS_SUCCESS; else - return SetIrpIoStatus(Irp, STATUS_NOT_SUPPORTED, sizeof(WDMAUD_DEVICE_INFO)); + return STATUS_NOT_SUPPORTED; } diff --git a/drivers/wdm/audio/legacy/wdmaud/sup.c b/drivers/wdm/audio/legacy/wdmaud/sup.c index 496eabf56e288..6e40a43086fea 100644 --- a/drivers/wdm/audio/legacy/wdmaud/sup.c +++ b/drivers/wdm/audio/legacy/wdmaud/sup.c @@ -11,7 +11,7 @@ #include -#define NDEBUG +#define YDEBUG #include #define TAG_WDMAUD 'DMDW' @@ -55,6 +55,32 @@ GetSysAudioDeviceCount( return Count; } +NTSTATUS +SetSysAudioDeviceInstance( + IN PWDMAUD_DEVICE_EXTENSION DeviceExtension, + IN ULONG VirtualDeviceId) +{ + NTSTATUS Status; + KSPROPERTY Property; + ULONG BytesReturned; + + /* setup property request */ + Property.Set = KSPROPSETID_Sysaudio; + Property.Id = KSPROPERTY_SYSAUDIO_DEVICE_INSTANCE; + Property.Flags = KSPROPERTY_TYPE_SET; + + /* attach to virtual device */ + Status = KsSynchronousIoControlDevice(DeviceExtension->FileObject, + KernelMode, + IOCTL_KS_PROPERTY, + (PVOID)&Property, + sizeof(KSPROPERTY), + (PVOID)&VirtualDeviceId, + sizeof(ULONG), + &BytesReturned); + return Status; +} + NTSTATUS SetIrpIoStatus( IN PIRP Irp, @@ -64,12 +90,11 @@ SetIrpIoStatus( Irp->IoStatus.Information = Length; Irp->IoStatus.Status = Status; IoCompleteRequest(Irp, IO_NO_INCREMENT); - return Status; } ULONG -ClosePin( +ClosePinByIndex( IN PWDMAUD_CLIENT ClientInfo, IN ULONG FilterId, IN ULONG PinId, @@ -77,15 +102,46 @@ ClosePin( { 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) + { + DPRINT("Closing pin %p, index %d\n", ClientInfo->hPins[Index].Handle, Index); + ClosePin(ClientInfo, Index); + return Index; + } + } + return MAXULONG; +} + +VOID +ClosePin( + IN PWDMAUD_CLIENT ClientInfo, + IN ULONG Index) +{ + if (ClientInfo->hPins[Index].Type != MIXER_DEVICE_TYPE) + { + ObDereferenceObject(ClientInfo->hPins[Index].FileObject); + ZwClose(ClientInfo->hPins[Index].Handle); + ClientInfo->hPins[Index].Handle = NULL; + ClientInfo->hPins[Index].Active = FALSE; + } +} + +ULONG +GetActivePin( + IN PWDMAUD_CLIENT ClientInfo) +{ + 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].Active == TRUE && + ClientInfo->hPins[Index].Type != MIXER_DEVICE_TYPE) { - if (ClientInfo->hPins[Index].Type != MIXER_DEVICE_TYPE) - { - ZwClose(ClientInfo->hPins[Index].Handle); - } - ClientInfo->hPins[Index].Handle = NULL; return Index; } } @@ -99,37 +155,33 @@ InsertPinHandle( IN ULONG PinId, IN SOUND_DEVICE_TYPE DeviceType, IN HANDLE PinHandle, + IN PFILE_OBJECT PinFileObject, IN ULONG FreeIndex) { - PWDMAUD_HANDLE Handles; - if (FreeIndex != MAXULONG) { /* re-use a free index */ ClientInfo->hPins[FreeIndex].Handle = PinHandle; + ClientInfo->hPins[FreeIndex].FileObject = PinFileObject; ClientInfo->hPins[FreeIndex].FilterId = FilterId; ClientInfo->hPins[FreeIndex].PinId = PinId; ClientInfo->hPins[FreeIndex].Type = DeviceType; + ClientInfo->hPins[FreeIndex].Active = TRUE; return STATUS_SUCCESS; } - Handles = AllocateItem(NonPagedPool, sizeof(WDMAUD_HANDLE) * (ClientInfo->NumPins+1)); + ClientInfo->hPins = AllocateItem(NonPagedPool, sizeof(WDMAUD_HANDLE) * (ClientInfo->NumPins+1)); - if (!Handles) + if (!ClientInfo->hPins) return STATUS_INSUFFICIENT_RESOURCES; - if (ClientInfo->NumPins) - { - RtlMoveMemory(Handles, ClientInfo->hPins, sizeof(WDMAUD_HANDLE) * ClientInfo->NumPins); - FreeItem(ClientInfo->hPins); - } - - ClientInfo->hPins = Handles; ClientInfo->hPins[ClientInfo->NumPins].Handle = PinHandle; + ClientInfo->hPins[ClientInfo->NumPins].FileObject = PinFileObject; ClientInfo->hPins[ClientInfo->NumPins].Type = DeviceType; ClientInfo->hPins[ClientInfo->NumPins].FilterId = FilterId; ClientInfo->hPins[ClientInfo->NumPins].PinId = PinId; + ClientInfo->hPins[ClientInfo->NumPins].Active = TRUE; ClientInfo->NumPins++; return STATUS_SUCCESS; @@ -353,9 +405,11 @@ GetSysAudioDevicePnpName( NTSTATUS Status; PWDMAUD_DEVICE_EXTENSION DeviceExtension; - /* first check if the device index is within bounds */ - if (DeviceIndex >= GetSysAudioDeviceCount(DeviceObject)) - return STATUS_INVALID_PARAMETER; + DeviceExtension = (PWDMAUD_DEVICE_EXTENSION)DeviceObject->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; @@ -363,14 +417,12 @@ GetSysAudioDevicePnpName( Pin.Property.Flags = KSPROPERTY_TYPE_GET; 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; + if (Status != STATUS_BUFFER_OVERFLOW || BytesReturned == 0) + return Status; /* allocate buffer for the device */ *Device = AllocateItem(NonPagedPool, BytesReturned); diff --git a/drivers/wdm/audio/legacy/wdmaud/wdmaud.h b/drivers/wdm/audio/legacy/wdmaud/wdmaud.h index 4c56a87e21ea8..8e243961ac75c 100644 --- a/drivers/wdm/audio/legacy/wdmaud/wdmaud.h +++ b/drivers/wdm/audio/legacy/wdmaud/wdmaud.h @@ -1,7 +1,9 @@ #ifndef _WDMAUD_PCH_ #define _WDMAUD_PCH_ +#include #include +#include #include #include "interface.h" @@ -14,13 +16,14 @@ typedef struct PFILE_OBJECT FileObject; }WDMAUD_COMPLETION_CONTEXT, *PWDMAUD_COMPLETION_CONTEXT; - typedef struct { HANDLE Handle; + PFILE_OBJECT FileObject; SOUND_DEVICE_TYPE Type; ULONG FilterId; ULONG PinId; + BOOL Active; PRKEVENT NotifyEvent; }WDMAUD_HANDLE, *PWDMAUD_HANDLE; @@ -42,22 +45,13 @@ typedef struct HANDLE hMixer; }EVENT_ENTRY, *PEVENT_ENTRY; -typedef struct -{ - LIST_ENTRY Entry; - UNICODE_STRING SymbolicLink; -}SYSAUDIO_ENTRY, *PSYSAUDIO_ENTRY; - typedef struct { KSDEVICE_HEADER DeviceHeader; PVOID SysAudioNotification; - BOOL DeviceInterfaceSupport; - KSPIN_LOCK Lock; ULONG NumSysAudioDevices; - LIST_ENTRY SysAudioDeviceList; HANDLE hSysAudio; PFILE_OBJECT FileObject; LIST_ENTRY WdmAudClientList; @@ -77,17 +71,6 @@ typedef struct SOUND_DEVICE_TYPE DeviceType; }PIN_CREATE_CONTEXT, *PPIN_CREATE_CONTEXT; - -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, @@ -95,11 +78,10 @@ WdmAudRegisterDeviceInterface( NTSTATUS WdmAudOpenSysAudioDevices( - IN PDEVICE_OBJECT DeviceObject, IN PWDMAUD_DEVICE_EXTENSION DeviceExtension); NTSTATUS -WdmAudOpenSysaudio( +WdmAudAllocateContext( IN PDEVICE_OBJECT DeviceObject, IN PWDMAUD_CLIENT *pClient); @@ -115,12 +97,6 @@ WdmAudReadWrite( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp); -NTSTATUS -NTAPI -WdmAudWrite( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp); - NTSTATUS WdmAudControlOpenMixer( IN PDEVICE_OBJECT DeviceObject, @@ -166,6 +142,10 @@ SetIrpIoStatus( IN NTSTATUS Status, IN ULONG Length); +NTSTATUS +GetSysAudioDeviceInterface( + OUT LPWSTR* SymbolicLonkList); + NTSTATUS WdmAudOpenSysAudioDevice( IN LPWSTR DeviceName, @@ -180,6 +160,7 @@ FindProductName( NTSTATUS WdmAudMixerCapabilities( IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp, IN PWDMAUD_DEVICE_INFO DeviceInfo, IN PWDMAUD_CLIENT ClientInfo, IN PWDMAUD_DEVICE_EXTENSION DeviceExtension); @@ -187,6 +168,7 @@ WdmAudMixerCapabilities( NTSTATUS WdmAudWaveCapabilities( IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp, IN PWDMAUD_DEVICE_INFO DeviceInfo, IN PWDMAUD_CLIENT ClientInfo, IN PWDMAUD_DEVICE_EXTENSION DeviceExtension); @@ -194,17 +176,33 @@ WdmAudWaveCapabilities( NTSTATUS WdmAudMidiCapabilities( IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp, IN PWDMAUD_DEVICE_INFO DeviceInfo, IN PWDMAUD_CLIENT ClientInfo, IN PWDMAUD_DEVICE_EXTENSION DeviceExtension); NTSTATUS NTAPI -WdmAudFrameSize( +WdmAudGetPosition( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp, + IN PWDMAUD_DEVICE_INFO DeviceInfo); + +NTSTATUS +WdmAudSetDeviceState( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PWDMAUD_DEVICE_INFO DeviceInfo, - IN PWDMAUD_CLIENT ClientInfo); + IN KSSTATE State, + IN BOOL CompleteIrp); + +NTSTATUS +NTAPI +WdmAudResetStream( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp, + IN PWDMAUD_DEVICE_INFO DeviceInfo, + IN BOOL CompleteIrp); NTSTATUS NTAPI @@ -246,6 +244,11 @@ WdmAudGetControlDetails( IN PWDMAUD_DEVICE_INFO DeviceInfo, IN PWDMAUD_CLIENT ClientInfo); +NTSTATUS +WdmAudControlInitialize( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp); + NTSTATUS WdmAudMixerInitialize( IN PDEVICE_OBJECT DeviceObject); @@ -256,12 +259,21 @@ WdmAudWaveInitialize( IN PDEVICE_OBJECT DeviceObject); ULONG -ClosePin( +ClosePinByIndex( IN PWDMAUD_CLIENT ClientInfo, IN ULONG FilterId, IN ULONG PinId, IN SOUND_DEVICE_TYPE DeviceType); +VOID +ClosePin( + IN PWDMAUD_CLIENT ClientInfo, + IN ULONG Index); + +ULONG +GetActivePin( + IN PWDMAUD_CLIENT ClientInfo); + NTSTATUS InsertPinHandle( IN PWDMAUD_CLIENT ClientInfo, @@ -269,6 +281,7 @@ InsertPinHandle( IN ULONG PinId, IN SOUND_DEVICE_TYPE DeviceType, IN HANDLE PinHandle, + IN PFILE_OBJECT PinFileObject, IN ULONG FreeIndex); NTSTATUS @@ -318,6 +331,10 @@ ULONG GetSysAudioDeviceCount( IN PDEVICE_OBJECT DeviceObject); +NTSTATUS +SetSysAudioDeviceInstance( + IN PWDMAUD_DEVICE_EXTENSION DeviceExtension, + IN ULONG VirtualDeviceId); PVOID AllocateItem( diff --git a/drivers/wdm/audio/sysaudio/control.c b/drivers/wdm/audio/sysaudio/control.c index 5d18c24ce92d3..0f74e9ab4797b 100644 --- a/drivers/wdm/audio/sysaudio/control.c +++ b/drivers/wdm/audio/sysaudio/control.c @@ -8,7 +8,7 @@ #include "sysaudio.h" -#define NDEBUG +#define YDEBUG #include const GUID KSPROPSETID_Sysaudio = {0xCBE3FAA0L, 0xCC75, 0x11D0, {0xB4, 0x65, 0x00, 0x00, 0x1A, 0x18, 0x18, 0xE6}}; @@ -135,134 +135,147 @@ NTSTATUS ComputeCompatibleFormat( IN PKSAUDIO_DEVICE_ENTRY Entry, IN ULONG PinId, - IN PKSDATAFORMAT_WAVEFORMATEX ClientFormat, - OUT PKSDATAFORMAT_WAVEFORMATEX MixerFormat) + IN PKSDATAFORMAT_WAVEFORMATEX InputFormat, + OUT PKSDATAFORMAT_WAVEFORMATEX OutputFormat) { - BOOL bFound; - ULONG BytesReturned; + ULONG BytesReturned, Length; PKSP_PIN PinRequest; NTSTATUS Status; PKSMULTIPLE_ITEM MultipleItem; - ULONG Length; - PKSDATARANGE_AUDIO AudioRange; - ULONG Index; + PKSDATARANGE_AUDIO DataRangeAudio; - Length = sizeof(KSP_PIN) + sizeof(KSMULTIPLE_ITEM) + ClientFormat->DataFormat.FormatSize; + /* Allocate pin request */ + Length = sizeof(KSP_PIN) + sizeof(KSMULTIPLE_ITEM) + InputFormat->DataFormat.FormatSize; PinRequest = AllocateItem(NonPagedPool, Length); if (!PinRequest) - return STATUS_UNSUCCESSFUL; + { + return STATUS_INSUFFICIENT_RESOURCES; + } + /* Setup request block */ + PinRequest->Reserved = 0; PinRequest->PinId = PinId; PinRequest->Property.Set = KSPROPSETID_Pin; PinRequest->Property.Flags = KSPROPERTY_TYPE_GET; - PinRequest->Property.Id = KSPROPERTY_PIN_DATAINTERSECTION; + PinRequest->Property.Id = KSPROPERTY_PIN_DATARANGES; + /* Prepare multiple item */ MultipleItem = (PKSMULTIPLE_ITEM)(PinRequest + 1); MultipleItem->Count = 1; - MultipleItem->Size = ClientFormat->DataFormat.FormatSize; + MultipleItem->Size = InputFormat->DataFormat.FormatSize; - RtlMoveMemory(MultipleItem + 1, ClientFormat, ClientFormat->DataFormat.FormatSize); - /* Query the miniport data intersection handler */ - Status = KsSynchronousIoControlDevice(Entry->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)PinRequest, Length, (PVOID)MixerFormat, sizeof(KSDATAFORMAT_WAVEFORMATEX), &BytesReturned); + RtlMoveMemory(MultipleItem + 1, InputFormat, InputFormat->DataFormat.FormatSize); - DPRINT("Status %x\n", Status); + /* Query pin data ranges size */ + Status = KsSynchronousIoControlDevice(Entry->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)PinRequest, sizeof(KSP_PIN), NULL, 0, &BytesReturned); + if (Status != STATUS_BUFFER_OVERFLOW) + { + DPRINT1("Property Request KSPROPERTY_PIN_DATARANGES failed with 0x%lx\n", Status); + FreeItem(PinRequest); + return Status; + } - if (NT_SUCCESS(Status)) + /* Allocate multiple item */ + MultipleItem = AllocateItem(NonPagedPool, BytesReturned); + if (!MultipleItem) { + FreeItem(PinRequest); + return STATUS_INSUFFICIENT_RESOURCES; + } + + /* Query pin data ranges */ + Status = KsSynchronousIoControlDevice(Entry->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)PinRequest, sizeof(KSP_PIN), (PVOID)MultipleItem, BytesReturned, &BytesReturned); + if (!NT_SUCCESS(Status)) + { + DPRINT1("Property Request KSPROPERTY_PIN_DATARANGES failed with 0x%lx\n", Status); FreeItem(PinRequest); return Status; } /* Setup request block */ - PinRequest->Property.Id = KSPROPERTY_PIN_DATARANGES; - /* Query pin data ranges */ - Status = KsSynchronousIoControlDevice(Entry->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)PinRequest, sizeof(KSP_PIN), NULL, 0, &BytesReturned); + PinRequest->Property.Id = KSPROPERTY_PIN_DATAINTERSECTION; - if (Status != STATUS_MORE_ENTRIES) + /* Copy multiple item */ + RtlMoveMemory(PinRequest + 1, MultipleItem, sizeof(KSMULTIPLE_ITEM) + InputFormat->DataFormat.FormatSize); + + /* Query the miniport data intersection handler size */ + Status = KsSynchronousIoControlDevice(Entry->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)PinRequest, Length, NULL, 0, &BytesReturned); + if (Status != STATUS_BUFFER_OVERFLOW) { - /* Failed to get data ranges */ + DPRINT1("Property Request KSPROPERTY_PIN_DATAINTERSECTION failed with 0x%lx\n", Status); + FreeItem(PinRequest); return Status; } - MultipleItem = AllocateItem(NonPagedPool, BytesReturned); - if (!MultipleItem) + /* Allocate data range */ + DataRangeAudio = AllocateItem(NonPagedPool, BytesReturned); + if (!DataRangeAudio) { FreeItem(PinRequest); - return STATUS_NO_MEMORY; + return STATUS_INSUFFICIENT_RESOURCES; } - Status = KsSynchronousIoControlDevice(Entry->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)PinRequest, sizeof(KSP_PIN), (PVOID)MultipleItem, BytesReturned, &BytesReturned); + /* Query the miniport data intersection handler */ + Status = KsSynchronousIoControlDevice(Entry->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)PinRequest, Length, (PVOID)DataRangeAudio, BytesReturned, &BytesReturned); if (!NT_SUCCESS(Status)) { - DPRINT("Property Request KSPROPERTY_PIN_DATARANGES failed with %x\n", Status); - FreeItem(MultipleItem); + DPRINT1("Property Request KSPROPERTY_PIN_DATAINTERSECTION failed with 0x%lx\n", Status); + FreeItem(DataRangeAudio); FreeItem(PinRequest); - return STATUS_UNSUCCESSFUL; + return Status; } - AudioRange = (PKSDATARANGE_AUDIO)(MultipleItem + 1); - bFound = FALSE; - for(Index = 0; Index < MultipleItem->Count; Index++) + /* HACK: normalize audio data range values in case they exceed maximal values. + * KSPROPERTY_PIN_DATARANGES doesn't work correctly and returns abnormally high values somewhy. + * TODO: investigate why! + */ + if (DataRangeAudio->MaximumChannels != 2) + DataRangeAudio->MaximumChannels = 2; + if (DataRangeAudio->MaximumBitsPerSample != 16) + DataRangeAudio->MaximumBitsPerSample = 16; + if (DataRangeAudio->MaximumSampleFrequency > 48000) + DataRangeAudio->MaximumSampleFrequency = 48000; + + /* Select best quality available */ + OutputFormat->DataFormat.FormatSize = sizeof(KSDATAFORMAT) + sizeof(WAVEFORMATEX) + InputFormat->WaveFormatEx.cbSize; + OutputFormat->DataFormat.Flags = 0; + OutputFormat->DataFormat.Reserved = 0; + OutputFormat->DataFormat.MajorFormat = KSDATAFORMAT_TYPE_AUDIO; + OutputFormat->DataFormat.SubFormat = KSDATAFORMAT_SUBTYPE_PCM; + OutputFormat->DataFormat.Specifier = KSDATAFORMAT_SPECIFIER_WAVEFORMATEX; + OutputFormat->DataFormat.SampleSize = 4; + OutputFormat->WaveFormatEx.wFormatTag = InputFormat->WaveFormatEx.wFormatTag; + OutputFormat->WaveFormatEx.nChannels = min(InputFormat->WaveFormatEx.nChannels, DataRangeAudio->MaximumChannels); + OutputFormat->WaveFormatEx.wBitsPerSample = min(InputFormat->WaveFormatEx.wBitsPerSample, DataRangeAudio->MaximumBitsPerSample); + OutputFormat->WaveFormatEx.nSamplesPerSec = min(InputFormat->WaveFormatEx.nSamplesPerSec, DataRangeAudio->MaximumSampleFrequency); + OutputFormat->WaveFormatEx.nBlockAlign = (OutputFormat->WaveFormatEx.nChannels * OutputFormat->WaveFormatEx.wBitsPerSample) / 8; + OutputFormat->WaveFormatEx.nAvgBytesPerSec = OutputFormat->WaveFormatEx.nSamplesPerSec * OutputFormat->WaveFormatEx.nBlockAlign; + OutputFormat->WaveFormatEx.cbSize = InputFormat->WaveFormatEx.cbSize; + + /* Write additional fields for Extensible audio format */ + if (InputFormat->WaveFormatEx.wFormatTag == WAVE_FORMAT_EXTENSIBLE) { - if (AudioRange->DataRange.FormatSize != sizeof(KSDATARANGE_AUDIO)) - { - UNIMPLEMENTED; - AudioRange = (PKSDATARANGE_AUDIO)((PUCHAR)AudioRange + AudioRange->DataRange.FormatSize); - continue; - } - /* Select best quality available */ - - MixerFormat->DataFormat.FormatSize = sizeof(KSDATAFORMAT) + sizeof(WAVEFORMATEX); - MixerFormat->DataFormat.Flags = 0; - MixerFormat->DataFormat.Reserved = 0; - MixerFormat->DataFormat.MajorFormat = KSDATAFORMAT_TYPE_AUDIO; - MixerFormat->DataFormat.SubFormat = KSDATAFORMAT_SUBTYPE_PCM; - MixerFormat->DataFormat.Specifier = KSDATAFORMAT_SPECIFIER_WAVEFORMATEX; - MixerFormat->DataFormat.SampleSize = 4; - MixerFormat->WaveFormatEx.wFormatTag = ClientFormat->WaveFormatEx.wFormatTag; -#ifndef NO_AC97_HACK - /* HACK: AC97 does not support mono render / record */ - MixerFormat->WaveFormatEx.nChannels = 2; - /*HACK: AC97 only supports 16-Bit Bits */ - MixerFormat->WaveFormatEx.wBitsPerSample = 16; - -#else - MixerFormat->WaveFormatEx.nChannels = min(ClientFormat->WaveFormatEx.nChannels, AudioRange->MaximumChannels); - MixerFormat->WaveFormatEx.wBitsPerSample = AudioRange->MaximumBitsPerSample; -#endif - -#ifdef KMIXER_RESAMPLING_IMPLEMENTED - MixerFormat->WaveFormatEx.nSamplesPerSec = AudioRange->MaximumSampleFrequency; -#else - MixerFormat->WaveFormatEx.nSamplesPerSec = max(AudioRange->MinimumSampleFrequency, min(ClientFormat->WaveFormatEx.nSamplesPerSec, AudioRange->MaximumSampleFrequency)); -#endif - - MixerFormat->WaveFormatEx.cbSize = 0; - MixerFormat->WaveFormatEx.nBlockAlign = (MixerFormat->WaveFormatEx.nChannels * MixerFormat->WaveFormatEx.wBitsPerSample) / 8; - MixerFormat->WaveFormatEx.nAvgBytesPerSec = MixerFormat->WaveFormatEx.nChannels * MixerFormat->WaveFormatEx.nSamplesPerSec * (MixerFormat->WaveFormatEx.wBitsPerSample / 8); - - bFound = TRUE; - break; - - AudioRange = (PKSDATARANGE_AUDIO)((PUCHAR)AudioRange + AudioRange->DataRange.FormatSize); + PWAVEFORMATEXTENSIBLE WaveFormatExtensible = (PWAVEFORMATEXTENSIBLE)&OutputFormat->WaveFormatEx; + WaveFormatExtensible->SubFormat = KSDATAFORMAT_SUBTYPE_PCM; + WaveFormatExtensible->Samples.wValidBitsPerSample = OutputFormat->WaveFormatEx.wBitsPerSample; + if (OutputFormat->WaveFormatEx.nChannels == 0) + WaveFormatExtensible->dwChannelMask = KSAUDIO_SPEAKER_DIRECTOUT; + else if (OutputFormat->WaveFormatEx.nChannels == 1) + WaveFormatExtensible->dwChannelMask = KSAUDIO_SPEAKER_MONO; + else if (OutputFormat->WaveFormatEx.nChannels == 2) + WaveFormatExtensible->dwChannelMask = KSAUDIO_SPEAKER_STEREO; + else if (OutputFormat->WaveFormatEx.nChannels == 4) + WaveFormatExtensible->dwChannelMask = KSAUDIO_SPEAKER_QUAD; + else if (OutputFormat->WaveFormatEx.nChannels == 5) + WaveFormatExtensible->dwChannelMask = KSAUDIO_SPEAKER_5POINT1; + else if (OutputFormat->WaveFormatEx.nChannels == 7) + WaveFormatExtensible->dwChannelMask = KSAUDIO_SPEAKER_7POINT1; } -#if 0 - DPRINT1("\nNum Max Channels %u Channels %u Old Channels %u\n Max SampleRate %u SampleRate %u Old SampleRate %u\n Max BitsPerSample %u BitsPerSample %u Old BitsPerSample %u\n", - AudioRange->MaximumChannels, MixerFormat->WaveFormatEx.nChannels, ClientFormat->WaveFormatEx.nChannels, - AudioRange->MaximumSampleFrequency, MixerFormat->WaveFormatEx.nSamplesPerSec, ClientFormat->WaveFormatEx.nSamplesPerSec, - AudioRange->MaximumBitsPerSample, MixerFormat->WaveFormatEx.wBitsPerSample, ClientFormat->WaveFormatEx.wBitsPerSample); - - -#endif - - FreeItem(MultipleItem); + FreeItem(DataRangeAudio); FreeItem(PinRequest); - if (bFound) - return STATUS_SUCCESS; - else - return STATUS_NOT_IMPLEMENTED; + return STATUS_SUCCESS; } NTSTATUS @@ -363,7 +376,7 @@ SysAudioHandleProperty( if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < BytesReturned) { /* too small buffer */ - return SetIrpIoStatus(Irp, STATUS_BUFFER_TOO_SMALL, BytesReturned); + return SetIrpIoStatus(Irp, STATUS_BUFFER_OVERFLOW, BytesReturned); } /* copy device name */ @@ -423,7 +436,8 @@ SysAudioHandleProperty( *((PULONG)Irp->UserBuffer) = DeviceExtension->NumberOfKsAudioDevices; return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(ULONG)); } - else if (Property->Id == KSPROPERTY_SYSAUDIO_DEVICE_INSTANCE) + else if (Property->Id == KSPROPERTY_SYSAUDIO_DEVICE_INSTANCE || + Property->Id == KSPROPERTY_SYSAUDIO_DEVICE_DEFAULT) { if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(ULONG)) { diff --git a/drivers/wdm/audio/sysaudio/deviface.c b/drivers/wdm/audio/sysaudio/deviface.c index fa4e3756c12b6..b1e1f95b3914b 100644 --- a/drivers/wdm/audio/sysaudio/deviface.c +++ b/drivers/wdm/audio/sysaudio/deviface.c @@ -8,13 +8,14 @@ #include "sysaudio.h" -#define NDEBUG +#define YDEBUG #include const GUID GUID_DEVICE_INTERFACE_ARRIVAL = {0xCB3A4004L, 0x46F0, 0x11D0, {0xB0, 0x8F, 0x00, 0x60, 0x97, 0x13, 0x05, 0x3F}}; const GUID GUID_DEVICE_INTERFACE_REMOVAL = {0xCB3A4005L, 0x46F0, 0x11D0, {0xB0, 0x8F, 0x00, 0x60, 0x97, 0x13, 0x05, 0x3F}}; const GUID KS_CATEGORY_AUDIO = {0x6994AD04L, 0x93EF, 0x11D0, {0xA3, 0xCC, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}}; -const GUID KS_CATEGORY_TOPOLOGY = {0xDDA54A40, 0x1E4C, 0x11D1, {0xA0, 0x50, 0x40, 0x57, 0x05, 0xC1, 0x00, 0x00}}; +const GUID KS_CATEGORY_TOPOLOGY = {0xDDA54A40L, 0x1E4C, 0x11D1, {0xA0, 0x50, 0x40, 0x57, 0x05, 0xC1, 0x00, 0x00}}; +const GUID KS_CATEGORY_WDMAUD = {0x3E227E76L, 0x690D, 0x11D2, {0x81, 0x61, 0x00, 0x00, 0xF8, 0x77, 0x5B, 0xF1}}; const GUID DMOCATEGORY_ACOUSTIC_ECHO_CANCEL = {0xBF963D80L, 0xC559, 0x11D0, {0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1}}; NTSTATUS @@ -103,16 +104,6 @@ InsertAudioDevice( RtlAppendUnicodeStringToString(&DeviceEntry->DeviceName, DeviceName); } else - { - /* the device name needs to be prefixed */ - RtlAppendUnicodeToString(&DeviceEntry->DeviceName, L"\\??\\"); - RtlAppendUnicodeStringToString(&DeviceEntry->DeviceName, DeviceName); - - /* open device */ - Status = OpenDevice(&DeviceEntry->DeviceName, &DeviceEntry->Handle, &DeviceEntry->FileObject); - } - - if (!NT_SUCCESS(Status)) { goto cleanup; } @@ -124,7 +115,7 @@ InsertAudioDevice( InterlockedIncrement((PLONG)&DeviceExtension->NumberOfKsAudioDevices); DPRINT("Successfully opened audio device %u Device %S\n", DeviceExtension->NumberOfKsAudioDevices, DeviceEntry->DeviceName.Buffer); - return Status; + return STATUS_SUCCESS; cleanup: if (DeviceEntry) diff --git a/drivers/wdm/audio/sysaudio/dispatcher.c b/drivers/wdm/audio/sysaudio/dispatcher.c index f673a738181c9..c991568d11458 100644 --- a/drivers/wdm/audio/sysaudio/dispatcher.c +++ b/drivers/wdm/audio/sysaudio/dispatcher.c @@ -8,9 +8,11 @@ #include "sysaudio.h" -#define NDEBUG +#define YDEBUG #include +const GUID KSCATEGORY_MIXER = {0xAD809C00L, 0x7B88, 0x11D0, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}}; + NTSTATUS NTAPI Dispatch_fnDeviceIoControl( @@ -133,21 +135,48 @@ SysAudioOpenKMixer( IN SYSAUDIODEVEXT *DeviceExtension) { NTSTATUS Status; - UNICODE_STRING DeviceInstanceName = RTL_CONSTANT_STRING(L"\\Device\\kmixer\\GLOBAL"); + LPWSTR SymbolicLinkList, SymbolicLink; + UNICODE_STRING SymbolicLinkU; UNICODE_STRING DevicePath = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\kmixer"); Status = ZwLoadDriver(&DevicePath); if (NT_SUCCESS(Status)) { - Status = OpenDevice(&DeviceInstanceName, &DeviceExtension->KMixerHandle, &DeviceExtension->KMixerFileObject); + Status = IoGetDeviceInterfaces(&KSCATEGORY_MIXER, + NULL, + 0, + &SymbolicLinkList); + if (!NT_SUCCESS(Status)) { + DPRINT1("IoGetDeviceInterfaces failed with status 0x%lx\n", Status); DeviceExtension->KMixerHandle = NULL; DeviceExtension->KMixerFileObject = NULL; + return Status; + } + + for (SymbolicLink = SymbolicLinkList; + *SymbolicLink != UNICODE_NULL; + SymbolicLink += wcslen(SymbolicLink) + 1) + { + DPRINT("Opening device %S\n", SymbolicLink); + RtlInitUnicodeString(&SymbolicLinkU, SymbolicLink); + Status = OpenDevice(&SymbolicLinkU, &DeviceExtension->KMixerHandle, &DeviceExtension->KMixerFileObject); + if (NT_SUCCESS(Status)) + { + DPRINT("Successfully opened %S, handle %p\n", SymbolicLink, DeviceExtension->KMixerHandle); + break; + } + else + { + RtlFreeUnicodeString(&SymbolicLinkU); + DeviceExtension->KMixerHandle = NULL; + DeviceExtension->KMixerFileObject = NULL; + } } } - DPRINT("Status %lx KMixerHandle %p KMixerFileObject %p\n", Status, DeviceExtension->KMixerHandle, DeviceExtension->KMixerFileObject); - return STATUS_SUCCESS; + DPRINT("Status 0x%lx KMixerHandle %p KMixerFileObject %p\n", Status, DeviceExtension->KMixerHandle, DeviceExtension->KMixerFileObject); + return Status; } diff --git a/drivers/wdm/audio/sysaudio/main.c b/drivers/wdm/audio/sysaudio/main.c index 12e5b2aacfc42..6f306bda07d9c 100644 --- a/drivers/wdm/audio/sysaudio/main.c +++ b/drivers/wdm/audio/sysaudio/main.c @@ -11,7 +11,7 @@ #include "sysaudio.h" -#define NDEBUG +#define YDEBUG #include #define TAG_SYSAUDIO 'AsyS' @@ -197,14 +197,6 @@ SysAudio_AddDevice( goto cleanup; } - /* Load kmixer */ - Status = SysAudioOpenKMixer(DeviceExtension); - if (!NT_SUCCESS(Status)) - { - DPRINT1("SysAudioOpenKMixer failed with %x\n", Status); - goto cleanup; - } - /* set io flags */ DeviceObject->Flags |= DO_DIRECT_IO | DO_POWER_PAGABLE; /* clear initializing flag */ diff --git a/drivers/wdm/audio/sysaudio/pin.c b/drivers/wdm/audio/sysaudio/pin.c index dd9663a31d9d8..534251ea8fbd8 100644 --- a/drivers/wdm/audio/sysaudio/pin.c +++ b/drivers/wdm/audio/sysaudio/pin.c @@ -8,22 +8,36 @@ #include "sysaudio.h" -#define NDEBUG +#define YDEBUG #include + NTSTATUS NTAPI -Pin_fnDeviceIoControl( +Pin_fnRead( + PDEVICE_OBJECT DeviceObject, + PIRP Irp) +{ + UNIMPLEMENTED; + + Irp->IoStatus.Status = STATUS_SUCCESS; + Irp->IoStatus.Information = 0; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + return STATUS_SUCCESS; +} + +NTSTATUS +NTAPI +Pin_fnWrite( PDEVICE_OBJECT DeviceObject, PIRP Irp) { PDISPATCH_CONTEXT Context; - NTSTATUS Status; - ULONG BytesReturned; - PFILE_OBJECT FileObject = NULL; PIO_STACK_LOCATION IoStack; + PFILE_OBJECT FileObject; + NTSTATUS Status; - DPRINT("Pin_fnDeviceIoControl called DeviceObject %p Irp %p\n", DeviceObject, Irp); + DPRINT("Pin_fnWrite called DeviceObject %p Irp %p\n", DeviceObject, Irp); /* Get current stack location */ IoStack = IoGetCurrentIrpStackLocation(Irp); @@ -33,71 +47,95 @@ Pin_fnDeviceIoControl( /* Sanity check */ ASSERT(Context); +#if 0 + if (Context->hMixerPin) + { + /* Acquire kmixer pin file object */ + Status = ObReferenceObjectByHandle(Context->hMixerPin, GENERIC_WRITE, *IoFileObjectType, KernelMode, (PVOID*)&FileObject, NULL); + if (!NT_SUCCESS(Status)) + { + DPRINT1("Failed to reference kmixer pin file object with status 0x%lx\n", Status); + return Status; + } - /* acquire real pin file object */ + /* Skip current irp location */ + IoSkipCurrentIrpStackLocation(Irp); + + /* Get next irp stack location */ + IoStack = IoGetNextIrpStackLocation(Irp); + + /* Setup stack parameters */ + IoStack->MajorFunction = IRP_MJ_WRITE; + IoStack->FileObject = FileObject; + + /* Call kmixer to convert stream */ + IoCallDriver(IoGetRelatedDeviceObject(FileObject), Irp); + + /* Dereference file object */ + ObDereferenceObject(FileObject); + } +#endif + /* Acquire sysaudio pin file object */ Status = ObReferenceObjectByHandle(Context->Handle, GENERIC_WRITE, *IoFileObjectType, KernelMode, (PVOID*)&FileObject, NULL); if (!NT_SUCCESS(Status)) { - Irp->IoStatus.Information = 0; - Irp->IoStatus.Status = Status; - /* Complete the irp */ - IoCompleteRequest(Irp, IO_NO_INCREMENT); + DPRINT1("Failed to reference sysaudio pin file object with status 0x%lx\n", Status); return Status; } - /* Re-dispatch the request to the real target pin */ - Status = KsSynchronousIoControlDevice(FileObject, KernelMode, IoStack->Parameters.DeviceIoControl.IoControlCode, - IoStack->Parameters.DeviceIoControl.Type3InputBuffer, - IoStack->Parameters.DeviceIoControl.InputBufferLength, - Irp->UserBuffer, - IoStack->Parameters.DeviceIoControl.OutputBufferLength, - &BytesReturned); - /* release file object */ + /* Skip current irp location */ + IoSkipCurrentIrpStackLocation(Irp); + + /* Get next irp stack location */ + IoStack = IoGetNextIrpStackLocation(Irp); + + /* Setup stack parameters */ + IoStack->MajorFunction = IRP_MJ_DEVICE_CONTROL; + IoStack->FileObject = FileObject; + + /* Send the stream */ + IoCallDriver(IoGetRelatedDeviceObject(FileObject), Irp); + + /* Dereference file object */ ObDereferenceObject(FileObject); - /* Save status and information */ - Irp->IoStatus.Information = BytesReturned; - Irp->IoStatus.Status = Status; - /* Complete the irp */ - IoCompleteRequest(Irp, IO_NO_INCREMENT); /* Done */ - return Status; + return STATUS_PENDING; } - - NTSTATUS NTAPI -Pin_fnWrite( +Pin_fnDeviceIoControl( PDEVICE_OBJECT DeviceObject, PIRP Irp) { PDISPATCH_CONTEXT Context; - PIO_STACK_LOCATION IoStack; - PFILE_OBJECT FileObject; NTSTATUS Status; + ULONG BytesReturned; + PFILE_OBJECT FileObject = NULL; + PIO_STACK_LOCATION IoStack; + + DPRINT("Pin_fnDeviceIoControl called DeviceObject %p Irp %p\n", DeviceObject, Irp); /* Get current stack location */ IoStack = IoGetCurrentIrpStackLocation(Irp); + /* Handle Read/Write I/O request */ + if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_READ_STREAM) + return Pin_fnRead(DeviceObject, Irp); + else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_WRITE_STREAM) + return Pin_fnWrite(DeviceObject, Irp); + /* The dispatch context is stored in the FsContext member */ Context = (PDISPATCH_CONTEXT)IoStack->FileObject->FsContext; /* Sanity check */ ASSERT(Context); - if (Context->hMixerPin) - { - // FIXME - // call kmixer to convert stream - UNIMPLEMENTED; - } - /* acquire real pin file object */ Status = ObReferenceObjectByHandle(Context->Handle, GENERIC_WRITE, *IoFileObjectType, KernelMode, (PVOID*)&FileObject, NULL); if (!NT_SUCCESS(Status)) { - DPRINT1("failed\n"); Irp->IoStatus.Information = 0; Irp->IoStatus.Status = Status; /* Complete the irp */ @@ -105,24 +143,23 @@ Pin_fnWrite( return Status; } - /* skip current irp location */ - IoSkipCurrentIrpStackLocation(Irp); - - /* get next stack location */ - IoStack = IoGetNextIrpStackLocation(Irp); - /* store file object of next device object */ - IoStack->FileObject = FileObject; - IoStack->MajorFunction = IRP_MJ_DEVICE_CONTROL; - //ASSERT(Irp->AssociatedIrp.SystemBuffer); - - /* now call the driver */ - Status = IoCallDriver(IoGetRelatedDeviceObject(FileObject), Irp); - - /* dereference file object */ + /* Re-dispatch the request to the real target pin */ + Status = KsSynchronousIoControlDevice(FileObject, KernelMode, IoStack->Parameters.DeviceIoControl.IoControlCode, + IoStack->Parameters.DeviceIoControl.Type3InputBuffer, + IoStack->Parameters.DeviceIoControl.InputBufferLength, + Irp->UserBuffer, + IoStack->Parameters.DeviceIoControl.OutputBufferLength, + &BytesReturned); + /* release file object */ ObDereferenceObject(FileObject); + /* Save status and information */ + Irp->IoStatus.Information = BytesReturned; + Irp->IoStatus.Status = Status; + /* Complete the irp */ + IoCompleteRequest(Irp, IO_NO_INCREMENT); + /* Done */ return Status; - } NTSTATUS @@ -134,7 +171,7 @@ Pin_fnClose( PDISPATCH_CONTEXT Context; PIO_STACK_LOCATION IoStack; - //DPRINT("Pin_fnClose called DeviceObject %p Irp %p\n", DeviceObject, Irp); + DPRINT("Pin_fnClose called DeviceObject %p Irp %p\n", DeviceObject, Irp); /* Get current stack location */ IoStack = IoGetCurrentIrpStackLocation(Irp); @@ -163,7 +200,7 @@ Pin_fnClose( static KSDISPATCH_TABLE PinTable = { Pin_fnDeviceIoControl, - KsDispatchInvalidDeviceRequest, + Pin_fnRead, Pin_fnWrite, KsDispatchInvalidDeviceRequest, Pin_fnClose, @@ -230,8 +267,8 @@ CreateMixerPinAndSetFormat( if (!NT_SUCCESS(Status)) { - DPRINT1("Failed to create Mixer Pin with %x\n", Status); - return STATUS_UNSUCCESSFUL; + DPRINT1("Failed to create Mixer Pin with 0x%lx\n", Status); + return Status; } Status = ObReferenceObjectByHandle(PinHandle, @@ -240,8 +277,9 @@ CreateMixerPinAndSetFormat( if (!NT_SUCCESS(Status)) { - DPRINT1("Failed to get file object with %x\n", Status); - return STATUS_UNSUCCESSFUL; + DPRINT1("Failed to get file object with 0x%lx\n", Status); + ZwClose(PinHandle); + return Status; } Status = SetMixerInputOutputFormat(FileObject, InputFormat, OutputFormat); @@ -252,10 +290,11 @@ CreateMixerPinAndSetFormat( return Status; } + *MixerPinHandle = PinHandle; + ObDereferenceObject(FileObject); - *MixerPinHandle = PinHandle; - return Status; + return Status; } @@ -269,8 +308,7 @@ InstantiatePins( { NTSTATUS Status; HANDLE RealPinHandle; - PKSDATAFORMAT_WAVEFORMATEX InputFormat; - PKSDATAFORMAT_WAVEFORMATEX OutputFormat = NULL; + PKSDATAFORMAT_WAVEFORMATEX InputFormat, OutputFormat = NULL; PKSPIN_CONNECT MixerPinConnect = NULL; KSPIN_CINSTANCES PinInstances; @@ -306,39 +344,42 @@ InstantiatePins( /* Let's try to create the audio irp pin */ Status = KsCreatePin(DeviceEntry->Handle, Connect, GENERIC_READ | GENERIC_WRITE, &RealPinHandle); - if (!NT_SUCCESS(Status)) - { - /* FIXME disable kmixer - */ - return STATUS_UNSUCCESSFUL; - } -#if 0 if (!NT_SUCCESS(Status)) { /* the audio irp pin didnt accept the input format * let's compute a compatible format */ - MixerPinConnect = AllocateItem(NonPagedPool, sizeof(KSPIN_CONNECT) + sizeof(KSDATAFORMAT_WAVEFORMATEX)); +#if 0 + if (!DeviceExtension->KMixerHandle || !DeviceExtension->KMixerFileObject) + { + /* Load kmixer */ + Status = SysAudioOpenKMixer(DeviceExtension); + if (!NT_SUCCESS(Status)) + { + DPRINT1("SysAudioOpenKMixer failed with 0x%lx\n", Status); + return Status; + } + } +#endif + /* Allocate pin connect */ + MixerPinConnect = AllocateItem(NonPagedPool, sizeof(KSPIN_CONNECT) + sizeof(KSDATAFORMAT_WAVEFORMATEX) + InputFormat->WaveFormatEx.cbSize); if (!MixerPinConnect) { /* not enough memory */ return STATUS_INSUFFICIENT_RESOURCES; } - /* Zero pin connect */ - RtlZeroMemory(MixerPinConnect, sizeof(KSPIN_CONNECT) + sizeof(KSDATAFORMAT_WAVEFORMATEX)); - /* Copy initial connect details */ RtlMoveMemory(MixerPinConnect, Connect, sizeof(KSPIN_CONNECT)); - + /* Fetch output format */ OutputFormat = (PKSDATAFORMAT_WAVEFORMATEX)(MixerPinConnect + 1); + /* Compute compatible format */ Status = ComputeCompatibleFormat(DeviceEntry, Connect->PinId, InputFormat, OutputFormat); if (!NT_SUCCESS(Status)) { - DPRINT1("ComputeCompatibleFormat failed with %x\n", Status); - FreeItem(MixerPinConnect); + DPRINT1("ComputeCompatibleFormat failed with 0x%lx\n", Status); return Status; } @@ -346,8 +387,8 @@ InstantiatePins( Status = KsCreatePin(DeviceEntry->Handle, MixerPinConnect, GENERIC_READ | GENERIC_WRITE, &RealPinHandle); if (!NT_SUCCESS(Status)) { - /* This should not fail */ - DPRINT1("KsCreatePin failed with %x\n", Status); + /* This should not fail */ + DPRINT1("KsCreatePin failed with 0x%lx\n", Status); DPRINT1(" InputFormat: SampleRate %u Bits %u Channels %u\n", InputFormat->WaveFormatEx.nSamplesPerSec, InputFormat->WaveFormatEx.wBitsPerSample, InputFormat->WaveFormatEx.nChannels); DPRINT1("OutputFormat: SampleRate %u Bits %u Channels %u\n", OutputFormat->WaveFormatEx.nSamplesPerSec, OutputFormat->WaveFormatEx.wBitsPerSample, OutputFormat->WaveFormatEx.nChannels); @@ -355,7 +396,6 @@ InstantiatePins( return Status; } } -#endif //DeviceEntry->Pins[Connect->PinId].References = 0; @@ -364,9 +404,9 @@ InstantiatePins( DispatchContext->PinId = Connect->PinId; DispatchContext->AudioEntry = DeviceEntry; - DPRINT("RealPinHandle %p\n", RealPinHandle); - + DPRINT("OutputFormat %p\n", OutputFormat); +#if 0 /* Do we need to transform the audio stream */ if (OutputFormat != NULL) { @@ -380,10 +420,12 @@ InstantiatePins( /* check for success */ if (!NT_SUCCESS(Status)) { - DPRINT1("Failed to create Mixer Pin with %x\n", Status); + DPRINT1("Failed to create Mixer Pin with 0x%lx\n", Status); + FreeItem(OutputFormat); FreeItem(MixerPinConnect); } } +#endif /* done */ return Status; } @@ -419,7 +461,7 @@ GetConnectRequest( RtlMoveMemory(Buffer, &IoStack->FileObject->FileName.Buffer[ObjectLength / sizeof(WCHAR)], ParametersLength); /* store result */ - *Result = (PKSPIN_CONNECT)Buffer; + *Result = Buffer; return STATUS_SUCCESS; } @@ -432,7 +474,7 @@ DispatchCreateSysAudioPin( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { - NTSTATUS Status = STATUS_SUCCESS; + NTSTATUS Status; PIO_STACK_LOCATION IoStack; PKSAUDIO_DEVICE_ENTRY DeviceEntry; PKSPIN_CONNECT Connect; @@ -451,15 +493,6 @@ DispatchCreateSysAudioPin( /* get current attached virtual device */ DeviceEntry = (PKSAUDIO_DEVICE_ENTRY)IoStack->FileObject->RelatedFileObject->FsContext; - /* check for success */ - if (!NT_SUCCESS(Status)) - { - /* failed */ - Irp->IoStatus.Status = Status; - IoCompleteRequest(Irp, IO_NO_INCREMENT); - return Status; - } - /* get connect details */ Status = GetConnectRequest(Irp, &Connect); diff --git a/drivers/wdm/audio/sysaudio/sysaudio.h b/drivers/wdm/audio/sysaudio/sysaudio.h index 5a18cc96f136b..b6e89db9fd28f 100644 --- a/drivers/wdm/audio/sysaudio/sysaudio.h +++ b/drivers/wdm/audio/sysaudio/sysaudio.h @@ -2,6 +2,7 @@ #define _SYSAUDIO_PCH_ #include +#include typedef struct { @@ -107,8 +108,8 @@ NTSTATUS ComputeCompatibleFormat( IN PKSAUDIO_DEVICE_ENTRY Entry, IN ULONG PinId, - IN PKSDATAFORMAT_WAVEFORMATEX ClientFormat, - OUT PKSDATAFORMAT_WAVEFORMATEX MixerFormat); + IN PKSDATAFORMAT_WAVEFORMATEX InputFormat, + OUT PKSDATAFORMAT_WAVEFORMATEX OutputFormat); PVOID AllocateItem( diff --git a/sdk/include/psdk/ks.h b/sdk/include/psdk/ks.h index 05a1dc9ed347c..9080f289d5259 100644 --- a/sdk/include/psdk/ks.h +++ b/sdk/include/psdk/ks.h @@ -5050,6 +5050,23 @@ KsFilterFactoryGetDevice( return KsGetDevice((PVOID)FilterFactory); } +_IRQL_requires_max_(PASSIVE_LEVEL) +KSDDKAPI +PVOID +NTAPI +KsGetObjectFromFileObject( + IN PFILE_OBJECT FileObject); + +_IRQL_requires_max_(PASSIVE_LEVEL) +static +__inline +PKSPIN +KsGetPinFromFileObject( + IN PFILE_OBJECT FileObject) +{ + return (PKSPIN)KsGetObjectFromFileObject(FileObject); +} + /* etc. */ #endif /* avstream */ diff --git a/sdk/include/psdk/ksmedia.h b/sdk/include/psdk/ksmedia.h index 83e717e9e93eb..db76f63c33298 100644 --- a/sdk/include/psdk/ksmedia.h +++ b/sdk/include/psdk/ksmedia.h @@ -191,6 +191,12 @@ DEFINE_GUIDSTRUCT("67C9CC3C-69C4-11D2-8759-00A0C9223196", KSCATEGORY_NETWORK); DEFINE_GUIDSTRUCT("3A13EB40-30A7-11D0-A5D6-28DB04C10000", KSINTERFACESETID_Media); #define KSINTERFACESETID_Media DEFINE_GUIDNAMED(KSINTERFACESETID_Media) +typedef enum { + KSINTERFACE_MEDIA_MUSIC, + KSINTERFACE_MEDIA_WAVE_BUFFERED, + KSINTERFACE_MEDIA_WAVE_QUEUED +} KSINTERFACE_MEDIA; + /* ... */ #define STATIC_KSCATEGORY_TOPOLOGY \ @@ -647,6 +653,11 @@ typedef struct { } WAVEFORMATEXTENSIBLE, *PWAVEFORMATEXTENSIBLE; #endif +typedef struct { + KSDATAFORMAT DataFormat; + WAVEFORMATEXTENSIBLE WaveFormatExt; +} KSDATAFORMAT_WAVEFORMATEXTENSIBLE, *PKSDATAFORMAT_WAVEFORMATEXTENSIBLE; + #if !defined(WAVE_FORMAT_EXTENSIBLE) #define WAVE_FORMAT_EXTENSIBLE 0xFFFE #endif diff --git a/sdk/include/psdk/mmddk.h b/sdk/include/psdk/mmddk.h index 48e7fb9ca58c1..293b8e5d049b5 100644 --- a/sdk/include/psdk/mmddk.h +++ b/sdk/include/psdk/mmddk.h @@ -395,6 +395,11 @@ typedef JOYDEVMSGPROC *LPJOYDEVMSGPROC; #define MAKEMCIRESOURCE(wRet, wRes) MAKELRESULT((wRet), (wRes)) +typedef struct { + DWORD cbSize; + LPVOID pCaps; +} MDEVICECAPSEX; + typedef struct { DWORD_PTR dwCallback; DWORD_PTR dwInstance; diff --git a/sdk/include/reactos/libs/sound/sndtypes.h b/sdk/include/reactos/libs/sound/sndtypes.h index 2f2017b24e068..0403c59c755d8 100644 --- a/sdk/include/reactos/libs/sound/sndtypes.h +++ b/sdk/include/reactos/libs/sound/sndtypes.h @@ -25,16 +25,16 @@ typedef enum { // The sound device types - WAVE_IN_DEVICE_TYPE = 1, - WAVE_OUT_DEVICE_TYPE = 2, - MIDI_IN_DEVICE_TYPE = 3, - MIDI_OUT_DEVICE_TYPE = 4, - AUX_DEVICE_TYPE = 5, - MIXER_DEVICE_TYPE = 6, + WAVE_IN_DEVICE_TYPE = 0, + WAVE_OUT_DEVICE_TYPE = 1, + MIDI_IN_DEVICE_TYPE = 2, + MIDI_OUT_DEVICE_TYPE = 3, + MIXER_DEVICE_TYPE = 4, + AUX_DEVICE_TYPE = 5, // Range of valid device type IDs - MIN_SOUND_DEVICE_TYPE = 1, - MAX_SOUND_DEVICE_TYPE = 6, + MIN_SOUND_DEVICE_TYPE = 0, + MAX_SOUND_DEVICE_TYPE = 5, // Number of sound device types SOUND_DEVICE_TYPES = 6 diff --git a/sdk/lib/drivers/sound/mmixer/controls.c b/sdk/lib/drivers/sound/mmixer/controls.c index a7521bf4dd335..a7051bc3741af 100644 --- a/sdk/lib/drivers/sound/mmixer/controls.c +++ b/sdk/lib/drivers/sound/mmixer/controls.c @@ -1543,8 +1543,8 @@ MMixerInitializeFilter( /* intialize mixer caps */ MixerInfo->MixCaps.wMid = MM_MICROSOFT; /* FIXME */ - MixerInfo->MixCaps.wPid = MM_PID_UNMAPPED; /* FIXME */ - MixerInfo->MixCaps.vDriverVersion = 1; /* FIXME */ + MixerInfo->MixCaps.wPid = MM_MSFT_WDMAUDIO_MIXER; /* FIXME */ + MixerInfo->MixCaps.vDriverVersion = 0x050a; /* FIXME */ MixerInfo->MixCaps.fdwSupport = 0; MixerInfo->MixCaps.cDestinations = 0; @@ -1584,7 +1584,6 @@ MMixerInitializeFilter( * For source pins (wave in) search down stream * The search direction is always the opposite of the current mixer type */ - PinsFound = 0; MMixerGetAllUpOrDownstreamPinsFromNodeIndex(MixerContext, Topology, NodeIndex, !bInputMixer, &PinsFound, Pins); /* if there is no pin found, we have a broken topology */ diff --git a/sdk/lib/drivers/sound/mmixer/filter.c b/sdk/lib/drivers/sound/mmixer/filter.c index 19033c831add2..92079c34448cd 100644 --- a/sdk/lib/drivers/sound/mmixer/filter.c +++ b/sdk/lib/drivers/sound/mmixer/filter.c @@ -180,11 +180,6 @@ MMixerGetControlTypeFromTopologyNode( /* mux control */ return MIXERCONTROL_CONTROLTYPE_MUX; } - else if (IsEqualGUIDAligned(NodeType, (LPGUID)&KSNODETYPE_MUX)) - { - /* mux control */ - return MIXERCONTROL_CONTROLTYPE_MUX; - } else if (IsEqualGUIDAligned(NodeType, (LPGUID)&KSNODETYPE_STEREO_WIDE)) { /* stero wide control */ diff --git a/sdk/lib/drivers/sound/mmixer/midi.c b/sdk/lib/drivers/sound/mmixer/midi.c index acca89ca5adbf..88eafe9580bb6 100644 --- a/sdk/lib/drivers/sound/mmixer/midi.c +++ b/sdk/lib/drivers/sound/mmixer/midi.c @@ -75,30 +75,7 @@ MMixerAddMidiPin( ASSERT(!DeviceName || (wcslen(DeviceName) < MAXPNAMELEN)); /* copy device name */ - if (bInput && DeviceName) - { - wcscpy(MidiInfo->u.InCaps.szPname, DeviceName); - } - else if (!bInput && DeviceName) - { - wcscpy(MidiInfo->u.OutCaps.szPname, DeviceName); - } - - /* FIXME determine manufacturer / product id */ - if (bInput) - { - MidiInfo->u.InCaps.dwSupport = 0; - MidiInfo->u.InCaps.wMid = MM_MICROSOFT; - MidiInfo->u.InCaps.wPid = MM_PID_UNMAPPED; - MidiInfo->u.InCaps.vDriverVersion = 1; - } - else - { - MidiInfo->u.OutCaps.dwSupport = 0; - MidiInfo->u.OutCaps.wMid = MM_MICROSOFT; - MidiInfo->u.OutCaps.wPid = MM_PID_UNMAPPED; - MidiInfo->u.OutCaps.vDriverVersion = 1; - } + MidiInfo->DeviceName = DeviceName; if (bInput) { @@ -187,7 +164,7 @@ MMixerInitializeMidiForFilter( if (MMixerGetDeviceName(MixerContext, szPname, MixerData->hDeviceInterfaceKey) != MM_STATUS_SUCCESS) { /* clear name */ - szPname[0] = 0; + szPname[0] = L'\0'; } /* iterate all pins and check for KSDATARANGE_MUSIC support */ @@ -334,8 +311,29 @@ MMixerMidiOutCapabilities( return MM_STATUS_UNSUCCESSFUL; } - /* copy capabilities */ - MixerContext->Copy(Caps, &MidiInfo->u.OutCaps, sizeof(MIDIOUTCAPSW)); + /* allocate capabilities */ + Caps = MixerContext->Alloc(sizeof(MIDIOUTCAPSW)); + if (!Caps) + { + /* no memory */ + return MM_STATUS_NO_MEMORY; + } + + /* FIXME determine manufacturer / product id */ + Caps->wMid = MM_MICROSOFT; + Caps->wPid = MM_MSFT_WDMAUDIO_MIDIOUT; + Caps->vDriverVersion = 0x050a; + Caps->wTechnology = MOD_MIDIPORT; /* FIXME */ + Caps->wVoices = 0; /* FIXME */ + Caps->wNotes = 0; /* FIXME */ + Caps->wChannelMask = 0xFFFF; /* FIXME */ + Caps->dwSupport = 0; /* FIXME */ + + /* copy device name */ + wcscpy(Caps->szPname, MidiInfo->DeviceName); + + /* make sure it's null terminated */ + Caps->szPname[MAXPNAMELEN-1] = L'\0'; return MM_STATUS_SUCCESS; } @@ -370,8 +368,25 @@ MMixerMidiInCapabilities( return MM_STATUS_UNSUCCESSFUL; } - /* copy capabilities */ - MixerContext->Copy(Caps, &MidiInfo->u.InCaps, sizeof(MIDIINCAPSW)); + /* allocate capabilities */ + Caps = MixerContext->Alloc(sizeof(MIDIINCAPSW)); + if (!Caps) + { + /* no memory */ + return MM_STATUS_NO_MEMORY; + } + + /* FIXME determine manufacturer / product id */ + Caps->wMid = MM_MICROSOFT; + Caps->wPid = MM_MSFT_WDMAUDIO_MIDIIN; + Caps->vDriverVersion = 0x050a; + Caps->dwSupport = 0; + + /* copy device name */ + wcscpy(Caps->szPname, MidiInfo->DeviceName); + + /* make sure it's null terminated */ + Caps->szPname[MAXPNAMELEN-1] = L'\0'; return MM_STATUS_SUCCESS; } @@ -426,9 +441,6 @@ MMixerGetMidiDevicePath( return MM_STATUS_NO_MEMORY; } - /* copy device path */ - MixerContext->Copy(*DevicePath, MixerData->DeviceName, Length * sizeof(WCHAR)); - /* done */ return MM_STATUS_SUCCESS; } diff --git a/sdk/lib/drivers/sound/mmixer/mixer.c b/sdk/lib/drivers/sound/mmixer/mixer.c index 4b98ed53ae3ea..0e7c4b36fc702 100644 --- a/sdk/lib/drivers/sound/mmixer/mixer.c +++ b/sdk/lib/drivers/sound/mmixer/mixer.c @@ -38,9 +38,11 @@ MIXER_STATUS MMixerGetCapabilities( IN PMIXER_CONTEXT MixerContext, IN ULONG MixerIndex, - OUT LPMIXERCAPSW MixerCaps) + OUT LPMIXERCAPSW Caps) { MIXER_STATUS Status; + PMIXER_LIST MixerList; + LPMIXER_DATA MixerData; LPMIXER_INFO MixerInfo; /* verify mixer context */ @@ -52,23 +54,45 @@ MMixerGetCapabilities( return Status; } + /* grab mixer list */ + MixerList = (PMIXER_LIST)MixerContext->MixerContext; + + /* get mixer data */ + MixerData = MMixerGetDataByDeviceId(MixerList, MixerIndex); + + if (!MixerData) + { + /* invalid device index */ + return MM_STATUS_INVALID_PARAMETER; + } + /* get mixer info */ MixerInfo = MMixerGetMixerInfoByIndex(MixerContext, MixerIndex); if (!MixerInfo) { - // invalid device index + /* invalid device index */ return MM_STATUS_INVALID_PARAMETER; } - MixerCaps->wMid = MixerInfo->MixCaps.wMid; - MixerCaps->wPid = MixerInfo->MixCaps.wPid; - MixerCaps->vDriverVersion = MixerInfo->MixCaps.vDriverVersion; - MixerCaps->fdwSupport = MixerInfo->MixCaps.fdwSupport; - MixerCaps->cDestinations = MixerInfo->MixCaps.cDestinations; + /* allocate capabilities */ + Caps = MixerContext->Alloc(sizeof(MIXERCAPSW)); + if (!Caps) + { + /* no memory */ + return MM_STATUS_NO_MEMORY; + } + /* intialize capabilities */ + Caps->wMid = MixerInfo->MixCaps.wMid; + Caps->wPid = MixerInfo->MixCaps.wPid; + Caps->vDriverVersion = MixerInfo->MixCaps.vDriverVersion; + Caps->fdwSupport = MixerInfo->MixCaps.fdwSupport; + Caps->cDestinations = MixerInfo->MixCaps.cDestinations; + + /* copy device name */ ASSERT(MixerInfo->MixCaps.szPname[MAXPNAMELEN-1] == 0); - wcscpy(MixerCaps->szPname, MixerInfo->MixCaps.szPname); + wcscpy(Caps->szPname, MixerInfo->MixCaps.szPname); return MM_STATUS_SUCCESS; } @@ -105,6 +129,12 @@ MMixerOpen( /* add the event */ Status = MMixerAddEvent(MixerContext, MixerInfo, MixerEventContext, MixerEventRoutine); + if (Status != MM_STATUS_SUCCESS) + { + /* failed */ + DPRINT1("failed to add mixer event\n"); + return Status; + } /* store result */ *MixerHandle = (HANDLE)MixerInfo; @@ -554,8 +584,22 @@ MMixerSetControlDetails( case MIXERCONTROL_CONTROLTYPE_MUX: Status = MMixerSetGetMuxControlDetails(MixerContext, MixerInfo, NodeId, TRUE, Flags, MixerControl, MixerControlDetails, MixerLine); break; + case MIXERCONTROL_CONTROLTYPE_ONOFF: + DPRINT1("Not Implemented MIXERCONTROL_CONTROLTYPE_ONOFF\n"); + break; + case MIXERCONTROL_CONTROLTYPE_LOUDNESS: + DPRINT1("Not Implemented MIXERCONTROL_CONTROLTYPE_LOUDNESS\n"); + break; + case MIXERCONTROL_CONTROLTYPE_PEAKMETER: + DPRINT1("Not Implemented MIXERCONTROL_CONTROLTYPE_PEAKMETER\n"); + break; + case MIXERCONTROL_CONTROLTYPE_FADER: + DPRINT1("Not Implemented MIXERCONTROL_CONTROLTYPE_FADER\n"); + break; + default: Status = MM_STATUS_NOT_IMPLEMENTED; + DPRINT1("ControlType %lx not implemented\n", MixerControl->Control.dwControlType); } return Status; @@ -588,10 +632,11 @@ MMixerGetControlDetails( { /* caller passed mixer id */ MixerHandle = (HANDLE)MMixerGetMixerInfoByIndex(MixerContext, MixerId); - + DPRINT1("MixerHandle %p\n", MixerHandle); if (!MixerHandle) { /* invalid parameter */ + DPRINT1("Invalid mixer handle\n"); return MM_STATUS_INVALID_PARAMETER; } } @@ -600,7 +645,7 @@ MMixerGetControlDetails( MixerInfo = (LPMIXER_INFO)MixerHandle; /* get mixer control */ - Status = MMixerGetMixerControlById(MixerInfo, MixerControlDetails->dwControlID, &MixerLine, &MixerControl, &NodeId); + Status = MMixerGetMixerControlById(MixerInfo, MixerControlDetails->dwControlID, &MixerLine, &MixerControl, &NodeId); /* check for success */ if (Status != MM_STATUS_SUCCESS) @@ -617,11 +662,20 @@ MMixerGetControlDetails( case MIXERCONTROL_CONTROLTYPE_VOLUME: Status = MMixerSetGetVolumeControlDetails(MixerContext, MixerInfo, NodeId, FALSE, MixerControl, MixerControlDetails, MixerLine); break; + case MIXERCONTROL_CONTROLTYPE_MUX: + Status = MMixerSetGetMuxControlDetails(MixerContext, MixerInfo, NodeId, FALSE, Flags, MixerControl, MixerControlDetails, MixerLine); + break; case MIXERCONTROL_CONTROLTYPE_ONOFF: DPRINT1("Not Implemented MIXERCONTROL_CONTROLTYPE_ONOFF\n"); break; - case MIXERCONTROL_CONTROLTYPE_MUX: - Status = MMixerSetGetMuxControlDetails(MixerContext, MixerInfo, NodeId, FALSE, Flags, MixerControl, MixerControlDetails, MixerLine); + case MIXERCONTROL_CONTROLTYPE_LOUDNESS: + DPRINT1("Not Implemented MIXERCONTROL_CONTROLTYPE_LOUDNESS\n"); + break; + case MIXERCONTROL_CONTROLTYPE_PEAKMETER: + DPRINT1("Not Implemented MIXERCONTROL_CONTROLTYPE_PEAKMETER\n"); + break; + case MIXERCONTROL_CONTROLTYPE_FADER: + DPRINT1("Not Implemented MIXERCONTROL_CONTROLTYPE_FADER\n"); break; default: diff --git a/sdk/lib/drivers/sound/mmixer/mmixer.h b/sdk/lib/drivers/sound/mmixer/mmixer.h index 7d88125ce369b..dc7e0428e2cc3 100644 --- a/sdk/lib/drivers/sound/mmixer/mmixer.h +++ b/sdk/lib/drivers/sound/mmixer/mmixer.h @@ -136,7 +136,7 @@ MIXER_STATUS MMixerGetCapabilities( IN PMIXER_CONTEXT MixerContext, IN ULONG MixerIndex, - OUT LPMIXERCAPSW MixerCaps); + OUT LPMIXERCAPSW Caps); MIXER_STATUS MMixerOpen( @@ -207,6 +207,12 @@ MMixerOpenWave( IN PVOID Context, OUT PHANDLE PinHandle); +MIXER_STATUS +MMixerGetWavePosition( + IN PMIXER_CONTEXT MixerContext, + IN HANDLE PinHandle, + OUT DWORD * Position); + MIXER_STATUS MMixerSetWaveStatus( IN PMIXER_CONTEXT MixerContext, diff --git a/sdk/lib/drivers/sound/mmixer/precomp.h b/sdk/lib/drivers/sound/mmixer/precomp.h index 4ffc3f7129bb5..680258bbce49f 100644 --- a/sdk/lib/drivers/sound/mmixer/precomp.h +++ b/sdk/lib/drivers/sound/mmixer/precomp.h @@ -88,7 +88,6 @@ typedef struct ULONG PinId; MIXERLINEW Line; LIST_ENTRY ControlsList; - }MIXERLINE_EXT, *LPMIXERLINE_EXT; typedef struct @@ -124,11 +123,8 @@ typedef struct LIST_ENTRY Entry; ULONG DeviceId; ULONG PinId; - union - { - WAVEOUTCAPSW OutCaps; - WAVEINCAPSW InCaps; - }u; + LPWSTR DeviceName; + PKSDATARANGE_AUDIO DataRangeAudio; }WAVE_INFO, *LPWAVE_INFO; typedef struct @@ -136,12 +132,7 @@ typedef struct LIST_ENTRY Entry; ULONG DeviceId; ULONG PinId; - union - { - MIDIOUTCAPSW OutCaps; - MIDIINCAPSW InCaps; - }u; - + LPWSTR DeviceName; }MIDI_INFO, *LPMIDI_INFO; typedef struct diff --git a/sdk/lib/drivers/sound/mmixer/wave.c b/sdk/lib/drivers/sound/mmixer/wave.c index e049ca485bd86..1fa5e63050af1 100644 --- a/sdk/lib/drivers/sound/mmixer/wave.c +++ b/sdk/lib/drivers/sound/mmixer/wave.c @@ -116,19 +116,17 @@ MMixerInitializeDataFormat( 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->WaveFormatEx.cbSize = WaveFormatEx->cbSize; + DataFormat->DataFormat.FormatSize = sizeof(KSDATAFORMAT) + sizeof(WAVEFORMATEX) + WaveFormatEx->cbSize; 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; @@ -274,11 +272,11 @@ MMixerOpenWavePin( VOID MMixerCheckFormat( IN PKSDATARANGE_AUDIO DataRangeAudio, - IN LPWAVE_INFO WaveInfo, - IN ULONG bInput) + OUT PULONG Result) { ULONG Index, SampleFrequency; - ULONG Result = 0; + + *Result = 0; for(Index = 0; Index < AUDIO_TEST_RANGE; Index++) { @@ -289,35 +287,30 @@ MMixerCheckFormat( /* the audio adapter supports the sample frequency */ if (DataRangeAudio->MinimumBitsPerSample <= 8 && DataRangeAudio->MaximumBitsPerSample >= 8) { - Result |= TestRange[Index].Bit8Mono; + *Result |= TestRange[Index].Bit8Mono; if (DataRangeAudio->MaximumChannels > 1) { /* check if pin supports the sample rate in 8-Bit Stereo */ - Result |= TestRange[Index].Bit8Stereo; + *Result |= TestRange[Index].Bit8Stereo; } } if (DataRangeAudio->MinimumBitsPerSample <= 16 && DataRangeAudio->MaximumBitsPerSample >= 16) { /* check if pin supports the sample rate in 16-Bit Mono */ - Result |= TestRange[Index].Bit16Mono; + *Result |= TestRange[Index].Bit16Mono; if (DataRangeAudio->MaximumChannels > 1) { /* check if pin supports the sample rate in 16-Bit Stereo */ - Result |= TestRange[Index].Bit16Stereo; + *Result |= TestRange[Index].Bit16Stereo; } } } } - if (bInput) - WaveInfo->u.InCaps.dwFormats = Result; - else - WaveInfo->u.OutCaps.dwFormats = Result; - - DPRINT("Format %lx bInput %u\n", Result, bInput); + DPRINT("Format %lx\n", *Result); } MIXER_STATUS @@ -332,7 +325,6 @@ MMixerInitializeWaveInfo( { MIXER_STATUS Status; PKSMULTIPLE_ITEM MultipleItem; - PKSDATARANGE_AUDIO DataRangeAudio; LPWAVE_INFO WaveInfo; WaveInfo = (LPWAVE_INFO)MixerContext->Alloc(sizeof(WAVE_INFO)); @@ -354,28 +346,7 @@ MMixerInitializeWaveInfo( ASSERT(wcslen(DeviceName) < MAXPNAMELEN); /* copy device name */ - if (bWaveIn) - { - wcscpy(WaveInfo->u.InCaps.szPname, DeviceName); - } - else - { - wcscpy(WaveInfo->u.OutCaps.szPname, DeviceName); - } - - /* FIXME determine manufacturer / product id */ - if (bWaveIn) - { - 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; - } + WaveInfo->DeviceName = DeviceName; /* get audio pin data ranges */ Status = MMixerGetAudioPinDataRanges(MixerContext, MixerData->hDevice, Pins[0], &MultipleItem); @@ -386,29 +357,25 @@ MMixerInitializeWaveInfo( return MM_STATUS_UNSUCCESSFUL; } + WaveInfo->DataRangeAudio = (PKSDATARANGE_AUDIO)MixerContext->Alloc(sizeof(KSDATARANGE_AUDIO)); + if (!WaveInfo->DataRangeAudio) + { + MixerContext->Free(MultipleItem); + MixerContext->Free(WaveInfo); + return MM_STATUS_NO_MEMORY; + } + /* find an KSDATARANGE_AUDIO range */ - Status = MMixerFindAudioDataRange(MultipleItem, &DataRangeAudio); + Status = MMixerFindAudioDataRange(MultipleItem, &WaveInfo->DataRangeAudio); if (Status != MM_STATUS_SUCCESS) { /* failed to find audio pin data range */ + MixerContext->Free(WaveInfo->DataRangeAudio); MixerContext->Free(MultipleItem); MixerContext->Free(WaveInfo); return MM_STATUS_UNSUCCESSFUL; } - /* store channel count */ - if (bWaveIn) - { - WaveInfo->u.InCaps.wChannels = DataRangeAudio->MaximumChannels; - } - else - { - WaveInfo->u.OutCaps.wChannels = DataRangeAudio->MaximumChannels; - } - - /* get all supported formats */ - MMixerCheckFormat(DataRangeAudio, WaveInfo, bWaveIn); - /* free dataranges buffer */ MixerContext->Free(MultipleItem); @@ -450,15 +417,15 @@ MMixerOpenWave( return Status; } - /* grab mixer list */ - MixerList = (PMIXER_LIST)MixerContext->MixerContext; - - if (WaveFormat->wFormatTag != WAVE_FORMAT_PCM) + if (WaveFormat->wFormatTag == WAVE_FORMAT_IEEE_FLOAT) { - /* not implemented */ - return MM_STATUS_NOT_IMPLEMENTED; + /* We don't support float audio yet */ + WaveFormat->wFormatTag = WAVE_FORMAT_EXTENSIBLE; } + /* grab mixer list */ + MixerList = (PMIXER_LIST)MixerContext->MixerContext; + /* find destination wave */ Status = MMixerGetWaveInfoByIndexAndType(MixerList, DeviceIndex, bWaveIn, &WaveInfo); if (Status != MM_STATUS_SUCCESS) @@ -511,8 +478,31 @@ MMixerWaveInCapabilities( return MM_STATUS_UNSUCCESSFUL; } - /* copy capabilities */ - MixerContext->Copy(Caps, &WaveInfo->u.InCaps, sizeof(WAVEINCAPSW)); + /* allocate capabilities */ + Caps = MixerContext->Alloc(sizeof(WAVEINCAPSW)); + if (!Caps) + { + /* no memory */ + return MM_STATUS_NO_MEMORY; + } + + /* FIXME determine manufacturer / product id */ + Caps->wMid = MM_MICROSOFT; + Caps->wPid = MM_MSFT_WDMAUDIO_WAVEIN; + Caps->vDriverVersion = 0x050a; + Caps->wReserved1 = 0; + + /* store channel count */ + Caps->wChannels = WaveInfo->DataRangeAudio->MaximumChannels; + + /* get all supported formats */ + MMixerCheckFormat(WaveInfo->DataRangeAudio, &Caps->dwFormats); + + /* copy device name */ + wcscpy(Caps->szPname, WaveInfo->DeviceName); + + /* make sure it's null terminated */ + Caps->szPname[MAXPNAMELEN-1] = L'\0'; return MM_STATUS_SUCCESS; } @@ -547,8 +537,32 @@ MMixerWaveOutCapabilities( return MM_STATUS_UNSUCCESSFUL; } - /* copy capabilities */ - MixerContext->Copy(Caps, &WaveInfo->u.OutCaps, sizeof(WAVEOUTCAPSW)); + /* allocate capabilities */ + Caps = MixerContext->Alloc(sizeof(WAVEOUTCAPSW)); + if (!Caps) + { + /* no memory */ + return MM_STATUS_NO_MEMORY; + } + + /* FIXME determine manufacturer / product id */ + Caps->wMid = MM_MICROSOFT; + Caps->wPid = MM_MSFT_WDMAUDIO_WAVEOUT; + Caps->vDriverVersion = 0x050a; + Caps->wReserved1 = 0; + Caps->dwSupport = WAVECAPS_VOLUME | WAVECAPS_LRVOLUME | WAVECAPS_SAMPLEACCURATE; + + /* store channel count */ + Caps->wChannels = WaveInfo->DataRangeAudio->MaximumChannels; + + /* get all supported formats */ + MMixerCheckFormat(WaveInfo->DataRangeAudio, &Caps->dwFormats); + + /* copy device name */ + wcscpy(Caps->szPname, WaveInfo->DeviceName); + + /* make sure it's null terminated */ + Caps->szPname[MAXPNAMELEN-1] = L'\0'; return MM_STATUS_SUCCESS; } @@ -597,6 +611,38 @@ MMixerGetWaveOutCount( return MixerList->WaveOutListCount; } +MIXER_STATUS +MMixerGetWavePosition( + IN PMIXER_CONTEXT MixerContext, + IN HANDLE PinHandle, + OUT DWORD * Position) +{ + KSAUDIO_POSITION AudioPosition; + KSPROPERTY Property; + MIXER_STATUS Status; + ULONG Length; + + /* verify mixer context */ + Status = MMixerVerifyContext(MixerContext); + + if (Status != MM_STATUS_SUCCESS) + { + /* invalid context passed */ + return Status; + } + + Property.Id = KSPROPERTY_AUDIO_POSITION; + Property.Set = KSPROPSETID_Audio; + Property.Flags = KSPROPERTY_TYPE_GET; + + Status = MixerContext->Control(PinHandle, IOCTL_KS_PROPERTY, &Property, sizeof(KSPROPERTY), &AudioPosition, sizeof(KSAUDIO_POSITION), &Length); + DPRINT("Success %x\n", Status == MM_STATUS_SUCCESS); + /* Store audio position */ + *Position = (DWORD)AudioPosition.PlayOffset; + + return Status; +} + MIXER_STATUS MMixerSetWaveStatus( IN PMIXER_CONTEXT MixerContext,