[v2,libinput,1/2] evdev: Query mouse DPI from udev

Submitted by Derek Foreman on Nov. 25, 2014, 5:46 p.m.

Details

Message ID 1416937603-29589-1-git-send-email-derekf@osg.samsung.com
State Not Applicable
Headers show

Not browsing as part of any series.

Commit Message

Derek Foreman Nov. 25, 2014, 5:46 p.m.
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 <derekf@osg.samsung.com>
---
 src/evdev.c         | 20 +++++++++++++++++++
 src/libinput-util.c | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/libinput-util.h |  2 ++
 3 files changed, 77 insertions(+)

Patch hide | download patch | download mbox

diff --git a/src/evdev.c b/src/evdev.c
index 908a8ba..d86f611 100644
--- a/src/evdev.c
+++ b/src/evdev.c
@@ -1220,9 +1220,29 @@  evdev_need_mtdev(struct evdev_device *device)
 static void
 evdev_tag_device(struct evdev_device *device)
 {
+	struct libinput *libinput = device->base.seat->libinput;
+	const char *mouse_dpi;
+	int dpi;
+
 	if (device->dispatch->interface->tag_device)
 		device->dispatch->interface->tag_device(device,
 							device->udev_device);
+
+	mouse_dpi = udev_device_get_property_value(device->udev_device,
+						   "MOUSE_DPI");
+	if (mouse_dpi) {
+		dpi = parse_mouse_dpi_property(mouse_dpi);
+		if (dpi)
+			device->dpi = dpi;
+		else {
+			log_error(libinput, "Mouse DPI property for '%s' is "
+					    "present but invalid, using %d "
+					    "DPI instead\n",
+					    device->devname,
+					    DEFAULT_MOUSE_DPI);
+			device->dpi = DEFAULT_MOUSE_DPI;
+		}
+	}
 }
 
 static inline int
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 a/src/libinput-util.h b/src/libinput-util.h
index 909c9db..6825841 100644
--- a/src/libinput-util.h
+++ b/src/libinput-util.h
@@ -296,4 +296,6 @@  struct ratelimit {
 void ratelimit_init(struct ratelimit *r, uint64_t ival_ms, unsigned int burst);
 enum ratelimit_state ratelimit_test(struct ratelimit *r);
 
+int parse_mouse_dpi_property(const char *prop);
+
 #endif /* LIBINPUT_UTIL_H */