From 29db3393bc6c4ac7d2ae4473d457856e8aca62d7 Mon Sep 17 00:00:00 2001 From: Alistair Leslie-Hughes Date: Tue, 7 May 2019 09:44:57 +1000 Subject: [PATCH] Updated dinput-joy-directX3 patchset --- ...stics-to-guess-if-a-device-is-a-game.patch | 203 ++++++++++++++++++ patches/dinput-joy-directX3/definition | 3 +- patches/patchinstall.sh | 7 +- 3 files changed, 210 insertions(+), 3 deletions(-) create mode 100644 patches/dinput-joy-directX3/0002--dinput-Use-heuristics-to-guess-if-a-device-is-a-game.patch diff --git a/patches/dinput-joy-directX3/0002--dinput-Use-heuristics-to-guess-if-a-device-is-a-game.patch b/patches/dinput-joy-directX3/0002--dinput-Use-heuristics-to-guess-if-a-device-is-a-game.patch new file mode 100644 index 00000000..bf93c670 --- /dev/null +++ b/patches/dinput-joy-directX3/0002--dinput-Use-heuristics-to-guess-if-a-device-is-a-game.patch @@ -0,0 +1,203 @@ +From ad66457e277817f93fdc4b26b72919ea85147d8e Mon Sep 17 00:00:00 2001 +From: Andrew Eikum +Date: Mon, 6 May 2019 10:14:24 -0500 +Subject: [PATCH] dinput: Use heuristics to guess if a device is a gamepad or a + joystick + +Fixes: https://bugs.winehq.org/show_bug.cgi?id=47123 + +--- + dlls/dinput/dinput_private.h | 2 +- + dlls/dinput/joystick.c | 6 +++++- + dlls/dinput/joystick_linux.c | 38 +++++++++++++++++++++++++++++++++++++- + dlls/dinput/joystick_linuxinput.c | 27 ++++++++++++++++++++++++--- + dlls/dinput/joystick_osx.c | 6 ++++-- + 5 files changed, 71 insertions(+), 8 deletions(-) + +diff --git a/dlls/dinput/dinput_private.h b/dlls/dinput/dinput_private.h +index c97a493..289b2f1 100644 +--- a/dlls/dinput/dinput_private.h ++++ b/dlls/dinput/dinput_private.h +@@ -81,7 +81,7 @@ extern void _copy_diactionformatWtoA(LPDIACTIONFORMATA, LPDIACTIONFORMATW) DECLS + extern HRESULT _configure_devices(IDirectInput8W *iface, LPDICONFIGUREDEVICESCALLBACK lpdiCallback, LPDICONFIGUREDEVICESPARAMSW lpdiCDParams, DWORD dwFlags, LPVOID pvRefData) DECLSPEC_HIDDEN; + + extern WCHAR* get_mapping_path(const WCHAR *device, const WCHAR *username) DECLSPEC_HIDDEN; +-extern DWORD get_device_type(DWORD version) DECLSPEC_HIDDEN; ++extern DWORD get_device_type(DWORD version, BOOL is_joystick) DECLSPEC_HIDDEN; + + #define IS_DIPROP(x) (((ULONG_PTR)(x) >> 16) == 0) + +diff --git a/dlls/dinput/joystick.c b/dlls/dinput/joystick.c +index 9240ba3..6bd0dc9 100644 +--- a/dlls/dinput/joystick.c ++++ b/dlls/dinput/joystick.c +@@ -76,8 +76,12 @@ DWORD typeFromGUID(REFGUID guid) + } + } + +-DWORD get_device_type(DWORD version) ++DWORD get_device_type(DWORD version, BOOL is_joystick) + { ++ if (is_joystick) ++ return version >= 0x0800 ? DI8DEVTYPE_JOYSTICK | (DI8DEVTYPEJOYSTICK_STANDARD << 8) : ++ DIDEVTYPE_JOYSTICK | (DIDEVTYPEJOYSTICK_TRADITIONAL << 8); ++ + return version >= 0x0800 ? DI8DEVTYPE_GAMEPAD | (DI8DEVTYPEJOYSTICK_STANDARD << 8) : + DIDEVTYPE_JOYSTICK | (DIDEVTYPEJOYSTICK_GAMEPAD << 8); + } +diff --git a/dlls/dinput/joystick_linux.c b/dlls/dinput/joystick_linux.c +index fb1b878..6e22e14 100644 +--- a/dlls/dinput/joystick_linux.c ++++ b/dlls/dinput/joystick_linux.c +@@ -84,6 +84,8 @@ struct JoyDev + int *dev_axes_map; + + WORD vendor_id, product_id, bus_type; ++ ++ BOOL is_joystick; + }; + + typedef struct JoystickImpl JoystickImpl; +@@ -177,6 +179,7 @@ static INT find_joystick_devices(void) + int fd; + struct JoyDev joydev, *new_joydevs; + BYTE axes_map[ABS_MAX + 1]; ++ SHORT btn_map[KEY_MAX - BTN_MISC + 1]; + + snprintf(joydev.device, sizeof(joydev.device), "%s%d", JOYDEV_NEW, i); + if ((fd = open(joydev.device, O_RDONLY)) == -1) +@@ -220,6 +223,39 @@ static INT find_joystick_devices(void) + joydev.button_count = 2; + #endif + ++ joydev.is_joystick = FALSE; ++ if (ioctl(fd, JSIOCGBTNMAP, btn_map) < 0) ++ { ++ WARN("ioctl(%s,JSIOCGBTNMAP) failed: %s\n", joydev.device, strerror(errno)); ++ } ++ else ++ { ++ INT j; ++ for (j = 0; !joydev.is_joystick && j < joydev.button_count; j++) ++ { ++ switch(btn_map[j]) ++ { ++ case BTN_TRIGGER: ++ case BTN_THUMB: ++ case BTN_THUMB2: ++ case BTN_TOP: ++ case BTN_TOP2: ++ case BTN_PINKIE: ++ case BTN_BASE: ++ case BTN_BASE2: ++ case BTN_BASE3: ++ case BTN_BASE4: ++ case BTN_BASE5: ++ case BTN_BASE6: ++ case BTN_DEAD: ++ joydev.is_joystick = TRUE; ++ break; ++ default: ++ break; ++ } ++ } ++ } ++ + if (ioctl(fd, JSIOCGAXMAP, axes_map) < 0) + { + WARN("ioctl(%s,JSIOCGAXMAP) failed: %s\n", joydev.device, strerror(errno)); +@@ -322,7 +358,7 @@ static void fill_joystick_dideviceinstanceW(LPDIDEVICEINSTANCEW lpddi, DWORD ver + lpddi->guidInstance = DInput_Wine_Joystick_GUID; + lpddi->guidInstance.Data3 = id; + lpddi->guidProduct = joystick_devices[id].guid_product; +- lpddi->dwDevType = get_device_type(version); ++ lpddi->dwDevType = get_device_type(version, joystick_devices[id].is_joystick); + + /* Assume the joystick as HID if it is attached to USB bus and has a valid VID/PID */ + if (joystick_devices[id].bus_type == BUS_USB && +diff --git a/dlls/dinput/joystick_linuxinput.c b/dlls/dinput/joystick_linuxinput.c +index bc3c4de..d386403 100644 +--- a/dlls/dinput/joystick_linuxinput.c ++++ b/dlls/dinput/joystick_linuxinput.c +@@ -100,7 +100,7 @@ struct JoyDev { + GUID guid; + GUID guid_product; + +- BOOL has_ff; ++ BOOL has_ff, is_joystick; + int num_effects; + + /* data returned by EVIOCGBIT for caps, EV_ABS, EV_KEY, and EV_FF */ +@@ -243,6 +243,24 @@ static void find_joydevs(void) + continue; + } + ++ /* in lieu of properly reporting HID usage, detect presence of ++ * "joystick buttons" and report those devices as joysticks instead of ++ * gamepads */ ++ joydev.is_joystick = ++ test_bit(joydev.keybits, BTN_TRIGGER) || ++ test_bit(joydev.keybits, BTN_THUMB) || ++ test_bit(joydev.keybits, BTN_THUMB2) || ++ test_bit(joydev.keybits, BTN_TOP) || ++ test_bit(joydev.keybits, BTN_TOP2) || ++ test_bit(joydev.keybits, BTN_PINKIE) || ++ test_bit(joydev.keybits, BTN_BASE) || ++ test_bit(joydev.keybits, BTN_BASE2) || ++ test_bit(joydev.keybits, BTN_BASE3) || ++ test_bit(joydev.keybits, BTN_BASE4) || ++ test_bit(joydev.keybits, BTN_BASE5) || ++ test_bit(joydev.keybits, BTN_BASE6) || ++ test_bit(joydev.keybits, BTN_DEAD); ++ + if (!(joydev.device = HeapAlloc(GetProcessHeap(), 0, strlen(buf) + 1))) + { + close(fd); +@@ -350,7 +368,7 @@ static void fill_joystick_dideviceinstanceW(LPDIDEVICEINSTANCEW lpddi, DWORD ver + lpddi->guidInstance = joydevs[id].guid; + lpddi->guidProduct = joydevs[id].guid_product; + lpddi->guidFFDriver = GUID_NULL; +- lpddi->dwDevType = get_device_type(version); ++ lpddi->dwDevType = get_device_type(version, joydevs[id].is_joystick); + + /* Assume the joystick as HID if it is attached to USB bus and has a valid VID/PID */ + if (joydevs[id].bus_type == BUS_USB && +@@ -358,7 +376,10 @@ static void fill_joystick_dideviceinstanceW(LPDIDEVICEINSTANCEW lpddi, DWORD ver + { + lpddi->dwDevType |= DIDEVTYPE_HID; + lpddi->wUsagePage = 0x01; /* Desktop */ +- lpddi->wUsage = 0x05; /* Game Pad */ ++ if (joydevs[id].is_joystick) ++ lpddi->wUsage = 0x04; /* Joystick */ ++ else ++ lpddi->wUsage = 0x05; /* Game Pad */ + } + + MultiByteToWideChar(CP_ACP, 0, joydevs[id].name, -1, lpddi->tszInstanceName, MAX_PATH); +diff --git a/dlls/dinput/joystick_osx.c b/dlls/dinput/joystick_osx.c +index cb88b2f..1955cb7 100644 +--- a/dlls/dinput/joystick_osx.c ++++ b/dlls/dinput/joystick_osx.c +@@ -967,7 +967,8 @@ static HRESULT joydev_enum_deviceA(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEINS + lpddi->guidInstance.Data3 = id; + lpddi->guidProduct = DInput_Wine_OsX_Joystick_GUID; + lpddi->guidProduct.Data1 = make_vid_pid(device); +- lpddi->dwDevType = get_device_type(version); ++ lpddi->dwDevType = get_device_type(version, ++ get_device_property_long(device, kIOHIDDeviceUsageKey) == kHIDUsage_GD_Joystick); + lpddi->dwDevType |= DIDEVTYPE_HID; + lpddi->wUsagePage = 0x01; /* Desktop */ + lpddi->wUsage = 0x05; /* Game Pad */ +@@ -1010,7 +1011,8 @@ static HRESULT joydev_enum_deviceW(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEINS + lpddi->guidInstance.Data3 = id; + lpddi->guidProduct = DInput_Wine_OsX_Joystick_GUID; + lpddi->guidProduct.Data1 = make_vid_pid(device); +- lpddi->dwDevType = get_device_type(version); ++ lpddi->dwDevType = get_device_type(version, ++ get_device_property_long(device, kIOHIDDeviceUsageKey) == kHIDUsage_GD_Joystick); + sprintf(friendly, "Joystick %d", id); + MultiByteToWideChar(CP_ACP, 0, friendly, -1, lpddi->tszInstanceName, MAX_PATH); + /* get the device name */ +-- +1.9.1 + diff --git a/patches/dinput-joy-directX3/definition b/patches/dinput-joy-directX3/definition index 4a1edf54..0c333e72 100644 --- a/patches/dinput-joy-directX3/definition +++ b/patches/dinput-joy-directX3/definition @@ -1,2 +1,3 @@ Fixes: [36764] dinput: Allow DirectX version 3 to enumerate joysticks. -# Other cleanups for dinput. +Fixes: [47123] dinput: Use heuristics to guess if a device is a gamepad or a joystick. + diff --git a/patches/patchinstall.sh b/patches/patchinstall.sh index 6169decc..91064ef9 100755 --- a/patches/patchinstall.sh +++ b/patches/patchinstall.sh @@ -3074,15 +3074,18 @@ fi # | # | This patchset fixes the following Wine bugs: # | * [#36764] dinput: Allow DirectX version 3 to enumerate joysticks. +# | * [#47123] dinput: Use heuristics to guess if a device is a gamepad or a joystick. # | # | Modified files: -# | * dlls/dinput/joystick_linux.c, dlls/dinput/joystick_linuxinput.c, dlls/dinput/joystick_osx.c, -# | dlls/dinput/tests/joystick.c +# | * dlls/dinput/dinput_private.h, dlls/dinput/joystick.c, dlls/dinput/joystick_linux.c, dlls/dinput/joystick_linuxinput.c, +# | dlls/dinput/joystick_osx.c, dlls/dinput/tests/joystick.c # | if test "$enable_dinput_joy_directX3" -eq 1; then patch_apply dinput-joy-directX3/0001-dinput-Allow-Enumeration-of-joysticks-with-DirectX-3.patch + patch_apply dinput-joy-directX3/0002--dinput-Use-heuristics-to-guess-if-a-device-is-a-game.patch ( printf '%s\n' '+ { "Alistair Leslie-Hughes", "dinput: Allow Enumeration of joysticks with DirectX 3.", 1 },'; + printf '%s\n' '+ { "Andrew Eikum", "dinput: Use heuristics to guess if a device is a gamepad or a joystick.", 1 },'; ) >> "$patchlist" fi