Mon, Jul 18, 2022 at 09:36:55AM +0300, Marko Mäkelä wrote:
TL;DR: How could I connect VDR to the kernel-provided /dev/lirc0 device? Is there a dummy lircd implementation that would simply open /dev/lirc0 in LIRC_MODE_SCANCODE and relay its contents over a socket?
I wrote a simple converter (attached) that is compatible with vdr --lirc=/dev/shm/lirc. Alas, as far as I can tell, the socket interface does not currently allow any "repeat" flag to be passed explicitly. Instead, lirc.c will detect long keypresses by itself based on some time stamps or timeouts, and then pass the parameter to cRemote::Put().
The Linux kernel documentation gave me the impression that the /dev/input/event interface is the modern way to handle any input.
I wonder if a /dev/input/event interface could be implemented natively in the VDR core. It would remove the need for both lircd and vdr-plugin-remote in many typical installations.
It seems that in any case, I'd better write a converter from /dev/lirc0 to /dev/uinput, to have the key events generated in my way, slightly differently from the kernel's built-in /dev/input/event driver.
Marko
#include <stdio.h> #include <string.h> #include <errno.h> #include <unistd.h> #include <poll.h> #include <fcntl.h> #include <sys/ioctl.h> #include <sys/socket.h> #include <sys/un.h> #include <linux/lirc.h> static struct lirc_scancode sc[64]; int main(void) { unsigned mode = LIRC_MODE_SCANCODE; int fd, s; struct sockaddr_un name; memset(&name, 0, sizeof name); name.sun_family = AF_UNIX; strncpy(name.sun_path, "/dev/shm/lirc", sizeof name.sun_path - 1); s = socket(AF_UNIX, SOCK_STREAM, 0); if (s == -1) { perror("socket"); return 1; } if (bind(s, (const struct sockaddr*) &name, sizeof name) == -1) { perror("bind"); return 1; } fd = open("/dev/lirc0", O_RDONLY | O_NONBLOCK); if (fd == -1) { perror("open"); return 1; } if (ioctl(fd, LIRC_SET_REC_MODE, &mode)) { perror("ioctl"); return 1; } if (listen(s, 1) == -1) { perror("listen"); return 2; } for (;;) { int sock = accept(s, NULL, NULL); if (sock == -1) { perror("accept"); return 2; } for (;;) { ssize_t rd; struct pollfd polls[2] = { { .fd = fd, .events = POLLIN }, { .fd = sock, .events = POLLERR }, }; if (poll(polls, 2, -1) < 0) { if (errno == EINTR) continue; perror("poll"); return 2; } rd = read(fd, sc, sizeof sc); if (rd > 0) { ssize_t i, n = rd / sizeof *sc; char buf[14]; for (i = 0; i < n; i++) { int l = sprintf(buf, "0 0 %08x\n", sc[i].keycode); if (-1 == write(sock, buf, 13)) { perror("write"); goto end; } } } else if (errno == EAGAIN) { continue; } else { perror("read"); return 2; } } end: close(sock); } }
_______________________________________________ vdr mailing list vdr@xxxxxxxxxxx https://www.linuxtv.org/cgi-bin/mailman/listinfo/vdr