Forum: Mikrocontroller und Digitale Elektronik AT90USB: Enumeration vollständig?


von Marja K. (trillian)


Lesenswert?

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

von Benjamin S. (recycler)


Lesenswert?

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 !

von Marja K. (trillian)


Lesenswert?

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)

von Benjamin S. (recycler)


Lesenswert?

Kannst du den kompletten Descriptor mal Posten mir per Email schicken. 
Dann würde ich mir den ansehen.

von Marja K. (trillian)


Lesenswert?

Ok E-Mail ist raus - hoffe sie kommt auch an ;) Danke schonmal

von Benjamin S. (recycler)


Lesenswert?

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

von Benjamin S. (recycler)


Lesenswert?

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.

von Marja K. (trillian)


Lesenswert?

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

von Benjamin S. (recycler)


Lesenswert?

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.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.