I already knew that I could get a USB switch pretty cheaply. For switching both the keyboard and the mouse, I was even willing to have two extremely cheap USB switches. Luckily, I found a very nice-looking USB switch with 4 input ports switchable between 2 host computers. You can find these with a variety of brand names for the same hardware on auction sites. For $10-12, you can get the USB 2.0 version. I splurged and spent $20 or so and got the USB 3.0 version (because you never know what the future will bring).

For tidiness, I used some double-sided tape and mounted this lengthwise to the pedestal arm of the monitor. (I also found a couple of other devices to share between the 2 computers.)

For a while, I operated by hitting the USB switch for the keyboard and mouse and then using my monitors built-in controls for switching between the 2 video inputs. That worked fine, but it's amazing how lazy you can become, and then you start thinking that doing two things to switch between computers is just an agonizing exertion.

Around that time, something drew my attention to an article about a project with the title Turn a $30 USB switch into a full-featured KVM. (See the links section for a URL). There were a couple of reasons that I was reluctant to use that project directly. I won't bore you with those reasons, but I credit that project with getting me thinking about what I ultimately used. In particular, it alerted me to the fact that there are wire protocols for switching video monitor inputs. Who knew? (Well, I guess a lot of people knew.)

After some searching around, I found the ddcutil (see the links section for a URL) application that knows how to speak that wire protocol. The web site has a nice write-up on how to discover the specific codes your monitor understands. For example, my monitor wants to receive the code "0x11" a certain way to switch to the HDMI-1 input and code "0x12" for HDMI-2. The code dumping didn't actually say what it wanted for switching to the HDMI-3 input, but I used my vast cerebral capacity to guess that it wanted "0x13", and I turned out to have guessed correctly.

The next thing to figure out was how to get those codes sent to my monitor. My personal machine runs Linux, so the trigger there would be hooking into the udev system to detect the presence of the keyboard or mouse. The work computer runs Windows. I decided that I would be happy with doing all of the reacting on the Linux computer. I would detect both the add and remove events via the udev system. When the usb devices showed up, I would switch to the Linux computer's video input on the monitor. When the usb devices went away, I would switch to the Windows computer's video input on the monitor. That system would not scale very well beyond 2 computers, but it works fine for exactly 2 computers.

I've included a couple of links in the links section to articles describing how to identify USB devices and hook into the udev system for custom activities.

Here is what I have in /etc/udev/rules.d/80-wjc.rules to notice and fire events when udev sees the keyboard coming and going. It's actually the USB hub inside the USB switch that is noticed by udev.

SUBSYSTEM=="usb", ENV{PRODUCT}=="5e3/612/9226" ENV{DEVTYPE}=="usb_device" ACTION=="add", RUN+="/home/wjc/bin/usbswitch.sh ADD"

SUBSYSTEM=="usb", ENV{PRODUCT}=="5e3/612/9226" ENV{DEVTYPE}=="usb_device" ACTION=="remove", RUN+="/home/wjc/bin/usbswitch.sh REMOVE"

Both the add and remove events run a short shell script, usbswitch.sh, with a single command line argument to indicate which way the wind is blowing. Here is that shell script:


# Run by a udev rule when my USB switch it switched away from this machine.
# Looks for the USB hub "remove" command.

/bin/echo `date` $1 >> /tmp/usbswitch.log

if [ "x$1" == "xADD" ]
    # HDMI-2
elif [ "x$1" == "xREMOVE" ]
    # HDMI-3
    /bin/echo `date` "unknown operation: " $1 >> /tmp/usbswitch.log
Read more »