From 2a3bdb99343946fd14aa5490d1dc9b03236dd687 Mon Sep 17 00:00:00 2001 From: Kaloyan Danchev Date: Sun, 1 Feb 2026 13:38:17 +0200 Subject: [PATCH] =?UTF-8?q?Fix=20KVM=20switch:=20working=20Nobara=20?= =?UTF-8?q?=E2=86=92=20Mac=20with=20correct=20HID++=20commands?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Discovered correct HID++ feature indices per device - Updated to_mac.sh with working hidapitester commands - Updated docs with complete setup instructions - Mac → Nobara direction still needs work (TODO) Co-Authored-By: Claude Opus 4.5 --- docs/wip/KVM-SWITCH-MAC-NOBARA.md | 296 +++++++++++++++++++----------- scripts/kvm/to_mac.sh | 46 ++--- scripts/kvm/to_nobara.sh | 39 ++-- 3 files changed, 233 insertions(+), 148 deletions(-) diff --git a/docs/wip/KVM-SWITCH-MAC-NOBARA.md b/docs/wip/KVM-SWITCH-MAC-NOBARA.md index 7df93c3..0d63fa1 100644 --- a/docs/wip/KVM-SWITCH-MAC-NOBARA.md +++ b/docs/wip/KVM-SWITCH-MAC-NOBARA.md @@ -1,12 +1,12 @@ # One-Key KVM: Mac ↔ Nobara -**Status:** WIP - Scripts created, needs testing -**Hardware:** Dell U3821DW, MX Keys S, MX Master 3S +**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 Pro M3) and Nobara Linux using DDC/CI and HID++ commands. +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 @@ -16,140 +16,195 @@ Software KVM solution to switch the Dell U3821DW ultrawide monitor and Logitech | USB-C | 27 | USB-C | Mac | | HDMI 2 | 18 | HDMI 2 | Nobara | -### Peripheral Channels -| Channel | Code | Connection | Computer | -|---------|------|------------|----------| -| 1 | 0x00 | Bluetooth | Mac | -| 2 | 0x01 | Logi Bolt USB | 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 3S (Easy-Switch capable) +- **Mouse:** Logitech MX Master 4 for Mac (Easy-Switch capable) - **Receiver:** Logi Bolt USB (PID: 046d:c548) -## Prerequisites +## Nobara Setup -### Mac +### 1. Install dependencies ```bash -# Install m1ddc (DDC control for Apple Silicon) -brew install m1ddc +sudo dnf install ddcutil +``` -# Install hidapitester (HID control) -curl -sL https://github.com/todbot/hidapitester/releases/latest/download/hidapitester-macos-arm64.zip -o /tmp/hidapitester.zip +### 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 ``` -### Nobara (Linux) +### 4. Udev rule for non-root HID access ```bash -# Install ddcutil -sudo dnf install ddcutil - -# Add user to i2c group (requires reboot) -sudo usermod -aG i2c $USER - -# Install hidapitester -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 - -# Udev rule for non-root HID access 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 Nobara (Run on Mac) +### 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 +#!/bin/bash # KVM Switch: Mac → Nobara -set -e +# TODO: Needs correct HID++ feature indices for Mac's Bolt receiver echo "Switching to Nobara..." # Switch Monitor to HDMI 2 m1ddc set input 18 -# Switch Mouse to Bolt (Channel 2) -~/bin/hidapitester --vid 046d --pid c548 --usage 0x0001 --usagePage 0xff00 \ - --open --length 7 --send-output "0x10,0x01,0x09,0x1b,0x01,0x00,0x00" +# 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 -# Switch Keyboard to Bolt (Channel 2) -~/bin/hidapitester --vid 046d --pid c548 --usage 0x0001 --usagePage 0xff00 \ - --open --length 7 --send-output "0x10,0x02,0x09,0x1b,0x01,0x00,0x00" - -echo "Done\!" +echo "Done!" ``` -### Switch to Mac (Run on Nobara) -**Location:** `~/scripts/to_mac.sh` +## 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 -#\!/bin/bash -# KVM Switch: Nobara → Mac -set -e - -echo "Switching to Mac..." - -# Switch Monitor to USB-C -ddcutil setvcp 60 27 - -# Switch Mouse to Bluetooth (Channel 1) -~/bin/hidapitester --vid 046d --pid c548 --usage 0x0001 --usagePage 0xff00 \ - --open --length 7 --send-output "0x10,0x01,0x09,0x1b,0x00,0x00,0x00" - -# Switch Keyboard to Bluetooth (Channel 1) -~/bin/hidapitester --vid 046d --pid c548 --usage 0x0001 --usagePage 0xff00 \ - --open --length 7 --send-output "0x10,0x02,0x09,0x1b,0x00,0x00,0x00" - -echo "Done\!" +# 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 ``` -## Keyboard Shortcuts - -### Mac (Logi Options+) -1. Logi Options+ → MX Keys S → Smart Actions -2. Create "KVM Switch" action -3. Trigger: F12 -4. Action: System → Open File → `~/scripts/to_nobara.sh` - -### Nobara (GNOME) -1. Settings → Keyboard → Custom Shortcuts -2. Command: `/home/USER/scripts/to_mac.sh` -3. Shortcut: F12 - -## Troubleshooting - -### Monitor doesn't switch -- **DDC/CI disabled:** Monitor Menu → Others → DDC/CI → On -- **USB-C hub blocking DDC:** Connect monitor directly to Mac USB-C port -- **Linux permissions:** Ensure user in `i2c` group, reboot after adding - -### Peripherals don't switch -- **Wrong device index:** The 0x01/0x02 values depend on Bolt pairing order - ```bash - # Find correct indices on machine with Bolt receiver - hidapitester --vid 046d --pid c548 --list-detail - ``` -- **Different Bolt PID:** Some receivers have different product IDs - ```bash - hidapitester --list | grep 046d - ``` - -### HID++ Command Reference -| Byte | Purpose | Values | -|------|---------|--------| -| 0x10 | Report ID (short) | Fixed | -| 0x01/0x02 | Device index | Mouse=0x01, Keyboard=0x02 (may vary) | -| 0x09 | Feature index | Change Host feature | -| 0x1b | Function | Set host | -| 0x00/0x01 | Channel | 0x00=Ch1, 0x01=Ch2, 0x02=Ch3 | - ## DDC Input Codes (Dell U3821DW) | Input | Code | Hex | @@ -160,18 +215,41 @@ echo "Done\!" | 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 -Scripts are stored on Mac at `~/scripts/`: -- `to_nobara.sh` - Switch to Nobara (run on Mac) -- `to_mac.sh` - Switch to Mac (copy to Nobara) -- `debug_kvm.sh` - Diagnostic script -- `setup_nobara.sh` - Nobara setup script +**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 -- [ ] Test monitor switching with DDC/CI enabled -- [ ] Verify Bolt receiver PID on Nobara -- [ ] Confirm device indices for keyboard/mouse -- [ ] Set up keyboard shortcuts on both machines -- [ ] Test bidirectional switching +- [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 diff --git a/scripts/kvm/to_mac.sh b/scripts/kvm/to_mac.sh index 146c126..aa28845 100755 --- a/scripts/kvm/to_mac.sh +++ b/scripts/kvm/to_mac.sh @@ -1,39 +1,39 @@ #!/bin/bash # KVM Switch: Nobara → Mac -# Switches monitor to USB-C and peripherals to Channel 3 (Mac Bolt via monitor hub) +# Switches monitor to USB-C and peripherals to Host 3 (Mac) # -# Channel setup: -# Channel 2 (0x01): Bolt #1 → Nobara -# Channel 3 (0x02): Bolt #2 → Mac (via monitor USB hub) - -set -e +# 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" -[ -x "$HIDAPITESTER" ] || HIDAPITESTER="/usr/local/bin/hidapitester" echo "Switching to Mac..." -# 1. Switch Monitor to USB-C (Dell U3821DW input code: 27) +# 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: sudo dnf install ddcutil" + echo " [WARN] ddcutil not installed" fi -# 2. Switch Mouse (MX Master 3S) to Channel 3 (Mac Bolt) -# Device index 0x01 - adjust if mouse was paired in different order -echo " Mouse -> Channel 3..." -"$HIDAPITESTER" --vidpid 046d/c548 --usage 0x0001 --usagePage 0xff00 \ - --open --length 7 --send-output 0x10,0x01,0x09,0x1b,0x02,0x00,0x00 2>/dev/null || \ - echo " [WARN] Mouse switch failed" - -# 3. Switch Keyboard (MX Keys S) to Channel 3 (Mac Bolt) -# Device index 0x02 - adjust if keyboard was paired in different order -echo " Keyboard -> Channel 3..." -"$HIDAPITESTER" --vidpid 046d/c548 --usage 0x0001 --usagePage 0xff00 \ - --open --length 7 --send-output 0x10,0x02,0x09,0x1b,0x02,0x00,0x00 2>/dev/null || \ - echo " [WARN] Keyboard switch failed" - echo "Done!" diff --git a/scripts/kvm/to_nobara.sh b/scripts/kvm/to_nobara.sh index e87064c..9460bd4 100755 --- a/scripts/kvm/to_nobara.sh +++ b/scripts/kvm/to_nobara.sh @@ -1,12 +1,16 @@ #!/bin/bash # KVM Switch: Mac → Nobara -# Switches monitor to HDMI 2 and peripherals to Channel 2 (Nobara Bolt) +# STATUS: NEEDS WORK - HID++ feature indices need to be discovered on Mac # -# Channel setup: -# Channel 2 (0x01): Bolt #1 → Nobara -# Channel 3 (0x02): Bolt #2 → Mac (via monitor USB hub) - -set -e +# Host mapping (0-indexed in HID++): +# Host 2 (0x01): Nobara (xtrm-pc) +# Host 3 (0x02): Mac (Kaloyan's MacBook Air) +# +# TODO: Find correct HID++ feature indices on Mac's Bolt receiver +# The feature indices discovered on Nobara were: +# Mouse (device 0x03): feature 0x0E +# Keyboard (device 0x02): feature 0x0A +# These may differ on Mac - need to verify with hidapitester or similar tool HIDAPITESTER="$HOME/bin/hidapitester" @@ -14,22 +18,25 @@ echo "Switching to Nobara..." # 1. Switch Monitor to HDMI 2 (Dell U3821DW input code: 18) echo " Monitor -> HDMI 2..." -if ! m1ddc set input 18 2>/dev/null; then - echo " [WARN] Monitor switch failed (DDC/CI disabled or not connected via USB-C)" +if command -v m1ddc &>/dev/null; then + m1ddc set input 18 2>/dev/null || \ + echo " [WARN] Monitor switch failed (DDC/CI disabled or not connected via USB-C)" +else + echo " [WARN] m1ddc not installed: brew install m1ddc" fi -# 2. Switch Mouse (MX Master 3S) to Channel 2 (Nobara Bolt) -# Device index 0x01 - adjust if mouse was paired in different order -echo " Mouse -> Channel 2..." +# 2. Switch Mouse (MX Master 4) to Host 2 (Nobara) +# TODO: Verify device index and feature index on Mac +echo " Mouse -> Nobara..." "$HIDAPITESTER" --vidpid 046d/c548 --usage 0x0001 --usagePage 0xff00 \ - --open --length 7 --send-output 0x10,0x01,0x09,0x1b,0x01,0x00,0x00 2>/dev/null || \ + --open --length 7 --send-output 0x10,0x03,0x0E,0x10,0x01,0x00,0x00 2>/dev/null || \ echo " [WARN] Mouse switch failed" -# 3. Switch Keyboard (MX Keys S) to Channel 2 (Nobara Bolt) -# Device index 0x02 - adjust if keyboard was paired in different order -echo " Keyboard -> Channel 2..." +# 3. Switch Keyboard (MX Keys S) to Host 2 (Nobara) +# TODO: Verify device index and feature index on Mac +echo " Keyboard -> Nobara..." "$HIDAPITESTER" --vidpid 046d/c548 --usage 0x0001 --usagePage 0xff00 \ - --open --length 7 --send-output 0x10,0x02,0x09,0x1b,0x01,0x00,0x00 2>/dev/null || \ + --open --length 7 --send-output 0x10,0x02,0x0A,0x10,0x01,0x00,0x00 2>/dev/null || \ echo " [WARN] Keyboard switch failed" echo "Done!"