Forum: PC Hard- und Software Verständnisproblem: USB -> String-Descriptor & Unicode


von Ralf (Gast)


Lesenswert?

Hi,

ich hab ein Verständnisproblem bzgl. Unicode in Verbindung den USB 
String-Descriptoren.
Für die String-Descriptoren ist laut USB-Spec der String-Descriptor 0 
eine Tabelle mit 16-Bit-Codes (LanguageID) für die vom Gerät 
implementierten Sprachen, beispielsweise 0x0409 für Amerikanisch, 0x0407 
für Deutsch, 0x0419 für Russisch, etc.

Die USB-Spec fordert Unicode-codierte Strings. In allen Beispielen, die 
bei diversen µC-DevKits dabei sind, werden die einzelnen Buchstaben 
durch jeweils zwei Bytes gebildet (was wohl UTF-16 bedeutet), wobei das 
High-Byte immer 0x00 ist.
Ich verstehe den Zusammenhang zwischen der LanguageID und den Buchstaben 
noch nicht ganz.

1) Ist das High-Byte der 'Buchstaben' immer 0x00? Wenn nicht, wann 
würde es sich ändern? -> Bei einem (als Beispiel) kyrillischen 
Buchstaben? Kyrillisch ist jetzt vielleicht ein schlechtes Beispiel, 
aber was besseres fiel mir nicht ein :/

2) Wird der 16-Bit-Wert der LanguageID auf irgendeine Weise zum 
16-Bit-Wert des Buchstabens dazu gerechnet oder sind diese unabhängig 
voneinander zu betrachten? -> Ich vermute unabhängig, denn wenn ich das 
High-Byte als 0x00 annehme, komme ich gemäß Unicode-Codierung bei 
ASCII-Zeichensatz raus (was erstmal sinnvoll erscheint). Dient die 
LanguageID dann eher zur Auswahl einer passenden Schriftart?

3) Damit der entsprechende String korrekt dargestellt wird muss das OS 
ja dann auch die passende Schriftart parat haben -> Ich kann mir aber 
nicht vorstellen, dass ein OS alle möglichen Schriftarten für alle 
Sprachen in petto hat. Ist es daher richtig anzunehmen, dass das 
High-Byte der Buchstaben deswegen immer 0x00 ist, weil der ASCII-Zeichen 
in allen Schriftarten implementiert ist?

Ralf

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Ralf schrieb:
> Ist das High-Byte der 'Buchstaben' immer 0x00?

Nö, das ist es recht schnell nicht mehr. Mach mal die 
Windows-Zeichentabelle (Start->Ausführen "charmap.exe") auf und sieh Dir 
die Unicode-Codierung an. Alles, was über ISO8859-1 ("ANSI", 
Windows-Codepage 1251) hinausgeht, hat Zeichencodes > 255, und belegt 
damit das obere Byte.

von Ralf (Gast)


Lesenswert?

> Alles, was über ISO8859-1 ("ANSI", Windows-Codepage 1251) hinausgeht, hat
> Zeichencodes > 255, und belegt damit das obere Byte.
Stimmt, danke für den Tip mit CharMap. D.h. aber, die Schriftart ist 
entgegen meiner Vermutung (nahezu) unabhängig von der Sprache bzw. dem 
eigentlichen Unicode-Wert, die Schriftart wird eher passend rausgesucht.

Ralf

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Die Schriftart ist völlig irrelevant, es geht um Zeichencodierung.

Es ist nur so, daß nicht jede mit Windows mitgelieferte Schriftart den 
vollen Unicode-Umfang darstellen kann.

von Ralf (Gast)


Lesenswert?

> Die Schriftart ist völlig irrelevant, es geht um Zeichencodierung.
> Es ist nur so, daß nicht jede mit Windows mitgelieferte Schriftart den
> vollen Unicode-Umfang darstellen kann.
Okay. Ich schätze ich werd nie vor dem Problem stehen, dass ich mal eine 
völlig ungewohnte Zeichencodierung für ein USB-Gerät brauche, aber die 
Zusammenhänge zu kennen ist sicher hilfreich.
Ich werd mich daher auf Englisch/Deutsch beschränken.

Danke!

Ralf

von MU45 (Gast)


Lesenswert?

Hallo,

ich versuche gerade ein

#define BUILD_NR "49"

welches automatisch von Subversion erzeugt wird in ein WORD array in 
einem USB string descriptor zu speichern. (siehe weiter Unten)
Die Struktur wird später ausgelesen und soll dann in einem C# Programm 
Version 49 anzeigen. D.h. Version ist hart codiert und die 
Versionsnummer wird variabel über Subversion erzeugt. Wenn ich das ganze 
Array mit Konstanten fülle, funktioniert es.

Leider habe ich gerade keinen Ansatzpunkt, wie ich die 4 und die 9 als 
einzelne Elemente in das ARRAY aus WORD Elementen bekomme.
Durch das Define habe ich ja nur eine Textersetzung. D.h. datentyplos.

Das ganze sieht so aus:

//Manufacturer string descriptor
ROM struct{BYTE bLength;BYTE bDscType;WORD string[29];}sd001={
sizeof(sd001),USB_DESCRIPTOR_STRING,
{'V','e','r','s','i','o','n',' ','hier soll die 4 stehen','hier soll die 
9 stehen'
}};

Hat jemand einen Ansatzpunkt, wie ich dieses Problem lösen könnte?
Habe google bereits ausgiebig gestresst. ;)

Gruß MU45

von Clemens L. (c_l)


Lesenswert?

Am einfachsten ginge das, wenn du den automatisch generierten Code in
1
#define BUILD_NR 49

oder
1
#define BUILD_NR '4','9'

ändern könntest.

Falls nicht, musst du ein separates Programm (oder ein ensprechendes 
Skript) benutzen:
1
#define BUILD_NR "49"
2
#include <stdio.h>
3
4
int main() {
5
    printf("{'V','e','r','s','i','o','n',' ','%c','%c'}\n",
6
           BUILD_NR[0], BUILD_NR[1]);
7
    return 0;
8
}

von Tobias W. (mu45)


Lesenswert?

Hallo vielen Dank für die schnelle Antwort.
Ich werde das gleich mal versuchen.

Gruß MU45

von Thomas (Gast)


Lesenswert?

Noch einfacher ist es nicht einen String zu verwenden sondern die im 
device descriptor vorgesehenen Felder zu benutzen. Vielleicht willst du 
mal ein von der Version abhängigen Treiber verwenden.
Thomas

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.