KI-Agenten, USB-Hubs und die Rettung meiner Fingerkuppe – oder: Wie man für ein paar Cent einen USB-Hub erzieht

Es ist Sonntagabend. Eigentlich könnte man auf dem Sofa sitzen, etwas Sinnvolles tun oder einfach gar nichts. Stattdessen liegt ein zerlegter USB-Hub auf dem Schreibtisch, daneben ein Lötkolben und die Erkenntnis, dass künstliche Intelligenz zwar beeindruckend viel Code schreiben kann, aber offenbar keinerlei Vorstellung davon hat, wie lange vier Minuten sein können.

Weiterlesen: KI-Agenten, USB-Hubs und die Rettung meiner Fingerkuppe – oder: Wie man für ein paar Cent einen USB-Hub erzieht

KI-Agenten sind toll. Solange sie keine Finger brauchen.

Wer sich aktuell mit KI-gestützter Softwareentwicklung beschäftigt, kennt das: Man gibt einem Coding-Agenten eine Aufgabe, lehnt sich zurück und schaut zu, wie er Code schreibt, kompiliert, Fehler findet, korrigiert und anschließend Tests ausführt.

Zumindest in der Theorie.

In meinem Fall geht es um die Entwicklung eines Bootloaders für einen nRF52840. Der soll natürlich nicht nur irgendwie funktionieren, sondern auch zuverlässig getestet werden. Und genau hier beginnt das Problem.

Der KI-Agent hat nämlich eine ausgesprochen kreative Vorstellung von Human in the Loop entwickelt.

Sinngemäß:

„Bitte halte jetzt den BOOTSEL-Taster gedrückt.“

Okay.

„Und jetzt den USB-Stecker abziehen.“

Äh, Moment.

„Den Taster bitte weiterhin gedrückt halten.“

Natürlich.

„Jetzt den USB-Stecker wieder einstecken.“

Mit welcher Hand eigentlich?

Und weil der Agent gerade einen längeren Testdurchlauf geplant hat, darf man das Spiel im Zweifelsfall auch noch vier Minuten lang wiederholen beziehungsweise den Taster entsprechend lange gedrückt halten.

Vier Minuten.

Probiert das ruhig einmal aus. Einen winzigen Taster vier Minuten gedrückt halten, während man gleichzeitig USB-Stecker jongliert und darauf wartet, dass eine KI mit ihrem Leben fertig wird.

Irgendwann stellt sich unweigerlich die Frage, wer hier eigentlich wen automatisiert.

Der Mensch sollte doch die KI beaufsichtigen. Nicht als biologischer GPIO-Expander auf Abruf bereitstehen.

Im Schrank liegt doch noch irgendwo ein USB-Hub

Die offensichtliche Lösung wäre natürlich ein professioneller, programmierbarer USB-Hub mit einzeln schaltbarer Stromversorgung der Ports.

Solche Geräte gibt es. Sie funktionieren vermutlich auch hervorragend. Nur kosten sie teilweise Beträge, für die man schon wieder einen respektablen Stapel Entwicklungsboards kaufen könnte.

Und eigentlich möchte ich ja nur einen USB-Stecker automatisiert ziehen und wieder einstecken.

Also wurde erst einmal der Schrank durchsucht.

Zum Vorschein kam ein günstiger 7-Port-USB-3.0-Hub mit der Platinenbezeichnung CH-H207U3 V2.6. Eines dieser Geräte, bei denen jeder USB-Port einen eigenen Taster besitzt. Man kann damit die Stromversorgung der Ports ein- und ausschalten.

Das klingt zunächst ziemlich praktisch.

Bis man feststellt, dass die Taster nicht einfach schalten, sondern erst nach längerem Drücken reagieren.

Offensichtlich hat jemand entschieden, dass ein USB-Port eine Art Sicherheitsfreigabe benötigt. Vermutlich damit niemand versehentlich seinen USB-Stick ausschaltet, während er gerade versucht, den Taster zu treffen.

