# joycontrol-rs **Repository Path**: luzhihaoTestingLab/joycontrol-rs ## Basic Information - **Project Name**: joycontrol-rs - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-09-02 - **Last Updated**: 2026-09-02 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # joycontrol-rs joycontrol 的 Rust 移植版:通过蓝牙模拟 Nintendo Switch 手柄(Joy-Con L/R、Pro Controller)。 > 这是**框架**,核心算法细节以 `TODO(留给你的核心细节)` 标注,建议先通读 > [Nintendo_Switch_Reverse_Engineering](https://github.com/dekuNukem/Nintendo_Switch_Reverse_Engineering) > 的 `bluetooth_hid_notes.md` 再动手。 ## 模块结构(与 Python 版对应) | Rust 模块 | Python 版 | 状态 | |---|---|---| | `controller.rs` | `controller.py` | ✅ 完成 | | `report.rs` | `report.py` | 🟡 框架(含 1 个 TODO:0x04 按键时长打包) | | `controller_state.rs` | `controller_state.py` | 🟡 框架(按钮位图 / 12-bit 摇杆打包 / 校准解析,含多个 TODO) | | `memory.rs` | `memory.py` | 🟡 框架(校准接入为 TODO) | | `protocol.rs` | `protocol.py` | 🟡 框架(持续发送模式 / 配对时长 / 就绪事件为 TODO) | | `transport.rs` | `transport.py` | 🟡 框架(真实 L2CAP socket 为 TODO,目前 TcpStream 占位) | | `server.rs` | `server.py` | ⬜ 未开始(SDP/DBus 广播,Linux only) | | `cli.rs` | `command_line_interface.py` | ⬜ 未开始 | ## 构建与测试 ```bash cd joycontrol-rs cargo test # 运行已实现的单元测试 cargo check # 只检查类型 ``` > **注意(Windows 安全软件)**:本仓库的 `target` 目录曾被本机安全软件拦截, > 导致 cargo build-script 报 `0xc0000022`。如果你的机器也遇到,请把 > `joycontrol-rs/target`(及 `%TEMP%\jc_rs_target`)加入杀软白名单后再构建。 > 框架核心模块(controller/report/controller_state/memory)不依赖外部 crate, > 可以用 `rustc --edition 2021 --crate-type lib .check_core.rs` 单独校验。 ## 核心算法细节(留给你的 TODO) 这些是移植时“最有趣”的部分,已把 Python 参考逻辑写在对应函数注释里: 1. **按钮位图**(`controller_state.rs`):按钮名 -> 3 字节位图。 不同手柄的按钮落在不同字节/位,注意 SL/SR 与 L/R 的语义差异。 2. **摇杆 12-bit 打包**(`controller_state.rs`):`(h, v)` 两个 12-bit 值 交错塞进 3 字节。这是 joycon 协议里最精巧的位操作。 3. **校准数据解析**(`controller_state.rs`):9 字节解出 6 个 12-bit 值; **左/右摇杆的字段顺序不同**(这是最大的坑)。 4. **配对按键时长**(`report.rs` + `protocol.rs`):0x04 子命令应答, 配对时让 Switch 分配玩家编号的关键数据。 5. **持续输入报告模式**(`protocol.rs`):0x30/0x31 报告 ~66Hz 持续发送, 期间还要响应子命令(Python 用 transport reader 切换实现)。 6. **真实 L2CAP 传输**(`transport.rs`):Linux 下用 `libc` 创建 `AF_BLUETOOTH` socket,经 `tokio::io::unix::AsyncFd` 异步化。 7. **SDP / DBus 广播**(`server.rs`,未开始):注册 HID profile、 设置设备名/class、等待 Switch 配对,对应 Python 的 `device.py` + `server.py`。 ## 协议速览 - Switch -> 手柄:0xA2 输出报告(control 通道 PSM 17),其中 0x01 子命令需要应答 - 手柄 -> Switch:0xA1 输入报告(interrupt 通道 PSM 19) - `0x21` 子命令应答(51 字节) - `0x30` 含 IMU(36 字节 IMU) - `0x31` 含 NFC - 报告头部:`[0xA1, report_id, timer, 0x8E, buttons(3), l_stick(3), r_stick(3), rumble(1), ack, reply_sub, data...]`