USB-Deskriptoren

in Entwicklung

zurück zu USB , Interfaces , Elektronik , Homepage


 
Einleitung
Device Deskriptor
Konfigurations Deskriptor
Interface Deskriptor
Endpunkt Deskriptor
String Deskriptor

USB mit PIC18Fxx5x

zurück zu USB



Einleitung

ein Device in der Einschalt-Konfiguration Nr. 0 Nach dem Einschalten der Betriebsspannung oder nach dem Anstecken an den USB-Bus ist ein Device sozusagen in seiner Konfiguration Nr. 0.

Es hat die fiktive Device-Adresse 0 und besitzt genau einen Endpunkt, den Endpunkt 0. Über diesen Endpunkt0 kann der Controller die vollständige Struktur des Device in Form von Device-Deskriptoren auslesen. Außerdem kann er das Device über diesen Endpunkt0 steuern, ihm z.B. eine richtige Adresse geben.

Ein Device kann verschiedene Konfigurationen (über die Einschalt-Konfiguration Nr. 0 hinaus) einnehmen.
In jeder Konfiguration hat das Device mindestens ein Interface.
Die Interfaces haben wiederum Endpunkte.

Dieser Aufbau wird mit den Deskriptoren (kleinen Datensätzen) beschrieben.

  • Jedes Device hat genau einen Device-Deskriptor. 
  • Je nachdem wie viele Konfigurationen ein Device besitzt, kann es ein oder mehrere Konfigurations-Deskriptoren haben. 
  • Zu jedem Konfigurations-Deskriptor gehört dann mindestens ein Interface-Deskriptor.
  • Zu jedem Interface-Deskriptor gehört mindestens ein Endpunkt-Deskriptor.
alle Deskriptoren
Beispiel-Konfiguration Nr. 1 Beispiel:

Ein Device soll nur (neben der Einschalt-Konfiguration Nr. 0) nur eine einzige Konfiguration beherrschen.Diese Konfiguration ist in der nebenstehenden Grafik dargestellt. Da die Konfigurations-Nummer 0 schon für die Einschaltkonfiguration vergeben ist, bekommt diese erste Einsatz-Konfiguration die Nummer 1.

In dieser Konfiguration 1 besitzt das Device (dem in diesem Beispiel vom Controller zuvor die USB-Bus-Adresse 1 zugewiesen wurde) nur ein Interface. Das ist das Interface mit der Nummer 0.

Das Interface0 besitzt ()neben dem Steuer-Endpunkt 0) zwei zusätzliche Endpunkte. Da es den Endpunkt0 schon gibt (er existiert in jeder Konfiguration, auch wenn er nicht explizit mit einem Deskriptor beschrieben wird, da er stets für die Steuerung des Device nötig ist.) sind das die Endpunkte Nummer 1 und 2.

Um das Beispiel-Device zu beschreiben, sind folgende Deskriptoren nötig:
  • der Device-Deskriptor

  • Er sagt, wie groß der Endpunkt0 ist, damit der Controller über den Endpunkt0 das Device steuern kann.
    Außerdem enthält er Informationen über den Hersteller, den Typ und die Seriennummer des Device,
    und enthält die Anzahl der Konfigurationen: in diesem Fall 1.
    .
  • der Configurations-Deskriptor Nummer1

  • Er enthält den Strombedarf des Device in der Konfiguration1,
    sowie die Zahl der Interfaces dieser Konfiguration: in diesem Fall 1
    .
  • der Interface-Deskriptor Nummer0

  • Er enthält Informationen über den Typ dieses Interfaces (Maus, Tastatur, Massenspeicher ...),
    sowie die Zahl seiner Endpunkte: in diesem Fall 2
    .
  • der Endpoint-Deskriptor Nummer1

  • er beschreibt die Speicher-Größe, Datenrichtung und Betriebsart des Endpunktes Nr. 1
    .
  • der Endpoint-Deskriptor Nummer2

  • er beschreibt die Speicher-Größe Datenrichtung und Betriebsart des Endpunktes Nr. 2
Liest der Controller diese 5 Deskriptoren via Endpunkt0 aus dem Device aus, dann kennt er dessen Aufbau.
Deskriptoren für das Beispiel-Device

