Here I got AI to write it.
Tested working on debian with Zidoo V12.
Run as root with the Zidoo V12 Keyboard device as arg 1: sudo ./uinput-forwarder /dev/input/eventX
I had to chmod /dev/uinput
sudo chmod +0666 /dev/uinput
since libre is running as root already drop the sudo for libre
// uinput-forwarder.c
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <linux/input.h>
#include <linux/uinput.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <time.h>
static void print_event(const struct input_event *ev) {
char timebuf[64];
struct tm tm;
time_t sec = ev->time.tv_sec;
localtime_r(&sec, &tm);
strftime(timebuf, sizeof(timebuf), "%F %T", &tm);
if (ev->type == EV_KEY) {
printf("%s.%06ld: EV_KEY code=%u value=%d\n", timebuf, ev->time.tv_usec, ev->code, ev->value);
} else if (ev->type == EV_SYN) {
printf("%s.%06ld: EV_SYN code=%u value=%d\n", timebuf, ev->time.tv_usec, ev->code, ev->value);
} else {
printf("%s.%06ld: type=%u code=%u value=%d\n", timebuf, ev->time.tv_usec, ev->type, ev->code, ev->value);
}
fflush(stdout);
}
int main(int argc, char **argv) {
const char *src = (argc > 1) ? argv[1] : "/dev/input/event0";
int ifd = -1, ufd = -1;
struct input_event ev;
ssize_t rd;
ifd = open(src, O_RDONLY);
if (ifd < 0) {
perror("open source device");
return 1;
}
ufd = open("/dev/uinput", O_WRONLY | O_NONBLOCK);
if (ufd < 0) {
perror("open /dev/uinput");
close(ifd);
return 1;
}
if (ioctl(ufd, UI_SET_EVBIT, EV_KEY) < 0) { perror("UI_SET_EVBIT EV_KEY"); goto cleanup; }
if (ioctl(ufd, UI_SET_EVBIT, EV_SYN) < 0) { perror("UI_SET_EVBIT EV_SYN"); goto cleanup; }
// Enable common keyboard key codes (0..KEY_MAX)
for (int k = 0; k <= KEY_MAX; ++k) {
if (ioctl(ufd, UI_SET_KEYBIT, k) < 0) {
// ignore individual failures
}
}
struct uinput_user_dev uidev;
memset(&uidev, 0, sizeof(uidev));
snprintf(uidev.name, UINPUT_MAX_NAME_SIZE, "forwarded-kbd-%s", strrchr(src, '/') ? strrchr(src, '/')+1 : src);
uidev.id.bustype = BUS_USB;
uidev.id.vendor = 0x1234;
uidev.id.product = 0x5678;
uidev.id.version = 1;
if (write(ufd, &uidev, sizeof(uidev)) < 0) { perror("write uidev"); goto cleanup; }
if (ioctl(ufd, UI_DEV_CREATE) < 0) { perror("UI_DEV_CREATE"); goto cleanup; }
while (1) {
rd = read(ifd, &ev, sizeof(ev));
if (rd == (ssize_t)-1) {
if (errno == EINTR) continue;
perror("read input");
break;
} else if (rd != sizeof(ev)) {
fprintf(stderr, "Short read\n");
break;
}
print_event(&ev);
if (ev.type == EV_KEY || ev.type == EV_SYN) {
ssize_t wr = write(ufd, &ev, sizeof(ev));
if (wr != sizeof(ev)) {
perror("write uinput");
break;
}
}
}
ioctl(ufd, UI_DEV_DESTROY);
cleanup:
if (ufd >= 0) close(ufd);
if (ifd >= 0) close(ifd);
return 0;
}
Display More