100% Software KVM switch with a single monitor

This post explains how to configure the keyboard/mouse sharing software barrier with automatic display switching to accomplish full KVM switch functionality. Unfortunately barrier does not work under wayland yet.

Introduction

barrier is a software KVM which allows sharing one computer’s keyboard and mouse (server) with another computer (client) over the network. Notice that its feature set does not include sharing a single display. Normally you would have two computers with their own displays and be able to switch from one to the other by moving the mouse off the screen in the direction that the other computer is placed in the configuration. It looks like the mouse pointer literally jumps from one screen to the other which is a totally different computer. When configured properly it works really well.

A hardware KVM switch on the other hand also has inputs and outputs for a monitor and it allows switching a single monitor to the appropriate computer. Obviously much more useful.

Luckily most recent monitors support multiple inputs. You can have more than one computer connected to a single monitor and use the buttons on the monitor to change the input. You can use barrier this way too though it is pretty cumbersome to have to do this manually every time.

We can however use software to switch the monitor input automatically. Monitors that allow this functionality can be controlled with DDC/CI sofware such as ddccontrol on Linux. Using ddccontrol we can tell our monitor to switch to whichever computer we’d like. Current releases of barrier come with a feature that can run a script when the user switches the keybaord/mouse to another computer. We are therefore able to switch the monitor along with the keyboard/mouse just like a hardware KVM switch.

This undocumented barrier feature is only available where a Linux host is configured as the server. I.e the keyboard and mouse have to be physically attached to a Linux computer. The clients can be running other operating systems.

In my case I am using a Linux laptop in a dual screen setup daily and switching to my Windows machine with a relatively nice graphics card for gaming.

To get things going, first install barrier on both machines. Use the configuration GUI to configure your setup for your monitors making sure the server is running on linux and the client is configured to connect to it on the other machines.

Once everything is up and running and you can switch to the other computer by dragging the mouse off the screen in that direction, we’ll be able to set up switching the monitor and automating the whole thing. (Instructions for configuration up to point is available on the barrier website. Note that you’ll have to change the monitor input manually for now.)

Switching display to the selected computer

Run ddccontrol -p in a terminal to to probe and find what monitor is attached to your computer. It will be listed under the Detected monitors section and have a name which in my case looked like /dev/i2c-4 . There may be multiples here. You can unplug your monitor and figure out the device name through a process of elimination or run some ddccontrol commands (like the ones below) to see which one is responding when you use which device name.

In the output of the same command there’s a section called Input settings whose last line in my case contains

Input settings
             > id=inputsource, name=Input Source Select, address=0x60, delay=-1ms, type=2
                  Possible values:
                        > id=analog - name=Analog, value=1
                        > id=digital - name=Digital, value=3
                  supported, value=15, maximum=17

This means the current input is 15 and maximum you can use is 17. This is my interpretation anyway. I am not sure if 16 means something in my case as I actually only have 2 inputs. The command to actually switch the monitor to an input 17 as an example is

ddccontrol -r 0x60 dev:/dev/i2c-4 -w 17

In my setup this switches the monitor to display the output of the Windows computer. Switching back to the Linux computer’s video output requires me to run the same command with 15 instead. You might need to test with your value and maximum numbers to figure out which input is which.

We will put the commands in a little script so we can switch to the correct computer using its name. The names should match the ones in the barrier configuration because we will use this same script from there later.

Here’s my the script for my setup where ‘t480s’ is the Linux computer and ‘mywindows’ is the Windows one. I will save all scripts at /home/xpufx/bin/mybarrier/barrier_switch.sh. For ease of use I saved my barrier server configuration in that directory as well.

#!/usr/bin/env bash

notify-send "Switching display to  $1"
case "$1" in
        "mywindows")
                ddccontrol -r 0x60 dev:/dev/i2c-4 -w 17
                ;;
        "t480s")
                ddccontrol -r 0x60 dev:/dev/i2c-4 -w 15
                ;;
esac

I can call this script as /home/xpufx/bin/mybarrier/barrier_switch.sh mywindows to switch to the Windows machine called mywindows. (We’re only switching the display here, not the keyboard/mouse)

I had to configure the Windows client side with Administrative rights otherwise it would ask for a password every time I switched to it.

