summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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;