2021/04/15

Teclado Hexadecimal USB

A raiz de mi cada vez mayor involucramiento con sistemas embebidos y fpga y un arrastre de hace años de networking, tengo una necesidad: ingresar letras de la "a" a la "f" para cosas como código de máquina, direcciones de memoria y direcciones MAC, o sea, datos en formato hexadecimal.

¿Qué es eso? Pues que las máquinas representan todo con unos y ceros, pero a las personas nos cuesta, rápido, decime cuál número es mayor:

10111110101110101100101011111110

10111110101100001100101011111110



Esos números son

3199912702

3199257342


Que no es el formato nativo de la compu pero si nuestro.

Si esos números los agrupamos:

1011 1110 1011 1010 1100 1010 1111 1110

1011 1110 1011 0000 1100 1010 1111 1110


Vemos que cada grupo va de 0000 a 1111, que son 16 combinaciones y podemos representar con 0 a 9 y seis caracteres más, arbitrariamente elegidos A a F:

 0   0
 1   1
 2   2
 3   3
 4   4
 5   5
 6   6
 7   7
 8   8
 9   9
10   A
11   B
12   C
13   D
14   E
15   F


Podemos reescribir así:

BEBACAFE

BEB0CAFE


No es nuestro formato nativo, es fácil de convertir a y desde binario y es más fácil leerlos y escribirlos sin equivocarse.

No voy a entrar en todos los detalles de este tema que se llama "sistemas numéricos".


Cuando son pocos caracteres, aunque incómodo no es tan terrible, cosa que cambia cuando con una mano estoy sosteniendo un dispositivo y tengo que mover la vista del dispositivo al teclado pues aunque puedo escribir al tacto y con la mano izquierda están cubiertas esas letras, si hay mezcla con números, (10:6) se me complica o cuando son muchos caracteres.

Fijate en este caso, de un aparente exploit que había en una máquina y no podía copiarlo, entonces hice hexdump -C y captura de pantalla. Por supuesto no lo puedo encontrar, así que te muestro algo equivalente, los primeros bytes de /bin/ls:


Hexdump
Hexdump



Mientras reflexionaba sobre estos temas e investigaba para un trabajo práctico como hacer que linux entienda que lo que le paso por serial dentro de USB en realidad es un mouse, recordé que tengo un viejo teclado numérico QTronix, me parece que lo compré hace muchos mucho años en compucanje y algún Teensy 2, que viene a ser una variante de arduino, de hecho se programa con una variante de arduino ide llamada teensyduino y tiene la particularidad de funcionar como teclado USB con extrema sencillez. Hace un tiempo hice la conversión de un touchpad PS/2 a USB.

Habiendo puesto todos los ingredientes en el tazón, revolví y me dije, para qué voy a sufrir con los caracteres hexadecimales si puedo sufrir adaptando el teclado a USB y reprogramando unas teclas.

La reprogramación la hago en el Teensy antes de transmitir por USB, con el agregado de poder cambiar de modo, ya sea volver a las teclas nativas o cambiar de mayúscula a minúscula, apretando rápidas secuencias de una tecla de poco uso como es NumLock, la que controla que se envíen números o flechitas.


Primera etapa: preparativos


Determinar cuál es el modo común entre AP y X




El teclado tiene un switch que dice AP y X, calculo que viene a ser AT y XT, pues creo recordar que los teclados de las XT (8086) no eran compatibles con las AT (80286). Esta operación es muy fácil con un simple adaptador de DIN 5 180 grados a PS/2 lo tenemos:


Adaptador PS/2 a mini din a USB
Adaptador PS/2 a mini din a USB

Bueno, no tan simple, no tengo interfaz PS/2, no importa, si tengo un cajón llenísimo de todo tipo de basura adaptadora, igual que vos. Esto incluye un adaptador PS/2 a USB:

El cajón de adaptadores
El cajón de adaptadores

Te juro que empecé a ordenarlo para que se vea más lindo pero no, si uso mi tiempo en eso no lo uso en esto.



Listo, tal como esperaba es AP.


