[PATCH libevdev 2/3] tools: add wheel click measurement

Peter Hutterer peter.hutterer at who-t.net
Mon Jan 12 16:57:56 PST 2015


Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
---
 tools/Makefile.am               |   3 +-
 tools/libevdev-measure-device.1 |   9 +++
 tools/libevdev-measure-device.c |   5 +-
 tools/libevdev-measure-device.h |   1 +
 tools/mouse-wheel-tool.c        | 169 ++++++++++++++++++++++++++++++++++++++++
 5 files changed, 185 insertions(+), 2 deletions(-)
 create mode 100644 tools/mouse-wheel-tool.c

diff --git a/tools/Makefile.am b/tools/Makefile.am
index 562bba1..5d9706d 100644
--- a/tools/Makefile.am
+++ b/tools/Makefile.am
@@ -15,7 +15,8 @@ libevdev_measure_device_SOURCES = \
 				  libevdev-measure-device.c \
 				  libevdev-measure-device.h \
 				  touchpad-edge-detector.c \
-				  mouse-dpi-tool.c
+				  mouse-dpi-tool.c \
+				  mouse-wheel-tool.c
 libevdev_measure_device_LDADD = $(libevdev_ldadd)
 libevdev_measure_device_MANS = libevdev-measure-device.1
 
diff --git a/tools/libevdev-measure-device.1 b/tools/libevdev-measure-device.1
index 69d0d31..cecd275 100644
--- a/tools/libevdev-measure-device.1
+++ b/tools/libevdev-measure-device.1
@@ -25,6 +25,10 @@ values do not reflect what the touchpad actually supports.
 .B dpi
 Measure the mouse sensor's resolution and frequency. See the section
 "Measuring the sensor resolution" for details.
+.TP 8
+.B wheel
+Measure the angle of each mouse wheel click. See the section "measuring
+wheel click angles" for details.
 .SH NOTES
 .SS Measuring the sensor resolution
 .PP
@@ -40,3 +44,8 @@ The frequency reported by
 is the maximum frequency encountered. Some mouse devices provide dynamic
 frequencies, it is recommended to measure multiple times to obtain the
 highest value.
+.SS Measuring wheel click angles
+.PP
+The best way to measure the wheel click angles is to mark the mouse wheel
+with a pen. Then rotate the wheel once until the marked spot lines up with
+the previous physical location again.
diff --git a/tools/libevdev-measure-device.c b/tools/libevdev-measure-device.c
index b6cf4b5..0f459be 100644
--- a/tools/libevdev-measure-device.c
+++ b/tools/libevdev-measure-device.c
@@ -46,6 +46,8 @@ mouse_run(int argc, char **argv)
 		rc = EXIT_USAGE;
 	else if (strcmp(argv[0], "dpi") == 0)
 		rc = mouse_dpi_tool(argc - 1, &argv[1]);
+	else if (strcmp(argv[0], "wheel") == 0)
+		rc = mouse_wheel_tool(argc - 1, &argv[1]);
 	else
 		rc = EXIT_USAGE;
 
@@ -129,7 +131,8 @@ usage(void)
 	       "    mode \"edges\" ... measure the edges of the touchpad\n"
 	       "\n"
 	       "For type \"mouse\":\n"
-	       "    mode \"dpi\" ... measure the DPI/frequency of the mouse\n");
+	       "    mode \"dpi\" ... measure the DPI/frequency of the mouse\n"
+	       "    mode \"wheel\" ... measure the angle for wheel clicks\n");
 }
 
 int
diff --git a/tools/libevdev-measure-device.h b/tools/libevdev-measure-device.h
index 94579e7..151244e 100644
--- a/tools/libevdev-measure-device.h
+++ b/tools/libevdev-measure-device.h
@@ -29,6 +29,7 @@
 
 int touchpad_edge_detector(int argc, char **argv);
 int mouse_dpi_tool(int argc, char **argv);
+int mouse_wheel_tool(int argc, char **argv);
 
 struct libevdev * open_device(const char *path);
 void close_device(struct libevdev * dev);
