HL-340 – man bekommt, was man bezahlt

Wie günstig oder vielmehr billig kann ein USB auf RS-232-Wandler sein?

Preislich lag das Teil bei 5,69 Euro mit Versand und einen Tag nach der Bestellung auf dem Tisch:

Da das Gehäuse halbtransparent ist, sieht man auch ein bisschen, was drin ist:

Nicht viel, um ehrlich zu sein. Auf dem Bild nicht ganz so gut zu erkennen: es ist wohl ein chip on board, zumindest sieht man einen schwarzen Blob. Nicht verwerflich, auch nicht unbedingt ein Merkmal von schlechter Qualität, sondern einfach ein Zeichen für Massenfertigung im Endstadium – und solange das Teil funktioniert habe ich nichts daran auszusetzen.

Am PC meldet sich das Teil als „USB-SERIAL CH340“ (VID: 1A86, PID: 7523), FTDI Chips zu faken lohnt sich offensichtlich nicht mehr, die CH340 sind mir bisher auch nicht als besonders unzuverlässig in Erscheinung getreten, soweit auch alles ok.

Allerdings habe ich immer noch meine Zweifel, ob das Teil hält, was es verspricht – ob da tatsächlich ein RS-232-kompatibles Signal rauskommt? Das Multimeter kurz an Pin 3 rangehalten: 0 V. Nope.

Das Oszi sagt ebenfalls nein:

Im Endeffekt ist es nur ein invertierter 5 V-TTL-UART in der Hoffnung dass das Gegenstück mit den Pegeln klarkommt. Auf der anderen Seite muss man hoffen, dass der kleine CH340 auch echte RS-232-Signale (also mit +12 V/-12 V) aushält.

Bisher habe ich noch nichts beobachtet, wobei der Fokus auch eher auf TX als RX stand. Mal schauen, wie das Langzeitverhalten ist (und der nächste Anschaffung wird wohl ein paar Euro mehr kosten).

Homeoffice oder: der dumme USB Sharing Switch

Seit Mitte März arbeite ich nun durchgehend zu Hause.

Damit es keine Doppelbelegung gibt und auch der Laborplatz verwendet werden kann, hängt das Arbeitsnotebook an meiner restlichen Peripherie. Die ersten Tage bin ich jeden Tag noch zweimal unter den Tisch, um die DisplayPort-Stecker von PC zu Notebook und wieder zurückzustecken. Recht schnell kam dabei der Gedanke: für wie viele Zyklen sind die Konnektoren überhaupt gemacht?

Leider hat das Dock vom Arbeitsgerät nur VGA (für 1440p eine Zumutung) und 2x DP. Aber: das Notebook selbst hat zumindest einen HDMI und meine Bildschirme jeweils auch. Mein uraltes Thinkpad hatte doch auch (nur) Displayport und alles, woran man es damals anschließen wollte, hatte wenn dann nur HDMI – also kam mal ein Adapter ins Haus.

Nun muss nur noch, Maus, Tastatur, Mikrofon und Kamera umgesteckt werden. Um nicht alles einzeln zu machen hängen alle Geräte an einem USB-Hub. Auch wenn es jetzt deutlich bequemer ist, unter den Tisch muss man trotzdem noch.

Aber auch das Problem lässt sich lösen. Für eine alte Bastelei hatte ich noch einen USB-Schalter – den auf Umschalter umzubauen, dazu noch mit vernünftigem Power select (keine Rückströme), dürfte ziemlich unangenehm sein. Glücklicherweise gibt es so etwas im Austausch kleine bunte Papierstreifen nach Hause geliefert:

USB-Umschalter „Auto Sharing Switch“

2 Buchsen für den PC, eine (verbogene) für ein Gerät, zwei Tasten. Einfach wie effektiv. Bei den Kosten und aus reiner Neugierde kann man schon einmal einen Blick ins Innere werfen. Zunächst die Unterseite:

Leiterkarte des USB-Umschalters von unten

Hmm, mit lecker Kruste sowie Hotfix (rechts oben) und ein bisschen Lötzinn an der USB-Buchse als Beilage. Das kann oben nur besser werden…

Oberseite des USB-Umschalters

