Skip to content

Generación de descriptores HID

Lucas M. Bacelo edited this page Dec 3, 2018 · 2 revisions

Generación del descriptor

En resumen, el descriptor es lo que le indica al host qué dispositivo es el que se conectó, los datos que se enviarán y su órden.
La mejor manera de entender como crear un descriptor para un dispositivo es haciendo uno de ejemplo.

Antes de empezar se debe tener a mano el documento Device Class Definition HID el cual nos proporcionará información muy útil acerca del protocolo HID y la HID Usage Table en la que se encuentran las USAGE_PAGE y los USAGE_ID para cada tipo de dispositivo. También se necesitará el software HID Descriptor Tool el cual nos brinda una manera rápida de configurar el descriptor sin tener que estar leyendo en la HID Usage Table los valores en hexadecimal, logrando así una mejor comprensión del código.

Para el ejemplo haremos un dispositivo HID comportandose como un mouse. El mouse cuenta con 3 botones (clic izquierdo, clic central y clic derecho) junto a dos dimensiones las cuales son dadas por el movimiento en el eje X y en el eje Y. De esta manera nos queda la siguiente tabla:

TablaMouse

Por lo que la estructura en C quedaría

struct mouse_t{  
    uint8_t botones;  
    int8_t x;  
    int8_t y;  
}

En el descriptor, el primer item debe describir los botones

USAGE_PAGE (Button)
USAGE_MINIMUM (Button 1)
USAGE_MAXIMUM (Button 3)

Cada boton está representado por un bit, por lo cual puede tomar el valor de 0 o de 1

LOGICAL_MINIMUM (0)
LOGICAL_MAXIMUM (1)

Son 3 datos (COUNT) en espacios de 1 bit (SIZE)

REPORT_COUNT (3)
REPORT_SIZE (1)

Envía el reporte a el host como un dato, variable, absoluto

INPUT (Data,Var,Abs)

Se deben enviar los 5 bits que no se usan como una constante

REPORT_COUNT (1)
REPORT_SIZE (5)
INPUT (Cnst,Var,Abs)

Ahora es el turno del eje X

USAGE_PAGE (Generic Desktop)
USAGE (X)

Como se quiere un entero con signo y el tamaño del dato es de 8 bits (un byte), el mínimo será -127 y el máximo 127

LOGICAL_MINIMUM (-127)
LOGICAL_MAXIMUM (127)

Es 1 dato de 8 bits

REPORT_COUNT (1)
REPORT_SIZE (8)

Envía el reporte al host como un dato, variable, relativo

INPUT (Data,Var,Rel)

Por último para el eje Y repetimos los pasos del eje X quedando como

USAGE_PAGE (Generic Desktop)
USAGE (Y)
LOGICAL_MINIMUM (-127)
LOGICAL_MAXIMUM (127)
REPORT_COUNT (1)
REPORT_SIZE (8)
INPUT (Data,Var,Rel)

Lo cual se puede simplificar en

USAGE_PAGE (Generic Desktop)
USAGE (X)
USAGE (Y)
LOGICAL_MINIMUM (-127)
LOGICAL_MAXIMUM (127)
REPORT_COUNT (2)
REPORT_SIZE (8)
INPUT (Data,Var,Rel)

Juntando los botones y los ejes obtenemos

USAGE_PAGE (Button)
USAGE_MINIMUM (Button 1)
USAGE_MAXIMUM (Button 3)
LOGICAL_MINIMUM (0)
LOGICAL_MAXIMUM (1)
REPORT_COUNT (3)
REPORT_SIZE (1)
INPUT (Data,Var,Abs)
REPORT_COUNT (1)
REPORT_SIZE (5)
INPUT (Cnst,Var,Abs)
USAGE_PAGE (Generic Desktop)
USAGE (X)
USAGE (Y)
LOGICAL_MINIMUM (-127)
LOGICAL_MAXIMUM (127)
REPORT_COUNT (2)
REPORT_SIZE (8)
INPUT (Data,Var,Rel)

Para que el host reconozca el dispositivo como un mouse se debe establecer

USAGE_PAGE (Generic Desktop)
USAGE (Mouse)
COLLECTION (Application)
    USAGE (Pointer)
    COLLECTION (Physical)
    
    //Acá el código escrito anteriormente
    
    END COLLECTION
END COLLECTION