Análisis y desarrollo de un driver para Xorg: EloTouch (I)

Análisis y desarrollo de driver para Elo Touch

Análisis y desarrollo de driver para Elo Touch

EloTouch es una empresa que se dedica a la fabricación de pantallas táctiles.

No tengo queja de su hardware. Sus controladores tienen interfaz serie y/o USB. Particularmente me gusta más el controlador USB debido a que existe un perfil HID que recoge este tipo de periférico y GNU/Linux tiene un driver HID que no funciona mal.

El caso es que recientemente he tenido que desarrollar un driver para una pantalla resistiva de EloTouch que funciona bajo GNU/Linux con Xorg.

La motivación viene de la necesidad de poder asociar un controlador touch a una pantalla (screen) determinada. De este modo podemos tener un escritorio extendido con dos monitores, cada uno de ellos con una interfaz táctil. Tanto los monitores como los controladores de touch están conectados a una misma CPU.

El fabricante tiene un driver (bastante tedioso de instalar) que no contempla esta posibilidad: asociar un controlador a un screen arbitrario.

Lo primero que se me vino a la mente fue buscar un driver GPL que cumpliera con este requisito.

Para “mi sorpresa” encontré en el repositorio de Xorg, los siguientes drivers:

La estructura de ambos es muy parecida y para mi asombro sí que implementan la funcionalidad que demandaba.

¿funcionarán con mi controlador?

No hubo suerte. Ni uno ni otro funcionaba a pesar de establecer la configuración tal y como describía la documentación asociada.

No queda más remedio que hacer mi propio driver.

1. Ingeniería inversa

¿Cual es el formato de los datos? ¿Cómo es su serialización?

La parte del análisis bruto de datos es sin duda la más crítica, más “artista” y difícil de todas. Es como “decodificar/desencriptar” un puzzle.

Para esta ardua tarea me bastan unas simples, pero no por ello menos potentes herramientas:

  • cat:  para la captura de datos desde la línea serie.
  • hexdump: para ver por pantalla en código hexadecimal el contenido de los datos procedentes de la línea serie.

