Desarrollo de un Stack USB con memoria estática y soporte...

107
Universidad de Buenos Aires Facultad de Ingenier´ ıa Tesis de Grado de Ingenier´ ıaElectr´onica 19 de abril de 2016 Desarrollo de un Stack USB con memoria est´ atica y soporte para m´ ultiples dispositivos dentro de los lineamientos del Proyecto CIAA Autor: Sebasti´ an Ceola Padr´ on: 91826 Correo electr´ onico: [email protected] Tel´ efono: (011) 15 2489 4444 Carrera: Ingenier´ ıa Electr´ onica Fecha de Presentaci´ on: 22 de abril de 2016 Director de Tesis: Ing. Juan Manuel Cruz

Transcript of Desarrollo de un Stack USB con memoria estática y soporte...

Universidad de Buenos Aires

Facultad de Ingenierıa

Tesis de Grado de Ingenierıa Electronica

19 de abril de 2016

Desarrollo de un Stack USB con memoria

estatica y soporte para multiples

dispositivos dentro de los lineamientos del

Proyecto CIAA

Autor: Sebastian Ceola

Padron: 91826

Correo electronico: [email protected]

Telefono: (011) 15 2489 4444

Carrera: Ingenierıa Electronica

Fecha de Presentacion: 22 de abril de 2016

Director de Tesis: Ing. Juan Manuel Cruz

Tesis de Grado – Stack USB

Indice

1. Introduccion 7

1.1. Universal Serial Bus . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9

1.2. Proyecto CIAA . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10

1.3. Estado del Arte . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10

2. Alcance y Objetivos 13

2.1. Objetivos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15

2.2. Supuestos y Restricciones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16

2.3. Requerimientos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16

3. Introduccion Teorica 19

3.1. Sistema USB . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21

3.2. Topologıa . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22

3.3. Host . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22

3.4. Flujo de Datos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24

3.5. Tipo de Flujo de Datos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26

3.6. Descripcion de la Estructura de un Dispositivo . . . . . . . . . . . . . . . . . . 27

4. Desarrollo 29

4.1. Estructura Logica . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31

4.1.1. Hardware, Controlador del Host – Host Controller . . . . . . . . . . . . 31

4.1.2. Drivers del Controlador del Host – Host Controller Drivers (HCD) . . . 32

4.1.3. Interfaz del Controlador del Host – Host Controller Interface (HCI) . . 33

4.1.4. Driver USB (USBD) . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33

4.1.5. Drivers de Dispositivos . . . . . . . . . . . . . . . . . . . . . . . . . . 34

4.1.6. Codigo Usuario . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35

4.2. Interfaces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36

4.2.1. Interfaz de Drivers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36

4.2.2. Interfaz del USBD y driver HUB . . . . . . . . . . . . . . . . . . . . . 38

4.2.3. Interfaz HCI . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39

4.2.4. Interfaz del Hardware . . . . . . . . . . . . . . . . . . . . . . . . . . . 40

4.3. Estructura Interna . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40

4.3.1. Pipes de Datos y de Mensajes . . . . . . . . . . . . . . . . . . . . . . 41

4.3.2. Interfaces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42

1

INDICE INDICE

4.3.3. Dispositivos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43

4.3.4. Stack USB . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45

4.4. Proceso de Enumeracion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46

4.5. Asignacion de Drivers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51

4.6. IO Request Packets – IRPs . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56

4.7. Driver HUB . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58

4.7.1. Estados y Procesamiento de Datos . . . . . . . . . . . . . . . . . . . . 59

4.7.2. Estructura del HUB . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64

4.8. Documentacion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66

5. Configuracion del Stack USB 69

5.1. Encabezado de Configuracion . . . . . . . . . . . . . . . . . . . . . . . . . . . 71

5.2. Archivo de Configuracion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73

5.3. Asignacion de Interfaces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76

6. Ensayos y Resultados 79

7. Conclusiones 87

Bibliografıa 93

Anexos

Anexo A. Ejemplo de Codigo de Configuracion Generado 95

A.1. Encabezado . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 95

A.2. Fuente . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96

Anexo B. Log del Ensayo del Caso de Uso Real 99

2

Tesis de Grado – Stack USB

Indice de Figuras

1. Topologıa USB . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22

2. Estructura simplificada del host USB . . . . . . . . . . . . . . . . . . . . . . . 24

3. Composicion logica de un stack USB . . . . . . . . . . . . . . . . . . . . . . . 25

4. Composicion de la red de dispositivos . . . . . . . . . . . . . . . . . . . . . . 26

5. Estructura de descriptores de un dispositivo . . . . . . . . . . . . . . . . . . . 28

6. Estructura del stack implementado . . . . . . . . . . . . . . . . . . . . . . . . 32

7. Diagrama de interfaces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37

8. Maquina de estados del Host, por dispositivo . . . . . . . . . . . . . . . . . . 48

9. Secuencia de enumeracion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52

10. Secuencia de asignacion de driver . . . . . . . . . . . . . . . . . . . . . . . . . 55

11. Mapa de bits de la notificacion de cambio de estados de un HUB . . . . . . . . 59

12. Maquina de estados del driver HUB . . . . . . . . . . . . . . . . . . . . . . . 60

13. Secuencia de procesamiento del driver HUB . . . . . . . . . . . . . . . . . . . 61

14. Ejemplo de documentacion generada a traves de Doxygen . . . . . . . . . . . . 67

15. Banco de pruebas de desarrollo . . . . . . . . . . . . . . . . . . . . . . . . . . 81

16. Banco de pruebas de caso de uso real . . . . . . . . . . . . . . . . . . . . . . 83

3

INDICE DE LISTADOS INDICE DE LISTADOS

Indice de Listados

1. Interfaz POSIX-compatible del driver HID . . . . . . . . . . . . . . . . . . . . 36

2. Estructure de los pipes de datos . . . . . . . . . . . . . . . . . . . . . . . . . 41

3. Estructure de los pipes de mensajes . . . . . . . . . . . . . . . . . . . . . . . . 42

4. Estructura de las interfaces . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43

5. Estructura de un dispositivo USB . . . . . . . . . . . . . . . . . . . . . . . . . 43

6. Estructura principal del stack USB . . . . . . . . . . . . . . . . . . . . . . . . 45

7. Estructura de las entradas en el arreglo de drivers . . . . . . . . . . . . . . . . 54

8. Ejemplo del arreglo de drivers . . . . . . . . . . . . . . . . . . . . . . . . . . . 54

9. Interfaz IRP del USBD . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56

10. Ejemplo de IRP de control . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57

11. Constantes de configuracion estatica del stack USB . . . . . . . . . . . . . . . 64

12. Documentacion en comentarios de los prototipos de asignacio de drivers . . . . 66

13. Constantes de configuracion estatica del stack USB . . . . . . . . . . . . . . . 73

14. Composicion de las entradas del archivo de configuracion . . . . . . . . . . . . 74

15. Estructura de configuracion estatica del stack USB . . . . . . . . . . . . . . . 74

16. Metodo para obtener configuracion asociada a un dispositivo . . . . . . . . . . 77

17. Encabezado de configuracion generado . . . . . . . . . . . . . . . . . . . . . . 95

18. Fuente de configuracion generado . . . . . . . . . . . . . . . . . . . . . . . . . 96

19. Log serie del ensayo del caso de uso real . . . . . . . . . . . . . . . . . . . . . 99

4

Tesis de Grado – Stack USB

Glosario

API Application Programming Interface, es un conjunto de rutinas y protocolos de comuni-

cacion entre un componente de software y su usuario, independientemente de su imple-

mentacion interna.

CIAA Computadora Industrial Abierta Argentina.

EDU-CIAA-NXP Plataforma educativa de la CIAA con un procesador NXP.

FreeOSEK Un RTOS implementado bajo el estandar OSEK.

FS Full-speed, velocidad de dispositivos USB con una tasa de trasnferencias de 12 Mbps.

HCD Host Controller Driver, driver del controlador del Host USB, o sea, el controlador de

hardware propio de la familia de microcontrolador.

HCI Host Controller Intreface, interfaz de comunicacion del HCD.

HID Human Interface Device, especifica una clase de dispositivo periferico (segun el estandar

USB) utilizable directamente por un ser humano.

HS velocidad de dispositivos USB con una tasa de trasa de trasnferencias de 480 Mbps.

HUB Dispositivo USB que expande un unico puerto USB con el fin de aumentar la cantidad

de disponibilidad de puertos disponibles.

IRP Input/Output Request Packet, pedidos a traves de los cuales se realizan transferencias

USB a traves del USBD.

Licencias BSD Es una familia de licencias de software libre con mınimas restricciones sobre

la redistribucion de software.

LS Low-speed, velocidad de dispositivos USB con una tasa de trasnferencias de 1.5 Mbps.

MPS Maximum Packet Size, es el maximo tamano de paquete en una transaccion sobre el

endpoint de control.

MSC Mass Storage device Class, clase de dispositivo USB utilizado para el almacenamiento

masivo de datos.

OSEK Offene Systeme und deren Schnittstellen fur die Elektronik in Kraftfahrzeugen, es un

estandar para sistemas operativos embebidos de llamadas al sistema y comunicaciones.

5

Glosario Glosario

POSIX Portable Operating System Interface, es una familia de estandares especificada y

mantenida por la IEEE que define la compatibilidad entre sistemas operativos.

RTOS Sistema Operativo de Tiempo Real (Real Time Operating System).

USB Universal Serial Bus, es un protocolo que define la comunicacion de dispositivos conec-

tados a un bus comun.

USB-IF USB Implementer’s Forum, es una organizacion sin fines de lucro que promueve y da

soporte al protocolo USB.

USB-OTG USB On-The-Go, es una especificacion que permite a dispositivos USB actuar

tanto como dispositivo o servidor.

USBD USB Driver, driver del Host USB.

6

Capıtulo 1

Introduccion

En este capıtulo se realiza una breve introduccion a la historia del Bus Serie

Universal (USB) y el proyecto CIAA dentro del cual se ha realizado esta tesis.

Por otro lado, se describe en forma general el estado del arte en cuanto al

desarrollos de stacks USB y los motivos por los cuales estos no se adaptan a

los requerimientos de la tesis. Siendo tales objetivos el soporte para multiples

dispositivos y utilizacion de recursos estaticos unicamente.

Tesis de Grado – Stack USB

1. Introduccion

1.1. Universal Serial Bus

A mediados de la decada de 1990, un grupo de siete companıas lıder en tecnologıa comenzo

el desarrollo de un bus universal en serie (Universal Serial Bus - USB) con el fin de unificar

la gran cantidad de conectores e interfaces entre PCs y dispositivos externos [1, capıtulo 1].

La intension tambien era aumentar la facilidad de conexion, pudiendo conectar y desconectar

dichos dispositivos con el equipo encendido. Esta unificacion permitirıa simplificar el software

necesario para su configuracion y utilizacion.

Una de las principales ventajas se vio en la alimentacion de los dispositivos, aquellos sen-

cillos de bajo consumo pueden alimentarse directamente del bus USB sin requerir de una

fuente externa. Esto permitio reducir considerablemente el tamano y costo de gran cantidad

de perifericos, como teclados, camaras, dispositivos de almacenamiento masivos, entre otros.

A lo largo de los anos este estandar se fue perfeccionando y distintas versiones fueron

creadas. La primer version de USB, la 1.0, y su modificacion, la 1.1, definen dos velocidades

de transmision de datos: 1.5 Mbps y 12 Mbps, conocidas como LS (low-speed) y FS (full-

speed), respectivamente. Hoy en dıa los controladores USB todavıa soportan estas versiones,

la de baja velocidad es particularmente usada en dispositivos simples de baja velocidad como

perifericos de computadora, mouse, teclado, joystick. La de velocidad completa en perifericos

simples que requieren mayor ancho de banda (por ejemplo mouse y teclados de alta gama,

impresoras, escaneres, entre otros).

En el ano 2000, se creo la especificacion USB 2.0, con la cual se obtienen transferencias

de hasta 480 Mbps y se utiliza hoy en dıa en la gran mayorıa de perifericos de computadores

que requieren de grandes transferencias de datos. Por ejemplo, dispositivos de almacenamiento

externo, camaras web, conversores USB-serie, entre otros.

Han continuado las mejoras con el pasar de los anos. En el 2008 se actualizo a la version 3.0

del estandar con la cual se aumento considerablemente la velocidad de transaccion a 5 Gbps

y se agrego soporte para transferencias full-duplex, esta nueva version implico un cambio

importante en el controlador y la arquitectura del stack USB. Luego se creo la version 3.1 en

el 2013 aumentando la velocidad a 10 Gbps y la version “tipo-C” en 2014 que modifico los

conectores utilizados en la 3.1.

El enfoque de esta tesis llega hasta el estandar USB 2.0 solamente. El motivo de esto

es simple, la altas velocidades de los nuevos estandares requieren de hardware cada vez mas

complejo y de mayor costo, mientras que la simplicidad de las velocidades LS, FS y HS hace

que los recursos necesarios puedan colocarse en la mayorıa de los microcontroladores de gama

9

1.2 Proyecto CIAA

media/alta de hoy en dıa.

1.2. Proyecto CIAA

El proyecto CIAA (Computadora Industrial Abierta Argentina) nacio en el ano 2013 como

una iniciativa conjunta entre el sector academico e industrial [3]. La idea de esta iniciativa

es impulsar el desarrollo tecnologico nacional, darle visibilidad internacional al desarrollo tec-

nologico y electronico de la Argentina y generar cambios estructurales en la forma de desarrollar

y utilizar conocimientos.

Como se indica en el nombre del proyecto, dos de los pilares fundamentales –y sobre los

cuales se basara el desarrollo de esta tesis– son:

• Ser Abierta, todo su diseno, en su totalidad, esta disponible bajo la licencia BSD para

libre uso, distribucion y/o modificacion.

• Ser Industrial, que su diseno este preparado para las exigencias de las condiciones de

operacion que demandan los productos y procesos industriales.

Es importante destacar que la CIAA es la primer y unica computadora del mundo que

reune ambas cualidades. Son estas cualidades bajo las cuales se rige este proyecto a las que

se busca incorporar el desarrollo del stack USB de esta tesis, para lo cual son de suma im-

portancia conocimientos de la relacion entre el bajo nivel de microcontroladores y el proceso

de compilacion desde un lenguaje de alto nivel (en comparacion) como lo es C, tecnicas de

desarrollo de firmware y tener presente los recursos con los cuales se esta trabajando.

1.3. Estado del Arte

El proposito de este proyecto es crear una solucion para las necesidades de una interfaz

USB en un microcontrolador embebido. En particular sera un desarrollo libre y abierto para

permitir ya sea a empresas o individuos el uso de este stack sin costo ni restriccion alguna y

poder adaptarlo y/o modificarlo de acuerdo a sus necesidades. Ademas, debera adaptarse a las

restricciones de un sistema operativo de tiempo real y una computadora orientada a la industria,

donde las especificaciones son mas estrictas y se espera un rendimiento y confiabilidad mayor.

Bajo la necesidad de incorporar un stack USB al Proyecto CIAA se buscaron soluciones

existentes que cumplieran con los lineamientos del mismo, particularmente el ser abierta y efi-

ciente en el uso de recursos. Se analizaron varios casos disponibles y en general las prestaciones

y problematicas fueron similares, a continuacion se mencionan brevemente.

En general los stacks libres disponibles evitan el uso de memoria dinamica de dos maneras.

10

Tesis de Grado – Stack USB

La primera es limitando su utilizacion a la inicializacion del sistema. La segunda –y principal–

es limitando la cantidad de dispositivos a uno, esto simplifica enormemente los requerimientos

del stack USB.

Se encontraron otras implementaciones simples y basicas, pero construidas fuertemente al

rededor de una familia de microcontroladores en particular. Esto dificulta considerablemente

la portabilidad del stack.

Por ultimo, una de las principales desventajas de la mayorıa de las soluciones disponibles

es la falta de actualizaciones y mantenimiento. Varias no han recibido cambios, a pesar de

indicar claramente que estan incompletas, en varios meses o incluso anos.

Desafortunadamente, si bien las soluciones anteriores son libres, no cumplen con los re-

querimientos principales del stack USB para el Proyecto CIAA. En particular, la capacidad

de conectarse con multiples dispositivos en simultaneo y un uso conservativo y eficiente de

los recursos del sistema, principalmente memoria. Es importante enfatizar esto ultimo, ya que

uno de los principales puntos detras de esta tesis es eliminar por completo el uso de memoria

dinamica en el stack USB, ya sea para almacenamiento de informacion de dispositivos como

datos pertinentes a transacciones en proceso, y poder desarrollar un stack completo con me-

moria estatica. Al realizar este cambio se elimina la incertidumbre de si un dispositivo podra o

no conectarse al sistema.

Por otro lado, existe una gran cantidad de soluciones comerciales. Sin embargo, es claro

que no cumplen con el segundo pilar fundamental del Proyecto CIAA, ser abierto y de libre

uso. A su vez, por ser de codigo cerrado no es posible analizar su funcionamiento a bajo nivel.

En resumen, con esta tesis se busca implementar un stack USB desarrollado desde la base

con memoria estatica, parametrizable y, por lo tanto, de utilizacion de recursos determinada.

Ademas, se implementara soporte para la conexion de multiples dispositivos, lo cual no se

encuentra en las soluciones libres y abiertas actuales, particularmente, teniendo en cuenta el

primer requisito mencionado.

11

Capıtulo 2

Alcance y Objetivos

Este capıtulo introduce, en primer lugar, los objetivos planteados para el stack

USB a desarrollar, siendo los principales el uso de memoria estatica y soporte para

multiples dispositivos. En segundo lugar, en que consiste el proyecto y que abarcara

el desarrollo, desde la implementacion del stack USB hasta la documentacion. En

tercer lugar, los supuestos y restricciones que determinan el marco de trabajo de

la tesis. Por ultimo, los recursos y elementos con los cuales se contara para el

desarrollo del proyecto.

Tesis de Grado – Stack USB

2. Alcance y Objetivos

2.1. Objetivos

El objetivo es disenar, desarrollar, implementar y documentar un stack USB apto para mi-

crocontroladores embebidos. El enfoque estara principalmente en el uso como servidor (host).

El sistema debera seguir las restricciones de calidad y confiabilidad a las que esta sujeta una

computadora industrial y la licencia BSD del proyecto CIAA.

Se plantea un cambio de enfoque en el pilar fundamental de un stack USB, el manejo

dinamico de dispositivos, por el manejo adecuado de recursos. La mayor cantidad de perifericos

hoy en dıa se comunican a traves de este estandar, pero en una situacion donde se requiere

mayor confiabilidad y robustez no es necesario tener la misma capacidad de soporte de variedad

de dispositivos. Por otro lado, reducir el dinamismo nos permitira optimizar los recursos de

hardware y, principalmente, memoria requeridos.

El proyecto consistira en el analisis y estudio de la mejor alternativa para el desarrollo de

un stack USB sin utilizacion de memoria dinamica y con soporte para multiples dispositivos.

Luego, se llevara a cabo su desarrollo, implementacion e integracion en el proyecto CIAA.

En la etapa de analisis y estudio se buscara la mejor manera de comenzar con el desarro-

llo, se vera si es conveniente partir de alguna solucion ya implementada (aunque no cumpla

con los requerimientos particulares de este proyecto). Tambien se realizara un estudio de la

especificacion USB para establecer que puntos de la misma son prioritarios en el desarrollo.

La etapa de desarrollo consistira en el diseno del firmware y la implementacion del stack

USB desde la interfaz de hardware de bajo nivel hasta la API que utilizaran los usuarios finales.

En la etapa de pruebas se debera corroborar el correcto funcionamiento del stack ante si-

tuaciones de funcionamiento tanto normal como no esperado. En un principio, y en la medida

que sea posible, sera analizado bajo el programa de conformidad creado por USB-IF [9]. Se

utilizara el proceso de desarrollo en un kit y posterior pasaje a la CIAA para probar la portabi-

lidad y la interfaz POSIX del stack. Ademas, dado que el proyecto es un desarrollo puramente

de software, todos los ensayos seran sobre este y no se realizaran aquellos correspondientes al

hardware.

En paralelo a las tres etapas mencionadas, debera realizarse la documentacion correspon-

diente de cada etapa de desarrollo e implementacion, junto con los documentos necesarios

para la incorporacion del stack en un sistema embebido y su guıa de uso.

Esta clase de proyecto no necesita de recursos especıficos por ser en su mayor parte

15

2.2 Supuestos y Restricciones

