Control LED con libusb

LedController for GNU/Linux

LedController for GNU/Linux

Hoy me ha llegado un chinagadget comprado en DealExtreme.

Se trata de un notificador de nuevos emails o eventos de mensajería.

Como era de esperar el driver/software sólo funciona para sistemas Windows pero me gustaría poder utilizar este “cachibache” en mi Ubuntu.

He supuesto que encender una bombilla vía USB no debía ser muy complicado y me he puesto manos a la obra.

Lo primero que tenia que averiguar era la configuración y el protocolo del driver para encender/apagar el LED a voluntad.

Para hacer esta mini ingeniería inversa he utilizado VirtualBox y Wireshark.

Wireshark es ampliamente usado como sistema de captura y análisis de paquetes de red. Ahora además nos permite “sniffar” el tráfico USB.

Con VirtualBox se crea una maquina virtual Windows donde instalamos los drivers oficiales del notificador.

Con nuestra máquina virtual corriendo, ponemos a escuchar a nuestro sniffer.

Es necesario saber en que bus se encuentra nuestro dispositivo. Ésto se soluciona con un simple lsusb.

Ahora le indicamos a WireShark que escuche en dicho bus y ejecutamos un escenario donde se encienda/apague el led.

El resultado es un gran fichero de captura con mucha morralla.

Analizando el tráfico se observa un incontable número de paquetes enviados por interrupción pero cuyo contenido es siempre el mismo. Desconozco su propósito (¿quizás un sistema rudimentario de heartbeat?).

Filtrando por endpoint, se ve que hay dos endpoints, 1 y 2 (además del EP de control 0).

El EP 1 es el que usa para transferencias por interrupción del mensaje repetitivo.

El EP 2 es el que se usa para el envio de comandos de encendido.

En concreto, después de jugar con la aplicación de notificación, detecte la siguiente trama para encender el led rojo:


0x02 0x04 0x04 0x04 0x04

Para apagarlo, se usa ésta otra:


0x00 0x04 0x04 0x04 0x04

Con el protocolo (a priori) detectado, decidí hacer el driver en espacio de usuario para GNU/Linux.

Para acometer ésto, opté por usar la librería de acceso a USB, libusb.

Esta librería permite el desarrollo rápido de drivers/aplicaciones USB en GNU/Linux (también está disponible para Windows). Para dispositivos sencillos como este se ajusta perfectamente. Si por el contrario queremos controlar un dispositivo con alta intesidad de E/S, es recomendable implementarlo mediante un módulo kernel.

La implementación es sencilla. Se pasa como parámetro el color del LED a encender (en la secuencia, 2 = rojo, 1 = azul, 2 = verde).

Lo relevante está en la línea 55. Aquí es donde se envía por interrupción, el comando por el EP 2.

También es interesante la línea 41. Aquí se descarga el manejador kernel de dispositivo en caso de que algún driver lo haya reclamado (en este caso el driver HID).


#include <stdio.h>
#include <libusb.h>
#include <errno.h>

#define VID 0x1294
#define PID 0x1320

static struct libusb_device_handle *devh = NULL;

int main(int argc,char** argv)
{
 int ret;
 unsigned char code = 0;
 if (argc != 2 )
 {
    printf("syntax: %s red | green | blue | off\n",argv[0]);
    return -1;
 }
 if ( strcmp(argv[1],"red") == 0 )
 {
     code = 2;
 }
 else if ( strcmp(argv[1],"green") == 0 )
 {
     code = 3;
 }
 else if ( strcmp(argv[1],"blue") == 0 )
 {
     code = 1;
 }
 libusb_init(NULL);
 devh = libusb_open_device_with_vid_pid(NULL, VID, PID);
 if (devh == NULL )
 {
	printf("not found\n");
        return -1;
 }
 if ( libusb_kernel_driver_active(devh,0) )
 {
	printf("detach from kernel\n");
        ret = libusb_detach_kernel_driver(devh,0);
        if (ret < 0 )
        {
		printf("can't detach\n");
                return -1;
        }
 }
 char data[5];
 data[0] = code;
 data[1] = 0x4;
 data[2] = 0x4;
 data[3] = 0x4;
 data[4] = 0x4;
 int dummy;
 ret =  libusb_interrupt_transfer(devh,0x2,data,5,&dummy,0);
 if ( ret < 0 )
 {
  perror("error");
 }
return 0;
}

Os dejo el fuente de programa, una versión compilada dinámicamente y otra estáticamente.
Fuente: ledcontroller.tar.gz

[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

Fumar 2.0

Fumar 2.0

Fumar 2.0

No soy fumador, pero un día vi en un wholesale un cigarrillo eléctrico recargable mediante USB. Me quedé a cuadros. La descripción corta real del producto es “Mini electronic atomizer“. No genera CO2 ni contamina ni tiene nicotina. Mi expresión se volvió aun más perpleja cuando vi el correspondiente cargador. El precio no llegaba a los 9$, así que no tenia excusa para darle uso a mi oxidada cuenta de PayPal.

Por fin ayer llegó. Después de dejar cargándolo en un puerto USB de mi PC unas 8 horas, tal y como indicaban las instrucciones, estaba en disposición de empezar a “fumar”.

Le puse un nuevo recambio, lo enrosque y ya sólo era cuestión de empezar a pegar caladas. Cada recarga tiene entre 150 y 200 caladas y es bueno saber que cuenta con los certificados CE y RoHS.

Mini Atomizer USB

Mini Atomizer USB

Mi primera calada. Mientras inspiraba aire por la boquilla, un LED situado en el extremo del cigarro empezó a iluminarse directamente proporcional a la “potencia” de la calada. Tuve que empezar a reir 🙂

Además de iluminarse como un cigarro real, se produce un ruido familiar cuando el aire pasa por el “atomizer” (que buena palabrota para venderlo mejor). La exhalación produce un vapor de agua que rápidamente desaparece.

Vamos a lo más importante: el sabor.

Como he comentado al principio no soy fumador, pero sí he probado alguna vez el tabaco. Sabe como a regaliz. Bajo mi punto de vista, el sabor no está muy conseguido. Me lo vendieron como “Marlboro taste“. Estoy esperando a que algún amigo “condenado” de Marlboro, lo pruebe y avale o refute mi afirmación. Tengo que decir que no pude darle sólo un par de caladas y estuve un rato “fumando”.

Mis conclusiones tienen poco valor, dado que no fumo. No obstante, veo que si se cumplieran algunas premisas, este tipo de producto podría verse por la calle y por muchos establecimientos donde esta prohibido fumar. Imaginaos el uso que se le puede dar a este “atomizer” (que no es “cigarro”) en bares, restaurantes, cines, pubs, teatros y demás locales si al final se aprueba la nueva ley antitabaco. Respecto a la premisa es sencilla: tiene que saber a tabaco. Sobre la nicotina, este dispositivo carece de ella. Esta diseñado para ayudar a dejar de fumar. He visto otros en las farmacias que sí tienen nicotina. Según el caso de cada uno, preferiran un tipo u otro.

Bueno, voy a ver si le pego una caladillas (espero no fumar silicio) 🙂

Translate to:English
MenefanteMenéame TwitterTwitter