In order to automate switching of the display we’ll have barrier run this same script when we’re switching computers. (barrier provides the name of the computer to the script as the first parameter) We used the barrier GUI to configure our server but we need to start the server process with some extra parameters which are not available on the GUI as far as I know. You can manually run this script when you start your Linux computer or have your window manager start it automatically. This is usually in the Sessions settings for your window manager and is called something like Auto start.

#!/usr/bin/env bash

/usr/bin/barriers -f --screen-change-script /home/xpufx/bin/mybarrier/barrier_switch.sh \
      --no-tray --debug DEBUG --name t480s \
      --disable-crypto --disable-client-cert-checking \
      -c /home/xpufx/bin/mybarrier/t480s-mywindows.conf > /home/xpuf/tmp/barrier.log

Once barrier is started this way you can start the GUI later if you need it. Note that my configuration is saved in a custom location and is called t480s-mywindows.conf. (I didn’t need encryption in my setup. The computers are connected directly to each other with an ethernet cable and private static IPs)

Now you will see that as soon as you switch your keyboard/mouse between computers, your monitor will also switch to that computer automatically.

Sample Barrier server config with keyboard shortcut

section: screens
        mywindows:
                halfDuplexCapsLock = false
                halfDuplexNumLock = false
                halfDuplexScrollLock = false
                xtestIsXineramaUnaware = false
                preserveFocus = false
                switchCorners = none
                switchCornerSize = 0
        t480s:
                halfDuplexCapsLock = false
                halfDuplexNumLock = false
                halfDuplexScrollLock = false
                xtestIsXineramaUnaware = false
                preserveFocus = false
                switchCorners = none
                switchCornerSize = 0
end

section: aliases
end

section: links
        mywindows:
        t480s:
end

section: options
        heartbeat = 5000
        relativeMouseMoves = false
        screenSaverSync = true
        win32KeepForeground = false
        clipboardSharing = true
        switchDelay = 250
        switchCorners = none +top-left +top-right +bottom-left +bottom-right
        switchCornerSize = 5
        keystroke(Control+Shift+q) = toggleScreen
end

Note that I am not actually using the mouse to switch computers so my config does not have info about which monitor is where or hot corner configuration. Instead I have a keyboard shortcut (CTRL+SHIT+q) to initiate the switch like a hardware KVM switch would usually work. This configuation is in the options section above and reads keystroke(Control+Shift+q) = toggleScreen.

Happy side effect, audio switching

If your monitor also has headphone or speakers output jacks, and you plug something in there you will notice that the audio is switching along with the KVM. Super useful.

Parting remarks

I am quite happy with this setup after prolonged use. The complete solution needs a bunch of technologies to cooperate and there are various things to set up but with relatively few moving parts.

Is it the same thing as a hardware switch? No. For instance, it needs a network connection to work. The system also needs to be up and have barrier running before you can switch. So no switching to a BIOS screen or boot loader.

On the other hand, you do not need to find a KVM switch that supports all your input types. No extra keyboard/mouse/video cables. You’d also have to pick a KVM switch that supports HDMI and/or Display Port and at the resolutions you’d like to use your computers at. This can get quite expensive.


1384 Words

2022-06-28 00:00 +0000

Fix Lenovo Thinkpad T480s USB mouse/keyboard not working after waking up from suspend.

I had an issue with my T480s recently when running Ubuntu 21.10. The laptop suspends properly and can be woken with the USB keyboard but right after waking up the USB keyboard and mouse do not work. Here’s the workaround.

After some research and trial error I noticed that I can manually remove and reinsert the usbhid kernel module (using the laptop’s own keyboard) to get the USB mouse and keyboard to function again. All that was left was to make this run automatically after waking up from suspend.

Create a new file in /lib/systemd/system-sleep and call it something like myusbhidfix. The following content removes the usbhid module when you suspend the laptop and loads it back up when the laptop wakes. I think both steps can also be implemented together in one post line but it doesn’t matter.

#!/bin/bash
[ "$1" = "post" ] && exec modprobe usbhid
[ "$1" = "pre" ] && exec rmmod usbhid
exit 0

Make this new file executable. (chmod +x myusbhidfix).