getevent.c 21 KB

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