Manos a la obra:

  1. Capturamos los datos de la controladora conectada en la línea serie 0 con:
     cat /dev/ttyS0 > dump1 
  2. Hacemos algunas pulsaciones cortas para recoger algunos datos.
  3. “Dumpeamos”  los datos para empezar a buscar alguna lógica en el stream de información.
     hexdump -v -e '"%04_ad    "' -e '10/1 "%02x "' -e '"     " ' -e '10/1 "%_p"' -e '"\n"' dump1

    Esto son los resultados:

    0000    55 54 01 17 04 5f 04 ff 00 d1     UT..._....
    0010    55 54 02 10 04 61 02 05 04 63     UT...a...c
    0020    04 ff 00 c4 55 54 02 02 04 63     ....UT...c
    0030    04 ff 03 6a 04 ff 00 bf 55 54     ...j....UT
    0040    02 fa 03 6a 04 ff 00 bf 04 ff     ...j......
    0050    00 bf 55 54 02 fa 03 6a 04 ff     ..UT...j..
    0060    00 bf 55 54 55 54 01 e1 08 86     ..UTUT....
    0070    04 ff 00 c6 55 54 02 dc 08 7d     ....UT...}
    0080    02 d5 08 78 04 ff 00 ad 55 54     ...x....UT
    0090    02 d5 08 78 04 ff 08 78 04 ff     ...x...x..
    0100    00 ad 55 54 04 d5 08 78 04 00     ..UT...x..
    0110    00 b0 0b ff 00 ec 55 54 02 54     ......UT.T
    0120    03 33 0b ff 00 e9 55 54 00 f8     .3....UT..
    0130    55 54 02 70 03 4b 0b ff 00 1d     UT.p.K....
    0140    55 54 02 85 55 54 02 d4 03 7d     UT..UT...}
    0150    0b ff 00 b3 55 54 02 fc 03 8e     ....UT....
    0160    02 6c 04 b1 0b ff 00 80 55 54     .l......UT
    0170    02 98 04 c1 0b ff 04 d7 0b ff     ..........
    0180    00 2a 55 54 02 33 05 df 0b ff     .*UT.3....
    0190    00 76 0b ff 00 db 55 54 02 c5     .v....UT..
    0200    05 e9 0b ff 00 12 55 54 00 a9     ......UT..
    0210    55 54 02 85 06 fc 0b ff 00 e6     UT........
    0220    55 54 02 da 55 54 02 4d 07 16     UT..UT.M..
    0230    0c ff 00 ca 55 54 02 86 07 1d     ....UT....
    0240    02 1a 08 2a 0c ff 00 ac 55 54     ...*....UT
    0250    02 56 08 2f 0c ff 08 3f 0c ff     .V./...?..
    0260    00 8d 55 54 02 23 09 47 0c ff     ..UT.#.G..
    0270    00 d3 0c ff 00 55 55 54 02 e5     .....UUT..
    0280    09 60 0c ff 00 ae 55 54 00 28     .`....UT.(
    0290    55 54 02 8b 0a 73 0c ff 00 68     UT...s...h
    0300    55 54 02 dc 55 54 02 4a 0b 85     UT..UT.J..
    0310    0c ff 00 3a 55 54 02 96 0b 8e     ...:UT....
    0320    02 f9 0b 9c 0c ff 00 00 55 54     ........UT
    0330    02 29 0c a0 0c ff 0c a4 0c ff     .)........
    0340    00 96 55 54 02 a0 0c a5 0c ff     ..UT......
    0350    00 b1 0c ff 00 eb 55 54 02 e6     ......UT..
    0360    0c a8 0c ff 00 fa 55 54 00 06     ......UT..
    0370    55 54 02 f6 0c a8 0c ff 00 0a     UT........
    0380    55 54 02 f7 55 54 02 f2 0c a8     UT..UT....
    0390    0c ff 00 06 55 54 02 ef 0c a8     ....UT....
    0400    02 ea 0c aa 0c ff 00 00 55 54     ........UT
    0410    02 e8 0c aa 0c ff 0c ab 0c ff     ..........
    0420    00 ff 55 54 02 e8 0c aa 0c ff     ..UT......
    0430    00 fe 0c ff 00 fe 55 54 02 e9     ......UT..
    0440    0c a9 0c ff 00 fe 55 54 00 01     ......UT.. 
  4. La parte complicada. El primer paso es determinar donde comienza y termina una trama de datos. Si os fijáis en la representación ASCII, veis que se repite mucho la secuencia “UT”. A priori parece que todas las tramas empiezan con “UT”, es decir, 0x55 0x54.  No parece que exista un delimitador de trama al final.En este momento corroboro la deducción con los fuentes de los drivers anteriores e identifico estos bytes como ELO_SYNC_BYTE y ELO_TOUCH. El último byte de trama es el checksum en los drivers, pero en este caso no lo ve claro. El siguiente byte a ELO_SYNC_BYTE y ELO_TOUCH suele tomar los valores: 0x00, 0x01, 0x02 y 0x04.
    55 54 01 17 04 5f 04 ff 00 d1
    55 54 02 02 04 63 04 ff 03 6a 04 ff 00 bf
    55 54 02 fa 03 6a 04 ff 00 bf 04 ff 00 bf
    55 54 04 d5 78 04 00 00 b0 0b ff 00 ec
    55 54 00 01

    No he visto ningún otro valor fuera de este rango. Según la secuencia y los drivers anteriores, se trata del identificador del tipo de evento. Los eventos asociados parecen ser:

    • PRESS = 0x01
    • MOTION = 0x2
    • RELEASE = 0x4
    • NULL = 0x0

    El tamaño de trama es distinto según el tipo de evento. Cuando el evento es PRESS, el tamaño suele ser 10, para MOTION suele ser 14. Digo “suele ser” porque hay paquetes que considero “mal formados”.
    En este punto estamos en posición de determinar la información útil: las coordenadas de pantalla. Podemos saber a ciencia cierta que el tamaño de dato tiene que ser mayor de 8 bits. Si no fuera así, obtendríamos una pobre resolución de la zona pulsada. Los drivers asignan el tipo unsigned short (16 bits). Para el caso del evento PRESS, los drivers asocian el informe de 3 coordenadas: X, Y, Z. El último byte es el supuesto checksum. El orden de los números es little endian, luego los supuesto valores para el evento:
    55 54 01 17 04 5f 04 ff 00 d1
    son:

    • X = 0x0417 = 1047
    • Y = 0x045f =  1119
    • Z = 0x00ff = 255
  5. Para comprobar que estos valores en realidad representan coordenadas, voy a hacer una nueva captura de datos, donde voy a hacer una pequeña pulsación en cada una de las cuatro esquinas de la pantalla. De esta manera, debería de obtener los rangos (mínimo y máximo) de la coordenadas.
    Analizando sólo los valores asociados al evento PRESS estos son los resultados:

    Coordenadas "brutas" correspondientes a pulsaciones en las esquinas de pantalla

    Coordenadas "brutas" correspondientes a pulsaciones en las esquinas de pantalla

    Podemos deducir que:

    • para el eje horizontal, la pulsación más a la izquierda vale aproximadamente 3500. Para la opuesta, 500.
    • para el eje vertical, la pulsación más abajo posible vale aproximadamente 600, siendo 3500 para la pulsación en la zona superior.

    Parece que el comportamiento es lineal y que el eje de coordenadas se encuentra en la esquina superior-derecha.

    Sistemas de referencia

    Sistemas de referencia

    Para comprobar esta teoría, voy a hacer un pequeño programa en Python que imprima las coordenadas de pantalla cuando se realice una pulsación. Es necesario realizar una conversión entre coordenadas brutas (o del controlador) y las coordenadas de pantalla. Usaremos las propias coordenadas anteriores como coordenadas de calibración.

Dejaremos el desarrollo del programa de test para la siguiente entrega. Salu2!🙂

Translate to:English
MenefanteMenéame TwitterTwitter

2 Responses to Análisis y desarrollo de un driver para Xorg: EloTouch (I)

  1. Mensa13 dice:

    Muy interesante, tiene una pinta cojonuda, espero con ansia la siguiente entrega😉

    • Chema dice:

      Gracias. La segunda entrega saldrá esta semana.

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s

A %d blogueros les gusta esto: