[PATCH libevdev 1/3] tools: add a libevdev-measure-device tool

Benjamin Tissoires benjamin.tissoires at gmail.com
Tue Jan 20 08:57:27 PST 2015


On Mon, Jan 12, 2015 at 7:57 PM, Peter Hutterer
<peter.hutterer at who-t.net> wrote:
> We shouldn't add a new tool for each small functionality, incorporate them
> into one tool with a couple of options instead.
>
> The current tools, touchpad-edge-detector and mouse-dpi-tool are kept for
> backwards compatibility. Only change here is the usage() function which now
> returns the new tool.
>
> Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
> ---
>  tools/.gitignore                |   1 +
>  tools/Makefile.am               |  17 +++-
>  tools/libevdev-measure-device.1 |  42 ++++++++++
>  tools/libevdev-measure-device.c | 172 ++++++++++++++++++++++++++++++++++++++++
>  tools/libevdev-measure-device.h |  35 ++++++++
>  tools/mouse-dpi-tool.c          |  52 +++---------
>  tools/touchpad-edge-detector.c  |  56 +++----------
>  7 files changed, 286 insertions(+), 89 deletions(-)
>  create mode 100644 tools/libevdev-measure-device.1
>  create mode 100644 tools/libevdev-measure-device.c
>  create mode 100644 tools/libevdev-measure-device.h
>
> diff --git a/tools/.gitignore b/tools/.gitignore
> index c2a2645..e583387 100644
> --- a/tools/.gitignore
> +++ b/tools/.gitignore
> @@ -2,3 +2,4 @@ libevdev-events
>  touchpad-edge-detector
>  mouse-dpi-tool
>  libevdev-tweak-device
> +libevdev-measure-device
> diff --git a/tools/Makefile.am b/tools/Makefile.am
> index d699c5c..562bba1 100644
> --- a/tools/Makefile.am
> +++ b/tools/Makefile.am
> @@ -1,5 +1,6 @@
>  noinst_PROGRAMS = libevdev-events
>  bin_PROGRAMS = \
> +              libevdev-measure-device \
>                touchpad-edge-detector \
>                mouse-dpi-tool \
>                libevdev-tweak-device
> @@ -10,11 +11,19 @@ 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)
> +libevdev_measure_device_SOURCES = \
> +                                 libevdev-measure-device.c \
> +                                 libevdev-measure-device.h \
> +                                 touchpad-edge-detector.c \
> +                                 mouse-dpi-tool.c
> +libevdev_measure_device_LDADD = $(libevdev_ldadd)
> +libevdev_measure_device_MANS = libevdev-measure-device.1
>
> -mouse_dpi_tool_SOURCES = mouse-dpi-tool.c
> -mouse_dpi_tool_LDADD = $(libevdev_ldadd)
> +touchpad_edge_detector_SOURCES = $(libevdev_measure_device_SOURCES)
> +touchpad_edge_detector_LDADD = $(libevdev_measure_device_LDADD)
> +
> +mouse_dpi_tool_SOURCES = $(libevdev_measure_device_SOURCES)
> +mouse_dpi_tool_LDADD = $(libevdev_measure_device_LDADD)
>
>  libevdev_tweak_device_SOURCES = libevdev-tweak-device.c
>  libevdev_tweak_device_LDADD = $(libevdev_ldadd)
> diff --git a/tools/libevdev-measure-device.1 b/tools/libevdev-measure-device.1
> new file mode 100644
> index 0000000..69d0d31
> --- /dev/null
> +++ b/tools/libevdev-measure-device.1
> @@ -0,0 +1,42 @@
> +.TH LIBEVDEV-MEASURE-DEVICE "1"
> +.SH NAME
> +libevdev-measure-device \- measure properties of an evdev kernel device
> +.SH SYNOPSIS
> +.B libevdev-measure-device
> +<type> <mode> /dev/input/eventX
> +.PP
> +.SH DESCRIPTION
> +.PP
> +The
> +.I libevdev-measure-device
> +tool measures properties of the evdev kernel device at
> +.I /dev/input/eventX.
> +.SH OPTIONS
> +The <type> may be one of "touchpad" or "mouse", each type has different
> +modes and options.
> +.SS Touchpad-specific options
> +.TP 8
> +.B edges
> +Measure the min/max edge values used by the touchpad. Each touchpad
> +advertises a min/max range for the x and y axis. On some touchpads, these
> +values do not reflect what the touchpad actually supports.
> +.SS Mouse-specific options
> +.TP 8
> +.B dpi
> +Measure the mouse sensor's resolution and frequency. See the section
> +"Measuring the sensor resolution" for details.
> +.SH NOTES
> +.SS Measuring the sensor resolution
> +.PP
> +The best way to measure the sensor resolution is to take a piece of paper
> +and mark two spots a fixed distance apart. Line up the left edge of the mouse
> +with the left spot, then move the mouse until the left edge of the mouse
> +lines up with the right spot. It is recommended that the two spots are at
> +least 25cm/10in apart. If the two spots are exactly 254mm/10in apart, the
> +sensor resolution is one-tenth of the device units measured.
> +.PP
> +The frequency reported by
> +.B libevdev-measure-device
> +is the maximum frequency encountered. Some mouse devices provide dynamic
> +frequencies, it is recommended to measure multiple times to obtain the
> +highest value.
> diff --git a/tools/libevdev-measure-device.c b/tools/libevdev-measure-device.c
> new file mode 100644
> index 0000000..b6cf4b5
> --- /dev/null
> +++ b/tools/libevdev-measure-device.c
> @@ -0,0 +1,172 @@
> +/*
> + * Copyright © 2015 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.
> + */
> +
> +#define _GNU_SOURCE
> +
> +#ifdef HAVE_CONFIG_H
> +#include "config.h"
> +#endif
> +
> +#include <errno.h>
> +#include <fcntl.h>
> +#include <stdio.h>
> +#include <string.h>
> +#include <unistd.h>
> +
> +#include <libevdev/libevdev.h>
> +
> +#include "libevdev-measure-device.h"
> +
> +static int
> +mouse_run(int argc, char **argv)
> +{
> +       int rc;
> +
> +       if (argc < 2)
> +               rc = EXIT_USAGE;
> +       else if (strcmp(argv[0], "dpi") == 0)
> +               rc = mouse_dpi_tool(argc - 1, &argv[1]);
> +       else
> +               rc = EXIT_USAGE;
> +
> +       return rc;
> +}
> +
> +static int
> +touchpad_run(int argc, char **argv)
> +{
> +       int rc;
> +
> +       if (argc < 2)
> +               rc = EXIT_USAGE;
> +       else if (strcmp(argv[0], "edges") == 0)
> +               rc = touchpad_edge_detector(argc - 1, &argv[1]);
> +       else
> +               rc = EXIT_USAGE;
> +
> +       return rc;
> +}
> +
> +struct mode {
> +       const char *mode;
> +       int (*run)(int argc, char **argv);
> +};
> +
> +static const struct mode modes[] = {
> +       { "touchpad", touchpad_run },
> +       { "mouse", mouse_run },
> +       { NULL, NULL },
> +};
> +
> +struct libevdev *
> +open_device(const char *path)
> +{
> +       struct libevdev *dev = NULL;
> +       int fd, rc;
> +
> +       fd = open(path, O_RDONLY|O_NONBLOCK);
> +       if (fd < 0) {
> +               fprintf(stderr, "Error opening the device: %s\n", strerror(errno));
> +               goto error;
> +       }
> +
> +       rc = libevdev_new_from_fd(fd, &dev);
> +       if (rc != 0) {
> +               fprintf(stderr, "Error fetching the device info: %s\n", strerror(-rc));
> +               goto error;
> +       }
> +
> +       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);
> +               goto error;
> +       }
> +       libevdev_grab(dev, LIBEVDEV_UNGRAB);
> +
> +       return dev;
> +
> +error:
> +       libevdev_free(dev);
> +       if (fd != -1)
> +               close(fd);
> +       return NULL;
> +}
> +
> +void
> +close_device(struct libevdev *dev)
> +{
> +       int fd = libevdev_get_fd(dev);
> +       libevdev_free(dev);
> +       close(fd);
> +}
> +
> +static void
> +usage(void)
> +{
> +       printf("libevdev-measure-device <type> <mode> [options] <path>\n"
> +              "\n"
> +              "For type \"touchpad\":\n"
> +              "    mode \"edges\" ... measure the edges of the touchpad\n"
> +              "\n"
> +              "For type \"mouse\":\n"
> +              "    mode \"dpi\" ... measure the DPI/frequency of the mouse\n");
> +}
> +
> +int
> +main (int argc, char **argv) {
> +       int rc = EXIT_USAGE;
> +       const struct mode *mode;
> +       const char *prgname = program_invocation_short_name;
> +
> +       if (strcmp(prgname, "mouse-dpi-tool") == 0 ||
> +           strcmp(prgname, "lt-mouse-dpi-tool") == 0) {
> +               rc = mouse_dpi_tool(argc - 1, &argv[1]);
> +       } else if (strcmp(prgname, "touchpad-edge-detector") == 0 ||
> +                  strcmp(prgname, "lt-touchpad-edge-detector") == 0) {
> +               rc = touchpad_edge_detector(argc - 1, &argv[1]);

Can't you unify these 2 tests with the mode->run code below?

> +       } else {
> +
> +               if (argc >= 2 &&
> +                   (strcmp(argv[1], "--help") == 0 ||
> +                          strcmp(argv[1], "-h") == 0)) {
> +                       usage();
> +                       return 0;

I would have a validate_params() function and call usage() only once
when rc == EXIT_USAGE.

> +               } else if (argc < 3) {
> +                       usage();
> +                       return EXIT_USAGE;
> +               }

If I call the program with "./libevdev-measure-device foo bar --help",
the following loop will be executed. Not that it matters that much,
but why do we check for -h and --help previously if the general case
will deal with it?

Just nitpicking because it was not obvious at first how the option
parsing was working.

Cheers,
Benjamin

> +
> +               mode = modes;
> +               while (mode->mode) {
> +                       if (strcmp(mode->mode, argv[1]) == 0) {
> +                               rc = mode->run(argc - 2, &argv[2]);
> +                               break;
> +                       }
> +                       mode++;
> +               }
> +       }
> +
> +       if (rc == EXIT_USAGE)
> +               usage();
> +       return rc;
> +}
> diff --git a/tools/libevdev-measure-device.h b/tools/libevdev-measure-device.h
> new file mode 100644
> index 0000000..94579e7
> --- /dev/null
> +++ b/tools/libevdev-measure-device.h
> @@ -0,0 +1,35 @@
> +/*
> + * Copyright © 2015 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.
> + */
> +
> +
> +#ifndef LIBEVDEV_MEASURE_DEVICE_H
> +#define LIBEVDEV_MEASURE_DEVICE_H
> +
> +#define EXIT_USAGE 2
> +
> +int touchpad_edge_detector(int argc, char **argv);
> +int mouse_dpi_tool(int argc, char **argv);
> +
> +struct libevdev * open_device(const char *path);
> +void close_device(struct libevdev * dev);
> +#endif /* LIBEVDEV_MEASURE_DEVICE_H */
> diff --git a/tools/mouse-dpi-tool.c b/tools/mouse-dpi-tool.c
> index be30a4d..b0543f0 100644
> --- a/tools/mouse-dpi-tool.c
> +++ b/tools/mouse-dpi-tool.c
> @@ -26,9 +26,9 @@
>  #endif
>
>  #include <libevdev/libevdev.h>
> +#include <libevdev/libevdev-util.h>
>  #include <sys/signalfd.h>
>  #include <errno.h>
> -#include <fcntl.h>
>  #include <limits.h>
>  #include <poll.h>
>  #include <signal.h>
> @@ -36,10 +36,8 @@
>  #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))
> +#include "libevdev-measure-device.h"
>
>  struct measurements {
>         int distance;
> @@ -47,17 +45,6 @@ struct measurements {
>         uint32_t ms;
>  };
>
> -static int
> -usage(void) {
> -       printf("Usage: %s /dev/input/event0\n", program_invocation_short_name);
> -       printf("\n");
> -       printf("This tool reads relative events from the kernel and calculates\n"
> -              "the distance covered and maximum frequency of the incoming events.\n"
> -              "Some mouse devices provide dynamic frequencies, it is\n"
> -              "recommended to measure multiple times to obtain the highest value.\n");
> -       return 1;
> -}
> -
>  static inline uint32_t
>  tv2ms(const struct timeval *tv)
>  {
> @@ -207,38 +194,20 @@ bustype(int bustype)
>  }
>
>  int
> -main (int argc, char **argv) {
> +mouse_dpi_tool (int argc, char **argv) {
>         int rc;
> -       int fd;
>         const char *path;
>         struct libevdev *dev;
>         struct measurements measurements = {0, 0, 0};
>
> -       if (argc < 2)
> -               return usage();
> +       if (argc < 1)
> +               return EXIT_USAGE;
>
> -       path = argv[1];
> -       if (path[0] == '-')
> -               return usage();
> +       path = argv[0];
>
> -       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);
> +       dev = open_device(path);
> +       if (!dev)
> +               return EXIT_FAILURE;
>
>         printf("Mouse %s on %s\n", libevdev_get_name(dev), path);
>         printf("Move the device 250mm/10in or more along the x-axis.\n");
> @@ -261,8 +230,7 @@ main (int argc, char **argv) {
>                libevdev_get_name(dev),
>                (int)measurements.frequency);
>
> -       libevdev_free(dev);
> -       close(fd);
> +       close_device(dev);
>
>         return rc;
>  }
> diff --git a/tools/touchpad-edge-detector.c b/tools/touchpad-edge-detector.c
> index b857934..df0f032 100644
> --- a/tools/touchpad-edge-detector.c
> +++ b/tools/touchpad-edge-detector.c
> @@ -26,9 +26,9 @@
>  #endif
>
>  #include <libevdev/libevdev.h>
> +#include <libevdev/libevdev-util.h>
>  #include <sys/signalfd.h>
>  #include <errno.h>
> -#include <fcntl.h>
>  #include <limits.h>
>  #include <poll.h>
>  #include <signal.h>
> @@ -36,19 +36,8 @@
>  #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;
> -}
> +#include "libevdev-measure-device.h"
>
>  struct dimensions {
>         int top, bottom, left, right;
> @@ -123,10 +112,10 @@ mainloop(struct libevdev *dev, struct dimensions *dim) {
>                         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;
> +                               return EXIT_FAILURE;
>                         } else if (rc != -EAGAIN && rc < 0) {
>                                 fprintf(stderr, "Error: %s\n", strerror(-rc));
> -                               return 1;
> +                               return EXIT_FAILURE;
>                         } else if (rc == LIBEVDEV_READ_STATUS_SUCCESS) {
>                                 handle_event(dim, &ev);
>                         }
> @@ -136,38 +125,20 @@ mainloop(struct libevdev *dev, struct dimensions *dim) {
>         return 0;
>  }
>
> -int main (int argc, char **argv) {
> +int
> +touchpad_edge_detector (int argc, char **argv) {
>         int rc;
> -       int fd;
>         const char *path;
>         struct libevdev *dev;
>         struct dimensions dim;
>
> -       if (argc < 2)
> -               return usage();
> +       if (argc < 1)
> +               return EXIT_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);
> +       path = argv[0];
> +       dev = open_device(path);
> +       if (!dev)
> +               return EXIT_FAILURE;
>
>         dim.left = INT_MAX;
>         dim.right = INT_MIN;
> @@ -188,8 +159,7 @@ int main (int argc, char **argv) {
>
>         printf("\n");
>
> -       libevdev_free(dev);
> -       close(fd);
> +       close_device(dev);
>
>         return rc;
>  }
> --
> 2.1.0
>
> _______________________________________________
> Input-tools mailing list
> Input-tools at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/input-tools


More information about the Input-tools mailing list