This is bambinounos/ms91xx-linux-drm plus six fixes that make a USB→VGA dongle built around an MS912C work at all, including as a machine's only physical text console (fbcon on
/dev/fb0). Upstream targets the MS9132/9133 portable monitor devices; on an MS912C VGA adapter every one of the problems below is silent — the driver reports success at every layer and the monitor stays black.Sent upstream as PR #2. If it lands, use upstream instead — this fork exists so the work is findable in the meantime.
Is this you?
lsusbshows534d:6021(possibly only after it mode-switches away from345f:9132on its own), anddmesg | grep 'chip id'showschip id:0x3—CHIP_ID_912C, not the0x0this driver was written for. Full setup and debugging notes: docs/MS912C-VGA.md.
Won't build on Debian 6.12 6.12.101+deb13backports the 6.13 EDID API while still reportingLINUX_VERSION_CODEas 6.12, so the>= 6.13guard misses it:implicit declaration of function 'drm_do_get_edid'. Upstreammasterdoes not compile on this kernel at all.Nothing binds the device 534d:6021— the identity these dongles mode-switch to on their own — was missing from all three independent ID lookup tables.No /dev/fb0, no consoleNo fbdev client was ever registered. Adding the standard drm_client_setup()call alone oopses (NULL pointer dereferenceindrm_fb_helper_single_fb_probe(), from an uninitializedret), because the driver never implemented.fbdev_probe. This fork implements one, plus the GEM.vmap/.vunmapit needs.Modes ignored / bogus EDID The custom_mode=module parameter was parsed and then never used. Meanwhile a DDC-less VGA monitor doesn't fail EDID cleanly — the read intermittently succeeds with a chip-internal canned EDID whose timings the chip then maps to an unrelated internal VIC, producing an invalid signal.The VGA DAC is never powered on The chip misreports its own port as S-Video, ms9132_set_screen_enable()has no case for that value, and it falls through to the CVBS output enable instead of the VGA DAC enable. Newport_type=override fixes it — and also writes the corrected value into the chip, because the firmware reads that same register when programming its timing generator.Everything is guarded so existing MS9132/9133/9135 users are unaffected (
port_typedefaults to-1, i.e. autodetection unchanged). Tested on Debian 13 /6.12.101+deb13-amd64with a DDC-less VGA monitor at 640×480@60, working from a cold boot with no manual steps. Not tested under a desktop compositor.Install exactly as described below, then add
/etc/modprobe.d/usbdisp.conf:options usbdisp_usb port_type=2 custom_mode=1_640x480@60,4_1280x720@60Both options are required on this hardware, for unrelated reasons — docs/MS912C-VGA.md explains each.
Linux DRM driver for MacroSilicon MS9132 / MS9133 / MS9135 USB display chips
(lsusb: 345f:9132 / 345f:9133 "MS USB Video"), based on MacroSilicon's
official GPL-2.0 source code, fixed to build and run on modern kernels
(6.8 → 7.0+) and packaged for DKMS.
These chips power countless brandless "lightweight" portable USB monitors and Chinese dual-screen / tri-screen laptop extenders sold on AliExpress, Temu, Amazon, etc., as well as generic USB 3.0 → HDMI/VGA adapters.
✅ Tested working on Ubuntu 24.04 (Noble), kernel 6.17.0-35-generic, GNOME 46 Wayland with a brandless dual-screen laptop monitor (MS9132 in single mode, 1920×1080@60, USB 3 SuperSpeed) — both mirror and extend modes.
$ lsusb | grep 345f
Bus 004 Device 003: ID 345f:9132 MS USB Video
If you see 345f:9132, 345f:9133 or 345f:9135, yes.
If you see 534d:6021 ("MacroSilicon USB Video" / "VGA Display Adapter"),
also yes — that is the functional identity these dongles mode-switch to on their
own after enumerating as 345f:9132. USB→VGA adapters in that family are
usually MS912C chips (dmesg reports chip id:0x3) and need two extra
module options to produce any picture at all; see
docs/MS912C-VGA.md.
Typical symptoms before installing this driver:
- The monitor only shows a red/standby LED on Linux (works fine on Windows).
- The device re-enumerates every ~10 seconds (
dmesgshows connect/disconnect loops) because no driver claims its video interface. - With the reverse-engineered
ms912xdriver, the panel flickers and then shows "No Signal" (see rhgndf/ms912x#42), or shows corrupted/magenta images. This driver fixes that: the official enable sequence keeps the video output muted until the first frame has been transferred, which the dual-screen (MS9133-family) firmware requires.
git clone https://github.com/bambinounos/ms91xx-linux-drm.git
cd ms91xx-linux-drm
sudo rsync -a --exclude .git ./ /usr/src/msdisp-3.0.3.13/
sudo dkms add msdisp/3.0.3.13
sudo dkms install msdisp/3.0.3.13Plug the screen in (or unplug/replug it). The usbdisp_usb module auto-loads via
the USB modalias, a new DRM card appears, and your desktop (tested on GNOME
Wayland/Mutter) lights the panel up like any other monitor. DKMS rebuilds the
modules automatically on every kernel update.
make # builds against the running kernel
sudo insmod drm/usbdisp_drm.ko
sudo insmod drm/usbdisp_usb.koMacroSilicon's last public release targets kernels up to ~6.6. On newer kernels it
does not compile — and even when it compiles, on 6.12+ the DRM node cannot be
opened at all (every open() of /dev/dri/cardN fails with EINVAL), so
compositors silently ignore the device. All fixes are guarded with
LINUX_VERSION_CODE, preserving compatibility with old kernels:
| Fix | Affected kernels |
|---|---|
.fop_flags = FOP_UNSIGNED_OFFSET in fops — without this, drm_open_helper() rejects every open and the GPU is unusable |
≥ 6.12 |
platform_driver.remove returns void |
≥ 6.11 |
drm_helper_mode_fill_fb_struct() / fb_create take const struct drm_format_info * |
≥ 6.15 |
drm_do_get_edid() removed → ported to drm_edid_read_custom() (raw EDID copy kept, rest of the flow unchanged) |
≥ 6.13 |
connector->mode_valid() takes const struct drm_display_mode * |
≥ 6.15 |
MODULE_IMPORT_NS("...") requires a string literal |
≥ 6.13 |
from_timer() → timer_container_of(), del_timer() → timer_delete() |
≥ 6.16 / 6.2 |
.date removed from struct drm_driver; PRIME fd/handle hooks now core defaults |
≥ 6.14 / 6.6 |
drm_legacy.h deleted; missing vmalloc.h / scatterlist.h includes |
≥ 6.8 |
struct_mutex removed from drm_device (GEM locking is internal); explicit drm_print.h includes; DRM_DEBUG_PRIME → drm_dbg_prime() |
≥ 7.0 |
Makefiles: removed vestigial KERNELRELEASE/include Kbuild branch that broke DKMS builds; $(PWD) → $(CURDIR); added dkms.conf |
all |
drm_do_get_edid() guard lowered to ≥ 6.12 — Debian's 6.12.101+deb13 backports the 6.13 EDID API while still reporting 6.12, so the build failed |
≥ 6.12 (Debian) |
.fbdev_probe implemented + GEM .vmap/.vunmap + drm_client_setup() — no fbdev client was ever registered, so /dev/fb0 and the text console never existed |
≥ 6.10 |
534d:6021 added to all three ID lookup tables; port_type= override; custom_mode= modes actually honoured; EDID no longer required for a DDC-less display — see docs/MS912C-VGA.md |
all |
The protocol/init logic is untouched — it is exactly the manufacturer's code.
- Do not
rmmod usbdisp_drm. The vendor teardown path has a use-after-free that oopses the kernel and leaves the module stuck (refcount -1). To reload the driver, reboot. In normal use the modules simply stay loaded. - If the panel shows only the red LED and never enumerates (no
dmesgevents at all when plugging), the chip's firmware is latched: disconnect the USB cable and any other power source for ~2 minutes, then reconnect. - A ~10 s connect/disconnect loop in
dmesgis normal only while no driver is bound; it stops as soon asusbdisp_usbclaims the device.
- MacroSilicon Technology Co., Ltd. — original driver, licensed GPL-2.0.
Source obtained from their public download server:
http://www.macrosilicon.com:9080/download/USBDisplay/Linux/SourceCode/(MS91xx_Linux_Drm_SourceCode_V3.0.3.13.zip, 2025-07-10 — the pristine zip is kept in this repo for provenance). - rhgndf/ms912x and contributors — the reverse-engineering work that kept these devices alive on Linux for years and whose issue tracker pointed the way here.
- Modern-kernel fixes and DKMS packaging: this fork (debugged live against a real dual-screen MS9132/MS9133 device, including USB protocol captures of the Windows driver).
GPL-2.0 (same as the original MacroSilicon code). See LICENSE.
Driver Linux para los chips MacroSilicon MS9132/MS9133 (lsusb: 345f:9132)
que usan las pantallas portátiles chinas sin marca y los monitores duales
para laptop ("dual screen", "lightweight monitor"). Es el código oficial GPL
del fabricante, corregido para kernels modernos (probado en Ubuntu 24.04 con
kernel 6.17, GNOME Wayland, modos espejo y extendido).
git clone https://github.com/bambinounos/ms91xx-linux-drm.git
cd ms91xx-linux-drm
sudo rsync -a --exclude .git ./ /usr/src/msdisp-3.0.3.13/
sudo dkms add msdisp/3.0.3.13
sudo dkms install msdisp/3.0.3.13Conecta la pantalla y listo: aparece como un monitor más. Consejos: nunca hagas
rmmod usbdisp_drm (bug del fabricante: para recargar, reinicia); si la pantalla
queda solo con el LED rojo y no aparece en lsusb, desconéctala de todo ~2
minutos y vuelve a conectarla.