23
Creación de drivers para dispositivos USB Diseño de computadores Ingeniería Técnica de Informática de Gestión Universidad de Jaén Profesor: Luis Miguel Nieto Nieto Rafa Muñoz Cárdenas

Creacion Drivers Usb

Embed Size (px)

DESCRIPTION

A work in spanish about libusb drivers.

Citation preview

Page 1: Creacion Drivers Usb

Creación de driverspara dispositivos USB

Diseño de computadores

Ingeniería Técnica de Informática de GestiónUniversidad de Jaén

Profesor: Luis Miguel Nieto Nieto

Rafa Muñoz Cárdenas

Page 2: Creacion Drivers Usb

Enero 2009 Rafa Muñoz Cárdenas 2

Contenidos

1. USB1.1. Descriptores de un dispositivo1.2. Comunicación con dispositivo1.3. Modos de transferencia de información

2. Kernel vs. Libusb3. Introducción a Usbfs

3.1. Libusb4. Creación de un driver de ratón5. Otros ejemplos de drivers

5.1. Ingeniería inversa5.2. Lanzamisiles

6. Bibliografía

Page 3: Creacion Drivers Usb

Enero 2009 Rafa Muñoz Cárdenas 3

1. USB

El Universal Serial Bus es un puerto que sirve para conectar periféricos a una computadora.

Fue creado en 1996 por siete empresas: IBM, Intel, Northern Telecom, Compaq, Microsoft, Digital Equipment Corporation y NEC.

Objetivos:

Permitir la conexión de periféricos en una sola interfaz de socket estandarizada.Mejorar la capacidad “plug-and-play” (permitiendo así el “hot swapping”).

Suministrar a través del mismo puerto energía a dispositivos de bajo consumo.

4 versiones:

1.0: Tasa de transferencia de hasta 1'5 Mbps (192 KB/s). Utilizado en teclados, ratones y joysticks.

