diff -ruN -x Makefile -x configure -x config.cache -x config.h -x *.[178] -x gpm.info -x gpmdoc.ps -x gpmdoc.txt -x gpm-root.c -x stamp-h* -x *.elc -x *.d gpm-1.19.6.orig/src/mice.c gpm-1.19.6/src/mice.c
--- gpm-1.19.6.orig/src/mice.c	Fri Mar 22 19:41:57 2002
+++ gpm-1.19.6/src/mice.c	Fri Mar 22 19:41:19 2002
@@ -5,6 +5,7 @@
  * Copyright (C) 1994-2000   Alessandro Rubini <rubini@linux.it>
  * Copyright (C) 1998,1999   Ian Zimmerman <itz@rahul.net>
  * Copyright (C) 2001        Nico Schottelius <nicos@pcsystems.de>
+ * Copyright (C) 2002        Zephaniah E. Hull <warp@debian.org
  *
  * Tue,  5 Jan 1999 23:44:58 +0000, modified by James Troup <james@nocrew.org>:
  *  Improved (?) descriptions of mouse types.
@@ -63,6 +64,7 @@
 #include <sys/types.h>
 #include <sys/stat.h> /* stat() */
 #include <sys/time.h> /* select() */
+#include <sys/poll.h> /* poll() */
 
 #include <linux/kdev_t.h> /* MAJOR */
 #include <linux/keyboard.h>
@@ -533,62 +535,64 @@
   return 0;
 }
 
+/*
+ * PS/2 mouse parser.
+ * Also called by the 'children' of the PS/2 mouse, for insanity sake.
+ *  -- Zephaniah E. Hull.
+ */
+/* Some PS/2 mice send reports with negative bit set in data[0]
+ * and zero for movement.  I think this is a bug in the mouse, but
+ * working around it only causes artifacts when the actual report is -256;
+ * they'll be treated as zero. This should be rare if the mouse sampling
+ * rate is set to a reasonable value; the default of 100 Hz is plenty.
+ * (Stephen Tell)
+ */
+
 static int M_ps2(Gpm_Event *state,  unsigned char *data)
 {
   static int tap_active=0; /* there exist glidepoint ps2 mice */
 
-  state->buttons=
-    !!(data[0]&1) * GPM_B_LEFT +
-    !!(data[0]&2) * GPM_B_RIGHT +
-    !!(data[0]&4) * GPM_B_MIDDLE;
+  state->dx = state->dy = state->wdx = state->wdy = 0;
+
+  state->buttons =
+    ((data[0] & 0x02) ? (1 << 0) : 0) |		// Right.
+    ((data[0] & 0x04) ? (1 << 1) : 0) |		// Middle.
+    ((data[0] & 0x01) ? (1 << 2) : 0);		// Left.
 
-  if (data[0]==0 && opt_glidepoint_tap) /* by default this is false */
+  if (!data[0] && opt_glidepoint_tap) /* by default this is false */
     state->buttons = tap_active = opt_glidepoint_tap;
   else if (tap_active) {
     if (data[0]==8)
       state->buttons = tap_active = 0;
     else state->buttons = tap_active;
-  }  
+  }
+
+  if (data[1])
+    state->dx =   (data[0] & 0x10) ? data[1]-256 : data[1];
+  if (data[2])
+    state->dy = -((data[0] & 0x20) ? data[2]-256 : data[2]);
 
- /* Some PS/2 mice send reports with negative bit set in data[0]
-  * and zero for movement.  I think this is a bug in the mouse, but
-  * working around it only causes artifacts when the actual report is -256;
-  * they'll be treated as zero. This should be rare if the mouse sampling
-  * rate is set to a reasonable value; the default of 100 Hz is plenty.
-  * (Stephen Tell)
-  */
-  if(data[1] != 0)
-    state->dx=   (data[0] & 0x10) ? data[1]-256 : data[1];
-  else
-    state->dx = 0;
-  if(data[2] != 0)
-    state->dy= -((data[0] & 0x20) ? data[2]-256 : data[2]);
-  else
-    state->dy = 0;
   return 0;
 }
 