diff --git a/tools/mouse-wheel-tool.c b/tools/mouse-wheel-tool.c
new file mode 100644
index 0000000..9b56cac
--- /dev/null
+++ b/tools/mouse-wheel-tool.c
@@ -0,0 +1,169 @@
+/*
+ * Copyright © 2014 Red Hat, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without
+ * fee, provided that the above copyright notice appear in all copies
+ * and that both that copyright notice and this permission notice
+ * appear in supporting documentation, and that the name of Red Hat
+ * not be used in advertising or publicity pertaining to distribution
+ * of the software without specific, written prior permission.  Red
+ * Hat makes no representations about the suitability of this software
+ * for any purpose.  It is provided "as is" without express or implied
+ * warranty.
+ *
+ * THE AUTHORS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
+ * NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
+ * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+ * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <libevdev/libevdev.h>
+#include <sys/signalfd.h>
+#include <errno.h>
+#include <limits.h>
+#include <poll.h>
+#include <signal.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "libevdev-measure-device.h"
+
+
+static int
+print_current_values(int wheel_counts)
+{
+	static int progress = 0;
+	char status = 0;
+
+	switch (progress) {
+		case 0: status = '|'; break;
+		case 1: status = '/'; break;
+		case 2: status = '-'; break;
+		case 3: status = '\\'; break;
+		default:
+			status = '?';
+			break;
+	}
+
+	progress = (progress + 1) % 4;
+	printf("\rWheel steps counted: %8d	%c",
+	        wheel_counts, status);
+
+	return 0;
+}
+
+static unsigned int
+mainloop(struct libevdev *dev) {
+	struct pollfd fds[2];
+	sigset_t mask;
+	int wheel_counts = 0;
+
+	fds[0].fd = libevdev_get_fd(dev);
+	fds[0].events = POLLIN;
+
+	sigemptyset(&mask);
+	sigaddset(&mask, SIGINT);
+	fds[1].fd = signalfd(-1, &mask, SFD_NONBLOCK);
+	fds[1].events = POLLIN;
+
+	sigprocmask(SIG_BLOCK, &mask, NULL);
+
+	while (poll(fds, 2, -1)) {
+		struct input_event ev;
+		int rc;
+
+		if (fds[1].revents)
+			break;
+
+		do {
+			rc = libevdev_next_event(dev, LIBEVDEV_READ_FLAG_NORMAL, &ev);
+			if (rc == LIBEVDEV_READ_STATUS_SYNC) {
+				fprintf(stderr, "Error: cannot keep up\n");
+				return 1;
+			} else if (rc != -EAGAIN && rc < 0) {
+				fprintf(stderr, "Error: %s\n", strerror(-rc));
+				return 1;
+			} else if (rc == LIBEVDEV_READ_STATUS_SUCCESS) {
+				if (libevdev_event_is_code(&ev,
+							   EV_REL,
+							   REL_WHEEL)) {
+					wheel_counts += ev.value;
+					print_current_values(abs(wheel_counts));
+				}
+			}
+		} while (rc != -EAGAIN);
+	}
+
+	return abs(wheel_counts);
+}
+
+static inline const char*
+bustype(int bustype)
+{
+	const char *bus;
+
+	switch(bustype) {
+		case BUS_PCI: bus = "pci"; break;
+		case BUS_ISAPNP: bus = "isapnp"; break;
+		case BUS_USB: bus = "usb"; break;
+		case BUS_HIL: bus = "hil"; break;
+		case BUS_BLUETOOTH: bus = "bluetooth"; break;
+		case BUS_VIRTUAL: bus = "virtual"; break;
+		default: bus = "unknown bus type"; break;
+	}
+
+	return bus;
+}
+
+int
+mouse_wheel_tool(int argc, char **argv) {
+	const char *path;
+	struct libevdev *dev;
+	unsigned int wheel_count = 0;
+
+	if (argc < 1)
+		return EXIT_USAGE;
+
+	path = argv[0];
+	dev = open_device(path);
+	if (!dev)
+		return EXIT_FAILURE;
+
+	if (!libevdev_has_event_code(dev, EV_REL, REL_WHEEL)) {
+		fprintf(stderr, "Error: this device doesn't have a wheel.\n");
+		close_device(dev);
+		return EXIT_FAILURE;
+	}
+
+	printf("Mouse %s on %s\n", libevdev_get_name(dev), path);
+	printf("Rotate the wheel by one full rotation. Ctrl+C to exit.\n");
+	setbuf(stdout, NULL);
+
+	wheel_count = mainloop(dev);
+
+	printf("\n");
+
+	printf("Entry for hwdb match (replace XXX with the resolution in DPI):\n"
+	       "mouse:%s:v%04xp%04x:name:%s:\n"
+	       " MOUSE_WHEEL_CLICK_ANGLE=%d\n",
+	       bustype(libevdev_get_id_bustype(dev)),
+	       libevdev_get_id_vendor(dev),
+	       libevdev_get_id_product(dev),
+	       libevdev_get_name(dev),
+	       360/wheel_count);
+
+	close_device(dev);
+
+	return 0;
+}
-- 
2.1.0



More information about the Input-tools mailing list