[systemd-devel] [PATCH v2 5/6] udev: builtin-keyboard: add support for EV_ABS_OVERRIDE

Reverend Homer mk.43.ecko at gmail.com
Sun Mar 22 23:15:02 PDT 2015



23.03.2015 04:30, Peter Hutterer пишет:
> Parse properties in the form
> EV_ABS_OVERRIDE_00="<min>:<max>:<res>:<fuzz>:<flat>"
>
> and apply them to the kernel device. Future processes that open that device
> will see the updated EV_ABS range.
>
> This is particularly useful for touchpads that don't provide a resolution in
> the kernel driver but can be fixed up through hwdb entries (e.g. bcm5974).
>
> All values in the property are optional, e.g. a string of "::45" is valid to
> set the resolution to 45.
>
> The order intentionally orders resolution before fuzz and flat despite it
> being the last element in the absinfo struct. The use-case for setting
> fuzz/flat is almost non-existent, resolution is probably the most common case
> we'll need.
> ---
> Changes to v1:
> - merge into the keyboard builtin rather than a separate one
> - make the parsing code less copy/paste-ish
>
> I didn't rename the keyboard builtin or merged it with input_id yet, IMO in
> both cases the churn of moving rules/hwdbs around is more effort and risk
> than the benefit we get from doing so.
>
>   Makefile.am                      |  2 +
>   hwdb/60-evdev.hwdb               | 37 +++++++++++++++++
>   rules/60-evdev.rules             | 14 +++++++
>   src/udev/udev-builtin-keyboard.c | 85 ++++++++++++++++++++++++++++++++++++++--
>   4 files changed, 134 insertions(+), 4 deletions(-)
>   create mode 100644 hwdb/60-evdev.hwdb
>   create mode 100644 rules/60-evdev.rules
>
> diff --git a/Makefile.am b/Makefile.am
> index 86bf53d..9f5b4b7 100644
> --- a/Makefile.am
> +++ b/Makefile.am
> @@ -3689,6 +3689,7 @@ dist_udevrules_DATA += \
>   	rules/50-udev-default.rules \
>   	rules/60-block.rules \
>   	rules/60-drm.rules \
> +	rules/60-evdev.rules \
>   	rules/60-keyboard.rules \
>   	rules/60-persistent-storage-tape.rules \
>   	rules/60-persistent-input.rules \
> @@ -3873,6 +3874,7 @@ dist_udevhwdb_DATA = \
>   	hwdb/20-acpi-vendor.hwdb \
>   	hwdb/20-OUI.hwdb \
>   	hwdb/20-net-ifname.hwdb \
> +	hwdb/60-evdev.hwdb \
>   	hwdb/60-keyboard.hwdb \
>   	hwdb/70-mouse.hwdb \
>   	hwdb/70-touchpad.hwdb
> diff --git a/hwdb/60-evdev.hwdb b/hwdb/60-evdev.hwdb
> new file mode 100644
> index 0000000..0d67f87
> --- /dev/null
> +++ b/hwdb/60-evdev.hwdb
> @@ -0,0 +1,37 @@
> +# This file is part of systemd.
> +#
> +# The lookup keys are composed in:
> +#   60-evdev.rules
> +#
> +# Note: The format of the "evdev:" prefix match key is a
> +# contract between the rules file and the hardware data, it might
> +# change in later revisions to support more or better matches, it
> +# is not necessarily expected to be a stable ABI.
> +#
> +# Match string formats:
> +# evdev:<modalias>
> +# evdev:name:<device name>:dmi:<dmi string>
> +#
> +# To add local entries, create a new file
> +#   /etc/udev/hwdb.d/61-evdev-local.hwdb
> +# and add your rules there. To load the new rules execute (as root):
> +#   udevadm hwdb --update
> +#   udevadm trigger /dev/input/eventXX
> +# where /dev/input/eventXX is the device in question. If in
> +# doubt, simply use /dev/input/event* to reload all input rules.
> +#
> +# If your changes are generally applicable, open a bug report on
> +#   http://bugs.freedesktop.org/enter_bug.cgi?product=systemd
> +# and include your new rules, a description of the device, and the
> +# output of
> +#   udevadm info /dev/input/eventXX
> +# (or /dev/input/event*).
> +#
> +# Allowed properties are:
> +#    EV_ABS_OVERRIDE_<axis>=<min>:<max>:<res>:<fuzz>:<flat>
> +#
> +# where <axis> is the hexadecimal EV_ABS code as listed in linux/input.h
> +# and min, max, res, fuzz, flat are the decimal values to the respective
> +# fields of the struct input_absinfo as listed in linux/input.h.
> +# If a field is missing the field will be left as-is. Not all fields need to
> +# be present. e.g. ::45 sets the resolution to 45 units/mm.
> diff --git a/rules/60-evdev.rules b/rules/60-evdev.rules
> new file mode 100644
> index 0000000..67308ad
> --- /dev/null
> +++ b/rules/60-evdev.rules
> @@ -0,0 +1,14 @@
> +# do not edit this file, it will be overwritten on update
> +
> +ACTION=="remove", GOTO="evdev_end"
> +KERNEL!="event*", GOTO="evdev_end"
> +
> +# skip later rules when we find something for this input device
> +IMPORT{builtin}="hwdb --subsystem=input --lookup-prefix=evdev:", \
> +  RUN{builtin}+="keyboard", GOTO="evdev_end"
> +
> +# device matching the input device name and the machine's DMI data
> +KERNELS=="input*", IMPORT{builtin}="hwdb 'evdev:name:$attr{name}:$attr{[dmi/id]modalias}'", \
> +  RUN{builtin}+="keyboard", GOTO="evdev_end"
> +
> +LABEL="evdev_end"
> diff --git a/src/udev/udev-builtin-keyboard.c b/src/udev/udev-builtin-keyboard.c
> index ed869ff..38ed800 100644
> --- a/src/udev/udev-builtin-keyboard.c
> +++ b/src/udev/udev-builtin-keyboard.c
> @@ -95,6 +95,68 @@ 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, "Error, 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("Error, unable to parse EV_ABS override '%s' for '%s'\n",
> +                          value, devnode);
> +                return;
> +        }
> +
> +        log_debug("keyboard: override %x with %d/%d/%d/%d/%d", evcode,
> +                  absinfo.minimum, absinfo.maximum, absinfo.resolution,
> +                  absinfo.fuzz, absinfo.flat);
> +        rc = ioctl(fd, EVIOCSABS(evcode), &absinfo);
> +        if (rc < 0)
> +                log_error_errno(errno, "Error, unable to update device '%s'",
> +                                devnode);
> +
> +        return;
Hmmm, do we actually need this "return"?
> +}
> +
> +static int open_device(const char *devnode) {
> +        int fd = open(devnode, O_RDWR|O_CLOEXEC|O_NONBLOCK|O_NOCTTY);
> +        if (fd < 0)
> +                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];
> @@ -140,14 +202,29 @@ 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, "EV_ABS_OVERRIDE_")) {
> +                        unsigned evcode;
> +
> +                        /* EV_ABS_OVERRIDE_<EV_ABS code>=<min>:<max>:<res>:<fuzz>:<flat> */
> +                        evcode = strtoul(key + 16, &endptr, 16);
> +                        if (endptr[0] != '\0') {
> +                                log_error("Error, 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));
>                   }
>           }
>   

-- 
Regards,
R.H.



More information about the systemd-devel mailing list