evdi: a Linux kernel module that puts a virtual display under user space control
Extensible Virtual Display Interface
At a glance
- What is it?
- EVDI is a Linux kernel module plus a libevdi wrapper that adds virtual displays to the DRM subsystem, letting an application create a screen, push pixels to it and receive updates. It is the plumbing under DisplayLink's user mode driver, and by itself it is not a driver for any hardware.
- Who is it for?
- evdi suits a developer who needs a display that user space owns, whether that is a remote session, a capture pipeline or a scripted GUI test, and it is the wrong choice if you expected a driver for DisplayLink hardware, since the readme states plainly that EVDI is not a complete driver for DisplayLink devices.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 18 days ago.
- What is it written in?
- Mainly C, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.
Editorial analysis
A display the application owns rather than a screen the kernel found
The Extensible Virtual Display Interface is a Linux kernel module that enables management of multiple screens, allowing user space programs to take control over what happens with the image. In the readme's phrasing, it is a virtual display you can add, remove and receive screen updates for, in an application that uses the `libevdi` library.
That is the core distinction from a physical monitor. A physical display is enumerated by the kernel and driven by a mode setting driver. An EVDI display is created by user space, at runtime, with a size and a set of connectors that the application chooses, and the application is the one that decides what the screen shows. Nothing is enumerated at the hardware level, which is why the module is a platform_driver rather than a device tied to a bus.
The project ships three pieces. The `evdi` kernel module, the `libevdi` wrapper library that applications use to send and receive information to and from the module, and `pyevdi`, a Python wrapper for `libevdi`. The readme names DisplayLink's user mode driver as the kind of application that consumes this, but the API is documented separately at displaylink.github.io/evdi.
The repository layout mirrors that split, with `module/`, `library/`, `pyevdi/` and `docs/` directories at the top level, plus a `ci/` directory, a `Dockerfile`, a `Makefile`, a `Jenkinsfile` and a `mkdocs.yml` for the documentation site.
The releases move steadily. Version 1.15.1 was published on 2026-09-15, 1.15.0 on 2026-07-01 and 1.14.16 on 2026-05-05, and the last push to the default branch was on 2026-10-05.
Because it speaks DRM, xrandr can drive the display
EVDI is described as a driver compatible with the standard Linux DRM subsystem. That compatibility is what makes the module usable without special tooling: displays can be controlled by standard tools, the readme gives `xrandr` as the example, or by the display settings applets in graphical environments such as Unity, GNOME or KDE.
So the model is not that EVDI replaces the display stack. It registers virtual displays as DRM devices, and everything that already speaks DRM, including the compositor's display settings and the X server's RandR extension, sees them. An application that creates a display through `libevdi` gets a device that the rest of the system can inspect, mirror, rotate or arrange as it would any other output.
The same is true of the Python side. The readme notes that virtual displays can also be created with the help of `pyevdi`, which means a test harness or a rendering pipeline can create and destroy a display from Python without writing C.
The practical consequence is that EVDI sits below the display server and above the hardware, in a layer where the graphics stack does not need to know the difference between a real monitor and a synthetic one. That is also why it can be combined with existing tooling rather than requiring a parallel stack.
The Makefile builds the module, the library and the binding
Building the three artifacts is one command at the top of the Makefile, and the targets are visible in the file.
all: module library pyevdi
install:
$(MAKE) -C module installThe `module` target passes the include paths for the kernel headers and builds the module with strict compiler flags, `-Werror -Wextra -Wall` plus stricter C flags including `-Wmissing-prototypes` and `-Wstrict-prototypes`. The `library` target adds the module include path so the wrapper can see the kernel side interface, and `pyevdi` adds both the module and library paths for the pybind11 based binding. `make install` installs all three, and `make uninstall` removes them.
The flags matter more than they look. The project compiles with warnings treated as errors, so a kernel API change that alters a struct layout or a function signature will fail the build rather than producing a module that misbehaves at runtime. For a component that sits between the kernel and a display driver, that is the right default.
There is also a `module-rc` target, which runs `ci/build_against_kernel --repo-ci rc` to build against a release candidate kernel, and `all-with-rc-linux` which chains it with the library and the binding. That is how the project keeps ahead of upstream kernel changes.
The Dockerfile shows the full build environment: a Debian bullseye slim base with the kernel build dependencies, the libdrm development headers for libevdi, cross compilers for i386, armhf and arm64, python3 and pybind11 for the binding, and tools including shellcheck and lintian.
Kernel support has a stated floor and a stated ceiling
The readme points to `module/README.md` for the detailed installation instructions and states the minimum supported kernel version is 4.15. DisplayLink has verified that the module compiles and works with Ubuntu variants of kernels up to 6.15, and it notes that although other vanilla Linux kernel sources are used for the CI jobs, newer kernels or kernel variants used by other distributions may require extra development.
That gap between the minimum and the verified ceiling is where the real work sits. A distribution kernel is not the same as a vanilla kernel, so a version that is below 6.15 on a non-Ubuntu distribution may still fail to build even though CI is green on the vanilla sources. The readme invites help with exactly this, listing among the contribution avenues the goal of ensuring that EVDI works on other distributions than Ubuntu.
Packages exist for the main routes. The project releases a deb package, or a standalone installer paired with the driver, and points to the DisplayLink downloads page for the latest release. There is a community driven project generating RPM packages for Fedora, CentOS Stream, Rocky Linux and AlmaLinux, built on this code, and an AUR package maintained by the community for Arch.
For most Linux desktops the practical path is therefore the vendor package, and this repository is what you build when you need a version the vendor does not ship, or when you are working on the module itself.
EVDI is not a DisplayLink driver on its own
The readme is explicit on this point and it deserves to be quoted rather than paraphrased: EVDI is not a complete driver for DisplayLink devices and will require the driver for the full functionality.
The relationship is that EVDI provides the display mechanism and the transport to the user space driver, and the DisplayLink driver provides the actual handling of the hardware. The readme says EVDI is usually combined with the DisplayLink driver, and that EVDI is released as a deb package or as a standalone installer paired with the driver.
That matters for anyone evaluating the project on its own terms. If your goal is to drive a DisplayLink adapter, EVDI is a component and you still need the vendor driver. If your goal is to create a virtual display for something that has nothing to do with DisplayLink hardware, EVDI stands alone, and `libevdi` or `pyevdi` is the whole story.
The licensing follows the same split. The readme states that elements of the project are licensed under various licenses: the `module` and `library` are licensed under GPL v2 and LGPL v2.1-or-later respectively, with separate `LICENSE` files in the subfolders, while the remaining files and subfolders are under the MIT licence unless a separate `LICENSE` file states otherwise. Copyright runs from 2015 to 2026 DisplayLink (UK) Ltd.
The kernel module being GPL v2 is not a formality, since linking a GPL v2 module into the kernel is what it is for, while the library being LGPL keeps it usable from proprietary applications.
The ioctl boundary is unauthenticated, and the readme says so
The most interesting section of the readme is the one about future development, because it names a security property that the current design does not have.
The communication between the EVDI kernel module and the wrapper libevdi library is not access-controlled or authenticated. The readme says this could be enhanced in a future release, making it more difficult to compromise the data that EVDI sends and receives.
So any user space process that can open the module's device can drive the displays and read what is being displayed. On a single user machine that is a minor concern, and on a shared or multi user system it is the kind of thing you want to know before you deploy. The readme is candid about it, which is the main thing, but it does mean the fix is on the roadmap rather than in the code.
The second item on the future list is about the driver model. The module is currently a platform_driver for several reasons, the most important being that virtual displays are not discoverable, that is, they cannot be enumerated at the hardware level. EVDI is also a generic device, not tied to any particular kind of device, transport layer or bus.
That reasoning also explains the shape of the API. If displays cannot be enumerated, the user space application has to hold the handle and keep track of which display is which, which is a different model from a DRM driver that the system discovers on its own.
Choosing between libevdi and pyevdi, and between EVDI and the driver
There are two decisions to make, and they are separate.
The first is the language. `libevdi` is a C library and is what the DisplayLink user mode driver links against. `pyevdi` is a Python wrapper around it, built with pybind11, and the readme notes that virtual displays can be created with its help. The difference in approach is the usual one: the C library is the interface, and the Python binding is a convenience layer for scripts, tests and tools that do not want to manage the C lifecycle by hand.
The second decision is whether EVDI is the whole answer. If you are driving DisplayLink hardware, the answer is no, and you need the vendor driver alongside it. If you want a display owned by a process, for example to capture frames from a remote session or to give a scripted GUI test a deterministic screen size, then EVDI plus one of the two libraries is the complete picture, and the DRM compatibility means the existing display tooling works with it.
What EVDI does not do is replace the display stack, the compositor or the kernel's own virtual display options. It adds a second source of DRM outputs that user space can create and destroy dynamically, with the image content under application control. If your requirement is a fixed headless framebuffer for a container, the kernel and the X server already offer lighter options, and EVDI earns its complexity when the application needs to push and receive screen updates.
For that case, the readme's own caveat is the deciding factor. If your threat model includes untrusted local users, the unauthenticated module interface is the piece to weigh, and the readme's future development note is the signal that the project intends to change it.
Editorial conclusion
evdi suits a developer who needs a display that user space owns, whether that is a remote session, a capture pipeline or a scripted GUI test, and it is the wrong choice if you expected a driver for DisplayLink hardware, since the readme states plainly that EVDI is not a complete driver for DisplayLink devices. Before building it, check your kernel against the stated support window, since the minimum is 4.15 and DisplayLink has verified the module up to 6.15 on Ubuntu variants, and read the licensing note, because the kernel module is GPL v2 and the library is LGPL v2.1-or-later while the remaining files are MIT.
Frequently asked questions
What is evdi?
The Extensible Virtual Display Interface is a Linux kernel module that lets user space programs add, remove and drive virtual displays, together with a `libevdi` wrapper library and a `pyevdi` Python binding. The API documentation lives at displaylink.github.io/evdi.
Which kernel versions does evdi support?
The minimum supported kernel version is 4.15. DisplayLink has verified the module compiles and works with Ubuntu variants of kernels up to 6.15, and newer kernels or other distribution variants may require extra development.
Is evdi a complete DisplayLink driver?
No. The readme states that EVDI is not a complete driver for DisplayLink devices and requires the DisplayLink driver for full functionality. It is usually combined with that driver.
How do I build and install evdi?
The readme points to `module/README.md` for detailed installation instructions. The top level Makefile has an `all` target that builds the module, the library and the Python binding, and an `install` target that installs all three.
How is evdi licensed?
The kernel module is licensed under GPL v2 and the library under LGPL v2.1-or-later, each with its own LICENSE file in the subfolder, while the remaining files and subfolders are under the MIT licence unless a separate LICENSE file says otherwise.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/displaylink-evdi)Was this useful?