Based on a patch from Zebediah Figura zfigura@codeweavers.com.
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/dinput8/tests/hid.c | 51 ------ dlls/winmm/Makefile.in | 2 +- dlls/winmm/joystick.c | 355 +++++++++++++++++++++++++++++++++------ dlls/winmm/winemm.h | 3 + dlls/winmm/winmm.c | 2 + 5 files changed, 308 insertions(+), 105 deletions(-)
diff --git a/dlls/dinput8/tests/hid.c b/dlls/dinput8/tests/hid.c index 31703601b6b..35d72409af5 100644 --- a/dlls/dinput8/tests/hid.c +++ b/dlls/dinput8/tests/hid.c @@ -9756,10 +9756,6 @@ static void test_winmm_joystick(void) ok( ret == 16, "joyGetNumDevs returned %u\n", ret );
ret = joyGetDevCapsW( 0, (JOYCAPSW *)&caps, sizeof(JOYCAPSW) ); - /* FIXME: Marvin somehow manages to get a device, ignore it */ - if (!strcmp( winetest_platform, "wine") && ret == 0 && - !wcscmp( caps.szPname, L"QEMU Virtio Tablet" )) - return; ok( ret == JOYERR_PARMS, "joyGetDevCapsW returned %u\n", ret );
memset( &caps, 0xcd, sizeof(caps) ); @@ -9803,7 +9799,6 @@ static void test_winmm_joystick(void) ret = joyGetPosEx( 0, &infoex ); /* first call for an index sometimes fail */ if (ret == JOYERR_PARMS) ret = joyGetPosEx( 0, &infoex ); - todo_wine ok( ret == 0, "joyGetPosEx returned %u\n", ret );
ret = joyGetDevCapsW( 1, (JOYCAPSW *)&caps, sizeof(JOYCAPSW) ); @@ -9811,43 +9806,29 @@ static void test_winmm_joystick(void)
memset( &caps, 0xcd, sizeof(caps) ); ret = joyGetDevCapsW( 0, (JOYCAPSW *)&caps, sizeof(caps) ); - todo_wine ok( ret == 0, "joyGetDevCapsW returned %u\n", ret ); - todo_wine check_member( caps, expect_caps, "%#x", wMid ); - todo_wine check_member( caps, expect_caps, "%#x", wPid ); todo_wine check_member_wstr( caps, expect_caps, szPname ); check_member( caps, expect_caps, "%#x", wXmin ); - todo_wine check_member( caps, expect_caps, "%#x", wXmax ); check_member( caps, expect_caps, "%#x", wYmin ); - todo_wine check_member( caps, expect_caps, "%#x", wYmax ); check_member( caps, expect_caps, "%#x", wZmin ); - todo_wine check_member( caps, expect_caps, "%#x", wZmax ); - todo_wine check_member( caps, expect_caps, "%#x", wNumButtons ); check_member( caps, expect_caps, "%#x", wPeriodMin ); check_member( caps, expect_caps, "%#x", wPeriodMax ); check_member( caps, expect_caps, "%#x", wRmin ); - todo_wine check_member( caps, expect_caps, "%#x", wRmax ); check_member( caps, expect_caps, "%#x", wUmin ); - todo_wine check_member( caps, expect_caps, "%#x", wUmax ); check_member( caps, expect_caps, "%#x", wVmin ); - todo_wine check_member( caps, expect_caps, "%#x", wVmax ); - todo_wine check_member( caps, expect_caps, "%#x", wCaps ); - todo_wine check_member( caps, expect_caps, "%#x", wMaxAxes ); - todo_wine check_member( caps, expect_caps, "%#x", wNumAxes ); - todo_wine check_member( caps, expect_caps, "%#x", wMaxButtons ); check_member_wstr( caps, expect_caps, szRegKey ); check_member_wstr( caps, expect_caps, szOEMVxD ); @@ -9856,7 +9837,6 @@ static void test_winmm_joystick(void) check_member_guid( caps, expect_caps, NameGuid );
ret = joyGetDevCapsW( 0, (JOYCAPSW *)&caps, sizeof(JOYCAPSW) ); - todo_wine ok( ret == 0, "joyGetDevCapsW returned %u\n", ret ); ret = joyGetDevCapsW( 0, NULL, sizeof(JOYCAPSW) ); ok( ret == MMSYSERR_INVALPARAM, "joyGetDevCapsW returned %u\n", ret ); @@ -9878,29 +9858,19 @@ static void test_winmm_joystick(void) infoex.dwSize = sizeof(JOYINFOEX); infoex.dwFlags = JOY_RETURNALL; ret = joyGetPosEx( 0, &infoex ); - todo_wine ok( ret == 0, "joyGetPosEx returned %u\n", ret ); check_member( infoex, expect_infoex[0], "%#x", dwSize ); check_member( infoex, expect_infoex[0], "%#x", dwFlags ); - todo_wine check_member( infoex, expect_infoex[0], "%#x", dwXpos ); - todo_wine check_member( infoex, expect_infoex[0], "%#x", dwYpos ); - todo_wine check_member( infoex, expect_infoex[0], "%#x", dwZpos ); - todo_wine check_member( infoex, expect_infoex[0], "%#x", dwRpos ); - todo_wine check_member( infoex, expect_infoex[0], "%#x", dwUpos ); - todo_wine check_member( infoex, expect_infoex[0], "%#x", dwVpos ); check_member( infoex, expect_infoex[0], "%#x", dwButtons ); check_member( infoex, expect_infoex[0], "%#x", dwButtonNumber ); - todo_wine check_member( infoex, expect_infoex[0], "%#x", dwPOV ); - todo_wine check_member( infoex, expect_infoex[0], "%#x", dwReserved1 ); - todo_wine check_member( infoex, expect_infoex[0], "%#x", dwReserved2 );
infoex.dwSize = sizeof(JOYINFOEX) - 4; @@ -9913,13 +9883,9 @@ static void test_winmm_joystick(void) ok( ret == JOYERR_PARMS, "joyGetPos returned %u\n", ret ); memset( &info, 0xcd, sizeof(info) ); ret = joyGetPos( 0, &info ); - todo_wine ok( ret == 0, "joyGetPos returned %u\n", ret ); - todo_wine check_member( info, expect_info, "%#x", wXpos ); - todo_wine check_member( info, expect_info, "%#x", wYpos ); - todo_wine check_member( info, expect_info, "%#x", wZpos ); check_member( info, expect_info, "%#x", wButtons );
@@ -9953,24 +9919,16 @@ static void test_winmm_joystick(void) infoex.dwSize = sizeof(JOYINFOEX); infoex.dwFlags = JOY_RETURNALL; ret = joyGetPosEx( 0, &infoex ); - todo_wine ok( ret == 0, "joyGetPosEx returned %u\n", ret ); check_member( infoex, expect_infoex[1], "%#x", dwSize ); check_member( infoex, expect_infoex[1], "%#x", dwFlags ); check_member( infoex, expect_infoex[1], "%#x", dwXpos ); - todo_wine check_member( infoex, expect_infoex[1], "%#x", dwYpos ); - todo_wine check_member( infoex, expect_infoex[1], "%#x", dwZpos ); - todo_wine check_member( infoex, expect_infoex[1], "%#x", dwRpos ); - todo_wine check_member( infoex, expect_infoex[1], "%#x", dwUpos ); - todo_wine check_member( infoex, expect_infoex[1], "%#x", dwVpos ); - todo_wine check_member( infoex, expect_infoex[1], "%#x", dwButtons ); - todo_wine check_member( infoex, expect_infoex[1], "%#x", dwButtonNumber ); check_member( infoex, expect_infoex[1], "%#x", dwPOV );
@@ -9983,26 +9941,17 @@ static void test_winmm_joystick(void) infoex.dwSize = sizeof(JOYINFOEX); infoex.dwFlags = JOY_RETURNALL; ret = joyGetPosEx( 0, &infoex ); - todo_wine ok( ret == 0, "joyGetPosEx returned %u\n", ret ); check_member( infoex, expect_infoex[2], "%#x", dwSize ); check_member( infoex, expect_infoex[2], "%#x", dwFlags ); - todo_wine check_member( infoex, expect_infoex[2], "%#x", dwXpos ); - todo_wine check_member( infoex, expect_infoex[2], "%#x", dwYpos ); - todo_wine check_member( infoex, expect_infoex[2], "%#x", dwZpos ); check_member( infoex, expect_infoex[2], "%#x", dwRpos ); - todo_wine check_member( infoex, expect_infoex[2], "%#x", dwUpos ); - todo_wine check_member( infoex, expect_infoex[2], "%#x", dwVpos ); - todo_wine check_member( infoex, expect_infoex[2], "%#x", dwButtons ); - todo_wine check_member( infoex, expect_infoex[2], "%#x", dwButtonNumber ); - todo_wine check_member( infoex, expect_infoex[2], "%#x", dwPOV );
ret = IDirectInputDevice8_Release( device ); diff --git a/dlls/winmm/Makefile.in b/dlls/winmm/Makefile.in index 3036526c14e..5439ae21678 100644 --- a/dlls/winmm/Makefile.in +++ b/dlls/winmm/Makefile.in @@ -1,7 +1,7 @@ EXTRADEFS = -D_WINMM_ MODULE = winmm.dll IMPORTLIB = winmm -IMPORTS = uuid user32 advapi32 ole32 msacm32 +IMPORTS = uuid user32 advapi32 ole32 msacm32 dinput8
C_SRCS = \ driver.c \ diff --git a/dlls/winmm/joystick.c b/dlls/winmm/joystick.c index 20a69e8119d..5f5683e3e35 100644 --- a/dlls/winmm/joystick.c +++ b/dlls/winmm/joystick.c @@ -1,10 +1,11 @@ -/* -*- tab-width: 8; c-basic-offset: 4 -*- */ /* * joystick functions * * Copyright 1997 Andreas Mohr - * 2000 Wolfgang Schwotzer - * Eric Pouech + * Copyright 2000 Wolfgang Schwotzer + * Copyright 2000 Eric Pouech + * Copyright 2020 Zebediah Figura for CodeWeavers + * Copyright 2021 Rémi Bernon for CodeWeavers * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -22,6 +23,7 @@ */
#include <stdarg.h> +#include <stdint.h> #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -30,11 +32,11 @@ #include "windef.h" #include "winbase.h" #include "mmsystem.h" -#include "wingdi.h" -#include "winuser.h" -#include "winnls.h"
-#include "mmddk.h" +#include "initguid.h" +#include "dinput.h" + +#include "winemm.h"
#include "wine/debug.h"
@@ -49,19 +51,185 @@ static CRITICAL_SECTION_DEBUG critsect_debug = }; static CRITICAL_SECTION joystick_cs = { &critsect_debug, -1, 0, 0, 0, 0 };
+struct joystick_state +{ + LONG x; + LONG y; + LONG z; + LONG u; + LONG v; + LONG r; + LONG pov; + BYTE buttons[32]; +}; + +static const DIOBJECTDATAFORMAT object_formats[] = +{ + { &GUID_XAxis, offsetof(struct joystick_state, x), DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE, DIDOI_ASPECTPOSITION }, + { &GUID_YAxis, offsetof(struct joystick_state, y), DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE, DIDOI_ASPECTPOSITION }, + { &GUID_ZAxis, offsetof(struct joystick_state, z), DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE, DIDOI_ASPECTPOSITION }, + { &GUID_RzAxis, offsetof(struct joystick_state, r), DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE, DIDOI_ASPECTPOSITION }, + { &GUID_Slider, offsetof(struct joystick_state, u), DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE, DIDOI_ASPECTPOSITION }, + { &GUID_RxAxis, offsetof(struct joystick_state, v), DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE, DIDOI_ASPECTPOSITION }, + { &GUID_POV, offsetof(struct joystick_state, pov), DIDFT_OPTIONAL|DIDFT_POV|DIDFT_ANYINSTANCE, 0 }, + { NULL, offsetof(struct joystick_state, buttons[0]), DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE, 0 }, + { NULL, offsetof(struct joystick_state, buttons[1]), DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE, 0 }, + { NULL, offsetof(struct joystick_state, buttons[2]), DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE, 0 }, + { NULL, offsetof(struct joystick_state, buttons[3]), DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE, 0 }, + { NULL, offsetof(struct joystick_state, buttons[4]), DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE, 0 }, + { NULL, offsetof(struct joystick_state, buttons[5]), DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE, 0 }, + { NULL, offsetof(struct joystick_state, buttons[6]), DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE, 0 }, + { NULL, offsetof(struct joystick_state, buttons[7]), DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE, 0 }, + { NULL, offsetof(struct joystick_state, buttons[8]), DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE, 0 }, + { NULL, offsetof(struct joystick_state, buttons[9]), DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE, 0 }, + { NULL, offsetof(struct joystick_state, buttons[10]), DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE, 0 }, + { NULL, offsetof(struct joystick_state, buttons[11]), DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE, 0 }, + { NULL, offsetof(struct joystick_state, buttons[12]), DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE, 0 }, + { NULL, offsetof(struct joystick_state, buttons[13]), DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE, 0 }, + { NULL, offsetof(struct joystick_state, buttons[14]), DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE, 0 }, + { NULL, offsetof(struct joystick_state, buttons[15]), DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE, 0 }, + { NULL, offsetof(struct joystick_state, buttons[16]), DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE, 0 }, + { NULL, offsetof(struct joystick_state, buttons[17]), DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE, 0 }, + { NULL, offsetof(struct joystick_state, buttons[18]), DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE, 0 }, + { NULL, offsetof(struct joystick_state, buttons[19]), DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE, 0 }, + { NULL, offsetof(struct joystick_state, buttons[20]), DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE, 0 }, + { NULL, offsetof(struct joystick_state, buttons[21]), DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE, 0 }, + { NULL, offsetof(struct joystick_state, buttons[22]), DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE, 0 }, + { NULL, offsetof(struct joystick_state, buttons[23]), DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE, 0 }, + { NULL, offsetof(struct joystick_state, buttons[24]), DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE, 0 }, + { NULL, offsetof(struct joystick_state, buttons[25]), DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE, 0 }, + { NULL, offsetof(struct joystick_state, buttons[26]), DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE, 0 }, + { NULL, offsetof(struct joystick_state, buttons[27]), DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE, 0 }, + { NULL, offsetof(struct joystick_state, buttons[28]), DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE, 0 }, + { NULL, offsetof(struct joystick_state, buttons[29]), DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE, 0 }, + { NULL, offsetof(struct joystick_state, buttons[30]), DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE, 0 }, + { NULL, offsetof(struct joystick_state, buttons[31]), DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE, 0 }, +}; + +static const DIDATAFORMAT data_format = +{ + .dwSize = sizeof(DIDATAFORMAT), + .dwObjSize = sizeof(DIOBJECTDATAFORMAT), + .dwFlags = DIDF_ABSAXIS, + .dwDataSize = sizeof(struct joystick_state), + .dwNumObjs = ARRAY_SIZE(object_formats), + .rgodf = (DIOBJECTDATAFORMAT *)object_formats, +}; + #define JOY_PERIOD_MIN (10) /* min Capture time period */ #define JOY_PERIOD_MAX (1000) /* max Capture time period */
-typedef struct tagWINE_JOYSTICK { +struct joystick +{ + DIDEVICEINSTANCEW instance; + IDirectInputDevice8W *device; + struct joystick_state state; + HANDLE event; + JOYINFO info; HWND capture; UINT timer; DWORD threshold; BOOL changed; - HDRVR driver; -} WINE_JOYSTICK; + ULONG last_check; +};
-static WINE_JOYSTICK joysticks[16]; +static DIDEVICEINSTANCEW instances[16]; +static struct joystick joysticks[16]; +static IDirectInput8W *dinput; + +static BOOL CALLBACK enum_instances( const DIDEVICEINSTANCEW *instance, void *context ) +{ + ULONG index = *(ULONG *)context; + BYTE type = instance->dwDevType; + + if (type == DI8DEVTYPE_MOUSE) return DIENUM_CONTINUE; + if (type == DI8DEVTYPE_KEYBOARD) return DIENUM_CONTINUE; + + instances[index++] = *instance; + if (index >= ARRAY_SIZE(instances)) return DIENUM_STOP; + *(ULONG *)context = index; + return DIENUM_CONTINUE; +} + +void joystick_load( HINSTANCE instance ) +{ + HRESULT hr = DirectInput8Create( instance, DIRECTINPUT_VERSION, &IID_IDirectInput8W, + (void **)&dinput, NULL ); + if (FAILED(hr)) WARN( "could not create dinput instance, hr %#x\n", hr ); +} + +void joystick_unload() +{ + int i; + + if (!dinput) return; + + for (i = 0; i < ARRAY_SIZE(joysticks); i++) + { + if (!joysticks[i].device) continue; + IDirectInputDevice8_Release( joysticks[i].device ); + CloseHandle( joysticks[i].event ); + } + + IDirectInput8_Release( dinput ); +} + +static void find_joysticks(void) +{ + IDirectInputDevice8W *device; + HANDLE event; + DWORD index; + HRESULT hr; + + if (!dinput) return; + + index = 0; + IDirectInput8_EnumDevices( dinput, DI8DEVCLASS_ALL, enum_instances, &index, DIEDFL_ATTACHEDONLY ); + TRACE( "found %u device instances\n", index ); + + while (index--) + { + if (!memcmp( &joysticks[index].instance, &instances[index], sizeof(DIDEVICEINSTANCEW) )) + continue; + + if (joysticks[index].device) + { + IDirectInputDevice8_Release( joysticks[index].device ); + CloseHandle( joysticks[index].event ); + } + + if (!(event = CreateEventW( NULL, FALSE, FALSE, NULL ))) + WARN( "could not event for device, error %u\n", GetLastError() ); + else if (FAILED(hr = IDirectInput8_CreateDevice( dinput, &instances[index].guidInstance, &device, NULL ))) + WARN( "could not create device %s instance, hr %#x\n", + debugstr_guid( &instances[index].guidInstance ), hr ); + else if (FAILED(hr = IDirectInputDevice8_SetEventNotification( device, event ))) + WARN( "SetEventNotification device %p hr %#x\n", device, hr ); + else if (FAILED(hr = IDirectInputDevice8_SetCooperativeLevel( device, NULL, DISCL_NONEXCLUSIVE|DISCL_BACKGROUND ))) + WARN( "SetCooperativeLevel device %p hr %#x\n", device, hr ); + else if (FAILED(hr = IDirectInputDevice8_SetDataFormat( device, &data_format ))) + WARN( "SetDataFormat device %p hr %#x\n", device, hr ); + else if (FAILED(hr = IDirectInputDevice8_Acquire( device ))) + WARN( "Acquire device %p hr %#x\n", device, hr ); + else + { + TRACE( "opened device %p event %p\n", device, event ); + + memset( &joysticks[index], 0, sizeof(struct joystick) ); + joysticks[index].instance = instances[index]; + joysticks[index].device = device; + joysticks[index].event = event; + continue; + } + + CloseHandle( event ); + if (device) IDirectInputDevice8_Release( device ); + memmove( joysticks + index, joysticks + index + 1, + (ARRAY_SIZE(joysticks) - index - 1) * sizeof(struct joystick) ); + memset( &joysticks[ARRAY_SIZE(joysticks) - 1], 0, sizeof(struct joystick) ); + } +}
static BOOL compare_uint(unsigned int x, unsigned int y, unsigned int max_diff) { @@ -69,29 +237,6 @@ static BOOL compare_uint(unsigned int x, unsigned int y, unsigned int max_diff) return diff <= max_diff; }
-/************************************************************************** - * JOY_LoadDriver [internal] - */ -static BOOL JOY_LoadDriver(DWORD dwJoyID) -{ - static BOOL winejoystick_missing = FALSE; - - if (dwJoyID >= ARRAY_SIZE(joysticks) || winejoystick_missing) return FALSE; - if (joysticks[dwJoyID].driver) return TRUE; - - joysticks[dwJoyID].driver = OpenDriverA( "winejoystick.drv", 0, dwJoyID ); - - if (!joysticks[dwJoyID].driver) - { - WARN("OpenDriverA("winejoystick.drv") failed\n"); - - /* The default driver is missing, don't attempt to load it again */ - winejoystick_missing = TRUE; - } - - return (joysticks[dwJoyID].driver != 0); -} - static void CALLBACK joystick_timer( HWND hwnd, UINT msg, UINT_PTR timer, DWORD time ) { MMRESULT res; @@ -163,6 +308,22 @@ UINT WINAPI DECLSPEC_HOTPATCH joyGetNumDevs(void) */ MMRESULT WINAPI DECLSPEC_HOTPATCH joyGetDevCapsW( UINT_PTR id, JOYCAPSW *caps, UINT size ) { + DIDEVICEOBJECTINSTANCEW instance = {.dwSize = sizeof(DIDEVICEOBJECTINSTANCEW)}; + DIDEVCAPS dicaps = {.dwSize = sizeof(DIDEVCAPS)}; + DIPROPDWORD diprop = + { + .diph = + { + .dwSize = sizeof(DIPROPDWORD), + .dwHeaderSize = sizeof(DIPROPHEADER), + .dwHow = DIPH_DEVICE, + }, + }; + MMRESULT res = JOYERR_NOERROR; + IDirectInputDevice8W *device; + ULONG ticks = GetTickCount(); + HRESULT hr; + TRACE( "id %d, caps %p, size %u.\n", (int)id, caps, size );
if (!caps) return MMSYSERR_INVALPARAM; @@ -173,12 +334,67 @@ MMRESULT WINAPI DECLSPEC_HOTPATCH joyGetDevCapsW( UINT_PTR id, JOYCAPSW *caps, U if (id == ~(UINT_PTR)0) return JOYERR_NOERROR;
if (id >= ARRAY_SIZE(joysticks)) return JOYERR_PARMS; - if (!JOY_LoadDriver( id )) return MMSYSERR_NODRIVER;
- caps->wPeriodMin = JOY_PERIOD_MIN; /* FIXME */ - caps->wPeriodMax = JOY_PERIOD_MAX; /* FIXME (same as MS Joystick Driver) */ + EnterCriticalSection( &joystick_cs );
- return SendDriverMessage( joysticks[id].driver, JDD_GETDEVCAPS, (LPARAM)caps, size ); + if (!(device = joysticks[id].device) && (ticks - joysticks[id].last_check) >= 2000) + { + joysticks[id].last_check = ticks; + find_joysticks(); + } + + if (!(device = joysticks[id].device)) res = JOYERR_PARMS; + else if (FAILED(hr = IDirectInputDevice8_GetCapabilities( device, &dicaps ))) + { + WARN( "GetCapabilities device %p returned %#x\n", device, hr ); + res = JOYERR_PARMS; + } + else + { + hr = IDirectInputDevice8_GetProperty( device, DIPROP_VIDPID, &diprop.diph ); + if (FAILED(hr)) WARN( "GetProperty device %p returned %#x\n", device, hr ); + else + { + caps->wMid = LOWORD(diprop.dwData); + caps->wPid = HIWORD(diprop.dwData); + } + + wcscpy( caps->szPname, L"Wine joystick driver" ); + caps->wXmin = 0; + caps->wXmax = 0xffff; + caps->wYmin = 0; + caps->wYmax = 0xffff; + caps->wZmin = 0; + caps->wZmax = 0xffff; + caps->wNumButtons = dicaps.dwButtons; + caps->wPeriodMin = JOY_PERIOD_MIN; + caps->wPeriodMax = JOY_PERIOD_MAX; + caps->wRmin = 0; + caps->wRmax = 0xffff; + caps->wUmin = 0; + caps->wUmax = 0xffff; + caps->wVmin = 0; + caps->wVmax = 0xffff; + caps->wCaps = 0; + caps->wMaxAxes = 6; + caps->wNumAxes = min( dicaps.dwAxes, caps->wMaxAxes ); + caps->wMaxButtons = 32; + + hr = IDirectInputDevice8_GetObjectInfo( device, &instance, offsetof(struct joystick_state, z), DIPH_BYOFFSET ); + if (SUCCEEDED(hr)) caps->wCaps |= JOYCAPS_HASZ; + hr = IDirectInputDevice8_GetObjectInfo( device, &instance, offsetof(struct joystick_state, r), DIPH_BYOFFSET ); + if (SUCCEEDED(hr)) caps->wCaps |= JOYCAPS_HASR; + hr = IDirectInputDevice8_GetObjectInfo( device, &instance, offsetof(struct joystick_state, u), DIPH_BYOFFSET ); + if (SUCCEEDED(hr)) caps->wCaps |= JOYCAPS_HASU; + hr = IDirectInputDevice8_GetObjectInfo( device, &instance, offsetof(struct joystick_state, v), DIPH_BYOFFSET ); + if (SUCCEEDED(hr)) caps->wCaps |= JOYCAPS_HASV; + hr = IDirectInputDevice8_GetObjectInfo( device, &instance, offsetof(struct joystick_state, pov), DIPH_BYOFFSET ); + if (SUCCEEDED(hr)) caps->wCaps |= JOYCAPS_HASPOV|JOYCAPS_POV4DIR; + } + + LeaveCriticalSection( &joystick_cs ); + + return res; }
/************************************************************************** @@ -243,25 +459,60 @@ MMRESULT WINAPI DECLSPEC_HOTPATCH joyGetDevCapsA( UINT_PTR id, JOYCAPSA *caps, U */ MMRESULT WINAPI DECLSPEC_HOTPATCH joyGetPosEx( UINT id, JOYINFOEX *info ) { + DWORD i, ticks = GetTickCount(); + MMRESULT res = JOYERR_NOERROR; + IDirectInputDevice8W *device; + struct joystick_state state; + HRESULT hr; + TRACE( "id %u, info %p.\n", id, info );
if (!info) return MMSYSERR_INVALPARAM; if (id >= ARRAY_SIZE(joysticks) || info->dwSize < sizeof(JOYINFOEX)) return JOYERR_PARMS; - if (!JOY_LoadDriver( id )) return MMSYSERR_NODRIVER;
- info->dwXpos = 0; - info->dwYpos = 0; - info->dwZpos = 0; - info->dwRpos = 0; - info->dwUpos = 0; - info->dwVpos = 0; - info->dwButtons = 0; - info->dwButtonNumber = 0; - info->dwPOV = 0; - info->dwReserved1 = 0; - info->dwReserved2 = 0; + EnterCriticalSection( &joystick_cs );
- return SendDriverMessage( joysticks[id].driver, JDD_GETPOSEX, (LPARAM)info, 0 ); + if (!(device = joysticks[id].device) && (ticks - joysticks[id].last_check) >= 2000) + { + joysticks[id].last_check = ticks; + find_joysticks(); + } + + if (!(device = joysticks[id].device)) + res = JOYERR_PARMS; + else if (FAILED(hr = IDirectInputDevice8_GetDeviceState( device, sizeof(struct joystick_state), &state ))) + { + WARN( "GetDeviceState device %p returned %#x\n", device, hr ); + res = JOYERR_PARMS; + } + else + { + if (info->dwFlags & JOY_RETURNX) info->dwXpos = state.x; + if (info->dwFlags & JOY_RETURNY) info->dwYpos = state.y; + if (info->dwFlags & JOY_RETURNZ) info->dwZpos = state.z; + if (info->dwFlags & JOY_RETURNR) info->dwRpos = state.r; + if (info->dwFlags & JOY_RETURNU) info->dwUpos = state.u; + if (info->dwFlags & JOY_RETURNV) info->dwVpos = state.v; + if (info->dwFlags & JOY_RETURNPOV) + { + if (state.pov == ~0) info->dwPOV = 0xffff; + else info->dwPOV = state.pov; + } + if (info->dwFlags & JOY_RETURNBUTTONS) + { + info->dwButtonNumber = info->dwButtons = 0; + for (i = 0; i < ARRAY_SIZE(state.buttons); ++i) + { + if (!state.buttons[i]) continue; + info->dwButtonNumber++; + info->dwButtons |= 1 << i; + } + } + } + + LeaveCriticalSection( &joystick_cs ); + + return res; }
/************************************************************************** @@ -313,7 +564,6 @@ MMRESULT WINAPI joyReleaseCapture( UINT id ) TRACE( "id %u.\n", id );
if (id >= ARRAY_SIZE(joysticks)) return JOYERR_PARMS; - if (!JOY_LoadDriver( id )) return MMSYSERR_NODRIVER;
EnterCriticalSection( &joystick_cs );
@@ -343,7 +593,6 @@ MMRESULT WINAPI joySetCapture( HWND hwnd, UINT id, UINT period, BOOL changed ) if (id >= ARRAY_SIZE(joysticks) || hwnd == 0) return JOYERR_PARMS; if (period < JOY_PERIOD_MIN) period = JOY_PERIOD_MIN; else if (period > JOY_PERIOD_MAX) period = JOY_PERIOD_MAX; - if (!JOY_LoadDriver( id )) return MMSYSERR_NODRIVER;
EnterCriticalSection( &joystick_cs );
diff --git a/dlls/winmm/winemm.h b/dlls/winmm/winemm.h index d7bab0f531d..3459c2a85ef 100644 --- a/dlls/winmm/winemm.h +++ b/dlls/winmm/winemm.h @@ -153,6 +153,9 @@ MMRESULT WINMM_CheckCallback(DWORD_PTR dwCallback, DWORD fdwOpen, BOOL mixer) DE
void WINMM_DeleteWaveform(void) DECLSPEC_HIDDEN;
+void joystick_load( HMODULE instance ) DECLSPEC_HIDDEN; +void joystick_unload( void ) DECLSPEC_HIDDEN; + /* Global variables */ extern CRITICAL_SECTION WINMM_cs DECLSPEC_HIDDEN; extern HINSTANCE hWinMM32Instance DECLSPEC_HIDDEN; diff --git a/dlls/winmm/winmm.c b/dlls/winmm/winmm.c index eea29ea61e5..aab8bfb51a9 100644 --- a/dlls/winmm/winmm.c +++ b/dlls/winmm/winmm.c @@ -145,11 +145,13 @@ BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID fImpLoad) if (!WINMM_CreateIData(hInstDLL)) return FALSE;
+ joystick_load( hInstDLL ); break; case DLL_PROCESS_DETACH: if(fImpLoad) break;
+ joystick_unload(); MCI_SendCommand(MCI_ALL_DEVICE_ID, MCI_CLOSE, MCI_WAIT, 0L); MMDRV_Exit(); DRIVER_UnloadAll();