A from-scratch Rust reimplementation of DisplayLink's
evdi — both the kernel module and the
userspace library — targeting DisplayLink DL3 docks (e.g. the Dell D6000). It is
a drop-in replacement for the stock C evdi + libevdi: the closed-source
DisplayLinkManager (DLM) loads it unchanged.
The module is written against the in-progress
Rust DRM/KMS bindings (Lyude Paul's safe
mode-object layer) and drives a virtual DRM display that DLM pulls pixels from,
exactly like the C evdi does through its own private ioctl ABI.
Replacing libevdi and evdi.ko leaves one closed component in the stack: the
DisplayLinkManager binary itself, which does the dock's HDCP/control-plane
handshake and encodes the video. chimera/ is the beginning of a replacement for
that — a userspace rig that already cold-starts a real dock over libusb using
the vino driver's control-plane code. Between the three, the whole DisplayLink
stack becomes open.
Naming. The kernel module identifies itself to userspace as
evdi(DRM driver name,/dev/dri/cardN, the/sys/devices/evdicontrol node) because DLM andlibevdihard-code that name. Only the project is called revdi.
| Path | What it is | License |
|---|---|---|
module/ |
The Rust EVDI kernel module (evdi.ko). Virtual DRM/KMS display, EVDI private ioctls, USB-dock pairing, DDC/CI bridge, damage-tracked GRABPIX. |
GPL-2.0 |
library/ |
librevdi: a Rust cdylib exposing the exact evdi_lib.h C ABI, installed as libevdi.so.1. |
LGPL-2.1-or-later |
chimera/ |
The DLM-replacement rig: compiles the vino driver's kernel control-plane sources verbatim in userspace and drives a dock over libusb. See chimera/README.md. |
GPL-2.0-or-later |
vino-driver/ |
libusb transport for the dock (the Dock type chimera drives). |
GPL-2.0-or-later |
vino-hdcp/ |
HDCP 2.2 helpers (certificate parsing, KDF) used by the bring-up tooling. | GPL-2.0-or-later |
kernel-shim/ |
A userspace stand-in for the kernel prelude, so the vendored kernel sources compile unmodified. | GPL-2.0-or-later |
LICENSES/ |
Full license texts. | — |
The module/library split mirrors upstream evdi: the module is GPL-2.0
(MODULE_LICENSE("GPL")), the library is LGPL-2.1-or-later so a proprietary
client may link it.
This project is standalone: it builds and its tests pass with no kernel tree checked out anywhere. It manages that by keeping its own copies of two sets of files that are edited in the kernel tree:
| Vendored copy | Upstream source |
|---|---|
module/*.rs |
drivers/gpu/drm/evdi/*.rs |
chimera/vino/*.rs |
drivers/gpu/drm/vino/*.rs |
The kernel tree is authoritative. Refresh the copies with:
make sync KSRC=/path/to/drm-next # defaults to ../drm
make check-sync # report drift, change nothing, exit 1 if anyDo not hand-edit a vendored file. chimera's proofs are only worth anything
because it compiles the literal driver sources — a local edit here would make
them silently stop tracking the real driver, which is exactly the drift the rig
exists to rule out. Edit the kernel tree, then re-run make sync.
The module consumes Rust DRM/KMS bindings that are not yet in a released kernel,
so it must be built against a kernel tree that has them (this project is
developed against drm-next + the vino bindings series):
export PATH=/usr/lib/llvm/22/bin:$PATH # kernel Rust toolchain (clang/rustc)
make -C module KDIR=/path/to/drm-next
sudo make -C module modules_install KDIR=/path/to/drm-nextmodules_install runs depmod for the target kernel (KDIR's release) itself,
so a separate depmod -a — which would target the running kernel, not the
one you installed into — is neither needed nor correct.
LLVM=1 is passed automatically; a stock distro kernel without the bindings
will not build it.
Builds with the system Rust toolchain (1.77+), no kernel tree required:
make -C library
sudo make -C library install # installs libevdi.so.{1.15.0,1} + libevdi.soBuilds with the system Rust toolchain, no kernel tree required (it uses the
vendored sources above). Needs libusb development headers for the live feature:
make chimera # release build of chimera-coldstart (--features live)
make test # the offline byte-exact proof vs captured DLM sessionsmake KDIR=/path/to/drm-next # module + library
sudo make install KDIR=/path/to/drm-next- Install the module and library as above.
- Make sure the stock C
libevdi.so.1is not shadowing ours (this replaces it at the same path/SONAME). modprobe evdi, then start the DisplayLinkManager service. Plug in the dock; DLM opens/dev/dri/cardN, connects with the monitor's EDID, and drives the virtual display — revdi tracks damage and hands back only the changed rectangles per frame.
If something goes wrong (a wedged client, a card that will not tear down on unplug, a suspected driver bug), the safe order is:
sudo systemctl stop displaylink-driver # or otherwise stop DLM cleanly
echo 1 | sudo tee /sys/devices/evdi/remove_all
sudo rmmod evdiremove_all unplugs every card in one shot without holding the registry lock
across the (sleeping) DRM/I2C teardown, and it is safe even while clients still
hold the DRM nodes: the cards are unplugged, not freed under them, so every
subsequent ioctl returns ENODEV and any in-kernel waiter (e.g. a pending
DDC/CI transfer) is woken and bails out instead of stalling the teardown. Once
the last client closes its file descriptors the module refcount drops to zero
and rmmod evdi succeeds. (rmmod while a client still has the node open is
refused with EBUSY by design — that is the kernel protecting you from a
use-after-free, not a hang.)
The same drain-then-drop path runs automatically when a dock is unplugged
(USB_DEVICE_REMOVE notifier) and when a single platform device unbinds.
Module + library: working end-to-end on a Dell D6000 under KWin/Wayland:
multi-head output, live frame updates with delta damage, hardware cursor, DDC/CI,
and clean teardown on dock unplug. See docs/ for the design notes and the
kernel-tree patch set.
Chimera: not a DLM replacement yet. The control-plane half is real — it
cold-starts a dock over libusb and the dock engages — but nothing here paints a
desktop unattended. See chimera/README.md for exactly what is and is not proven.
Dual-licensed by component, matching upstream evdi: the kernel module under
GPL-2.0, the library under LGPL-2.1-or-later. Each file carries an
SPDX-License-Identifier. Full texts are in LICENSES/.