summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Hutterer <peter.hutterer@who-t.net>2014-02-20 14:40:32 +1000
committerPeter Hutterer <peter.hutterer@who-t.net>2014-02-25 13:18:18 +1000
commit5250243b6fad91a85f326148f176af5ac0ca31c9 (patch)
tree16fba24334b6f8912dbd0621984c49156a03fb77
parenta5a06035f96c6f0e1156cb7f25797e843e3cd396 (diff)
downloadlibevdev-5250243b6fad91a85f326148f176af5ac0ca31c9.tar.gz
tools: add a tool to print the actual range provided by a touchpad
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
-rw-r--r--tools/.gitignore1
-rw-r--r--tools/Makefile.am4
-rw-r--r--tools/touchpad-edge-detector.c196
3 files changed, 201 insertions, 0 deletions
diff --git a/tools/.gitignore b/tools/.gitignore
index a511263..8084fed 100644
--- a/tools/.gitignore
+++ b/tools/.gitignore
@@ -1 +1,2 @@
libevdev-events
+touchpad-edge-detector
diff --git a/tools/Makefile.am b/tools/Makefile.am
index 7ac4431..0b8fbd0 100644
--- a/tools/Makefile.am
+++ b/tools/Makefile.am
@@ -1,4 +1,5 @@
noinst_PROGRAMS = libevdev-events
+bin_PROGRAMS = touchpad-edge-detector
AM_CPPFLAGS = $(GCC_CFLAGS) -I$(top_srcdir)/include -I$(top_srcdir)/libevdev
libevdev_ldadd = $(top_builddir)/libevdev/libevdev.la
@@ -6,3 +7,6 @@ libevdev_ldadd = $(top_builddir)/libevdev/libevdev.la
libevdev_events_SOURCES = libevdev-events.c
libevdev_events_LDADD = $(libevdev_ldadd)
+touchpad_edge_detector_SOURCES = touchpad-edge-detector.c
+touchpad_edge_detector_LDADD = $(libevdev_ldadd)
+
diff --git a/tools/touchpad-edge-detector.c b/tools/touchpad-edge-detector.c
new file mode 100644
index 0000000..76f83e2
--- /dev/null
+++ b/tools/touchpad-edge-detector.c
@@ -0,0 +1,196 @@
+/*
+ * 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 <fcntl.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>
+
+#define min(a, b) (((a) < (b)) ? (a) : (b))
+#define max(a, b) (((a) > (b)) ? (a) : (b))
+
+static int
+usage(void) {
+ printf("Usage: %s /dev/input/event0\n", program_invocation_short_name);
+ printf("\n");
+ printf("This tool reads the touchpad events from the kernel and calculates\n "
+ "the minimum and maximum for the x and y coordinates, respectively.\n");
+ return 1;
+}
+
+struct dimensions {
+ int top, bottom, left, right;
+};
+
+static int
+print_current_values(const struct dimensions *d)
+{
+ static int progress;
+ char status;
+
+ switch (progress) {
+ case 0: status = '|'; break;
+ case 1: status = '/'; break;
+ case 2: status = '-'; break;
+ case 3: status = '\\'; break;
+ }
+
+ progress = (progress + 1) % 4;
+
+ printf("\rTouchpad sends: x [%d..%d], y [%d..%d] %c",
+ d->left, d->right, d->top, d->bottom, status);
+ return 0;
+}
+
+static int
+handle_event(struct dimensions *d, const struct input_event *ev) {
+ if (ev->type == EV_SYN) {
+ return print_current_values(d);
+ } else if (ev->type != EV_ABS)
+ return 0;
+
+ switch(ev->code) {
+ case ABS_X:
+ case ABS_MT_POSITION_X:
+ d->left = min(d->left, ev->value);
+ d->right = max(d->right, ev->value);
+ break;
+ case ABS_Y:
+ case ABS_MT_POSITION_Y:
+ d->top = min(d->top, ev->value);
+ d->bottom = max(d->bottom, ev->value);
+ break;
+ }
+
+ return 0;
+}
+
+static int
+mainloop(struct libevdev *dev, struct dimensions *dim) {
+ struct pollfd fds[2];
+ sigset_t mask;
+
+ 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) {
+ handle_event(dim, &ev);
+ }
+ } while (rc != -EAGAIN);
+ }
+
+ return 0;
+}
+
+int main (int argc, char **argv) {
+ int rc;
+ int fd;
+ const char *path;
+ struct libevdev *dev;
+ struct dimensions dim;
+
+ if (argc < 2)
+ return usage();
+
+ path = argv[1];
+ if (path[0] == '-')
+ return usage();
+
+ fd = open(path, O_RDONLY|O_NONBLOCK);
+ if (fd < 0) {
+ fprintf(stderr, "Error opening the device: %s\n", strerror(errno));
+ return 1;
+ }
+
+ rc = libevdev_new_from_fd(fd, &dev);
+ if (rc != 0) {
+ fprintf(stderr, "Error fetching the device info: %s\n", strerror(-rc));
+ return 1;
+ }
+
+ if (libevdev_grab(dev, LIBEVDEV_GRAB) != 0) {
+ fprintf(stderr, "Error: cannot grab the device, something else is grabbing it.\n");
+ fprintf(stderr, "Use 'fuser -v %s' to find processes with an open fd\n", path);
+ return 1;
+ }
+ libevdev_grab(dev, LIBEVDEV_UNGRAB);
+
+ dim.left = INT_MAX;
+ dim.right = INT_MIN;
+ dim.top = INT_MAX;
+ dim.bottom = INT_MIN;
+
+ printf("Touchpad %s on %s\n", libevdev_get_name(dev), path);
+ printf("Move one finger around the touchpad to detect the actual edges\n");
+ printf("Kernel says: x [%d..%d], y [%d..%d]\n",
+ libevdev_get_abs_minimum(dev, ABS_X),
+ libevdev_get_abs_maximum(dev, ABS_X),
+ libevdev_get_abs_minimum(dev, ABS_Y),
+ libevdev_get_abs_maximum(dev, ABS_Y));
+
+ setbuf(stdout, NULL);
+
+ rc = mainloop(dev, &dim);
+
+ printf("\n");
+
+ libevdev_free(dev);
+ close(fd);
+
+ return rc;
+}
+