Einleitung Device Deskriptor Konfigurations Deskriptor Interface Deskriptor Endpunkt Deskriptor String Deskriptor |
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.
|
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:
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. . Er enthält den Strombedarf des Device in der Konfiguration1, sowie die Zahl der Interfaces dieser Konfiguration: in diesem Fall 1 . Er enthält Informationen über den Typ dieses Interfaces (Maus, Tastatur, Massenspeicher ...), sowie die Zahl seiner Endpunkte: in diesem Fall 2 . er beschreibt die Speicher-Größe, Datenrichtung und Betriebsart des Endpunktes Nr. 1 . er beschreibt die Speicher-Größe Datenrichtung und Betriebsart des Endpunktes Nr. 2 |
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.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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.
Der Konfigurations-Deskriptor enhält u.A. die Anzahl der in dieser Konfiguration enthaltenen Interfaces, sowie den maximalen Stromverbrauches des Devices in dieser Konfiguration.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bus-powered;0x80 |
|
|
|
|
|
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).
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
in: 0x81..0x8F |
|
|
|
|
|
|
|
|
|
|
|
|
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.