+/*
+ * I cheat, because the two protocols are almost identical except for
+ * the 4th and 5th buttons, I just handle both.
+ *
+ * Note, the only thing that I've seen describe the 4th and 5th buttons
+ * for the IMPS/2 protocol is the X4 source, someone let me know if they
+ * actually see this used?
+ *  -- Zephaniah E. Hull.
+ */
 static int M_imps2(Gpm_Event *state,  unsigned char *data)
 {
-  static int tap_active=0;     // there exist glidepoint ps2 mice
-  state->wdx = state->wdy = 0; // Clear them..
-
-  state->dx = state->dy = state->wdx = state->wdy = 0;
-
-  state->buttons= ((data[0] & 1) << 2) // left
-    | ((data[0] & 6) >> 1); // middle and right
-
-  if (data[0]==0 && opt_glidepoint_tap) // by default this is false
-    state->buttons = tap_active = opt_glidepoint_tap;
-  else if (tap_active) {
-    if (data[0]==8)
-      state->buttons = tap_active = 0;
-    else state->buttons = tap_active;
-  }
+  M_ps2(state, data);
 
-  // Standard movement..
-  state->dx = (data[0] & 0x10) ? data[1] - 256 : data[1];
-  state->dy = (data[0] & 0x20) ? -(data[2] - 256) : -data[2];
+  state->buttons +=
+    ((data[0] & 0x40) ? (1 << 3) : 0) | // IMPS/2 Button 4
+    ((data[0] & 0x80) ? (1 << 4) : 0) | // IMPS/2 Button 5
+    ((data[3] & 0x10) ? (1 << 3) : 0) | // EXPS/2 Button 4
+    ((data[3] & 0x20) ? (1 << 4) : 0);  // EXPS/2 Button 5
 
   // The wheels..
   switch (data[3] & 0x0f) {
@@ -1814,97 +1818,167 @@
  * 
  * Returns 0 if OK, or >0 if 1 or more errors occurred.
  */
-static int write_to_mouse(int fd, unsigned char *data, size_t len)
+static int write_ps2(int fd, unsigned char cmd0, unsigned char cmd1,
+    	size_t num, size_t rnum, unsigned long int sleep)
 {
-  int i;
-  int error = 0;
-  for (i = 0; i < len; i++) {
-    unsigned char c;
-    write(fd, &data[i], 1);
-    read(fd, &c, 1);
-    if (c != GPM_AUX_ACK) {
+  int i, error = 0, rcnt;
+  unsigned char cmd[2], ret[512];
+
+  cmd[0] = cmd0; cmd[1] = cmd1;
+
+  if (sleep == -1)
+      sleep = 50000;
+
+  alarm(5);
+  rcnt = write(fd, cmd, num);
+  alarm(0);
+  if (rcnt != num)
+    return 1;
+
+  usleep(sleep);
+
+  alarm(5);
+  rcnt = read(fd, ret, rnum);
+  alarm(0);
+
+  usleep(sleep);
+
+  if (rcnt <= 0)
+	error++;
+
+  for (i = 0; i < rcnt; i++) {
+    if (ret[i] != GPM_AUX_ACK) {
+      gpm_debug_log(LOG_ERR, "write_ps2: %d %d, %x", rcnt, i, ret[i]);
       error++;
     }
   }
 
-  /* flush any left-over input */
-  usleep (30000);
-  tcflush (fd, TCIFLUSH);
   return(error);
 }
 
+static Gpm_Type *get_mouse_type (char *name)
+{
+  Gpm_Type *type;
+
+  for (type=mice; type->fun; type++) {
+    if (strcmp(type->name, name) == 0) {
+      return(type);
+    }
+  }
+  return NULL;
+}
 
 /* intellimouse, ps2 version: Ben Pfaff and Colin Plumb */
 /* Autodetect: Steve Bennett */
-static Gpm_Type *I_imps2(int fd, unsigned short flags, struct Gpm_Type *type)
+static Gpm_Type *I_ps2(int fd, unsigned short flags_unused,
+	struct Gpm_Type *type, int argc, char **argv)
 {
-  int id;
-  static unsigned char basic_init[] = { GPM_AUX_ENABLE_DEV, GPM_AUX_SET_SAMPLE, 100 };
-  static unsigned char imps2_init[] = { GPM_AUX_SET_SAMPLE, 200, GPM_AUX_SET_SAMPLE, 100, GPM_AUX_SET_SAMPLE, 80, };
-  static unsigned char ps2_init[] = { GPM_AUX_SET_SCALE11, GPM_AUX_ENABLE_DEV, GPM_AUX_SET_SAMPLE, 100, GPM_AUX_SET_RES, 3, };
-
-  /* Do a basic init in case the mouse is confused */
-  write_to_mouse(fd, basic_init, sizeof (basic_init));
-
-  /* Now try again and make sure we have a PS/2 mouse */
-  if (write_to_mouse(fd, basic_init, sizeof (basic_init)) != 0) {
-    gpm_debug_log(LOG_ERR, "imps2: PS/2 mouse failed init");
-    return(NULL);
-  }
-
-  /* Try to switch to 3 button mode */
-  if (write_to_mouse(fd, imps2_init, sizeof (imps2_init)) != 0) {
-    gpm_debug_log(LOG_ERR, "imps2: PS/2 mouse failed (3 button) init");
-    return(NULL);
-  }
+  int id, error = 0, rate;
 
-  /* Read the mouse id */
-  id = read_mouse_id(fd);
-  if (id == GPM_AUX_ID_ERROR) {
-    gpm_debug_log(LOG_ERR, "imps2: PS/2 mouse failed to read id, assuming standard PS/2");
-    id = GPM_AUX_ID_PS2;
-  }
+  /* Flush any existing input. */
+  tcflush (fd, TCIOFLUSH);
 
-  /* And do the real initialisation */
-  if (write_to_mouse(fd, ps2_init, sizeof (ps2_init)) != 0) {
-    gpm_debug_log(LOG_ERR, "imps2: PS/2 mouse failed setup, continuing...");
+  if (write_ps2 (fd, GPM_AUX_DEFAULTS, '\0', 1, 1, -1)) {
+    gpm_debug_log(LOG_ERR, "PS/2 mouse failed init");
+    return(NULL);
   }
 
-  if (id == GPM_AUX_ID_IMPS2) {
-    /* Really an intellipoint, so initialise 3 button mode (4 byte packets) */
-    gpm_debug_log(LOG_NOTICE, "imps2: Auto-detected intellimouse PS/2");
-
-    return type;
-  }
-  if (id != GPM_AUX_ID_PS2) {
-    gpm_debug_log(LOG_ERR, "imps2: Auto-detected unknown mouse type %d, assuming standard PS/2", id);
-  }
-  else {
-    gpm_debug_log(LOG_NOTICE, "imps2: Auto-detected standard PS/2");
-  }
-  for (type=mice; type->fun; type++) {
-    if (strcmp(type->name, "ps2") == 0) {
-      return(type);
+  // Magic to enable the IMPS/2 protocol.
+  if ((!strcmp(type->name, "imps2")) || (!strcmp(type->name, "autops2"))) {
+    error += write_ps2 (fd, GPM_AUX_SET_SAMPLE, 200, 2, 2, -1);
+    error += write_ps2 (fd, GPM_AUX_SET_SAMPLE, 100, 2, 2, -1);
+    error += write_ps2 (fd, GPM_AUX_SET_SAMPLE, 80, 2, 2, -1);
+    if (error) {
+      gpm_debug_log(LOG_ERR, "imps2: PS/2 mouse failed (3 button) init");
+      return(NULL);
+    }
+  }
+  if ((!strcmp(type->name, "exps2")) || (!strcmp(type->name, "autops2"))) {
+    error += write_ps2 (fd, GPM_AUX_SET_SAMPLE, 200, 2, 2, -1);
+    error += write_ps2 (fd, GPM_AUX_SET_SAMPLE, 200, 2, 2, -1);
+    error += write_ps2 (fd, GPM_AUX_SET_SAMPLE, 80, 2, 2, -1);
+    if (error) {
+      gpm_debug_log (LOG_ERR, "exps2: PS/2 mouse failed (3 button) init");
+      return (NULL);
+    }
+  }
+
+  if (write_ps2 (fd, GPM_AUX_SET_SCALE11, '\0', 1, 1, -1)) {
+    gpm_debug_log(LOG_ERR, "PS/2 mouse failed init: Unable to set 1:1 scale.");
+    return (NULL);
+  }
+
+  if (opt_sample > 0) {
+    if (opt_sample >= 200) rate = 200;
+    else if (opt_sample >= 100) rate = 100;
+    else if (opt_sample >= 80) rate = 80;
+    else if (opt_sample >= 60) rate = 60;
+    else if (opt_sample >= 40) rate = 40;
+    else if (opt_sample >= 20) rate = 20;
+    else if (opt_sample >= 10) rate = 10;
+    else rate = 100;
+  } else {
+    rate = 100;
+  }
+
+  if (write_ps2 (fd, GPM_AUX_SET_SAMPLE, rate, 2, 1, -1)) {
+    gpm_debug_log(LOG_ERR, "PS/2 mouse failed init: Unable to set rate.");
+    return (NULL);
+  }
+
+  if (!strcmp(type->name, "autops2")) {
+    /* Read the mouse id */
+    id = read_mouse_id(fd);
+
+    switch (id) {
+      case GPM_AUX_ID_ERROR:
+	gpm_debug_log (LOG_ERR, "Unable to read PS/2 mouse ID: Using base PS/2 protocol.\n");
+	write_ps2 (fd, GPM_AUX_SET_STREAM, '\0', 1, 1, 1);
+	write_ps2 (fd, GPM_AUX_ENABLE_DEV, '\0', 1, 1, 1);
+	return get_mouse_type("ps2");
+      case GPM_AUX_ID_PS2:
+	gpm_debug_log(LOG_NOTICE, "Detected base PS/2 protocol mouse.");
+	write_ps2 (fd, GPM_AUX_SET_STREAM, '\0', 1, 1, 1);
+	write_ps2 (fd, GPM_AUX_ENABLE_DEV, '\0', 1, 1, 1);
+	return get_mouse_type("ps2");
+      case GPM_AUX_ID_IMPS2:
+	gpm_debug_log(LOG_NOTICE, "Detected IMPS/2 protocol mouse.");
+	write_ps2 (fd, GPM_AUX_SET_STREAM, '\0', 1, 1, 1);
+	write_ps2 (fd, GPM_AUX_ENABLE_DEV, '\0', 1, 1, 1);
+	return get_mouse_type("imps2");
+      case GPM_AUX_ID_EXPS2:
+	gpm_debug_log(LOG_NOTICE, "Detected EXPS/2 protocol mouse.");
+	write_ps2 (fd, GPM_AUX_SET_STREAM, '\0', 1, 1, 1);
+	write_ps2 (fd, GPM_AUX_ENABLE_DEV, '\0', 1, 1, 1);
+	return get_mouse_type("exps2");
+      default:
+	gpm_debug_log (LOG_ERR, "Unknown mouse ID, using base PS/2 protocol.");
+	write_ps2 (fd, GPM_AUX_SET_STREAM, '\0', 1, 1, 1);
+	write_ps2 (fd, GPM_AUX_ENABLE_DEV, '\0', 1, 1, 1);
+	return get_mouse_type("ps2");
     }
   }
-  /* ps2 was not found!!! */
-  return(NULL);
+
+  write_ps2 (fd, GPM_AUX_SET_STREAM, '\0', 1, 1, 1);
+  write_ps2 (fd, GPM_AUX_ENABLE_DEV, '\0', 1, 1, 1);
+  return type;
 }
 
-/*
- * This works with Dexxa Optical Mouse, but because in X same initstring
- * is named ExplorerPS/2 so I named it in the same way.
- */
-static Gpm_Type *I_exps2(int fd, unsigned short flags,
-			 struct Gpm_Type *type, int argc, char **argv)
+/* PS/2 Init */
+static Gpm_Type *I_fuimps2(int fd, unsigned short flags,
+                               struct Gpm_Type *type, int argc, char **argv)
 {
-  static unsigned char s1[] = { 243, 200, 243, 200, 243, 80, };
+  int error = 0;
 
   if (check_no_argv(argc, argv)) return NULL;
 
-  write (fd, s1, sizeof (s1));
-  usleep (30000);
-  tcflush (fd, TCIFLUSH);
+  // Magic to enable the IMPS/2 protocol.
+  error += write_ps2 (fd, GPM_AUX_SET_SAMPLE, 200, 2, 2, -1);
+  error += write_ps2 (fd, GPM_AUX_SET_SAMPLE, 100, 2, 2, -1);
+  error += write_ps2 (fd, GPM_AUX_SET_SAMPLE, 80, 2, 2, -1);
+  if (error)
+    gpm_debug_log(LOG_ERR, "fuimps2: %d errors in init, ignoring.", error);
+
   return type;
 }
 
@@ -2251,10 +2325,6 @@
   {"bm",   "For some busmice, including Microsoft and Logitech busmice.",
            "BusMouse", M_bm, I_empty, STD_FLG, /* bm is sun */
                                 {0xf8, 0x80, 0x00, 0x00}, 3, 3, 0, 0, 0},
-  {"ps2",  "For most busmice connected to a PS/2 port (round with 6 metal\n"
-           "                     pins).",
-           "PS/2", M_ps2, I_empty, STD_FLG,
-                                {0xc0, 0x00, 0x00, 0x00}, 3, 1, 0, 0, 0},
   {"ncr",  "Ncr3125pen, found on some laptops",
            "", M_ncr, NULL, STD_FLG,
                                 {0x08, 0x08, 0x00, 0x00}, 7, 7, 0, 1, 0},
@@ -2272,14 +2342,26 @@
            "                     Try it if '-t ms' does not work.",
            "", M_bare, I_pnp, CS7 | STD_FLG,
                                 {0x40, 0x40, 0x40, 0x00}, 3, 1, 0, 0, 0},
-  {"imps2","For the Microsoft IntelliMouse on a PS/2 port (round\n"
-           "                     connector with 6 pins), 3 buttons (wheel is repeated).",
-
-           "", M_imps2, I_imps2, STD_FLG,
+  {"ps2",  "For PS/2 mice (round with 6 metal pins).\n",
+           "PS/2", M_ps2, I_ps2, STD_FLG,
+                                {0xc0, 0x00, 0x00, 0x00}, 3, 1, 0, 0, 0},
+  {"fups2",  "For /BROKEN/ PS/2 mice (round with 6 metal pins).\n",
+           "PS/2", M_ps2, I_empty, STD_FLG,
+                                {0xc0, 0x00, 0x00, 0x00}, 3, 1, 0, 0, 0},
+  {"imps2","For the Microsoft IntelliMouse on a PS/2 port\n"
+           "(round connector with 6 pins), 3 buttons (wheel is repeated).",
+           "", M_imps2, I_ps2, STD_FLG,
                                 {0xc0, 0x00, 0x00, 0x00}, 4, 1, 0, 0, 0},
-  {"exps2",   "IntelliMouse Explorer (ps2) - 3 buttons, wheel unused",
-           "ExplorerPS/2", M_ps2, I_exps2, STD_FLG,
+  {"fuimps2","For BROKEN wheel mice on a PS/2 port\n"
+           "(round connector with 6 pins), 3 buttons (wheel is repeated).",
+           "", M_imps2, I_fuimps2, STD_FLG,
                                 {0xc0, 0x00, 0x00, 0x00}, 4, 1, 0, 0, 0},
+  {"exps2",  "IntelliMouse Explorer (ps2) - 3 buttons (wheel is repeated).",
+           "ExplorerPS/2", M_imps2, I_ps2, STD_FLG,
+                                {0xc0, 0x00, 0x00, 0x00}, 4, 1, 0, 0, 0},
+  {"autops2","For PS/2 type mouse, specific protocol will be auto detected",
+           "", M_ps2, I_ps2, STD_FLG,
+                                {0xc0, 0x00, 0x00, 0x00}, 3, 1, 0, 0, 0},
   {"ms3",  "For the Microsoft IntelliMouse (serial), 3 buttons (wheel is repeated).",
            "", M_ms3, I_pnp, CS7 | STD_FLG,
                                 {0xc0, 0x40, 0xc0, 0x00}, 4, 1, 0, 0, R_ms3},
