--- /dev/null
+/*
+ * evdev-manip [<options> <device> ...]
+ * options:
+ * --dump default
+ * --[no-]grab --nograb is default
+ */
+
+#include <input.h>
+
+#include "common.h"
+
+typedef struct {
+ void (*onevent)();
+ void (*mainloop)();
+} ModeInfo;
+
+typedef const ModeInfo *Mode;
+
+typedef struct {
+ char *path;
+ int fd;
+} Device;
+
+static int ndevices;
+static Device *devices;
+
+static Mode mode;
+static int grab;
+
+static void mode_dump(void) {
+}
+
+static void process_device(Device *d) {
+ struct input_event ie;
+ int r, remain;
+ char *p;
+
+ printf("event-group-start device %s\n",d->path);
+
+ for (;;) {
+ for (p=&ie, remain=sizeof(ie);
+ remain;
+ p+=r, remain-=r) {
+ r= read(d->fd, &ie, remain);
+ if (r<0) {
+ if (errno==EINTR) continue;
+ diee("%s: error reading", d->path);
+ }
+ if (r==0)
+ die("%s: eof ?!", d->path);
+ assert(r <= remain);
+ }
+ if (ie.type == EV_SYN) {
+ printf("synchronised %ju.%06d\n",
+ (uintmax_t)ie.time.tv_sec,
+ (int)ie.time_tv_usec);
+ break;
+ }
+
+}
+
+static void mainloop(void) {
+ struct pollfd *polls;
+
+ polls= mmalloc(sizeof(*polls)*ndevices);
+ for (i=0; i<ndevices; i++) {
+ polls[i].fd= devices[i].fd;
+ polls[i].events= POLLIN;
+ }
+
+ for (;;) {
+ for (i=0; i<ndevices; i++)
+ polls[i].revents= 0;
+
+ r= poll(&polls,ndevices,-1);
+ if (r==-1) {
+ if (errno==EINTR) continue;
+ diee("poll failed");
+ }
+ assert(r>0);
+
+ for (i=0; i<ndevices; i++) {
+ if (polls[i].revent & ~POLLIN)
+ die("device %s (fd %d) gave unexpected poll revent %#x",
+ devices[i].path, devices[i].fd, polls[i].revent);
+ if (polls[i].revent)
+ process_device(&devices[i]);
+ }
+ }
+}
+
+static void getdevice(const char *path) {
+ int r;
+ struct input_id iid;
+ Device *d;
+ ndevices++;
+ devices= mrealloc(devices, sizeof(*devices)*ndevices);
+ d= &devices[ndevices-1];
+
+ d->path= mstrdup(path);
+ d->fd= open(path, O_RDONLY); if (d->fd<0) diee("%s: failed to open",path);
+
+ r= ioctl(d->fd, EVIOCGID, &iid); if (r) diee("%s: failed to get id",path);
+ printf("device %s bustype %#x vendor %#x product #%x version %#x\n"
+ path, iid.bustype, iid.vendor, iid.product, iid.version);
+ mflushstdout();
+
+ if (grab)
+ r= ioctl(d->fd, EVIOCGRAB, 1); if (r) diee("%s: failed to grab",path);
+}
+
+int main(int argc, const char **argv) {
+ const char *arg;
+
+ while ((arg= *++argv)) {
+ if (arg[0] != '-') {
+ getdevice(arg);
+ }
+ else if (!strcmp(arg,"--dump")) { mode= mode_dump; }
+ else if (!strcmp(arg,"--grab")) { grab= 1; }
+ else if (!strcmp(arg,"--no-grab")) { grab= 0; }
+ else badusage("unknown option `%s'",arg);
+ }
+ mode->mainloop();
+ return 0;
+}
--- /dev/null
+#!/usr/bin/perl -w
+
+use strict 'vars';
+
+# "/usr/include/linux/input.h
+
+our (%strs, %checkunique);
+
+sub strs ($) {
+ my ($t) = @_;
+ $strs{$t}= [ ];
+}
+sub evtype ($) {
+ my ($t) = @_;
+ strs($t);
+}
+
+our ($t);
+foreach $t (qw(EV BUS)) {
+ strs($t);
+}
+foreach $t (qw(KEY REL ABS MSC LED)) {
+ evtype($t);
+}
+$strs{'BTN'}= $strs{'KEY'};
+
+our ($tab,$str,$val);
+
+while (<>) {
+ if (m/^\#define (\w+)_(\w+)\s+(0|[1-9]\d+|0x[0-9a-f]+)\s*$/) {
+ ($tab,$str,$val)=($1,$2, eval $3);
+ next if "${tab}_${str}" =~
+ m/^BTN_(?:MISC|MOUSE|JOYSTICK|GAMEPAD|DIGI)$|^EV_VERSION$/;
+ next if $str eq 'MAX';
+ if (exists($strs{$tab})) {
+ die "$tab $str $val" if defined $strs{$tab}[$val];
+ $strs{$tab}[$val]= $str;
+ }
+ die "$tab $str $val" if $checkunique{$tab}{$str}++;
+ }
+}
+
+our ($s,$i);
+
+for $t (sort keys %strs) {
+ printf "static const char *iesis_%s[]= {\n", lc $t
+ or die $!;
+ $s= $strs{$t};
+ for ($i=0; $i<@$s; $i++) {
+ printf " %s,\n", (defined $s->[$i] ? "\"$s->[$i]\"" : "0")
+ or die $!;
+ }
+ printf "};\n"
+ or die $!;
+}