Medir consumo


Tendría que desarmar un poquito el teclado y medir. Luego agregarle el consumo del teensy, probablemente fabricando un cable USB donde puede poner en serie el tester o conseguir uno de estos:


Usb Tester
Usb Tester

No he hallado manera de que el mother te diga cuánto está consumiendo.

Mejor pensemos de otra manera:

Si el teclado con el adaptador PS/2 USB funciona, ¿qué tan distinto puede ser el consumo del Teensy? Listo, una preocupación menos.



Segunda etapa: implementar el software


Estoy seguro de tener una VM con teensyduino instalado, pero no recuerdo cuál. Si hubiera anotado en la descripción ese detalle podría encontrarlo, veamos...

Con este comando:

find $DIR1 $DIR2 -iname "*.vbox" | \
  while read CONF; do grep -ie teens -ie duino "$CONF";
done



Lo que hace el comando es buscar en las carpetas donde tengo VMs ($DIR1, $DIR2) archivos con extensión vbox y busca menciones a arduino o teensy.


No encontré nada, mala suerte. Ya instalaré una VM con eso. Uso mientras el de mi la máquina real, que no debería tener instaladas esas cosas.


Los requerimientos del programa son:

  • Debe convertir del protocolo del teclado PS/2 a USB Keyboard.
  • Debe reemplazar los keycodes determinados por [a-f] y tab.
  • Si se aprieta NumLock dos veces en rápida secuencia:
    • Debe cambiar ciclar entre [a-f] y [A-F]
  • Si se aprieta NumLock cuatro veces en rápida secuencia:
    • Debe cambiar ciclar entre el reemplazo y las funciones nativas.



+-----------+-----------+-----------+
|   print   |   scroll  |   pause   |
|   screen  |    lock   |           |
|    tab    |           |           |
+-----------+-----------+-----------+



+-----------+-----------+-----------+
|   insert  |    home   |  Page Up  |
|     A     |     B     |     C     |
+-----------+-----------+-----------+
|   delete  |    end    | Page Down |
|     D     |     E     |     F     |
+-----------+-----------+-----------+




El programa es básicamente el ejemplo de Teensy de adaptador de teclado PS/2 a USB, sólo que estoy mandando al Serial para diagnosticar.


include <PS2Keyboard.h>

const int DataPin = 5;
const int IRQpin =  3;

PS2Keyboard keyboard;
 
void setup() {
  delayMicroseconds(1000);
  Serial.begin(9600);
  keyboard.begin(DataPin, IRQpin);
  delay(2000);
  Serial.println("Keyboard Init");
}

void loop() {
 if (keyboard.available()) {
    char c = keyboard.read();

    if (c == PS2_ENTER) {
      Serial.println("[Enter]");
    } else if (c == PS2_TAB) {
      Serial.println("[Tab]");
    } else if (c == PS2_ESC) {
      Serial.println("[ESC]");
    } else if (c == PS2_PAGEDOWN) {
      Serial.
println("[PgDn]");
    } else if (c == PS2_PAGEUP) {
      Serial.
println("[PgUp]");
    } else if (c == PS2_LEFTARROW) {
      Serial.
println("[Left]");
    } else if (c == PS2_RIGHTARROW) {
      Serial.
println("[Right]");
    } else if (c == PS2_UPARROW) {
      Serial.
println("[Up]");
    } else if (c == PS2_DOWNARROW) {
      Serial.
println("[Down]");
    } else if (c == PS2_DELETE) {
      Serial.
println("[Del]");
    } else {
      Serial.println(c);
    }
  }
}


Y anda bastante bien, salvo que parece faltar una inicialización hacia el teclado, pues no prende la luz de KeyLock ni la detecta, asi como a varias otras teclas.


Prototipo, el teensy a la izquierda
Prototipo, el teensy a la izquierda


Tengo que analizar el protocolo, corre riesgo el proyecto, en pocos días regreso...


Debo además el cambio de función y mayúscula/minúscula y el armado físico.

Sigue en la primera versión.


No hay comentarios:

Publicar un comentario