I am actually trying to write a small program to catch global keyboard inputs from specific USB keyboards under linux.
I am testing with this piece of code :
#include <stdlib.h> #include <unistd.h> #include <fcntl.h> #include <errno.h> #include <linux/input.h> #include <string.h> #include <stdio.h> static const char *const evval[3] = { "RELEASED", "PRESSED ", "REPEATED" }; int main(void) { const char *dev = "/dev/input/event2"; struct input_event ev; ssize_t n; int fd; char name[256]= "Unknown"; // int codes[2]; // codes[0] = 58; /* M keycap */ // codes[1] = 49; /* assign to N */ fd = open(dev, O_RDONLY); if (fd == -1) { fprintf(stderr, "Cannot open %s: %s.n", dev, strerror(errno)); return EXIT_FAILURE; } if(ioctl(fd, EVIOCGNAME(sizeof(name)), name) > 0) { printf("The device on %s says its name is '%s'n", dev, name); } /* int err = ioctl(fd, EVIOCSKEYCODE, codes); if (err) { perror("evdev ioctl"); }*/ while (1) { n = read(fd, &ev, sizeof ev); if (n == (ssize_t)-1) { if (errno == EINTR) continue; else break; } else if (n != sizeof ev) { errno = EIO; break; } if (ev.type == EV_KEY && ev.value >= 0 && ev.value <= 2) printf("%s 0x%04x (%d)n", evval[ev.value], (int)ev.code, (int)ev.code); } fflush(stdout); fprintf(stderr, "%s.n", strerror(errno)); return EXIT_FAILURE; }
Ths point is that I don’t know how to change some input key by other. I tried by calling write() on currently red event by changing the event code, sent key was still previous one, and I tried to used ioctl with EVIOCSKEYCODE, but the call failed with an “invalid argument” error (and I’m not sure to call it correctly).
How can I change outputed key correctly ?
Advertisement
Answer
Use the EVIOCGRAB ioctl to grab the input device, so that by reading the events you consume them. Normally (not-grabbed) the events are not consumed when you read them. The ioctl takes an additional parameter, (int)1
for grabbing, (int)0
for releasing.
To re-inject any events, just write them to the uinput
device. See eg. a mouse example here. (The event structures are the same type, you only need to write a struct uinput_user_dev
structure to the uinput
device first, to describe your new input device (which provides the mapped events).)
In other words, you don’t remap: you consume and forward.