evdev hacks

Peter Hutterer mailinglists at who-t.net
Thu Apr 19 03:06:10 PDT 2007


The current evdev driver shoots the server when you hotplug devices  
(sigaborts on double free, segfaults when you fix that, etc.) The  
following patch fixes these problems and hotplugging works reliably.  
But it changes the behaviour of the driver slightly.

Previously evdev kept watching the device file until something  
happened, and then bypassed all the dbus hotplugging and added the  
device itself. So it was basically two separate hotplugging  
mechanisms that didn't know about each other. One inside the driver  
and one inside the server.

If you try to add a device that doesn't exist, nothing will happen,  
and you will have to try again later when the device actually exists.  
Hotplugging devices _always_ has to be initiated by a dbus command.

If there's no complaints about this, I'll push it in the next few days.


diff --git a/src/evdev.c b/src/evdev.c
index f506997..5455062 100644
--- a/src/evdev.c
+++ b/src/evdev.c
@@ -461,6 +461,14 @@ EvdevCorePreInit(InputDriverPtr drv, IDe
      if (pEvdev->devices && pEvdev->devices->pInfo)
	return pEvdev->devices->pInfo;
+    /* In some cases pEvdev->devices is NULL, but on the next
+     * evdevRescanDevices the device suddenly appears. If we return  
NULL here,
+     * the server will clean up and the sudden appearance of the  
device will
+     * segfault. We need to remove the driver from the list to avoid  
this.
+     * No. I don't know why it just appears. (whot)
+     */
+    evdevRemoveDriver(pEvdev);
+
      return NULL;
}
diff --git a/src/evdev.h b/src/evdev.h
index c6e9188..81abbb6 100644
--- a/src/evdev.h
+++ b/src/evdev.h
@@ -256,6 +256,8 @@ Bool evdevStart (InputDriverPtr drv);
Bool evdevNewDriver (evdevDriverPtr driver);
Bool evdevGetBits (int fd, evdevBitsPtr bits);
void evdevRemoveDevice (evdevDevicePtr device);
+void evdevDeleteDevice (evdevDevicePtr device);
+void evdevRemoveDriver (evdevDriverPtr device);
int EvdevBtnInit (DeviceIntPtr device);
int EvdevBtnOn (DeviceIntPtr device);
diff --git a/src/evdev_brain.c b/src/evdev_brain.c
index d0d1ac6..03506c4 100644
--- a/src/evdev_brain.c
+++ b/src/evdev_brain.c
@@ -555,16 +555,24 @@ evdevNewDriver (evdevDriverPtr driver)
void
evdevRemoveDevice (evdevDevicePtr pEvdev)
{
-    evdevDriverPtr driver;
+    evdevDriverPtr driver, prev;
      evdevDevicePtr *device;
-    for (driver = evdev_drivers; driver; driver = driver->next) {
+    prev = evdev_drivers;
+
+    for (driver = evdev_drivers; driver; prev = driver, driver =  
driver->next) {
          for (device = &driver->devices; *device; device = & 
(*device)->next) {
              if (*device == pEvdev) {
                  *device = pEvdev->next;
-                xf86DeleteInput(pEvdev->pInfo, 0);
                  pEvdev->next = NULL;
+                /* driver without device? get rid of it, otherwise  
it'll
+                 * auto-hotplug when a device is plugged in again.
+                 */
                  if (!driver->devices)
+                {
+                    evdevDeleteDevice(pEvdev);
+                    evdevRemoveDriver(driver);
+                }
                  return;
              }
          }
@@ -600,3 +608,51 @@ evdevGetBits (int fd, evdevBitsPtr bits)
      return TRUE;
}
+/**
+ * Free memory associated with device.
+ */
+void
+evdevDeleteDevice(evdevDevicePtr pEvdev)
+{
+    /* pEvdev->pInp is freed in xf86DeleteInput() when
+     * DeleteInputDeviceRequest is called. */
+    xfree(pEvdev->name);
+    xfree(pEvdev->phys);
+    xfree(pEvdev->device);
+    xfree(pEvdev);
+}
+
+/**
+ * Remove a driver from the list, free memory.
+ */
+void evdevRemoveDriver(evdevDriverPtr drv)
+{
+    evdevDriverPtr driver, prev;
+    evdevDevicePtr device;
+
+    if (drv == evdev_drivers)
+        evdev_drivers = evdev_drivers->next;
+    else
+        for (prev = evdev_drivers, driver = prev->next; driver;
+                prev = driver, driver = driver->next)
+        {
+            if (driver == drv)
+            {
+                prev->next = driver->next;
+            }
+        }
+
+    xfree(drv->name);
+    xfree(drv->phys);
+    xfree(drv->device);
+
+    device = drv->devices;
+    while(device)
+    {
+        evdevDeleteDevice(device);
+        device = device->next;
+    }
+
+    xfree(drv);
+}
+


--
Multi-Pointer X Server
http://wearables.unisa.edu.au/mpx





More information about the xorg mailing list