1c0abf9e6Sopenharmony_ci// SPDX-License-Identifier: MIT 2c0abf9e6Sopenharmony_ci/* 3c0abf9e6Sopenharmony_ci * Copyright © 2014 Red Hat, Inc. 4c0abf9e6Sopenharmony_ci */ 5c0abf9e6Sopenharmony_ci 6c0abf9e6Sopenharmony_ci#include "config.h" 7c0abf9e6Sopenharmony_ci 8c0abf9e6Sopenharmony_ci#include <assert.h> 9c0abf9e6Sopenharmony_ci#include <errno.h> 10c0abf9e6Sopenharmony_ci#include <fcntl.h> 11c0abf9e6Sopenharmony_ci#include <getopt.h> 12c0abf9e6Sopenharmony_ci#include <libgen.h> 13c0abf9e6Sopenharmony_ci#include <limits.h> 14c0abf9e6Sopenharmony_ci#include <linux/input.h> 15c0abf9e6Sopenharmony_ci#include <stdbool.h> 16c0abf9e6Sopenharmony_ci#include <stdio.h> 17c0abf9e6Sopenharmony_ci#include <stdlib.h> 18c0abf9e6Sopenharmony_ci#include <string.h> 19c0abf9e6Sopenharmony_ci#include <sys/stat.h> 20c0abf9e6Sopenharmony_ci#include <sys/types.h> 21c0abf9e6Sopenharmony_ci#include <unistd.h> 22c0abf9e6Sopenharmony_ci 23c0abf9e6Sopenharmony_ci#include "libevdev/libevdev.h" 24c0abf9e6Sopenharmony_ci 25c0abf9e6Sopenharmony_cistatic void 26c0abf9e6Sopenharmony_ciusage(const char *progname) 27c0abf9e6Sopenharmony_ci{ 28c0abf9e6Sopenharmony_ci printf("%s --abs <axis> [--min min] [--max max] [--res res] [--fuzz fuzz] [--flat flat] /dev/input/eventXYZ\n" 29c0abf9e6Sopenharmony_ci "\tChange the absinfo struct for the named axis\n" 30c0abf9e6Sopenharmony_ci "%s --resolution res[,yres] /dev/input/eventXYZ\n" 31c0abf9e6Sopenharmony_ci "\tChange the x/y resolution on the given device\n" 32c0abf9e6Sopenharmony_ci "%s --led <led> --on|--off /dev/input/eventXYZ\n" 33c0abf9e6Sopenharmony_ci "\tEnable or disable the named LED\n", 34c0abf9e6Sopenharmony_ci progname, 35c0abf9e6Sopenharmony_ci progname, 36c0abf9e6Sopenharmony_ci progname); 37c0abf9e6Sopenharmony_ci} 38c0abf9e6Sopenharmony_ci 39c0abf9e6Sopenharmony_cienum mode { 40c0abf9e6Sopenharmony_ci MODE_NONE = 0, 41c0abf9e6Sopenharmony_ci MODE_ABS, 42c0abf9e6Sopenharmony_ci MODE_LED, 43c0abf9e6Sopenharmony_ci MODE_RESOLUTION, 44c0abf9e6Sopenharmony_ci MODE_HELP, 45c0abf9e6Sopenharmony_ci}; 46c0abf9e6Sopenharmony_ci 47c0abf9e6Sopenharmony_cienum opts { 48c0abf9e6Sopenharmony_ci OPT_ABS = 1 << 0, 49c0abf9e6Sopenharmony_ci OPT_MIN = 1 << 1, 50c0abf9e6Sopenharmony_ci OPT_MAX = 1 << 2, 51c0abf9e6Sopenharmony_ci OPT_FUZZ = 1 << 3, 52c0abf9e6Sopenharmony_ci OPT_FLAT = 1 << 4, 53c0abf9e6Sopenharmony_ci OPT_RES = 1 << 5, 54c0abf9e6Sopenharmony_ci OPT_LED = 1 << 6, 55c0abf9e6Sopenharmony_ci OPT_ON = 1 << 7, 56c0abf9e6Sopenharmony_ci OPT_OFF = 1 << 8, 57c0abf9e6Sopenharmony_ci OPT_RESOLUTION = 1 << 9, 58c0abf9e6Sopenharmony_ci OPT_HELP = 1 << 10, 59c0abf9e6Sopenharmony_ci}; 60c0abf9e6Sopenharmony_ci 61c0abf9e6Sopenharmony_cistatic bool 62c0abf9e6Sopenharmony_ciparse_resolution_argument(const char *arg, int *xres, int *yres) 63c0abf9e6Sopenharmony_ci{ 64c0abf9e6Sopenharmony_ci int matched; 65c0abf9e6Sopenharmony_ci 66c0abf9e6Sopenharmony_ci matched = sscanf(arg, "%d,%d", xres, yres); 67c0abf9e6Sopenharmony_ci 68c0abf9e6Sopenharmony_ci switch(matched) { 69c0abf9e6Sopenharmony_ci case 2: 70c0abf9e6Sopenharmony_ci break; 71c0abf9e6Sopenharmony_ci case 1: 72c0abf9e6Sopenharmony_ci *yres = *xres; 73c0abf9e6Sopenharmony_ci break; 74c0abf9e6Sopenharmony_ci default: 75c0abf9e6Sopenharmony_ci return false; 76c0abf9e6Sopenharmony_ci } 77c0abf9e6Sopenharmony_ci 78c0abf9e6Sopenharmony_ci return true; 79c0abf9e6Sopenharmony_ci} 80c0abf9e6Sopenharmony_ci 81c0abf9e6Sopenharmony_cistatic inline bool 82c0abf9e6Sopenharmony_cisafe_atoi(const char *str, int *val) 83c0abf9e6Sopenharmony_ci{ 84c0abf9e6Sopenharmony_ci char *endptr; 85c0abf9e6Sopenharmony_ci long v; 86c0abf9e6Sopenharmony_ci 87c0abf9e6Sopenharmony_ci v = strtol(str, &endptr, 10); 88c0abf9e6Sopenharmony_ci if (str == endptr) 89c0abf9e6Sopenharmony_ci return false; 90c0abf9e6Sopenharmony_ci if (*str != '\0' && *endptr != '\0') 91c0abf9e6Sopenharmony_ci return false; 92c0abf9e6Sopenharmony_ci 93c0abf9e6Sopenharmony_ci if (v > INT_MAX || v < INT_MIN) 94c0abf9e6Sopenharmony_ci return false; 95c0abf9e6Sopenharmony_ci 96c0abf9e6Sopenharmony_ci *val = v; 97c0abf9e6Sopenharmony_ci return true; 98c0abf9e6Sopenharmony_ci} 99c0abf9e6Sopenharmony_ci 100c0abf9e6Sopenharmony_cistatic int 101c0abf9e6Sopenharmony_ciparse_event_code(int type, const char *str) 102c0abf9e6Sopenharmony_ci{ 103c0abf9e6Sopenharmony_ci int code; 104c0abf9e6Sopenharmony_ci 105c0abf9e6Sopenharmony_ci code = libevdev_event_code_from_name(type, str); 106c0abf9e6Sopenharmony_ci if (code != -1) 107c0abf9e6Sopenharmony_ci return code; 108c0abf9e6Sopenharmony_ci 109c0abf9e6Sopenharmony_ci if (safe_atoi(str, &code)) 110c0abf9e6Sopenharmony_ci return code; 111c0abf9e6Sopenharmony_ci 112c0abf9e6Sopenharmony_ci return -1; 113c0abf9e6Sopenharmony_ci} 114c0abf9e6Sopenharmony_ci 115c0abf9e6Sopenharmony_cistatic int 116c0abf9e6Sopenharmony_ciparse_options_abs(int argc, char **argv, unsigned int *changes, 117c0abf9e6Sopenharmony_ci int *axis, struct input_absinfo *absinfo) 118c0abf9e6Sopenharmony_ci{ 119c0abf9e6Sopenharmony_ci int rc = 1; 120c0abf9e6Sopenharmony_ci int c; 121c0abf9e6Sopenharmony_ci int option_index = 0; 122c0abf9e6Sopenharmony_ci static struct option opts[] = { 123c0abf9e6Sopenharmony_ci { "abs", 1, 0, OPT_ABS }, 124c0abf9e6Sopenharmony_ci { "min", 1, 0, OPT_MIN }, 125c0abf9e6Sopenharmony_ci { "max", 1, 0, OPT_MAX }, 126c0abf9e6Sopenharmony_ci { "fuzz", 1, 0, OPT_FUZZ }, 127c0abf9e6Sopenharmony_ci { "flat", 1, 0, OPT_FLAT }, 128c0abf9e6Sopenharmony_ci { "res", 1, 0, OPT_RES }, 129c0abf9e6Sopenharmony_ci { NULL, 0, 0, 0 }, 130c0abf9e6Sopenharmony_ci }; 131c0abf9e6Sopenharmony_ci 132c0abf9e6Sopenharmony_ci if (argc < 2) 133c0abf9e6Sopenharmony_ci goto error; 134c0abf9e6Sopenharmony_ci 135c0abf9e6Sopenharmony_ci optind = 1; 136c0abf9e6Sopenharmony_ci while (1) { 137c0abf9e6Sopenharmony_ci c = getopt_long(argc, argv, "h", opts, &option_index); 138c0abf9e6Sopenharmony_ci if (c == -1) 139c0abf9e6Sopenharmony_ci break; 140c0abf9e6Sopenharmony_ci 141c0abf9e6Sopenharmony_ci switch (c) { 142c0abf9e6Sopenharmony_ci case OPT_ABS: 143c0abf9e6Sopenharmony_ci *axis = parse_event_code(EV_ABS, optarg); 144c0abf9e6Sopenharmony_ci if (*axis == -1) 145c0abf9e6Sopenharmony_ci goto error; 146c0abf9e6Sopenharmony_ci break; 147c0abf9e6Sopenharmony_ci case OPT_MIN: 148c0abf9e6Sopenharmony_ci absinfo->minimum = atoi(optarg); 149c0abf9e6Sopenharmony_ci break; 150c0abf9e6Sopenharmony_ci case OPT_MAX: 151c0abf9e6Sopenharmony_ci absinfo->maximum = atoi(optarg); 152c0abf9e6Sopenharmony_ci break; 153c0abf9e6Sopenharmony_ci case OPT_FUZZ: 154c0abf9e6Sopenharmony_ci absinfo->fuzz = atoi(optarg); 155c0abf9e6Sopenharmony_ci break; 156c0abf9e6Sopenharmony_ci case OPT_FLAT: 157c0abf9e6Sopenharmony_ci absinfo->flat = atoi(optarg); 158c0abf9e6Sopenharmony_ci break; 159c0abf9e6Sopenharmony_ci case OPT_RES: 160c0abf9e6Sopenharmony_ci absinfo->resolution = atoi(optarg); 161c0abf9e6Sopenharmony_ci break; 162c0abf9e6Sopenharmony_ci default: 163c0abf9e6Sopenharmony_ci goto error; 164c0abf9e6Sopenharmony_ci } 165c0abf9e6Sopenharmony_ci *changes |= c; 166c0abf9e6Sopenharmony_ci } 167c0abf9e6Sopenharmony_ci rc = 0; 168c0abf9e6Sopenharmony_cierror: 169c0abf9e6Sopenharmony_ci return rc; 170c0abf9e6Sopenharmony_ci} 171c0abf9e6Sopenharmony_ci 172c0abf9e6Sopenharmony_cistatic int 173c0abf9e6Sopenharmony_ciparse_options_led(int argc, char **argv, int *led, int *led_state) 174c0abf9e6Sopenharmony_ci{ 175c0abf9e6Sopenharmony_ci int rc = 1; 176c0abf9e6Sopenharmony_ci int c; 177c0abf9e6Sopenharmony_ci int option_index = 0; 178c0abf9e6Sopenharmony_ci static struct option opts[] = { 179c0abf9e6Sopenharmony_ci { "led", 1, 0, OPT_LED }, 180c0abf9e6Sopenharmony_ci { "on", 0, 0, OPT_ON }, 181c0abf9e6Sopenharmony_ci { "off", 0, 0, OPT_OFF }, 182c0abf9e6Sopenharmony_ci { NULL, 0, 0, 0 }, 183c0abf9e6Sopenharmony_ci }; 184c0abf9e6Sopenharmony_ci 185c0abf9e6Sopenharmony_ci if (argc < 2) 186c0abf9e6Sopenharmony_ci goto error; 187c0abf9e6Sopenharmony_ci 188c0abf9e6Sopenharmony_ci optind = 1; 189c0abf9e6Sopenharmony_ci while (1) { 190c0abf9e6Sopenharmony_ci c = getopt_long(argc, argv, "h", opts, &option_index); 191c0abf9e6Sopenharmony_ci if (c == -1) 192c0abf9e6Sopenharmony_ci break; 193c0abf9e6Sopenharmony_ci 194c0abf9e6Sopenharmony_ci switch (c) { 195c0abf9e6Sopenharmony_ci case OPT_LED: 196c0abf9e6Sopenharmony_ci *led = parse_event_code(EV_LED, optarg); 197c0abf9e6Sopenharmony_ci if (*led == -1) 198c0abf9e6Sopenharmony_ci goto error; 199c0abf9e6Sopenharmony_ci break; 200c0abf9e6Sopenharmony_ci case OPT_ON: 201c0abf9e6Sopenharmony_ci if (*led_state != -1) 202c0abf9e6Sopenharmony_ci goto error; 203c0abf9e6Sopenharmony_ci *led_state = 1; 204c0abf9e6Sopenharmony_ci break; 205c0abf9e6Sopenharmony_ci case OPT_OFF: 206c0abf9e6Sopenharmony_ci if (*led_state != -1) 207c0abf9e6Sopenharmony_ci goto error; 208c0abf9e6Sopenharmony_ci *led_state = 0; 209c0abf9e6Sopenharmony_ci break; 210c0abf9e6Sopenharmony_ci default: 211c0abf9e6Sopenharmony_ci goto error; 212c0abf9e6Sopenharmony_ci } 213c0abf9e6Sopenharmony_ci } 214c0abf9e6Sopenharmony_ci 215c0abf9e6Sopenharmony_ci rc = 0; 216c0abf9e6Sopenharmony_cierror: 217c0abf9e6Sopenharmony_ci return rc; 218c0abf9e6Sopenharmony_ci} 219c0abf9e6Sopenharmony_ci 220c0abf9e6Sopenharmony_cistatic int 221c0abf9e6Sopenharmony_ciparse_options_resolution(int argc, char **argv, int *xres, int *yres) 222c0abf9e6Sopenharmony_ci{ 223c0abf9e6Sopenharmony_ci int rc = 1; 224c0abf9e6Sopenharmony_ci int c; 225c0abf9e6Sopenharmony_ci int option_index = 0; 226c0abf9e6Sopenharmony_ci static struct option opts[] = { 227c0abf9e6Sopenharmony_ci { "resolution", 1, 0, OPT_RESOLUTION }, 228c0abf9e6Sopenharmony_ci { NULL, 0, 0, 0 }, 229c0abf9e6Sopenharmony_ci }; 230c0abf9e6Sopenharmony_ci 231c0abf9e6Sopenharmony_ci if (argc < 2) 232c0abf9e6Sopenharmony_ci goto error; 233c0abf9e6Sopenharmony_ci 234c0abf9e6Sopenharmony_ci optind = 1; 235c0abf9e6Sopenharmony_ci while (1) { 236c0abf9e6Sopenharmony_ci c = getopt_long(argc, argv, "h", opts, &option_index); 237c0abf9e6Sopenharmony_ci if (c == -1) 238c0abf9e6Sopenharmony_ci break; 239c0abf9e6Sopenharmony_ci 240c0abf9e6Sopenharmony_ci switch (c) { 241c0abf9e6Sopenharmony_ci case OPT_RESOLUTION: 242c0abf9e6Sopenharmony_ci if (!parse_resolution_argument(optarg, 243c0abf9e6Sopenharmony_ci xres, yres)) 244c0abf9e6Sopenharmony_ci goto error; 245c0abf9e6Sopenharmony_ci break; 246c0abf9e6Sopenharmony_ci default: 247c0abf9e6Sopenharmony_ci goto error; 248c0abf9e6Sopenharmony_ci } 249c0abf9e6Sopenharmony_ci } 250c0abf9e6Sopenharmony_ci 251c0abf9e6Sopenharmony_ci rc = 0; 252c0abf9e6Sopenharmony_cierror: 253c0abf9e6Sopenharmony_ci return rc; 254c0abf9e6Sopenharmony_ci} 255c0abf9e6Sopenharmony_ci 256c0abf9e6Sopenharmony_cistatic enum mode 257c0abf9e6Sopenharmony_ciparse_options_mode(int argc, char **argv) 258c0abf9e6Sopenharmony_ci{ 259c0abf9e6Sopenharmony_ci int c; 260c0abf9e6Sopenharmony_ci int option_index = 0; 261c0abf9e6Sopenharmony_ci static const struct option opts[] = { 262c0abf9e6Sopenharmony_ci { "abs", 1, 0, OPT_ABS }, 263c0abf9e6Sopenharmony_ci { "led", 1, 0, OPT_LED }, 264c0abf9e6Sopenharmony_ci { "resolution", 1, 0, OPT_RESOLUTION }, 265c0abf9e6Sopenharmony_ci { "help", 0, 0, OPT_HELP }, 266c0abf9e6Sopenharmony_ci { NULL, 0, 0, 0 }, 267c0abf9e6Sopenharmony_ci }; 268c0abf9e6Sopenharmony_ci enum mode mode = MODE_NONE; 269c0abf9e6Sopenharmony_ci 270c0abf9e6Sopenharmony_ci if (argc < 2) 271c0abf9e6Sopenharmony_ci return mode; 272c0abf9e6Sopenharmony_ci 273c0abf9e6Sopenharmony_ci while (mode == MODE_NONE) { 274c0abf9e6Sopenharmony_ci c = getopt_long(argc, argv, "h", opts, &option_index); 275c0abf9e6Sopenharmony_ci if (c == -1) 276c0abf9e6Sopenharmony_ci break; 277c0abf9e6Sopenharmony_ci 278c0abf9e6Sopenharmony_ci switch (c) { 279c0abf9e6Sopenharmony_ci case 'h': 280c0abf9e6Sopenharmony_ci case OPT_HELP: 281c0abf9e6Sopenharmony_ci mode = MODE_HELP; 282c0abf9e6Sopenharmony_ci break; 283c0abf9e6Sopenharmony_ci case OPT_ABS: 284c0abf9e6Sopenharmony_ci mode = MODE_ABS; 285c0abf9e6Sopenharmony_ci break; 286c0abf9e6Sopenharmony_ci case OPT_LED: 287c0abf9e6Sopenharmony_ci mode = MODE_LED; 288c0abf9e6Sopenharmony_ci break; 289c0abf9e6Sopenharmony_ci case OPT_RESOLUTION: 290c0abf9e6Sopenharmony_ci mode = MODE_RESOLUTION; 291c0abf9e6Sopenharmony_ci break; 292c0abf9e6Sopenharmony_ci default: 293c0abf9e6Sopenharmony_ci break; 294c0abf9e6Sopenharmony_ci } 295c0abf9e6Sopenharmony_ci } 296c0abf9e6Sopenharmony_ci 297c0abf9e6Sopenharmony_ci if (optind >= argc && mode != MODE_HELP) 298c0abf9e6Sopenharmony_ci return MODE_NONE; 299c0abf9e6Sopenharmony_ci 300c0abf9e6Sopenharmony_ci return mode; 301c0abf9e6Sopenharmony_ci} 302c0abf9e6Sopenharmony_ci 303c0abf9e6Sopenharmony_cistatic void 304c0abf9e6Sopenharmony_ciset_abs(struct libevdev *dev, unsigned int changes, 305c0abf9e6Sopenharmony_ci unsigned int axis, struct input_absinfo *absinfo) 306c0abf9e6Sopenharmony_ci{ 307c0abf9e6Sopenharmony_ci int rc; 308c0abf9e6Sopenharmony_ci struct input_absinfo abs; 309c0abf9e6Sopenharmony_ci const struct input_absinfo *a; 310c0abf9e6Sopenharmony_ci 311c0abf9e6Sopenharmony_ci if ((a = libevdev_get_abs_info(dev, axis)) == NULL) { 312c0abf9e6Sopenharmony_ci fprintf(stderr, 313c0abf9e6Sopenharmony_ci "Device '%s' doesn't have axis %s\n", 314c0abf9e6Sopenharmony_ci libevdev_get_name(dev), 315c0abf9e6Sopenharmony_ci libevdev_event_code_get_name(EV_ABS, axis)); 316c0abf9e6Sopenharmony_ci return; 317c0abf9e6Sopenharmony_ci } 318c0abf9e6Sopenharmony_ci 319c0abf9e6Sopenharmony_ci abs = *a; 320c0abf9e6Sopenharmony_ci if (changes & OPT_MIN) 321c0abf9e6Sopenharmony_ci abs.minimum = absinfo->minimum; 322c0abf9e6Sopenharmony_ci if (changes & OPT_MAX) 323c0abf9e6Sopenharmony_ci abs.maximum = absinfo->maximum; 324c0abf9e6Sopenharmony_ci if (changes & OPT_FUZZ) 325c0abf9e6Sopenharmony_ci abs.fuzz = absinfo->fuzz; 326c0abf9e6Sopenharmony_ci if (changes & OPT_FLAT) 327c0abf9e6Sopenharmony_ci abs.flat = absinfo->flat; 328c0abf9e6Sopenharmony_ci if (changes & OPT_RES) 329c0abf9e6Sopenharmony_ci abs.resolution = absinfo->resolution; 330c0abf9e6Sopenharmony_ci 331c0abf9e6Sopenharmony_ci rc = libevdev_kernel_set_abs_info(dev, axis, &abs); 332c0abf9e6Sopenharmony_ci if (rc != 0) 333c0abf9e6Sopenharmony_ci fprintf(stderr, 334c0abf9e6Sopenharmony_ci "Failed to set absinfo %s: %s", 335c0abf9e6Sopenharmony_ci libevdev_event_code_get_name(EV_ABS, axis), 336c0abf9e6Sopenharmony_ci strerror(-rc)); 337c0abf9e6Sopenharmony_ci} 338c0abf9e6Sopenharmony_ci 339c0abf9e6Sopenharmony_cistatic void 340c0abf9e6Sopenharmony_ciset_led(struct libevdev *dev, unsigned int led, int led_state) 341c0abf9e6Sopenharmony_ci{ 342c0abf9e6Sopenharmony_ci int rc; 343c0abf9e6Sopenharmony_ci enum libevdev_led_value state = 344c0abf9e6Sopenharmony_ci led_state ? LIBEVDEV_LED_ON : LIBEVDEV_LED_OFF; 345c0abf9e6Sopenharmony_ci 346c0abf9e6Sopenharmony_ci if (!libevdev_has_event_code(dev, EV_LED, led)) { 347c0abf9e6Sopenharmony_ci fprintf(stderr, 348c0abf9e6Sopenharmony_ci "Device '%s' doesn't have %s\n", 349c0abf9e6Sopenharmony_ci libevdev_get_name(dev), 350c0abf9e6Sopenharmony_ci libevdev_event_code_get_name(EV_LED, led)); 351c0abf9e6Sopenharmony_ci return; 352c0abf9e6Sopenharmony_ci } 353c0abf9e6Sopenharmony_ci 354c0abf9e6Sopenharmony_ci rc = libevdev_kernel_set_led_value(dev, led, state); 355c0abf9e6Sopenharmony_ci if (rc != 0) 356c0abf9e6Sopenharmony_ci fprintf(stderr, 357c0abf9e6Sopenharmony_ci "Failed to set LED %s: %s", 358c0abf9e6Sopenharmony_ci libevdev_event_code_get_name(EV_LED, led), 359c0abf9e6Sopenharmony_ci strerror(-rc)); 360c0abf9e6Sopenharmony_ci} 361c0abf9e6Sopenharmony_ci 362c0abf9e6Sopenharmony_cistatic void 363c0abf9e6Sopenharmony_ciset_resolution(struct libevdev *dev, int xres, int yres) 364c0abf9e6Sopenharmony_ci{ 365c0abf9e6Sopenharmony_ci struct input_absinfo abs; 366c0abf9e6Sopenharmony_ci 367c0abf9e6Sopenharmony_ci abs.resolution = xres; 368c0abf9e6Sopenharmony_ci if (libevdev_has_event_code(dev, EV_ABS, ABS_X)) 369c0abf9e6Sopenharmony_ci set_abs(dev, OPT_RES, ABS_X, &abs); 370c0abf9e6Sopenharmony_ci if (libevdev_has_event_code(dev, EV_ABS, ABS_MT_POSITION_X)) 371c0abf9e6Sopenharmony_ci set_abs(dev, OPT_RES, ABS_MT_POSITION_X, &abs); 372c0abf9e6Sopenharmony_ci 373c0abf9e6Sopenharmony_ci abs.resolution = yres; 374c0abf9e6Sopenharmony_ci if (libevdev_has_event_code(dev, EV_ABS, ABS_Y)) 375c0abf9e6Sopenharmony_ci set_abs(dev, OPT_RES, ABS_Y, &abs); 376c0abf9e6Sopenharmony_ci if (libevdev_has_event_code(dev, EV_ABS, ABS_MT_POSITION_Y)) 377c0abf9e6Sopenharmony_ci set_abs(dev, OPT_RES, ABS_MT_POSITION_Y, &abs); 378c0abf9e6Sopenharmony_ci} 379c0abf9e6Sopenharmony_ci 380c0abf9e6Sopenharmony_ciint 381c0abf9e6Sopenharmony_cimain(int argc, char **argv) 382c0abf9e6Sopenharmony_ci{ 383c0abf9e6Sopenharmony_ci struct libevdev *dev = NULL; 384c0abf9e6Sopenharmony_ci int fd = -1; 385c0abf9e6Sopenharmony_ci int rc = EXIT_FAILURE; 386c0abf9e6Sopenharmony_ci enum mode mode; 387c0abf9e6Sopenharmony_ci const char *path; 388c0abf9e6Sopenharmony_ci struct input_absinfo absinfo; 389c0abf9e6Sopenharmony_ci int axis = -1; 390c0abf9e6Sopenharmony_ci int led = -1; 391c0abf9e6Sopenharmony_ci int led_state = -1; 392c0abf9e6Sopenharmony_ci unsigned int changes = 0; /* bitmask of changes */ 393c0abf9e6Sopenharmony_ci int xres = 0, 394c0abf9e6Sopenharmony_ci yres = 0; 395c0abf9e6Sopenharmony_ci 396c0abf9e6Sopenharmony_ci mode = parse_options_mode(argc, argv); 397c0abf9e6Sopenharmony_ci switch (mode) { 398c0abf9e6Sopenharmony_ci case MODE_HELP: 399c0abf9e6Sopenharmony_ci rc = EXIT_SUCCESS; 400c0abf9e6Sopenharmony_ci /* fallthrough */ 401c0abf9e6Sopenharmony_ci case MODE_NONE: 402c0abf9e6Sopenharmony_ci usage(basename(argv[0])); 403c0abf9e6Sopenharmony_ci goto out; 404c0abf9e6Sopenharmony_ci case MODE_ABS: 405c0abf9e6Sopenharmony_ci rc = parse_options_abs(argc, argv, &changes, &axis, 406c0abf9e6Sopenharmony_ci &absinfo); 407c0abf9e6Sopenharmony_ci break; 408c0abf9e6Sopenharmony_ci case MODE_LED: 409c0abf9e6Sopenharmony_ci rc = parse_options_led(argc, argv, &led, &led_state); 410c0abf9e6Sopenharmony_ci break; 411c0abf9e6Sopenharmony_ci case MODE_RESOLUTION: 412c0abf9e6Sopenharmony_ci rc = parse_options_resolution(argc, argv, &xres, 413c0abf9e6Sopenharmony_ci &yres); 414c0abf9e6Sopenharmony_ci break; 415c0abf9e6Sopenharmony_ci default: 416c0abf9e6Sopenharmony_ci fprintf(stderr, 417c0abf9e6Sopenharmony_ci "++?????++ Out of Cheese Error. Redo From Start.\n"); 418c0abf9e6Sopenharmony_ci goto out; 419c0abf9e6Sopenharmony_ci } 420c0abf9e6Sopenharmony_ci 421c0abf9e6Sopenharmony_ci if (rc != EXIT_SUCCESS) 422c0abf9e6Sopenharmony_ci goto out; 423c0abf9e6Sopenharmony_ci 424c0abf9e6Sopenharmony_ci if (optind >= argc) { 425c0abf9e6Sopenharmony_ci rc = EXIT_FAILURE; 426c0abf9e6Sopenharmony_ci usage(basename(argv[0])); 427c0abf9e6Sopenharmony_ci goto out; 428c0abf9e6Sopenharmony_ci } 429c0abf9e6Sopenharmony_ci 430c0abf9e6Sopenharmony_ci path = argv[optind]; 431c0abf9e6Sopenharmony_ci 432c0abf9e6Sopenharmony_ci fd = open(path, O_RDWR); 433c0abf9e6Sopenharmony_ci if (fd < 0) { 434c0abf9e6Sopenharmony_ci rc = EXIT_FAILURE; 435c0abf9e6Sopenharmony_ci perror("Failed to open device"); 436c0abf9e6Sopenharmony_ci goto out; 437c0abf9e6Sopenharmony_ci } 438c0abf9e6Sopenharmony_ci 439c0abf9e6Sopenharmony_ci rc = libevdev_new_from_fd(fd, &dev); 440c0abf9e6Sopenharmony_ci if (rc < 0) { 441c0abf9e6Sopenharmony_ci fprintf(stderr, "Failed to init libevdev (%s)\n", strerror(-rc)); 442c0abf9e6Sopenharmony_ci goto out; 443c0abf9e6Sopenharmony_ci } 444c0abf9e6Sopenharmony_ci 445c0abf9e6Sopenharmony_ci switch (mode) { 446c0abf9e6Sopenharmony_ci case MODE_ABS: 447c0abf9e6Sopenharmony_ci set_abs(dev, changes, axis, &absinfo); 448c0abf9e6Sopenharmony_ci break; 449c0abf9e6Sopenharmony_ci case MODE_LED: 450c0abf9e6Sopenharmony_ci set_led(dev, led, led_state); 451c0abf9e6Sopenharmony_ci break; 452c0abf9e6Sopenharmony_ci case MODE_RESOLUTION: 453c0abf9e6Sopenharmony_ci set_resolution(dev, xres, yres); 454c0abf9e6Sopenharmony_ci break; 455c0abf9e6Sopenharmony_ci default: 456c0abf9e6Sopenharmony_ci break; 457c0abf9e6Sopenharmony_ci } 458c0abf9e6Sopenharmony_ci 459c0abf9e6Sopenharmony_ciout: 460c0abf9e6Sopenharmony_ci libevdev_free(dev); 461c0abf9e6Sopenharmony_ci if (fd != -1) 462c0abf9e6Sopenharmony_ci close(fd); 463c0abf9e6Sopenharmony_ci 464c0abf9e6Sopenharmony_ci return rc; 465c0abf9e6Sopenharmony_ci} 466