Forum: Mikrocontroller und Digitale Elektronik Übersetzungshilfe USB Protokoll


von USB (Gast)


Lesenswert?

Hallo,

mag mir einer von euch bei der Übersetzung eines USB-Protokolls helfen, 
bzw. mal kontrollieren, ob ich das soweit richtig gemacht habe?

Ich empfange in einer HID-Tastatur-SETUP Sequenz folgendes:

80 06 00 01 00 00 40 00

Aus
https://www.lowlevel.eu/wiki/Universal_Serial_Bus
würde ich es wie folg übersetzen:


Byte 0: 0x80
bmRequestType:
Bit 0-4: Empfänger = Geräte
Bit 5-6: Typ des Request = Standardrequest
Bit 7:   Richtung des Transfers = Host zum Gerät

Byte 1: 0x06
bRequest: Nummer des Request = 6

Byte 2+3: 0x0001
wValue: Requestspezifischer Wert = 1 (k.A. was das bedeutet)

Byte 4+5: 0x0000
wIndex: Requestspezifisch, kein Index, kein Offset = 0

Byte 6+7: 0x4000
wLength: Länge der zu übertragenden Daten = 0


Danach bekomme ich ein DATA0 Paket ohne Dateninhalt und ein ACK. Würde 
also mit der Datenlänge = 0 passen.

Habe ich das soweit richtig übersetzt?

von Clemens L. (c_l)


Lesenswert?

USB schrieb:
> Byte 0: 0x80
> bmRequestType:
> Bit 7:   Richtung des Transfers = Host zum Gerät

falsch

> Byte 1: 0x06
> bRequest: Nummer des Request = 6

GET_DESCRIPTOR

> Byte 2+3: 0x0001
> wValue: Requestspezifischer Wert = 1 (k.A. was das bedeutet)

Die Spezifikation sagt:
> The wValue field specifies the descriptor type in the high byte and
> the descriptor index in the low byte.

Und du hast hier Little Endian und Big Endian verwechselt; der 
Deskriptor-Typ ist 1 (Gerät).

> Byte 6+7: 0x4000
> wLength: Länge der zu übertragenden Daten = 0

Nein, diese Zahl ist nicht Null, sondern 64.

von USB (Gast)


Lesenswert?

ok, Danke.

Einige Nachfragen hätte ich noch, vielleicht mal von hinten begonnen:

Byte 6+7 = 64 weil erst das höherwertige 0x00 Übertragen wird, danach 
die 0x40 und dies eben zusammen 0x0040 = 64 ergibt. Ok, aber was ich 
dann nicht verstehe, es werden in den nachfolgenden Sequenzen keineswegs 
64 Bytes übertragen, sondern ein DATA0 Paket ohne Inhalt. Danach kommt 
dann ein Device-Deskriptor mit 18Byte Länge... Danach neue 
Setupprozesse.

Frage:
Was sagen mir diese 64 Byte Länge an dieser Stelle?
Tatsächlich ist in einem sehr viel späteren Frame wirklich mal ein 
Datenpaket dieser Länge mit dabei... das kommt aber erst sehr viel 
später...


Byte 1: 0x06
Ist klar. Ist ein GetDescriptor.
Danach kommt auch ein Descriptor von 18 Byte Länge im nächsten Frame im 
DATA0. Macht also Sinn für mich.


Byte 0: 0x80
Ist das nicht 1000.0000 und somit die 1 im 7. Bit gesetzt?
Wenn ich dies nun "anders-herum" übersetze und die Zahl 0000.0001 daraus 
mache, dann stimmen doch die aussagen für die oben angegebenen Werte 
nicht mehr... Ich kann doch nicht mal die Werte verdrehen und mal 
nicht... Da verstehe ich eine Sache irgendwie noch nicht 100%...

von Clemens L. (c_l)


Lesenswert?

USB schrieb:
> weil erst das höherwertige 0x00 Übertragen wird

