diff options
author | Philip Guenther <guenther@cvs.openbsd.org> | 2017-12-31 23:31:42 +0000 |
---|---|---|
committer | Philip Guenther <guenther@cvs.openbsd.org> | 2017-12-31 23:31:42 +0000 |
commit | d519d823a14d9ef7ecbb7d53335573269db47671 (patch) | |
tree | 9525df755f29ad21c9f42f58b678938f819cfbf1 /driver/xf86-input-ws/src | |
parent | 1df1da40d8b5fc197aa9340225d9d74ce9282c63 (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.c | 36 | ||||
-rw-r--r-- | driver/xf86-input-ws/src/ws.h | 2 |
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; |