brianpht/librepods-rs

GitHub: brianpht/librepods-rs

纯 Rust 实现的 Apple Accessory Protocol,让 Linux 用户无需 Apple 设备即可完整使用 AirPods 的降噪控制、电池监控、入耳检测等功能,同时为蓝牙协议安全研究提供了可嵌入的开源参考。

Stars: 0 | Forks: 0

# LIBREPODS-RS Apple Accessory Protocol (AAP) 的纯 Rust 实现,用于 AirPods™,具有跨平台核心和特定平台的 I/O。 ## 概述 `librepods-rs` 是一个开源工具,可让您在 Linux 上将 AirPods 作为一等公民使用。它通过蓝牙 L2CAP 传输 AAP 协议,以读取电池电量、控制降噪、检测入耳手势、自动播放/暂停媒体等。无需 Apple 设备。 这是一个受 [LibrePods](https://github.com/kavishdevar/librepods) (Kotlin/C++) 启发的洁净室 Rust 重写,专为可嵌入性、可移植性和严格的 crate 边界分离而设计。 ## 功能 - **电池监控**:实时左/右/耳机盒电池电量和充电状态 - **噪音控制**:在关闭、ANC、通透模式和自适应模式之间切换 - **入耳检测**:戴上或摘下 AirPods 时自动播放/暂停 - **对话感知**:在音频播放期间监控和切换 CA 状态 - **长按配置**:自定义按住耳机柄时循环切换的噪音控制模式 - **重命名**:通过 AAP 更改您的 AirPods 设备名称 - **BLE 广播解码**:无需配对即可扫描附近的 AirPods。查看型号、电池、盒盖状态 - **加密电池**:对来自 BLE 广播的高分辨率电池数据进行 AES-128 解密 - **头部追踪**:接收原始的空间音频头部追踪传感器数据 - **设备元数据**:读取设备名称、型号、制造商 - **媒体控制**:自动 A2DP 激活,PipeWire (`wpctl`) / PulseAudio (`pactl`) 后端检测 - **跨平台核心**:`librepods-core` 是纯 Rust,无操作系统依赖,随时可嵌入到未来的平台目标中 ## 设备兼容性 | 型号 | 状态 | 备注 | |---|---|---| | AirPods Pro 2 (USB-C) | ✅ 已测试 | 主要开发设备 | | AirPods Pro 2 (Lightning) | ✅ 已测试 | 与 USB-C 版本协议相同 | | AirPods Pro | ⚠️ 预期支持 | 同属相同协议族,尚未验证 | | AirPods Max (Lightning) | ⚠️ 预期支持 | 同属相同协议族,尚未验证 | | AirPods Max (USB-C) | ⚠️ 预期支持 | 同属相同协议族,尚未验证 | | AirPods (4th gen, ANC) | ⚠️ 预期支持 | 基本功能应可正常使用 | | AirPods (4th gen) | ⚠️ 预期支持 | 基本功能(电池、入耳检测) | | AirPods (3rd gen) | ⚠️ 预期支持 | 基本功能(电池、入耳检测) | | AirPods (2nd gen) | ⚠️ 预期支持 | 基本功能(电池、入耳检测) | | AirPods (1st gen) | ⚠️ 预期支持 | 基本功能(电池、入耳检测) | AAP 协议在所有 AirPods 型号中保持一致(基于对 macOS 蓝牙协议栈的分析)。噪音控制、自适应通透模式和对话感知仅限于在硬件上支持它们的型号使用。 ## 架构 ``` ┌──────────────────────────────────────────────────────────┐ │ librepods-cli CLI daemon, state machine, │ │ clap, env_logger │ ├──────────────────────────────────────────────────────────┤ │ librepods-linux L2CAP socket (nix, libc), │ │ BlueZ D-Bus (zbus, tokio), │ │ BLE scan (btleplug), │ │ Media (wpctl / pactl / playerctl)│ ├──────────────────────────────────────────────────────────┤ │ librepods-core AAP parser, packet builder, │ │ device state, BLE ad decoder, │ │ transport traits │ │ ⚠ NO platform I/O, pure Rust │ └──────────────────────────────────────────────────────────┘ ``` | Crate | 允许的依赖 | 用途 | |---|---|---| | `librepods-core` | `serde`, `thiserror`, `log`, `aes` | 协议引擎、设备状态、BLE 解析 | | `librepods-linux` | `nix`, `zbus`, `btleplug`, `tokio`, `libc` | Linux 蓝牙 + 媒体 I/O | | `librepods-cli` | `clap`, `env_logger`, `tokio` | 无头守护进程 | ## 前置条件 (Ubuntu / Debian) ### 构建依赖 ``` sudo apt update sudo apt install -y build-essential pkg-config curl \ libdbus-1-dev libudev-dev ``` | 软件包 | 用途 | |---|---| | `build-essential` | 用于原生 crate 构建脚本的 C 链接器 | | `pkg-config` | 在编译时查找 `libdbus` 和 `libudev` | | `libdbus-1-dev` | D-Bus 头文件,`zbus` (BlueZ 监视器) 和 `btleplug` (BLE 扫描) 必需 | | `libudev-dev` | udev 头文件,`btleplug` 枚举设备时必需 | ### Rust 工具链 ``` curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh source "$HOME/.cargo/env" ``` ### 蓝牙协议栈 ``` sudo apt install -y bluetooth bluez sudo systemctl enable --now bluetooth ``` 验证适配器是否已启动: ``` bluetoothctl show # should print adapter info ``` ### 音频与媒体(可选,用于自动播放/暂停) Ubuntu 22.04+ 默认搭载 PipeWire。安装守护进程在运行时使用的 CLI 工具: ``` # PipeWire (推荐,Ubuntu 22.04+) sudo apt install -y wireplumber # 或 PulseAudio (较旧的 Ubuntu) sudo apt install -y pulseaudio-utils # 播放控制 (佩戴检测播放/暂停) sudo apt install -y playerctl ``` ### TL;DR 一键命令 ``` sudo apt install -y build-essential pkg-config libdbus-1-dev libudev-dev \ bluetooth bluez wireplumber playerctl \ && curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh ``` ## 快速入门 ### 1. 配对您的 AirPods ``` bluetoothctl # scan on # (等待 "AirPods" 出现,记下 MAC 地址) # pair AA:BB:CC:DD:EE:FF # trust AA:BB:CC:DD:EE:FF # connect AA:BB:CC:DD:EE:FF # exit ``` ### 2. 构建并运行 ``` cargo build --release -p librepods-cli # Bluetooth sockets 需要 CAP_NET_RAW sudo setcap cap_net_raw,cap_net_admin+eip ./target/release/librepods-cli # 自动检测已连接的 AirPods RUST_LOG=info ./target/release/librepods-cli # 或直接指定地址 RUST_LOG=info ./target/release/librepods-cli --address AA:BB:CC:DD:EE:FF ``` ### 3. 扫描附近的 AirPods(无需配对) ``` ./target/release/librepods-cli --scan ``` 输出示例: ``` ┌───────────────────────────────────────────── │ 🎧 AirPods found! │ Model: AirPodsPro2Usbc │ BLE address: XX:XX:XX:XX:XX:XX (random) │ RSSI: -42 dBm │ Paired: yes (to another device) │ Left: 80% │ Right: 90% ⚡ │ Case: 40% │ Lid: Open │ Connection: Idle └───────────────────────────────────────────── ``` ## CLI 选项 ``` Usage: librepods-cli [OPTIONS] Options: -a, --address
Bluetooth address (e.g. "AA:BB:CC:DD:EE:FF") --retries Maximum connection retry attempts [default: 3] -s, --scan Scan for nearby AirPods via BLE advertisements --no-media Disable media control (no auto play/pause) -h, --help Print help ``` ## VendorID 配置 某些 AirPods 功能(助听器、自定义通透模式、多设备连接)仅在连接的设备标识为 Apple 设备时启用。 在 Linux 上,您可以通过编辑 `/etc/bluetooth/main.conf` 来更改蓝牙 VendorID: ``` # 将此行添加到 [General] 部分 DeviceID = bluetooth:004C:0000:0000 ``` 然后重启蓝牙服务: ``` sudo systemctl restart bluetooth ``` ## 工作原理 ### AAP 数据包布局 L2CAP 链路上有三个数据包族。前两个字节用于区分它们。 **标准数据包:** ``` block-beta columns 7 a["04"]:1 b["00"]:1 c["04"]:1 d["00"]:1 e["opcode"]:1 f["00"]:1 g["data …"]:1 style a fill:#2e3440,color:#d8dee9 style b fill:#2e3440,color:#d8dee9 style c fill:#2e3440,color:#d8dee9 style d fill:#2e3440,color:#d8dee9 style e fill:#5e81ac,color:#eceff4 style f fill:#5e81ac,color:#eceff4 style g fill:#a3be8c,color:#2e3440 ``` **握手**(由我们发送,16 字节): ``` block-beta columns 9 a["00"]:1 b["00"]:1 c["04"]:1 d["00"]:1 e["01"]:1 f["00"]:1 g["02"]:1 h["00"]:1 i["00 … pad"]:1 style a fill:#4c566a,color:#d8dee9 style b fill:#4c566a,color:#d8dee9 style c fill:#4c566a,color:#d8dee9 style d fill:#4c566a,color:#d8dee9 style e fill:#88c0d0,color:#2e3440 style f fill:#88c0d0,color:#2e3440 style g fill:#88c0d0,color:#2e3440 style h fill:#88c0d0,color:#2e3440 style i fill:#d8dee9,color:#4c566a ``` **握手 ACK**(来自 AirPods): ``` block-beta columns 5 a["01"]:1 b["00"]:1 c["04"]:1 d["00"]:1 e["…"]:1 style a fill:#4c566a,color:#d8dee9 style b fill:#4c566a,color:#d8dee9 style c fill:#4c566a,color:#d8dee9 style d fill:#4c566a,color:#d8dee9 style e fill:#d8dee9,color:#4c566a ``` **功能 ACK**(来自 AirPods,标准头部,操作码 `0x2B`): ``` block-beta columns 7 a["04"]:1 b["00"]:1 c["04"]:1 d["00"]:1 e["2B"]:1 f["00"]:1 g["…"]:1 style a fill:#2e3440,color:#d8dee9 style b fill:#2e3440,color:#d8dee9 style c fill:#2e3440,color:#d8dee9 style d fill:#2e3440,color:#d8dee9 style e fill:#5e81ac,color:#eceff4 style f fill:#5e81ac,color:#eceff4 style g fill:#d8dee9,color:#4c566a ``` **控制命令**(标准数据的子类型,固定 11 字节): ``` block-beta columns 11 a["04"]:1 b["00"]:1 c["04"]:1 d["00"]:1 e["09"]:1 f["00"]:1 g["id"]:1 h["d1"]:1 i["d2"]:1 j["d3"]:1 k["d4"]:1 style a fill:#2e3440,color:#d8dee9 style b fill:#2e3440,color:#d8dee9 style c fill:#2e3440,color:#d8dee9 style d fill:#2e3440,color:#d8dee9 style e fill:#5e81ac,color:#eceff4 style f fill:#5e81ac,color:#eceff4 style g fill:#81a1c1,color:#2e3440 style h fill:#a3be8c,color:#2e3440 style i fill:#a3be8c,color:#2e3440 style j fill:#a3be8c,color:#2e3440 style k fill:#a3be8c,color:#2e3440 ``` ### 握手序列 连接 AirPods 需要严格的三步握手: ``` sequenceDiagram participant C as Client (us) participant A as AirPods C->>A: HANDSHAKE (00 00 04 00 …) A->>C: Handshake ACK (01 00 04 00 …) C->>A: SET_SPECIFIC_FEATURES (04 00 04 00 4D 00 …) A->>C: Features ACK (04 00 04 00 2B 00 …) C->>A: REQUEST_NOTIFICATIONS (04 00 04 00 0F 00 …) loop Receive Loop A->>C: Battery / Ear / Noise / Metadata / … end ``` 握手完成后,AirPods 将持续推送电池、入耳检测、噪音控制和其他通知。 ### 控制命令 控制命令使用固定的 11 字节布局: ``` use librepods_core::protocol::control_command::ControlCommand; // Set noise cancellation mode ControlCommand::create(0x0D, &[0x02, 0x00, 0x00, 0x00]) // Enable conversational awareness ControlCommand::enabled(0x28) // Disable conversational awareness ControlCommand::disabled(0x28) ``` ### BLE 广播解析 无需连接即可解码 Apple 近距离配对消息: ``` use librepods_core::device::ble_advert::parse_advertisement; // Raw Apple manufacturer data (company ID 0x004C already stripped) let data: &[u8] = &[0x07, 0x19, 0x01, 0x24, 0x20, /* ... */]; if let Some(ad) = parse_advertisement(data) { println!("Model: {:?}", ad.model); println!("Left: {:?}%", ad.left_battery); println!("Right: {:?}%", ad.right_battery); println!("Case: {:?}%", ad.case_battery); } ``` ## 构建与测试 ``` # 构建所有 crates cargo build # 运行所有测试 cargo test # 仅核心 (必须在任何 target 上通过) cargo test -p librepods-core ``` ## 故障排除 ### 连接时 `Permission denied` 蓝牙 L2CAP 套接字需要 `CAP_NET_RAW` 权限。可以: ``` # 选项 A: 在二进制文件上设置 capabilities (推荐) sudo setcap cap_net_raw,cap_net_admin+eip ./target/release/librepods-cli # 选项 B: 使用 sudo 运行 sudo RUST_LOG=info ./target/release/librepods-cli ``` ### `不支持 AF_BLUETOOTH` 未加载蓝牙内核模块: ``` sudo modprobe bluetooth sudo systemctl restart bluetooth ``` ### `No BLE adapter found`(使用 `--scan` 时) ``` # 检查 adapter 是否存在 hciconfig -a # 如果已关闭 sudo hciconfig hci0 up # 如果没有显示 adapter,请检查 USB 或验证 driver lsusb | grep -i bluetooth dmesg | grep -i bluetooth ``` ### `未找到音频 backend` ``` # 检查正在运行的内容 pactl info 2>/dev/null && echo "PulseAudio OK" || echo "No PulseAudio" wpctl status 2>/dev/null && echo "WirePlumber OK" || echo "No WirePlumber" # 安装缺失的内容 sudo apt install -y wireplumber # PipeWire # 或 sudo apt install -y pulseaudio-utils # PulseAudio ``` ### AirPods 已连接但未收到数据 确保已注册 AirPods 服务 UUID。尝试重新配对: ``` bluetoothctl # remove AA:BB:CC:DD:EE:FF # scan on # pair AA:BB:CC:DD:EE:FF # trust AA:BB:CC:DD:EE:FF # connect AA:BB:CC:DD:EE:FF ``` ## 开发 ``` # 使用 debug 日志记录运行 sudo RUST_LOG=debug cargo run -p librepods-cli -- --address AA:BB:CC:DD:EE:FF # 或设置一次 capabilities 并在没有 sudo 的情况下运行 sudo setcap cap_net_raw,cap_net_admin+eip ./target/debug/librepods-cli RUST_LOG=debug ./target/debug/librepods-cli --address AA:BB:CC:DD:EE:FF ``` ## 致谢 本项目是一个 Rust 重写版本,基于 [@kavishdevar](https://github.com/kavishdevar) 的 [LibrePods](https://github.com/kavishdevar/librepods) 项目的研究和逆向工程工作。 特别感谢: - [@tyalie](https://github.com/tyalie):首次公开 AAP 协议文档 ([AAP-Protocol-Definition](https://github.com/tyalie/AAP-Protocol-Defintion)) - [@rithvikvibhu](https://github.com/rithvikvibhu) 和 Lagrange Point 社区:助听器功能研究 - [@timgromeyer](https://github.com/timgromeyer):LibrePods Linux 应用的首个版本 - 所有解码该协议的 [LibrePods 贡献者](https://github.com/kavishdevar/librepods/graphs/contributors) *AirPods 是 Apple Inc. 的商标,已在美国和其他国家及地区注册。所有商标、标志和品牌名称均归其各自所有者所有。本项目不隶属于、未受其认可或赞助 Apple Inc。*
标签:AAP, AirPods, Apple Accessory Protocol, BLE, L2CAP, Linux音频, PipeWire, PulseAudio, Rust, Rust重写, 可视化界面, 外设驱动, 头追踪, 嵌入性, 开源, 开源硬件适配, 电池监控, 空间音频, 网络流量审计, 耳机控制, 蓝牙, 设备集成, 通知系统, 降噪, 音频处理