summaryrefslogtreecommitdiff
path: root/driver/xf86-input-ws/src
diff options
context:
space:
mode:
authorPhilip Guenther <guenther@cvs.openbsd.org>2017-12-31 23:31:42 +0000
committerPhilip Guenther <guenther@cvs.openbsd.org>2017-12-31 23:31:42 +0000
commitd519d823a14d9ef7ecbb7d53335573269db47671 (patch)
tree9525df755f29ad21c9f42f58b678938f819cfbf1 /driver/xf86-input-ws/src
parent1df1da40d8b5fc197aa9340225d9d74ce9282c63 (diff)
If read() returns EIO, then the wsmouse device has gone away and our fd
to it is useless, so detach the xserver driver and close it. Modeled on similar code in xf86-input-{keyboard,mouse} reminded by Frank Groeneveld (frank (at) frankgroeneveld.nl) ok matthieu@ kettenis@
Diffstat (limited to 'driver/xf86-input-ws/src')
-rw-r--r--driver/xf86-input-ws/src/ws.c36
-rw-r--r--driver/xf86-input-ws/src/ws.h2
2 files changed, 36 insertions, 2 deletions
diff --git a/driver/xf86-input-ws/src/ws.c b/driver/xf86-input-ws/src/ws.c
index 268d71401..369a66032 100644
--- a/driver/xf86-input-ws/src/ws.c
+++ b/driver/xf86-input-ws/src/ws.c
@@ -13,7 +13,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-/* $OpenBSD: ws.c,v 1.62 2015/08/29 08:48:29 shadchin Exp $ */
+/* $OpenBSD: ws.c,v 1.63 2017/12/31 23:31:41 guenther Exp $ */
#ifdef HAVE_CONFIG_H
#include "config.h"
@@ -427,6 +427,11 @@ wsDeviceOn(DeviceIntPtr pWS)
}
}
}
+ if (priv->remove_timer == NULL) {
+ /* allocate here where it's safe */
+ priv->remove_timer = TimerSet(priv->remove_timer,
+ 0, 0, NULL, NULL);
+ }
xf86AddEnabledDevice(pInfo);
wsmbEmuOn(pInfo);
pWS->public.on = TRUE;
@@ -457,6 +462,20 @@ wsDeviceOff(DeviceIntPtr pWS)
pWS->public.on = FALSE;
}
+/*
+ * Called as an OsTimer() callback to remove the device while xf86Wakeup()
+ * isn't playing with the list.
+ */
+static CARD32
+wsRemoveMouse(OsTimerPtr timer, CARD32 now, pointer arg)
+{
+ InputInfoPtr pInfo = (InputInfoPtr) arg;
+
+ xf86DisableDevice(pInfo->dev, TRUE);
+
+ return 0; /* don't set to run again */
+}
+
static size_t
wsReadEvents(InputInfoPtr pInfo)
{
@@ -466,7 +485,14 @@ wsReadEvents(InputInfoPtr pInfo)
priv->events_count = priv->events_pos = 0;
len = read(pInfo->fd, priv->events, sizeof(priv->events));
if (len < 0) {
- if (errno != EAGAIN)
+ if (errno == EIO) {
+ xf86IDrvMsg(pInfo, X_ERROR,
+ "device no longer present - removing: %s\n",
+ strerror(errno));
+ xf86RemoveEnabledDevice(pInfo);
+ priv->remove_timer = TimerSet(priv->remove_timer, 0, 1,
+ wsRemoveMouse, pInfo);
+ } else if (errno != EAGAIN)
xf86IDrvMsg(pInfo, X_ERROR, "read error %s\n",
strerror(errno));
} else if (len % sizeof(struct wscons_event)) {
@@ -680,6 +706,12 @@ wsOpen(InputInfoPtr pInfo)
static void
wsClose(InputInfoPtr pInfo)
{
+ WSDevicePtr priv = (WSDevicePtr)pInfo->private;
+
+ if (priv->remove_timer != NULL) {
+ TimerFree(priv->remove_timer);
+ priv->remove_timer = NULL;
+ }
xf86CloseSerial(pInfo->fd);
pInfo->fd = -1;
}
diff --git a/driver/xf86-input-ws/src/ws.h b/driver/xf86-input-ws/src/ws.h
index 5efd063cc..aeac5f258 100644
--- a/driver/xf86-input-ws/src/ws.h
+++ b/driver/xf86-input-ws/src/ws.h
@@ -87,6 +87,8 @@ typedef struct WSDevice {
Time timeout;
} emulateWheel;
+ OsTimerPtr remove_timer; /* Callback for removal on EIO */
+
struct wscons_event events[NWSEVENTS];
size_t events_count;
size_t events_pos;