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

Peter Hutterer peter.hutterer at who-t.net
Tue Feb 10 17:31:55 PST 2015


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");
+	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