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.
243 lines
7.7 KiB
Diff
243 lines
7.7 KiB
Diff
diff -up xf86-input-evdev-2.0.4/man/evdev.man.reopen-device xf86-input-evdev-2.0.4/man/evdev.man
|
|
--- xf86-input-evdev-2.0.4/man/evdev.man.reopen-device 2008-08-14 22:27:13.000000000 -0400
|
|
+++ xf86-input-evdev-2.0.4/man/evdev.man 2008-09-12 15:45:50.000000000 -0400
|
|
@@ -67,6 +67,11 @@ button event is registered.
|
|
Sets the timeout (in milliseconds) that the driver waits before deciding
|
|
if two buttons where pressed "simultaneously" when 3 button emulation is
|
|
enabled. Default: 50.
|
|
+.TP 7
|
|
+.BI "Option \*qReopenAttempts\*q \*q" integer \*q
|
|
+Number of reopen attempts after a read error occurs on the device (e.g. after
|
|
+waking up from suspend). In between each attempt is a 100ms wait. Default: 10.
|
|
+
|
|
.SH AUTHORS
|
|
Kristian Høgsberg.
|
|
.SH "SEE ALSO"
|
|
diff -up xf86-input-evdev-2.0.4/src/evdev.c.reopen-device xf86-input-evdev-2.0.4/src/evdev.c
|
|
--- xf86-input-evdev-2.0.4/src/evdev.c.reopen-device 2008-08-14 22:27:13.000000000 -0400
|
|
+++ xf86-input-evdev-2.0.4/src/evdev.c 2008-09-12 15:55:42.000000000 -0400
|
|
@@ -73,6 +73,7 @@
|
|
#define EVDEV_RELATIVE_EVENTS (1 << 2)
|
|
#define EVDEV_ABSOLUTE_EVENTS (1 << 3)
|
|
#define EVDEV_TOUCHPAD (1 << 4)
|
|
+#define EVDEV_INITIALIZED (1 << 5) /* WheelInit etc. called already? */
|
|
|
|
#define MIN_KEYCODE 8
|
|
#define GLYPHS_PER_KEY 2
|
|
@@ -96,6 +97,8 @@ static const char *evdevDefaults[] = {
|
|
NULL
|
|
};
|
|
|
|
+static int EvdevOn(DeviceIntPtr);
|
|
+
|
|
static void
|
|
SetXkbOption(InputInfoPtr pInfo, char *name, char **option)
|
|
{
|
|
@@ -154,6 +157,48 @@ PostKbdEvent(InputInfoPtr pInfo, struct
|
|
xf86PostKeyboardEvent(pInfo->dev, code, value);
|
|
}
|
|
|
|
+
|
|
+/**
|
|
+ * Coming back from resume may leave us with a file descriptor that can be
|
|
+ * opened but fails on the first read (ENODEV).
|
|
+ * In this case, try to open the device until it becomes available or until
|
|
+ * the predefined count expires.
|
|
+ */
|
|
+static CARD32
|
|
+EvdevReopenTimer(OsTimerPtr timer, CARD32 time, pointer arg)
|
|
+{
|
|
+ InputInfoPtr pInfo = (InputInfoPtr)arg;
|
|
+ EvdevPtr pEvdev = pInfo->private;
|
|
+
|
|
+ do {
|
|
+ pInfo->fd = open(pEvdev->device, O_RDWR, 0);
|
|
+ } while (pInfo->fd < 0 && errno == EINTR);
|
|
+
|
|
+ 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);
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ pEvdev->reopen_left--;
|
|
+
|
|
+ if (!pEvdev->reopen_left)
|
|
+ {
|
|
+ xf86Msg(X_ERROR, "%s: Failed to reopen device after %d attempts.\n",
|
|
+ pInfo->name, pEvdev->reopen_attempts);
|
|
+ DisableDevice(pInfo->dev);
|
|
+ pEvdev->reopen_timer = NULL;
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ return 100; /* come back in 100 ms */
|
|
+}
|
|
+
|
|
static void
|
|
EvdevReadInput(InputInfoPtr pInfo)
|
|
{
|
|
@@ -173,6 +218,15 @@ EvdevReadInput(InputInfoPtr pInfo)
|
|
/* The kernel promises that we always only read a complete
|
|
* event, so len != sizeof ev is an error. */
|
|
xf86Msg(X_ERROR, "%s: Read error: %s\n", pInfo->name, strerror(errno));
|
|
+
|
|
+ if (errno == ENODEV) /* May happen after resume */
|
|
+ {
|
|
+ xf86RemoveEnabledDevice(pInfo);
|
|
+ close(pInfo->fd);
|
|
+ pInfo->fd = -1;
|
|
+ pEvdev->reopen_left = pEvdev->reopen_attempts;
|
|
+ pEvdev->reopen_timer = TimerSet(NULL, 0, 100, EvdevReopenTimer, pInfo);
|
|
+ }
|
|
break;
|
|
}
|
|
|
|
@@ -836,6 +890,47 @@ EvdevInit(DeviceIntPtr device)
|
|
return Success;
|
|
}
|
|
|
|
+/**
|
|
+ * Init all extras (wheel emulation, etc.) and grab the device.
|
|
+ *
|
|
+ * Coming from a resume, the grab may fail with ENODEV. In this case, we set a
|
|
+ * timer to wake up and try to reopen the device later.
|
|
+ */
|
|
+static int
|
|
+EvdevOn(DeviceIntPtr device)
|
|
+{
|
|
+ InputInfoPtr pInfo;
|
|
+ EvdevPtr pEvdev;
|
|
+
|
|
+ pInfo = device->public.devicePrivate;
|
|
+ pEvdev = pInfo->private;
|
|
+
|
|
+ if (!pEvdev->kernel24 && ioctl(pInfo->fd, EVIOCGRAB, (void *)1))
|
|
+ xf86Msg(X_WARNING, "%s: Grab failed (%s)\n", pInfo->name,
|
|
+ strerror(errno));
|
|
+
|
|
+ if (errno == ENODEV) /* may happen after resume */
|
|
+ {
|
|
+ close(pInfo->fd);
|
|
+ pInfo->fd = -1;
|
|
+ pEvdev->reopen_left = pEvdev->reopen_attempts;
|
|
+ pEvdev->reopen_timer = TimerSet(NULL, 0, 100, EvdevReopenTimer, pInfo);
|
|
+ } else
|
|
+ {
|
|
+ xf86AddEnabledDevice(pInfo);
|
|
+ if ((pEvdev->flags & EVDEV_BUTTON_EVENTS) &&
|
|
+ !(pEvdev->flags & EVDEV_INITIALIZED))
|
|
+ {
|
|
+ EvdevMBEmuPreInit(pInfo);
|
|
+ }
|
|
+ pEvdev->flags |= EVDEV_INITIALIZED;
|
|
+ device->public.on = TRUE;
|
|
+ }
|
|
+
|
|
+ return Success;
|
|
+}
|
|
+
|
|
+
|
|
static int
|
|
EvdevProc(DeviceIntPtr device, int what)
|
|
{
|
|
@@ -851,30 +946,30 @@ EvdevProc(DeviceIntPtr device, int what)
|
|
return EvdevInit(device);
|
|
|
|
case DEVICE_ON:
|
|
- if (!pEvdev->kernel24 && ioctl(pInfo->fd, EVIOCGRAB, (void *)1))
|
|
- xf86Msg(X_WARNING, "%s: Grab failed (%s)\n", pInfo->name,
|
|
- strerror(errno));
|
|
- if (errno != ENODEV)
|
|
- {
|
|
- xf86AddEnabledDevice(pInfo);
|
|
- if (pEvdev->flags & EVDEV_BUTTON_EVENTS)
|
|
- EvdevMBEmuPreInit(pInfo);
|
|
- device->public.on = TRUE;
|
|
- }
|
|
- break;
|
|
+ return EvdevOn(device);
|
|
|
|
case DEVICE_OFF:
|
|
- if (!pEvdev->kernel24 && ioctl(pInfo->fd, EVIOCGRAB, (void *)0))
|
|
- xf86Msg(X_WARNING, "%s: Release failed (%s)\n", pInfo->name,
|
|
- strerror(errno));
|
|
- xf86RemoveEnabledDevice(pInfo);
|
|
- EvdevMBEmuFinalize(pInfo);
|
|
+ if (pInfo->fd != -1)
|
|
+ {
|
|
+ if (!pEvdev->kernel24 && ioctl(pInfo->fd, EVIOCGRAB, (void *)0))
|
|
+ xf86Msg(X_WARNING, "%s: Release failed (%s)\n", pInfo->name,
|
|
+ strerror(errno));
|
|
+ xf86RemoveEnabledDevice(pInfo);
|
|
+ }
|
|
+ if (pEvdev->flags & EVDEV_INITIALIZED)
|
|
+ EvdevMBEmuFinalize(pInfo);
|
|
+ pEvdev->flags &= ~EVDEV_INITIALIZED;
|
|
device->public.on = FALSE;
|
|
break;
|
|
|
|
case DEVICE_CLOSE:
|
|
xf86Msg(X_INFO, "%s: Close\n", pInfo->name);
|
|
- close(pInfo->fd);
|
|
+ if (pEvdev->reopen_timer) {
|
|
+ TimerCancel(pEvdev->reopen_timer);
|
|
+ pEvdev->reopen_timer = NULL;
|
|
+ }
|
|
+ if (pInfo->fd != -1)
|
|
+ close(pInfo->fd);
|
|
break;
|
|
}
|
|
|
|
@@ -1060,11 +1155,12 @@ EvdevPreInit(InputDriverPtr drv, IDevPtr
|
|
return NULL;
|
|
}
|
|
|
|
+ pEvdev->device = device;
|
|
+
|
|
xf86Msg(deviceFrom, "%s: Device: \"%s\"\n", pInfo->name, device);
|
|
do {
|
|
pInfo->fd = open(device, O_RDWR, 0);
|
|
- }
|
|
- while (pInfo->fd < 0 && errno == EINTR);
|
|
+ } while (pInfo->fd < 0 && errno == EINTR);
|
|
|
|
if (pInfo->fd < 0) {
|
|
xf86Msg(X_ERROR, "Unable to open evdev device \"%s\".\n", device);
|
|
@@ -1072,6 +1168,8 @@ EvdevPreInit(InputDriverPtr drv, IDevPtr
|
|
return NULL;
|
|
}
|
|
|
|
+ pEvdev->reopen_attempts = xf86SetIntOption(pInfo->options, "ReopenAttempts", 10);
|
|
+
|
|
pEvdev->noXkb = noXkbExtension;
|
|
/* parse the XKB options during kbd setup */
|
|
|
|
diff -up xf86-input-evdev-2.0.4/src/evdev.h.reopen-device xf86-input-evdev-2.0.4/src/evdev.h
|
|
--- xf86-input-evdev-2.0.4/src/evdev.h.reopen-device 2008-08-14 22:27:13.000000000 -0400
|
|
+++ xf86-input-evdev-2.0.4/src/evdev.h 2008-09-12 15:55:44.000000000 -0400
|
|
@@ -41,6 +41,7 @@
|
|
#endif
|
|
|
|
typedef struct {
|
|
+ const char *device;
|
|
int kernel24;
|
|
int screen;
|
|
int min_x, min_y, max_x, max_y;
|
|
@@ -67,6 +68,10 @@ typedef struct {
|
|
Time expires; /* time of expiry */
|
|
Time timeout;
|
|
} emulateMB;
|
|
+
|
|
+ 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;
|
|
} EvdevRec, *EvdevPtr;
|
|
|
|
/* Middle Button emulation */
|