xorg-x11-drv-evdev/evdev-2.0.4-cache-info.patch
Adam Jackson a7b51f43ac - evdev-2.0.4-reopen-device.patch: When arming the reopen timer, stash it
in the driver private, and explicitly cancel it if the server decides
    to close the device for real.
- evdev-2.0.4-cache-info.patch: Rebase to account for same.
2008-09-12 20:08:52 +00:00

200 lines
6.3 KiB
Diff

diff -up xf86-input-evdev-2.0.4/src/evdev.c.jx xf86-input-evdev-2.0.4/src/evdev.c
--- xf86-input-evdev-2.0.4/src/evdev.c.jx 2008-09-12 16:04:34.000000000 -0400
+++ xf86-input-evdev-2.0.4/src/evdev.c 2008-09-12 16:04:56.000000000 -0400
@@ -98,6 +98,7 @@ static const char *evdevDefaults[] = {
};
static int EvdevOn(DeviceIntPtr);
+static int EvdevCacheCompare(InputInfoPtr pInfo, Bool compare);
static void
SetXkbOption(InputInfoPtr pInfo, char *name, char **option)
@@ -176,12 +177,19 @@ EvdevReopenTimer(OsTimerPtr timer, CARD3
if (pInfo->fd != -1)
{
- xf86Msg(X_INFO, "%s: Device reopened after %d attempts.\n", pInfo->name,
- pEvdev->reopen_attempts - pEvdev->reopen_left);
-
pEvdev->reopen_left = 0;
pEvdev->reopen_timer = NULL;
- EvdevOn(pInfo->dev);
+ if (EvdevCacheCompare(pInfo, TRUE) == Success)
+ {
+ xf86Msg(X_INFO, "%s: Device reopened after %d attempts.\n", pInfo->name,
+ pEvdev->reopen_attempts - pEvdev->reopen_left);
+ EvdevOn(pInfo->dev);
+ } else
+ {
+ xf86Msg(X_ERROR, "%s: Device has changed - disabling.\n",
+ pInfo->name);
+ DisableDevice(pInfo->dev);
+ }
return 0;
}
@@ -370,8 +378,6 @@ EvdevReadInput(InputInfoPtr pInfo)
}
}
-#define LONG_BITS (sizeof(long) * 8)
-#define NBITS(x) (((x) + LONG_BITS - 1) / LONG_BITS)
#define TestBit(bit, array) (array[(bit) / LONG_BITS]) & (1 << ((bit) % LONG_BITS))
static void
@@ -1000,6 +1006,116 @@ EvdevConvert(InputInfoPtr pInfo, int fir
return TRUE;
}
+/**
+ * Get as much information as we can from the fd and cache it.
+ * If compare is True, then the information retrieved will be compared to the
+ * one already cached. If the information does not match, then this function
+ * returns an error.
+ *
+ * @return Success if the information was cached, or !Success otherwise.
+ */
+static int
+EvdevCacheCompare(InputInfoPtr pInfo, Bool compare)
+{
+ int i;
+ EvdevPtr pEvdev = pInfo->private;
+ char name[1024] = {0};
+ long bitmask[NBITS(EV_MAX)] = {0};
+ long key_bitmask[NBITS(KEY_MAX)] = {0};
+ long rel_bitmask[NBITS(REL_MAX)] = {0};
+ long abs_bitmask[NBITS(ABS_MAX)] = {0};
+ long led_bitmask[NBITS(LED_MAX)] = {0};
+ struct input_absinfo absinfo[ABS_MAX];
+
+ if (ioctl(pInfo->fd,
+ EVIOCGNAME(sizeof(name) - 1), name) < 0) {
+ xf86Msg(X_ERROR, "ioctl EVIOCGNAME failed: %s\n", strerror(errno));
+ goto error;
+ }
+
+ if (compare && strcmp(pEvdev->name, name))
+ goto error;
+
+ if (ioctl(pInfo->fd,
+ EVIOCGBIT(0, sizeof(bitmask)), bitmask) < 0) {
+ xf86Msg(X_ERROR, "ioctl EVIOCGNAME failed: %s\n", strerror(errno));
+ goto error;
+ }
+
+ if (compare && memcmp(pEvdev->bitmask, bitmask, sizeof(bitmask)))
+ goto error;
+
+
+ if (ioctl(pInfo->fd,
+ EVIOCGBIT(EV_REL, sizeof(rel_bitmask)), rel_bitmask) < 0) {
+ xf86Msg(X_ERROR, "ioctl EVIOCGBIT failed: %s\n", strerror(errno));
+ goto error;
+ }
+
+ if (compare && memcmp(pEvdev->rel_bitmask, rel_bitmask, sizeof(rel_bitmask)))
+ goto error;
+
+ if (ioctl(pInfo->fd,
+ EVIOCGBIT(EV_ABS, sizeof(abs_bitmask)), abs_bitmask) < 0) {
+ xf86Msg(X_ERROR, "ioctl EVIOCGBIT failed: %s\n", strerror(errno));
+ goto error;
+ }
+
+ if (compare && memcmp(pEvdev->abs_bitmask, abs_bitmask, sizeof(abs_bitmask)))
+ goto error;
+
+ if (ioctl(pInfo->fd,
+ EVIOCGBIT(EV_KEY, sizeof(key_bitmask)), key_bitmask) < 0) {
+ xf86Msg(X_ERROR, "ioctl EVIOCGBIT failed: %s\n", strerror(errno));
+ goto error;
+ }
+
+ if (compare && memcmp(pEvdev->key_bitmask, key_bitmask, sizeof(key_bitmask)))
+ goto error;
+
+ if (ioctl(pInfo->fd,
+ EVIOCGBIT(EV_LED, sizeof(led_bitmask)), led_bitmask) < 0) {
+ xf86Msg(X_ERROR, "ioctl EVIOCGBIT failed: %s\n", strerror(errno));
+ goto error;
+ }
+
+ if (compare && memcmp(pEvdev->led_bitmask, led_bitmask, sizeof(led_bitmask)))
+ goto error;
+
+ memset(absinfo, 0, sizeof(absinfo));
+
+ for (i = 0; i < ABS_MAX; i++)
+ {
+ if (TestBit(i, abs_bitmask))
+ {
+ if (ioctl(pInfo->fd, EVIOCGABS(i), &absinfo[i]) < 0) {
+ xf86Msg(X_ERROR, "ioctl EVIOCGABS failed: %s\n", strerror(errno));
+ goto error;
+ }
+ }
+ }
+
+ if (compare && memcmp(pEvdev->absinfo, absinfo, sizeof(absinfo)))
+ goto error;
+
+ /* cache info */
+ if (!compare)
+ {
+ strcpy(pEvdev->name, name);
+ memcpy(pEvdev->bitmask, bitmask, sizeof(bitmask));
+ memcpy(pEvdev->key_bitmask, key_bitmask, sizeof(key_bitmask));
+ memcpy(pEvdev->rel_bitmask, rel_bitmask, sizeof(rel_bitmask));
+ memcpy(pEvdev->abs_bitmask, abs_bitmask, sizeof(abs_bitmask));
+ memcpy(pEvdev->led_bitmask, led_bitmask, sizeof(led_bitmask));
+ memcpy(pEvdev->absinfo, absinfo, sizeof(absinfo));
+ }
+
+ return Success;
+
+error:
+ return !Success;
+}
+
static int
EvdevProbe(InputInfoPtr pInfo)
{
@@ -1179,6 +1295,8 @@ EvdevPreInit(InputDriverPtr drv, IDevPtr
return NULL;
}
+ EvdevCacheCompare(pInfo, FALSE); /* cache device data */
+
return pInfo;
}
diff -up xf86-input-evdev-2.0.4/src/evdev.h.jx xf86-input-evdev-2.0.4/src/evdev.h
--- xf86-input-evdev-2.0.4/src/evdev.h.jx 2008-09-12 16:04:34.000000000 -0400
+++ xf86-input-evdev-2.0.4/src/evdev.h 2008-09-12 16:04:56.000000000 -0400
@@ -40,6 +40,9 @@
#include <X11/extensions/XKBstr.h>
#endif
+#define LONG_BITS (sizeof(long) * 8)
+#define NBITS(x) (((x) + LONG_BITS - 1) / LONG_BITS)
+
typedef struct {
const char *device;
int kernel24;
@@ -72,6 +75,15 @@ typedef struct {
int reopen_attempts; /* max attempts to re-open after read failure */
int reopen_left; /* number of attempts left to re-open the device */
OsTimerPtr reopen_timer;
+
+ /* Cached info from device. */
+ char name[1024];
+ long bitmask[NBITS(EV_MAX)];
+ long key_bitmask[NBITS(KEY_MAX)];
+ long rel_bitmask[NBITS(REL_MAX)];
+ long abs_bitmask[NBITS(ABS_MAX)];
+ long led_bitmask[NBITS(LED_MAX)];
+ struct input_absinfo absinfo[ABS_MAX];
} EvdevRec, *EvdevPtr;
/* Middle Button emulation */