diff options
author | Peter Hutterer <peter@cs.unisa.edu.au> | 2007-04-23 10:08:48 +0930 |
---|---|---|
committer | Peter Hutterer <peter@cs.unisa.edu.au> | 2007-04-23 10:08:48 +0930 |
commit | ba65c34068a836ae393565a6a8260a4e96709816 (patch) | |
tree | 7bf959c46149514dc73a16f07c1cf54213df95a4 | |
parent | 9644a4afbfd8ac4cb51facf0409f73f55743d8a3 (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.c | 8 | ||||
-rw-r--r-- | src/evdev.h | 2 | ||||
-rw-r--r-- | src/evdev_brain.c | 62 |
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); +} + |