Jump to content

Displaylink: Difference between revisions

From Official NixOS Wiki
Sandro (talk | contribs)
Sandro (talk | contribs)
 
Line 39: Line 39:
   };
   };
};
};
<syntaxhighlight lang="nix">
</syntaxhighlight>


====='''Gnome Wayland'''=====
====='''Gnome Wayland'''=====
Line 45: Line 45:
Install displayLink package
Install displayLink package


{{bc|<nowiki>
<syntaxhighlight lang="nix">
environment.systemPackages = with pkgs; [
environment.systemPackages = with pkgs; [
   displaylink
   displaylink
];
];
</nowiki>}}
</syntaxhighlight>


Define videoDrivers
Define videoDrivers
Line 57: Line 57:


Add dlm service
Add dlm service
{{bc|<nowiki>
<syntaxhighlight lang="nix">
systemd.services.dlm.wantedBy = [ "multi-user.target" ];
systemd.services.dlm.wantedBy = [ "multi-user.target" ];
</nowiki>}}
</syntaxhighlight>
====='''KDE Plasma'''=====
====='''KDE Plasma'''=====


Line 66: Line 66:
Esnure you properly enabled wayland session  
Esnure you properly enabled wayland session  


{{bc|<nowiki>
<syntaxhighlight lang="nix">
environment.variables = {
environment.variables = {
   KWIN_DRM_PREFER_COLOR_DEPTH = "24";
   KWIN_DRM_PREFER_COLOR_DEPTH = "24";
Line 84: Line 84:


};
};
</nowiki>}}
</syntaxhighlight>


Install displayLink package
Install displayLink package


{{bc|<nowiki>
<syntaxhighlight lang="nix">
environment.systemPackages = with pkgs; [
environment.systemPackages = with pkgs; [
   displaylink
   displaylink
];
];
</nowiki>}}
</syntaxhighlight>


Instead of dlm setup display-link server as follows:
Instead of dlm setup display-link server as follows:


{{bc|<nowiki>
<syntaxhighlight lang="nix">
# --- THIS IS THE CRUCIAL PART FOR ENABLING THE SERVICE ---
systemd.services.displaylink-server = {
systemd.services.displaylink-server = {
   enable = true;
   enable = true;
  # Ensure it starts after udev has done its work
   requires = [ "systemd-udevd.service" ];
   requires = [ "systemd-udevd.service" ];
   after = [ "systemd-udevd.service" ];
   after = [ "systemd-udevd.service" ];
   wantedBy = [ "multi-user.target" ]; # Start at boot
   wantedBy = [ "multi-user.target" ];
  # *** THIS IS THE CRITICAL 'serviceConfig' BLOCK ***
   serviceConfig = {
   serviceConfig = {
     Type = "simple"; # Or "forking" if it forks (simple is common for daemons)
     Type = "simple";
    # The ExecStart path points to the DisplayLinkManager binary provided by the package
     ExecStart = "${pkgs.displaylink}/bin/DisplayLinkManager";
     ExecStart = "${pkgs.displaylink}/bin/DisplayLinkManager";
    # User and Group to run the service as (root is common for this type of daemon)
     User = "root";
     User = "root";
     Group = "root";
     Group = "root";
    # Environment variables that the service itself might need
    # Environment = [ "DISPLAY=:0" ]; # Might be needed in some cases, but generally not for this
     Restart = "on-failure";
     Restart = "on-failure";
     RestartSec = 5; # Wait 5 seconds before restarting
     RestartSec = 5; # Wait 5 seconds before restarting
   };
   };
};
};
</nowiki>}}
</syntaxhighlight>


==Sway==
==Sway==

Latest revision as of 09:59, 18 January 2026

In order to use DisplayLink monitors over USB, such as the ASUS MB16AC, the DisplayLink driver needs to be installed.

Since these drivers depend on binary unfree blobs, you will need to first add it to your Nix store.

Run nix-shell -p displaylink --arg config '{ allowUnfree = true; }' to get the instructions and follow them.

When you try to use pkgs.displaylink in your nixos system, you will get the same instructions printed to the stderr, follow those to prefetch the driver. Once the blob is in the Nix store you can add the package

environment.systemPackages = with pkgs; [
 displaylink
];

Then add the videoDrivers:

services.xserver.videoDrivers = [ "displaylink" "modesetting" ];

The module nixos/modules/hardware/video/displaylink.nix should also work for wlroots compositors.

Xserver

Connecting a second external monitor

In order to add a second external monitor you can add the following to your configuration:

services.xserver.displayManager.sessionCommands = ''
    ${lib.getBin pkgs.xorg.xrandr}/bin/xrandr --setprovideroutputsource 2 0
