#include #include #include #include #include #include #include #include #include #define DELAY_MS 30 #define DEFAULT_KBD "/dev/input/by-id/usb-Marson_Marson_Keyboard_and_Mouse_Link_Ver:ps2120L-event-kbd" /* eventually, this will take options to set the device and delay for the Enter key, and will have an rc script to start it...? */ const char *self; int debugging = 1; const char *keyboard_dev; /* variadic macros are apparently C99 and not just a GNU extension */ void logmsg(const char *prefix, const char *fmt, ...) { va_list ap; va_start(ap, fmt); fprintf(stderr, "%s: %s: ", self, prefix); vfprintf(stderr, fmt, ap); va_end(ap); fputc('\n', stderr); } #define die(fmt, ...) { logmsg("fatal", fmt, ##__VA_ARGS__); exit(1); }; #define warn(fmt, ...) logmsg("warning", fmt, ##__VA_ARGS__); #define info(fmt, ...) logmsg("info", fmt, ##__VA_ARGS__); #define debug(fmt, ...) { if(debugging) logmsg("debug", fmt, ##__VA_ARGS__); }; void set_self(const char *argv0) { char *p; self = argv0; p = strrchr(self, '/'); if(p) self = p + 1; } int main(int argc, char **argv) { int infd, outfd, i; struct uinput_user_dev dev; struct input_event ev; static struct input_event deferred_ev; set_self(argv[0]); debug("starting up"); if(!keyboard_dev) keyboard_dev = DEFAULT_KBD; if((outfd = open("/dev/uinput", O_WRONLY | O_NONBLOCK)) >= 0) { debug("opened /dev/uinput"); } else { die("failed to open /dev/uinput: %s", strerror(errno)); } if((infd = open(keyboard_dev, O_RDONLY)) >= 0) { debug("opened %s", keyboard_dev); } else { die("failed to open %s: %s", keyboard_dev, strerror(errno)); } if(ioctl(infd, EVIOCGRAB, 1) >= 0) { debug("grabbed %s", keyboard_dev); } else { die("failed to grab %s: %s", keyboard_dev, strerror(errno)); } if(ioctl(outfd, UI_SET_EVBIT, EV_KEY) >= 0) { debug("UI_SET_EVBIT OK"); } else { die("UI_SET_EVBIT failed: %s", strerror(errno)); } for(i = 0; i < KEY_MAX; i++) { if(ioctl(outfd, UI_SET_KEYBIT, i) >= 0) { /* we don't wanna be *that* verbose */ } else { die("UI_SET_EVBIT failed: %s", strerror(errno)); } } memset(&dev, 0, sizeof(dev)); snprintf(dev.name, UINPUT_MAX_NAME_SIZE, "marsond virtual keyboard"); dev.id.bustype == BUS_USB; dev.id.vendor = 1; dev.id.product = 1; dev.id.version = 1; if(write(outfd, &dev, sizeof(dev)) >= 0) { debug("wrote dev structure to /dev/uinput"); } else { die("write to /dev/uinput failed: %s", strerror(errno)); } if(ioctl(outfd, UI_DEV_CREATE) >= 0) { debug("created virtual keyboard device"); } else { die("UI_DEV_CREATE failed: %s", strerror(errno)); } while(1) { if(read(infd, &ev, sizeof(ev)) < 0) { die("read from %s failed: %s", keyboard_dev, strerror(errno)); } debug("event: type %d, code %d, value %d\n", ev.type, ev.code, ev.value); if(ev.type == EV_KEY && ev.code == KEY_ENTER && ev.value == 0) { debug("got Enter key release, delaying %d ms", DELAY_MS); usleep(DELAY_MS * 1000); } if(write(outfd, &ev, sizeof(ev)) < 0) { die("write to /dev/uinput failed: %s", strerror(errno)); } } exit(0); } /* for the A key: event: type 4, code 4, value 458756 event: type 1, code 30, value 1 event: type 0, code 0, value 0 event: type 4, code 4, value 458756 event: type 1, code 30, value 0 event: type 0, code 0, value 0 for Enter: event: type 4, code 4, value 458792 event: type 1, code 28, value 1 event: type 0, code 0, value 0 event: type 4, code 4, value 458792 event: type 1, code 28, value 0 event: type 0, code 0, value 0 */