Nein, USB ist immer Little Endian; die Bytes auf dem Bus sind 40 00.
Siehe Abschnitt 8.1 der Spezifikation.

> es werden in den nachfolgenden Sequenzen keineswegs
> 64 Bytes übertragen, sondern ein DATA0 Paket ohne Inhalt. Danach kommt
> dann ein Device-Deskriptor mit 18Byte Länge

wLength ist die maximale Länge.

> Byte 0: 0x80
> Ist das nicht 1000.0000 und somit die 1 im 7. Bit gesetzt?

Ja, das 7. Bit ist gesetzt.
Und 1 = Device-to-host.

Du darfst halt nicht irgendeiner Webseite glauben, sondern irgendeiner 
anderen: http://www.usb.org/developers/docs/usb20_docs/usb_20_080416.zip

von USB (Gast)


Lesenswert?

aah ja, da scheint dann ja ein Fehler in meiner Quelle zu liegen... 
Danke!

von USB (Gast)


Lesenswert?

so langsam komme ich weiter.

Mein Device schickt einen get_Konfigurationsdescriptor mit dem Befehl:

SETUP
DATA0: 80 06 00 02 00 00 09 00
es wird also (0x80) Host seitig ein Get-(0x60) Transfer vom Gerät zum 
Host angefordert. Die 0x02 kennzeichnet einen Konfigurationsdescriptor.
Der Host erlaubt dabei zunächst bis zu 9 Bytes (0x0009) anzunehmen.


Der Host bekommt  als Antwort:
DATA1: 09 02 22 00 01 01 04 80 C8

Länge dieses Frames 0x09 = 9 Bytes
Es ist ein Konfigurationsdescriptor 0x02
Die totale Länge des gesamten Descritpors wäre 0x0022 Bytes lang.
Es gibt nur eine Konfiguration des Gerätes 0x01
Die Nummer dieser einen Konfiguration wird mit 0x01 angewählt
Die 0x80 ist ein historisches Artefkat
0xC8 gibt an, dass das Gerät bis zu 200mA Strom verbrauchen wird.

Danach fordert der Host mir
SETUP
DATA0 80 06 00 02 00 00 22 00

genau den gleichen Descriptor an, doch reserviert dieses mal einen 
genügenden Speicherbereich von 22 Bytes.

In dem nächsten DATA1 Paket erhalte ich jetzt den ganzen 
Konfigurationsdeskriptor.

DATA1:
09 02 22 00 01 01 04 80 C8 09 04 00 00 01 03 01 01 05 09 21 10 01 00 01 
22 41 00 07 05 82 03 40 00 01

Die ersten 9 Bytes sind klar, doch was sagen mir die Bytes dahinter?
Ich suche jetzt schon eine ganze Zeit lang nach den Stichworten 
Konfigurationsdescriptor, doch finde nicht so richtig eine 
Übersetzungshilfe was ich hier nun wo zu erwarten habe.
Wie übersetze ich die Bytes 10 bis 22?

von USB (Gast)


Lesenswert?

ich meine natürlich die Bytes 10 bis 0x22 also von Dec. 10 bis Dec. 34

von Clemens L. (c_l)


Lesenswert?

USB schrieb:
> Die ersten 9 Bytes sind klar, doch was sagen mir die Bytes dahinter?

Abschnitt 9.6.3 der Spezifikation sagt:
> When the host requests the configuration descriptor, all related
> interface and endpoint descriptors are returned (refer to Section 9.4.3).

Abschnitt 9.4.3 sagt:
> A request for a configuration descriptor returns the configuration
> descriptor, all interface descriptors, and endpoint descriptors for
> all of the interfaces in a single request. The first interface
> descriptor follows the configuration descriptor. The endpoint
> descriptors for the first interface follow the first interface
> descriptor. If there are additional interfaces, their interface
> descriptor and endpoint descriptors follow the first interface’s endpoint
> descriptors. Class-specific and/or vendor-specific
> descriptors follow the standard descriptors they extend or modify.

