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

Peter Hutterer peter.hutterer at who-t.net
Mon Jan 12 16:57:55 PST 2015


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]);
+	} else {
+
+		if (argc >= 2 &&
+		    (strcmp(argv[1], "--help") == 0 ||
+			   strcmp(argv[1], "-h") == 0)) {
+			usage();
+			return 0;
+		} else if (argc < 3) {
+			usage();
+			return EXIT_USAGE;
+		}
+
+		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



More information about the Input-tools mailing list