firmware, por lo que el desarrollo no requiere instalaciones ni instrumental particular. Sola-

mente se debera disponer de una plataforma CIAA para probar el resultado final.

El desarrollo de un stack USB como tema de tesis ha sido propuesto al tesista por el Ing.

Mariano Cerdeiro, miembro del Proyecto CIAA, mientras que quien acompanara y guiara al

tesista en el trascurso del proyecto sera el Ing. Juan Manual Cruz como director de tesis.

2.2. Supuestos y Restricciones

Para el desarrollo exitoso del proyecto se trabajara bajo los siguientes supuestos:

• Desarrollar sobre la CIAA (EDU-CIAA-NXP) provista por el Proyecto CIAA sera suficiente

en todos los aspectos para implementar y probar el stack USB.

• Las funciones POSIX necesarias para desarrollar el stack (en particular de exploracion de

directorios) estan o seran implementadas en el transcurso del proyecto.

El proyecto sera limitado y orientado por las siguientes restricciones:

• Cualquier comunicacion que se realice entre el stack y el kernel del sistema operativo

debera ser POSIX-compatible.

• La configuracion del stack USB y los dispositivos a conectar se debera realizar en tiempo

de compilacion (o previo) para poder optimizar recursos.

• Solo esta previsto el uso del FreeOSEK (el que se ha incorporado en la CIAA) como

RTOS para desarrollar y validar el proyecto.

2.3. Requerimientos

1. Permitir comunicarse a traves del protocolo USB 2.0 en los microcontroladores utilizados

dentro del proyecto CIAA.

2. Interfaz POSIX compatible.

3. Permitir configurar el microcontrolador en tiempo de compilacion para una mejor admi-

nistracion de los recursos.

4. Utilizar recursos estaticos y determinables en tiempo de compilacion, evitar la memoria

dinamica y cualquier incerteza en los recursos necesarios para asegurar el funcionamiento

del stack USB.

5. Debera poder extenderse a otras plataformas con cambios mınimos.

16

Tesis de Grado – Stack USB

6. Dar prioridad a las transferencias de control, interrupcion y bulk. Las isocronas seran un

desarrollo secundario en comparacion.

7. El stack USB estara manejado por un RTOS, en este caso el OSEK del Proyecto CIAA y

debera ser migrable a otros sistemas operativos con cambios mınimos y bien documen-

tados.

8. Se tendra la opcion de compilar y utilizar el stack sin ningun sistema operativo, sino a

traves de una maquina de estados.

9. Documentacion detallada de como portar el stack a otro sistema operativo o hardware,

para facilitar la futura migracion a distintos dispositivos y/o RTOS.

10. Documentacion detallada sobre la estructura interna del stack y los distintos modulos,

funciones, estructuras y tipos de datos utilizados.

11. Manual de uso y ejemplos de la interfaz con la que trabajara el usuario final (API).

12. Al compilar como servidor deberan implementarse drivers basicos de HUB, HID mouse

y HID teclado, por lo menos.

17

Capıtulo 3

Introduccion Teorica

En este capıtulo se explicaran los conceptos basicos de un sistema USB y su

composicion. Estos elementos se utilizaran extensamente en el desarrollo de la

tesis por lo cual una imagen basica, pero clara, es fundamental.

Se introduciran los componentes de un sistema USB; las funciones y responsa-

bilidades de cada uno, en particular del servidor encargado del control del sistema

en su totalidad; la topologıa del bus USB y como se forma una red de dispositi-

vos; los distintos tipos de flujo de datos; y, por ultimo, la estructura logica de un

dispositivo USB y como esta se describe y es transmitida.

Tesis de Grado – Stack USB

3. Introduccion Teorica

A continuacion se explicaran brevemente los terminos y conceptos sobre USB que seran

usados a lo largo de esta tesis.

3.1. Sistema USB

El estandar USB define un unico dispositivo encargado de controlar y manejar todas las

transmisiones y demas dispositivos en el bus, este es el servidor o host [7, capıtulo 4]. La

ventaja de que un unico dispositivo inicie y controle todas las transacciones en el bus es que

se puede determinar perfectamente el ancho de banda en uso de la red y evitar colisiones entre

dispositivos que inician transferencias simultaneas. Por otro lado, que el host deba controlar

todas las transacciones hace que se requiera una logica mas compleja que en aquellos sistemas

donde el bus no esta controlado. Ademas, esto no permite que los dispositivos se comuniquen

entre sı por cuenta propia.

Es fundamental de un sistema USB permitir la conexion y desconexion de dispositivos sin

requerir el apagado del sistema. Para lograr esto se utilizan mecanismos electricos entre el host

y el dispositivo para detectar el momento de conexion y negociar la velocidad de transferencia

de datos, tambien mecanismos logicos para poder configurar dicho dispositivo sin afectar al

resto de los ya conectados al bus.

Para que el host pueda conectarse con mas de un dispositivo en simultaneo se utilizan

HUBs USB. Un HUB se encarga de tomar la senal proveniente del host y repetirla en todos

sus puertos de salida. Ademas, realiza las siguientes tareas de control de suma importancia:

• Permite que el host pueda comunicarse con dispositivos de distintas velocidades. Por

ejemplo, puede conectarse un dispositivo LS al puerto de un HUB FS, este luego se

configurara como corresponda para que el host pueda realizar la transaccion a velocidades

LS a pesar de estar conectado directamente a un dispositivo FS.

• Se encarga de transmitir individualmente a cada dispositivo las senales de control re-

queridas cuando este se conecta. Dado que el estandar USB permite la conexion y

desconexion de dispositivos en el acto, es necesario que el host pueda detectar estos

cambios e identificar donde sucedieron.

• Manejar la alimentacion requerida por los distintos dispositivos conectados a sus puertos

y las condiciones de sobre-carga. Puede utilizar una fuente de alimentacion externa para

no depender solamente de la energıa suministrada por el host.

Inmediatamente despues del host y su controlador, integrado en el microcontrolador, se

ubica el HUB raız del sistema o root HUB. El comportamiento de un root HUB es el mis-

21

3.2 Topologıa

mo que el de un HUB ordinario, pero la interfaz de comunicacion con este dependera del

microcontrolador particular.

3.2. Topologıa

La topologıa de una red de dispositivos USB es la de una estrella seccionada en niveles,

como se puede observar en la figura 1. La conexion entre el host y cada dispositivo se realiza

punto a punto y posee un camino fısico independiente. En el centro de la estrella se encuentra

el host y en cada punta una funcionalidad o funcion (function).

Es importante diferenciar entre funcion y dispositivo. La primera es aquella que nos presenta

una capacidad o prestacion, por ejemplo de impresora o teclado. El segundo, en cambio, puede

agrupar un grupo de funcionalidades, como lo es una impresora con escaner. Los usuarios se

comunica con las funciones de un dispositivo y no con este como tal.

Figura 1: Topologıa USB

Fuente: Especificacion USB 2.0, seccion 4.1.1, figura 4-1 – Bus Topology

3.3. Host

La comunicacion de los dispositivos en el bus USB es manejada completamente por el host,

este debe encargarse de:

22

Tesis de Grado – Stack USB

• Detectar la conexion y desconexion de dispositivos.

• Manejar el flujo de control y de datos con todos los dispositivos.

• Recolectar el estado de cada conexion y la actividad del bus.

• Proveer de alimentacion a los dispositivos conectados y que la requieran.

Para poder llevar a cabo estas actividades el host debe mantener un mapa del bus USB y sus

dispositivos para conocer exactamente donde y bajo que condiciones esta cada uno conectado.

Tiene que poder determinar si ya no es posible conectar mas dispositivos, por ejemplo, en el

caso de que se requiera mayor ancho de banda que el disponible.

En forma ilustrativa (ver figura 2), el host se encuentra compuesto por los siguientes

componentes:

• Controlador (HCD), el hardware encargado de manejar el protocolo de bajo nivel y carac-

terısticas electricas y mecanicas. Los drivers de bajo nivel que se comunican directamente

con el hardware.

• Drivers de bajo nivel (o interfaz del controlador – HCI), es la capa que intercomunica al

host con el hardware sobre el que opera.

• Driver USB (USBD), es el encargado de manejar y controlar las transacciones y toda

actividad a realizarse sobre el bus.

• Software del Host, en conjunto con el driver, es quien se utiliza para configurar y controlar

al host.

• Drivers de dispositivos, son los encargados de administrar las distintas funciones de los

dispositivos. Los usuarios utilizaran esta capa para comunicarse con el bus USB.

• Software usuario, o sea, los clientes que accederan al bus USB para realizar transacciones.

Es fundamental dejar en claro la importancia del host en el bus USB, ya que es gracias

a este que cualquier tipo de recoleccion de informacion desde un periferico o envıo de datos

hacia este es posible. Es aquı donde se concentrara el enfoque de esta tesis, representado por

los bloques resaltados en la figura 2.

Un stack USB moderno debe poder realizar todas las tareas anteriores eficientemente y

permitir que los usuarios tengan acceso al bus de una forma simple y sin conocer todos los

detalles de implementacion y protocolo. Por otro lado, como se menciono anteriormente, uno

de los pilares fundamentales de este estandar es el dinamismo, o sea, que pueda conectarse

cualquier tipo de dispositivo y que esto se realice en el acto.

23

3.4 Flujo de Datos

Drivers

Driver USB(USBD - USB Driver)

Softwaredel Host

Drivers de bajo nivel(HCI - Host Controller Interface)

Controlador / Hardware(HCD - Host Controller Driver

Bus USB

ClienteSoftware usuario

Figura 2: Estructura simplificada del host USB

En el mundo de los microcontroladores y sistemas embebidos hace algunos anos se ha

comenzado a incorporar este tipo de bus de datos para la conexion de perifericos. Si bien las

capacidades de tales procesadores hoy en dıa son mas que suficiente para cumplir con todas

estas tareas, en general se buscan sistemas mas chicos, de menor consumo y, particularmente

en el area industrial, de alta confianza. Una de las desventajas de tener un sistema tan dinamico

como lo el USB es la utilizacion de recursos de memoria dinamica.

3.4. Flujo de Datos

El estandar USB permite realizar transferencias de control y/o datos entre el host y cada

uno de los dispositivos conectados. El flujo de informacion puede interpretarse en tres niveles

logicos distintos. En la figura 3 se muestra una version simplificada del la estructura del stack

donde cada bloque representa un nivel logico y su flujo de datos hacia/desde el dispositivo.

En la capa superior se encuentra el codigo usuario, este solo debe saber con que dispositivo

se esta comunicando y cual es su funcion. La interfaz dependera del sistema USB en particular

ya sea propia o estandar, por ejemplo POSIX-compatible.

24

Tesis de Grado – Stack USB

La capa intermedia es la que empaquete los mensajes a enviar segun el protocolo USB y

dispositivo objetivo e interpreta los datos recibidos. Aquı es donde se encuentran los drivers

de las distintas clases de dispositivos. A diferencia de la capa superior, es necesario conocer

el protocolo particular de comunicacion y saber como comunicarse con la funcion objetivo del

dispositivo a traves de la interfaz correspondiente y utilizando los endpoints –detallados mas

adelante– adecuados.

Por ultimo, la capa inferior es aquella que comunica al sistema USB con el hardware propio

de la plataforma y maneja el intercambio de datos con el bus fısico. La interfaz depende del

hardware y es en este punto que difiere entre los distintos microcontroladores.

USB LogicalDevice

Function

Physical Device

USB BusInterface

Actual communications flow

Logical communications flow

Client SW

USB HostController

Host

USB System SW

Figura 3: Composicion logica de un stack USB.

Fuente: Especificacion USB 2.0, seccion 5.2.1 figura 5-3 (Host Composition) y seccion 5.2.2 figura 5-4 PhysicalDevice Composition).

En la figura 4 se detalla la capa intermedia mencionada anteriormente con el fin de explicar

como se comunica el host con las distintas funciones de cada dispositivo.

Toda fuente o receptaculo de datos en un dispositivo USB se denomina endpoint y se

diferencian entre sı por su direccion unica (numero del endpoint – endpoint number) y sentido

de datos (desde (OUT) y hacia (IN) el host). Todo dispositivo debe implementar en forma

obligatoria dos endpoints, el numero 0 en direccion IN y OUT, este es el que se utiliza para

controlar el dispositivo.

El host se comunica con cada uno de estos en manera independiente. Al conectarse un

dispositivo se crea una asociacion entre el software usuario responsable de cada funcion y

el endpoint correspondiente, esta asociacion se la denomina pipe, representada con la lınea

25

3.5 Tipo de Flujo de Datos

punteada en la figura 4. Notar de la figura como cada dispositivo puede tener una cantidad

diferente de endpoints, los LS pueden tener hasta 4 mientras que los FS y HS hasta 32. Todos

estos se conectan logicamente al host a traves de pipes.

Flujo lógico

Flujo físico

Dispositivo Dispositivo

CapaLógica

CapaLógica

Capa física Capa física

Capa Lógica

Capa física

Bus de datos

Figura 4: Composicion de la red de dispositivos

Todos los endpoints asociados a una funcion del dispositivos se agrupan en una interfaz.

Para soportar multiples funciones por dispositivo es necesario definir multiples interfaces. La

unica excepcion es el endpoint 0, este no se incluye dentro de una interfaz ya que se utiliza

para configurar tanto el dispositivo como todas las funciones del mismo.

3.5. Tipo de Flujo de Datos

Se han definido cuatro tipos basicos de transferencia de datos:

Transferencias de control. (control transfers)

Se utilizan para configurar el dispositivo, tanto en la enumeracion como durante la

vida del mismo para configurar endpoints o sus funciones. Por ejemplo, para cambiar

la resolucion de video de una camara web. Los endpoints asignados a transferencias de

control son los unicos con un protocolo de comunicacion especıfico, los pipes asociados

a estos se denominan de mensaje – message pipes.

Transferencias de datos en bulto. (bulk data transfers)

Especializadas en el envıo o recepcion de grandes cantidades de datos que no requieren

un tiempo de transmision determinado. La informacion se transmite en rafagas y se

utiliza la mayor parte del ancho de banda disponible en el bus, el cual puede variar.

26

Tesis de Grado – Stack USB

Transferencias de datos en interrupcion. (interrupt data transfers)

Utilizadas para la transmision confiable de informacion, con latencia maxima asegurada.

En general para interfaces que no manejan gran cantidad de datos. El ancho de banda

requerido se determina al momento de creacion de los pipes correspondientes. Es un tipo

de transferencia periodica.

Transferencias de datos isocronas. (isochronous data transfers)

Se caracterizan por el envıo o recepcion de datos en forma continua y en tiempo real,

a diferencia de las de control o en bulto que depended del grado de utilizacion del bus

en el momento. Al igual que las de interrupcion, el ancho de banda se determina en la

creacion. Se diferencia de las transferencias anteriores en que no admite retransmision

ante errores con el objetivo de minimizar la latencia y permitir mantener la tasa de

transferencia de datos constante. En general se utilizan para dispositivos de streaming,

que requieren alta tasa de datos en tiempo real. Es un tipo de transferencia periodica.

3.6. Descripcion de la Estructura de un Dispositivo

Los dispositivos USB exponen su estructura logica a traves de descriptores. En la figura 5

puede observarse como se compone la jerarquıa de estos. Cada uno informa al host sobre los

distintos atributos y cualidades de cada componente del dispositivo.

1. Descriptor del dispositivo. Describe datos general del dispositivo: version, clase y subcla-

se, protocolo, numero de configuraciones y MPS, entre otros.

2. Descriptor de configuracion. Indica al host cuantas interfaces posee el dispositivo y

devuelve todos los descriptores asociados a ellas, ver los siguientes items. Es importante

notar que el resto de los descriptores que forman parte de la configuracion no pueden

pedirse en forma individual, deben obtener todos en conjunto dentro del de configuracion.

Tambien informa al host del maximo consumo de energıa que el dispositivo requiere bajo

esta configuracion.

3. Descriptor de interfaz. Contiene informacion acerca de la clase y subclase de la inter-

faz, el protocolo utilizado y la cantidad de endpoints usados por la misma. Es posible

que una interfaz tenga configuraciones alternativas, en tal caso, se describiran en forma

consecutiva. Los descriptores de los endpoints correspondientes deben incluirse obliga-

toriamente antes del descriptor de la proxima interfaz o configuracion alternativa, sin

embargo, entre estos pueden ubicarse otros descriptores especıficos de la clase.

4. Descriptores especıficos a la clase. Si la interfaz contiene descriptores especıficos de

la clase que utilizan el mismo formato que los de configuracion estandar, estos pueden

incluirse dentro del de configuracion. Por ejemplo, una interfaz HID devuelve el descriptor

HID entre el de interfaz y el de endpoint.

27

3.6 Descripcion de la Estructura de un Dispositivo

Figura 5: Estructura de descriptores de un dispositivo

5. Descriptor de endpoint. Contiene la informacion necesaria para que el host puede crear

el pipe correspondiente entre el software usuario y el endpoint descripto. Incluye el tipo,

direccion, MPS e intervalo de transferencia para el caso de aquellas periodicas.

28

Capıtulo 4

Desarrollo

El presenta capıtulo describe la composicion del stack USB desarrollado. Se

explican en detalle cada uno de los componentes del mismo y los motivos detras

de la eleccion y definicion de cada una de las estructuras de datos. Se enfatiza

principalmente la separacion en capas logicas y las interfaces intermedias que

permiten la interaccion con el codigo usuario en el nivel superior y los drivers de

bajo nivel dependientes del microcontrolador de la plataforma utilizada. A su vez,

se describen los estados por los cuales transita cada dispositivo dentro del stack

USB en su inicializacion y como llegan a su estado de funcionamiento normal.

Tesis de Grado – Stack USB

4. Desarrollo

El desarrollo del stack USB se llevo a cabo en tres etapas diferentes. En la primera se armo

la estructura deseada, dejando de lado los temas de memoria estatica y recursos limitados

para poder enfocarse en el manejo del sistema USB y su topologıa, para ello se fijaron ciertas

restricciones que facilitarıan el desarrollo pero luego deberıan ser modificadas en la segunda

etapa, esto se detallara mas adelante. En la segunda etapa, se utilizo la estructura del stack

creada en la primera y se modifico para adaptarse a los objetivos de asignacion estatica de

recursos. Por ultimo, en la tercer etapa se implementaron el driver HUB para poder conectar

varios dispositivos a la vez y, a modo de ejemplo, la base del driver HID.

Si bien puede realizarse esta separacion logica de las etapas de desarrollo, en el proceso

real se solaparon y fueron complementando entre sı.

Antes de comenzar a desarrollar el tema es importante diferenciar dos terminos que se

utilizaran constantemente:

• Drivers de bajo nivel o Drivers de hardware. Son aquellos que se utilizan para acceder

al hardware del microcontrolador, o sea, a los registros de este. Son dependientes de la

familia utilizada.

• Drivers de dispositivos. Son aquellos que conocen el protocolo propio de cada clase de

dispositivo o interfaz USB y se comunican con este/a a traves del stack USB. Estan

implementados sobre el stack y no dependen del hardware.

Es importante aclarar esta diferencia para no confundir los drivers de dispositivos (HID, HUB,

MSC) con los que manejan al hardware USB. Los primeros son portables al estar ubicados

sobre esta implementacion de un stack USB mientras que los segundos son propios de cada

microcontrolador.

4.1. Estructura Logica

Se comenzo el desarrollo realizando un diagrama simplificado de la estructura deseada del

stack USB, ver figura 6. Se ha separado dicha estructura en 6 capas, enumeradas de abajo

hacia arriba.

4.1.1. Hardware, Controlador del Host – Host Controller

La capa inferior contempla el hardware del microcontrolador, esto incluye componentes

fısicos como el bus y el control electrico de este desde el integrado. Tambien incluye los

31

4.1 Estructura Logica

Figura 6: Estructura del stack implementado

registros de configuracion con los que se utiliza y controla el sistema USB. Esta capa es

completamente dependiente del microcontrolador elegido.

4.1.2. Drivers del Controlador del Host – Host Controller Drivers (HCD)

Por encima del hardware se encuentra el driver del controlador del host (Host Controller

Driver - HCD). Existe una especificacion que estandariza su interfaz, la especificacion EHCI

de Intel. Lamentablemente, no todas las familias de integrados siguen dicha especificacion,

principalmente para reducir recursos y simplificar la interfaz en los casos mas acotados que

permite el hardware USB en estos casos particulares. Es por este motivo que se asumira que

esta capa tambien sera dependiente del microcontrolador.