Ok, das Teil heißt also FJ-U02S und stammt von www.fj-gear.com und sieht soweit gar nicht mal so gut aus – man beachte den Bereich rechts unten – da ist wohl mal der Schraubendreher (oder Hammer?) ausgerutscht…

Noch einmal ein bisschen näher:

Was um alles in der Welt haben die in der Fabrik mit dem Teil angestellt? Es fehlen Pads von 5 Bauteilen und der Hotfix macht es auch nicht besser… Die beiden Widerstände sind übrigens 1k. Der C war warscheinlich ein kläglicher Versuch, noch irgendwas am Ausgang zu filtern. Der kann von mir aus weg bleiben. Trotzdem habe ich es mir nicht nehmen lassen, die Leitungen noch ein bisschen zu verstärken.

Der Transistor schaltet übrigens die Versorgung des angeschlossenen Devices – auch dank der Dioden in Reihe mit VBUS von den Hosts ist es nicht ratsam, ein Gerät das sich über USB versorgt anzuschließen – zumindest ohne aktivem USB-Hub. Ohne Last habe ich am Ausgang knapp 4,3 V gemessen (obwohl es nach Marking Schottky-Dioden sein sollten).

Ansonsten finden sich folgende Hauptkomponenten auf dem Board:

  • WCH CH440G – Analog-Switch (PDF-Link nach China)
  • WCH CH9882 – Vermutlich ein Mikrocontroller mit USB
  • OnSemi NC7SZ32 – TinyLogic OR-Gate
  • NXP 74HC123D – Dual retriggerable monostable multivibrator with reset
  • ST LM358 – Operationsverstärker

Warum das Teil einen Mikrocontroller hat? Vermutlich aus dem gleichen Grund, warum eine CD beiliegt: Damit man vom (nicht verbundenen) PC aus den Host umschalten kann. Ich war so mutig/dumm und habe die Software installiert – allerdings tut sich soweit gar nichts.

Das Gerät meldet sich mit VID 0x1A86 und PID 0xE040 als HID an und hat sonst keinerlei Beschreibungen. Laut HID-Descriptor hat es eine Reportlänge (in und out) von 9 Byte (inkl. Report ID). Wer sich für mehr interessiert, hier mal der komplette Dump aus USB Device Tree Viewer

Leider ist das Teil nicht intelligent genug, auf den Host umzuschalten, der gerade aktiv ist (wenn der andere aus ist). Damit könnte das Teil einfach unsichtbar unterm Schreibtisch verschwinden.

Unterm Strich sieht mein Setup nun ungefähr wie folgt aus:

Einzig der (powered) USB-Hub muss manchmal aus- und wieder eingeschaltet werden, wenn die Einschaltreihenfolge der Stromversorgung und PC nicht passt. Aber vielleicht findet sich dafür auch eine sinnvolle Lösung 🙂

Beim Schreiben des Beitrags ist mir übrigens aufgefallen, dass Video auch gänzlich übers Dock funktionieren dürfte, da die Grafikkarte am PC auch einen HDMI hat. Also: 1x DP und 1x HDMI jeweils vom PC & Notebook. Solange ich aber nicht spontan zwischen Homeoffice und Arbeitsplatz wechsle bleibt es erst einmal so wie es ist.

Die perfekte USB-I2C-Bridge

TL;DR: Ich habe sie noch nicht gefunden und mich beschleicht das Gefühl, dass ich selbst eine (weitere, nicht perfekte) bauen muss.

Aber erst einmal auf Anfange: Mangels halbwegs flotter Alternative habe ich Libs in Python und C# (ein paar fixes stehen noch aus) um mit dem MCP2221 von Microchip zu sprechen.