Für die Automatisierung ist das jedenfalls ungefähr so hilfreich wie eine elektronische Parkbremse, die erst nach einem dreiminütigen Gespräch mit dem Fahrzeug löst.

Aber: Die Hardware zum Schalten ist bereits vorhanden.

Also aufschrauben.

Zwei Renesas-Chips und eine interessante Entdeckung

Auf der Platine sitzen zwei Renesas µPD720210. Das sind USB-3.0-Hub-Controller mit jeweils vier Downstream-Ports. Einer davon wird für die Kaskadierung verwendet, womit man auf die sieben externen USB-Anschlüsse kommt.

Soweit nichts Ungewöhnliches.

Interessant wird es beim Blick ins Datenblatt.

Der µPD720210 besitzt nämlich eigene Ausgänge zur Steuerung der Port-Stromversorgung. Sie heißen PPON beziehungsweise PPONxB und sind genau für diesen Zweck gedacht.

Ein USB-Hub-Controller, der die Stromversorgung seiner USB-Ports selbst schalten kann.

Wer hätte das gedacht?

Offenbar nicht unbedingt derjenige, der diese Platine entwickelt hat.

Denn die sieben USB-Ports werden hier über P-Kanal-MOSFETs geschaltet, deren Gates wiederum von zusätzlichen kleinen Controllern angesteuert werden. Diese kümmern sich um die Taster, die Long-Press-Erkennung und sogar darum, sich den Schaltzustand über einen Stromausfall hinweg zu merken.

Eine bemerkenswerte Menge Aufwand für die Aufgabe, einen USB-Port ein- und auszuschalten.

Das eigentlich Erfreuliche: Unter Linux gibt es längst ein Werkzeug, um die Port-Power-Funktion der Renesas-Controller anzusprechen.

Es heißt uhubctl.

Und damit war klar: Der Hub kann softwareseitig bereits genau das, was ich brauche.

Nur die Platine hat davon offenbar noch nichts mitbekommen.

Kurzer Exkurs: Unbeschriftete ICs sind eine Unsitte

Natürlich wollte ich zunächst verstehen, was die zusätzlichen Controller eigentlich machen.

Auf der Platine sitzen zwei kleine SOIC-14-Bausteine.

Ohne lesbare Typenbezeichnung.

Keine Herstellerkennung. Keine Teilenummer. Kein vernünftiger Hinweis, was sich darin befindet.

Einfach vierzehn Beinchen und viel Selbstbewusstsein.

Liebe Elektronikhersteller: Wenn ihr schon Mikrocontroller auf eine Platine lötet, wäre es ausgesprochen nett, wenn man erkennen könnte, welche.

Ich erwarte ja nicht, dass ihr den vollständigen Quellcode auf das Gehäuse graviert. Eine Teilenummer würde schon reichen. Und Ehrlich die Funktion die er übernimmt ist nicht so schützenswert.

Stattdessen darf man Leiterbahnen verfolgen, Pins durchklingeln, Spannungen messen und anschließend Datenblätter nach einem Pinout durchsuchen, das ungefähr passen könnte.

Bei diesem Hub ergab die Analyse:

  • Versorgung mit 5 V.
  • Vier Eingänge für Taster.
  • Vier Ausgänge zur Ansteuerung der P-MOSFETs.
  • Ein paar weitere Pins mit zunächst unbekannter Funktion.
  • Keine externe EEPROM-Speicherung.
  • Keine vernünftige Beschriftung.

Die Pinbelegung erinnerte auffällig an einige kleine Padauk- und ELAN-Mikrocontroller.

Also wurden Datenblätter gewälzt, mögliche Ersatzcontroller gesucht und zwischenzeitlich sogar überlegt, die beiden Bausteine komplett durch eigene Firmware zu ersetzen.