speziell für PIC18Fxx5x
Als Hardware existieren in einem USB-PIC eigentlich nur die Schnittstelle zum Controller und die 16 Endpunkte. Alles dazwischen (Device, Configuration, Interface) ist nur Teil der Firmware, und kann deshalb beliebig verändert werden.
Da der PIC nur eine USB-Schnittstelle hat ist er auch nur ein Device. Er kann aber beliebig viele Configurationen mit beliebig vielen Interfaces haben, solange dafür nicht mehr als 16 Endpunkte nötig sind.
Der Firmware wird die Struktur des Device über die gleichen Deskriptoren mitgeteilt, die auch an den Controller übermittelt werden.


Device Deskriptor

Die Länge des Device-Deskriptors hängt von der USB-Version ab. In der Version 2.0 ist die Länge 18 Byte. Die folgende Tabelle stellt die Struktur des Device-Descriptors da. Werte, die für für typische PIC18Fxx5x-Anwendungen immer gleich bleiben können , habe ich schon eingetragen.
 
Device-Deskriptor
Feldname
Größe in Byte
Wert
Beschreibung
bLength 
1
0x12
Länge des Deskriptors in Byte
bDescriptorType
1
0x01
Kennzeichen für Device-Deskriptor
bcdUSB
2
0x0200
Kennzeichen für USB2.0 (BCD)
bDeviceClass
1
0x00
Geräteklasse
bDeviceSubClass
1
0x00
Geräteunterklasse
bDeviceProtocol
1
0x00
Geräteprotokoll
bMaxPacketSize0
1
 8 / 16 / 32 / 64
Größe des Pufferspeichers von Endpunkt0
idVendor
2
0x04D8
Hersteller-ID von Microchip
idProduct
2
 0x0000..0xFFFF
Produkt-ID
bcdDevice
2
 0x0000..0x9999
Device-Relaise (BCD)
iManufacturer
1
0x01
Index des Strings für den Herstellernamen
iProduct
1
0x02
Indes des Strings der Produktbeschreibung
iSerialnumber
1
0x00
Index des Strings mit der Seriennummer des Device
bNumConfigurations
1
 1...255
Anzahl der möglichen Configurationen

bMaxPacketSize0
Das ist de Puffergröße des Endpunktes0 (in Byte).

idVendor
Jeder Hersteller eines USB-Device bekommt eine 2 Byte lange Identifikationsnummer, die Vendor-ID (Hersteller-ID). Microchip ist 0x04D8. Da der private Bastler wohl kaum eine eigene Vendor-ID bekommen wird, sollten PIC-Bastler die Microchip-ID verwenden können

idProduct
Jedes Produkt eines Device-Herstellers bekommt vom Hersteller eine 2 Byte lange Produkt-Identifikationsnummer zugewiesen. Anhand von Vendor-ID und Product-ID entscheidet der Controller, welcher Treiber für dieses Gerät geladen (bzw. installiert) werden muss. Aus diesem Grunde sollte die Kombination aus Product-ID und Vendor-ID eindeutig sein.
Der Microchip Custom Driver ist zuständig, wenn in einem Device die Vendor-ID 0x004D mit der Product-ID 0x000B oder 0x000C gefunden wird. Das lässt sich aber beliebig erweitern, wenn man den entsprechenden Eintrag in der Datei mchpusb.inf (liegt in C:\MCHPFSUSB\Pc\MCHPUSB Driver\Release) erweitert.

bcdDevice
Das ist die Revisionsnummer des Device in BCD-Code. Dem USB-Controller ist sie egal. Die Anwendungssoftware mag sie benutzen, um unterschiedliche Revisionen des gleichen Produkts unterschiedlich zu behandeln.

iManufacturer / iProduct / iSerialnumber
Das sind Indexe auf Text-Strings. Mit  diesen Strings lassen sich der Herstellername, die Produktbezeichnung und die Seriennummer des Produktes im Klartext angeben. Der Controller benötigt diese Strings nicht. Will man sie nicht verwenden, dann setzt man den Wert des Indexes einfach auf 0. Andernfalls muss man die Strings im String-Deskriptor definieren.

bNumConfigurations
Das ist die Anzahl der Konfigurationen, die das Device neben der Einschalt-Konfiguration0 noch annehmen kann.


Konfigurations Deskriptor

Im Device Deskriptor stand die Anzahl der möglichen Konfigurationen des Devices. Für jede dieser Konfigurationen muss ein Konfigurations-Deskriptor existieren. Diese sind durchnummeriert. Der erste ist CFG01.

