Re: How to use /dev/lirc0 in VDR?

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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

[Index of Archives]     [Linux Media]     [Asterisk]     [DCCP]     [Netdev]     [Xorg]     [Util Linux NG]     [Xfree86]     [Big List of Linux Books]     [Fedora Users]     [Fedora Women]     [ALSA Devel]     [Linux USB]

  Powered by Linux