chiark / gitweb /
hostside: hidrawconv: break out dispatch()
[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  * joystick values are always doubles from -1 to 0 to +1
13  */
14
15 #include "hidrawconv.h"
16
17 void die_vprintf_hook(const char *fmt, va_list al) { }
18 void die_hook(void) { }
19
20 static LastReports lasts;
21
22 void reportbits(const uint8_t msg[], const uint8_t last[],
23                 int len, const KeyBit *bit) {
24   for (; bit->str; bit++) {
25     if (bit->pos >= len) continue;
26     uint8_t m= msg[bit->pos] & bit->mask;
27     uint8_t l= last[bit->pos] & bit->mask;
28     if (m==l) continue;
29     printf("%s %d\n", bit->str, !!m);
30   }
31 }
32
33 void reportlocs(const uint8_t msg[], const uint8_t last[],
34                 int len, const ValLoc *loc) {
35   for (; loc->str; loc++) {
36     if (loc->pos >= len) continue;
37     uint8_t mb= msg[loc->pos] & loc->mask;
38     uint8_t lb= last[loc->pos] & loc->mask;
39     if (mb==lb) continue;
40     mb >>= loc->rshift;
41     mb -= loc->zero;
42     double val= (int8_t)mb;
43     val /= (val >= 0 ? 127 : 128);
44     printf("%s %.5f\n", loc->str, loc->sign * val);
45   }
46 }
47
48 void dispatch(LastReports *lasts, const char *message_prefix,
49               ProcessReport *const report_processors[MAXREPORTS],
50               const uint8_t *msg, int l) {
51   ProcessReport *pr= report_processors[msg[0]];
52   Last *last= &lasts->lasts[msg[0]];
53   if (!pr) {
54     if (!last->len)
55       fprintf(stderr,"%s:%s unexpected report 0x%02x\n",
56               progname, message_prefix, msg[0]);
57     last->len= l;
58     return;
59   }
60   if (last->len < l) {
61     last->msg= mrealloc(last->msg, l);
62     memset(last->msg + last->len, 0, l - last->len);
63     last->len= l;
64   }
65   pr(msg, l, last->msg);
66   memcpy(last->msg, msg, l);
67 }  
68
69 static void events(void) {
70   uint8_t msg[MAXREPORTLEN];
71
72   for (;;) {
73     int l= read(0, msg, sizeof(msg));
74     if (!l) break;
75     if (l<0) { perror("hidrawconv: read"); exit(-1); }
76     dispatch(&lasts,"",report_processors, msg,l);
77     if (ferror(stdout) || fflush(stdout))
78       diee("failed flushing event to stdout");
79   }
80 }
81
82 int main(int argc, char **argv) {
83   const char *how;
84
85   if (!*argv || !(how=*++argv) || *how++!='-' || !*how || how[1] || *++argv)
86     badusage("need exactly one argument, -d or -e");
87
88   switch (how[0]) {
89   case 'd':
90     puts(descriptor);
91     break;
92
93   case 'e':
94     events();
95     break;
96
97   default:
98     badusage("unknown option/mode");
99   }
100
101   if (ferror(stdout) || fflush(stdout))
102     diee("write/flush stdout");
103
104   return 0;
105 }