]> git.ipfire.org Git - thirdparty/systemd.git/blobdiff - src/udev/udev-builtin-keyboard.c
treewide: Correct typos and spell plural of bus consistent
[thirdparty/systemd.git] / src / udev / udev-builtin-keyboard.c
index 785a607c9aee272a1e7c78eb245add769c0ab33e..ed990c58fb97041474e3e77b505773dba1a0b0e6 100644 (file)
@@ -80,7 +80,7 @@ static void map_keycode(int fd, const char *devnode, int scancode, const char *k
                 /* check if it's a numeric code already */
                 keycode_num = strtoul(keycode, &endptr, 0);
                 if (endptr[0] !='\0') {
-                        log_error("Error, unknown key identifier '%s'", keycode);
+                        log_error("Unknown key identifier '%s'", keycode);
                         return;
                 }
         }
@@ -95,6 +95,93 @@ static void map_keycode(int fd, const char *devnode, int scancode, const char *k
                 log_error_errno(errno, "Error calling EVIOCSKEYCODE on device node '%s' (scan code 0x%x, key code %d): %m", devnode, map.scan, map.key);
 }
 
+static inline char* parse_token(const char *current, int32_t *val_out) {
+        char *next;
+        int32_t val;
+
+        if (!current)
+                return NULL;
+
+        val = strtol(current, &next, 0);
+        if (*next && *next != ':')
+                return NULL;
+
+        if (next != current)
+                *val_out = val;
+
+        if (*next)
+                next++;
+
+        return next;
+}
+
+static void override_abs(int fd, const char *devnode,
+                         unsigned evcode, const char *value) {
+        struct input_absinfo absinfo;
+        int rc;
+        char *next;
+
+        rc = ioctl(fd, EVIOCGABS(evcode), &absinfo);
+        if (rc < 0) {
+                log_error_errno(errno, "Unable to EVIOCGABS device \"%s\"", devnode);
+                return;
+        }
+
+        next = parse_token(value, &absinfo.minimum);
+        next = parse_token(next, &absinfo.maximum);
+        next = parse_token(next, &absinfo.resolution);
+        next = parse_token(next, &absinfo.fuzz);
+        next = parse_token(next, &absinfo.flat);
+        if (!next) {
+                log_error("Unable to parse EV_ABS override '%s' for '%s'", value, devnode);
+                return;
+        }
+
+        log_debug("keyboard: %x overridden with %"PRIi32"/%"PRIi32"/%"PRIi32"/%"PRIi32"/%"PRIi32" for \"%s\"",
+                  evcode,
+                  absinfo.minimum, absinfo.maximum, absinfo.resolution, absinfo.fuzz, absinfo.flat,
+                  devnode);
+        rc = ioctl(fd, EVIOCSABS(evcode), &absinfo);
+        if (rc < 0)
+                log_error_errno(errno, "Unable to EVIOCSABS device \"%s\"", devnode);
+}
+
+static void set_trackpoint_sensitivity(struct udev_device *dev, const char *value)
+{
+        struct udev_device *pdev;
+        char val_s[DECIMAL_STR_MAX(int)];
+        int r, val_i;
+
+        /* The sensitivity sysfs attr belongs to the serio parent device */
+        pdev = udev_device_get_parent_with_subsystem_devtype(dev, "serio", NULL);
+        if (!pdev) {
+                log_warning("Failed to get serio parent for '%s'", udev_device_get_devnode(dev));
+                return;
+        }
+
+        r = safe_atoi(value, &val_i);
+        if (r < 0) {
+                log_error("Unable to parse POINTINGSTICK_SENSITIVITY '%s' for '%s'", value, udev_device_get_devnode(dev));
+                return;
+        }
+
+        xsprintf(val_s, "%d", val_i);
+
+        r = udev_device_set_sysattr_value(pdev, "sensitivity", val_s);
+        if (r < 0)
+                log_error_errno(r, "Failed to write 'sensitivity' attribute for '%s': %m", udev_device_get_devnode(pdev));
+}
+
+static int open_device(const char *devnode) {
+        int fd;
+
+        fd = open(devnode, O_RDWR|O_CLOEXEC|O_NONBLOCK|O_NOCTTY);
+        if (fd < 0)
+                return log_error_errno(errno, "Error opening device \"%s\": %m", devnode);
+
+        return fd;
+}
+
 static int builtin_keyboard(struct udev_device *dev, int argc, char *argv[], bool test) {
         struct udev_list_entry *entry;
         unsigned release[1024];
@@ -104,7 +191,7 @@ static int builtin_keyboard(struct udev_device *dev, int argc, char *argv[], boo
 
         node = udev_device_get_devnode(dev);
         if (!node) {
-                log_error("Error, no device node for '%s'", udev_device_get_syspath(dev));
+                log_error("No device node for \"%s\"", udev_device_get_syspath(dev));
                 return EXIT_FAILURE;
         }
 
@@ -120,7 +207,7 @@ static int builtin_keyboard(struct udev_device *dev, int argc, char *argv[], boo
                         /* KEYBOARD_KEY_<hex scan code>=<key identifier string> */
                         scancode = strtoul(key + 13, &endptr, 16);
                         if (endptr[0] != '\0') {
-                                log_error("Error, unable to parse scan code from '%s'", key);
+                                log_warning("Unable to parse scan code from \"%s\"", key);
                                 continue;
                         }
 
@@ -139,14 +226,31 @@ static int builtin_keyboard(struct udev_device *dev, int argc, char *argv[], boo
                         }
 
                         if (fd == -1) {
-                                fd = open(node, O_RDWR|O_CLOEXEC|O_NONBLOCK|O_NOCTTY);
-                                if (fd < 0) {
-                                        log_error_errno(errno, "Error, opening device '%s': %m", node);
+                                fd = open_device(node);
+                                if (fd < 0)
                                         return EXIT_FAILURE;
-                                }
                         }
 
                         map_keycode(fd, node, scancode, keycode);
+                } else if (startswith(key, "EVDEV_ABS_")) {
+                        unsigned evcode;
+
+                        /* EVDEV_ABS_<EV_ABS code>=<min>:<max>:<res>:<fuzz>:<flat> */
+                        evcode = strtoul(key + 10, &endptr, 16);
+                        if (endptr[0] != '\0') {
+                                log_warning("Unable to parse EV_ABS code from \"%s\"", key);
+                                continue;
+                        }
+
+                        if (fd == -1) {
+                                fd = open_device(node);
+                                if (fd < 0)
+                                        return EXIT_FAILURE;
+                        }
+
+                        override_abs(fd, node, evcode, udev_list_entry_get_value(entry));
+                } else if (streq(key, "POINTINGSTICK_SENSITIVITY")) {
+                        set_trackpoint_sensitivity(dev, udev_list_entry_get_value(entry));
                 }
         }