[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