[PATCH v2 libinput 2/3] Add a udev bits to assign LIBINPUT_DEVICE_GROUP

Benjamin Tissoires benjamin.tissoires at gmail.com
Thu Feb 12 12:28:26 PST 2015


On Tue, Feb 10, 2015 at 8:31 PM, Peter Hutterer
<peter.hutterer at who-t.net> wrote:
> 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.
>
> 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 <peter.hutterer at who-t.net>
> ---
> Pretty big revamp.
>
> Changes to v1:
> - configure.ac: handle AC_ARG_WITH better (e.g. --without-...)
> - configure.ac: change from udev_rules_dir to udev_dir for the base dir, we
>   have a binary now too
> - change to a rule that matches on non-zero ATTRS{phys} and calls into a
>   binary. That binary runs up the device tree and spits out a device group
>   name based on phys
> - move from rules/ into udev/ now that we have more than a simple rule,
>   rename the rule to a more generic name
>
>  Makefile.am                          |  2 +-
>  configure.ac                         | 17 ++++++++-
>  udev/.gitignore                      |  1 +
>  udev/80-libinput-device-groups.rules |  8 +++++
>  udev/Makefile.am                     |  9 +++++
>  udev/libinput-device-group.c         | 67 ++++++++++++++++++++++++++++++++++++
>  6 files changed, 102 insertions(+), 2 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 f47c5a4..490d1ee 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,11 +176,13 @@ AC_CONFIG_FILES([Makefile
>                  src/libinput.pc
>                  src/libinput-version.h
>                  test/Makefile
> -                tools/Makefile])
> +                tools/Makefile
> +                udev/Makefile])
>  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..16f55d9
> --- /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..eaf23d1
> --- /dev/null
> +++ b/udev/libinput-device-group.c
> @@ -0,0 +1,67 @@
> +#include <stdio.h>
> +#include <stdlib.h>
> +#include <string.h>
> +#include <libudev.h>
> +
> +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");

I know I told you before that this should work on the 22 HD Touch, but
it doesn't. Actually, the 22HDT has two separate USB devices, and they
show up as:
usb-0000:00:14.0-6.3.1/input0 for the touch
usb-0000:00:14.0-6.3.0/input0 for the pen

What the kernel does is looking for the first '.' in the phys, and
truncate here. See
https://git.kernel.org/cgit/linux/kernel/git/jikos/hid.git/tree/drivers/hid/wacom_sys.c?h=for-3.20/wacom#n481

I tried replacing "/input" by "." in the group string, and the tablets
gets assigned the same group.

Cheers,
Benjamin

> +       if (str)
> +               *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.1.0
>


More information about the wayland-devel mailing list