Seite 1 von 2

Virtuelles USB-Serial-Device (FTDI-Treiber), Bytestream "garbled"

Verfasst: Sa 25. Jan 2025, 03:50
von mh1962
Ich habe auf meinem Laptop ein mit Xen virtualisiertes Android-x86.

Um auch Applikationen sinnvoll nutzen zu können, die einen Standort abfragen, nutze ich den GPS Connector. Mit dem Simulations-Modus und dem "Abspielen" einer Datei, die ich ebenfalls mit dem GPS-Connector auf meinem Handy erzeugt habe, klappt das auch wunderbar.

Um die GPS-Funktion granularer steuern zu können wollte ich mir nun ein virtuelles USB-Serial-Device einrichten, dass ich vom Host aus mit NMEA-Daten versorgen kann. Dabei wird ein FTDI-USB-Serial-Device emuliert. Das funktioniert nur "fast".

Fast heißt: Die NMEA-Daten kommen an und sind im Terminal-Modus des GPS-Connector an, sind aber "verhunzt". Lasse ich sie mitschreiben sehe ich im Hexdump, dass wiederholt die zwei Byte "B1 00" in den Byte-Stream "eingestreut" wurden. Dann können die NMEA-Sätze natürlich nicht mehr sauber geparst werden. Die Daten kommen aber alle an, nur die zusätzlichen Bytes stören offensichtlich.

Richte ich ein identisches USB-Serial-Device in einer Linux-VM ein, passiert das nicht. Und wenn ich in meinem virtualisierten Android die App "Serial USB Terminal" benutze, passiert das auch nicht. Das Problem müsste von daher am ehesten im GPS-Connector selbst liegen, möglicherweise in der FTDI-Unterstützung.

Ich habe mir also mal ein Debug-Log erzeugt. Es ist auch voller Meldungen "invalid status byte". Ein kausaler Zusammenhang mit meinem Problem ist also nicht unwahrscheinlich.

Ich würde es auch gerne anhängen, aber egal welche Extension ich für die Datei verwende, wird das Hochladen mit "ungültige Dateierweiterung" vom Forum abgelehnt?!

Daher hier ein kurzer Ausschnitt, die vollständige Datei sende ich gerne auf anderem Wege:

Code: Alles auswählen

