On my Dell Vostro 1520, pressing the brightness up/down keys results in GNOME adjusting the brightness by two steps instead of one.
This is demonstrated by running libinput-debug-events and pressing the brightness control keys:
# libinput-debug-events WARNING: This compatibility wrapper will be removed in the future. Please run 'libinput debug-events' instead -event4 DEVICE_ADDED Power Button seat0 default group1 cap:k -event5 DEVICE_ADDED Video Bus seat0 default group2 cap:k -event2 DEVICE_ADDED Power Button seat0 default group3 cap:k -event1 DEVICE_ADDED Lid Switch seat0 default group4 cap:S -event3 DEVICE_ADDED Sleep Button seat0 default group5 cap:k -event9 DEVICE_ADDED HDA Intel Mic seat0 default group6 cap: -event10 DEVICE_ADDED HDA Intel Front Headphone seat0 default group6 cap: -event0 DEVICE_ADDED AT Translated Set 2 keyboard seat0 default group7 cap:k -event6 DEVICE_ADDED AlpsPS/2 ALPS GlidePoint seat0 default group8 cap:p size 73x51mm tap(dl off) left scroll-nat scroll-edge dwt-on -event0 KEYBOARD_KEY +5.62s KEY_BRIGHTNESSDOWN (224) pressed event0 KEYBOARD_KEY +5.62s KEY_BRIGHTNESSDOWN (224) released -event5 KEYBOARD_KEY +5.63s KEY_BRIGHTNESSDOWN (224) pressed event5 KEYBOARD_KEY +5.63s KEY_BRIGHTNESSDOWN (224) released event5 KEYBOARD_KEY +6.43s KEY_BRIGHTNESSDOWN (224) pressed event5 KEYBOARD_KEY +6.43s KEY_BRIGHTNESSDOWN (224) released -event0 KEYBOARD_KEY +6.43s KEY_BRIGHTNESSDOWN (224) pressed event0 KEYBOARD_KEY +6.43s KEY_BRIGHTNESSDOWN (224) released -event5 KEYBOARD_KEY +7.11s KEY_BRIGHTNESSDOWN (224) pressed event5 KEYBOARD_KEY +7.11s KEY_BRIGHTNESSDOWN (224) released -event0 KEYBOARD_KEY +7.11s KEY_BRIGHTNESSDOWN (224) pressed event0 KEYBOARD_KEY +7.11s KEY_BRIGHTNESSDOWN (224) released event0 KEYBOARD_KEY +8.38s KEY_BRIGHTNESSUP (225) pressed event0 KEYBOARD_KEY +8.38s KEY_BRIGHTNESSUP (225) released -event5 KEYBOARD_KEY +8.38s KEY_BRIGHTNESSUP (225) pressed event5 KEYBOARD_KEY +8.38s KEY_BRIGHTNESSUP (225) released -event0 KEYBOARD_KEY +9.01s KEY_BRIGHTNESSUP (225) pressed event0 KEYBOARD_KEY +9.01s KEY_BRIGHTNESSUP (225) released -event5 KEYBOARD_KEY +9.01s KEY_BRIGHTNESSUP (225) pressed event5 KEYBOARD_KEY +9.01s KEY_BRIGHTNESSUP (225) released -event0 KEYBOARD_KEY +9.61s KEY_BRIGHTNESSUP (225) pressed event0 KEYBOARD_KEY +9.61s KEY_BRIGHTNESSUP (225) released -event5 KEYBOARD_KEY +9.61s KEY_BRIGHTNESSUP (225) pressed event5 KEYBOARD_KEY +9.61s KEY_BRIGHTNESSUP (225) released
It appears that pressing a brightness key once results in two sets of events from different input devices: event0, the regular keyboard, and event5 which is a keyboard named Video Bus.
We want to ignore events from one of these devices. We could do this by running xinput disable 'Video Bus', but this is not a permanent solution. It would be better to use udev rules to tell libinput to ignore events from the device instead.
From the libinput documentation we can see we want to apply the LIBINPUT_IGNORE_DEVICE property to the device. In order to do this, we need to identify it with udevadm info:
$ udevadm info -a -p /sys/class/input/event5 Udevadm info starts with the device specified by the devpath and then walks up the chain of parent devices. It prints for every device found, all possible attributes in the udev rules key format. A rule to match, can be composed by the attributes of the device and the attributes from one single parent device. looking at device '/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/LNXVIDEO:01/input/input7/event5': KERNEL=="event5" SUBSYSTEM=="input" DRIVER=="" looking at parent device '/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/LNXVIDEO:01/input/input7': KERNELS=="input7" SUBSYSTEMS=="input" DRIVERS=="" ATTRS{name}=="Video Bus" ATTRS{phys}=="LNXVIDEO/video/input0" ATTRS{properties}=="0" ATTRS{uniq}=="" looking at parent device '/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/LNXVIDEO:01': KERNELS=="LNXVIDEO:01" SUBSYSTEMS=="acpi" DRIVERS=="video" ATTRS{adr}=="0x00020000" ATTRS{hid}=="LNXVIDEO" ATTRS{path}=="\_SB_.PCI0.GFX0" looking at parent device '/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00': KERNELS=="PNP0A08:00" SUBSYSTEMS=="acpi" DRIVERS=="" ATTRS{adr}=="0x00000000" ATTRS{hid}=="PNP0A08" ATTRS{path}=="\_SB_.PCI0" ATTRS{uid}=="0" looking at parent device '/devices/LNXSYSTM:00/LNXSYBUS:00': KERNELS=="LNXSYBUS:00" SUBSYSTEMS=="acpi" DRIVERS=="" ATTRS{hid}=="LNXSYBUS" ATTRS{path}=="\_SB_" looking at parent device '/devices/LNXSYSTM:00': KERNELS=="LNXSYSTM:00" SUBSYSTEMS=="acpi" DRIVERS=="" ATTRS{hid}=="LNXSYSTM" ATTRS{path}=="\"
Using the ACPI bus path of an ancestor device looks like a reasonable way to identify the device. This leaves us with the following rule:
$ cat /etc/udev/rules.d/90-libinput-ignore-video-brightness.rules KERNEL=="event*", ATTRS{path}=="\_SB_.PCI0.GFX0", ENV{LIBINPUT_IGNORE_DEVICE}="1"
With that in place, we can test the rule to see if the match works;
udevadm test /sys/class/input/event5 calling: test version 238 Load module index Parsed configuration file /lib/systemd/network/99-default.link Created link configuration context. Reading rules file: /lib/udev/rules.d/39-usbmuxd.rules Reading rules file: /lib/udev/rules.d/40-usb-media-players.rules Reading rules file: /lib/udev/rules.d/40-usb_modeswitch.rules Reading rules file: /lib/udev/rules.d/50-firmware.rules Reading rules file: /lib/udev/rules.d/50-udev-default.rules Reading rules file: /lib/udev/rules.d/55-Argyll.rules /lib/udev/rules.d/55-Argyll.rules:132: IMPORT found builtin 'usb_id --export %p', replacing Reading rules file: /lib/udev/rules.d/55-dm.rules Reading rules file: /lib/udev/rules.d/56-hpmud.rules Reading rules file: /lib/udev/rules.d/56-lvm.rules Reading rules file: /lib/udev/rules.d/60-block.rules Reading rules file: /lib/udev/rules.d/60-cdrom_id.rules Reading rules file: /lib/udev/rules.d/60-crda.rules Reading rules file: /lib/udev/rules.d/60-drm.rules Reading rules file: /lib/udev/rules.d/60-evdev.rules Reading rules file: /lib/udev/rules.d/60-fuse.rules Reading rules file: /lib/udev/rules.d/60-input-id.rules Reading rules file: /lib/udev/rules.d/60-libgphoto2-6.rules Reading rules file: /lib/udev/rules.d/60-libsane.rules Reading rules file: /lib/udev/rules.d/60-pcmcia.rules Reading rules file: /lib/udev/rules.d/60-persistent-alsa.rules Reading rules file: /lib/udev/rules.d/60-persistent-input.rules Reading rules file: /lib/udev/rules.d/60-persistent-storage-dm.rules Reading rules file: /lib/udev/rules.d/60-persistent-storage-tape.rules Reading rules file: /lib/udev/rules.d/60-persistent-storage.rules Reading rules file: /lib/udev/rules.d/60-persistent-v4l.rules Reading rules file: /lib/udev/rules.d/60-sensor.rules Reading rules file: /lib/udev/rules.d/60-serial.rules Reading rules file: /lib/udev/rules.d/61-gnome-settings-daemon-rfkill.rules Reading rules file: /lib/udev/rules.d/64-btrfs.rules Reading rules file: /lib/udev/rules.d/64-xorg-xkb.rules Reading rules file: /lib/udev/rules.d/65-libwacom.rules Reading rules file: /lib/udev/rules.d/69-cd-sensors.rules Reading rules file: /lib/udev/rules.d/69-libmtp.rules Reading rules file: /lib/udev/rules.d/69-lvm-metad.rules Reading rules file: /lib/udev/rules.d/69-wacom.rules Reading rules file: /lib/udev/rules.d/69-yubikey.rules Reading rules file: /lib/udev/rules.d/70-joystick.rules Reading rules file: /lib/udev/rules.d/70-mouse.rules Reading rules file: /lib/udev/rules.d/70-power-switch.rules Reading rules file: /lib/udev/rules.d/70-printers.rules Reading rules file: /lib/udev/rules.d/70-touchpad.rules Reading rules file: /lib/udev/rules.d/70-u2f.rules Reading rules file: /lib/udev/rules.d/70-uaccess.rules Reading rules file: /lib/udev/rules.d/71-seat.rules Reading rules file: /lib/udev/rules.d/73-seat-late.rules Reading rules file: /lib/udev/rules.d/73-special-net-names.rules Reading rules file: /lib/udev/rules.d/73-usb-net-by-mac.rules Reading rules file: /lib/udev/rules.d/75-net-description.rules Reading rules file: /lib/udev/rules.d/75-probe_mtd.rules Reading rules file: /lib/udev/rules.d/77-mm-cinterion-port-types.rules Reading rules file: /lib/udev/rules.d/77-mm-dell-port-types.rules Reading rules file: /lib/udev/rules.d/77-mm-ericsson-mbm.rules Reading rules file: /lib/udev/rules.d/77-mm-haier-port-types.rules Reading rules file: /lib/udev/rules.d/77-mm-huawei-net-port-types.rules Reading rules file: /lib/udev/rules.d/77-mm-longcheer-port-types.rules Reading rules file: /lib/udev/rules.d/77-mm-mtk-port-types.rules Reading rules file: /lib/udev/rules.d/77-mm-nokia-port-types.rules Reading rules file: /lib/udev/rules.d/77-mm-pcmcia-device-blacklist.rules Reading rules file: /lib/udev/rules.d/77-mm-qdl-device-blacklist.rules Reading rules file: /lib/udev/rules.d/77-mm-sierra.rules Reading rules file: /lib/udev/rules.d/77-mm-simtech-port-types.rules Reading rules file: /lib/udev/rules.d/77-mm-telit-port-types.rules Reading rules file: /lib/udev/rules.d/77-mm-ublox-port-types.rules Reading rules file: /lib/udev/rules.d/77-mm-usb-device-blacklist.rules Reading rules file: /lib/udev/rules.d/77-mm-usb-serial-adapters-greylist.rules Reading rules file: /lib/udev/rules.d/77-mm-x22x-port-types.rules Reading rules file: /lib/udev/rules.d/77-mm-zte-port-types.rules Reading rules file: /lib/udev/rules.d/78-sound-card.rules Reading rules file: /lib/udev/rules.d/80-debian-compat.rules Reading rules file: /lib/udev/rules.d/80-drivers.rules Reading rules file: /lib/udev/rules.d/80-iio-sensor-proxy.rules Reading rules file: /lib/udev/rules.d/80-libinput-device-groups.rules Reading rules file: /lib/udev/rules.d/80-mm-candidate.rules Reading rules file: /lib/udev/rules.d/80-net-setup-link.rules Reading rules file: /lib/udev/rules.d/80-udisks2.rules Reading rules file: /lib/udev/rules.d/84-nm-drivers.rules Reading rules file: /lib/udev/rules.d/85-hdparm.rules Reading rules file: /lib/udev/rules.d/85-hplj10xx.rules Reading rules file: /lib/udev/rules.d/85-hwclock.rules Reading rules file: /lib/udev/rules.d/85-nm-unmanaged.rules Reading rules file: /lib/udev/rules.d/85-regulatory.rules Reading rules file: /lib/udev/rules.d/90-alsa-restore.rules Reading rules file: /lib/udev/rules.d/90-console-setup.rules Reading rules file: /lib/udev/rules.d/90-libgpod.rules Reading rules file: /etc/udev/rules.d/90-libinput-ignore-video-brightness.rules Reading rules file: /lib/udev/rules.d/90-libinput-model-quirks.rules Reading rules file: /lib/udev/rules.d/90-pulseaudio.rules Reading rules file: /lib/udev/rules.d/95-cd-devices.rules Reading rules file: /lib/udev/rules.d/95-dm-notify.rules Reading rules file: /lib/udev/rules.d/95-upower-csr.rules Reading rules file: /lib/udev/rules.d/95-upower-hid.rules Reading rules file: /lib/udev/rules.d/95-upower-wup.rules Reading rules file: /lib/udev/rules.d/97-hid2hci.rules Reading rules file: /lib/udev/rules.d/99-systemd.rules rules contain 393216 bytes tokens (32768 * 12 bytes), 38660 bytes strings 29504 strings (242601 bytes), 25643 de-duplicated (207803 bytes), 3862 trie nodes used GROUP 106 /lib/udev/rules.d/50-udev-default.rules:29 IMPORT builtin 'hwdb' /lib/udev/rules.d/60-evdev.rules:8 IMPORT builtin 'hwdb' returned non-zero IMPORT builtin 'hwdb' /lib/udev/rules.d/60-evdev.rules:17 IMPORT builtin 'hwdb' returned non-zero IMPORT builtin 'hwdb' /lib/udev/rules.d/60-evdev.rules:21 IMPORT builtin 'hwdb' returned non-zero IMPORT builtin 'input_id' /lib/udev/rules.d/60-input-id.rules:5 capabilities/ev raw kernel attribute: 3 capabilities/abs raw kernel attribute: 0 capabilities/rel raw kernel attribute: 0 capabilities/key raw kernel attribute: 3e000b00000000 0 0 0 properties raw kernel attribute: 0 test_key: checking bit block 0 for any keys; found=0 test_key: checking bit block 64 for any keys; found=0 test_key: checking bit block 128 for any keys; found=0 test_key: checking bit block 192 for any keys; found=1 IMPORT builtin 'hwdb' /lib/udev/rules.d/60-input-id.rules:6 IMPORT builtin 'hwdb' returned non-zero IMPORT builtin 'path_id' /lib/udev/rules.d/60-persistent-input.rules:35 PROGRAM 'libinput-device-group /sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/LNXVIDEO:01/input/input7/event5' /lib/udev/rules.d/80-libinput-device-groups.rules:7 starting 'libinput-device-group /sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/LNXVIDEO:01/input/input7/event5' 'libinput-device-group /sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/LNXVIDEO:01/input/input7/event5'(out) '19/0/6:LNXVIDEO/video' Process 'libinput-device-group /sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/LNXVIDEO:01/input/input7/event5' succeeded. IMPORT builtin 'hwdb' /lib/udev/rules.d/90-libinput-model-quirks.rules:46 IMPORT builtin 'hwdb' returned non-zero IMPORT builtin 'hwdb' /lib/udev/rules.d/90-libinput-model-quirks.rules:50 IMPORT builtin 'hwdb' returned non-zero handling device node '/dev/input/event5', devnum=c13:69, mode=0660, uid=0, gid=106 preserve permissions /dev/input/event5, 020660, uid=0, gid=106 preserve already existing symlink '/dev/char/13:69' to '../input/event5' Unload module index Unloaded link configuration context. This program is for debugging only, it does not run any program specified by a RUN key. It may show incorrect results, because some values may be different, or not available at a simulation run. ACTION=add BACKSPACE=guess DEVNAME=/dev/input/event5 DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/LNXVIDEO:01/input/input7/event5 ID_INPUT=1 ID_INPUT_KEY=1 ID_PATH=acpi-LNXVIDEO:01 ID_PATH_TAG=acpi-LNXVIDEO_01 LIBINPUT_DEVICE_GROUP=19/0/6:LNXVIDEO/video LIBINPUT_IGNORE_DEVICE=1 MAJOR=13 MINOR=69 SUBSYSTEM=input TAGS=:power-switch: USEC_INITIALIZED=13461510 XKBLAYOUT=gb XKBMODEL=pc105 XKBOPTIONS= XKBVARIANT=
Looks like it worked. Let's apply the rule for real:
# udevadm trigger /sys/class/input/event5 $ udevadm info /sys/class/input/event5 P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/LNXVIDEO:01/input/input7/event5 N: input/event5 E: BACKSPACE=guess E: DEVNAME=/dev/input/event5 E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/LNXVIDEO:01/input/input7/event5 E: ID_INPUT=1 E: ID_INPUT_KEY=1 E: ID_PATH=acpi-LNXVIDEO:01 E: ID_PATH_TAG=acpi-LNXVIDEO_01 E: LIBINPUT_DEVICE_GROUP=19/0/6:LNXVIDEO/video E: LIBINPUT_IGNORE_DEVICE=1 E: MAJOR=13 E: MINOR=69 E: SUBSYSTEM=input E: TAGS=:power-switch: E: USEC_INITIALIZED=13461510 E: XKBLAYOUT=gb E: XKBMODEL=pc105
Surely enough, running libinput-list-devices no longer lists event5, so from now on Xorg will ignore the unwanted device!
Having re-read the libinput page, it appears that an entry in the libinput quirks hwdb file can be used instead of a udev rule. This was submitted upstream as https://bugs.freedesktop.org/show_bug.cgi?id=106057.