tpconfig (3.1.3-13) debian-changes-3.1.3-13

Summary

 ALPS.c                     |   92 +-
 psaux-2.4.12-combined.diff |  409 +++++++++++
 psaux-2.4.15-combined.diff | 1630 +++++++++++++++++++++++++++++++++++++++++++++
 psaux-2.4.9-combined.diff  |  408 +++++++++++
 synaptics.c                |  105 +-
 tpconfig.c                 |  194 +++--
 tpconfig.h                 |    1 
 utils.c                    |   77 --
 8 files changed, 2724 insertions(+), 192 deletions(-)

    
download this patch

Patch contents

Description: Upstream changes introduced in version 3.1.3-13
 This patch has been created by dpkg-source during the package build.
 Here's the last changelog entry, hopefully it gives details on why
 those changes were made:
 .
 tpconfig (3.1.3-13) unstable; urgency=low
 .
   * Adopt tpconfig. Thanks to Osamu Aoki for his previous work.
     Closes: #479218.
   * Bump Standards Version to 3.9.0. (No changes needed).
   * Correct debian/watch to state that no upstream is available.
   * Update README.Debian to remove outdated information.
   * Remove empty debian/prerm.
   * Rewrite debian/rules to take advantage of debhelper 7.
   * Depends on autotools-dev.
   * Switch to 3.0 (quilt) format.
   * Add a lintian override for sourcing /etc/default/tpconfig: the
     existence of the file is tested in a way that lintian does not detect.
 .
 The person named in the Author field signed this changelog entry.
Author: Vincent Bernat <bernat@debian.org>
Bug-Debian: http://bugs.debian.org/479218

---
The information above should follow the Patch Tagging Guidelines, please
checkout http://dep.debian.net/deps/dep3/ to learn about the format. Here
are templates for supplementary fields that you might want to add:

Origin: <vendor|upstream|other>, <url of original patch>
Bug: <url in upstream bugtracker>
Bug-Debian: http://bugs.debian.org/<bugnumber>
Bug-Ubuntu: https://launchpad.net/bugs/<bugnumber>
Forwarded: <no|not-needed|url proving that it has been forwarded>
Reviewed-By: <name and email of someone who approved the patch>
Last-Update: <YYYY-MM-DD>

--- tpconfig-3.1.3.orig/tpconfig.h
+++ tpconfig-3.1.3/tpconfig.h
@@ -73,6 +73,7 @@
 typedef unsigned char byte;
 
 extern int DEBUG_LEVEL;
+extern int ignore_selected_assertions;
 extern int silent;
 extern float firmware_rev;
 extern char single_mode_byte;
--- tpconfig-3.1.3.orig/synaptics.c
+++ tpconfig-3.1.3/synaptics.c
@@ -185,12 +185,10 @@ static unsigned int model_id;
 #define QUAD_MODE_BYTE		0x0302
 
 void
-synaptics_usage (char *progname) 
+synaptics_usage (void) 
 {
-  copyright ();
-  printf ("Usage: %s [OPTION]...\n", progname);
   printf
-    ("Configure a Synaptics TouchPad.\n"
+    ("Options for a Synaptics TouchPad:\n"
      "\n"
      "  -i, --info                    display current TouchPad configuration\n"
      "  -x, --reset                   perform a software reset on the TouchPad\n"
@@ -241,11 +239,11 @@ synaptics_usage (char *progname)
     }
   printf
     ("\n"
-     "      --help                    display this help and exit\n"
-     "      --version                 output version information\n"
-     "\n"
-     "Report bugs to <kall@compass.com>\n");
-  exit(1);
+     "  -h, --help                    display this help and exit\n"
+     "  -v, --version                 output version information\n"
+     "  -D, --debug=[0-3]             generate debug output\n"
+     "  -d, --device=DEVICE           use alternate device file\n"
+     "\n");
 }
 
 
