[PATCH libevdev 2/3] tools: add wheel click measurement
Benjamin Tissoires
benjamin.tissoires at gmail.com
Tue Jan 20 09:09:09 PST 2015
On Mon, Jan 12, 2015 at 7:57 PM, Peter Hutterer
<peter.hutterer at who-t.net> wrote:
> 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]);
I missed that in the previous patch. You are mixing function pointers
in an array for the first arg, but then a plain function call for the
second arg.
Maybe we should either have only one array, or plain functions calls,
but this seems a little bit weird (not to mention that the code of
mouse_run and touchpad_run are similar).
> 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;
> +}
Isn't this code also in the dpi tool?
> +
> +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
I agree that this code works. But if you have one tool, and the
sub-tools code share a lot of similarities, can't we have only one
generic call and a few variant callbacks (are plain calls)?
On the other hand, maybe we don't want you to spend too much time on
this either :)
Cheers,
Benjamin
More information about the Input-tools
mailing list