A modo de ejemplo, el LPC4337 –utilizado en la EDU-CIAA-NXP y la CIAA-NXP– sigue

la especificacion EHCI (salvo ligeras desviaciones) pero el STM32F4 no lo hace.

La construccion de las transacciones (armado del paquete TOKEN, campos PID y de

direccion, etc.) debera realizarse en este punto. Esto es ası ya que, si bien la estructura es

estandar para USB, la forma en que se arman y como se organizan para poder enviarse dentro

32

Tesis de Grado – Stack USB

de los (micro)frames USB correspondientes es dependiente del hardware. Se dejara a cargo de

esta capa la correcta construccion de paquetes de velocidades mixtas, o sea, para dispositivos

LS/FS a traves de un HUB HS, por ejemplo.

4.1.3. Interfaz del Controlador del Host – Host Controller Interface (HCI)

Luego sigue la interfaz del controlador, Host Controller Interface, esta es la que se encarga

de unificar la interfaz del HCD con el driver USB (ver punto siguiente) para que puede utilizarse

sin depender del hardware inferior. Esta capa debera ser lo mas simple y liviana posible, la

intencion es definir una interfaz a utilizar por el stack USB y que, internamente, tenga la logica

suficiente para traducir dichos metodos a los requeridos por el HCD. Desde el lado superior

esta interfaz sera unica, mientras que desde el inferior tendra rutinas y objetos dependientes

del hardware utilizado.

4.1.4. Driver USB (USBD)

El Driver USB (USBD) es donde se implementara el stack USB como tal, aquı se realizaran

todas las tareas de administracion del bus de datos. Tendra que descubrir y almacenar la

topologıa y estructura de los dispositivos actualmente conectados, los motivos son varios:

• Es necesario poder determinar el camino que recorren los paquetes hasta llegar al dis-

positivo, saber a traves de que HUBs se comunican. Esto es particularmente importante

en la comunicacion con dispositivos de velocidad distinta a la del HUB.

• Validar la profundidad de la red USB que tiene un lımite dado por cantidad de HUBs.

• Conocer que dispositivos se conectan a traves de que HUBs, lo cual determinara las

acciones a realizar ante una desconexion.

• Administrar la creacion y configuracion de pipes.

• Manejar la asociacion entre interfaces y drivers de dispositivos.

• Realizar la enumeracion de cada dispositivo.

• Administrar los pipes de control para cada dispositivo. La diferencia entre estos y los

demas pipes es que estos son compartidos por todas las interfaces de un mismo dispo-

sitivo, mientras que los otros son independientes y no es necesario controlar quien tiene

acceso luego de que se hayan configurado y asignado en la enumeracion.

En una primera instancia, el USBD tendra una estructura interna de datos donde almace-

nara los dispositivos conectados y sus pipes de control correspondientes. Dentro de cada uno

de estos habra una estructura de interfaces, cada una asociada a un driver de dispositivos, o

33

4.1 Estructura Logica

a ninguno, en caso de no corresponder al ser enumerado. Por ultimo cada interfaz tendra un

arreglo de los pipes sobre los cuales tendra control y responsabilidad, tambien a determinar al

momento de enumeracion.

En paralelo al USBD, dentro de esta capa se encuentra el driver HUB. Si bien este es un

driver de dispositivo y, por consiguiente, debiera estar en la capa siguiente, a nivel logico y

funcional es mejor representado en este punto. Este driver es el encargado de administrar la

conexion y desconexion de todos los dispositivos que no se conecten directamente al hardware

del microcontrolador y lo hagan a traves de HUBs. No tendra una interfaz POSIX-compatible

ya que el unico usuario de este sera el host, entre ellos habra un intercambio de datos y pedidos

de acciones muy particular y acotado, por lo que definir una interfaz propia y especıfica es mas

conveniente. Debido a esta ubicacion en la estructura del stack, los HUBs poseen las unicas

interfaces USB de las cuales el host es dueno y posee control. Para el resto de los dispositivos,

las interfaces quedan a cargo de los drivers especıficos.

La comunicacion entre los drivers y el USBD se realizara a traves de IRPs (Input/Output

Request Packets). Todos los distintos tipos de drivers podran comunicarse con el USBD a

traves de la misma interfaz y acceder al bus USB de la misma manera, el control de dichos

accesos se realizara en la capa actual. A pesar del driver HUB ser un caso particular, tambien

se utilizaran IRPs para las transferencias que se requieran realizar sobre el bus de datos, como

puede observarse en la figura 6.

4.1.5. Drivers de Dispositivos

Los drivers de dispositivos (HID, MSC, Video, etc.) se ubican por encima del USBD. De-

beran utilizar IRPs para pedir transferencias sobre el bus de datos. Es necesario conocer el

protocolo especıfico del dispositivo conectado, este no esta definido por la especificacion USB

2.0 pero sı por la especificacion particular de la clase, puede ser propietario y en tal caso

dependera de quien implemente del driver. Este es el ultimo punto donde la implementacion

debe estar al tanto del protocolo de mensajes USB. Este determina la estructura de las trans-

ferencias de control, las cuales estan definidas por el estandar y se utilizaran para configurar e

inicializar el dispositivo.

Todo driver tiene que definir una serie de funciones especıficas a traves de las cuales el

USBD se comunicara con este durante el proceso de enumeracion. Esto se explica mas en

detalle en la seccion 4.5. Basicamente al enumerar un dispositivo se tomara cada interfaz que

este contenga y se validara contra todos los drivers disponibles, en caso de haber uno que

coincida se registrara la interfaz en este y ası podra luego controlar el dispositivo, al removerse

del bus USB se le notificara al driver de tal suceso.

Hacia la capa superior, cada driver debera implementar la interfaz POSIX-compatible co-

34

Tesis de Grado – Stack USB

rrespondiente. Esto debe hacerse en esta capa y no en la anterior ya que su implementacion

dependera completamente de la clase de dispositivo, mientras que hacia el USBD es conve-

niente mantener la estructura de interfaz-endpoint y tipo de transferencia (control o datos).

4.1.6. Codigo Usuario

Por ultimo, la capa superior es donde se ubica el codigo usuario y se encuentra ya fuera

del stack USB. Se accedera al stack a traves de los distintos drivers de dispositivos utilizando

la interfaz POSIX-compatible. No sera posible acceder a interfaces que no hayan podido regis-

trarse en un driver, esto es ası ya que el codigo usuario no es quien deba conocer el protocolo

de clase de la interfaz ni su interpretacion.

Esta tesis se enfoca principalmente en la capa numero 4 que es la que contiene al USBD

y driver HUB y es, basicamente, el nucleo del stack USB. Ademas, se definen las interfaces

a utilizar para implementar las capas 3 y 4, para la primera se creara como ejemplo la base

del driver HID y para la segunda se utilizara el microcontrolador LPC4337 (con la EDU-CIAA-

NXP), mas detalles sobre esta a continuacion.

Para las capas de bajo nivel y el controlador del host (hardware mas HCD) se utilizara la

librerıa de NXP “LPCOpen”. Esta librerıa implementa los drivers de bajo nivel para el LPC4337,

sobre estos se ha implementado la interfaz HCI (capa 3). El objetivo de esto es poder utilizar

los drivers creados por el fabricante y adaptarlos a la interfaz definida para el stack USB. Para

poder llevar esto a cabo ciertas modificaciones se han realizado sobre la librerıa, estas han sido

mınimas con el fin de mantener la compatibilidad ante futuras actualizaciones de la misma, en

forma resumida se nombran a continuacion:

• Introducir funciones de callback para notificar al stack de la conexion y desconexion de

un dispositivo al hardware del microcontrolador.

• Eliminar las rutinas bloqueantes. El reset del bus USB utiliza un bucle bloqueante para

esperar el tiempo necesario de 10–20 ms, este cambio es imprescindible para poder

incluir el stack dentro de un sistema operativo de tiempo real como lo es el OSEK de la

CIAA. Tambien, la espera de respuestas ante transacciones en el bus USB no puede ser

bloqueante ya que el host debe seguir en funcionamiento para el resto de los dispositivos.

• Adaptar las rutinas de interrupcion al formato esperado por el sistema operativo de la

CIAA y poder configurarlas en el archivo oil correspondiente. Este es el ultimo punto

que es dependiente del hardware ya que cada familia de microcontroladores puede tener

distinto tipo y cantidad de interrupciones para manejar el hardware USB.

35

4.2 Interfaces

Cabe aclarar que la mayorıa de estos problemas provienen del hecho de que dicha implemen-

tacion del HCD no se ha pensado para manejar multiples dispositivos a la vez, lo que permite

realizar bastantes simplificaciones a la hora de manejar recursos y tiempos de espera.

4.2. Interfaces

En la figura 7 se ilustran las interfaces de comunicacion entre las distintas capas. Se han

diferenciado el driver de HUB y HID ya que el primero tiene una segunda serie de metodos

utilizados para comunicarse con el host, por ser un caso especial de driver como se ha explicado

anteriormente.

4.2.1. Interfaz de Drivers

La capa 5 (de drivers) se ha representado con el driver HID. Las interfaces se han dividido

en tres, la superior es aquella dedicada a la inicializacion y administracion del driver como tal,

con la cual se actualizaran los dispositivos HID. Estos metodos se ejecutan en la misma tarea

en la que corre el stack USB.

La interfaz intermedia incluye las funciones POSIX-compatibles, a traves de estas el codigo

usuario se comunicara con los distintos dispositivos HID, estos solo estaran disponibles para

abrir cuando hayan terminado de enumerarse por el host y ser configurados por el driver. A

continuacion se muestran los prototipos de estas funciones:

int usb_hid_open( const char *pathname, int flags );

int usb_hid_close( int fd );

ssize_t usb_hid_read( int fd, void *buf, size_t count );

ssize_t usb_hid_write( int fd, const void *buf, size_t count );

Listado 1: Interfaz POSIX-compatible del driver HID

La ultima interfaz es aquella utilizada al momento de la enumeracion para validar y asignar

drivers. Ver mas detalles en el capıtulo 4.5.

Lo importante del driver HID en particular es tener un ejemplo claro de como debe utilizarse

la interfaz, tanto hacia el codigo usuario como hacia el stack USB. Tener en cuenta que, en

este caso particular, se ha implementado para dispositivos HID basicos como mouse o teclado

y como estos no requieren de una funcion de write, la indicada anteriormente se encuentra

para ejemplificar la implementacion. En realidad, solo pueden ser abiertos para su lectura.

36

Tesis de Grado – Stack USB

USB task

User Application

USB Stack

Low-level Drivers .

Host Controller Driver (HCD)

Hardware/Library dependant

_usb_host_on_connection()_usb_host_on_disconnection()

HID Driver

usb_hid_inti()usb_hid_update()

usb_hid_open()usb_hid_close()usb_hid_read()usb_hid_write()

usb_hid_probe()usb_hid_assign()usb_hid_remove()

Host Controller Interface (HCI)

usbhci_init()usbhci_deinit()

usbhci_reset_start()usbhci_reset_stop()usbhci_get_speed()usbhci_is_connected()usbhci_get_frame_number()

usbhci_pipe_alloc()usbhci_pipe_dealloc()usbhci_pipe_configure()usbhci_msg_pipe_configure()

usbhci_xfer_start()usbhci_ctrlxfer_start()usbhci_xfer_status()usbhci_ctrlxfer_status()usbhci_xfer_cancel()usbhci_ctrlxfer_cancel()

HUB Driver

usb_hub_init()usb_hub_update()

usb_hub_get_speed()usb_hub_port_reset_start()usb_hub_port_reset_status()usb_hub_get_address()usb_hub_get_n_ports()

