summaryrefslogtreecommitdiff
path: root/src/evdev_brain.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/evdev_brain.c')
-rw-r--r--src/evdev_brain.c62
1 files changed, 59 insertions, 3 deletions
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);
+}
+