| Zeile 54: | Zeile 54: | ||
Zu einem bestimmten Zeitraum besitzt ein Gerät alle Interfaces, die durch die aktuelle Konfiguration aktiviert sind, gleichzeitig. | Zu einem bestimmten Zeitraum besitzt ein Gerät alle Interfaces, die durch die aktuelle Konfiguration aktiviert sind, gleichzeitig. | ||
| + | |||
| + | ==== Alternative Einstellungen ==== | ||
| + | Ein Gerät kann es für nötig befinden, dass ein einzelnes Interface während des Betriebs ausgetauscht werden muss, ohne die gesamte Konfiguration zu verändern. Dies wird über alternative Einstellungen erreicht. | ||
| + | |||
| + | Kommen wir zurück zur Webcam: Diese besitzt wie gesagt zwei Interfaces. Nun soll das Videointerface aber mehrere Auflösungen unterstützen, um sich an die verfügbare Bandbreite auf dem USB anzupassen. Hier könnte man einerseits mehrere Konfigurationen anbieten, da sich aber das Audiointerface nicht ändert, kann man auch mehrere Variationen für das Videointerface anbieten. Dies geschieht über alternative Einstellung. Beim Laden der Konfiguration wird die alternative Einstellung 0 geladen. Der USB-Gerätetreiber kann später eine andere alternative Einstellung (und so ein komplett anderes Interface) auswählen, falls dies nötig sein sollte. | ||
=== Endpunkte === | === Endpunkte === | ||
| Zeile 490: | Zeile 495: | ||
! Phase !! Pakettyp !! Bedeutung | ! Phase !! Pakettyp !! Bedeutung | ||
|- | |- | ||
| − | | Setup || SETUP || Hier wird ein 8 Byte langes SETUP-Paket zum Gerät gesendet, dessen Aufbau für alle Controltransfers einheitlich ist und u. a. die Länge und Richtung des Transfers angibt. Unterstützt das Gerät die Funktion nicht, kann sie hier bereits ein STALL zurückgeben. | + | | Setup || SETUP || Hier wird ein 8 Byte langes SETUP-Paket zum Gerät gesendet, dessen Aufbau für alle Controltransfers einheitlich ist und u. a. die Länge und Richtung des Transfers angibt. Unterstützt das Gerät die Funktion nicht, kann sie hier bereits ein STALL zurückgeben. Für das SETUP-Paket wird immer DATA0 verwendet. |
|- | |- | ||
| − | | Daten || IN/OUT || Je nach in der Setupphase angegebenen Richtung werden nun Daten ein- oder ausgegeben. Ist die Länge der Datenphase im SETUP-Paket als 0 angegeben worden, existiert diese Phase nicht. | + | | Daten || IN/OUT || Je nach in der Setupphase angegebenen Richtung werden nun Daten ein- oder ausgegeben. Ist die Länge der Datenphase im SETUP-Paket als 0 angegeben worden, existiert diese Phase nicht. Das erste Datenpaket der Datenphase ist immer DATA1, da das Toggle-Bit beim SETUP-Paket auf 0 gesetzt war. |
|- | |- | ||
| − | | Handshake || OUT/IN || Umgekehrt zur in der Datenphase verwendeten Richtung (oder der Richtung, die verwendet worden wäre, wenn es keine Datenphase gab) wird nun ein IN- bzw. OUT-Paket gesendet. Dies dient als nochmalige Versicherung, dass das Gerät die Anfrage auch verstanden und verarbeitet hat. | + | | Handshake || OUT/IN || Umgekehrt zur in der Datenphase verwendeten Richtung (oder der Richtung, die verwendet worden wäre, wenn es keine Datenphase gab) wird nun ein IN- bzw. OUT-Paket gesendet. Dies dient als nochmalige Versicherung, dass das Gerät die Anfrage auch verstanden und verarbeitet hat. In der Handshakephase wird immer DATA1 eingesetzt. |
|} | |} | ||
| Zeile 823: | Zeile 828: | ||
Tipp: Wie beschrieben weiß man anfangs nicht, wie lang alle Konfigurations-, Interface- und Endpunktdescriptoren einer Konfiguration zusammen sind. Daher müsste man theoretisch einen ausreichend großen Datenpuffer reservieren. Besser ist, zuerst nur die ersten neun Bytes dieses Descriptorenarrays (oder auch -liste) einzulesen (also nur den Konfigurationsdescriptor), daraus zu ermitteln, wie viel Platz alle Descriptoren zusammen brauchen (wTotalLength) und dann einen Puffer dieser Größe zu reservieren. | Tipp: Wie beschrieben weiß man anfangs nicht, wie lang alle Konfigurations-, Interface- und Endpunktdescriptoren einer Konfiguration zusammen sind. Daher müsste man theoretisch einen ausreichend großen Datenpuffer reservieren. Besser ist, zuerst nur die ersten neun Bytes dieses Descriptorenarrays (oder auch -liste) einzulesen (also nur den Konfigurationsdescriptor), daraus zu ermitteln, wie viel Platz alle Descriptoren zusammen brauchen (wTotalLength) und dann einen Puffer dieser Größe zu reservieren. | ||
| + | |||
| + | ==== Stringdescriptor ==== | ||
| + | Ein Stringdescriptor besitzt keinen besonders spezifischen Aufbau. Er enthält Strings, die z. B. den Hersteller oder den Namen des Produkts selbst beinhalten – somit haben sie für den Treiber selbst eher eine untergeordnete Bedeutung und dienen eher der Information des Benutzers. | ||
| + | |||
| + | {| {{Prettytable}} | ||
| + | ! Offset !! Länge !! Name !! Bedeutung oder Inhalt | ||
| + | |- | ||
| + | | 0x00 || 1 || bLength || Länge dieses Descriptors (Anzahl der Zeichen im String mal zwei plus zwei: Mal zwei, weil UTF16 verwendet wird und plus zwei, weil der String erst bei Offset 2 beginnt) | ||
| + | |- | ||
| + | | 0x01 || 1 || bDescriptorType || 3 | ||
| + | |- | ||
| + | | 0x02 || beliebig || bString || Enthält den String, UTF16-kodiert. Wenn man keine UTF16-Unterstützung hat, genügt es in den meisten Fällen, das höherwertige Byte zu ignorieren und das niederwertige als ASCII auszugeben (oder ein Ersatzzeichen ausgeben, wenn der Wert größer als 127 ist). | ||
| + | |} | ||
| + | |||
| + | Alle Stringdescriptoren haben einen Index größer als 0. Dieser Index ist für die Liste der verfügbaren Sprachen reserviert. Anstatt von Unicodezeichen enthält der Stringdescriptor 0 ein Array von 16-Bit-Werten, welche die verfügbaren Sprach-IDs enthalten. | ||
| + | |||
| + | ==== Interfacedescriptor ==== | ||
| + | Ein Interfacedescriptor beschreibt ein Interface einer Konfiguration. Solche Descriptoren können nicht einzeln abgefragt werden, sie werden vom Gerät immer zusammen mit dem Konfigurationsdescriptor geliefert. | ||
| + | |||
| + | {| {{Prettytable}} | ||
| + | ! Offset !! Länge !! Name !! Bedeutung oder Inhalt | ||
| + | |- | ||
| + | | 0x00 || 1 || bLength || 9 | ||
| + | |- | ||
| + | | 0x01 || 1 || bDescriptorType || 4 | ||
| + | |- | ||
| + | | 0x02 || 1 || bInterfaceNumber || Eindeutiger Index dieses Interfaces in der aktuellen Konfiguration | ||
| + | |- | ||
| + | | 0x03 || 1 || bAlternateSetting || Gibt die ID dieser alternativen Einstellung an (Standardeinstellung ist 0). | ||
| + | |- | ||
| + | | 0x04 || 1 || bNumEndpoints || Enthält die Anzahl der Endpunkte dieses Interfaces. | ||
| + | |- | ||
| + | | 0x05 || 1 || bInterfaceClass || USB-Klassencode (Wert 0 ist reserviert, 255 bedeutet herstellerspezifisch) | ||
| + | |- | ||
| + | | 0x06 || 1 || bInterfaceSubClass || Unterklasse | ||
| + | |- | ||
| + | | 0x07 || 1 || bInterfaceProtocol || Protokolltyp | ||
| + | |- | ||
| + | | 0x08 || 1 || iInterface || ID des Stringdescriptors, der dieses Interface beschreibt. | ||
| + | |} | ||
| + | |||
| + | ==== Endpunktdescriptor ==== | ||
| + | Der letzte Descriptor in der Kette Gerät → Konfiguration → Interface → Endpunkt ist eben dieser. Er beschreibt logischerweise einen Endpunkt und wie auch der Interfacedescriptor können Endpunktdescriptoren nicht einzeln, sondern nur zusammen mit dem Konfigurationsdescriptor abgefragt werden. | ||
| + | |||
| + | {| {{Prettytable}} | ||
| + | ! Offset !! Länge !! Name !! Bedeutung oder Inhalt | ||
| + | |- | ||
| + | | 0x00 || 1 || bLength || 7 | ||
| + | |- | ||
| + | | 0x01 || 1 || bDescriptorType || 5 | ||
| + | |- | ||
| + | | 0x02 || 1 || bEndpointAddress || Beschreibt die Adresse des Endpunkts nach dem folgenden Schema: | ||
| + | * Bit 0 – 3: ID des Endpunkts (die tatsächliche Adresse) | ||
| + | * Bit 4 – 6: Reserviert (auf 0 zu setzen) | ||
| + | * Bit 7: Richtung (wird bei Controlendpunkten ignoriert, da sie sich bidirektional verhalten): | ||
| + | ** 0: OUT | ||
| + | ** 1: IN | ||
| + | |- | ||
| + | | 0x03 || 1 || bmAttributes || Eigenschaften des Endpunkts: | ||
| + | * Bit 0 – 1: Übertragungstyp: | ||
| + | ** 00b: Control | ||
| + | ** 01b: Isochronous | ||
| + | ** 10b: Bulk | ||
| + | ** 11b: Interrupt | ||
| + | * Bit 2 – 3: Synchronisation (nur für Isochronous): | ||
| + | ** 00b: Keine | ||
| + | ** 01b: Asynchron | ||
| + | ** 10b: Adaptiv | ||
| + | ** 11b: Synchron | ||
| + | * Bit 4 – 5: Benutzung (nur für Isochronous): | ||
| + | ** 00b: Datenendpunkt | ||
| + | ** 01b: Feedbackendpunkt | ||
| + | ** 10b: Daten und gleichzeitig Feedback für einen anderen Endpunkt | ||
| + | ** 11b: Reserviert | ||
| + | * Bit 6 – 7: Reserviert und auf 0 zu setzen (ebenso die Bits 2 – 5 für nicht-Isochronoustransfers) | ||
| + | |- | ||
| + | | 0x04 || 2 || wMaxPacketSize || Enthält u. a. die MPS für diesen Endpunkt: | ||
| + | * Bit 0 – 10: MPS in Bytes | ||
| + | * Bit 11 – 12: Gibt für High-Speed-Interrupt- und -Isochronoustransfers die Anzahl von zusätzlichen Übertragungen pro Microframe an (bei Interrupttransfers: falls eine fehlschlagen sollte): | ||
| + | ** 00b: Keine (max. eine Übertragung pro Microframe) | ||
| + | ** 01b: Eine (max. zwei Übertragungen pro Microframe) | ||
| + | ** 10b: Zwei (max. drei Übertragungen pro Microframe) | ||
| + | * Bit 13 – 15: Reserviert | ||
| + | |- | ||
| + | | 0x06 || 1 || bInterval || Die Bedeutung hängt vom Endpunkttyp ab: | ||
| + | * Isochronous: 2^bInterval gibt an, wie häufig Transfers stattfinden sollen (aller wie viel (Micro-)Frames). | ||
| + | * Low-/Full-Speed-Interrupt: Gibt die Anzahl der Frames an, die zwischen zwei Interrupttransfers vergehen sollen. | ||
| + | * High-Speed-Interrupt: 2^bInterval gibt die Anzahl dieser Microframes an. | ||
| + | * High-Speed-Control/Bulk-OUT: Sozusagen die Anzahl der Microframes pro NAK. Ist der Wert 0, so gibt es nie ein NAK. Ist er 42, so gibt es höchstens aller 42 Microframes ein NAK. | ||
| + | |} | ||
| + | |||
| + | ==== Device-Qualifier ==== | ||
| + | Wenn ein High-Speed-Gerät an einen Full-Speed-Rootport angeschlossen wird, dann zeigen sowohl Windows als auch Linux eine nette Meldung à la „Dieses Gerät kann eine höhere Leistung erzielen“. Wie geht das, ein High-Speed-Gerät hat sich an Full-Speed-Rootports doch als normales Full-Speed-Gerät auszugeben? | ||
| + | |||
| + | Die Antwort liegt im Device-Qualifier. Dieser Descriptor enthält Informationen darüber, ob ein Gerät mit einer anderen Geschwindigkeit arbeiten kann und wie es sich dann verhalten würde. Arbeitet z. B. ein High-Speed-Gerät im Full-Speed-Modus, dann muss der Device-Qualifier Informationen über den High-Speed-Modus enthalten, arbeitet es im High-Speed-Modus, muss er Informationen zum Full-Speed-Modus enthalten. | ||
| + | |||
| + | {| {{Prettytable}} | ||
| + | ! Offset !! Länge !! Name !! Bedeutung oder Inhalt | ||
| + | |- | ||
| + | | 0x00 || 1 || bLength || 10 | ||
| + | |- | ||
| + | | 0x01 || 1 || bDescriptorType || 6 | ||
| + | |- | ||
| + | | 0x02 || 2 || bcdUSB || USB-Versionsnummer in BCD-Forum (mindestens 0x0200 für 2.00) | ||
| + | |- | ||
| + | | 0x04 || 1 || bDeviceClass || USB-Klassencode | ||
| + | |- | ||
| + | | 0x05 || 1 || bDeviceSubClass || Unterklasse | ||
| + | |- | ||
| + | | 0x06 || 1 || bDeviceProtocol || Protokolltyp | ||
| + | |- | ||
| + | | 0x07 || 1 || bMaxPacketSize0 || MPS für EP0 | ||
| + | |- | ||
| + | | 0x08 || 1 || bNumConfigurations || Anzahl der Konfigurationen | ||
| + | |- | ||
| + | | 0x09 || 1 || bReserved || 0 (reserviert) | ||
| + | |} | ||
| + | |||
| + | ==== Other-Speed-Konfigurationsdescriptor ==== | ||
| + | Nun enthält der Device-Qualifier in etwa so viel Information wie der Device-Descriptor. Da fehlt natürlich noch jede Menge, um z. B. entscheiden zu können, wie viel die andere Geschwindigkeit denn wirklich brächte, vor allem die dann verfügbaren Konfigurationen, Interfaces und Endpunkte. Dafür gibt es den Other-Speed-Konfigurationsdescriptor. | ||
| + | |||
| + | Dieser enthält die gleichen Informationen und ist genauso aufgebaut wie ein normaler Konfigurationsdescriptor, nur dass er einen anderen Code besitzt und so unabhängig von den normalen Konfigurationsdescriptoren abgefragt werden kann. Genau wie beim normalen Descriptor werden auch hier die entsprechenden Interface- und Endpunktdescriptoren angehangen. | ||
| + | |||
| + | {| {{Prettytable}} | ||
| + | ! Offset !! Länge !! Name !! Bedeutung oder Inhalt | ||
| + | |- | ||
| + | | 0x00 || 1 || bLength || 9 | ||
| + | |- | ||
| + | | 0x01 || 1 || bDescriptorType || 7 | ||
| + | |- | ||
| + | | 0x02 || 2 || wTotalLength || s. [[#Konfigurationsdescriptor|Konfigurationsdescriptor]] | ||
| + | |- | ||
| + | | 0x04 || 1 || bNumInterfaces || s. Konfigurationsdescriptor | ||
| + | |- | ||
| + | | 0x05 || 1 || bConfigurationValue || s. Konfigurationsdescriptor | ||
| + | |- | ||
| + | | 0x06 || 1 || iConfiguration || s. Konfigurationsdescriptor | ||
| + | |- | ||
| + | | 0x07 || 1 || bmAttributes || s. Konfigurationsdescriptor | ||
| + | |- | ||
| + | | 0x08 || 1 || bMaxPower || s. Konfigurationsdescriptor | ||
| + | |} | ||
== Übersetzung == | == Übersetzung == | ||
| Zeile 830: | Zeile 977: | ||
{| {{Prettytable}} | {| {{Prettytable}} | ||
! Deutsch !! Englisch | ! Deutsch !! Englisch | ||
| + | |- | ||
| + | | Alternative Einstellung || Alternate Setting | ||
|- | |- | ||
| Asynchron || Asynchronous | | Asynchron || Asynchronous | ||
| Zeile 851: | Zeile 1.000: | ||
{| {{Prettytable}} | {| {{Prettytable}} | ||
! Englisch !! Deutsch | ! Englisch !! Deutsch | ||
| + | |- | ||
| + | | Alternate Setting || Alternative Einstellung | ||
|- | |- | ||
| Asynchronous || Asynchron | | Asynchronous || Asynchron | ||