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, 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 struct pollfd *new_ufds; 299 char **new_device_names; 300 char name[80]; 301 char location[80]; 302 char idstr[80]; 303 struct input_id id; 304 305 fd = open(device, O_RDWR); 306 if(fd < 0) { 307 if(print_flags & PRINT_DEVICE_ERRORS) 308 fprintf(stderr, "could not open %s, %s\n", device, strerror(errno)); 309 return -1; 310 } 311 312 if(ioctl(fd, EVIOCGVERSION, &version)) { 313 if(print_flags & PRINT_DEVICE_ERRORS) 314 fprintf(stderr, "could not get driver version for %s, %s\n", device, strerror(errno)); 315 return -1; 316 } 317 if(ioctl(fd, EVIOCGID, &id)) { 318 if(print_flags & PRINT_DEVICE_ERRORS) 319 fprintf(stderr, "could not get driver id for %s, %s\n", device, strerror(errno)); 320 return -1; 321 } 322 name[sizeof(name) - 1] = '\0'; 323 location[sizeof(location) - 1] = '\0'; 324 idstr[sizeof(idstr) - 1] = '\0'; 325 if(ioctl(fd, EVIOCGNAME(sizeof(name) - 1), &name) < 1) { 326 //fprintf(stderr, "could not get device name for %s, %s\n", device, strerror(errno)); 327 name[0] = '\0'; 328 } 329 if(ioctl(fd, EVIOCGPHYS(sizeof(location) - 1), &location) < 1) { 330 //fprintf(stderr, "could not get location for %s, %s\n", device, strerror(errno)); 331 location[0] = '\0'; 332 } 333 if(ioctl(fd, EVIOCGUNIQ(sizeof(idstr) - 1), &idstr) < 1) { 334 //fprintf(stderr, "could not get idstring for %s, %s\n", device, strerror(errno)); 335 idstr[0] = '\0'; 336 } 337 338 new_ufds = realloc(ufds, sizeof(ufds[0]) * (nfds + 1)); 339 if(new_ufds == NULL) { 340 fprintf(stderr, "out of memory\n"); 341 return -1; 342 } 343 ufds = new_ufds; 344 new_device_names = realloc(device_names, sizeof(device_names[0]) * (nfds + 1)); 345 if(new_device_names == NULL) { 346 fprintf(stderr, "out of memory\n"); 347 return -1; 348 } 349 device_names = new_device_names; 350 351 if(print_flags & PRINT_DEVICE) 352 printf("add device %d: %s\n", nfds, device); 353 if(print_flags & PRINT_DEVICE_INFO) 354 printf(" bus: %04x\n" 355 " vendor %04x\n" 356 " product %04x\n" 357 " version %04x\n", 358 id.bustype, id.vendor, id.product, id.version); 359 if(print_flags & PRINT_DEVICE_NAME) 360 printf(" name: \"%s\"\n", name); 361 if(print_flags & PRINT_DEVICE_INFO) 362 printf(" location: \"%s\"\n" 363 " id: \"%s\"\n", location, idstr); 364 if(print_flags & PRINT_VERSION) 365 printf(" version: %d.%d.%d\n", 366 version >> 16, (version >> 8) & 0xff, version & 0xff); 367 368 if(print_flags & PRINT_POSSIBLE_EVENTS) { 369 print_possible_events(fd, print_flags); 370 } 371 372 if(print_flags & PRINT_INPUT_PROPS) { 373 print_input_props(fd); 374 } 375 if(print_flags & PRINT_HID_DESCRIPTOR) { 376 print_hid_descriptor(id.bustype, id.vendor, id.product); 377 } 378 379 ufds[nfds].fd = fd; 380 ufds[nfds].events = POLLIN; 381 device_names[nfds] = strdup(device); 382 nfds++; 383 384 return 0; 385 } 386 387 int close_device(const char *device, int print_flags) 388 { 389 int i; 390 for(i = 1; i < nfds; i++) { 391 if(strcmp(device_names[i], device) == 0) { 392 int count = nfds - i - 1; 393 if(print_flags & PRINT_DEVICE) 394 printf("remove device %d: %s\n", i, device); 395 free(device_names[i]); 396 memmove(device_names + i, device_names + i + 1, sizeof(device_names[0]) * count); 397 memmove(ufds + i, ufds + i + 1, sizeof(ufds[0]) * count); 398 nfds--; 399 return 0; 400 } 401 } 402 if(print_flags & PRINT_DEVICE_ERRORS) 403 fprintf(stderr, "remote device: %s not found\n", device); 404 return -1; 405 } 406 407 static int read_notify(const char *dirname, int nfd, int print_flags) 408 { 409 int res; 410 char devname[PATH_MAX]; 411 char *filename; 412 char event_buf[512]; 413 int event_size; 414 int event_pos = 0; 415 struct inotify_event *event; 416 417 res = read(nfd, event_buf, sizeof(event_buf)); 418 if(res < (int)sizeof(*event)) { 419 if(errno == EINTR) 420 return 0; 421 fprintf(stderr, "could not get event, %s\n", strerror(errno)); 422 return 1; 423 } 424 //printf("got %d bytes of event information\n", res); 425 426 strcpy(devname, dirname); 427 filename = devname + strlen(devname); 428 *filename++ = '/'; 429 430 while(res >= (int)sizeof(*event)) { 431 event = (struct inotify_event *)(event_buf + event_pos); 432 //printf("%d: %08x \"%s\"\n", event->wd, event->mask, event->len ? event->name : ""); 433 if(event->len) { 434 strcpy(filename, event->name); 435 if(event->mask & IN_CREATE) { 436 open_device(devname, print_flags); 437 } 438 else { 439 close_device(devname, print_flags); 440 } 441 } 442 event_size = sizeof(*event) + event->len; 443 res -= event_size; 444 event_pos += event_size; 445 } 446 return 0; 447 } 448 449 static int scan_dir(const char *dirname, int print_flags) 450 { 451 char devname[PATH_MAX]; 452 char *filename; 453 DIR *dir; 454 struct dirent *de; 455 dir = opendir(dirname); 456 if(dir == NULL) 457 return -1; 458 strcpy(devname, dirname); 459 filename = devname + strlen(devname); 460 *filename++ = '/'; 461 while((de = readdir(dir))) { 462 if(de->d_name[0] == '.' && 463 (de->d_name[1] == '\0' || 464 (de->d_name[1] == '.' && de->d_name[2] == '\0'))) 465 continue; 466 strcpy(filename, de->d_name); 467 open_device(devname, print_flags); 468 } 469 closedir(dir); 470 return 0; 471 } 472 473 static void usage(int argc, char *argv[]) 474 { 475 fprintf(stderr, "Usage: %s [-t] [-n] [-s switchmask] [-S] [-v [mask]] [-d] [-p] [-i] [-l] [-q] [-c count] [-r] [device]\n", argv[0]); 476 fprintf(stderr, " -t: show time stamps\n"); 477 fprintf(stderr, " -n: don't print newlines\n"); 478 fprintf(stderr, " -s: print switch states for given bits\n"); 479 fprintf(stderr, " -S: print all switch states\n"); 480 fprintf(stderr, " -v: verbosity mask (errs=1, dev=2, name=4, info=8, vers=16, pos. events=32, props=64)\n"); 481 fprintf(stderr, " -d: show HID descriptor, if available\n"); 482 fprintf(stderr, " -p: show possible events (errs, dev, name, pos. events)\n"); 483 fprintf(stderr, " -i: show all device info and possible events\n"); 484 fprintf(stderr, " -l: label event types and names in plain text\n"); 485 fprintf(stderr, " -q: quiet (clear verbosity mask)\n"); 486 fprintf(stderr, " -c: print given number of events then exit\n"); 487 fprintf(stderr, " -r: print rate events are received\n"); 488 } 489 490 int getevent_main(int argc, char *argv[]) 491 { 492 int c; 493 int i; 494 int res; 495 int pollres; 496 int get_time = 0; 497 int print_device = 0; 498 char *newline = "\n"; 499 uint16_t get_switch = 0; 500 struct input_event event; 501 int version; 502 int print_flags = 0; 503 int print_flags_set = 0; 504 int dont_block = -1; 505 int event_count = 0; 506 int sync_rate = 0; 507 int64_t last_sync_time = 0; 508 const char *device = NULL; 509 const char *device_path = "/dev/input"; 510 511 opterr = 0; 512 do { 513 c = getopt(argc, argv, "tns:Sv::dpilqc:rh"); 514 if (c == EOF) 515 break; 516 switch (c) { 517 case 't': 518 get_time = 1; 519 break; 520 case 'n': 521 newline = ""; 522 break; 523 case 's': 524 get_switch = strtoul(optarg, NULL, 0); 525 if(dont_block == -1) 526 dont_block = 1; 527 break; 528 case 'S': 529 get_switch = ~0; 530 if(dont_block == -1) 531 dont_block = 1; 532 break; 533 case 'v': 534 if(optarg) 535 print_flags |= strtoul(optarg, NULL, 0); 536 else 537 print_flags |= PRINT_DEVICE | PRINT_DEVICE_NAME | PRINT_DEVICE_INFO | PRINT_VERSION; 538 print_flags_set = 1; 539 break; 540 case 'd': 541 print_flags |= PRINT_HID_DESCRIPTOR; 542 break; 543 case 'p': 544 print_flags |= PRINT_DEVICE_ERRORS | PRINT_DEVICE 545 | PRINT_DEVICE_NAME | PRINT_POSSIBLE_EVENTS | PRINT_INPUT_PROPS; 546 print_flags_set = 1; 547 if(dont_block == -1) 548 dont_block = 1; 549 break; 550 case 'i': 551 print_flags |= PRINT_ALL_INFO; 552 print_flags_set = 1; 553 if(dont_block == -1) 554 dont_block = 1; 555 break; 556 case 'l': 557 print_flags |= PRINT_LABELS; 558 break; 559 case 'q': 560 print_flags_set = 1; 561 break; 562 case 'c': 563 event_count = atoi(optarg); 564 dont_block = 0; 565 break; 566 case 'r': 567 sync_rate = 1; 568 break; 569 case '?': 570 fprintf(stderr, "%s: invalid option -%c\n", 571 argv[0], optopt); 572 case 'h': 573 usage(argc, argv); 574 exit(1); 575 } 576 } while (1); 577 if(dont_block == -1) 578 dont_block = 0; 579 580 if (optind + 1 == argc) { 581 device = argv[optind]; 582 optind++; 583 } 584 if (optind != argc) { 585 usage(argc, argv); 586 exit(1); 587 } 588 nfds = 1; 589 ufds = calloc(1, sizeof(ufds[0])); 590 ufds[0].fd = inotify_init(); 591 ufds[0].events = POLLIN; 592 if(device) { 593 if(!print_flags_set) 594 print_flags |= PRINT_DEVICE_ERRORS; 595 res = open_device(device, print_flags); 596 if(res < 0) { 597 return 1; 598 } 599 } else { 600 if(!print_flags_set) 601 print_flags |= PRINT_DEVICE_ERRORS | PRINT_DEVICE | PRINT_DEVICE_NAME; 602 print_device = 1; 603 res = inotify_add_watch(ufds[0].fd, device_path, IN_DELETE | IN_CREATE); 604 if(res < 0) { 605 fprintf(stderr, "could not add watch for %s, %s\n", device_path, strerror(errno)); 606 return 1; 607 } 608 res = scan_dir(device_path, print_flags); 609 if(res < 0) { 610 fprintf(stderr, "scan dir failed for %s\n", device_path); 611 return 1; 612 } 613 } 614 615 if(get_switch) { 616 for(i = 1; i < nfds; i++) { 617 uint16_t sw; 618 res = ioctl(ufds[i].fd, EVIOCGSW(1), &sw); 619 if(res < 0) { 620 fprintf(stderr, "could not get switch state, %s\n", strerror(errno)); 621 return 1; 622 } 623 sw &= get_switch; 624 printf("%04x%s", sw, newline); 625 } 626 } 627 628 if(dont_block) 629 return 0; 630 631 while(1) { 632 pollres = poll(ufds, nfds, -1); 633 //printf("poll %d, returned %d\n", nfds, pollres); 634 if(ufds[0].revents & POLLIN) { 635 read_notify(device_path, ufds[0].fd, print_flags); 636 } 637 for(i = 1; i < nfds; i++) { 638 if(ufds[i].revents) { 639 if(ufds[i].revents & POLLIN) { 640 res = read(ufds[i].fd, &event, sizeof(event)); 641 if(res < (int)sizeof(event)) { 642 fprintf(stderr, "could not get event\n"); 643 return 1; 644 } 645 if(get_time) { 646 printf("[%8ld.%06ld] ", event.time.tv_sec, event.time.tv_usec); 647 } 648 if(print_device) 649 printf("%s: ", device_names[i]); 650 print_event(event.type, event.code, event.value, print_flags); 651 if(sync_rate && event.type == 0 && event.code == 0) { 652 int64_t now = event.time.tv_sec * 1000000LL + event.time.tv_usec; 653 if(last_sync_time) 654 printf(" rate %lld", 1000000LL / (now - last_sync_time)); 655 last_sync_time = now; 656 } 657 printf("%s", newline); 658 if(event_count && --event_count == 0) 659 return 0; 660 } 661 } 662 } 663 } 664 665 return 0; 666 } 667