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 * -E pretend to be evdev-manip, print to stderr about the device at start
11 * other some other problem
13 * joystick values are always doubles from -1 to 0 to +1
16 #include "hidrawconv.h"
18 void die_vprintf_hook(const char *fmt, va_list al) { }
19 void die_hook(void) { }
21 static LastReports lasts;
24 /*---------- helpful macros for reporter functions ----------*/
27 * These expect/define:
29 * const uint8_t msg[], last[];
32 * uint8_t mb, lb; // bits from the message, masked but unshifted
41 #define FOR_REPORTENTRIES(ent) \
43 for (; (ent)->str; (ent)++) \
44 if ((ent)->pos >= len) continue; \
47 #define MSG_BITS(ent) (msg[(ent)->pos] & (ent)->mask)
48 #define LAST_BITS(ent) (msg[(ent)->pos] & (ent)->mask)
49 /* uint8_t MSG_BITS(EntType *ent);
50 * uint8_t LAST_BITS(EntType *ent);
53 #define DEFINE_STANDARD_REPORTER(EntType, ent, BODY_BLOCK) \
54 void report##ent##s(const uint8_t msg[], const uint8_t last[], \
55 int len, const EntType *ent) { \
56 FOR_REPORTENTRIES(ent) { \
57 uint8_t mb= MSG_BITS(ent); \
58 uint8_t lb= LAST_BITS(ent); \
59 if (mb==lb) continue; \
65 /*---------- reporter functions ----------*/
67 DEFINE_STANDARD_REPORTER(KeyBit, bit, {
68 printf("%s %d\n", bit->str, !!mb);
71 DEFINE_STANDARD_REPORTER(ValLoc, loc, {
74 double val= (int8_t)mb;
75 val /= (val >= 0 ? 127 : 128);
76 printf("%s %.5f\n", loc->str, loc->sign * val);
80 /*---------- core functions ----------*/
82 void dispatch(LastReports *lasts, const char *message_prefix,
83 ProcessReport *const report_processors[MAXREPORTS],
84 const uint8_t *msg, int l) {
86 fprintf(stderr,"%s:%s report too short\n", progname, message_prefix);
90 ProcessReport *pr= report_processors[msg[0]];
91 Last *last= &lasts->lasts[msg[0]];
94 fprintf(stderr,"%s:%s unexpected report 0x%02x\n",
95 progname, message_prefix, msg[0]);
100 last->msg= mrealloc(last->msg, l);
101 memset(last->msg + last->len, 0, l - last->len);
104 pr(msg, l, last->msg);
105 memcpy(last->msg, msg, l);
108 /*---------- main program ----------*/
110 static void events(int verbose) {
111 uint8_t msg[MAXREPORTLEN+1];
112 char phys[PATH_MAX], name[PATH_MAX];
113 int rphys, errnophys=0, rname, errnoname=0;
116 rphys= ioctl(0, HIDIOCGRAWPHYS(PATH_MAX), phys); errnophys=errno;
117 rname= ioctl(0, HIDIOCGRAWNAME(PATH_MAX), name); errnoname=errno;
118 if (rphys>=0 && rname>=0) {
121 fprintf(stderr,"%s: %.*s %.*s\n",progname,rphys,phys,rname,name);
122 } else if (rphys<0 && errnophys==EINVAL &&
123 rname<0 && errnoname==EINVAL) {
124 fprintf(stderr,"%s: warning, HIDIOCGRAWPHYS/NAME gave EINVAL,"
125 " assuming kernel eats report number, assuming reports are 00\n",
129 die("HIDIOCGRAWPHYS %s / HIDIOCGRAWNAME %s",
130 rphys<0 ? strerror(errnophys) : "ok",
131 rname<0 ? strerror(errnoname) : "ok");
134 if (reportnumbug) msg[0]=0;
137 int l= read(0, msg+reportnumbug, sizeof(msg)-reportnumbug);
139 if (l<0) { perror("hidrawconv: read"); exit(-1); }
141 dispatch(&lasts,"",report_processors, msg,l);
142 if (ferror(stdout) || fflush(stdout))
143 diee("failed flushing event to stdout");
147 int main(int argc, char **argv) {
150 if (!*argv || !(how=*++argv) || *how++!='-' || !*how || how[1] || *++argv)
151 badusage("need exactly one argument, -d, -e or -E");
167 badusage("unknown option/mode");
170 if (ferror(stdout) || fflush(stdout))
171 diee("write/flush stdout");