Logi Options+ 代理 IPC 协议的逆向工程文档。支持在 macOS 和 Windows 上通过程序控制 Logitech 多主机设备(主机切换、设备查询),无需原始 HID 访问。
此协议此前从未被公开记录过。
macOS 在内核层面禁止对蓝牙输入设备的原始 HID 访问。没有权限、授权或黑客手段可以绕过。Logi Options+ 代理拥有苹果签名的授权(com.apple.security.device.bluetooth),从而获得蓝牙 HID 访问权限。本项目通过其 IPC 通道与代理通信。
| 文件 | 描述 |
|---|---|
logi-options-ipc-reverse-engineering.md | 完整的逆向工程记录 |
software-kvm-setup.md | 双向软件 KVM 设置指南(Windows + Mac) |
switch_to_windows.py | Mac 端脚本,通过 Unix 套接字 IPC 切换 Logitech 设备和显示器输入 |
api-reference.md | 代理 API 参考:可用的端点、protobuf 类型、设备能力 |
kvm.ahk | AutoHotkey v2 脚本:Win+1/2/3 热键调用 kvm_daemon_windows.py --switch(在系统托盘中运行) |
kvm_daemon_windows.py | Windows 设备切换(通过命名管道)、显示器切换(通过 DDC/CI) |
kvm_config.ini | Windows 配置(热键、显示器输入) |
query_feature_index.py | 发现 Logitech 设备的 HID++ ChangeHost 特性索引(Windows) |
query_agent_windows.py | 通过命名管道查询 Windows 上的代理 |
config.ini | 旧的 UnifiedSwitch 配置(已被 kvm_daemon_windows.py 取代) |
python3 switch_to_windows.py 0 # 切换到主机 0(DisplayPort)
python3 switch_to_windows.py 1 # 切换到主机 1(HDMI)
python3 switch_to_windows.py --dry-run 0 # 显示将要执行的操作
需要运行 Logi Options+ 并安装 m1ddc(brew install m1ddc)。
# 启动 AHK 热键监听器(在系统托盘中运行,无控制台窗口)
# 需要 AutoHotkey v2:winget install AutoHotkey.AutoHotkey
start kvm.ahk
# 或直接从命令行切换
python kvm_daemon_windows.py --switch 1
# 显示已发现的设备和已配置的热键,不进行切换
python kvm_daemon_windows.py --dry-run
需要运行 Logi Options+。安装依赖:pip install pywin32。
AHK 脚本监听 Win+1/2/3 并分别调用 kvm_daemon_windows.py --switch N。Python 脚本自动从代理发现设备(无需硬编码设备 ID 或 HID 路径)。编辑 kvm_config.ini 配置热键和显示器 DDC/CI 输入值。
代理监听在:
/tmp/logitech_kiros_agent-<hash>\\.\pipe\logitech_kiros_agent-<hash>两个平台使用相同的线路协议。二进制帧格式:
LE32(total_len) + BE32(proto_name_len) + "json" + BE32(msg_len) + JSON_message
将设备切换到另一主机:
{
"msg_id": "1",
"verb": "SET",
"path": "/change_host/<device_id>/host",
"payload": {
"@type": "type.googleapis.com/logi.protocol.devices.ChangeHost",
"host": 0
}
}
有效载荷是一个 google.protobuf.Any 字段,以内联 JSON 序列化并带有 @type 注解。代理使用严格的 protobuf JSON 解析器;未知字段会导致 INVALID_MESSAGE_RECEIVED。
请求使用 msg_id(下划线命名法)。响应使用 msgId(驼峰命名法)。动词是字符串:"GET"、"SET"、"SUBSCRIBE"、"BROADCAST"。
完整协议文档见 logi-options-ipc-reverse-engineering.md。
对于长时间运行的自动化,在 BrokenPipeError 时重新连接,并重新发现套接字/管道路径。
以下适用于直接发送 HID++ 命令而非通过代理的情况。
kvm_daemon_windows.py通过代理的命名管道避免了所有这些麻烦。
HID++ 集合因设备而异。 MX Master 3S 在 COL02 上暴露 HID++。MX Keys S 使用 COL05。两者都使用用法页面 FF43:0202。通过以下命令验证:
Get-PnpDeviceProperty -InstanceId "<instance_id>" -KeyName DEVPKEY_Device_HardwareIds
# 查找 UP:FF43_U:0202
特性索引因设备而异。 ChangeHost (0x1814) 在 MX Keys S 上的索引为 0x0A,但在 MX Mechanical 上为 0x09。运行时通过 IRoot::GetFeature 查询:
发送: {0x11, 0x00, 0x00, 0x0D, 0x18, 0x14, ...} (20 字节)
读取: 响应字节 4 = 特性索引
设备重新配对会改变 HID 路径。 从 Bolt 接收器切换到直接 BT LE 会完全改变路径。运行 query_agent_windows.py 从代理获取当前路径。
BT LE GATT 供应商集合显示为“未知”。 Windows 偶尔无法初始化 HID++ GATT 服务。设备正常工作但供应商命令通道失效。解决方法:在 Windows 设置中切换蓝牙关闭/开启。这是 Windows/固件问题。
| 版本 | 状态 |
|---|---|
| Logi Options+ 2.0.840907 | 正常工作(macOS Tahoe, Windows 11) |
线路协议和核心 API 路径(/devices/list、/change_host/<id>/host)保持稳定。设备重新配对会破坏 HID 路径和集合编号,但 IPC 协议本身未受影响。
本项目仅用于教育和研究目的。它记录了一个未公开、不受支持的协议,Logitech 可随时更改或移除。作者不对因使用此代码或文档造成的任何损坏、数据丢失、设备损坏或功能失效负责。使用风险自负。
本项目与 Logitech 无关,也未获得 Logitech 的认可。
| 场景 | 发生情况 | 检测方法 |
|---|
| 代理未运行 | 套接字/管道不存在 | connect() 引发 FileNotFoundError 或 ConnectionRefusedError |
| 代理在会话中重启 | 连接中断 | send() 引发 BrokenPipeError;recv() 返回空值 |
| 设备在其他主机上 | NO_SUCH_PATH | 检查 result.code |
| 设备不可达 | 约 3 秒后超时 TIMEOUT | 检查 result.code |
| 格式错误的有效载荷 | INVALID_MESSAGE_RECEIVED | 缺少 @type 或存在未知字段 |
| 套接字哈希值变化 | 旧路径消失 | 始终动态发现,切勿硬编码 |
| 重启后残留的套接字 | ConnectionRefusedError | 短暂延迟后重试 |
| 并发客户端 | 正常工作 | 代理处理多个连接 |