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

Marko Mäkelä <[email protected]> Wed, 20 Jul 2022 12:34:19 +0300
Newsgroups gmane.linux.vdr
Message-ID <YtfMGxSNcnzEBK1C@jyty>
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

_______________________________________________
vdr mailing list
[email protected]
https://www.linuxtv.org/cgi-bin/mailman/listinfo/vdr
lirc-adapt.c (text/x-csrc, 1.8 KB)
#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);
  }
}