On Monday, 22 May 2000, Kees Cook wrote: > On Mon, May 22, 2000 at 10:40:51AM -0700, Andrei Pitis wrote: > > I enjoyed writing the patch, though :-) I hope you have the latest > > version? I think my last message on the subject on linux-kernel was > > in jan or feb 99, if you didn't get it, I'll send it again.Maybe it > > didn't get to linux-kernel? That would be strange, but would explain > > the silence. > > Hm. If it's easy, can you dig that out of your email? I have the email > dated Dec 13th. It's the patch that does dynamic delay stuff? I didn't > look too closely at it, actually. This was the last one I CCed to linux-kernel. It's kinda long, maybe it just got filtered out of the mailing list :-) Enjoy! Andrei -------------- From: Andrei Pitis To: Paul Ashton CC: linux-kernel@vger.rutgers.edu, torvalds@transmeta.com Subject: Re: toshiba kbd patch Date: Mon, 6 Mar 2000 02:39:11 -0500 (EST) On Friday, 3 March 2000, Paul Ashton wrote: > Hi Andrei, > > It seems your keyboard patch didn't make it into the 2.3 kernel. Do > you know why not? Do you have an ftp/web site for the latest copy > of it? Well, though Linus used to reply my email concerning this Toshiba kbd patch, after I sent to him the latest version he ceased to reply. Since this was in December, I think, and Transmeta was about to release it's processor in January, probably he was very busy. I tried to send it a couple of times more, didn't got any answers, probably he is busy, or this patch is not of such a great interest. Or, maybe my new (strange) email setup generates messages that are filtered out by whatever filters he has installed. Anyway, no problem, I didn't push it because it's a specific hardware problem and it would be better to just forget about it than to make it a patch into the kernel. However, for those interested, here is the message that I tried a few times to get through to Linus. If you cannot get it to work, please send me the drivers/char/pc_keyb.c file you are using and I'll send you the patched file back. I have a patch for 2.3.x, but I am sure x is too small to be of any use... Regards, Andrei --------------- Hi Linus, Sorry to bother you, just wondering if my kbd patch is going to find its way into the kernel or not. I hope you received the latest version (though I suspect a problem somewhere, it was CCed on linux-kernel, nobody answered - I am not a subscriber, therefore there might have been replies to the list only, but...). I can tell you that this patch helps a lot: not only it removes glitches, but it also evens the kbd repeat delay, which is in the range 160-250 on my laptop and it seems that on other kbds as well. It can be thought off as a pre-handler, maybe taking care of other problems (if any) in the future. I have included it in this message, for your convenience, not as a patch, because I am really not fully aware of how to find the latest source tree (CVS, perhaps?) and I saw that he latest 2.3. version has some rearrangements in that area of pc_keyb.c. The fix consist of a function: 'handle_delay', which should be called like this: handle_delay(scancode); instead of (replacing) the call to handle_scancode in pc_keyb.c, wherever this may be in the current version: handle_scancode(scancode, !(scancode & 0x80)); Thanks, Andrei --------------------- /* * Made for a Toshiba Satellite 2595XDVD, useful for * other Toshiba laptops and not only, apparently. Under some * circumstances, these keyboards behave 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 occurrence of the second identical make code within * the kbd delay, which is dynamically computed. Takes into account * keys with 0xE0. It adapts to the kbd delay, computing it from * normal kbd repeats, which are defined to be those of no less * than MIN_KBD_DELAY (100ms). * * Andrei Pitis Dec 1999 */ /* Minimum KBD delay is considered to be 100 ms. */ #define MIN_KBD_DELAY (HZ / 10) /* E0_PREFIX_BIT is to be ORed into every scancode that was preceeded by an 0xE0 prefix. It is to be temporarily storeed into prev_scancode shifted left by E0_STORE_SHL. */ #define E0_PREFIX_BIT 0x100 #define E0_STORE_SHL 16 /* PULSE_BIT is ORed into the prev_scancode in the beginning of each repeat sequence. Used to detect the "delay" - i.e. the time between the first and the second consecutive identical make codes. */ #define PULSE_BIT 0x200 #define KEYUP_BIT 0x80 #define SCANCODE_MASK 0xFF static void handle_delay(unsigned int scancode) { /* State variables. */ static unsigned int prev_scancode = 0; static unsigned long stop_jiffies = 0; /* Some reasonable start values for the mean delay. */ static unsigned int kbd_delay_sum = MIN_KBD_DELAY; static unsigned int kbd_n_repeats = 1; unsigned int different_bits = 0; /* Just remember that we've got the E0 prefix, will take care of it next time. Use the high word of prev_scancode. */ if (scancode == 0xE0) { prev_scancode |= (E0_PREFIX_BIT << E0_STORE_SHL); return; } /* Mark the E0 prefix as a bit in scancode. */ scancode |= (prev_scancode >> E0_STORE_SHL) & E0_PREFIX_BIT; prev_scancode &= ~(E0_PREFIX_BIT << E0_STORE_SHL); /* Compute different_bits of scancode and prev_scancode, including the E0_PREFIX_BIT. */ different_bits = ((scancode ^ prev_scancode) & (SCANCODE_MASK | E0_PREFIX_BIT)); /* True if the scancodes are different. */ if (different_bits) { /* Any make code triggers the delay and updates prev_scancode. */ if (!(scancode & KEYUP_BIT)) { stop_jiffies = jiffies; prev_scancode = scancode | PULSE_BIT; } /* True if this is the break code of the prev_scancode, i.e. if only the KEYUP_BIT is different. Reset the delay. */ else if (different_bits == KEYUP_BIT) stop_jiffies = prev_scancode = 0; } else /* Same make code. */ { int delta_jiffies = jiffies - stop_jiffies; /* True only for the second scancode in a row, i.e. the first repetition of a scancode. */ if (prev_scancode & PULSE_BIT) { /* Reset the bit. */ prev_scancode &= ~PULSE_BIT; /* Dynamically update the kbd repeat delay. */ if (delta_jiffies >= MIN_KBD_DELAY) { /* Reset it from time to time, to keep it dynamic, in case the hard kbd repeat rate is changed. */ if (kbd_n_repeats > 400) kbd_delay_sum = kbd_n_repeats = 0; kbd_delay_sum += delta_jiffies; kbd_n_repeats++; } else printk(KERN_INFO "KBD glitch (delay %d ms) at %d ms: [%03X]\n", ((kbd_delay_sum / kbd_n_repeats) * 1000) / HZ, (delta_jiffies * 1000) / HZ, scancode); } /* Reject scancode if within mean delay. Apply a correction of -1 since kbd interrups are asynchronous wrt timer interrupts. */ if (delta_jiffies < kbd_delay_sum / kbd_n_repeats - 1) return; } /* Handle the scancode, do not forget the E0 prefix. */ if (scancode & E0_PREFIX_BIT) handle_scancode(0xE0, 0); handle_scancode(scancode & SCANCODE_MASK, !(scancode & KEYUP_BIT)); }