Back to Articles

DeskHop: Building a Hardware KVM That Switches Faster Than Your Monitor's Refresh Rate

[ View on GitHub ]

DeskHop: Building a Hardware KVM That Switches Faster Than Your Monitor’s Refresh Rate

Hook

Your $200 KVM switch takes 1-2 seconds to switch between computers. DeskHop does it in under a millisecond using $8 worth of Raspberry Pi Picos—by staying connected to both computers simultaneously.

Context

If you work with multiple computers—say, a Linux development machine and a macOS laptop, or a personal desktop and a work-issued PC—you’ve faced the peripheral problem. You can buy separate keyboards and mice for each machine, cluttering your desk and forcing constant mental context switches. You can use software KVM solutions like Barrier or Synergy, but they require installation on both machines, introduce network latency, and often break with OS updates or security policies. Commercial USB KVM switches seem like the perfect solution until you experience their fundamental flaw: they physically disconnect and reconnect USB devices during switching, causing 1-2 seconds of dead time where neither computer responds to input.

DeskHop emerged from a simple observation: the Raspberry Pi Pico can act as both a USB host and a USB device. What if you used two Picos to maintain simultaneous connections to both computers, eliminating the reconnection delay entirely? The result is a fast desktop switching device that feels more like moving your mouse between monitors on a single computer than switching between separate machines. Your keyboard and mouse connect to one Pico acting as a USB host, while both Picos present themselves as HID devices to your two computers. Move your mouse past the screen edge or press a hotkey, and your input instantly redirects to the other machine. No disconnection, no delay, no software installation required.

Technical Insight

Board B (Secondary)

Board A (Primary)

Raw HID Reports

Relative Movement

Boundary Check

State Sync

Switch Events

HID Reports

HID Reports

USB Host

Keyboard/Mouse

HID Report

Parser

Virtual Cursor

Tracker

USB Device

Output A

USB Device

Output B

Isolated UART

ADUM1201

Computer A

Computer B

System architecture — auto-generated

The architecture centers on two RP2040 microcontrollers connected via UART with galvanic isolation—typically using an ADUM1201 or similar chip to prevent ground loops when connecting computers on different power circuits. This isn’t just paranoia; connecting two computers with different ground potentials can cause USB communication errors or, in extreme cases, hardware damage. The isolation chip costs about $2 and eliminates an entire class of potential failures.

The firmware leverages TinyUSB to implement dual USB roles on each Pico. Board A connects to your keyboard and mouse as a USB host, parsing incoming HID reports. Both boards connect to computers as USB HID devices (keyboard and mouse). The critical technical challenge is mouse handling. Standard USB mice report relative movements (“moved 5 pixels right”), not absolute positions. To enable seamless transitions between screens, DeskHop maintains a virtual cursor position by accumulating these relative movements:

// Simplified mouse tracking from the firmware
typedef struct {
    int16_t x;
    int16_t y;
    uint16_t screen_width;
    uint16_t screen_height;
    uint8_t active_output;  // 0 or 1
} mouse_state_t;

void process_mouse_report(mouse_state_t* state, int8_t delta_x, int8_t delta_y) {
    // Accumulate relative movements into absolute position
    state->x += delta_x;
    state->y += delta_y;
    
    // Clamp to screen boundaries
    if (state->x < 0) state->x = 0;
    if (state->x > state->screen_width) state->x = state->screen_width;
    if (state->y < 0) state->y = 0;
    if (state->y > state->screen_height) state->y = state->screen_height;
    
    // Check for screen boundary crossing
    if (state->active_output == 0 && state->x >= state->screen_width - 1) {
        switch_to_output(state, 1);
        state->x = 0;  // Wrap to other screen's left edge
    } else if (state->active_output == 1 && state->x <= 0) {
        switch_to_output(state, 0);
        state->x = state->screen_width - 1;  // Wrap to other screen's right edge
    }
}

This virtual cursor tracking enables the magic: when you push your mouse beyond the right edge of Computer A’s screen, DeskHop knows to switch output to Computer B and reposition the cursor at the left edge. The switch happens by simply routing HID reports to the other Pico via UART. Since both Picos maintain active USB connections to their respective computers, there’s no reconnection penalty—just a UART message transfer that takes tens of microseconds.

