Quirks del kernel Linux

Lo primero, ¿sabes lo que es un «quirk«?  Según el traductor, tiene varias acepciones como capricho o peculiaridad. Es esta última acepción de la que vamos a hablar.

Linux tiene código «quirk» (peculiaridades) para ciertos dispositivos concretos.

Esto se debe a que hay muchos dispositivos que aunque tienen funcionalidades en común, incorporan «peculiaridades» que deben ser tratadas para explotar al máximo el dispositivo. Un ejemplo claro son los teclados con teclas multimedia o esos joysticks enormes que se emplean en los simuladores de vuelo.

Os voy a poner un ejemplo con un dispositivo de interfaz-humana (HID) al que vamos a intercambiar la funcionalidad de dos de sus teclas.

Como sabéis, cada dispositivo USB tiene asociado un par de códigos que representan un código unívoco de producto (identificador de fabricantes e identificador de producto). Cuando un dispositivo HID USB se conecta al sistema, el kernel busca si tiene asociado algún quirk, y si procede, aplica el «remapeo» de eventos.

Un fragmento de hid-belkin.c para un teclado Belkin.


static int belkin_input_mapping(struct hid_device ∗ hdev, struct hid_input ∗ hi, struct hid_field ∗ field, struct hid_usage ∗ usage,unsigned long ∗ ∗ bit, int  max)
{
unsigned long quirks = (unsigned long)hid_get_drvdata(hdev);

    if ((usage >hid & HID_USAGE_PAGE) != HID_UP_CONSUMER || !(quirks & BELKIN_WKBD))
          return 0;
    switch (usage >hid & HID_USAGE) {
          case 0x03a: belkin_map_key_clear(KEY_SOUND);
          case 0x03b: belkin_map_key_clear(KEY_CAMERA);
          case 0x03c: belkin_map_key_clear(KEY_DOCUMENTS);
          default:
          return 0;
    }
    return 1;
}

¿es fácil de entender no? El código «mapea» tres eventos distintos a los códigos de kernel correspondientes a las teclas KEY_SOUND, KEY_CAMERA y KEY_DOCUMENTS.
Esta función de «mapeo» se ejecuta después de que la función «probe» del driver sea positiva y se haya obtenido la tabla de usos del dispositivo USB HID.
Dicha función de «mapeado» se aplica para cada uno de los códigos que reporte el dispositivo. Si os fijáis, cuando se produce un intercambio el código de retorno es 0.
Se devuelve 1 si no hay alteración (como puede ser el caso de la tecla ‘a’).

Si tenéis curiosidad veréis en que en todo el kernel hay numerosos «quirks» a todos los niveles.

 

[Tip] Deshabilitar dispositivos USB

Hay muchas bondades en usar GNU/Linux como sistema operativo. Una de las características que más me gusta es poder controlar en tiempo de ejecución el comportamiento de los dispositivos escribiendo cadenas de texto sencillas en algún fichero que cuelga de /sys o /proc.

En el tip de hoy vamos a ver como habilitar o deshabilitar un dispositivo USB (un pendrive).

Lo primero que hay que hacer es identificar de donde cuelga nuestro pendrive. Hay multitud de opciones para hacer esto (por ejemplo, escuchando el bus system de D-Bus).

Voy a usar un método más «raw«. La información/control del bus USB se encuentra bajo el directorio /sys/bus/usb.

Empezemos buscando bajo que bus se encuentra nuestro pendrive.

lsusb -t
/:  Bus 05.Port 1: Dev 1, Class=root_hub, Driver=uhci_hcd/2p, 12M
/:  Bus 04.Port 1: Dev 1, Class=root_hub, Driver=uhci_hcd/2p, 12M
/:  Bus 03.Port 1: Dev 1, Class=root_hub, Driver=uhci_hcd/2p, 12M
/:  Bus 02.Port 1: Dev 1, Class=root_hub, Driver=uhci_hcd/2p, 12M
/:  Bus 01.Port 1: Dev 1, Class=root_hub, Driver=ehci_hcd/8p, 480M
        |__ Port 2: Dev 2, If 0, Class=hub, Driver=hub/4p, 480M
        |__ Port 1: Dev 3, If 0, Class=HID, Driver=usbhid, 1.5M
        |__ Port 1: Dev 3, If 1, Class=HID, Driver=usbhid, 1.5M
        |__ Port 7: Dev 6, If 0, Class=stor., Driver=usb-storage, 480M

Vemos que nuestro dispositivo cuelga del bus 1 y está en el puerto 7. Para localizar la información de nuestro dispositivo, sólo tenemos que acceder a la ruta: /sys/bus/usb/usb1/1-7. Si hacemos un listado sobre ese directorio obtenemos:

1-7:1.0
authorized
bcdDevice
bConfigurationValue
bDeviceClass
bDeviceProtoco
bDeviceSubClass
bmAttributes
bMaxPacketSize0
bMaxPower
bNumConfigurations
bNumInterfaces
busnum
configuration
descriptors
dev
devnum
driver
ep_00
idProduct
idVendor
manufacturer
maxchild
power
product
quirks
serial
speed
subsystem
uevent
urbnum
version

De todos estos ficheros, el que nos interesa en este caso es authorized. Este fichero acepta los valores «0» y «1» (correspondientes a habilitar y deshabilitar respectivamente).
Por defecto este valor vale 1 (cat authorized). Luego si queremos deshabilitarlo sólo tenemos que ejecutar:

echo "0" > authorized

Os animo a que hagáis la prueba y veáis que ocurre.

Gracias a esta interfaz, es muy sencillo implementar un sistema de seguridad en el lenguaje de programación que queráis (sólo tiene que tener gestión de ficheros).

Translate to:English
MenefanteMenéame TwitterTwitter