sexta-feira, 2 de março de 2012

Linux e teclados



um legado complicado...


Não é exatamente a minha praia mas algumas pessoas têm tido problemas com teclados no Linux. O fato é que por ser proprietário de uma SunBlade 2000 com um teclado Sun, já experimentei usar o teclado da Sun em um PC e tive este tipo de problema: basta encostar em uma tecla e o resultado é uma dúzia de caracteres. Assim, vou dar algumas dicas e , embora um pouco off-topic, o assunto está relacionado com o SO.

Trata-se de problemas com teclados específicos e/ou distribuições Linux que necessitam de uma configuração manual. As distribuições modernas não apresentam este problema — bem, pelo menos nunca tentei instalar o Ubuntu num i486, por exemplo.

Este problema acontece porque, durante o boot, o kernel ajusta a velocidade do teclado para o máximo valor (0x0305). Bem, isto não é problema para a maioria dos teclados modernos e nem funciona para teclados USB, mas alguns tipos de teclado respondem "violentamente" a isto. No Linux, o problema pode ser contornado usando o programa kbdrate (veja: man 8 kbdrate) que muda a velocidade de repetição do teclado.

Alternativamente, podes alterar o kernel e recompilá-lo. Mas antes, vamos entender o que e porque.

Em kernels mais antigos, o arquivo:

/usr/src/linux/arch/i386/boot/setup.S

tem um código Assembly para ajustar a taxa de repetição do teclado:

     ! set the keyboard repeat rate to the max

         mov     ax,#0x0305
         xor     bx,bx           ! clear bx
         int     0x16

Nos novos kernels, esta chamada de interrupção está no código do arquivo:

/usr/src/linux/arch/x86/boot/main.c


...

/*
 * Set the keyboard repeat rate to maximum.  Unclear why this
 * is done here; this might be possible to kill off as stale code.
 */
static void keyboard_set_repeat(void)
{
        struct biosregs ireg;
        initregs(&ireg);
        ireg.ax = 0x0305;
        intcall(0x16, &ireg, NULL);
}

...

void main(void)
{

...

        /* Set keyboard repeat rate (why?) */
        keyboard_set_repeat();
...


...


Este código chama a interrupção 16 da BIOS com o valor hexa 0305 no acumulador, ou seja, AH=03 (set keyboard rate) usando o valor 05 (máximo) para o AL. Esta faixa de valor (0-5) pode ser de 02 a 30 caracteres por segundo ou de 02 a 1440 em alguns teclados. E isto pode resultar, em alguns casos, em um teclado hiper-sensível.

A sugestão, de vários desenvolvedores do kernel é alterar ou mesmo retirar esta parte do código e recompilá-lo. Mas porque então não retirá-lo do código (o que já foi até sugerido ao Linus). Bem tudo tem uma explicação, embora o próprio Linus nunca tenha esclarecido.

Primeiro, eu imagino que isto seja um código legado e que é mantido para compatibilidade. Segundo é que, por experiência própria, esta solução pode causar problemas no Accelerated-X que pode ficar instável e demorar para terminar.

Ainda, existem certos hardware (p. ex. Dell Inspiron) que depois da hibernação ajusta a velocidade do teclado para o default, deixando-o mais lento. Neste último caso, pode-se regular a velocidade usando o comando:

$ kbdrate -r 30 -d 250

Isto não aconteceria se o kernel controlasse a interrupção da BIOS.

Embora eu concorde com o comentarista do código ("why this is done here?") é melhor deixar o código onde está. Afinal, quem vai usar um teclado "alienígena" em um computador "Frankenstein" deve saber onde e como alterar o código do kernel.

Happy linuxing!

Nenhum comentário:

Postar um comentário