'';

Wayland

At first add displayLink driver to nix store as above described.

evdi module

You probably will need the `evdi` module

boot = {
  extraModulePackages = [ config.boot.kernelPackages.evdi ];
  initrd = {
    # List of modules that are always loaded by the initrd.
    kernelModules = [
      "evdi"
    ];
  };
};
Gnome Wayland

Install displayLink package

environment.systemPackages = with pkgs; [
  displaylink
];

Define videoDrivers

services.xserver.videoDrivers = [ "displaylink" ];

Add dlm service

systemd.services.dlm.wantedBy = [ "multi-user.target" ];
KDE Plasma

Apparently KDE Plasma (Wayland) requires a slight different approach.

Esnure you properly enabled wayland session

environment.variables = {
  KWIN_DRM_PREFER_COLOR_DEPTH = "24";
};

services = {
  desktopManager.plasma6 = {
    enable = true;
  };
  displayManager = {
    sddm = {
      enable = true;
      wayland.enable = true;
    };
    defaultSession = "plasma";
  };

};

Install displayLink package

environment.systemPackages = with pkgs; [
  displaylink
];

Instead of dlm setup display-link server as follows:

systemd.services.displaylink-server = {
  enable = true;
  requires = [ "systemd-udevd.service" ];
  after = [ "systemd-udevd.service" ];
  wantedBy = [ "multi-user.target" ];
  serviceConfig = {
    Type = "simple";
    ExecStart = "${pkgs.displaylink}/bin/DisplayLinkManager";
    User = "root";
    Group = "root";
    Restart = "on-failure";
    RestartSec = 5; # Wait 5 seconds before restarting
  };
};

Sway

Identify which card has the render device, evdi is the DisplayLink interface, so it's not card0, but card1.

$ ls -l /dev/dri/by-path
lrwxrwxrwx - root  2 Nov 13:38 pci-0000:00:02.0-card -> ../card1
lrwxrwxrwx - root  2 Nov 13:38 pci-0000:00:02.0-render -> ../renderD128
lrwxrwxrwx - root  2 Nov 13:38 platform-evdi.0-card -> ../card0
environment.variables = {    
  WLR_EVDI_RENDER_DEVICE = "/dev/dri/card1";                                                                                                   
};
nixpkgs.overlays = [
  (final: prev: {    
    wlroots_0_17 = prev.wlroots_0_17.overrideAttrs (old: { # you may need to use 0_18
      patches = (old.patches or [ ]) ++ [
        (prev.fetchpatch {
          url = "https://gitlab.freedesktop.org/wlroots/wlroots/uploads/bd115aa120d20f2c99084951589abf9c/DisplayLink_v2.patch";
              hash = "sha256-vWQc2e8a5/YZaaHe+BxfAR/Ni8HOs2sPJ8Nt9pfxqiE=";
            })       
          ];
        });
      })
];
services.xserver.videoDrivers = [ "displaylink" ];
systemd.services.dlm.wantedBy = [ "multi-user.target" ];

Note as of 2024-10-30 nixos-unstable sway uses wlroots_0_18. The patch above applies correctly but you will need to invoke sway with the --unsupported-gpu flag.


Source

Troubleshooting

Suspend blocked by pre-sleep.service

As of NixOS 25.05, installing pkgs.displaylink inserts some directives into the script referenced by pre-sleep.service. If suspending does not work and causes the reboot and poweroff buttons to stop working, it may be a symptom of suspend being blocked by pre-sleep.service.

The script in question:

#!/nix/store/cfqbabpc7xwg8akbcchqbq3cai6qq2vs-bash-5.2p37/bin/bash
set -e

#flush any bytes in pipe
while read -n 1 -t 1 SUSPEND_RESULT < /tmp/PmMessagesPort_out; do : ; done;

#suspend DisplayLinkManager
echo "S" > /tmp/PmMessagesPort_in

#wait until suspend of DisplayLinkManager finish
if [ -f /tmp/PmMessagesPort_out ]; then
  #wait until suspend of DisplayLinkManager finish
  read -n 1 -t 10 SUSPEND_RESULT < /tmp/PmMessagesPort_out
fi

Because of a stray /tmp/PmMessagesPort_out caused by an unclean shutdown, the suspend action was blocked by this script trying to flush the port. A myriad of solutions can be used to unblock the script and restore suspend:

  • Start dlm.service so that DisplayLinkManager can clear the ports and unblock the script
  • Use sudo DisplayLinkManager to clear the ports and unblock the script

Untested solutions:

  • Removing the file
  • Killing the script