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)
Kannst du den kompletten Descriptor mal Posten mir per Email schicken.
Dann würde ich mir den ansehen.
Ok E-Mail ist raus - hoffe sie kommt auch an ;) Danke schonmal
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
Sorry hab noch was vergessen. Zum HID Descriptor brauchst du noch nen
Report Descriptor :)
const unsigned char RepD[]= // Report descriptor
{
0x05,0x01, // Usage Page (generic desktop)
0x09,0x06, // Usage (keyboard)
0xA1,0x01, // Collection
0x05,0x07, // Usage Page 7 (keyboard/keypad)
0x19,0xE0, // Usage Minimum = 224
0x29,0xE7, // Usage Maximum = 231
0x15,0x00, // Logical Minimum = 0
0x25,0x01, // Logical Maximum = 1
0x75,0x01, // Report Size = 1
0x95,0x08, // Report Count = 8
0x81,0x02, // Input(Data,Variable,Absolute)
0x95,0x01, // Report Count = 1
0x75,0x08, // Report Size = 8
0x81,0x01, // Input(Constant)
0x19,0x00, // Usage Minimum = 0
0x29,0x65, // Usage Maximum = 101
0x15,0x00, // Logical Minimum = 0,
0x25,0x65, // Logical Maximum = 101
0x75,0x08, // Report Size = 8
0x95,0x01, // Report Count = 1
0x81,0x00, // Input(Data,Variable,Array)
0xC0}; // End Collection
Wieder aus dem Beispielcode vom Maxim. MAcht ne schöne Tastatur.
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
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
|