[25.01.2025 03:11:14.537]       [D]     [TID:131390530090224]   [0360::IpcServer.cpp]   [doWork()]      IPC-NMEA-DataServer [0x45]: wait for msg from client [timeout=60s]
[25.01.2025 03:11:14.817]       [E]     [TID:131390211257584]   [1230::DevImplLibUSB.cpp]       [stripFTDIStatusBytes()]        Invalid status byte at 0: 0xB1
[25.01.2025 03:11:14.836]       [D]     [TID:131390211257584]   [1231::DevImplLibUSB.cpp]       [stripFTDIStatusBytes()]        Len=512: B1 00 24 47 
[25.01.2025 03:11:14.836]       [E]     [TID:131390211257584]   [1230::DevImplLibUSB.cpp]       [stripFTDIStatusBytes()]        Invalid status byte at 64: 0xB1
[25.01.2025 03:11:14.841]       [D]     [TID:131390211257584]   [1231::DevImplLibUSB.cpp]       [stripFTDIStatusBytes()]        Len=512: B1 00 24 47 50 47 47 41 2C 30 32 31 31 31 34 2E 34 36 35 2C 34 38 34 37 2E 31 37 37 2C 4E 2C 30 30 38 30 36 2E 37 34 39 2C 45 2C 31 2C 31 30 2C 31 2E 30 2C 31 32 32 2E 30 2C 4D 2C 2C 4D 2C 2C B1 00 2A 34 
[25.01.2025 03:11:14.841]       [E]     [TID:131390211257584]   [1230::DevImplLibUSB.cpp]       [stripFTDIStatusBytes()]        Invalid status byte at 128: 0xB1
[25.01.2025 03:11:14.845]       [D]     [TID:131390211257584]   [1231::DevImplLibUSB.cpp]       [stripFTDIStatusBytes()]        Len=512: B1 00 24 47 50 47 47 41 2C 30 32 31 31 31 34 2E 34 36 35 2C 34 38 34 37 2E 31 37 37 2C 4E 2C 30 30 38 30 36 2E 37 34 39 2C 45 2C 31 2C 31 30 2C 31 2E 30 2C 31 32 32 2E 30 2C 4D 2C 2C 4D 2C 2C B1 00 2A 34 39 0D 0A 24 47 50 47 4C 4C 2C 34 38 34 37 2E 31 37 37 2C 4E 2C 30 30 38 30 36 2E 37 34 39 2C 45 2C 30 32 31 31 31 34 2E 34 36 35 2C 41 2C 41 2A 35 33 0D 0A 24 47 50 47 53 41 2C 41 B1 00 2C 33 
[25.01.2025 03:11:14.845]       [E]     [TID:131390211257584]   [1230::DevImplLibUSB.cpp]       [stripFTDIStatusBytes()]        Invalid status byte at 192: 0xB1
[25.01.2025 03:11:14.849]       [D]     [TID:131390211257584]   [1231::DevImplLibUSB.cpp]       [stripFTDIStatusBytes()]        Len=512: B1 00 24 47 50 47 47 41 2C 30 32 31 31 31 34 2E 34 36 35 2C 34 38 34 37 2E 31 37 37 2C 4E 2C 30 30 38 30 36 2E 37 34 39 2C 45 2C 31 2C 31 30 2C 31 2E 30 2C 31 32 32 2E 30 2C 4D 2C 2C 4D 2C 2C B1 00 2A 34 39 0D 0A 24 47 50 47 4C 4C 2C 34 38 34 37 2E 31 37 37 2C 4E 2C 30 30 38 30 36 2E 37 34 39 2C 45 2C 30 32 31 31 31 34 2E 34 36 35 2C 41 2C 41 2A 35 33 0D 0A 24 47 50 47 53 41 2C 41 B1 00 2C 33 2C 33 2C 36 2C 37 2C 31 31 2C 31 32 2C 31 33 2C 31 34 2C 31 38 2C 33 30 2C 33 32 2C 2C 2C 2C 31 2E 30 2C 2A 30 45 0D 0A 24 47 50 47 53 56 2C 33 2C 31 2C 31 30 2C 30 33 2C 33 38 2C B1 00 32 31 
[25.01.2025 03:11:14.850]       [E]     [TID:131390211257584]   [1230::DevImplLibUSB.cpp]       [stripFTDIStatusBytes()]        Invalid status byte at 256: 0xB1
[25.01.2025 03:11:14.854]       [D]     [TID:131390211257584]   [1231::DevImplLibUSB.cpp]       [stripFTDIStatusBytes()]        Len=512: B1 00 24 47 50 47 47 41 2C 30 32 31 31 31 34 2E 34 36 35 2C 34 38 34 37 2E 31 37 37 2C 4E 2C 30 30 38 30 36 2E 37 34 39 2C 45 2C 31 2C 31 30 2C 31 2E 30 2C 31 32 32 2E 30 2C 4D 2C 2C 4D 2C 2C B1 00 2A 34 39 0D 0A 24 47 50 47 4C 4C 2C 34 38 34 37 2E 31 37 37 2C 4E 2C 30 30 38 30 36 2E 37 34 39 2C 45 2C 30 32 31 31 31 34 2E 34 36 35 2C 41 2C 41 2A 35 33 0D 0A 24 47 50 47 53 41 2C 41 B1 00 2C 33 2C 33 2C 36 2C 37 2C 31 31 2C 31 32 2C 31 33 2C 31 34 2C 31 38 2C 33 30 2C 33 32 2C 2C 2C 2C 31 2E 30 2C 2A 30 45 0D 0A 24 47 50 47 53 56 2C 33 2C 31 2C 31 30 2C 30 33 2C 33 38 2C B1 00 32 31 31 2C 33 32 2C 30 36 2C 34 33 2C 33 34 36 2C 33 38 2C 30 37 2C 31 34 2C 30 32 34 2C 33 31 2C 31 31 2C 30 35 2C 32 30 37 2C 33 32 2A 37 44 0D 0A 24 47 50 47 53 56 2C 33 2C 32 2C 31 B1 00 30 2C 
[25.01.2025 03:11:14.854]       [E]     [TID:131390211257584]   [1230::DevImplLibUSB.cpp]       [stripFTDIStatusBytes()]        Invalid status byte at 320: 0xB1
[25.01.2025 03:11:14.892]       [D]     [TID:131390211257584]   [1231::DevImplLibUSB.cpp]       [stripFTDIStatusBytes()]        Len=512: B1 00 24 47 50 47 47 41 2C 30 32 31 31 31 34 2E 34 36 35 2C 34 38 34 37 2E 31 37 37 2C 4E 2C 30 30 38 30 36 2E 37 34 39 2C 45 2C 31 2C 31 30 2C 31 2E 30 2C 31 32 32 2E 30 2C 4D 2C 2C 4D 2C 2C B1 00 2A 34 39 0D 0A 24 47 50 47 4C 4C 2C 34 38 34 37 2E 31 37 37 2C 4E 2C 30 30 38 30 36 2E 37 34 39 2C 45 2C 30 32 31 31 31 34 2E 34 36 35 2C 41 2C 41 2A 35 33 0D 0A 24 47 50 47 53 41 2C 41 B1 00 2C 33 2C 33 2C 36 2C 37 2C 31 31 2C 31 32 2C 31 33 2C 31 34 2C 31 38 2C 33 30 2C 33 32 2C 2C 2C 2C 31 2E 30 2C 2A 30 45 0D 0A 24 47 50 47 53 56 2C 33 2C 31 2C 31 30 2C 30 33 2C 33 38 2C B1 00 32 31 31 2C 33 32 2C 30 36 2C 34 33 2C 33 34 36 2C 33 38 2C 30 37 2C 31 34 2C 30 32 34 2C 33 31 2C 31 31 2C 30 35 2C 32 30 37 2C 33 32 2A 37 44 0D 0A 24 47 50 47 53 56 2C 33 2C 32 2C 31 B1 00 30 2C 31 32 2C 31 30 2C 32 31 30 2C 33 35 2C 31 33 2C 34 35 2C 32 38 32 2C 33 33 2C 31 34 2C 37 30 2C 33 31 35 2C 33 32 2C 31 38 2C 36 39 2C 32 35 35 2C 33 39 2A 37 46 0D 0A 24 47 50 47 B1 00 53 56 
[25.01.2025 03:11:14.893]       [E]     [TID:131390211257584]   [1230::DevImplLibUSB.cpp]       [stripFTDIStatusBytes()]        Invalid status byte at 384: 0xB1
[25.01.2025 03:11:14.898]       [D]     [TID:131390211257584]   [1231::DevImplLibUSB.cpp]       [stripFTDIStatusBytes()]        Len=512: B1 00 24 47 50 47 47 41 2C 30 32 31 31 31 34 2E 34 36 35 2C 34 38 34 37 2E 31 37 37 2C 4E 2C 30 30 38 30 36 2E 37 34 39 2C 45 2C 31 2C 31 30 2C 31 2E 30 2C 31 32 32 2E 30 2C 4D 2C 2C 4D 2C 2C B1 00 2A 34 39 0D 0A 24 47 50 47 4C 4C 2C 34 38 34 37 2E 31 37 37 2C 4E 2C 30 30 38 30 36 2E 37 34 39 2C 45 2C 30 32 31 31 31 34 2E 34 36 35 2C 41 2C 41 2A 35 33 0D 0A 24 47 50 47 53 41 2C 41 B1 00 2C 33 2C 33 2C 36 2C 37 2C 31 31 2C 31 32 2C 31 33 2C 31 34 2C 31 38 2C 33 30 2C 33 32 2C 2C 2C 2C 31 2E 30 2C 2A 30 45 0D 0A 24 47 50 47 53 56 2C 33 2C 31 2C 31 30 2C 30 33 2C 33 38 2C B1 00 32 31 31 2C 33 32 2C 30 36 2C 34 33 2C 33 34 36 2C 33 38 2C 30 37 2C 31 34 2C 30 32 34 2C 33 31 2C 31 31 2C 30 35 2C 32 30 37 2C 33 32 2A 37 44 0D 0A 24 47 50 47 53 56 2C 33 2C 32 2C 31 B1 00 30 2C 31 32 2C 31 30 2C 32 31 30 2C 33 35 2C 31 33 2C 34 35 2C 32 38 32 2C 33 33 2C 31 34 2C 37 30 2C 33 31 35 2C 33 32 2C 31 38 2C 36 39 2C 32 35 35 2C 33 39 2A 37 46 0D 0A 24 47 50 47 B1 00 53 56 2C 33 2C 33 2C 31 30 2C 33 30 2C 30 34 
[25.01.2025 03:11:14.898]       [E]     [TID:131390211257584]   [1230::DevImplLibUSB.cpp]       [stripFTDIStatusBytes()]        Invalid status byte at 448: 0xB1
[25.01.2025 03:11:14.903]       [D]     [TID:131390211257584]   [1231::DevImplLibUSB.cpp]       [stripFTDIStatusBytes()]        Len=512: B1 00 24 47 50 47 47 41 2C 30 32 31 31 31 34 2E 34 36 35 2C 34 38 34 37 2E 31 37 37 2C 4E 2C 30 30 38 30 36 2E 37 34 39 2C 45 2C 31 2C 31 30 2C 31 2E 30 2C 31 32 32 2E 30 2C 4D 2C 2C 4D 2C 2C B1 00 2A 34 39 0D 0A 24 47 50 47 4C 4C 2C 34 38 34 37 2E 31 37 37 2C 4E 2C 30 30 38 30 36 2E 37 34 39 2C 45 2C 30 32 31 31 31 34 2E 34 36 35 2C 41 2C 41 2A 35 33 0D 0A 24 47 50 47 53 41 2C 41 B1 00 2C 33 2C 33 2C 36 2C 37 2C 31 31 2C 31 32 2C 31 33 2C 31 34 2C 31 38 2C 33 30 2C 33 32 2C 2C 2C 2C 31 2E 30 2C 2A 30 45 0D 0A 24 47 50 47 53 56 2C 33 2C 31 2C 31 30 2C 30 33 2C 33 38 2C B1 00 32 31 31 2C 33 32 2C 30 36 2C 34 33 2C 33 34 36 2C 33 38 2C 30 37 2C 31 34 2C 30 32 34 2C 33 31 2C 31 31 2C 30 35 2C 32 30 37 2C 33 32 2A 37 44 0D 0A 24 47 50 47 53 56 2C 33 2C 32 2C 31 B1 00 30 2C 31 32 2C 31 30 2C 32 31 30 2C 33 35 2C 31 33 2C 34 35 2C 32 38 32 2C 33 33 2C 31 34 2C 37 30 2C 33 31 35 2C 33 32 2C 31 38 2C 36 39 2C 32 35 35 2C 33 39 2A 37 46 0D 0A 24 47 50 47 B1 00 53 56 2C 33 2C 33 2C 31 30 2C 33 30 2C 30 34


