tools - tweak-device: revamp to reduce use of globals

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@who-t.net>
Reviewed-by: Benjamin Tissoires <benjamin.tissoires@gmail.com>
This commit is contained in:
Peter Hutterer 2015-06-29 10:44:10 +10:00
parent 743deafb95
commit 4d058bc2b0

View file

@ -37,13 +37,6 @@
#include "libevdev.h" #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 static void
usage(void) usage(void)
{ {
@ -54,6 +47,13 @@ usage(void)
program_invocation_short_name, program_invocation_short_name); program_invocation_short_name, program_invocation_short_name);
} }
enum mode {
MODE_NONE = 0,
MODE_ABS,
MODE_LED,
MODE_HELP,
};
enum opts { enum opts {
OPT_ABS = 1 << 0, OPT_ABS = 1 << 0,
OPT_MIN = 1 << 1, OPT_MIN = 1 << 1,
@ -68,7 +68,8 @@ enum opts {
}; };
static int 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 rc = 1;
int c; int c;
@ -80,16 +81,115 @@ parse_options(int argc, char **argv)
{ "fuzz", 1, 0, OPT_FUZZ }, { "fuzz", 1, 0, OPT_FUZZ },
{ "flat", 1, 0, OPT_FLAT }, { "flat", 1, 0, OPT_FLAT },
{ "res", 1, 0, OPT_RES }, { "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 }, { NULL, 0, 0, 0 },
}; };
if (argc < 2) if (argc < 2)
goto error; goto error;
optind = 1;
while (1) {
c = getopt_long(argc, argv, "h", opts, &option_index);
if (c == -1)
break;
switch (c) {
case OPT_ABS:
*axis = libevdev_event_code_from_name(EV_ABS,
optarg);
if (*axis == -1)
goto error;
break;
case OPT_MIN:
absinfo->minimum = atoi(optarg);
break;
case OPT_MAX:
absinfo->maximum = atoi(optarg);
break;
case OPT_FUZZ:
absinfo->fuzz = atoi(optarg);
break;
case OPT_FLAT:
absinfo->flat = atoi(optarg);
break;
case OPT_RES:
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;
optind = 1;
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)
goto error;
*led_state = 1;
break;
case OPT_OFF:
if (*led_state != -1)
goto error;
*led_state = 0;
break;
default:
goto error;
}
}
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", 1, 0, OPT_ABS },
{ "led", 1, 0, OPT_LED },
{ "help", 0, 0, OPT_HELP },
{ NULL, 0, 0, 0 },
};
enum mode mode = MODE_NONE;
if (argc < 2)
return mode;
while (1) { while (1) {
c = getopt_long(argc, argv, "h", opts, &option_index); c = getopt_long(argc, argv, "h", opts, &option_index);
if (c == -1) if (c == -1)
@ -98,67 +198,30 @@ parse_options(int argc, char **argv)
switch (c) { switch (c) {
case 'h': case 'h':
case OPT_HELP: case OPT_HELP:
goto error; mode = MODE_HELP;
break;
case OPT_ABS: case OPT_ABS:
if (changes & OPT_LED) mode = MODE_ABS;
goto error;
axis = libevdev_event_code_from_name(EV_ABS,
optarg);
if (axis == -1)
goto error;
break; break;
case OPT_LED: case OPT_LED:
if (changes & OPT_ABS) mode = MODE_LED;
goto error;
led = libevdev_event_code_from_name(EV_LED,
optarg);
if (led == -1)
goto error;
break;
case OPT_MIN:
absinfo.minimum = atoi(optarg);
break;
case OPT_MAX:
absinfo.maximum = atoi(optarg);
break;
case OPT_FUZZ:
absinfo.fuzz = atoi(optarg);
break;
case OPT_FLAT:
absinfo.flat = atoi(optarg);
break;
case OPT_RES:
absinfo.resolution = atoi(optarg);
break;
case OPT_ON:
if (led_state != -1)
goto error;
led_state = 1;
break;
case OPT_OFF:
if (led_state != -1)
goto error;
led_state = 0;
break; break;
default: default:
goto error; break;
} }
changes |= c;
} }
if (optind >= argc) if (optind >= argc)
goto error; return MODE_NONE;
path = argv[optind];
rc = 0; *path = argv[optind];
error:
return rc; return mode;
} }
static void static void
set_abs(struct libevdev *dev) set_abs(struct libevdev *dev, unsigned int changes,
unsigned int axis, struct input_absinfo *absinfo)
{ {
int rc; int rc;
struct input_absinfo abs; struct input_absinfo abs;
@ -174,15 +237,15 @@ set_abs(struct libevdev *dev)
abs = *a; abs = *a;
if (changes & OPT_MIN) if (changes & OPT_MIN)
abs.minimum = absinfo.minimum; abs.minimum = absinfo->minimum;
if (changes & OPT_MAX) if (changes & OPT_MAX)
abs.maximum = absinfo.maximum; abs.maximum = absinfo->maximum;
if (changes & OPT_FUZZ) if (changes & OPT_FUZZ)
abs.fuzz = absinfo.fuzz; abs.fuzz = absinfo->fuzz;
if (changes & OPT_FLAT) if (changes & OPT_FLAT)
abs.flat = absinfo.flat; abs.flat = absinfo->flat;
if (changes & OPT_RES) if (changes & OPT_RES)
abs.resolution = absinfo.resolution; abs.resolution = absinfo->resolution;
rc = libevdev_kernel_set_abs_info(dev, axis, &abs); rc = libevdev_kernel_set_abs_info(dev, axis, &abs);
if (rc != 0) if (rc != 0)
@ -193,7 +256,7 @@ set_abs(struct libevdev *dev)
} }
static void static void
set_led(struct libevdev *dev) set_led(struct libevdev *dev, unsigned int led, int led_state)
{ {
int rc; int rc;
enum libevdev_led_value state = enum libevdev_led_value state =
@ -221,13 +284,38 @@ main(int argc, char **argv)
struct libevdev *dev = NULL; struct libevdev *dev = NULL;
int fd = -1; int fd = -1;
int rc = 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); mode = parse_options_mode(argc, argv, &path);
if (rc != 0 || !path) { switch (mode) {
usage(); case MODE_HELP:
goto out; 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); fd = open(path, O_RDWR);
if (fd < 0) { if (fd < 0) {
perror("Failed to open device"); perror("Failed to open device");
@ -240,13 +328,16 @@ main(int argc, char **argv)
goto out; goto out;
} }
if (changes & OPT_ABS) switch (mode) {
set_abs(dev); case MODE_ABS:
else if (changes & OPT_LED) set_abs(dev, changes, axis, &absinfo);
set_led(dev); break;
else case MODE_LED:
fprintf(stderr, set_led(dev, led, led_state);
"++?????++ Out of Cheese Error. Redo From Start.\n"); break;
default:
break;
}
out: out:
libevdev_free(dev); libevdev_free(dev);