Upload
others
View
5
Download
0
Embed Size (px)
Citation preview
(para realizar el ejercicio 1 de la ejercitación propuesta para la Unidad 1)
� comencemos por entender un poco como se estructura el USB …
� Diseñado para vincular dispositivos (“devices” or“nodes”) con computadoras (host)
� Velocidades de 1.5Mbps (USB1.0) a 10Gbps (USB3.1)
� 4 hilos: V(5v), Data+, Data-, Ground
� Hasta 127 dispositivos por host
� Hasta 5 capas (“tiers”) vía “hubs”
� El cliente (software) se comunica con un dispositivo utilizando “pipes” (conducto, tubo o cañería)
� Cada “pipe” es un canal de comunicación entre el software corriendo en el host y un “endpoint” (punto de conexión) del dispositivo
Dispositivo
ep0
ep15
epX
Software
Cliente
(aplicación)
� Cada endpoint tiene un propósito específico (ej.: recibir comandos, transmitir datos, etc.)
� Hasta 16 endpoints (solo 3 en dispositivos de baja velocidad).
� El endpoint “0” esta siempre disponible: se usa para las inicializaciones y para obtener cuales otros endpoints están disponibles en el dispositivo
� Cada endpoint se caracteriza por su número (cualquier número decidido por el diseñador), ancho de banda, tipo de modo de transferencia, etc.
� Los endpoints se agrupan en “interfaces” y estas en “configuraciones”.
� Estas entidades lógicas tienen una representación en el código basada en descriptores
� Dos tipos de pipes:◦ Para transportar mensajes con datos concernientes a USB
◦ Para transportar flujos (streams): con datos que solo interesan a la aplicación y el dispositivo.
� Cuatro tipos de transferencia (siempre por paquetes):◦ Transferencias para control: comandos o pedidos de estado
◦ Transferencias para interrupción: iniciada por el dispositivo para que el host haga algo
◦ Transferencias isosíncronas: para transportar datos donde el tiempo es crítico (video, voz, etc.)
◦ Transferencias “bulk” (paquete o bulto): que usan todo el ancho de banda pero no tienen requisitos estrictos de tiempo
� Permite comunicar una aplicación de nivel de usuario (“userspace”) con dispositivos USB
� No hacen falta privilegios para acceder a un dispositivo USB
� Cada dispositivo USB es manipulado mediante dos objetos que provee la API: libusb_device y libusb_device_handle
� EL API provee de dos interfaces para acceder a los dispositivos de diferentes modo: una sincrónica y otra asincrónica
� Vea rápidamente las funciones y estructuras que componen esta API: http://libusb.sourceforge.net/api-1.0/api.html
(los nombres deben darle una idea de la función de cada elemento)
� Vea como se agrupan “módulos”´: http://libusb.sourceforge.net/api-1.0/modules.html
� Vea los diversos “descriptores” que existen (sus propiedades).
� Relacione las funciones con algunos de los conceptos vistos en la unidad 1
Hagamos un programa que :Hagamos un programa que :Hagamos un programa que :Hagamos un programa que :
1) Inicialice la librería: llamar a la fuinción libusb_init y crear una sesión.
2) Obtenga una la lista de dispositivos conectados al sistema: llamar a la
función libusb_get_device_list (esto crea un arreglo de libusb_device).
3) Barra la lista de dispositivos y muestre que opciones (interfaces,
configuraciones, endpoints, etc.) tiene cada uno .
4) Libere la lista de dispositivos : lamar a libusb_free_device_list
5) Cierre el dispositivo: llamar a libusb_close
6) Libere el API : llamar a libusb_exit
� En su linux:Verifique que cuenta con el compilador (gcc)
Asegúrese que la librería está instalada
� Puede realizar todo “a mano”:◦ Usando un editor de texto para escribir su programa (el “nano” por ejemplo)
◦ Y compilar a mano desde línea de comando:
gcc –miprog.c . . .
� O quizás prefiera utilizar un IDE completo como el Eclipse o elemental como el Genie
� Ejemplo de programa posiblePrimero el programa principal:
#include <iostream>#include </usr/include/libusb-1.0/libusb.h>using namespace std;void printdev(libusb_device *dev); //declaracion de la funcionint main() {
libusb_device **dispositivos; //puntero a puntero de dispositivos (la lista de dispositivos)libusb_context *contexto = NULL; //esta será la sessionint resultado; //para guardar los valores de retorno de funcionesssize_t cantidad; //numero de dispositivos conectadosssize_t i; //variable auxiliar
//inicializo la librería y creo una session: devuelve 0 si todo va bienresultado = libusb_init(&contexto); if(resultado < 0) {
cout<<"Error al inicializar"<<resultado<<endl;return 1;
}
//esto setea el nivel de "verbosidad" de las llamadas a funciones (vea que tiene disponible)libusb_set_debug(contexto, LIBUSB_LOG_LEVEL_NONE);
� Ahora la función:
//obtener la lista de dispositivos (notar la TRIPLE indireccion)cantidad = libusb_get_device_list(contexto, &dispositivos); if(cantidad < 0) {
cout<<"Hubo un error"<<endl;return 1;
}
cout<< cantidad <<" dispositivos en la lista."<<endl;
//barro la listafor(i = 0; i < cantidad; i++) {
cout<< "Dispositivo "<< i+1 <<endl;printdevprintdevprintdevprintdev(dispositivos[i]); (dispositivos[i]); (dispositivos[i]); (dispositivos[i]); //muestro algunos datos de los dispositivos
}//libero la listalibusb_free_device_list(dispositivos, 1);
//cierro la sesionlibusb_exit(contexto); return 0;
}
void printdev(libusb_device *dev) {libusb_device_descriptor descriptor;//obtengo la descripcion del dispositivoint resultado = libusb_get_device_descriptor(dev, &descriptor);if (resultado < 0) {
cout<<"No se pudo obtener la descripcion del dispositivor"<<endl;return;
}cout<<"Configuraciones posibles: "<<(int)descriptor.bNumConfigurations<<" ";cout<<"Clase de dispositivo: "<<(int)descriptor.bDeviceClass<<" ";cout<<"Fabricante (vendorID): "<<descriptor.idVendor<<" ";cout<<"Producto ID: "<<descriptor.idProduct<<endl;
libusb_config_descriptor *config;libusb_get_config_descriptor(dev, 0, &config);
const libusb_interface *inter;const libusb_interface_descriptor *interdesc;const libusb_endpoint_descriptor *epdesc;cout<<"Interfaces: "<<(int)config->bNumInterfaces<<endl;
for(int i=0; i<(int)config->bNumInterfaces; i++) {cout << "Interface:"<<i<<endl;inter = &config->interface[i];cout<<"Numero de configuraciones alternativas: "<<inter->num_altsetting<<endl;for(int j=0; j<inter->num_altsetting; j++) {
interdesc = &inter->altsetting[j];cout<<"Numero de interfaces: "<<(int)interdesc->bInterfaceNumber<<" | ";cout<<"Numero de endpoints: "<<(int)interdesc->bNumEndpoints<<endl;for(int k=0; k<(int)interdesc->bNumEndpoints; k++) {
epdesc = &interdesc->endpoint[k];cout<<"Tipo de descriptor: "<<(int)epdesc->bDescriptorType<<" | ";cout<<"Direccion del Endpont: "<<(int)epdesc->bEndpointAddress<<" | ";cout<<endl;
}}cout<<endl;
}cout<<endl<<endl<<endl;//libero el descriptorlibusb_free_config_descriptor(config);
}
� Compile el programa y ejecútelo (si hay errores debería ser capaz de corregirlos)
� Inserte algún dispositivo USB y vea los cambios en la salida del programa
� Ahora:El comando lsusb de linux brinda una salida distinta: vuelva a ver los descriptores del API y modifique el programa para que su salida se parezca a la de lsusb
(puede consultar directamente los fuentes de lsusb, si le parece)