Hallo,
ich habe eine Frage zur Enumeration von USB (HID) Devices unter
WindowsXP. Bin nun mit meiner Firmware für den AT90USB647 irgendwie an
einem toten Punkt angelangt... Meine konkrete Frage lautet: Wann ist die
Enumeration device-seitig abgeschlossen? Meinen USB Traffic beobachte
ich mit USBlyzer, und der gibt mir nach dem (vollständigen oder eben
unvollständigen) Enumerationsprozess folgende Infos zu meinem Device:
1
Connection Status Device connected
2
Current Configuration 0
3
Speed Low
4
Device Address 0
5
Number Of Open Pipes 0
6
7
Device Descriptor
8
Offset Field Size Value Description
9
0 bLength 1 12h
10
1 bDescriptorType 1 01h Device
11
2 bcdUSB 2 0110h USB Spec 1.1
12
4 bDeviceClass 1 00h Class info in Ifc Descriptors
13
5 bDeviceSubClass 1 00h
14
6 bDeviceProtocol 1 00h
15
7 bMaxPacketSize0 1 08h 8 bytes
16
8 idVendor 2 03EBh Atmel Corp.
17
10 idProduct 2 2013h
18
12 bcdDevice 2 0100h 1.00
19
14 iManufacturer 1 01h
20
15 iProduct 1 02h
21
16 iSerialNumber 1 03h
22
17 bNumConfigurations 1 01h
Windows-seitig ist noch kein Treiber für mein Gerät vorhanden, und ich
frage mich, ob das allein der Grund dafür ist, dass:
1. Full-Speed nicht erkannt wird
2. die Strings nicht komplett ausgelesen werden (nur StringIndex3 und
StringIndex2)
3. im Windows Gerätemanager bei meinem Device das gelbe Ausrufezeichen
auftaucht.
Ist mit der Enumeration erstmal alles in Ordnung und wird sich alles
fügen, wenn ich Windows-seitig für einen Treiber gesorgt habe? Oder
sollte mein Device-Status auch ohne vorhandenen Windowstreiber schon
anders aussehen?
Gruß,
Trillian
Hallo,
unter http://www.beyondlogic.org/usbnutshell/usb7.htm wird der
Enum-Vorgang beschrieben. Du solltest mindestens eine Geräteadresse
bekommen.
Ich kann dir für eine HID-Tastatur den Bespielcode von Maxim empfehlen,
speziell für MAX3421E und MAX3420. Die untere Schicht musst du selber
implementieren. Irgendwo liegt ein sauber umgeschriebener Code für den
Blackfin DSP bei mir rum. Der ist auch lesbar :)
Die Speederkennung läuft über Pull-Up und Down-Widerstände, die meist
per Software geschaltet werden können. Wie es beim Atmel ist weiß ich
leider nicht, ich habe die oben genannten Chips verwendet. Wenn dies
nicht erfolgt, wird ein Low-Speedgerät signalisiert.
2. Wie schaut dein Stringdescriptor aus? Index 0 (das erste Element)
muss die Sprachversionen der folgenden Elemente beinhalten. Das kann ein
Grund sein, weshalb der eine nicht gelesen wird, weil Index 1 bei dir
als Sprache verwendet wird.
3. Das Device hat keinen Treiber und ist Windows in der Ansteuerung
unbekannt, deswegen das !
Hallo Benjamin,
danke schonmal für die Antwort :) Also durch den ganzen Enum-kram hab
ich mich schon einigermaßen durchgewühlt und grob auch alles verstanden.
Das was ich im USBlyzer nachvollziehen kann ist folgendes:
1. komischerweise wird zuerst nach dem String0 Deskriptor (Str Lang ID)
gefragt, der dann auch offensichtlich korrekt übertragen wird. Sieht
dann eingelesenerweise so aus:
1
String Descriptor
2
Offset Field Size Value Description
3
0 bLength 1 04h
4
1 bDescriptorType 1 03h String
5
2 wLANGID[0] 2 0409h English (United States)
2. dann wird gleich String Deskriptor 3 abgefragt
1
String Descriptor
2
Offset Field Size Value Description
3
0 bLength 1 0Eh
4
1 bDescriptorType 1 03h String
5
2 bString 12 0031h 0030h 0041h 0030h
6
0031h 0031h "10A011"
3. dann wird schon der komplette Konfigurationsdeskriptor bzw 255 Byte
(inkl. 1 Interface- und 2 Endpointdeskriptoren) verlangt und gesendet
1
Configuration Descriptor 1 Self Powered
2
Offset Field Size Value Description
3
0 bLength 1 09h
4
1 bDescriptorType 1 02h Configuration
5
2 wTotalLength 2 0020h
6
4 bNumInterfaces 1 01h
7
5 bConfigurationValue 1 01h
8
6 iConfiguration 1 00h
9
7 bmAttributes 1 C0h Self Powered
10
4..0: Reserved ...00000
11
5: Remote Wakeup ..0..... No
12
6: Self Powered .1...... Yes
13
7: Reserved (set to one)1.......
14
(bus-powered for 1.0)
15
8 bMaxPower 1 32h 100 mA
16
17
Interface Descriptor 0/0 HID, 2 Endpoints
18
Offset Field Size Value Description
19
0 bLength 1 09h
20
1 bDescriptorType 1 04h Interface
21
2 bInterfaceNumber 1 00h
22
3 bAlternateSetting 1 00h
23
4 bNumEndpoints 1 02h
24
5 bInterfaceClass 1 03h HID
25
6 bInterfaceSubClass 1 00h
26
7 bInterfaceProtocol 1 00h
27
8 iInterface 1 00h
28
29
Endpoint Descriptor 01 1, Control, 8 bytes
30
...
31
32
Endpoint Descriptor 82 2, Control, 8 bytes
33
...
4. Port Status wird abgefragt mit der Antwort, dass ein Device
angesteckt ist, der Port enabled ist und das Device "Low-Speed" wäre
5. jetzt wirds irgendwie komisch: Es wird nochmal String Deskriptor 0
abgefragt und gesendet. Dann String Deskriptor 2. Dann nochmal String
Deskriptor 0 und nochmals Nummer 2.
6. Abfrage und Übertragung des Device Deskriptors (wie oben im
Eröffnungsbeitrag)
7. Abfrage und Übertragung von 9 Byte des Config Descriptors
8. Abfrage und Übertragung von 32 Byte des Config Descriptors
9. ClearPortFeature Request mit Value 0001h (Feature: Enabled/Disabled)
<-- weiß ich nich so recht was mit anzufangen, der Port in dem mein
Device steckt wird geenabled bzw. gedisabled??
So und dann is Ende mit meinem Device. Ist im Großen und Ganzen
irgendwie anders als bei USB in a nutshell beschrieben - oder der
USBlyzer gibt das Ganze ein bisschen komisch wieder.
Meine Frage ist immernoch: Kann ich mich jetzt der Windows-Seite widmen
oder läuft was schief bei meiner "Enumeration"?
LG Trillian
Edit: Achso ja, mein AT90 sagt mir, er hätte eine Adresse bekommen. Das
Register UDADDR sieht so aus: 10000010 (es wurde die Adresse 2 vergeben
und diese ist auch enabled)
Hallo,
habs bekommen. Ich hab zwei kleine Fehler gefunden. Beim Entpunkt gibtst
du als Typ Isochron an. Als Wert nimmst du aber 0x00 was für Control
steht. Wenn es wirklich isochron sein soll, dann muss es 0x01 sein +
zusätzliche Flags. Und dann muss auch das letzte Byte gesetzt sein fürs
Polling Intervall.
Bei den Strings musst du auch für Index 2 und 3 die Sprache setzen. Ich
kopiers mal ohne explizite Erlaubnis hier herein.
USB_STRING0_DESCRIPTOR:
0x08;.......size of descriptor (4bytes)
0x03;.......string descriptor
0x09
0x04;.......index of unicode language (english)
0x09
0x04;.......index of unicode language (english)
0x09
0x04;.......index of unicode language (english)
so müsste das aussehen. Wenn du ein HID Gerät hast, musst du zusätzlich
noch den HID-Descriptor schreiben und den übertragen, deswegen das ! im
Gerätemanager. Sonst lädt Windoof die Treiber selber.
Ist aus dem Appnote vom MAX3421E, mit dem ich ein anderes Interconnect
gebaut habe.
// HID Descriptor--It's at CD[18]
0x09, // bLength
0x21, // bDescriptorType = HID
0x10,0x01, // bcdHID(L/H) Rev 1.1
0x00, // bCountryCode (none)
0x01, // bNumDescriptors (one report descriptor)
0x22, // bDescriptorType (report)
43,0 // CD[25]: wDescriptorLength(L/H) (report
descriptor size is 43 bytes)
Dafür gibt es noch weitere Abfragen im Standardprotokoll, die
implementiert sein müssen und den Descriptor explizit abfragen. Du musst
dann diesen (obiges Beispiel ist Tastatur) zurückliefern.
In meinem Code sind die Descriptoren für Config/Interface/HID/Endpunkte
direkt in einem char Array, weil der Host den gesamten Descriptor haben
will.
Hoffe es hilft,
Benjamin
Nochmals vielen Dank für so eine ausführliche Antwort :)
Ok - alles schaff ich heute abend nicht mehr zu realisieren - dafür war
der Tag schon zu lang ;) Die Sache mit dem Isochronous Endpoint hatte
ich nur noch falsch auskommentiert, es soll tatsächlich ein Control EP
sein. Sorry...
Das mit dem String 0 Descriptor habe ich mal probiert, aber an der oben
beschrieben Abfolge und dem erstmal fehlenden String 1 Descriptor hat
sich nichts geändert. Ich glaube auch nicht dass man für jeden einzelnen
String eine extra Sprach-Definition im String 0 Descriptor vornehmen
muss - vielmehr hat man eben die Möglichkeit, bei Bedarf mehr als eine
unterstützte Sprache dort zu hinterlegen.
Ich glaube die Sache mit dem HID- und dem HID-Report Descriptor ist das
Problem bei mir. Ich muss zugeben, dass mir das vollkommen neu ist...
Ich werde die beiden morgen gleich mal zu den anderen Descriptoren
hinzufügen und dann hier nochmal berichten.
Ich denke wirklich das isses nun. Super, dankeschön :)
LG Trillian
Bei den String D. musst du, soweit ich weiß, die Sprachen angeben, weil
er damit die Anzahl berechnet. Ausser sind oben bereits irgendwo
genannt. Genau kann ichs dir aber nicht sagen.
Nur noch als Info:
Wenn die Anfrage kommt über einen Setuprequest, ich kenns als
SUD-Packet,
dann musst du in Offset 0x03 nachsehen, so wie jetzt auch.
Der Wert dort drinnen, sagt dir, welchen Descriptor du senden musst.
0x01 // Device
0x02 // Configuration
0x03 // String
0x21 // HID
0x22 // Report