Der Konfigurations-Deskriptor enhält u.A. die Anzahl der in dieser Konfiguration enthaltenen Interfaces, sowie den maximalen Stromverbrauches des Devices in dieser Konfiguration.
Konfigurations-Deskriptor
Feldname
Größe in Byte
Wert
Beschreibung
bLength 
1
0x09
Länge des Deskriptors in Byte
bDescriptorType
1
0x02
Kennzeichen für Konfigurations-Deskriptor
wTotalLength
2
 
Länge der gesamten Konfiguration mit Interface- und Endpoint-Deskriptoren
wNumInterfaces
1
1..16
Anzahl der Interfaces in dieser Konfiguration
bConfigurationValue
1
 1..
Kennummer mit der diese Konfiguration via SetConfiguration() ausgewählt wird.
iConfiguration
1
 0
Index des Strings mit der Beschreibung der Konfiguration
bmAttributes
1
self-powered:0xC0
bus-powered;0x80
Einstellung der Stromversorgung und von remote Wakeup
bMaxPower
1
50..250
Stromaufnahme aus dem USB-Bus in der Einheit "2 mA"

wTotalLength
Zu einer Konfiguration gehören ja Interfaces und Endpunkte mit ihren Deskriptoren. Der Controller will den Konfigurationsdeskriptor zusammen mit seinen Interface-Deskriptoren und dere Endpoint-Deskriptoren in einem rutsch einlesen. Deshalb muss er wissen, wie lang dieses Paket insgesamt ist. Die Länge (in Byte) wird hier eingetragen.

wNumInterfaces
Das ist die Anzahl der Interfaces in dieser Konfiguration.

bConfigurationValue
Das ist die Kennummer dieser Konfiguration. Soll das Device später diese Konfiguration einnehmen, dann wird dafür die Funktion SetConfiguration() mit dieser Kennummer aufgerufen. Es ist sinnvoll, dafür einfach die Nummer der Konfiguration (z.B. 1) zu wählen.

iConfiguration
Das ist ein Index auf einen Text-String. Mit  diesen Strings lässt sich für diese Konfiguration ein Name im Klartext angeben. Der Controller benötigt diesen String nicht. Will man ihn nicht verwenden, dann setzt man den Wert des Indexes einfach auf 0. Andernfalls muss man den String im String-Deskriptor definieren.

bmAttributes
 

bMaxPower
Dieser Eintrag ist die maximale Stromaufnahme des Device in dieser Konfiguration in der Einheit "2 mA". Eine 1 bedeutet also 2mA und eine 10 bedeutet 20 mA.
Typisch sind Werte zwischen 50 (100 mA) und dem Maximal zulässigen Wert 250 (500 mA).
 


Interface Deskriptor

Im Konfigurations Deskriptor stand die Anzahl der Interfaces dieser Konfiguration. Für jedes dieser Interfaces muss ein Interface-Deskriptor existieren. Diese sind durchnummeriert. Der erste hat die Nummer 0.
Der Interface-Deskriptor enhält u.A. die Anzahl der in dieser Konfiguration enthaltenen Endpunkte.
Interface-Deskriptor
Feldname
Größe in Byte
Wert
Beschreibung
bLength 
1
0x09
Länge des Deskriptors in Byte
bDescriptorType
1
0x04
Kennzeichen für Interface-Deskriptor
bInterfaceNumber
1
 0...
Nummer dieses Interfaces 
bAlternateSettings
1
 0
 
bNumEndpoints
1
 1..16
Anzahl der Endpunkte dieses Interfaces
bInterfaceClass
1
 0
 Klasse
bInterfaceSubClass
1
 0
 SubKlasse
bInterfaceProtokoll
1
 0
 Protokoll
iInterface
1
 0
Index des Strings mit der Beschreibung des Interfaces

bInterfaceNumber
Die Nummer dieses Interfaces. Das erste Interface bekommt die Nummer 0 u.s.w.

bAlternateSettings
 

bNumEndpoints
Das ist die Anzahl der Endpunkte in diesem Interface.

