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) (last[(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, val, {
75 v /= (v >= 0 ? 127 : 128);
76 printf("%s %.5f\n", val->str, val->sign * v);
79 DEFINE_STANDARD_REPORTER(HatLoc, hat, {
84 /*---------- core functions ----------*/
86 void dispatch(LastReports *lasts, const char *message_prefix,
87 ProcessReport *const report_processors[MAXREPORTS],
88 const uint8_t *msg, int l) {
90 fprintf(stderr,"%s:%s report too short\n", progname, message_prefix);
94 ProcessReport *pr= report_processors[msg[0]];
95 Last *last= &lasts->lasts[msg[0]];
98 fprintf(stderr,"%s:%s unexpected report 0x%02x\n",
99 progname, message_prefix, msg[0]);
104 last->msg= mrealloc(last->msg, l);
105 memset(last->msg + last->len, 0, l - last->len);
108 pr(msg, l, last->msg);
109 memcpy(last->msg, msg, l);
112 /*---------- main program ----------*/
114 static void events(int verbose) {
115 uint8_t msg[MAXREPORTLEN+1];
116 char phys[PATH_MAX], name[PATH_MAX];
117 int rphys, errnophys=0, rname, errnoname=0;
120 rphys= ioctl(0, HIDIOCGRAWPHYS(PATH_MAX), phys); errnophys=errno;
121 rname= ioctl(0, HIDIOCGRAWNAME(PATH_MAX), name); errnoname=errno;
122 if (rphys>=0 && rname>=0) {
125 fprintf(stderr,"%s: %.*s %.*s\n",progname,rphys,phys,rname,name);
126 } else if (rphys<0 && errnophys==EINVAL &&
127 rname<0 && errnoname==EINVAL) {
128 fprintf(stderr,"%s: warning, HIDIOCGRAWPHYS/NAME gave EINVAL,"
129 " assuming kernel eats report number, assuming reports are 00\n",
133 die("HIDIOCGRAWPHYS %s / HIDIOCGRAWNAME %s",
134 rphys<0 ? strerror(errnophys) : "ok",
135 rname<0 ? strerror(errnoname) : "ok");
138 if (reportnumbug) msg[0]=0;
141 int l= read(0, msg+reportnumbug, sizeof(msg)-reportnumbug);
143 if (l<0) { perror("hidrawconv: read"); exit(-1); }
145 dispatch(&lasts,"",report_processors, msg,l);
146 if (ferror(stdout) || fflush(stdout))
147 diee("failed flushing event to stdout");
151 int main(int argc, char **argv) {
154 if (!*argv || !(how=*++argv) || *how++!='-' || !*how || how[1] || *++argv)
155 badusage("need exactly one argument, -d, -e or -E");
171 badusage("unknown option/mode");
174 if (ferror(stdout) || fflush(stdout))
175 diee("write/flush stdout");