本文最后更新于 2026-08-06T11:52:17+00:00
本文记录在 LubanCat-3 开发板(RK3576,Ubuntu 22.04.5,内核 6.1.99-rk3576)上编译安装 Realtek RTL8851BU WiFi+蓝牙 combo 驱动的完整过程。提供一键安装脚本,也详解每个步骤的原理和踩坑经验。
适用环境:LubanCat-3 / RK3576 / Ubuntu 22.04 / Kernel 6.1.99-rk3576 目标芯片:Realtek RTL8851BU(WiFi 6 + BT 5.3 combo) USB 设备 ID:0bda:1a2b(CDROM 模式)→ 0bda:b851(WiFi+BT 模式)
资源下载 本文所用驱动源码、固件及一键安装脚本已打包:
wifi_linux.zip (约 11.2 MB,含 WiFi/BT 源码 + lubancat3_rtk_fix.sh 一键脚本)
解压后目录结构:
1 2 3 4 5 wifi_linux/ ├── lubancat3_rtk_fix.sh └── Linux/ ├── WIFI/ └── BT/
1. 快速开始(一键安装) 如果你只想尽快跑起来,三步搞定:
1 2 3 4 5 6 7 8 9 unzip wifi_linux.zipcd wifi_linuxchmod +x lubancat3_rtk_fix.shsudo ./lubancat3_rtk_fix.sh
脚本会自动完成以下全部流程:安装编译依赖 → 修复源码 bug → 编译 WiFi 驱动 → 安装 WiFi 驱动 → 复制蓝牙固件 → 编译蓝牙驱动 → 安装蓝牙驱动 → USB 模式切换 → 加载模块 → 验证结果。
整个过程约 12 分钟(主要耗时在编译)。执行完毕后如果 wlan0 没有立即出现,等几秒或 sudo reboot 重启即可。
下面详细介绍每个步骤的原理,方便遇到问题时排查。
2. 环境准备 2.1 确认系统信息 1 2 3 4 5 uname -acat /etc/os-release
2.2 安装编译工具链 1 2 sudo apt-get updatesudo apt-get install -y build-essential linux-headers-$(uname -r) git python3-usb
注意 :python3-usb(pyusb)后续用于 USB 模式切换,务必提前安装。
2.3 准备驱动源码 将下载的 wifi_linux.zip 传到开发板(通过 U 盘、scp 或其他方式),解压:
1 2 unzip wifi_linux.zipcd wifi_linux/Linux
3. 编译 WiFi 驱动 (8851bu) 3.1 修复源码 bug 打开 WIFI/phl/phl_regulation_def.h,有一处 sizeof 写错了结构体类型,会导致编译报 sizeof-array-div 错误。
Bug 位置 — 第 114 行附近,PHL_GET_CHDEF_6G 宏:
1 2 3 4 5 u8 size = sizeof (_chdef_tbl_) / sizeof (struct regulatory_domain_mapping_6g); u8 size = sizeof (_chdef_tbl_) / sizeof (struct chdef_6ghz);
一键脚本中已包含自动修复逻辑,会精确定位 PHL_GET_CHDEF_6G 宏并替换,不会影响第 122 行的 PHL_GET_DOMAIN_INDEX_6G 宏(那个是正确的)。
手动修复命令:
1 2 cd WIFI sed -i '/PHL_GET_CHDEF_6G/,/;/ s/sizeof(struct regulatory_domain_mapping_6g)/sizeof(struct chdef_6ghz)/' phl/phl_regulation_def.h
3.2 编译驱动 关键 :必须显式指定 ARCH=arm64,不能依赖 uname -m 的默认值(会返回 aarch64,但内核目录是 arch/arm64/)。
1 2 cd WIFIsudo make all ARCH=arm64
编译时间约 10 分钟。如果通过 SSH 操作,建议用 nohup 放到后台避免超时:
1 2 nohup sudo make all ARCH=arm64 > /tmp/wifi_build.log 2>&1 &tail -f /tmp/wifi_build.log
编译成功后生成 8851bu.ko(约 10.8MB)。
3.3 安装并加载 WiFi 模块 1 2 3 4 5 6 7 8 9 10 11 12 13 14 sudo cp 8851bu.ko /lib/modules/$(uname -r)/kernel/drivers/net/wireless/sudo depmod -asudo modprobe 8851bu lsmod | grep 8851bu dmesg | tail -5
此时 8851bu 模块已加载,但由于 USB 设备还在 CDROM 模式,wlan0 接口不会出现 。需要先完成 USB 模式切换。
4. 编译安装蓝牙驱动 (rtk_btusb) 4.1 复制固件文件 1 2 3 4 sudo cp BT/rtkbt-firmware/lib/firmware/rtl8851bu_* /lib/firmware/ls /lib/firmware/rtl8851bu*
4.2 编译蓝牙驱动 1 2 cd BT/usbsudo make all ARCH=arm64
4.3 安装并加载蓝牙模块 1 2 3 4 5 6 7 8 9 10 11 sudo cp rtk_btusb.ko /lib/modules/$(uname -r)/kernel/drivers/bluetooth/sudo depmod -asudo modprobe rtk_btusb lsmod | grep rtk_btusb dmesg | grep rtk_btusb
蓝牙模块加载完成,但同样需要 USB 模式切换后才能看到 hci0 设备。
5. USB 模式切换(核心难点) 这是整个流程中最关键的一步。RTL8851BU 的 USB 设备初始状态是 CDROM/Mass Storage 模式 (用于 Windows 安装驱动),需要发送特定 SCSI 命令切换到 WiFi+BT 模式。
5.1 确认当前状态
设备显示为 0bda:1a2b,Product 字符串为 “DISK”,bInterfaceClass 为 Mass Storage (8)。这就是 CDROM 模式。
5.2 尝试 usb_modeswitch(失败) 最常见的思路是用 usb_modeswitch:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 sudo usb_modeswitch -W -v 0bda -p 1a2bsudo usb_modeswitch -J -v 0bda -p 1a2bsudo tee /usr/share/usb_modeswitch/0bda:1a2b << EOF TargetVendor=0x0bda TargetProduct=0x8851 StandardEject=1 EOF sudo usb_modeswitch -v 0bda -p 1a2b
结论 :usb_modeswitch 的所有标准方法对 0bda:1a2b 均无效。
5.3 成功方案:pyusb 直接发送 SCSI 命令 通过 Python pyusb 库直接向 USB 设备发送 Bulk-Only Transport (BOT) 协议的 SCSI 命令。
原理 :USB Mass Storage 设备使用 BOT 协议通信,主机通过 Bulk OUT 端点发送 Command Block Wrapper (CBW, 31字节),设备通过 Bulk IN 端点返回 Command Status Wrapper (CSW, 13字节)。切换流程分两步:先发 ALLOW MEDIUM REMOVAL(0x1e)解除介质锁定,再发 START STOP UNIT(0x1b)带 Load/Eject 位触发模式切换。
一键脚本中已内嵌了完整的 Python 切换逻辑。如需手动执行,核心代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 import usb.coreimport structimport time dev = usb.core.find(idVendor=0x0bda , idProduct=0x1a2b )if dev is None : print ("设备未处于 CDROM 模式" ) exit(0 )if dev.is_kernel_driver_active(0 ): dev.detach_kernel_driver(0 ) cfg = dev.get_active_configuration() intf = cfg[(0 , 0 )] ep_out = ep_in = None for ep in intf: if usb.util.endpoint_direction(ep.bEndpointAddress) == usb.util.ENDPOINT_OUT: ep_out = ep else : ep_in = epdef send_scsi (cmd, tag ): cbw = struct.pack('<IIIB' , 0x43425355 , tag, 0 , 0 ) cbw += struct.pack('<BB' , 0 , len (cmd)) cbw += cmd + b'\x00' * (31 - 6 - len (cmd)) dev.write(ep_out.bEndpointAddress, cbw, timeout=5000 ) try : dev.read(ep_in.bEndpointAddress, 13 , timeout=3000 ) except : pass send_scsi(bytes ([0x1e , 0 , 0 , 0 , 0 , 0 ]), 1 ) time.sleep(0.5 ) send_scsi(bytes ([0x1b , 0 , 0 , 0 , 0x02 , 0 ]), 2 ) time.sleep(2 )if usb.core.find(idVendor=0x0bda , idProduct=0x1a2b ) is None : print ("切换成功!" )
运行:
1 sudo python3 usb_switch.py
预期输出 :
5.4 切换后的设备信息
设备现在暴露了 3 个接口:If 0/1 是 Bluetooth(rtk_btusb 驱动),If 2 是 WiFi(rtl8851bu 驱动)。
6. 验证功能 6.1 WiFi 1 2 3 4 5 6 7 8 9 10 11 12 13 14 ip link show wlan0 iwconfig wlan0 nmcli device wifi list nmcli device wifi connect <SSID> password <密码> ping -c 3 8.8.8.8
6.2 蓝牙 1 2 3 4 5 6 7 8 9 10 11 hciconfig hci0 rfkill listsudo hcitool inq
补充 :BLE 扫描 hcitool lescan 可能出现 “Input/output error”,这是 rtk_btusb 驱动版本对 LE 命令支持不完整导致的,不影响经典蓝牙功能。
7. 设置开机自动加载 7.1 模块自动加载 1 2 echo "8851bu" | sudo tee -a /etc/modulesecho "rtk_btusb" | sudo tee -a /etc/modules
7.2 USB 模式切换自动化 创建 systemd 服务,开机自动执行 USB 模式切换:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 sudo tee /usr/local/bin/rtl8851bu_modeswitch.py << 'PYEOF' "" "RTL8851BU USB mode switch: CDROM (0bda:1a2b) -> WiFi+BT (0bda:b851)" "" import usb.core, struct, time , sys def switch_mode(): dev = usb.core.find(idVendor=0x0bda, idProduct=0x1a2b) if dev is None: return True try: if dev.is_kernel_driver_active(0): dev.detach_kernel_driver(0) except: pass cfg = dev.get_active_configuration() intf = cfg[(0, 0)] ep_out = ep_in = None for ep in intf: if usb.util.endpoint_direction(ep.bEndpointAddress) == usb.util.ENDPOINT_OUT: ep_out = ep else : ep_in = ep if not ep_out or not ep_in: return False def send_scsi(cmd, tag): cbw = struct.pack('<IIIB' , 0x43425355, tag, 0, 0) cbw += struct.pack('<BB' , 0, len(cmd)) cbw += cmd + b'\x00' * (31 - 6 - len(cmd)) dev.write(ep_out.bEndpointAddress, cbw, timeout =5000) try: dev.read(ep_in.bEndpointAddress, 13, timeout =3000) except: pass send_scsi(bytes([0x1e, 0, 0, 0, 0, 0]), 1) time.sleep(0.5) send_scsi(bytes([0x1b, 0, 0, 0, 0x02, 0]), 2) time.sleep(2) return usb.core.find(idVendor=0x0bda, idProduct=0x1a2b) is Noneif __name__ == '__main__' : sys.exit(0 if switch_mode() else 1) PYEOFsudo chmod +x /usr/local/bin/rtl8851bu_modeswitch.pysudo tee /etc/systemd/system/rtl8851bu-modeswitch.service << 'EOF' [Unit] Description=RTL8851BU USB Mode Switch After=usb.target Before=NetworkManager.service [Service] Type=oneshot ExecStart=/usr/bin/python3 /usr/local/bin/rtl8851bu_modeswitch.py RemainAfterExit=yes TimeoutStartSec=15 [Install] WantedBy=multi-user.target EOFsudo systemctl daemon-reloadsudo systemctl enable rtl8851bu-modeswitch.service
8. 踩坑总结
问题
原因
解决方案
WiFi 驱动编译报 sizeof-array-div 错误
phl_regulation_def.h 第 114 行 sizeof 使用了错误的结构体类型
将 sizeof(struct regulatory_domain_mapping_6g) 改为 sizeof(struct chdef_6ghz)
编译报 arch/aarch64/Makefile: No such file
Makefile 默认用 uname -m 得到 aarch64,但内核目录是 arch/arm64/
编译时显式指定 ARCH=arm64
SSH 编译超时
编译时间超过 SSH 会话超时
使用 nohup + 后台脚本 + 日志轮询
USB 设备始终显示为 CDROM 模式
usb_modeswitch 标准方法对 0bda:1a2b 无效
用 pyusb 发送 SCSI BOT 命令(ALLOW MEDIUM REMOVAL + START STOP UNIT)
蓝牙 hciconfig 无设备
USB 设备未切换模式,BT 接口不可见
先完成 USB 模式切换
蓝牙 rfkill soft blocked
某些操作触发了 rfkill 开关
sudo rfkill unblock all
BLE 扫描报 I/O error
rtk_btusb 驱动版本对 LE 命令支持不完整
不影响经典蓝牙,可尝试更新驱动或换用内核 btusb 模块
9. 参考资料