bInterfaceClass / bInterfaceSubClass / bInterfaceProtokoll
Einige USB-Devices sind dem Betriebssystem wohl bekannt, und benötigen deshalb keine zusätzlichen Treiber (Treiber sind schon in Windows enthalten). Dabei handelt es sich z.B. um Tastaturen, Mäuse, Memorysticks...
Wenn man ein solches Device entwickelt hat, trägt man die für so ein Device festgelegten Interface-Class, Interface-SubClass und Interface-Protokoll in den Interface-Deskriptor ein.
Warum nicht im Device-Deskriptor? Weil ein Device durchaus mehrere Geräte in sich vereinen kann. Der per USB an den PC angeschlossenen Funkempfänger für die Funkmaus und die Funktastatur ist für den PC sowohl Maus wie auch Tastatur. Das sind dann einfach mehrere Interfaces in einem Device.
Ist das Device kein Windows-bekanntes Standardgerät, dann trägt man  überall 0 ein, und muss einen speziellen Treiber verwenden. (z.B. den Microchip Custom Driver)

iInterface
Das ist ein Index auf einen Text-String. Mit  diesen Strings lässt sich für dieses Interface ein Name im Klartext angeben. Der Controller benötigt diesen String nicht. Will man ihn nicht verwenden, dann setzt man den Wert des Indexes einfach auf 0. Andernfalls muss man den String im String-Deskriptor definieren.
 


Endpunkt Deskriptor

Im Interface Deskriptor stand die Anzahl der Endpunkte dieser Konfiguration. Für jeden dieser Endpunkte muss ein Endpunkt-Deskriptor existieren. Dieser enthält die Endpunkt-Nummer, die Datenrichtung und die Betriebsart des Endpunktes.
 
Endpoint-Deskriptor
Feldname
Größe in Byte
Wert
Beschreibung
bLength 
1
0x07
Länge des Deskriptors in Byte
bDescriptorType
1
0x05
Kennzeichen für Endpoint-Deskriptor
bEndpointAdress
1
out: 0x01..0x0F
in: 0x81..0x8F
Nummer und Datenrichtung des Endpunktes
bmAttributes
1
 
Transfer-Typ & Extrainfos für den isochonous-Mode
wMaxPacketSize
2
 
maximale Datenpaketgröße
bInterval
1
 
Abfrageintervall in der Einheit "1 ms" (low speed) oder "125 µs" (full speed) oder als dBµs

bEndpointAdress
Dieser Wert beinhaltet die Nummer des Endpunktes und seine Datenrichtung. Im PIC gibt es maximal 16 Endpunkte mit den Adressen 0x00 bis 0x0F. Der Endpunkt 0x00 ist aber als Control-Endpunkt schon fest vergeben. Es bleiben also die Adressen 0x001 bis 0x0F zur Auswahl.
Das MSB (Bit 7) dieses Byte kennzeichnet die Datenrichtung. Eine 0 (also 0x01 .. 0x0F) steht für den Datenfluss vom Controller zum Device (out). Eine 1 (also 0x81 .. 0x8F) steht dagegen für den Datenfluss vom Device zum Controller (in).

bmAttributes
 

wMaxPacketSize
 

bInterval
Hat ein Device in einem Endpunkt  Daten für den Controller, so kann es ihm das leider nicht mitteilen. Stattdessen kann es den Controller beauftragen, den Endpunkt in regelmäßigen Abständen auf neue Daten abzufragen (pollen).
Das Abfrageintervall wird in Schritten von 125µs (full-speed-USB) bzw. 1 ms (low speed) eingestellt. Ein Wert von 32 entspricht einer Abfrage alle 4 ms (125 µs x 32 = 4 ms) oder einer Abfragefrequenz von 250 Hz.
Bei Control- und Bulk-Endpunkten wird dieser Wert ignoriert.

 


String Deskriptor

In anderen Deskriptoren gab es Indexe auf Strings. In solchen Strings lassen sich z.B. der Name des Herstellers oder der Name des Device im Klartext ablegen. Nicht immer ist ein solcher String sinnvoll, und im Prinzip kann man auf die Strings auch ganz verzichten. Will man in einem Deskriptor nicht auf einen String verweisen, dann setzt man den Index des Strings im Deskriptor einfach auf 0.
 

 
weiter zu USB mit PIC18Fxx5x
 
nach oben

zurück zu USB , Interfaces , Elektronik , Homepage


Autor: sprut
erstellt: 01.02.2006
letzte Änderung: 03.03.2006