Ich würde mich freuen, wenn man damit den Fehler näher untersuchen und eventuell gar beheben könnte.

Re: Virtuelles USB-Serial-Device (FTDI-Treiber), Bytestream "garbled"

Verfasst: Sa 25. Jan 2025, 05:05
von Mazuch
Wie wird denn der Datenstrom im Connector gelesen?
Eingabequelle = USB / FTDI?

FTDI Decices senden zyklisch ein Füll-Byte mit Hex 0 das ich bei der Analyse herausfiltern muss. Eventuell passiert genau das hier?

Emuliert man USB Geräte dann funktioniert das oft nicht sauber.

Falls Eingabe= USB/FTDI dann einfach mal zum Test den Generic Vendor nutzen.

Re: Virtuelles USB-Serial-Device (FTDI-Treiber), Bytestream "garbled"

Verfasst: Sa 25. Jan 2025, 05:22
von mh1962
Danke für die sehr schnelle Antwort!

Ja, bei USB Vendor ist FTDI eingestellt. Wenn ich das probeweise auf Generic umstelle, kommen aber keine Daten an. Wenn ich dann in der USB-Geräte-Liste das richtige Device auswähle, ist wieder auf FTDI umgestellt. Ich weiß jetzt nicht, wie ich das richtige Device mit dem Generic-Treiber nutzen soll. Vielleicht mache ich da ja was falsch.

