[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