von USB (Gast)


Lesenswert?

aah, ok Danke.


dann ist der Konfigurationsdescriptor:
09 02 22 00 01 01 04 80 C8

danach kommt ein Interfacedescriptor:
09 04 00 00 01 03 01 01 05


dann scheint ein Classspecific-Interfacedecriptor zu kommen:
09 21 10 01 00 01 22 41 00
welcher scheinbar ein HID Device beschreibt...?

und schließlich ein Endpunktdescriptor:
05 82 03 40 00 01

von USB (Gast)


Lesenswert?

Nachdem diese Descriptoren allesamt eingelesen ist, führt das Device 
folgendes Code aus:

SETUP
DATA0: 00 09 01 00 00 00 00 00
ACK

dies übersetze ich zu einem Set_Coniguration.
Da es nur eine Configuration gibt, ist diese natürlich die 01 im dritten 
Byte.

Nun beobachte ich folgendes auf dem Bus:

SETUP
DATA0: 81 06 00 21 00 00 09 00

Die Antwort lautet:
DATA1: 09 21 10 01 00 01 22 41 00

Offenbar wird mit 0x81 der bmRequestType von 10000001 gesetzt. In der 
Tabelle 9-3 unter Überschrift Standard Device Requests findet man diese 
Kombination nur zusammen mit bRequest GET_STATUS und GET_INTERFACE.
Die 0x06 hingegen beschreibt einen GET_DESCRIPTOR.
Das 4. Byte beschreibt den Typ des verlangten Descriptors und das 3. 
Byte den Index. Es wird also der HID-specific-Descriptor abgefragt.


Die letzten beiden Bytes geben den aktuell reservierten Speicherplatz im 
Host an, es sind nur 9 Stück.
Die Antwort des HID-Devices (0x21) sagt mit 0x0041, dass der Report 
Descriptor 65 Bytes umfasst.

Danach sendet der Host die abgewandelte Anfrage:

SETUP
DATA0: 81 06 00 22 00 00 41 00

Danach empfange ich den gesamten Report Descriptor:
DATA1
05 01 09 06 A1 01 05 07 19 E0 29 E7 15 00 25 01 75 01 95 08 81 02 95 01 
75 08 81 01 95 05 75 01 05 08 19 01 29 05 91 02 95 01 75 03 91 01 95 06 
75 08 15 00 26 FF 00 05 07 19 00 2A FF 00 81 00

und danach ein
DATA0 C0

Nun habe ich eine ganze Reihe Fragen hierzu:

Das 4. Byte beschreibt den Descriptor Typ = Report.
Wo finde ich weitere Informationen, wie ich nun die Kommunikation mit 
meinem Device gestalte, bzw. wie ich die Daten aus diesem Report nun für 
mich brauchbar überführen kann?

von Clemens L. (c_l)


Lesenswert?

USB schrieb:
> Wo finde ich weitere Informationen, wie ich nun die Kommunikation mit
> meinem Device gestalte

In der HID-Spezifikation. (Die ich mir nicht antun werde. Viel Erfolg 
noch ...)

von USB (Gast)


Lesenswert?

In jedem Fall vielen Dank, hast mir gerade am Anfang gut in die Spur 
geholfen.

Ich gucke mal, was ich noch so raus bekomme.
Vielleicht guckt ja noch ein anderer USB-Profi mal rüber...?

von Jim M. (turboj)


Lesenswert?