An dieser Stelle fiel mir auf, dass ich gerade dabei war, aus einem simplen USB-Replug-Test ein vollständiges USB-Hub-Redesign zu machen.

Auch eine Form der Prokrastination. Nur mit Oszilloskop.

Der entscheidende Test: Kann uhubctl die Ports überhaupt schalten?

Zunächst wurde der Hub unter Linux untersucht.

uhubctl lässt sich unter Debian beziehungsweise Ubuntu beispielsweise so installieren:

sudo apt install uhubctl

Anschließend zeigt ein einfacher Aufruf die erkannten kompatiblen Hubs:

sudo uhubctl

In meinem Fall tauchten unter anderem diese beiden Geräte auf:

Current status for hub 2-3 [045b:0210, USB 3.00, 4 ports, ppps]
Current status for hub 1-3 [045b:0209, USB 2.10, 4 ports, ppps]

Das interessante Kürzel ist ppps.

Es steht für Per-Port Power Switching.

Der Hub meldet also ausdrücklich, dass sich die Stromversorgung seiner Ports einzeln steuern lässt.

Ein Test mit Port 4:

sudo uhubctl -l 1-3 -p 4 -a off

Und tatsächlich:

Sent power off request
New status for hub 1-3
  Port 4: 0000 off

Der angeschlossene nRF52840 verschwand aus der USB-Geräteliste.

Großartig.

Nur leuchtete seine LED weiterhin.

Der Hub hatte also den Port logisch abgeschaltet, aber die 5-V-Versorgung blieb bestehen.

Das ist für einen echten Kaltstart natürlich ungefähr so hilfreich wie ein Neustart-Knopf, der nur den Bildschirm ausschaltet.

Warum die Hardware nicht mitspielt

Die vorhandenen USB-Ports werden über P-Kanal-MOSFETs geschaltet.

Bei einem der untersuchten Ports sah die Beschaltung vereinfacht so aus:

High side P-Kanal Mosfet der direkt von unkenntlichen MCU geschaltet wurde und ein 100kOhm Pull-Up auf VBUS hat.

Die Logik ist einfach:

  • Gate auf 0 V: MOSFET leitet, USB-Port bekommt 5 V.
  • Gate auf 5 V: MOSFET sperrt, USB-Port ist stromlos.

Der Renesas-Controller besitzt zwar die passenden PPON-Ausgänge, liefert aber 3,3-V-Logik.

Und 3,3 V am Gate eines P-MOSFETs, dessen Source auf 5 V liegt, sind eben keine zuverlässige Abschaltung.

Also brauchen wir eine kleine Pegelanpassung von 3,3 V auf 5 V.

Man könnte dafür zusätzliche Logikgatter einsetzen. Oder Transistorstufen aufbauen. Oder einen weiteren Mikrocontroller verwenden.

Man könnte auch eine neue Platine entwerfen und sich damit das komplette Wochenende ruinieren.

Oder man schaut in die Elektronik-Kiste.

Die Lösung kostet ein paar Cent und liegt schon im Fundus

Dort lag noch ein kleines bidirektionales 4-Kanal-Level-Shifter-Modul, wie man es normalerweise für I²C verwendet.

Diese Module bestehen üblicherweise aus vier BSS138-MOSFETs und ein paar Widerständen.

Auf der einen Seite 3,3 V, auf der anderen 5 V.

LOW wird durchgereicht, HIGH auf den jeweiligen Versorgungsspannungspegel gezogen.

Und genau das brauchen wir.

Die Verbindung vom ursprünglichen Tastercontroller zur Gate-Ansteuerung wurde getrennt. Stattdessen geht der PPON-Ausgang des Renesas auf die 3,3-V-Seite des Pegelwandlers und die 5-V-Seite auf den vorhandenen Gate-Widerstand.

Vereinfacht:

PPON -> LV1 HV1 -> P Mosfet Gate