Der Chip ist einfach und macht auch ungefähr, was er soll. Nur leider ist er – nicht nur aufgrund der natürlichen Beschränkung von USB HID – verdammt langsam. Speziell wenn es um Standardaufgaben wie Register lesen geht. Das ist ein richtig großer Zeit- und Performancefresser, denn: man muss es „kleinteilig“ durchführen: Register an den Controller schicken ist ein Befehl, auf den geantwortet wird, dann muss man den Lesebefehl senden (auf den auch wieder geantwortet wird) und anschließend muss man für jeden 60-Byte-Chunk der gelesenen Daten auch wieder lesen und auf die Antwort warten. Ich bin mir nicht ganz sicher, ob die Antwort im gleichen oder nächsten USB-Interrupt-Zeitschlitz kommt, aber im dümmsten Fall würde das bei einer ein Chunk großen Leseanforderung 2+2+2 ms bedeuten. Bei 20 Registern (manche Chips lassen das Lesen im Block nicht zu, durchaus aus guten Gründen) wären das 120 ms. Dann war’s das mit 10 Refreshes pro Sekunde – zugleich stottert das UI, wenn man die Kommunikation nicht in einen anderen Thread auslagert. Alles großer Mist. Im Datenblatt sind zudem Fehler u. a. in der Protokollbeschreibung und der einzige Kontakt bei Microchip (immerhin, sie haben geantwortet, was ich nicht erwartet hätte) hat sich hinter seiner NDA versteckt – obwohl die erfragten Infos teilweise schon im (von Microchip geschriebenen) Treiber für Linux stecken.

In der Hoffnung, dass es andere Hersteller besser machen, habe ich mir einen CP2112 von Silicon Labs geholt. Silabs hat einige Dinge deutlich besser gemacht – neben den deutlich höheren Bustakten (> 1 MHz) es gibt einen Befehl (und Konfiguration), der Leseanfragen deutlich verkürzt. Mit aktiviertem „Automatically send read response“ lässt sich ein Register mit n byte Länge am Chip mit Adresse a wählen und die Antwort der Länge l wird ohne weitere WriteReports an den Controller zurückgesendet. Im Schlimmsten Fall dauert der Lesen eines Chunks 2 ms. Beide Baumen Hoch!

Tja, wenn sie nicht in anderen Situationen ziemlich verkackt hätten. Hat man den auto read response an und möchte mit einer I2C-Adresse sprechen, die es auf dem Bus nicht gibt, läuft man ohne Threading in einen Deadlock, da es einfach keine Antwort vom Controller gibt und die ReadReport-Methode blocking ist (auch das Setzen des read timeout und retry count bringt nichts). Gerade beim I2C-Detect ist das ziemlich bescheiden. Richtig bescheiden ist an dieser Stelle auch, dass man keinen „Klingelstreich“ (Start, Adresse auswählen, Stop und einfach nur Auswerten, ob ein oder kein ACK kam) machen kann. Man muss immer mindestens ein Byte lesen. Das kann bei manchen Devices für Ärger sorgen. Gleichzeitig habe ich es nicht geschafft, bei Adresse 0 zu „klingeln“. Obwohl diese, gerade wenn man einen SMBus auf dem Tisch hat, wichtig ist.

Ja, das kann man alles umschiffen, aber wiederum zulasten der Performance. Dabei wäre alles super einfach in der Firmware zu implementieren. Anderes Manko des Chips: Man kann höchstens 512 Byte am Stück lesen und nur 61 (?) Byte am Stück schreiben. Warum nur?

