USB

Présentation du protocole

L'USB (Universal Serial Bus) est un protocole de communication série.
Du point de vue utilisateur, le bus USB se présente sous la forme d'une architecture étoilée et pyramidale, l'hôte se trouvant au centre du réseau, et les périphériques à l'extérieur. Les échanges de données se font à une vitesse prédéfinie dans la spécification USB 1.1: 1,5 Mbits/s ou 12 Mbits/s selon la tolérance du périphérique concerné.
L'intérêt principal de ce bus est le fait qu'un grand nombre de périphériques (jusqu'à 126) peuvent être connectés simultanément au même hôte, et qu'à tout moment, il est possible de les débrancher et de les rebrancher sans redémarrer le contrôleur hôte (c'est-à-dire l'ordinateur).
Cependant, si pour l'utilisateur la manipulation est aisée, pour le concepteur de circuit électronique ou de logiciels faisant appel aux ports USB, le protocole est loin d'être facile à comprendre et à maîtriser.

Description physique

Le bus USB utilise 4 fils, ainsi que des connecteurs particuliers. Deux des fils permettent d'acheminer l'alimentation électrique au périphérique (une souris USB par exemple), et deux véhiculent les données elles-mêmes.

img3
Connecteur de type A

img4
Connecteur de type B

La spécification USB impose une tension maximale de 5V sur les fils et un courant de 500 mA au plus.

img2

Les fils d'alimentation sont toujours au potentiel de 5V. Pour les2 fils de données, la tension différentielle entre les deux peut valoir 0, 3,3 ou 5V.

Protocole

La spécification USB impose un protocole de communication en plusieurs couches superposées ; ce qui permet à l'utilisateur de ne manipuler que la ou les couches supérieures.

Schéma type des transactions

Les transactions USB se font par l'intermédiaire de l'émission de plusieurs paquets dont le format obéit à un standard.
Chaque transaction consiste en la succession
- d'un paquet Jeton (Token)
- d'un paquet de données (DATA)
- d'un paquet d'état (HandShake)

Décrivons rapidement le schéma type d'une communication USB :
le bus est géré par l'hôte, ce qui signifie que c'est lui qui initie toutes les transactions en envoyant un paquet Jeton dans lequel figurent le type de transaction (lecture ou écriture), l'adresse du périphérique de destination, et la terminaison désignée (nous reviendrons sur ce terme plus loin).
Suit le paquet DATA qui contient les informations réellement utiles dans la transaction, puis le paquet d'état qui indique si l'échange s'est correctement déroulé.

Pour plus de détails sur le contenu de chaque paquet, se reporter à la spécification USB.


Les terminaisons

Nous avons déjà mentionné cette terminologie au-dessus. En fait, comme l'indique le schéma ci-dessous, chaque périphérique USB est décomposé en plusieurs sous blocs, possédant chacun un rôle différent dans la communication. Il s'agit ici de décrire de manière générale cette architecture, et non de développer complètement le fonctionnement précis de chaque étage ; pour cela, il conviendra de se reporter à la spécification.

img4

Nous pouvons distinguer 3 sous blocs principaux :
- La partie qui décode l'adresse émise par l'hôte dans le paquet Jeton. Cette entité permet au périphérique de savoir que c'est bien à lui que l'hôte s'adresse,
- La partie terminaison,
- La partie réalisant la fonction USB proprement dit.

Les terminaisons peuvent être vues comme des intermédiaires, des tampons entre le bus et la fonction USB. En effet, il n'est pas possible pour le bus d'écrire directement dans la fonction, et pour la fonction d'écrire directement sur le bus. Les données sont donc stockées temporairement (jusqu'à ce que l'hôte ou le périphérique les lisent) dans les terminaisons. C'est donc pour cette raison que dans le paquet Jeton, l'hôte précise la terminaison à laquelle il veut s'adresser.

On peut remarquer qu'une même fonction USB peut utiliser plusieurs terminaisons. Dans la spécification UB 1.1 , le nombre de paires de terminaisons est limité à 2, c'est-à-dire que les communications peuvent se faire via EP0 In, EP0 Out, EP1 In et EP1 Out. La paire de terminaisons utilisée par défaut par l'hôte pour dialoguer avec le périphérique est EP0.

Les types de transfert

La spécification de l'USB définit 4 types de transferts entre l'hôte et les périphériques.

- Les transferts de commande

Ce sont les transferts qui sont généralement utilisés pour les opérations de commande et d'état. L'énumération du périphérique par exemple, que nous détaillerons plus loin, se fait en mode transfert de commande.
Ces transferts surviennent généralement en paquets directs et par rafales initiés par l'hôte, de manière à utiliser le meilleur rendement de livraison.
Le transfert de commande est fiable : en cas d'erreur sur un paquet, il est répété.

- Les transferts d'interruption

Ce type de transfert est très utilisé, puisque c'est celui qui est mis en oeuvre pour les souris, les claviers,… En fait, quand le périphérique a une donnée à transférer à l'hôte, il lui faut attendre que l'hôte l'interroge pour lui signaler qu'il a une information urgente à transférer. En fait, ce n'est pas réellement un système d'interruption au sens informatique du terme. L'hôte n'interrompt pas le transfert en cours avec un autre périphérique pour se précipiter vers le périphérique nécessitant un transfert urgent.

- Les transferts isochrones

C'est certainement le mode de transfert le plus efficace en matière de débit, de disponibilité de la bande passante et du délai d'attente. Mais c'est aussi le plus complexe. Il est utilisé principalement pour des données ayant des durées de vie critiques tels que les trames audio ou vidéo. Ce type de transfert assure un débit minimum, mais il y peut arriver que certains paquets soient erronnés.

- Les transferts en Bloc

Ce type de transfert est utilisé quand il faut transférer une grande quantité d'information pendant en temps relativement court. Par exemple, un appareil photo ou un caméscope utilise ce type de transfert pendant lequel 90% de la bande passante du bus est attribué au périphérique et les paquets erronnés sont répétés.

Les descripteurs USB

Ce point est essentiel pour le fonctionnement correct du bus. En effet chaque périphérique possède des caractéristiques propres qui le différencient du voisin. L'hôte doit être en possession de toutes ces caractéristiques pour initier une communication avec le périphérique en question.

Pour cela, chaque périphérique possède « en dur » une série de descripteurs qui précisent complètement son identité, la façon de communiquer avec lui, …

Il nous semble inutile pour cette partie de développer plus. La page mise en lien est très complète et explique très bien toutes les subtilités des descripteurs.

La liste des descripteurs sera allongée quand nous traiterons de la spécification HID…

L'hôte accède aux différents champs des descripteurs par un jeu de requêtes, que nous ne détaillerons pas.

 

L'énumération

Le concept de l'énumération est plutôt simple : il s'agit pour le périphérique nouvellement connecté au bus de s'identifier auprès de l'hôte, pour que celui-ci lui attribue une adresse.

En pratique, l'hôte remarque qu'un nouveau périphérique a été connecté au bus en détectant la variation de tension résultant.
Après avoir attendu que l'alimentation 5V se stabilise, l'hôte émet un Reset , autorisant ainsi le périphérique à répondre sur l'adresse 0 (qui est réservée à cet effet).
Le périphérique, à la demande de l'hôte, envoie la liste de ses descripteurs, et se voit attribuer une adresse.

De son côté, l'hôte informe le système d'exploitation de l'ordinateur qu'un périphérique a été connecté, pour qu'il se charge d'aller chercher le driver correspondant.

Le périphérique est alors prêt à fonctionner.

Liens

Le site officiel de l'USB : http://www.usb.org

Les cours de Bernard Acquier zippés au format PDF , très complet.

La spécification USB 1.1

 

La spécification HID

La spécification HID (Human Interface Device) est une couche d'abstraction plus élevée que le protocole USB.

Introduction

Le bus USB définit une architecture de communication qui permet à un ordinateur de se connecter à des périphériques simplement en utilisant 4 fils. Précisément, l'USB établit une communication série sur 2 fils à un débit de 1.5 ou 12 Mbits/s (USB 1.1). L'USB peut également configurer les périphériques au démarrage ou à leur connexion. Ces périphériques sont divisés en plusieurs classes. Chaque classe définit un comportement commun et des protocoles pour les périphériques qui utilisent les mêmes fonctionnalités. Quelques exemples de classes de périphériques USB sont indiqués ci-dessous :

Classe
Exemple
Display
Ecran
Communication
Modem
Audio
Hauts-parleurs
Mass storage
Disques durs
Human Interface
Souris, claviers, …


Cette page a pour but de décrire la classe HID et fonctionnement dans l'architecture USB.

La classe HID consiste à la base en un ensemble de périphériques utilisés par les humains pour contrôler des systèmes informatiques. Des exemples typiques de périphériques de cette classe sont :
- les claviers et les dispositifs de pointage ( souris, trackballs, joysticks, …),
- les boutons,
- les contrôles que l'on peut trouver sur des périphériques tels que les téléphones, les dispositifs de simulation comme les volants, les pédales, …

Compléments sur les descripteurs de périphériques

Nous avons vus dans la partie consacrée à l'USB, et notamment sur la page de Bernard Acquier, la liste des descripteurs que le périphérique expédie à l'hôte pour s'identifier. Notamment, au niveau des descripteurs d'interface, il existe un champ nommé « bInterfaceClasse » qui spécifie le type de classe à laquelle appartient le périphérique. C'est à ce niveau que l'on peut définir un périphérique comme appartenant à la classe HID.

Cependant, il faut également rajouter un paragraphe de descripteurs de périphérique HID, dans lequel toutes les informations sur cette classe seront exposées.
Notamment, ce paragraphe identifie quels autres descripteurs de classe HID sont présents, et précise leur taille. Parmi ces descripteurs, il existe principalement un Report Descriptor et un « Physical Descriptor.

Un Report Descriptor décrit le format des données contenues dans les paquets échangés.

Par exemple, il définit des champs qui décrivent une position ou l'état d'un bouton. Ces champs sont utilisés pour permettre à un logiciel de faire la correspondance entre l'action sur le périphérique et le déclenchement d'une action logicielle.

Voici pour information, le contenu du descripteur de périphérique HID

Partie Offset/Taille Description
bLength 0/1 Taille totale du descripteur HID
bDescriptorType 1/1 Nom spécifiant le type du descripteur HID
bcdHID 2/2 Version de la spécification HID utilisée
bCountryCode 4/1

Numéro du pays

bNumDescriptors 5/1 Nombre de descripteurs de classe
bDescriptorType 6/1 Nom du type du descripteur de classe
wDescriptorLength 7/2 Taille totale du Report Descriptor
[bDescriptorType] 9/1 Nom du type du descripteur de classe optionnel

[wDescriptorLength]

10/2 Taille totale du descripteur optionnel

 

Report Descriptor

La classe HID n'utilise pas la notion de sous-classe, originellement créée pour différencier les protocoles différents des périphériques HID. En effet, à la vue du grande nombre de ces périphérique, il est vite devenu impossible de tous en répertorier les protocoles de communication.
Ainsi, l'idée est venue d'un descripteur décrivant la façon dont les données transitent entre l'hôte et le périphérique HID. Ainsi, chaque périphérique peut définir son propre protocole de transfert. C'est au driver générique HID du système d'exploitation de formater les données du paquet reçu selon le Report Descriptor.

Un Report Descriptor est composé de plusieurs blocs d'informations diverses, appelées Items. On peut donc voir le Report Descriptor comme un agglomérat d'Items. Cette suite d'Items est envoyée dès la connection du périphérique au bus USB, avec les autres descripteurs.

Au niveau du driver générique HID, une analyse linéaire est effectuée sur ce Report Descriptor pour permettre à l'application de mettre en correspondance les données reçues avec l'action réalisée par l'utilisateur sur le périphérique.

Du point de vue de l'analyseur, un périphérique de classe HID ressemble à l'organigramme suivant (les termes sont en anglais, et seront explicités par la suite).

imghid

Même si ce système de Report ne paraît pas évident, c'est là que réside toute la force de la classe HID. En effet, il est possible pour une application de dialoguer avec n'importe quel périphérique HID, sans nécessairement en connaître la nature, juste en analysant son Report.

C'est avec l'exemple d'une souris que nous allons illustrer le concept de Report .

Un Report Descriptor se présente sous la forme d'une liste de paramètres regroupés, comme indiqué sur le shéma précédent, en Reports et en Collections. Un Report représente un transfert sur le Bus USB. Il existe en fait 3 types de Reports :

- Ceux qui permettent de recevoir des données du périphérique (de type Input),

- Ceux qui permettent d'envoyer des données au périphérique (de type Output),

- Ceux qui permettent d'envoyer et de recevoir des informations de configuration entre l'hôte et le périphérique (de type Feature).

Les Collections permettent de regrouper plusieurs éléments du Report Descriptor ensemble.

Les Usages permettent de mettre en relation un champ ou un ensemble de champs du Report Descriptor avec une ou plusieurs interactions physiques sur le périphérique.

Il existe des Usages et des Collections déjà définies dans la spécification HID. Pour s'en convaincre, il s'agit de regarder dans la liste des identificaters USB!

Voici un Report de souris :

Usage Page (Generic Desktop)
Usage (Mouse)
Collection (Application)
.........Usage (Pointer)
.........Collection (Physical)
.................Usage Page (Buttons)
.................Usage Minimum (01)
.................Usage Maximum (03)
.................Logical Minimum (0)
.................Logical Maximum (1)
.................Report Count (3)
.................Report Size (1)
.................Input (Data, Variable, Absolute)
.................Report Count (1)
.................Report Size (5)
.................Input (Constant)
.................Usage Page (Generic Desktop)
.................Usage (X)
.................Usage (Y)
.................Logical Minimum (-127)
.................Logical Maximum (127)
.................Report Count (2)
.................Report Size (8)
.................Input (Data, Variable, Relative)
.........End Collection
End Collection

Ainsi, comme nous pouvons le voir, une collection est définie dans un usage de type "Pointer". Cette collection possède 1 Report Input composé de 3 champs, définissant le format de données comme suit :

Etat du bouton gauche: 1 bit
Etat du bouton central : 1 bit
Etat du bouton droit : 1 bit
5 bits de remplissage (Zero Padding)
Valeur relative du déplacement sur X : 8 bits
Valeur relative du déplacement sur Y: 8 bits

Les 5 bits de remplissage sont simplement placés ici pour terminer l'octet commencé par l'état des 3 boutons.

Il est à noter que dans le cas de plusieurs Reports de même type, déclarés dans des Usages différents, il est indispensable de rajouter une identifaction (Report ID en anglais) pour permettre à l'analyseur du driver HID générique de s'y retrouver.