Gemeinsame Masse natürlich vorausgesetzt.

Das Ganze funktioniert, weil die PPON-Ausgänge aktiv LOW sind:

PPON-AusgangLevel-Shifter-AusgangUSB-Port
0 Vca. 0 VEingeschaltet
3,3 Vca. 5 VAusgeschaltet

Keine Firmware.

Keine I²C-Kommandos an einen zusätzlichen Controller.

Keine Long-Press-Erkennung.

Kein Zustandsspeicher.

Und vor allem: kein menschlicher Finger mehr notwendig.

Auf der Platine wurden zunächst drei Ports umgebaut. Die PPON-Signale kommen direkt von den Renesas-Controllern, der kleine Level-Shifter sitzt links neben den USB-Buchsen und die vorhandenen Leistungsschalter werden weiterverwendet.

Die ursprüngliche Hardware darf also weiterhin die eigentliche Arbeit machen. Sie bekommt nur endlich die richtigen Befehle.

Und plötzlich funktioniert es

Nach dem Einlöten kam der spannende Moment.

USB-Stick einstecken.

LED leuchtet.

Dann:

sudo uhubctl -l 1-3 -p 4 -a off

Die LED geht aus.

Nicht nur die USB-Verbindung verschwindet. Auch die Stromversorgung wird abgeschaltet.

Und anschließend:

sudo uhubctl -l 1-3 -p 4 -a on

Der Stick startet wieder.

Genau so soll ein USB-Replug funktionieren.

Anschließend wurden auch die beiden anderen Ports angeschlossen und getestet.

Alle drei Ports lassen sich jetzt unabhängig voneinander über uhubctl schalten.

Ein paar praktische uhubctl-Beispiele

Damit sich der Umbau auch lohnt, hier noch ein paar Kommandos für den Alltag.

Alle kompatiblen Hubs anzeigen

sudo uhubctl

Einen bestimmten Port ausschalten

sudo uhubctl -l 1-3 -p 2 -a off

Port wieder einschalten

sudo uhubctl -l 1-3 -p 2 -a on

Mehrere Ports gleichzeitig ausschalten

sudo uhubctl -l 1-3 -p 2,3,4 -a off

Mehrere Ports wieder einschalten

sudo uhubctl -l 1-3 -p 2,3,4 -a on

Einen vollständigen USB-Replug ausführen

sudo uhubctl -l 1-3 -p 4 -a off
sleep 1
sudo uhubctl -l 1-3 -p 4 -a on

Die Portpfade wie 1-3 sind natürlich vom jeweiligen Rechner und der USB-Topologie abhängig. In meinem Fall besitzt der Hub getrennte USB-2.0- und USB-3.0-Instanzen, die uhubctl beim Schalten entsprechend berücksichtigt.

Automatisierter Replug-Dauertest

Wer einen Bootloader entwickelt, möchte natürlich nicht nur einmal wissen, ob das funktioniert.

Also:

#!/usr/bin/env bash
set -euo pipefail

HUB="1-3"
PORT=4

for i in $(seq 1 100); do
    echo "USB-Replug $i/100"

    sudo uhubctl -l "$HUB" -p "$PORT" -a off >/dev/null
    sleep 1

    sudo uhubctl -l "$HUB" -p "$PORT" -a on >/dev/null
    sleep 2
done

Damit lassen sich 100 Power-Cycles durchführen, ohne auch nur einmal einen USB-Stecker anfassen zu müssen.

Ob das angeschlossene Gerät nach jedem Zyklus korrekt enumeriert und sein Bootloader tatsächlich funktioniert, sollte die Testsoftware natürlich zusätzlich überprüfen. Das reine Ein- und Ausschalten ist noch kein vollständiger Funktionstest.

Und weil es geht: K.I.T.T.-Lauflicht

Wenn man schon drei einzeln schaltbare USB-Ports besitzt, kann man natürlich auch vollkommen sinnvolle Dinge damit tun.