Ich denke nicht, dass die Null-Bytes allein das Problem sind. Schau doch mal in das Log-Extrakt: Da steht was von einem "Invalid Status Byte ... 0xB1". Ich habe den Eindruck, dass der FTDI-Treiber im vorliegenden Fall nicht nur ein 0x0 "einstreut", sondern eben "0xb1 0x0" und man beide Bytes rausfiltern müsste. Gemäß dem Debug Log und auch gemäß dem Terminal Log scheinen beide drin zu bleiben.

Re: Virtuelles USB-Serial-Device (FTDI-Treiber), Bytestream "garbled"

Verfasst: Sa 25. Jan 2025, 06:55
von mh1962
OK, wenn man das Device erst auswählt und dann den Vendor auf Generic umstellt, scheint diese Einstellung (auch laut Debug-Log) aktiv zu sein und auch zu wirken.

Das eigentliche Fehlerbild bleibt dennoch unverändert, es kommt dieselbe Meldung "Invalid Status Byte ... 0xB1" im Debug-Log.

Re: Virtuelles USB-Serial-Device (FTDI-Treiber), Bytestream "garbled"

Verfasst: Sa 25. Jan 2025, 07:16
von Mazuch
Ok ... wenn da immer noch ein fehlerhaftes Byte kommt,
dann stimmt tatsächlich etwas mit der FTDI Emulation nicht.

