diff options
Diffstat (limited to 'toolbox/getevent.c')
-rw-r--r-- | toolbox/getevent.c | 242 |
1 files changed, 219 insertions, 23 deletions
diff --git a/toolbox/getevent.c b/toolbox/getevent.c index 256720d..352f6f9 100644 --- a/toolbox/getevent.c +++ b/toolbox/getevent.c @@ -8,9 +8,11 @@ #include <sys/inotify.h> #include <sys/limits.h> #include <sys/poll.h> -#include <linux/input.h> // this does not compile +#include <linux/input.h> #include <errno.h> +#include "getevent.h" + static struct pollfd *ufds; static char **device_names; static int nfds; @@ -22,18 +24,66 @@ enum { PRINT_DEVICE_INFO = 1U << 3, PRINT_VERSION = 1U << 4, PRINT_POSSIBLE_EVENTS = 1U << 5, + PRINT_INPUT_PROPS = 1U << 6, + PRINT_HID_DESCRIPTOR = 1U << 7, + + PRINT_ALL_INFO = (1U << 8) - 1, + + PRINT_LABELS = 1U << 16, }; -static int print_possible_events(int fd) +static const char *get_label(const struct label *labels, int value) +{ + while(labels->name && value != labels->value) { + labels++; + } + return labels->name; +} + +static int print_input_props(int fd) +{ + uint8_t bits[INPUT_PROP_CNT / 8]; + int i, j; + int res; + int count; + const char *bit_label; + + printf(" input props:\n"); + res = ioctl(fd, EVIOCGPROP(sizeof(bits)), bits); + if(res < 0) { + printf(" <not available\n"); + return 1; + } + count = 0; + for(i = 0; i < res; i++) { + for(j = 0; j < 8; j++) { + if (bits[i] & 1 << j) { + bit_label = get_label(input_prop_labels, i * 8 + j); + if(bit_label) + printf(" %s\n", bit_label); + else + printf(" %04x\n", i * 8 + j); + count++; + } + } + } + if (!count) + printf(" <none>\n"); + return 0; +} + +static int print_possible_events(int fd, int print_flags) { uint8_t *bits = NULL; ssize_t bits_size = 0; const char* label; int i, j, k; int res, res2; - + struct label* bit_labels; + const char *bit_label; + printf(" events:\n"); - for(i = 0; i <= EV_MAX; i++) { + for(i = EV_KEY; i <= EV_MAX; i++) { // skip EV_SYN since we cannot query its available codes int count = 0; while(1) { res = ioctl(fd, EVIOCGBIT(i, bits_size), bits); @@ -42,52 +92,64 @@ static int print_possible_events(int fd) bits_size = res + 16; bits = realloc(bits, bits_size * 2); if(bits == NULL) { - fprintf(stderr, "failed to allocate buffer of size %d\n", bits_size); + fprintf(stderr, "failed to allocate buffer of size %d\n", (int)bits_size); return 1; } } res2 = 0; switch(i) { - case EV_SYN: - label = "SYN"; - break; case EV_KEY: res2 = ioctl(fd, EVIOCGKEY(res), bits + bits_size); label = "KEY"; + bit_labels = key_labels; break; case EV_REL: label = "REL"; + bit_labels = rel_labels; break; case EV_ABS: label = "ABS"; + bit_labels = abs_labels; break; case EV_MSC: label = "MSC"; + bit_labels = msc_labels; break; case EV_LED: res2 = ioctl(fd, EVIOCGLED(res), bits + bits_size); label = "LED"; + bit_labels = led_labels; break; case EV_SND: res2 = ioctl(fd, EVIOCGSND(res), bits + bits_size); label = "SND"; + bit_labels = snd_labels; break; case EV_SW: res2 = ioctl(fd, EVIOCGSW(bits_size), bits + bits_size); label = "SW "; + bit_labels = sw_labels; break; case EV_REP: label = "REP"; + bit_labels = rep_labels; break; case EV_FF: label = "FF "; + bit_labels = ff_labels; break; case EV_PWR: label = "PWR"; + bit_labels = NULL; + break; + case EV_FF_STATUS: + label = "FFS"; + bit_labels = ff_status_labels; break; default: res2 = 0; label = "???"; + bit_labels = NULL; } for(j = 0; j < res; j++) { for(k = 0; k < 8; k++) @@ -99,13 +161,23 @@ static int print_possible_events(int fd) down = ' '; if(count == 0) printf(" %s (%04x):", label, i); - else if((count & 0x7) == 0 || i == EV_ABS) + else if((count & (print_flags & PRINT_LABELS ? 0x3 : 0x7)) == 0 || i == EV_ABS) printf("\n "); - printf(" %04x%c", j * 8 + k, down); + if(bit_labels && (print_flags & PRINT_LABELS)) { + bit_label = get_label(bit_labels, j * 8 + k); + if(bit_label) + printf(" %.20s%c%*s", bit_label, down, 20 - strlen(bit_label), ""); + else + printf(" %04x%c ", j * 8 + k, down); + } else { + printf(" %04x%c", j * 8 + k, down); + } if(i == EV_ABS) { struct input_absinfo abs; if(ioctl(fd, EVIOCGABS(j * 8 + k), &abs) == 0) { - printf(" value %d, min %d, max %d, fuzz %d flat %d", abs.value, abs.minimum, abs.maximum, abs.fuzz, abs.flat); + printf(" : value %d, min %d, max %d, fuzz %d, flat %d, resolution %d", + abs.value, abs.minimum, abs.maximum, abs.fuzz, abs.flat, + abs.resolution); } } count++; @@ -118,6 +190,107 @@ static int print_possible_events(int fd) return 0; } +static void print_event(int type, int code, int value, int print_flags) +{ + const char *type_label, *code_label, *value_label; + + if (print_flags & PRINT_LABELS) { + type_label = get_label(ev_labels, type); + code_label = NULL; + value_label = NULL; + + switch(type) { + case EV_SYN: + code_label = get_label(syn_labels, code); + break; + case EV_KEY: + code_label = get_label(key_labels, code); + value_label = get_label(key_value_labels, value); + break; + case EV_REL: + code_label = get_label(rel_labels, code); + break; + case EV_ABS: + code_label = get_label(abs_labels, code); + switch(code) { + case ABS_MT_TOOL_TYPE: + value_label = get_label(mt_tool_labels, value); + } + break; + case EV_MSC: + code_label = get_label(msc_labels, code); + break; + case EV_LED: + code_label = get_label(led_labels, code); + break; + case EV_SND: + code_label = get_label(snd_labels, code); + break; + case EV_SW: + code_label = get_label(sw_labels, code); + break; + case EV_REP: + code_label = get_label(rep_labels, code); + break; + case EV_FF: + code_label = get_label(ff_labels, code); + break; + case EV_FF_STATUS: + code_label = get_label(ff_status_labels, code); + break; + } + + if (type_label) + printf("%-12.12s", type_label); + else + printf("%04x ", type); + if (code_label) + printf(" %-20.20s", code_label); + else + printf(" %04x ", code); + if (value_label) + printf(" %-20.20s", value_label); + else + printf(" %08x ", value); + } else { + printf("%04x %04x %08x", type, code, value); + } +} + +static void print_hid_descriptor(int bus, int vendor, int product) +{ + const char *dirname = "/sys/kernel/debug/hid"; + char prefix[16]; + DIR *dir; + struct dirent *de; + char filename[PATH_MAX]; + FILE *file; + char line[2048]; + + snprintf(prefix, sizeof(prefix), "%04X:%04X:%04X.", bus, vendor, product); + + dir = opendir(dirname); + if(dir == NULL) + return; + while((de = readdir(dir))) { + if (strstr(de->d_name, prefix) == de->d_name) { + snprintf(filename, sizeof(filename), "%s/%s/rdesc", dirname, de->d_name); + + file = fopen(filename, "r"); + if (file) { + printf(" HID descriptor: %s\n\n", de->d_name); + while (fgets(line, sizeof(line), file)) { + fputs(" ", stdout); + fputs(line, stdout); + } + fclose(file); + puts(""); + } + } + } + closedir(dir); +} + static int open_device(const char *device, int print_flags) { int version; @@ -193,7 +366,14 @@ static int open_device(const char *device, int print_flags) version >> 16, (version >> 8) & 0xff, version & 0xff); if(print_flags & PRINT_POSSIBLE_EVENTS) { - print_possible_events(fd); + print_possible_events(fd, print_flags); + } + + if(print_flags & PRINT_INPUT_PROPS) { + print_input_props(fd); + } + if(print_flags & PRINT_HID_DESCRIPTOR) { + print_hid_descriptor(id.bustype, id.vendor, id.product); } ufds[nfds].fd = fd; @@ -292,13 +472,16 @@ static int scan_dir(const char *dirname, int print_flags) static void usage(int argc, char *argv[]) { - fprintf(stderr, "Usage: %s [-t] [-n] [-s switchmask] [-S] [-v [mask]] [-p] [-q] [-c count] [-r] [device]\n", argv[0]); + fprintf(stderr, "Usage: %s [-t] [-n] [-s switchmask] [-S] [-v [mask]] [-d] [-p] [-i] [-l] [-q] [-c count] [-r] [device]\n", argv[0]); fprintf(stderr, " -t: show time stamps\n"); fprintf(stderr, " -n: don't print newlines\n"); fprintf(stderr, " -s: print switch states for given bits\n"); fprintf(stderr, " -S: print all switch states\n"); - fprintf(stderr, " -v: verbosity mask (errs=1, dev=2, name=4, info=8, vers=16, pos. events=32)\n"); + fprintf(stderr, " -v: verbosity mask (errs=1, dev=2, name=4, info=8, vers=16, pos. events=32, props=64)\n"); + fprintf(stderr, " -d: show HID descriptor, if available\n"); fprintf(stderr, " -p: show possible events (errs, dev, name, pos. events)\n"); + fprintf(stderr, " -i: show all device info and possible events\n"); + fprintf(stderr, " -l: label event types and names in plain text\n"); fprintf(stderr, " -q: quiet (clear verbosity mask)\n"); fprintf(stderr, " -c: print given number of events then exit\n"); fprintf(stderr, " -r: print rate events are received\n"); @@ -316,7 +499,7 @@ int getevent_main(int argc, char *argv[]) uint16_t get_switch = 0; struct input_event event; int version; - int print_flags = PRINT_DEVICE_ERRORS | PRINT_DEVICE | PRINT_DEVICE_NAME; + int print_flags = 0; int print_flags_set = 0; int dont_block = -1; int event_count = 0; @@ -327,7 +510,7 @@ int getevent_main(int argc, char *argv[]) opterr = 0; do { - c = getopt(argc, argv, "tns:Sv::pqc:rh"); + c = getopt(argc, argv, "tns:Sv::dpilqc:rh"); if (c == EOF) break; switch (c) { @@ -349,19 +532,31 @@ int getevent_main(int argc, char *argv[]) break; case 'v': if(optarg) - print_flags = strtoul(optarg, NULL, 0); + print_flags |= strtoul(optarg, NULL, 0); else print_flags |= PRINT_DEVICE | PRINT_DEVICE_NAME | PRINT_DEVICE_INFO | PRINT_VERSION; print_flags_set = 1; break; + case 'd': + print_flags |= PRINT_HID_DESCRIPTOR; + break; case 'p': - print_flags = PRINT_DEVICE_ERRORS | PRINT_DEVICE | PRINT_DEVICE_NAME | PRINT_POSSIBLE_EVENTS; + print_flags |= PRINT_DEVICE_ERRORS | PRINT_DEVICE + | PRINT_DEVICE_NAME | PRINT_POSSIBLE_EVENTS | PRINT_INPUT_PROPS; + print_flags_set = 1; + if(dont_block == -1) + dont_block = 1; + break; + case 'i': + print_flags |= PRINT_ALL_INFO; print_flags_set = 1; if(dont_block == -1) dont_block = 1; break; + case 'l': + print_flags |= PRINT_LABELS; + break; case 'q': - print_flags = 0; print_flags_set = 1; break; case 'c': @@ -396,13 +591,14 @@ int getevent_main(int argc, char *argv[]) ufds[0].events = POLLIN; if(device) { if(!print_flags_set) - print_flags = PRINT_DEVICE_ERRORS; + print_flags |= PRINT_DEVICE_ERRORS; res = open_device(device, print_flags); if(res < 0) { return 1; } - } - else { + } else { + if(!print_flags_set) + print_flags |= PRINT_DEVICE_ERRORS | PRINT_DEVICE | PRINT_DEVICE_NAME; print_device = 1; res = inotify_add_watch(ufds[0].fd, device_path, IN_DELETE | IN_CREATE); if(res < 0) { @@ -451,7 +647,7 @@ int getevent_main(int argc, char *argv[]) } if(print_device) printf("%s: ", device_names[i]); - printf("%04x %04x %08x", event.type, event.code, event.value); + print_event(event.type, event.code, event.value, print_flags); if(sync_rate && event.type == 0 && event.code == 0) { int64_t now = event.time.tv_sec * 1000000LL + event.time.tv_usec; if(last_sync_time) |