The UART communication protocol between Picos is deliberately simple and robust. Each message includes a type identifier, payload length, and checksum. When Board A (the primary controller with the keyboard/mouse attached) decides to switch outputs, it sends a state synchronization message to Board B containing the current keyboard modifier state, mouse button status, and target cursor position. This ensures both computers see consistent HID device states and prevents weird edge cases like a mouse button staying “pressed” on the abandoned computer.

One clever implementation detail is how DeskHop handles keyboard shortcuts. Rather than defining a fixed hotkey, the firmware watches for a configurable sequence (default: both left and right Ctrl pressed simultaneously). The hotkey detection happens in the USB host code on Board A before the HID reports are forwarded to either computer, so the computers themselves never see these special combinations. This makes the switching mechanism completely transparent to the operating systems.

The firmware also implements a “gaming mode” toggle (activated by another keyboard shortcut) that switches to pure relative mouse reporting without position tracking. This solves compatibility issues with games and virtual machines that expect raw mouse input and implement their own cursor handling. In gaming mode, DeskHop stops attempting to switch outputs based on mouse position and only responds to keyboard hotkeys, behaving more like a traditional KVM switch but still maintaining the instant switching capability.

Firmware updates deserve special mention. DeskHop implements a custom USB bootloader mode that gets triggered by a specific keyboard combination. When activated, the Pico presents itself as a mass storage device, allowing you to drag-and-drop a new firmware image without physically accessing the device or pressing the tiny BOOTSEL button on the board. For a device that’s often mounted under a desk or behind monitors, this is a significant usability improvement over the standard Pico firmware update process.

Gotcha

The absolute mouse positioning that makes seamless screen transitions possible becomes a liability with applications that expect raw relative mouse input. Virtual machines, especially when the guest OS cursor doesn’t perfectly track with the host cursor, create a confusing experience where DeskHop thinks the cursor is at the screen edge but the VM shows it elsewhere. Some games, particularly first-person shooters that rely on continuous mouse motion without edge constraints, behave unpredictably. Gaming mode mitigates this, but you need to remember to toggle it before launching affected applications. There’s no way to automatically detect when gaming mode is needed, so it’s a manual switch.

The single monitor per computer assumption is baked deeply into the architecture. If Computer A has a three-monitor setup, DeskHop treats it as one giant logical screen and will only switch when the cursor reaches the rightmost pixel of the rightmost monitor. You can’t configure it to switch when moving between specific monitors in a multi-monitor array. Similarly, the left-to-right screen arrangement is configurable but limited—you can swap which computer is “left” and which is “right,” but you can’t arrange them vertically or in more complex topologies.

The hardware requirement is both a strength and a barrier. Yes, two Raspberry Pi Picos cost under $10 total, and the additional components (isolation chip, USB connectors, some wire) add maybe $5 more. But you need to solder the boards together, either following the PCB designs in the repository or hand-wiring on a breadboard. For developers comfortable with hardware, this is a fun weekend project. For those who haven’t touched a soldering iron since college, it’s a significant hurdle. There are no pre-assembled commercial versions available, though the repository includes full KiCad designs if you want to order custom PCBs.

Verdict

Use DeskHop if: you regularly work with two computers simultaneously, value instant switching over the convenience of software-only solutions, and have basic soldering skills (or a friend who does). It’s particularly compelling for developers managing different OS environments (Windows for work, Linux for personal projects) or anyone in a secure work environment where installing third-party software like Barrier isn’t permitted. The sub-$15 total cost makes it a low-risk experiment, and the open-source firmware means you can customize behavior to your exact workflow. Skip it if: you need multi-monitor awareness, exclusively work with virtual machines or games requiring raw mouse input, or want a plug-and-play solution without any DIY assembly. For those scenarios, spending more on a commercial KVM switch or accepting the limitations of software solutions like Barrier will save you frustration. Also skip if you’re already comfortable with separate peripherals for each machine—DeskHop solves a problem that not everyone experiences as painful enough to address.

// ADD TO YOUR README
[![Featured on Starlog](https://starlog.is/api/badge/developer-tools/hrvach-deskhop.svg)](https://starlog.is/api/badge-click/developer-tools/hrvach-deskhop)