mihaits/rtl8852bd-bt-linux
GitHub: mihaits/rtl8852bd-bt-linux
一个通过重新打包 Realtek 专有固件并提供 DKMS 补丁模块的方式,让 RTL8852BD 蓝牙芯片在 Linux 上正常工作的驱动修复项目。
Stars: 0 | Forks: 0
# 适用于 Linux 的 RTL8852BD 蓝牙驱动
使 Realtek **RTL8852BD** 蓝牙模块(USB ID 为 `0bda:b853`)能够在 Linux 上正常工作。
这款芯片被广泛应用于 2024–2025 年笔记本电脑中常见的 RTL8852BE Wi-Fi/蓝牙 combo 卡中。
开箱即用的是 Wi-Fi 功能;而蓝牙功能在任何当前版本的 kernel 上均无法直接使用。
## 这适用于我的机器吗?
需要进行两项检查 —— **两者**必须同时满足:
```
lsusb | grep -i 0bda:b853 # the Bluetooth USB adapter
dmesg | grep -i "RTL: rom_version" # must say version=3
```
`0bda:b853` 涵盖了整个 RTL8852BE 家族,但此修复专门针对报告为 **`rom_version=3`**(即“8852BD”)的特定芯片版本。如果您设备报告的版本号不同,说明它是不同的芯片版本,此修复并不适用您的情况。
`0bda:b853` / RTL8852BE combo 常见于 2024–2025 年的笔记本电脑中。已知出货包含该模块的产品系列有:**Lenovo** LOQ / IdeaPad / Legion / ThinkBook,**HP** Victus / 15-fc,**Acer** Nitro / Aspire,以及 **Asus** TUF / Vivobook。这并非兼容性保证 —— 同一型号在不同批次中可能会搭载 Intel 或 MediaTek 的模块,且并非所有的 8852BE 都是 `rom_version=3` 版本。上述的两条命令是唯一可靠的检测方法。
## 问题所在
`btrtl` 能够检测到该芯片,但随后静默失败:
```
Bluetooth: hci0: RTL: examining hci_ver=0b hci_rev=000b lmp_ver=0b lmp_subver=8852
Bluetooth: hci0: RTL: rom_version status=0 version=3
Bluetooth: hci0: RTL: loading rtl_bt/rtl8852bu_fw.bin
Bluetooth: hci0: RTL: didn't find patch for chip id 3 <-- the giveaway
```
并且 `hci0` 始终无法开启:
```
$ hciconfig hci0 up
Can't init device hci0: Invalid argument (22)
$ hciconfig -a
hci0: BD Address: 00:00:00:00:00:00
```
此版本的芯片报告 `rom_version=3`,因此需要带有 **eco 4** 的 firmware 补丁。`linux-firmware` 中的 `rtl8852bu_fw.bin` 仅包含 eco 1 和 2,因此解析器提取到零字节并返回 `-ENODATA``。这是一个 firmware 内容缺失的问题,而不是 kernel 的 bug —— 目前没有任何主线 kernel 或 `linux-firmware` 版本为这一芯片版本提供 eco-4 支持。
实际上,eco-4 firmware 是存在的,就在 Realtek 的 Windows 驱动程序中。本仓库对其进行了重新打包,并添加了该芯片所需的下载路径。
## 环境要求
- `dkms`、`build-essential`、`linux-headers-$(uname -r)`、`python3`
- `innoextract` —— 仅当您需要让安装程序处理厂商提供的 `.exe` 文件时需要
在基于 apt 的系统上,`install.sh` 会自动安装缺失的软件包。
### Kernel 兼容性
本项目提供了一个**经过补丁修改的 `btrtl` 模块完整副本**,并通过 DKMS 针对您正在运行的 kernel 进行编译,以替换系统内置的 `btrtl`。在将其安装在未经测试的 kernel 上之前,有些影响值得您了解:
- **新代码**(即 eco-4 下载功能)仅使用长期稳定的 kernel API(`request_firmware`、`kmalloc`、`__hci_cmd_sync`、`put_unaligned_le32`)—— 不包含任何容易因版本变动而出问题的部分。
- **基础** 的 `btrtl.c` 是 **kernel 6.8** 版本中该模块的快照。由于它会替换内置模块,其导出的符号必须与您 kernel 中已有的 `btusb` 保持 ABI 兼容。如果某个 kernel 更改了内部的 `btrtl`↔`btusb` 接口,此副本可能会编译失败,或者虽然编译成功但拒绝绑定(符号版本/CRC 不匹配)—— 在这种情况下,蓝牙将无法启动,您应该执行 `./uninstall.sh`。
- 任何树外的 DKMS 模块都不会经过签名,因此在 **Secure Boot** 下将无法加载,除非您注册了 MOK。请禁用 Secure Boot 或自行对模块进行签名。
**已测试环境:** Lenovo LOQ 15ARP10E,Ubuntu 22.04.5 HWE,kernel **6.8.0** (x86_64);该模块在 6.8 系列的其他小版本中也能顺利编译。其他 kernel 系列**未经测试** —— 6.8 LTS 系列(Ubuntu 22.04.5 / 24.04)是已知兼容的目标环境。在其他环境中尝试也是安全的:编译或绑定失败可以通过 `./uninstall.sh` 撤销,并恢复原生的 `btrtl`。
## 第 1 步 — 获取 firmware
**此处不包含任何 firmware。** 它是 Realtek 的专有代码,无法重新分发。您需要以下这一个文件:
```
rtl8852bd_mp_chip_new.dat
```
这个 `.dat` 文件是适用于 **8852BD** 芯片的 Realtek firmware,与笔记本电脑型号无关 —— 任何厂商为 `0bda:b853` 适配器提供的 Realtek 蓝牙驱动包中都包含一份可用副本(Dell、HP、Asus 或 Realtek 官方驱动均有提供)。
前往您的设备厂商支持网站,下载您对应型号的**蓝牙驱动程序** —— 以 Lenovo 为例:*Support → 您的型号 → Drivers & Software → Bluetooth*。您下载到的是一个 **Windows 安装程序 `.exe`**,通常名称晦涩,例如 `53lo030fqufmvnj0.exe`。**请勿运行或重命名该文件** —— 只需记住其下载路径(例如 `~/Downloads/53lo030fqufmvnj0.exe`)。
您**不需要**手动提取任何内容:`install.sh` 会直接读取该 `.exe`(它会在后台替您运行 `innoextract`)。请直接跳到第 2 步。
可选:自行提取
该 `.exe` 是一个 Inno Setup 安装程序,因此可以直接在 Linux 上进行解包 —— 无需 Windows 环境:
```
innoextract -s -d extracted ~/Downloads/53lo030fqufmvnj0.exe
find extracted -name 'rtl8852bd_mp_chip_new.dat'
```
完整性检查 —— 该文件的开头应为 ASCII magic `BTNIC003`:
```
head -c 8 path/to/rtl8852bd_mp_chip_new.dat # -> BTNIC003
```
然后,您可以将该 `.dat` 文件(而不是 `.exe`)传递给 `install.sh`。
## 第 2 步 — 安装
```
git clone https://github.com/mihaits/rtl8852bd-bt-linux
cd rtl8852bd-bt-linux
```
`install.sh` 接受**一个参数** —— 即您下载的驱动程序的路径。
将其指向厂商的 `.exe` 文件,它会自动提取 firmware:
```
sudo ./install.sh ~/Downloads/53lo030fqufmvnj0.exe
```
(请替换为您实际下载的文件名)。它会根据扩展名决定后续操作:`.exe` 会通过 `innoextract` 自动解包,其他所有格式都会被视为已提取的 `.dat` 文件:
```
sudo ./install.sh /path/to/rtl8852bd_mp_chip_new.dat
```
无论采取哪种方式,安装程序随后都会编译 firmware,安装 DKMS 模块,清除可能存在的陈旧 rfkill 屏蔽,重新加载驱动程序,并验证结果。
## 验证
```
$ dmesg | grep -i rtl
Bluetooth: hci0: RTL: RTL8852BD: using multi-record eco4 download
Bluetooth: hci0: RTL: RTL8852BD eco4 firmware loaded (3 records)
$ hciconfig hci0
hci0: Type: Primary Bus: USB
BD Address: XX:XX:XX:XX:XX:XX
UP RUNNING
$ bluetoothctl scan on # should list nearby devices
```
确认补丁是否真正在运行 —— 一旦补丁生效,控制器会报告不同的 firmware 版本:
```
sudo hcitool -i hci0 cmd 0x04 0x01
```
| | HCI 版本 | fw 版本 |
|---|---|---|
| ROM(异常) | `0x0B` (BT 5.2) | `0x000B8852` |
| 已打补丁(正常) | `0x0D` (BT 5.4) | `0x3C91950E` |
## 故障排除
**重启后蓝牙关闭 / `hci0` 显示为 `DOWN`,但 `dmesg` 看起来很干净。**
这几乎总是由于陈旧的 rfkill 屏蔽导致的,而不是 firmware 问题:
```
rfkill list bluetooth
sudo rfkill unblock bluetooth
```
`systemd-rfkill` 会在每次启动时恢复*已保存的*屏蔽状态,因此如果该模块在损坏期间被禁用,该屏蔽状态在修复后依然会保留。`install.sh` 会清除已保存的状态;如果屏蔽再次出现,请在您的桌面设置中启用一次蓝牙,以便在关机时保存正确的状态。
**`hciconfig` 没有任何显示。** 请检查设备是否存在并已绑定:
`lsusb | grep 0bda:b853` 和 `dmesg | grep -i bluetooth`。
**模块未能编译。** 请确保 `linux-headers-$(uname -r)` 与您当前运行的 kernel 相匹配,然后运行 `sudo dkms build -m rtl8852bd-bt -v 1.0` 查看错误。
**安装后依然使用的是 ROM firmware**(即上述的 `0x000B8852`)。说明下载过程已执行,但补丁未能启动 —— 请检查 `dmesg` 中是否有 `eco4` 相关错误,并确认您的 `.dat` 文件确实适用于 **8852BD**,而不是 `rtl8852b_mp_chip_new.dat` 或 `rtl8852c_mp_chip_new.dat`。
## Kernel 更新
DKMS 会在 kernel 升级时自动重新编译该模块。您无需进行任何操作。
## 卸载
```
sudo ./uninstall.sh
```
## 工作原理
`btrtl` 通常会解析 EPATCH/`RTBTCore` 格式的 firmware,并选择 eco 匹配 `rom_version + 1` 的代码片段。但在 `linux-firmware` 中的任何地方都找不到适用于此芯片的 eco-4 代码片段,因此该执行路径走不通。
Realtek 的 Windows 驱动程序并未针对此部件使用 EPATCH。它将补丁作为三个独立的记录放在一个 `BTNIC003` 容器中,每个记录都有各自的 RAM 加载地址,并通过厂商专有的下载协议进行推送:
| opcode | 含义 |
|---|---|
| `0xfc61` | read memory — `[0x21][addr:le32]` |
| `0xfc62` | **write memory** — `[0x21][dst:le32][value:le32]` |
| `0xfc20` | download fragment — `[index][data…]`, ≤252 B, index 1…0x7f wrapping |
关键细节在于:`0x801200cc` 保存了控制器将 `0xfc20` 数据片段写入的流地址。在发送每个记录的数据片段之前,必须将其加载地址**写入该指针**:
```
for each record:
fc62 [0x21][0x801200cc][record_load_addr] # aim the download buffer
fc20 [idx][data] ... # plain indices, no bit 7
fc20 [0x80] # commit, once, at the end
```
如果遗漏了指针写入,所有的记录都会被写入默认缓冲区(`0x8010f720`)。此时所有的命令依然会返回成功,firmware 也驻留在设备中,控制器也能响应 HCI —— 但是代码并没有存在于入口点所期望的位置,因此补丁永远无法启动,蓝牙模块依然无法工作。这种失败是完全静默的,这也正是该芯片在调试时如此令人困惑的原因。
`extract-firmware.py` 会将 `.dat` 记录重新打包为一个小巧的容器(包含 `E4RD` + 数量 + 每个记录的 `[load][len][blob]`),位于 `src/btrtl.c` 中打过补丁的 `rtl_download_eco4()` 函数会读取该容器。
如果您打算自行适配此方案,需要注意一个细节:根据您的 kernel 附带的容器格式不同,原生解析器在失败时会返回*不同*的 errno —— v1 `Realtech` EPATCH 格式返回 `-EINVAL`,v2 `RTBTCore` 格式则返回 `-ENODATA`。该 hook 对两者均予以接受,并按芯片 ID 限定范围,因此不会误吞不相关的错误。
## 推送至上游
这是对 `btrtl.c` 的独立扩展,如果合入主线会更好。目前的阻碍在于 firmware 本身尚未包含在 `linux-firmware` 中;Realtek 需要发布适用于 8852BD 的 eco-4 文件。欢迎提交补丁和报告。
## 许可协议
`src/btrtl.c`、`src/btrtl.h`、`src/hci_codec.h` 源自 Linux kernel,并保持 **GPL-2.0** 协议。本仓库中的脚本同样遵循 GPL-2.0 协议。
此处不包含或重新分发任何 Realtek 的 firmware。
## 免责声明
**这是一个完全“vibecoded”(依靠 AI 凭感觉编写)的项目。** 它的调研、逆向工程以及端到端的编写工作均由 AI 完成 —— Claude Opus 4.8 和部分 Fable 5 —— 仅由我通过提示词并在属于我自己的这台机器上进行测试来驱动。**我不是驱动开发者,也不是 kernel 维护者**,我无法像那些专职编写蓝牙驱动的人那样对这段代码提供担保。本代码按“原样”提供,不附带任何形式的保证。
具体而言,这意味着:它会将厂商提供的 firmware 加载到您的蓝牙控制器上,并通过 DKMS 替换内置的 kernel 模块;目前仅在确切的一台笔记本电脑和一个 kernel 系列上得到了验证;尽管不良后果是可逆的(`./uninstall.sh` 可恢复原生模块),但您需自行承担运行风险。在以 root 身份运行这些脚本之前,请务必先阅读它们 —— 对于从互联网上获取的任何内容您都应如此谨慎,在这里更需加倍小心。
本项目为非官方性质,与 Realtek 或任何笔记本电脑厂商没有任何关系。
可选:自行提取 .dat 文件,而不是直接传递 .exe
该 `.exe` 是一个 Inno Setup 安装程序,因此可以直接在 Linux 上进行解包 —— 无需 Windows 环境:
```
innoextract -s -d extracted ~/Downloads/53lo030fqufmvnj0.exe
find extracted -name 'rtl8852bd_mp_chip_new.dat'
```
完整性检查 —— 该文件的开头应为 ASCII magic `BTNIC003`:
```
head -c 8 path/to/rtl8852bd_mp_chip_new.dat # -> BTNIC003
```
然后,您可以将该 `.dat` 文件(而不是 `.exe`)传递给 `install.sh`。
标签:Cutter, DKMS, Realtek, 内核模块, 固件, 安全资源, 客户端加密, 硬件驱动, 蓝牙