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重写, 可视化界面, 外设驱动, 头追踪, 嵌入性, 开源, 开源硬件适配, 电池监控, 空间音频, 网络流量审计, 耳机控制, 蓝牙, 设备集成, 通知系统, 降噪, 音频处理