Hallo zusammen, für ein Projekt mit einem ATmega644 an einer SD-Karte (unter Anderem) benötige ich eine USB-Schnittstelle. Dazu verwende ich den Software-USB-Treiber von obdev, was soweit auch ganz gut zu funktionieren scheint (Was die prinzipielle Übertragung angeht), allerdings möchte ich das Gerät als Massenspeicher verwenden. Dazu habe ich DeviceClass und DeviceSubClass auf 0 und InterfaceClass, InterfaceSubClass und InterfaceProtocol auf 0x08 (Mass storage), 0x01 (Reduced Block Commands) und 0x50 (Bulk-only) gestellt. Soweit so gut. Wenn ich das Teil nun aber unter Windows anstecke, dann fragt mich das System nach einem Treiber, obwohl die Unterstützung für Massenspeichergeräte gegeben ist (Treiber sind im System verfügbar). Anhand der Debug-Ausgaben sehe ich, dass die Enumeration bis zur Übertragung der String-Deskriptoren läuft und dann abbricht. Wahrscheinlich weil dann eben der Treiber zu fehlen scheint. Warum auch immer. Wie auch immer, jedenfalls habe ich das Teil dann mal testweise unter Linux angeschlossen und dort wird es korrekt als Massenspeicher erkannt und der Treiber installiert?! Hier wäre vielleicht noch anzumerken, dass für Massenspeicher Bulk-Endpoints benötigt werden, die für Low-Speed-Geräte gemäss USB-Spezifikation nicht zugelassen sind. Ich kann mir aber schlecht vorstellen, dass es daran liegt, Windows hält sich eh nicht an Standards und die Enumeration bricht ja nicht nach dem Config-Deskriptor ab, sondern erst etwas später. Langer Rede kurzer Sinn: Hat schonmal jemand (erfolgreich) ein Massenspeichergerät mit dem obdev-Treiber realisiert und was muss ich dabei speziell beachten? Mit welchen Programmen lässt sich gescheit analysieren, wie die Enumeration abläuft und was möglicherweise für Fehler auftreten? USB-Monitor von HHD-Software und SnoopyPro habe ich bereits ausprobiert, doch beide liefern überhaupt keine übertragene Pakete. Obwohl USB-Monitor die Device- und Config-Deskriptoren korrekt anzeigen kann! Gibt es Alternativen, die ohne Treiber auskommen und sich ebenfalls verhalten können wie externer Speicher (In der HID-Klasse vielleicht)? Achja: Es geht nicht nur um den Zugriff auf die SD-Karte, der Controller sollte selber auch noch Dateien vorgaukeln die da nicht drauf sind. Fertige USB<->SD-Wandler (-ICs) sind also keine Alternative. Grüsse, Philipp
Für MSD benötigst Du BULK Endpoints. Diese gibt es nicht für Low-Speed Devices, das ist per Spezifikation verboten. Die logische Konsequenz ist das Deaktivieren des Gerätes. Außerdem lese ich das jetzt so, als hast Du nur die Deskriptoren Deines Gerätes verändert (und vermutlich nichtmal vollständig, da die Spezifikation auch eine Seriennummer in einem bestimmt Format vorschreibt). Das reicht nicht aus, denn der Host wird Dein Gerät mit einigen der Geräteklasse zugehörigen Requests kontaktieren (z.B. SCSI_INQUIRY, SCSI_MODE_SENSE_6, SCSI_START_STOP_UNIT usw.). Wenn Du darauf nicht antwortest, wird das Gerät erst recht deaktiviert. Wie auch immer, ich kenne obdev nicht. Das scheint aber auschließlich eine Low-Speed Implementierung zu sein, deswegen funktioniert das, was Du da vor hast, auf jeden Fall nicht. Suche Dir lieber einen Controller mit On-Chip USB und füttere diesen mit den AppNotes des Herstellers, z.B. SiLabs C8051F340 zusammen mit dem MSD Reference Design.
René König wrote: > Für MSD benötigst Du BULK Endpoints. Diese gibt es nicht für Low-Speed > Devices, das ist per Spezifikation verboten. Die logische Konsequenz ist > das Deaktivieren des Gerätes. Das ist mir bekannt, schrieb' ich oben ja auch. Allerdings gehe ich einfach mal davon aus, dass sich da kaum eine Host-Implementierung drum kümmert. Jedenfalls steht in der Firmware von obdev auch, dass es meistens funktioniert (Wie (oft) das getestet wurde weiss ich nicht), daher möchte ich es gerne mal probieren. Dass es nicht ideal ist, ist klar. > Außerdem lese ich das jetzt so, als hast Du nur die Deskriptoren Deines > Gerätes verändert (und vermutlich nichtmal vollständig, da die > Spezifikation auch eine Seriennummer in einem bestimmt Format Hm, wo finde ich das? Von einer erforderlichen Seriennummer habe ich nirgendwo etwas gelesen. Gleich mal nachschauen... > vorschreibt). Das reicht nicht aus, denn der Host wird Dein Gerät mit > einigen der Geräteklasse zugehörigen Requests kontaktieren (z.B. > SCSI_INQUIRY, SCSI_MODE_SENSE_6, SCSI_START_STOP_UNIT usw.). Wenn Du > darauf nicht antwortest, wird das Gerät erst recht deaktiviert. Natürlich habe ich noch nix dergleichen implementiert, doch ich bekomme ja auch keine solchen Requests. Der Host bricht schon früher (Ohne Fehlermeldung) ab. Deaktiviert wird das Gerät aber nicht. > Wie auch immer, ich kenne obdev nicht. Das scheint aber auschließlich > eine Low-Speed Implementierung zu sein, deswegen funktioniert das, was > Du da vor hast, auf jeden Fall nicht. Suche Dir lieber einen Controller "Auf jeden Fall nicht" mag ich nicht ;) Aber es ist eine reine Low-Speed-Implementierung, da hast du recht. > mit On-Chip USB und füttere diesen mit den AppNotes des Herstellers, > z.B. SiLabs C8051F340 zusammen mit dem MSD Reference Design. Interessanter Chip. Allerdings würde ich dann lieber bei den AVRs bleiben und einen AT90USB verwenden. Aber meine Protos möchte ich eigentlich noch so zum Laufen bringen, notfalls halt doch mit entsprechender Software auf dem PC.
Philipp Burch wrote: > Das ist mir bekannt, schrieb' ich oben ja auch. Allerdings gehe ich > einfach mal davon aus, dass sich da kaum eine Host-Implementierung drum > kümmert. Jedenfalls steht in der Firmware von obdev auch, dass es Na gut, wenn Du zu Deinem Gerät auch gleich noch 'nen Host ausliefern willst, um Funktion zu garantieren, kannst Du davon ruhig ausgehen. > Hm, wo finde ich das? Von einer erforderlichen Seriennummer habe ich > nirgendwo etwas gelesen. Gleich mal nachschauen... Das steht auf Seite 9: http://www.usb.org/developers/devclass_docs/usbmassbulk_10.pdf Gewöhne Dir aber ruhig an, für alle Geräteklassen Seriennummern zu liefern. ;-) > Natürlich habe ich noch nix dergleichen implementiert, doch ich bekomme > ja auch keine solchen Requests. Der Host bricht schon früher (Ohne > Fehlermeldung) ab. Deaktiviert wird das Gerät aber nicht. Es wird nicht deaktiviert, das ist sicher? Ich denke, die Leitung bleibt IDLE (was nach 3 ms als SUSPEND erkannt wird), oder habe ich Dich noch falsch verstanden? Allerdings ist es so oder so interessant zu sehen, wann der Host abbricht. Vielleicht kannst Du mal einen Auszug Deines Logs des Protokoll-Analyzers posten, damit wir uns hier ein genaueres Bild der Lage machen können. Oder wird abgebrochen, nachdem Du keine Seriennummer lieferst? > "Auf jeden Fall nicht" mag ich nicht ;) Für mich trifft es trotzdem zu, da ich mich nicht auf bestimmte Hosts festlegen will. :-) > Interessanter Chip. Allerdings würde ich dann lieber bei den AVRs > bleiben und einen AT90USB verwenden. Aber meine Protos möchte ich > eigentlich noch so zum Laufen bringen, notfalls halt doch mit > entsprechender Software auf dem PC. Gibt es von Atmel keine MSD Reference Designs, auf die Du zurückgreifen kannst? Immerhin sieht man soetwas heutzutage immer öfter, bei allen möglichen Herstellern. Und Atmel ist doch, wass AppNotes betrifft, recht vielfältig.
René König wrote: > Philipp Burch wrote: >> Das ist mir bekannt, schrieb' ich oben ja auch. Allerdings gehe ich >> einfach mal davon aus, dass sich da kaum eine Host-Implementierung drum >> kümmert. Jedenfalls steht in der Firmware von obdev auch, dass es > > Na gut, wenn Du zu Deinem Gerät auch gleich noch 'nen Host ausliefern > willst, um Funktion zu garantieren, kannst Du davon ruhig ausgehen. Aber klar doch, ich implementiere einen Hi-Speed-Host in einem AVR (In Software) und packe den auch gleich drauf ;D >> Hm, wo finde ich das? Von einer erforderlichen Seriennummer habe ich >> nirgendwo etwas gelesen. Gleich mal nachschauen... > > Das steht auf Seite 9: > http://www.usb.org/developers/devclass_docs/usbmassbulk_10.pdf > > Gewöhne Dir aber ruhig an, für alle Geräteklassen Seriennummern zu > liefern. ;-) Naja, hat schon was. Auch wenn die Seriennummer erstmal einfach statisch ist. Egal, jetzt ist jedenfalls eine drin, geändert hat sich nix. >> Natürlich habe ich noch nix dergleichen implementiert, doch ich bekomme >> ja auch keine solchen Requests. Der Host bricht schon früher (Ohne >> Fehlermeldung) ab. Deaktiviert wird das Gerät aber nicht. > > Es wird nicht deaktiviert, das ist sicher? Ich denke, die Leitung bleibt > IDLE (was nach 3 ms als SUSPEND erkannt wird), oder habe ich Dich noch > falsch verstanden? Nö, es kommt nach wie vor jede Millisekunde ein SE0 (D- und D+ für eine Bitzeit auf Low), sieht für mich gar nicht nach IDLE aus... > Allerdings ist es so oder so interessant zu sehen, wann der Host > abbricht. Vielleicht kannst Du mal einen Auszug Deines Logs des > Protokoll-Analyzers posten, damit wir uns hier ein genaueres Bild der > Lage machen können. Ich habe leider keinen Protokoll-Analyzer. Der obdev-Treiber hat einige Debug-Ausgaben per RS232 eingebaut wenn Daten übertragen werden. Wenn du willst, kann ich das hier mal posten, ist allerdings nicht übermässig aufschlussreich ohne jedes Byte einzeln zu dekodieren. Wie auch immer, ich lese daraus folgende Vorgänge: 1. Device Reset 2. Anforderung von 64 Bytes des Device-Deskriptors 3. Übertragung des Device-Deskriptors (18 Bytes) 4. Device Reset 5. Set Device Address 6. ACK vom Device 7. Anforderung von 64 Bytes des Device-Deskriptors 8. Übertragung des Device-Deskriptors (18 Bytes) 9. Device Reset 10. Set Device Address 11. ACK vom Device 12. Anforderung von 18 Bytes des Device-Deskriptors 13. Übertragung des Device-Deskriptors 14. Anforderung von 9 Bytes des Configuration-Deskriptors 15. Übertragung des Configuration-Deskriptors 16. Anforderung von 255 Bytes des String-Deskriptors 0 (Unterstützte Sprachen) 17. Übertragung des String-Deskriptors 0 (EN/US) 18. Anforderung des String-Deskriptors 3 (Seriennummer) 19. Übertragung der Seriennummer (12 Zeichen, 24 Bytes) 20. Anforderung von 255 Bytes des Configuration-Deskriptors 21. Übertragung des Configuration Deskriptors inkl. Interface- und Endpoint-Deskriptoren 22. Anforderung von 255 Bytes des String-Deskriptors 0 (Unterstützte Sprachen) 23. Übertragung des String-Deskriptors 0 (EN/US) 24. Anforderung von 255 Bytes des String-Deskriptors 2 (Device-Name) 25. Übertragung des String-Deskriptors 2 ('morsix3330') 26. Anforderung des String-Deskriptors 0 (...) 27. Übertragung des String-Deskriptors 0 (EN/US) 28. Anforderung des String-Deskriptors 2 (Device-Name) 29. Übertragung des String-Deskriptors 2 ('morsix3330') 30. Nüscht... Punkt 7 - 11 deutet auf einen Übertragungsfehler beim Device-Deskriptor hin, das habe ich jetzt zum Ersten Mal gesehen. Scheint aber nicht weiter problematisch zu sein, jedenfalls geht's nachher ganz normal weiter. > Oder wird abgebrochen, nachdem Du keine Seriennummer lieferst? Neine, es wird zweimal der Device-Name angefordert und dann ist Ende... >> "Auf jeden Fall nicht" mag ich nicht ;) > > Für mich trifft es trotzdem zu, da ich mich nicht auf bestimmte Hosts > festlegen will. :-) Schon klar. >> Interessanter Chip. Allerdings würde ich dann lieber bei den AVRs >> bleiben und einen AT90USB verwenden. Aber meine Protos möchte ich >> eigentlich noch so zum Laufen bringen, notfalls halt doch mit >> entsprechender Software auf dem PC. > > Gibt es von Atmel keine MSD Reference Designs, auf die Du zurückgreifen > kannst? Immerhin sieht man soetwas heutzutage immer öfter, bei allen > möglichen Herstellern. Und Atmel ist doch, wass AppNotes betrifft, recht > vielfältig. Jep, gibt's tatsächlich, danke für den Tipp! http://atmel.com/dyn/resources/prod_documents/doc6283.pdf
Philipp Burch wrote: > Jep, gibt's tatsächlich, danke für den Tipp! > http://atmel.com/dyn/resources/prod_documents/doc6283.pdf Hoppla, den ersten Fehler habe ich damit schonmal gefunden: "For example, Microsoft® Windows® does not currently support the Reduced Block Command set." Das hatte ich eingestellt, leider ändert auch die Einstellung "SCSI transparent command set" nix...
> 4. Device Reset > 5. Set Device Address > 6. ACK vom Device > 7. Anforderung von 64 Bytes des Device-Deskriptors > 8. Übertragung des Device-Deskriptors (18 Bytes) > 9. Device Reset > 10. Set Device Address Das sehe ich ähnlich wie Du: Gleich 2x "Set Device Address" ist kein gutes Zeichen. Wie sieht er denn genau aus, Dein DEVICE_DESCRIPTOR? > 19. Übertragung der Seriennummer (12 Zeichen, 24 Bytes) Das müssen natürlich 26 Bytes sein (1 Byte bLength, 1 Byte bDescriptorType, 24 Bytes für 12 Zeichen)
Philipp Burch wrote: > Naja, hat schon was. Auch wenn die Seriennummer erstmal einfach statisch > ist. Egal, jetzt ist jedenfalls eine drin, geändert hat sich nix. Natürlich nicht, dafür interessiert sich der Treiber/Installer nicht. Da langt ggf. die PID/VID bzw. die Klassenzugehörigkeit. Aber zur eigentlichen Problemlösung kann ich leider nichts beitragen...
> Natürlich nicht, dafür interessiert sich der Treiber/Installer nicht.
Massenspeicher ohne Seriennummer funktioniert nicht unter Windows.
Probier es einfach mal aus.
René König wrote: >> 4. Device Reset >> 5. Set Device Address >> 6. ACK vom Device >> 7. Anforderung von 64 Bytes des Device-Deskriptors >> 8. Übertragung des Device-Deskriptors (18 Bytes) >> 9. Device Reset >> 10. Set Device Address > > Das sehe ich ähnlich wie Du: Gleich 2x "Set Device Address" ist kein > gutes Zeichen. Wie sieht er denn genau aus, Dein DEVICE_DESCRIPTOR? So sieht der aus: 32 30 3A 4B 12 01 10 01 00 00 00 08 11 77 0A 32 30 3A C3 C0 16 DF 05 01 00 01 02 9A A7 0A 32 30 3A 4B 03 01 3F 7F 0A Wie gesagt, ist nicht so einfach zu dekodieren. Das Teil ist in vier Pakete zu acht Bytes aufgeteilt und aus Debugging-Gründen steht vor jedem Paket noch "20:" (32, 30, 3A) und die PID (4B -> 1011b -> DATA1, bzw. C3 -> 0011b -> DATA0). Ausserdem hängt am Ende jeweils noch die CRC und ein Zeilenumbruch. Der reine Deskriptor sieht damit so aus: 12 01 10 01 00 00 00 08 C0 16 DF 05 01 00 01 02 03 01 >> 19. Übertragung der Seriennummer (12 Zeichen, 24 Bytes) > > Das müssen natürlich 26 Bytes sein (1 Byte bLength, 1 Byte > bDescriptorType, 24 Bytes für 12 Zeichen) Ja richtig, hatte mich geirrt. Wird aber schon richtig übertragen.
Was für ein OS hast Du? Ich glaube, ich habe irgendwo gelesen (war es "USB in the Nutshell?" oder so etwas?), das es eine "Feature" von MS-Windows ist...
Petr Tomášek wrote: > Was für ein OS hast Du? Ich glaube, ich habe irgendwo gelesen (war es Windows XP. > "USB in the Nutshell?" oder so etwas?), das es eine "Feature" von > MS-Windows ist... Meinst du das hier? "Step 4 often confuses people writing firmware for the first time. The Host asks for the first 64 bytes of the device descriptor, so when the host resets your device after it receives the first 8 bytes, it is only natural to think there is something wrong with your device descriptor or how your firmware handles the request. However as many will tell you, if you keep persisting by implementing the Set Address Command it will pay off by asking for a full 18 bytes of device descriptor next." Das ist schon richtig, er macht ja zwei Resets. Was mich mehr verwundert, ist die Wiederholung von Step 3 bis Step 5 (Anforderung von 64 Bytes des Device-Deskriptors und SET_ADDRESS). Siehe hier: http://www.beyondlogic.org/usbnutshell/usb7.htm#Enumeration Allerdings steht da, dass der Host nach den ersten 8 Bytes einen Reset macht, bei mir passiert das erst nach 18 Bytes. Ist das nun ein Schreibfehler, oder soll der Host wirklich mitten im Deskriptor einen Reset machen? In der Spec steht das so: 4. The hub performs the required reset processing for that port (see Section 11.5.1.5). When the reset signal is released, the port has been enabled. The USB device is now in the Default state and can draw no more than 100 mA from VBUS. All of its registers and state have been reset and it answers to the default address. 5. The host assigns a unique address to the USB device, moving the device to the Address state. 6. Before the USB device receives a unique address, its Default Control Pipe is still accessible via the default address. The host reads the device descriptor to determine what actual maximum data payload size this USB device’s default pipe can use. Schaut in meinen Augen eigentlich ok aus...
> Allerdings steht da, dass der Host nach den ersten 8 Bytes einen Reset > macht, bei mir passiert das erst nach 18 Bytes. Ja, das macht der (Windows-)Host. Jetzt frage ich mich aber gerade, wie Du die 18 Bytes überträgst. Ich hoffe, Du machst das nicht am Stück. Das könnte den Host nämlich auch zweifeln lassen, da Du im DEVICE_DESCRIPTOR richtigerweise bMaxPacketSize mit 8 angegeben hast (auch ansonsten schaut der DEVICE_DESCRIPTOR nicht falsch aus). Du mußt das Ganze in drei Transfers verpacken! Jetzt wäre natürlich ein Protokoll-Analyzer nicht schlecht...
Petr Tomášek wrote: > Was für ein OS hast Du? Ich glaube, ich habe irgendwo gelesen (war es > "USB in the Nutshell?" oder so etwas?), das es eine "Feature" von > MS-Windows ist... Der SET_ADDRESS Request darf nur ein mal kommen, das ist definitv kein "Feature" von Windows.
René König wrote: >> Allerdings steht da, dass der Host nach den ersten 8 Bytes einen Reset >> macht, bei mir passiert das erst nach 18 Bytes. > > Ja, das macht der (Windows-)Host. Jetzt frage ich mich aber gerade, wie > Du die 18 Bytes überträgst. Ich hoffe, Du machst das nicht am Stück. Das > könnte den Host nämlich auch zweifeln lassen, da Du im DEVICE_DESCRIPTOR > richtigerweise bMaxPacketSize mit 8 angegeben hast (auch ansonsten > schaut der DEVICE_DESCRIPTOR nicht falsch aus). Du mußt das Ganze in > drei Transfers verpacken! Natürlich sind es drei einzelne Transfers (Ich schrieb oben ja "Wie gesagt, ist nicht so einfach zu dekodieren. Das Teil ist in vier Pakete zu acht Bytes aufgeteilt und aus Debugging-Gründen steht vor jedem Paket noch "20:" (32, 30, 3A) und die PID (4B -> 1011b -> DATA1,", obwohl es natürlich drei Teile heissen müsste). > Jetzt wäre natürlich ein Protokoll-Analyzer nicht schlecht... Korrekt. Allerdings kleines Status-Update: ES GEHT! Das Teil wird korrekt als Massenspeichergerät enumeriert und der entsprechende Treiber geladen. Warum ist mir jedoch ein Rätsel, ich habe nix geändert?! Ob das nun an der Verletzung der Spezifikation durch Low-Speed-Bulks liegen mag? Naja, ich habe jetzt wenigstens eine "Basis" zum Weiterentwicklung, ob das nur zeitweise geht oder nicht wird sich wohl bald zeigen... Jedenfalls kommt er jetzt bis zum Anfordern des CBW (Command Block Wrapper) und bricht dann ab, da keine Antwort kommt (Ist ja auch noch nicht implementiert). Ich werde euch auf dem Laufenden halten, ist jedenfalls schonmal ein grosser Fortschritt. Danke für die Hilfe!
Das wäre dann wohl eine Bugmeldung an die USB Gruppe bei Linux wert... Was ist eigentlich so schlimm an Standards, dass keiner versucht sie einzuhalten?
Es ist überhaupt nix Schlimmes an Standards. Aber wenn die Möglichkeit besteht, ein sehr einfaches Interface bereitzustellen, dann darf ich das doch wohl nutzen wenn es denn funktioniert. Das ist ja auch kein Gerät zum Verkaufen, sonst würde ich einen Full-Speed-USB-Controller (Für entsprechendes Geld) verwenden und alles hätte wieder seine Richtigkeit. Ausserdem dürfte in diesem Fall die Einschränkung auf Full-Speed-Geräte mit der "Last" auf dem Bus zusammenhängen (Durch das Polling ist der Bus zu etwa 90% "belastet", da die Mitteilungen nur mit 1.5Mbit/s übertragen werden).
> Was ist eigentlich so schlimm an Standards, dass keiner versucht sie > einzuhalten? Das hier geht doch fast noch. Ich kann mich dunkel an einen Thread hier im Forum erinnern, in dem erklärt wurde, was der USB für eine Fehl-Konstruktion ist. Da entwickelt man bewusst an der Spezifikation vorbei und hinterher funktioniert es nicht an allen möglichen Hosts, Frechheit sowas. > Aber wenn die Möglichkeit besteht, ein sehr einfaches Interface > bereitzustellen, dann darf ich das doch wohl nutzen wenn es denn > funktioniert. Na klar. Und wenn die Möglichkeit besteht, mit 120 durch die geschlossene Ortschaft zu fahren, dann darfst Du das auch. Die Spezifikation ist ein Gesetz, nicht eine Empfehlung!
Moppel wrote: >> Aber wenn die Möglichkeit besteht, ein sehr einfaches Interface >> bereitzustellen, dann darf ich das doch wohl nutzen wenn es denn >> funktioniert. > > Na klar. Und wenn die Möglichkeit besteht, mit 120 durch die > geschlossene Ortschaft zu fahren, dann darfst Du das auch. Die > Spezifikation ist ein Gesetz, nicht eine Empfehlung! Ein Gesetz. Na aber loool. Würden sich alle Leute an alle Spezifikationen halten, gäbe es keine Probleme mit Inkompatibilitäten und solchem Mist. Willst du jetzt alle einsperren, die sich nicht daran halten? Ausserdem: Euch braucht meine Verletzung der Spezifikation ja nicht zu stören, ich zwinge niemanden, den Code zu verwenden. Übrigens: Äpfel und Birnen sind gut für Fruchtsalat, nicht für Vergleiche.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.