[PATCH libevdev 1/2] tools - tweak-device: revamp to reduce use of globals

Peter Hutterer peter.hutterer at who-t.net
Tue Jun 30 00:21:00 PDT 2015


Make the code base a bit more modular so it's easier to add new commands.
Main change here is: options are parsed twice now, first time for the mode
(abs/led) and the device path, then again for the mode-specific options.

Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
---
 tools/libevdev-tweak-device.c | 213 ++++++++++++++++++++++++++++++------------
 1 file changed, 151 insertions(+), 62 deletions(-)

diff --git a/tools/libevdev-tweak-device.c b/tools/libevdev-tweak-device.c
index 21cd69c..3d1cd23 100644
--- a/tools/libevdev-tweak-device.c
+++ b/tools/libevdev-tweak-device.c
@@ -37,13 +37,6 @@
 
 #include "libevdev.h"
 
-static unsigned int changes; /* bitmask of changes */
-static struct input_absinfo absinfo;
-static int axis;
-static int led;
-static int led_state = -1;
-const char *path;
-
 static void
 usage(void)
 {
@@ -54,6 +47,13 @@ usage(void)
 	       program_invocation_short_name, program_invocation_short_name);
 }
 
+enum mode {
+	MODE_NONE = 0,
+	MODE_ABS,
+	MODE_LED,
+	MODE_HELP,
+};
+
 enum opts {
 	OPT_ABS = 1 << 0,
 	OPT_MIN = 1 << 1,
@@ -68,7 +68,8 @@ enum opts {
 };
 
 static int
-parse_options(int argc, char **argv)
+parse_options_abs(int argc, char **argv, unsigned int *changes,
+		  int *axis, struct input_absinfo *absinfo)
 {
 	int rc = 1;
 	int c;
@@ -80,10 +81,6 @@ parse_options(int argc, char **argv)
 		{ "fuzz", 1, 0, OPT_FUZZ },
 		{ "flat", 1, 0, OPT_FLAT },
 		{ "res", 1, 0, OPT_RES },
-		{ "led", 1, 0, OPT_LED },
-		{ "on", 0, 0, OPT_ON },
-		{ "off", 0, 0, OPT_OFF },
-		{ "help", 0, 0, OPT_HELP },
 		{ NULL, 0, 0, 0 },
 	};
 
@@ -96,69 +93,133 @@ parse_options(int argc, char **argv)
 			break;
 
 		switch (c) {
-			case 'h':
-			case OPT_HELP:
-				goto error;
 			case OPT_ABS:
-				if (changes & OPT_LED)
-					goto error;
-
-				axis = libevdev_event_code_from_name(EV_ABS,
+				*axis = libevdev_event_code_from_name(EV_ABS,
 								     optarg);
-				if (axis == -1)
-					goto error;
-				break;
-			case OPT_LED:
-				if (changes & OPT_ABS)
-					goto error;
-
-				led = libevdev_event_code_from_name(EV_LED,
-								    optarg);
-				if (led == -1)
+				if (*axis == -1)
 					goto error;
 				break;
 			case OPT_MIN:
-				absinfo.minimum = atoi(optarg);
+				absinfo->minimum = atoi(optarg);
 				break;
 			case OPT_MAX:
-				absinfo.maximum = atoi(optarg);
+				absinfo->maximum = atoi(optarg);
 				break;
 			case OPT_FUZZ:
-				absinfo.fuzz = atoi(optarg);
+				absinfo->fuzz = atoi(optarg);
 				break;
 			case OPT_FLAT:
-				absinfo.flat = atoi(optarg);
+				absinfo->flat = atoi(optarg);
 				break;
 			case OPT_RES:
-				absinfo.resolution = atoi(optarg);
+				absinfo->resolution = atoi(optarg);
+				break;
+			default:
+				goto error;
+		}
+		*changes |= c;
+	}
+	rc = 0;
+error:
+	return rc;
+}
+
+static int
+parse_options_led(int argc, char **argv, int *led, int *led_state)
+{
+	int rc = 1;
+	int c;
+	int option_index = 0;
+	static struct option opts[] = {
+		{ "led", 1, 0, OPT_LED },
+		{ "on", 0, 0, OPT_ON },
+		{ "off", 0, 0, OPT_OFF },
+		{ NULL, 0, 0, 0 },
+	};
+
+	if (argc < 2)
+		goto error;
+
+	while (1) {
+		c = getopt_long(argc, argv, "h", opts, &option_index);
+		if (c == -1)
+			break;
+
+		switch (c) {
+			case OPT_LED:
+				*led = libevdev_event_code_from_name(EV_LED,
+								     optarg);
+				if (*led == -1)
+					goto error;
 				break;
 			case OPT_ON:
-				if (led_state != -1)
+				if (*led_state != -1)
 					goto error;
-				led_state = 1;
+				*led_state = 1;
 				break;
 			case OPT_OFF:
-				if (led_state != -1)
+				if (*led_state != -1)
 					goto error;
-				led_state = 0;
+				*led_state = 0;
 				break;
 			default:
 				goto error;
 		}
-		changes |= c;
+	}
+
+	rc = 0;
+error:
+	return rc;
+}
+
+static enum mode
+parse_options_mode(int argc, char **argv, const char **path)
+{
+	int c;
+	int option_index = 0;
+	static const struct option opts[] = {
+		{ "abs", 0, 0, OPT_ABS },
+		{ "led", 0, 0, OPT_LED },
+		{ "help", 0, 0, OPT_HELP },
+		{ NULL, 0, 0, 0 },
+	};
+	enum mode mode = MODE_NONE;
+
+	if (argc < 2)
+		return mode;
+
+	while (1) {
+		c = getopt_long(argc, argv, "h", opts, &option_index);
+		if (c == -1)
+			break;
+
+		switch (c) {
+			case 'h':
+			case OPT_HELP:
+				mode = MODE_HELP;
+				break;
+			case OPT_ABS:
+				mode = MODE_ABS;
+				break;
+			case OPT_LED:
+				mode = MODE_LED;
+				break;
+			default:
+				break;
+		}
 	}
 
 	if (optind >= argc)
-		goto error;
-	path = argv[optind];
+		return MODE_NONE;
 
-	rc = 0;
-error:
-	return rc;
+	*path = argv[optind];
+
+	return mode;
 }
 
 static void
