Re: Toshiba kbd patch

Andrei Pitis (pink@roedu.net)
Thu, 9 Dec 1999 01:21:56 +0200 (EET)


As a result of your feedback, I have written a slightly more elaborate
patch, featuring:

- dynamically adjusts to the actual kbd repeat delay, by computing a
min among delays (no smaller than 100ms (HZ/10) in order to avoid
taking glitches into account). This makes hardcoding of the delay
(the so much blamed 250ms) unnecessary (n.b. - smbd was right, it is
smaller than 250, on my laptop it is 200ms - good :-)).

- logging _actual_ kbd glitches, and only the first in a row. I also
log, the actual minimum kbd delay, so people will know what their
kbd's actual delay is :-) If you want, I can make some more kbd
statistics in that routine and print them...

It's funny, I started by writing a quick'n'dirty patch for my own use
and I will probably end up writing kbd software repeat (is it really a
demand for such a feature? imagine that we would be able to set up
repeat rates of up to 100 cps!! :-)) Anyway, I am happy doing this,
between two consecutive cries (she has stomach aches, any known
remedies for a 1 month baby?) of my first newborn (Andra, 12 nov) late
in the night (in my TZ - EET Bucharest/Romania). It would be neat if
a child's crying repeat delay/rate would be customizable :-)))

Andrei

--- linux-2.3.39/drivers/char/pc_keyb.c Tue Dec 7 01:10:31 1999
+++ pc_keyb.c Fri Dec 10 13:54:16 1999
@@ -413,6 +413,105 @@
}

/*
+ * Made initially for a Toshiba Satellite 2595XDVD, useful for
+ * other Toshiba laptops and not only. Under some
+ * circumstances, its keyboards behaves like ignoring the
+ * kbd repeat _delay_. This happens in conjunction with shift
+ * keys (ctrl, alt, shift) and leads to undesirable repeat
+ * of a key even if pressed briefly. Fixed it by ignoring any
+ * subsequent occurence of the second identical scancode within
+ * the kbd delay, which is dynamically computed. Takes into account
+ * keys with 0xE0, doesn't care about the Break key. This doesn't
+ * break anything on a good keyboard, because it addapts itself to
+ * the kbd delay, computing it from normal kbd repeats, which are
+ * those with a delay of no less than MIN_KBD_DELAY (100ms).
+ *
+ * Andrei Pitis <pink@roedu.net> Dec 1999
+ */
+
+#define MIN_KBD_DELAY (HZ/10)
+
+static void handle_delay(unsigned char scancode)
+{
+ static int E0_detected = 0;
+ static int prev_scancode = 0;
+ static int stop_jiffies = 0;
+ static int repeating_scancode = 0;
+ static int first_repeat = 0;
+ static int kbd_delay = HZ; /* Start with one second - quickly convergent. */
+
+ /* Silently ignore the E0 prefix, will take care of it next time. */
+ if (scancode == 0xE0)
+ {
+ E0_detected = 1;
+ return;
+ }
+
+ if (scancode != prev_scancode)
+ {
+ /* Reset the repeating scancode. */
+ if ((scancode & 0x80) && (scancode & 0x7F) == repeating_scancode)
+ repeating_scancode = 0;
+
+ /* New MAKE scancode, or we are not in a repating sequence, or,
+ if we are repeating, the repeating BREAK scancode -
+ this is the condition that triggers the delay and updates
+ prev_scancode. */
+ if ((scancode & 0x80) == 0 ||
+ !repeating_scancode ||
+ (scancode & 0x7F) == repeating_scancode)
+ {
+ stop_jiffies = jiffies;
+ prev_scancode = scancode;
+ first_repeat = 1;
+ }
+ } else {
+ /* Same scancode. */
+ int delta_jiffies = jiffies - stop_jiffies;
+
+ /* Remember which scancode are we repeating. */
+ repeating_scancode = scancode;
+
+ /* Dynamically update the kbd repeat delay. */
+ if (delta_jiffies < kbd_delay &&
+ delta_jiffies >= MIN_KBD_DELAY &&
+ first_repeat)
+ {
+ printk(KERN_INFO "Setting kbd delay to: %d ms.\n", delta_jiffies * 10);
+ kbd_delay = delta_jiffies;
+ }
+
+ /* Reject if within delay, and reset E0 detection. */
+ if (delta_jiffies < kbd_delay)
+ {
+ if (first_repeat)
+ printk(KERN_INFO "Toshiba kbd glitch: %d ms.\n", delta_jiffies * 10);
+
+ E0_detected = 0;
+ first_repeat = 0;
+
+ return;
+ }
+
+ first_repeat = 0;
+ }
+
+ /* Handle the scancode if different from the previous one, or
+ if the same, but after the delay passed. Don't forget
+ the E0 prefix, if it was detected. */
+ if (E0_detected)
+ {
+ handle_scancode(0xE0, 0);
+ E0_detected = 0;
+ }
+
+ handle_scancode(scancode, !(scancode & 0x80));
+}
+
+
+
+
+/*
* This reads the keyboard status port, and does the
* appropriate action.
*
@@ -433,7 +532,7 @@
} else {
#ifdef CONFIG_VT
if (do_acknowledge(scancode))
- handle_scancode(scancode, !(scancode & 0x80));
+ handle_delay(scancode);
#endif
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/