From ea568a7bcb37d3365a92269aa07d721cbd3fad3a Mon Sep 17 00:00:00 2001 From: =?utf8?q?Jos=C3=A9=20Exp=C3=B3sito?= Date: Tue, 1 Mar 2022 20:08:11 +0100 Subject: [PATCH] evdev: check well-known keyboard keys on joystick/gamepad detection MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Create a list of well-known keyboard keys containing one the most representative key(s) of a group. The rule is based on the assumption that if the representative key is present, other keys of the group should be present as well. The groups are: - Modifiers group: KEY_LEFTCTRL. - Character group: KEY_CAPSLOCK. - Numeric group: KEY_NUMLOCK. - Editing keys: KEY_INSERT. - Multimedia keys: KEY_MUTE, KEY_CALC, KEY_FILE, KEY_MAIL, KEY_PLAYPAUSE and KEY_BRIGHTNESSDOWN. When 4 of these keys are found, the device is tagged as a keyboard. Fix #745 Signed-off-by: José Expósito --- src/evdev.c | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/src/evdev.c b/src/evdev.c index 6d81f58..453ac3f 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -88,6 +88,19 @@ static const struct evdev_udev_tag_match evdev_udev_tag_matches[] = { {"ID_INPUT_SWITCH", EVDEV_UDEV_TAG_SWITCH}, }; +static const unsigned int well_known_keyboard_keys[] = { + KEY_LEFTCTRL, + KEY_CAPSLOCK, + KEY_NUMLOCK, + KEY_INSERT, + KEY_MUTE, + KEY_CALC, + KEY_FILE, + KEY_MAIL, + KEY_PLAYPAUSE, + KEY_BRIGHTNESSDOWN, +}; + static inline bool parse_udev_flag(struct evdev_device *device, struct udev_device *udev_device, @@ -1868,8 +1881,9 @@ evdev_device_is_joystick_or_gamepad(struct evdev_device *device) * 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 */ + * 2. The device doesn't have 4 well-known keyboard keys + * 3. It has at least 2 joystick buttons + * 4. It doesn't have 10 keyboard keys */ udev_tags = evdev_device_get_udev_tags(device, device->udev_device); has_joystick_tags = (udev_tags & EVDEV_UDEV_TAG_JOYSTICK) && @@ -1880,6 +1894,17 @@ evdev_device_is_joystick_or_gamepad(struct evdev_device *device) return false; + unsigned int num_well_known_keys = 0; + + for (size_t i = 0; i < ARRAY_LENGTH(well_known_keyboard_keys); i++) { + code = well_known_keyboard_keys[i]; + if (libevdev_has_event_code(evdev, EV_KEY, code)) + num_well_known_keys++; + } + + if (num_well_known_keys >= 4) /* should not have 4 well-known keys */ + return false; + for (code = BTN_JOYSTICK; code < BTN_DIGI; code++) { if (libevdev_has_event_code(evdev, EV_KEY, code)) num_joystick_btns++; -- 2.7.4