From 2b2a1b0eb9f4e3bc835401e1436731fcf4b2163b Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Tue, 10 Feb 2015 14:23:32 +1000 Subject: [PATCH] Add udev bits to assign LIBINPUT_DEVICE_GROUP The easiest way to get a device group is by looking at the phys path of the input device (which looks like usb-0000:00:14.0-1/input1) and dropping the /inputX bit. The rest is the same for devices that belong together (except on the Cintiq 22HD Touch). Ideally we could just take ATTRS{phys} but we can't select substrings to drop into ENV so we need to do it ourselves. This patch adds a callout that takes a syspath and prints the mangled path, to be used in LIBINPUT_DEVICE_GROUP. The rule triggers on any device that has a non-zero phys attribute, this groups devices like tablets together but also devices like mice with multiple interfaces. Signed-off-by: Peter Hutterer Tested-by: Benjamin Tissoires --- Makefile.am | 2 +- configure.ac | 18 ++++++++- udev/.gitignore | 1 + udev/80-libinput-device-groups.rules | 8 ++++ udev/Makefile.am | 9 +++++ udev/libinput-device-group.c | 77 ++++++++++++++++++++++++++++++++++++ 6 files changed, 112 insertions(+), 3 deletions(-) create mode 100644 udev/.gitignore create mode 100644 udev/80-libinput-device-groups.rules create mode 100644 udev/Makefile.am create mode 100644 udev/libinput-device-group.c diff --git a/Makefile.am b/Makefile.am index 05698ba..fc6e6b7 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,4 +1,4 @@ -SUBDIRS = src doc test tools +SUBDIRS = src doc test tools udev ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS} diff --git a/configure.ac b/configure.ac index 1e60e58..2ccd30d 100644 --- a/configure.ac +++ b/configure.ac @@ -69,6 +69,19 @@ fi AC_SUBST(GCC_CFLAGS) AC_SUBST(GCC_CXXFLAGS) +udev_dir_default="$libdir/udev" +AC_ARG_WITH(udev-dir, + AS_HELP_STRING([--with-udev-dir=DIR], + [udev base directory [[default=$udev_dir_default]]]), + [], + [with_udev_dir="yes"]) +AS_CASE($with_udev_dir, + [no|""], [AC_MSG_ERROR([You must define a udev base directory])], + [yes], [udevdir="$udev_dir_default"], + [udevdir="$with_udev_dir"]) +UDEV_DIR=${udevdir} +AC_SUBST(UDEV_DIR) + AC_ARG_ENABLE([documentation], [AC_HELP_STRING([--enable-documentation], [Enable building the documentation (default=auto)])], @@ -163,14 +176,15 @@ AC_CONFIG_FILES([Makefile src/libinput.pc src/libinput-version.h test/Makefile - tools/Makefile]) + tools/Makefile + udev/Makefile]) AC_CONFIG_FILES([test/symbols-leak-test], [chmod +x test/symbols-leak-test]) - AC_OUTPUT AC_MSG_RESULT([ Prefix ${prefix} + udev base dir ${UDEV_DIR} Build documentation ${build_documentation} Build tests ${build_tests} diff --git a/udev/.gitignore b/udev/.gitignore new file mode 100644 index 0000000..d8e1456 --- /dev/null +++ b/udev/.gitignore @@ -0,0 +1 @@ +libinput-device-group diff --git a/udev/80-libinput-device-groups.rules b/udev/80-libinput-device-groups.rules new file mode 100644 index 0000000..f826bec --- /dev/null +++ b/udev/80-libinput-device-groups.rules @@ -0,0 +1,8 @@ +ACTION!="add|change", GOTO="libinput_device_group_end" +KERNEL!="event[0-9]*", GOTO="libinput_device_group_end" + +ATTRS{phys}=="?*", \ + PROGRAM="libinput-device-group %S%p", \ + ENV{LIBINPUT_DEVICE_GROUP}="%c" + +LABEL="libinput_device_group_end" diff --git a/udev/Makefile.am b/udev/Makefile.am new file mode 100644 index 0000000..3691172 --- /dev/null +++ b/udev/Makefile.am @@ -0,0 +1,9 @@ +udevdir=$(UDEV_DIR) +udev_PROGRAMS = libinput-device-group + +libinput_device_group_SOURCES = libinput-device-group.c +libinput_device_group_CFLAGS = $(LIBUDEV_CFLAGS) $(GCC_CFLAGS) +libinput_device_group_LDADD = $(LIBUDEV_LIBS) + +udev_rulesdir=$(UDEV_DIR)/rules.d +dist_udev_rules_DATA = 80-libinput-device-groups.rules diff --git a/udev/libinput-device-group.c b/udev/libinput-device-group.c new file mode 100644 index 0000000..50bfbe0 --- /dev/null +++ b/udev/libinput-device-group.c @@ -0,0 +1,77 @@ +#include +#include +#include +#include + +int main(int argc, char **argv) +{ + int rc = 1; + struct udev *udev = NULL; + struct udev_device *device = NULL; + const char *syspath, + *phys = NULL; + char *group, + *str; + + if (argc != 2) + return 1; + + syspath = argv[1]; + + udev = udev_new(); + if (!udev) + goto out; + + device = udev_device_new_from_syspath(udev, syspath); + if (!device) + goto out; + + /* Find the first parent with ATTRS{phys} set. For tablets that + * value looks like usb-0000:00:14.0-1/input1. Drop the /input1 + * bit and use the remainder as device group identifier */ + while (device != NULL) { + struct udev_device *parent; + + phys = udev_device_get_sysattr_value(device, "phys"); + if (phys) + break; + + parent = udev_device_get_parent(device); + udev_device_ref(parent); + udev_device_unref(device); + device = parent; + } + + if (!phys) + goto out; + + group = strdup(phys); + if (!group) + goto out; + + str = strstr(group, "/input"); + if (str) + *str = '\0'; + + /* Cintiq 22HD Touch has + usb-0000:00:14.0-6.3.1/input0 for the touch + usb-0000:00:14.0-6.3.0/input0 for the pen + Check if there's a . after the last -, if so, cut off the string + there. + */ + str = strrchr(group, '.'); + if (str && str > strrchr(group, '-')) + *str = '\0'; + + printf("%s\n", group); + free(group); + + rc = 0; +out: + if (device) + udev_device_unref(device); + if (udev) + udev_unref(udev); + + return rc; +} -- 2.7.4