Die Status Bytes des FTDI sind ja per Spezifikation fix vorgegeben,
d.h. der Emulator sendet die Status Bytes falsch oder gar nicht.
Beides hätte denselben Effekt wie im Log ausgegeben.

Ehrlich gesagt kann ich da nicht viel tun, da sonst ja reale FTDI Geräte nicht mehr funktionieren würden.

Sorry

Re: Virtuelles USB-Serial-Device (FTDI-Treiber), Bytestream "garbled"

Verfasst: Sa 25. Jan 2025, 09:13
von mh1962
Na ja... Das zusätzliche Byte taucht aber - wie schon gesagt - in selber Konstellation bei einem Linux-System nicht auf (das war mein erster Versuch, das Problem einzugrenzen, was in Linux natürlich einfacher ist als in Android) und in einer anderen App (Serial USB Terminal) auf demselben Android wo der GPS-Connector läuft auch nicht. Also irgendwo her muss das 0xB1 ja kommen bzw. irgendwie muss man es weg kriegen.

Ich werde noch mal versuchen, das Problem einzugrenzen, so weit mir das möglich ist. Ansonsten kann ich meinen schönen Ansatz, NMEA auf dem Host zu erzeugen, leider vergessen.

Trotzdem danke!

Re: Virtuelles USB-Serial-Device (FTDI-Treiber), Bytestream "garbled"

Verfasst: Sa 25. Jan 2025, 10:39
von mh1962
Hm, beim einfachen "hexdump -C /dev/ttyUSB0" als root in einem Terminal tritt das Problem unter Android auch nicht auf. Also kann es eigentlich weder an der Emulation noch am Linux-Kernel liegen.

Sobald sich eine Android-Anwendung das Serial Device holt, verschwindet (!) jedoch /dev/ttyUSB0. Offensichtlich macht da Android mal wieder was eigenes und damit kenne ich mich im Gegensatz zu Linux nicht aus. Ist wahrscheinlich eh wieder alles "vernagelt" und kaum zu debuggen. Dann vergesse ich wohl am besten meinen Ansatz.

Re: Virtuelles USB-Serial-Device (FTDI-Treiber), Bytestream "garbled"

Verfasst: So 26. Jan 2025, 01:53
von Mazuch
Ich habe mir den Code jetzt nochmal genau angeschaut - es ist exakt wie ich meinte:
Es fehlen die 2 Status Bytes der FTDI Implementierung.
FTDI Geräte senden exakt an der Paketgrenze 2 Statusbytes mit Inhalt: 0x01 XX (xx = internter FTDI Status)

Bei der Analyse suche ich die 2 Bytes und gebe im Fehlerfall die Log-Message aus, die du gepostet hast.
D.h. in deinem Fall steht an der Paketgrenze "B1 00" es müsste aber "01 XX" kommen!

Aber selbst wenn da "01 xx" noch zusätzlich mit eingestreut wäre, dann ist "B1" ja auch kein Standard ASCII Zeichen (+/-)
d.h. spätestens bei der NMEA Analyse kommt Schotter raus.
ODER
Deine FTDI Emulation sendet NMEA Binärdaten? Dann kann natürlich alles mögliche an Daten kommen.
ODER
Die Emulation gibt "B1" statt "01" aus ... das wäre eine Erklärung.

