diff options
author | José Expósito <jose.exposito89@gmail.com> | 2021-11-23 18:07:53 +0100 |
---|---|---|
committer | Peter Hutterer <peter.hutterer@who-t.net> | 2021-12-03 00:20:47 +0000 |
commit | 8dd8786c482b8811cf0628571e6724e540ce61d7 (patch) | |
tree | fecb552fd896a5d7d99728e427702f49e4656a7b /src | |
parent | a694a06b925009d836e5ba17cb73e29fdbcb188c (diff) |
evdev: improve joystick and gamepad detection
The EVDEV_UDEV_TAG_JOYSTICK is set when a joystick or gamepad button
is found. However, it can not be used to identify joysticks or
gamepads because there are keyboards that also have it. Even worse,
many joysticks also map KEY_* and thus are tagged as keyboards.
In order to be able to detect joysticks and gamepads and
differentiate them from keyboards, apply the following rules:
1. The device is tagged as joystick but not as tablet
2. It has at least 2 joystick buttons
3. It doesn't have 10 keyboard keys
Fix #701
Fix #415
Fix #703
Signed-off-by: José Expósito <jose.exposito89@gmail.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/evdev.c | 58 |
1 files changed, 55 insertions, 3 deletions
diff --git a/src/evdev.c b/src/evdev.c index 9eb2d30b..cf0a2846 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -1854,12 +1854,64 @@ static bool evdev_device_is_joystick_or_gamepad(struct evdev_device *device) { enum evdev_device_udev_tags udev_tags; + bool has_joystick_tags; + struct libevdev *evdev = device->evdev; + unsigned int code, num_joystick_btns = 0, num_keys = 0; + + /* The EVDEV_UDEV_TAG_JOYSTICK is set when a joystick or gamepad button + * is found. However, it can not be used to identify joysticks or + * gamepads because there are keyboards that also have it. Even worse, + * many joysticks also map KEY_* and thus are tagged as keyboards. + * + * In order to be able to detect joysticks and gamepads and + * differentiate them from keyboards, apply the following rules: + * + * 1. The device is tagged as joystick but not as tablet + * 2. It has at least 2 joystick buttons + * 3. It doesn't have 10 keyboard keys */ udev_tags = evdev_device_get_udev_tags(device, device->udev_device); - if (udev_tags == (EVDEV_UDEV_TAG_INPUT|EVDEV_UDEV_TAG_JOYSTICK)) - return true; + has_joystick_tags = (udev_tags & EVDEV_UDEV_TAG_JOYSTICK) && + !(udev_tags & EVDEV_UDEV_TAG_TABLET) && + !(udev_tags & EVDEV_UDEV_TAG_TABLET_PAD); - return false; + if (!has_joystick_tags) + return false; + + + for (code = BTN_JOYSTICK; code < BTN_DIGI; code++) { + if (libevdev_has_event_code(evdev, EV_KEY, code)) + num_joystick_btns++; + } + + for (code = BTN_TRIGGER_HAPPY; code <= BTN_TRIGGER_HAPPY40; code++) { + if (libevdev_has_event_code(evdev, EV_KEY, code)) + num_joystick_btns++; + } + + if (num_joystick_btns < 2) /* require at least 2 joystick buttons */ + return false; + + + for (code = KEY_ESC; code <= KEY_MICMUTE; code++) { + if (libevdev_has_event_code(evdev, EV_KEY, code) ) + num_keys++; + } + + for (code = KEY_OK; code <= KEY_LIGHTS_TOGGLE; code++) { + if (libevdev_has_event_code(evdev, EV_KEY, code) ) + num_keys++; + } + + for (code = KEY_ALS_TOGGLE; code < BTN_TRIGGER_HAPPY; code++) { + if (libevdev_has_event_code(evdev, EV_KEY, code) ) + num_keys++; + } + + if (num_keys >= 10) /* should not have 10 keyboard keys */ + return false; + + return true; } static struct evdev_dispatch * |