--- programs/Xserver/hw/tinyx/linux/mouse.c.old	Thu Nov  2 21:51:21 2006
+++ programs/Xserver/hw/tinyx/linux/mouse.c	Thu Jun 11 03:55:09 2009
@@ -1,5 +1,5 @@
 /*
- * $XFree86: xc/programs/Xserver/hw/tinyx/linux/mouse.c,v 1.3 2006/11/02 21:55:26 tsi Exp $
+ * $RCSId: xc/programs/Xserver/hw/kdrive/linux/mouse.c,v 1.6 2002/08/02 16:11:35 keithp Exp $
  *
  * Copyright © 2001 Keith Packard, member of The XFree86 Project, Inc.
  *
@@ -68,19 +68,23 @@
  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
 #define NEED_EVENTS
 #include <X11/X.h>
 #include <X11/Xproto.h>
 #include "inputstr.h"
 #include "scrnintstr.h"
 #include "tinyx.h"
-#include <X11/Xpoll.h>
 #include <errno.h>
+#include <X11/Xpoll.h>
 #include <termios.h>
 
 #undef DEBUG
 #undef DEBUG_BYTES
 #define KBUFIO_SIZE 256
+#define MOUSE_TIMEOUT	100
 
 typedef struct _kbufio {
     int		    fd;
@@ -95,20 +99,32 @@
     fd_set	    set;
     struct timeval  tv, *tp;
     int		    n;
+    CARD32	    done;
 
-    FD_ZERO (&set);
-    FD_SET (fd, &set);
-    if (timeout == -1)
-	tp = 0;
-    else
+    done = GetTimeInMillis () + timeout;
+    for (;;)
     {
-	tv.tv_sec = timeout / 1000;
-	tv.tv_usec = (timeout % 1000) * 1000;
-	tp = &tv;
+	FD_ZERO (&set);
+	FD_SET (fd, &set);
+	if (timeout == -1)
+	    tp = 0;
+	else
+	{
+	    tv.tv_sec = timeout / 1000;
+	    tv.tv_usec = (timeout % 1000) * 1000;
+	    tp = &tv;
+	}
+	n = select (fd + 1, &set, 0, 0, tp);
+	if (n > 0)
+	    return TRUE;
+	if (n < 0 && (errno == EAGAIN || errno == EINTR))
+	{
+	    timeout = (int) (done - GetTimeInMillis ());
+	    if (timeout > 0)
+		continue;
+	}
+	break;
     }
-    n = select (fd + 1, &set, 0, 0, tp);
-    if (n > 0)
-	return TRUE;
     return FALSE;
 }
 
@@ -119,7 +135,12 @@
     if (b->avail <= b->used)
     {
 	if (timeout && !MouseWaitForReadable (b->fd, timeout))
+	{
+#ifdef DEBUG_BYTES
+	    ErrorF ("\tTimeout %d\n", timeout);
+#endif
 	    return -1;
+	}
 	n = read (b->fd, b->buf, KBUFIO_SIZE);
 	if (n <= 0)
 	    return -1;
@@ -132,7 +153,7 @@
     return b->buf[b->used++];
 }
 
-#if 0
+#if NOTUSED
 static int
 MouseFlush (Kbufio *b, char *buf, int size)
 {
@@ -169,7 +190,7 @@
 	--b->used;
     return c;
 }
-#endif
+#endif /* NOTUSED */
 
 static Bool
 MouseWaitForWritable (int fd, int timeout)
@@ -263,8 +284,7 @@
     unsigned long	state;	/* private per protocol, init to prot->state */
 } Kmouse;
     
-static int
-mouseValid (KdMouseInfo *mi, unsigned char *ev, int ne)
+static int mouseValid (KdMouseInfo *mi, unsigned char *ev, int ne)
 {
     Kmouse		*km = mi->driver;
     const KmouseProt	*prot = km->prot;
@@ -281,26 +301,22 @@
     return 0;
 }
 
-static Bool
-threeComplete (KdMouseInfo *mi, unsigned char *ev, int ne)
+static Bool threeComplete (KdMouseInfo *mi, unsigned char *ev, int ne)
 {
     return ne == 3;
 }
 
-static Bool
-fourComplete (KdMouseInfo *mi, unsigned char *ev, int ne)
+static Bool fourComplete (KdMouseInfo *mi, unsigned char *ev, int ne)
 {
     return ne == 4;
 }
 
-static Bool
-fiveComplete (KdMouseInfo *mi, unsigned char *ev, int ne)
+static Bool fiveComplete (KdMouseInfo *mi, unsigned char *ev, int ne)
 {
     return ne == 5;
 }
 
