summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Hutterer <peter.hutterer@who-t.net>2014-05-06 09:20:05 +1000
committerPeter Hutterer <peter.hutterer@who-t.net>2014-05-07 10:30:22 +1000
commit62010287ebd8a72902630e3ba72e643f1f145c3c (patch)
tree02fbafa3db8ed9b08ef4ff4289013dbcd0d92a6f
parente41befa83f1e693a91b6de39c0ad01f7c9e5653d (diff)
downloadxorg-driver-xf86-input-evdev-62010287ebd8a72902630e3ba72e643f1f145c3c.tar.gz
Use the server's device list for duplicate detection (#78309)
EvdevAddDevice/EvdevRemoveDevice keep a reference to the device to detect duplicate devices based on the dev_t. EvdevAddDevices was called during PreInit, EvdevRemoveDevice was called during DEVICE_CLOSE. That makes it imbalanced if the device succeeds PreInit but the server skips everything else because MAX_DEVICES is exceeded. So for all devices after MAX_DEVICES, we'd add a reference but never remove it, eventually reading/writing past evdev_devices. The server keeps the list of devices for us anyway, so remove the copy of all the pointers and instead run through the device list the server gives us. X.Org Bug 78309 <http://bugs.freedesktop.org/show_bug.cgi?id=78309> Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net> Reviewed-by: Hans de Goede <hdegoede@redhat.com> (cherry picked from commit 13dea90bc8ef2a2e6f55fb5ff5f54afe41d22f95)
-rw-r--r--src/evdev.c72
1 files changed, 12 insertions, 60 deletions
diff --git a/src/evdev.c b/src/evdev.c
index 47c7cf0..7f4f0c3 100644
--- a/src/evdev.c
+++ b/src/evdev.c
@@ -65,11 +65,6 @@
/* removed from server, purge when dropping support for server 1.10 */
#define XI86_SEND_DRAG_EVENTS 0x08
-#ifndef MAXDEVICES
-#include <inputstr.h> /* for MAX_DEVICES */
-#define MAXDEVICES MAX_DEVICES
-#endif
-
#define ArrayLength(a) (sizeof(a) / (sizeof((a)[0])))
#define MIN_KEYCODE 8
@@ -138,11 +133,6 @@ static Atom prop_btn_label;
static Atom prop_device;
static Atom prop_virtual;
-/* All devices the evdev driver has allocated and knows about.
- * MAXDEVICES is safe as null-terminated array, as two devices (VCP and VCK)
- * cannot be used by evdev, leaving us with a space of 2 at the end. */
-static EvdevPtr evdev_devices[MAXDEVICES] = {NULL};
-
static int EvdevSwitchMode(ClientPtr client, DeviceIntPtr device, int mode)
{
InputInfoPtr pInfo;
@@ -225,58 +215,23 @@ static BOOL
EvdevIsDuplicate(InputInfoPtr pInfo)
{
EvdevPtr pEvdev = pInfo->private;
- EvdevPtr* dev = evdev_devices;
+ InputInfoPtr d;
- if (pEvdev->min_maj)
+ nt_list_for_each_entry(d, xf86FirstLocalDevice(), next)
{
- while(*dev)
- {
- if ((*dev) != pEvdev &&
- (*dev)->min_maj &&
- (*dev)->min_maj == pEvdev->min_maj)
- return TRUE;
- dev++;
- }
- }
- return FALSE;
-}
+ EvdevPtr e;
-/**
- * Add to internal device list.
- */
-static void
-EvdevAddDevice(InputInfoPtr pInfo)
-{
- EvdevPtr pEvdev = pInfo->private;
- EvdevPtr* dev = evdev_devices;
-
- while(*dev)
- dev++;
-
- *dev = pEvdev;
-}
-
-/**
- * Remove from internal device list.
- */
-static void
-EvdevRemoveDevice(InputInfoPtr pInfo)
-{
- EvdevPtr pEvdev = pInfo->private;
- EvdevPtr *dev = evdev_devices;
- int count = 0;
+ if (strcmp(d->drv->driverName, "evdev") != 0)
+ continue;
- while(*dev)
- {
- count++;
- if (*dev == pEvdev)
- {
- memmove(dev, dev + 1,
- sizeof(evdev_devices) - (count * sizeof(EvdevPtr)));
- break;
- }
- dev++;
+ e = (EvdevPtr)d->private;
+ if (e != pEvdev &&
+ e->min_maj &&
+ e->min_maj == pEvdev->min_maj)
+ return TRUE;
}
+
+ return FALSE;
}
static BOOL
@@ -1972,7 +1927,6 @@ EvdevProc(DeviceIntPtr device, int what)
xf86IDrvMsg(pInfo, X_INFO, "Close\n");
EvdevCloseDevice(pInfo);
EvdevFreeMasks(pEvdev);
- EvdevRemoveDevice(pInfo);
pEvdev->min_maj = 0;
break;
@@ -2639,8 +2593,6 @@ EvdevPreInit(InputDriverPtr drv, InputInfoPtr pInfo, int flags)
pInfo->type_name);
pInfo->type_name = pEvdev->type_name;
- EvdevAddDevice(pInfo);
-
if (pEvdev->flags & EVDEV_BUTTON_EVENTS)
{
EvdevMBEmuPreInit(pInfo);