@@ -282,7 +280,7 @@ status_rqst (int fd, byte cmd, byte *byt
 static void
 set_modes (int fd, unsigned int modes)
 {
-  if (DEBUG_LEVEL)
+  if (DEBUG_LEVEL > DEBUG_LOW)
     fprintf (stderr, "[set modes: %#02x]\n", modes);
   if (single_mode_byte)
     {
@@ -318,7 +316,9 @@ query_identify (int fd,
 {
   byte b1, b2, b3;
   status_rqst (fd, STP_QRY_IDENTIFY, &b1, &b2, &b3);
-  assert (b2 == 0x47);
+  if (!ignore_selected_assertions)
+    /* Recent 2.6 kernels return 0x03 instead.  */
+    assert (b2 == 0x47 || b2 == 0x03);
   if (version_major) (*version_major) = (b3 & 0x0F);
   if (version_minor) (*version_minor) = b1;
   if (model_code)    (*model_code)    = ((b3 & 0xF0) >> 4);
@@ -330,10 +330,13 @@ query_modes (int fd)
   byte b1, b2, b3;
   byte b4, b5, b6;
   status_rqst (fd, STP_QRY_READ_MODES, &b1, &b2, &b3);
-  assert (b2 == 0x47);
+  if (!ignore_selected_assertions)
+    /* Recent 2.6 kernels return 0x03 instead.  */
+    assert (b2 == 0x47 || b2 == 0x03);
   if (single_mode_byte)
     {
-      assert (b1 == 0x3B);
+      if (!ignore_selected_assertions)
+	assert (b1 == 0x3B);
       return b3;
     }
   else
@@ -342,7 +345,9 @@ query_modes (int fd)
       if (fw_version < QUAD_MODE_BYTE)
 	{
 	  status_rqst (fd, STP_QRY_READ_CAPS, &b4, &b5, &b6);
-	  assert (b5 == 0x47);
+	  if (!ignore_selected_assertions)
+	    /* Recent 2.6 kernels return 0x03 instead.  */
+	    assert (b5 == 0x47 || b5 == 0x03);
 	  return ((unsigned int) b1 << 24) | ((unsigned int) b3 << 16) |
 	    ((unsigned int) b4 << 8) | (unsigned int) b6;
 	}
@@ -392,7 +397,8 @@ query_resolutions (int fd, unsigned int
 {
   byte b1, b2, b3;
   status_rqst (fd, STP_QRY_READ_RES, &b1, &b2, &b3);
-  assert ((b2 & 0x80) != 0);
+  if (!ignore_selected_assertions)
+    assert ((b2 & 0x80) != 0);
   (*xres) = b1;
   (*yres) = b3;
 }
@@ -413,7 +419,8 @@ is_Synaptics (int fd)
       b3 = getbyte (fd);
     }
 #endif
-  retval = (b2 == 0x47);
+  /* Recent 2.6 kernels return 0x03 instead.  */
+  retval = (b2 == 0x47 || b2 == 0x03);
   if (retval)
     {
       fw_version_major = (b3 & 0x0F);
@@ -426,11 +433,12 @@ is_Synaptics (int fd)
 void
 reset_synaptics (int fd)
 {
-  fprintf (stderr,"Performing software reset on TouchPad.\n");
+  fprintf (stdout,"Performing software reset on TouchPad.\n");
   putbyte (fd, AUX_RESET);
   getbyte_expected (fd, AUX_RESET_ACK1, "software reset ACK 1");
   getbyte_expected (fd, AUX_RESET_ACK2, "software reset ACK 2");
-  fprintf (stderr, "Software reset of TouchPad complete.\n");
+  putbyte (fd, AUX_ENABLE_DEV);
+  fprintf (stdout, "Software reset of TouchPad complete.\n");
 }
 
 void
@@ -572,6 +580,8 @@ set_z_threshold (int fd)
   if (optarg)
     {
       int a = get_argument (7);
+      if (DEBUG_LEVEL)
+        fprintf (stderr, "Z threshold set as \"%s\".\n", optarg);
       if (a < 0)
 	{
 	  fprintf (stderr, "Invalid Z threshold \"%s\" [use 0-7].\n", optarg);
@@ -580,7 +590,7 @@ set_z_threshold (int fd)
       set_modes (fd, STP_SET_OMODE_Z_THRESH (query_modes (fd), a));
     }
   if (!silent)
-    show_z_threshold (query_modes (fd), stderr);
+    show_z_threshold (query_modes (fd), stdout);
 }
 
 static void
@@ -590,6 +600,8 @@ set_tap_mode (int fd)
   if (optarg)
     {
       int a = get_argument (limit);
+      if (DEBUG_LEVEL)
+        fprintf (stderr, "Tap mode set as \"%s\".\n", optarg);
       if (a < 0)
 	{
 	  fprintf (stderr, "Invalid tap mode \"%s\" [use 0-%d].\n",
@@ -602,7 +614,7 @@ set_tap_mode (int fd)
 	set_modes (fd, STP_SET_OMODE_TAP_MODE (query_modes (fd), a));
     }
   if (!silent)
-    show_tap_mode (query_modes (fd), stderr);
+    show_tap_mode (query_modes (fd), stdout);
 }
 
 static void
@@ -616,6 +628,8 @@ set_edge_motion (int fd)
   if (optarg)
     {
       int a = get_argument (3);
+      if (DEBUG_LEVEL)
+        fprintf (stderr, "Edge motion set as \"%s\".\n", optarg);
       if (a < 0 || a == 2)
 	{
 	  fprintf (stderr, "Invalid edge motion \"%s\" [use 0, 1, 3].\n",
@@ -625,7 +639,7 @@ set_edge_motion (int fd)
       set_modes (fd, STP_SET_OMODE_EDGE_MOTN (query_modes (fd), a));
     }
   if (!silent)
-    show_edge_motion (query_modes (fd), stderr);
+    show_edge_motion (query_modes (fd), stdout);
 }
 
 static void
@@ -639,6 +653,8 @@ set_corner_mode (int fd)
   if (optarg)
     {
       int a = get_argument (1);
+      if (DEBUG_LEVEL)
+        fprintf (stderr, "Corner mode set as \"%s\".\n", optarg);
       if (a < 0)
 	{
 	  fprintf (stderr, "Invalid corner mode \"%s\" [use 0-1].\n", optarg);
@@ -647,7 +663,7 @@ set_corner_mode (int fd)
       set_modes (fd, STP_SET_OMODE_CORNER (query_modes (fd), a));
     }
   if (!silent)
-    show_tap_mode (query_modes (fd), stderr);
+    show_tap_mode (query_modes (fd), stdout);
 }
 
 static void
@@ -658,7 +674,7 @@ set_packet_mode (int fd, int absolute)
   else
     set_modes (fd, STP_SET_OMODE_ABSOLUTE (query_modes (fd), absolute));
   if (!silent)
-    show_packet_mode (query_modes (fd), stderr);
+    show_packet_mode (query_modes (fd), stdout);
 }
 
 static void
@@ -667,6 +683,8 @@ set_rate (int fd)
   if (optarg)
     {
       int a = get_argument (1);
+      if (DEBUG_LEVEL)
+        fprintf (stderr, "Rate set as \"%s\".\n", optarg);
       if (a < 0)
 	{
 	  fprintf (stderr, "Invalid rate \"%s\" [use 0-%c].\n",
@@ -679,7 +697,7 @@ set_rate (int fd)
 	set_modes (fd, STP_SET_OMODE_RATE (query_modes (fd), a));
     }
   if (!silent)
-    show_packet_mode (query_modes (fd), stderr);
+    show_packet_mode (query_modes (fd), stdout);
 }
 
 static void
@@ -692,7 +710,7 @@ set_button_mode (int fd, int three)
     }
   set_modes (fd, STP_SET_OMODE_3_BUTTON (query_modes (fd), three));
   if (!silent)
-    show_button_mode (query_modes (fd), stderr);
+    show_button_mode (query_modes (fd), stdout);
 }
 
 static void
@@ -705,7 +723,7 @@ set_corner_click (int fd, int middle)
     }
   set_modes (fd, STP_SET_OMODE_MIDDLE (query_modes (fd), middle));
   if (!silent)
-    show_button_mode (query_modes (fd), stderr);
+    show_button_mode (query_modes (fd), stdout);
 }
 
 static void
@@ -719,6 +737,8 @@ set_sleep_mode (int fd)
   if (optarg)
     {
       int a = get_argument (1);
+      if (DEBUG_LEVEL)
+        fprintf (stderr, "Sleep mode set as \"%s\".\n", optarg);
       if (a < 0)
 	{
 	  fprintf (stderr, "Invalid sleep mode \"%s\" [use 0-1].\n", optarg);
@@ -727,7 +747,7 @@ set_sleep_mode (int fd)
       set_modes (fd, STP_SET_MODE_SLEEP (query_modes (fd), a));
     }
   if (!silent)
-    show_sleep_mode (query_modes (fd), stderr);
+    show_sleep_mode (query_modes (fd), stdout);
 }
 
 static void
@@ -741,6 +761,8 @@ set_right_margin (int fd)
   if (optarg)
     {
       int a = get_argument (15);
+      if (DEBUG_LEVEL)
+        fprintf (stderr, "Right margin set as \"%s\".\n", optarg);
       if (a < 0)
 	{
 	  fprintf (stderr, "Invalid right margin \"%s\" [use 0-15].\n", optarg);
@@ -749,7 +771,7 @@ set_right_margin (int fd)
       set_modes (fd, STP_SET_OMODE_RIGHT_MGN (query_modes (fd), a));
     }
   if (!silent)
-    show_margins (query_modes (fd), stderr);
+    show_margins (query_modes (fd), stdout);
 }
 
 static void
@@ -763,6 +785,8 @@ set_left_margin (int fd)
   if (optarg)
     {
       int a = get_argument (15);
+      if (DEBUG_LEVEL)
+        fprintf (stderr, "Left margin set as \"%s\".\n", optarg);
       if (a < 0)
 	{
 	  fprintf (stderr, "Invalid left margin \"%s\" [use 0-15].\n", optarg);
@@ -771,7 +795,7 @@ set_left_margin (int fd)
       set_modes (fd, STP_SET_OMODE_LEFT_MGN (query_modes (fd), a));
     }
   if (!silent)
-    show_margins (query_modes (fd), stderr);
+    show_margins (query_modes (fd), stdout);
 }
 
 static void
@@ -785,6 +809,8 @@ set_top_margin (int fd)
   if (optarg)
     {
       int a = get_argument (15);
+      if (DEBUG_LEVEL)
+        fprintf (stderr, "Top margin set as \"%s\".\n", optarg);
       if (a < 0)
 	{
 	  fprintf (stderr, "Invalid top margin \"%s\" [use 0-15].\n", optarg);
@@ -793,7 +819,7 @@ set_top_margin (int fd)
       set_modes (fd, STP_SET_OMODE_TOP_MGN (query_modes (fd), a));
     }
   if (!silent)
-    show_margins (query_modes (fd), stderr);
+    show_margins (query_modes (fd), stdout);
 }
 
 static void
@@ -807,6 +833,8 @@ set_bottom_margin (int fd)
   if (optarg)
     {
       int a = get_argument (15);
+      if (DEBUG_LEVEL)
+        fprintf (stderr, "Bottom margin set as \"%s\".\n", optarg);
       if (a < 0)
 	{
 	  fprintf (stderr, "Invalid bottom margin \"%s\" [use 0-15].\n", optarg);
@@ -815,7 +843,7 @@ set_bottom_margin (int fd)
       set_modes (fd, STP_SET_OMODE_BOTTOM_MGN (query_modes (fd), a));
     }
   if (!silent)
-    show_margins (query_modes (fd), stderr);
+    show_margins (query_modes (fd), stdout);
 }
 
 static void
@@ -901,7 +929,9 @@ synaptics_functions (int c, int fd, char
   switch (c) 
     {
     case 'h': /* --help */
-      synaptics_usage (argv[0]);
+      printf ("Usage: %s [OPTION]...\n", (argv[0]));
+      synaptics_usage ();
+      printf ("Report bugs to <kall@compass.com>\n");
       break;
     case 'q': /* --quiet */
       silent = 1;
@@ -909,12 +939,9 @@ synaptics_functions (int c, int fd, char
     case 'x': /* --reset */
       reset_synaptics (fd);
       break;
-    case 'v': /* --version */
-      version_info ();
-      break;
     case 'i': /* --info */
       if (!silent)
-	synaptics_info (fd, stderr);
+	synaptics_info (fd, stdout);
       break;
     case 'z': /* --zthreshold */
       set_z_threshold (fd);
@@ -945,7 +972,7 @@ synaptics_functions (int c, int fd, char
 	    set_packet_mode (fd, a);
 	}
       else if (!silent)
-	show_tap_mode (query_modes (fd), stderr);
+	show_tap_mode (query_modes (fd), stdout);
       break;
     case 'r': /* --rate */
       set_rate (fd);
@@ -975,7 +1002,7 @@ synaptics_functions (int c, int fd, char
 	    set_corner_click (fd, a);
 	}
       else if (!silent)
-	show_button_mode (query_modes (fd), stderr);
+	show_button_mode (query_modes (fd), stdout);
       break;
     case 's': /* --sleep */
       set_sleep_mode (fd);
@@ -985,7 +1012,7 @@ synaptics_functions (int c, int fd, char
 	fprintf (stderr, "Adjustable margins not supported on this TouchPad.\n");
       else if (!silent)
 	/* Firmware prior to version 3.2 has four mode bytes */
-	show_margins (query_modes (fd), stderr);
+	show_margins (query_modes (fd), stdout);
       break;
     case '4': /* --right-margin */
       set_right_margin (fd);
--- tpconfig-3.1.3.orig/tpconfig.c
+++ tpconfig-3.1.3/tpconfig.c
@@ -106,15 +106,17 @@ static char rcsid[]="$Id: tpconfig.c,v 2
 
 #include "tpconfig.h"
 
-extern void synaptics_usage(char *progname);
+extern void synaptics_usage(void);
 extern void set_firmware_options(int fd, FILE *out);
-extern void ALPS_usage(char *progname);
+extern void ALPS_usage(void);
 extern void synaptics_functions(int c,int fd,char **argv);
 extern void alps_functions(int c,int fd,char **argv);
 extern int is_ALPS(int fd);
 extern int is_Synaptics(int fd);
 
 int DEBUG_LEVEL;
+int ignore_selected_assertions;
+char mousedev[128] = "/dev/psaux";
 int silent;
 float firmware_rev;
 char single_mode_byte;
@@ -126,10 +128,17 @@ void init_fd(int *fd)
 int status;
 if (*fd<0)
   {
-  *fd = open("/dev/psaux", O_RDWR|O_NDELAY);
+  if (DEBUG_LEVEL)
+    fprintf (stderr, "Probing mouse port [%s].\n", mousedev);
+  *fd = open(mousedev, O_RDWR|O_NDELAY);
   if (*fd < 0)
-    fatal("Could not open PS/2 Port [/dev/psaux]");
+    {
+      fprintf(stderr, "Could not open PS/2 Port [%s].\n", mousedev);
+      exit (0);
+    }
 #ifdef __linux
+  if (DEBUG_LEVEL)
+    fprintf (stderr, "Grabbing mouse port [%s].\n", mousedev);
   /* If AUX_GRAB kernel patch present, use it. */
   while (ioctl (*fd, AUX_GRAB, 0) < 0)
     {
@@ -137,15 +146,19 @@ if (*fd<0)
 	break;
       if (errno != EAGAIN)
 	{
-	  perror ("/dev/psaux");
+	  perror (mousedev);
 	  fatal ("Unable to get exclusive access to PS/2 Port.");
 	  exit (1);
 	}
     }
 #endif
   tcflush(*fd,TCIOFLUSH);
+  if (DEBUG_LEVEL)
+    fprintf (stderr, "Trying Synaptics detection.\n");
   if (!is_Synaptics(*fd))
     {
+    if (DEBUG_LEVEL)
+      fprintf (stderr, "Trying Alps detection.\n");
     status = is_ALPS(*fd);
     if(status == 0)
       {
@@ -191,7 +204,97 @@ DEBUG_LEVEL = DEBUG_NONE;
 DEBUG_LEVEL = DEBUG_LOW;
 #endif
 
-copyright();
+static struct option synaptics_long_options[] =
+  {
+    {"help",          no_argument, NULL, 'h'}, /* -h */
+    {"version",       no_argument, NULL, 'v'}, /* -v */
+    {"debug",         optional_argument, NULL, 'D'}, /* -D */
+    {"device",        required_argument, NULL, 'd'}, /* -d */
+    {"silent",        no_argument, NULL, 'q'}, /* -q */
+    {"quiet",         no_argument, NULL, 'q'}, /* -q */
+    {"info",          no_argument, NULL, 'i'}, /* -i */
+    {"reset",         no_argument, NULL, 'x'}, /* -x */
+    /* Mode 1 options */
+    {"zthreshold",    optional_argument, NULL, 'z'}, /* -z */
+    {"threshold",     optional_argument, NULL, 'z'}, /* -z */
+    {"corner",        optional_argument, NULL, 'c'}, /* -c */
+    {"tapmode",       optional_argument, NULL, 't'}, /* -t */
+    {"edgemode",      optional_argument, NULL, 'e'}, /* -e */
+    /* Mode 2 options */
+    {"absolute",      no_argument, NULL, 'A'},       /* similar to -a */
+    {"relative",      no_argument, NULL, 'R'},       /* similar to -a */
+    {"rate",          optional_argument, NULL, 'r'}, /* -r */
+    {"two-button",    no_argument, NULL, '2'},       /* -2 */
+    {"three-button",  no_argument, NULL, '3'},       /* -3 */
+    {"middle-button", no_argument, NULL, '<'},       /* similar to -m */
+    {"right-button",  no_argument, NULL, '>'},       /* similar to -m */
+    {"sleep",         optional_argument, NULL, 's'}, /* -s */
+    /* Mode 3 options */
+    {"right-margin",  optional_argument, NULL, '4'}, /* similar to -M */
+    {"left-margin",   optional_argument, NULL, '5'}, /* similar to -M */
+    /* Mode 4 options */
+    {"top-margin",    optional_argument, NULL, '6'}, /* similar to -M */
+    {"bottom-margin", optional_argument, NULL, '7'}, /* similar to -M */
+    {NULL,            no_argument, NULL, 0}
+  };
+const char * synaptics_short_options = "hvD::d:qiz::x::c::t::e::a::r::23m::s::M";
+
+static struct option ALPS_long_options[] = 
+  {
+    {"help",          no_argument, NULL, 'h'}, /* -h */
+    {"version",       no_argument, NULL, 'v'}, /* -v */
+    {"debug",         optional_argument, NULL, 'D'}, /* -D */
+    {"device",        required_argument, NULL, 'd'}, /* -d */
+    {"info",		no_argument, NULL, 'i'}, /* -i */
+    {"reset",         no_argument, NULL, 'x'}, /* -x */
+    {"tapmode",	optional_argument, NULL, 't'}, /* -t */
+    {NULL, 		no_argument, NULL, 0}
+  };
+const char * ALPS_short_options = "hvD::d:irt::";
+
+/* Initial option processing to handle special options.  */
+optind = 1;
+while (1)
+  {
+    switch (getopt_long (argc, argv, synaptics_short_options,
+			 synaptics_long_options, &option_index))
+      {
+      case 'h':
+	printf ("Usage: %s [OPTION]...\n", (argv[0]));
+	synaptics_usage ();
+	ALPS_usage ();
+	printf ("Report bugs to <kall@compass.com>\n");
+	return (0);
+
+      case 'v':
+	copyright ();
+	return (0);
+
+      case 'D':
+	if (optarg == 0)
+	  DEBUG_LEVEL = DEBUG_LOW;
+	else if ((strcmp (optarg, "0")) == 0)
+	  DEBUG_LEVEL = DEBUG_NONE;
+	else if ((strcmp (optarg, "1")) == 0)
+	  DEBUG_LEVEL = DEBUG_LOW;
+	else if ((strcmp (optarg, "2")) == 0)
+	  DEBUG_LEVEL = DEBUG_MEDIUM;
+	else
+	  DEBUG_LEVEL = DEBUG_HIGH;
+	break;
+
+      case 'd':
+	strncpy (mousedev, optarg, ((sizeof (mousedev)) - 1));
+	break;
+
+      case -1:
+	goto initial_options_done;
+
+      default:
+	break;
+      }
+  }
+initial_options_done:
 
 
 /* Open file descriptor and determine if we are connected to a touchpad */
@@ -200,72 +303,37 @@ init_fd(&fd);
 if(touchpad_type == SYNAPTICS_TOUCHPAD)
   set_firmware_options(fd,stdout);
 
-if((argc <  2)  && (touchpad_type == SYNAPTICS_TOUCHPAD))
-  synaptics_usage(argv[0]); /* no command line options */
-else if((argc <  2)  && 
-    ((touchpad_type == ALPS_GLIDEPAD) || (touchpad_type == ALPS_STICKPOINTER_AND_GLIDEPOINT)))
-  ALPS_usage(argv[0]);
-
+optind = 1;
 opterr=1;
 while (1) 
   {
-  static struct option synaptics_long_options[] =
-    {
-      {"help",          no_argument, NULL, 'h'},
-      {"silent",        no_argument, NULL, 'q'}, /* -q */
-      {"quiet",         no_argument, NULL, 'q'}, /* -q */
-      {"info",          no_argument, NULL, 'i'}, /* -i */
-      {"version",       no_argument, NULL, 'v'}, /* -v */
-      {"reset",         no_argument, NULL, 'x'}, /* -x */
-      /* Mode 1 options */
-      {"zthreshold",    optional_argument, NULL, 'z'}, /* -z */
-      {"threshold",     optional_argument, NULL, 'z'}, /* -z */
-      {"corner",        optional_argument, NULL, 'c'}, /* -c */
-      {"tapmode",       optional_argument, NULL, 't'}, /* -t */
-      {"edgemode",      optional_argument, NULL, 'e'}, /* -e */
-      /* Mode 2 options */
-      {"absolute",      no_argument, NULL, 'A'},       /* similar to -a */
-      {"relative",      no_argument, NULL, 'R'},       /* similar to -a */
-      {"rate",          optional_argument, NULL, 'r'}, /* -r */
-      {"two-button",    no_argument, NULL, '2'},       /* -2 */
-      {"three-button",  no_argument, NULL, '3'},       /* -3 */
-      {"middle-button", no_argument, NULL, '<'},       /* similar to -m */
-      {"right-button",  no_argument, NULL, '>'},       /* similar to -m */
-      {"sleep",         optional_argument, NULL, 's'}, /* -s */
-      /* Mode 3 options */
-      {"right-margin",  optional_argument, NULL, '4'}, /* similar to -M */
-      {"left-margin",   optional_argument, NULL, '5'}, /* similar to -M */
-      /* Mode 4 options */
-      {"top-margin",    optional_argument, NULL, '6'}, /* similar to -M */
-      {"bottom-margin", optional_argument, NULL, '7'}, /* similar to -M */
-      {NULL,            no_argument, NULL, 0}
-    };
-
-  static struct option ALPS_long_options[] = 
-    {
-      {"help",		no_argument, NULL, 'h'},
-      {"info",		no_argument, NULL, 'i'}, /* -i */
-      {"reset",         no_argument, NULL, 'x'}, /* -x */
-      {"tapmode",	optional_argument, NULL, 't'}, /* -t */
-      {"version", 	no_argument, NULL, 'v'}, /* -v */
-      {NULL, 		no_argument, NULL, 0}
-    };
-
   if(touchpad_type == SYNAPTICS_TOUCHPAD)
-    c = getopt_long (argc, argv, "qivzx::c::t::e::a::r::23m::s::M",
+    c = getopt_long (argc, argv, synaptics_short_options,
       synaptics_long_options, &option_index);
   else if((touchpad_type == ALPS_STICKPOINTER_AND_GLIDEPOINT) || (touchpad_type == ALPS_GLIDEPAD))
-    c = getopt_long (argc, argv, "hirtv",
+    c = getopt_long (argc, argv, ALPS_short_options,
       ALPS_long_options, &option_index);
 
-  if (c == -1)
-    break;
-  
-  if(touchpad_type == SYNAPTICS_TOUCHPAD)
-    synaptics_functions(c,fd,argv);
-  else if((touchpad_type == ALPS_STICKPOINTER_AND_GLIDEPOINT) || (touchpad_type == ALPS_GLIDEPAD))
-    alps_functions(c,fd,argv);
+  switch (c)
+    {
+    case 'h':
+    case 'v':
+    case 'D':
+    case 'd':
+      break;
+
+    case -1:
+      goto options_done;
+
+    default:
+      if (touchpad_type == SYNAPTICS_TOUCHPAD)
+	synaptics_functions (c, fd, argv);
+      else if ((touchpad_type == ALPS_STICKPOINTER_AND_GLIDEPOINT)
+	       || (touchpad_type == ALPS_GLIDEPAD))
+	alps_functions (c, fd, argv);
+    }
   }
+options_done:
 if (optind < argc) 
   {
   fprintf(stderr, "Extra options: ");
--- /dev/null
+++ tpconfig-3.1.3/psaux-2.4.12-combined.diff
@@ -0,0 +1,409 @@
+diff -ruN linux-2.4.12-orig/drivers/char/pc_keyb.c linux-2.4.12/drivers/char/pc_keyb.c
+--- linux-2.4.12-orig/drivers/char/pc_keyb.c	Tue Sep 18 01:52:35 2001
++++ linux-2.4.12/drivers/char/pc_keyb.c	Thu Oct 11 13:10:03 2001
+@@ -13,6 +13,15 @@
+  * Code fixes to handle mouse ACKs properly.
+  * C. Scott Ananian <cananian@alumni.princeton.edu> 1999-01-29.
+  *
++ * More work to handle mouse ACKs properly.  (Modified version of
++ * patch by Julian Bradfield <jcb@dcs.ed.ac.uk>.)
++ * Chris Hanson <cph@zurich.ai.mit.edu> 2000-12-11.
++ *
++ * Implement exclusive access mechanism for aux device.
++ * This permits grabbing the mouse away from the X server,
++ * which is needed by fancy mice that have configurable features.
++ * Chris Hanson <cph@zurich.ai.mit.edu> 2000-10-30.
++ *
+  */
+ 
+ #include <linux/config.h>
+@@ -66,6 +75,8 @@
+ static void aux_write_ack(int val);
+ static void __aux_write_ack(int val);
+ static int aux_reconnect = 0;
++static void aux_kill_fasync(struct fasync_struct **fasync, int sig, int band);
++static int aux_release_ioctl(struct file *file);
+ #endif
+ 
+ static spinlock_t kbd_controller_lock = SPIN_LOCK_UNLOCKED;
+@@ -89,13 +100,30 @@
+  
+ static struct aux_queue *queue;	/* Mouse data buffer. */
+ static int aux_count;
+-/* used when we send commands to the mouse that expect an ACK. */
++/* Used when we (as opposed to user programs using the aux device)
++   send commands to the mouse. */
+ static unsigned char mouse_reply_expected;
+ 
++/* Used to make sure we have received an ACK from the byte last
++   written to the mouse before writing another.  */
++static unsigned long mouse_ack_pending;
++static wait_queue_head_t mouse_ack_wait;
++/* How many jiffies to wait for the mouse to respond to a command with
++   an ACK.  25 msec is the maximum allowed delay for the hardware to
++   respond.  We round that up to the nearest jiffy.  */
++#define MOUSE_ACK_TIMEOUT ((25 * HZ + 999) / 1000)
++
+ #define AUX_INTS_OFF (KBD_MODE_KCC | KBD_MODE_DISABLE_MOUSE | KBD_MODE_SYS | KBD_MODE_KBD_INT)
+ #define AUX_INTS_ON  (KBD_MODE_KCC | KBD_MODE_SYS | KBD_MODE_MOUSE_INT | KBD_MODE_KBD_INT)
+ 
+ #define MAX_RETRIES	60		/* some aux operations take long time*/
++
++/* Support for exclusive access to the AUX device. */
++static struct file *aux_exclusive;
++static wait_queue_head_t aux_exclusive_wait;
++static unsigned long aux_last_write;
++#define AUX_GRAB _IO('M', 1)
++#define AUX_RELEASE _IO('M', 2)
+ #endif /* CONFIG_PSMOUSE */
+ 
+ /*
+@@ -427,6 +455,13 @@
+ {
+ #ifdef CONFIG_PSMOUSE
+ 	static unsigned char prev_code;
++ 	if (mouse_ack_pending) {
++ 		/* It needn't actually be an ack, it could be an echo;
++ 		   but every byte sent to the mouse results in a byte
++ 		   back. */
++ 		wake_up_interruptible(&mouse_ack_wait);
++ 		mouse_ack_pending = 0;
++ 	}
+ 	if (mouse_reply_expected) {
+ 		if (scancode == AUX_ACK) {
+ 			mouse_reply_expected--;
+@@ -451,7 +486,7 @@
+ 		head = (head + 1) & (AUX_BUF_SIZE-1);
+ 		if (head != queue->tail) {
+ 			queue->head = head;
+-			kill_fasync(&queue->fasync, SIGIO, POLL_IN);
++			aux_kill_fasync(&queue->fasync, SIGIO, POLL_IN);
+ 			wake_up_interruptible(&queue->proc_list);
+ 		}
+ 	}
+@@ -968,19 +1003,75 @@
+ 	return retval;
+ }
+ 
++static void mouse_ack_timeout(unsigned long data)
++{
++	wake_up_interruptible(&mouse_ack_wait);
++}
++
+ /*
+  * Send a byte to the mouse.
+  */
+-static void aux_write_dev(int val)
++static int aux_write_dev(int val, int dont_block, int handle_ack)
+ {
+ 	unsigned long flags;
+ 
+ 	spin_lock_irqsave(&kbd_controller_lock, flags);
+ 	kb_wait();
++	/* If we haven't yet received the ACK from the previous write,
++	   we must wait for it.  */
++	if (mouse_ack_pending) {
++		unsigned long expires;
++		struct timer_list timer;
++		DECLARE_WAITQUEUE(wait, current);
++
++		if (dont_block) {
++			spin_unlock_irqrestore(&kbd_controller_lock, flags);
++			return -EAGAIN;
++		}
++		expires = mouse_ack_pending + MOUSE_ACK_TIMEOUT;
++		if (jiffies >= expires)
++			goto timed_out;
++
++		add_wait_queue(&mouse_ack_wait, &wait);
++		init_timer (&timer);
++		timer.expires = expires;
++		timer.data = 0;
++		timer.function = mouse_ack_timeout;
++		add_timer(&timer);
++
++		do {
++			current->state = TASK_INTERRUPTIBLE;
++			spin_unlock_irqrestore(&kbd_controller_lock, flags);
++			schedule();
++			spin_lock_irqsave(&kbd_controller_lock, flags);
++		} while (mouse_ack_pending
++			 && jiffies < expires
++			 && !signal_pending(current));
++
++		del_timer(&timer);
++		remove_wait_queue(&mouse_ack_wait, &wait);
++
++		if (mouse_ack_pending && jiffies >= expires) {
++		timed_out:
++			printk(KERN_WARNING "mouse ack timeout\n");
++			mouse_ack_pending = 0;
++			spin_unlock_irqrestore(&kbd_controller_lock, flags);
++			return -EIO;
++		}
++		if (signal_pending(current)) {
++			spin_unlock_irqrestore(&kbd_controller_lock, flags);
++			return -ERESTARTSYS;
++		}
++	}
+ 	kbd_write_command(KBD_CCMD_WRITE_MOUSE);
+ 	kb_wait();
+ 	kbd_write_output(val);
++	mouse_ack_pending = jiffies;
++	if (handle_ack)
++		/* We will deal with the ACK ourselves.  */
++		mouse_reply_expected++;
+ 	spin_unlock_irqrestore(&kbd_controller_lock, flags);
++	return 0;
+ }
+ 
+ /*
+@@ -992,11 +1083,13 @@
+ 	kbd_write_command(KBD_CCMD_WRITE_MOUSE);
+ 	kb_wait();
+ 	kbd_write_output(val);
+-	/* we expect an ACK in response. */
++	mouse_ack_pending = jiffies;
++	/* We will deal with the ACK ourselves.  */
+ 	mouse_reply_expected++;
+ 	kb_wait();
+ }
+ 
++#ifdef INITIALIZE_MOUSE
+ static void aux_write_ack(int val)
+ {
+ 	unsigned long flags;
+@@ -1005,6 +1098,33 @@
+ 	__aux_write_ack(val);
+ 	spin_unlock_irqrestore(&kbd_controller_lock, flags);
+ }
++#endif /* INITIALIZE_MOUSE */
++
++static void aux_kill_fasync(struct fasync_struct **fasync, int sig, int band)
++{
++	struct fasync_struct * fp;
++	struct fasync_struct fa;
++
++	fp = *fasync;
++	/* If someone has grabbed the AUX device, send signal only to
++	   them and not to other processes.  We could do this directly
++	   if send_sigio was exported, but since it isn't we must
++	   synthesize a "struct fasync_struct" to pass to
++	   kill_fasync. */
++	if (aux_exclusive) {
++		while (1) {
++			if (!fp)
++				return;
++			if (fp->fa_file == aux_exclusive)
++				break;
++			fp = fp->fa_next;
++		}
++		fa = (*fp);
++		fa.fa_next = NULL;
++		fp = &fa;
++	}
++	kill_fasync(&fp, sig, band);
++}
+ 
+ static unsigned char get_from_queue(void)
+ {
+@@ -1044,6 +1164,8 @@
+ {
+ 	lock_kernel();
+ 	fasync_aux(-1, file, 0);
++	if (aux_exclusive == file)
++		aux_release_ioctl(file);
+ 	if (--aux_count) {
+ 		unlock_kernel();
+ 		return 0;
+@@ -1073,7 +1195,7 @@
+ 	kbd_write_command_w(KBD_CCMD_MOUSE_ENABLE);	/* Enable the
+ 							   auxiliary port on
+ 							   controller. */
+-	aux_write_ack(AUX_ENABLE_DEV); /* Enable aux device */
++	aux_write_dev(AUX_ENABLE_DEV, 0, 1); /* Enable aux device */
+ 	kbd_write_cmd(AUX_INTS_ON); /* Enable controller ints */
+ 	
+ 	mdelay(2);			/* Ensure we follow the kbc access delay rules.. */
+@@ -1084,6 +1206,33 @@
+ }
+ 
+ /*
++ * Implement exclusive access mechanism.
++ */
++
++#define AUX_ACCESS_ALLOWED(file) (!aux_exclusive || aux_exclusive == (file))
++
++static ssize_t aux_wait_for_access(struct file * file)
++{
++	DECLARE_WAITQUEUE(wait, current);
++
++	if (!AUX_ACCESS_ALLOWED(file)) {
++		if (file->f_flags & O_NONBLOCK)
++			return -EAGAIN;
++		add_wait_queue(&aux_exclusive_wait, &wait);
++		do {
++			current->state = TASK_INTERRUPTIBLE;
++			schedule();
++		}
++		while (!AUX_ACCESS_ALLOWED(file)
++		       && !signal_pending(current));
++		remove_wait_queue(&aux_exclusive_wait, &wait);
++	}
++	if (!AUX_ACCESS_ALLOWED(file))
++		return -ERESTARTSYS;
++	return 0;
++}
++
++/*
+  * Put bytes from input queue to buffer.
+  */
+ 
+@@ -1093,7 +1242,11 @@
+ 	DECLARE_WAITQUEUE(wait, current);
+ 	ssize_t i = count;
+ 	unsigned char c;
++	ssize_t retval;
+ 
++	retval = aux_wait_for_access(file);
++	if (retval < 0)
++		return retval;
+ 	if (queue_empty()) {
+ 		if (file->f_flags & O_NONBLOCK)
+ 			return -EAGAIN;
+@@ -1128,23 +1281,32 @@
+ static ssize_t write_aux(struct file * file, const char * buffer,
+ 			 size_t count, loff_t *ppos)
+ {
+-	ssize_t retval = 0;
++	ssize_t retval;
+ 
++	retval = aux_wait_for_access(file);
++	if (retval < 0)
++		return retval;
+ 	if (count) {
+ 		ssize_t written = 0;
+ 
++		retval = -EIO;
+ 		if (count > 32)
+ 			count = 32; /* Limit to 32 bytes. */
+ 		do {
+ 			char c;
++			int write_result;
+ 			get_user(c, buffer++);
+-			aux_write_dev(c);
++			write_result = aux_write_dev(c, file->f_flags & O_NONBLOCK, 0);
++			if (write_result) {
++				retval = write_result;
++				break;
++			}
+ 			written++;
+ 		} while (--count);
+-		retval = -EIO;
+ 		if (written) {
+ 			retval = written;
+ 			file->f_dentry->d_inode->i_mtime = CURRENT_TIME;
++			aux_last_write = jiffies;
+ 		}
+ 	}
+ 
+@@ -1155,15 +1317,80 @@
+ static unsigned int aux_poll(struct file *file, poll_table * wait)
+ {
+ 	poll_wait(file, &queue->proc_list, wait);
+-	if (!queue_empty())
++	if (AUX_ACCESS_ALLOWED(file) && !queue_empty())
+ 		return POLLIN | POLLRDNORM;
+ 	return 0;
+ }
+ 
++/* Wait this long after last write to mouse before allowing AUX_GRAB
++   to happen.  This ensures that any outstanding mouse command is
++   completed.  The ACK from the command is supposed to arrive in 25
++   msec, and each subsequent status bytes are supposed to arrive
++   within 20 msec, so a command with 5 status bytes (I don't know any
++   this long) might take 125 msec.  Fudge this up a bit to account for
++   additional delay introduced by bus locking.  */
++#define AUX_GRAB_MIN_TIME (aux_last_write + (((200 * HZ) + 500) / 1000))
++#define AUX_GRAB_ALLOWED (aux_exclusive == 0 && (jiffies >= AUX_GRAB_MIN_TIME))
++
++static void aux_grab_timeout(unsigned long data)
++{
++	wake_up_interruptible(&aux_exclusive_wait);
++}
++
++static int aux_grab_ioctl(struct file *file)
++{
++	DECLARE_WAITQUEUE(wait, current);
++	struct timer_list timer;
++
++	if (aux_exclusive == file)
++		return -EINVAL;
++	if (!AUX_GRAB_ALLOWED) {
++		if (file->f_flags & O_NONBLOCK)
++			return -EAGAIN;
++		init_timer (&timer);
++		timer.expires = AUX_GRAB_MIN_TIME;
++		timer.data = 0;
++		timer.function = aux_grab_timeout;
++		add_wait_queue(&aux_exclusive_wait, &wait);
++		add_timer(&timer);
++		do {
++			current->state = TASK_INTERRUPTIBLE;
++			schedule();
++		}
++		while (!AUX_GRAB_ALLOWED && !signal_pending(current));
++		del_timer(&timer);
++		remove_wait_queue(&aux_exclusive_wait, &wait);
++	}
++	if (!AUX_GRAB_ALLOWED)
++		return -ERESTARTSYS;
++	aux_exclusive = file;
++	return 0;
++}
++
++static int aux_release_ioctl(struct file *file)
++{
++	if (aux_exclusive != file)
++		return -ENOENT;
++	aux_exclusive = 0;
++	wake_up_interruptible(&aux_exclusive_wait);
++	return 0;
++}
++
++static int aux_ioctl(struct inode *inode, struct file *file,
++		     unsigned int cmd, unsigned long arg)
++{
++	switch (cmd) {
++	case AUX_GRAB: return aux_grab_ioctl(file);
++	case AUX_RELEASE: return aux_release_ioctl(file);
++	default: return -EINVAL;
++	}
++}
++
+ struct file_operations psaux_fops = {
+ 	read:		read_aux,
+ 	write:		write_aux,
+ 	poll:		aux_poll,
++	ioctl:		aux_ioctl,
+ 	open:		open_aux,
+ 	release:	release_aux,
+ 	fasync:		fasync_aux,
+@@ -1195,6 +1422,8 @@
+ 	memset(queue, 0, sizeof(*queue));
+ 	queue->head = queue->tail = 0;
+ 	init_waitqueue_head(&queue->proc_list);
++	init_waitqueue_head(&mouse_ack_wait);
++ 	init_waitqueue_head(&aux_exclusive_wait);
+ 
+ #ifdef INITIALIZE_MOUSE
+ 	kbd_write_command_w(KBD_CCMD_MOUSE_ENABLE); /* Enable Aux. */
+@@ -1206,6 +1435,8 @@
+ #endif /* INITIALIZE_MOUSE */
+ 	kbd_write_command(KBD_CCMD_MOUSE_DISABLE); /* Disable aux device. */
+ 	kbd_write_cmd(AUX_INTS_OFF); /* Disable controller ints. */
++
++	aux_last_write = jiffies;
+ 
+ 	return 0;
+ }
--- /dev/null
+++ tpconfig-3.1.3/psaux-2.4.9-combined.diff
@@ -0,0 +1,408 @@
+--- linux-2.4.9/drivers/char/pc_keyb.c.orig	Tue Aug 14 18:49:50 2001
++++ linux-2.4.9/drivers/char/pc_keyb.c	Thu Aug 16 22:29:33 2001
+@@ -13,6 +13,15 @@
+  * Code fixes to handle mouse ACKs properly.
+  * C. Scott Ananian <cananian@alumni.princeton.edu> 1999-01-29.
+  *
++ * More work to handle mouse ACKs properly.  (Modified version of
++ * patch by Julian Bradfield <jcb@dcs.ed.ac.uk>.)
++ * Chris Hanson <cph@zurich.ai.mit.edu> 2000-12-11.
++ *
++ * Implement exclusive access mechanism for aux device.
++ * This permits grabbing the mouse away from the X server,
++ * which is needed by fancy mice that have configurable features.
++ * Chris Hanson <cph@zurich.ai.mit.edu> 2000-10-30.
++ *
+  */
+ 
+ #include <linux/config.h>
+@@ -64,6 +73,8 @@
+ static void aux_write_ack(int val);
+ static void __aux_write_ack(int val);
+ static int aux_reconnect = 0;
++static void aux_kill_fasync(struct fasync_struct **fasync, int sig, int band);
++static int aux_release_ioctl(struct file *file);
+ #endif
+ 
+ static spinlock_t kbd_controller_lock = SPIN_LOCK_UNLOCKED;
+@@ -87,13 +98,30 @@
+  
+ static struct aux_queue *queue;	/* Mouse data buffer. */
+ static int aux_count;
+-/* used when we send commands to the mouse that expect an ACK. */
++/* Used when we (as opposed to user programs using the aux device)
++   send commands to the mouse. */
+ static unsigned char mouse_reply_expected;
+ 
++/* Used to make sure we have received an ACK from the byte last
++   written to the mouse before writing another.  */
++static unsigned long mouse_ack_pending;
++static wait_queue_head_t mouse_ack_wait;
++/* How many jiffies to wait for the mouse to respond to a command with
++   an ACK.  25 msec is the maximum allowed delay for the hardware to
++   respond.  We round that up to the nearest jiffy.  */
++#define MOUSE_ACK_TIMEOUT ((25 * HZ + 999) / 1000)
++
+ #define AUX_INTS_OFF (KBD_MODE_KCC | KBD_MODE_DISABLE_MOUSE | KBD_MODE_SYS | KBD_MODE_KBD_INT)
+ #define AUX_INTS_ON  (KBD_MODE_KCC | KBD_MODE_SYS | KBD_MODE_MOUSE_INT | KBD_MODE_KBD_INT)
+ 
+ #define MAX_RETRIES	60		/* some aux operations take long time*/
++
++/* Support for exclusive access to the AUX device. */
++static struct file *aux_exclusive;
++static wait_queue_head_t aux_exclusive_wait;
++static unsigned long aux_last_write;
++#define AUX_GRAB _IO('M', 1)
++#define AUX_RELEASE _IO('M', 2)
+ #endif /* CONFIG_PSMOUSE */
+ 
+ /*
+@@ -399,6 +427,13 @@
+ {
+ #ifdef CONFIG_PSMOUSE
+ 	static unsigned char prev_code;
++ 	if (mouse_ack_pending) {
++ 		/* It needn't actually be an ack, it could be an echo;
++ 		   but every byte sent to the mouse results in a byte
++ 		   back. */
++ 		wake_up_interruptible(&mouse_ack_wait);
++ 		mouse_ack_pending = 0;
++ 	}
+ 	if (mouse_reply_expected) {
+ 		if (scancode == AUX_ACK) {
+ 			mouse_reply_expected--;
+@@ -423,7 +458,7 @@
+ 		head = (head + 1) & (AUX_BUF_SIZE-1);
+ 		if (head != queue->tail) {
+ 			queue->head = head;
+-			kill_fasync(&queue->fasync, SIGIO, POLL_IN);
++			aux_kill_fasync(&queue->fasync, SIGIO, POLL_IN);
+ 			wake_up_interruptible(&queue->proc_list);
+ 		}
+ 	}
+@@ -895,19 +930,75 @@
+ 	return retval;
+ }
+ 
++static void mouse_ack_timeout(unsigned long data)
++{
++	wake_up_interruptible(&mouse_ack_wait);
++}
++
+ /*
+  * Send a byte to the mouse.
+  */
+-static void aux_write_dev(int val)
++static int aux_write_dev(int val, int dont_block, int handle_ack)
+ {
+ 	unsigned long flags;
+ 
+ 	spin_lock_irqsave(&kbd_controller_lock, flags);
+ 	kb_wait();
++	/* If we haven't yet received the ACK from the previous write,
++	   we must wait for it.  */
++	if (mouse_ack_pending) {
++		unsigned long expires;
++		struct timer_list timer;
++		DECLARE_WAITQUEUE(wait, current);
++
++		if (dont_block) {
++			spin_unlock_irqrestore(&kbd_controller_lock, flags);
++			return -EAGAIN;
++		}
++		expires = mouse_ack_pending + MOUSE_ACK_TIMEOUT;
++		if (jiffies >= expires)
++			goto timed_out;
++
++		add_wait_queue(&mouse_ack_wait, &wait);
++		init_timer (&timer);
++		timer.expires = expires;
++		timer.data = 0;
++		timer.function = mouse_ack_timeout;
++		add_timer(&timer);
++
++		do {
++			current->state = TASK_INTERRUPTIBLE;
++			spin_unlock_irqrestore(&kbd_controller_lock, flags);
++			schedule();
++			spin_lock_irqsave(&kbd_controller_lock, flags);
++		} while (mouse_ack_pending
++			 && jiffies < expires
++			 && !signal_pending(current));
++
++		del_timer(&timer);
++		remove_wait_queue(&mouse_ack_wait, &wait);
++
++		if (mouse_ack_pending && jiffies >= expires) {
++		timed_out:
++			printk(KERN_WARNING "mouse ack timeout\n");
++			mouse_ack_pending = 0;
++			spin_unlock_irqrestore(&kbd_controller_lock, flags);
++			return -EIO;
++		}
++		if (signal_pending(current)) {
++			spin_unlock_irqrestore(&kbd_controller_lock, flags);
++			return -ERESTARTSYS;
++		}
++	}
+ 	kbd_write_command(KBD_CCMD_WRITE_MOUSE);
+ 	kb_wait();
+ 	kbd_write_output(val);
++	mouse_ack_pending = jiffies;
++	if (handle_ack)
++		/* We will deal with the ACK ourselves.  */
++		mouse_reply_expected++;
+ 	spin_unlock_irqrestore(&kbd_controller_lock, flags);
++	return 0;
+ }
+ 
+ /*
+@@ -919,11 +1010,13 @@
+ 	kbd_write_command(KBD_CCMD_WRITE_MOUSE);
+ 	kb_wait();
+ 	kbd_write_output(val);
+-	/* we expect an ACK in response. */
++	mouse_ack_pending = jiffies;
++	/* We will deal with the ACK ourselves.  */
+ 	mouse_reply_expected++;
+ 	kb_wait();
+ }
+ 
++#ifdef INITIALIZE_MOUSE
+ static void aux_write_ack(int val)
+ {
+ 	unsigned long flags;
+@@ -932,6 +1025,33 @@
+ 	__aux_write_ack(val);
+ 	spin_unlock_irqrestore(&kbd_controller_lock, flags);
+ }
++#endif /* INITIALIZE_MOUSE */
++
++static void aux_kill_fasync(struct fasync_struct **fasync, int sig, int band)
++{
++	struct fasync_struct * fp;
++	struct fasync_struct fa;
++
++	fp = *fasync;
++	/* If someone has grabbed the AUX device, send signal only to
++	   them and not to other processes.  We could do this directly
++	   if send_sigio was exported, but since it isn't we must
++	   synthesize a "struct fasync_struct" to pass to
++	   kill_fasync. */
++	if (aux_exclusive) {
++		while (1) {
++			if (!fp)
++				return;
++			if (fp->fa_file == aux_exclusive)
++				break;
++			fp = fp->fa_next;
++		}
++		fa = (*fp);
++		fa.fa_next = NULL;
++		fp = &fa;
++	}
++	kill_fasync(&fp, sig, band);
++}
+ 
+ static unsigned char get_from_queue(void)
+ {
+@@ -971,6 +1091,8 @@
+ {
+ 	lock_kernel();
+ 	fasync_aux(-1, file, 0);
++	if (aux_exclusive == file)
++		aux_release_ioctl(file);
+ 	if (--aux_count) {
+ 		unlock_kernel();
+ 		return 0;
+@@ -1000,7 +1122,7 @@
+ 	kbd_write_command_w(KBD_CCMD_MOUSE_ENABLE);	/* Enable the
+ 							   auxiliary port on
+ 							   controller. */
+-	aux_write_ack(AUX_ENABLE_DEV); /* Enable aux device */
++	aux_write_dev(AUX_ENABLE_DEV, 0, 1); /* Enable aux device */
+ 	kbd_write_cmd(AUX_INTS_ON); /* Enable controller ints */
+ 	
+ 	mdelay(2);			/* Ensure we follow the kbc access delay rules.. */
+@@ -1011,6 +1133,33 @@
+ }
+ 
+ /*
++ * Implement exclusive access mechanism.
++ */
++
++#define AUX_ACCESS_ALLOWED(file) (!aux_exclusive || aux_exclusive == (file))
++
++static ssize_t aux_wait_for_access(struct file * file)
++{
++	DECLARE_WAITQUEUE(wait, current);
++
++	if (!AUX_ACCESS_ALLOWED(file)) {
++		if (file->f_flags & O_NONBLOCK)
++			return -EAGAIN;
++		add_wait_queue(&aux_exclusive_wait, &wait);
++		do {
++			current->state = TASK_INTERRUPTIBLE;
++			schedule();
++		}
++		while (!AUX_ACCESS_ALLOWED(file)
++		       && !signal_pending(current));
++		remove_wait_queue(&aux_exclusive_wait, &wait);
++	}
++	if (!AUX_ACCESS_ALLOWED(file))
++		return -ERESTARTSYS;
++	return 0;
++}
++
++/*
+  * Put bytes from input queue to buffer.
+  */
+ 
+@@ -1020,7 +1169,11 @@
+ 	DECLARE_WAITQUEUE(wait, current);
+ 	ssize_t i = count;
+ 	unsigned char c;
++	ssize_t retval;
+ 
++	retval = aux_wait_for_access(file);
++	if (retval < 0)
++		return retval;
+ 	if (queue_empty()) {
+ 		if (file->f_flags & O_NONBLOCK)
+ 			return -EAGAIN;
+@@ -1055,23 +1208,32 @@
+ static ssize_t write_aux(struct file * file, const char * buffer,
+ 			 size_t count, loff_t *ppos)
+ {
+-	ssize_t retval = 0;
++	ssize_t retval;
+ 
++	retval = aux_wait_for_access(file);
++	if (retval < 0)
++		return retval;
+ 	if (count) {
+ 		ssize_t written = 0;
+ 
++		retval = -EIO;
+ 		if (count > 32)
+ 			count = 32; /* Limit to 32 bytes. */
+ 		do {
+ 			char c;
++			int write_result;
+ 			get_user(c, buffer++);
+-			aux_write_dev(c);
++			write_result = aux_write_dev(c, file->f_flags & O_NONBLOCK, 0);
++			if (write_result) {
++				retval = write_result;
++				break;
++			}
+ 			written++;
+ 		} while (--count);
+-		retval = -EIO;
+ 		if (written) {
+ 			retval = written;
+ 			file->f_dentry->d_inode->i_mtime = CURRENT_TIME;
++			aux_last_write = jiffies;
+ 		}
+ 	}
+ 
+@@ -1082,15 +1244,80 @@
+ static unsigned int aux_poll(struct file *file, poll_table * wait)
+ {
+ 	poll_wait(file, &queue->proc_list, wait);
+-	if (!queue_empty())
++	if (AUX_ACCESS_ALLOWED(file) && !queue_empty())
+ 		return POLLIN | POLLRDNORM;
+ 	return 0;
+ }
+ 
++/* Wait this long after last write to mouse before allowing AUX_GRAB
++   to happen.  This ensures that any outstanding mouse command is
++   completed.  The ACK from the command is supposed to arrive in 25
++   msec, and each subsequent status bytes are supposed to arrive
++   within 20 msec, so a command with 5 status bytes (I don't know any
++   this long) might take 125 msec.  Fudge this up a bit to account for
++   additional delay introduced by bus locking.  */
++#define AUX_GRAB_MIN_TIME (aux_last_write + (((200 * HZ) + 500) / 1000))
++#define AUX_GRAB_ALLOWED (aux_exclusive == 0 && (jiffies >= AUX_GRAB_MIN_TIME))
++
++static void aux_grab_timeout(unsigned long data)
++{
++	wake_up_interruptible(&aux_exclusive_wait);
++}
++
++static int aux_grab_ioctl(struct file *file)
++{
++	DECLARE_WAITQUEUE(wait, current);
++	struct timer_list timer;
++
++	if (aux_exclusive == file)
++		return -EINVAL;
++	if (!AUX_GRAB_ALLOWED) {
++		if (file->f_flags & O_NONBLOCK)
++			return -EAGAIN;
++		init_timer (&timer);
++		timer.expires = AUX_GRAB_MIN_TIME;
++		timer.data = 0;
++		timer.function = aux_grab_timeout;
++		add_wait_queue(&aux_exclusive_wait, &wait);
++		add_timer(&timer);
++		do {
++			current->state = TASK_INTERRUPTIBLE;
++			schedule();
++		}
++		while (!AUX_GRAB_ALLOWED && !signal_pending(current));
++		del_timer(&timer);
++		remove_wait_queue(&aux_exclusive_wait, &wait);
++	}
++	if (!AUX_GRAB_ALLOWED)
++		return -ERESTARTSYS;
++	aux_exclusive = file;
++	return 0;
++}
++
++static int aux_release_ioctl(struct file *file)
++{
++	if (aux_exclusive != file)
++		return -ENOENT;
++	aux_exclusive = 0;
++	wake_up_interruptible(&aux_exclusive_wait);
++	return 0;
++}
++
++static int aux_ioctl(struct inode *inode, struct file *file,
++		     unsigned int cmd, unsigned long arg)
++{
++	switch (cmd) {
++	case AUX_GRAB: return aux_grab_ioctl(file);
++	case AUX_RELEASE: return aux_release_ioctl(file);
++	default: return -EINVAL;
++	}
++}
++
+ struct file_operations psaux_fops = {
+ 	read:		read_aux,
+ 	write:		write_aux,
+ 	poll:		aux_poll,
++	ioctl:		aux_ioctl,
+ 	open:		open_aux,
+ 	release:	release_aux,
+ 	fasync:		fasync_aux,
+@@ -1115,6 +1342,8 @@
+ 	memset(queue, 0, sizeof(*queue));
+ 	queue->head = queue->tail = 0;
+ 	init_waitqueue_head(&queue->proc_list);
++	init_waitqueue_head(&mouse_ack_wait);
++ 	init_waitqueue_head(&aux_exclusive_wait);
+ 
+ #ifdef INITIALIZE_MOUSE
+ 	kbd_write_command_w(KBD_CCMD_MOUSE_ENABLE); /* Enable Aux. */
+@@ -1126,6 +1355,8 @@
+ #endif /* INITIALIZE_MOUSE */
+ 	kbd_write_command(KBD_CCMD_MOUSE_DISABLE); /* Disable aux device. */
+ 	kbd_write_cmd(AUX_INTS_OFF); /* Disable controller ints. */
++
++	aux_last_write = jiffies;
+ 
+ 	return 0;
+ }
--- tpconfig-3.1.3.orig/utils.c
+++ tpconfig-3.1.3/utils.c
@@ -89,17 +89,17 @@ int left;
 int i;
  
 if (DEBUG_LEVEL == DEBUG_HIGH)
-  printf ("PS2_write: %d bytes\n", num_bytes);
+  fprintf (stderr, "PS2_write: %d bytes\n", num_bytes);
 /* Use the temporary buffer to store the data as it arrives */
 gettimeofday(&start, 0);
 at = 0;
 left = num_bytes;
 if (DEBUG_LEVEL == DEBUG_HIGH)
   {
-    printf ("PS2_write:");
+    fprintf (stderr, "PS2_write:");
     for (i = 0; i < num_bytes; i++)
-      printf(" %#2x", *(buffer + i));
-    printf("\n");
+      fprintf (stderr, " %#02x", *(buffer + i));
+    fprintf (stderr, "\n");
   }
 
 do
@@ -116,14 +116,14 @@ do
        / 1000000.0)
       > TIMEOUT)
     {
-      printf ("\nTimed out waiting to write to device.\n");
+      fprintf (stderr, "\nTimed out waiting to write to device.\n");
       exit (-1);
     }
   }
 while(left > 0);
 
 if (DEBUG_LEVEL == DEBUG_HIGH)
-  printf ("PS2_write: done\n");
+  fprintf (stderr, "PS2_write: done\n");
  
 return(at);
 } /* ps2_write */
@@ -138,7 +138,7 @@ int left;
 int i;
  
 if (DEBUG_LEVEL == DEBUG_HIGH)
-  printf ("PS2_read: %d bytes\n", num_bytes);
+  fprintf (stderr, "PS2_read: %d bytes\n", num_bytes);
 /* Use the temporary buffer to store the data as it arrives */
 gettimeofday(&start, 0);
 at = 0;
@@ -157,55 +157,44 @@ do
        / 1000000.0)
       > TIMEOUT)
     {
-      printf("\nTimed out waiting to read from device (is pc_keyb.c kernel patch installed?)\n");
-      exit(-1);
+      fprintf (stderr, "\nTimed out waiting to read from device (is pc_keyb.c kernel patch installed?)\n");
+      exit (-1);
     }
   }
 while(left > 0);
 if (DEBUG_LEVEL == DEBUG_HIGH)
   {
-    printf("PS2_read:");
+    fprintf (stderr, "PS2_read:");
     for (i = 0; i < at; i++)
-      printf (" %#2x", *(buffer + i));
-    printf ("\n");
-    printf ("PS2_read: read %d\n", at);
+      fprintf (stderr, " %#2x", *(buffer + i));
+    fprintf (stderr, "\n");
+    fprintf (stderr, "PS2_read: read %d\n", at);
   }
 return(at);
 } /* ps2_read */
- 
-
-
-void version_info(void)
-{ /* version_info */
-printf( "\nSynaptics Touchpad and ALPS GlidePad/Glidepoint configuration tool\n");
-printf("                   version: " VERSION "\n\n");
-} /* version_info */
-
 
 void copyright(void) 
-{ /* copyright */
-  printf("\n========================================================================\n");
-  printf("=                                                                      =\n");
-  printf("=                tpconfig   version: %-9s                         =\n", VERSION);
-  printf("=                                                                      =\n");
-  printf("= Synaptics Touchpad and ALPS GlidePad/Stickpointer configuration tool =\n");
-  printf("=                                                                      =\n");
-  printf("= Copyright (C) 1997 C. Scott Ananian<cananian@alumni.princeton.edu>   =\n");
-  printf("= Copyright (C) 1998-2001 Bruce Kall <kall@compass.com>                =\n");
-  printf("= Last Modified (Version 3.1.3) by Bruce Kall, 2/22/2002              =\n");
-  printf("=                                                                      =\n");
-  printf("= tpconfig comes with ABSOLUTELY NO WARRANTY.  This is free software,  =\n");
-  printf("= and you are welcome to redistribute it under the terms of the GPL.   =\n");
-  printf("=                                                                      =\n");
-  printf("========================================================================\n\n");
-} /* copyright */
+{
+  printf("\n");
+  printf("                tpconfig version: %s\n", VERSION);
+  printf("\n");
+  printf(" Synaptics Touchpad and ALPS GlidePad/Stickpointer configuration tool\n");
+  printf("\n");
+  printf(" Copyright (C) 1997 C. Scott Ananian <cananian@alumni.princeton.edu>\n");
+  printf(" Copyright (C) 1998-2001 Bruce Kall <kall@compass.com>\n");
+  printf(" Last Modified (Version 3.1.3) by Bruce Kall, 2/22/2002\n");
+  printf("\n");
+  printf(" tpconfig comes with ABSOLUTELY NO WARRANTY.  This is free software,\n");
+  printf(" and you are welcome to redistribute it under the terms of the GPL.\n");
+  printf("\n");
+}
 
 /* write a byte to the ps/2 port, handling ACK */
 void
 putbyte (int fd, byte b) 
 {
   if (DEBUG_LEVEL > DEBUG_LOW)
-    printf ("putbyte: write %#02x\n", b);
+    fprintf (stderr, "putbyte: write %#02x\n", b);
   ps2_write (fd, &b, 1);
   getbyte_expected (fd, AUX_ACK, "putbyte");
 }
@@ -217,7 +206,7 @@ getbyte (int fd)
   byte b;
   ps2_read (fd, &b, 1);
   if (DEBUG_LEVEL > DEBUG_LOW)
-    printf ("ps2_read_byte: read %#02x\n", b);
+    fprintf (stderr, "ps2_read_byte: read %#02x\n", b);
   return b;
 }
 
@@ -226,6 +215,10 @@ getbyte_expected (int fd, byte expected,
 {
   byte b = getbyte (fd);
   if (DEBUG_LEVEL && b != expected)
-    printf ("Read %#02x, expected %#02x in %s.\n", b, expected, what);
-  assert (b == expected);
+    fprintf (stderr, "Read %#02x, expected %#02x in %s.\n", b, expected, what);
+#if 0
+  /* Upstream recommends commenting this out for 2.6 kernels.  */
+  if (!ignore_selected_assertions)
+    assert (b == expected);
+#endif
 }
--- tpconfig-3.1.3.orig/ALPS.c
+++ tpconfig-3.1.3/ALPS.c
@@ -62,7 +62,6 @@ static char rcsid[]="$Header: /home/bruc
 
 extern int ps2_write(int fd,char *buffer,int num_bytes);
 extern int ps2_read(int fd,char *buffer,int num_bytes);
-extern void version_info(void);
 extern void putbyte(int fd, byte b);
 extern byte getbyte(int fd);
 
@@ -81,8 +80,8 @@ for(i = 0;i < 3;i++)
   putbyte(fd,c);
   }
 c = 0xe9;
-if(DEBUG_LEVEL)
-  printf("Writing [%x]\n",c);
+if(DEBUG_LEVEL > DEBUG_LOW)
+  printf("Writing [%#04x]\n",c);
 num_written = ps2_write(fd,&c,1);
 if(num_written != 1)
   {
@@ -98,10 +97,10 @@ if(num_read != 4)
 
 /* resend enable command for xmission of external mouse data */
 c = 0xf4;
-if(DEBUG_LEVEL)
+if(DEBUG_LEVEL > DEBUG_LOW)
   {
   printf("Resending Enable command\n");
-  printf("Writing [%x]\n",c);
+  printf("Writing [%#04x]\n",c);
   }
 num_written = ps2_write(fd,&c,1);
 if(num_written != 1)
@@ -109,12 +108,12 @@ if(num_written != 1)
   fprintf(stderr,"Error writing byte\n");
   return(0);
   }
-if(DEBUG_LEVEL)
+if(DEBUG_LEVEL > DEBUG_LOW)
   {
-  printf("Response 0 [%x]\n",status[0]);
-  printf("Response 1 [%x]\n",status[1]);
-  printf("Response 2 [%x]\n",status[2]);
-  printf("Response 3 [%x]\n",status[3]);
+  printf("Response 0 [%#04x]\n",status[0]);
+  printf("Response 1 [%#04x]\n",status[1]);
+  printf("Response 2 [%#04x]\n",status[2]);
+  printf("Response 3 [%#04x]\n",status[3]);
   }
 return(!ERROR);
 } /* ALPS_status */
@@ -125,7 +124,7 @@ byte response[4];
 int tap_on = TRUE;
 int error;
 
-if(DEBUG_LEVEL)
+if(DEBUG_LEVEL > DEBUG_LOW)
   printf("\n\nChecking Whether ALPS Tap status is enabled or disabled\n");
 
 
@@ -149,7 +148,7 @@ else if(touchpad_type == ALPS_GLIDEPAD)
   }
 
 
-if(DEBUG_LEVEL)
+if(DEBUG_LEVEL > DEBUG_LOW)
   {
   if(tap_on)
     printf("Done Checking Status of Tap Enabled/Disable, Tap is ON \n");
@@ -166,8 +165,8 @@ byte c;
 int num_written;
 
 c = 0xff;
-if(DEBUG_LEVEL)
-  printf("\nWriting Reset [%x], Reading Nothing\n",(int)c);
+if(DEBUG_LEVEL > DEBUG_LOW)
+  printf("\nWriting Reset [%#04x], Reading Nothing\n",(int)c);
 num_written = ps2_write(fd,&c,1);
 if(num_written != 1)
   {
@@ -183,7 +182,7 @@ int ALPS_SP_tap(int fd,char enable)
 { /* ALPS_SP_tap */
 byte c;
 int i;
-if(DEBUG_LEVEL)
+if(DEBUG_LEVEL > DEBUG_LOW)
   {
   if(enable)
     printf("\n\nEnabling SP tap\n");
@@ -204,7 +203,7 @@ else
   c = 0x0a;
 
 putbyte(fd,c);
-if(DEBUG_LEVEL)
+if(DEBUG_LEVEL > DEBUG_LOW)
   printf("Done Enabling/Disabling SP tap\n");
 return(!ERROR);
 } /* ALPS_SP_tap */
@@ -214,7 +213,7 @@ int ALPS_through_mode(int fd,char set)
 { /* ALPS_through_mode */
 byte c;
 int i;
-if(DEBUG_LEVEL)
+if(DEBUG_LEVEL > DEBUG_LOW)
   {
   if(set)
     printf("\n\nEnabling ALPS_through_mode\n");
@@ -236,7 +235,7 @@ putbyte(fd,c);
 
 /* We may receive 3 more bytes, ignore them */
 tcflush(fd,TCIOFLUSH);
-if(DEBUG_LEVEL)
+if(DEBUG_LEVEL > DEBUG_LOW)
   {
   if(set)
     printf("Done Enabling ALPS_through_mode\n\n\n");
@@ -256,7 +255,7 @@ int num_read;
 int num_written;
 int error;
 
-if(DEBUG_LEVEL)
+if(DEBUG_LEVEL > DEBUG_LOW)
   {
   if(enable)
     printf("\n\nEnabling GP tap\n");
@@ -275,22 +274,22 @@ if(touchpad_type == ALPS_STICKPOINTER_AN
   }
 
 c = 0xE9;
-if(DEBUG_LEVEL)
-  printf("Writing Initial [%x]\n",(int)c);
+if(DEBUG_LEVEL > DEBUG_LOW)
+  printf("Writing Initial [%#04x]\n",(int)c);
 num_written = ps2_write(fd,&c,1);
 num_read = ps2_read(fd,response,4);
-if(DEBUG_LEVEL)
+if(DEBUG_LEVEL > DEBUG_LOW)
   {
   printf("Just Read num = [%d] bytes",num_read);
   printf("\n");
   }
 if((num_read != 4) || (response[0] != AUX_ACK))
     {
-    printf("-----> Invalid response from Alps Glidepad/Glidepoint [%x] \n",(int)response[0]);
+    printf("-----> Invalid response from Alps Glidepad/Glidepoint [%#04x] \n",(int)response[0]);
     return(ERROR);
     }
-if(DEBUG_LEVEL)
-  printf("Current Settings [%x] [%x] [%x]\n",response[1],response[2],response[3]);
+if(DEBUG_LEVEL > DEBUG_LOW)
+  printf("Current Settings [%#04x] [%#04x] [%#04x]\n",response[1],response[2],response[3]);
 
 for(i = 0;i < 2;i++)
   {
@@ -300,13 +299,13 @@ for(i = 0;i < 2;i++)
 
 if(enable)
   {
-  if(DEBUG_LEVEL)
+  if(DEBUG_LEVEL > DEBUG_LOW)
     printf("Enabling Tap\n");
   c = 0xF3;
   }
 else
   {
-  if(DEBUG_LEVEL)
+  if(DEBUG_LEVEL > DEBUG_LOW)
     printf("Disabling Tap\n");
   c = 0xE8;
   }
@@ -373,8 +372,8 @@ for(i = 0;i < 3;i++)
   putbyte(fd,c);
   }
 c = 0xe9;
-if(DEBUG_LEVEL)
-  printf("Writing Initial [%x] in is_ALPS\n",(int)c);
+if(DEBUG_LEVEL > DEBUG_LOW)
+  printf("Writing Initial [%#04x] in is_ALPS\n",(int)c);
 num_written = ps2_write(fd,&c,1);
 if(num_written != 1)
   {
@@ -388,8 +387,8 @@ if(num_read != 4)
   return(0);
   }
 
-if(DEBUG_LEVEL)
-  printf("ALPS Configuration Info [%2x][%2x][%2x]\n",response[1],response[2],response[3]);
+if(DEBUG_LEVEL > DEBUG_LOW)
+  printf("ALPS Configuration Info [%#04x][%#04x][%#04x]\n",response[1],response[2],response[3]);
 
 return_value = 0;
 for(i = 0;i < NUM_SINGLES;i++)
@@ -427,7 +426,7 @@ if(return_value)
   { 
   if(!tap_on)
     { /* reset tap_on to off since we just had to do a reset */
-    if(DEBUG_LEVEL)
+    if(DEBUG_LEVEL > DEBUG_LOW)
       printf("Turning ALPS Tap Back OFF\n");
     if(touchpad_type == ALPS_STICKPOINTER_AND_GLIDEPOINT)
       {
@@ -445,22 +444,20 @@ return(return_value);
 
 
 
-void ALPS_usage(char *progname) 
+void ALPS_usage(void) 
 {
-  copyright ();
-  printf ("Usage: %s [OPTION]...\n", progname);
-  printf ("Configure an ALPS GlidePad/GlidePoint.\n"
+  printf ("Options for an ALPS GlidePad/GlidePoint:\n"
 	  "\n"
 	  "  -i, --info                    display current TouchPad configuration\n"
 	  "  -t, --tapmode=[0-1]           display/set tapping mode:\n"
 	  "                                   0 = tapping off\n"
 	  "                                   1 = tapping on\n"
 	  "  -r, --reset                   reset ALPS device\n"
-	  "      --help                    display this help and exit\n"
-	  "      --version                 output version information\n"
-	  "\n"
-	  "Report bugs to <kall@compass.com\n");
-  exit(0);
+	  "  -h, --help                    display this help and exit\n"
+	  "  -v, --version                 output version information\n"
+	  "  -D, --debug=[0-3]             generate debug output\n"
+	  "  -d, --device=DEVICE           use alternate device file\n"
+	  "\n");
 }
 
 
@@ -471,7 +468,9 @@ void alps_functions(int c,int fd,char **
   int mode;
   switch (c) 
     {
-    case 'h': ALPS_usage(argv[0]);
+    case 'h': printf ("Usage: %s [OPTION]...\n", (argv[0]));
+	      ALPS_usage();
+              printf ("Report bugs to <kall@compass.com>\n");
               break;
     case 'i': if(touchpad_type == ALPS_GLIDEPAD)
                printf("\nFound ALPS GlidePad\n\n");
@@ -497,11 +496,11 @@ void alps_functions(int c,int fd,char **
                 else
                   {
   	          mode = optarg[0]-'0';
-                  if(DEBUG_LEVEL)
+                  if(DEBUG_LEVEL > DEBUG_LOW)
                     printf("User Asked to set Tap mode to [%d]\n",mode);
                   if(mode > 0)
                     {
-                    if(DEBUG_LEVEL)
+                    if(DEBUG_LEVEL > DEBUG_LOW)
                       printf("Turning ALPS Tap ON\n");
                     if(touchpad_type == ALPS_STICKPOINTER_AND_GLIDEPOINT)
                       {
@@ -513,7 +512,7 @@ void alps_functions(int c,int fd,char **
                     }
                   else
                     { /* disable tap mode */
-                    if(DEBUG_LEVEL)
+                    if(DEBUG_LEVEL > DEBUG_LOW)
                       printf("Turning ALPS Tap OFF\n");
                     if(touchpad_type == ALPS_STICKPOINTER_AND_GLIDEPOINT)
                       {
@@ -531,9 +530,6 @@ void alps_functions(int c,int fd,char **
                   }
                 }
               break;
-    case 'v': /* --version */
-      version_info();
-      break;
 
     default:
       fprintf(stderr, "Unknown option %c.\n", (char)c);
--- /dev/null
+++ tpconfig-3.1.3/psaux-2.4.15-combined.diff
@@ -0,0 +1,1630 @@
+diff -ruN linux-2.4.15-orig/drivers/char/pc_keyb.c linux-2.4.15/drivers/char/pc_keyb.c
+--- linux-2.4.15-orig/drivers/char/pc_keyb.c	Fri Nov  9 17:01:21 2001
++++ linux-2.4.15/drivers/char/pc_keyb.c	Sat Nov 24 20:45:47 2001
+@@ -13,6 +13,15 @@
+  * Code fixes to handle mouse ACKs properly.
+  * C. Scott Ananian <cananian@alumni.princeton.edu> 1999-01-29.
+  *
++ * More work to handle mouse ACKs properly.  (Modified version of
++ * patch by Julian Bradfield <jcb@dcs.ed.ac.uk>.)
++ * Chris Hanson <cph@zurich.ai.mit.edu> 2000-12-11.
++ *
++ * Implement exclusive access mechanism for aux device.
++ * This permits grabbing the mouse away from the X server,
++ * which is needed by fancy mice that have configurable features.
++ * Chris Hanson <cph@zurich.ai.mit.edu> 2000-10-30.
++ *
+  */
+ 
+ #include <linux/config.h>
+@@ -67,6 +76,8 @@
+ static void aux_write_ack(int val);
+ static void __aux_write_ack(int val);
+ static int aux_reconnect = 0;
++static void aux_kill_fasync(struct fasync_struct **fasync, int sig, int band);
++static int aux_release_ioctl(struct file *file);
+ #endif
+ 
+ static spinlock_t kbd_controller_lock = SPIN_LOCK_UNLOCKED;
+@@ -90,13 +101,30 @@
+  
+ static struct aux_queue *queue;	/* Mouse data buffer. */
+ static int aux_count;
+-/* used when we send commands to the mouse that expect an ACK. */
++/* Used when we (as opposed to user programs using the aux device)
++   send commands to the mouse. */
+ static unsigned char mouse_reply_expected;
+ 
++/* Used to make sure we have received an ACK from the byte last
++   written to the mouse before writing another.  */
++static unsigned long mouse_ack_pending;
++static wait_queue_head_t mouse_ack_wait;
++/* How many jiffies to wait for the mouse to respond to a command with
++   an ACK.  25 msec is the maximum allowed delay for the hardware to
++   respond.  We round that up to the nearest jiffy.  */
++#define MOUSE_ACK_TIMEOUT ((25 * HZ + 999) / 1000)
++
+ #define AUX_INTS_OFF (KBD_MODE_KCC | KBD_MODE_DISABLE_MOUSE | KBD_MODE_SYS | KBD_MODE_KBD_INT)
+ #define AUX_INTS_ON  (KBD_MODE_KCC | KBD_MODE_SYS | KBD_MODE_MOUSE_INT | KBD_MODE_KBD_INT)
+ 
+ #define MAX_RETRIES	60		/* some aux operations take long time*/
++
++/* Support for exclusive access to the AUX device. */
++static struct file *aux_exclusive;
++static wait_queue_head_t aux_exclusive_wait;
++static unsigned long aux_last_write;
++#define AUX_GRAB _IO('M', 1)
++#define AUX_RELEASE _IO('M', 2)
+ #endif /* CONFIG_PSMOUSE */
+ 
+ /*
+@@ -431,6 +459,13 @@
+ {
+ #ifdef CONFIG_PSMOUSE
+ 	static unsigned char prev_code;
++ 	if (mouse_ack_pending) {
++ 		/* It needn't actually be an ack, it could be an echo;
++ 		   but every byte sent to the mouse results in a byte
++ 		   back. */
++ 		wake_up_interruptible(&mouse_ack_wait);
++ 		mouse_ack_pending = 0;
++ 	}
+ 	if (mouse_reply_expected) {
+ 		if (scancode == AUX_ACK) {
+ 			mouse_reply_expected--;
+@@ -455,7 +490,7 @@
+ 		head = (head + 1) & (AUX_BUF_SIZE-1);
+ 		if (head != queue->tail) {
+ 			queue->head = head;
+-			kill_fasync(&queue->fasync, SIGIO, POLL_IN);
++			aux_kill_fasync(&queue->fasync, SIGIO, POLL_IN);
+ 			wake_up_interruptible(&queue->proc_list);
+ 		}
+ 	}
+@@ -972,19 +1007,75 @@
+ 	return retval;
+ }
+ 
++static void mouse_ack_timeout(unsigned long data)
++{
++	wake_up_interruptible(&mouse_ack_wait);
++}
++
+ /*
+  * Send a byte to the mouse.
+  */
+-static void aux_write_dev(int val)
++static int aux_write_dev(int val, int dont_block, int handle_ack)
+ {
+ 	unsigned long flags;
+ 
+ 	spin_lock_irqsave(&kbd_controller_lock, flags);
+ 	kb_wait();
++	/* If we haven't yet received the ACK from the previous write,
++	   we must wait for it.  */
++	if (mouse_ack_pending) {
++		unsigned long expires;
++		struct timer_list timer;
++		DECLARE_WAITQUEUE(wait, current);
++
++		if (dont_block) {
++			spin_unlock_irqrestore(&kbd_controller_lock, flags);
++			return -EAGAIN;
++		}
++		expires = mouse_ack_pending + MOUSE_ACK_TIMEOUT;
++		if (jiffies >= expires)
++			goto timed_out;
++
++		add_wait_queue(&mouse_ack_wait, &wait);
++		init_timer (&timer);
++		timer.expires = expires;
++		timer.data = 0;
++		timer.function = mouse_ack_timeout;
++		add_timer(&timer);
++
++		do {
++			current->state = TASK_INTERRUPTIBLE;
++			spin_unlock_irqrestore(&kbd_controller_lock, flags);
++			schedule();
++			spin_lock_irqsave(&kbd_controller_lock, flags);
++		} while (mouse_ack_pending
++			 && jiffies < expires
++			 && !signal_pending(current));
++
++		del_timer(&timer);
++		remove_wait_queue(&mouse_ack_wait, &wait);
++
++		if (mouse_ack_pending && jiffies >= expires) {
++		timed_out:
++			printk(KERN_WARNING "mouse ack timeout\n");
++			mouse_ack_pending = 0;
++			spin_unlock_irqrestore(&kbd_controller_lock, flags);
++			return -EIO;
++		}
++		if (signal_pending(current)) {
++			spin_unlock_irqrestore(&kbd_controller_lock, flags);
++			return -ERESTARTSYS;
++		}
++	}
+ 	kbd_write_command(KBD_CCMD_WRITE_MOUSE);
+ 	kb_wait();
+ 	kbd_write_output(val);
++	mouse_ack_pending = jiffies;
++	if (handle_ack)
++		/* We will deal with the ACK ourselves.  */
++		mouse_reply_expected++;
+ 	spin_unlock_irqrestore(&kbd_controller_lock, flags);
++	return 0;
+ }
+ 
+ /*
+@@ -996,11 +1087,13 @@
+ 	kbd_write_command(KBD_CCMD_WRITE_MOUSE);
+ 	kb_wait();
+ 	kbd_write_output(val);
+-	/* we expect an ACK in response. */
++	mouse_ack_pending = jiffies;
++	/* We will deal with the ACK ourselves.  */
+ 	mouse_reply_expected++;
+ 	kb_wait();
+ }
+ 
++#ifdef INITIALIZE_MOUSE
+ static void aux_write_ack(int val)
+ {
+ 	unsigned long flags;
+@@ -1009,6 +1102,33 @@
+ 	__aux_write_ack(val);
+ 	spin_unlock_irqrestore(&kbd_controller_lock, flags);
+ }
++#endif /* INITIALIZE_MOUSE */
++
++static void aux_kill_fasync(struct fasync_struct **fasync, int sig, int band)
++{
++	struct fasync_struct * fp;
++	struct fasync_struct fa;
++
++	fp = *fasync;
++	/* If someone has grabbed the AUX device, send signal only to
++	   them and not to other processes.  We could do this directly
++	   if send_sigio was exported, but since it isn't we must
++	   synthesize a "struct fasync_struct" to pass to
++	   kill_fasync. */
++	if (aux_exclusive) {
++		while (1) {
++			if (!fp)
++				return;
++			if (fp->fa_file == aux_exclusive)
++				break;
++			fp = fp->fa_next;
++		}
++		fa = (*fp);
++		fa.fa_next = NULL;
++		fp = &fa;
++	}
++	kill_fasync(&fp, sig, band);
++}
+ 
+ static unsigned char get_from_queue(void)
+ {
+@@ -1048,6 +1168,8 @@
+ {
+ 	lock_kernel();
+ 	fasync_aux(-1, file, 0);
++	if (aux_exclusive == file)
++		aux_release_ioctl(file);
+ 	if (--aux_count) {
+ 		unlock_kernel();
+ 		return 0;
+@@ -1077,7 +1199,7 @@
+ 	kbd_write_command_w(KBD_CCMD_MOUSE_ENABLE);	/* Enable the
+ 							   auxiliary port on
+ 							   controller. */
+-	aux_write_ack(AUX_ENABLE_DEV); /* Enable aux device */
++	aux_write_dev(AUX_ENABLE_DEV, 0, 1); /* Enable aux device */
+ 	kbd_write_cmd(AUX_INTS_ON); /* Enable controller ints */
+ 	
+ 	mdelay(2);			/* Ensure we follow the kbc access delay rules.. */
+@@ -1088,6 +1210,33 @@
+ }
+ 
+ /*
++ * Implement exclusive access mechanism.
++ */
++
++#define AUX_ACCESS_ALLOWED(file) (!aux_exclusive || aux_exclusive == (file))
++
++static ssize_t aux_wait_for_access(struct file * file)
++{
++	DECLARE_WAITQUEUE(wait, current);
++
++	if (!AUX_ACCESS_ALLOWED(file)) {
++		if (file->f_flags & O_NONBLOCK)
++			return -EAGAIN;
++		add_wait_queue(&aux_exclusive_wait, &wait);
++		do {
++			current->state = TASK_INTERRUPTIBLE;
++			schedule();
++		}
++		while (!AUX_ACCESS_ALLOWED(file)
++		       && !signal_pending(current));
++		remove_wait_queue(&aux_exclusive_wait, &wait);
++	}
++	if (!AUX_ACCESS_ALLOWED(file))
++		return -ERESTARTSYS;
++	return 0;
++}
++
++/*
+  * Put bytes from input queue to buffer.
+  */
+ 
+@@ -1097,7 +1246,11 @@
+ 	DECLARE_WAITQUEUE(wait, current);
+ 	ssize_t i = count;
+ 	unsigned char c;
++	ssize_t retval;
+ 
++	retval = aux_wait_for_access(file);
++	if (retval < 0)
++		return retval;
+ 	if (queue_empty()) {
+ 		if (file->f_flags & O_NONBLOCK)
+ 			return -EAGAIN;
+@@ -1132,23 +1285,32 @@
+ static ssize_t write_aux(struct file * file, const char * buffer,
+ 			 size_t count, loff_t *ppos)
+ {
+-	ssize_t retval = 0;
++	ssize_t retval;
+ 
++	retval = aux_wait_for_access(file);
++	if (retval < 0)
++		return retval;
+ 	if (count) {
+ 		ssize_t written = 0;
+ 
++		retval = -EIO;
+ 		if (count > 32)
+ 			count = 32; /* Limit to 32 bytes. */
+ 		do {
+ 			char c;
++			int write_result;
+ 			get_user(c, buffer++);
+-			aux_write_dev(c);
++			write_result = aux_write_dev(c, file->f_flags & O_NONBLOCK, 0);
++			if (write_result) {
++				retval = write_result;
++				break;
++			}
+ 			written++;
+ 		} while (--count);
+-		retval = -EIO;
+ 		if (written) {
+ 			retval = written;
+ 			file->f_dentry->d_inode->i_mtime = CURRENT_TIME;
++			aux_last_write = jiffies;
+ 		}
+ 	}
+ 
+@@ -1159,15 +1321,80 @@
+ static unsigned int aux_poll(struct file *file, poll_table * wait)
+ {
+ 	poll_wait(file, &queue->proc_list, wait);
+-	if (!queue_empty())
++	if (AUX_ACCESS_ALLOWED(file) && !queue_empty())
+ 		return POLLIN | POLLRDNORM;
+ 	return 0;
+ }
+ 
++/* Wait this long after last write to mouse before allowing AUX_GRAB
++   to happen.  This ensures that any outstanding mouse command is
++   completed.  The ACK from the command is supposed to arrive in 25
++   msec, and each subsequent status bytes are supposed to arrive
++   within 20 msec, so a command with 5 status bytes (I don't know any
++   this long) might take 125 msec.  Fudge this up a bit to account for
++   additional delay introduced by bus locking.  */
++#define AUX_GRAB_MIN_TIME (aux_last_write + (((200 * HZ) + 500) / 1000))
++#define AUX_GRAB_ALLOWED (aux_exclusive == 0 && (jiffies >= AUX_GRAB_MIN_TIME))
++
++static void aux_grab_timeout(unsigned long data)
++{
++	wake_up_interruptible(&aux_exclusive_wait);
++}
++
++static int aux_grab_ioctl(struct file *file)
++{
++	DECLARE_WAITQUEUE(wait, current);
++	struct timer_list timer;
++
++	if (aux_exclusive == file)
++		return -EINVAL;
++	if (!AUX_GRAB_ALLOWED) {
++		if (file->f_flags & O_NONBLOCK)
++			return -EAGAIN;
++		init_timer (&timer);
++		timer.expires = AUX_GRAB_MIN_TIME;
++		timer.data = 0;
++		timer.function = aux_grab_timeout;
++		add_wait_queue(&aux_exclusive_wait, &wait);
++		add_timer(&timer);
++		do {
++			current->state = TASK_INTERRUPTIBLE;
++			schedule();
++		}
++		while (!AUX_GRAB_ALLOWED && !signal_pending(current));
++		del_timer(&timer);
++		remove_wait_queue(&aux_exclusive_wait, &wait);
++	}
++	if (!AUX_GRAB_ALLOWED)
++		return -ERESTARTSYS;
++	aux_exclusive = file;
++	return 0;
++}
++
++static int aux_release_ioctl(struct file *file)
++{
++	if (aux_exclusive != file)
++		return -ENOENT;
++	aux_exclusive = 0;
++	wake_up_interruptible(&aux_exclusive_wait);
++	return 0;
++}
++
++static int aux_ioctl(struct inode *inode, struct file *file,
++		     unsigned int cmd, unsigned long arg)
++{
++	switch (cmd) {
++	case AUX_GRAB: return aux_grab_ioctl(file);
++	case AUX_RELEASE: return aux_release_ioctl(file);
++	default: return -EINVAL;
++	}
++}
++
+ struct file_operations psaux_fops = {
+ 	read:		read_aux,
+ 	write:		write_aux,
+ 	poll:		aux_poll,
++	ioctl:		aux_ioctl,
+ 	open:		open_aux,
+ 	release:	release_aux,
+ 	fasync:		fasync_aux,
+@@ -1199,6 +1426,8 @@
+ 	memset(queue, 0, sizeof(*queue));
+ 	queue->head = queue->tail = 0;
+ 	init_waitqueue_head(&queue->proc_list);
++	init_waitqueue_head(&mouse_ack_wait);
++ 	init_waitqueue_head(&aux_exclusive_wait);
+ 
+ #ifdef INITIALIZE_MOUSE
+ 	kbd_write_command_w(KBD_CCMD_MOUSE_ENABLE); /* Enable Aux. */
+@@ -1210,6 +1439,8 @@
+ #endif /* INITIALIZE_MOUSE */
+ 	kbd_write_command(KBD_CCMD_MOUSE_DISABLE); /* Disable aux device. */
+ 	kbd_write_cmd(AUX_INTS_OFF); /* Disable controller ints. */
++
++	aux_last_write = jiffies;
+ 
+ 	return 0;
+ }
+diff -ruN linux-2.4.15-orig/drivers/char/pc_keyb.c.orig linux-2.4.15/drivers/char/pc_keyb.c.orig
+--- linux-2.4.15-orig/drivers/char/pc_keyb.c.orig	Wed Dec 31 19:00:00 1969
++++ linux-2.4.15/drivers/char/pc_keyb.c.orig	Fri Nov  9 17:01:21 2001
+@@ -0,0 +1,1217 @@
++/*
++ * linux/drivers/char/pc_keyb.c
++ *
++ * Separation of the PC low-level part by Geert Uytterhoeven, May 1997
++ * See keyboard.c for the whole history.
++ *
++ * Major cleanup by Martin Mares, May 1997
++ *
++ * Combined the keyboard and PS/2 mouse handling into one file,
++ * because they share the same hardware.
++ * Johan Myreen <jem@iki.fi> 1998-10-08.
++ *
++ * Code fixes to handle mouse ACKs properly.
++ * C. Scott Ananian <cananian@alumni.princeton.edu> 1999-01-29.
++ *
++ */
++
++#include <linux/config.h>
++
++#include <linux/spinlock.h>
++#include <linux/sched.h>
++#include <linux/interrupt.h>
++#include <linux/tty.h>
++#include <linux/mm.h>
++#include <linux/signal.h>
++#include <linux/init.h>
++#include <linux/kbd_ll.h>
++#include <linux/delay.h>
++#include <linux/random.h>
++#include <linux/poll.h>
++#include <linux/miscdevice.h>
++#include <linux/slab.h>
++#include <linux/kbd_kern.h>
++#include <linux/vt_kern.h>
++#include <linux/smp_lock.h>
++#include <linux/kd.h>
++#include <linux/pm.h>
++
++#include <asm/keyboard.h>
++#include <asm/bitops.h>
++#include <asm/uaccess.h>
++#include <asm/irq.h>
++#include <asm/system.h>
++
++#include <asm/io.h>
++
++/* Some configuration switches are present in the include file... */
++
++#include <linux/pc_keyb.h>
++
++/* Simple translation table for the SysRq keys */
++
++#ifdef CONFIG_MAGIC_SYSRQ
++unsigned char pckbd_sysrq_xlate[128] =
++	"\000\0331234567890-=\177\t"			/* 0x00 - 0x0f */
++	"qwertyuiop[]\r\000as"				/* 0x10 - 0x1f */
++	"dfghjkl;'`\000\\zxcv"				/* 0x20 - 0x2f */
++	"bnm,./\000*\000 \000\201\202\203\204\205"	/* 0x30 - 0x3f */
++	"\206\207\210\211\212\000\000789-456+1"		/* 0x40 - 0x4f */
++	"230\177\000\000\213\214\000\000\000\000\000\000\000\000\000\000" /* 0x50 - 0x5f */
++	"\r\000/";					/* 0x60 - 0x6f */
++#endif
++
++static void kbd_write_command_w(int data);
++static void kbd_write_output_w(int data);
++#ifdef CONFIG_PSMOUSE
++static void aux_write_ack(int val);
++static void __aux_write_ack(int val);
++static int aux_reconnect = 0;
++#endif
++
++static spinlock_t kbd_controller_lock = SPIN_LOCK_UNLOCKED;
++static unsigned char handle_kbd_event(void);
++
++/* used only by send_data - set by keyboard_interrupt */
++static volatile unsigned char reply_expected;
++static volatile unsigned char acknowledge;
++static volatile unsigned char resend;
++
++
++#if defined CONFIG_PSMOUSE
++/*
++ *	PS/2 Auxiliary Device
++ */
++
++static int __init psaux_init(void);
++
++#define AUX_RECONNECT1 0xaa	/* scancode1 when ps2 device is plugged (back) in */
++#define AUX_RECONNECT2 0x00	/* scancode2 when ps2 device is plugged (back) in */
++ 
++static struct aux_queue *queue;	/* Mouse data buffer. */
++static int aux_count;
++/* used when we send commands to the mouse that expect an ACK. */
++static unsigned char mouse_reply_expected;
++
++#define AUX_INTS_OFF (KBD_MODE_KCC | KBD_MODE_DISABLE_MOUSE | KBD_MODE_SYS | KBD_MODE_KBD_INT)
++#define AUX_INTS_ON  (KBD_MODE_KCC | KBD_MODE_SYS | KBD_MODE_MOUSE_INT | KBD_MODE_KBD_INT)
++
++#define MAX_RETRIES	60		/* some aux operations take long time*/
++#endif /* CONFIG_PSMOUSE */
++
++/*
++ * Wait for keyboard controller input buffer to drain.
++ *
++ * Don't use 'jiffies' so that we don't depend on
++ * interrupts..
++ *
++ * Quote from PS/2 System Reference Manual:
++ *
++ * "Address hex 0060 and address hex 0064 should be written only when
++ * the input-buffer-full bit and output-buffer-full bit in the
++ * Controller Status register are set 0."
++ */
++
++static void kb_wait(void)
++{
++	unsigned long timeout = KBC_TIMEOUT;
++
++	do {
++		/*
++		 * "handle_kbd_event()" will handle any incoming events
++		 * while we wait - keypresses or mouse movement.
++		 */
++		unsigned char status = handle_kbd_event();
++
++		if (! (status & KBD_STAT_IBF))
++			return;
++		mdelay(1);
++		timeout--;
++	} while (timeout);
++#ifdef KBD_REPORT_TIMEOUTS
++	printk(KERN_WARNING "Keyboard timed out[1]\n");
++#endif
++}
++
++/*
++ * Translation of escaped scancodes to keycodes.
++ * This is now user-settable.
++ * The keycodes 1-88,96-111,119 are fairly standard, and
++ * should probably not be changed - changing might confuse X.
++ * X also interprets scancode 0x5d (KEY_Begin).
++ *
++ * For 1-88 keycode equals scancode.
++ */
++
++#define E0_KPENTER 96
++#define E0_RCTRL   97
++#define E0_KPSLASH 98
++#define E0_PRSCR   99
++#define E0_RALT    100
++#define E0_BREAK   101  /* (control-pause) */
++#define E0_HOME    102
++#define E0_UP      103
++#define E0_PGUP    104
++#define E0_LEFT    105
++#define E0_RIGHT   106
++#define E0_END     107
++#define E0_DOWN    108
++#define E0_PGDN    109
++#define E0_INS     110
++#define E0_DEL     111
++
++#define E1_PAUSE   119
++
++/*
++ * The keycodes below are randomly located in 89-95,112-118,120-127.
++ * They could be thrown away (and all occurrences below replaced by 0),
++ * but that would force many users to use the `setkeycodes' utility, where
++ * they needed not before. It does not matter that there are duplicates, as
++ * long as no duplication occurs for any single keyboard.
++ */
++#define SC_LIM 89
++
++#define FOCUS_PF1 85           /* actual code! */
++#define FOCUS_PF2 89
++#define FOCUS_PF3 90
++#define FOCUS_PF4 91
++#define FOCUS_PF5 92
++#define FOCUS_PF6 93
++#define FOCUS_PF7 94
++#define FOCUS_PF8 95
++#define FOCUS_PF9 120
++#define FOCUS_PF10 121
++#define FOCUS_PF11 122
++#define FOCUS_PF12 123
++
++#define JAP_86     124
++/* tfj@olivia.ping.dk:
++ * The four keys are located over the numeric keypad, and are
++ * labelled A1-A4. It's an rc930 keyboard, from
++ * Regnecentralen/RC International, Now ICL.
++ * Scancodes: 59, 5a, 5b, 5c.
++ */
++#define RGN1 124
++#define RGN2 125
++#define RGN3 126
++#define RGN4 127
++
++static unsigned char high_keys[128 - SC_LIM] = {
++  RGN1, RGN2, RGN3, RGN4, 0, 0, 0,                   /* 0x59-0x5f */
++  0, 0, 0, 0, 0, 0, 0, 0,                            /* 0x60-0x67 */
++  0, 0, 0, 0, 0, FOCUS_PF11, 0, FOCUS_PF12,          /* 0x68-0x6f */
++  0, 0, 0, FOCUS_PF2, FOCUS_PF9, 0, 0, FOCUS_PF3,    /* 0x70-0x77 */
++  FOCUS_PF4, FOCUS_PF5, FOCUS_PF6, FOCUS_PF7,        /* 0x78-0x7b */
++  FOCUS_PF8, JAP_86, FOCUS_PF10, 0                   /* 0x7c-0x7f */
++};
++
++/* BTC */
++#define E0_MACRO   112
++/* LK450 */
++#define E0_F13     113
++#define E0_F14     114
++#define E0_HELP    115
++#define E0_DO      116
++#define E0_F17     117
++#define E0_KPMINPLUS 118
++/*
++ * My OmniKey generates e0 4c for  the "OMNI" key and the
++ * right alt key does nada. [kkoller@nyx10.cs.du.edu]
++ */
++#define E0_OK	124
++/*
++ * New microsoft keyboard is rumoured to have
++ * e0 5b (left window button), e0 5c (right window button),
++ * e0 5d (menu button). [or: LBANNER, RBANNER, RMENU]
++ * [or: Windows_L, Windows_R, TaskMan]
++ */
++#define E0_MSLW	125
++#define E0_MSRW	126
++#define E0_MSTM	127
++
++static unsigned char e0_keys[128] = {
++  0, 0, 0, 0, 0, 0, 0, 0,			      /* 0x00-0x07 */
++  0, 0, 0, 0, 0, 0, 0, 0,			      /* 0x08-0x0f */
++  0, 0, 0, 0, 0, 0, 0, 0,			      /* 0x10-0x17 */
++  0, 0, 0, 0, E0_KPENTER, E0_RCTRL, 0, 0,	      /* 0x18-0x1f */
++  0, 0, 0, 0, 0, 0, 0, 0,			      /* 0x20-0x27 */
++  0, 0, 0, 0, 0, 0, 0, 0,			      /* 0x28-0x2f */
++  0, 0, 0, 0, 0, E0_KPSLASH, 0, E0_PRSCR,	      /* 0x30-0x37 */
++  E0_RALT, 0, 0, 0, 0, E0_F13, E0_F14, E0_HELP,	      /* 0x38-0x3f */
++  E0_DO, E0_F17, 0, 0, 0, 0, E0_BREAK, E0_HOME,	      /* 0x40-0x47 */
++  E0_UP, E0_PGUP, 0, E0_LEFT, E0_OK, E0_RIGHT, E0_KPMINPLUS, E0_END,/* 0x48-0x4f */
++  E0_DOWN, E0_PGDN, E0_INS, E0_DEL, 0, 0, 0, 0,	      /* 0x50-0x57 */
++  0, 0, 0, E0_MSLW, E0_MSRW, E0_MSTM, 0, 0,	      /* 0x58-0x5f */
++  0, 0, 0, 0, 0, 0, 0, 0,			      /* 0x60-0x67 */
++  0, 0, 0, 0, 0, 0, 0, E0_MACRO,		      /* 0x68-0x6f */
++  0, 0, 0, 0, 0, 0, 0, 0,			      /* 0x70-0x77 */
++  0, 0, 0, 0, 0, 0, 0, 0			      /* 0x78-0x7f */
++};
++
++int pckbd_setkeycode(unsigned int scancode, unsigned int keycode)
++{
++	if (scancode < SC_LIM || scancode > 255 || keycode > 127)
++	  return -EINVAL;
++	if (scancode < 128)
++	  high_keys[scancode - SC_LIM] = keycode;
++	else
++	  e0_keys[scancode - 128] = keycode;
++	return 0;
++}
++
++int pckbd_getkeycode(unsigned int scancode)
++{
++	return
++	  (scancode < SC_LIM || scancode > 255) ? -EINVAL :
++	  (scancode < 128) ? high_keys[scancode - SC_LIM] :
++	    e0_keys[scancode - 128];
++}
++
++static int do_acknowledge(unsigned char scancode)
++{
++	if (reply_expected) {
++	  /* Unfortunately, we must recognise these codes only if we know they
++	   * are known to be valid (i.e., after sending a command), because there
++	   * are some brain-damaged keyboards (yes, FOCUS 9000 again) which have
++	   * keys with such codes :(
++	   */
++		if (scancode == KBD_REPLY_ACK) {
++			acknowledge = 1;
++			reply_expected = 0;
++			return 0;
++		} else if (scancode == KBD_REPLY_RESEND) {
++			resend = 1;
++			reply_expected = 0;
++			return 0;
++		}
++		/* Should not happen... */
++#if 0
++		printk(KERN_DEBUG "keyboard reply expected - got %02x\n",
++		       scancode);
++#endif
++	}
++	return 1;
++}
++
++int pckbd_translate(unsigned char scancode, unsigned char *keycode,
++		    char raw_mode)
++{
++	static int prev_scancode;
++
++	/* special prefix scancodes.. */
++	if (scancode == 0xe0 || scancode == 0xe1) {
++		prev_scancode = scancode;
++		return 0;
++	}
++
++	/* 0xFF is sent by a few keyboards, ignore it. 0x00 is error */
++	if (scancode == 0x00 || scancode == 0xff) {
++		prev_scancode = 0;
++		return 0;
++	}
++
++	scancode &= 0x7f;
++
++	if (prev_scancode) {
++	  /*
++	   * usually it will be 0xe0, but a Pause key generates
++	   * e1 1d 45 e1 9d c5 when pressed, and nothing when released
++	   */
++	  if (prev_scancode != 0xe0) {
++	      if (prev_scancode == 0xe1 && scancode == 0x1d) {
++		  prev_scancode = 0x100;
++		  return 0;
++	      } else if (prev_scancode == 0x100 && scancode == 0x45) {
++		  *keycode = E1_PAUSE;
++		  prev_scancode = 0;
++	      } else {
++#ifdef KBD_REPORT_UNKN
++		  if (!raw_mode)
++		    printk(KERN_INFO "keyboard: unknown e1 escape sequence\n");
++#endif
++		  prev_scancode = 0;
++		  return 0;
++	      }
++	  } else {
++	      prev_scancode = 0;
++	      /*
++	       *  The keyboard maintains its own internal caps lock and
++	       *  num lock statuses. In caps lock mode E0 AA precedes make
++	       *  code and E0 2A follows break code. In num lock mode,
++	       *  E0 2A precedes make code and E0 AA follows break code.
++	       *  We do our own book-keeping, so we will just ignore these.
++	       */
++	      /*
++	       *  For my keyboard there is no caps lock mode, but there are
++	       *  both Shift-L and Shift-R modes. The former mode generates
++	       *  E0 2A / E0 AA pairs, the latter E0 B6 / E0 36 pairs.
++	       *  So, we should also ignore the latter. - aeb@cwi.nl
++	       */
++	      if (scancode == 0x2a || scancode == 0x36)
++		return 0;
++
++	      if (e0_keys[scancode])
++		*keycode = e0_keys[scancode];
++	      else {
++#ifdef KBD_REPORT_UNKN
++		  if (!raw_mode)
++		    printk(KERN_INFO "keyboard: unknown scancode e0 %02x\n",
++			   scancode);
++#endif
++		  return 0;
++	      }
++	  }
++	} else if (scancode >= SC_LIM) {
++	    /* This happens with the FOCUS 9000 keyboard
++	       Its keys PF1..PF12 are reported to generate
++	       55 73 77 78 79 7a 7b 7c 74 7e 6d 6f
++	       Moreover, unless repeated, they do not generate
++	       key-down events, so we have to zero up_flag below */
++	    /* Also, Japanese 86/106 keyboards are reported to
++	       generate 0x73 and 0x7d for \ - and \ | respectively. */
++	    /* Also, some Brazilian keyboard is reported to produce
++	       0x73 and 0x7e for \ ? and KP-dot, respectively. */
++
++	  *keycode = high_keys[scancode - SC_LIM];
++
++	  if (!*keycode) {
++	      if (!raw_mode) {
++#ifdef KBD_REPORT_UNKN
++		  printk(KERN_INFO "keyboard: unrecognized scancode (%02x)"
++			 " - ignored\n", scancode);
++#endif
++	      }
++	      return 0;
++	  }
++ 	} else
++	  *keycode = scancode;
++ 	return 1;
++}
++
++char pckbd_unexpected_up(unsigned char keycode)
++{
++	/* unexpected, but this can happen: maybe this was a key release for a
++	   FOCUS 9000 PF key; if we want to see it, we have to clear up_flag */
++	if (keycode >= SC_LIM || keycode == 85)
++	    return 0;
++	else
++	    return 0200;
++}
++
++int pckbd_pm_resume(struct pm_dev *dev, pm_request_t rqst, void *data) 
++{
++#if defined CONFIG_PSMOUSE
++       unsigned long flags;
++
++       if (rqst == PM_RESUME) {
++               if (queue) {                    /* Aux port detected */
++                       if (aux_count == 0) {   /* Mouse not in use */ 
++                               spin_lock_irqsave(&kbd_controller_lock, flags);
++			       /*
++				* Dell Lat. C600 A06 enables mouse after resume.
++				* When user touches the pad, it posts IRQ 12
++				* (which we do not process), thus holding keyboard.
++				*/
++			       kbd_write_command(KBD_CCMD_MOUSE_DISABLE);
++			       /* kbd_write_cmd(AUX_INTS_OFF); */ /* Config & lock */
++			       kb_wait();
++			       kbd_write_command(KBD_CCMD_WRITE_MODE);
++			       kb_wait();
++			       kbd_write_output(AUX_INTS_OFF);
++			       spin_unlock_irqrestore(&kbd_controller_lock, flags);
++		       }
++	       }
++       }
++#endif
++       return 0;
++}
++
++
++static inline void handle_mouse_event(unsigned char scancode)
++{
++#ifdef CONFIG_PSMOUSE
++	static unsigned char prev_code;
++	if (mouse_reply_expected) {
++		if (scancode == AUX_ACK) {
++			mouse_reply_expected--;
++			return;
++		}
++		mouse_reply_expected = 0;
++	}
++	else if(scancode == AUX_RECONNECT2 && prev_code == AUX_RECONNECT1
++		&& aux_reconnect) {
++		printk (KERN_INFO "PS/2 mouse reconnect detected\n");
++		queue->head = queue->tail = 0;	/* Flush input queue */
++		__aux_write_ack(AUX_ENABLE_DEV);  /* ping the mouse :) */
++		return;
++	}
++
++	prev_code = scancode;
++	add_mouse_randomness(scancode);
++	if (aux_count) {
++		int head = queue->head;
++
++		queue->buf[head] = scancode;
++		head = (head + 1) & (AUX_BUF_SIZE-1);
++		if (head != queue->tail) {
++			queue->head = head;
++			kill_fasync(&queue->fasync, SIGIO, POLL_IN);
++			wake_up_interruptible(&queue->proc_list);
++		}
++	}
++#endif
++}
++
++static unsigned char kbd_exists = 1;
++
++static inline void handle_keyboard_event(unsigned char scancode)
++{
++#ifdef CONFIG_VT
++	kbd_exists = 1;
++	if (do_acknowledge(scancode))
++		handle_scancode(scancode, !(scancode & 0x80));
++#endif				
++	tasklet_schedule(&keyboard_tasklet);
++}	
++
++/*
++ * This reads the keyboard status port, and does the
++ * appropriate action.
++ *
++ * It requires that we hold the keyboard controller
++ * spinlock.
++ */
++static unsigned char handle_kbd_event(void)
++{
++	unsigned char status = kbd_read_status();
++	unsigned int work = 10000;
++
++	while ((--work > 0) && (status & KBD_STAT_OBF)) {
++		unsigned char scancode;
++
++		scancode = kbd_read_input();
++
++		/* Error bytes must be ignored to make the 
++		   Synaptics touchpads compaq use work */
++#if 1
++		/* Ignore error bytes */
++		if (!(status & (KBD_STAT_GTO | KBD_STAT_PERR)))
++#endif
++		{
++			if (status & KBD_STAT_MOUSE_OBF)
++				handle_mouse_event(scancode);
++			else
++				handle_keyboard_event(scancode);
++		}
++
++		status = kbd_read_status();
++	}
++		
++	if (!work)
++		printk(KERN_ERR "pc_keyb: controller jammed (0x%02X).\n", status);
++
++	return status;
++}
++
++
++static void keyboard_interrupt(int irq, void *dev_id, struct pt_regs *regs)
++{
++#ifdef CONFIG_VT
++	kbd_pt_regs = regs;
++#endif
++
++	spin_lock_irq(&kbd_controller_lock);
++	handle_kbd_event();
++	spin_unlock_irq(&kbd_controller_lock);
++}
++
++/*
++ * send_data sends a character to the keyboard and waits
++ * for an acknowledge, possibly retrying if asked to. Returns
++ * the success status.
++ *
++ * Don't use 'jiffies', so that we don't depend on interrupts
++ */
++static int send_data(unsigned char data)
++{
++	int retries = 3;
++
++	do {
++		unsigned long timeout = KBD_TIMEOUT;
++
++		acknowledge = 0; /* Set by interrupt routine on receipt of ACK. */
++		resend = 0;
++		reply_expected = 1;
++		kbd_write_output_w(data);
++		for (;;) {
++			if (acknowledge)
++				return 1;
++			if (resend)
++				break;
++			mdelay(1);
++			if (!--timeout) {
++#ifdef KBD_REPORT_TIMEOUTS
++				printk(KERN_WARNING "keyboard: Timeout - AT keyboard not present?(%02x)\n", data);
++#endif
++				return 0;
++			}
++		}
++	} while (retries-- > 0);
++#ifdef KBD_REPORT_TIMEOUTS
++	printk(KERN_WARNING "keyboard: Too many NACKs -- noisy kbd cable?\n");
++#endif
++	return 0;
++}
++
++void pckbd_leds(unsigned char leds)
++{
++	if (kbd_exists && (!send_data(KBD_CMD_SET_LEDS) || !send_data(leds))) {
++		send_data(KBD_CMD_ENABLE);	/* re-enable kbd if any errors */
++		kbd_exists = 0;
++	}
++}
++
++#define DEFAULT_KEYB_REP_DELAY	250
++#define DEFAULT_KEYB_REP_RATE	30	/* cps */
++
++static struct kbd_repeat kbdrate={
++	DEFAULT_KEYB_REP_DELAY,
++	DEFAULT_KEYB_REP_RATE
++};
++
++static unsigned char parse_kbd_rate(struct kbd_repeat *r)
++{
++	static struct r2v{
++		int rate;
++		unsigned char val;
++	} kbd_rates[]={	{5,0x14},
++			{7,0x10},
++			{10,0x0c},
++			{15,0x08},
++			{20,0x04},
++			{25,0x02},
++			{30,0x00}
++	};
++	static struct d2v{
++		int delay;
++		unsigned char val;
++	} kbd_delays[]={{250,0},
++			{500,1},
++			{750,2},
++			{1000,3}
++	};
++	int rate=0,delay=0;
++	if (r != NULL){
++		int i,new_rate=30,new_delay=250;
++		if (r->rate <= 0)
++			r->rate=kbdrate.rate;
++		if (r->delay <= 0)
++			r->delay=kbdrate.delay;
++		for (i=0; i < sizeof(kbd_rates)/sizeof(struct r2v); i++)
++			if (kbd_rates[i].rate == r->rate){
++				new_rate=kbd_rates[i].rate;
++				rate=kbd_rates[i].val;
++				break;
++			}
++		for (i=0; i < sizeof(kbd_delays)/sizeof(struct d2v); i++)
++			if (kbd_delays[i].delay == r->delay){
++				new_delay=kbd_delays[i].delay;
++				delay=kbd_delays[i].val;
++				break;
++			}
++		r->rate=new_rate;
++		r->delay=new_delay;
++	}
++	return (delay << 5) | rate;
++}
++
++static int write_kbd_rate(unsigned char r)
++{
++	if (!send_data(KBD_CMD_SET_RATE) || !send_data(r)){
++		send_data(KBD_CMD_ENABLE); 	/* re-enable kbd if any errors */
++		return 0;
++	}else
++		return 1;
++}
++
++static int pckbd_rate(struct kbd_repeat *rep)
++{
++	if (rep == NULL)
++		return -EINVAL;
++	else{
++		unsigned char r=parse_kbd_rate(rep);
++		struct kbd_repeat old_rep;
++		memcpy(&old_rep,&kbdrate,sizeof(struct kbd_repeat));
++		if (write_kbd_rate(r)){
++			memcpy(&kbdrate,rep,sizeof(struct kbd_repeat));
++			memcpy(rep,&old_rep,sizeof(struct kbd_repeat));
++			return 0;
++		}
++	}
++	return -EIO;
++}
++
++/*
++ * In case we run on a non-x86 hardware we need to initialize both the
++ * keyboard controller and the keyboard.  On a x86, the BIOS will
++ * already have initialized them.
++ *
++ * Some x86 BIOSes do not correctly initialize the keyboard, so the
++ * "kbd-reset" command line options can be given to force a reset.
++ * [Ranger]
++ */
++#ifdef __i386__
++ int kbd_startup_reset __initdata = 0;
++#else
++ int kbd_startup_reset __initdata = 1;
++#endif
++
++/* for "kbd-reset" cmdline param */
++static int __init kbd_reset_setup(char *str)
++{
++	kbd_startup_reset = 1;
++	return 1;
++}
++
++__setup("kbd-reset", kbd_reset_setup);
++
++#define KBD_NO_DATA	(-1)	/* No data */
++#define KBD_BAD_DATA	(-2)	/* Parity or other error */
++
++static int __init kbd_read_data(void)
++{
++	int retval = KBD_NO_DATA;
++	unsigned char status;
++
++	status = kbd_read_status();
++	if (status & KBD_STAT_OBF) {
++		unsigned char data = kbd_read_input();
++
++		retval = data;
++		if (status & (KBD_STAT_GTO | KBD_STAT_PERR))
++			retval = KBD_BAD_DATA;
++	}
++	return retval;
++}
++
++static void __init kbd_clear_input(void)
++{
++	int maxread = 100;	/* Random number */
++
++	do {
++		if (kbd_read_data() == KBD_NO_DATA)
++			break;
++	} while (--maxread);
++}
++
++static int __init kbd_wait_for_input(void)
++{
++	long timeout = KBD_INIT_TIMEOUT;
++
++	do {
++		int retval = kbd_read_data();
++		if (retval >= 0)
++			return retval;
++		mdelay(1);
++	} while (--timeout);
++	return -1;
++}
++
++static void kbd_write_command_w(int data)
++{
++	unsigned long flags;
++
++	spin_lock_irqsave(&kbd_controller_lock, flags);
++	kb_wait();
++	kbd_write_command(data);
++	spin_unlock_irqrestore(&kbd_controller_lock, flags);
++}
++
++static void kbd_write_output_w(int data)
++{
++	unsigned long flags;
++
++	spin_lock_irqsave(&kbd_controller_lock, flags);
++	kb_wait();
++	kbd_write_output(data);
++	spin_unlock_irqrestore(&kbd_controller_lock, flags);
++}
++
++#if defined(__alpha__)
++/*
++ * Some Alphas cannot mask some/all interrupts, so we have to
++ * make sure not to allow interrupts AT ALL when polling for
++ * specific return values from the keyboard.
++ *
++ * I think this should work on any architecture, but for now, only Alpha.
++ */
++static int kbd_write_command_w_and_wait(int data)
++{
++	unsigned long flags;
++	int input;
++
++	spin_lock_irqsave(&kbd_controller_lock, flags);
++	kb_wait();
++	kbd_write_command(data);
++	input = kbd_wait_for_input();
++	spin_unlock_irqrestore(&kbd_controller_lock, flags);
++	return input;
++}
++
++static int kbd_write_output_w_and_wait(int data)
++{
++	unsigned long flags;
++	int input;
++
++	spin_lock_irqsave(&kbd_controller_lock, flags);
++	kb_wait();
++	kbd_write_output(data);
++	input = kbd_wait_for_input();
++	spin_unlock_irqrestore(&kbd_controller_lock, flags);
++	return input;
++}
++#else
++static int kbd_write_command_w_and_wait(int data)
++{
++	kbd_write_command_w(data);
++	return kbd_wait_for_input();
++}
++
++static int kbd_write_output_w_and_wait(int data)
++{
++	kbd_write_output_w(data);
++	return kbd_wait_for_input();
++}
++#endif /* __alpha__ */
++
++#if defined CONFIG_PSMOUSE
++static void kbd_write_cmd(int cmd)
++{
++	unsigned long flags;
++
++	spin_lock_irqsave(&kbd_controller_lock, flags);
++	kb_wait();
++	kbd_write_command(KBD_CCMD_WRITE_MODE);
++	kb_wait();
++	kbd_write_output(cmd);
++	spin_unlock_irqrestore(&kbd_controller_lock, flags);
++}
++#endif /* CONFIG_PSMOUSE */
++
++static char * __init initialize_kbd(void)
++{
++	int status;
++
++	/*
++	 * Test the keyboard interface.
++	 * This seems to be the only way to get it going.
++	 * If the test is successful a x55 is placed in the input buffer.
++	 */
++	kbd_write_command_w(KBD_CCMD_SELF_TEST);
++	if (kbd_wait_for_input() != 0x55)
++		return "Keyboard failed self test";
++
++	/*
++	 * Perform a keyboard interface test.  This causes the controller
++	 * to test the keyboard clock and data lines.  The results of the
++	 * test are placed in the input buffer.
++	 */
++	kbd_write_command_w(KBD_CCMD_KBD_TEST);
++	if (kbd_wait_for_input() != 0x00)
++		return "Keyboard interface failed self test";
++
++	/*
++	 * Enable the keyboard by allowing the keyboard clock to run.
++	 */
++	kbd_write_command_w(KBD_CCMD_KBD_ENABLE);
++
++	/*
++	 * Reset keyboard. If the read times out
++	 * then the assumption is that no keyboard is
++	 * plugged into the machine.
++	 * This defaults the keyboard to scan-code set 2.
++	 *
++	 * Set up to try again if the keyboard asks for RESEND.
++	 */
++	do {
++		kbd_write_output_w(KBD_CMD_RESET);
++		status = kbd_wait_for_input();
++		if (status == KBD_REPLY_ACK)
++			break;
++		if (status != KBD_REPLY_RESEND)
++			return "Keyboard reset failed, no ACK";
++	} while (1);
++
++	if (kbd_wait_for_input() != KBD_REPLY_POR)
++		return "Keyboard reset failed, no POR";
++
++	/*
++	 * Set keyboard controller mode. During this, the keyboard should be
++	 * in the disabled state.
++	 *
++	 * Set up to try again if the keyboard asks for RESEND.
++	 */
++	do {
++		kbd_write_output_w(KBD_CMD_DISABLE);
++		status = kbd_wait_for_input();
++		if (status == KBD_REPLY_ACK)
++			break;
++		if (status != KBD_REPLY_RESEND)
++			return "Disable keyboard: no ACK";
++	} while (1);
++
++	kbd_write_command_w(KBD_CCMD_WRITE_MODE);
++	kbd_write_output_w(KBD_MODE_KBD_INT
++			      | KBD_MODE_SYS
++			      | KBD_MODE_DISABLE_MOUSE
++			      | KBD_MODE_KCC);
++
++	/* ibm powerpc portables need this to use scan-code set 1 -- Cort */
++	if (!(kbd_write_command_w_and_wait(KBD_CCMD_READ_MODE) & KBD_MODE_KCC))
++	{
++		/*
++		 * If the controller does not support conversion,
++		 * Set the keyboard to scan-code set 1.
++		 */
++		kbd_write_output_w(0xF0);
++		kbd_wait_for_input();
++		kbd_write_output_w(0x01);
++		kbd_wait_for_input();
++	}
++
++	if (kbd_write_output_w_and_wait(KBD_CMD_ENABLE) != KBD_REPLY_ACK)
++		return "Enable keyboard: no ACK";
++
++	/*
++	 * Finally, set the typematic rate to maximum.
++	 */
++	if (kbd_write_output_w_and_wait(KBD_CMD_SET_RATE) != KBD_REPLY_ACK)
++		return "Set rate: no ACK";
++	if (kbd_write_output_w_and_wait(0x00) != KBD_REPLY_ACK)
++		return "Set rate: no 2nd ACK";
++
++	return NULL;
++}
++
++void __init pckbd_init_hw(void)
++{
++	kbd_request_region();
++
++	/* Flush any pending input. */
++	kbd_clear_input();
++
++	if (kbd_startup_reset) {
++		char *msg = initialize_kbd();
++		if (msg)
++			printk(KERN_WARNING "initialize_kbd: %s\n", msg);
++	}
++
++#if defined CONFIG_PSMOUSE
++	psaux_init();
++#endif
++
++	kbd_rate = pckbd_rate;
++
++	/* Ok, finally allocate the IRQ, and off we go.. */
++	kbd_request_irq(keyboard_interrupt);
++}
++
++#if defined CONFIG_PSMOUSE
++
++static int __init aux_reconnect_setup (char *str)
++{
++	aux_reconnect = 1;
++	return 1;
++}
++
++__setup("psaux-reconnect", aux_reconnect_setup);
++
++/*
++ * Check if this is a dual port controller.
++ */
++static int __init detect_auxiliary_port(void)
++{
++	unsigned long flags;
++	int loops = 10;
++	int retval = 0;
++
++	/* Check if the BIOS detected a device on the auxiliary port. */
++	if (aux_device_present == 0xaa)
++		return 1;
++
++	spin_lock_irqsave(&kbd_controller_lock, flags);
++
++	/* Put the value 0x5A in the output buffer using the "Write
++	 * Auxiliary Device Output Buffer" command (0xD3). Poll the
++	 * Status Register for a while to see if the value really
++	 * turns up in the Data Register. If the KBD_STAT_MOUSE_OBF
++	 * bit is also set to 1 in the Status Register, we assume this
++	 * controller has an Auxiliary Port (a.k.a. Mouse Port).
++	 */
++	kb_wait();
++	kbd_write_command(KBD_CCMD_WRITE_AUX_OBUF);
++
++	kb_wait();
++	kbd_write_output(0x5a); /* 0x5a is a random dummy value. */
++
++	do {
++		unsigned char status = kbd_read_status();
++
++		if (status & KBD_STAT_OBF) {
++			(void) kbd_read_input();
++			if (status & KBD_STAT_MOUSE_OBF) {
++				printk(KERN_INFO "Detected PS/2 Mouse Port.\n");
++				retval = 1;
++			}
++			break;
++		}
++		mdelay(1);
++	} while (--loops);
++	spin_unlock_irqrestore(&kbd_controller_lock, flags);
++
++	return retval;
++}
++
++/*
++ * Send a byte to the mouse.
++ */
++static void aux_write_dev(int val)
++{
++	unsigned long flags;
++
++	spin_lock_irqsave(&kbd_controller_lock, flags);
++	kb_wait();
++	kbd_write_command(KBD_CCMD_WRITE_MOUSE);
++	kb_wait();
++	kbd_write_output(val);
++	spin_unlock_irqrestore(&kbd_controller_lock, flags);
++}
++
++/*
++ * Send a byte to the mouse & handle returned ack
++ */
++static void __aux_write_ack(int val)
++{
++	kb_wait();
++	kbd_write_command(KBD_CCMD_WRITE_MOUSE);
++	kb_wait();
++	kbd_write_output(val);
++	/* we expect an ACK in response. */
++	mouse_reply_expected++;
++	kb_wait();
++}
++
++static void aux_write_ack(int val)
++{
++	unsigned long flags;
++
++	spin_lock_irqsave(&kbd_controller_lock, flags);
++	__aux_write_ack(val);
++	spin_unlock_irqrestore(&kbd_controller_lock, flags);
++}
++
++static unsigned char get_from_queue(void)
++{
++	unsigned char result;
++	unsigned long flags;
++
++	spin_lock_irqsave(&kbd_controller_lock, flags);
++	result = queue->buf[queue->tail];
++	queue->tail = (queue->tail + 1) & (AUX_BUF_SIZE-1);
++	spin_unlock_irqrestore(&kbd_controller_lock, flags);
++	return result;
++}
++
++
++static inline int queue_empty(void)
++{
++	return queue->head == queue->tail;
++}
++
++static int fasync_aux(int fd, struct file *filp, int on)
++{
++	int retval;
++
++	retval = fasync_helper(fd, filp, on, &queue->fasync);
++	if (retval < 0)
++		return retval;
++	return 0;
++}
++
++
++/*
++ * Random magic cookie for the aux device
++ */
++#define AUX_DEV ((void *)queue)
++
++static int release_aux(struct inode * inode, struct file * file)
++{
++	lock_kernel();
++	fasync_aux(-1, file, 0);
++	if (--aux_count) {
++		unlock_kernel();
++		return 0;
++	}
++	kbd_write_cmd(AUX_INTS_OFF);			    /* Disable controller ints */
++	kbd_write_command_w(KBD_CCMD_MOUSE_DISABLE);
++	aux_free_irq(AUX_DEV);
++	unlock_kernel();
++	return 0;
++}
++
++/*
++ * Install interrupt handler.
++ * Enable auxiliary device.
++ */
++
++static int open_aux(struct inode * inode, struct file * file)
++{
++	if (aux_count++) {
++		return 0;
++	}
++	queue->head = queue->tail = 0;		/* Flush input queue */
++	if (aux_request_irq(keyboard_interrupt, AUX_DEV)) {
++		aux_count--;
++		return -EBUSY;
++	}
++	kbd_write_command_w(KBD_CCMD_MOUSE_ENABLE);	/* Enable the
++							   auxiliary port on
++							   controller. */
++	aux_write_ack(AUX_ENABLE_DEV); /* Enable aux device */
++	kbd_write_cmd(AUX_INTS_ON); /* Enable controller ints */
++	
++	mdelay(2);			/* Ensure we follow the kbc access delay rules.. */
++
++	send_data(KBD_CMD_ENABLE);	/* try to workaround toshiba4030cdt problem */
++
++	return 0;
++}
++
++/*
++ * Put bytes from input queue to buffer.
++ */
++
++static ssize_t read_aux(struct file * file, char * buffer,
++			size_t count, loff_t *ppos)
++{
++	DECLARE_WAITQUEUE(wait, current);
++	ssize_t i = count;
++	unsigned char c;
++
++	if (queue_empty()) {
++		if (file->f_flags & O_NONBLOCK)
++			return -EAGAIN;
++		add_wait_queue(&queue->proc_list, &wait);
++repeat:
++		set_current_state(TASK_INTERRUPTIBLE);
++		if (queue_empty() && !signal_pending(current)) {
++			schedule();
++			goto repeat;
++		}
++		current->state = TASK_RUNNING;
++		remove_wait_queue(&queue->proc_list, &wait);
++	}
++	while (i > 0 && !queue_empty()) {
++		c = get_from_queue();
++		put_user(c, buffer++);
++		i--;
++	}
++	if (count-i) {
++		file->f_dentry->d_inode->i_atime = CURRENT_TIME;
++		return count-i;
++	}
++	if (signal_pending(current))
++		return -ERESTARTSYS;
++	return 0;
++}
++
++/*
++ * Write to the aux device.
++ */
++
++static ssize_t write_aux(struct file * file, const char * buffer,
++			 size_t count, loff_t *ppos)
++{
++	ssize_t retval = 0;
++
++	if (count) {
++		ssize_t written = 0;
++
++		if (count > 32)
++			count = 32; /* Limit to 32 bytes. */
++		do {
++			char c;
++			get_user(c, buffer++);
++			aux_write_dev(c);
++			written++;
++		} while (--count);
++		retval = -EIO;
++		if (written) {
++			retval = written;
++			file->f_dentry->d_inode->i_mtime = CURRENT_TIME;
++		}
++	}
++
++	return retval;
++}
++
++/* No kernel lock held - fine */
++static unsigned int aux_poll(struct file *file, poll_table * wait)
++{
++	poll_wait(file, &queue->proc_list, wait);
++	if (!queue_empty())
++		return POLLIN | POLLRDNORM;
++	return 0;
++}
++
++struct file_operations psaux_fops = {
++	read:		read_aux,
++	write:		write_aux,
++	poll:		aux_poll,
++	open:		open_aux,
++	release:	release_aux,
++	fasync:		fasync_aux,
++};
++
++/*
++ * Initialize driver.
++ */
++static struct miscdevice psaux_mouse = {
++	PSMOUSE_MINOR, "psaux", &psaux_fops
++};
++
++static int __init psaux_init(void)
++{
++	int retval;
++
++	if (!detect_auxiliary_port())
++		return -EIO;
++
++	if ((retval = misc_register(&psaux_mouse)))
++		return retval;
++
++	queue = (struct aux_queue *) kmalloc(sizeof(*queue), GFP_KERNEL);
++	if (queue == NULL) {
++		printk(KERN_ERR "psaux_init(): out of memory\n");
++		misc_deregister(&psaux_mouse);
++		return -ENOMEM;
++	}
++	memset(queue, 0, sizeof(*queue));
++	queue->head = queue->tail = 0;
++	init_waitqueue_head(&queue->proc_list);
++
++#ifdef INITIALIZE_MOUSE
++	kbd_write_command_w(KBD_CCMD_MOUSE_ENABLE); /* Enable Aux. */
++	aux_write_ack(AUX_SET_SAMPLE);
++	aux_write_ack(100);			/* 100 samples/sec */
++	aux_write_ack(AUX_SET_RES);
++	aux_write_ack(3);			/* 8 counts per mm */
++	aux_write_ack(AUX_SET_SCALE21);		/* 2:1 scaling */
++#endif /* INITIALIZE_MOUSE */
++	kbd_write_command(KBD_CCMD_MOUSE_DISABLE); /* Disable aux device. */
++	kbd_write_cmd(AUX_INTS_OFF); /* Disable controller ints. */
++
++	return 0;
++}
++
++#endif /* CONFIG_PSMOUSE */