summaryrefslogtreecommitdiff
path: root/src/sun_mouse.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/sun_mouse.c')
-rw-r--r--src/sun_mouse.c70
1 files changed, 55 insertions, 15 deletions
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;