3. 蓝牙驱动基础:USB蓝牙适配器驱动(btusb)、UART蓝牙驱动(hci_uart)、SDIO蓝牙驱动架构
蓝牙主机控制器接口(HCI)是蓝牙协议栈与蓝牙硬件之间的标准通信接口。在Linux内核中,蓝牙驱动主要分为传输层驱动和协议层驱动。传输层驱动负责管理物理总线(USB、UART、SDIO)上的数据收发,而协议层驱动则处理HCI数据帧的解析与封装。本章将深入剖析三种主流蓝牙传输驱动的架构设计与性能关键点。
3.1 蓝牙驱动分层模型
Linux蓝牙子系统采用分层架构,从上到下依次为:蓝牙协议栈(BlueZ)、HCI核心层、HCI传输层驱动。传输层驱动直接与硬件总线交互,是性能优化的第一道关口。
3.2 USB蓝牙适配器驱动(btusb)
btusb 是Linux中最广泛使用的蓝牙传输驱动,支持绝大多数USB接口的蓝牙适配器(如CSR、Broadcom、Intel、Realtek等芯片)。它基于USB核心框架,利用URB(USB Request Block)进行异步数据传输。
3.2.1 驱动注册与探测流程
| 阶段 | 关键函数 | 说明 |
|---|---|---|
| 模块初始化 | btusb_init() |
注册USB驱动,绑定VID/PID表 |
| 设备探测 | btusb_probe() |
分配btusb_data结构体,获取USB接口端点 |
| HCI注册 | hci_register_dev() |
向HCI核心层注册蓝牙设备 |
| URB提交 | btusb_submit_intr_urb() |
提交中断URB用于接收HCI事件 |
3.2.2 关键数据结构
struct btusb_data {
struct hci_dev *hdev; /* HCI设备指针 */
struct usb_device *udev; /* USB设备 */
struct usb_interface *intf; /* USB接口 */
unsigned long flags; /* 驱动标志位 */
/* 端点信息 */
struct usb_endpoint_descriptor *intr_ep; /* 中断端点 */
struct usb_endpoint_descriptor *bulk_tx_ep; /* 批量发送端点 */
struct usb_endpoint_descriptor *bulk_rx_ep; /* 批量接收端点 */
struct usb_endpoint_descriptor *isoc_ep; /* 同步端点(音频) */
/* URB池 */
struct urb *intr_urb; /* 中断URB */
struct sk_buff_head rx_anchor; /* 接收数据队列 */
spinlock_t rx_lock; /* 接收锁 */
};
3.2.3 数据流路径
3.3 UART蓝牙驱动(hci_uart)
UART蓝牙驱动主要用于嵌入式平台,常见于Broadcom(BCM)、Marvell、TI等芯片。UART传输具有低延迟、低功耗的特点,但受限于波特率和流控机制。
3.3.1 驱动架构
hci_uart 驱动基于Linux TTY层,通过线路规程(Line Discipline)实现HCI数据帧的封装与解析。每个蓝牙UART设备对应一个 hci_uart 结构体。
struct hci_uart {
struct hci_dev *hdev; /* HCI设备 */
struct tty_struct *tty; /* TTY设备 */
struct hci_uart_proto *proto; /* 协议处理(H4/BCSP/3-Wire) */
unsigned long flags; /* 状态标志 */
struct work_struct write_work; /* 写工作队列 */
struct sk_buff_head txq; /* 发送队列 */
struct sk_buff_head rxq; /* 接收队列 */
spinlock_t rx_lock;
int init_speed; /* 初始波特率 */
int oper_speed; /* 工作波特率 */
};
3.3.2 三种主流UART协议
| 协议 | 特点 | 适用芯片 | 性能考量 |
|---|---|---|---|
| H4(UART HCI) | 简单,无差错控制,每帧加4字节头 | BCM、CSR | 波特率直接决定吞吐量,推荐≥3Mbps |
| BCSP(BlueCore Serial Protocol) | 带CRC校验和重传,可靠性高 | CSR BlueCore | 协议开销约10%,适合噪声环境 |
| 3-Wire(H5) | 基于HDLC,支持电源管理 | TI、STM | 支持休眠唤醒,但吞吐略低于H4 |
3.3.3 数据接收流程
3.4 SDIO蓝牙驱动架构
SDIO蓝牙驱动主要用于Wi-Fi/BT组合芯片(如Broadcom BCM4339、CYW43455、Marvell 88W8897)。SDIO接口具有高带宽(可达200MB/s)、低延迟的特点,适合同时承载Wi-Fi和蓝牙流量。
3.4.1 驱动组成
SDIO蓝牙驱动通常与Wi-Fi驱动共享同一个SDIO功能设备,通过函数编号(Function Number)区分。蓝牙使用Function 1,Wi-Fi使用Function 2。
struct bt_sdio_dev {
struct hci_dev *hdev;
struct sdio_func *func; /* SDIO功能设备 */
struct sdio_device_id *id; /* 设备ID */
unsigned long flags;
struct sk_buff_head txq; /* 发送队列 */
struct sk_buff_head rxq; /* 接收队列 */
struct work_struct tx_work; /* 发送工作队列 */
struct work_struct rx_work; /* 接收工作队列 */
spinlock_t lock;
int block_size; /* SDIO块大小(通常512字节) */
int rx_block_mode; /* 是否使用块模式 */
};
3.4.2 数据传输模式
| 模式 | 传输方式 | 优势 | 劣势 |
|---|---|---|---|
| 字节模式 | 逐字节读写 | 实现简单,兼容性好 | 吞吐低,CPU占用高 |
| 块模式 | 固定块大小(512/1024字节) | 吞吐高,适合大包传输 | 小包填充浪费带宽 |
| SDMA/ADMA | 硬件DMA传输 | 零CPU拷贝,吞吐最高 | 需要硬件支持,驱动复杂 |
3.4.3 中断处理机制
SDIO蓝牙驱动通过SDIO中断线接收蓝牙事件。中断处理函数中,驱动需要读取SDIO中断状态寄存器,判断中断来源(蓝牙/Wi-Fi),然后调度对应的工作队列处理数据。
3.5 三种驱动架构对比
| 特性 | btusb(USB) | hci_uart(UART) | SDIO |
|---|---|---|---|
| 典型带宽 | USB 2.0: 480Mbps USB 3.0: 5Gbps |
3~4Mbps(典型) 最高12Mbps |
50~200MB/s |
| 延迟 | 中等(USB帧调度) | 低(直接中断) | 低(SDIO中断) |
| CPU占用 | 低(USB URB批量处理) | 高(逐字节中断) | 中(DMA可降低) |
| 适用场景 | 桌面、笔记本、工控机 | 嵌入式、IoT、低功耗设备 | 智能手机、平板、高端嵌入式 |
| 驱动复杂度 | 中等 | 低 | 高 |
| 电源管理 | USB挂起/唤醒 | UART休眠/唤醒 | SDIO休眠/唤醒 |
3.6 设备树配置要点
在嵌入式Linux中,蓝牙设备通常通过设备树(Device Tree)描述。以下是三种接口的设备树配置示例:
3.6.1 USB蓝牙(通常无需设备树)
USB蓝牙适配器通过USB VID/PID自动匹配驱动,一般不需要设备树配置。但在某些嵌入式平台,需要配置USB控制器节点。
3.6.2 UART蓝牙设备树
&uart1 {
status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&uart1_pins>;
current-speed = <3000000>; /* 3Mbps */
bluetooth {
compatible = "brcm,bcm43438-bt";
max-speed = <3000000>;
shutdown-gpios = <&gpio0 4 GPIO_ACTIVE_HIGH>;
device-wakeup-gpios = <&gpio0 5 GPIO_ACTIVE_HIGH>;
host-wakeup-gpios = <&gpio0 6 GPIO_ACTIVE_HIGH>;
clocks = <&clk32k>;
clock-names = "lpo";
};
};
3.6.3 SDIO蓝牙设备树
&sdio1 {
status = "okay";
bus-width = <4>; /* 4位SDIO模式 */
max-frequency = <50000000>; /* 50MHz时钟 */
non-removable;
cap-sd-highspeed;
bluetooth {
compatible = "brcm,bcm4339-bt";
reg = <1>; /* Function 1 */
interrupt-parent = <&sdio1>;
interrupts = <0 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clk32k>;
clock-names = "lpo";
};
};
dtc -I dtb -O dts 反编译设备树二进制文件,检查蓝牙节点是否正确加载。通过 ls /sys/firmware/devicetree/base/ 查看运行时设备树属性。对于UART蓝牙,务必确认 max-speed 与驱动设置的波特率一致。
3.7 本章小结
三种蓝牙传输驱动各有优劣:btusb 适合高性能桌面场景,URB池深度和批量端点配置是优化重点;hci_uart 在嵌入式领域广泛使用,波特率和流控机制直接影响吞吐量;SDIO 驱动架构最复杂,但能提供最高的带宽和最低的延迟,适合高端移动设备。理解这些驱动的底层数据流和关键数据结构,是后续进行蓝牙抓包分析和性能优化的基础。