Remote plugin breakage with 2.6.15-rc1+ kernel

Message ID 4DC97B4361%linux@youmustbejoking.demon.co.uk
State New
Headers

Commit Message

Darren Salt Nov. 14, 2005, 3:30 a.m. UTC
  I demand that C.Y.M may or may not have written...

> C.Y.M wrote:
>> As of 2.6.15-rc1 (actually the change was originally made in 2.6.14-git8),
>> there is no more /dev/input/event0 node.  The nodes now start at event1
>> and up.  This breaks the autodetect feature in the remote plugin for VDR. 
>> I was able to kludge a fix by hacking the default to the event I am
>> currently using, but a real fix should be made instead.

>> This is *hacked* fix for a remote that is using event3.  This only a
>> kludge.

> OK, this seems like a much better fix for 2.6.15-rc1+ kernels and the
> remote plugin.  Now autodetect works again for the events.

There could be gaps in the list due to some other device (probably USB)
having been unplugged, leaving, for example, event0, event1 and event3. Now
imagine that event3 is for the DVB remote control.

The attached patch *should* fix this.

(For completeness, I'm also attaching my older patches.)
  

Comments

C.Y.M Nov. 14, 2005, 11:52 a.m. UTC | #1
> There could be gaps in the list due to some other device (probably USB)
> having been unplugged, leaving, for example, event0, event1 and event3. Now
> imagine that event3 is for the DVB remote control.
> 
> The attached patch *should* fix this.
> 
> (For completeness, I'm also attaching my older patches.)
> 

Thanks, Darren.  This works great with both 2.4 and 2.6 kernels.

Best Regards,
  

Patch

--- vdr-plugin-remote-0.3.3.orig/remote.c
+++ vdr-plugin-remote-0.3.3/remote.c
@@ -174,7 +174,7 @@ 
 //          -1 - error
 //
 // ---------------------------------------------------------------------------
-int identifyInputDevice(const int fh, char *name)
+int identifyInputDevice(const int fh, const char *name)
 // ---------------------------------------------------------------------------
 {
     char description[256];
@@ -651,6 +651,23 @@ 
 }
 
 
+class cListString : public cListObject
+{
+private:
+  cString *content;
+public:
+  cListString (const char *obj) { content = new cString (obj); }
+  ~cListString () { delete content; }
+  int Compare (const cListObject &obj) const;
+  const cString& Get () { return *content; }
+};
+
+int cListString::Compare (const cListObject &obj) const
+{
+  return strcmp (**content, **((const cListString &)obj).content);
+}
+
+
 // ---------------------------------------------------------------------------
 bool cPluginRemote::Start(void)
 // ---------------------------------------------------------------------------
@@ -668,17 +685,59 @@ 
         devcnt = 1;
     }
 
+    cList<cListString> devices;
+
+    DIR *dir = opendir ("/dev/input");
+    if (!dir)
+    {
+        esyslog ("%s: unable to open '%s': %s",
+                 Name (), "/dev/input", strerror (errno));
+        return false;
+    }
+
+    long devmin = INT_MAX;
+    for (;;)
+    {
+        dirent obj, *ret;
+        int err = readdir_r (dir, &obj, &ret);
+        if (err)
+        {
+            esyslog ("%s: unable to read '%s': %s",
+                     Name (), "/dev/input", strerror (errno));
+            closedir (dir);
+            return false;
+        }
+        if (!ret)
+            break;
+
+        if (strncmp (obj.d_name, "event", 5))
+            continue;
+
+        long j;
+        char *end;
+        j = strtol (obj.d_name + 5, &end, 10);
+        if (j < 0 || end == obj.d_name || *end)
+            continue;
+
+        // keep track of the lowest device number (in case it's not 0)
+        if (j < devmin)
+            devmin = j;
+
+        devices.Add (new cListString (cString::sprintf ("/dev/input/%s", obj.d_name)));
+    }
+    closedir (dir);
+
+    devices.Sort ();
+
     /* probe eventX devices */
     for (int i = 0; i < devcnt; i++)
     {
         if (devtyp[i] == 'i' && strcmp(devnam[i], "autodetect") == 0)
         {
-            char nam[80];
 
-            for (int j = 0; ; j++)
+            for (cListString *dev = devices.First (); dev; dev = devices.Next (dev))
             {
-                sprintf(nam, "/dev/input/event%d", j);
-                fh[i] = open(nam, O_RDONLY);
+                fh[i] = open(dev->Get (), O_RDONLY);
                 if (fh[i] < 0)
                 {
                     switch (errno)
@@ -691,22 +750,23 @@ 
                     break;
                 }
 		
-                if (identifyInputDevice(fh[i], nam) >= 1)
+                if (identifyInputDevice(fh[i], dev->Get ()) >= 1)
                 {
                     // found DVB card receiver
-                    devnam[i] = strdup(nam);
+                    devnam[i] = strdup(dev->Get ());
                     close(fh[i]);
+                    devices.Del (dev);
                     break;
                 }
 
                 // unknown device, try next one
                 close(fh[i]);
-            } // for j
+            } // for each (remaining) eventX
         } // if autodetect
 
         // use default device if nothing could be identified
         if (devtyp[i] == 'i' && strcmp(devnam[i], "autodetect") == 0)
-            devnam[i] = "/dev/input/event0";
+            asprintf (&devnam[i], "/dev/input/event%ld", devmin);
     } // for i
 
     for (int i = 0; i < devcnt; i++)