loading . . . Billiger VGA-USB-Capture-Stick seziert: MS2109-Firmware, EDID-Hack und die 1080p-LĂŒge Eigentlich wollte ich nur etwas ganz Simples: Aufnahmen von meinem alten DOS-Rechner machen. BIOS-POST, der Speichertest, ein paar DOS-Spiele, einmal das alles sauber als Video festgehalten. DafĂŒr landete ein **âVGA to USB 3.0 HD 1080P Video Capture Cardâ** in meinem Warenkorb, so ein billiger Dongle fĂŒr ein paar Euro. _Spoiler_ : in genau der Form hat das nicht geklappt. Und warum es nicht klappt, ist die eigentlich spannende Geschichte. Es geht um einen 8051 mit recyceltem Mask-ROM, eine EDID die der Quelle einen Monitor vorlĂŒgt, ein â1080pâ das horizontal gar keins ist, und eine Strings-Modifikation die ich bis heute nicht ĂŒberlistet habe.
Das konkrete GerĂ€t, falls es jemand nachvollziehen will, gibt es bei Amazon unter diesem Link. Es ist einer von hunderten optisch identischen Sticks, die alle den gleichen MacroSilicon-Chipsatz tragen. Die Erkenntnisse hier gelten also fĂŒr eine ganze GerĂ€teklasse, nicht nur dieses eine Exemplar.
Die Platine des Sticks: VGA-Stecker, USB-A, 3-poliger Audio-Header und der Silkscreen AFN_VGA_Captor 2020/0615_V1.1.
### Was steckt auf der Platine?
Aufgeschraubt zeigt sich eine winzige Platine mit Silkscreen-Aufdruck `AFN_VGA_Captor 2020/0615_V1.1`, einem VGA-Stecker, einer USB-A-Buchse und einem 3-poligen Audio-Header. Drei Halbleiter machen die eigentliche Arbeit:
Ref| Chip| Funktion
---|---|---
U3| MacroSilicon MS2109| 8051-basierte UVC-Bridge, USB 2.0 High-Speed
U7| MacroSilicon MS9288A| Analoger VGA-EmpfÀnger (PLL plus ADC plus Scaler)
U2| HK / Holtek 24C16| IÂČC-EEPROM, 2 KiB
Der **MS2109** ist berĂŒhmt-berĂŒchtigt. Er steckt in den meisten der spottbilligen HDMI-Capture-Sticks, die seit Jahren durchs Netz geistern. Hier sitzt derselbe Chip in einer VGA-Variante, mit dem MS9288A als analogem Frontend davor. Wie eng die beiden Welten verwandt sind, wird sich beim Mask-ROM-Dump zeigen: die Firmware ist nachweislich aus der HDMI-Variante recycelt.
U3, der MacroSilicon MS2109. Der gleiche 8051-Chip wie in den billigen HDMI-Capture-Sticks, hier in der VGA-Variante.
U7, der MacroSilicon MS9288A. Analoges Frontend mit PLL, ADC und Scaler, lockt das VGA-Signal und digitalisiert es.
U2, der HK 24C16. 2 KiB I2C-EEPROM, hier liegen EDID, Vendor-Strings und die beiden 8051-Patch-Blöcke.
### Wie meldet sich das Ding am USB?
Beim Anstecken kommt der erste Hinweis darauf, dass die Verpackung schwindelt. âUSB 3.0âł steht drauf, der Kernel sieht aber ein High-Speed-GerĂ€t, also USB 2.0:
usb 1-1.1: new high-speed USB device number 15 using xhci_hcd
usb 1-1.1: New USB device found, idVendor=534d, idProduct=2109, bcdDevice=21.00
usb 1-1.1: Manufacturer: MACROSILICON
usb 1-1.1: Found UVC 1.00 device <unnamed> (534d:2109)
hid-generic 0003:534D:2109.0009: hiddev4,hidraw8: USB HID v1.10 Device
Vendor `0x534d` ist MacroSilicon, Produkt `0x2109` der nackte MS2109. Das GerĂ€t enumeriert als UVC-1.00-Kamera plus USB-Audio plus ein vendor-spezifisches HID-Interface. Genau dieses HID-Interface ist spĂ€ter der SchlĂŒssel: darĂŒber kommt man an das EEPROM und sogar an den Arbeitsspeicher des 8051 heran, ganz ohne Lötkolben am IÂČC-Bus.
### Das Werkzeug: ms-tools
Die zentrale Referenz fĂŒr alles, was mit MS2109 zu tun hat, ist das Projekt ms-tools von Bertold Van den Bergh. Das ist eine kleine Goldgrube: EEPROM lesen und schreiben ĂŒber die HID-Schnittstelle, Live-Zugriff auf den XDATA-Speicher zur Laufzeit (per eingeschleustem 8051-Patch-Code), das Werkzeug `mshack` zum Injizieren eigener 8051-Routinen, Ghidra-Skripte mit teildisassemblierter Firmware und ein `dump-rom`, das den kompletten 64-KiB-Mask-ROM ausliest.
Auf Ubuntu 24.04 ist das schnell gebaut:
sudo apt install golang-go libhidapi-dev libudev-dev
git clone https://github.com/BertoldVdb/ms-tools.git
cd ms-tools/cli && go build -o ../msctl .
### Der EEPROM-Dump und eine erste Korrektur
Manche MS2109-Revisionen mögen das ĂŒbliche RAM-Patching nicht, das ms-tools fĂŒr komfortable Zugriffe nutzt. Mit `--no-patch` liest der Dump trotzdem sauber, weil dann der rohe HID-Pfad ohne vorgeschaltete Firmware-Manipulation genommen wird:
msctl --raw-path /dev/hidraw8 --no-patch read EEPROM 0 2048 --filename=dumps/eeprom-vga-raw.bin
Von den 2048 Bytes sind nur 962 belegt. Die Aufteilung sieht so aus:
Offset| GröĂe| Inhalt
---|---|---
0x000 bis 0x00F| 16 B| Header: Magic `a5 5a`, dann Build-Datum `19 11 20 00` = 2019-11-20
0x010 bis 0x02F| 32 B| Vendor-Strings im Pascal-Format: `AFN_Cap video`, `AFN_Cap audio`
0x030 bis 0x079| 74 B| 8051-Patch-Code #1 (ROM-Hook-Routinen)
0x07A bis 0x179| 256 B| VollstÀndige EDID (128 Base plus 128 CTA-861-Extension)
0x17A bis 0x3C1| 584 B| 8051-Patch-Code #2, Keil-C51-kompiliert
Die ersten Bytes mit dem Hexeditor angeschaut, da steht die Geschichte schon drin:
0000 a5 5a 03 8e 09 10 ff ff ff ff ff ff 19 11 20 00 .Z............ .
0010 0e 41 46 4e 5f 43 61 70 20 76 69 64 65 6f ff ff .AFN_Cap video..
0020 0e 41 46 4e 5f 43 61 70 20 61 75 64 69 6f ff ff .AFN_Cap audio..
0030 90 de 07 ef f0 12 cd d6 90 de 07 e0 ff 02 cf 25 ...............%
Das `0e` vor jedem String ist die Pascal-LÀngenangabe (14 Zeichen). Ab `0x30` beginnt der erste 8051-Patch-Block. Spannend ist die EDID-Sektion ab `0x07A`. Mein erster Analyse-Versuch ging davon aus, der klassische EDID-Header `00 FF FF FF FF FF FF 00` sei wegoptimiert und werde erst zur Laufzeit ergÀnzt. Das war falsch. Nach dem Mask-ROM-Dump und einem genaueren Blick steht der Header sauber im EEPROM. Solche Korrektur-Momente sind mir lieber als ein zu glattes Narrativ, also schreibe ich sie hier auch hin.
Die EDID selbst enthĂ€lt einen Monitor-Namen `MACROSILICON` (EDID-Descriptor mit Tag `0xFC`), als erstes Detailed-Timing 1280Ă720 bei 60 Hz mit 74,25 MHz Pixeltakt, ein zweites Timing 1280Ă768, dazu eine CTA-861-Extension mit nativem VIC=4 (720p60) plus VICs fĂŒr 1080p60, 1080i, 720p50, 480p und 576p. Es gibt sogar einen HDMI-VSDB-Block mit dem OUI `00:0C:03` von HDMI Licensing und einer Source Physical Address. Eine VGA-only-Platine, die HDMI-Strukturen in ihrer EDID trĂ€gt. Das ist schon der erste deutliche Fingerabdruck der gemeinsamen Codebasis.
### Der Mask-ROM verrÀt die Herkunft
Der eigentliche Programmcode des 8051 liegt in einem nicht beschreibbaren Mask-ROM. `dump-rom` lĂ€dt dafĂŒr eigenen 8051-Code in den USERRAM, der per `MOVC` den ROM ausliest und ĂŒber HID zurĂŒckschiebt:
msctl --raw-path /dev/hidraw8 --no-patch dump-rom dumps/maskrom-vga.bin
64 KiB komplette CODE-Memory, davon rund 36 KiB belegt im Bereich `0x0000` bis `0x8FFF` und weitere 12 KiB ab `0xC000`. Die Highlights:
* **0x7738** : eine zweite, im ROM fest verdrahtete Default-EDID, intakt mit Standard-Header, Hersteller-ID âHJWâ und Monitor-Name **âHDMI TO USBâ**. Das ist der Beweis: diese Firmware wurde ursprĂŒnglich fĂŒr den HDMI-Bruder geschrieben.
* **0x77A9** : der ASCII-String âHDMI TO USBâ noch einmal direkt.
* **0x7087** und **0x709B** : die USB-String-Descriptor-Fallbacks âUSB Videoâ und âUSB Digital Audioâ in UTF-16LE. Diese beiden werden uns gleich noch Ă€rgern.
* **0x0000** : der Reset-Vector `02 41 49`, also `LJMP 0x4149`.
* Ein `LCALL 0xCC10` bei ROM-Adresse `0x478F`: das ist der zentrale Einstieg vom Mask-ROM in den EEPROM-Patch-Code, der zur Laufzeit in den RAM kopiert wurde.
Der Bootloader kopiert dabei die EEPROM-Bytes ab Offset `0x30` in den USERRAM ab Adresse `0xCBD0`. Die Strings-Sektion `0x10` bis `0x2F` wird **explizit nicht** mitkopiert. Die Patch-Firmware liest die Strings stattdessen zur Laufzeit direkt per IÂČC aus dem EEPROM und baut daraus die USB-String-Descriptoren an festen RAM-Adressen zusammen. Diese Mapping-Tabelle ist der Kern, um den herum sich die ganze Bastelei dreht:
EEPROM| Code-RAM| Was
---|---|---
0x030| 0xCC00| Patch #1, kleine Hook-Routinen
0x07A| 0xCC4A| EDID-Header `00 FF FF FF FF FF FF 00`
0x080| 0xCC50| EDID-Body
0x0FA| 0xCCCA| CTA-861-Extension
0x17A| 0xCD4A| Patch #2, C51-Startup
0x180| 0xCD50| `MOV SP,#0x3B; LJMP 0xCD91`
0x1C1| 0xCD91| `main()` der Patch-Firmware
### Erkenntnis 1: Die EDID lĂŒgt der Quelle einen Monitor vor
Ăber die DDC-Leitungen am VGA-Stecker (Pins 12 und 15) prĂ€sentiert der Dongle dem Quell-PC eine EDID. Damit gibt sich das GerĂ€t als Monitor namens âMACROSILICONâ mit 720p60 als nativer Auflösung aus. Genau deshalb liefert ein Quell-PC, an dem gar kein echter Monitor hĂ€ngt, trotzdem ein sinnvolles Bild: er glaubt, ein 720p-Display gefunden zu haben. So weit, so clever.
### Erkenntnis 2: Das â1080pâ ist Marketing
Die UVC-Frame-Tabelle im Mask-ROM listet zwar brav 1920Ă1080 mit 30 fps als MJPEG. Die RealitĂ€t sieht anders aus. Mit `v4l2-ctl` lĂ€sst sich die Format-Liste auslesen:
$ v4l2-ctl -d /dev/video2 --list-formats-ext
[0]: 'MJPG' (Motion-JPEG, compressed)
Size: Discrete 1920x1080 30/25/20/10/5 fps
Size: Discrete 1280x720 60/50/30/20/10 fps
Size: Discrete 1024x768 60/50/30/20/10 fps
[1]: 'YUYV' (YUYV 4:2:2)
Size: Discrete 1920x1080 5 fps
Size: Discrete 640x480 30/20/10/5 fps
Unkomprimiertes YUYV bei 1080p ist auf magere 5 fps gedeckelt. Das native Detailed-Timing der EDID ist 720p60, das 1080p wird intern hochskaliert. Und USB 3.0 ist nirgends, der Chip kann nur High-Speed. Drei Behauptungen auf der Verpackung, drei mal geschummelt. Auf die 5-fps-Grenze komme ich am Ende noch genauer zurĂŒck, die hat einen sehr konkreten technischen Grund.
### Erkenntnis 3: Kein DOS, und das lÀsst sich nicht reparieren
Jetzt zum eigentlichen Frustpunkt, der Grund, warum mein DOS-Plan scheiterte. Die UVC-Frame-Tabelle enthĂ€lt **keine 70-Hz-Modi**. Ein DOS-BIOS gibt aber im Standard-VGA-Textmodus 720Ă400 bei 70 Hz aus. Das analoge Frontend, der MS9288A, könnte dieses Signal vermutlich locken, der Horizontaltakt von 31,469 kHz ist derselbe wie bei 640Ă480 bei 60 Hz. Aber die MS2109-Firmware bietet schlicht keinen passenden UVC-Frame-Mode an, an dem ein Aufnahmeprogramm andocken könnte.
Und das Bittere: **im EEPROM kann man das nicht reparieren**. Die Frame-Tabelle liegt im nicht-flashbaren Mask-ROM. Das EEPROM steuert nur EDID, Strings und ein paar Patch-Routinen, nicht die Liste der angebotenen Auflösungen. Wer mit so einem Dongle echte DOS-Signale aufnehmen will, kommt um eine vorgeschaltete Scaler-Box nicht herum. Mehr dazu am Ende.
### Was wir trotzdem geÀndert haben: die EDID
Wenn die Frame-Tabelle schon unantastbar ist, dann wenigstens die EDID anfassen. Ich habe das erste Detailed-Timing von 720p60 auf **1920Ă1080 bei 60 Hz** umgeschrieben (148,5 MHz Pixeltakt, das Standard-CEA-861-1080p60-Timing), die EDID-Checksumme neu berechnet und das EEPROM zurĂŒckgeflasht. Das neue DTD #1 sieht so aus:
02 3a 80 18 71 38 2d 40 58 2c 45 00 00 00 00 00 00 1e
Nach einem Replug liefert das GerĂ€t die modifizierte EDID. Zumindest dachte ich das. Ob sie auch wirklich bei einer Quelle ankommt, war eine ganz eigene Odyssee, dazu komme ich beim A/B-Test. Vorweggenommen: Die Mod tut technisch genau das, was sie soll, sie Ă€ndert nur am Ende nichts an dem, was aufgenommen wird. Eine reine âich sage der Quelle, ich kann 1080pâ-Kosmetik.
### Was NICHT geklappt hat: die Strings
Das ist der lehrreichste Teil des Projekts, gerade weil er bis heute offen ist. Ich wollte die USB-Function-Strings Ă€ndern, aus dem hĂ€sslichen âAFN_Cap videoâ sollte ein sauberes âVGA Capture HDâ werden. Das EEPROM-Schreiben verifiziert sauber per Readback-Hash. Die EDID-Mod aus demselben Reflash funktioniert. Aber die Strings fallen nach dem Replug auf die ROM-Defaults âUSB Videoâ und âUSB Digital Audioâ zurĂŒck. Irgendetwas in der Firmware sagt âneinâ.
Also empirisch rangegangen, drei Single-Byte-Tests in der Strings-Region `0x10` bis `0x2F`: einmal ein ASCII-Zeichen geĂ€ndert, einmal ein `FF`-Padding-Byte, einmal das LĂ€ngen-Byte. Jeder einzelne dieser Eingriffe löst den Fallback aus. Egal welches Byte, egal welcher Inhalt. Das ist eine klare Indikation fĂŒr ein **Content-Gate ĂŒber die gesamte 32-Byte-Region** , nicht fĂŒr eine simple LĂ€ngen- oder InhaltsprĂŒfung an einer Stelle.
Ein Gegencheck zur eigenen Analyse hat ein paar Punkte geschÀrft. Die Bytes `0x02` und `0x03` (`03 8E`) sind verifiziert die **Payload-LÀnge** und keine Checksumme: 910 Bytes ab `0x30` reichen bis `0x3BD`, exakt bis vor den End-Marker. Der Verdacht: ein lokales Validierungs-Gate auf den 32-Byte-Strings-Slots, wahrscheinlich ein Hash oder ein Exact-Content-Compare in einem ROM-Helper, nicht im Patch-Code selbst. Ein Quervergleich mit dem usbkvm-Projekt zeigt dasselbe Header-Muster bei verwandter Hardware.
Der spannendste Nebenbefund kam aus einem XDATA-Boot-Trace bei `0xC630` bis `0xC67F`: die âAFN_Capâ-Strings landen **gar nicht dauerhaft im RAM**. Was dort steht, ist die Fallback-Variante. Die echten Strings werden erst zur Laufzeit beim USB-`GetDescriptor` aus dem EEPROM gebaut, und genau in diesem Moment greift offenbar das Gate. Wer das knacken will, mĂŒsste den USB-Control-Transfer mit `usbmon` und Wireshark wĂ€hrend der Enumeration mitschneiden, die ROM-Helper bei `0x6345` und Nachbarn disassemblieren, oder mit `mshack` einen Bypass-Patch auf den Fallback-Branch setzen. Der schnellste Weg wĂ€re allerdings, ein vom offiziellen MacroSilicon-Windows-Tool editiertes EEPROM byteweise gegen mein eigenes zu diffen. Dieses Tool schreibt vermutlich versteckte Metadaten mit, die das öffentliche Reverse-Engineering noch nicht dokumentiert hat. Das ist mein heiĂester Kandidat fĂŒrs Strings-Mysterium, aber bisher unbewiesen.
### Der A/B-Test, oder: die Suche nach einer ehrlichen VGA-Quelle
Ich wollte zwei Dinge empirisch klĂ€ren. Erstens: Kommt die modifizierte 1080p-EDID ĂŒberhaupt bei der Quelle an? Zweitens: Löst das Ding echtes 1080p auf oder ist das hochskalierter Matsch? Beides braucht eine VGA-Quelle, die ihre DDC-Leitung auch wirklich ausliest. Das war schwerer zu finden als gedacht.
**Erster Anlauf, ein Notebook mit âVGA-Outâ.** Plot-Twist: der VGA-Anschluss lief ĂŒber einen aktiven DisplayPort-auf-VGA-Adapter und tauchte als `DP-4` auf. Der Adapter liefert ein eigenes synthetisches EDID (âNVDâ, âLCD_VGAâ, 1280Ă1024). Das ist nicht das EDID aus dem Dongle. Der EDID-Pfad vom Dongle bis zur GPU ist also unterbrochen. Erste Lehre: aktive DP-auf-VGA-Adapter verhalten sich wie eine eigene EDID-Quelle und maskieren alles dahinter.
**Zweiter Anlauf, ein ThinkPad L560 mit echter VGA-Buchse hinten.** Wieder gescheitert, und zwar aus einem prinzipiellen Grund. Ab Haswell und Skylake hat Intel den analogen RAMDAC komplett aus der GPU geworfen. Die physische VGA-Buchse hÀngt an einem Onboard-DP-auf-VGA-Bridge-Chip. Der Kernel verrÀt es selbst:
$ xrandr --verbose | grep -i subconnector
subconnector: VGA
$ cat /sys/class/drm/card1-DP-2/edid | wc -c
0
Null Byte EDID. Die Bridge reicht das DDC vom Dongle nicht durch, der Connector bietet nur die VESA-Default-Modi an. Exakt dasselbe Problem wie beim ersten Notebook, nur diesmal onboard statt als Dongle. Auf beiden getesteten Bridge-Pfaden kam die EDID des Capture-Sticks nicht zur Quelle durch. Als Trend lĂ€sst sich sagen: neuere Intel-Notebooks haben den analogen RAMDAC verloren (der fiel etwa um Haswell und Broadwell, also rund 2013 bis 2015) und fĂŒhren âVGAâ ĂŒber DP-Bridges, die DDC abschneiden. Das als âkein Notebook taugt jeâ zu verkaufen wĂ€re ĂŒbertrieben, es ist ein Trend, kein Beweis.
Ein netter Nebenbefund vom L560, den ich erst fĂŒr einen kaputten Aufbau hielt: nach jedem Auflösungswechsel liefert der Dongle erstmal 1 bis 6 Sekunden ein komplett schwarzes Bild, bis die MS9288A-PLL wieder eingerastet ist. Ich hatte reihenweise schwarze Frames gegrabbt und schon den Analogpfad fĂŒr tot erklĂ€rt. In Wirklichkeit hatte ich nur immer ins Re-Lock-Fenster reingeschossen. Mit 4 bis 6 Sekunden Settle-Zeit kommt das Bild stabil. Passt zur dokumentierten Sync-TrĂ€gheit des Chips.
### Der A/B-Test selbst
Trotz blockiertem DDC habe ich den A/B durchgezogen, einfach um es schwarz auf weiĂ zu haben. Als Quelle ein 1920Ă1080-Testbild mit vier Quadranten aus 1-Pixel-Gittern: Schachbrett, vertikale Linien, horizontale Linien, Diagonale. Dazu grĂŒne Eck-Marker, um sicher zu sein, dass der ganze Frame ankommt.
Das Quell-Testbild: vier Quadranten mit 1px-Schachbrett, Vertikal-, Horizontal- und Diagonalgittern, dazu Eck-Marker.
Erst der Befund, der mich am meisten interessiert hat: 1px-Vertikallinien und Schachbrett kollabieren zu flachem Grau, das horizontale Feindetail ist weg. 1px-Horizontallinien und Diagonale zeigen schwache Resttextur. Die vertikale Auflösung kommt also weitgehend durch (jede Scanline ist eine eigene analoge Zeile), die horizontale ist deutlich begrenzt. Wichtiges Ehrlichkeits-Caveat: das ist die **komplette** Analogkette, also Bridge-DAC im L560, Kabel und MS9288A-ADC zusammen. Mit diesem Aufbau lÀsst sich nicht sauber trennen, wieviel davon der Dongle ist.
Dann der eigentliche EEPROM-A/B. EEPROM gegen das Original-Backup getauscht, Readback-Hash jedes Mal verifiziert. Etwas, das ich erst lernen musste: nach dem Flashen muss der Dongle einmal **physisch ab- und wieder angesteckt** werden. Ein reiner USB-Bus-Reset reicht nicht, der 8051 lÀuft einfach weiter und liest das neue EEPROM gar nicht ein. Software-seitig ging das nicht (kein schaltbarer Port), also von Hand. Die Zahlen, ImageMagick MAE auf einer Skala von 0 bis 1:
Vergleich| MAE| pro 255
---|---|---
Rauschen mod3 (zwei Aufnahmen, gleiches EEPROM)| 0,0041| 1,05
Rauschen Original| 0,0043| 1,10
**mod3 gegen Original**| 0,0071| 1,82
Der Cross-Wert liegt nur minimal ĂŒber dem Rauschpegel. Das maximal verstĂ€rkte Differenzbild zeigt keine strukturierte Ănderung, nur MJPEG-Blockrauschen in den hochfrequenten Quadranten. Die kleine Differenz ist Re-Lock- und AGC-Varianz zwischen den Sessions, nicht das EDID.
Maximal verstÀrkte Differenz: mod3-EDID gegen Original-EDID. Nur Blockrauschen, keine Struktur. Die EDID-Mod Àndert am Bild nichts.
**Fazit des A/B** : Die EDID-Mod von 720p auf 1080p verÀndert das aufgenommene Bild exakt null. Aus erstem Prinzip war das klar, die EDID ist das, was das GerÀt der Quelle anbietet, sie steuert nicht den Aufnahmepfad. Aber jetzt steht es empirisch da.
### Endlich eine echte Analog-Quelle, und zwei dicke Befunde
Dritter Anlauf, diesmal ein Desktop mit einer **NVIDIA GeForce GT 630** (Kepler). Kepler hat noch einen echten analogen RAMDAC, ĂŒber einen passiven DVI-I-auf-VGA-Adapter kommt echtes analoges VGA raus. Endlich die Hardware, die den Notebooks fehlte.
**Befund 1: Die EDID-Mod ist sogar grundsĂ€tzlich fĂŒr die Katz.** Der NVIDIA-Treiber cached die analoge EDID hartnĂ€ckig (analoges VGA hat kein Hotplug), also einmal lightdm neugestartet fĂŒr einen frischen Read. Das Ergebnis im Xorg-Log:
(--) NVIDIA(GPU-0): CRT-0: connected
(WW) NVIDIA(0): CRT-0 does not have an EDID
Der Dongle liefert auf seinem VGA-Eingang **gar keine DDC und keine EDID**. Sauber belegt: derselbe Adapter hat vorher die EDID eines echten Monitors gelesen (ein Fujitsu P24-9, mit 1920Ă1080 und physischen MaĂen), der Adapter reicht DDC also durch. Es ist der Dongle, der nichts treibt. Das kippt eine Annahme aus meinen eigenen Notizen, wo stand, das Patch-Modul beantworte âwahrscheinlichâ DDC-Reads. Dieses âwahrscheinlichâ war nie gemessen.
Ehrlich bei der Konfidenz bleiben: hoch dafĂŒr, dass in diesem GT-630-Test keine lesbare EDID vom Dongle kam. Nur mittel fĂŒr das universelle âkeine Quelle sieht die EDID jeâ. Restzweifel, die ich noch nicht ausgerĂ€umt habe: NVIDIA-Eigenheiten bei analogem DDC, ob die Dongle-DDC die 5 Volt auf VGA-Pin 9 braucht, oder ob der DDC-Responder erst nach Sync-Lock aufwacht. Ein Pin-9-Check plus Logic-Analyzer auf den Pins 12 und 15 (mit dem Fujitsu als Positiv-Kontrolle) wĂŒrde es hart machen. Arbeitshypothese: auf dem getesteten echten Analogpfad prĂ€sentierte der Dongle keine lesbare EDID, vermutlich weil der VGA-DDC-Pfad in der geteilten HDMI/VGA-Codebasis schlicht nicht verdrahtet ist. HDMI hat HPD und DDC, VGA hier offenbar nicht.
**Befund 2: Das â1080pâ ist vertikal echt, horizontal Fake.** Mit echtem RAMDAC konnte ich endlich den Dongle-Anteil am Blur isolieren (eigene xorg.conf mit `UseEDID false` und forciertem 1080p-Modeline, NVIDIA lehnt xrandr-Modelines ab). Testbild: reine 1px-Schwarz-WeiĂ-Gitter per `xsetroot`. Das Resultat, gemessen als Standardabweichung der Luma (ein ideales Gitter liegt bei rund 128, flaches Grau bei 0):
1px-Gitter bei echtem Analog-1080p| Std-Abw.| Bedeutung
---|---|---
**horizontale** Linien| 119| vertikal sauber aufgelöst
**vertikale** Linien| 0,6| horizontal komplett verschmiert
Schachbrett| 0,55| weg
Echte Analog-Quelle (GT 630): links das vertikale 1px-Gitter zu Grau verschmiert, mittig horizontale Linien gestochen scharf, rechts das Schachbrett weg.
Der Dongle hat also echte 1080 Zeilen vertikal, aber horizontal kommt weit weniger als 1920 Pixel an. Und weil hier kein Bridge mehr dazwischen sitzt: der Blur ist der Dongle selbst, nicht das billige Notebook. Das ist die belastbare Aussage.
Den Mechanismus habe ich auf einen Vorschlag aus dem Gegencheck hin gleich nachgemessen, ein Phasen- und Balkenbreiten-Test. Das 1px-Gitter ist bei Phase 0 und Phase 1 gleich grau (Std-Abw. 0,18 gegen 0,19), ein PLL- oder Phasen-Mislock ist damit **ausgeschlossen** , sonst wĂŒrde der 1px-Versatz den Kontrast kippen. Und der Kontrast steigt sauber mit der Balkenbreite: 1px liegt bei rund 0, 2px bei 35, 3px bei 61, 4px bei 79 (Ideal rund 128). Das ist die klassische Tiefpass-Signatur, also ein echtes Horizontal-Auflösungs-Limit und kein Lock-Artefakt. Ob das an der ADC-Abtastrate oder an einem internen Rescale liegt, kann ich noch nicht trennen, aber beides heiĂt: der Dongle begrenzt die Horizontalauflösung.
Balkenbreiten-Rampe: 1px bleibt grau, ab 2px wird Kontrast sichtbar. Klassische Tiefpass-Signatur, ein echtes Horizontal-Limit.
### Warum YUYV bei 1080p nur 5 fps macht
Zum Schluss noch die berĂŒchtigte 5-fps-Grenze, diesmal gemessen statt aus der Tabelle abgeschrieben (Quelle GT 630 bei 1080p60, `v4l2-ctl --stream-mmap`):
Format bei 1920Ă1080| gemessen
---|---
MJPEG| **29 fps** (Tabelle: 30)
YUYV (unkomprimiert)| **exakt 5,0 fps**
Meine erste ErklĂ€rung mit âungefĂ€hr 40 MB/s USB-2.0-Bandbreiteâ war zu schludrig. Der genaue Grund ist das **Payload-Limit des isochronen UVC-Endpoints**. Das gröĂte Altsetting des Video-Endpoints ist 3 mal 1024 Bytes pro Microframe, also 24,576 MB/s (steht so im `lsusb -v`). Unkomprimiertes YUYV bei 1080p sind 1920 mal 1080 mal 2 Bytes, also 4,15 MB pro Frame. Die Firmware-Frametabelle ist genau so gewĂ€hlt, dass die YUYV-Raten knapp darunter passen:
* 1080p mal 5 fps = 20,7 MB/s
* 720p mal 10 fps = 18,4 MB/s
* 480p mal 30 fps = 20,7 MB/s
Also keine generische âUSB-2.0-Bandbreiteâ, sondern der High-Speed-Isoch-Endpoint plus die fest verdrahteten Frametabellen. MJPEG komprimiert vorher, deshalb bleiben dort 30 fps bei 1080p und bis zu 60 bei 720p und darunter. Klare Ansage: am MS2109 ist MJPEG bei hoher Auflösung Pflicht. Und âUSB 3.0âł auf der Verpackung ist und bleibt gelogen, das Ding enumeriert als USB-2.0-High-Speed, ohne SuperSpeed.
### Stabiles Device-Naming per udev
Damit das GerÀt im Alltag immer unter demselben Pfad auftaucht, eine udev-Regel. Die Regeln stehen bewusst jeweils auf einer Zeile, weil mehrzeilige Fortsetzungen mit Backslash schnell zur Fehlerquelle werden:
# /etc/udev/rules.d/70-vga-capture-ms2109.rules
SUBSYSTEM=="video4linux", ENV{ID_VENDOR_ID}=="534d", ENV{ID_MODEL_ID}=="2109", ENV{ID_V4L_PRODUCT}=="*AFN_Cap*", ATTR{index}=="0", SYMLINK+="video-vga"
SUBSYSTEM=="hidraw", ATTRS{idVendor}=="534d", ATTRS{idProduct}=="2109", ATTRS{product}=="USB3.0 Capture", GOTO="ms2109_vga_end"
SUBSYSTEM=="hidraw", ATTRS{idVendor}=="534d", ATTRS{idProduct}=="2109", SYMLINK+="hidraw-vga", MODE="0660", GROUP="plugdev"
LABEL="ms2109_vga_end"
Die GOTO-Konstruktion ist nötig, weil `ATTRS{product}!="..."` nicht so funktioniert, wie man denkt. udev sperrt die Attribut-Suche auf einen Parent-Device-Walk, und âFehlen eines Attributsâ verhĂ€lt sich anders als ein echtes Ungleich. Deshalb der Umweg ĂŒber ein positives Match plus Sprungmarke.
### Fazit, und der Workaround der wirklich hilft
Was bleibt? Der Dongle ist ein nettes Studienobjekt, aber fĂŒr mein ursprĂŒngliches Ziel, alte DOS-Signale aufnehmen, ist er unbrauchbar. Es gibt keine 70-Hz-Modi, und reparieren lĂ€sst sich das nicht, weil die Frame-Tabelle im Mask-ROM festgebrannt ist. Das â1080pâ ist horizontal Marketing, âUSB 3.0âł eine glatte LĂŒge, und die EDID-Mod ist auf dem getesteten Analogpfad wirkungslos, weil der Dongle gar keine EDID treibt. Drei Korrektur-Momente gegenĂŒber meinen ersten Annahmen, alle drei lehrreicher als wenn alles gleich funktioniert hĂ€tte.
Wer wirklich exotische VGA-Signale wie DOS-Textmodi sauber aufnehmen will, schaltet eine externe Scaler-Box vor. Mein Tipp ist GBS-Control, eine offene Firmware fĂŒr die rund 20 Euro teuren GBS-8200-Boards. Sie nimmt das krumme Quellsignal, lockt sauber und gibt ein normgerechtes Bild aus, das jeder Capture-Stick frisst. Die andere Liga ist der Open Source Scan Converter, dessen Firmware-Update ich hier schon beschrieben habe. Wer es noch gĂŒnstiger mag, fĂ€ngt einen gebrauchten Extron-Scaler aus einer Konferenzraum-Ausmusterung.
Offen bleibt das Strings-Mysterium (ohne das Vendor-Tool komme ich an den Gate-Algorithmus nicht ran), die Disassembly des zweiten Patch-Blocks in Ghidra, ein Latenz-Benchmark fĂŒr den Einsatz als KVM-Console-Viewer, und der finale DOS-Test mit GBS-Control davor. Material fĂŒr einen zweiten Teil ist also reichlich da.
**Siehe auch:**
* Open Source Scan Converter: Firmware-Update von 1.08a auf 1.21 nachgeholt
* LCR-T4-Plus v2: m-firmware flashen, Display-Tuning und die 8-MHz-Quartz-Falle
* TC1 Multifunction Tester: Open-Source Firmware flashen, kalibrieren und die Stolperfallen dabei
Habt ihr selbst schon so einen MS2109-Stick auseinandergenommen oder das Strings-Gate geknackt? Dann lasst es mich gerne wissen, ihr dĂŒrft mich jederzeit fragen. https://www.kernel-error.de/2026/05/29/ms2109-vga-usb-capture-reverse-engineering-edid-1080p/