evdev: check well-known keyboard keys on joystick/gamepad detection

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 <jose.exposito89@gmail.com>
This commit is contained in:
José Expósito 2022-03-01 20:08:11 +01:00
parent 2e7dd3f84e
commit ea568a7bcb

View file

@ -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++;