diff --git a/Makefile.am b/Makefile.am index c61f371a8e..9fc2faf211 100644 --- a/Makefile.am +++ b/Makefile.am @@ -3887,6 +3887,7 @@ dist_udevrules_DATA += \ nodist_udevrules_DATA += \ rules/50-udev-default.rules \ + rules/60-input-id.rules \ rules/99-systemd.rules udevconfdir = $(sysconfdir)/udev @@ -3925,10 +3926,10 @@ noinst_LTLIBRARIES += \ src/udev/keyboard-keys-list.txt: $(AM_V_at)$(MKDIR_P) $(dir $@) - $(AM_V_GEN)$(CPP) $(CFLAGS) $(AM_CPPFLAGS) $(CPPFLAGS) -dM -include linux/input.h - < /dev/null | $(AWK) '/^#define[ \t]+KEY_[^ ]+[ \t]+[0-9K]/ { if ($$2 != "KEY_MAX") { print $$2 } }' > $@ + $(AM_V_GEN)$(top_srcdir)/src/udev/generate-keyboard-keys-list.sh "$(CPP) $(CFLAGS) $(AM_CPPFLAGS) $(CPPFLAGS)" > $@ src/udev/keyboard-keys-from-name.gperf: src/udev/keyboard-keys-list.txt - $(AM_V_GEN)$(AWK) 'BEGIN{ print "struct key_name { const char* name; unsigned short id; };"; print "%null-strings"; print "%%";} { print tolower(substr($$1 ,5)) ", " $$1 }' < $< > $@ + $(AM_V_GEN)$(top_srcdir)/src/udev/generate-keyboard-keys-gperf.sh $< > $@ src/udev/keyboard-keys-from-name.h: src/udev/keyboard-keys-from-name.gperf $(AM_V_GPERF)$(GPERF) -L ANSI-C -t -N keyboard_lookup_key -H hash_key_name -p -C < $< > $@ diff --git a/hwdb/60-keyboard.hwdb b/hwdb/60-keyboard.hwdb index e8be567166..881a531b67 100644 --- a/hwdb/60-keyboard.hwdb +++ b/hwdb/60-keyboard.hwdb @@ -58,6 +58,8 @@ # KEYBOARD_KEY_= # The scan code should be expressed in hex lowercase. The key codes # are retrieved and normalized from the kernel input API header. +# Keycodes are either KEY_* defines in lowercase with the key_ prefix +# optionally removed or BTN_ defines in lowercase with btn_ preserved. # # An '!' as the first character of the key identifier string # will add the scan code to the AT keyboard's list of scan codes @@ -80,7 +82,8 @@ # systemd-hwdb update # udevadm trigger /dev/input/eventXX # where /dev/input/eventXX is the keyboard in question. If in -# doubt, simply use /dev/input/event* to reload all input rules. +# doubt, simply reload all input rules +# udevadm trigger --verbose --sysname-match="event*" # # If your changes are generally applicable, preferably send them as a pull # request to diff --git a/hwdb/parse_hwdb.py b/hwdb/parse_hwdb.py index 23809a9f1f..c7b49b83df 100755 --- a/hwdb/parse_hwdb.py +++ b/hwdb/parse_hwdb.py @@ -172,7 +172,9 @@ def check_one_keycode(prop, value): if value != '!' and ecodes is not None: key = 'KEY_' + value.upper() if key not in ecodes: - error('Keycode {} unknown', key) + key = value.upper() + if key not in ecodes: + error('Keycode {} unknown', key) def check_properties(groups): grammar = property_grammar() diff --git a/rules/50-udev-default.rules.in b/rules/50-udev-default.rules.in index e556533020..898148c064 100644 --- a/rules/50-udev-default.rules.in +++ b/rules/50-udev-default.rules.in @@ -11,7 +11,6 @@ SUBSYSTEM=="rtc", ATTR{hctosys}=="1", SYMLINK+="rtc" SUBSYSTEM=="rtc", KERNEL=="rtc0", SYMLINK+="rtc", OPTIONS+="link_priority=-100" SUBSYSTEM=="usb", ENV{DEVTYPE}=="usb_device", IMPORT{builtin}="usb_id", IMPORT{builtin}="hwdb --subsystem=usb" -SUBSYSTEM=="input", ENV{ID_INPUT}=="", IMPORT{builtin}="input_id" ENV{MODALIAS}!="", IMPORT{builtin}="hwdb --subsystem=$env{SUBSYSTEM}" ACTION!="add", GOTO="default_end" diff --git a/rules/60-evdev.rules b/rules/60-evdev.rules index f5d5ba6a5f..e5e608acd3 100644 --- a/rules/60-evdev.rules +++ b/rules/60-evdev.rules @@ -8,7 +8,7 @@ IMPORT{builtin}="hwdb --subsystem=input --lookup-prefix=evdev:", \ RUN{builtin}+="keyboard", GOTO="evdev_end" # AT keyboard matching by the machine's DMI data -ENV{ID_INPUT_KEY}=="?*", DRIVERS=="atkbd", \ +DRIVERS=="atkbd", \ IMPORT{builtin}="hwdb 'evdev:atkbd:$attr{[dmi/id]modalias}'", \ RUN{builtin}+="keyboard", GOTO="evdev_end" diff --git a/rules/60-input-id.rules b/rules/60-input-id.rules new file mode 100644 index 0000000000..dee42199b6 --- /dev/null +++ b/rules/60-input-id.rules @@ -0,0 +1,7 @@ +# do not edit this file, it will be overwritten on update + +ACTION=="remove", GOTO="id_input_end" + +SUBSYSTEM=="input", ENV{ID_INPUT}=="", IMPORT{builtin}="input_id" + +LABEL="id_input_end" diff --git a/src/udev/generate-keyboard-gperf.py b/src/udev/generate-keyboard-gperf.py deleted file mode 100755 index 03d3bba7d3..0000000000 --- a/src/udev/generate-keyboard-gperf.py +++ /dev/null @@ -1,16 +0,0 @@ -#!/usr/bin/env python3 - -"""Generate keyboard-keys-from-name.gperf from keyboard-keys-list.txt -""" - -import sys - -input = sys.argv[1] - -print("""\ -struct key_name { const char* name; unsigned short id; }; -%null-strings -%%""") - -for line in open(input): - print("{0}, {1}".format(line.rstrip()[4:].lower(), line.rstrip())) diff --git a/src/udev/generate-keyboard-keys-gperf.sh b/src/udev/generate-keyboard-keys-gperf.sh new file mode 100755 index 0000000000..5724e4e3dc --- /dev/null +++ b/src/udev/generate-keyboard-keys-gperf.sh @@ -0,0 +1,10 @@ +#!/bin/sh -eu +awk ' BEGIN { + print "struct key_name { const char* name; unsigned short id; };" + print "%null-strings" + print "%%" + } + + /^KEY_/ { print tolower(substr($1 ,5)) ", " $1 } + { print tolower($1) ", " $1 } +' < "$1" diff --git a/src/udev/generate-keyboard-keys-list.sh b/src/udev/generate-keyboard-keys-list.sh index 479e493182..7a74e0dae1 100755 --- a/src/udev/generate-keyboard-keys-list.sh +++ b/src/udev/generate-keyboard-keys-list.sh @@ -1,4 +1,6 @@ #!/bin/sh -eu -$1 -dM -include linux/input.h - / { next } + /^#define[ \t]+(KEY|BTN)_[^ ]+[ \t]+[0-9BK]/ { print $2 } +' diff --git a/src/udev/meson.build b/src/udev/meson.build index 9c81bce545..eeb341f8d1 100644 --- a/src/udev/meson.build +++ b/src/udev/meson.build @@ -59,13 +59,13 @@ keyboard_keys_list_txt = custom_target( command : [generate_keyboard_keys_list, cpp], capture : true) -generate_keyboard_gperf = find_program('generate-keyboard-gperf.py') +generate_keyboard_keys_gperf = find_program('generate-keyboard-keys-gperf.sh') fname = 'keyboard-keys-from-name.gperf' gperf_file = custom_target( fname, input : keyboard_keys_list_txt, output : fname, - command : [generate_keyboard_gperf, '@INPUT@'], + command : [generate_keyboard_keys_gperf, '@INPUT@'], capture : true) fname = 'keyboard-keys-from-name.h' diff --git a/src/udev/udev-builtin-input_id.c b/src/udev/udev-builtin-input_id.c index 47f41a6607..d6579374b7 100644 --- a/src/udev/udev-builtin-input_id.c +++ b/src/udev/udev-builtin-input_id.c @@ -158,6 +158,7 @@ static bool test_pointers(struct udev_device *dev, const unsigned long* bitmask_rel, const unsigned long* bitmask_props, bool test) { + int button, axis; bool has_abs_coordinates = false; bool has_rel_coordinates = false; bool has_mt_coordinates = false; @@ -193,7 +194,8 @@ static bool test_pointers(struct udev_device *dev, is_pointing_stick = test_bit(INPUT_PROP_POINTING_STICK, bitmask_props); stylus_or_pen = test_bit(BTN_STYLUS, bitmask_key) || test_bit(BTN_TOOL_PEN, bitmask_key); finger_but_no_pen = test_bit(BTN_TOOL_FINGER, bitmask_key) && !test_bit(BTN_TOOL_PEN, bitmask_key); - has_mouse_button = test_bit(BTN_LEFT, bitmask_key); + for (button = BTN_MOUSE; button < BTN_JOYSTICK && !has_mouse_button; button++) + has_mouse_button = test_bit(button, bitmask_key); has_rel_coordinates = test_bit(EV_REL, bitmask_ev) && test_bit(REL_X, bitmask_rel) && test_bit(REL_Y, bitmask_rel); has_mt_coordinates = test_bit(ABS_MT_POSITION_X, bitmask_abs) && test_bit(ABS_MT_POSITION_Y, bitmask_abs); @@ -205,18 +207,12 @@ static bool test_pointers(struct udev_device *dev, /* joysticks don't necessarily have buttons; e. g. * rudders/pedals are joystick-like, but buttonless; they have * other fancy axes. Others have buttons only but no axes. */ - has_joystick_axes_or_buttons = test_bit(BTN_TRIGGER, bitmask_key) || - test_bit(BTN_TRIGGER_HAPPY, bitmask_key) || - test_bit(BTN_A, bitmask_key) || - test_bit(BTN_1, bitmask_key) || - test_bit(ABS_RX, bitmask_abs) || - test_bit(ABS_RY, bitmask_abs) || - test_bit(ABS_RZ, bitmask_abs) || - test_bit(ABS_THROTTLE, bitmask_abs) || - test_bit(ABS_RUDDER, bitmask_abs) || - test_bit(ABS_WHEEL, bitmask_abs) || - test_bit(ABS_GAS, bitmask_abs) || - test_bit(ABS_BRAKE, bitmask_abs); + for (button = BTN_JOYSTICK; button < BTN_DIGI && !has_joystick_axes_or_buttons; button++) + has_joystick_axes_or_buttons = test_bit(button, bitmask_key); + for (button = BTN_TRIGGER_HAPPY1; button <= BTN_TRIGGER_HAPPY40 && !has_joystick_axes_or_buttons; button++) + has_joystick_axes_or_buttons = test_bit(button, bitmask_key); + for (axis = ABS_RX; axis < ABS_PRESSURE && !has_joystick_axes_or_buttons; axis++) + has_joystick_axes_or_buttons = test_bit(axis, bitmask_abs); if (has_abs_coordinates) { if (stylus_or_pen) @@ -244,7 +240,9 @@ static bool test_pointers(struct udev_device *dev, is_touchscreen = true; } - if (has_rel_coordinates && has_mouse_button) + if (has_mouse_button && + (has_rel_coordinates || + !has_abs_coordinates)) /* mouse buttons and no axis */ is_mouse = true; if (is_pointing_stick)