-set_abs(struct libevdev *dev)
+set_abs(struct libevdev *dev, unsigned int changes,
+	unsigned int axis, struct input_absinfo *absinfo)
 {
 	int rc;
 	struct input_absinfo abs;
@@ -174,15 +235,15 @@ set_abs(struct libevdev *dev)
 
 	abs = *a;
 	if (changes & OPT_MIN)
-		abs.minimum = absinfo.minimum;
+		abs.minimum = absinfo->minimum;
 	if (changes & OPT_MAX)
-		abs.maximum = absinfo.maximum;
+		abs.maximum = absinfo->maximum;
 	if (changes & OPT_FUZZ)
-		abs.fuzz = absinfo.fuzz;
+		abs.fuzz = absinfo->fuzz;
 	if (changes & OPT_FLAT)
-		abs.flat = absinfo.flat;
+		abs.flat = absinfo->flat;
 	if (changes & OPT_RES)
-		abs.resolution = absinfo.resolution;
+		abs.resolution = absinfo->resolution;
 
 	rc = libevdev_kernel_set_abs_info(dev, axis, &abs);
 	if (rc != 0)
@@ -193,7 +254,7 @@ set_abs(struct libevdev *dev)
 }
 
 static void
-set_led(struct libevdev *dev)
+set_led(struct libevdev *dev, unsigned int led, int led_state)
 {
 	int rc;
 	enum libevdev_led_value state =
@@ -221,13 +282,38 @@ main(int argc, char **argv)
 	struct libevdev *dev = NULL;
 	int fd = -1;
 	int rc = 1;
+	enum mode mode;
+	const char *path;
+	struct input_absinfo absinfo;
+	int axis;
+	int led;
+	int led_state = -1;
+	unsigned int changes; /* bitmask of changes */
 
-	rc = parse_options(argc, argv);
-	if (rc != 0 || !path) {
-		usage();
-		goto out;
+	mode = parse_options_mode(argc, argv, &path);
+	switch (mode) {
+		case MODE_HELP:
+			rc = EXIT_SUCCESS;
+			/* fallthrough */
+		case MODE_NONE:
+			usage();
+			goto out;
+		case MODE_ABS:
+			rc = parse_options_abs(argc, argv, &changes, &axis,
+					       &absinfo);
+			break;
+		case MODE_LED:
+			rc = parse_options_led(argc, argv, &led, &led_state);
+			break;
+		default:
+			fprintf(stderr,
+				"++?????++ Out of Cheese Error. Redo From Start.\n");
+			goto out;
 	}
 
+	if (rc != EXIT_SUCCESS)
+		goto out;
+
 	fd = open(path, O_RDWR);
 	if (fd < 0) {
 		perror("Failed to open device");
@@ -240,13 +326,16 @@ main(int argc, char **argv)
 		goto out;
 	}
 
-	if (changes & OPT_ABS)
-		set_abs(dev);
-	else if (changes & OPT_LED)
-		set_led(dev);
-	else
-		fprintf(stderr,
-			"++?????++ Out of Cheese Error. Redo From Start.\n");
+	switch (mode) {
+		case MODE_ABS:
+			set_abs(dev, changes, axis, &absinfo);
+			break;
+		case MODE_LED:
+			set_led(dev, led, led_state);
+			break;
+		default:
+			break;
+	}
 
 out:
 	libevdev_free(dev);
-- 
2.4.3



More information about the Input-tools mailing list