chiark / gitweb /
hostside/hidrawconv*: tools for converting hidraw according to our own idea of how...
[trains.git] / hostside / hidrawconv.c
1 /*
2  * usage:
3  *   .../hidrawconv-<controller> -d
4  *   .../hidrawconv-<controller> -e </dev/hidrawN
5  * where -a means all, and the other letters are:
6  *   -d   print expected descriptor (as for hidraw-ioctl -d)
7  *   -e   pretend to be evdev-manip
8  * exit status:
9  *   0      all ok
10  *   other  some other problem
11  */
12
13 #include "hidrawconv.h"
14
15 void die_vprintf_hook(const char *fmt, va_list al) { }
16 void die_hook(void) { }
17
18 typedef struct { int len; uint8_t *msg; } Last;
19 static Last lasts[MAXREPORTS];
20
21 void reportbits(const uint8_t msg[], const uint8_t last[],
22                 int len, const KeyBit *bit) {
23   for (; bit->str; bit++) {
24     if (bit->pos >= len) continue;
25     uint8_t m= msg[bit->pos] & bit->mask;
26     uint8_t l= last[bit->pos] & bit->mask;
27     if (m==l) continue;
28     printf("%s %d\n", bit->str, !!m);
29   }
30 }
31
32 void reportlocs(const uint8_t msg[], const uint8_t last[],
33                 int len, const ValLoc *loc) {
34   for (; loc->str; loc++) {
35     if (loc->pos >= len) continue;
36     uint8_t mb= msg[loc->pos] & loc->mask;
37     uint8_t lb= last[loc->pos] & loc->mask;
38     if (mb==lb) continue;
39     mb >>= loc->rshift;
40     mb -= loc->zero;
41     printf("%s %d\n", loc->str, loc->sign * (int8_t)mb);
42   }
43 }
44   
45 static void events(void) {
46   uint8_t msg[MAXREPORTLEN];
47   for (;;) {
48     int l= read(0, msg, sizeof(msg));
49     if (!l) break;
50     if (l<0) { perror("hidrawconv: read"); exit(-1); }
51     ProcessReport *pr= report_processors[msg[0]];
52     Last *last= &lasts[msg[0]];
53     if (!pr) {
54       if (!last->len)
55         fprintf(stderr,"%s: unexpected report 0x%02x", progname, msg[0]);
56       last->len= l;
57       continue;
58     }
59     if (last->len < l) {
60       last->msg= mrealloc(last->msg, l);
61       memset(last->msg + last->len, 0, l - last->len);
62       last->len= l;
63     }
64     pr(msg, l, last->msg);
65     if (ferror(stdout) || fflush(stdout))
66       diee("failed flushing event to stdout");
67     memcpy(last->msg, msg, l);
68   }
69 }
70
71 int main(int argc, char **argv) {
72   const char *how;
73
74   if (!*argv || !(how=*++argv) || *how++!='-' || !*how || how[1] || *++argv)
75     badusage("need exactly one argument, -d or -e");
76
77   switch (how[0]) {
78   case 'd':
79     puts(descriptor);
80     break;
81
82   case 'e':
83     events();
84     break;
85
86   default:
87     badusage("unknown option/mode");
88   }
89
90   if (ferror(stdout) || fflush(stdout))
91     diee("write/flush stdout");
92
93   return 0;
94 }