diff options
author | Peter Hutterer <peter.hutterer@who-t.net> | 2014-02-20 14:40:32 +1000 |
---|---|---|
committer | Peter Hutterer <peter.hutterer@who-t.net> | 2014-02-25 13:18:18 +1000 |
commit | 5250243b6fad91a85f326148f176af5ac0ca31c9 (patch) | |
tree | 16fba24334b6f8912dbd0621984c49156a03fb77 | |
parent | a5a06035f96c6f0e1156cb7f25797e843e3cd396 (diff) | |
download | libevdev-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/.gitignore | 1 | ||||
-rw-r--r-- | tools/Makefile.am | 4 | ||||
-rw-r--r-- | tools/touchpad-edge-detector.c | 196 |
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; +} + |