udev: guess if usb devices are internal external (#40649)

Actually we are defining databases to determine when a usb device is
inherent part of the system or if it's a external device.

Let's use the removable attribute of the port where it is connected to
say that. That gives us the ability to not rely on a particular vendor
only does external devices or to not having the need to be quirking
input subsystem for that purpose that will become unreliable as more and
more internal devices are connected over usb instead over ps2 or i2c
buses. Eg.
https://gitlab.freedesktop.org/libinput/libinput/-/commit/02b495e79022e64514015e1a3dea32997035dd4f?merge_request_iid=1389

Actually this has been seen as reliable in a small set of device from
normal laptops, to detachable ones. The need to check maxchild is 0 is
for detachable devices, pogo pin usbs are fixed, while we attach the
keyboard|touchpad dock the input devices tend to be directly connected
to that port and if the dock has more usbs tend to be a hub that then
exposes removable as unknow. If we don't set maxchild 0 we will not only
guess that the keyboard and touchpad are internal but also incorrectly
other input devices like mice connected to the dock's usb ports.

I have use a very generic name like INTEGRATION because is not actually
used for any other thing and is used to determine not only over usb bus
but for acpi, pci, platform actually.

Also a remap to actual libinput variables is done for compatibility
purposes. if it's possible to have only the INTEGRATION variable instead
multiple ones will be done in the future but is actually unclear.

This can also be used for example to achieve an actual feature that we
lack in linux, when a device with accelerometers and cameras is rotated
the video output is not, this tag the own device cameras as internal
while external ones as external to be able to only do that for the
internal ones.

Note that this has nothing to do with the removable attribute found in
usb storage devices where it's values can be 0 or 1. There is no
conflict at all because the removable attribute we check is specifically
the one found in usb port ones.
This commit is contained in:
Yu Watanabe
2026-02-16 13:25:35 +09:00
committed by GitHub
6 changed files with 51 additions and 46 deletions
+8 -11
View File
@@ -30,15 +30,12 @@
#
# If the property is missing, user-space can assume:
# ID_INPUT_JOYSTICK_INTEGRATION=external
#
# By default i8042, i2c, and rmi devices are assumed to be internal,
# bluetooth devices are assumed to be external, usb devices are assumed
# to be internal when connected to a PCB port and external otherwise.
joystick:bluetooth:*
ID_INPUT_JOYSTICK_INTEGRATION=external
###########################################################
# GPD
###########################################################
# GPD Win, Classic and XBox 360 compat modes
joystick:usb:v11c5p5507*
joystick:usb:v045ep028e*
ID_INPUT_JOYSTICK_INTEGRATION=internal
# Example entry; vid: ffff, pid: 0000; both must be lowecase.
# this will make this usb joystick to behave as internal.
#joystick:usb:vffffp0000*
# ID_INPUT_JOYSTICK_INTEGRATION=internal
+8 -34
View File
@@ -28,44 +28,18 @@
# Permitted keys:
# Specify whether a touchpad is a built-in one or external:
# ID_INPUT_TOUCHPAD_INTEGRATION=internal|external
#
# By default i8042, i2c, and rmi devices are assumed to be internal,
# bluetooth devices are assumed to be external, usb devices are assumed
# to be internal when connected to a PCB port and external otherwise.
touchpad:i8042:*
touchpad:rmi:*
touchpad:usb:*
ID_INPUT_TOUCHPAD_INTEGRATION=internal
touchpad:bluetooth:*
ID_INPUT_TOUCHPAD_INTEGRATION=external
###########################################################
# Apple
###########################################################
# Magic Trackpad (1 and 2)
touchpad:usb:v05acp030e:*
touchpad:usb:v05acp0265:*
touchpad:usb:v05acp0324:*
ID_INPUT_TOUCHPAD_INTEGRATION=external
###########################################################
# HP Elite x2 1013 G3
###########################################################
touchpad:usb:v044ep1221:*
ID_INPUT_TOUCHPAD_INTEGRATION=external
# Example entry; vid: ffff, pid: 0000; both must be lowecase.
# this will make this bluetooth touchpad to behave as internal.
#touchpad:bluetooth:vffffp0000:*
# ID_INPUT_TOUCHPAD_INTEGRATION=internal
###########################################################
# Lenovo IdeaPad Duet3 10IGL5 (82AT)
###########################################################
touchpad:bluetooth:v17efp60fa:*
ID_INPUT_TOUCHPAD_INTEGRATION=internal
###########################################################
# Logitech
###########################################################
touchpad:usb:v046d*
ID_INPUT_TOUCHPAD_INTEGRATION=external
###########################################################
# Wacom
###########################################################
touchpad:usb:v056a*
ID_INPUT_TOUCHPAD_INTEGRATION=external
+1 -1
View File
@@ -350,7 +350,7 @@ def print_summary(fname, groups):
print(f'{fname}: {len(groups)} match groups, {n_matches} matches, {n_props} properties')
if n_matches == 0 or n_props == 0:
error(f'{fname}: no matches or props')
print(f'{fname}: no matches or props')
if __name__ == '__main__':
args = sys.argv[1:] or sorted([
+8
View File
@@ -5,11 +5,19 @@ SUBSYSTEM!="input", GOTO="persistent_input_end"
SUBSYSTEMS=="bluetooth", ENV{ID_BUS}="bluetooth", GOTO="persistent_input_end"
# Bluetooth devices don't always have the bluetooth subsystem
ATTRS{id/bustype}=="0005", ENV{ID_BUS}="bluetooth", GOTO="persistent_input_end"
SUBSYSTEMS=="acpi", ENV{ID_BUS}="acpi"
# platform must be before serio as serio can be child
SUBSYSTEMS=="platform", ENV{ID_BUS}="platform"
SUBSYSTEMS=="i2c", ENV{ID_BUS}="i2c"
SUBSYSTEMS=="rmi4", ENV{ID_BUS}="rmi"
SUBSYSTEMS=="serio", ENV{ID_BUS}="i8042"
SUBSYSTEMS=="usb", ENV{ID_BUS}=="", IMPORT{builtin}="usb_id"
# subsystems before (usb, platform, i2c) can be under pci so only set them if we still have no ID_BUS.
# we could set this the first but will break the ENV{ID_BUS}=="" condition for usb.
SUBSYSTEMS=="pci", ENV{ID_BUS}=="", ENV{ID_BUS}="pci"
# determine class name for persistent symlinks
ENV{ID_INPUT_KEYBOARD}=="?*", ENV{.INPUT_CLASS}="kbd"
ENV{ID_INPUT_MOUSE}=="?*", ENV{.INPUT_CLASS}="mouse"
+25
View File
@@ -0,0 +1,25 @@
# do not edit this file, it will be overwritten on update
# ID_INTEGRATION variable tells us if a device is internal (inherent part of the system) or external otherwise.
# This must be loaded after 60-persistent-*.rules to have ID_BUS.
ACTION=="remove", GOTO="integration_end"
ENV{ID_BUS}=="", GOTO="integration_end"
# ACPI, platform, PS/2, I2C, RMI and PCI devices: Internal by default.
ENV{ID_BUS}=="acpi|platform|i8042|i2c|rmi|pci", ENV{ID_INTEGRATION}="internal"
# Bluetooth devices: External by default.
ENV{ID_BUS}=="bluetooth", ENV{ID_INTEGRATION}="external"
# USB devices: Internal if it's connected to a fixed port, external to a removable or unknown.
ENV{ID_BUS}=="usb", DRIVERS=="usb", ATTRS{maxchild}=="0", ATTRS{removable}=="fixed", ENV{ID_INTEGRATION}="internal"
ENV{ID_BUS}=="usb", DRIVERS=="usb", ATTRS{maxchild}=="0", ATTRS{removable}=="removable|unknown", ENV{ID_INTEGRATION}="external"
# libinput compatibility variables, must be loaded before 70-(joystick|touchpad).rules to allow hwdb quirks to override.
ENV{ID_INPUT}=="", GOTO="integration_libinput_end"
ENV{ID_INPUT_JOYSTICK}=="1", ENV{ID_INPUT_JOYSTICK_INTEGRATION}="$env{ID_INTEGRATION}"
ENV{ID_INPUT_TOUCHPAD}=="1", ENV{ID_INPUT_TOUCHPAD_INTEGRATION}="$env{ID_INTEGRATION}"
LABEL="integration_libinput_end"
LABEL="integration_end"
+1
View File
@@ -23,6 +23,7 @@ rules = [
'60-persistent-v4l.rules',
'60-sensor.rules',
'60-serial.rules',
'65-integration.rules',
'70-camera.rules',
'70-joystick.rules',
'70-mouse.rules',