usb_hub_probe()usb_hub_assign(usb_hub_remove()

USB Driver (USBD)

usb_init()usb_deinit()usb_run()usb_systick_inc()

usb_irp()usb_ctrlirp()usb_irp_status()usb_irp_cancel()usb_ctrlirp_bypass()

usb_device_attach()usb_release_from_port()usb_device_reset()usb_device_get_addr()usb_pipe_get_interval()

Figura 7: Diagrama de interfaces

37

4.2 Interfaces

4.2.2. Interfaz del USBD y driver HUB

En la capa siguiente (4) se encuentra el codigo del host y del driver HUB. Ambos tambien

estan separados en tres grupos de interfaces.

El driver HUB posee la misma interfaz superior e inferior que los drivers de dispositivos

(HID), o sea, para inicializacion, actualizacion y asignacion del driver. Mientras que la interfaz

intermedia se diseno especıficamente para que el host pueda comunicarse con los HUBs. Las

funcionalidades que se exponen en este punto son:

• Obtener la cantidad de puertos soportados por el HUB.

• Obtener la velocidad de conexion de un dispositivo en un dado puerto del HUB indicado.

Esto se utiliza para saber si el dispositivo enumerara como LS ,FS o HS.

• Obtener la direccion que se le ha asignado al HUB. Esto es importante ya que los ındices

que representan a cada HUB dentro de su estructura no necesariamente corresponden

con la direccion que el host asigna al dispositivo

• Iniciar el reset del bus USB y consultar su estado.

Para mas detalles ver el capıtulo 4.7.

El host es un caso mas particular ya que no hay codigo usuario que deba interactuar con

este directamente. Se necesita una tarea dedicada al stack USB, desde la cual se inicializara

y actualizara el stack con las funciones indicadas en la interfaz superior en la figura. Toda la

administracion de dispositivos se maneja internamente.

El grupo inferior contiene los metodos de administracion de dispositivos, estos seran utili-

zados tanto por el mismo USBD como por el driver HUB. Se resumen en:

• Conexion o desconexion de un dispositivo. Esto sera indicado desde los callbacks de

conexion y desconexion incluidos en el driver de bajo nivel HCD (en caso de un evento

directo sobre el hardware del equipo) o desde el driver HUB (en caso de un evento

detectado por el driver HUB).

El metodo de desconexion debe, ademas, realizar un trabajo extra. Al desconectarse un

dispositivo, si es un HUB, es necesario recorrer la red USB para ver si hay dispositivos USB

conectados a traves de este. En caso afirmativo, se procede recursivamente a desconectar

todos los dispositivos que correspondan. El caso extremo es la desconexion del dispositivo

raız, esto desencadena la desconexion de toda la red USB.

• Reset de un dispositivo. A diferencia del reset del bus USB, este es a nivel host y deja al

dispositivo en el estado inmediato luego de una conexion. Si el dispositivo se encuentra

en un estado funcional proseguira a ser enumerado y asignado drivers nuevamente.

38

Tesis de Grado – Stack USB

• Obtener la direccion asignada al dispositivo. Si bien esta direccion es fija para el host,

de esta manera los drivers no requieren conocer el metodo de asignacion.

• Obtener el intervalo de pedido de datos del endpoint indicado, solo si se aplica.

• Si en el futuro se requiere acceder a mas datos de los dispositivos, interfaces o endpoints

este es el punto donde agregarlos.

Por ultimo, la interfaz intermedia es a traves de la cual los drivers y el mismo host durante la

enumeracion utilizaran IRPs para comunicarse con dispositivos USB. Para facilitar los pedidos

estandar USB, o sea, aquellos realizados hacia y desde el endpoint de control con un pipe de

mensajes, se definio un metodo independiente. Para mas detalles ver el capıtulo 4.6. El ultimo

metodo dentro de esta interfaz usb_ctrlirp_bypass() esta incluido en la figura solo

como referencia, este sera usado por el stack USB solamente y no por los drivers, el motivo

de esto se explica en detalle en la seccion antes mencionada.

4.2.3. Interfaz HCI

La capa de los drivers de bajo nivel (3) se ha separado en cuatro grupos de interfaces,

ordenados desde el superior hasta el inferior en la figura 7. El primer grupo se encarga de

la inicializacion del hardware, no hay metodo de actualizacion ya que el HCD se manejara a

traves de interrupciones o pedidos del host.

A continuacion se encuentra el grupo de administracion y estado de bus USB. Se destacan

principalmente los funciones de manejo del reset del bus de datos y obtencion de la velocidad

del dispositivo conectado al puerto USB fısico del microcontrolador. En este punto puede

consultarse el estado de conexion de dicho puerto, internamente se actualiza con los callbacks

de conexion y desconexion del HCD. Se define que el reset del bus se maneje de la siguiente

manera:

1. Comenzar el reset con usbhci_reset_start().

2. Detener el reset con usbhci_reset_stop(), idealmente de 10 a 20 ms luego del

comienzo. Es posible de que esto se maneje automaticamente por el microcontrolador

(como lo hace el LPC4337), en tal caso este metodo debera devolver el estado del reset,

o sea, si aun esta en curso o ha finalizado.

El tercer grupo de interfaces contiene todo metodo relacionado con la administracion de

endpoints y pipes. Es necesario poder realizar las siguientes operaciones:

• Pedir y devolver un pipe. Si bien al configurar el stack no puede utilizarse mas pipes

que los presentes en el hardware, es necesario poder pedir una referencia a un pipe en

la representacion interna que estos usen, de otra manera el host tendrıa que conocer

39

4.3 Estructura Interna

dicha implementacion y se perjudicarıa la portabilidad. Por otro lado, en caso de estar

incorrectamente configurado el stack, los dispositivos que se conecten antes de llegar al

numero maximo de pipes funcionaran sin inconvenientes.

usbhci_pipe_alloc()

usbhci_pipe_dealloc()

• Configurar los pipes. Se prepara al pipe para una transaccion con los parametros indica-

dos: velocidad, numero de endpoint, direccion de dispositivo, MPS, entre otros.

usbhci_pipe_configure()

• Configurar los pipes de mensajes. En esencia, se configuran como los de datos, pero hay

ciertos parametros implıcitos o diferentes como el numero de endpoint, intervalo, tipo y

direccion.

usbhci_msg_pipe_configure()

Por ultimo, el grupo inferior complementa al grupo de pedidos IRPs en el USBD. Es

necesario que la interfaz HCI exponga los metodos correspondientes para iniciar transacciones

USB, consultar su estado y cancelarlas. La diferencia con el USBD es que aquı ya no hay

control de pipes, estado del dispositivo ni repeticion ante errores, es simplemente la interfaz

unica definida para dar al host acceso al bus USB. Ya que la estructura de los pipes de datos

y los de mensajes son diferentes es necesario tener dos juegos de interfaces, uno para las

transferencias normales y otra para las de control.

4.2.4. Interfaz del Hardware

La ultima capa (2) es dependiente del hardware y no pertenece al desarrollo de esta tesis.

Como se ha comentado antes, se utilizaron los drivers de bajo nivel implementados en la

librerıa LPCOpen para la EDU-CIAA-NXP. El unico agregado a destacar es la inclusion de las

funciones de callback que notifican la conexion o desconexion de un dispositivo. Sin embargo,

esto tambien es dependiente del hardware, en este caso particular fue necesario incluirlas ya

que tal evento se presencia dentro de rutinas de interrupcion y no esta expuesto hacia afuera.

En caso de que los drivers de bajo nivel permitan consultar el estado del puerto directamente

los callbacks no seran necesarios.

4.3. Estructura Interna

En esta seccion se explicaran las distintas estructuras que se utilizaron para implemen-

tar el stack USB. Se mantuvieron similares a la topologıa del sistema USB para facilitar la

comprension y mantenibilidad del stack.

40

Tesis de Grado – Stack USB

4.3.1. Pipes de Datos y de Mensajes

Las estructuras de los pipes de datos y de mensajes son similares, se diferencian en que

las de datos tienen varios miembros que en las segundas son implıcitos. Ademas, los mensajes

deben almacenar la informacion del pedido estandar USB.

Los miembros que tienen en comun son los siguientes:

• El numero de intentos que lleva la transaccion actual.

• El buffer de donde se toman los datos a enviar o donde se escriben los recibidos, esto

es necesario para poder re-intentar una transmision.

• El handle, este representa al pipe en el driver de bajo nivel, como se utiliza internamente

en el HCI dependera de la familia del microcontrolador.

El pipe de datos (o streaming) debe almacenar toda la informacion que describe el com-

portamiento del endpoint al que se ha asociado en la enumeracion. La informacion se lista a

continuacion.

• Tipo. Puede ser Isocrono, en Bulto, de Control o de Interrupcion.

• Direccion. Hacia el host (IN), hacia el dispositivo (OUT) o token (utilizada para describir

las transferencias de control).

• Largo. Largo del buffer de datos, ya sea para envıo o recepcion.

• Numero. Numero del endpoint asociado.

• MPS. Tamano maximo de paquete que acepta el endpoint asociado.

• Intervalo. Intervalo de transaccion, solo utilizable en los tipos que aplica.

typedef struct _usb_pipe_t

{

usb_xfer_type_t type;

usb_dir_t dir;

uint32_t length;

uint8_t* buffer;

uint8_t retries;

uint8_t handle;

uint8_t number;

uint8_t mps;

uint8_t interval;

} usb_pipe_t;

Listado 2: Estructure de los pipes de datos

41

4.3 Estructura Interna

Los pipes de mensajes deben almacenar el dispositivo al cual estan actualmente asignados.

Cuando se hace un pedido a traves de un IRP de control, el pipe asignado se bloquea para no

poder ser reasignado a otro pedido. Es importante saber a que dispositivo se asigno ya que si

ocurre la desconexion de un dispositivo en proceso de ser enumerado, se invocara el proceso

de desconexion y este necesita poder buscar dentro de los pipes de control al que este siendo

bloqueado por el dispositivo (en caso de haberlo) para poder liberarlo. De no realizarse esto,

el pipe quedarıa bloqueado indefinidamente.

typedef struct _usb_msg_pipe_t

{

uint8_t* buffer;

uint8_t stdreq[USB_STDREQ_SIZE];

uint8_t retries;

uint8_t handle;

uint8_t lock;

} usb_msg_pipe_t;

Listado 3: Estructure de los pipes de mensajes

Al iniciarse una transaccion con un pipe de control, se almacena el pedido estandar USB

dentro del buffer stdreq. Esto cumple tres funciones:

1. Que no sea necesario almacenar dicha informacion fuera.

2. Permite que los pedidos IRP reciban una estructura con los datos en lugar de un buffer,

en caso contrario habrıa que tener en cuenta que el compilador puede agregar padding

a la estructura y transferirla a un buffer manualmente.

3. Reordena el pedido en el formato utilizado por el bus USB (little-endian), lo cual es de

suma importancia para asegurar la portabilidad del stack y que fuera se pueda trabajar

directamente con la estructura de datos sin ser afectado por el orden de transmision de

estos.

Todos los demas elementos que describen a un endpoint que se encuentran presentes en

los pipes de datos pero no en los de control no son necesarios ya que sus valores pueden deter-

minarse implıcitamente. Las caracterısticas de estos endpoints son: tipo de Control, direccion

token, numero zero, el intervalo no se aplica, el MPS se almacena en el dispositivo y el largo

del buffer esta ya incluido en uno de los campos de stdreq.

4.3.2. Interfaces

La estructura de las interfaces es mas simple que aquella de los pipes. Los dos elementos

imprescindibles son el arreglo de endpoints y el identificador del driver asignado a la interfaz. Por

conveniencia tambien se incluye la informacion de clase, subclase y protocolo del dispositivo,

42

Tesis de Grado – Stack USB

estos datos pueden ser utiles en determinar la causa de que un dispositivo haya terminado en

estado de error. En esta interfaz se intercambian los terminos endpoints y pipes libremente ya

que, si bien conceptualmente son diferentes, el stack se comunicara con los endpoints a traves

de los pipes y, por lo tanto, la informacion contenida en ambos es la misma.

El arreglo de endpoints, como puede observarse en el listado siguiente, es constante. Todas

las estructuras de interfaces se inicializan estaticamente y tiene, por lo tanto, una serie de

pipes ya asignados a ellas, para mas detalles ver el capıtulo 5. Ademas, el protocolo cumple

una segunda funcion adicional que es determinar si la estructura de la interfaz ha sido asignada,

ver la seccion antes indicada para mas informacion.

typedef struct _usb_interface_t

{

usb_pipe_t*const endpoints;

usb_driver_handle_t driver_handle;

uint8_t class;

uint8_t subclass;

uint8_t protocol;

} usb_interface_t;

Listado 4: Estructura de las interfaces

El identificador de driver es el elemento mas importante de la interfaz, es la unica asociacion

entre el dispositivo almacenado en el USBD y los drivers que le corresponden a cada una de sus

interfaces. En la desconexion de un dispositivo se itera sobre todas sus interfaces y se anuncia

al driver correspondiente de dicho evento.

4.3.3. Dispositivos

La mayor parte del procesamiento del stack USB se encuentra asociado al manejo de cada

dispositivo. En consecuencia, tambien su estructura correspondiente es la mas compleja.

typedef struct _usb_device_t

{

usb_dev_state_t state;

usb_dev_state_t next_state;

usb_speed_t speed;

usb_interface_t* interfaces;

uint32_t status;

uint32_t err_status;

uint16_t ticket;

uint16_t vendor_ID;

uint16_t product_ID;

uint16_t ticks_delay;

#if (USB_MAX_HUBS > 0)

uint8_t parent_hub;

43

4.3 Estructura Interna

uint8_t parent_port;

#endif

uint8_t cte_index;

uint8_t max_power;

uint8_t addr;

uint8_t mps;

uint8_t cfg_value;

} usb_device_t;

Listado 5: Estructura de un dispositivo USB

El stack USB necesita una gran cantidad de informacion acerca de cada dispositivo para

poder administrarlo y configurarlo correctamente, incluso luego de la enumeracion al ser utili-

zado por los drivers. En primer lugar, es necesario almacenar el estado actual del dispositivo,

este es mas complejo que simplemente los estados posibles de un dispositivo como se ha defi-

nido en la especificacion USB ya que incluye todo el proceso de enumeracion. Esto se detalla

en el capıtulo 4.4.

Siguiendo la topologıa USB, cada dispositivo tiene un arreglo de interfaces asociadas a

este. La forma en que se inicializa y configura se describe en el capıtulo 5.

Hay otros elementos que se obtienen al inicializar el dispositivo, estos son:

• La velocidad, obtenida ya sea a traves del HCI o del driver HUB.

• Las coordenadas del dispositivo en la red USB, o sea, el HUB y puerto al que esta

conectado. Dado que el stack puede configurarse para soportar solo un dispositivo, la

compilacion de estos elementos es opcional.

• La direccion asignada en el proceso de enumeracion.

• El tamano maximo de paquete del endpoint de control (MPS).

• Valor de configuracion con el cual se ha configurado el dispositivo. De momento, una de

las limitaciones del stack es que solo permite utilizar la primer configuracion (1), por lo

que este miembro esta presente para su uso a futuro.

• Vendor ID y Product ID.

Durante el proceso de enumeracion se pueden dar varias situacion a contemplar. Algunos

estados requieren esperar cierta cantidad de tiempo (en general algunas centenas de milise-

gundos). El stack USB almacena los ticks transcurridos desde el arranque (ver capıtulo 4.3.4)

y cada dispositivo tiene un registro propio con el cual determinar la espera necesaria, en ticks,

para que transcurra el tiempo deseado. Otros estados realizan pedidos de IRPs de control,

para ello se debe almacenar el ticket correspondiente para poder consultar luego el estado, ver

seccion 4.6 para mas detalles sobre esto.

44

Tesis de Grado – Stack USB

Por ultimo, cada dispositivo posee varios bits que describen su situacion actual. El miembro

status contiene informacion acerca de la activacion del dispositivo, si esta siendo enumerado,

si ha finalizado la inicializacion, entre otros. Ademas, un segundo miembro err_status, en

caso de que el dispositivo termine en un estado de error, almacena el motivo de la falla. Cada

momento a lo largo del proceso de inicializacion y enumeracion que pueda fallar asigna un

valor diferente a err_status para facilitar su identificacion.

4.3.4. Stack USB

En la parte superior de la jerarquıa de estructuras se encuentra el contenedor principal del

stack USB. En este nivel el procesamiento a realizar es menor, se concentra principalmente en

ver si se ha conectado el dispositivo raız –aquel conectado al hardware e identificado a traves

del HCI–. En caso de haber una conexion se procede a actualizar todos los dispositivos y el

driver HUB. El stack puede estar en solo tres posibles estados:

1. IDLE. En espera de la conexion del dispositivo raız.

2. RUNNING. Estado general de procesamiento, aquı se actualizan los dispositivos y el

driver HUB.

3. SUSPENDED. Otra de las limitaciones del stack USB de momento es la falta de la

capacidad para ser suspendido en caso de no haber utilizacion del bus, a pesar de tener

dispositivos conectados. Este estado se encuentra para su uso a futuro.

typedef struct _usb_stack_t

{

usb_host_state_t state;

usb_msg_pipe_t def_ep[USB_N_CTRL_ENDPOINTS];

usb_device_t devices[USB_MAX_DEVICES];

uint32_t status;

uint16_t ticks;

uint8_t xfer_buffer[USB_XFER_BUFFER_LEN];

uint8_t xfer_length;

uint8_t n_devices;

} usb_stack_t;

Listado 6: Estructura principal del stack USB

Uno de los principales puntos de esta tesis es la utilizacion exclusiva de memoria estatica

para el stack USB. Por otro lado, una de las principales limitaciones del hardware USB en

microcontrolador es la cantidad de pipes que pueden alocarse. Para mejorar el uso de recursos

se ha decidido no asignar un pipe de mensajes al endpoint de control de cada dispositivo,

en cambio, se configurara el stack con una dada cantidad de pipes de control y todas las

operaciones que requieran de ellos (IRPs de control) deberan compartirlos. Es por esto que

45

4.4 Proceso de Enumeracion

todos los pipes de control se almacenan en esta estructura.

No limitar la cantidad de pipes de mensajes tiene dos desventajas importantes. En primer

lugar, es posible que el hardware no permita que todos los pipes sean utilizados como de

control, este es el caso del LPC4337 que solo admite dos. En caso de necesitar un pipe

por dispositivo se estarıa limitando tales microcontroladores a solo poder soportar la misma

cantidad de dispositivos como pipes de control. En segundo lugar, si el hardware admite que

todos los pipes sean de control, asignar uno por dispositivo serıa un mal uso de los recursos ya

que es un endpoint que se utiliza muy poco en comparacion con los de datos, incluso podrıa

no volver a utilizarse luego de la inicializacion.

En la configuracion del stack USB (ver capıtulo 5) se debe indicar la cantidad de pipes que

seran asignados a los de control. Luego, en la inicializacion del stack el host pedira a traves

del HCI todos los pipes especificados. En caso de haber un error de configuracion y querer

solicitar mayor cantidad que la soportada por el hardware, fallara la inicializacion y el stack

quedara bloqueado junto con un comentario explicando exactamente el problema. Entonces,

en la inicializacion el stack completara el arreglo de endpoints def_ep, esto es un proceso

que no puede fallar, y luego controlara su uso a traves de los IRPs.

La estructura del stack USB contiene un buffer para transferencias muy particular. Si bien

el stack se configura con un tamano adecuado para la configuracion de cada dispositivo, no

puede saberse a que dispositivo le corresponde hasta luego de haber interpretado parte del

descriptor de configuracion. Para solucionar este problema se utiliza un buffer comun a todos

los dispositivos, xfer_buffer, donde se almacena la informacion hasta poder determinar

a quien le corresponde. Es por ello, tambien, que dicho buffer puede limitarse a un tamano

pequeno (18 bytes), ya que se sabe exactamente que descriptores debe almacenar.

Utilizar un buffer comun trae una segunda consecuencia importante. Para reducir los recur-

sos necesario por el stack y simplificar el proceso de enumeracion se ha limitado dicho proceso

a solo un dispositivo a la vez. Esto significa que no es posible enumerar mas de un dispo-

sitivo en simultaneo, hay que esperar a que uno finalice su inicializacion antes de continuar

con el siguiente. Si bien esto agrega un retardo relativamente importante a la inicializacion y

configuracion de todos los dispositivos conectados –linealmente creciente con la cantidad de

dispositivos– no se lo considera un inconveniente ya que se realizara solamente en el arranque

del equipo. En caso de dispositivos conectados dinamicamente luego del arranque, tampoco

se lo considera un problema ya que solo se realizara una vez por cada conexion nueva.

4.4. Proceso de Enumeracion

Al conectarse un nuevo dispositivo USB este debe inicializarse y configurarse siguiendo una

serie especıfica de pasos, esto se lo conoce como el proceso de enumeracion. Dicho proceso

46

Tesis de Grado – Stack USB

esta definido por la especificacion USB 2.0, sin embargo, la forma en que se lleva a cabo es

dependiente de la implementacion del host en particular. El stack es notificado de este evento

de dos maneras, la primera es a traves de polling sobre el estado del dispositivo raız en el HCI

y la segunda es desde el driver HUB.

El proceso de enumeracion se encuentra gobernado por una extensa maquina de estados.

El largo de esta esta dado por las transacciones USB mas que por la complejidad ya que para

poder correr el stack USB en una sola tarea del sistema operativo y no depender de cambios en

el bajo nivel, todas las esperas y diversas consultas deben manejarse en estados independientes.

En la figura 8 puede observarse el diagrama de estados de los dispositivos. A continuacion se

describe este proceso en detalle, se utilizaran los nombres de los estados del diagrama para

facilitar el seguimiento.

1. Disconnected

En este estado se encuentran todos los dispositivos, para los cuales se ha configurado el

stack USB, en espera de una conexion.

2. Attached

Al detectarse una conexion, el dispositivo pasa al estado de “conectado” y esperara por

lo menos 100 ms antes de proseguir, para dejar que la lınea de alimentacion se estabilice.

3. Powered

Luego de estabilizar la alimentacion, el dispositivo pasa al estado de “alimentado”. En

este esperara a que el host libera la direccion 0 del bus de datos, o sea, que termine

de enumerar otros dispositivos. Una vez liberada la direccion 0, se bloquea nuevamente

para senalizar que el host se encuentra enumerando este dispositivo. Se ha limitado el

stack USB a enumerar solo un dispositivo a la vez.

4. Reset

El proceso de enumeracion comienza en este estado enviando un reset al dispositivo USB

de al menos 10 ms. Si el hardware del microcontrolador no limita la duracion del reset,

el host lo hara con una granularidad igual a los milisegundos por tick con los que se

haya configurado el stack.

Debe diferenciarse entre un reset manejado directamente por el hardware del microcon-

trolador y uno que deba pedirse a un HUB. El primer caso se da solamente para el

dispositivo raız. El segundo caso puede demorar considerablemente mas que el primero

ya que depende del uso que el HUB le este dando a su endpoint de control, las respuestas

a eventos propios tienen prioridad ante el pedido de reset.

5. Default, get speed

Luego de reiniciar el dispositivo por primera vez, se deben analizar las lıneas de datos

para determinar la velocidad de conexion, esta puede ser Low-Speed, Full-Speed o High-

Speed.

47

4.4 Proceso de Enumeracion

Figura 8: Maquina de estados del Host, por dispositivo

48

Tesis de Grado – Stack USB

6. Get MPS

El dispositivo recien reiniciado sabe que debera responder a la direccion 0 en el bus USB.

Como el host aun no conoce el MPS de los endpoints de control, se realiza un pedido

de los primeros 8 bytes del descriptor del dispositivo, la especificacion USB asegura que

el ultimo byte de estos 8 indicara el MPS. Se asume un MPS de 8 bytes para este pedido

inicial.

7. Reset

Para evitar cualquier inconveniente que pueda surgir al comunicarse con un dispositivo sin

conocer su MPS, se envıa un reset nuevamente. Las condiciones del tiempo de duracion

y el manejo por hardware o a traves de un HUB son las mismas que en el anterior.

8. Set Address

Inmediatamente despues del segundo reset, ya conociendo el MPS del endpoint de con-

trol, el host le asignara al dispositivo una direccion unica. Como internamente los dispo-

sitivos se almacenan en un arreglo estatico, asignarles una direccion es tan simple como

utilizar el ındice de cada uno (mas uno, pues la direccion 0 esta reservado para el estado

de Get MPS y el actual). Este pedido de control es el ultimo que se envıa a la direccion

0.

A pesar de la simplicidad en la asignacion de direcciones, es importante enfatizar que el

orden de conexion de los dispositivos no esta asegurado por la especificacion USB, sin

importar que siempre esten ubicados en los mismos puertos fısicos del microcontrolador

y HUBs. Esto significa que la asignacion de recursos no puede depender de la direc-

cion del dispositivo ni su ubicacion de almacenamiento interna, para mas detalles ver el

capıtulo 5.

9. Get Device Descriptor

En este estado se pide, espera y procesa el descriptor del dispositivo. Se obtiene el

VendorID y el ProductID, utilizados en el proceso de asignacion de drivers y recursos.

10. Get Config Descriptor’s first 9 Bytes

El descriptor de configuracion de un dispositivo depende de la cantidad y clase de inter-

faces, cantidad de endpoints, entre otros. Esto significa que no hay manera de conocer

su largo de antemano, este se encuentra dentro de los primeros 9 bytes del descriptor

(largo mınimo). Ademas, en estos primeros bytes, se obtiene la cantidad de interfaces

que componen al dispositivo. Estos dos valores clave mas los IDs obtenidos en el estado

anterior se utilizan para obtener la configuracion generada para el dispositivo (el arreglo

estatico de interfaces y endpoints y el buffer de configuracion), para mas detalles sobre

esto ver el capıtulo 5.

Este estado cumple una funcion fundamental en el uso de recursos estaticos para el

stack USB ya que antes de este punto no es posible conocer a que dispositivo se le debe

asignar cual configuracion de las generadas.

49

4.4 Proceso de Enumeracion

11. Get Config Descriptor

Una vez identificado el dispositivo dentro de las configuraciones disponibles y obtenido el

largo del descriptor de configuracion, se procede a pedir su totalidad. Este es el segundo

estado clave en el proceso de enumeracion, una vez obtenido el descriptor se prosigue

a validar cada una de las interfaces disponibles contra todos los drivers disponibles, al

encontrarse una coincidencia se asigna la interfaz al driver exitosos. De no poder ubicar

un driver adecuado, la interfaz se marca como “no disponible” y se continua con la

siguiente. Luego de asignar el driver correspondiente, se itera sobre todos los endpoints

de cada interfaz y se piden y configuran los recursos necesarios para cada pipe asociado.

En caso de fallar (por ejemplo, al conectar un dispositivo con mas endpoints de lo

esperado), se liberan todos los pipes asociados a la interfaz que ha fallado, pero igual

se prosigue con la siguiente en caso de que sea posible ser utilizada.

Al finalizar este proceso iterativo –asumiendo no han ocurrido errores– todas las interfaces

quedan asignadas a un driver y configuradas en su primer configuracion alternativa. Todos

los pipes asociados tambien estaran asignados y configurados.

El proceso de verificacion del dispositivo e interfaces es muy importante por dos motivos:

a. Proteger al stack USB contra la conexion de dispositivos inesperados pero simila-

res a los configurados. O sea, dispositivos que verifiquen como configurables pero

debido a tener caracterısticas diferentes fallen la enumeracion o requieran mayor

cantidad de recursos que la prevista.

b. Permitir que, en caso de una conexion inesperada, se desperdicie la menor cantidad

de recursos posibles con el fin de que los demas dispositivos (sı esperados) puedan

enumerar y funcionar correctamente.

12. Set Configuration

Para finalizar el proceso de enumeracion, se indica al dispositivo que utilice su primer

configuracion. El stack USB se ha limitado a solo permitir una posible configuracion por

dispositivo que es el caso mas general y comun. En caso de haber mas de una, el resto

se ignora.

13. Unlock Address

Por ultimo, se libera la direccion 0 para que el host pueda enumerar otros dispositivos

y se senaliza al dispositivo como “inicializado”, esto permite que los drivers asignados a

cada interfaz puedan comenzar a utilizarlas.

14. Configured

Finalmente, el dispositivo queda en el estado de “configurado” donde no realiza ninguna

accion, simplemente deja que los drivers asignados a cada interfaz se comuniquen a

traves de el.

15. Error

Todos los estados anteriores –a excepcion del primero– pueden fallar si se conecta un

50

Tesis de Grado – Stack USB

dispositivo diferente a la configuracion del stack (ver capıtulo 5) o, mas probablemente,

si hay un error de transmision o en el dispositivo conectado. En caso de falla, el dis-

positivo pasara directamente a este estado cancelando toda transferencia en progreso y

liberando al host para enumerar otros dispositivos. Ademas, se le asigna un codigo de

error apropiado en el miembro err_status de la estructura del dispositivo.

Uno de los ensayos realizados en este punto fue conectar un dispositivo a un HUB con un

puerto no funcional, conocido de antemano. Otro ensayo fue configurar incorrectamente

el largo de la configuracion, o sea, con un valor menor al adecuado. Para mas detalles

ver el capıtulo 6.

Se ha mencionado que una de las limitaciones del stack USB es no poder entrar en un

estado de suspension cuando los dispositivos no utilizan el bus de datos. Esta limitacion se

aplica tambien a los dispositivos, no se ha implementado la capacidad de reconocer que el

dispositivo a entrado en el estado de suspension. Sin embargo, el estado se ha creado y se

encuentra disponible para su uso a futuro.

En la figura 9 se muestra el diagrama de secuencia asociado al proceso de enumeracion. Se

han indicado que eventos corresponden a que estados de la figura 8. Ademas, se han detallado

ciertas acciones que no se pueden observar en el diagrama de estados:

• Al conectarse un dispositivo el host debe buscar una posicion libre en su arreglo interno

de dispositivos. Ya que el orden de conexion no esta asegurado por la especificacion USB,

ni siquiera al mantener la red de dispositivos, es importante tener en cuenta que no puede

dependerse del ındice de un dispositivo para asociarlo a las configuraciones generadas a

partir del archivo de configuracion. Por ello es que la configuracion se obtiene recien en

el estado Get Config Descriptor’s first 9 bytes.

Tambien es posible que los dispositivos se desconecten y conecten en forma completa-

mente impredecible, por lo que el host debe poder tratar con ellos en cualquier posicion

y que esto sea dinamico.

• El bloqueo de la direccion 0 hacia el host.

• El proceso, simplificado, de obtencion de la configuracion del dispositivo, aquella gene-

rada a partir del archivo de configuracion.

El proceso de asignacion de drivers se explica con mas detalles en el capıtulo 4.5.

4.5. Asignacion de Drivers

Durante el proceso de enumeracion llega el momento en que el host debe interpretar las

distintas interfaces de un dispositivo. Para cada una de ellas, debera asignarle un driver respon-

51

4.5 Asignacion de Drivers

Figura 9: Secuencia de enumeracion

52

Tesis de Grado – Stack USB

Figura 9: Secuencia de enumeracion (cont.)

sable de administrarla y configurarla, es a traves de este que el codigo usuario se comunicara

con las diferentes funciones del dispositivo.

El controlador de drivers utiliza un arreglo estatico de entradas. Cada entrada corresponde

a un driver diferente y se compone de los siguientes elementos:

• Vendor y Product ID

Aquı pueden darse dos situaciones, si el driver es especıfico para un vendedor o producto

(o ambos) particular debe especificarse aquı su identificador. En caso contrario, se utili-

zara el valor 0xFFFF para indicar que el driver es independiente del ID.

Si se considera necesario puede especificarse mas de un driver para la misma clase, uno

general y varios particulares segun el ID de vendedor y/o producto, en tal caso se deben

colocarse primero en el arreglo los particulares.

• probe

Este metodo es invocado por el host una vez por cada interfaz, debe determinar si

dicha interfaz puede ser controlada por el driver. Por ejemplo, en el caso de un HUB se

verificara la clase, subclase y cantidad de endpoints.

• assign

Si el metodo probe resulta exitoso, el host asignara el driver a la interfaz actual. En la

asignacion se indica al driver el stack USB al cual corresponde la interfaz y se entregara

un identificador que identifica el par dispositivo/interfaz.

53

4.5 Asignacion de Drivers

• remove

Al desconectar un dispositivo se invoca esta funcion para todos los drivers que lograron

ser asignados, esto notifica a cada driver que se ha producido una desconexion y debe

eliminar la asignacion correspondiente.

A continuacion se listan los prototipos de las entradas de drivers, seguido del arreglo

utilizado en el stack con soporte para HUBs y dispositivo HID. Se han configurado ambos

drivers para no depender de un ID de producto o vendedor.

typedef int (*usb_fcn_probe_t)(

const uint8_t* buffer,

uint16_t len

);

typedef int (*usb_fcn_assign_t)(

usb_stack_t* pstack,

uint16_t id,

const uint8_t* buffer,

uint16_t length

);

typedef int (*usb_fcn_remove_t)(

usb_stack_t* pstack,

uint16_t id

);

typedef struct _usb_driver_t

{

const uint16_t vendor_ID;

const uint16_t product_ID;

const usb_fcn_probe_t probe;

const usb_fcn_assign_t assign;

const usb_fcn_remove_t remove;

} usb_driver_t;

Listado 7: Estructura de las entradas en el arreglo de drivers

static const usb_driver_t usb_drivers[USB_MAX_DRIVERS] =

{

#if (USB_MAX_HUBS > 0)

{ /* HUB */

USB_FORCE_PROBING_ID,

USB_FORCE_PROBING_ID,

usb_hub_probe,

usb_hub_assign,

usb_hub_remove

},

#endif

{ /* HID */

54

Tesis de Grado – Stack USB

USB_FORCE_PROBING_ID,

USB_FORCE_PROBING_ID,

usb_hid_probe,

usb_hid_assign,

usb_hid_remove

},

};

Listado 8: Ejemplo del arreglo de drivers

La figura 10 ilustra, en forma simplificada, la secuencia de asignacion de drivers. El proceso

comienza y termina en el USBD. Notar que la creacion de los pipes correspondientes a los

endpoints de cada interfaz se lleva a cabo por el host y no el driver. Es aquı donde se valida

la disponibilidad de endpoints y que puedan ser configurados como lo indica la interfaz. Esto

es importante ya que, como se ha mencionado antes, es posible que un usuario no conecte el

dispositivo para el cual se ha configurado el stack y, por lo tanto, cualquier punto del proceso

de enumeracion puede fallar.

Asignación de drivers

Para cada endpoint

Para cada interfaz

Figura 10: Secuencia de asignacion de driver

55

4.6 IO Request Packets – IRPs

Es posible que una interfaz no pueda ser validada ante ningun driver o que el driver no

pueda ser asignado dicha interfaz. Esto presenta un punto muy importante a tener en cuenta

sobre el stack USB. Esta tesis se enfoca en el uso de memoria estatica, sin embargo, la principal

cualidad de un sistema USB es el dinamismo. Esto significa que si bien es posible configurar

el stack exactamente con los dispositivos que se van a conectar, es completamente posible (y

probable) que se conecte algo fuera de lo esperado. Ademas, un usuario puede esperar que sea

posible conectar una clase de dispositivo y no un modelo especıfico, por ejemplo un mouse

generico en lugar de un modelo y marca en particular.

En caso de no poder asignarse una interfaz, esto quedara indicado en driver_handle

en la estructura correspondiente. Sin importar esto, el resto de las interfaces continuaran con

su asignacion. Esto es importante ya que un dispositivo puede tener varias funcionalidades –y

por lo tanto interfaces– diferentes, mientras que el usuario puede estar interesado en acceder

solo a una de estas y no desperdiciar los recursos necesarios para implementar los drivers del

resto.

4.6. IO Request Packets – IRPs

Para comunicarse con los dispositivos USB conectados al bus, los drivers (incluido el de

HUB) y el host deberan acceder a este a traves del USBD con un protocolo determinado:

pedidos de paquetes de entrada o salida de datos, IRPs. La interfaz se ha explicado en el

capıtulo 4.2. A continuacion se listan los prototipos de los metodos correspondientes.

int usb_irp(

usb_stack_t* pstack,

uint16_t device_id,

uint8_t pipe,

uint8_t* buffer,

uint32_t len

);

int usb_ctrlirp(

usb_stack_t* pstack,

uint16_t* ticket,

uint16_t device_id,

const usb_stdreq_t* pstdreq,

uint8_t* buffer

);

int usb_irp_status(

usb_stack_t* pstack,

uint16_t device_id,

uint16_t irp_id

);

int usb_irp_cancel(

usb_stack_t* pstack,

uint16_t device_id,

56

Tesis de Grado – Stack USB

uint16_t irp_id

);

int usb_ctrlirp_bypass(

usb_stack_t* pstack,

uint16_t* ticket,

uint16_t device_id,

const usb_stdreq_t* pstdreq,

uint8_t* buffer

);

Listado 9: Interfaz IRP del USBD

Los primeros dos metodos usb_irp() y usb_ctrlirp() se utilizan para iniciar trans-

ferencias de datos y control, respectivamente, sobre el bus USB. La informacion de dispo-

sitivo –con su direccion asociada–, numero de endpoint y datos del pipe se indexan con el

device_id y el pipe, en el caso de una transferencia de control el pipe es implıcito.

Las IRP de control requieren ciertas consideraciones extras. En primer lugar, como se ha

visto en el capıtulo 4.3, no se crea un pipe de control por dispositivo, por lo tanto es necesario

obtener un pipe de control disponible para poder ejecutar la IRP. De no haber uno disponible,

se retornara del metodo con un codigo de espera, esto no puede suceder en las transferencias

de datos ya que estos pipes si se han asignado en la enumeracion. Como se desconoce el pipe

utilizado hasta luego de hecho el pedido, la funcion retorna un ticket con el cual el responsable

de dicha transaccion podra luego consultar el estado.

Por otro lado, como los drivers son asignados a cada dispositivo antes de que este termine

la enumeracion, es necesario validar que esta haya finalizado antes de permitir un pedido de

IRP de control. El host es el unico que conoce el estado de este proceso y por ello, para

evitar validaciones innecesarias, acelerar los pedidos y poder adelantarse a la finalizacion de la

enumeracion, utiliza el metodo usb_ctrlirp_bypass().

Ademas, como las transferencias de control tienen un formato especificado, se agrega como

parametro la estructura misma de un pedido estandar USB de control. Esta estructura se debe

inicializar fuera antes de llamar a la funcion, luego esta se encargara de convertir los miembros

al formato adecuado (recordar que USB utiliza el formato little-endian). A continuacion se

incluye un ejemplo, es el fragmento de codigo utilizado en el driver HUB para obtener el

estado de un puerto (aclaracion: el siguiente fragmento de codigo es la union de dos funciones para

simplificar el ejemplo y ayudar a la claridad):

static int _GetPortStatus( usb_hub_t* phub, uint8_t port )

{

int status;

usb_stdreq_t stdreq;

stdreq.bmRequestType = USB_STDREQ_REQTYPE(

USB_DIR_IN,

57

4.7 Driver HUB

USB_STDREQ_TYPE_CLASS,

USB_STDREQ_RECIP_OTHER

);

stdreq.bRequest = USB_HUB_CLASSREQ_GET_STATUS;

stdreq.wValue = 0;

stdreq.wIndex = port+1; /* HUB port indices start at 1, not 0 */

stdreq.wLength = USB_HUB_PORT_STATUS_LENGTH;

status = usb_ctrlirp(

phub->pstack,

&phub->ticket,

phub->id,

&stdreq,

phub->buffer

);

...

}

Listado 10: Ejemplo de IRP de control

El metodo de consulta de estado de una transaccion es unico. Internamente se distingue

entre aquellas de control y de datos con el ticket, las de datos deben utilizar el numero de

endpoint como ticket. En caso de haber un error en la transmision, internamente el host se

encarga de repetir el pedido hasta tres veces. Antes de reintentar un pedido se debe cancelar

el anterior. Las transacciones en endpoints isocronos no deben repetirse, sin embargo, el host

no debe realizar ninguna atencion especial para ellas ya que la indicacion de error (condicion

de HALT) que indica la falla no esta permitida en tales endpoints.

El ultimo metodo expuesto por esta interfaz, usb_irp_cancel(), se utiliza para cance-

lar una transaccion que aun no ha finalizado. Es el mismo utilizado al reintentar una transmi-

sion. En general, no deberıa haber motivo para utilizarlo, todas las situaciones que lo requieren

son manejadas dentro del host.

4.7. Driver HUB

Los HUBs son uno de los componentes mas importantes de la red USB. Su funcion es

expandir la cantidad de puertos y, por lo tanto, el numero de dispositivos que pueden conectarse

a la vez. Al conectar un HUB al host se inicializa, enumera y asigna un driver como cualquier

otro dispositivo. Luego, el driver HUB es quien se encarga de realizar la configuracion inicial

del dispositivo como HUB y su administracion a lo largo de la vida del sistema.

58

Tesis de Grado – Stack USB

4.7.1. Estados y Procesamiento de Datos

Los HUBs notifican al host de cambios en el estado del dispositivo o de alguno de sus

puertos a traves del endpoint de interrupcion. Se recibe un mapa de bits con la estructura

ilustrada en la figura 11.

Figura 11: Mapa de bits de la notificacion de cambio de estados de un HUB

Fuente: Especificacion USB 2.0, seccion 11.12.4, figura 11-22 – Hub and Port Status Change Bitmap

Se ha utilizado una maquina de estados implementada de forma muy similar a la del host.

Es ligeramente mas complicada ya que se reutilizan ciertos estados para tareas similares que se

realizan ante distintos eventos y ası evitar repetir codigo. Por ello, algunos estados se relacionan

de forma mas compleja y no siguen una secuencia puramente lineal. En la figura 12 se muestra

el diagrama de estados correspondiente y en la figura 13 se muestra el diagrama de secuencia

asociado. Se han indicado que eventos corresponden a que estados entre ambos diagramas y,

en el segundo, se han incluido algunos detalles extra que no corresponden en el primero.

A continuacion se explican brevemente los distintos estados:

1. Idle

Todos los HUBs, para los cuales se ha configurado el stack USB, se encuentran en espera

de la asignacion de una interfaz. Una vez asignada la interfaz se espera a que se libere el

dispositivo ya que el proceso de enumeracion no termina hasta que el host haya asignado

una configuracion al dispositivo.

2. Get HUB Descriptor

Se pide el descriptor de HUB, este es de largo variable segun la cantidad de puertos del

59

4.7 Driver HUB

Figura 12: Maquina de estados del driver HUB

60

Tesis de Grado – Stack USB

Figura 13: Secuencia de procesamiento del driver HUB

61

4.7 Driver HUB

Figura 13: Secuencia de procesamiento del driver HUB (cont.)

HUB. Se pide por primera vez con el largo mınimo y se obtiene la cantidad de puertos,

de no ser suficiente se pedira una segunda vez con el largo adecuado.

3. Get HUB Status

Se obtiene el estado del HUB, de este se puede obtener el estado de la alimentacion y

si hay condicion de sobre-corriente. Este estado se utiliza en dos momentos diferentes:

a. En la inicializacion para obtener el estado inicial de HUB.

b. Cuando el HUB se encuentra corriendo y se detecta un cambio en la condicion del

HUB en el estado de Update Status.

4. Power Up

Se realiza un pedido de SetPortFeature para encender un puerto del HUB. Esto se repite

para cada uno de los puertos detectados anteriormente.

62

Tesis de Grado – Stack USB

5. Get Port Status

Una vez encendidos todos los puertos, se pide el estado de cada uno. De este se puede

obtener toda la informacion pertinente a cada uno: estado de conexion de un dispositivo,

habilitacion del puerto, sobre-corriente, progreso de reset del puerto, estado de la ali-

mentacion y velocidad del dispositivo conectado. Este estado se utiliza en dos momentos

diferentes:

a. En la inicializacion para obtener el estado inicial de cada puerto, luego de encen-

derlos.

b. Cuando el HUB se encuentra corriendo y se detecta un cambio en la condicion del

puerto del HUB en el estado de Update Status.

6. Running

Una vez finalizada la inicializacion el HUB pasa al estado de funcionamiento normal. Aquı

se realizan pedidos a traves del pipe asociado al endpoint de interrupcion del HUB con

un perıodo segun se haya especificado en la configuracion del endpoint, con granularidad

en ticks. Si se recibe respuesta significa que ha habido un cambio en el HUB y se pasa al

estado siguiente para su interpretacion. En caso contrario, el HUB no ha sufrido ningun

cambio y no posee respuesta para reportar, se utiliza este tiempo para revisar si el host

ha pedido el reset de algun puerto y pasar al estado Reset Port en caso afirmativo. Como

puede verse, los cambios del HUB tienen prioridad sobre los pedidos de reset, esto puede

causar que se retrasen ante otros eventos y se extienda el proceso de enumeracion.

El tiempo de duracion del reset de cada puerto es controlado por el HUB. El driver es

notificado a traves del endpoint de interrupcion cuando este tiempo finaliza.

7. Update Status

En este estado se toma el mapa de bits obtenido en el estado anterior (ver figura 11) y

se determina que cambios han ocurrido y a si le corresponden al HUB, puertos o ambos.

Se pueden dar dos situaciones:

a. En caso de haber un cambio en el estado general del HUB se procede a pedir el

estado del HUB en Get HUB Status y luego al estado HUB Status Clear para

limpiar dicho bit.

b. De ser un cambio en el estado de uno o mas puertos se realiza el mismo proceso

solo que utilizando los estados analogos para puertos: Get Port Status y Port Status

Clear.

Se volvera a este estado hasta que no haya mas cambios que interpretar.

8. HUB Status Clear

Se hace un pedido al HUB de ClearHubFeature para indicar que el host ha sido notificado

de los cambios.

Este pedido se repite una vez por cambio.

63

4.7 Driver HUB

9. Port Status Clear

Se hace un pedido al HUB de ClearPortFeature para indicar que el host ha sido notificado

de los cambios. Hay dos cambios en particular para los cuales se deben realizar acciones

extra:

a. Estado de reset del puerto. Cuando el host pide al driver HUB que se reinicie un

puerto, la finalizacion de dicho reset se notifica con este cambio.

b. Estado de conexion del puerto. El HUB utilizara este evento para notificar al host

de conexiones o desconexiones de dispositivos.

Este pedido se repite una vez por cambio.

10. Reset Port

Se hace un pedido al HUB de SetPortFeature para comenzar un reset del bus USB en

el puerto especificado. La duracion del reset es controlada por el HUB y notificara al

host de su finalizacion a traves del endpoint de interrupcion, como se ha explicado en

el estado Running.

4.7.2. Estructura del HUB

La estructura de los HUBs requiere almacenar bastante informacion. El siguiente listado

muestra la estructura de datos utilizada:

typedef struct _usb_hub_t

{

usb_stack_t* pstack;

usb_hub_state_t state;

uint32_t status;

uint16_t id;

uint16_t ticket;

uint16_t interval;

uint16_t wait_count;

uint16_t port_status[USB_MAX_HUB_PORTS];

uint8_t port_change[USB_MAX_HUB_PORTS];

uint8_t poweron_t;

uint8_t power_req;

uint8_t n_ports;

uint8_t current_port;

uint8_t buffer[USB_HUB_BUFF_LEN];

uint8_t buffer_len;

uint8_t sc_bitmap[USB_HUB_SC_BITMAP_LEN];

} usb_hub_t;

Listado 11: Constantes de configuracion estatica del stack USB

A continuacion se explican brevemente los miembros de la estructura:

64

Tesis de Grado – Stack USB

• Puntero al stack USB que asigno la interfaz al driver, a traves de este se realizan los

pedidos de IRPs y notificaciones de conexion, desconexion y resets.

Este elemento se ha incluido para facilitar la expansion del stack USB a futuro. En caso

de utilizar un microcontrolador con mas de un controlador USB se podra utilizar el mismo

driver HUB para todos los dispositivos conectados en cualquiera de los controladores ya

que cada HUB posee la informacion del stack USB que asigno la interfaz.

• Estado del HUB, como se ha descripto en la seccion anterior.

• Ticket asociado al pedido IRP de control en curso, de suma importancia ya que estos se

realizan constantemente en la administracion del HUB.

• Identificador del dispositivo en el stack USB, o sea, las coordenadas dispositivo/interfaz

obtenidas en la asignacion de driver.

• Perıodo en ticks para realizar pedidos al endpoint de interrupcion, junto con el elemento

asociado que cuenta el tiempo transcurrido.

• Estado actual y de cambio de cada puerto.

• Tiempo de estabilizacion de lınea de los puertos y alimentacion maxima requerida por

el HUB. De momento una limitacion del stack USB es no utilizar estos parametros, sin

embargo, estan presentes y son inicializados para permitir ser incluidos en el futuro.

• Numero de puertos. Esta variable es importante ya que para los HUBs se ha optado

por elegir con una macro del pre-procesador C cuantos puertos maximos soportan, esto

significa que puede conectarse un HUB con menor cantidad de puertos y debe poder ser

utilizado.

• Puerto actual sobre el cual se esta operando. El analisis de cambios en el estado de

los puertos y la administracion de puertos del HUB pueden requerir varios pedidos de

control y, por lo tanto, extenderse sobre varios estados. Debido a esto, es necesario poder

almacenar sobre que puerto se esta actualmente trabajando.

• Buffer de control y su largo. Los pedidos de control que requieren recibir datos utilizan

este buffer para su almacenamiento, principalmente aquellos de estado del HUB y sus

puertos.

• Mapa de bits. Al recibir un reporte de estado desde el endpoint de interrupcion del HUB

se almacenara el mapa de bits resultante en este buffer. No es posible mantenerlo en el

buffer de control ya que el procesamiento del mapa requiere varios pedidos de control y

se perderıa la informacion. En general no supera un byte de largo.

65

4.8 Documentacion

4.8. Documentacion

La documentacion del codigo se ha integrado en el codigo fuente a traves de comentarios

como lo especifica el generador de documentacion Doxygen. A modo de ejemplo, a conti-

nuacion se incluye la documentacion del prototipo del metodo de asignacion de driver y luego

el resultado al generar el pdf correspondiente:

/**

* @brief Assign interface to driver.

*

* Once a valid driver has been found for a given interface (through the

* @ref usb_drivers_probe method), the driver should be notified of a new

* interface being assigned to it. During probing certain descriptors might

* have been ignored to determine a valid driver, because of this the

* buffer containing the same interface descriptor used for probing should

* be once again passed down to the driver for a more thorough parsing.

*

* In addition, the driver should be notified of the USB stack assigning

* the interface and a proper identification for the device/interface pair.

*

* @param pstack Pointer to USB stack owner of the interface being assigned

* @param id Identification of device/interface pair within USB stack.

* @param buffer Buffer containing the entire interface descriptor.

* @param length Buffer’s length.

* @param handle Driver to which the interface is being assigned to.

*

* @return -1 if driver could not be assigned, 0 on success.

*/

int usb_drivers_assign(

usb_stack_t* pstack,

uint16_t id,

const uint8_t* buffer,

uint16_t length,

usb_driver_handle_t handle

);

Listado 12: Documentacion en comentarios de los prototipos de asignacio de drivers

66

Tesis de Grado – Stack USB

Figura 14: Ejemplo de documentacion generada a traves de Doxygen

67

Capıtulo 5

Configuracion del Stack USB

Este capıtulo describe la configuracion del stack USB. Se plantea el metodo

de configuracion elegido y como este influye en el cumplimiento de los principales

objetivos de la tesis, el uso de memoria estatica y soporte para multiples dispositi-

vos. Se detallan las dos etapas de configuracion del stack USB, aquella que ocurre

al momento de la compilacion y aquella que requiere de un script generador de

codigo con las estructuras de datos adecuadas.

Tesis de Grado – Stack USB

5. Configuracion del Stack USB

En esta seccion se describe la forma de configuracion del stack USB. Esto es fundamental

para poder asignar recursos estatica y eficientemente, de utilizarse simplemente macros del

pre-procesador C no se podrıa configurar cada dispositivo en forma independiente.

La configuracion se separa en dos partes, la primera utiliza un encabezado en C para

definir ciertos parametros simples. La segunda es mas compleja, esta utiliza un archivo de

configuracion para generar codigo en C a traves de un script, se explicara en detalle mas

adelante. El motivo de la separacion es no tener que regenerar el codigo de configuracion si

solamente se necesita cambiar parametros que no lo afectan.

Ambas partes de la configuracion se procesan luego por un segundo encabezado que se

encarga de validar los parametros y no permitir la utilizacion de valores invalidos entre sı. Por

ejemplo, no es posible configurar soporte para un solo dispositivo USB y, al mismo tiempo,

habilitar el soporte de HUBs pues claramente no tendrıa sentido conectar un HUB como

dispositivo unico. Si bien es una situacion logicamente valida, si solo se requiere un unico

dispositivo USB es conveniente no reservar recursos para un HUB y solo permitir drivers de

otros dispositivos.

La cantidad de parametros que pueden validarse en tiempo de compilacion es reducida.

Esto se debe a que la mayor parte de la configuracion se centra en la de cada dispositivo y

esto varıa considerablemente entre las distintas clases. Por otro lado, es mas simple, sencillo y

versatil validar el archivo de configuracion con el script que lo procesa en lugar de utilizando

el pre-procesador de C.

5.1. Encabezado de Configuracion

El encabezado de configuracion usb_cfg.h contiene los siguientes parametros:

• Perıodo de la tarea USB en milisegundos

Indica cuanto tiempo trascurre entre ticks del sistema USB.

Es muy importante que este valor se ajuste segun las necesidades del usuario. Si se utiliza

un valor elevado es posible que el stack USB no pueda realizar transacciones a la velocidad

requerida por el endpoint de un dispositivo y se pierdan datos. Para ello hay que tener en

cuenta que el USBD permite realizar un IRP por pipe por ciclo de ejecucion y la cantidad

de datos que este puede transferir o recibir dependera exclusivamente del endpoint del

dispositivo conectado, en particular del MPS e intervalo de peticion de datos. Ademas,

el MPS e intervalo pueden estar limitados por el hardware del microcontrolador o los

drivers de bajo nivel (HCD).

71

5.1 Encabezado de Configuracion

• Maxima cantidad de HUBs soportada

Es posible luego conectar menos de lo indicado pero esto no se recomienda para aprove-

char mejor los recursos. Este parametro puede valer 0, sin embargo, el stack solo podra

soportar un dispositivo de esta manera.

De configurarse para un solo dispositivo se quitaran todos los recursos necesarios para

el soporte de HUBs. Esto incluye el driver, la entrada del driver en la asignacion de

interfaces y los datos almacenados por el stack sobre la estructura de la red USB para

cada dispositivo.

• Maxima cantidad de puertos por HUB

Indica el numero maximo de puertos que soporta cada HUB, no es necesario que tengan

esta cantidad.

Se evaluo si incluir este parametro en el archivo de configuracion, pero dado que cada

puerto extra soportado solo requiere 3 bytes adicionales de espacio por HUB no se

considero conveniente teniendo en cuenta la complejidad de incluir el codigo generado

en la configuracion.

• Cantidad de endpoints de control

Este parametro es de suma importancia, le indica al host cuantos pipes de control pedir

al HCI en la inicializacion del stack. Debe utilizarse un valor apropiado para el hardware

por lo que no puede ser generico y debe configurarse acordemente, la unica excepcion

es que se utilice solamente un pipe de control.

Utilizar uno solo pipe implica un proceso mas lento de enumeracion y configuracion de

los dispositivos, sin embargo, es conveniente en el caso de necesitar los pipes para otro

uso. Este valor no puede superar el maximo permitido por el hardware, por ejemplo 2

en el LPC4337, de lo contrario fallara la inicializacion del stack USB.

El tiempo extra que se agrega al reducir la cantidad de pipes de control afectara al stack

USB en solo tres situaciones:

1. La enumeracion, ya que mientras se enumera un dispositivo otros ya inicializados

pueden necesitar utilizar su endpoint de control.

2. En la configuracion, cada driver asociado a cada interfaz de los distintos dispositivos

realiza la configuracion inicial de los mismos. Al haber menos pipes de control el

uso compartido de los recursos causara que haya mas esperas.

3. La administracion de los HUBs. Cada vez que haya un cambio de estado en un

HUB o uno de sus puertos el driver HUB debe realizar una transaccion de control

indicando que ha sido notificado de dicho evento.

Dependiendo de como se configure el stack USB el efecto de este parametro tendra

distintas consecuencias. Por ejemplo, si es necesario configurar varios HUBs no es reco-

mendable que solo se utilice un pipe de control ya que debera ser compartido constante-

mente por varios dispositivos. Por otro lado, si solo se tendra un HUB USB, es probable

que no sea necesario mas de un pipe de control ya que las esperas introducidas seran

72

Tesis de Grado – Stack USB

mayormente en la inicializacion y no durante la vida de los dispositivos.

Las consecuencias de este parametro tambien dependeran de la configuracion del perıodo

de la tarea USB. Una dada cantidad de pipes puede ser suficiente si se tiene un perıodo

adecuadamente corto o insuficiente si la tarea USB se ejecuta con baja frecuencia.

Es importante que el usuario analice las condiciones particulares de su situacion para

determinar estos parametros.

A continuacion se listan las macros definidas en el encabezado de configuracion con uno

de los sets de valores utilizados para ensayar el stack USB.

#define USB_TASK_TICKS 50

#define USB_MAX_HUBS 2

#define USB_MAX_HUB_PORTS 7

#define USB_N_CTRL_ENDPOINTS 2

Listado 13: Constantes de configuracion estatica del stack USB

El ejemplo anterior configura al stack USB para ejecutar su tarea cada 50 ms, soportar un

maximo de dos HUBs con hasta 7 puertos cada uno y se indica al stack que pida al HCI en la

inicializacion los recursos correspondientes a dos pipes de control.

La cantidad de dispositivos por driver se configura en el encabezado correspondiente

de cada driver. Por ejemplo, para los dispositivos HID se ha configurado en el encabezado

drivers/usb_hid.h un maximo de uno. Como ya se ha explicado, el HUB es un caso

especial y por ello se encuentra junto con la configuracion del stack USB.

5.2. Archivo de Configuracion

La configuracion principal del stack USB se realiza a traves de un archivo de configuracion.

Esto es lo que permite un uso eficiente de los recursos del sistema utilizando diferente cantidad

de elementos para cada dispositivo e interfaz del sistema, de otra manera todos los dispositivos,

interfaces y pipes estarıan configurados por igual.

El script de procesamiento del archivo de configuracion se ha implementado separado del

de configuracion del sistema operativo de la CIAA. Por simplicidad se ha implementado en un

lenguaje diferente (en lua) y se encuentra asociado explıcitamente al modulo USB. Quedara

pendiente como mejora futura a realizar sobre el stack USB la integracion del mismo a la

configuracion general del CIAA –con su correspondiente archivo de configuracion oil– y su

implementacion en php.

El archivo de configuracion debe respetar una simple estructura determinada. La composi-

cion de cada entrada del archivo se lista a continuacion seguido de un ejemplo de configuracion

para dos HUBs, un mouse y una camara web.

73

5.2 Archivo de Configuracion

<Identificador> = {

[VendorID = <ID del vendedor>,]

[ProductID = <ID del producto>,]

[CfgDescLen = <largo del descriptor de configuracion>,]

Interfaces = {

<Identificador de interfaz 0> = <cantidad de endpoints>,

<Identificador de interfaz 1> = <cantidad de endpoints>,

...

}

}

Listado 14: Composicion de las entradas del archivo de configuracion

1 USBStack = {

2 Mouse = {

3 VendorID = 0x046D,

4 ProductID = 0xC247,

5 CfgDescLen = 34,

6 Interfaces = {

7 iface0 = 1

8 }

9 },

10 Webcam = {

11 VendorID = 0x046D,

12 ProductID = 0x0825,

13 CfgDescLen = 2466,

14 Interfaces = {

15 iface0 = 1,

16 iface1 = 0,

17 iface2 = 1,

18 iface3 = 0

19 },

20 },

21 HUB1 = {

22 CfgDescLen = 25,

23 Interfaces = {

24 iface0 = 1

25 }

26 },

27 HUB0 = {

28 CfgDescLen = 41,

29 Interfaces = {

30 iface0 = 1

31 }

32 }

33 }

Listado 15: Estructura de configuracion estatica del stack USB

Los elementos entre < > son los configurables por el usuario. Los elementos entre [ ]

74

Tesis de Grado – Stack USB

son opcionales, pero el valor por defecto puede no ser el adecuado para el dispositivo por lo

que no es recomendable depender de este.

Los elementos que componen cada entrada configuracion se detallan a continuacion.

• VendorID y ProductID

Igual que como se ha explicado en la asignacion de drivers (capıtulo 4.5), estos identifi-

cadores pueden tomar un valor entre 0x0000 y 0xFFFF, donde este ultimo indica que

el dispositivo puede asumir cualquier valor de vendedor y/o producto.

• Largo del descriptor de configuracion

Indica el tamano del buffer que requiere el dispositivo para poder almacenar dicho des-

criptor. Este parametro es primordial para poder enumerar dispositivos con largos des-

criptores de configuracion por dos motivos. Primero, la especificacion USB indica que los

descriptores de interfaz, endpoints y demas que se transmiten junto con el de configu-

racion no pueden obtenerse por separado y, ademas, un descriptor no puede pedirse en

secciones. Esto significa que es necesario poder obtener del dispositivo todo el descriptor

de configuracion entero. En segundo lugar, si este descriptor fuera corto no serıa proble-

ma tomar el valor maximo y asignarlo por igual a todos los dispositivos, sin embargo,

hay casos (por ejemplo la camara web) cuyo largo es varias veces mayor al resto y serıa

un desperdicio de memoria.

Al enumerar los dispositivos se almacena su descriptor de configuracion. Sucede que cuan-

do se requiere luego configurar una interfaz a traves del driver o esta permite cambiar su

configuracion como es el caso de la resolucion en una camara web, de no almacenar el

descriptor habrıa que repetir el pedido con cada nuevo evento. Esto es una carga sobre

los pipes de control, en particular en aquellos que deban procesar largos descriptores y,

por otro lado, harıa que haya mayores tiempos de espera para el codigo usuario cada vez

que se requiera un cambio.

De momento, el almacenamiento de todos los descriptores de configuracion se considera

una limitacion del stack USB. Para mejorar aun mas el uso de memoria un cambio a

futuro serıa indicar junto con este elemento si es necesario o no almacenar tales datos

y luego determinar que buffer de datos utilizara el dispositivo en su enumeracion y con-

figuracion. Esto no es un cambio trivial ya que, al compartir recursos, el host debera a

arbitrar todos los pedidos de drivers que requieran acceso a estos buffers.

• Arreglo de interfaces

Cada dispositivo requiere que se especifique cuantas interfaces lo componen y cuantos

endpoints utiliza cada una de estas. La cantidad de endpoints a configurar es la maxima

que puede llegar a requerir una interfaz, esto es ası ya que en sus distintas configuraciones

alternativas es posible que utilice un numero distintos de endpoints.

• Identificadores

Cada dispositivo e interfaz puede ser asignado un nombre unico. Este no tiene efecto

75

5.3 Asignacion de Interfaces

alguno sobre el codigo generado, su utilidad es simplemente ayudar a la visibilidad.

La configuracion del stack USB no es simple. Si bien los parametros permitidos son pocos,

es necesario conocer la estructura del dispositivo que se desea conectar. Por ejemplo, uno de los

ensayos del stack USB utilizo un HUB de 10 puertos, resulta ser que este esta implementado

como 2 HUBs en cascada de 7 y 4 puertos. De no conocer este detalle, el archivo de confi-

guracion indicarıa solo un HUB y fallarıa luego la enumeracion ya que se intentarıa conectar

un dispositivo extra. Otro caso es el de un mouse de computadora, hay una gran cantidad de

modelos con largos del descriptor de configuracion diferentes. Si el stack se configura para el

menor de ellos despues no serıa posible intercambiar el dispositivo con otro de la misma clase

pero distinto largo de descriptor.

En el apendice A se incluyen los dos archivos de configuracion (encabezado y fuente)

generados a partir del archivo de configuracion antes ejemplificado. Es el fuente el de mayor

interes pues contiene la mayor parte de la configuracion generada. En el encabezado solamente

se indican ciertas constantes representativas de la configuracion y las declaracion necesarias

utilizadas en el fuente.

5.3. Asignacion de Interfaces

Al inicializar el stack USB, las estructuras de los dispositivos no tienen asignado un arreglo

de interfaces. El motivo de esto es el siguiente, si bien el host conoce las caracterısticas de

cada dispositivo gracias al archivo de configuracion, no es posible saber a cual pertenece el que

esta siendo actualmente enumerado hasta haber obtenido los primeros 9 bytes del descriptor

de configuracion. Esto significa que el dispositivo ya fue asignado a un ındice en la estructura

interna del stack (esto se hace al momento de la conexion) pero este probablemente no coincida

con aquel en el listado de interfaces, a esto se le suma que la enumeracion puede darse en

cualquier orden dependiendo de cual dispositivo se conecte primero cada vez que se inicie el

equipo. Para solucionar este problema los dispositivos no solicitan un arreglo de interfaces hasta

haber obtenido los datos necesarios, o sea, el numero de interfaces, ID de vendedor/producto

y tamano del descriptor de configuracion.

Es importante notar que esta rutina puede fallar. Como se ha mencionado en las secciones

anteriores, es posible y probable que un usuario conecte un dispositivo fuera de lo previsto. En

caso de que dicho dispositivo tenga una serie de interfaces que cumpla con las condiciones de

alguno de los arreglos de configuracion, este le sera asignado. En caso contrario, este metodo

fallara y el USBD se encargara de tratar con la situacion. Al disenar el sistema se decidio no

asumir que el usuario conectara exactamente lo que se ha configurado, principalmente debido

a la situacion en que se desee conectar una clase de dispositivo y no un modelo exacto.

Cada uno de los posibles arreglos de interfaces son constantes y creados estaticamente.

76

Tesis de Grado – Stack USB

Su declaracion y definicion se genera a partir del archivo de configuracion. A continuacion

se lista el prototipo del metodo que recorre los arreglos de interfaces generados en busca del

correspondiente para un dado dispositivo.

int16_t usb_device_get_config(

usb_interface_t** ppiface,

uint8_t** pbuffer,

uint16_t pid,

uint16_t vid,

uint16_t len,

uint8_t n_ifaces

);

Listado 16: Metodo para obtener configuracion asociada a un dispositivo

Este metodo utiliza internamente el protocolo almacenado en la estructura de la interfaz

para determinar si ya se ha asignado un arreglo de interfaces. Para esto se reserva el valor de

protocolo 255.

Desde el punto de vista del usuario no es importante conocer estos detalles. Sin embargo,

es una caracterıstica importante que muestra como se ha tratado la configuracion de disposi-

tivos para poder utilizar estructuras de datos estaticas sin perder la capacidad de administrar

dinamicamente al sistema USB.

77

Capıtulo 6

Ensayos y Resultados

El presenta capıtulo describe la forma en que se ensayo el stack USB ante

situaciones controladas de simulacion de dispositivos y ante un caso de uso real.

A su vez, se detalla los resultados obtenidos del caso de uso real.

Tesis de Grado – Stack USB

6. Ensayos y Resultados

La mayor parte del desarrollo del stack USB consistio en el analisis de la especificacion USB

2.0 y determinar la manera mas conveniente de llevar a cabo la implementacion utilizando solo

recursos estaticos. Para verificar el funcionamiento de los distintos modulos que componen al

stack USB se utilizo otra placa de desarrollo emulando un dispositivo USB. Se utilizo el kit de

desarrollo STM32F4Discovery, en la figura 15 puede observarse el banco de pruebas utilizado

con ambas placas.

Figura 15: Banco de pruebas de desarrollo

1. EDU-CIAA-NXP

2. STM32F4Discovery

Se utilizo este metodo para evaluar las distintas funcionalidades que se implementaron en

el stack USB por los siguientes motivos:

• Facilidad de evaluar la conexion con un dispositivo USB y ver que sucede en el otro

extremo del bus USB.

• Pudo utilizarse como dispositivo HID sin tener que desarrollar el codigo necesario para

ello. El entorno de desarrollo del kit de STM incluye las bibliotecas y el software necesario

para esto.

81

6 Ensayos y Resultados

• Utilizar un dispositivo programable en lugar de uno fijo –como lo serıa un mouse generico–

permitio modificar el codigo para evaluar el comportamiento del stack USB ante una

variedad de situaciones diferentes, desde diferentes valores para el mismo contenido hasta

condiciones fuera de lo comun o directamente erroneas. Por ejemplo:

1. Diferentes contenidos en el mismo descriptor.

2. Descriptores de largo incorrecto.

3. Descriptores con parametros incorrectos o no soportados por el stack USB.

4. Cantidad o parametros de interfaces y/o endpoints diferentes a los indicados en la

configuracion del stack USB.

• Permitio probar descriptores obtenidos de otros dispositivos HID diferentes mantenien-

do el resto de los parametros constantes. Para ello se utilizo una PC con el software

Wireshark1 para capturar la interaccion entre la PC y cada dispositivo y luego poder

emularlos en el kit STM.

Por otro lado, el metodo anterior no permite ensayar todos los modulos del stack USB

desarrollado, tiene dos inconvenientes principales. En primer lugar, el kit de desarrollo de STM

solo tiene el hardware necesario para transferencias LS o FS, por lo que no es posible utilizarlo

para emular dispositivos HS. En segundo lugar, no es posible utilizarlo para ensayar un HUB

USB, siendo este uno de los principales objetivos de esta tesis.

El desarrollo del driver HUB se realizo analizando en detalle la seccion correspondiente de

la especificacion USB 2.0 y analizando capturas de uso de distintos HUBs realizadas con el

Wireshark. Como caso particular de ensayo se utilizaron dos HUBs diferentes, uno FS de 4

puertos y otro HS de 10 puertos.

A la hora de probar dispositivos reales conectados a la placa de desarrollo se utilizaron una

variedad de diferentes mouse de distintas marcas y modelos. Se utilizo tambien una camara web

moderna con gran cantidad de interfaces y distintas configuracion. Por ultimo, los HUBs antes

mencionados para poder conectar varios dispositivos en simultaneo, cambiando la organizacion

de los dispositivos en el bus USB en distintas corridas.

A continuacion se describe un caso particular de uso, este es el que se ha utilizado para

ejemplificar la configuracion del stack USB a lo largo de las secciones anteriores y el que utiliza

todos los modulos que se han desarrollado. En la figura 16 se muestra el banco de pruebas

utilizado con todos los dispositivos conectados.

Los dispositivos conectados son los siguientes:

1https://www.wireshark.org/

82

Tesis de Grado – Stack USB

Figura 16: Banco de pruebas de caso de uso real

1. Dispositivo HID FS

Mouse FS generico, este dispositivo cumple dos objetivos en el ensayo. En primer lugar,

se utiliza como HID para con sus movimientos controlar los tres LEDs indicados en 3

en la placa EDU-CIAA-NXP. En segundo lugar, se utiliza para realizar transferencias de

velocidad mixta, o sea, FS a traves de un HUB HS.

2. EDU-CIAA-NXP

Placa de desarrollo corriendo el stack USB configurado como se ha ejemplificado y

explicado en las secciones anteriores.

3. LEDs indicadores de movimientos del mouse

Como se ha explicado en 1, estos LEDs se encienden y apagan segun los movimientos

del mouse. Se utiliza la interfaz POSIX-compatible definida en el proyecto CIAA para

salidas digitales.

4. HUB FS de 4 puertos

Este HUB no se utiliza como tal, si no que se conecta como dispositivo extra para el

cual el stack USB no ha sido configurado. Como se ha configurado el stack con soporte

para el HUB HS (ıtem 5) en forma generica sin identificadores de vendedor ni producto,

para que el host no permita la enumeracion del HUB FS este se conecta luego de los

83

6 Ensayos y Resultados

otros aquı listados. Esto se detalla mas adelante.

5. HUB HS de 10 puertos

En el capıtulo 5 se ha explicado como este HUB esta internamente implementado como

2 HUBs de 7 y 4 puertos conectados en cascada, primero el de 7. En este caso se ha

conectado la camara web (ıtem 6) al primer HUB de 7 puertos y el mouse (ıtem 1) al

HUB de 4 puertos.

Por otro lado, luego de realizar pruebas con una PC y el Wireshark se pudo determinar

que uno de los puertos del HUB de 4 se encuentra en falla. Esto permitio ensayar el codigo

del host ante un equipo con fallas de hardware, lo cual no era posible realizar con el kit

de desarrollo de STM.

6. Camara web HS

Camara web estandar que implementa las clases USB de video y de audio. Si bien no se

ha implementado el driver para estas clases, se la ha utilizado para evaluar la verificacion

de drivers ya que posee gran cantidad de interfaces con varias configuraciones. Ademas,

posee un descriptor de configuracion varias veces mas largo que un dispositivo HID

generico.

El host USB y sus drivers registran todos los eventos importantes que ocurren a lo largo de

su ejecucion. En el apendice B se adjunta el log del ensayo antes explicado y, a continuacion,

se agrupan conceptualmente los distintos eventos ocurridos y se explican brevemente. Se in-

dican tambien las lınea en donde ocurren los principales eventos para poder encontrarlos mas

facilmente.

1. Se comienza con la inicializacion de los drivers de bajo nivel (HCI), el host USB y los

drivers (HUB y HID).

2. Luego, se conecta el HUB FS de 4 puertos a la EDU-CIAA-NXP. Comenzando en la lınea

8 se detecta la conexion del dispositivo raız y se procede al proceso de enumeracion.

Notar en las lıneas 25 a 26 la verificacion y asignacion del driver HUB. Este primer

paso se realizo con el objetivo de mostrar la capacidad del stack USB para utilizar un

dispositivo para el cual no ha sido configurado mientras sus caracterısticas esten dentro

de la configuracion sı especificada, en este caso el HUB de 4 puertos es compatible con

las configuraciones del de 7 o del de 4.

3. En la lınea 31 comienza el proceso de inicializacion y configuracion del dispositivo por

el driver HUB. Puede observarse como se obtiene el estado del HUB y de cada puerto y

los bits indicadores en cada uno.

4. Se desconecta el HUB de 4 puertos, la intencion es ensayar que el host vuelva al estado

original. Se libera el dispositivo y se notifica al driver HUB de dicho evento.

5. Se conecta el HUB de 10 puertos, recordar que esta internamente implementado como

84

Tesis de Grado – Stack USB

uno de 7 y otro de 4 puertos. A partir de la lınea 57 puede verse nuevamente la detec-

cion del dispositivo raız y su enumeracion y asignacion de driver HUB, en este caso se

comienza con el HUB de 7 puertos.

6. Se procede a inicializar el HUB de 7 puertos, se pide el estado general del HUB y de

cada uno de los 7 puertos. Luego se habilita la alimentacion de cada uno.

7. En la lınea 114 puede observarse como el driver HUB recibe una notificacion de cambio

de estado en uno de sus puertos. Se procede a pedir el estado, se detecta la conexion

de un dispositivo (en este caso el HUB de 4 puertos que compone al de 10) y se lo

notifica al USBD, indicando a su vez cual es el HUB y puerto donde se ha producido

dicho evento.

8. En este punto se mezclan los registros del driver HUB y el host. Sucede que el host

comienza con la enumeracion mientras el driver procesa el cambio de estado del puerto

del HUB. El host realiza un pedido de reset del puerto correspondiente, registrado en la

lınea 121 cuando el driver HUB lo identifica y procede a comunicarlo al HUB.

9. Se espera a la finalizacion del reset y, una vez indicado el USBD por el driver HUB de

tal evento, se procede con el resto de la enumeracion del segundo HUB. En las lıneas

147 a 148 se realiza la nueva asignacion de drivers.

10. Luego, el driver HUB realiza la inicializacion del segundo HUB a partir de la lınea 153.

Es identica a la del punto 6 pero con solo 4 puertos.

11. Nuevamente se detecta un cambio de estado, lınea 175, esta vez en el segundo HUB.

Se procede a notificar al USBD quien nuevamente pide y espera por el reset del puerto.

12. Una vez finalizado el reset, el host prosigue con la enumeracion. Esta vez se ha detectado

un dispositivo FS. Al llegar a la asignacion de drivers falla la verificacion del driver HUB,

se continua con la del driver HID la cual es exitosa y se le asigna la nueva interfaz.

13. En la lınea 214 es el driver HID quien realiza la inicializacion y configuracion de la nueva

interfaz. Se finaliza con un pedido de datos y la espera hasta su finalizacion.

14. El driver HUB nuevamente detecta un cambio de estado en el primer HUB, lınea 219. Se

notifica al USBD y se realiza el mismo procedimiento anterior ante el pedido de reset.

15. Esta vez el host ha detectado la camara web. A partir de la lınea 234 comienza el proceso

de enumeracion (a excepcion del reset antes mencionado). Es importante notar en este

caso como la asignacion de drivers es mas extensa: de la lınea 250 a la 261 se intentan

verificar las 4 interfaces del dispositivo, se prueba contra los dos drivers disponibles y en

los cuatro casos fallan, ya que las interfaces son de video y audio. A pesar de esto, la

enumeracion termina pero el dispositivo queda con sus interfaces sin asignar a ningun

driver y ningun pipe se le ha asignado para su uso.

85

6 Ensayos y Resultados

16. En este punto el stack USB ya tiene conectados y configurados los cuatro dispositivos

para los cuales se ha configurado con el archivo de configuracion. En la lınea 265 se

conecta nuevamente el otro HUB FS de 4 puertos, puede verse en este caso como el

driver HUB notifica al USBD del evento pero este lo rechaza ya que no puede almacenar

mas dispositivos. El nuevo HUB quedara sin enumerar, no sera reseteado y no podra

recibir una direccion en el bus USB. Esta situacion se termina al desconectar el nuevo

HUB, de lo cual es notificado el driver HUB en la lınea 271.

17. Por ultimo se desconecta el HUB de 10 puertos, lınea 276. Este esta conectado directa-

mente al hardware del microcontrolador por lo que dicho evento se notifica directamente

al host sin pasar a traves del driver HUB. Al detectarse la desconexion del dispositivo raız

se desencadena la liberacion de todos los dispositivos conectados en la red y la respectiva

notificacion a los drivers para cada una de sus interfaces. El dispositivo 3 (camara web)

no notifica a ningun driver ya que sus interfaces no han podido ser verificadas contra

ninguno de los dos disponibles.

86

Capıtulo 7

Conclusiones

Tesis de Grado – Stack USB

7. Conclusiones

El desarrollo del stack USB estuvo centrado en los dos objetivos principales que definieron

a esta tesis: soportar multiples dispositivos USB en forma configurable y no utilizar memoria

dinamica. Esto llevo a una contradiccion con los fundamentos de un sistema USB, ser dinamico

y no requerir configuracion o conocimiento previo de los dispositivos a conectar.

Poder cumplir con los objetivos y mantener a la vez el dinamismo del sistema USB im-

plico realizar compromisos entre la configurabilidad del stack USB y la capacidad de conectar

dispositivos arbitrarios. Esto afecta tanto a la implementacion del stack como al usuario final.

En este caso, “usuario final” hace referencia a quien incluya el stack USB en su aplicacion

y no al codigo usuario cliente del stack. Los compromisos que debieron realizarse se listan a

continuacion:

• La cantidad total de dispositivos a conectar se fija en la compilacion. Por un lado, se

limita la cantidad de dispositivos para poder determinar los recursos necesarios en forma

estatica en tiempo de compilacion. Por otro lado, tambien se utiliza como lımite superior

los recursos de hardware disponibles segun la familia de microcontroladores utilizada, de

esta manera se redujo la complejidad del stack USB.

Este punto no es trivial, hay dispositivos que exponen una unica funcionalidad que puede

estar implementada –internamente– como varios dispositivos. Es el caso, por ejemplo,

de algunos HUBs de mas de 7 puertos, uno de los utilizados en los ensayos de esta tesis

de 10 puertos en realidad enumera como dos HUBs de 7 y 4 puertos conectados en

cascada.

Limitar el numero de dispositivos permite saber exactamente la cantidad de recursos

maxima que utilizara el stack USB en funcionamiento. Sin embargo, requiere que el

usuario conozca que dispositivos seran luego conectados y ciertos detalles no menores

de los mismos.

• Debido a las limitaciones de hardware para los distintos microcontroladores el usuario de-

be conocer la cantidad de pipes de control que el stack USB puede utilizar. Esto permite

asegurar que todos los dispositivos a conectar puedan ser enumerados y configurados.

Por otro lado, este punto limita la cantidad de recursos que requiere el stack y permite

su uso mas eficiente. Por ejemplo, en caso de no necesitar utilizar todos los pipes de

control puede configurarse un numero menor al maximo soportado por el hardware y

ahorrar recursos que no se utilizaran.

Similarmente al punto anterior, esta configuracion requiere que el usuario conozca los

lımites del hardware y las necesidades conjuntas de los dispositivos a conectar.

• Se ha optado por balancear la configuracion de cada dispositivo con la libertad del usuario

a utilizar parametros genericos para poder extenderse fuera de un vendedor y producto

en particular. El tamano del buffer de configuracion y IDs de producto y vendedor son

89

7 Conclusiones

opcionales, sin embargo debe tenerse en cuenta que sus valores por defecto pueden no

ser validos para cualquier dispositivo.

Puede tambien utilizarse un tamano de buffer y cantidad de endpoints que abarque varios

dispositivos. Por ejemplo, un dispositivo HID mouse tiene en la mayorıa de los casos una

sola interfaz con un endpoint de interrupcion mientras que la configuracion puede tener

varios largos distintos segun el modelo y marca. Es posible configurar un dispositivo que

englobe a varios mouse utilizando el largo maximo de todos los posibles a soportar, o,

de no ser tan crıtico el espacio en memoria, utilizar un largo considerablemente mayor y

no requerir conocer todos los distintos tipos que se planea conectar.

• No es conveniente utilizar una interfaz POSIX-compatible a nivel USBD ya que es ne-

cesario utilizar parametros propios del protocolo USB de difıcil acceso a traves de tal

interfaz. Sin embargo, entre el codigo usuario y los drivers de dispositivos ya no se re-

quiere conocimiento de ninguno de los protocolos –USB o dispositivo– y, por ello, es

simple adaptar las interfaces para hacerlas POSIX-compatibles.

El desarrollo de un stack USB completo es un proyecto ambicioso y complejo, por lo

que ademas de los compromisos antes mencionados hubo que imponer limitaciones para no

extenderse en la duracion de la tesis. La primer y principal limitacion es solo tener la capacidad

de actuar como Host, originalmente se planifico crear un stack USB OTG lo cual incluye

tambien la funcionalidad de dispositivo, sin embargo, en la etapa de diseno se vio que la

mayor parte del desarrollo tendrıa que enfocarse en el host ya que este es el encargado de

las funcionalidades mas complejas. Ademas, debido a la sencillez de la implementacion como

dispositivo, no requiere ninguna consideracion particular para el uso de memoria estatica por

lo que podrıa mas facilmente tomarse una de las tantas implementaciones libres ya existentes

y adaptarla.

En cuanto a las capacidades particulares del host, tambien se impusieron ciertas limita-

ciones con el fin de no excederse del alcance de la tesis. Se ha tenido en cuenta, en forma

complementaria, posibles mejoras futuras a realizar para eliminar –o reducir– estas restriccio-

nes.

• El uso de los pipes de control no esta controlado por un algoritmo de uso equitativo,

simplemente se permite a los distintos dispositivos acceso a este en forma circular.

Codigo usuario irresponsable podrıa apropiarse de un pipe de no ser cuidadoso, esto

puede mejorarse desde el host con un control de timeout por pipe.

• Los pipes de control son los unicos que pueden ser compartidos entre interfaces y dis-

positivos. Como consecuencia, la cantidad de dispositivos, interfaces y endpoints que el

host puede soportar va a estar limitada estrictamente por la cantidad de pipes que el

90

Tesis de Grado – Stack USB

hardware disponga.

Para mejorar esta situacion pueden realizarse dos modificaciones a futuro:

1. Compartir los pipes de tipo bulk de la misma manera que los de control.

2. Compartir los pipes de transferencias periodicas segun el ancho de banda requerido

por cada interfaz. Esto requiere un uso muy preciso y cuidadoso de los tiempos del

stack, dependera de la configuracion de los ticks del sistema y deberan utilizarse

transferencias en rafagas para poder intercalar en el tiempo transacciones hacia

distintos endpoints.

• Como se ha explicado anteriormente, se decidio limitar la cantidad de dispositivos enu-

merados a la vez tal que solo uno pueda hacerlo. En la mayorıa de los casos esto no es un

inconveniente, en particular si se tiene en cuenta que los dispositivos solo se enumeran

una vez en su inicializacion.

• Debido uso interno de los recursos del sistema y al metodo de configuracion del stack, no

es posible configurarlo para que soporte cualquier dispositivo de una clase dada. Si bien

algunas clases simples como HID (mouse o teclado, por ejemplo) pueden abarcarse en

gran parte, otras poseen dispositivos muy diferentes entre sı lo que hace que conocer su

configuracion sea imprescindible. Un dispositivo de video puede tener descriptores com-

pletamente diferentes en largo y clase, tambien puede tener distinta clase de interfaces

si no acepta audio, por ejemplo.

Esta limitacion es consecuencia del la implementacion disenada para cumplir los objeti-

vos de uso de recursos determinıstico y memoria estatica. Esto se relaciona directamente

el ultimo compromiso antes mencionado.

91

Tesis de Grado – Stack USB

Bibliografıa

[1] Janet L. Axelson. USB Complete Fourth Edition: The Developer’s Guide. Lakeview Re-

search LLC, 2009.

[2] Janet L. Axelson. USB Embedded Hosts: The Developer’s Guide. Lakeview Research LLC,

2011.

[3] Computadora Industrial Abierta Argentina (CIAA). http://www.proyecto-ciaa.

com.ar/devwiki/doku.php. Fecha de acceso: 2016-04-17.

[4] Enhanced Host Controller Interface Specification for Universal Serial Bus. Revision 1.0.

Intel Corporation. Mar. de 2002.

[5] Greg Kroah-Hartman Jonathan Corbet Alessandro Rubini. Linux Device Drivers, Third

Edition. Lakeview Research LLC, 2011. Cap. 13.

[6] R. Regupathy. Bootstrap yourself with Linux-USB stack: design, develop, debug, and

validate embedded USB. Course Technology, 2012.

[7] Universal Serial Bus Specification. Revision 2.0. Compaq, Hewllet-Packard, Intel, Lucent,

Microsoft, NEC, Philips. Abr. de 2000.

[8] USB Device Class Definition for Human Interface Devices. Revision 1.1. 2001.

[9] USB-IF Compliance Program. http://www.usb.org/developers/compliance/.

Fecha de acceso: 2016-04-17.

93

Tesis de Grado – Stack USB

Anexos

Anexo A Ejemplo de Codigo de Configuracion Generado

A.1 Encabezado

1 #i f n d e f USB DEVICES CFG T

2 #d e f i n e USB DEVICES CFG T

34 #i n c l u d e <s t d i o . h>

56 /∗∗ @ b r i e f Number o f s i m u l a t n e o u s d e v i c e s s u p p o r t e d . ∗/

7 #d e f i n e USB MAX DEVICES 4

8 /∗∗ @ b r i e f Number o f s i m u l a t n e o u s i n t e r f a c e s s u p p o r t e d . ∗/

9 #d e f i n e USB MAX INTERFACES 7

10 /∗∗ @ b r i e f Number o f s i m u l a t n e o u s e n d p o i n t s s u p p o r t e d ( e n d p o i n t 0 e x c l u d e d ) . ∗/

11 #d e f i n e USB MAX ENDPOINTS 5

1213 /∗∗ @ b r i e f Get number o f i n t e r f a c e s o f d e v i c e ’ dev ’ . ∗/

14 #d e f i n e USB GET IFACES N ( dev ) u s b c t e d e v i c e s [ dev ] . n i f a c e s

15 /∗∗ @ b r i e f Get number o f e n d p o i n t s o f i n t e r f a c e ’ i f ’ o f d e v i c e ’ dev ’ . ∗/

16 #d e f i n e USB GET EPS N ( dev , i f ) u s b c t e d e v i c e s [ dev ] . i f a c e s [ i f ] . n e n d p o i n t s

17 /∗∗ @ b r i e f Get p r o d u c t ID o f d e v i c e ’ dev ’ . ∗/

18 #d e f i n e USB GET PRODUCT ID( dev ) u s b c t e d e v i c e s [ dev ] . p r o d u c t i d

19 /∗∗ @ b r i e f Get vendor ID o f d e v i c e ’ dev ’ . ∗/

20 #d e f i n e USB GET VENDOR ID( dev ) u s b c t e d e v i c e s [ dev ] . v e n d o r i d

21 /∗∗ @ b r i e f Get l e n g t h o f c o n f i g u r a t i o n d e s c r i p t o r b u f f e r o f d e v i c e ’ dev ’ . ∗/

22 #d e f i n e USB GET CFG LEN ( dev ) u s b c t e d e v i c e s [ dev ] . c f g l e n

2324 /∗∗ @ b r i e f D e f a u l t data f o r u s b i n t e r f a c e t i n i t i a l i z a t i o n . ∗/

25 #d e f i n e USB DEFAULT IFACE DATA( eps ) { eps , USB IFACE NO DRIVER , 0 , 0 , 0 , 255}2627 t y p e d e f s t r u c t u s b c t e i f a c e t

28 {29 u i n t 8 t n e n d p o i n t s ;

30 } u s b c t e i f a c e t ;

3132 t y p e d e f s t r u c t u s b c t e d e v t

33 {34 u s b c t e i f a c e t ∗ i f a c e s ;

35 u i n t 1 6 t v e n d o r i d ;

36 u i n t 1 6 t p r o d u c t i d ;

37 u i n t 1 6 t c f g l e n ;

38 u i n t 8 t n i f a c e s ;

39 } u s b c t e d e v t ;

4041 /∗ This c o n s t a n t c o t a i n s t h e number o f i n t e r f a c e s and e n d p o i n t s p e r i n t e r f a c e . ∗/

42 /∗ A cc es s them w i t h @ r e f USB GET IFACES N ( ) and @ r e f USB GET EPS N ( ) macros . ∗/

43 e x t e r n const u s b c t e d e v t u s b c t e d e v i c e s [ USB MAX DEVICES ] ;

4445 #e n d i f /∗ USB DEVICES CFG T ∗/

Listado 17: Encabezado de configuracion generado

95

A.2 Fuente

A.2 Fuente

1 #i n c l u d e <s t d i o . h>

2 #i n c l u d e ” usb . h”

3 #i n c l u d e ” u s b d e v i c e s c f g . h”

456 /∗ E n d p o i n t s a r r a y s . ∗/

7 s t a t i c u s b p i p e t u s b e p s 0 1 [ 1 ] ;

8 s t a t i c u s b p i p e t u s b e p s 0 3 [ 1 ] ;

9 s t a t i c u s b p i p e t u s b e p s 1 0 [ 1 ] ;

10 s t a t i c u s b p i p e t u s b e p s 2 0 [ 1 ] ;

11 s t a t i c u s b p i p e t u s b e p s 3 0 [ 1 ] ;

1213 /∗ I n t e r f a c e s a r r a y s . ∗/

14 s t a t i c u s b i n t e r f a c e t u s b i f a c e s 0 [ 4 ] = {15 USB DEFAULT IFACE DATA(NULL) ,

16 USB DEFAULT IFACE DATA( u s b e p s 0 1 ) ,

17 USB DEFAULT IFACE DATA(NULL) ,

18 USB DEFAULT IFACE DATA( u s b e p s 0 3 ) ,

19 } ;

20 s t a t i c u s b i n t e r f a c e t u s b i f a c e s 1 [ 1 ] = {21 USB DEFAULT IFACE DATA( u s b e p s 1 0 ) ,

22 } ;

23 s t a t i c u s b i n t e r f a c e t u s b i f a c e s 2 [ 1 ] = {24 USB DEFAULT IFACE DATA( u s b e p s 2 0 ) ,

25 } ;

26 s t a t i c u s b i n t e r f a c e t u s b i f a c e s 3 [ 1 ] = {27 USB DEFAULT IFACE DATA( u s b e p s 3 0 ) ,

28 } ;

2930 /∗ C o n f i g u r a t i o n b u f f e r s . ∗/

31 s t a t i c u i n t 8 t u s b c f g b u f f e r 0 [ 2 4 6 6 ] ;

32 s t a t i c u i n t 8 t u s b c f g b u f f e r 1 [ 3 4 ] ;

33 s t a t i c u i n t 8 t u s b c f g b u f f e r 2 [ 4 1 ] ;

34 s t a t i c u i n t 8 t u s b c f g b u f f e r 3 [ 2 5 ] ;

353637 /∗ C o n s t a n t s . ∗/

38 s t a t i c const u s b c t e i f a c e t u s b c t e i f a c e s 0 [ 4 ] = { {0} , {1} , {0} , {1} } ;

39 s t a t i c const u s b c t e i f a c e t u s b c t e i f a c e s 1 [ 1 ] = { {1} } ;

40 s t a t i c const u s b c t e i f a c e t u s b c t e i f a c e s 2 [ 1 ] = { {1} } ;

41 s t a t i c const u s b c t e i f a c e t u s b c t e i f a c e s 3 [ 1 ] = { {1} } ;

4243 const u s b c t e d e v t u s b c t e d e v i c e s [ USB MAX DEVICES ] = {44 { u s b c t e i f a c e s 0 , 0x046D , 0 x0825 , 2466 , 4} , /∗ Webcam ∗/

45 { u s b c t e i f a c e s 1 , 0x046D , 0xC247 , 34 , 1} , /∗ Mouse ∗/

46 { u s b c t e i f a c e s 2 , 0xFFFF , 0xFFFF , 41 , 1} , /∗ HUB0 ∗/

47 { u s b c t e i f a c e s 3 , 0xFFFF , 0xFFFF , 25 , 1} , /∗ HUB1 ∗/

48 } ;

4950 /∗ Array o f i n t e r f a c e s , t h e s e w i l l be r e q u e s t e d d u r i n g e n u m e r a t i o n . ∗/

51 s t a t i c u s b i n t e r f a c e t ∗ const u s b i f a c e s [ USB MAX DEVICES ] = {52 u s b i f a c e s 0 ,

53 u s b i f a c e s 1 ,

54 u s b i f a c e s 2 ,

55 u s b i f a c e s 3 ,

96

Tesis de Grado – Stack USB

56 } ;

5758 /∗ Array o f c o n f i g b u f f e r s , t h e s e w i l l be r e q u e s t e d a l o n g s i d e t h e i n t e r f a c e s . ∗/

59 s t a t i c u i n t 8 t ∗ const u s b c f g b u f f e r s [ USB MAX DEVICES ] = {60 u s b c f g b u f f e r 0 ,

61 u s b c f g b u f f e r 1 ,

62 u s b c f g b u f f e r 2 ,

63 u s b c f g b u f f e r 3 ,

64 } ;

6566 . . . e l r e s t o d e l f u e n t e e s c o n s t a n t e , no depende de l a c o n f i g u r a c i o n .

Listado 18: Fuente de configuracion generado

97

Tesis de Grado – Stack USB

Anexo B Log del Ensayo del Caso de Uso Real

1 USB HCI initialized.

2 USB devices initialized to default state.

3 USB acquired control pipe 0 from HCI.

4 USB acquired control pipe 1 from HCI.

5 USB HUB driver initialized.

6 USB HID driver initialized.

7

8 USB root device connection detected.

9 USB attached device at index 0 with parent HUB (255,0).

10 USB waiting for device 0’s powerline to settle.

11 USB DEV 0 powered, locking address 0 on Host and resetting.

12 USB DEV 0 reset done.

13 USB DEV 0 connected at full-speed.

14 USB DEV 0 requesting MPS.

15 USB DEV 0 with MPS = 8, resetting again.

16 USB DEV 0 reset done.

17 USB DEV 0 setting address to 1.

18 USB DEV 0 requesting device descriptor.

19 USB DEV 0 with VendorID:ProductID 03EB:0902

20 USB DEV 0 requesting first 9 Bytes of configuration descriptor.

21 USB DEV 0 cfg. desc. is 34 bytes long.

22 USB DEV 0 requesting entire configuration descriptor.

23 USB DEV 0 is sefpowered.

24 USB DEV 0 supports remote wakeup.

25 USB probing HUB driver ... SUCCESS

26 USB assigning HUB driver to dev:iface 0:0

27 USB HUB connected at index 0.

28 USB DEV 0 setting configuration to 1

29 USB DEV 0 releasing lock on address 0.

30

31 USB HUB 0 requesting HUB descriptor.

32 USB HUB 0 wHubCharacteristics (INDIV_PWR, INDIV_OVC)

33 USB HUB 0 requesting HUB status.

34 USB HUB 0 wHubStatus & wHubChange (none)

35 USB HUB 0 preparing to power up ports.

36 USB HUB 0 requesting SetPortFeature(PORT_POWER) from port 0.

37 USB HUB 0 port 0 powered up.

38 USB HUB 0 requesting SetPortFeature(PORT_POWER) from port 1.

39 USB HUB 0 port 1 powered up.

40 USB HUB 0 requesting SetPortFeature(PORT_POWER) from port 2.

41 USB HUB 0 port 2 powered up.

42 USB HUB 0 requesting SetPortFeature(PORT_POWER) from port 3.

43 USB HUB 0 port 3 powered up.

44 USB HUB 0 requesting port 0 status.

45 USB HUB 0 port 0 status (POWER)

46 USB HUB 0 requesting port 1 status.

47 USB HUB 0 port 1 status (POWER)

48 USB HUB 0 requesting port 2 status.

99

B Log del Ensayo del Caso de Uso Real

49 USB HUB 0 port 2 status (POWER)

50 USB HUB 0 requesting port 3 status.

51 USB HUB 0 port 3 status (POWER)

52

53 USB root device disconnection detected.

54 USB releasing device 0

55 USB removing dev:iface 0:0 from HUB driver.

56

57 USB root device connection detected.

58 USB attached device at index 0 with parent HUB (255,0).

59 USB waiting for device 0’s powerline to settle.

60 USB DEV 0 powered, locking address 0 on Host and resetting.

61 USB DEV 0 reset done.

62 USB DEV 0 connected at high-speed.

63 USB DEV 0 requesting MPS.

64 USB DEV 0 with MPS = 64, resetting again.

65 USB DEV 0 reset done.

66 USB DEV 0 setting address to 1.

67 USB DEV 0 requesting device descriptor.

68 USB DEV 0 with VendorID:ProductID 1A40:0201

69 USB DEV 0 requesting first 9 Bytes of configuration descriptor.

70 USB DEV 0 cfg. desc. is 41 bytes long.

71 USB DEV 0 requesting entire configuration descriptor.

72 USB DEV 0 is sefpowered.

73 USB DEV 0 supports remote wakeup.

74 USB probing HUB driver ... SUCCESS

75 USB assigning HUB driver to dev:iface 0:0

76 USB HUB connected at index 0.

77 USB DEV 0 setting configuration to 1

78 USB DEV 0 releasing lock on address 0.

79

80 USB HUB 0 requesting HUB descriptor.

81 USB HUB 0 wHubCharacteristics (INDIV_OVC, STS_INDICATORS)

82 USB HUB 0 requesting HUB status.

83 USB HUB 0 wHubStatus & wHubChange (none)

84 USB HUB 0 preparing to power up ports.

85 USB HUB 0 requesting SetPortFeature(PORT_POWER) from port 0.

86 USB HUB 0 port 0 powered up.

87 USB HUB 0 requesting SetPortFeature(PORT_POWER) from port 1.

88 USB HUB 0 port 1 powered up.

89 USB HUB 0 requesting SetPortFeature(PORT_POWER) from port 2.

90 USB HUB 0 port 2 powered up.

91 USB HUB 0 requesting SetPortFeature(PORT_POWER) from port 3.

92 USB HUB 0 port 3 powered up.

93 USB HUB 0 requesting SetPortFeature(PORT_POWER) from port 4.

94 USB HUB 0 port 4 powered up.

95 USB HUB 0 requesting SetPortFeature(PORT_POWER) from port 5.

96 USB HUB 0 port 5 powered up.

97 USB HUB 0 requesting SetPortFeature(PORT_POWER) from port 6.

98 USB HUB 0 port 6 powered up.

100

Tesis de Grado – Stack USB

99 USB HUB 0 requesting port 0 status.

100 USB HUB 0 port 0 status (POWER)

101 USB HUB 0 requesting port 1 status.

102 USB HUB 0 port 1 status (POWER)

103 USB HUB 0 requesting port 2 status.

104 USB HUB 0 port 2 status (POWER)

105 USB HUB 0 requesting port 3 status.

106 USB HUB 0 port 3 status (POWER)

107 USB HUB 0 requesting port 4 status.

108 USB HUB 0 port 4 status (POWER)

109 USB HUB 0 requesting port 5 status.

110 USB HUB 0 port 5 status (POWER)

111 USB HUB 0 requesting port 6 status.

112 USB HUB 0 port 6 status (POWER)

113

114 USB HUB 0 status/port change detected.

115 USB HUB 0 requesting port 0 status.

116 USB HUB 0 port 0 status (CONNECTION, POWER)

117 USB HUB 0 requesting ClearPortFeature(C_PORT_CONNECTION) from port 0.

118 USB attached device at index 1 with parent HUB (0,0).

119 USB waiting for device 1’s powerline to settle.

120 USB DEV 1 powered, locking address 0 on Host and resetting.

121 USB HUB 0 reset pending on port 0, going for reset.

122 USB HUB 0 requesting SetPortFeature(PORT_RESET) from port 0.

123 USB HUB 0 status/port change detected.

124 USB HUB 0 requesting port 0 status.

125 USB HUB 0 port 0 status (CONNECTION, High-Speed, ENABLE, POWER)

126 USB DEV 1 reset done.

127 USB HUB 0 requesting ClearPortFeature(C_PORT_RESET) from port 0.

128

129 USB DEV 1 connected at high-speed.

130 USB DEV 1 requesting MPS.

131 USB DEV 1 with MPS = 64, resetting again.

132 USB HUB 0 reset pending on port 0, going for reset.

133 USB HUB 0 requesting SetPortFeature(PORT_RESET) from port 0.

134 USB HUB 0 status/port change detected.

135 USB HUB 0 requesting port 0 status.

136 USB HUB 0 port 0 status (CONNECTION, ENABLE, POWER)

137 USB DEV 1 reset done.

138 USB HUB 0 requesting ClearPortFeature(C_PORT_RESET) from port 0.

139 USB DEV 1 setting address to 2.

140 USB DEV 1 requesting device descriptor.

141 USB DEV 1 with VendorID:ProductID 1A40:101

142 USB DEV 1 requesting first 9 Bytes of configuration descriptor.

143 USB DEV 1 cfg. desc. is 25 bytes long.

144 USB DEV 1 requesting entire configuration descriptor.

145 USB DEV 1 is sefpowered.

146 USB DEV 1 supports remote wakeup.

147 USB probing HUB driver ... SUCCESS

148 USB assigning HUB driver to dev:iface 1:0

101

B Log del Ensayo del Caso de Uso Real

149 USB HUB connected at index 1.

150 USB DEV 1 setting configuration to 1

151 USB DEV 1 releasing lock on address 0.

152

153 USB HUB 1 requesting HUB descriptor.

154 USB HUB 1 wHubCharacteristics (GLOBAL_OVC)

155 USB HUB 1 requesting HUB status.

156 USB HUB 1 wHubStatus & wHubChange (none)

157 USB HUB 1 preparing to power up ports.

158 USB HUB 1 requesting SetPortFeature(PORT_POWER) from port 0.

159 USB HUB 1 port 0 powered up.

160 USB HUB 1 requesting SetPortFeature(PORT_POWER) from port 1.

161 USB HUB 1 port 1 powered up.

162 USB HUB 1 requesting SetPortFeature(PORT_POWER) from port 2.

163 USB HUB 1 port 2 powered up.

164 USB HUB 1 requesting SetPortFeature(PORT_POWER) from port 3.

165 USB HUB 1 port 3 powered up.

166 USB HUB 1 requesting port 0 status.

167 USB HUB 1 port 0 status (POWER)

168 USB HUB 1 requesting port 1 status.

169 USB HUB 1 port 1 status (POWER)

170 USB HUB 1 requesting port 2 status.

171 USB HUB 1 port 2 status (POWER)

172 USB HUB 1 requesting port 3 status.

173 USB HUB 1 port 3 status (POWER)

174

175 USB HUB 1 status/port change detected.

176 USB HUB 1 requesting port 3 status.

177 USB HUB 1 port 3 status (CONNECTION, POWER)

178 USB HUB 1 requesting ClearPortFeature(C_PORT_CONNECTION) from port 3.

179 USB attached device at index 2 with parent HUB (1,3).

180 USB waiting for device 2’s powerline to settle.

181 USB DEV 2 powered, locking address 0 on Host and resetting.

182 USB HUB 1 reset pending on port 3, going for reset.

183 USB HUB 1 requesting SetPortFeature(PORT_RESET) from port 3.

184 USB HUB 1 status/port change detected.

185 USB HUB 1 requesting port 3 status.

186 USB HUB 1 port 3 status (CONNECTION, Full-Speed, ENABLE, POWER)

187 USB DEV 2 reset done.

188 USB HUB 1 requesting ClearPortFeature(C_PORT_RESET) from port 3.

189

190 USB DEV 2 connected at full-speed.

191 USB DEV 2 requesting MPS.

192 USB DEV 2 with MPS = 8, resetting again.

193 USB HUB 1 reset pending on port 3, going for reset.

194 USB HUB 1 requesting SetPortFeature(PORT_RESET) from port 3.

195 USB HUB 1 status/port change detected.

196 USB HUB 1 requesting port 3 status.

197 USB HUB 1 port 3 status (CONNECTION, ENABLE, POWER)

198 USB DEV 2 reset done.

102

Tesis de Grado – Stack USB

199 USB HUB 1 requesting ClearPortFeature(C_PORT_RESET) from port 3.

200 USB DEV 2 setting address to 3.

201 USB DEV 2 requesting device descriptor.

202 USB DEV 2 with VendorID:ProductID 046D:49735

203 USB DEV 2 requesting first 9 Bytes of configuration descriptor.

204 USB DEV 2 cfg. desc. is 34 bytes long.

205 USB DEV 2 requesting entire configuration descriptor.

206 USB DEV 2 supports remote wakeup.

207 USB probing HUB driver ... FAILED

208 USB probing HID driver ... SUCCESS

209 USB assigning HUB driver to dev:iface 2:0

210 USB HID connected at index 0.

211 USB DEV 2 setting configuration to 1

212 USB DEV 2 releasing lock on address 0.

213

214 USB HID 0 requesting HID descriptor.

215 USB HID 0 opening device: mouse0

216 USB HID 0 transfer started, waiting for completion.

217 USB HID 0 transfer complete.

218

219 USB HUB 0 status/port change detected.

220 USB HUB 0 requesting port 3 status.

221 USB HUB 0 port 3 status (CONNECTION, POWER)

222 USB HUB 0 requesting ClearPortFeature(C_PORT_CONNECTION) from port 3.

223 USB attached device at index 3 with parent HUB (0,3).

224 USB waiting for device 3’s powerline to settle.

225 USB DEV 3 powered, locking address 0 on Host and resetting.

226 USB HUB 0 reset pending on port 3, going for reset.

227 USB HUB 0 requesting SetPortFeature(PORT_RESET) from port 3.

228 USB HUB 0 status/port change detected.

229 USB HUB 0 requesting port 3 status.

230 USB HUB 0 port 3 status (CONNECTION, High-Speed, ENABLE, POWER)

231 USB DEV 3 reset done.

232 USB HUB 0 requesting ClearPortFeature(C_PORT_RESET) from port 3.

233

234 USB DEV 3 connected at high-speed.

235 USB DEV 3 requesting MPS.

236 USB DEV 3 with MPS = 64, resetting again.

237 USB HUB 0 reset pending on port 3, going for reset.

238 USB HUB 0 requesting SetPortFeature(PORT_RESET) from port 3.

239 USB HUB 0 status/port change detected.

240 USB HUB 0 requesting port 3 status.

241 USB HUB 0 port 3 status (CONNECTION, ENABLE, POWER)

242 USB DEV 3 reset done.

243 USB HUB 0 requesting ClearPortFeature(C_PORT_RESET) from port 3.

244 USB DEV 3 setting address to 4.

245 USB DEV 3 requesting device descriptor.

246 USB DEV 3 with VendorID:ProductID 046D:0825

247 USB DEV 3 requesting first 9 Bytes of configuration descriptor.

248 USB DEV 3 cfg. desc. is 2466 bytes long.

103

B Log del Ensayo del Caso de Uso Real

249 USB DEV 3 requesting entire configuration descriptor.

250 USB probing HUB driver ... FAILED

251 USB probing HID driver ... FAILED

252 USB DEV 3, iface 0 could not be assigned a driver.

253 USB probing HUB driver ... FAILED

254 USB probing HID driver ... FAILED

255 USB DEV 3, iface 1 could not be assigned a driver.

256 USB probing HUB driver ... FAILED

257 USB probing HID driver ... FAILED

258 USB DEV 3, iface 2 could not be assigned a driver.

259 USB probing HUB driver ... FAILED

260 USB probing HID driver ... FAILED

261 USB DEV 3, iface 3 could not be assigned a driver.

262 USB DEV 3 setting configuration to 1

263 USB DEV 3 releasing lock on address 0.

264

265 USB HUB 1 status/port change detected.

266 USB HUB 1 requesting port 0 status.

267 USB HUB 1 port 0 status (CONNECTION, POWER)

268 USB HUB 1 requesting ClearPortFeature(C_PORT_CONNECTION) from port 0.

269 USB unable to allocate device connected at HUB 1 port 0. Maximum number of

devices reached.

270

271 USB HUB 1 status/port change detected.

272 USB HUB 1 requesting port 0 status.

273 USB HUB 1 port 0 status (DISCONNECTION, POWER)

274 USB HUB 1 requesting ClearPortFeature(C_PORT_CONNECTION) from port 0.

275

276 USB root device disconnection detected.

277 USB releasing device 2

278 USB removing dev:iface 2:0 from HID driver.

279 USB releasing device 1

280 USB removing dev:iface 1:0 from HUB driver.

281 USB releasing device 3

282 USB releasing device 0

283 USB removing dev:iface 0:0 from HUB driver.

Listado 19: Log serie del ensayo del caso de uso real

104