Der USB-Device-Descriptor enthält u. a. Einträge für herstellerspezifische Strings (USB-String-Descriptor). Diese Einträge gibt es anscheinend in zwei Versionen. Version 1 enthält Indizes, die den String-Descriptor als Array von einzelnen Bytes ansprechen. Version 2 enthält Indizes, die den String-Descriptor als Array von einzelnen Strings ansprechen. Version 2 ist natürlich attraktiver, da die String einfach numeriert werden. In Version 1 ist "mühseliges" abzählen angesagt. Version 1 funktioniert in meiner Anwendung. Meine Frage ist: Wie muß das USB-System beschaffen sein, damit ich Version 2 nehmen kann? Einfach 1,2 und 3 eintragen funktioniert leider nicht. Version 1 (Auszug) ... 0x04, /* iManufacturer */ 0x20, /* iProduct */ 0x48, /* iSerialNumber */ ... Version 2 (Auszug) ... 0x01, /* iManufacturer */ 0x02, /* iProduct */ 0x03, /* iSerialNumber */ ...
Karsten wrote: > Meine Frage ist: Wie muß das USB-System beschaffen sein, damit ich > Version 2 nehmen kann? Einfach 1,2 und 3 eintragen funktioniert leider > nicht. Doch, natürlich funktioniert das. Warum sollte es auch nicht? Vielleicht hilft Dir das hier weiter:
1 | const unsigned char String0[] = |
2 | {
|
3 | 4, 3, 9, 4 |
4 | };
|
5 | |
6 | const unsigned char String1[] = |
7 | {
|
8 | sizeof("String 1") * 2, 0x03, |
9 | 'S', 0, |
10 | 't', 0, |
11 | 'r', 0, |
12 | 'i', 0, |
13 | 'n', 0, |
14 | 'g', 0, |
15 | ' ', 0, |
16 | '1', 0 |
17 | };
|
18 | |
19 | const unsigned char String2[] = |
20 | {
|
21 | sizeof("String 2") * 2, 0x03, |
22 | 'S', 0, |
23 | 't', 0, |
24 | 'r', 0, |
25 | 'i', 0, |
26 | 'n', 0, |
27 | 'g', 0, |
28 | ' ', 0, |
29 | '2', 0 |
30 | };
|
31 | |
32 | const unsigned char String3[] = |
33 | {
|
34 | sizeof("String 3") * 2, 0x03, |
35 | 'S', 0, |
36 | 't', 0, |
37 | 'r', 0, |
38 | 'i', 0, |
39 | 'n', 0, |
40 | 'g', 0, |
41 | ' ', 0, |
42 | '3', 0 |
43 | };
|
44 | |
45 | const unsigned char* const pStrings[] = |
46 | {
|
47 | String0, |
48 | String1, |
49 | String2, |
50 | String3
|
51 | };
|
52 | |
53 | const unsigned char* getStringDescriptor(unsigned char idx) |
54 | {
|
55 | if(idx >= (sizeof(pStrings) / sizeof(pStrings[0]))) |
56 | return(NULL); |
57 | |
58 | return(pStrings[idx]); |
59 | }
|
Die Stringroutinen haben mich zum Spielen animiert. Geht ja jetzt schön einfach:) Nun ist mir aufgefallen, dass Windows mit neuen Stringdescriptoren auch einen neues USB-Device erkennt. Aber intern (Eigenschaften) den Namen aus der ersten Anmeldung mit dieser PID/VID anzeigt. Kann man die alten Namen wieder entfernen? Und wenn ja - wie?
Entweder zu Fuß mit regedt32, oder im Gerätemanager das Gerät löschen. Ist halt unglaublich dämlich wenn sich ein Betriebssystem Daten über Hot-Plug Geräte persistent hält...
Das ist wirklich sehr lästig, wenn man USB-Geräte mit Hilfe von XP entwickelt und sich nach und nach das System mit inf-Dateien und Registry-Einträgen vollmüllt. Ich würde auch gern den ein oder anderen Tipp entgegennehmen, wie man das wieder aufgeräumt bekommt. Manuell ist jedenfalls die Hölle, zumal sich nicht alle Registry-Keys löschen lassen. Manche sind wie "schreibgeschützt".
So dämlich ist das nicht. Bei eignetragenem Serial-Nummern-String erspart einem diese Windows-Funktion, dass man sich jedes mal als Admin anmelden muss, um das Gerät wieder anzumelden (wenn der Treiber nicht signiert ist). Zu Hause am Basteltisch mag das lästig erscheinen, aber wenn man dafür erst in der Firma immerzu den blöden Dialog ausfüllen muss, ist es praktisch, wenn Windows sich das merkt. Zum Enternen: Im Gerätemanager die nicht aktiven Geräte anzeigen und dann klappts: http://support.microsoft.com/kb/315539/de
ARM-Fan wrote: > Das ist wirklich sehr lästig, wenn man USB-Geräte mit Hilfe von XP > entwickelt und sich nach und nach das System mit inf-Dateien und > Registry-Einträgen vollmüllt. Dann nimm was anderes als Windows. <SCNR> Im Ernst: ich hatte letztens mal die Ehre, eine USB-Firmware zu entwickeln und kann nur sagen, dass das Windows-Verhalten, bei jedem Gerät an jedem Port den Treiber neu installieren zu wollen, meines Erachtens einfach komplett am Sinn von USB vorbei schießt. Für die Zuordnung eines Geräts zum Treiber hat USB das VID:PID-Paar gedacht (und als Alternative den Fallback auf einen klassenspezifischen Treiber). Jedenfalls war Windows das mit Abstand letzte Hostsystem, an dem ich das entwickelt habe: zeitlich, aber halt auch von den Umständen, die man damit hat (zumal ich die Windows-Kiste nur geborgt hatte in der Firma und dort natürlich nicht Admin war). Zurück zum Anfang: die Indizes sind für den Host komplett transparent. Er nimmt sie aus dem device descriptor einfach nur entgegen und präsentiert sie dir später wieder, wenn er die string descriptors anfordert. Wie du aus den Nummern zu deinen Strings kommst, ist dabei komplett deine Sache, bis auf Index 0 natürlich, der per Definition auf die Tabelle der existierenden Sprachcodes zeigt. Wenn dein Compiler C99 versteht und dein Ziel little endian ist, kannst du die Strings übrigens direkt als Unicode ablegen:
1 | #define USB_PRODUCT_NAME L"Demo"
|
2 | ...
|
3 | static struct string_descriptor const PROGMEM product_name = |
4 | {
|
5 | .bLength = sizeof(struct string_descriptor) + |
6 | sizeof(USB_PRODUCT_NAME) - sizeof(wchar_t), |
7 | .bDescriptorType = STRING_DESC, |
8 | .bString = USB_PRODUCT_NAME |
9 | };
|
Hallo Jörg, vielen Dank für deinen Programmabschnitt (GNU-Compiler für AVR-Controller?). Deinem Beitrag entnehme ich, dass du die (Un-)Tiefen der Entwicklung von USB-Systemen kennst. Kannst du mir ein Programm (für XP) nennen, mit dem ich den USB-Datenverkehr aufzeichnen und mir anschauen kann? Karsten
Karsten wrote: > vielen Dank für deinen Programmabschnitt (GNU-Compiler für > AVR-Controller?). Ja, AVR-GCC, Ziel war ein AT90USB1287. > Deinem Beitrag entnehme ich, dass du die (Un-)Tiefen der Entwicklung von > USB-Systemen kennst. Kannst du mir ein Programm (für XP) nennen, mit dem > ich den USB-Datenverkehr aufzeichnen und mir anschauen kann? Nein, ich schrob doch, dass ich nicht auf Windows arbeite. Gegen ein WinXP hatte ich damals einfach nur als letztes getestet, und fand es ringsum einfach nur lästig. Zuvor habe ich auf Linux und FreeBSD entwickelt. Das war schon deshalb praktisch unabdingbar, weil ich Zugriff auf den Sourcecode des entsprechenden Gerätetreibers bzw. die systemimmanenten Debugfunktionen der USB-Stacks benötigt habe, um die Probleme mit meiner Firmware-Implementierung sukzessive auch von der Hostseite aus einkreisen zu können. Sorry, ich habe keine Ahnung, wie man etwas vergleichbares auf Windows anstellen würde (und ich will es wahrscheinlich auch gar nicht wissen :-). Moment, da fällt mir noch ein, Snoopypro kennst du, oder? Damit habe ich bei anderen Gelegenheiten mal auf Windows arbeiten müssen (reverse engineering des Datenverkehrs zwischen AVR Studio und JTAG ICE).
> Im Ernst: ich hatte letztens mal die Ehre, eine USB-Firmware zu > entwickeln und kann nur sagen, dass das Windows-Verhalten, bei jedem > Gerät an jedem Port den Treiber neu installieren zu wollen, meines > Erachtens einfach komplett am Sinn von USB vorbei schießt. Das ist aber nur dann war, wenn den Geräten die Seriennummer fehlt. Glücklicherweise habe viele Geräte eine solche, damit stellst sich das Problem dann gar nicht erst. Aber davon ab: Wie machst Du z.B. bei CDC Devices die Zuweisung des Anschluss-Nummer, wenn Du lediglich über VID:PID gehst? Prinzip Zufall? Das wird sicherlich besonders schön, wenn Du die in Reihenfolge A anstöpselst und der Rechner nach dem Neustart in Reihenfolge B enumeriert. MSDs fallen mir noch ein, selbes Problem. Kurz: Wie willst Du mehrere Geräte mit selber VID:PID-Paarung eindeutig identifizieren, wenn Du weder über Port noch über Seriennummer gehen willst? Tatsächlich gar nicht?
Mox wrote: > Das ist aber nur dann war, wenn den Geräten die Seriennummer fehlt. > Glücklicherweise habe viele Geräte eine solche, damit stellst sich das > Problem dann gar nicht erst. Seriennummer ist so ziemlich das letzte, was man in eine eigene Firmware implementieren wird. (Also nicht, dass man es nicht haben will, aber es hat die geringste Priorität.) > Aber davon ab: Wie machst Du z.B. bei CDC Devices die Zuweisung des > Anschluss-Nummer, wenn Du lediglich über VID:PID gehst? Prinzip Zufall? Wenn keine Seriennummer da ist: ja, warum nicht? Jede Reihenfolge ist dann gleich gut. Dieses ,,ich merke mir alles bis in alle Ewgikeit''-Szenario hat halt auch nur andere Nachteile -- wenn bspw. die entsprechenden Geräte x-beliebig kommen und gehen, teilweise auf Nimmerwiedersehen, hast du dann einen Haufen ,,Karteileichen'', und wenn so ein Kommen und Gehen für zwei Hubs in Kette passiert, dann multipliziert sich das Problem. Idealerweise sollte der Nutzer irgendwo sagen können: ,,Dieses Gerät (VID, PID, Seriennummer) immer an dieser Stelle einsortieren.'' oder: ,,Ist mir egal, mach was draus.'' Wenn man die Logik, die Windows da bspw. bei CDC-Geräten ansetzt, auf Speichermedien weiterführen würde, würden dem Windows ziemlich schnell die CP/M- Laufwerksbuchstaben ausgehen... So richtig konsistent ist es also auch nicht, denn dort wird es halt nicht so gemacht. Außerdem hilft dir dieses Zuweisen bspw. einer bestimmten COM-Nummer für jeden USB-Port einzeln (bei einem Gerät ohne Seriennummer) auch nicht wirklich: du steckst dein Demoboard an einem neuen Port an, und plötzlich kraucht es mit einer völlig anderen Nummer daher... Der Effekt ist dann nicht anders, als wenn man es gleich zufällig nummeriert: du musst einfach nachgucken, wie es denn heißt. > Kurz: Wie willst Du mehrere Geräte mit selber VID:PID-Paarung eindeutig > identifizieren, wenn Du weder über Port noch über Seriennummer gehen > willst? Tatsächlich gar nicht? Selbst, wenn man das Schema gut findet, ist das ja noch lange kein Grund, für jeden neuen Port auch noch ein Fenster aufzuklappen und nach dem Admin zu rufen. Geier, dafür hat doch der Admin damals den Treiber installiert (und wenn er nicht signiert war, dann entsteht doch auch nicht mehr Sicherheit, indem man die entsprechende Bestätigung x-mal einfordern geht), warum muss man den für jeden neuen Port neu rufen? In einer kommerziellen Umgebung ist das schnell tödlich: da du nicht vorhersehen kannst, in welcher Topologie ein Nutzer später mal die Geräte benutzen wird (neuer Hub kommt dazu etc.), kannst du unmöglich vorab als Admin alle möglichen Instanzen des Geräts bereits anlegen. Das bringt dann wieder den alten Unruhm hervor, dass Windows-Administratoren gute Turnschuhe benötigen... Mind you: USB möchte Plug & Play sein, das ist eine der Grundprämissen. Davon ist die USB-Implementierung von Windows derzeit weit entfernt, da haben die Opensource-Unixe es meilenweit links liegen lassen mittlerweile.
> Seriennummer ist so ziemlich das letzte, was man in eine eigene > Firmware implementieren wird. (Also nicht, dass man es nicht haben > will, aber es hat die geringste Priorität.) Das ist so ziemlich das erste, was ich in meinen Projekten haben will. Warum auch nicht? Der Generator steht, das Einbinden kostet mich nicht mehr als ein müdes Augenzwinkern. Meine Geräte haben ausnahmslos alle eine Seriennummer, auch die privat gebastelten! Da verbiete ich meinem Windows nach der Seriennummer zu schauen, wenn mir das mal nicht passen sollte. Aber auf die Nummer selbst werde ich ganz sicher nicht verzichten. Bei CDC und MSD kann der User einzelne Geräte voneinander unterscheiden, aber bei anderen Klassen wird's schwierig. Ich wüsste auch gar nicht, wie ich mein UI gestalten sollte, wenn ich die Nummer nicht hätte. > Selbst, wenn man das Schema gut findet, ist das ja noch lange kein > Grund, für jeden neuen Port auch noch ein Fenster aufzuklappen und > nach dem Admin zu rufen. Ich halte das Schema nach wie vor für gut und richtig, aber damit hast Du natürlich recht. Das ist aber wieder ein anderes Thema.
Mox wrote: >> Seriennummer ist so ziemlich das letzte, was man in eine eigene >> Firmware implementieren wird. (Also nicht, dass man es nicht haben >> will, aber es hat die geringste Priorität.) > > Das ist so ziemlich das erste, was ich in meinen Projekten haben will. > Warum auch nicht? Weil das erste ist, erstmal den ganzen Krempel von Setup-Messages sauber zu empfangen und zu verdauen, in der Zeit zu antworten usw. usf. String descriptoren (und dazu gehört die Seriennummer nun mal) sind da eben nicht das Primäre. Wenn man so weit ist, dass man die bearbeiten kann, dann war aber zumindest für mich an dieser Stelle der Auftrag beendet, mehr war nicht zu tun. Damit war die Serien- nummer halt das letzte, was ich implementieren konnte (wobei sich deren Implementierung als Boomerang an den Auftraggeber gestaltet hat, da es noch gar kein API gab, mit dem die entsprechenden Daten im von mir geschriebenen USB-Layer hätten ermittelt werden können).
> Weil das erste ist, erstmal den ganzen Krempel von Setup-Messages > sauber zu empfangen und zu verdauen, in der Zeit zu antworten usw. Ohne Descriptoren kannst Du Dir all das auch sparen. Und ob ich da nun noch 'nen String-Descriptor zusätzlich aufsetze oder nicht macht für mich keinen Unterschied. Jedenfalls merke ich die "Mehrarbeit" nicht wirklich. > Wenn man so weit ist, dass man die bearbeiten kann, dann war aber > zumindest für mich an dieser Stelle der Auftrag beendet, mehr war nicht > zu tun. Auf SET_DESCRIPTOR-Requests reagiere ich bisher nur mit STALLs. Ich war bislang also noch nie soweit, das man die bearbeiten konnte. Das halte ich bei einer Seriennummer auch für falsch. Deswegen vermute ich mal, dass ich hier noch etwas falsch verstehe. > wobei sich deren Implementierung als Boomerang an den Auftraggeber > gestaltet hat, da es noch gar kein API gab, mit dem die entsprechenden > Daten im von mir geschriebenen USB-Layer hätten ermittelt werden können). ??? API? USB Layer? Daten ermitteln? Hier läuft das so: Ich weiß, wo die Seriennummer im Speicher zu finden ist. Nachdem ich das Device programmiert habe, ändere ich eben die entsprechenden Stellen. Das läuft automatisch, davon merke ich nix. Und wenn ich das mal nicht weiß, liest das programmierende Script eben das MAP-File. Davon merke ich auch nix. Zusätzliche Arbeit kann ich also beim besten Willen nicht erkennen. Gut, damit das entsprechend automatisch laufen kann, habe einmal etwas Arbeit. Die Betonung liegt hier auf einmal.
Mox wrote: > Auf SET_DESCRIPTOR-Requests reagiere ich bisher nur mit STALLs. Darum ging's mir nicht. > ??? API? USB Layer? Daten ermitteln? Nicht alle Projekte sind Ein-Mann-Projekte. ;-) Ich hatte den Auftrag, für ein existierendes System einen communication layer über den USB- PHY eines AT90S1287 zu zimmern, der äquivalent zu einer normalen UART-Verbindung ins System integrierbar sein sollte, die bei anderen Controllern genutzt worden ist. Da das System bislang aber nur UARTs unterstützt hatte, gab es erst einmal darin kein API, mit dem die USB-Schicht sich hätte eine Seriennummer ermitteln können. Diese Aufgabe habe ich also letztlich an diejenigen wieder abgetreten, die mir den Auftrag (innerbetrieblich) erteilt haben, natürlich war alles so weit vorbereitet, dass man das später einfach nachrüsten konnte. Die restlichen Descriptoren liegen ja alle im Flash-ROM, aber für die Seriennummer ist das wenig sinnvoll. Die sollte besser in irgendeiner Form aus einem EEPROM kommen.
> Da das System bislang aber nur UARTs unterstützt hatte, gab es erst einmal > darin kein API, mit dem die USB-Schicht sich hätte eine Seriennummer > ermitteln können. Ach so. Aber das kann Dir im Zweifel auch egal sein. Wichtig ist ja erstmal nur, dass Du die Seriennummer hast. Wenn die Anderen dann soweit sind, haben sie sofort etwas, dass sie anfragen können. Außerdem zählen die Geräte dann auch nicht mehr die Nummer hoch, je nach Anschluss und HUB. :-) > Die restlichen Descriptoren liegen ja alle im Flash-ROM, aber für die > Seriennummer ist das wenig sinnvoll. Warum? Ich halte die Seriennummer immer im FLASH und hatte damit bislang noch nicht ein einziges Problem. Was erwartet mich denn da noch? > Die sollte besser in irgendeiner Form aus einem EEPROM kommen. Extra Hardware und Platinenplatz nur für die Seriennummer? Wozu das? Und wieso EEPROM und nicht gleich eine fertige Seriennummer, z.B. DS28CM00 oder DS2401?
Hi USB MSD benütigt meines wissens per definition eine Seriennummer. Schon mal versucht an einem XP PC 2 USB MSD anzuschliessen die die gleiche Seriennummer haben? Bluesreen lässt grüssen. (kann mitlerweile besser sein, bis XP SP2 wars jedenfalls so) und Seirennummern im FW Flash? für jedes gerät, das Produziert wird eine neue FW generieren? wie soll ggf ein FW Update laufen ohne die nummer zu verlieren? auser du meinst eine sepeaten block des FW speichers, der nur für konfigdaten wie z.B. die Seriennummer verwendet wird, und der bei eine FW update nicht gelöscht wird.
Mox wrote: >> Die sollte besser in irgendeiner Form aus einem EEPROM kommen. > > Extra Hardware und Platinenplatz nur für die Seriennummer? Wir sprechen von einem AVR, der hat sowas on board. ;-) Außerdem haben noch ein Teil unserer Boards ohnehin einen Konfig-EEPROM, in dem factory calibration data abgelegt werden. Der könnte auch für die Seriennummer herhalten.
> USB MSD benütigt meines wissens per definition eine Seriennummer. Sogar das Format der Seriennummer ist in diesem Fall vorgeschrieben. > und Seirennummern im FW Flash? für jedes gerät, das Produziert wird eine > neue FW generieren? Natürlich nicht. Wie das geht, steht weiter oben. Beispielsweise kennt eines meiner Tools zum FLASHen diese Parameter: Change / IEEE address: [A=a,D=d] [KI(F=f)] [WI(F=f,I=i)] A=a,D=d Change one or more bytes in the hex file before downloading it. a Hexadecimal address (e.g. 2C03, 01BC25) d One or more bytes to be changed, in hexadecimal format, separated with dots (e.g. 4B, 1.2.3.A.B.C, 12.34.56.AB.CD.EF or 12.3.AB) dieses Tool rufst Du entsprechend auf und fertig. > wie soll ggf ein FW Update laufen ohne die nummer zu verlieren? Na wie soll das schon laufen? Bootloader sind ja nun schliesslich auch kein Hexenwerk.
> Wir sprechen von einem AVR, der hat sowas on board. ;-) Außerdem > haben noch ein Teil unserer Boards ohnehin einen Konfig-EEPROM, > in dem factory calibration data abgelegt werden. Der könnte auch > für die Seriennummer herhalten. Auch der AVR kann sich selbst programmieren, Du kannst die Daten auch locker im FLASH halten. :-) Unhandlich wird's allerdings, wenn sich die Daten ständig ändern. Da hast Du wohl recht. Aber wenn Du eh schon alles hast, dann ist es doch ein leichtes dies auch zu nutzen. Das kostet Dich doch dann keine zwei Minuten, dem Ding eine Seriennummer zu verpassen. Warum machst Du's nicht einfach?
Eine Frage zu den Seriennummern (USB MSD). Was passiert, wenn die Seriennummer nicht dem vorgeschriebenen Format entspricht? Gibt es Betriebssysteme, die dann das Gerät abweisen?
Mox wrote: > Auch der AVR kann sich selbst programmieren, Du kannst die Daten auch > locker im FLASH halten. :-) Ziemlich unpraktikabel in unserem Fall. Die Daten wären ja dann garantiert beim nächsten chip erase wieder weg. Den EEPROM kann man zumindest einigermaßen schützen, der externe EEPROM, den einige der Zielbaugruppen haben, ist sogar hardwaremäßig schreib- geschützt (und wie schon gesagt, er ist drauf, um auch noch Kalibrierungsdaten aufzunehmen, die bei der Fertigung ermittelt werden). > Aber wenn Du eh schon alles hast, dann ist es doch ein leichtes dies > auch zu nutzen. Das kostet Dich doch dann keine zwei Minuten, dem Ding > eine Seriennummer zu verpassen. Warum machst Du's nicht einfach? Weil das nicht mehr mein Bier war. Ich hatte eine abgegrenzte Aufgabe, die ich irgendwann abgeliefert habe. Und alles, was ich anfangs gesagt habe war ja, dass die Seriennummer halt das letzte Stückchen der Aufgabe war, alles andere davor war (für mich) sehr viel aufwändiger, da war aber eben an eine Seriennummer noch lange nicht zu denken.
> Weil das nicht mehr mein Bier war. Ich hatte eine abgegrenzte Aufgabe, > die ich irgendwann abgeliefert habe. Wenn Deine Aufgabe in der Implementierung des USB Teiles bestand, hast Du Deine Aufgabe eben nicht erfüllt. Die Seriennummer fehlt noch. Hier könnte ich sowas nicht abgeben. > Und alles, was ich anfangs gesagt habe war ja, dass die Seriennummer halt > das letzte Stückchen der Aufgabe war, Siehst Du, das ist der Unterschied: Bei mir beginnt die Entwicklung rund um USB beim Descriptor, einschließlich Seriennummer. Hier ist es demnach das erste Stückchen der Aufgabe. Du fängst also anders an, ohne Descriptoren? > alles andere davor war (für mich) sehr viel aufwändiger, da war aber eben > an eine Seriennummer noch lange nicht zu denken. Aufwändig? Na gut, Du willst mir also sagen, dass Du nicht bereit bist, bis zum Ende zu arbeiten und beschwerst Dich dann über Windows?
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.