Package: lirc
Version: 0.8.0-2
Tags: patch

lircd doesn't cope well with non-static node names, such as those of my
Nova-Ts' IR inputs: if the device isn't at the expected location, lircd will
exit when another program tries to use it (however, this isn't the point of
this report).

For instance, the device which I'm trying to use *currently* has the
following names:

  /dev/input/event2
  /dev/input/by-path/pci-0000:02:06.0--event-

(Note nothing in /dev/input/by-id.)

These names are not static. The following two (at least) are also possible,
due to differences in initialisation order of input devices and other
components of the DVB card:

  /dev/input/event3
  /dev/input/by-path/pci-0000:02:06.2--event-

Now, it's true that a udev rule would fix this, but who's to say that udev is
in use? That's where scanning the available input devices, using the two
identification ioctls, comes in.

Patch attached. With it, I can say things like (in /etc/lirc/hardware.conf):
  DEVICE="phys=pci-0000:02:06.*/ir0"
and the device will Just Work regardless (so long as it remains in the same
slot).

This is also upstream:
<URL:http://sourceforge.net/tracker/?func=detail&atid=305444&aid=1434830&group_id=5444>

-- 
| Darren Salt    | linux or ds at              | nr. Ashington, | Toon
| RISC OS, Linux | youmustbejoking,demon,co,uk | Northumberland | Army
| + Buy local produce. Try to walk or cycle. TRANSPORT CAUSES GLOBAL WARMING.

You will be recognised and honoured as a community leader.
diff -urNad lirc-0.8.0~/daemons/hw_devinput.c lirc-0.8.0/daemons/hw_devinput.c
--- lirc-0.8.0~/daemons/hw_devinput.c   2006-02-19 21:12:39.000000000 +0000
+++ lirc-0.8.0/daemons/hw_devinput.c    2006-02-19 21:12:46.110150218 +0000
@@ -25,6 +25,9 @@
 
 #include <stdio.h>
 #include <sys/fcntl.h>
+#include <sys/types.h>
+#include <dirent.h>
+#include <fnmatch.h>
 
 #include <linux/input.h>
 
@@ -63,9 +66,101 @@
 static ir_code code;
 static int repeat_flag=0;
 
+static int do_match (const char *text, const char *wild)
+{
+       while (*wild) {
+               if (*wild == '*') {
+                       const char *next = text - 1;
+                       ++wild;
+                       while (*++next)
+                               if (!do_match (next, wild))
+                                       return 0;
+                       return 1;
+                       }
+               else if (*wild == '?') {
+                       if (!*text++)
+                               return 1;
+               }
+               else if (*wild == '\\') {
+                       if (wild[1] != *text++)
+                               return 1;
+                       if (!wild[1])
+                               return 0;
+                       wild += 2;
+               }
+               else if (*wild++ != *text++)
+                       return 1;
+       }
+       return 0;
+}
+
+static int locate_dev (const char *label, int type)
+{
+       static char devname[FILENAME_MAX];
+       char ioname[255];
+       DIR *dir;
+       struct dirent *obj;
+       int ionum;
+
+       dir = opendir ("/dev/input");
+       if (!dir)
+               return 1;
+
+       devname[0] = 0;
+       switch (type) {
+               case 0:
+                       ionum = EVIOCGNAME (sizeof (ioname));
+                       break;
+               case 1:
+                       ionum = EVIOCGPHYS (sizeof (ioname));
+                       break;
+               default:
+                       closedir (dir);
+                       return 1;
+       }
+
+       while ((obj = readdir (dir))) {
+               int fd;
+               if (obj->d_name[0] == '.' &&
+                   (obj->d_name[1] == 0 ||
+                    (obj->d_name[1] == '.' && obj->d_name[2] == 0)))
+                       continue; /* skip "." and ".." */
+               sprintf (devname, "/dev/input/%s", obj->d_name);
+               fd = open (devname, O_RDONLY);
+               if (!fd)
+                       continue;
+               if (ioctl (fd, ionum, ioname) >= 0) {
+                       close (fd);
+                       int ret = do_match (ioname, label);
+                       if (!ret) {
+                               hw.device = devname;
+                               closedir (dir);
+                               return 0;
+                       }
+               }
+               close (fd);
+       }
+
+       closedir (dir);
+       return 1;
+}
+
 int devinput_init()
 {
        logprintf(LOG_INFO, "initializing '%s'", hw.device);
+
+       if (!strncmp (hw.device, "name=", 5)) {
+               if (locate_dev (hw.device + 5, 0)) {
+                       logprintf(LOG_ERR, "unable to find '%s'", hw.device);
+                       return 0;
+               }
+       }
+       else if (!strncmp (hw.device, "phys=", 5)) {
+               if (locate_dev (hw.device + 5, 1)) {
+                       logprintf(LOG_ERR, "unable to find '%s'", hw.device);
+                       return 0;
+               }
+       }
        
        if ((hw.fd = open(hw.device, O_RDONLY)) < 0) {
                logprintf(LOG_ERR, "unable to open '%s'", hw.device);
diff -urNad lirc-0.8.0~/doc/html/lircd.html lirc-0.8.0/doc/html/lircd.html
--- lirc-0.8.0~/doc/html/lircd.html     2006-02-19 21:12:39.000000000 +0000
+++ lirc-0.8.0/doc/html/lircd.html      2006-02-19 21:12:46.110150218 +0000
@@ -91,6 +91,12 @@
 should read from. The default currently is /dev/lirc but it probably
 will change in future.
 <P>
+If you're using the dev/input driver, you can use <tt>name=STRING</tt> or
+<tt>phys=STRING</tt> to select the device; lircd will look in /dev/input to
+find a device with a matching description. This is useful in case the device
+name isn't fixed. <tt>STRING</tt> may contain the '*' and '?' wildcards and
+\ to mark them as literal.
+<P>
 With the --listen option you can let lircd listen for network
 connections on the given port. The default port is 8765. No security
 checks are currently implemented.
diff -urNad lirc-0.8.0~/doc/man/lircd.8 lirc-0.8.0/doc/man/lircd.8
--- lirc-0.8.0~/doc/man/lircd.8 2006-02-19 21:12:45.000000000 +0000
+++ lirc-0.8.0/doc/man/lircd.8  2006-02-19 21:13:19.208016076 +0000
@@ -57,6 +57,16 @@
 should read from. The default currently is /dev/lirc but it probably
 will change in future.
 
+If you're using the dev/input driver, you can use
+.I name=STRING
+or
+.I phys=STRING
+to select the device; lircd will look in /dev/input to
+find a device with a matching description. This is useful in case the
+device name isn't fixed.
+.I STRING
+may contain the '*' and '?' wildcards and '\\' to mark them as literal.
+
 With the \-\-listen option you can let lircd listen for network
 connections on the given port. The default port is 8765. No security
 checks are currently implemented.

Attachment: signature.asc
Description: PGP signature

Reply via email to