Package: lirc
Version: 0.7.2-2
Severity: wishlist

I've found that while unloading and reloading an input device module
(remote control input via budget-ci, which I'm modifying a bit), the input
device number isn't stable - it normally appears as input3 but has appeared
as input4 (with nothing at input3).

The attached patch (which should be applied after 04_man_page)) allows the
use of "name=foo" and "phys=foo" for --device (or, for that matter, DEVICE in
/etc/lirc/hardware.conf); shell wildcards are allowed.

-- 
| Darren Salt   | nr. Ashington, | linux (or ds) at
| sarge,        | Northumberland | youmustbejoking
| RISC OS       | Toon Army      | demon co uk
|   Kill all extremists!

Nothing endures but change.
--- lirc.orig/doc/man/lircd.8
+++ lirc/doc/man/lircd.8
@@ -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.
--- lirc.orig/doc/html/lircd.html
+++ lirc/doc/html/lircd.html
@@ -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.
--- lirc.orig/daemons/hw_devinput.c
+++ lirc/daemons/hw_devinput.c
@@ -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,105 @@
 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);
+
+printf ("device = %s\n", 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)) {
+puts ("checking phys");
+               if (locate_dev (hw.device + 5, 1)) {
+                       logprintf(LOG_ERR, "unable to find '%s'", hw.device);
+                       return 0;
+               }
+printf ("match found: %s\n", hw.device);
+       }
        
        if ((hw.fd = open(hw.device, O_RDONLY)) < 0) {
                logprintf(LOG_ERR, "unable to open '%s'", hw.device);

Reply via email to