Re: [PATCH v3 libinput] evdev: Query mouse DPI from udev
Hi, On 11/25/2014 11:41 PM, Peter Hutterer wrote: From: Derek Foreman der...@osg.samsung.com Instead of using a hard coded mouse DPI value, we query it from udev. If it's not present or the property is obviously broken we fall back to default. Signed-off-by: Derek Foreman der...@osg.samsung.com Signed-off-by: Peter Hutterer peter.hutte...@who-t.net Looks good: Reviewed-by: Hans de Goede hdego...@redhat.com Regards, Hans --- sorry, clearly didn't have the right caffeine/blood ratio yesterday, so I figured I fix up the remaining comments myself. Changes to v3: - move parsing code to be called when we set the DPI. evdev_tag_device isn't the right place for this. - squashed test patch into this one, better to have the tests together with the code that wants the tests - added more testcases for missing *, and @a invalid frequencies - change ck_assert(a == b) to ck_assert_int_eq(a, b) src/evdev.c | 26 - src/libinput-util.c | 55 + src/libinput-util.h | 2 ++ test/misc.c | 42 4 files changed, 124 insertions(+), 1 deletion(-) diff --git a/src/evdev.c b/src/evdev.c index baa1c51..015dc2f 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -1226,6 +1226,30 @@ evdev_tag_device(struct evdev_device *device) } static inline int +evdev_read_dpi_prop(struct evdev_device *device) +{ + struct libinput *libinput = device-base.seat-libinput; + const char *mouse_dpi; + int dpi = DEFAULT_MOUSE_DPI; + + mouse_dpi = udev_device_get_property_value(device-udev_device, + MOUSE_DPI); + if (mouse_dpi) { + dpi = parse_mouse_dpi_property(mouse_dpi); + if (!dpi) { + log_error(libinput, Mouse DPI property for '%s' is + present but invalid, using %d + DPI instead\n, + device-devname, + DEFAULT_MOUSE_DPI); + dpi = DEFAULT_MOUSE_DPI; + } + } + + return dpi; +} + +static inline int evdev_fix_abs_resolution(struct libevdev *evdev, unsigned int code, const struct input_absinfo *absinfo) @@ -1530,7 +1554,7 @@ evdev_device_create(struct libinput_seat *seat, device-devname = libevdev_get_name(device-evdev); device-scroll.threshold = 5.0; /* Default may be overridden */ device-scroll.direction = 0; - device-dpi = DEFAULT_MOUSE_DPI; + device-dpi = evdev_read_dpi_prop(device); /* at most 5 SYN_DROPPED log-messages per 30s */ ratelimit_init(device-syn_drop_limit, 30ULL * 1000, 5); diff --git a/src/libinput-util.c b/src/libinput-util.c index 34d5549..923e116 100644 --- a/src/libinput-util.c +++ b/src/libinput-util.c @@ -28,7 +28,9 @@ #include config.h +#include ctype.h #include stdarg.h +#include stdbool.h #include stdio.h #include stdlib.h @@ -113,3 +115,56 @@ ratelimit_test(struct ratelimit *r) return RATELIMIT_EXCEEDED; } + +/* Helper function to parse the mouse DPI tag from udev. + * The tag is of the form: + * MOUSE_DPI=400 *1000 2000 + * or + * MOUSE_DPI=400@125 *1000@125 2000@125 + * Where the * indicates the default value and @number indicates device poll + * rate. + * Numbers should be in ascending order, and if rates are present they should + * be present for all entries. + * + * When parsing the mouse DPI property, if we find an error we just return 0 + * since it's obviously invalid, the caller will treat that as an error and + * use a reasonable default instead. If the property contains multiple DPI + * settings but none flagged as default, we return the last because we're + * lazy and that's a silly way to set the property anyway. + */ +int +parse_mouse_dpi_property(const char *prop) +{ + bool is_default = false; + int nread, dpi = 0, rate; + + while (*prop != 0) { + if (*prop == ' ') { + prop++; + continue; + } + if (*prop == '*') { + prop++; + is_default = true; + if (!isdigit(prop[0])) + return 0; + } + + /* While we don't do anything with the rate right now we +* will validate that, if it's present, it is non-zero and +* positive +*/ + rate = 1; + nread = 0; + sscanf(prop, %d@%d%n, dpi, rate, nread); + if (!nread) + sscanf(prop, %d%n, dpi, nread); + if (!nread || dpi = 0 || rate = 0 || prop[nread] == '@') + return 0; + +
[PATCH v3 libinput] evdev: Query mouse DPI from udev
From: Derek Foreman der...@osg.samsung.com Instead of using a hard coded mouse DPI value, we query it from udev. If it's not present or the property is obviously broken we fall back to default. Signed-off-by: Derek Foreman der...@osg.samsung.com Signed-off-by: Peter Hutterer peter.hutte...@who-t.net --- sorry, clearly didn't have the right caffeine/blood ratio yesterday, so I figured I fix up the remaining comments myself. Changes to v3: - move parsing code to be called when we set the DPI. evdev_tag_device isn't the right place for this. - squashed test patch into this one, better to have the tests together with the code that wants the tests - added more testcases for missing *, and @a invalid frequencies - change ck_assert(a == b) to ck_assert_int_eq(a, b) src/evdev.c | 26 - src/libinput-util.c | 55 + src/libinput-util.h | 2 ++ test/misc.c | 42 4 files changed, 124 insertions(+), 1 deletion(-) diff --git a/src/evdev.c b/src/evdev.c index baa1c51..015dc2f 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -1226,6 +1226,30 @@ evdev_tag_device(struct evdev_device *device) } static inline int +evdev_read_dpi_prop(struct evdev_device *device) +{ + struct libinput *libinput = device-base.seat-libinput; + const char *mouse_dpi; + int dpi = DEFAULT_MOUSE_DPI; + + mouse_dpi = udev_device_get_property_value(device-udev_device, + MOUSE_DPI); + if (mouse_dpi) { + dpi = parse_mouse_dpi_property(mouse_dpi); + if (!dpi) { + log_error(libinput, Mouse DPI property for '%s' is + present but invalid, using %d + DPI instead\n, + device-devname, + DEFAULT_MOUSE_DPI); + dpi = DEFAULT_MOUSE_DPI; + } + } + + return dpi; +} + +static inline int evdev_fix_abs_resolution(struct libevdev *evdev, unsigned int code, const struct input_absinfo *absinfo) @@ -1530,7 +1554,7 @@ evdev_device_create(struct libinput_seat *seat, device-devname = libevdev_get_name(device-evdev); device-scroll.threshold = 5.0; /* Default may be overridden */ device-scroll.direction = 0; - device-dpi = DEFAULT_MOUSE_DPI; + device-dpi = evdev_read_dpi_prop(device); /* at most 5 SYN_DROPPED log-messages per 30s */ ratelimit_init(device-syn_drop_limit, 30ULL * 1000, 5); diff --git a/src/libinput-util.c b/src/libinput-util.c index 34d5549..923e116 100644 --- a/src/libinput-util.c +++ b/src/libinput-util.c @@ -28,7 +28,9 @@ #include config.h +#include ctype.h #include stdarg.h +#include stdbool.h #include stdio.h #include stdlib.h @@ -113,3 +115,56 @@ ratelimit_test(struct ratelimit *r) return RATELIMIT_EXCEEDED; } + +/* Helper function to parse the mouse DPI tag from udev. + * The tag is of the form: + * MOUSE_DPI=400 *1000 2000 + * or + * MOUSE_DPI=400@125 *1000@125 2000@125 + * Where the * indicates the default value and @number indicates device poll + * rate. + * Numbers should be in ascending order, and if rates are present they should + * be present for all entries. + * + * When parsing the mouse DPI property, if we find an error we just return 0 + * since it's obviously invalid, the caller will treat that as an error and + * use a reasonable default instead. If the property contains multiple DPI + * settings but none flagged as default, we return the last because we're + * lazy and that's a silly way to set the property anyway. + */ +int +parse_mouse_dpi_property(const char *prop) +{ + bool is_default = false; + int nread, dpi = 0, rate; + + while (*prop != 0) { + if (*prop == ' ') { + prop++; + continue; + } + if (*prop == '*') { + prop++; + is_default = true; + if (!isdigit(prop[0])) + return 0; + } + + /* While we don't do anything with the rate right now we +* will validate that, if it's present, it is non-zero and +* positive +*/ + rate = 1; + nread = 0; + sscanf(prop, %d@%d%n, dpi, rate, nread); + if (!nread) + sscanf(prop, %d%n, dpi, nread); + if (!nread || dpi = 0 || rate = 0 || prop[nread] == '@') + return 0; + + if (is_default) + break; + prop += nread; + } + return dpi; +} diff --git