Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/winmm/joystick.c | 96 ++++++++++++++++++++++++------------------- 1 file changed, 53 insertions(+), 43 deletions(-)
diff --git a/dlls/winmm/joystick.c b/dlls/winmm/joystick.c index 2b1811d3778..bc9632df75c 100644 --- a/dlls/winmm/joystick.c +++ b/dlls/winmm/joystick.c @@ -167,64 +167,74 @@ UINT WINAPI DECLSPEC_HOTPATCH joyGetNumDevs(void) /************************************************************************** * joyGetDevCapsW [WINMM.@] */ -MMRESULT WINAPI DECLSPEC_HOTPATCH joyGetDevCapsW(UINT_PTR wID, LPJOYCAPSW lpCaps, UINT wSize) +MMRESULT WINAPI DECLSPEC_HOTPATCH joyGetDevCapsW( UINT_PTR id, LPJOYCAPSW caps, UINT size ) { - if (wID >= MAXJOYSTICK) return JOYERR_PARMS; - if (!JOY_LoadDriver(wID)) return MMSYSERR_NODRIVER; + TRACE( "id %d, caps %p, size %u.\n", (int)id, caps, size );
- lpCaps->wPeriodMin = JOY_PERIOD_MIN; /* FIXME */ - lpCaps->wPeriodMax = JOY_PERIOD_MAX; /* FIXME (same as MS Joystick Driver) */ + if (!caps) return MMSYSERR_INVALPARAM; + if (size != sizeof(JOYCAPSW) && size != sizeof(JOYCAPS2W)) return JOYERR_PARMS;
- return SendDriverMessage(JOY_Sticks[wID].hDriver, JDD_GETDEVCAPS, (LPARAM)lpCaps, wSize); + if (id >= MAXJOYSTICK) 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) */ + + return SendDriverMessage( JOY_Sticks[id].hDriver, JDD_GETDEVCAPS, (LPARAM)caps, size ); }
/************************************************************************** * joyGetDevCapsA [WINMM.@] */ -MMRESULT WINAPI DECLSPEC_HOTPATCH joyGetDevCapsA(UINT_PTR wID, LPJOYCAPSA lpCaps, UINT wSize) +MMRESULT WINAPI DECLSPEC_HOTPATCH joyGetDevCapsA( UINT_PTR id, JOYCAPSA *caps, UINT size ) { - JOYCAPSW jcw; - MMRESULT ret; + JOYCAPS2W caps_w; + MMRESULT res;
- if (lpCaps == NULL) return MMSYSERR_INVALPARAM; + TRACE( "id %d, caps %p, size %u.\n", (int)id, caps, size );
- ret = joyGetDevCapsW(wID, &jcw, sizeof(jcw)); + if (!caps) return MMSYSERR_INVALPARAM; + if (size != sizeof(JOYCAPSA) && size != sizeof(JOYCAPS2A)) return JOYERR_PARMS;
- if (ret == JOYERR_NOERROR) + res = joyGetDevCapsW( id, (JOYCAPSW *)&caps_w, sizeof(caps_w) ); + if (res) return res; + + caps->wMid = caps_w.wMid; + caps->wPid = caps_w.wPid; + WideCharToMultiByte( CP_ACP, 0, caps_w.szPname, -1, caps->szPname, + sizeof(caps->szPname), NULL, NULL ); + caps->wXmin = caps_w.wXmin; + caps->wXmax = caps_w.wXmax; + caps->wYmin = caps_w.wYmin; + caps->wYmax = caps_w.wYmax; + caps->wZmin = caps_w.wZmin; + caps->wZmax = caps_w.wZmax; + caps->wNumButtons = caps_w.wNumButtons; + caps->wPeriodMin = caps_w.wPeriodMin; + caps->wPeriodMax = caps_w.wPeriodMax; + caps->wRmin = caps_w.wRmin; + caps->wRmax = caps_w.wRmax; + caps->wUmin = caps_w.wUmin; + caps->wUmax = caps_w.wUmax; + caps->wVmin = caps_w.wVmin; + caps->wVmax = caps_w.wVmax; + caps->wCaps = caps_w.wCaps; + caps->wMaxAxes = caps_w.wMaxAxes; + caps->wNumAxes = caps_w.wNumAxes; + caps->wMaxButtons = caps_w.wMaxButtons; + WideCharToMultiByte( CP_ACP, 0, caps_w.szRegKey, -1, caps->szRegKey, + sizeof(caps->szRegKey), NULL, NULL ); + WideCharToMultiByte( CP_ACP, 0, caps_w.szOEMVxD, -1, caps->szOEMVxD, + sizeof(caps->szOEMVxD), NULL, NULL ); + + if (size == sizeof(JOYCAPS2A)) { - lpCaps->wMid = jcw.wMid; - lpCaps->wPid = jcw.wPid; - WideCharToMultiByte( CP_ACP, 0, jcw.szPname, -1, lpCaps->szPname, - sizeof(lpCaps->szPname), NULL, NULL ); - lpCaps->wXmin = jcw.wXmin; - lpCaps->wXmax = jcw.wXmax; - lpCaps->wYmin = jcw.wYmin; - lpCaps->wYmax = jcw.wYmax; - lpCaps->wZmin = jcw.wZmin; - lpCaps->wZmax = jcw.wZmax; - lpCaps->wNumButtons = jcw.wNumButtons; - lpCaps->wPeriodMin = jcw.wPeriodMin; - lpCaps->wPeriodMax = jcw.wPeriodMax; - - if (wSize >= sizeof(JOYCAPSA)) { /* Win95 extensions ? */ - lpCaps->wRmin = jcw.wRmin; - lpCaps->wRmax = jcw.wRmax; - lpCaps->wUmin = jcw.wUmin; - lpCaps->wUmax = jcw.wUmax; - lpCaps->wVmin = jcw.wVmin; - lpCaps->wVmax = jcw.wVmax; - lpCaps->wCaps = jcw.wCaps; - lpCaps->wMaxAxes = jcw.wMaxAxes; - lpCaps->wNumAxes = jcw.wNumAxes; - lpCaps->wMaxButtons = jcw.wMaxButtons; - WideCharToMultiByte( CP_ACP, 0, jcw.szRegKey, -1, lpCaps->szRegKey, - sizeof(lpCaps->szRegKey), NULL, NULL ); - WideCharToMultiByte( CP_ACP, 0, jcw.szOEMVxD, -1, lpCaps->szOEMVxD, - sizeof(lpCaps->szOEMVxD), NULL, NULL ); - } + ((JOYCAPS2A *)caps)->ManufacturerGuid = caps_w.ManufacturerGuid; + ((JOYCAPS2A *)caps)->ProductGuid = caps_w.ProductGuid; + ((JOYCAPS2A *)caps)->NameGuid = caps_w.NameGuid; }
- return ret; + return JOYERR_NOERROR; }
/**************************************************************************
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/dinput8/tests/Makefile.in | 2 +- dlls/dinput8/tests/hid.c | 337 +++++++++++++++++++++++++++++++++ 2 files changed, 338 insertions(+), 1 deletion(-)
diff --git a/dlls/dinput8/tests/Makefile.in b/dlls/dinput8/tests/Makefile.in index 18624b9d523..336dbd500ba 100644 --- a/dlls/dinput8/tests/Makefile.in +++ b/dlls/dinput8/tests/Makefile.in @@ -1,5 +1,5 @@ TESTDLL = dinput8.dll -IMPORTS = dinput8 dinput ole32 user32 hid advapi32 uuid crypt32 newdev setupapi wintrust +IMPORTS = dinput8 dinput ole32 user32 hid advapi32 uuid crypt32 newdev setupapi wintrust winmm
driver_hid_IMPORTS = winecrt0 ntoskrnl hal hidclass driver_hid_EXTRADLLFLAGS = -nodefaultlibs -nostartfiles -Wl,--subsystem,native diff --git a/dlls/dinput8/tests/hid.c b/dlls/dinput8/tests/hid.c index 0a58f215ea9..4aa37539202 100644 --- a/dlls/dinput8/tests/hid.c +++ b/dlls/dinput8/tests/hid.c @@ -46,6 +46,7 @@ #include "wingdi.h" #include "dinput.h" #include "dinputd.h" +#include "mmsystem.h"
#include "initguid.h" #include "ddk/wdm.h" @@ -9588,6 +9589,338 @@ done: winetest_pop_context(); }
+static void test_winmm_joystick(void) +{ +#include "psh_hid_macros.h" + const unsigned char report_desc[] = { + USAGE_PAGE(1, HID_USAGE_PAGE_GENERIC), + USAGE(1, HID_USAGE_GENERIC_JOYSTICK), + COLLECTION(1, Application), + USAGE(1, HID_USAGE_GENERIC_JOYSTICK), + COLLECTION(1, Report), + REPORT_ID(1, 1), + + USAGE(1, HID_USAGE_GENERIC_X), + USAGE(1, HID_USAGE_GENERIC_Y), + USAGE(1, HID_USAGE_GENERIC_Z), + USAGE(1, HID_USAGE_GENERIC_WHEEL), + USAGE(1, HID_USAGE_GENERIC_SLIDER), + USAGE(1, HID_USAGE_GENERIC_RX), + USAGE(1, HID_USAGE_GENERIC_RY), + USAGE(1, HID_USAGE_GENERIC_RZ), + LOGICAL_MINIMUM(1, 1), + LOGICAL_MAXIMUM(4, 0xffff), + PHYSICAL_MINIMUM(1, 1), + PHYSICAL_MAXIMUM(4, 0xffff), + REPORT_SIZE(1, 16), + REPORT_COUNT(1, 8), + INPUT(1, Data|Var|Abs), + + USAGE(1, HID_USAGE_GENERIC_HATSWITCH), + LOGICAL_MINIMUM(1, 1), + LOGICAL_MAXIMUM(1, 8), + PHYSICAL_MINIMUM(1, 0), + PHYSICAL_MAXIMUM(1, 8), + REPORT_SIZE(1, 4), + REPORT_COUNT(1, 1), + INPUT(1, Data|Var|Abs|Null), + + USAGE_PAGE(1, HID_USAGE_PAGE_BUTTON), + USAGE_MINIMUM(1, 1), + USAGE_MAXIMUM(1, 4), + LOGICAL_MINIMUM(1, 0), + LOGICAL_MAXIMUM(1, 1), + PHYSICAL_MINIMUM(1, 0), + PHYSICAL_MAXIMUM(1, 1), + REPORT_SIZE(1, 1), + REPORT_COUNT(1, 4), + INPUT(1, Data|Var|Abs), + END_COLLECTION, + END_COLLECTION, + }; +#include "pop_hid_macros.h" + + static const HIDP_CAPS hid_caps = + { + .InputReportByteLength = 18, + }; + static const JOYCAPS2W expect_regcaps = + { + .szRegKey = L"DINPUT.DLL", + }; + static const JOYCAPS2W expect_caps = + { + .wMid = 0x1209, + .wPid = 0x0001, + .szPname = L"Microsoft PC-joystick driver", + .wXmax = 0xffff, + .wYmax = 0xffff, + .wZmax = 0xffff, + .wNumButtons = 4, + .wPeriodMin = 10, + .wPeriodMax = 1000, + .wRmax = 0xffff, + .wUmax = 0xffff, + .wVmax = 0xffff, + .wCaps = JOYCAPS_HASZ|JOYCAPS_HASR|JOYCAPS_HASU|JOYCAPS_HASV|JOYCAPS_HASPOV|JOYCAPS_POV4DIR, + .wMaxAxes = 6, + .wNumAxes = 6, + .wMaxButtons = 32, + .szRegKey = L"DINPUT.DLL", + }; + static const JOYINFOEX expect_infoex = + { + .dwSize = sizeof(JOYINFOEX), + .dwFlags = 0xff, + .dwXpos = 0x7fff, + .dwYpos = 0x7fff, + .dwZpos = 0x7fff, + .dwRpos = 0x7fff, + .dwUpos = 0x7fff, + .dwVpos = 0x7fff, + .dwButtons = 0, + .dwButtonNumber = 0, + .dwPOV = 0xffff, + .dwReserved1 = 0xcdcdcdcd, + .dwReserved2 = 0xcdcdcdcd, + }; + static const JOYINFO expect_info = + { + .wXpos = 0x7fff, + .wYpos = 0x7fff, + .wZpos = 0x7fff, + .wButtons = 0, + }; + JOYINFOEX infoex = {.dwSize = sizeof(JOYINFOEX)}; + WCHAR cwd[MAX_PATH], tempdir[MAX_PATH]; + JOYCAPS2W caps = {0}; + JOYINFO info = {0}; + UINT ret; + + GetCurrentDirectoryW( ARRAY_SIZE(cwd), cwd ); + GetTempPathW( ARRAY_SIZE(tempdir), tempdir ); + SetCurrentDirectoryW( tempdir ); + + cleanup_registry_keys(); + + ret = joyGetNumDevs(); + todo_wine + 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) ); + ret = joyGetDevCapsW( -1, (JOYCAPSW *)&caps, sizeof(caps) ); + todo_wine + ok( ret == 0, "joyGetDevCapsW returned %u\n", ret ); + todo_wine + check_member( caps, expect_regcaps, "%#x", wMid ); + todo_wine + check_member( caps, expect_regcaps, "%#x", wPid ); + todo_wine + check_member_wstr( caps, expect_regcaps, szPname ); + todo_wine + check_member( caps, expect_regcaps, "%#x", wXmin ); + todo_wine + check_member( caps, expect_regcaps, "%#x", wXmax ); + todo_wine + check_member( caps, expect_regcaps, "%#x", wYmin ); + todo_wine + check_member( caps, expect_regcaps, "%#x", wYmax ); + todo_wine + check_member( caps, expect_regcaps, "%#x", wZmin ); + todo_wine + check_member( caps, expect_regcaps, "%#x", wZmax ); + todo_wine + check_member( caps, expect_regcaps, "%#x", wNumButtons ); + todo_wine + check_member( caps, expect_regcaps, "%#x", wPeriodMin ); + todo_wine + check_member( caps, expect_regcaps, "%#x", wPeriodMax ); + todo_wine + check_member( caps, expect_regcaps, "%#x", wRmin ); + todo_wine + check_member( caps, expect_regcaps, "%#x", wRmax ); + todo_wine + check_member( caps, expect_regcaps, "%#x", wUmin ); + todo_wine + check_member( caps, expect_regcaps, "%#x", wUmax ); + todo_wine + check_member( caps, expect_regcaps, "%#x", wVmin ); + todo_wine + check_member( caps, expect_regcaps, "%#x", wVmax ); + todo_wine + check_member( caps, expect_regcaps, "%#x", wCaps ); + todo_wine + check_member( caps, expect_regcaps, "%#x", wMaxAxes ); + todo_wine + check_member( caps, expect_regcaps, "%#x", wNumAxes ); + todo_wine + check_member( caps, expect_regcaps, "%#x", wMaxButtons ); + todo_wine + check_member_wstr( caps, expect_regcaps, szRegKey ); + todo_wine + check_member_wstr( caps, expect_regcaps, szOEMVxD ); + todo_wine + check_member_guid( caps, expect_regcaps, ManufacturerGuid ); + todo_wine + check_member_guid( caps, expect_regcaps, ProductGuid ); + todo_wine + check_member_guid( caps, expect_regcaps, NameGuid ); + + if (!dinput_driver_start( report_desc, sizeof(report_desc), &hid_caps, NULL, 0 )) goto done; + + ret = joyGetNumDevs(); + todo_wine + ok( ret == 16, "joyGetNumDevs returned %u\n", ret ); + + ret = joyGetPosEx( 1, &infoex ); + ok( ret == JOYERR_PARMS, "joyGetPosEx returned %u\n", ret ); + 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) ); + ok( ret == JOYERR_PARMS, "joyGetDevCapsW returned %u\n", ret ); + + 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 ); + todo_wine + check_member( caps, expect_caps, "%#x", wXmin ); + todo_wine + check_member( caps, expect_caps, "%#x", wXmax ); + todo_wine + check_member( caps, expect_caps, "%#x", wYmin ); + todo_wine + check_member( caps, expect_caps, "%#x", wYmax ); + todo_wine + 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 ); + todo_wine + check_member( caps, expect_caps, "%#x", wRmin ); + todo_wine + check_member( caps, expect_caps, "%#x", wRmax ); + todo_wine + check_member( caps, expect_caps, "%#x", wUmin ); + todo_wine + check_member( caps, expect_caps, "%#x", wUmax ); + todo_wine + 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 ); + todo_wine + check_member_wstr( caps, expect_caps, szRegKey ); + todo_wine + check_member_wstr( caps, expect_caps, szOEMVxD ); + todo_wine + check_member_guid( caps, expect_caps, ManufacturerGuid ); + todo_wine + check_member_guid( caps, expect_caps, ProductGuid ); + todo_wine + 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 ); + ret = joyGetDevCapsW( 0, (JOYCAPSW *)&caps, sizeof(JOYCAPSW) + 4 ); + ok( ret == JOYERR_PARMS, "joyGetDevCapsW returned %u\n", ret ); + ret = joyGetDevCapsW( 0, (JOYCAPSW *)&caps, sizeof(JOYCAPSW) - 4 ); + ok( ret == JOYERR_PARMS, "joyGetDevCapsW returned %u\n", ret ); + + infoex.dwSize = sizeof(JOYINFOEX); + infoex.dwFlags = JOY_RETURNALL; + ret = joyGetPosEx( -1, &infoex ); + ok( ret == JOYERR_PARMS, "joyGetPosEx returned %u\n", ret ); + ret = joyGetPosEx( 1, &infoex ); + ok( ret == JOYERR_PARMS, "joyGetPosEx returned %u\n", ret ); + ret = joyGetPosEx( 16, &infoex ); + ok( ret == JOYERR_PARMS, "joyGetPosEx returned %u\n", ret ); + + memset( &infoex, 0xcd, sizeof(infoex) ); + 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, "%#x", dwSize ); + check_member( infoex, expect_infoex, "%#x", dwFlags ); + todo_wine + check_member( infoex, expect_infoex, "%#x", dwXpos ); + todo_wine + check_member( infoex, expect_infoex, "%#x", dwYpos ); + todo_wine + check_member( infoex, expect_infoex, "%#x", dwZpos ); + todo_wine + check_member( infoex, expect_infoex, "%#x", dwRpos ); + todo_wine + check_member( infoex, expect_infoex, "%#x", dwUpos ); + todo_wine + check_member( infoex, expect_infoex, "%#x", dwVpos ); + check_member( infoex, expect_infoex, "%#x", dwButtons ); + check_member( infoex, expect_infoex, "%#x", dwButtonNumber ); + todo_wine + check_member( infoex, expect_infoex, "%#x", dwPOV ); + todo_wine + check_member( infoex, expect_infoex, "%#x", dwReserved1 ); + todo_wine + check_member( infoex, expect_infoex, "%#x", dwReserved2 ); + + infoex.dwSize = sizeof(JOYINFOEX) - 4; + ret = joyGetPosEx( 0, &infoex ); + ok( ret == JOYERR_PARMS, "joyGetPosEx returned %u\n", ret ); + + ret = joyGetPos( -1, &info ); + ok( ret == JOYERR_PARMS, "joyGetPos returned %u\n", ret ); + ret = joyGetPos( 1, &info ); + 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 ); + +done: + pnp_driver_stop(); + cleanup_registry_keys(); + SetCurrentDirectoryW( cwd ); +} + START_TEST( hid ) { HANDLE mapping; @@ -9630,6 +9963,10 @@ START_TEST( hid ) CoInitialize( NULL ); if (test_device_types( 0x800 )) { + /* This needs to be done before doing anything involving dinput.dll + * on Windows, or the tests will fail, dinput8.dll is fine though. */ + test_winmm_joystick(); + test_device_types( 0x500 ); test_device_types( 0x700 );
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/dinput8/tests/hid.c | 171 ++++++++++++++++++++++++++++++++------- 1 file changed, 144 insertions(+), 27 deletions(-)
diff --git a/dlls/dinput8/tests/hid.c b/dlls/dinput8/tests/hid.c index 4aa37539202..677d436b894 100644 --- a/dlls/dinput8/tests/hid.c +++ b/dlls/dinput8/tests/hid.c @@ -9668,21 +9668,37 @@ static void test_winmm_joystick(void) .wMaxButtons = 32, .szRegKey = L"DINPUT.DLL", }; - static const JOYINFOEX expect_infoex = + struct hid_expect injected_input[] = { - .dwSize = sizeof(JOYINFOEX), - .dwFlags = 0xff, - .dwXpos = 0x7fff, - .dwYpos = 0x7fff, - .dwZpos = 0x7fff, - .dwRpos = 0x7fff, - .dwUpos = 0x7fff, - .dwVpos = 0x7fff, - .dwButtons = 0, - .dwButtonNumber = 0, - .dwPOV = 0xffff, - .dwReserved1 = 0xcdcdcdcd, - .dwReserved2 = 0xcdcdcdcd, + { + .code = IOCTL_HID_READ_REPORT, + .report_buf = {1,0x00,0x00,0x00,0x08,0x00,0x10,0x00,0x18,0x00,0x20,0x00,0x28,0x00,0x30,0x00,0x38,0xf1}, + }, + { + .code = IOCTL_HID_READ_REPORT, + .report_buf = {1,0x00,0x38,0x00,0x30,0x00,0x28,0x00,0x20,0x00,0x18,0x00,0x10,0x00,0x08,0x00,0x00,0x63}, + }, + }; + static const JOYINFOEX expect_infoex[] = + { + { + .dwSize = sizeof(JOYINFOEX), .dwFlags = 0xff, + .dwXpos = 0x7fff, .dwYpos = 0x7fff, .dwZpos = 0x7fff, .dwRpos = 0x7fff, .dwUpos = 0x7fff, .dwVpos = 0x7fff, + .dwButtons = 0, .dwButtonNumber = 0, .dwPOV = 0xffff, + .dwReserved1 = 0xcdcdcdcd, .dwReserved2 = 0xcdcdcdcd, + }, + { + .dwSize = sizeof(JOYINFOEX), .dwFlags = 0xff, + .dwXpos = 0, .dwYpos = 0x07ff, .dwZpos = 0x17ff, .dwRpos = 0x37ff, .dwUpos = 0x1fff, .dwVpos = 0x27ff, + .dwButtons = 0xf, .dwButtonNumber = 0x4, .dwPOV = 0, + .dwReserved1 = 0xcdcdcdcd, .dwReserved2 = 0xcdcdcdcd, + }, + { + .dwSize = sizeof(JOYINFOEX), .dwFlags = 0xff, + .dwXpos = 0x37ff, .dwYpos = 0x2fff, .dwZpos = 0x1fff, .dwRpos = 0, .dwUpos = 0x17ff, .dwVpos = 0x0fff, + .dwButtons = 0x6, .dwButtonNumber = 0x2, .dwPOV = 0x2328, + .dwReserved1 = 0xcdcdcdcd, .dwReserved2 = 0xcdcdcdcd, + }, }; static const JOYINFO expect_info = { @@ -9692,9 +9708,22 @@ static void test_winmm_joystick(void) .wButtons = 0, }; JOYINFOEX infoex = {.dwSize = sizeof(JOYINFOEX)}; + DIPROPGUIDANDPATH prop_guid_path = + { + .diph = + { + .dwSize = sizeof(DIPROPGUIDANDPATH), + .dwHeaderSize = sizeof(DIPROPHEADER), + .dwHow = DIPH_DEVICE, + }, + }; WCHAR cwd[MAX_PATH], tempdir[MAX_PATH]; + DIDEVICEINSTANCEW devinst = {0}; + IDirectInputDevice8W *device; JOYCAPS2W caps = {0}; JOYINFO info = {0}; + HANDLE event, file; + HRESULT hr; UINT ret;
GetCurrentDirectoryW( ARRAY_SIZE(cwd), cwd ); @@ -9872,28 +9901,28 @@ static void test_winmm_joystick(void) ret = joyGetPosEx( 0, &infoex ); todo_wine ok( ret == 0, "joyGetPosEx returned %u\n", ret ); - check_member( infoex, expect_infoex, "%#x", dwSize ); - check_member( infoex, expect_infoex, "%#x", dwFlags ); + check_member( infoex, expect_infoex[0], "%#x", dwSize ); + check_member( infoex, expect_infoex[0], "%#x", dwFlags ); todo_wine - check_member( infoex, expect_infoex, "%#x", dwXpos ); + check_member( infoex, expect_infoex[0], "%#x", dwXpos ); todo_wine - check_member( infoex, expect_infoex, "%#x", dwYpos ); + check_member( infoex, expect_infoex[0], "%#x", dwYpos ); todo_wine - check_member( infoex, expect_infoex, "%#x", dwZpos ); + check_member( infoex, expect_infoex[0], "%#x", dwZpos ); todo_wine - check_member( infoex, expect_infoex, "%#x", dwRpos ); + check_member( infoex, expect_infoex[0], "%#x", dwRpos ); todo_wine - check_member( infoex, expect_infoex, "%#x", dwUpos ); + check_member( infoex, expect_infoex[0], "%#x", dwUpos ); todo_wine - check_member( infoex, expect_infoex, "%#x", dwVpos ); - check_member( infoex, expect_infoex, "%#x", dwButtons ); - check_member( infoex, expect_infoex, "%#x", dwButtonNumber ); + 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, "%#x", dwPOV ); + check_member( infoex, expect_infoex[0], "%#x", dwPOV ); todo_wine - check_member( infoex, expect_infoex, "%#x", dwReserved1 ); + check_member( infoex, expect_infoex[0], "%#x", dwReserved1 ); todo_wine - check_member( infoex, expect_infoex, "%#x", dwReserved2 ); + check_member( infoex, expect_infoex[0], "%#x", dwReserved2 );
infoex.dwSize = sizeof(JOYINFOEX) - 4; ret = joyGetPosEx( 0, &infoex ); @@ -9915,6 +9944,94 @@ static void test_winmm_joystick(void) check_member( info, expect_info, "%#x", wZpos ); check_member( info, expect_info, "%#x", wButtons );
+ if (FAILED(hr = create_dinput_device( DIRECTINPUT_VERSION, &devinst, &device ))) goto done; + + event = CreateEventW( NULL, FALSE, FALSE, NULL ); + ok( event != NULL, "CreateEventW failed, last error %u\n", GetLastError() ); + hr = IDirectInputDevice8_SetEventNotification( device, event ); + ok( hr == DI_OK, "SetEventNotification returned: %#x\n", hr ); + + hr = IDirectInputDevice8_GetProperty( device, DIPROP_GUIDANDPATH, &prop_guid_path.diph ); + ok( hr == DI_OK, "GetProperty DIPROP_GUIDANDPATH returned %#x\n", hr ); + file = CreateFileW( prop_guid_path.wszPath, FILE_READ_ACCESS | FILE_WRITE_ACCESS, + FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, + FILE_FLAG_OVERLAPPED | FILE_FLAG_NO_BUFFERING, NULL ); + ok( file != INVALID_HANDLE_VALUE, "got error %u\n", GetLastError() ); + + hr = IDirectInputDevice8_SetDataFormat( device, &c_dfDIJoystick2 ); + ok( hr == DI_OK, "SetDataFormat returned: %#x\n", hr ); + hr = IDirectInputDevice8_SetCooperativeLevel( device, NULL, DISCL_BACKGROUND | DISCL_NONEXCLUSIVE ); + ok( hr == DI_OK, "SetCooperativeLevel returned: %#x\n", hr ); + hr = IDirectInputDevice8_Acquire( device ); + ok( hr == DI_OK, "Acquire returned: %#x\n", hr ); + + send_hid_input( file, &injected_input[0], sizeof(struct hid_expect) ); + ret = WaitForSingleObject( event, 100 ); + ok( ret != WAIT_TIMEOUT, "WaitForSingleObject returned %#x\n", ret ); + Sleep( 50 ); /* leave some time for winmm to keep up */ + + memset( &infoex, 0xcd, sizeof(infoex) ); + 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 ); + + send_hid_input( file, &injected_input[1], sizeof(struct hid_expect) ); + ret = WaitForSingleObject( event, 100 ); + ok( ret != WAIT_TIMEOUT, "WaitForSingleObject returned %#x\n", ret ); + Sleep( 50 ); /* leave some time for winmm to keep up */ + + memset( &infoex, 0xcd, sizeof(infoex) ); + 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 ); + ok( ret == 0, "Release returned %d\n", ret ); + + CloseHandle( event ); + CloseHandle( file ); + done: pnp_driver_stop(); cleanup_registry_keys();
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/dinput8/tests/hid.c | 39 --------------------------------------- dlls/winmm/joystick.c | 4 ++++ 2 files changed, 4 insertions(+), 39 deletions(-)
diff --git a/dlls/dinput8/tests/hid.c b/dlls/dinput8/tests/hid.c index 677d436b894..13b6e7bbec4 100644 --- a/dlls/dinput8/tests/hid.c +++ b/dlls/dinput8/tests/hid.c @@ -9745,61 +9745,33 @@ static void test_winmm_joystick(void)
memset( &caps, 0xcd, sizeof(caps) ); ret = joyGetDevCapsW( -1, (JOYCAPSW *)&caps, sizeof(caps) ); - todo_wine ok( ret == 0, "joyGetDevCapsW returned %u\n", ret ); - todo_wine check_member( caps, expect_regcaps, "%#x", wMid ); - todo_wine check_member( caps, expect_regcaps, "%#x", wPid ); - todo_wine check_member_wstr( caps, expect_regcaps, szPname ); - todo_wine check_member( caps, expect_regcaps, "%#x", wXmin ); - todo_wine check_member( caps, expect_regcaps, "%#x", wXmax ); - todo_wine check_member( caps, expect_regcaps, "%#x", wYmin ); - todo_wine check_member( caps, expect_regcaps, "%#x", wYmax ); - todo_wine check_member( caps, expect_regcaps, "%#x", wZmin ); - todo_wine check_member( caps, expect_regcaps, "%#x", wZmax ); - todo_wine check_member( caps, expect_regcaps, "%#x", wNumButtons ); - todo_wine check_member( caps, expect_regcaps, "%#x", wPeriodMin ); - todo_wine check_member( caps, expect_regcaps, "%#x", wPeriodMax ); - todo_wine check_member( caps, expect_regcaps, "%#x", wRmin ); - todo_wine check_member( caps, expect_regcaps, "%#x", wRmax ); - todo_wine check_member( caps, expect_regcaps, "%#x", wUmin ); - todo_wine check_member( caps, expect_regcaps, "%#x", wUmax ); - todo_wine check_member( caps, expect_regcaps, "%#x", wVmin ); - todo_wine check_member( caps, expect_regcaps, "%#x", wVmax ); - todo_wine check_member( caps, expect_regcaps, "%#x", wCaps ); - todo_wine check_member( caps, expect_regcaps, "%#x", wMaxAxes ); - todo_wine check_member( caps, expect_regcaps, "%#x", wNumAxes ); - todo_wine check_member( caps, expect_regcaps, "%#x", wMaxButtons ); - todo_wine check_member_wstr( caps, expect_regcaps, szRegKey ); - todo_wine check_member_wstr( caps, expect_regcaps, szOEMVxD ); - todo_wine check_member_guid( caps, expect_regcaps, ManufacturerGuid ); - todo_wine check_member_guid( caps, expect_regcaps, ProductGuid ); - todo_wine check_member_guid( caps, expect_regcaps, NameGuid );
if (!dinput_driver_start( report_desc, sizeof(report_desc), &hid_caps, NULL, 0 )) goto done; @@ -9829,15 +9801,12 @@ static void test_winmm_joystick(void) check_member( caps, expect_caps, "%#x", wPid ); todo_wine check_member_wstr( caps, expect_caps, szPname ); - todo_wine check_member( caps, expect_caps, "%#x", wXmin ); todo_wine check_member( caps, expect_caps, "%#x", wXmax ); - todo_wine check_member( caps, expect_caps, "%#x", wYmin ); todo_wine check_member( caps, expect_caps, "%#x", wYmax ); - todo_wine check_member( caps, expect_caps, "%#x", wZmin ); todo_wine check_member( caps, expect_caps, "%#x", wZmax ); @@ -9845,15 +9814,12 @@ static void test_winmm_joystick(void) check_member( caps, expect_caps, "%#x", wNumButtons ); check_member( caps, expect_caps, "%#x", wPeriodMin ); check_member( caps, expect_caps, "%#x", wPeriodMax ); - todo_wine check_member( caps, expect_caps, "%#x", wRmin ); todo_wine check_member( caps, expect_caps, "%#x", wRmax ); - todo_wine check_member( caps, expect_caps, "%#x", wUmin ); todo_wine check_member( caps, expect_caps, "%#x", wUmax ); - todo_wine check_member( caps, expect_caps, "%#x", wVmin ); todo_wine check_member( caps, expect_caps, "%#x", wVmax ); @@ -9865,15 +9831,10 @@ static void test_winmm_joystick(void) check_member( caps, expect_caps, "%#x", wNumAxes ); todo_wine check_member( caps, expect_caps, "%#x", wMaxButtons ); - todo_wine check_member_wstr( caps, expect_caps, szRegKey ); - todo_wine check_member_wstr( caps, expect_caps, szOEMVxD ); - todo_wine check_member_guid( caps, expect_caps, ManufacturerGuid ); - todo_wine check_member_guid( caps, expect_caps, ProductGuid ); - todo_wine check_member_guid( caps, expect_caps, NameGuid );
ret = joyGetDevCapsW( 0, (JOYCAPSW *)&caps, sizeof(JOYCAPSW) ); diff --git a/dlls/winmm/joystick.c b/dlls/winmm/joystick.c index bc9632df75c..89bd74433e3 100644 --- a/dlls/winmm/joystick.c +++ b/dlls/winmm/joystick.c @@ -174,6 +174,10 @@ MMRESULT WINAPI DECLSPEC_HOTPATCH joyGetDevCapsW( UINT_PTR id, LPJOYCAPSW caps, if (!caps) return MMSYSERR_INVALPARAM; if (size != sizeof(JOYCAPSW) && size != sizeof(JOYCAPS2W)) return JOYERR_PARMS;
+ memset( caps, 0, size ); + wcscpy( caps->szRegKey, L"DINPUT.DLL" ); + if (id == ~(UINT_PTR)0) return JOYERR_NOERROR; + if (id >= MAXJOYSTICK) return JOYERR_PARMS; if (!JOY_LoadDriver( id )) return MMSYSERR_NODRIVER;
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=103271
Your paranoid android.
=== w8 (32 bit report) ===
dinput8: driver_hid.c:236: Test failed: id 1: hid.c:9235 got spurious packet driver_hid.c:593: Test failed: id 1: hid.c:9235 expect[0]: got 0xb000f, expected 0 driver_hid.c:594: Test failed: id 1: hid.c:9235 expect[0]: got id 6 driver_hid.c:595: Test failed: id 1: hid.c:9235 expect[0]: got len 2
=== debiant2 (32 bit report) ===
winmm: joystick.c:94: Test failed: Expected 0 == 2 joystick.c:94: Test failed: Expected 0 == 2
=== debiant2 (32 bit Chinese:China report) ===
winmm: joystick.c:94: Test failed: Expected 0 == 2 joystick.c:94: Test failed: Expected 0 == 2
=== debiant2 (32 bit WoW report) ===
winmm: joystick.c:94: Test failed: Expected 0 == 2 joystick.c:94: Test failed: Expected 0 == 2
=== debiant2 (64 bit WoW report) ===
winmm: joystick.c:94: Test failed: Expected 0 == 2 joystick.c:94: Test failed: Expected 0 == 2
And rename the array from JOY_Sticks to joysticks.
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/dinput8/tests/hid.c | 2 - dlls/winmm/joystick.c | 79 ++++++++++++++++------------------------ 2 files changed, 32 insertions(+), 49 deletions(-)
diff --git a/dlls/dinput8/tests/hid.c b/dlls/dinput8/tests/hid.c index 13b6e7bbec4..f82fa9a7cb0 100644 --- a/dlls/dinput8/tests/hid.c +++ b/dlls/dinput8/tests/hid.c @@ -9733,7 +9733,6 @@ static void test_winmm_joystick(void) cleanup_registry_keys();
ret = joyGetNumDevs(); - todo_wine ok( ret == 16, "joyGetNumDevs returned %u\n", ret );
ret = joyGetDevCapsW( 0, (JOYCAPSW *)&caps, sizeof(JOYCAPSW) ); @@ -9777,7 +9776,6 @@ static void test_winmm_joystick(void) if (!dinput_driver_start( report_desc, sizeof(report_desc), &hid_caps, NULL, 0 )) goto done;
ret = joyGetNumDevs(); - todo_wine ok( ret == 16, "joyGetNumDevs returned %u\n", ret );
ret = joyGetPosEx( 1, &infoex ); diff --git a/dlls/winmm/joystick.c b/dlls/winmm/joystick.c index 89bd74433e3..43c68bd453c 100644 --- a/dlls/winmm/joystick.c +++ b/dlls/winmm/joystick.c @@ -40,7 +40,6 @@
WINE_DEFAULT_DEBUG_CHANNEL(winmm);
-#define MAXJOYSTICK (JOYSTICKID2 + 30) #define JOY_PERIOD_MIN (10) /* min Capture time period */ #define JOY_PERIOD_MAX (1000) /* max Capture time period */
@@ -53,7 +52,7 @@ typedef struct tagWINE_JOYSTICK { HDRVR hDriver; } WINE_JOYSTICK;
-static WINE_JOYSTICK JOY_Sticks[MAXJOYSTICK]; +static WINE_JOYSTICK joysticks[16];
static BOOL compare_uint(unsigned int x, unsigned int y, unsigned int max_diff) { @@ -68,14 +67,12 @@ static BOOL JOY_LoadDriver(DWORD dwJoyID) { static BOOL winejoystick_missing = FALSE;
- if (dwJoyID >= MAXJOYSTICK || winejoystick_missing) - return FALSE; - if (JOY_Sticks[dwJoyID].hDriver) - return TRUE; + if (dwJoyID >= ARRAY_SIZE(joysticks) || winejoystick_missing) return FALSE; + if (joysticks[dwJoyID].hDriver) return TRUE;
- JOY_Sticks[dwJoyID].hDriver = OpenDriverA("winejoystick.drv", 0, dwJoyID); + joysticks[dwJoyID].hDriver = OpenDriverA( "winejoystick.drv", 0, dwJoyID );
- if (!JOY_Sticks[dwJoyID].hDriver) + if (!joysticks[dwJoyID].hDriver) { WARN("OpenDriverA("winejoystick.drv") failed\n");
@@ -83,7 +80,7 @@ static BOOL JOY_LoadDriver(DWORD dwJoyID) winejoystick_missing = TRUE; }
- return (JOY_Sticks[dwJoyID].hDriver != 0); + return (joysticks[dwJoyID].hDriver != 0); }
/************************************************************************** @@ -98,10 +95,11 @@ static void CALLBACK JOY_Timer(HWND hWnd, UINT wMsg, UINT_PTR wTimer, DWORD dwTi LONG pos; unsigned buttonChange;
- for (i = 0; i < MAXJOYSTICK; i++) { - joy = &JOY_Sticks[i]; + for (i = 0; i < ARRAY_SIZE(joysticks); i++) + { + joy = &joysticks[i];
- if (joy->hCapture != hWnd) continue; + if (joy->hCapture != hWnd) continue;
res = joyGetPos(i, &ji); if (res != JOYERR_NOERROR) { @@ -153,15 +151,7 @@ MMRESULT WINAPI joyConfigChanged(DWORD flags) */ UINT WINAPI DECLSPEC_HOTPATCH joyGetNumDevs(void) { - UINT ret = 0; - int i; - - for (i = 0; i < MAXJOYSTICK; i++) { - if (JOY_LoadDriver(i)) { - ret += SendDriverMessage(JOY_Sticks[i].hDriver, JDD_GETNUMDEVS, 0, 0); - } - } - return ret; + return ARRAY_SIZE(joysticks); }
/************************************************************************** @@ -178,13 +168,13 @@ MMRESULT WINAPI DECLSPEC_HOTPATCH joyGetDevCapsW( UINT_PTR id, LPJOYCAPSW caps, wcscpy( caps->szRegKey, L"DINPUT.DLL" ); if (id == ~(UINT_PTR)0) return JOYERR_NOERROR;
- if (id >= MAXJOYSTICK) return JOYERR_PARMS; + 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) */
- return SendDriverMessage( JOY_Sticks[id].hDriver, JDD_GETDEVCAPS, (LPARAM)caps, size ); + return SendDriverMessage( joysticks[id].hDriver, JDD_GETDEVCAPS, (LPARAM)caps, size ); }
/************************************************************************** @@ -249,7 +239,7 @@ MMRESULT WINAPI DECLSPEC_HOTPATCH joyGetPosEx(UINT wID, LPJOYINFOEX lpInfo) TRACE("(%d, %p);\n", wID, lpInfo);
if (!lpInfo) return MMSYSERR_INVALPARAM; - if (wID >= MAXJOYSTICK || lpInfo->dwSize < sizeof(JOYINFOEX)) return JOYERR_PARMS; + if (wID >= ARRAY_SIZE(joysticks) || lpInfo->dwSize < sizeof(JOYINFOEX)) return JOYERR_PARMS; if (!JOY_LoadDriver(wID)) return MMSYSERR_NODRIVER;
lpInfo->dwXpos = 0; @@ -264,7 +254,7 @@ MMRESULT WINAPI DECLSPEC_HOTPATCH joyGetPosEx(UINT wID, LPJOYINFOEX lpInfo) lpInfo->dwReserved1 = 0; lpInfo->dwReserved2 = 0;
- return SendDriverMessage(JOY_Sticks[wID].hDriver, JDD_GETPOSEX, (LPARAM)lpInfo, 0); + return SendDriverMessage( joysticks[wID].hDriver, JDD_GETPOSEX, (LPARAM)lpInfo, 0 ); }
/************************************************************************** @@ -275,7 +265,7 @@ MMRESULT WINAPI joyGetPos(UINT wID, LPJOYINFO lpInfo) TRACE("(%d, %p);\n", wID, lpInfo);
if (!lpInfo) return MMSYSERR_INVALPARAM; - if (wID >= MAXJOYSTICK) return JOYERR_PARMS; + if (wID >= ARRAY_SIZE(joysticks)) return JOYERR_PARMS; if (!JOY_LoadDriver(wID)) return MMSYSERR_NODRIVER;
lpInfo->wXpos = 0; @@ -283,7 +273,7 @@ MMRESULT WINAPI joyGetPos(UINT wID, LPJOYINFO lpInfo) lpInfo->wZpos = 0; lpInfo->wButtons = 0;
- return SendDriverMessage(JOY_Sticks[wID].hDriver, JDD_GETPOS, (LPARAM)lpInfo, 0); + return SendDriverMessage( joysticks[wID].hDriver, JDD_GETPOS, (LPARAM)lpInfo, 0 ); }
/************************************************************************** @@ -293,9 +283,9 @@ MMRESULT WINAPI joyGetThreshold(UINT wID, LPUINT lpThreshold) { TRACE("(%04X, %p);\n", wID, lpThreshold);
- if (wID >= MAXJOYSTICK) return JOYERR_PARMS; + if (wID >= ARRAY_SIZE(joysticks)) return JOYERR_PARMS;
- *lpThreshold = JOY_Sticks[wID].threshold; + *lpThreshold = joysticks[wID].threshold; return JOYERR_NOERROR; }
@@ -306,13 +296,13 @@ MMRESULT WINAPI joyReleaseCapture(UINT wID) { TRACE("(%04X);\n", wID);
- if (wID >= MAXJOYSTICK) return JOYERR_PARMS; + if (wID >= ARRAY_SIZE(joysticks)) return JOYERR_PARMS; if (!JOY_LoadDriver(wID)) return MMSYSERR_NODRIVER; - if (JOY_Sticks[wID].hCapture) + if (joysticks[wID].hCapture) { - KillTimer(JOY_Sticks[wID].hCapture, JOY_Sticks[wID].wTimer); - JOY_Sticks[wID].hCapture = 0; - JOY_Sticks[wID].wTimer = 0; + KillTimer( joysticks[wID].hCapture, joysticks[wID].wTimer ); + joysticks[wID].hCapture = 0; + joysticks[wID].wTimer = 0; } else TRACE("Joystick is not captured, ignoring request.\n"); @@ -327,22 +317,17 @@ MMRESULT WINAPI joySetCapture(HWND hWnd, UINT wID, UINT wPeriod, BOOL bChanged) { TRACE("(%p, %04X, %d, %d);\n", hWnd, wID, wPeriod, bChanged);
- if (wID >= MAXJOYSTICK || hWnd == 0) return JOYERR_PARMS; + if (wID >= ARRAY_SIZE(joysticks) || hWnd == 0) return JOYERR_PARMS; if (wPeriod<JOY_PERIOD_MIN) wPeriod = JOY_PERIOD_MIN; else if(wPeriod>JOY_PERIOD_MAX) wPeriod = JOY_PERIOD_MAX; if (!JOY_LoadDriver(wID)) return MMSYSERR_NODRIVER;
- if (JOY_Sticks[wID].hCapture || !IsWindow(hWnd)) - return JOYERR_NOCANDO; /* FIXME: what should be returned ? */ + if (joysticks[wID].hCapture || !IsWindow( hWnd )) return JOYERR_NOCANDO; /* FIXME: what should be returned ? */ + if (joyGetPos( wID, &joysticks[wID].ji ) != JOYERR_NOERROR) return JOYERR_UNPLUGGED; + if ((joysticks[wID].wTimer = SetTimer( hWnd, 0, wPeriod, JOY_Timer )) == 0) return JOYERR_NOCANDO;
- if (joyGetPos(wID, &JOY_Sticks[wID].ji) != JOYERR_NOERROR) - return JOYERR_UNPLUGGED; - - if ((JOY_Sticks[wID].wTimer = SetTimer(hWnd, 0, wPeriod, JOY_Timer)) == 0) - return JOYERR_NOCANDO; - - JOY_Sticks[wID].hCapture = hWnd; - JOY_Sticks[wID].bChanged = bChanged; + joysticks[wID].hCapture = hWnd; + joysticks[wID].bChanged = bChanged;
return JOYERR_NOERROR; } @@ -354,9 +339,9 @@ MMRESULT WINAPI joySetThreshold(UINT wID, UINT wThreshold) { TRACE("(%04X, %d);\n", wID, wThreshold);
- if (wID >= MAXJOYSTICK || wThreshold > 65535) return MMSYSERR_INVALPARAM; + if (wID >= ARRAY_SIZE(joysticks) || wThreshold > 65535) return MMSYSERR_INVALPARAM;
- JOY_Sticks[wID].threshold = wThreshold; + joysticks[wID].threshold = wThreshold;
return JOYERR_NOERROR; }
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/winmm/joystick.c | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-)
diff --git a/dlls/winmm/joystick.c b/dlls/winmm/joystick.c index 43c68bd453c..85e46153ec8 100644 --- a/dlls/winmm/joystick.c +++ b/dlls/winmm/joystick.c @@ -260,20 +260,26 @@ MMRESULT WINAPI DECLSPEC_HOTPATCH joyGetPosEx(UINT wID, LPJOYINFOEX lpInfo) /************************************************************************** * joyGetPos [WINMM.@] */ -MMRESULT WINAPI joyGetPos(UINT wID, LPJOYINFO lpInfo) +MMRESULT WINAPI joyGetPos( UINT id, JOYINFO *info ) { - TRACE("(%d, %p);\n", wID, lpInfo); + JOYINFOEX infoex = + { + .dwSize = sizeof(JOYINFOEX), + .dwFlags = JOY_RETURNX | JOY_RETURNY | JOY_RETURNZ | JOY_RETURNBUTTONS, + }; + MMRESULT res;
- if (!lpInfo) return MMSYSERR_INVALPARAM; - if (wID >= ARRAY_SIZE(joysticks)) return JOYERR_PARMS; - if (!JOY_LoadDriver(wID)) return MMSYSERR_NODRIVER; + TRACE( "id %u, info %p.\n", id, info );
- lpInfo->wXpos = 0; - lpInfo->wYpos = 0; - lpInfo->wZpos = 0; - lpInfo->wButtons = 0; + if (!info) return MMSYSERR_INVALPARAM; + if ((res = joyGetPosEx( id, &infoex ))) return res;
- return SendDriverMessage( joysticks[wID].hDriver, JDD_GETPOS, (LPARAM)lpInfo, 0 ); + info->wXpos = infoex.dwXpos; + info->wYpos = infoex.dwYpos; + info->wZpos = infoex.dwZpos; + info->wButtons = infoex.dwButtons; + + return JOYERR_NOERROR; }
/**************************************************************************
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/winmm/joystick.c | 202 ++++++++++++++++++++---------------------- 1 file changed, 98 insertions(+), 104 deletions(-)
diff --git a/dlls/winmm/joystick.c b/dlls/winmm/joystick.c index 85e46153ec8..dea1e3b51ac 100644 --- a/dlls/winmm/joystick.c +++ b/dlls/winmm/joystick.c @@ -44,12 +44,12 @@ WINE_DEFAULT_DEBUG_CHANNEL(winmm); #define JOY_PERIOD_MAX (1000) /* max Capture time period */
typedef struct tagWINE_JOYSTICK { - JOYINFO ji; - HWND hCapture; - UINT wTimer; - DWORD threshold; - BOOL bChanged; - HDRVR hDriver; + JOYINFO info; + HWND capture; + UINT timer; + DWORD threshold; + BOOL changed; + HDRVR driver; } WINE_JOYSTICK;
static WINE_JOYSTICK joysticks[16]; @@ -68,11 +68,11 @@ static BOOL JOY_LoadDriver(DWORD dwJoyID) static BOOL winejoystick_missing = FALSE;
if (dwJoyID >= ARRAY_SIZE(joysticks) || winejoystick_missing) return FALSE; - if (joysticks[dwJoyID].hDriver) return TRUE; + if (joysticks[dwJoyID].driver) return TRUE;
- joysticks[dwJoyID].hDriver = OpenDriverA( "winejoystick.drv", 0, dwJoyID ); + joysticks[dwJoyID].driver = OpenDriverA( "winejoystick.drv", 0, dwJoyID );
- if (!joysticks[dwJoyID].hDriver) + if (!joysticks[dwJoyID].driver) { WARN("OpenDriverA("winejoystick.drv") failed\n");
@@ -80,56 +80,50 @@ static BOOL JOY_LoadDriver(DWORD dwJoyID) winejoystick_missing = TRUE; }
- return (joysticks[dwJoyID].hDriver != 0); + return (joysticks[dwJoyID].driver != 0); }
-/************************************************************************** - * JOY_Timer [internal] - */ -static void CALLBACK JOY_Timer(HWND hWnd, UINT wMsg, UINT_PTR wTimer, DWORD dwTime) +static void CALLBACK joystick_timer( HWND hwnd, UINT msg, UINT_PTR timer, DWORD time ) { - int i; - WINE_JOYSTICK* joy; - MMRESULT res; - JOYINFO ji; - LONG pos; - unsigned buttonChange; + MMRESULT res; + JOYINFO info; + WORD change; + LONG pos; + int i;
for (i = 0; i < ARRAY_SIZE(joysticks); i++) { - joy = &joysticks[i]; + if (joysticks[i].capture != hwnd) continue; + if ((res = joyGetPos( i, &info ))) + { + WARN( "joyGetPos failed: %08x\n", res ); + continue; + }
- if (joy->hCapture != hWnd) continue; + pos = MAKELONG( info.wXpos, info.wYpos );
- res = joyGetPos(i, &ji); - if (res != JOYERR_NOERROR) { - WARN("joyGetPos failed: %08x\n", res); - continue; - } - - pos = MAKELONG(ji.wXpos, ji.wYpos); - - if (!joy->bChanged || - !compare_uint(joy->ji.wXpos, ji.wXpos, joy->threshold) || - !compare_uint(joy->ji.wYpos, ji.wYpos, joy->threshold)) { - SendMessageA(joy->hCapture, MM_JOY1MOVE + i, ji.wButtons, pos); - joy->ji.wXpos = ji.wXpos; - joy->ji.wYpos = ji.wYpos; - } - if (!joy->bChanged || - !compare_uint(joy->ji.wZpos, ji.wZpos, joy->threshold)) { - SendMessageA(joy->hCapture, MM_JOY1ZMOVE + i, ji.wButtons, pos); - joy->ji.wZpos = ji.wZpos; - } - if ((buttonChange = joy->ji.wButtons ^ ji.wButtons) != 0) { - if (ji.wButtons & buttonChange) - SendMessageA(joy->hCapture, MM_JOY1BUTTONDOWN + i, - (buttonChange << 8) | (ji.wButtons & buttonChange), pos); - if (joy->ji.wButtons & buttonChange) - SendMessageA(joy->hCapture, MM_JOY1BUTTONUP + i, - (buttonChange << 8) | (joy->ji.wButtons & buttonChange), pos); - joy->ji.wButtons = ji.wButtons; - } + if (!joysticks[i].changed || + !compare_uint( joysticks[i].info.wXpos, info.wXpos, joysticks[i].threshold ) || + !compare_uint( joysticks[i].info.wYpos, info.wYpos, joysticks[i].threshold )) + { + SendMessageA( hwnd, MM_JOY1MOVE + i, info.wButtons, pos ); + joysticks[i].info.wXpos = info.wXpos; + joysticks[i].info.wYpos = info.wYpos; + } + if (!joysticks[i].changed || + !compare_uint( joysticks[i].info.wZpos, info.wZpos, joysticks[i].threshold )) + { + SendMessageA( hwnd, MM_JOY1ZMOVE + i, info.wButtons, pos ); + joysticks[i].info.wZpos = info.wZpos; + } + if ((change = joysticks[i].info.wButtons ^ info.wButtons) != 0) + { + if (info.wButtons & change) + SendMessageA( hwnd, MM_JOY1BUTTONDOWN + i, (change << 8) | (info.wButtons & change), pos ); + if (joysticks[i].info.wButtons & change) + SendMessageA( hwnd, MM_JOY1BUTTONUP + i, (change << 8) | (joysticks[i].info.wButtons & change), pos ); + joysticks[i].info.wButtons = info.wButtons; + } } }
@@ -138,11 +132,8 @@ static void CALLBACK JOY_Timer(HWND hWnd, UINT wMsg, UINT_PTR wTimer, DWORD dwTi */ MMRESULT WINAPI joyConfigChanged(DWORD flags) { - FIXME("(%x) - stub\n", flags); - - if (flags) - return JOYERR_PARMS; - + FIXME( "flags %#x stub!\n", flags ); + if (flags) return JOYERR_PARMS; return JOYERR_NOERROR; }
@@ -174,7 +165,7 @@ MMRESULT WINAPI DECLSPEC_HOTPATCH joyGetDevCapsW( UINT_PTR id, LPJOYCAPSW caps, caps->wPeriodMin = JOY_PERIOD_MIN; /* FIXME */ caps->wPeriodMax = JOY_PERIOD_MAX; /* FIXME (same as MS Joystick Driver) */
- return SendDriverMessage( joysticks[id].hDriver, JDD_GETDEVCAPS, (LPARAM)caps, size ); + return SendDriverMessage( joysticks[id].driver, JDD_GETDEVCAPS, (LPARAM)caps, size ); }
/************************************************************************** @@ -234,27 +225,27 @@ MMRESULT WINAPI DECLSPEC_HOTPATCH joyGetDevCapsA( UINT_PTR id, JOYCAPSA *caps, U /************************************************************************** * joyGetPosEx [WINMM.@] */ -MMRESULT WINAPI DECLSPEC_HOTPATCH joyGetPosEx(UINT wID, LPJOYINFOEX lpInfo) +MMRESULT WINAPI DECLSPEC_HOTPATCH joyGetPosEx( UINT id, JOYINFOEX *info ) { - TRACE("(%d, %p);\n", wID, lpInfo); + TRACE( "id %u, info %p.\n", id, info );
- if (!lpInfo) return MMSYSERR_INVALPARAM; - if (wID >= ARRAY_SIZE(joysticks) || lpInfo->dwSize < sizeof(JOYINFOEX)) return JOYERR_PARMS; - if (!JOY_LoadDriver(wID)) return MMSYSERR_NODRIVER; + if (!info) return MMSYSERR_INVALPARAM; + if (id >= ARRAY_SIZE(joysticks) || info->dwSize < sizeof(JOYINFOEX)) return JOYERR_PARMS; + if (!JOY_LoadDriver( id )) return MMSYSERR_NODRIVER;
- lpInfo->dwXpos = 0; - lpInfo->dwYpos = 0; - lpInfo->dwZpos = 0; - lpInfo->dwRpos = 0; - lpInfo->dwUpos = 0; - lpInfo->dwVpos = 0; - lpInfo->dwButtons = 0; - lpInfo->dwButtonNumber = 0; - lpInfo->dwPOV = 0; - lpInfo->dwReserved1 = 0; - lpInfo->dwReserved2 = 0; + 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;
- return SendDriverMessage( joysticks[wID].hDriver, JDD_GETPOSEX, (LPARAM)lpInfo, 0 ); + return SendDriverMessage( joysticks[id].driver, JDD_GETPOSEX, (LPARAM)info, 0 ); }
/************************************************************************** @@ -285,33 +276,34 @@ MMRESULT WINAPI joyGetPos( UINT id, JOYINFO *info ) /************************************************************************** * joyGetThreshold [WINMM.@] */ -MMRESULT WINAPI joyGetThreshold(UINT wID, LPUINT lpThreshold) +MMRESULT WINAPI joyGetThreshold( UINT id, UINT *threshold ) { - TRACE("(%04X, %p);\n", wID, lpThreshold); + TRACE( "id %u, threshold %p.\n", id, threshold );
- if (wID >= ARRAY_SIZE(joysticks)) return JOYERR_PARMS; + if (id >= ARRAY_SIZE(joysticks)) return JOYERR_PARMS;
- *lpThreshold = joysticks[wID].threshold; + *threshold = joysticks[id].threshold; return JOYERR_NOERROR; }
/************************************************************************** * joyReleaseCapture [WINMM.@] */ -MMRESULT WINAPI joyReleaseCapture(UINT wID) +MMRESULT WINAPI joyReleaseCapture( UINT id ) { - TRACE("(%04X);\n", wID); + TRACE( "id %u.\n", id );
- if (wID >= ARRAY_SIZE(joysticks)) return JOYERR_PARMS; - if (!JOY_LoadDriver(wID)) return MMSYSERR_NODRIVER; - if (joysticks[wID].hCapture) - { - KillTimer( joysticks[wID].hCapture, joysticks[wID].wTimer ); - joysticks[wID].hCapture = 0; - joysticks[wID].wTimer = 0; - } - else + if (id >= ARRAY_SIZE(joysticks)) return JOYERR_PARMS; + if (!JOY_LoadDriver( id )) return MMSYSERR_NODRIVER; + + if (!joysticks[id].capture) TRACE("Joystick is not captured, ignoring request.\n"); + else + { + KillTimer( joysticks[id].capture, joysticks[id].timer ); + joysticks[id].capture = 0; + joysticks[id].timer = 0; + }
return JOYERR_NOERROR; } @@ -319,21 +311,23 @@ MMRESULT WINAPI joyReleaseCapture(UINT wID) /************************************************************************** * joySetCapture [WINMM.@] */ -MMRESULT WINAPI joySetCapture(HWND hWnd, UINT wID, UINT wPeriod, BOOL bChanged) +MMRESULT WINAPI joySetCapture( HWND hwnd, UINT id, UINT period, BOOL changed ) { - TRACE("(%p, %04X, %d, %d);\n", hWnd, wID, wPeriod, bChanged); + TRACE( "hwnd %p, id %u, period %u, changed %u.\n", hwnd, id, period, changed );
- if (wID >= ARRAY_SIZE(joysticks) || hWnd == 0) return JOYERR_PARMS; - if (wPeriod<JOY_PERIOD_MIN) wPeriod = JOY_PERIOD_MIN; - else if(wPeriod>JOY_PERIOD_MAX) wPeriod = JOY_PERIOD_MAX; - if (!JOY_LoadDriver(wID)) return MMSYSERR_NODRIVER; + 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;
- if (joysticks[wID].hCapture || !IsWindow( hWnd )) return JOYERR_NOCANDO; /* FIXME: what should be returned ? */ - if (joyGetPos( wID, &joysticks[wID].ji ) != JOYERR_NOERROR) return JOYERR_UNPLUGGED; - if ((joysticks[wID].wTimer = SetTimer( hWnd, 0, wPeriod, JOY_Timer )) == 0) return JOYERR_NOCANDO; + if (joysticks[id].capture || !IsWindow( hwnd )) + return JOYERR_NOCANDO; /* FIXME: what should be returned ? */ + if (joyGetPos( id, &joysticks[id].info ) != JOYERR_NOERROR) return JOYERR_UNPLUGGED; + if ((joysticks[id].timer = SetTimer( hwnd, 0, period, joystick_timer )) == 0) + return JOYERR_NOCANDO;
- joysticks[wID].hCapture = hWnd; - joysticks[wID].bChanged = bChanged; + joysticks[id].capture = hwnd; + joysticks[id].changed = changed;
return JOYERR_NOERROR; } @@ -341,13 +335,13 @@ MMRESULT WINAPI joySetCapture(HWND hWnd, UINT wID, UINT wPeriod, BOOL bChanged) /************************************************************************** * joySetThreshold [WINMM.@] */ -MMRESULT WINAPI joySetThreshold(UINT wID, UINT wThreshold) +MMRESULT WINAPI joySetThreshold( UINT id, UINT threshold ) { - TRACE("(%04X, %d);\n", wID, wThreshold); + TRACE( "id %u, threshold %u.\n", id, threshold );
- if (wID >= ARRAY_SIZE(joysticks) || wThreshold > 65535) return MMSYSERR_INVALPARAM; + if (id >= ARRAY_SIZE(joysticks) || threshold > 65535) return MMSYSERR_INVALPARAM;
- joysticks[wID].threshold = wThreshold; + joysticks[id].threshold = threshold;
return JOYERR_NOERROR; }
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/winmm/joystick.c | 46 +++++++++++++++++++++++++++++++++++-------- 1 file changed, 38 insertions(+), 8 deletions(-)
diff --git a/dlls/winmm/joystick.c b/dlls/winmm/joystick.c index dea1e3b51ac..d5e27b5930d 100644 --- a/dlls/winmm/joystick.c +++ b/dlls/winmm/joystick.c @@ -40,6 +40,15 @@
WINE_DEFAULT_DEBUG_CHANNEL(winmm);
+static CRITICAL_SECTION joystick_cs; +static CRITICAL_SECTION_DEBUG critsect_debug = +{ + 0, 0, &joystick_cs, + { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList }, + 0, 0, { (DWORD_PTR)(__FILE__ ": joystick_cs") } +}; +static CRITICAL_SECTION joystick_cs = { &critsect_debug, -1, 0, 0, 0, 0 }; + #define JOY_PERIOD_MIN (10) /* min Capture time period */ #define JOY_PERIOD_MAX (1000) /* max Capture time period */
@@ -91,6 +100,8 @@ static void CALLBACK joystick_timer( HWND hwnd, UINT msg, UINT_PTR timer, DWORD LONG pos; int i;
+ EnterCriticalSection( &joystick_cs ); + for (i = 0; i < ARRAY_SIZE(joysticks); i++) { if (joysticks[i].capture != hwnd) continue; @@ -125,6 +136,8 @@ static void CALLBACK joystick_timer( HWND hwnd, UINT msg, UINT_PTR timer, DWORD joysticks[i].info.wButtons = info.wButtons; } } + + LeaveCriticalSection( &joystick_cs ); }
/************************************************************************** @@ -282,7 +295,10 @@ MMRESULT WINAPI joyGetThreshold( UINT id, UINT *threshold )
if (id >= ARRAY_SIZE(joysticks)) return JOYERR_PARMS;
+ EnterCriticalSection( &joystick_cs ); *threshold = joysticks[id].threshold; + LeaveCriticalSection( &joystick_cs ); + return JOYERR_NOERROR; }
@@ -296,6 +312,8 @@ MMRESULT WINAPI joyReleaseCapture( UINT id ) if (id >= ARRAY_SIZE(joysticks)) return JOYERR_PARMS; if (!JOY_LoadDriver( id )) return MMSYSERR_NODRIVER;
+ EnterCriticalSection( &joystick_cs ); + if (!joysticks[id].capture) TRACE("Joystick is not captured, ignoring request.\n"); else @@ -305,6 +323,8 @@ MMRESULT WINAPI joyReleaseCapture( UINT id ) joysticks[id].timer = 0; }
+ LeaveCriticalSection( &joystick_cs ); + return JOYERR_NOERROR; }
@@ -313,6 +333,8 @@ MMRESULT WINAPI joyReleaseCapture( UINT id ) */ MMRESULT WINAPI joySetCapture( HWND hwnd, UINT id, UINT period, BOOL changed ) { + MMRESULT res = JOYERR_NOERROR; + TRACE( "hwnd %p, id %u, period %u, changed %u.\n", hwnd, id, period, changed );
if (id >= ARRAY_SIZE(joysticks) || hwnd == 0) return JOYERR_PARMS; @@ -320,16 +342,22 @@ MMRESULT WINAPI joySetCapture( HWND hwnd, UINT id, UINT period, BOOL changed ) else if (period > JOY_PERIOD_MAX) period = JOY_PERIOD_MAX; if (!JOY_LoadDriver( id )) return MMSYSERR_NODRIVER;
+ EnterCriticalSection( &joystick_cs ); + if (joysticks[id].capture || !IsWindow( hwnd )) - return JOYERR_NOCANDO; /* FIXME: what should be returned ? */ - if (joyGetPos( id, &joysticks[id].info ) != JOYERR_NOERROR) return JOYERR_UNPLUGGED; - if ((joysticks[id].timer = SetTimer( hwnd, 0, period, joystick_timer )) == 0) - return JOYERR_NOCANDO; + res = JOYERR_NOCANDO; /* FIXME: what should be returned ? */ + else if (joyGetPos( id, &joysticks[id].info ) != JOYERR_NOERROR) + res = JOYERR_UNPLUGGED; + else if ((joysticks[id].timer = SetTimer( hwnd, 0, period, joystick_timer )) == 0) + res = JOYERR_NOCANDO; + else + { + joysticks[id].capture = hwnd; + joysticks[id].changed = changed; + }
- joysticks[id].capture = hwnd; - joysticks[id].changed = changed; - - return JOYERR_NOERROR; + LeaveCriticalSection( &joystick_cs ); + return res; }
/************************************************************************** @@ -341,7 +369,9 @@ MMRESULT WINAPI joySetThreshold( UINT id, UINT threshold )
if (id >= ARRAY_SIZE(joysticks) || threshold > 65535) return MMSYSERR_INVALPARAM;
+ EnterCriticalSection( &joystick_cs ); joysticks[id].threshold = threshold; + LeaveCriticalSection( &joystick_cs );
return JOYERR_NOERROR; }
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 | 357 +++++++++++++++++++++++++++++++++------ dlls/winmm/winemm.h | 3 + dlls/winmm/winmm.c | 2 + 5 files changed, 309 insertions(+), 106 deletions(-)
diff --git a/dlls/dinput8/tests/hid.c b/dlls/dinput8/tests/hid.c index f82fa9a7cb0..c7bf549deb1 100644 --- a/dlls/dinput8/tests/hid.c +++ b/dlls/dinput8/tests/hid.c @@ -9736,10 +9736,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) ); @@ -9783,7 +9779,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) ); @@ -9791,43 +9786,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 ); @@ -9836,7 +9817,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 ); @@ -9858,29 +9838,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; @@ -9893,13 +9863,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 );
@@ -9933,24 +9899,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 );
@@ -9963,26 +9921,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 d5e27b5930d..12dee4064d0 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; @@ -161,8 +306,24 @@ UINT WINAPI DECLSPEC_HOTPATCH joyGetNumDevs(void) /************************************************************************** * joyGetDevCapsW [WINMM.@] */ -MMRESULT WINAPI DECLSPEC_HOTPATCH joyGetDevCapsW( UINT_PTR id, LPJOYCAPSW caps, UINT size ) +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, LPJOYCAPSW caps, 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; }
/************************************************************************** @@ -240,25 +456,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; }
/************************************************************************** @@ -310,7 +561,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 );
@@ -340,7 +590,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();
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- configure.ac | 2 - dlls/winejoystick.drv/Makefile.in | 10 - dlls/winejoystick.drv/joystick.c | 52 -- dlls/winejoystick.drv/joystick.h | 34 - dlls/winejoystick.drv/joystick_linux.c | 462 ---------- dlls/winejoystick.drv/joystick_osx.c | 935 -------------------- dlls/winejoystick.drv/winejoystick.drv.spec | 1 - tools/winapi/win32.api | 13 - 8 files changed, 1509 deletions(-) delete mode 100644 dlls/winejoystick.drv/Makefile.in delete mode 100644 dlls/winejoystick.drv/joystick.c delete mode 100644 dlls/winejoystick.drv/joystick.h delete mode 100644 dlls/winejoystick.drv/joystick_linux.c delete mode 100644 dlls/winejoystick.drv/joystick_osx.c delete mode 100644 dlls/winejoystick.drv/winejoystick.drv.spec
diff --git a/configure.ac b/configure.ac index 2fe4b186fd6..328f80f17c9 100644 --- a/configure.ac +++ b/configure.ac @@ -899,7 +899,6 @@ esac enable_winecoreaudio_drv=${enable_winecoreaudio_drv:-no} enable_wineandroid_drv=${enable_wineandroid_drv:-no} enable_winemac_drv=${enable_winemac_drv:-no} -test "$ac_cv_header_linux_joystick_h" = "yes" -o "$ac_cv_header_IOKit_hid_IOHIDLib_h" = "yes" || enable_winejoystick_drv=${enable_winejoystick_drv:-no}
dnl Check for cross compiler to build test programs AC_SUBST(CROSSTARGET) @@ -3488,7 +3487,6 @@ WINE_CONFIG_MAKEFILE(dlls/winecrt0) WINE_CONFIG_MAKEFILE(dlls/wined3d) WINE_CONFIG_MAKEFILE(dlls/winegstreamer) WINE_CONFIG_MAKEFILE(dlls/winehid.sys) -WINE_CONFIG_MAKEFILE(dlls/winejoystick.drv) WINE_CONFIG_MAKEFILE(dlls/winemac.drv) WINE_CONFIG_MAKEFILE(dlls/winemapi) WINE_CONFIG_MAKEFILE(dlls/wineoss.drv) diff --git a/dlls/winejoystick.drv/Makefile.in b/dlls/winejoystick.drv/Makefile.in deleted file mode 100644 index 52564855994..00000000000 --- a/dlls/winejoystick.drv/Makefile.in +++ /dev/null @@ -1,10 +0,0 @@ -MODULE = winejoystick.drv -IMPORTS = winmm user32 -EXTRALIBS = $(IOKIT_LIBS) - -EXTRADLLFLAGS = -mcygwin - -C_SRCS = \ - joystick.c \ - joystick_linux.c \ - joystick_osx.c diff --git a/dlls/winejoystick.drv/joystick.c b/dlls/winejoystick.drv/joystick.c deleted file mode 100644 index 3e140b91175..00000000000 --- a/dlls/winejoystick.drv/joystick.c +++ /dev/null @@ -1,52 +0,0 @@ -/* - * WinMM joystick driver common code - * - * Copyright 1997 Andreas Mohr - * Copyright 2000 Wolfgang Schwotzer - * Copyright 2002 David Hagood - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA - */ - -#include "joystick.h" - - -/************************************************************************** - * DriverProc (JOYSTICK.@) - */ -LRESULT CALLBACK JSTCK_DriverProc(DWORD_PTR dwDevID, HDRVR hDriv, UINT wMsg, LPARAM dwParam1, LPARAM dwParam2) -{ - switch(wMsg) { - case DRV_LOAD: return 1; - case DRV_FREE: return 1; - case DRV_OPEN: return driver_open((LPSTR)dwParam1, dwParam2); - case DRV_CLOSE: return driver_close(dwDevID); - case DRV_ENABLE: return 1; - case DRV_DISABLE: return 1; - case DRV_QUERYCONFIGURE: return 1; - case DRV_CONFIGURE: MessageBoxA(0, "JoyStick MultiMedia Driver !", "JoyStick Driver", MB_OK); return 1; - case DRV_INSTALL: return DRVCNF_RESTART; - case DRV_REMOVE: return DRVCNF_RESTART; - - case JDD_GETNUMDEVS: return 1; - case JDD_GETDEVCAPS: return driver_joyGetDevCaps(dwDevID, (LPJOYCAPSW)dwParam1, dwParam2); - case JDD_GETPOS: return driver_joyGetPos(dwDevID, (LPJOYINFO)dwParam1); - case JDD_SETCALIBRATION: - case JDD_CONFIGCHANGED: return JOYERR_NOCANDO; - case JDD_GETPOSEX: return driver_joyGetPosEx(dwDevID, (LPJOYINFOEX)dwParam1); - default: - return DefDriverProc(dwDevID, hDriv, wMsg, dwParam1, dwParam2); - } -} diff --git a/dlls/winejoystick.drv/joystick.h b/dlls/winejoystick.drv/joystick.h deleted file mode 100644 index 1ec1edb8133..00000000000 --- a/dlls/winejoystick.drv/joystick.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * WinMM joystick driver header - * - * Copyright 2015 Ken Thomases for CodeWeavers Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA - */ - - -#include <stdarg.h> - -#include "windef.h" -#include "winbase.h" -#include "mmddk.h" -#include "winuser.h" - - -LRESULT driver_open(LPSTR str, DWORD index) DECLSPEC_HIDDEN; -LRESULT driver_close(DWORD_PTR device_id) DECLSPEC_HIDDEN; -LRESULT driver_joyGetDevCaps(DWORD_PTR device_id, JOYCAPSW* caps, DWORD size) DECLSPEC_HIDDEN; -LRESULT driver_joyGetPosEx(DWORD_PTR device_id, JOYINFOEX* info) DECLSPEC_HIDDEN; -LRESULT driver_joyGetPos(DWORD_PTR device_id, JOYINFO* info) DECLSPEC_HIDDEN; diff --git a/dlls/winejoystick.drv/joystick_linux.c b/dlls/winejoystick.drv/joystick_linux.c deleted file mode 100644 index 7fd2c95aff1..00000000000 --- a/dlls/winejoystick.drv/joystick_linux.c +++ /dev/null @@ -1,462 +0,0 @@ -/* - * joystick functions - * - * Copyright 1997 Andreas Mohr - * Copyright 2000 Wolfgang Schwotzer - * Copyright 2002 David Hagood - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA - * - * NOTES: - * - * - nearly all joystick functions can be regarded as obsolete, - * as Linux (2.1.x) now supports extended joysticks with a completely - * new joystick driver interface - * New driver's documentation says: - * "For backward compatibility the old interface is still included, - * but will be dropped in the future." - * Thus we should implement the new interface and at most keep the old - * routines for backward compatibility. - * - better support of enhanced joysticks (Linux 2.2 interface is available) - * - support more joystick drivers (like the XInput extension) - * - should load joystick DLL as any other driver (instead of hardcoding) - * the driver's name, and load it as any low lever driver. - */ - -#include "config.h" - -#ifdef HAVE_LINUX_22_JOYSTICK_API - -#ifdef HAVE_UNISTD_H -# include <unistd.h> -#endif -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <fcntl.h> -#ifdef HAVE_SYS_IOCTL_H -#include <sys/ioctl.h> -#endif -#ifdef HAVE_LINUX_IOCTL_H -#include <linux/ioctl.h> -#endif -#include <linux/joystick.h> -#ifdef SW_MAX -#undef SW_MAX -#endif -#define JOYDEV_NEW "/dev/input/js%d" -#define JOYDEV_OLD "/dev/js%d" -#include <errno.h> - -#include "joystick.h" - -#include "wingdi.h" -#include "winnls.h" -#include "wine/debug.h" - -WINE_DEFAULT_DEBUG_CHANNEL(joystick); - -#define MAXJOYSTICK (JOYSTICKID2 + 30) - -typedef struct tagWINE_JSTCK { - int joyIntf; - BOOL in_use; - /* Some extra info we need to make this actually work under the - Linux 2.2 event api. - First of all, we cannot keep closing and reopening the device file - - that blows away the state of the stick device, and we lose events. So, we - need to open the low-level device once, and close it when we are done. - - Secondly, the event API only gives us what's changed. However, Windows apps - want the whole state every time, so we have to cache the data. - */ - - int dev; /* Linux level device file descriptor */ - int x; - int y; - int z; - int r; - int u; - int v; - int pov_x; - int pov_y; - int buttons; - char axesMap[ABS_MAX + 1]; -} WINE_JSTCK; - -static WINE_JSTCK JSTCK_Data[MAXJOYSTICK]; - -/************************************************************************** - * JSTCK_drvGet [internal] - */ -static WINE_JSTCK *JSTCK_drvGet(DWORD_PTR dwDevID) -{ - int p; - - if ((dwDevID - (DWORD_PTR)JSTCK_Data) % sizeof(JSTCK_Data[0]) != 0) - return NULL; - p = (dwDevID - (DWORD_PTR)JSTCK_Data) / sizeof(JSTCK_Data[0]); - if (p < 0 || p >= MAXJOYSTICK || !((WINE_JSTCK*)dwDevID)->in_use) - return NULL; - - return (WINE_JSTCK*)dwDevID; -} - -/************************************************************************** - * driver_open - */ -LRESULT driver_open(LPSTR str, DWORD dwIntf) -{ - if (dwIntf >= MAXJOYSTICK || JSTCK_Data[dwIntf].in_use) - return 0; - - JSTCK_Data[dwIntf].joyIntf = dwIntf; - JSTCK_Data[dwIntf].dev = -1; - JSTCK_Data[dwIntf].in_use = TRUE; - return (LRESULT)&JSTCK_Data[dwIntf]; -} - -/************************************************************************** - * driver_close - */ -LRESULT driver_close(DWORD_PTR dwDevID) -{ - WINE_JSTCK* jstck = JSTCK_drvGet(dwDevID); - - if (jstck == NULL) - return 0; - jstck->in_use = FALSE; - if (jstck->dev > 0) - { - close(jstck->dev); - jstck->dev = 0; - } - return 1; -} - -struct js_status -{ - int buttons; - int x; - int y; -}; - -/************************************************************************** - * JSTCK_OpenDevice [internal] - */ -static int JSTCK_OpenDevice(WINE_JSTCK* jstick) -{ - char buf[20]; - int flags, fd, found_ix, i; - static DWORD last_attempt; - DWORD now; - - if (jstick->dev > 0) - return jstick->dev; - - now = GetTickCount(); - if (now - last_attempt < 2000) - return -1; - last_attempt = now; - - flags = O_RDONLY | O_NONBLOCK; - - /* The first joystick may not be at /dev/input/js0, find the correct - * first or second device. For example the driver for XBOX 360 wireless - * receiver creates entries starting at 20. - */ - for (found_ix = i = 0; i < MAXJOYSTICK; i++) { - sprintf(buf, JOYDEV_NEW, i); - if ((fd = open(buf, flags)) < 0) { - sprintf(buf, JOYDEV_OLD, i); - if ((fd = open(buf, flags)) < 0) - continue; - } - - if (found_ix++ == jstick->joyIntf) - { - TRACE("Found joystick[%d] at %s\n", jstick->joyIntf, buf); - jstick->dev = fd; - last_attempt = 0; - break; - } - - close(fd); - } - - if (jstick->dev > 0) - ioctl(jstick->dev, JSIOCGAXMAP, jstick->axesMap); - - return jstick->dev; -} - - -/************************************************************************** - * JoyGetDevCaps [MMSYSTEM.102] - */ -LRESULT driver_joyGetDevCaps(DWORD_PTR dwDevID, LPJOYCAPSW lpCaps, DWORD dwSize) -{ - WINE_JSTCK* jstck; - int dev; - char nrOfAxes; - char nrOfButtons; - char identString[MAXPNAMELEN]; - int i; - int driverVersion; - - if ((jstck = JSTCK_drvGet(dwDevID)) == NULL) - return MMSYSERR_NODRIVER; - - if ((dev = JSTCK_OpenDevice(jstck)) < 0) return JOYERR_PARMS; - ioctl(dev, JSIOCGAXES, &nrOfAxes); - ioctl(dev, JSIOCGBUTTONS, &nrOfButtons); - ioctl(dev, JSIOCGVERSION, &driverVersion); - ioctl(dev, JSIOCGNAME(sizeof(identString)), identString); - TRACE("Driver: 0x%06x, Name: %s, #Axes: %d, #Buttons: %d\n", - driverVersion, identString, nrOfAxes, nrOfButtons); - lpCaps->wMid = MM_MICROSOFT; - lpCaps->wPid = MM_PC_JOYSTICK; - MultiByteToWideChar(CP_UNIXCP, 0, identString, -1, lpCaps->szPname, MAXPNAMELEN); - lpCaps->szPname[MAXPNAMELEN-1] = '\0'; - lpCaps->wXmin = 0; - lpCaps->wXmax = 0xFFFF; - lpCaps->wYmin = 0; - lpCaps->wYmax = 0xFFFF; - lpCaps->wZmin = 0; - lpCaps->wZmax = (nrOfAxes >= 3) ? 0xFFFF : 0; -#ifdef BODGE_THE_HAT - /* Half-Life won't allow you to map an axis event to things like - "next weapon" and "use". Linux reports the hat on my stick as - axis U and V. So, IFF BODGE_THE_HAT is defined, lie through our - teeth and say we have 32 buttons, and we will map the axes to - the high buttons. Really, perhaps this should be a registry entry, - or even a parameter to the Linux joystick driver (which would completely - remove the need for this.) - */ - lpCaps->wNumButtons = 32; -#else - lpCaps->wNumButtons = nrOfButtons; -#endif - if (dwSize == sizeof(JOYCAPSW)) { - /* complete 95 structure */ - lpCaps->wRmin = 0; - lpCaps->wRmax = 0xFFFF; - lpCaps->wUmin = 0; - lpCaps->wUmax = 0xFFFF; - lpCaps->wVmin = 0; - lpCaps->wVmax = 0xFFFF; - lpCaps->wMaxAxes = 6; /* same as MS Joystick Driver */ - lpCaps->wNumAxes = 0; /* nr of axes in use */ - lpCaps->wMaxButtons = 32; /* same as MS Joystick Driver */ - lpCaps->szRegKey[0] = 0; - lpCaps->szOEMVxD[0] = 0; - lpCaps->wCaps = 0; - for (i = 0; i < nrOfAxes; i++) { - switch (jstck->axesMap[i]) { - case 0: /* X */ - case 1: /* Y */ - case 8: /* Wheel */ - case 9: /* Gas */ - lpCaps->wNumAxes++; - break; - case 2: /* Z */ - case 6: /* Throttle */ - case 10: /* Brake */ - lpCaps->wNumAxes++; - lpCaps->wCaps |= JOYCAPS_HASZ; - break; - case 5: /* Rz */ - case 7: /* Rudder */ - lpCaps->wNumAxes++; - lpCaps->wCaps |= JOYCAPS_HASR; - break; - case 3: /* Rx */ - lpCaps->wNumAxes++; - lpCaps->wCaps |= JOYCAPS_HASU; - break; - case 4: /* Ry */ - lpCaps->wNumAxes++; - lpCaps->wCaps |= JOYCAPS_HASV; - break; - case 16: /* Hat 0 X */ - case 17: /* Hat 0 Y */ - lpCaps->wCaps |= JOYCAPS_HASPOV | JOYCAPS_POV4DIR; - /* TODO: JOYCAPS_POVCTS handling */ - break; - default: - WARN("Unknown axis %hhu(%u). Skipped.\n", jstck->axesMap[i], i); - } - } - } - - return JOYERR_NOERROR; -} - -/************************************************************************** - * driver_joyGetPos - */ -LRESULT driver_joyGetPosEx(DWORD_PTR dwDevID, LPJOYINFOEX lpInfo) -{ - WINE_JSTCK* jstck; - int dev; - struct js_event ev; - - if ((jstck = JSTCK_drvGet(dwDevID)) == NULL) - return MMSYSERR_NODRIVER; - - if ((dev = JSTCK_OpenDevice(jstck)) < 0) return JOYERR_PARMS; - - while ((read(dev, &ev, sizeof(struct js_event))) > 0) { - if (ev.type == (JS_EVENT_AXIS)) { - switch (jstck->axesMap[ev.number]) { - case 0: /* X */ - case 8: /* Wheel */ - jstck->x = ev.value; - break; - case 1: /* Y */ - case 9: /* Gas */ - jstck->y = ev.value; - break; - case 2: /* Z */ - case 6: /* Throttle */ - case 10: /* Brake */ - jstck->z = ev.value; - break; - case 5: /* Rz */ - case 7: /* Rudder */ - jstck->r = ev.value; - break; - case 3: /* Rx */ - jstck->u = ev.value; - break; - case 4: /* Ry */ - jstck->v = ev.value; - break; - case 16: /* Hat 0 X */ - jstck->pov_x = ev.value; - break; - case 17: /* Hat 0 Y */ - jstck->pov_y = ev.value; - break; - default: - FIXME("Unknown joystick event '%d'\n", ev.number); - } - } else if (ev.type == (JS_EVENT_BUTTON)) { - if (ev.value) { - jstck->buttons |= (1 << ev.number); - /* FIXME: what to do for this field when - * multiple buttons are depressed ? - */ - if (lpInfo->dwFlags & JOY_RETURNBUTTONS) - lpInfo->dwButtonNumber = ev.number + 1; - } - else - jstck->buttons &= ~(1 << ev.number); - } - } - /* EAGAIN is returned when the queue is empty */ - if (errno != EAGAIN) { - /* FIXME: error should not be ignored */ - ERR("Error while reading joystick state (%s)\n", strerror(errno)); - } - /* Now, copy the cached values into Window's structure... */ - if (lpInfo->dwFlags & JOY_RETURNBUTTONS) - lpInfo->dwButtons = jstck->buttons; - if (lpInfo->dwFlags & JOY_RETURNX) - lpInfo->dwXpos = jstck->x + 32767; - if (lpInfo->dwFlags & JOY_RETURNY) - lpInfo->dwYpos = jstck->y + 32767; - if (lpInfo->dwFlags & JOY_RETURNZ) - lpInfo->dwZpos = jstck->z + 32767; - if (lpInfo->dwFlags & JOY_RETURNR) - lpInfo->dwRpos = jstck->r + 32767; -# ifdef BODGE_THE_HAT - else if (lpInfo->dwFlags & JOY_RETURNBUTTONS) - { - if (jstck->r > 0) - lpInfo->dwButtons |= 1<<7; - else if (jstck->r < 0) - lpInfo->dwButtons |= 1<<8; - } -# endif - if (lpInfo->dwFlags & JOY_RETURNU) - lpInfo->dwUpos = jstck->u + 32767; -# ifdef BODGE_THE_HAT - else if (lpInfo->dwFlags & JOY_RETURNBUTTONS) - { - if (jstck->u > 0) - lpInfo->dwButtons |= 1<<9; - else if (jstck->u < 0) - lpInfo->dwButtons |= 1<<10; - } -# endif - if (lpInfo->dwFlags & JOY_RETURNV) - lpInfo->dwVpos = jstck->v + 32767; - if (lpInfo->dwFlags & JOY_RETURNPOV) { - if (jstck->pov_y > 0) { - if (jstck->pov_x < 0) - lpInfo->dwPOV = 22500; /* SW */ - else if (jstck->pov_x > 0) - lpInfo->dwPOV = 13500; /* SE */ - else - lpInfo->dwPOV = 18000; /* S, JOY_POVBACKWARD */ - } else if (jstck->pov_y < 0) { - if (jstck->pov_x < 0) - lpInfo->dwPOV = 31500; /* NW */ - else if (jstck->pov_x > 0) - lpInfo->dwPOV = 4500; /* NE */ - else - lpInfo->dwPOV = 0; /* N, JOY_POVFORWARD */ - } else if (jstck->pov_x < 0) - lpInfo->dwPOV = 27000; /* W, JOY_POVLEFT */ - else if (jstck->pov_x > 0) - lpInfo->dwPOV = 9000; /* E, JOY_POVRIGHT */ - else - lpInfo->dwPOV = JOY_POVCENTERED; /* Center */ - } - - TRACE("x: %d, y: %d, z: %d, r: %d, u: %d, v: %d, buttons: 0x%04x, flags: 0x%04x (fd %d)\n", - lpInfo->dwXpos, lpInfo->dwYpos, lpInfo->dwZpos, - lpInfo->dwRpos, lpInfo->dwUpos, lpInfo->dwVpos, - lpInfo->dwButtons, lpInfo->dwFlags, dev - ); - - return JOYERR_NOERROR; -} - -/************************************************************************** - * driver_joyGetPos - */ -LRESULT driver_joyGetPos(DWORD_PTR dwDevID, LPJOYINFO lpInfo) -{ - JOYINFOEX ji; - LONG ret; - - memset(&ji, 0, sizeof(ji)); - - ji.dwSize = sizeof(ji); - ji.dwFlags = JOY_RETURNX | JOY_RETURNY | JOY_RETURNZ | JOY_RETURNBUTTONS; - ret = driver_joyGetPosEx(dwDevID, &ji); - if (ret == JOYERR_NOERROR) { - lpInfo->wXpos = ji.dwXpos; - lpInfo->wYpos = ji.dwYpos; - lpInfo->wZpos = ji.dwZpos; - lpInfo->wButtons = ji.dwButtons; - } - - return ret; -} - -#endif /* HAVE_LINUX_JOYSTICK_H */ diff --git a/dlls/winejoystick.drv/joystick_osx.c b/dlls/winejoystick.drv/joystick_osx.c deleted file mode 100644 index 6f53477937f..00000000000 --- a/dlls/winejoystick.drv/joystick_osx.c +++ /dev/null @@ -1,935 +0,0 @@ -/* - * WinMM joystick driver OS X implementation - * - * Copyright 1997 Andreas Mohr - * Copyright 1998 Marcus Meissner - * Copyright 1998,1999 Lionel Ulmer - * Copyright 2000 Wolfgang Schwotzer - * Copyright 2000-2001 TransGaming Technologies Inc. - * Copyright 2002 David Hagood - * Copyright 2009 CodeWeavers, Aric Stewart - * Copyright 2015 Ken Thomases for CodeWeavers Inc. - * Copyright 2016 David Lawrie - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA - */ - -#include "config.h" - -#if defined(HAVE_IOKIT_HID_IOHIDLIB_H) - -#define DWORD UInt32 -#define LPDWORD UInt32* -#define LONG SInt32 -#define LPLONG SInt32* -#define E_PENDING __carbon_E_PENDING -#define ULONG __carbon_ULONG -#define E_INVALIDARG __carbon_E_INVALIDARG -#define E_OUTOFMEMORY __carbon_E_OUTOFMEMORY -#define E_HANDLE __carbon_E_HANDLE -#define E_ACCESSDENIED __carbon_E_ACCESSDENIED -#define E_UNEXPECTED __carbon_E_UNEXPECTED -#define E_FAIL __carbon_E_FAIL -#define E_ABORT __carbon_E_ABORT -#define E_POINTER __carbon_E_POINTER -#define E_NOINTERFACE __carbon_E_NOINTERFACE -#define E_NOTIMPL __carbon_E_NOTIMPL -#define S_FALSE __carbon_S_FALSE -#define S_OK __carbon_S_OK -#define HRESULT_FACILITY __carbon_HRESULT_FACILITY -#define IS_ERROR __carbon_IS_ERROR -#define FAILED __carbon_FAILED -#define SUCCEEDED __carbon_SUCCEEDED -#define MAKE_HRESULT __carbon_MAKE_HRESULT -#define HRESULT __carbon_HRESULT -#define STDMETHODCALLTYPE __carbon_STDMETHODCALLTYPE -#include <IOKit/IOKitLib.h> -#include <IOKit/hid/IOHIDLib.h> -#undef ULONG -#undef E_INVALIDARG -#undef E_OUTOFMEMORY -#undef E_HANDLE -#undef E_ACCESSDENIED -#undef E_UNEXPECTED -#undef E_FAIL -#undef E_ABORT -#undef E_POINTER -#undef E_NOINTERFACE -#undef E_NOTIMPL -#undef S_FALSE -#undef S_OK -#undef HRESULT_FACILITY -#undef IS_ERROR -#undef FAILED -#undef SUCCEEDED -#undef MAKE_HRESULT -#undef HRESULT -#undef STDMETHODCALLTYPE -#undef DWORD -#undef LPDWORD -#undef LONG -#undef LPLONG -#undef E_PENDING - -#include "joystick.h" - -#include "wine/debug.h" - - -WINE_DEFAULT_DEBUG_CHANNEL(joystick); - - -#define MAXJOYSTICK (JOYSTICKID2 + 30) - - -enum { - AXIS_X, /* Winmm X */ - AXIS_Y, /* Winmm Y */ - AXIS_Z, /* Winmm Z */ - AXIS_RX, /* Winmm V */ - AXIS_RY, /* Winmm U */ - AXIS_RZ, /* Winmm R */ - NUM_AXES -}; - -struct axis { - IOHIDElementRef element; - CFIndex min_value, max_value; -}; - -typedef struct { - BOOL in_use; - IOHIDElementRef element; - struct axis axes[NUM_AXES]; - CFMutableArrayRef buttons; - IOHIDElementRef hatswitch; -} joystick_t; - - -static joystick_t joysticks[MAXJOYSTICK]; -static CFMutableArrayRef device_main_elements = NULL; - -static long get_device_property_long(IOHIDDeviceRef device, CFStringRef key) -{ - CFTypeRef ref; - long result = 0; - - if (device) - { - assert(IOHIDDeviceGetTypeID() == CFGetTypeID(device)); - - ref = IOHIDDeviceGetProperty(device, key); - - if (ref && CFNumberGetTypeID() == CFGetTypeID(ref)) - CFNumberGetValue((CFNumberRef)ref, kCFNumberLongType, &result); - } - - return result; -} - -static CFStringRef copy_device_name(IOHIDDeviceRef device) -{ - CFStringRef name; - - if (device) - { - CFTypeRef ref_name; - - assert(IOHIDDeviceGetTypeID() == CFGetTypeID(device)); - - ref_name = IOHIDDeviceGetProperty(device, CFSTR(kIOHIDProductKey)); - - if (ref_name && CFStringGetTypeID() == CFGetTypeID(ref_name)) - name = CFStringCreateCopy(kCFAllocatorDefault, ref_name); - else - { - long vendID, prodID; - - vendID = get_device_property_long(device, CFSTR(kIOHIDVendorIDKey)); - prodID = get_device_property_long(device, CFSTR(kIOHIDProductIDKey)); - name = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("0x%04lx 0x%04lx"), vendID, prodID); - } - } - else - { - ERR("NULL device\n"); - name = CFStringCreateCopy(kCFAllocatorDefault, CFSTR("")); - } - - return name; -} - -static long get_device_location_ID(IOHIDDeviceRef device) -{ - return get_device_property_long(device, CFSTR(kIOHIDLocationIDKey)); -} - -static const char* debugstr_cf(CFTypeRef t) -{ - CFStringRef s; - const char* ret; - - if (!t) return "(null)"; - - if (CFGetTypeID(t) == CFStringGetTypeID()) - s = t; - else - s = CFCopyDescription(t); - ret = CFStringGetCStringPtr(s, kCFStringEncodingUTF8); - if (ret) ret = debugstr_a(ret); - if (!ret) - { - const UniChar* u = CFStringGetCharactersPtr(s); - if (u) - ret = debugstr_wn((const WCHAR*)u, CFStringGetLength(s)); - } - if (!ret) - { - UniChar buf[200]; - int len = min(CFStringGetLength(s), ARRAY_SIZE(buf)); - CFStringGetCharacters(s, CFRangeMake(0, len), buf); - ret = debugstr_wn(buf, len); - } - if (s != t) CFRelease(s); - return ret; -} - -static const char* debugstr_device(IOHIDDeviceRef device) -{ - return wine_dbg_sprintf("<IOHIDDevice %p product %s IOHIDLocationID %lu>", device, - debugstr_cf(IOHIDDeviceGetProperty(device, CFSTR(kIOHIDProductKey))), - get_device_location_ID(device)); -} - -static const char* debugstr_element(IOHIDElementRef element) -{ - return wine_dbg_sprintf("<IOHIDElement %p type %d usage %u/%u device %p>", element, - IOHIDElementGetType(element), IOHIDElementGetUsagePage(element), - IOHIDElementGetUsage(element), IOHIDElementGetDevice(element)); -} - -static int axis_for_usage_GD(int usage) -{ - switch (usage) - { - case kHIDUsage_GD_X: return AXIS_X; - case kHIDUsage_GD_Y: return AXIS_Y; - case kHIDUsage_GD_Z: return AXIS_Z; - case kHIDUsage_GD_Rx: return AXIS_RX; - case kHIDUsage_GD_Ry: return AXIS_RY; - case kHIDUsage_GD_Rz: return AXIS_RZ; - } - - return -1; -} - -static int axis_for_usage_Sim(int usage) -{ - switch (usage) - { - case kHIDUsage_Sim_Rudder: return AXIS_RZ; - case kHIDUsage_Sim_Throttle: return AXIS_Z; - case kHIDUsage_Sim_Steering: return AXIS_X; - case kHIDUsage_Sim_Accelerator: return AXIS_Y; - case kHIDUsage_Sim_Brake: return AXIS_RZ; - } - - return -1; -} - -/************************************************************************** - * joystick_from_id - */ -static joystick_t* joystick_from_id(DWORD_PTR device_id) -{ - int index; - - if ((device_id - (DWORD_PTR)joysticks) % sizeof(joysticks[0]) != 0) - return NULL; - index = (device_id - (DWORD_PTR)joysticks) / sizeof(joysticks[0]); - if (index < 0 || index >= MAXJOYSTICK || !((joystick_t*)device_id)->in_use) - return NULL; - - return (joystick_t*)device_id; -} - -/************************************************************************** - * create_osx_device_match - */ -static CFDictionaryRef create_osx_device_match(int usage) -{ - CFDictionaryRef result = NULL; - int number; - CFStringRef keys[] = { CFSTR(kIOHIDDeviceUsagePageKey), CFSTR(kIOHIDDeviceUsageKey) }; - CFNumberRef values[2]; - int i; - - TRACE("usage %d\n", usage); - - number = kHIDPage_GenericDesktop; - values[0] = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &number); - values[1] = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &usage); - - if (values[0] && values[1]) - { - result = CFDictionaryCreate(NULL, (const void**)keys, (const void**)values, ARRAY_SIZE(values), - &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - - if (!result) - ERR("CFDictionaryCreate failed.\n"); - } - else - ERR("CFNumberCreate failed.\n"); - - for (i = 0; i < ARRAY_SIZE(values); i++) - if (values[i]) CFRelease(values[i]); - - return result; -} - -/************************************************************************** - * find_top_level - */ -static CFIndex find_top_level(IOHIDDeviceRef hid_device, CFMutableArrayRef main_elements) -{ - CFArrayRef elements; - CFIndex total = 0; - - TRACE("hid_device %s\n", debugstr_device(hid_device)); - - if (!hid_device) - return 0; - - elements = IOHIDDeviceCopyMatchingElements(hid_device, NULL, 0); - - if (elements) - { - CFIndex i, count = CFArrayGetCount(elements); - for (i = 0; i < count; i++) - { - IOHIDElementRef element = (IOHIDElementRef)CFArrayGetValueAtIndex(elements, i); - int type = IOHIDElementGetType(element); - - TRACE("element %s\n", debugstr_element(element)); - - /* Check for top-level gaming device collections */ - if (type == kIOHIDElementTypeCollection && IOHIDElementGetParent(element) == 0) - { - int usage_page = IOHIDElementGetUsagePage(element); - int usage = IOHIDElementGetUsage(element); - - if (usage_page == kHIDPage_GenericDesktop && - (usage == kHIDUsage_GD_Joystick || usage == kHIDUsage_GD_GamePad || usage == kHIDUsage_GD_MultiAxisController)) - { - CFArrayAppendValue(main_elements, element); - total++; - } - } - } - CFRelease(elements); - } - - TRACE("-> total %d\n", (int)total); - return total; -} -/************************************************************************** - * device_name_comparator - * - * Virtual joysticks may not have a kIOHIDLocationIDKey and will default to location ID of 0, this orders virtual joysticks by their name - */ -static CFComparisonResult device_name_comparator(IOHIDDeviceRef device1, IOHIDDeviceRef device2) -{ - CFStringRef name1 = copy_device_name(device1), name2 = copy_device_name(device2); - CFComparisonResult result = CFStringCompare(name1, name2, (kCFCompareForcedOrdering | kCFCompareNumerically)); - CFRelease(name1); - CFRelease(name2); - return result; -} - -/************************************************************************** - * device_location_name_comparator - * - * Helper to sort device array first by location ID, since location IDs are consistent across boots & launches, then by product name - */ -static CFComparisonResult device_location_name_comparator(const void *val1, const void *val2, void *context) -{ - IOHIDDeviceRef device1 = (IOHIDDeviceRef)val1, device2 = (IOHIDDeviceRef)val2; - long loc1 = get_device_location_ID(device1), loc2 = get_device_location_ID(device2); - - if (loc1 < loc2) - return kCFCompareLessThan; - else if (loc1 > loc2) - return kCFCompareGreaterThan; - return device_name_comparator(device1, device2); -} - -/************************************************************************** - * copy_set_to_array - * - * Helper to copy the CFSet to a CFArray - */ -static void copy_set_to_array(const void *value, void *context) -{ - CFArrayAppendValue(context, value); -} - -/************************************************************************** - * find_osx_devices - */ -static int find_osx_devices(void) -{ - IOHIDManagerRef hid_manager; - int usages[] = { kHIDUsage_GD_Joystick, kHIDUsage_GD_GamePad, kHIDUsage_GD_MultiAxisController }; - int i; - CFDictionaryRef matching_dicts[ARRAY_SIZE(usages)]; - CFArrayRef matching; - CFSetRef devset; - - TRACE("()\n"); - - hid_manager = IOHIDManagerCreate(kCFAllocatorDefault, 0L); - if (IOHIDManagerOpen(hid_manager, 0) != kIOReturnSuccess) - { - ERR("Couldn't open IOHIDManager.\n"); - CFRelease(hid_manager); - return 0; - } - - for (i = 0; i < ARRAY_SIZE(matching_dicts); i++) - { - matching_dicts[i] = create_osx_device_match(usages[i]); - if (!matching_dicts[i]) - { - while (i > 0) - CFRelease(matching_dicts[--i]); - goto fail; - } - } - - matching = CFArrayCreate(NULL, (const void**)matching_dicts, ARRAY_SIZE(matching_dicts), - &kCFTypeArrayCallBacks); - - for (i = 0; i < ARRAY_SIZE(matching_dicts); i++) - CFRelease(matching_dicts[i]); - - IOHIDManagerSetDeviceMatchingMultiple(hid_manager, matching); - CFRelease(matching); - devset = IOHIDManagerCopyDevices(hid_manager); - if (devset) - { - CFIndex num_devices, num_main_elements; - CFMutableArrayRef devices; - - num_devices = CFSetGetCount(devset); - devices = CFArrayCreateMutable(kCFAllocatorDefault, num_devices, &kCFTypeArrayCallBacks); - CFSetApplyFunction(devset, copy_set_to_array, (void *)devices); - CFArraySortValues(devices, CFRangeMake(0, num_devices), device_location_name_comparator, NULL); - - CFRelease(devset); - if (!devices) - goto fail; - - device_main_elements = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); - if (!device_main_elements) - { - CFRelease(devices); - goto fail; - } - - num_main_elements = 0; - for (i = 0; i < num_devices; i++) - { - IOHIDDeviceRef hid_device = (IOHIDDeviceRef)CFArrayGetValueAtIndex(devices, i); - TRACE("hid_device %s\n", debugstr_device(hid_device)); - num_main_elements += find_top_level(hid_device, device_main_elements); - } - - CFRelease(devices); - - TRACE("found %i device(s), %i collection(s)\n",(int)num_devices,(int)num_main_elements); - return (int)num_main_elements; - } - -fail: - IOHIDManagerClose(hid_manager, 0); - CFRelease(hid_manager); - return 0; -} - -/************************************************************************** - * collect_joystick_elements - */ -static void collect_joystick_elements(joystick_t* joystick, IOHIDElementRef collection) -{ - CFIndex i, count; - CFArrayRef children = IOHIDElementGetChildren(collection); - - TRACE("collection %s\n", debugstr_element(collection)); - - count = CFArrayGetCount(children); - for (i = 0; i < count; i++) - { - IOHIDElementRef child; - int type; - uint32_t usage_page; - - child = (IOHIDElementRef)CFArrayGetValueAtIndex(children, i); - TRACE("child %s\n", debugstr_element(child)); - type = IOHIDElementGetType(child); - usage_page = IOHIDElementGetUsagePage(child); - - switch (type) - { - case kIOHIDElementTypeCollection: - collect_joystick_elements(joystick, child); - break; - case kIOHIDElementTypeInput_Button: - { - TRACE("kIOHIDElementTypeInput_Button usage_page %d\n", usage_page); - - /* avoid strange elements found on the 360 controller */ - if (usage_page == kHIDPage_Button) - CFArrayAppendValue(joystick->buttons, child); - break; - } - case kIOHIDElementTypeInput_Axis: - case kIOHIDElementTypeInput_Misc: - { - uint32_t usage = IOHIDElementGetUsage( child ); - switch (usage_page) - { - case kHIDPage_GenericDesktop: - { - switch(usage) - { - case kHIDUsage_GD_Hatswitch: - { - TRACE("kIOHIDElementTypeInput_Axis/Misc / kHIDUsage_GD_Hatswitch\n"); - if (joystick->hatswitch) - TRACE(" ignoring additional hatswitch\n"); - else - joystick->hatswitch = (IOHIDElementRef)CFRetain(child); - break; - } - case kHIDUsage_GD_X: - case kHIDUsage_GD_Y: - case kHIDUsage_GD_Z: - case kHIDUsage_GD_Rx: - case kHIDUsage_GD_Ry: - case kHIDUsage_GD_Rz: - { - int axis = axis_for_usage_GD(usage); - TRACE("kIOHIDElementTypeInput_Axis/Misc / kHIDUsage_GD_<axis> (%d) axis %d\n", usage, axis); - if (axis < 0 || joystick->axes[axis].element) - TRACE(" ignoring\n"); - else - { - joystick->axes[axis].element = (IOHIDElementRef)CFRetain(child); - joystick->axes[axis].min_value = IOHIDElementGetLogicalMin(child); - joystick->axes[axis].max_value = IOHIDElementGetLogicalMax(child); - } - break; - } - case kHIDUsage_GD_Slider: - case kHIDUsage_GD_Dial: - case kHIDUsage_GD_Wheel: - { - /* if one axis is taken, fall to the next until axes are filled */ - int possible_axes[3] = {AXIS_Z,AXIS_RY,AXIS_RX}; - int axis = 0; - while(axis < 3 && joystick->axes[possible_axes[axis]].element) - axis++; - if (axis == 3) - TRACE("kIOHIDElementTypeInput_Axis/Misc / kHIDUsage_GD_<axis> (%d)\n ignoring\n", usage); - else - { - TRACE("kIOHIDElementTypeInput_Axis/Misc / kHIDUsage_GD_<axis> (%d) axis %d\n", usage, possible_axes[axis]); - joystick->axes[possible_axes[axis]].element = (IOHIDElementRef)CFRetain(child); - joystick->axes[possible_axes[axis]].min_value = IOHIDElementGetLogicalMin(child); - joystick->axes[possible_axes[axis]].max_value = IOHIDElementGetLogicalMax(child); - } - break; - } - default: - FIXME("kIOHIDElementTypeInput_Axis/Misc / Unhandled GD Page usage %d\n", usage); - break; - } - break; - } - case kHIDPage_Simulation: - { - switch(usage) - { - case kHIDUsage_Sim_Rudder: - case kHIDUsage_Sim_Throttle: - case kHIDUsage_Sim_Steering: - case kHIDUsage_Sim_Accelerator: - case kHIDUsage_Sim_Brake: - { - int axis = axis_for_usage_Sim(usage); - TRACE("kIOHIDElementTypeInput_Axis/Misc / kHIDUsage_Sim_<axis> (%d) axis %d\n", usage, axis); - if (axis < 0 || joystick->axes[axis].element) - TRACE(" ignoring\n"); - else - { - joystick->axes[axis].element = (IOHIDElementRef)CFRetain(child); - joystick->axes[axis].min_value = IOHIDElementGetLogicalMin(child); - joystick->axes[axis].max_value = IOHIDElementGetLogicalMax(child); - } - break; - } - default: - FIXME("kIOHIDElementTypeInput_Axis/Misc / Unhandled Sim Page usage %d\n", usage); - break; - } - break; - } - default: - FIXME("kIOHIDElementTypeInput_Axis/Misc / Unhandled Usage Page %d\n", usage_page); - break; - } - break; - } - case kIOHIDElementTypeFeature: - /* Describes input and output elements not intended for consumption by the end user. Ignoring. */ - break; - default: - FIXME("Unhandled type %i\n",type); - break; - } - } -} - -/************************************************************************** - * button_usage_comparator - */ -static CFComparisonResult button_usage_comparator(const void *val1, const void *val2, void *context) -{ - IOHIDElementRef element1 = (IOHIDElementRef)val1, element2 = (IOHIDElementRef)val2; - int usage1 = IOHIDElementGetUsage(element1), usage2 = IOHIDElementGetUsage(element2); - - if (usage1 < usage2) - return kCFCompareLessThan; - if (usage1 > usage2) - return kCFCompareGreaterThan; - return kCFCompareEqualTo; -} - -/************************************************************************** - * driver_open - */ -LRESULT driver_open(LPSTR str, DWORD index) -{ - if (index >= MAXJOYSTICK || joysticks[index].in_use) - return 0; - - joysticks[index].in_use = TRUE; - return (LRESULT)&joysticks[index]; -} - -/************************************************************************** - * driver_close - */ -LRESULT driver_close(DWORD_PTR device_id) -{ - joystick_t* joystick = joystick_from_id(device_id); - int i; - - if (joystick == NULL) - return 0; - - CFRelease(joystick->element); - for (i = 0; i < NUM_AXES; i++) - { - if (joystick->axes[i].element) - CFRelease(joystick->axes[i].element); - } - if (joystick->buttons) - CFRelease(joystick->buttons); - if (joystick->hatswitch) - CFRelease(joystick->hatswitch); - - memset(joystick, 0, sizeof(*joystick)); - return 1; -} - -/************************************************************************** - * open_joystick - */ -static BOOL open_joystick(joystick_t* joystick) -{ - CFIndex index; - CFRange range; - - if (joystick->element) - return TRUE; - - if (!device_main_elements) - { - find_osx_devices(); - if (!device_main_elements) - return FALSE; - } - - index = joystick - joysticks; - if (index >= CFArrayGetCount(device_main_elements)) - return FALSE; - - joystick->element = (IOHIDElementRef)CFArrayGetValueAtIndex(device_main_elements, index); - joystick->buttons = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); - collect_joystick_elements(joystick, joystick->element); - - /* Sort buttons into correct order */ - range.location = 0; - range.length = CFArrayGetCount(joystick->buttons); - CFArraySortValues(joystick->buttons, range, button_usage_comparator, NULL); - if (range.length > 32) - { - /* Delete any buttons beyond the first 32 */ - range.location = 32; - range.length -= 32; - CFArrayReplaceValues(joystick->buttons, range, NULL, 0); - } - - return TRUE; -} - - -/************************************************************************** - * driver_joyGetDevCaps - */ -LRESULT driver_joyGetDevCaps(DWORD_PTR device_id, JOYCAPSW* caps, DWORD size) -{ - joystick_t* joystick; - IOHIDDeviceRef device; - - if ((joystick = joystick_from_id(device_id)) == NULL) - return MMSYSERR_NODRIVER; - - if (!open_joystick(joystick)) - return JOYERR_PARMS; - - caps->szPname[0] = 0; - - device = IOHIDElementGetDevice(joystick->element); - if (device) - { - CFStringRef product_name = IOHIDDeviceGetProperty(device, CFSTR(kIOHIDProductKey)); - if (product_name) - { - CFRange range; - - range.location = 0; - range.length = min(MAXPNAMELEN - 1, CFStringGetLength(product_name)); - CFStringGetCharacters(product_name, range, (UniChar*)caps->szPname); - caps->szPname[range.length] = 0; - } - } - - caps->wMid = MM_MICROSOFT; - caps->wPid = MM_PC_JOYSTICK; - caps->wXmin = 0; - caps->wXmax = 0xFFFF; - caps->wYmin = 0; - caps->wYmax = 0xFFFF; - caps->wZmin = 0; - caps->wZmax = joystick->axes[AXIS_Z].element ? 0xFFFF : 0; - caps->wNumButtons = CFArrayGetCount(joystick->buttons); - if (size == sizeof(JOYCAPSW)) - { - int i; - - /* complete 95 structure */ - caps->wRmin = 0; - caps->wRmax = 0xFFFF; - caps->wUmin = 0; - caps->wUmax = 0xFFFF; - caps->wVmin = 0; - caps->wVmax = 0xFFFF; - caps->wMaxAxes = 6; /* same as MS Joystick Driver */ - caps->wNumAxes = 0; - caps->wMaxButtons = 32; /* same as MS Joystick Driver */ - caps->szRegKey[0] = 0; - caps->szOEMVxD[0] = 0; - caps->wCaps = 0; - - for (i = 0; i < NUM_AXES; i++) - { - if (joystick->axes[i].element) - { - caps->wNumAxes++; - switch (i) - { - case AXIS_Z: caps->wCaps |= JOYCAPS_HASZ; break; - case AXIS_RX: caps->wCaps |= JOYCAPS_HASV; break; - case AXIS_RY: caps->wCaps |= JOYCAPS_HASU; break; - case AXIS_RZ: caps->wCaps |= JOYCAPS_HASR; break; - } - } - } - - if (joystick->hatswitch) - caps->wCaps |= JOYCAPS_HASPOV | JOYCAPS_POV4DIR; - } - - TRACE("name %s buttons %u axes %d caps 0x%08x\n", debugstr_w(caps->szPname), caps->wNumButtons, caps->wNumAxes, caps->wCaps); - - return JOYERR_NOERROR; -} - -/* - * Helper to get the value from an element - */ -static LRESULT driver_getElementValue(IOHIDDeviceRef device, IOHIDElementRef element, IOHIDValueRef *pValueRef) -{ - IOReturn ret; - ret = IOHIDDeviceGetValue(device, element, pValueRef); - switch (ret) - { - case kIOReturnSuccess: - return JOYERR_NOERROR; - case kIOReturnNotAttached: - return JOYERR_UNPLUGGED; - default: - ERR("IOHIDDeviceGetValue returned 0x%x\n",ret); - return JOYERR_NOCANDO; - } -} - -/************************************************************************** - * driver_joyGetPosEx - */ -LRESULT driver_joyGetPosEx(DWORD_PTR device_id, JOYINFOEX* info) -{ - static const struct { - DWORD flag; - off_t offset; - } axis_map[NUM_AXES] = { - { JOY_RETURNX, FIELD_OFFSET(JOYINFOEX, dwXpos) }, - { JOY_RETURNY, FIELD_OFFSET(JOYINFOEX, dwYpos) }, - { JOY_RETURNZ, FIELD_OFFSET(JOYINFOEX, dwZpos) }, - { JOY_RETURNV, FIELD_OFFSET(JOYINFOEX, dwVpos) }, - { JOY_RETURNU, FIELD_OFFSET(JOYINFOEX, dwUpos) }, - { JOY_RETURNR, FIELD_OFFSET(JOYINFOEX, dwRpos) }, - }; - - joystick_t* joystick; - IOHIDDeviceRef device; - CFIndex i, count; - IOHIDValueRef valueRef; - long value; - LRESULT rc; - - if ((joystick = joystick_from_id(device_id)) == NULL) - return MMSYSERR_NODRIVER; - - if (!open_joystick(joystick)) - return JOYERR_PARMS; - - device = IOHIDElementGetDevice(joystick->element); - - if (info->dwFlags & JOY_RETURNBUTTONS) - { - info->dwButtons = 0; - info->dwButtonNumber = 0; - - count = CFArrayGetCount(joystick->buttons); - for (i = 0; i < count; i++) - { - IOHIDElementRef button = (IOHIDElementRef)CFArrayGetValueAtIndex(joystick->buttons, i); - rc = driver_getElementValue(device, button, &valueRef); - if (rc != JOYERR_NOERROR) - return rc; - value = IOHIDValueGetIntegerValue(valueRef); - if (value) - { - info->dwButtons |= 1 << i; - info->dwButtonNumber++; - } - } - } - - for (i = 0; i < NUM_AXES; i++) - { - if (info->dwFlags & axis_map[i].flag) - { - DWORD* field = (DWORD*)((char*)info + axis_map[i].offset); - if (joystick->axes[i].element) - { - rc = driver_getElementValue(device, joystick->axes[i].element, &valueRef); - if (rc != JOYERR_NOERROR) - return rc; - value = IOHIDValueGetIntegerValue(valueRef) - joystick->axes[i].min_value; - *field = MulDiv(value, 0xFFFF, joystick->axes[i].max_value - joystick->axes[i].min_value); - } - else - { - *field = 0; - info->dwFlags &= ~axis_map[i].flag; - } - } - } - - if (info->dwFlags & JOY_RETURNPOV) - { - if (joystick->hatswitch) - { - rc = driver_getElementValue(device, joystick->hatswitch, &valueRef); - if (rc != JOYERR_NOERROR) - return rc; - value = IOHIDValueGetIntegerValue(valueRef); - if (value >= 8) - info->dwPOV = JOY_POVCENTERED; - else - info->dwPOV = value * 4500; - } - else - { - info->dwPOV = JOY_POVCENTERED; - info->dwFlags &= ~JOY_RETURNPOV; - } - } - - TRACE("x: %d, y: %d, z: %d, r: %d, u: %d, v: %d, buttons: 0x%04x, pov %d, flags: 0x%04x\n", - info->dwXpos, info->dwYpos, info->dwZpos, info->dwRpos, info->dwUpos, info->dwVpos, info->dwButtons, info->dwPOV, info->dwFlags); - - return JOYERR_NOERROR; -} - -/************************************************************************** - * driver_joyGetPos - */ -LRESULT driver_joyGetPos(DWORD_PTR device_id, JOYINFO* info) -{ - JOYINFOEX ji; - LONG ret; - - memset(&ji, 0, sizeof(ji)); - - ji.dwSize = sizeof(ji); - ji.dwFlags = JOY_RETURNX | JOY_RETURNY | JOY_RETURNZ | JOY_RETURNBUTTONS; - ret = driver_joyGetPosEx(device_id, &ji); - if (ret == JOYERR_NOERROR) - { - info->wXpos = ji.dwXpos; - info->wYpos = ji.dwYpos; - info->wZpos = ji.dwZpos; - info->wButtons = ji.dwButtons; - } - - return ret; -} - -#endif /* HAVE_IOKIT_HID_IOHIDLIB_H */ diff --git a/dlls/winejoystick.drv/winejoystick.drv.spec b/dlls/winejoystick.drv/winejoystick.drv.spec deleted file mode 100644 index 29932efde7c..00000000000 --- a/dlls/winejoystick.drv/winejoystick.drv.spec +++ /dev/null @@ -1 +0,0 @@ -@ stdcall -private DriverProc(long long long long long) JSTCK_DriverProc diff --git a/tools/winapi/win32.api b/tools/winapi/win32.api index d9b77dbce39..5f3dd85cc93 100644 --- a/tools/winapi/win32.api +++ b/tools/winapi/win32.api @@ -5615,19 +5615,6 @@ IUnknown * IWineD3D * IWineD3DClipper *
-%%winejoystick.drv - -%long - -HDRVR -LPARAM -LRESULT -UINT - -%long --pointer - -DWORD_PTR - %%l3codeca.acm
%long
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=103268
Your paranoid android.
=== debiant2 (32 bit report) ===
winmm: joystick.c:94: Test failed: Expected 7471204 == 2 joystick.c:94: Test failed: Expected 7471204 == 2
=== debiant2 (32 bit Chinese:China report) ===
winmm: joystick.c:94: Test failed: Expected 7471204 == 2 joystick.c:94: Test failed: Expected 7471204 == 2
=== debiant2 (32 bit WoW report) ===
winmm: joystick.c:94: Test failed: Expected 7471204 == 2 joystick.c:94: Test failed: Expected 7471204 == 2
=== debiant2 (64 bit WoW report) ===
winmm: joystick.c:94: Test failed: Expected 6617488 == 2 joystick.c:94: Test failed: Expected 6617488 == 2