1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <string.h> 4 #include <stdint.h> 5 #include <dirent.h> 6 #include <fcntl.h> 7 #include <sys/ioctl.h> 8 #include <sys/inotify.h> 9 #include <sys/limits.h> 10 #include <sys/poll.h> 11 #include <linux/input.h> 12 #include <err.h> 13 #include <errno.h> 14 #include <unistd.h> 15 16 struct label { 17 const char *name; 18 int value; 19 }; 20 21 #define LABEL(constant) { #constant, constant } 22 #define LABEL_END { NULL, -1 } 23 24 static struct label key_value_labels[] = { 25 { "UP", 0 }, 26 { "DOWN", 1 }, 27 { "REPEAT", 2 }, 28 LABEL_END, 29 }; 30 31 #include "input.h-labels.h" 32 33 #undef LABEL 34 #undef LABEL_END 35 36 static struct pollfd *ufds; 37 static char **device_names; 38 static int nfds; 39 40 enum { 41 PRINT_DEVICE_ERRORS = 1U << 0, 42 PRINT_DEVICE = 1U << 1, 43 PRINT_DEVICE_NAME = 1U << 2, 44 PRINT_DEVICE_INFO = 1U << 3, 45 PRINT_VERSION = 1U << 4, 46 PRINT_POSSIBLE_EVENTS = 1U << 5, 47 PRINT_INPUT_PROPS = 1U << 6, 48 PRINT_HID_DESCRIPTOR = 1U << 7, 49 50 PRINT_ALL_INFO = (1U << 8) - 1, 51 52 PRINT_LABELS = 1U << 16, 53 }; 54 55 static const char *get_label(const struct label *labels, int value) 56 { 57 while(labels->name && value != labels->value) { 58 labels++; 59 } 60 return labels->name; 61 } 62 63 static int print_input_props(int fd) 64 { 65 uint8_t bits[INPUT_PROP_CNT / 8]; 66 int i, j; 67 int res; 68 int count; 69 const char *bit_label; 70 71 printf(" input props:\n"); 72 res = ioctl(fd, EVIOCGPROP(sizeof(bits)), bits); 73 if(res < 0) { 74 printf(" <not available\n"); 75 return 1; 76 } 77 count = 0; 78 for(i = 0; i < res; i++) { 79 for(j = 0; j < 8; j++) { 80 if (bits[i] & 1 << j) { 81 bit_label = get_label(input_prop_labels, i * 8 + j); 82 if(bit_label) 83 printf(" %s\n", bit_label); 84 else 85 printf(" %04x\n", i * 8 + j); 86 count++; 87 } 88 } 89 } 90 if (!count) 91 printf(" <none>\n"); 92 return 0; 93 } 94 95 static int print_possible_events(int fd, int print_flags) 96 { 97 uint8_t *bits = NULL; 98 ssize_t bits_size = 0; 99 const char* label; 100 int i, j, k; 101 int res, res2; 102 struct label* bit_labels; 103 const char *bit_label; 104 105 printf(" events:\n"); 106 for(i = EV_KEY; i <= EV_MAX; i++) { // skip EV_SYN since we cannot query its available codes 107 int count = 0; 108 while(1) { 109 res = ioctl(fd, EVIOCGBIT(i, bits_size), bits); 110 if(res < bits_size) 111 break; 112 bits_size = res + 16; 113 bits = realloc(bits, bits_size * 2); 114 if(bits == NULL) 115 err(1, "failed to allocate buffer of size %d\n", (int)bits_size); 116 } 117 res2 = 0; 118 switch(i) { 119 case EV_KEY: 120 res2 = ioctl(fd, EVIOCGKEY(res), bits + bits_size); 121 label = "KEY"; 122 bit_labels = key_labels; 123 break; 124 case EV_REL: 125 label = "REL"; 126 bit_labels = rel_labels; 127 break; 128 case EV_ABS: 129 label = "ABS"; 130 bit_labels = abs_labels; 131 break; 132 case EV_MSC: 133 label = "MSC"; 134 bit_labels = msc_labels; 135 break; 136 case EV_LED: 137 res2 = ioctl(fd, EVIOCGLED(res), bits + bits_size); 138 label = "LED"; 139 bit_labels = led_labels; 140 break; 141 case EV_SND: 142 res2 = ioctl(fd, EVIOCGSND(res), bits + bits_size); 143 label = "SND"; 144 bit_labels = snd_labels; 145 break; 146 case EV_SW: 147 res2 = ioctl(fd, EVIOCGSW(bits_size), bits + bits_size); 148 label = "SW "; 149 bit_labels = sw_labels; 150 break; 151 case EV_REP: 152 label = "REP"; 153 bit_labels = rep_labels; 154 break; 155 case EV_FF: 156 label = "FF "; 157 bit_labels = ff_labels; 158 break; 159 case EV_PWR: 160 label = "PWR"; 161 bit_labels = NULL; 162 break; 163 case EV_FF_STATUS: 164 label = "FFS"; 165 bit_labels = ff_status_labels; 166 break; 167 default: 168 res2 = 0; 169 label = "???"; 170 bit_labels = NULL; 171 } 172 for(j = 0; j < res; j++) { 173 for(k = 0; k < 8; k++) 174 if(bits[j] & 1 << k) { 175 char down; 176 if(j < res2 && (bits[j + bits_size] & 1 << k)) 177 down = '*'; 178 else 179 down = ' '; 180 if(count == 0) 181 printf(" %s (%04x):", label, i); 182 else if((count & (print_flags & PRINT_LABELS ? 0x3 : 0x7)) == 0 || i == EV_ABS) 183 printf("\n "); 184 if(bit_labels && (print_flags & PRINT_LABELS)) { 185 bit_label = get_label(bit_labels, j * 8 + k); 186 if(bit_label) 187 printf(" %.20s%c%*s", bit_label, down, (int) (20 - strlen(bit_label)), ""); 188 else 189 printf(" %04x%c ", j * 8 + k, down); 190 } else { 191 printf(" %04x%c", j * 8 + k, down); 192 } 193 if(i == EV_ABS) { 194 struct input_absinfo abs; 195 if(ioctl(fd, EVIOCGABS(j * 8 + k), &abs) == 0) { 196 printf(" : value %d, min %d, max %d, fuzz %d, flat %d, resolution %d", 197 abs.value, abs.minimum, abs.maximum, abs.fuzz, abs.flat, 198 abs.resolution); 199 } 200 } 201 count++; 202 } 203 } 204 if(count) 205 printf("\n"); 206 } 207 free(bits); 208 return 0; 209 } 210 211 static void print_event(int type, int code, int value, int print_flags) 212 { 213 const char *type_label, *code_label, *value_label; 214 215 if (print_flags & PRINT_LABELS) { 216 type_label = get_label(ev_labels, type); 217 code_label = NULL; 218 value_label = NULL; 219 220 switch(type) { 221 case EV_SYN: 222 code_label = get_label(syn_labels, code); 223 break; 224 case EV_KEY: 225 code_label = get_label(key_labels, code); 226 value_label = get_label(key_value_labels, value); 227 break; 228 case EV_REL: 229 code_label = get_label(rel_labels, code); 230 break; 231 case EV_ABS: 232 code_label = get_label(abs_labels, code); 233 switch(code) { 234 case ABS_MT_TOOL_TYPE: 235 value_label = get_label(mt_tool_labels, value); 236 } 237 break; 238 case EV_MSC: 239 code_label = get_label(msc_labels, code); 240 break; 241 case EV_LED: 242 code_label = get_label(led_labels, code); 243 break; 244 case EV_SND: 245 code_label = get_label(snd_labels, code); 246 break; 247 case EV_SW: 248 code_label = get_label(sw_labels, code); 249 break; 250 case EV_REP: 251 code_label = get_label(rep_labels, code); 252 break; 253 case EV_FF: 254 code_label = get_label(ff_labels, code); 255 break; 256 case EV_FF_STATUS: 257 code_label = get_label(ff_status_labels, code); 258 break; 259 } 260 261 if (type_label) 262 printf("%-12.12s", type_label); 263 else 264 printf("%04x ", type); 265 if (code_label) 266 printf(" %-20.20s", code_label); 267 else 268 printf(" %04x ", code); 269 if (value_label) 270 printf(" %-20.20s", value_label); 271 else 272 printf(" %08x ", value); 273 } else { 274 printf("%04x %04x %08x", type, code, value); 275 } 276 } 277 278 static void print_hid_descriptor(int bus, int vendor, int product) 279 { 280 const char *dirname = "/sys/kernel/debug/hid"; 281 char prefix[16]; 282 DIR *dir; 283 struct dirent *de; 284 char filename[PATH_MAX]; 285 FILE *file; 286 char line[2048]; 287 288 snprintf(prefix, sizeof(prefix), "%04X:%04X:%04X.", bus, vendor, product); 289 290 dir = opendir(dirname); 291 if(dir == NULL) 292 return; 293 while((de = readdir(dir))) { 294 if (strstr(de->d_name, prefix) == de->d_name) { 295 snprintf(filename, sizeof(filename), "%s/%s/rdesc", dirname, de->d_name); 296 297 file = fopen(filename, "r"); 298 if (file) { 299 printf(" HID descriptor: %s\n\n", de->d_name); 300 while (fgets(line, sizeof(line), file)) { 301 fputs(" ", stdout); 302 fputs(line, stdout); 303 } 304 fclose(file); 305 puts(""); 306 } 307 } 308 } 309 closedir(dir); 310 } 311 312 static int open_device(const char *device, int print_flags) 313 { 314 int version; 315 int fd; 316 int clkid = CLOCK_MONOTONIC; 317 struct pollfd *new_ufds; 318 char **new_device_names; 319 char name[80]; 320 char location[80]; 321 char idstr[80]; 322 struct input_id id; 323 324 fd = open(device, O_RDWR); 325 if(fd < 0) { 326 if(print_flags & PRINT_DEVICE_ERRORS) 327 fprintf(stderr, "could not open %s, %s\n", device, strerror(errno)); 328 return -1; 329 } 330 331 if(ioctl(fd, EVIOCGVERSION, &version)) { 332 if(print_flags & PRINT_DEVICE_ERRORS) 333 fprintf(stderr, "could not get driver version for %s, %s\n", device, strerror(errno)); 334 return -1; 335 } 336 if(ioctl(fd, EVIOCGID, &id)) { 337 if(print_flags & PRINT_DEVICE_ERRORS) 338 fprintf(stderr, "could not get driver id for %s, %s\n", device, strerror(errno)); 339 return -1; 340 } 341 name[sizeof(name) - 1] = '\0'; 342 location[sizeof(location) - 1] = '\0'; 343 idstr[sizeof(idstr) - 1] = '\0'; 344 if(ioctl(fd, EVIOCGNAME(sizeof(name) - 1), &name) < 1) { 345 //fprintf(stderr, "could not get device name for %s, %s\n", device, strerror(errno)); 346 name[0] = '\0'; 347 } 348 if(ioctl(fd, EVIOCGPHYS(sizeof(location) - 1), &location) < 1) { 349 //fprintf(stderr, "could not get location for %s, %s\n", device, strerror(errno)); 350 location[0] = '\0'; 351 } 352 if(ioctl(fd, EVIOCGUNIQ(sizeof(idstr) - 1), &idstr) < 1) { 353 //fprintf(stderr, "could not get idstring for %s, %s\n", device, strerror(errno)); 354 idstr[0] = '\0'; 355 } 356 357 if (ioctl(fd, EVIOCSCLOCKID, &clkid) != 0) { 358 fprintf(stderr, "Can't enable monotonic clock reporting: %s\n", strerror(errno)); 359 // a non-fatal error 360 } 361 362 new_ufds = realloc(ufds, sizeof(ufds[0]) * (nfds + 1)); 363 if(new_ufds == NULL) { 364 fprintf(stderr, "out of memory\n"); 365 return -1; 366 } 367 ufds = new_ufds; 368 new_device_names = realloc(device_names, sizeof(device_names[0]) * (nfds + 1)); 369 if(new_device_names == NULL) { 370 fprintf(stderr, "out of memory\n"); 371 return -1; 372 } 373 device_names = new_device_names; 374 375 if(print_flags & PRINT_DEVICE) 376 printf("add device %d: %s\n", nfds, device); 377 if(print_flags & PRINT_DEVICE_INFO) 378 printf(" bus: %04x\n" 379 " vendor %04x\n" 380 " product %04x\n" 381 " version %04x\n", 382 id.bustype, id.vendor, id.product, id.version); 383 if(print_flags & PRINT_DEVICE_NAME) 384 printf(" name: \"%s\"\n", name); 385 if(print_flags & PRINT_DEVICE_INFO) 386 printf(" location: \"%s\"\n" 387 " id: \"%s\"\n", location, idstr); 388 if(print_flags & PRINT_VERSION) 389 printf(" version: %d.%d.%d\n", 390 version >> 16, (version >> 8) & 0xff, version & 0xff); 391 392 if(print_flags & PRINT_POSSIBLE_EVENTS) { 393 print_possible_events(fd, print_flags); 394 } 395 396 if(print_flags & PRINT_INPUT_PROPS) { 397 print_input_props(fd); 398 } 399 if(print_flags & PRINT_HID_DESCRIPTOR) { 400 print_hid_descriptor(id.bustype, id.vendor, id.product); 401 } 402 403 ufds[nfds].fd = fd; 404 ufds[nfds].events = POLLIN; 405 device_names[nfds] = strdup(device); 406 nfds++; 407 408 return 0; 409 } 410 411 int close_device(const char *device, int print_flags) 412 { 413 int i; 414 for(i = 1; i < nfds; i++) { 415 if(strcmp(device_names[i], device) == 0) { 416 int count = nfds - i - 1; 417 if(print_flags & PRINT_DEVICE) 418 printf("remove device %d: %s\n", i, device); 419 free(device_names[i]); 420 memmove(device_names + i, device_names + i + 1, sizeof(device_names[0]) * count); 421 memmove(ufds + i, ufds + i + 1, sizeof(ufds[0]) * count); 422 nfds--; 423 return 0; 424 } 425 } 426 if(print_flags & PRINT_DEVICE_ERRORS) 427 fprintf(stderr, "remote device: %s not found\n", device); 428 return -1; 429 } 430 431 static int read_notify(const char *dirname, int nfd, int print_flags) 432 { 433 int res; 434 char devname[PATH_MAX]; 435 char *filename; 436 char event_buf[512]; 437 int event_size; 438 int event_pos = 0; 439 struct inotify_event *event; 440 441 res = read(nfd, event_buf, sizeof(event_buf)); 442 if(res < (int)sizeof(*event)) { 443 if(errno == EINTR) 444 return 0; 445 fprintf(stderr, "could not get event, %s\n", strerror(errno)); 446 return 1; 447 } 448 //printf("got %d bytes of event information\n", res); 449 450 strcpy(devname, dirname); 451 filename = devname + strlen(devname); 452 *filename++ = '/'; 453 454 while(res >= (int)sizeof(*event)) { 455 event = (struct inotify_event *)(event_buf + event_pos); 456 //printf("%d: %08x \"%s\"\n", event->wd, event->mask, event->len ? event->name : ""); 457 if(event->len) { 458 strcpy(filename, event->name); 459 if(event->mask & IN_CREATE) { 460 open_device(devname, print_flags); 461 } 462 else { 463 close_device(devname, print_flags); 464 } 465 } 466 event_size = sizeof(*event) + event->len; 467 res -= event_size; 468 event_pos += event_size; 469 } 470 return 0; 471 } 472 473 static int scan_dir(const char *dirname, int print_flags) 474 { 475 char devname[PATH_MAX]; 476 char *filename; 477 DIR *dir; 478 struct dirent *de; 479 dir = opendir(dirname); 480 if(dir == NULL) 481 return -1; 482 strcpy(devname, dirname); 483 filename = devname + strlen(devname); 484 *filename++ = '/'; 485 while((de = readdir(dir))) { 486 if(de->d_name[0] == '.' && 487 (de->d_name[1] == '\0' || 488 (de->d_name[1] == '.' && de->d_name[2] == '\0'))) 489 continue; 490 strcpy(filename, de->d_name); 491 open_device(devname, print_flags); 492 } 493 closedir(dir); 494 return 0; 495 } 496 497 static void usage(char *name) 498 { 499 fprintf(stderr, "Usage: %s [-t] [-n] [-s switchmask] [-S] [-v [mask]] [-d] [-p] [-i] [-l] [-q] [-c count] [-r] [device]\n", name); 500 fprintf(stderr, " -t: show time stamps\n"); 501 fprintf(stderr, " -n: don't print newlines\n"); 502 fprintf(stderr, " -s: print switch states for given bits\n"); 503 fprintf(stderr, " -S: print all switch states\n"); 504 fprintf(stderr, " -v: verbosity mask (errs=1, dev=2, name=4, info=8, vers=16, pos. events=32, props=64)\n"); 505 fprintf(stderr, " -d: show HID descriptor, if available\n"); 506 fprintf(stderr, " -p: show possible events (errs, dev, name, pos. events)\n"); 507 fprintf(stderr, " -i: show all device info and possible events\n"); 508 fprintf(stderr, " -l: label event types and names in plain text\n"); 509 fprintf(stderr, " -q: quiet (clear verbosity mask)\n"); 510 fprintf(stderr, " -c: print given number of events then exit\n"); 511 fprintf(stderr, " -r: print rate events are received\n"); 512 } 513 514 int getevent_main(int argc, char *argv[]) 515 { 516 int c; 517 int i; 518 int res; 519 int get_time = 0; 520 int print_device = 0; 521 char *newline = "\n"; 522 uint16_t get_switch = 0; 523 struct input_event event; 524 int print_flags = 0; 525 int print_flags_set = 0; 526 int dont_block = -1; 527 int event_count = 0; 528 int sync_rate = 0; 529 int64_t last_sync_time = 0; 530 const char *device = NULL; 531 const char *device_path = "/dev/input"; 532 533 opterr = 0; 534 do { 535 c = getopt(argc, argv, "tns:Sv::dpilqc:rh"); 536 if (c == EOF) 537 break; 538 switch (c) { 539 case 't': 540 get_time = 1; 541 break; 542 case 'n': 543 newline = ""; 544 break; 545 case 's': 546 get_switch = strtoul(optarg, NULL, 0); 547 if(dont_block == -1) 548 dont_block = 1; 549 break; 550 case 'S': 551 get_switch = ~0; 552 if(dont_block == -1) 553 dont_block = 1; 554 break; 555 case 'v': 556 if(optarg) 557 print_flags |= strtoul(optarg, NULL, 0); 558 else 559 print_flags |= PRINT_DEVICE | PRINT_DEVICE_NAME | PRINT_DEVICE_INFO | PRINT_VERSION; 560 print_flags_set = 1; 561 break; 562 case 'd': 563 print_flags |= PRINT_HID_DESCRIPTOR; 564 break; 565 case 'p': 566 print_flags |= PRINT_DEVICE_ERRORS | PRINT_DEVICE 567 | PRINT_DEVICE_NAME | PRINT_POSSIBLE_EVENTS | PRINT_INPUT_PROPS; 568 print_flags_set = 1; 569 if(dont_block == -1) 570 dont_block = 1; 571 break; 572 case 'i': 573 print_flags |= PRINT_ALL_INFO; 574 print_flags_set = 1; 575 if(dont_block == -1) 576 dont_block = 1; 577 break; 578 case 'l': 579 print_flags |= PRINT_LABELS; 580 break; 581 case 'q': 582 print_flags_set = 1; 583 break; 584 case 'c': 585 event_count = atoi(optarg); 586 dont_block = 0; 587 break; 588 case 'r': 589 sync_rate = 1; 590 break; 591 case '?': 592 fprintf(stderr, "%s: invalid option -%c\n", 593 argv[0], optopt); 594 case 'h': 595 usage(argv[0]); 596 exit(1); 597 } 598 } while (1); 599 if(dont_block == -1) 600 dont_block = 0; 601 602 if (optind + 1 == argc) { 603 device = argv[optind]; 604 optind++; 605 } 606 if (optind != argc) { 607 usage(argv[0]); 608 exit(1); 609 } 610 nfds = 1; 611 ufds = calloc(1, sizeof(ufds[0])); 612 ufds[0].fd = inotify_init(); 613 ufds[0].events = POLLIN; 614 if(device) { 615 if(!print_flags_set) 616 print_flags |= PRINT_DEVICE_ERRORS; 617 res = open_device(device, print_flags); 618 if(res < 0) { 619 return 1; 620 } 621 } else { 622 if(!print_flags_set) 623 print_flags |= PRINT_DEVICE_ERRORS | PRINT_DEVICE | PRINT_DEVICE_NAME; 624 print_device = 1; 625 res = inotify_add_watch(ufds[0].fd, device_path, IN_DELETE | IN_CREATE); 626 if(res < 0) { 627 fprintf(stderr, "could not add watch for %s, %s\n", device_path, strerror(errno)); 628 return 1; 629 } 630 res = scan_dir(device_path, print_flags); 631 if(res < 0) { 632 fprintf(stderr, "scan dir failed for %s\n", device_path); 633 return 1; 634 } 635 } 636 637 if(get_switch) { 638 for(i = 1; i < nfds; i++) { 639 uint16_t sw; 640 res = ioctl(ufds[i].fd, EVIOCGSW(1), &sw); 641 if(res < 0) { 642 fprintf(stderr, "could not get switch state, %s\n", strerror(errno)); 643 return 1; 644 } 645 sw &= get_switch; 646 printf("%04x%s", sw, newline); 647 } 648 } 649 650 if(dont_block) 651 return 0; 652 653 while(1) { 654 //int pollres = 655 poll(ufds, nfds, -1); 656 //printf("poll %d, returned %d\n", nfds, pollres); 657 if(ufds[0].revents & POLLIN) { 658 read_notify(device_path, ufds[0].fd, print_flags); 659 } 660 for(i = 1; i < nfds; i++) { 661 if(ufds[i].revents) { 662 if(ufds[i].revents & POLLIN) { 663 res = read(ufds[i].fd, &event, sizeof(event)); 664 if(res < (int)sizeof(event)) { 665 fprintf(stderr, "could not get event\n"); 666 return 1; 667 } 668 if(get_time) { 669 printf("[%8ld.%06ld] ", event.time.tv_sec, event.time.tv_usec); 670 } 671 if(print_device) 672 printf("%s: ", device_names[i]); 673 print_event(event.type, event.code, event.value, print_flags); 674 if(sync_rate && event.type == 0 && event.code == 0) { 675 int64_t now = event.time.tv_sec * 1000000LL + event.time.tv_usec; 676 if(last_sync_time) 677 printf(" rate %lld", 1000000LL / (now - last_sync_time)); 678 last_sync_time = now; 679 } 680 printf("%s", newline); 681 if(event_count && --event_count == 0) 682 return 0; 683 } 684 } 685 } 686 } 687 688 return 0; 689 } 690