I have recently acquired a Dell UltraSharp 34, a very nice screen able to drive up to four different inputs. It also has an USB hub.
I use it with two laptops:
one laptop for working, plugged in USB-C
one laptop for testing, plugged in DisplayPort and USB upstream
As for the USB hub, I plug in it my keyboard, mouse and headphones. Now, when I
toggle the input the USB hub automatically switches to the laptop which
currently uses the screen. This is cool but not that easy. To effectively
switch the input source, one needs to click on a button behind the screen,
choose the function input source
with a kind of joystick, then select the
desired input and click again. This is quite complicated for such a simple and
common task.
Fortunately the screen provides an I2C interface allowing to programmatically change the screen settings from a computer connected to it. On Linux these settings can be changed using the software ddcutil.
Firstly, in order to use this tool, the kernel module i2c-dev
must be loaded.
Then rights must be set to access the device as a non-root user. For
simplicity’s sake, I decided to give the rights to the users
group. Here is
the relevant part of my configuration.nix
for NixOS
users:
[ "i2c-dev" ];
boot.kernelModules = "KERNEL==\"i2c-[0-9]*\", GROUP+=\"users\""; services.udev.extraRules =
Now to make sure ddcutil
is working correctly, call the commands detect
:
$ ddcutil detect
Invalid display
I2C bus: /dev/i2c-4
EDID synopsis:
Mfg id: AUO
Model:
Product code: 22333
Serial number:
Binary serial number: 0 (0x00000000)
Manufacture year: 2018, Week: 0
DDC communication failed
This is an eDP laptop display. Laptop displays do not support DDC/CI.
Display 1
I2C bus: /dev/i2c-5
EDID synopsis:
Mfg id: DEL
Model: DELL U3421WE
Product code: 41349
Serial number: 9C6P653
Binary serial number: 810566732 (0x3050444c)
Manufacture year: 2020, Week: 52
VCP version: 2.1
My Dell screen is correctly detected. Then the command capabilities
:
$ ddcutil capabilities
...
Feature: 60 (Input Source)
Values:
1b: Unrecognized value
0f: DisplayPort-1
11: HDMI-1
12: HDMI-2
...
This last command will dump a bunch of things that can be set using ddcutil
and in particular the command to switch inputs.
Now if I want to switch the screen input to DisplayPort-1
, all I have to do
is calling the command setvcp
for the feature Input Source
with the value
given by the capabilities
command:
$ ddcutil setvcp 60 0x0f
And if I want to switch it back to USB-C:
$ ddcutil setvcp 60 0x1b
I only use these two inputs so I made a script to quickly toggle between the two:
#!/usr/bin/env bash
set -o nounset
set -o errexit
# Get current input
current=$(ddcutil getvcp 60 | sed -n "s/.*(sl=\(.*\))/\1/p")
# Get the other input
case $current in
# Usb
0x1b)
output=0x0f
;;
# Display port
0x0f)
output=0x1b
;;
*)
echo "Unknown input"
exit 1
;;
esac
# Set new input
ddcutil setvcp 60 $output
I’d love to be able to switch only the USB hub as well but unfortunately it doesn’t seem possible with this screen. If you know a way to do it, let me know.