Problemas com teclado ABNT2 no QEMU [Resolvido] [Dica]
Problemas com teclado ABNT2 no QEMU [Resolvido]
Publicado por Paulo em 14/08/2013
[ Hits: 7.328 ]
Blog: http://unixntools.blogspot.com.br/
Esta dica foi publicada inicialmente no meu blog, mas trago-a a todos no VOL, para que possa ter um alcance maior.
O objeto desta postagem é o QEMU 1.0, que é aquele distribuído com o Ubuntu 12.04 LTS. Não sei (ainda) se os problemas com teclados ABNT2 continuam ocorrendo em versões mais novas do QEMU.
Mesmo que não ocorram mais, a dica fica para quem preferir (ou for forçado a) usar versões mais antigas que acompanham as distribuições com suporte LTS, quer no mundo Debian (e Ubuntu, como é o meu caso), quer no mundo Red Hat/Fedora.
Precisando recorrer ao velho MS-DOS para escrever um artigo para este site, tive a ideia de usar o QEMU para subir uma máquina virtual (VM) com o MS-DOS 6.2, a fim de fazer testes de que precisava com velhas ferramentas de desenvolvimento voltadas para essa plataforma.
Por sorte, já havia uma imagem de HD para o QEMU com DOS que achei nos meus alfarrábios, e decidi usá-la, para não perder tempo instalando uma imagem de HD nova, até porque, eu ainda teria de preparar muitas outras coisas no ambiente, além do sistema operacional.
No entanto, logo no começo da instalação das outras ferramentas, eu comecei a sentir o desconforto de não conseguir mapear adequadamente o teclado ABNT2 dentro da VM.
Sem carregar no DOS os drivers do MS-DOS para remapear o teclado, o layout assumido era o do teclado americano, o que implicava ter de lembrar que para obter o caráter "/", eu tinha de digitar ";", para obter o ";", digitar "ç", digitar "]" para obter "|", e assim por diante - efeito semelhante àquele por que passamos com nossos PCs quando se tenta usar o teclado antes do carregamento do sistema chegar ao ponto de selecionar o mapeamento ABNT2.
Só que essa inconveniência fica particularmente mais incômoda quando, como era o meu caso, eu ficava alterando a digitação entre a janela do QEMU, em que tinha de aplicar o "mapa mental de teclado", e outras janelas do Desktop do X11, no qual o teclado funcionava normalmente.
Carregando os drivers de teclado do MS-DOS, o problema ficou pior, porque, embora, quase todas as teclas funcionassem, mas a tecla com a barra e o ponto de interrogação ficou simplesmente morta dentro da VM (embora eu ainda pudesse obter a barra usando o teclado numérico, o ponto de interrogação ficava completamente inacessível).
Cheguei a pensar que era problema com o DOS, cujo driver de teclado que estaria esperando um Scancode para a tecla que tem a barra e o ponto de interrogação diferente daquele enviado pelo QEMU.
Para tirar a dúvida sobre essa hipótese, acrescentei à VM um LiveCD do Ubuntu (e aumentei a quantidade de memória da VM de singelos 4 MB para 1 GB), e tentei usar o teclado ABNT2 no Ubuntu dentro da VM. Com o exame da saída do comando showkey no console e do xev no ambiente X11, a conclusão foi óbvia: o QEMU não estava mesmo enviando qualquer sinal para dentro da VM quando eu apertava a tecla.
Até aquele momento, eu estava usando a interface SDL do QEMU. Tive então a ideia de usar a interface VNC. Só que o resultado foi pior ainda. Quando se usa a opção "-vnc", deve-se dizer também qual o layout do teclado através da opção "-k".
Ao tentar usar "-k pt-br" (que indica ABNT2 para o QEMU), uma tecla em particular ficou com um comportamento muito ruim (até tolerável no Ubuntu, mas totalmente inviabilizador do MS-DOS): a tecla que contém a vírgula e o sinal de "menor que" funcionou de modo errático, ora produzindo a vírgula, ora não, e deixando o teclado num estado que, no DOS, o confundia de modo tal que tudo o que se digitava depois de teclar a vírgula, mesmo que só uma vez, ficava embaralhado. Já ao usar "-k en-us" na invocação do QEMU, eu não conseguia produzir qualquer dos caracteres das teclas acentuadas, como se elas não existissem.
Isso implicava em não conseguir obter os caracteres ASCII "^", "~" e "`". Por mais que eu não precisasse desses caracteres para o meu artigo, resolver o problema com o QEMU já tinha se tornado uma questão de honra.
Comecei a procurar no Google, artigos sobre problemas semelhantes. A maioria do que eu encontrava eram constatações do problema ou reclamações, mas sem solução. Até que eu achei um artigo particularmente interessante e útil no blog de Niels Horn, um holandês que vive (ou vivia) no Brasil.
Em seu artigo ele descrevia o problema, dizia como ele localizara no código fonte do QEMU, o ponto que fazia com que a tecla com a barra e o ponto de interrogação fosse ignorada (e também uma outra tecla, que fica no teclado numérico para produzir o caráter ponto, usado como separador de milhares - só que o meu teclado não possui tal tecla, e eu não teria como testá-la, e não vou considerá-la mais neste artigo), e como ele fez para, em lugar de ter tal tecla ignorada, ela devolvesse alguma coisa que ele depois conseguisse interceptar. Vale a pena ler o artigo dele (em inglês).
Como eu estava usando o Ubuntu, eu executei os seguinte comandos para obter o código fonte sobre o qual iria trabalhar para fazer as modificações sugeridas pelo Niels Horn:
sudo apt-get build-dep # Instala pacotes necessários para compilar o QEMU
mkdir -p build/qemu
$ cd build/qemu
$ apt-get source qemu # Note que aqui não tem sudo
cd qemu-kvm-1.0+noroms
Com os fontes disponíveis, fiz as modificações sugeridas no artigo (no arquivo "ui/x_keymap.c"). Em seguida, gerei novos pacotes do QEMU, que instalei em seguida.
$ sudo dpkg --install \
qemu-kvm_1.0+noroms-0ubuntu14.10_amd64.deb \
qemu-utils_1.0+noroms-0ubuntu14.10_amd64.deb \
kvm_84+dfsg-0ubuntu16+1.0+noroms+0ubuntu14.10_amd64.deb \
qemu_1.0+noroms-0ubuntu14.10_amd64.deb \
qemu-common_1.0+noroms-0ubuntu14.10_all.deb
Contudo, a solução dele não me servia. As modificações por ele sugeridas faziam com que se conseguisse obter alguma coisa das teclas que antes não produziam coisa alguma, só que os códigos enviados para dentro da VM não eram exatamente os correspondentes àqueles que teriam sido produzidos por um teclado ligado a um PC real.
O próprio Niels Horn relata isso no seu artigo, e parte para uma solução no lado interno da VM: como ele estava usando GNU/Linux, ele modificou o mapa de teclado "br-abnt2.map.gz" para mapear os códigos recebidos para os símbolos pretendidos, e fez a mesma coisa no X11 por meio do comando xmodmap.
Só que eu não teria como fazer o mesmo na minha VM, já que ela tinha de rodar MS-DOS - pelo menos não com a mesma facilidade com que se consegue fazer no GNU/Linux e no X11.
Minha abordagem, então, foi fazer com que o QEMU entregasse para a VM os códigos de tecla "corretos", efetivamente esperados pelo sistema operacional.
O problema, é que eu não conseguia descobrir qual era o código da tecla com a barra e o ponto de interrogação. Num PC real, esse código é 89 (0x59). No X11, que parece somar sempre 8 ao código bruto da tecla, 97 (0x61).
Mas nenhum desses desses valores parecia servir quando usado na posição correspondente (a primeira) do "array evdev_keycode_to_pc_keycode" no código do QEMU.
Tentei ainda, me basear no mapeamento de outras teclas que funcionavam adequadamente para tentar obter o valor da constante que deveria somar ou subtrair de 89, para obter do QEMU algo que funcionasse dentro da VM (todas as teclas de movimentação de cursor. Por exemplo, tinham a constante 97 (0x61) somada ao código real da tecla), mas também esse pensamento por analogia não funcionava para a tecla que eu queria.
Fui varrendo o código do QEMU, e identifiquei que o ponto em que o array era usado, era numa trecho que mapeava eventos do X11 para eventos da SDL. Em função disso, vasculhei a documentação sobre Scancodes da SDL, bem como vários arquivos de cabeçalho ou de mapeamento em tempo de execução tanto da SDL quanto do X11, mas em lugar nenhum encontrei algo que se relacionasse explicitamente com essa tecla, que não tem num símbolo nem nome próprio em lugar algum (ao contrário, por exemplo, das teclas do teclado americano ou dos modernos teclados "multimídia" ou teclados "web", cujas teclas têm nomes simbólicos como "XF86Email", "XF86HomePage", "XF86AudiRaiseVolume" etc.). Essa tecla do nosso teclado ABNT2 parece "existir" somente por meio do seu código numérico.
Depois de umas boas horas procurando, finalmente me ocorreu a ideia de olhar na própria implementação do mapeamento de teclado "pt-br" do QEMU. Descobri que esse mapeamento não é estático, mas sim definido num arquivo instalado em "/usr/share/qemu/keymaps/pt-br".
Olhando tal arquivo, vi que o Scancode atribuído à tecla com a barra e o ponto de interrogação, era 115 (0x73). Vi também que eles fizeram o mapeamento da tecla com a vírgula e o sinal "menor que" do teclado principal compartilhado com a tecla de separador de decimais do teclado numérico (que produz "Delete" quando "Num Lock" está inativo), o que provavelmente ajuda a explicar o comportamento errático da vírgula na VM com DOS quando eu tentei usar a interface VNC.
Não entendi qual a origem desse valor 115 (0x73), mas coloquei-o na primeira posição do "array evdev_keycode_to_pc_keycode", e gerei mais uma fornada de pacotes do QEMU. E agora - finalmente - consegui usar com sucesso a barra e o ponto de interrogação com sucesso dentro da VM, tanto no DOS quanto no GNU/Linux.
Pontos de melhoria que ainda poderiam ser feitos:
Tentar separar dentro do mapeamento de teclado "pt-br" a vírgula produzida pela tecla no teclado principal daquela produzida pelo teclado numérico. Isso beneficiaria usuários da interface VNC do QEMU, bem como usuários da interface SDL que, por algum motivo, precisem especificar a opção "-k pt-br".
Descobrir o código de teclado esperado pelo QEMU para conseguir entregar à VM o Scancode correto do ponto do teclado numérico (separador de milhares). Este eu não tenho como testar aqui, pois meu teclado não possui tal tecla.
Fazer o mesmo com a tecla vírgula (separador de decimais) + "Delete" do teclado numérico, uma vez que se tenha conseguido separá-la da vírgula do teclado principal.
Usando find para expandir listas de arquivos em argumentos de modo seguro
APP Notify - Como fazer seu servidor Linux enviar notificação para o celular
Criando uma chave privada (OpenVPN)
Sarg no CentOS 6 - Configuração com suporte a gráficos
Compilando seus RPMs como usuário comum
Roteiro de estudos para a certificação LPI2
[1] Comentário enviado por rwolosker em 25/10/2015 - 08:58h
É exatamente esse o problema, eu quase acreditei que ia conseguir resolver, porque eu também já fiz todas estas combinações que você descreve no artigo. Infelizmente não tem solução, este artigo é de 2013 e estamos em 2015, eu baixei as últimas versões do QEMU no próprio site.
Nas minhas andanças, descobri que este problema também acontece com o RDESKTOP, que utiliza os mesmos arquivos de mapeamento. Lá, tentaram trocar o código do mapa, de 0x416 para 0x10416.
Eu programo em JAVA, já programei em C também. Quanto ao arquivo ui/x_keymap.c, até parece que alguém vai conseguir dar manutenção naquela bagaça. É o mito do opensource.
É exatamente esse o problema, eu quase acreditei que ia conseguir resolver, porque eu também já fiz todas estas combinações que você descreve no artigo. Infelizmente não tem solução, este artigo é de 2013 e estamos em 2015, eu baixei as últimas versões do QEMU no próprio site. Nas minhas andanças, descobri que este problema também acontece com o RDESKTOP, que utiliza os mesmos arquivos de mapeamento. Lá, tentaram trocar o código do mapa, de 0x416 para 0x10416. Eu programo em JAVA, já programei em C também. Quanto ao arquivo ui/x_keymap.c, até parece que alguém vai conseguir dar manutenção naquela bagaça. É o mito do opensource. NÃO RESOLVIDO.