1.1: Tasa de transferencia de hasta 12 Mbps (1'5 MB/s).2.0: Tasa de transferencia de hasta 480 Mbps (60 MB/s).

3.0: Tasa de transferencia de hasta 4.8 Gbps (600 MB/s).

Page 4: Creacion Drivers Usb

Enero 2009 Rafa Muñoz Cárdenas 4

1.1. Descriptores de un dispositivo

Son bloques de información que permiten al host aprender características del periférico. Los descriptores más importantes son los siguientes:

Descriptor de dispositivo:

Contiene información básica del dispositivo.

Descriptor de configuración:

Representan el estado del dispositivo (activo, standby, inicialización) y su configuración básica (potencia, nº de interfaces, etc).

Descriptor de interfaz:

Contiene identificador de interfaz, número de endpoints de interfaz, etc.

Un dispositivo USB puede consistir en varios sub-dispositivos lógicos (cada uno tendrá una interfaz). Por ejemplo: una webcam con micrófono incorporado (interfaz vídeo+interfaz audio). Es necesario un driver por cada interfaz.

Descriptor de endpoint:

Describe endpoints distintos del 0.

Page 5: Creacion Drivers Usb

Enero 2009 Rafa Muñoz Cárdenas 5

1.2. Comunicación con dispositivo

Esta comunicación se realiza a través de pipes (canales lógicos).

Los pipes son conexiones del anfitrión al endpoint.

El endpoint es el buffer desde el cual los datos entran o salen del dispositivo.

Sólo será posible acceder a los datos de los descriptores anteriormente explicados a través de endpoints.Por ejemplo: para acceder a la configuración accedemos al endpoint 0.

Dos tipos de transferencia unidireccional: IN (dispositivo a PC) o OUT (PC a dispositivo).

Page 6: Creacion Drivers Usb

Enero 2009 Rafa Muñoz Cárdenas 6

1.3. Modos de transferencia de información

También denominados como tipos de endpoints. Tipos:

De control:Los endpoints de control son usados para controlar el dispositivo USB asíncronamente. P.e.: enviar comandos o pedir información de estado del periférico.Todo dispositivo debe tener este “endpoint 0”, usado para inicializar el periférico al conectarlo.

De interrupción:El host solicita periódicamente pequeños paquetes de datos de tamaño fijo al dispositivo. El dispositivo siempre tiene que esperar a ser atendido.Se usa para ratones y teclados normalmente.

Bulk:Transfieren grandes cantidades de datos. Con ella se asegura que los datos llegan siempre a su destino. Se usa para almacenamiento de datos o impresoras.

Isochronous:Transfieren grandes cantidades de datos. No se garantiza la llegada de los datos a su destino. Se usa para dispositivos en tiempo real de vídeo o audio.

Page 7: Creacion Drivers Usb

Enero 2009 Rafa Muñoz Cárdenas 7

2. Kernel vs. Libusb

Nuestro sistema no es capaz de manejar un periférico USB => Escribir un driver.

Alternativas al escribir drivers:

Kernel driver

Drivers centralizados en el núcleo.

Buena velocidad y rendimiento.

Soporta cualquier dispositivo complejo.Flexibilidad

Pequeños cambios para otras arquitecturas (p.e: ARM).No portable a otros SO.

Programación muy compleja.

Page 8: Creacion Drivers Usb

Enero 2009 Rafa Muñoz Cárdenas 8

2. Kernel vs. Libusb

Libusb driver

Fácil de programar.Esconde detalles innecesarios al programador.

Reduce el tamaño de los programas de forma notable.

Código portable a otras plataformas.

Drivers dispersos por internet (escasos grandes repositorios).

La comunicación con periféricos es más lenta respecto a drivers en kernel.

No válida para periféricos complejos.

Page 9: Creacion Drivers Usb

Enero 2009 Rafa Muñoz Cárdenas 9

3. Introducción a Usbfs

Usbfs es un sistema de archivos diseñado específicamente para periféricos USB y está incluido en el kernel Linux.

Recopila información de todos los dispositivos conectados al PC.

Evita escribir drivers como módulos en kernel.

Los drivers son ejecutados en espacio de usuario (no root).

Identifica los dispositivos y crea sus archivos asociados aunque su driver no haya sido creado aún.

Para simplificar aún más la programación sobre Usbfs, podemos hacer uso de las librerías Libusb (C/C++) y jUSB (Java). Ambas corren sobre esta capa software en sistemas GNU/Linux.

Page 10: Creacion Drivers Usb

Enero 2009 Rafa Muñoz Cárdenas 10

3.1. Libusb

Ideal para dispositivos sencillos: cámaras, teclados, ratones, scanners, impresoras...

Multiplataforma: GNU/Linux, *BSD, Mac OS X y Win32.

Funciona en espacio de usuario => Fácil de depurar.

A continuación se muestra un ejemplo de información de un ratón recopilada por Usbfs sobre un ratón:

Page 11: Creacion Drivers Usb

Enero 2009 Rafa Muñoz Cárdenas 11

3.1. Libusb

$lsusb -v

Bus 002 Device 004: ID 046d:c001 Logitech, Inc. N48/M-BB48 [FirstMouse Plus]Device Descriptor:...... idVendor 0x046d Logitech, Inc. idProduct 0xc001 N48/M-BB48 [FirstMouse Plus]...... bNumConfigurations 1 Configuration Descriptor:...... bNumInterfaces 1...... (Bus Powered) Remote Wakeup MaxPower 50mA Interface Descriptor:...... bNumEndpoints 1 bInterfaceClass 3 Human Interface Device BinterfaceSubClass 1 Boot Interface Subclass bInterfaceProtocol 2 Mouse iInterface 0...... Endpoint Descriptor: bLength 7 bDescriptorType 5 bEndpointAddress 0x81 EP 1 IN bmAttributes 3 Transfer Type Interrupt Synch Type None Usage Type Data wMaxPacketSize 0x0008 1x 8 bytes BInterval 10

Page 12: Creacion Drivers Usb

Enero 2009 Rafa Muñoz Cárdenas 12

4. Creación de un driver de ratón

Observando la salida de “lsusb -v” podemos empezar a crear nuestro driver usando la librería Libusb.

raton.c:

Recorremos los buses buscando el dispositivo anteriormente definido:

// Estos datos dependeran del dispositivo#define VENDOR 0x046d#define PRODUCT 0xc001

static struct usb_device *find_device(const uint16_t &vendor, const uint16_t &product) { struct usb_bus *bus; struct usb_device *dev; struct usb_bus *busses;

usb_init(); usb_find_busses(); usb_find_devices(); busses = usb_get_busses();

// Recorremos todos los buses for (bus = busses; bus; bus = bus->next) { for (dev = bus->devices; dev; dev = dev->next) { if ((dev->descriptor.idVendor == vendor) && (dev->descriptor.idProduct == product)) { return dev; } } }

return NULL;}

Page 13: Creacion Drivers Usb

Enero 2009 Rafa Muñoz Cárdenas 13

4. Creación de un driver de ratón

Ahora declaramos las estructuras del dispositivo y lo buscamos usando la función anteriormente declarada:

Abrimos dispositivo y deshabilitamos driver si es que estaba funcionando antes:

Reservamos interfaz para nuestra aplicación:

Vamos a leer las interrupciones del ratón:

int main() { struct usb_device *dev; struct usb_dev_handle *udev; dev = find_device(VENDOR, PRODUCT);

udev = usb_open(dev); usb_detach_kernel_driver_np(udev, dev->config->interface->altsetting->bInterfaceNumber);

reserva = usb_claim_interface(udev, 0);

// Monitorizamos hasta que no pulsemos boton derecho e izquierdo a la vez (3 0 0 0) while (data[0] != 3) { data[0] = data[1] = data[2] = data[3] = 0; // (0 0 0 0) intr = usb_interrupt_read(udev, 0x81, data, 4, 0); // Leemos 4 bytes del dispositivo usando interrupt_read

for (i = 0; i < 4 && intr > 0; i++) { printf("%d ", data[i]); } printf("\n");

usb_clear_halt(udev, 0x81); // Reseteamos dispositivo para evitar que se sigan enviando // los mismos bytes despues de hacer click }

Page 14: Creacion Drivers Usb

Enero 2009 Rafa Muñoz Cárdenas 14

4. Creación de un driver de ratón

Terminamos y cerramos la comunicación con el periférico:

usb_release_interface(udev, 0); usb_close(udev);

Page 15: Creacion Drivers Usb

Enero 2009 Rafa Muñoz Cárdenas 15

4. Creación de un driver de ratón

Probamos el programa:

$ g++ -Wall -W raton.c -o driver_raton -L/usr/lib/ -lusb$ sudo ./driver_ratonBuscando raton USB... ¡Encontrado! Deshabilitando driver de raton...

Estado de solicitud de interfaz: 0Protocolo de dispositivo: 0Longitud de descriptor: 18Tipo de descriptor: 1Numero de endpoints: 1Clase de interfaz: 3Protocolo: 2Numero de interfaz: 0Nombre de fichero de dispositivo: 006

Fabricante: LogitechNombre del producto: USB MouseNumero de serie de dispositivo: ?Direccion de endpoint: 0x81

0 -1 0 00 -2 0 00 -1 0 00 -1 -1 00 -1 0 00 -1 0 01 0 0 03 0 0 0Cerrando dispositivo.

Page 16: Creacion Drivers Usb

Enero 2009 Rafa Muñoz Cárdenas 16

5. Otros ejemplos de drivers

Necesitamos crear drivers de dispositivos complejos a los que hay que enviar señales de control para poder interactuar con ellos o URB's.

No disponemos de documentación sobre su funcionamiento, por lo que necesitaremos realizar ingeniería inversa sobre drivers existentes (de Windows la mayoría).

Page 17: Creacion Drivers Usb

Enero 2009 Rafa Muñoz Cárdenas 17

5.1. Ingeniería inversa

Un programa conocido para “espiar” la información que circula por los buses USB es SnoopyPro.

El procedimiento para capturar información revelante es el siguiente:

1. Iniciamos SnoopyPro y señalamos la interfaz a monitorizar.

2. Realizamos una acción simple con el dispositivo.3. Guardamos la salida obtenida de realizar la acción simple.

4. Volvemos a realizar la acción simple con el periférico reiniciado para asegurarnos y guardamos de nuevo el log con la salida.

Page 18: Creacion Drivers Usb

Enero 2009 Rafa Muñoz Cárdenas 18

5.1. Ingeniería inversa

Ejemplo de i. inversa de dispositivo

Cada comando enviado al dispositivo requiere 3 mensajes de control:

El primero son todo ceros, probablemente como señal de que una orden va a llegar.

En el segundo mensaje vemos que el buffer tiene el valor 0x00000008, yel endpoint para escribir el buffer es el 0 (0x00).Finalmente un mensaje con todo ceros para no repetir infinitamente el segundo mensaje.

Esta secuencia de mensajes viene de mover hacia la derecha un dispositivo a través de un programa para Windows proporcionado por el fabricante.

Page 19: Creacion Drivers Usb

Enero 2009 Rafa Muñoz Cárdenas 19

5.2. Lanzamisiles

El ejemplo anterior correspondía a un lanzamisiles... de juguete :)

Si continuamos monitorizando los movimientos del lanzamisiles vemos que:

Moviéndolo hacia arriba el contenido del buffer es 0x00000001.

A menos que se envíe un comando stop (0x00000000), se mantiene ejecutando continuamente el último comando enviado.

Continuamos la monitorización y ya podemos escribir:

Si continuamos moviendo el lanzamisiles hacia un lado y llega a su ángulo máximo de giro, detectamos que aparecen los siguientes bytes en el buffer del endpoint de interrupciones (de tipo IN):

#define ML_STOP 0x00#define ML_ARR 0x01#define ML_ABA 0x02#define ML_IZQ 0x04#define ML_DER 0x08#define ML_FUEGO 0x10

#define ML_MAX_ARR 0x80 /* 80 00 00 00 00 00 00 00 */#define ML_MAX_ABA 0x40 /* 40 00 00 00 00 00 00 00 */#define ML_MAX_IZQ 0x04 /* 00 04 00 00 00 00 00 00 */#define ML_MAX_DER 0x08 /* 00 08 00 00 00 00 00 00 */

Page 20: Creacion Drivers Usb

Enero 2009 Rafa Muñoz Cárdenas 20

5.2. Lanzamisiles

Otros datos interesantes extraídos:

Buffer de transferencia de 8 bytes.Request type=0x21.Request=0x9.Value=0x200.Index: “1” para el primer y tercer mensaje y “0” para el mensaje segundo.

Page 21: Creacion Drivers Usb

Enero 2009 Rafa Muñoz Cárdenas 21

5.2. Lanzamisiles

Ahora podríamos ser capaces de crear nuestro driver para controlar el lanzamisiles.

Para cualquier movimiento excepto disparar, sería tan fácil como:movement_handler(ML_ARR);

Aquí podemos ver una demostración del funcionamiento de este juguete.

int send_message(char* msg, int index) { int j = usb_control_msg(launcher, 0x21, 0x9, 0x200, index, msg, // movimiento arriba/derecha/etc. 8, //bytes 1000); // timeout return j;}

void movement_handler(char mov) { char msg[8]; msg[0] = 0x0; msg[1] = 0x0; msg[2] = 0x0; msg[3] = 0x0; msg[4] = 0x0; msg[5] = 0x0; msg[6] = 0x0; msg[7] = 0x0;

int deally = send_message(msg, 1); // enviamos ceros msg[0] = mov; deally = send_message(msg, 0); // enviamos movimiento deally = send_message(msg, 1); // enviamos ceros}

Page 22: Creacion Drivers Usb

Enero 2009 Rafa Muñoz Cárdenas 22

6. Bibliografía

1. USB

http://en.wikipedia.org/wiki/USB

http://free-electrons.com/doc/linux-usb.pdf

http://www.tech-pro.net/intro_usb.html

http://www.fujitsu.com/downloads/EU/es/soporte/discosduros/UnpaseoporUSBMSD.pdf

http://catarina.udlap.mx/u_dl_a/tales/documentos/lep/ordaz_g_r/capitulo2.pdf

Linux Device Drivers, Third Edition (O'Reilly): http://lwn.net/Kernel/LDD3/

http://www.lrr.in.tum.de/Par/arch/usb/download/usbdoc/usbdoc-1.32.pdf

2. Kernel vs. Libusb

http://www.freesoftwaremagazine.com/articles/drivers_linux?page=0%2C0

http://www.linuxquestions.org/questions/linux-kernel-70/kernel-driver-vs-libusb-662647/

http://www.nabble.com/Write-Linux-USB-Driver-td14913265.html

3. Introducción a Usbfs

http://www.linuxforums.org/forum/linux-tutorials-howtos-reference-material/10865-developing-usb-device-drivers-userspace-using-libusb.html

http://libusb.wiki.sourceforge.net/

http://en.wikipedia.org/wiki/Libusb

http://www.linux-usb.org/USB-guide/x173.html

Page 23: Creacion Drivers Usb

Enero 2009 Rafa Muñoz Cárdenas 23

6. Bibliografía

4. Creación de un driver de ratón

http://www.linuxjournal.com/article/7466

http://www.cs.indiana.edu/~bpisupat/work/usb.html

http://www.linuxjournal.com/article/6396

http://xianfengdesign.blogspot.com/2007/02/linux-usb-input-subsystem.html

5. Otros ejemplos de drivers:

http://www.linuxquestions.org/questions/linux-hardware-18/driver-help-with-libusb-512040/page2.html

http://matthias.vallentin.cc/2007/04/writing-a-linux-kernel-driver-for-an-unknown-usb-device/

http://scott.weston.id.au/software/pymissile/

http://www.jespersaur.com/drupal/book/export/html/21

http://www.amctrl.com/rocketlauncher.html