summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlan Coopersmith <alan.coopersmith@sun.com>2010-01-20 17:47:20 -0800
committerAlan Coopersmith <alan.coopersmith@sun.com>2010-03-22 18:43:43 -0700
commitc74d482378a85eef26dd85fc191f602e0f7c667f (patch)
tree89c91577d918da3e5bc71ed8a023d2ad0bf70e36
parenta2d158c290a831dffef3613ddb736c04377c51e7 (diff)
Solaris: Handle ENODEV & other errors from VUID protocol mice
Adapted code from keyboard fix for ENODEV to do the same thing for the mouse Use normal read() calls for reading from the mouse so we can get the ENODEV errors, instead of going through the Xisb*() wrappers, which are needed for reading directly from serial ports (which this code never does since it's only used with VUID mouse event streams from the kernel). Fixes http://bugs.opensolaris.org/bugdatabase/view_bug.do?bug_id=6844148 Signed-off-by: Alan Coopersmith <alan.coopersmith@sun.com>
-rw-r--r--COPYING2
-rw-r--r--src/sun_mouse.c70
2 files changed, 56 insertions, 16 deletions
diff --git a/COPYING b/COPYING
index 2f7d809..8a618a6 100644
--- a/COPYING
+++ b/COPYING
@@ -1,4 +1,4 @@
-Copyright 2004-2005, 2008-2009 Sun Microsystems, Inc. All rights reserved.
+Copyright 2004-2005, 2008-2010 Sun Microsystems, Inc. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
diff --git a/src/sun_mouse.c b/src/sun_mouse.c
index e16592c..f6e8dbb 100644
--- a/src/sun_mouse.c
+++ b/src/sun_mouse.c
@@ -1,5 +1,5 @@
/*
- * Copyright © 2004-2005, 2008-2009 Sun Microsystems, Inc.
+ * Copyright © 2004-2005, 2008-2010 Sun Microsystems, Inc.
* All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
@@ -103,6 +103,7 @@ typedef struct _VuidMseRec {
#ifdef HAVE_ABSOLUTE_MOUSE_SCALING
Ms_screen_resolution absres;
#endif
+ OsTimerPtr remove_timer; /* Callback for removal on ENODEV */
} VuidMseRec, *VuidMsePtr;
static VuidMsePtr vuidMouseList = NULL;
@@ -134,6 +135,18 @@ VuidMsePtr getVuidMsePriv(InputInfoPtr pInfo)
return m;
}
+/* Called from OsTimer callback, since removing a device from the device
+ list or changing pInfo->fd while xf86Wakeup is looping through the list
+ causes server crashes */
+static CARD32
+vuidRemoveMouse(OsTimerPtr timer, CARD32 time, pointer arg)
+{
+ InputInfoPtr pInfo = (InputInfoPtr) arg;
+
+ xf86DisableDevice(pInfo->dev, TRUE);
+
+ return 0; /* All done, don't set to run again */
+}
/*
* Initialize and enable the mouse wheel, if present.
@@ -330,19 +343,40 @@ vuidReadInput(InputInfoPtr pInfo)
pMse = pInfo->private;
pVuidMse = getVuidMsePriv(pInfo);
buttons = pMse->lastButtons;
- XisbBlockDuration(pMse->buffer, -1);
pBuf = pVuidMse->buffer;
n = 0;
do {
- while (n < sizeof(Firm_event) && (c = XisbRead(pMse->buffer)) >= 0) {
- pBuf[n++] = (unsigned char)c;
- }
-
- if (n == 0)
- return;
-
- if (n != sizeof(Firm_event)) {
+ n = read(pInfo->fd, pBuf, sizeof(Firm_event));
+
+ if (n == 0) {
+ break;
+ } else if (n == -1) {
+ switch (errno) {
+ case EAGAIN: /* Nothing to read now */
+ n = 0; /* End loop, go on to flush events & return */
+ continue;
+ case EINTR: /* Interrupted, try again */
+ continue;
+ case ENODEV: /* May happen when USB mouse is unplugged */
+ /* We use X_NONE here because it doesn't alloc since we
+ may be called from SIGIO handler */
+ xf86MsgVerb(X_NONE, 0,
+ "%s: Device no longer present - removing.\n",
+ pInfo->name);
+ xf86RemoveEnabledDevice(pInfo);
+ pVuidMse->remove_timer =
+ TimerSet(pVuidMse->remove_timer, 0, 1,
+ vuidRemoveMouse, pInfo);
+ return;
+ default: /* All other errors */
+ /* We use X_NONE here because it doesn't alloc since we
+ may be called from SIGIO handler */
+ xf86MsgVerb(X_NONE, 0, "%s: Read error: %s\n", pInfo->name,
+ strerror(errno));
+ return;
+ }
+ } else if (n != sizeof(Firm_event)) {
xf86Msg(X_WARNING, "%s: incomplete packet, size %d\n",
pInfo->name, n);
}
@@ -412,11 +446,6 @@ vuidReadInput(InputInfoPtr pInfo)
}
#endif
- n = 0;
- if ((c = XisbRead(pMse->buffer)) >= 0) {
- /* Another packet. Handle it right away. */
- pBuf[n++] = c;
- }
} while (n != 0);
if (absXset || absYset) {
@@ -559,6 +588,13 @@ vuidMouseProc(DeviceIntPtr pPointer, int what)
vuidMouseSendScreenSize(screenInfo.screens[0], pVuidMse);
#endif
xf86FlushInput(pInfo->fd);
+
+ /* Allocate here so we don't alloc in ReadInput which may be called
+ from SIGIO handler. */
+ if (pVuidMse->remove_timer == NULL) {
+ pVuidMse->remove_timer = TimerSet(pVuidMse->remove_timer,
+ 0, 0, NULL, NULL);
+ }
}
break;
@@ -574,6 +610,10 @@ vuidMouseProc(DeviceIntPtr pPointer, int what)
}
}
}
+ if (pVuidMse->remove_timer) {
+ TimerFree(pVuidMse->remove_timer);
+ pVuidMse->remove_timer = NULL;
+ }
ret = pVuidMse->wrapped_device_control(pPointer, what);
break;