I’m having some problems getting both sides of code using uinput
working.
Based on Getting started with uinput: the user level input subsystem[dead link; archived] I put together the following writer (minus error handling):
int main(int ac, char **av) { int fd = open("/dev/uinput", O_WRONLY | O_NONBLOCK); int ret = ioctl(fd, UI_SET_EVBIT, EV_ABS); ret = ioctl(fd, UI_SET_ABSBIT, ABS_X); struct uinput_user_dev uidev = {0}; snprintf(uidev.name, UINPUT_MAX_NAME_SIZE, "uinput-rotary"); uidev.absmin[ABS_X] = 0; uidev.absmax[ABS_X] = 255; ret = write(fd, &uidev, sizeof(uidev)); ret = ioctl(fd, UI_DEV_CREATE); struct input_event ev = {0}; ev.type = EV_ABS; ev.code = ABS_X; ev.value = 42; ret = write(fd, &ev, sizeof(ev)); getchar(); ret = ioctl(fd, UI_DEV_DESTROY); return EXIT_SUCCESS; }
That seems to work, at least the full input_event
structure seems to be written.
I then wrote the most naive reader of events I could come up with:
int main(int ac, char **av) { int fd = open(av[1], O_RDONLY); char name[256] = "unknown"; ioctl(fd, EVIOCGNAME(sizeof(name)), name); printf("reading from %sn", name); struct input_event ev = {0}; int ret = read(fd, &ev, sizeof(ev)); printf("Read an event! %in", ret); printf("ev.time.tv_sec: %lin", ev.time.tv_sec); printf("ev.time.tv_usec: %lin", ev.time.tv_usec); printf("ev.type: %hin", ev.type); printf("ev.code: %hin", ev.code); printf("ev.value: %lin", ev.value); return EXIT_SUCCESS; }
Unfortunately the reader side doesn’t work at all; only manages to read 8 bytes each time, which isn’t nearly a full input_event
structure.
What silly mistake am I making?
Advertisement
Answer
You should also be writing a sync event after the actual event. In your writer side code:
struct input_event ev = {0}; ev.type = EV_ABS; ev.code = ABS_X; ev.value = 42; usleep(1500); memset(&ev, 0, sizeof(ev)); ev.type = EV_SYN; ev.code = 0; ev.value = 0; ret = write(fd, &ev, sizeof(ev)); getchar();