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