summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Hutterer <peter@cs.unisa.edu.au>2007-04-23 10:08:48 +0930
committerPeter Hutterer <peter@cs.unisa.edu.au>2007-04-23 10:08:48 +0930
commitba65c34068a836ae393565a6a8260a4e96709816 (patch)
tree7bf959c46149514dc73a16f07c1cf54213df95a4
parent9644a4afbfd8ac4cb51facf0409f73f55743d8a3 (diff)
Remove driver from list if no device is associated any more.
This effectively stops the driver from hotplugging new devices. Devices have to be added with the dbus hotplugging events.
-rw-r--r--src/evdev.c8
-rw-r--r--src/evdev.h2
-rw-r--r--src/evdev_brain.c62
3 files changed, 69 insertions, 3 deletions
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, IDevPtr dev, int flags)
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);
+}
+