BlueZ的简介和使用总结

发布时间:2026/6/17 16:17:34

BlueZ的简介和使用总结 BlueZ 就是Linux 系统里的蓝牙驱动 蓝牙管家你可以把它理解成Linux 系统的官方蓝牙系统 BlueZ就像Windows 有自己的蓝牙管理Android 有自己的蓝牙系统Linux 用的就是 BlueZ它是官方、标准、唯一的蓝牙协议栈几乎所有 Linux 设备包括你这个设备都必须用它。它到底做什么让蓝牙硬件能工作管理蓝牙扫描、连接、配对、传输给上层 APP / 服务提供蓝牙接口BlueZ 由哪些部分组成简单了解BlueZ 不是一个单一程序而是一套组件内核驱动让蓝牙芯片能被系统识别bluetoothd蓝牙守护进程后台一直跑bluetoothctl命令行工具D-Bus API给上层 APP 使用的接口配置文件蓝牙名称、配对模式、音量等一句话总结你的设备蓝牙就是靠 BlueZ 驱动和运行的。源码相关BlueZ 分两大部分内核态源码在 Linux 内核里、用户态源码 / 运行文件独立项目。下面给你最清晰的位置与目录说明。一、内核态 BlueZ 源码Linux 内核自带这部分是蓝牙底层驱动与协议栈编译进内核不是单独安装的。1. 核心路径必看# 内核源码根目录下 net/bluetooth/ # 蓝牙核心协议栈HCI/L2CAP/RFCOMM/BNEP等 drivers/bluetooth/ # 蓝牙硬件驱动USB/SDIO/UART蓝牙芯片2. net/bluetooth/ 关键子目录协议层net/bluetooth/bluetooth.h核心头文件、数据结构net/bluetooth/hci/HCI 主机控制接口最底层hci_core.cHCI 核心逻辑hci_sock.cHCI Socket 接口net/bluetooth/l2cap/L2CAP 协议层net/bluetooth/rfcomm/RFCOMM 串口模拟net/bluetooth/bnep/BNEP 以太网封装net/bluetooth/mgmt/内核管理接口3. drivers/bluetooth/ 关键驱动btusb.cUSB 蓝牙适配器驱动最常用hci_uart.cUART 蓝牙如 H5、BCSPbtintel.c/btrtl.c/btbcm.cIntel/Realtek/Broadcom 专用芯片驱动二、用户态 BlueZ 源码独立项目需下载这是bluetoothd、bluetoothctl、btmon等工具的源码不在内核里需单独下载编译。1. 源码获取官方官网https://www.bluez.org/源码包https://www.kernel.org/pub/linux/bluetooth/Gitgit clone https://github.com/bluez/bluez.git2. 解压后顶层目录以 bluez-5.x 为例bluez-5.x/ ├── android/ # Android 适配层 ├── attrib/ # GATT/ATT 协议BLE 核心 ├── btio/ # 与内核蓝牙通信的 I/O 层 ├── client/ # bluetoothctl 命令行工具源码 ├── doc/ # D-Bus API 文档adapter-api.txt 等 ├── emulator/ # 虚拟蓝牙控制器vhci ├── gdbus/ # BlueZ 内部 D-Bus 封装 ├── lib/ # libbluetooth.so 源码BlueZ 4 兼容 API ├── monitor/ # btmon 蓝牙抓包工具 ├── obexd/ # OBEX 文件传输服务 ├── peripheral/ # BLE Peripheral 模式实现 ├── plugins/ # 插件autopair、neard 等 ├── profiles/ # 蓝牙应用规范A2DP/HID/HFP 等 ├── src/ # bluetoothd 守护进程主源码核心 ├── tools/ # hciconfig、hcitool、sdptool 等工具 └── test/ # 测试脚本example-gatt-server.py 等三、系统运行时 BlueZ 文件目录已安装编译安装后BlueZ 会分布在这些系统路径1. 守护进程与工具可执行文件/usr/lib/bluetooth/ # 主目录 ├── bluetoothd # 核心守护进程必须运行 ├── bluetoothctl # 命令行客户端 ├── hciconfig # HCI 设备配置 ├── hcitool # HCI 底层工具 ├── sdptool # SDP 服务查询 ├── btmon # 蓝牙抓包 └── ...2. 配置文件/etc/bluetooth/ ├── main.conf # 全局配置蓝牙名称、可发现等 ├── bluetooth.service # systemd 服务文件 └── ...3. 库文件/usr/lib/libbluetooth.so # 应用开发链接库 /usr/include/bluetooth/ # 头文件4. 运行时数据/var/lib/bluetooth/ # 配对信息、设备缓存MAC 命名目录四、一句话分清 “内核 vs 用户态”内核态net/bluetooth/ drivers/bluetooth/让蓝牙硬件能被系统识别、收发底层数据。用户态bluez 源码提供bluetoothd管理服务、bluetoothctl命令、D-Bus 接口给上层 APP。职责分工一、一句话分清两层驱动层 硬件通信底层应用层 业务逻辑上层二、驱动层内核里负责什么位置Linux 内核 →net/bluetooth/drivers/bluetooth/它只干和硬件相关的事驱动层核心功能初始化蓝牙芯片上电、复位、加载固件收发底层蓝牙数据包HCI 指令 / 事件 / 数据管理蓝牙控制器hci0提供标准接口给上层Socket/HCI处理底层协议HCI / L2CAP不处理配对、不处理连接逻辑、不跑服务简单比喻驱动层 蓝牙硬件的翻译官 快递员把上层指令发给芯片把芯片数据传回上层不理解指令含义只负责传输三、应用层BlueZ 用户态负责什么位置BlueZ 源码 →bluetoothd、client/、profiles/、src/它干所有智能逻辑、业务功能应用层核心功能启动蓝牙服务 bluetoothd打开 / 关闭蓝牙扫描周围设备配对、绑定、加密连接设备、断开设备运行蓝牙服务A2DP 音频、HID 键盘、BLE 广播、GATT 等提供 D-Bus 接口给 APP 使用提供命令行工具 bluetoothctl简单比喻应用层 蓝牙指挥官 管家决定什么时候扫描决定连哪个设备决定发什么广播处理所有业务逻辑四、最直观的分工对比表功能驱动层内核应用层BlueZ控制蓝牙芯片上电✅加载蓝牙固件✅收发 HCI 数据包✅扫描设备✅配对 / 加密✅连接 / 断开设备✅BLE 广播✅GATT 服务✅音频 A2DP✅提供 bluetoothctl✅提供 D-Bus 接口✅五、数据流超级好懂APP → BlueZ应用层 → 驱动层 → 蓝牙芯片 蓝牙芯片 → 驱动层 → BlueZ应用层 → APP驱动层只负责传输应用层负责理解、控制、管理如何移植一、移植 BlueZ 总共分 3 层你只需要搞定这3 件事内核配置驱动层BlueZ 编译应用层蓝牙芯片适配UART/SDIO/USB 固件 供电二、第一步内核配置必须先做进入内核make menuconfig打开下面这些Networking support → Bluetooth subsystem support * 必选 → HCI UART driver * UART 蓝牙必开 → HCI USB driver * USB 蓝牙必开 → HCI SDIO driver * SDIO 蓝牙必开 → BLE 低功耗蓝牙必开作用让内核识别蓝牙硬件 驱动层就绪三、第二步编译 BlueZ应用层你只需要做 4 步1. 下载 BlueZ 源码git clone https://github.com/bluez/bluez.git2. 配置交叉编译假设你的交叉编译器是arm-linux-gnueabihf-gcc./configure \ --hostarm-linux-gnueabihf \ --prefix/usr \ --sysconfdir/etc \ --localstatedir/var \ --disable-systemd \ --enable-library \ --disable-obex \ --disable-manpages3. 编译make -j84. 安装到文件系统make install DESTDIR你的rootfs路径做完这步你的文件系统就有bluetoothd蓝牙守护进程bluetoothctl命令行工具libbluetooth.so蓝牙库四、第三步适配蓝牙芯片最关键这是嵌入式移植最容易卡壳的地方。蓝牙一般 3 种接口UART最常见RTL8723、AIC8800、BES、Beken…SDIOWiFi 蓝牙二合一USB免驱你只需要做 3 件事1. 给蓝牙上电LDO 使能、复位脚设备树 DTS 配置bt_en: gpio-output LOW/HIGH bt_rst: gpio-reset内核启动 → 拉高低电平 → 蓝牙芯片上电。2. 加载蓝牙固件.hcd/.bin不同芯片要烧固件realtek 用RTL8723BU_fw.binaic8800 用aic8800_bt.binbroadcom 用BCM4343A0.hcd把固件放到/lib/firmware/3. 用 hciattach /btattach 绑定串口btattach -B /dev/ttyS1 -P bcm -S 115200 /dev/uart0或hciattach /dev/ttyS1 bcm 115200成功后会出现hci0 蓝牙设备五、第四步启动 BlueZ 服务bluetoothd 然后就能用bluetoothctl出现[hci0]就代表移植成功六、嵌入式工程师的极简总结记这个移植 BlueZ 内核打开蓝牙交叉编译 BlueZ蓝牙芯片上电 放固件hciattach 绑定串口 → 出现 hci0运行 bluetoothd → 完成七、你现在的设备从日志看你的蓝牙是AIC8800D80SDIO UART 双模你需要内核打开hci_uart hci_sdio放入aic8800 蓝牙固件开机自动执行hciattach或厂商提供的mibt工具启动bluetoothd在哪能看到hci0hci0是蓝牙控制器的设备节点类似网卡 eth0。它出现在以下3 个位置你按下面顺序检查就能立刻定位问题1. 最直观/dev/ 目录下硬件节点这是蓝牙硬件被内核识别后的文件入口。查看命令ls /dev/hci0✅ 成功输出/dev/hci0说明内核驱动已加载成功硬件通电且正常通讯。❌ 失败输出No such file or directory说明内核驱动没开或硬件没上电。2. 最常用蓝牙工具列表系统状态这是通过 BlueZ 工具查看所有蓝牙控制器的状态。查看命令# 传统工具较老系统 hciconfig # 现代推荐命令新系统 bluetoothctl show✅ 成功hciconfig会显示hci0: Type: Primary Bus: SDIO/UART等信息。bluetoothctl show会显示 MAC 地址和控制器状态。❌ 失败Cant open HCI socket说明bluetoothd服务没启动或无权限。No available controllers说明/dev/hci0不存在回到底部第一步排查。3. 内核底层HCI 设备驱动日志如果你是开发移植人员必须看内核是否识别到芯片。查看命令dmesg | grep -i blue✅ 正常日志示例AIC8800 为例Bluetooth: Core ver 2.22 Bluetooth: HCI device and connection manager initialized Bluetooth: HCI socket layer initialized Bluetooth: L2CAP socket layer initialized Bluetooth: SCO socket layer initialized aic8800: probing ... hci0: AIC8800 ... added❌ 异常日志示例Failed to load firmware固件放错位置或文件名不对。timeout串口通讯失败波特率 / 引脚错。 极简排查逻辑按顺序看/dev有文件 硬件通电 内核驱动 OK。看hciconfig能显示 蓝牙服务 (bluetoothd) 正常。看dmesg有报错 查固件 / 接线 / 芯片初始化。结合你之前的日志你之前的日志里出现了/org/bluez/hci0/...这说明/dev/hci0肯定存在否则 bluez 连不上。bluetoothd正在运行并接管了它。你现在直接在终端敲hciconfig就能看到。调试调试是用bluetoothd还是bluetoothctl指令我给你用最直白、嵌入式开发最实用的方式讲清楚两个都用但分工完全不一样你只要记住下面这张表调试永远不懵一句话结论bluetoothd 后台服务必须先跑bluetoothctl 调试命令行你用来操作1. bluetoothd 是干什么的服务端它是蓝牙的 “后台管家”不能用来交互调试作用启动 BlueZ 核心服务加载蓝牙协议栈管理 hci0处理配对、连接、GATT、广播等所有逻辑给 APP 提供 D-Bus 接口调试用法嵌入式必用bluetoothd -d -n-d打开调试日志超级重要-n前台运行不后台 daemon你用它来干嘛看底层报错比如蓝牙打不开连接失败GATT 异常协议报错芯片不响应它会把内核 ↔ 芯片的所有底层通信打印出来。2. bluetoothctl 是干什么的调试工具它是你手动操作蓝牙的工具作用扫描设备配对连接断开查看服务测试 BLE 广播手动控制蓝牙启动方式bluetoothctl常用调试命令你一定会用到power on # 打开蓝牙 scan on # 扫描设备 connect XX:XX # 连接设备 disconnect # 断开 pair XX:XX # 配对 advertise on # 打开BLE广播 list # 查看控制器 show # 查看状态你用它来干嘛手动验证蓝牙功能是否正常3. 正确调试流程嵌入式工程师标准姿势第一步先启动后台服务看日志bluetoothd -d -n # 前台调试模式看所有底层日志✅ 出现这个说明服务正常bluetoothd[1234]: Bluetooth daemon 5.65 bluetoothd[1234]: Starting SDP server bluetoothd[1234]: Bluetooth management interface 1.21 initialized第二步开另一个终端用 bluetoothctl 调试bluetoothctl然后执行power on scan on✅ 能扫描到设备 蓝牙完全正常4. 超清晰分工表记这个就够指令身份用来做什么调试场景bluetoothd后台服务跑蓝牙核心逻辑看底层错误日志bluetoothctl调试工具手动扫描 / 连接 / 配对做功能测试5. 最简单记忆法bluetoothd 服务不能少bluetoothctl 遥控器你用的6. 你现在的设备怎么调试直接照做# 终端1看日志 bluetoothd -d -n # 终端2操作调试 bluetoothctl power on scan on总结调试蓝牙时两个都要开看底层问题 → 看bluetoothd -d日志手动测试功能 → 用bluetoothctl接口调用BlueZ 经典蓝牙BR/EDR BLE 双模式完整 C 语言调用方式不讲废话、不绕弯、全部是产品级可直接用的代码。 终极结论先记死BlueZ同时支持 BLE 和经典蓝牙接口完全分开互不干扰BLE 低功耗蓝牙→ 用hci_le_xxx系列 API经典蓝牙 BR/EDR→ 用RFCOMM HCI inquiry系列 API你在嵌入式产品里两套代码可以同时跑。一、头文件两套蓝牙都需要#include stdio.h #include stdlib.h #include string.h #include unistd.h #include sys/socket.h #include bluetooth/bluetooth.h #include bluetooth/hci.h #include bluetooth/hci_lib.h #include bluetooth/rfcomm.h // 经典蓝牙专用二、先讲经典蓝牙BR/EDRC 接口串口 / 耳机 / HC-051. 扫描经典蓝牙设备int dev_id hci_get_route(NULL); int sock hci_open_dev(dev_id); inquiry_info ii[10]; int num hci_inquiry( dev_id, 5, 10, NULL, ii, IREQ_CACHE_FLUSH ); for (int i 0; i num; i) { char mac[18]; ba2str(ii[i].bdaddr, mac); printf(发现经典设备%s\n, mac); }2. 连接经典蓝牙RFCOMM 串口HC-05 标准int sock socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM); struct sockaddr_rc addr {0}; addr.rc_family AF_BLUETOOTH; addr.rc_channel 1; str2ba(00:11:22:33:44:55, addr.rc_bdaddr); connect(sock, (struct sockaddr*)addr, sizeof(addr));3. 发送 / 接收数据和网络 socket 完全一样write(sock, hello, 5); read(sock, buf, 1024);4. 经典蓝牙服务端被别人连接struct sockaddr_rc loc_addr {0}; loc_addr.rc_family AF_BLUETOOTH; loc_addr.rc_bdaddr *BDADDR_ANY; loc_addr.rc_channel 1; int s socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM); bind(s, (struct sockaddr*)loc_addr, sizeof(loc_addr)); listen(s, 1); int client accept(s, NULL, NULL);三、再讲BLE低功耗蓝牙C 接口传感器 / 手环 / 广播1. 打开 HCI 控制器int dev_id hci_get_route(NULL); int sock hci_open_dev(dev_id);2. 设置广播参数le_set_advertising_parameters_cp params {0}; params.min_interval htobs(0x00A0); params.max_interval htobs(0x0140); params.adv_type 0x00; params.channel_map 7; hci_le_set_advertising_parameters(sock, params, 1000);3. 设置广播数据le_set_advertising_data_cp data {0}; uint8_t buf[] { 0x02,0x01,0x06, 0x05,0x09,A,B,C }; data.length sizeof(buf); memcpy(data.data, buf, sizeof(buf)); hci_le_set_advertising_data(sock, data, 1000);4. 启动广播hci_le_set_advertise_enable(sock, 1, 1000);5. BLE 扫描设备le_set_scan_parameters_cp scan {0}; scan.type 0; scan.interval htobs(0x0010); scan.window htobs(0x0010); hci_le_set_scan_parameters(sock, scan, 1000); hci_le_set_scan_enable(sock, 1, 0, 1000);四、最清晰对比嵌入式工程师必背功能经典蓝牙 BR/EDRBLE打开设备hci_open_devhci_open_dev扫描hci_inquiry()hci_le_set_scan_enable连接RFCOMM SocketGATT / HCI LE Connect数据read / writeWriteCharacteristic串口RFCOMM标准无音频A2DP不支持广播不支持hci_le_set_advertise_enable功耗高极低典型设备耳机、HC-05、音箱手环、传感器、标签五、最重要的结论你一定要记住✔ BlueZ 不是只做 BLE它是全功能蓝牙栈✔ 经典蓝牙 RFCOMM HCI✔ BLE hci_le_xxx 指令集✔ 嵌入式 C 语言直接调用不需要 D-Bus、不需要框架✔ 你的设备可以同时跑经典蓝牙 BLE

相关新闻