-static Bool
-MouseReasonable (KdMouseInfo *mi, unsigned long flags, int dx, int dy)
+static Bool MouseReasonable (KdMouseInfo *mi, unsigned long flags, int dx, int dy)
 {
     Kmouse		*km = mi->driver;
 
@@ -326,12 +342,12 @@
 /*
  * Standard PS/2 mouse protocol
  */
-static Bool
-ps2Parse (KdMouseInfo *mi, unsigned char *ev, int ne)
+static Bool ps2Parse (KdMouseInfo *mi, unsigned char *ev, int ne)
 {
     Kmouse	    *km = mi->driver;
     int		    dx, dy, dz;
     unsigned long   flags;
+    unsigned long   flagsrelease = 0;
     
     flags = KD_MOUSE_DELTA;
     if (ev[0] & 4)
@@ -344,10 +360,16 @@
     if (ne > 3)
     {
 	dz = (int) (signed char) ev[3];
-	if (dz > 0)
+	if (dz < 0)
+	{
 	    flags |= KD_BUTTON_4;
-	else if (dz < 0)
+	    flagsrelease = KD_BUTTON_4;
+	}
+	else if (dz > 0)
+	{
 	    flags |= KD_BUTTON_5;
+	    flagsrelease = KD_BUTTON_5;
+	}
     }
 	
     dx = ev[1];
@@ -360,7 +382,14 @@
     if (!MouseReasonable (mi, flags, dx, dy))
 	return FALSE;
     if (km->stage == MouseWorking)
+    {
 	KdEnqueueMouseEvent (mi, flags, dx, dy);
+	if (flagsrelease)
+	{
+	    flags &= ~flagsrelease;
+	    KdEnqueueMouseEvent (mi, flags, dx, dy);
+	}
+    }
     return TRUE;
 }
 
@@ -470,7 +499,7 @@
 ps2SkipInit (KdMouseInfo *mi, int ninit, Bool ret_next)
 {
     Kmouse  *km = mi->driver;
-    int	    c = 0;
+    int	    c = -1;
     int	    skipping;
     Bool    waiting;
     
@@ -478,7 +507,7 @@
     waiting = FALSE;
     while (ninit || ret_next)
     {
-	c = MouseReadByte (&km->iob, 100);
+	c = MouseReadByte (&km->iob, MOUSE_TIMEOUT);
 	if (c == -1)
 	    break;
 	/* look for ACK */
@@ -508,7 +537,7 @@
     int		    ninit;
     
     /* Send Intellimouse initialization sequence */
-    MouseWriteBytes (km->iob.fd, intelli_init, strlen ((char *)intelli_init), 100);
+    MouseWriteBytes (km->iob.fd, intelli_init, strlen (intelli_init), 100);
     /*
      * Send ID command
      */
@@ -535,7 +564,7 @@
 	break;
     }
     if (init)
-	MouseWriteBytes (km->iob.fd, init, strlen ((char *)init), 100);
+	MouseWriteBytes (km->iob.fd, init, strlen (init), 100);
     /*
      * Flush out the available data to eliminate responses to the
      * initialization string.  Make sure any partial event is
@@ -545,8 +574,7 @@
     return TRUE;
 }
 
-static Bool
-busParse (KdMouseInfo *mi, unsigned char *ev, int ne)
+static Bool busParse (KdMouseInfo *mi, unsigned char *ev, int ne)
 {
     Kmouse	    *km = mi->driver;
     int		    dx, dy;
@@ -579,8 +607,7 @@
  * Standard MS serial protocol, three bytes
  */
 
-static Bool
-msParse (KdMouseInfo *mi, unsigned char *ev, int ne)
+static Bool msParse (KdMouseInfo *mi, unsigned char *ev, int ne)
 {
     Kmouse	    *km = mi->driver;
     int		    dx, dy;
@@ -619,8 +646,7 @@
  * first byte of a synchronized protocol stream and see if it's got
  * any bits turned on that can't occur in that fourth byte
  */
-static Bool
-logiComplete (KdMouseInfo *mi, unsigned char *ev, int ne)
+static Bool logiComplete (KdMouseInfo *mi, unsigned char *ev, int ne)
 {
     Kmouse		*km = mi->driver;
 
@@ -631,8 +657,7 @@
     return FALSE;
 }
 
-static int
-logiValid (KdMouseInfo *mi, unsigned char *ev, int ne)
+static int logiValid (KdMouseInfo *mi, unsigned char *ev, int ne)
 {
     Kmouse		*km = mi->driver;
     const KmouseProt	*prot = km->prot;
@@ -653,8 +678,7 @@
     return 0;
 }
 
-static Bool
-logiParse (KdMouseInfo *mi, unsigned char *ev, int ne)
+static Bool logiParse (KdMouseInfo *mi, unsigned char *ev, int ne)
 {
     Kmouse	    *km = mi->driver;
     int		    dx, dy;
@@ -704,8 +728,7 @@
 /*
  * Mouse systems protocol, 5 bytes
  */
-static Bool
-mscParse (KdMouseInfo *mi, unsigned char *ev, int ne)
+static Bool mscParse (KdMouseInfo *mi, unsigned char *ev, int ne)
 {
     Kmouse	    *km = mi->driver;
     int		    dx, dy;
@@ -878,6 +901,8 @@
 	    km->invalid += i + km->tested;
 	    km->valid = 0;
 	    km->tested = 0;
+	    if (km->stage == MouseWorking)
+		km->i_prot--;
 	    km->stage = MouseBroken;
 	    if (km->invalid > MAX_SKIP)
 	    {
@@ -921,7 +946,7 @@
 				km->stage = MouseBroken;
 			}
 			break;
-		    default:
+		    case MouseWorking:
 			break;
 		    }
 		}
@@ -936,7 +961,7 @@
 		timeout = 0;
 	    }
 	    else
-		timeout = 100;
+		timeout = MOUSE_TIMEOUT;
 	}
     }
 }
@@ -954,11 +979,11 @@
 
 #define NUM_DEFAULT_MOUSE    (sizeof (kdefaultMouse) / sizeof (kdefaultMouse[0]))
 
-static int
+static Bool
 MouseInit (void)
 {
     int		i;
-    int		fd = -1;
+    int		fd;
     Kmouse	*km;
     KdMouseInfo	*mi, *next;
     int		n = 0;
@@ -977,8 +1002,6 @@
 	{
 	    for (i = 0; i < NUM_DEFAULT_MOUSE; i++)
 	    {
-		if (kdNoSerialMouse && strstr(kdefaultMouse[i], "/dev/ttyS"))
-		    continue;
 		fd = open (kdefaultMouse[i], 2);
 		if (fd >= 0)
 		{
@@ -1010,7 +1033,7 @@
 		close (fd);
 	}
     }
-    return n;
+    return TRUE;
 }
 
 static void