FTDI FT232H (und andere). Kein HID, also muss man sich entweder mit einer DLL von FTDI herumschlagen oder mit LibUSB/WinUSB herumbasteln (Tolle Projekte aber da man Zadig verwenden muss, ist es kein wirkliches Plug & Play mehr. Was mir an der Sache überhaupt nicht gefällt: Obwohl man für das beste Benutzererlebnis die DLL von FTDI benutzten muss, ist es nötig, die MPSSE-Pakete selbst zusammenbasteln. Gleichzeitig gibt es beim Initialisieren anscheinend Glitches auf den Busleitungen und zwischen Start condition, Adressierung und Stop condition habe ich bei ersten Tests wahnsinnig große Zeitlücken gesehen. Ich habe mich nicht wirklich intensiv damit auseinandergesetzt, aber bis jetzt hat mich das elendige Treibergeschwurbel aktiv davon abgehalten, Code dafür zu schreiben.

WCH CH341A: Ein Kit liegt hier und ich habe aus Anwendersicht erste Tests (mit einem EEProm) durchgeführt. Sieht nicht ganz schlecht aus. Wie der FT232H ist es kein USB-HID und man darf wieder mit der bereitgestellten DLL oder anderen Libs basteln. Ein Bastelkollege hat sich der Sache schon angenommen. Großes Problem: Alles aus erster Hand ist nur auf chinesisch. Da ich auf der Website nix lesen kann, ist sie auch nicht verlinkt. Englische Dokus kommen m. W. nur aus der Community. Muss nicht schlecht sein, aber es riecht halt alles ein bisschen arg bastelig.

Von Cypress habe ich mal ein PSoc4-Devkit (so ein Stick) mit Kitprog USB bekommen, der auch sehr schnell I2C sprechen kann. Das Teil hat sich aber durch mehrere Dinge sehr schnell disqualifiziert: Den Treiber gab’s nicht einzeln, eine Doku zum Protokoll glaube ich auch nicht und das Teil hat sich extrem schnell so stark verschluckt, dass man die Hardware neu starten musste.
Es gibt noch z. B. den CY7C65211, allerdings ist mir in freier Wildbahn noch kein Devkit über den Weg gelaufen und ich hatte mit einem anderen USB-Chipsatz schon ein bisschen Probleme, was Treiberstabilität (irgendein USB-UART-Wandler, man konnte den Port öffnen, aber es gingen keine Daten durch). Ein paar haben sich auch ziemlich empfindlich gegenüber Störungen von außen gezeigt. Ob es der Chip oder die externe Beschaltung war, ließ sich nicht mehr richtig rekonstruieren, aber da haben doch ein paar Bauteile dicke Backen gemacht.

Alternativen? Da gäbe es noch den Buspirate von Dangerous Prototypes. Für den Entwickler-Tisch ok, aber für den ganzen Rest einfach zu groß. Zudem bis jetzt keine Single-Chip-Lösung eher ein USB <> UART <> irgendwas-Wandler

Ok, wenn wir schon beim Entwicklertisch sind – Aardvark von TotalPhase. Macht man da einmal den Deckel auf (zumindest den, den ich mal auf dem Tisch hatte), sieht man nix anderes als einen USB <> UART + AVR. Zugleich konnte man ihn nicht standalone verwenden, sondern braucht(e) eigentlich immer den ziemlich klobigen Levelshifter. Die Software ist fummelig und instabil, wobei ich nicht herausgefunden hab, ob es nicht vielleicht auch die Hardware war. Hab das Teil auf jeden Fall sehr schnell wieder zur Seite gelegt. Für meine Begriffe ist das Teil nicht seinen Kosten gerecht.

Was wäre da sonst noch? TI? Die hatten IIRC mal etwas im Programm aber das war entweder ziemlich lausig oder zumindest für Normalsterbliche faktisch nicht verfügbar.

Sonst fällt mir nicht mehr viel ein. Außer, dass ich schon vor längerer Zeit die Idee hatte, selbst einen USB<>irgendwas-Wandler zu bauen. Leider ist es bis jetzt in der Planungs-Featuritis hängen geblieben. Mal grob, was ich mir vorgestellt habe, was es können muss^Wsoll:

  • GPIOs + IRQs, PWM, …
  • ADCs
  • SPI
  • I2C
  • OneWire
  • SMI/MDIO (clause 22/45)
  • UART + RS485

Nachtrag vom 16.12.2019:
Christoph hat mich auf I2C-MP-USB von Thomas Fischl aufmerksam gemacht – vielen Dank für den Hinweis – das Teil landet auf der Bastelliste und wird sobald wie möglich getestet.

廉价 oder 有利

Günstig oder billig?

Ein Kollege brachte heute ein Stück Technik vorbei, das zwar funktionierte, aber nicht so richtig wertig wirkte:

Links ist das gute Stück, rechts ein zum Verwechseln ähnlicher USB-Charger von Samsung. Abgesehen von der Größe und und dem fehlenden Samsung-Logo (ok, das CE-Logo sieht auch eher nach „China Export“ aus) merkt man den Unterschied, wenn die Steckernetzteile in der Hand hält: Das Gewicht ist doch ziemlich unterschiedlich: Der Samsung-Charger wiegt mit 40 g ein bisschen mehr als doppelt so viel wie das Teil aus dem Reich der Mitte (18 g).

Mit ein bisschen Gewalt am oberen Ende offenbarte das Ladegerät seine inneren Werte, die man vorher schon an der USB-Buchse riechen konnte (heißes Hartpapier). Entsprechend meinen Erwartungen wurde ich nicht enttäuscht:

Hmmm, Crusty!

Zum Vergleich die Innereien eines anderen Samsung-Ladegerätes, das ich mal auseinandergenommen habe (IIRC ohne „adaptive fast charging“):

Auffälligster Unterschied: Eine richtige Sicherung, eine Common-Mode-Choke zur Funkentstörung, bisschen höherwertige Kondensatoren (wobei mir „Chang“ nicht als besonders hochwertig in Erinnerung ist), ein im Vergleich richtig fetter Transformator und ein halbwegs seriöser X-Kondensator zwischen Primär- und Sekundärseite. Der größte und auffälligste Unterschied: Eine Isolationsplatte, die durch den Slot zwischen Netzspannung und Schutzkleinspannung greift. In den Bildern sieht man es leider nicht so richtig: sie ragt 3,5 mm über die andere Seite der Leiterkarte heraus.

Aber auch auf der Unterseite sieht man deutliche Unterschiede. Zunächst, als Positivbeispiel Samsung:


Muss man noch etwas dazu sagen?

…und nun das, was man für 3,50 1,86 Euro mit USB-Kabel und Versand bekommt:

Der Isolationsabstand zwischen Primär- und Sekundärseite beträgt ca. 1,5 mm. Die Kriechstrecke sollte IIRC eher die vierfache Breite haben

Völlig unklar ist auch, wie gut die Wicklungen im Trafo voneinander isoliert sind. Wenn man genauer hinsieht, kann man zwar noch eine rote Folie unter der äußeren Wicklung erkennen, aber die Zweifel bleiben

Kurzgesagt: Das Teil würde ich definitiv nicht an mein Telefon oder etwas anderes anschließen.

Noch ein weiteres Leckerchen: Die Interpretation einer Sicherung (der Eingangswiderstand) oder besser sein Beinchen (unten mitte-links im Bild) ist so ungeschickt abgeschnitten, dass der Pin sehr nah in Richtung Ausgangsseite des Gleichrichters reicht.

Den Ausfall dürfte man dann ziemlich schnell merken 😉

USB 3.2 – Ist die Lösung schlimmer als das Problem?

Vor knapp zwei Wochen gab es in der c’t (4/2019) einen Artikel zu USB 3.2, das neben der doppelten Geschwindigkeit (20 GBit/s) auch ein älteres Problem des Systems beheben soll: BadUSB. Dabei kann z. B. ein USB-Stick mehr als Massenspeicher. Als beispielsweise Maus- und Tastatur-Simulator kann er Eingaben am Rechner durchführen, als RNDIS kann es ggf. sogar Netzwerkverkehr manipulieren. Hurra!

Mit USB 3.2 soll das alles besser werden. Mit Zerifikaten und Crypto. An der Stelle sei erwähnt, dass Apple mit im Gremium war. Wofür haben die nochmal Crypto in ihren Lightning-Steckern hinzugefügt? Um ihre Produkte sicherer zu machen oder um sich vor günstiger Nachbauware zu schützen? Ein Schelm, ….

So, jetzt stellt sich einer mal das hier vor: Ein USB-Device, sei es eine Maus, eine Tastatur, ein USB-Speicherstick, hat ein gültiges Zertifikat. Soweit, so gut. Was hindert die Maus oder Tastatur nun daran, böswillige Eingaben zu machen, von denen der User nix mitbekommt? Wenn man wollen würde, könnte man sogar hinter dem USB-Controller, also direkt an der Tastaturmatrix etwas böswilliges einbauen. Schützt einen das Zertifikat, das man wahrscheinlich für teuer Geld kaufen muss davor?

Andersrum: Wenn ein legitimer Chip mit diesem Angriffsvektor in einem dadurch illegitimen Produkt verbaut wird und dieses Zertifikat zurückgezogen oder für ungültig erklärt werden muss (wie läuft das überhaupt, muss man nun beim Einstecken eines USB-Geräts online sein?), sitzen dann die Nutzer des legitimen Produkts im Dunkeln? Was hält einen Hersteller davon ab, schlechte Firmware zu schreiben, dass man trotz Zertifikat Schadsoftware injizieren kann?

Oder noch viel einfacher: Wenn ein Angreifer eine Maus und Tastatur in einen USB-Stick (zusätzlich zum Speicher) unterjubeln will, dann kann er doch einfach einen legitimen USB-Hub vor den legitimen USB-Speicher hängen und nebendran noch eine legitime Tastatur anbasteln, die über einen weiteren µC (oder auf andere Wege) illegitime Befehle an den PC weitergibt. Zwar werden dadurch mehrere Geräte erkannt, aber welchen Unterschied macht’s?

Und wie schaut es mit alten USB-Geräten aus? Es ist ja schon ein riesiges Problem, bei USB-Type-C-Buchsen & -Steckern zu sagen, was sie denn überhaupt können. USB 2.0, USB 3.0, USB 3.1, USB 3.2, Tunderbolt, Display Port, Power Delivery mit 5 W, 10 W, 20 W, 100 W, Quelle, Senke oder beides. Kann sie Analog Audio, kann ich daran meinen Mixer anschließen?

Aber ich schweife ab: Wie sieht es mit Legacy-Devices aus? Sie von der Verwendung auszuschließen wäre Irrsinn, also müssen sie weiter funktionieren – und wen hält es ab, einen scheinbar modernen USB-Stick (z. B. mit USB Type C) einfach nur ein USB 2.0-Interface zu implementieren, das dann fleißig böse Dinge tut.

Ich muss zugeben, ich habe die Spec (noch) nicht gelesen, aber die die (ok, nicht exklusive) Apple’sche Zwangsneurose alles verdongeln zu müssen kotzt mich als User, Bastler und Entwickler einfach nur noch an.

Warum löst man das BadUSB-Problem nicht wie früher bei den Personal Firewalls: Ein Gerät meldet sich an, wird enumeriert, darf aber erst einmal nichts machen. Der Benutzer bekommt einen Popup mit dem neu erkannten Gerät (oder Gerätebaum) präsentiert und muss sich entscheiden, ob er die Verwendung zulassen oder verweigern möchte. Noch eine Checkbox dazu, ob man dies vorübergehend oder dauerhaft will und ob dies für alle USB-Buchsen der Fall sein soll und fertig.

Einen halbwegs eindeutigen Fingerabdruck (Vendor- & Product ID, Seriennummer, Descriptors) haben eigentlich alle Geräte und ja ich weiß, es ist nicht perfekt und hindert ein wenig die Usability. Aber es könnte jetzt sofort für alle USB-Generationen implementiert werden. Selbst bei Eingabegeräten (Maus/Tastatur), die man an einen jungfräulichen PC anschließt, dürfte die Kopplung funktionieren, indem man eine angezeigte, zufällige Tastenfolge, eingibt.

Ich befürchte nur, dass das Ganze eher wieder ein Mittel wird, um Firmeninteressen zu verfolgen und die Sicherheit der User nur eine gefühlte bleibt.

Fail: USB-Switch

Man spricht und schreibt eher ungern über eigene Fehler und/oder das eigene Unvermögen.

Aber Fehler gehören dazu. Man kann zwar ohne sie auch lernen, aber am besten und meisten lernt man meiner Meinung immer noch aus Fehlern.

Folgende Bastelei liegt schon ewig auf dem Tisch, genau genommen seit 2016:

An den Fädeldrähten sieht man – da passte etwas am Layout nicht. Der Schaltplan dazu sieht wie folgt aus:

Keine Ahnung woran es lag, der Knoten im Kopf mit negiertem Output Enable, high side switch und Inverter war wahrscheinlich zu groß. Eigentlich total Pillepalle aber es wollte einfach nicht.

Mit Fädeldraht hat es dann auch funktioniert aber das ganze Teil ist so unbefriedigend, dass ich mich entschieden habe keinen Artikel zu schreiben. Der USB-Switch ist schlecht beschaffbar und noch bescheidener zu Löten, die Einschaltfolge (erst Strom dann Daten beim Einschalten, beim Ausschalten umgekehrt) wird nicht eingehalten, die Höhe von Stecker und Buchse passen nicht zueinander, von richtigem Differential-Pair-Routing fange ich noch nicht einmal an zu sprechen.

Trotzdem hat das Teil seinen Zweck zumindest einmal erfüllt. Ob es mal eine out-of-box funktionierende Variante geben wird – keine Ahnung. Am liebsten wäre – zumindest mir – etwas, das deutlich mehr kann, sprich: USB Switch, Strommessung, Stromlimit, Schalten per PC (ohne zusätzliche Hardware), usw.

Vielleicht. Irgendwann.


MCP2221 mit C# – aber schnell.

Nachdem die Python-Lib ganz gut funktioniert (ein paar Bugs habe ich bereits gefunden, Fixes stehen noch aus), wollte ich die Implementierung auch in C# umsetzen. Zwar gibt es von Microchip schon eine Lib, allerdings ist diese nicht Native und auch nicht open source und dadurch auf bestimmte .NET-Versionen eingeschränkt.

Um das Rad nicht neu erfinden zu müssen, wollte ich zumindest für die USB-HID-Kommunikation eine fertige Bibliothek verwenden. Bei der Suche bin ich auf HidLibrary gestoßen, die zwar nicht mehr so aktiv gepflegt wird – aber das muss nicht unbedingt viel bedeuten. Ja, auch Software kann mal fertig sein 😉

Heruntergeladen und die ersten Funktionsblöcke geschrieben. Als ersten Test habe ich i2c_detect portiert und laufen lassen. Für 127 Adressen dauert der Scan knapp über 17 Sekunden. Mit Microships MCP2221 I2C/SMBus Terminal sind es nicht ganz 11 Sekunden und mit meiner Python-Lib unter 0,7 Sekunden. Was ist da los?

Im ersten Schritt habe ich mit System.Diagnostics.Stopwatch die Schreib und Lesezeiten gemessen – jeweils braucht die Lib im Schnitt 21 ms, für jeden Probe einer Adresse sind zwei Schreib-/Lesezyklen erforderlich, kommt kein ACK für eine Adresse ist ein weiterer Zyklus für ein i2c_cancel erforderlich. Macht für einen Proben einer nicht genutzten Adresse ca. 126 ms, für 127 Adressen sind das bisschen über 16 Sekunden – kommt also hin.

Visual Studio kann Performance-Analysen und der schuldige ist schnell gefunden:

Es hängt also am HidLibrary.HidDevice::IsConnected bzw. EnumerateDevices.

Auf GitHub gibt es (Stand November 2018) auch Bugs zum Thema Performance.

Die Tickets existieren seit 2011, 2014 und 2016 – also besteht offenbar kein Interesse, das zu fixen. Ein User namens kaczart hat eine Lösung gefunden.

Um im ersten Schritt nicht zu viel zu verbasteln, habe ich einfach mal „IsConnected“ ein einstweiliges „return true;“ verpasst. Nun benötigt ein Schreibvorgang um die 3,4 ms und ein Lesevorgang knapp 2,3 ms. Unterm Strich dauert der Scan nun 2,5 Sekunden. Besser aber noch nicht gut genug.

In anderen „Projekten“ hat mir in Sachen Timing gerne mal der Debugger in die Suppe gespuckt, also mal als Release ausgeführt und Tadaa: 0,78 Sekunden. Fast so schnell wie die Python-Implementierung.

Um es nochmal genau zu wissen habe das „return true;“ aus HidDevice::IsConnected wieder entfernt und als Release ausgeführt: 14 Sekunden.

Der Hund liegt also definitiv in der Lib begraben. Workaround, Fixen, nach Alternativen suchen oder selber machen (oder einfach eine Weile abhängen lassen und etwas anderes machen)?

Mal sehen.

Was der MCP2221 sonst noch kann

Es gibt Dinge, die Zeit verschwenden, nicht richtig funktionieren und schlussendlich nicht einmal einen Sinn ergeben. Manche nennen das sogar Hobby.

Nachdem mir im Zuge der MCP-USB-Bridges keine Python-Implementierung so richtig gefallen habe, bin ich gerade dabei, selbst eine zu schreiben und mehr oder weniger ausgiebig zu testen.

GPIOs, ADC funktionieren so wie es aussieht genz gut, heute war der DAC dran.
So richtig toll ist er nicht, aber besser als nichts. Um Seine Leidensfähigkeit zu zeigen, musste ein kleines Beispiel her.

Warum nicht einfach so etwas ähnliches wie einen Hellschreiber implementieren? Nur halt extrem ranzig.

In Python geht das ordentlich schnell und einfach:

txt = "Hallo Welt!"

vals = [22,20,18,16,14,12,10,8]

meh = []
for c in txt:
    meh.extend(font[ord(c)-32])
    meh += [0]

for col in meh:
    for reps in range(4):
        curcol = col
        for y in range(8):
            if curcol & 1 == 1:
                dev.dac_setvalue(vals[y])
            else:
                dev.dac_setvalue(0)
            curcol >>= 1
            time.sleep(0.003)

Die Font liegt in als Liste vor, die alle wichtigen Zeichen ab dem Leerzeichen enthält. Vals beinhaltet die Analogwerte der jeweiligen Bits der Zeichen (in der Höhe). Der Text wird sprichwörtlich in eine Bitmap umgewandelt und einfach über den DAC rausgejagt. Damit die Zeichen etwas besser lesbar sind, werden sie 4 mal wiederholt. Die kurze Pause ist nötig, weil sich sonst der MCP verhaspelt.


Ist das nun Kunst oder kann das weg? 😉

BadUSB gone worse!?

Vor zwei Jahren präsentierte Karsten Nohl auf der Black Hat seinen Vortrag über BadUSB. Auf dem Chaos Communication Congress danach wurden, wenn ich mich richtig erinnere, USB-Sticks verteilt, deren Firmware sich einfach anpassen lässt. Von konkreten Angriffen habe ich bis jetzt von nichts gehört, trotzdem ist die „Bedrohung“ durchaus real.

USB macht seinem Namen alle Ehre – der Anschluss ist extrem universell und den Geräten sieht man nicht an, als was sie sich gegenüber dem PC anmelden. Dazu kommt, dass jedes Device nicht auf eine Funktion beschränkt ist, was grundsätzlich nichts böses ist und in manchen Fällen sogar zwingend erforderlich ist. Hier fängt aber auch das Problem an: Ein USB-Stick kann neben dem Massenspeicher auch noch ein einen Endpunkt haben, der z. B. eine Netzwerkkarte mimt. Diese kann dann den Datenverkehr belauschen und interessantes in einen unsichtbaren Bereich des Speichers ablegen. Hat der Angreifer keinen physischen Zugriff auf das Gerät, kann aber auch einfach nur der DNS umgebogen werden.

Einfacher und auf den ersten Blick weniger fatal wäre, wenn der USB-Stick auch eine Maus implementiert und den Cursor alle paar Minuten um einen Pixel verschiebt. Wären da nicht die User, die ihren PC nicht manuell sondern durch den Bildschirmschoner sperren lassen – und schon hat ein dritter zumindest Benutzerrechte. Genauso mit einer emulierten Tastatur. Wer tiefer gehen will, kann auch DMA nutzen und somit (mehr oder weniger) direkt auf den Speicher des PCs zugreifen.

Gegenmaßnahmen gab es bis jetzt keine praktikablen. Aber das USB-IF blieb nicht untätig, wie heise berichtet. Dennoch halte ich das für den falschen Weg. Wie bereits im dortigen Forum bemängelt wird, öffnet das Tür und Tor, USB bzw. Zubehör in Apple-Manier zu verdongeln – was aus Nutzersicht nur Nachteile bringt. Zudem muss wieder mal eine Crypto- und Zertifikatsinfrastruktur aufgebaut werden, die, wie wir alle gelernt haben, wahrscheinlich irgendwann geknackt wird und somit Angreifer wieder einen Vektor haben – denn ganz ehrlich: Wenn sich das Ziel sich lohnt, findet sich auch ein Weg. Ich verweise einfach mal auf die prominenten Beispiele DVD und HDCP.

Mein Vorschlag wäre deutlich pragmatischer: eine Firewall für den Host. Wird ein USB-Gerät (das erste Mal) eingesteckt, wird es zwar enumeriert aber nicht eingebunden. Der Benutzer bekommt angezeigt, welche Device-Klassen implementiert sind und wählt Zulassen oder Verweigern. Zur Unterstützung könnte das Betriebssystem auch anzeigen, ob die Funktionen plausibel wären – z. B. dass eine Maus mit RNDIS (Netzwerkinterface) dubios ist. Das schöne wäre, dass dies nicht nur für den USB-C-Type-Stecker, sondern für alle anderen USB-Versionen und komplett plattformunabhängig funktionieren könnte. Natürlich mit der Einschränkung, dass der Nutzer mit einer Meldung belämmert wird, die er unter Umständen nicht versteht. Vielleicht ist das mit den Zertifikaten doch nicht so schlecht. 😉