Zum Beispiel drei USB-Leuchten anschließen und ein Lauflicht wie bei K.I.T.T. aus Knight Rider bauen.

#!/usr/bin/env bash
set -euo pipefail

HUB="1-3"
DELAY=0.25

cleanup() {
    sudo uhubctl -l "$HUB" -p 2,3,4 -a on >/dev/null
}
trap cleanup EXIT

while true; do
    for port in 2 3 4 3; do
        sudo uhubctl -l "$HUB" -p 2,3,4 -a off >/dev/null
        sudo uhubctl -l "$HUB" -p "$port" -a on >/dev/null
        sleep "$DELAY"
    done
done

Die Geschwindigkeit ist durch die USB-Kommandos natürlich begrenzt.

Aber immerhin hat der Hub jetzt mehr Unterhaltungswert als vorher.

Und ja, selbstverständlich ist das technisch völlig unnötig.

Das war aber noch nie ein überzeugendes Argument gegen ein Lauflicht.

Ein paar technische Einschränkungen

Bevor jetzt jemand den erstbesten USB-Hub aufschraubt und wahllos BSS138-Module hineinlötet: Diese Lösung funktioniert nicht automatisch bei jedem Hub.

Der verwendete Controller muss die Port-Power-Steuerung unterstützen und die entsprechenden Signale müssen zugänglich sein. Außerdem muss die vorhandene Leistungsschaltung zur aktiven LOW-Ansteuerung passen.

Die bisherigen Controller-Ausgänge dürfen nicht einfach parallel zu den neuen Signalen hängen bleiben. Zwei gegeneinander arbeitende Ausgänge sind keine besonders elegante Form der digitalen Kommunikation.

Und natürlich sollte man vor dem Umbau die Pegel messen, die Versorgung prüfen und sicherstellen, dass der Hub nach dem Einschalten noch korrekt enumeriert. Manche PPON-Pins haben zusätzlich Konfigurationsfunktionen beim Reset.

Auch wichtig: Bei angeschlossenen USB-Speichermedien ist ein erzwungener Power-Cycle keine gute Idee. Die haben üblicherweise wenig Verständnis dafür, mitten in einem Schreibvorgang den Strom zu verlieren.

Fazit: Sonntagabend und eine gerettete Fingerkuppe

Am Ende brauchte es keine neue USB-Hub-Platine, keinen eigenen Mikrocontroller, keine zusätzliche Firmware und keinen teuren industriellen USB-Hub.

Nur einen günstigen Hub aus dem Schrank, einen Blick ins Renesas-Datenblatt, ein paar Messungen, etwas Löterei und einen BSS138-Level-Shifter aus dem Fundus.

Drei Ports lassen sich jetzt einzeln per Software ein- und ausschalten.

Der Bootloader kann damit automatisiert getestet werden. USB-Replug-Zyklen lassen sich reproduzierbar ausführen. Und der KI-Agent muss nicht mehr alle paar Minuten einen Menschen darum bitten, einen winzigen Taster gedrückt zu halten.

Was bleibt, ist eine durchaus interessante Erkenntnis:

KI-Agenten können inzwischen erstaunlich selbstständig Software entwickeln. Aber wenn man nicht aufpasst, degradieren sie den Menschen zum teuersten und unzuverlässigsten GPIO der gesamten Testumgebung.

Immerhin lässt sich dieses Problem für ein paar Cent beheben.

Es ist Sonntagabend.

Der USB-Hub funktioniert.

Die Fingerkuppe ist gerettet.

Und wenn der KI-Agent morgen wieder einen vierminütigen Tastendruck verlangt, bekommt er statt eines Fingers ein Shell-Skript.

Das nennt man dann wohl Human out of the Loop.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert

Diese Website verwendet Akismet, um Spam zu reduzieren. Erfahre, wie deine Kommentardaten verarbeitet werden.