A small Windows tray utility that switches a Logitech MX Master 3S (or any Logitech mouse with Easy-Switch) between its three Bluetooth channels, with global hotkeys.
It talks to the mouse directly over HID++ 2.0 (feature 0x1814 "Change Host"), so it does not need Logi Options+ and works alongside it. No installer, no services, no dependencies beyond the .NET runtime.
- Tray icon that shows which Easy-Switch channel this PC is on, and greys out while the mouse is away.
- One global hotkey per channel (defaults: Ctrl+Alt+1 / 2 / 3) plus an optional "next channel" hotkey.
- Settings window: record hotkeys by pressing them, see the device name paired on each channel (read from the mouse itself), choose which Logitech devices a hotkey switches, start with Windows.
- Command-line mode for AutoHotkey, Stream Deck, Task Scheduler or scripts.
- Works with several Logitech devices at once (for example an MX Keys keyboard on the same channels).
- Single portable exe, settings in
%APPDATA%\MxSwitch.
- Windows 10 or 11, 64-bit.
- The mouse paired with this PC over Bluetooth (or connected through a Logi Bolt / Unifying receiver, which is supported in code but not yet tested, see the open issues).
- .NET 10 Desktop Runtime for the default build (Windows usually prompts to install it on first launch), or build the self-contained variant described under Building.
-
Run
MxSwitch.exe. A blue disc with the current channel number appears in the system tray. -
Press a hotkey to send the mouse to another channel:
Default hotkey Action Ctrl + Alt + 1 switch to channel 1 Ctrl + Alt + 2 switch to channel 2 Ctrl + Alt + 3 switch to channel 3 (none) cycle to the next channel -
Left-click the tray icon (or right-click > Settings...) to change the hotkeys, see which device is paired on each channel, pick a different device, or enable Start with Windows.
-
Right-click the tray icon for a menu with the three channels and Next channel.
Hotkeys need Ctrl, Alt or Win (Shift alone is not enough, it would hijack normal typing), or an F-key. Click a hotkey box and press the combination; Backspace clears it. While a hotkey box has keyboard focus the existing hotkeys are paused so you can re-use them.
- The hotkey only works while the mouse is connected to this PC. Once the mouse has moved to channel 2, this PC can no longer talk to it. To come back, press the channel button on the bottom of the mouse, or run MxSwitch on the other computer too (the exe is portable: copy it over and set a hotkey there).
- Switching to a channel whose device is off or out of range leaves the mouse looking for it. Press the channel button on the mouse to get it back.
- The tray icon shows
-while the mouse is away and goes back to the channel number when it reconnects. - Logitech recommends pairing each computer to only one channel; two channels on the same PC cause lag.
- Other Logitech devices (for example an MX Keys keyboard) are listed in Settings; untick "Switch every connected Logitech mouse" to pick exactly which devices a hotkey switches.
- Settings live in
%APPDATA%\MxSwitch\settings.json; a short diagnostic log (mxswitch.log) sits next to it.
The same exe doubles as a command-line tool:
MxSwitch --host 2 switch to channel 2 and exit (exit code 0 on success)
MxSwitch --next switch to the next paired channel and exit
MxSwitch --list show connected Logitech devices and their channels
MxSwitch --probe detailed HID++ diagnostics (add --out report.txt to save)
MxSwitch --settings open the settings window of the running tray instance
MxSwitch is a windowed program, so an interactive prompt returns before it has finished and the printed exit
code belongs to the previous command. When you need the exit code, wait for it explicitly:
start /wait MxSwitch --host 2 (cmd), (Start-Process .\MxSwitch.exe -ArgumentList '--host','2' -Wait -PassThru).ExitCode
(PowerShell) or RunWait (AutoHotkey). Batch files, Task Scheduler and Stream Deck wait anyway.
- Nothing happens on the hotkey. Check the tray tooltip: if it says no mouse is connected, the mouse is on another channel or asleep. Wake it or press its channel button, then try again.
- "Hotkey already taken by another program." Another app registered that combination first. Pick a different one in Settings.
- The mouse is connected but never reacts. Tick Send reports with HidD_SetOutputReport in Settings:
a few Bluetooth adapters drop
WriteFileoutput reports and need the control-transfer path. - Logi Options+ is running. The HID++ collection is shared, so both can coexist. If MxSwitch reports that it cannot open the device, close Options+ and try again.
- SmartScreen warns about an unknown publisher. The exe is not code-signed. Build it yourself from this repository if you prefer.
- Something else. Run
MxSwitch --probe --out probe.txtwith the mouse connected; it lists every Logitech HID interface, the feature indices and the raw HID++ traffic, and%APPDATA%\MxSwitch\mxswitch.logrecords failed switches. Attach both to an issue.
Requires the .NET 10 SDK. Then:
build.cmd
which runs dotnet publish -c Release -o dist and leaves dist\MxSwitch.exe (single file, needs the
.NET 10 Desktop Runtime on the target machine). build.cmd first looks for a user-local SDK in
%LOCALAPPDATA%\Microsoft\dotnet (where the official dotnet-install.ps1 script puts it), then for dotnet
on the PATH, and prints which one it uses. For an exe that needs no runtime at all:
dotnet publish -c Release -o dist --self-contained true
app.ico is generated by tools\make-icon.ps1. There are no NuGet dependencies.
Logitech devices expose a vendor-specific HID collection next to the normal mouse collection. On that collection they speak HID++ 2.0, a request/reply protocol in 20-byte "long" reports:
byte 0 0x11 long report id
byte 1 0xFF device index (0xFF = directly connected; 1..6 = receiver slot)
byte 2 feature index resolved at runtime via IRoot (feature 0x0000)
byte 3 fn << 4 | swId function number and a software id echoed in the reply
byte 4.. parameters 16 bytes
MxSwitch uses four features:
| Feature | Name | Used for |
|---|---|---|
| 0x0000 | IRoot | ping (is this HID++ 2.0?) and feature index lookup |
| 0x0005 | Device Name and Type | the name ("MX Master 3S") and kind (mouse / keyboard) |
| 0x1814 | Change Host | number of hosts, current host, and SetCurrentHost(n) |
| 0x1815 | Hosts Info | per-channel pairing status and the paired device's name |
SetCurrentHost is special: the mouse does not answer, it simply drops the Bluetooth link and connects to
the other host. MxSwitch therefore keeps the handle open briefly, polls once more, treats "no longer
answering" as success and re-sends once if the mouse is still there.
Source layout:
Logitech/NativeMethods.cs- Win32 declarations (SetupAPI, hid.dll, overlapped I/O).Logitech/HidEnumerator.cs- finds the HID collections Windows creates for Logitech devices and picks the vendor collection that carries HID++ (usage page0xFF43over Bluetooth LE,0xFF00via a receiver or classic Bluetooth).Logitech/HidppDevice.cs- writes long reports with overlapped I/O and matches replies, including HID++ error frames, with aHidD_SetOutputReportfallback.Logitech/LogiDevices.cs- device discovery, name/type, host list, and the switch itself.App/- tray icon and menu (TrayApplicationContext), settings window (SettingsForm), hotkeys and device-change notifications (Infrastructure), persisted settings, command line (Cli).
The protocol details were checked against Solaar,
logiops, the Linux hid-logitech-hidpp driver and Logitech's
published HID++ 2.0 feature documents.
The build, device enumeration, settings window, hotkey registration and command line have been exercised. The switch itself still has to be confirmed against the mouse on a machine where it is connected; see the open issues for that and for other known gaps.
MIT, see LICENSE.