Nur nochmal für mein Verständnis:
Warum emulierst die ein FTDI Gerät und nicht ein Standard CDC Device?
Das Standard CDC Gerät streut - im Gegensatz zum FTDI - keine Status Bytes ein.

Cheers,
Markus

Re: Virtuelles USB-Serial-Device (FTDI-Treiber), Bytestream "garbled"

Verfasst: So 26. Jan 2025, 04:08
von mh1962
Danke für Deine Geduld mit diesem Problem und für die neuerliche gute Erklärung, nach der ich auch denke, dass das Problem das ist, dass 0xB1 statt 0x01 gesendet wird, denn es sind ja ZWEI Bytes, die nicht in den (ASCII-)Datenstrom rein gehören, nämlich 0xB1 und das folgende (eigentlich immer 0x00, ich nehme an, das steht als Status-Byte für "Success").

Das ist doch mal ein Ansatz für die Fehlersuche. Da muss ich mal schauen, wie das zustande kommt. Die Stelle sollte sich ja im Source-Code der Emulation ja halbwegs einfach finden lassen und notfalls sogar patchen. Und man wird nicht dümmer dabei und lernt noch was fürs Leben. :D Die Device-Emulation wird übrigens einfach über das bekannte qemu-Paket realisiert. Also, da schaue ich mal nach.

Mit CDC-Device meinst Du das, was unter Linux /dev/ttyACM0 heißt? Das scheint leider qemu als Device-Emulation nicht anzubieten, wenigstens auf den ersten Blick habe ich den Eindruck. Da schaue ich aber auch noch mal.

Re: Virtuelles USB-Serial-Device (FTDI-Treiber), Bytestream "garbled"

Verfasst: So 26. Jan 2025, 08:21
von mh1962
So... Ich habe jetzt das Problem hinreichend verstanden und für mich einen ersten Workaround gefunden.

Wie gesagt, die Device-Emulation läuft über qemu und ist dort in dev-serial.c ab Zeile 436 implementiert, siehe https://github.com/qemu/qemu/blob/maste ... ial.c#L436 und dort wird der Code ab Zeile 232 aufgerufen, siehe https://github.com/qemu/qemu/blob/maste ... ial.c#L232

Dort sieht man, dass die Emulation das unterste Bit tatsächlich auf 1 setzt, in den oberen Bits aber offensichtlich den Status der Modem-Control-Leitungen einblendet.

Ich habe nun einen einfachen Patch gemacht, der das erste der beiden Header-Bytes "hart" auf 0x01 setzt - und siehe da, mit der gepatchten Emulation läuft der GPS Connector auf Anhieb korrekt. Meine Interpretation des Sachverhalts kann so falsch also nicht sein.

Ich frage mich nun, was echte Hardware auf FTDI-Basis macht. Ich würde annehmen, dass das dort auch passieren KANN (qemu macht das vermutlich so, um echter Hardware möglichst nahe zu sein) und die "korrekteste" Lösung wäre möglicherweise, seitens der GPS-Connectors die oberen Bits des ersten Header-Bytes einfach auszublenden.

Ich werde nun mal schauen, ob ich die Modem-Control-Leitungen einfach in der Emulation auf 0 setzen kann, die sind ja in einer VM letztlich ohnehin außer Funktion und nur für Programme da, die die ausdrücklich abfragen. Das wäre auf meiner Seite ein etwas defensiveres Handling des Sachverhalts im Vergleich zu einem Patch. Wenn das nicht geht, kann ich immer noch (nur) für diese VM meinen Patch benutzen. Für mich gibt es also auf jeden Fall eine Lösung.

Solltest Du Dich allerdings entschließen, den GPS-Connector an der Stelle zu verändern, sag Bescheid, dann benutze ich gerne dessen neue Version. Ich bin natürlich auch gerne bereit, die auf Funktion in einer VM zu testen. Solltest Du diesen Fall einfach ignorieren wollen, ist das für mich natürlich auch OK.

Aber danke für Dein Feedback von heute Nacht, ohne dass ich meine Lösung nicht gefunden hätte!