[systemd-devel] [PATCH udev v3] udev: Add builtin/rule to export touchscreen/tablet size as udev properties

Carlos Garnacho carlosg at gnome.org
Fri Dec 19 09:31:57 PST 2014


This rule is only run on tablet/touchscreen devices, and extracts their size
in millimeters, as it can be found out through their struct input_absinfo.

This may be useful to separate policy and application at the time of mapping
these devices to the available outputs in windowing environments that don't
offer that information as readily (eg. Wayland). This way the compositor can
stay deterministic, and the mix-and-match heuristics are performed outside.

Conceivably, that information can be changed through EVIOCSABS anywhere
else, but we're only interested in values prior to any calibration, this
rule is thus only run on "add", and no tracking of changes is performed.
This should only remain a problem if calibration were automatically applied
by an earlier udev rule (read: don't).

  v2: Folded rationale into commit log, made a builtin, set properties
      on device nodes themselves
  v3: Use inline function instead of macro for mm. size calculation,
      use DECIMAL_STR_MAX, other code style issues
---
 Makefile.am                            |  2 +
 rules/60-input_abs_size.rules          |  8 ++++
 src/udev/udev-builtin-input_abs_size.c | 81 ++++++++++++++++++++++++++++++++++
 src/udev/udev-builtin.c                |  1 +
 src/udev/udev.h                        |  2 +
 5 files changed, 94 insertions(+)
 create mode 100644 rules/60-input_abs_size.rules
 create mode 100644 src/udev/udev-builtin-input_abs_size.c

diff --git a/Makefile.am b/Makefile.am
index ab07d3b..db3e014 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -3412,6 +3412,7 @@ dist_udevrules_DATA += \
 	rules/42-usb-hid-pm.rules \
 	rules/50-udev-default.rules \
 	rules/60-drm.rules \
+	rules/60-input_abs_size.rules \
 	rules/60-keyboard.rules \
 	rules/70-mouse.rules \
 	rules/60-persistent-storage-tape.rules \
@@ -3512,6 +3513,7 @@ libudev_core_la_SOURCES = \
 	src/udev/udev-builtin.c \
 	src/udev/udev-builtin-btrfs.c \
 	src/udev/udev-builtin-hwdb.c \
+	src/udev/udev-builtin-input_abs_size.c \
 	src/udev/udev-builtin-input_id.c \
 	src/udev/udev-builtin-keyboard.c \
 	src/udev/udev-builtin-net_id.c \
diff --git a/rules/60-input_abs_size.rules b/rules/60-input_abs_size.rules
new file mode 100644
index 0000000..1541ced
--- /dev/null
+++ b/rules/60-input_abs_size.rules
@@ -0,0 +1,8 @@
+# do not edit this file, it will be overwritten on update
+
+ACTION!="add", GOTO="input_abs_size_end"
+
+ENV{ID_INPUT_TOUCHSCREEN}=="1", IMPORT{builtin}="input_abs_size"
+ENV{ID_INPUT_TABLET}=="1", IMPORT{builtin}="input_abs_size"
+
+LABEL="input_abs_size_end"
diff --git a/src/udev/udev-builtin-input_abs_size.c b/src/udev/udev-builtin-input_abs_size.c
new file mode 100644
index 0000000..faf707e
--- /dev/null
+++ b/src/udev/udev-builtin-input_abs_size.c
@@ -0,0 +1,81 @@
+/*
+ * input_abs_size - extracts abs X/Y size in millimeters from input devices
+ *
+ * Copyright (C) 2014 Red Hat
+ * Author:
+ *   Carlos Garnacho  <carlosg at gnome.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with keymap; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include <linux/input.h>
+#include "udev.h"
+
+static inline int abs_size_mm(const struct input_absinfo *absinfo)
+{
+        /* Resolution is defined to be in units/mm for ABS_X/Y */
+        return (absinfo->maximum - absinfo->minimum) / absinfo->resolution;
+}
+
+static void extract_info(struct udev_device *dev, const char *devpath, bool test)
+{
+        char width[DECIMAL_STR_MAX(int)], height[DECIMAL_STR_MAX(int)];
+        struct input_absinfo xabsinfo = {}, yabsinfo = {};
+        _cleanup_close_ int fd = -1;
+
+        fd = open(devpath, O_RDONLY|O_CLOEXEC);
+
+        if (fd < 0)
+                return;
+
+        if (ioctl(fd, EVIOCGABS(ABS_X), &xabsinfo) < 0 ||
+            ioctl(fd, EVIOCGABS(ABS_Y), &yabsinfo) < 0)
+                return;
+
+        if (xabsinfo.resolution <= 0 || yabsinfo.resolution <= 0)
+                return;
+
+        snprintf(width, sizeof(width), "%d", abs_size_mm(&xabsinfo));
+        snprintf(height, sizeof(height), "%d", abs_size_mm(&yabsinfo));
+
+        udev_builtin_add_property(dev, test, "ID_INPUT_WIDTH_MM", width);
+        udev_builtin_add_property(dev, test, "ID_INPUT_HEIGHT_MM", height);
+}
+
+static int builtin_input_abs_size(struct udev_device *dev, int argc, char *argv[], bool test) {
+        const char *subsystem;
+        const char *devnode;
+
+        subsystem = udev_device_get_subsystem(dev);
+
+        if (!subsystem || !streq(subsystem, "input"))
+                return EXIT_SUCCESS;
+
+        devnode = udev_device_get_devnode(dev);
+
+        /* not an evdev node */
+        if (!devnode)
+                return EXIT_SUCCESS;
+
+        extract_info(dev, devnode, test);
+
+        return EXIT_SUCCESS;
+}
+
+const struct udev_builtin udev_builtin_input_abs_size = {
+        .name = "input_abs_size",
+        .cmd = builtin_input_abs_size,
+        .help = "input device size information",
+};
diff --git a/src/udev/udev-builtin.c b/src/udev/udev-builtin.c
index 3bcbd6e..9febf4c 100644
--- a/src/udev/udev-builtin.c
+++ b/src/udev/udev-builtin.c
@@ -47,6 +47,7 @@ static const struct udev_builtin *builtins[] = {
 #ifdef HAVE_ACL
         [UDEV_BUILTIN_UACCESS] = &udev_builtin_uaccess,
 #endif
+        [UDEV_BUILTIN_INPUT_ABS_SIZE] = &udev_builtin_input_abs_size,
 };
 
 void udev_builtin_init(struct udev *udev) {
diff --git a/src/udev/udev.h b/src/udev/udev.h
index dece6ec..d3b3b51 100644
--- a/src/udev/udev.h
+++ b/src/udev/udev.h
@@ -164,6 +164,7 @@ enum udev_builtin_cmd {
 #ifdef HAVE_ACL
         UDEV_BUILTIN_UACCESS,
 #endif
+        UDEV_BUILTIN_INPUT_ABS_SIZE,
         UDEV_BUILTIN_MAX
 };
 struct udev_builtin {
@@ -190,6 +191,7 @@ extern const struct udev_builtin udev_builtin_net_setup_link;
 extern const struct udev_builtin udev_builtin_path_id;
 extern const struct udev_builtin udev_builtin_usb_id;
 extern const struct udev_builtin udev_builtin_uaccess;
+extern const struct udev_builtin udev_builtin_input_abs_size;
 void udev_builtin_init(struct udev *udev);
 void udev_builtin_exit(struct udev *udev);
 enum udev_builtin_cmd udev_builtin_lookup(const char *command);
-- 
2.1.0



More information about the systemd-devel mailing list