# One-Key KVM: Mac ↔ Nobara **Status:** WIP - Nobara → Mac working, Mac → Nobara needs work **Hardware:** Dell U3821DW, MX Keys S, MX Master 4 for Mac **Updated:** 2026-02-01 ## Overview Software KVM solution to switch the Dell U3821DW ultrawide monitor and Logitech MX peripherals between Mac (MacBook Air M3) and Nobara Linux using DDC/CI and HID++ commands. ## Hardware Mapping ### Monitor Inputs | Input | Code | Port | Computer | |-------|------|------|----------| | USB-C | 27 | USB-C | Mac | | HDMI 2 | 18 | HDMI 2 | Nobara | ### Peripheral Hosts (Logi Bolt) | Host | Index (HID++) | Connection | Computer | |------|---------------|------------|----------| | 1 | 0x00 | Bolt #1 | MacBook Air (Bluetooth?) | | 2 | 0x01 | Bolt #1 | Nobara (xtrm-pc) | | 3 | 0x02 | Bolt #2 | MacBook Air (via monitor hub) | ### Devices - **Monitor:** Dell U3821DW (38" Ultrawide, DDC/CI enabled) - **Keyboard:** Logitech MX Keys S (Easy-Switch capable) - **Mouse:** Logitech MX Master 4 for Mac (Easy-Switch capable) - **Receiver:** Logi Bolt USB (PID: 046d:c548) ## Nobara Setup ### 1. Install dependencies ```bash sudo dnf install ddcutil ``` ### 2. Add user to i2c group (requires reboot) ```bash sudo usermod -aG i2c $USER ``` ### 3. Install hidapitester ```bash curl -sL https://github.com/todbot/hidapitester/releases/latest/download/hidapitester-linux-amd64.zip -o /tmp/hidapitester.zip unzip -o /tmp/hidapitester.zip -d ~/bin/ chmod +x ~/bin/hidapitester ``` ### 4. Udev rule for non-root HID access ```bash echo 'SUBSYSTEM=="usb", ATTRS{idVendor}=="046d", ATTRS{idProduct}=="c548", MODE="0666"' | \ sudo tee /etc/udev/rules.d/99-logitech-bolt.rules sudo udevadm control --reload-rules && sudo udevadm trigger ``` ### 5. Reboot ```bash sudo reboot ``` ### 6. Verify setup ```bash # Check i2c group membership groups | grep i2c # Check monitor detection ddcutil detect # Check Bolt receiver ~/bin/hidapitester --vidpid 046d/c548 --list-detail ``` ### 7. Copy script and set up shortcut ```bash # Copy script mkdir -p ~/scripts cp /path/to/xtrm/infrastructure/scripts/kvm/to_mac.sh ~/scripts/ chmod +x ~/scripts/to_mac.sh # Set up keyboard shortcut (Ctrl+Shift+Up) gsettings set org.gnome.settings-daemon.plugins.media-keys custom-keybindings \ "$(gsettings get org.gnome.settings-daemon.plugins.media-keys custom-keybindings | sed "s/]$/, '\/org\/gnome\/settings-daemon\/plugins\/media-keys\/custom-keybindings\/custom-kvm\/']/")" gsettings set org.gnome.settings-daemon.plugins.media-keys.custom-keybinding:/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom-kvm/ name 'KVM Switch to Mac' gsettings set org.gnome.settings-daemon.plugins.media-keys.custom-keybinding:/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom-kvm/ command '/home/jazzymc/scripts/to_mac.sh' gsettings set org.gnome.settings-daemon.plugins.media-keys.custom-keybinding:/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom-kvm/ binding 'Up' ``` ## Mac Setup ### 1. Install dependencies ```bash # Install m1ddc (DDC control for Apple Silicon) brew install m1ddc # Install hidapitester curl -sL https://github.com/todbot/hidapitester/releases/latest/download/hidapitester-macos-arm64.zip -o /tmp/hidapitester.zip unzip -o /tmp/hidapitester.zip -d ~/bin/ chmod +x ~/bin/hidapitester ``` ### 2. Copy script ```bash mkdir -p ~/scripts cp /path/to/xtrm/infrastructure/scripts/kvm/to_nobara.sh ~/scripts/ chmod +x ~/scripts/to_nobara.sh ``` ### 3. Set up keyboard shortcut TODO: Configure via Logi Options+ or macOS Shortcuts app ## Scripts ### Switch to Mac (Run on Nobara) - WORKING **Location:** `~/scripts/to_mac.sh` ```bash #!/bin/bash # KVM Switch: Nobara → Mac # Switches monitor to USB-C and peripherals to Host 3 (Mac) # # Host mapping (0-indexed in HID++): # Host 1 (0x01): Nobara (xtrm-pc) # Host 3 (0x02): Mac (Kaloyan's MacBook Air) # # HID++ command format: ReportID, DeviceIdx, FeatureIdx, Function, HostIdx, 0, 0 # Mouse: device 0x03, feature 0x0E (CHANGE_HOST) # Keyboard: device 0x02, feature 0x0A (CHANGE_HOST) # Function 0x10 = setCurrentHost (function 0 << 4) HIDAPITESTER="$HOME/bin/hidapitester" echo "Switching to Mac..." # 1. Switch Mouse (MX Master 4) to Host 3 (Mac) echo " Mouse -> Mac..." "$HIDAPITESTER" --vidpid 046d/c548 --usage 0x0001 --usagePage 0xff00 \ --open --length 7 --send-output 0x10,0x03,0x0E,0x10,0x02,0x00,0x00 2>/dev/null || \ echo " [WARN] Mouse switch failed" # 2. Switch Keyboard (MX Keys S) to Host 3 (Mac) echo " Keyboard -> Mac..." "$HIDAPITESTER" --vidpid 046d/c548 --usage 0x0001 --usagePage 0xff00 \ --open --length 7 --send-output 0x10,0x02,0x0A,0x10,0x02,0x00,0x00 2>/dev/null || \ echo " [WARN] Keyboard switch failed" # 3. Switch Monitor to USB-C (Dell U3821DW input code: 27) echo " Monitor -> USB-C..." if command -v ddcutil &>/dev/null; then ddcutil setvcp 60 27 2>/dev/null || \ echo " [WARN] Monitor switch failed (DDC/CI disabled or permissions issue)" else echo " [WARN] ddcutil not installed" fi echo "Done!" ``` ### Switch to Nobara (Run on Mac) - NEEDS WORK **Location:** `~/scripts/to_nobara.sh` ```bash #!/bin/bash # KVM Switch: Mac → Nobara # TODO: Needs correct HID++ feature indices for Mac's Bolt receiver echo "Switching to Nobara..." # Switch Monitor to HDMI 2 m1ddc set input 18 # TODO: Find correct HID++ commands for Mac # The feature indices may differ on Mac's Bolt receiver # Use: hidapitester --vidpid 046d/c548 --list-detail # Then use solaar (if available) or HID++ protocol to find feature indices echo "Done!" ``` ## HID++ Command Reference ### Command Format | Byte | Purpose | Description | |------|---------|-------------| | 0 | Report ID | 0x10 (short report) | | 1 | Device Index | Device slot on Bolt receiver (0x01-0x06) | | 2 | Feature Index | **Device-specific** - must be discovered per device | | 3 | Function | 0x10 = setCurrentHost (function 0 << 4) | | 4 | Host Index | 0x00=Host1, 0x01=Host2, 0x02=Host3 | | 5-6 | Padding | 0x00, 0x00 | ### Current Device Configuration (Nobara Bolt Receiver) | Device | Solaar Index | HID++ Device Index | CHANGE_HOST Feature Index | |--------|--------------|-------------------|---------------------------| | MX Keys S | 2 | 0x02 | 0x0A (10) | | MX Master 4 for Mac | 3 | 0x03 | 0x0E (14) | ### Finding Feature Indices The CHANGE_HOST feature index varies per device. To find it: ```bash # On Linux with solaar solaar show 2>&1 | strings | grep "CHANGE HOST" # Look for: "14: CHANGE HOST {1814}" - the number before the colon is the feature index ``` ## DDC Input Codes (Dell U3821DW) | Input | Code | Hex | |-------|------|-----| | DisplayPort 1 | 15 | 0x0F | | DisplayPort 2 | 16 | 0x10 | | HDMI 1 | 17 | 0x11 | | HDMI 2 | 18 | 0x12 | | USB-C | 27 | 0x1B | ## Troubleshooting ### Monitor doesn't switch - **DDC/CI disabled:** Monitor Menu → Others → DDC/CI → On - **Linux permissions:** Ensure user in `i2c` group, reboot after adding - **Verify:** `ddcutil detect` should show monitor ### Peripherals don't switch - **Wrong feature index:** Feature indices are device-specific and must be discovered - **Device offline:** Move mouse/press key to wake device before switching - **Wrong device index:** Check `solaar show` for correct device numbers ### Solaar vs hidapitester - `solaar config` doesn't reliably switch hosts on some devices - Use `hidapitester` with correct HID++ commands instead - Solaar is useful for discovering device info and feature indices ## Files Location **Nobara:** - `~/scripts/to_mac.sh` - Switch to Mac (working) - `~/bin/hidapitester` - HID control tool **Mac:** - `~/scripts/to_nobara.sh` - Switch to Nobara (needs work) - `~/bin/hidapitester` - HID control tool **Repository:** - `infrastructure/scripts/kvm/to_mac.sh` - `infrastructure/scripts/kvm/to_nobara.sh` ## TODO - [x] Nobara → Mac switching (working) - [x] Set up keyboard shortcut on Nobara (Ctrl+Shift+Up) - [ ] **Mac → Nobara switching** - needs correct HID++ feature indices for Mac's Bolt receiver - [ ] Set up keyboard shortcut on Mac - [ ] Test monitor switching from Mac side