Siehe
> http://eleccelerator.com/usbdescreqparser/
1
0x05, 0x01,        // Usage Page (Generic Desktop Ctrls)
2
0x09, 0x06,        // Usage (Keyboard)
3
0xA1, 0x01,        // Collection (Application)
4
0x05, 0x07,        //   Usage Page (Kbrd/Keypad)
5
0x19, 0xE0,        //   Usage Minimum (0xE0)
6
0x29, 0xE7,        //   Usage Maximum (0xE7)
7
0x15, 0x00,        //   Logical Minimum (0)
8
0x25, 0x01,        //   Logical Maximum (1)
9
0x75, 0x01,        //   Report Size (1)
10
0x95, 0x08,        //   Report Count (8)
11
0x81, 0x02,        //   Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
12
0x95, 0x01,        //   Report Count (1)
13
0x75, 0x08,        //   Report Size (8)
14
0x81, 0x01,        //   Input (Const,Array,Abs,No Wrap,Linear,Preferred State,No Null Position)
15
0x95, 0x05,        //   Report Count (5)
16
0x75, 0x01,        //   Report Size (1)
17
0x05, 0x08,        //   Usage Page (LEDs)
18
0x19, 0x01,        //   Usage Minimum (Num Lock)
19
0x29, 0x05,        //   Usage Maximum (Kana)
20
0x91, 0x02,        //   Output (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
21
0x95, 0x01,        //   Report Count (1)
22
0x75, 0x03,        //   Report Size (3)
23
0x91, 0x01,        //   Output (Const,Array,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
24
0x95, 0x06,        //   Report Count (6)
25
0x75, 0x08,        //   Report Size (8)
26
0x15, 0x00,        //   Logical Minimum (0)
27
0x26, 0xFF, 0x00,  //   Logical Maximum (255)
28
0x05, 0x07,        //   Usage Page (Kbrd/Keypad)
29
0x19, 0x00,        //   Usage Minimum (0x00)
30
0x2A, 0xFF, 0x00,  //   Usage Maximum (0xFF)
31
0x81, 0x00,        //   Input (Data,Array,Abs,No Wrap,Linear,Preferred State,No Null Position)
32
0xC0,              // End Collection
33
34
// 64 bytes

Das ist also eine Tastatur.

von USB (Gast)


Lesenswert?

ja, dass es eine Tastatur ist, ist mir auch klar.

Ich nähere mich der Sache derzeit mit den Usage-Table Dokumenten.

Der Beginn des Reports lautet:
0x05 0x01

Im HID-TableDokument V1.12 findet man:
Usages are 32-bit identifiers, where the high order 16 bits represents 
the usage page and the low order 16-bits represents the usage ID.

Also:
high 16-bit: usage page
low  16-bit: usage ID


0x05 0x01

Also Little Endian:
Usage Page: 01 = Generic Desktop
Usage ID: 05 = GamePad ???????????????

Dickes Fragezeichen dahinter...

Es ist kein Gamepad, sondern eine Tastatur.

Kann mir einer dieses Problem auflösen?

von Jim M. (turboj)


Lesenswert?

USB schrieb:
> Dickes Fragezeichen dahinter...

Schau Dir doch mal den Post darüber an.

von USB (Gast)


Lesenswert?

Was soll mir der Post darüber denn sagen?

Laut den HID-Usage-Table Dokumenten muss ich diese 32 Bit in jeweils 2 
16Bit Wörter unterteilen und werde damit auf die Fährte eines Gamepads 
gelenkt, was natürlich falsch ist, aber warum?
Welches Detail übersehe ich bei der manuellen Übersetzung?

von guest (Gast)


Lesenswert?

USB schrieb:
> high 16-bit: usage page
> low  16-bit: usage ID

Du weist schon warum da '16-bit' steht?

USB schrieb:
> Was soll mir der Post darüber denn sagen?

Das daß:
USB schrieb:
> Der Beginn des Reports lautet:
> 0x05 0x01

nicht mit dem zusammenpasst

USB schrieb:
> Also Little Endian:
> Usage Page: 01 = Generic Desktop
> Usage ID: 05 = GamePad ???????????????

sondern Dein '0x05 0x01' zusammen die 'Usage Page' ist und nicht Page & 
ID und das steht auch so im Post davor:
1
0x05, 0x01,        // Usage Page (Generic Desktop Ctrls)

von USB (Gast)


Lesenswert?

...ach manchmal sieht man den Wald vor lauter Bäumen nicht...

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.