]> mj.ucw.cz Git - misc.git/blob - spy/keyspy.c
Merge branch 'master' of git+ssh://git.ucw.cz/home/mj/GIT/misc
[misc.git] / spy / keyspy.c
1 #include <stdio.h>
2 #include <stdarg.h>
3 #include <stdlib.h>
4 #include <string.h>
5 #include <fcntl.h>
6 #include <unistd.h>
7 #include <inttypes.h>
8 #include <sys/time.h>
9 #include <linux/input.h>
10
11 struct spy_event {
12   uint16_t delta_ms;
13   uint16_t key;                 // bit 15: 0=press, 1=release
14 };
15
16 static void __attribute__((noreturn)) __attribute__((format(printf,1,2))) die(char *fmt, ...)
17 {
18   va_list args;
19   va_start(args, fmt);
20   fprintf(stderr, "keyspy: ");
21   vfprintf(stderr, fmt, args);
22   exit(1);
23 }
24
25 static void record(char *logname)
26 {
27   int evfd = open("/dev/input/by-path/platform-i8042-serio-0-event-kbd", O_RDONLY);
28   if (evfd < 0)
29     die("Cannot open event device: %m\n");
30
31   int spyfd = open(logname, O_WRONLY | O_CREAT | O_APPEND, 0600);
32   if (spyfd < 0)
33     die("Cannot open spy log %s: %m\n", logname);
34
35   int64_t last_t = 0;
36   for (;;)
37     {
38       struct input_event ev;
39       if (read(evfd, &ev, sizeof(ev)) != sizeof(ev))
40         die("Error reading event device: %m\n");
41       // printf("type=%04x code=%04x value=%08x\n", ev.type, ev.code, ev.value);
42       if (ev.type == EV_KEY)
43         {
44           struct spy_event se;
45           int64_t t = (uint64_t) ev.time.tv_sec * 1000 + ev.time.tv_usec / 1000;
46           int64_t dt = t - last_t;
47           if (dt < 0)
48             dt = 0;
49           else if (dt > 0xffff)
50             dt = 0xffff;
51           last_t = t;
52           se.delta_ms = dt;
53           se.key = (ev.code < 0x8000 ? ev.code : 0x7fff);
54           if (!ev.value)
55             se.key |= 0x8000;
56           if (write(spyfd, &se, sizeof(se)) != sizeof(se))
57             die("Error writing spy log: %m\n");
58         }
59     }
60 }
61
62 const char *key_names[] = {
63 #include "keytab.h"
64 };
65
66 static void show(char *logname)
67 {
68   FILE *f = fopen(logname, "r");
69   if (!f)
70     die("Cannot read log: %m\n");
71   struct spy_event se;
72   while (fread(&se, sizeof(se), 1, f))
73     {
74       if (se.delta_ms == 0xffff)
75         printf("----- ");
76       else
77         printf("%5d ", se.delta_ms);
78       printf("%c ", (se.key & 0x8000 ? '-' : '+'));
79       unsigned k = se.key & 0x7fff;
80       if (k < sizeof(key_names) / sizeof(key_names[0]) && key_names[k])
81         printf("%s\n", key_names[k]);
82       else
83         printf("#%04x\n", k);
84     }
85 }
86
87 static void usage(void)
88 {
89   fprintf(stderr, "\
90 Usage: keyspy record <logfile>\n\
91    or: keyspy show <logfile>\n\
92 ");
93   exit(1);
94 }
95
96 int main(int argc, char **argv)
97 {
98   if (argc != 3)
99     usage();
100   if (!strcmp(argv[1], "record"))
101     record(argv[2]);
102   else if (!strcmp(argv[1], "show"))
103     show(argv[2]);
104   else
105     usage();
106 }