More on the Toshiba keyboard problem

Kristian Nielsen (kristian.nielsen@risoe.dk)
Tue, 21 Dec 1999 10:47:20 +0100


Bu chance I stumbled upon the discussion of the Toshiba keyboard
controller problem in Kernel Traffic #47. Since I just recently wrote a
similar patch for this problem, I thought I should contribute my work in
case it may be useful.

I have experienced the problem with spurious keyboard repeats on the
Toshiba Tecra 8000 laptop. I wrote the patch below, which is similar to
the one by Andrei Pitis. One difference is that it uses get_fast_time()
to print out accurately the time interval between wrongly repeated scan
codes. I use a 20ms delay which is well below the 33ms minimum repeat
rate; all spurious repeats I have seen happened within less than 11ms. I
was wondering if the very long 200 ms interval that Andrei Pitis used is
really needed?

The patch is not of "production quality" yet, and I guess it does not
handle escaped key sequences etc. properly. Let me know if I should work
more on it or if anyone wants more information.

I am not subscribed to the list, so please CC any replies to
kristian.nielsen@risoe.dk.

- Kristian.

-----------------------------------------------------------------------
diff -u --recursive orig/drivers/char/pc_keyb.c new/drivers/char/pc_keyb.c
--- orig/drivers/char/pc_keyb.c Fri Dec 10 10:27:17 1999
+++ new/drivers/char/pc_keyb.c Fri Dec 10 10:28:33 1999
@@ -410,6 +410,11 @@
#endif
}

+/* Discard repeated scan codes that arrive within less than this many
+ * microseconds. This fixes a Tecra 8000 problem with spurious key repeats.
+ */
+#define MIN_REPEAT_RATE 20000
+
/*
* This reads the keyboard status port, and does the
* appropriate action.
@@ -429,7 +434,32 @@
if (status & KBD_STAT_MOUSE_OBF) {
handle_mouse_event(scancode);
} else {
- if (do_acknowledge(scancode))
+ static int oldcode = -1;
+ static struct timeval oldtv;
+ struct timeval tv;
+ int skip_key;
+
+ get_fast_time(&tv);
+/* printk(KERN_INFO "pc_keyb: 0x%02X (%ld,%ld) 0x%02X (%ld,%ld).\n ", oldcode, oldtv.tv_sec, oldtv.tv_usec, scancode, tv.tv_sec, tv.tv_usec); */
+ if(oldcode == scancode && oldcode != -1 &&
+ !(scancode & 0x80) &&
+ ((tv.tv_sec == oldtv.tv_sec &&
+ tv.tv_usec - oldtv.tv_usec <= MIN_REPEAT_RATE) ||
+ (tv.tv_sec == oldtv.tv_sec + 1 &&
+ tv.tv_usec + 1000000 - oldtv.tv_usec <= MIN_REPEAT_RATE))) {
+ skip_key = 1;
+ printk(KERN_WARNING "pc_keyb: discarding repeated "
+ "scancode 0x%02X after %ld usec.\n",
+ scancode,
+ tv.tv_usec +
+ (tv.tv_sec == oldtv.tv_sec ? 0 : 1000000L)
+ - oldtv.tv_usec);
+ } else {
+ skip_key = 0;
+ }
+ oldcode = scancode;
+ oldtv = tv;
+ if (do_acknowledge(scancode) && !skip_key)
handle_scancode(scancode, !(scancode & 0x80));
mark_bh(KEYBOARD_BH);
}

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/