Fix KVM switch: working Nobara → Mac with correct HID++ commands
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful

- 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 <noreply@anthropic.com>
This commit is contained in:
Kaloyan Danchev
2026-02-01 13:38:17 +02:00
parent 2d67ba5cb5
commit 2a3bdb9934
3 changed files with 233 additions and 148 deletions

View File

@@ -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 '<Shift><Control>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 <device_number> 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

View File

@@ -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!"

View File

@@ -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!"