Re: toshiba kbd patch

From: Andrei Pitis (pink@simple.ro)
Date: Mon Mar 06 2000 - 02:39:11 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 <pink@simple.ro> 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));
}

-
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/



This archive was generated by hypermail 2b29 : Tue Mar 07 2000 - 21:00:18 EST