saimanish1/logitech-ipc-protocol
GitHub: saimanish1/logitech-ipc-protocol
逆向工程 Logi Options+ agent 的 IPC 协议,实现对罗技多主机设备的编程控制,绕过 macOS 蓝牙 HID 访问限制。
Stars: 4 | Forks: 0
# logitech-ipc-protocol
Logi Options+ agent IPC 协议的逆向工程文档。无需原始 HID 访问即可实现对罗技多主机设备的编程控制(主机切换、设备查询)。
该协议在此项目之前从未被公开记录。
## 问题
macOS 在内核层面阻止了对蓝牙输入设备的原始 HID 访问。没有任何权限、授权或手段可以绕过此限制。Logi Options+ agent 拥有 Apple 签名的授权 (`com.apple.security.device.bluetooth`),这赋予了它 Bluetooth HID 访问权限。本项目通过其 IPC 通道与该 agent 进行通信。
## 文件
| 文件 | 描述 |
|------|-------------|
| `logi-options-ipc-reverse-engineering.md` | 完整的逆向工程记录 |
| `software-kvm-setup.md` | 双向软件 KVM 设置指南 (Windows + Mac) |
| `switch_to_windows.py` | 通过 IPC 协议切换罗技设备和显示器输入 |
| `query_feature_index.py` | 发现罗技设备的 HID++ ChangeHost 功能索引 (Windows) |
| `query_agent_windows.py` | 通过命名管道查询 Windows 上的 agent |
| `config.ini` | UnifiedSwitch 配置示例 |
## 使用方法
```
python3 switch_to_windows.py 0 # Switch to host 0 (DisplayPort)
python3 switch_to_windows.py 1 # Switch to host 1 (HDMI)
python3 switch_to_windows.py --dry-run 0 # Show what would happen
```
需要运行 Logi Options+ 并安装 `m1ddc` (`brew install m1ddc`)。
## 协议
Agent 监听地址:
- **macOS**: Unix domain socket,位于 `/tmp/logitech_kiros_agent-`
- **Windows**: Named pipe,位于 `\\.\pipe\logitech_kiros_agent-`
两个平台使用相同的传输协议。二进制帧格式:
```
LE32(total_len) + BE32(proto_name_len) + "json" + BE32(msg_len) + JSON_message
```
将设备切换到不同的主机:
```
{
"msg_id": "1",
"verb": "SET",
"path": "/change_host//host",
"payload": {
"@type": "type.googleapis.com/logi.protocol.devices.ChangeHost",
"host": 0
}
}
```
Payload 是一个 `google.protobuf.Any` 字段,以带有 `@type` 注解的内联 JSON 形式序列化。Agent 使用严格的 protobuf JSON 解析器;未知字段会导致 `INVALID_MESSAGE_RECEIVED`。
请求使用 `msg_id` (snake_case)。响应使用 `msgId` (camelCase)。动词为字符串:`"GET"`, `"SET"`, `"SUBSCRIBE"`, `"BROADCAST"`。
查看 `logi-options-ipc-reverse-engineering.md` 获取完整的协议文档。
## IPC 错误处理
| 场景 | 发生情况 | 检测方法 |
|----------|-------------|-----------|
| Agent 未运行 | Socket/pipe 不存在 | `connect()` 抛出 `FileNotFoundError` 或 `ConnectionRefusedError` |
| Agent 在会话中重启 | 连接断开 | `send()` 抛出 `BrokenPipeError`;`recv()` 返回空 |
| 设备在另一台主机上 | `NO_SUCH_PATH` | 检查 `result.code` |
| 设备不可达 | 约 3 秒后 `TIMEOUT` | 检查 `result.code` |
| Payload 格式错误 | `INVALID_MESSAGE_RECEIVED` | 缺少 `@type` 或存在未知字段 |
| Socket hash 变更 | 旧路径失效 | 始终动态发现,切勿硬编码 |
| 重启后 Socket 过期 | `ConnectionRefusedError` | 短暂延迟后重试 |
| 并发客户端 | 正常工作 | Agent 支持多连接 |
对于长时间运行的自动化任务,在遇到 `BrokenPipeError` 时重新连接,并重新发现 socket/pipe 路径。
## Windows HID++ 注意事项
这些适用于直接发送 HID++ 命令(而非通过 Agent)的情况:
**HID++ collection 因设备而异。** MX Master 3S 在 COL02 上暴露 HID++。MX Keys S 使用 COL05。两者都使用 usage page `FF43:0202`。请通过以下方式验证:
```
Get-PnpDeviceProperty -InstanceId "" -KeyName DEVPKEY_Device_HardwareIds
# 查找 UP:FF43_U:0202
```
**功能索引因设备而异。** ChangeHost (0x1814) 在 MX Keys S 上位于索引 `0x0A`,但在 MX Mechanical 上是 `0x09`。在运行时通过 IRoot::GetFeature 查询:
```
Send: {0x11, 0x00, 0x00, 0x0D, 0x18, 0x14, ...} (20 bytes)
Read: response byte 4 = feature index
```
**设备重新配对会更改 HID 路径。** 从 Bolt 接收器切换到直连 BT LE 会完全改变路径。运行 `query_agent_windows.py` 以从 Agent 获取当前路径。
**BT LE GATT vendor collection 显示为 "Unknown"。** Windows 偶尔无法初始化 HID++ GATT 服务。设备工作正常,但 vendor command channel 处于失效状态。解决方法:在 Windows 设置中关闭/开启 Bluetooth。这是一个 Windows/固件问题。
## 测试版本
| 版本 | 状态 |
|---------|--------|
| Logi Options+ 2.0.840907 | 工作正常 |
传输协议和核心 API 路径 (`/devices/list`, `/change_host//host`) 一直保持稳定。设备重新配对会破坏 HID 路径和 collection 编号,但 IPC 协议本身不受影响。
## 免责声明
本项目仅用于**教育和研究目的**。它记录了一个未公开、不受支持的协议,Logitech 随时可能更改或移除该协议。对于因使用本代码或文档而导致的任何损坏、数据丢失、设备变砖或功能故障,作者不承担任何责任。使用风险自负。
本项目未隶属于或受 endorsement 于 Logitech。
## 许可证
[MIT](LICENSE)
标签:Homebrew安装, IPC协议, KVM切换, Logi Options+, Python, Unix Socket, 云资产清单, 协议分析, 命名管道, 外设管理, 多主机切换, 数字取证, 无后门, 权限提升, 硬件接口, 系统编程, 罗技Logitech, 自动化脚本, 蓝牙HID, 跨平台控制, 输入设备, 逆向工具, 逆向工程