Skip to content

Latest commit

 

History

History
3407 lines (2662 loc) · 112 KB

File metadata and controls

3407 lines (2662 loc) · 112 KB

Linux 内核蓝牙(Bluetooth)子系统深度分析

基于内核源码版本:Linux 主线(master,含 nfsd-7.0-2 合并) 分析日期:2026-03-22


目录

  1. 总体架构概览
  2. BlueZ 内核协议栈层次
  3. HCI 设备抽象:struct hci_dev
  4. HCI 连接抽象:struct hci_conn
  5. HCI 传输层驱动:USB、UART、SDIO
  6. HCI 核心工作流:命令/数据/事件
  7. HCI 事件处理:hci_event.c
  8. L2CAP 层:连接、信道与协议复用
  9. L2CAP 信道类型与传输模式
  10. 低功耗蓝牙(LE):扫描、广播与连接
  11. AF_BLUETOOTH Socket 层
  12. MGMT 接口:用户态与内核的管理桥梁
  13. SMP(Security Manager Protocol)
  14. 上层协议:RFCOMM / BNEP / HIDP / ISO
  15. 关键数据结构关系图
  16. 核心锁机制与并发模型
  17. 调试接口与工具
  18. HCI 同步命令框架:hci_sync.c
  19. RFCOMM 层深度分析
  20. BNEP 层深度分析
  21. HIDP 层深度分析
  22. ISO 层与 LE Audio
  23. BLE 扫描与广播深度分析
  24. 蓝牙 5.x 新特性
  25. SMP 配对深度分析
  26. MGMT Mesh 网络支持
  27. A2DP / AVDTP 音频配置文件
  28. HCI 初始化流程详解
  29. 蓝牙子系统电源管理
  30. 完整数据流追踪示例

1. 总体架构概览

Linux 内核蓝牙子系统(BlueZ)由两大部分组成:

  • net/bluetooth/:协议栈核心,包含 HCI 核心、L2CAP、SMP、RFCOMM、BNEP、HIDP、SCO、ISO 等。
  • drivers/bluetooth/:具体硬件传输层驱动,包含 USB(btusb)、UART(hci_ldisc/hci_uart)、SDIO(btsdio/btmrvl_sdio)等。
 +---------------------------------------------------------+
 |                用户空间(User Space)                    |
 |  bluetoothd(BlueZ)   bluetoothctl   hcitool  obexd     |
 +-----------+--------------------+-------------------+----+
             |  AF_BLUETOOTH socket                   |
             |  (socket(AF_BLUETOOTH, ...))           | MGMT socket
 +-----------v----------------------------------------v----+
 |                  AF_BLUETOOTH 协议族                    |
 |    bt_sock_create()  -->  bt_proto[]->create()         |
 |                                                        |
 |  BTPROTO_L2CAP  BTPROTO_HCI  BTPROTO_RFCOMM           |
 |  BTPROTO_SCO    BTPROTO_BNEP BTPROTO_HIDP             |
 |  BTPROTO_AVDTP  BTPROTO_ISO                           |
 +---+------------+----------+----------+---------+-------+
     |            |          |          |         |
 +---v---+   +---v--+  +----v--+  +----v--+  +---v---+
 |RFCOMM |   |BNEP  |  |HIDP   |  | SCO   |  | ISO   |
 +---+---+   +--+---+  +---+---+  +---+---+  +---+---+
     |           |          |          |          |
 +---v-----------v----------v----------v----------v-------+
 |                   L2CAP 核心层                          |
 |   l2cap_core.c  l2cap_sock.c                          |
 |   struct l2cap_conn  /  struct l2cap_chan              |
 +-----------------------------+--------------------------+
                               |
 +-----------------------------v--------------------------+
 |                   HCI 核心层                           |
 |   hci_core.c  hci_conn.c  hci_event.c                |
 |   struct hci_dev  /  struct hci_conn                  |
 |   struct hci_chan                                     |
 +--------+---------------+---------------+--------------+
          |               |               |
 +--------v---+  +--------v---+  +--------v---+
 |  btusb     |  | hci_ldisc  |  |  btsdio    |
 |  (USB)     |  | (UART/TTY) |  |  (SDIO)    |
 +--------+---+  +--------+---+  +--------+---+
          |               |               |
 +--------v---------------v---------------v--------------+
 |                    物理硬件                            |
 |   USB Controller  UART/serdev  SDIO/MMC Host          |
 +--------------------------------------------------------+

核心源码文件索引:

文件 说明
include/net/bluetooth/bluetooth.h 基础类型、协议号、socket 选项定义
include/net/bluetooth/hci_core.h hci_devhci_connhci_chan 等核心结构
include/net/bluetooth/l2cap.h L2CAP 协议结构、l2cap_connl2cap_chan
net/bluetooth/hci_core.c HCI 设备注册、发现缓存、TX/RX 工作队列
net/bluetooth/hci_conn.c 连接建立、断开、SCO 参数配置
net/bluetooth/hci_event.c 全部 HCI 事件和 LE meta 事件处理
net/bluetooth/hci_sync.c HCI 同步命令框架、初始化序列
net/bluetooth/l2cap_core.c L2CAP 信道管理、PSM 分配、ERTM 状态机
net/bluetooth/mgmt.c MGMT 接口命令与事件分发
net/bluetooth/smp.c SMP 配对协议、LE SC 加密算法
net/bluetooth/af_bluetooth.c AF_BLUETOOTH socket 族注册与创建
drivers/bluetooth/btusb.c 通用 USB 蓝牙驱动
drivers/bluetooth/hci_ldisc.c UART HCI line discipline 驱动

2. BlueZ 内核协议栈层次

协议号定义

include/net/bluetooth/bluetooth.h 第 52-61 行定义了所有 Bluetooth 协议号:

#define BTPROTO_L2CAP   0
#define BTPROTO_HCI     1
#define BTPROTO_SCO     2
#define BTPROTO_RFCOMM  3
#define BTPROTO_BNEP    4
#define BTPROTO_CMTP    5
#define BTPROTO_HIDP    6
#define BTPROTO_AVDTP   7
#define BTPROTO_ISO     8
#define BTPROTO_LAST    BTPROTO_ISO

协议族号为 AF_BLUETOOTH = 31(第 39 行)。

BT_MAX_PROTO = BTPROTO_LAST + 1 = 9,对应 9 个可注册的子协议。

版本信息

// include/net/bluetooth/bluetooth.h,第 34-35 行
#define BT_SUBSYS_VERSION   2
#define BT_SUBSYS_REVISION  22

当前 MGMT 接口版本(net/bluetooth/mgmt.c,第 43-44 行):

#define MGMT_VERSION    1
#define MGMT_REVISION   23

3. HCI 设备抽象:struct hci_dev

struct hci_dev 是内核蓝牙子系统中最重要的数据结构,定义在 include/net/bluetooth/hci_core.h 第 355-664 行,代表一个完整的 HCI 控制器。

3.1 结构体主要字段分组

struct hci_dev {
    /* === 标识与基础信息 === */
    struct list_head list;       // 全局 hci_dev_list 链表节点
    struct mutex     lock;       // 设备大锁
    struct srcu_struct srcu;     // SRCU(sleepable RCU)
    const char       *name;      // "hci0", "hci1" 等
    unsigned long    flags;      // HCI_UP, HCI_INQUIRY 等
    __u16            id;         // 数字索引,由 ida_alloc_max() 分配
    __u8             bus;        // HCI_USB, HCI_UART, HCI_SDIO 等

    /* === 地址信息 === */
    bdaddr_t bdaddr;             // 公共 BD 地址
    bdaddr_t random_addr;        // LE 随机地址
    bdaddr_t static_addr;        // LE 静态随机地址
    bdaddr_t rpa;                // 当前 Resolvable Private Address

    /* === 特性与版本 === */
    __u8  features[HCI_MAX_PAGES][8];   // BR/EDR LMP 特性位图
    __u8  le_features[248];             // LE 特性位图
    __u8  hci_ver;                      // HCI 版本
    __u16 manufacturer;                 // 制造商 ID

    /* === LE 参数 === */
    __u8  le_scan_type;                 // LE_SCAN_PASSIVE / LE_SCAN_ACTIVE
    __u16 le_scan_interval;
    __u16 le_scan_window;
    __u16 le_conn_min_interval;
    __u16 le_conn_max_interval;
    __u8  le_accept_list_size;          // Accept list(白名单)大小
    __u8  le_resolv_list_size;          // 地址解析列表大小
    __u8  le_num_of_adv_sets;           // 扩展广播集数量

    /* === 流控计数器 === */
    unsigned int acl_cnt;     // ACL 数据包可用配额
    unsigned int sco_cnt;     // SCO 配额
    unsigned int le_cnt;      // LE ACL 配额
    unsigned int iso_cnt;     // ISO 配额
    atomic_t     cmd_cnt;     // HCI 命令配额

    /* === MTU === */
    unsigned int acl_mtu, sco_mtu, le_mtu, iso_mtu;

    /* === 工作队列 === */
    struct workqueue_struct *workqueue;      // 一般异步任务
    struct workqueue_struct *req_workqueue;  // HCI 请求同步任务
    struct work_struct       rx_work;        // 接收数据处理
    struct work_struct       cmd_work;       // 命令发送
    struct work_struct       tx_work;        // 数据发送

    /* === SKB 队列 === */
    struct sk_buff_head rx_q;      // 从硬件收到的原始 SKB
    struct sk_buff_head raw_q;     // 原始 HCI 包(for HCI socket)
    struct sk_buff_head cmd_q;     // 待发送 HCI 命令队列

    /* === 连接哈希表 === */
    struct hci_conn_hash conn_hash;

    /* === 密钥存储 === */
    struct list_head link_keys;            // BR/EDR link key 列表
    struct list_head long_term_keys;       // LE LTK 列表
    struct list_head identity_resolving_keys; // LE IRK 列表

    /* === 发现状态机 === */
    struct discovery_state discovery;

    /* === 驱动回调函数(类似 ops 接口)=== */
    int  (*open)(struct hci_dev *hdev);
    int  (*close)(struct hci_dev *hdev);
    int  (*flush)(struct hci_dev *hdev);
    int  (*setup)(struct hci_dev *hdev);
    int  (*shutdown)(struct hci_dev *hdev);
    int  (*send)(struct hci_dev *hdev, struct sk_buff *skb);
    void (*notify)(struct hci_dev *hdev, unsigned int evt);
    void (*hw_error)(struct hci_dev *hdev, u8 code);
    int  (*post_init)(struct hci_dev *hdev);
    int  (*set_diag)(struct hci_dev *hdev, bool enable);
    int  (*set_bdaddr)(struct hci_dev *hdev, const bdaddr_t *bdaddr);
    void (*reset)(struct hci_dev *hdev);
    bool (*wakeup)(struct hci_dev *hdev);
};

3.2 驱动回调(hci_dev_ops 等效接口)

Linux Bluetooth 不使用单独的 hci_dev_ops 结构体,而是将回调函数直接嵌入 struct hci_dev(第 645-663 行)。这是一组必须由传输层驱动实现的操作:

回调 含义
open 上电并初始化硬件
close 关闭硬件
flush 清空发送队列
setup 初始化固件/补丁(btusb 中的 btusb_setup_*
shutdown 优雅关机
send 将 SKB 发往硬件
notify 通知驱动状态变化(SCO 开关等)
hw_error 硬件错误回调
set_bdaddr 设置本地蓝牙地址
wakeup 判断是否允许唤醒系统

3.3 设备注册流程

hci_register_dev()net/bluetooth/hci_core.c 第 2585 行)是驱动完成初始化后调用的入口:

// hci_core.c:2585
int hci_register_dev(struct hci_dev *hdev)
{
    // 1. 验证必须实现的回调
    if (!hdev->open || !hdev->close || !hdev->send)
        return -EINVAL;

    // 2. 从 IDA 分配设备 ID(hci0, hci1 ...)
    id = ida_alloc_max(&hci_index_ida, HCI_MAX_ID - 1, GFP_KERNEL);

    // 3. 创建有序工作队列(高优先级)
    hdev->workqueue = alloc_ordered_workqueue("%s", WQ_HIGHPRI, hdev->name);
    hdev->req_workqueue = alloc_ordered_workqueue("%s", WQ_HIGHPRI, ...);

    // 4. 注册 sysfs device,创建 debugfs 目录
    device_add(&hdev->dev);
    hdev->debugfs = debugfs_create_dir(hdev->name, bt_debugfs);

    // 5. 注册 rfkill
    hdev->rfkill = rfkill_alloc(...);

    // 6. 加入全局 hci_dev_list
    write_lock(&hci_dev_list_lock);
    list_add(&hdev->list, &hci_dev_list);
    write_unlock(&hci_dev_list_lock);

    // 7. 调度 setup 工作,触发 HCI Reset 和特性读取
    queue_work(hdev->req_workqueue, &hdev->power_on);
}

HCI_MAX_ID = 10000(第 45 行),系统支持最多 10000 个 HCI 设备。

3.4 设备查找

net/bluetooth/hci_core.c 第 67 行实现了按 ID 查找设备:

static struct hci_dev *__hci_dev_get(int index, int *srcu_index)
{
    read_lock(&hci_dev_list_lock);
    list_for_each_entry(d, &hci_dev_list, list) {
        if (d->id == index) {
            hdev = hci_dev_hold(d);   // 引用计数 +1
            if (srcu_index)
                *srcu_index = srcu_read_lock(&d->srcu);
            break;
        }
    }
    read_unlock(&hci_dev_list_lock);
}

4. HCI 连接抽象:struct hci_conn

struct hci_conninclude/net/bluetooth/hci_core.h 第 679-788 行)代表一条物理级蓝牙连接,无论是 BR/EDR ACL、SCO、LE 还是 ISO CIS/BIS。

4.1 连接类型

// 连接类型由 hci_conn.type 字段区分
// include/net/bluetooth/hci.h 中定义:
#define SCO_LINK        0x00
#define ACL_LINK        0x01
#define ESCO_LINK       0x02
#define LE_LINK         0x80
#define ISO_LINK        0x81
#define INVALID_LINK    0xff

4.2 连接状态机

hci_conn.state 字段遵循标准 BT socket 状态机,状态值定义于 include/net/bluetooth/bluetooth.hBT_CONNECTEDBT_OPENBT_CONNECTBT_CONNECT2BT_CONFIGBT_DISCONNBT_CLOSED):

  BT_OPEN ──[连接请求]──> BT_CONNECT
                              |
                              v
                        BT_CONNECT2  <── 等待对端响应
                              |
                              v
                        BT_CONFIG    <── 执行 L2CAP 配置
                              |
                              v
                        BT_CONNECTED <── 数据传输中
                              |
                    [断连请求或超时]
                              |
                              v
                        BT_DISCONN   <── 等待断连完成
                              |
                              v
                        BT_CLOSED

4.3 关键字段解析

struct hci_conn {
    struct list_head list;      // 挂在 hci_dev.conn_hash.list

    atomic_t refcnt;            // 引用计数

    bdaddr_t dst;               // 对端蓝牙地址
    __u8     dst_type;          // BDADDR_BREDR / BDADDR_LE_PUBLIC / BDADDR_LE_RANDOM
    bdaddr_t src;               // 本地地址
    __u16    handle;            // HCI connection handle(0x0000-0x0EFF)
    __u16    state;             // BT_OPEN / BT_CONNECTED 等
    __u8     type;              // ACL_LINK / SCO_LINK / LE_LINK / ISO_LINK
    __u8     role;              // HCI_ROLE_MASTER / HCI_ROLE_SLAVE
    bool     out;               // true = 本端发起的出向连接

    /* 安全相关 */
    __u8  sec_level;            // BT_SECURITY_SDP/LOW/MEDIUM/HIGH/FIPS
    __u8  auth_type;
    __u8  enc_key_size;         // 加密密钥长度(字节)
    __u8  io_capability;        // IO 能力(用于 SSP/SMP 配对)

    /* LE 专用参数 */
    __u16 le_conn_min_interval;
    __u16 le_conn_max_interval;
    __u16 le_conn_interval;     // 协商后的实际 conn interval
    __u16 le_conn_latency;      // peripheral latency
    __u16 le_supv_timeout;      // supervision timeout

    /* ISO QoS(CIS/BIS)*/
    struct bt_iso_qos iso_qos;
    __u8 num_bis;
    __u8 bis[HCI_MAX_ISO_BIS];

    /* 发送队列 */
    struct sk_buff_head data_q;
    struct list_head    chan_list;   // 挂载在此连接上的 l2cap_chan 列表

    /* 关联的父设备 */
    struct hci_dev *hdev;
    void           *l2cap_data;    // l2cap_conn 指针
    void           *sco_data;
    void           *iso_data;

    /* 延迟工作 */
    struct delayed_work disc_work;        // 断连定时器
    struct delayed_work le_conn_timeout;  // LE 连接超时

    /* 驱动回调 */
    void (*connect_cfm_cb)(struct hci_conn *conn, u8 status);
    void (*security_cfm_cb)(struct hci_conn *conn, u8 status);
    void (*disconn_cfm_cb)(struct hci_conn *conn, u8 reason);
    void (*cleanup)(struct hci_conn *conn);
};

4.4 连接哈希表

struct hci_conn_hash(第 128-137 行)是 hci_dev 中管理所有连接的容器:

struct hci_conn_hash {
    struct list_head list;          // 所有连接的链表头
    unsigned int     acl_num;       // 当前 ACL 连接数
    unsigned int     sco_num;       // 当前 SCO 连接数
    unsigned int     cis_num;       // ISO CIS 连接数
    unsigned int     bis_num;       // ISO BIS 连接数
    unsigned int     pa_num;        // Periodic Advertisement 连接数
    unsigned int     le_num;        // LE 连接总数
    unsigned int     le_num_peripheral; // 作为 peripheral 的 LE 连接数
};

5. HCI 传输层驱动:USB、UART、SDIO

5.1 USB 驱动:btusb

文件drivers/bluetooth/btusb.c

btusb 是最常用的蓝牙传输层驱动,支持所有符合 Bluetooth USB 规范的设备(Class e0/01/01)。

USB 端点映射

一个标准 USB 蓝牙设备有三类端点(btusb_probe() 第 4066-4080 行):

Interface 0:
  ├── Interrupt IN  ──> HCI 事件接收(HCI_EVENT_PKT)
  ├── Bulk IN       ──> ACL 数据接收(HCI_ACLDATA_PKT)
  └── Bulk OUT      ──> ACL 数据发送 + HCI 命令发送

Interface 1 (等时):
  ├── Isoc IN       ──> SCO 语音数据接收
  └── Isoc OUT      ──> SCO 语音数据发送

驱动操作绑定(btusb_probe 第 4164-4167 行)

hdev->open    = btusb_open;
hdev->close   = btusb_close;
hdev->flush   = btusb_flush;
hdev->send    = btusb_send_frame;   // 根据厂商可能替换为 btusb_send_frame_intel / _mtk
hdev->notify  = btusb_notify;

设备标志位(第 41-69 行)

#define BTUSB_IGNORE            BIT(0)   // 应忽略该接口
#define BTUSB_INTEL_COMBINED    BIT(8)   // Intel 组合固件设备
#define BTUSB_BCM_PATCHRAM      BIT(10)  // Broadcom patchram 设备
#define BTUSB_REALTEK           BIT(16)  // Realtek 设备
#define BTUSB_MEDIATEK          BIT(20)  // MediaTek 设备
#define BTUSB_QCA_WCN6855       BIT(23)  // Qualcomm WCN6855
#define BTUSB_WIDEBAND_SPEECH   BIT(21)  // 支持宽带语音

数据包发送路径

应用层 write()
    |
    v
l2cap_sock_sendmsg()
    |
    v
hci_send_acl() / hci_send_cmd()
    |
    v  (enqueue to hdev->cmd_q 或 hci_conn->data_q)
hci_tx_work (work_struct)
    |
    v
hdev->send(hdev, skb) = btusb_send_frame()
    |
    v  (根据 bt_cb(skb)->pkt_type 选择端点)
usb_fill_bulk_urb()  或  usb_fill_control_urb()
    |
    v
USB Host Controller

5.2 UART 驱动:hci_uart(Line Discipline)

文件drivers/bluetooth/hci_ldisc.chci_h4.chci_h5.chci_bcsp.c

UART 传输通过 TTY Line Discipline(N_HCI,ldisc id = 15)实现。

协议注册(hci_ldisc.c 第 40-54 行)

static const struct hci_uart_proto *hup[HCI_UART_MAX_PROTO];

int hci_uart_register_proto(const struct hci_uart_proto *p)
{
    if (p->id >= HCI_UART_MAX_PROTO)
        return -EINVAL;
    hup[p->id] = p;
    BT_INFO("HCI UART protocol %s registered", p->name);
    return 0;
}

支持的 UART 子协议:

子协议 文件 特点
H4 (HCI_UART_H4) hci_h4.c 最简单,4 字节头标识包类型
BCSP (HCI_UART_BCSP) hci_bcsp.c 带 CRC 和重传的可靠传输
H5 (HCI_UART_3WIRE) hci_h5.c 三线串口,SLIP 编码
LL (HCI_UART_LL) hci_ll.c TI CC256x 专用
ATH3K (HCI_UART_ATH3K) hci_ath.c Qualcomm Atheros
QCA (HCI_UART_QCA) hci_qca.c Qualcomm QCA 系列
BCM (HCI_UART_BCM) hci_bcm.c Broadcom UART
INTEL (HCI_UART_INTEL) hci_intel.c Intel UART

UART TX 工作机制(hci_ldisc.c 第 98-143 行)

// 非抢占式 TX 调度
int hci_uart_tx_wakeup(struct hci_uart *hu)
{
    set_bit(HCI_UART_TX_WAKEUP, &hu->tx_state);
    if (test_and_set_bit(HCI_UART_SENDING, &hu->tx_state))
        goto no_schedule;
    schedule_work(&hu->write_work);
    ...
}

5.3 SDIO 驱动:btsdio / btmrvl_sdio

文件drivers/bluetooth/btsdio.cbtmrvl_sdio.c

SDIO 蓝牙驱动通过 sdio_claim_irq() 注册中断,在中断上下文中触发接收工作。

Marvell SDIO(btmrvl_sdio.c)使用专用固件加载和命令通道,与通用 btsdio 略有区别,提供 btmrvl_sdio_card_reg 硬件寄存器映射。


6. HCI 核心工作流:命令/数据/事件

6.1 三条主要工作流

net/bluetooth/hci_core.c 第 50-52 行声明了三个工作项处理函数:

static void hci_rx_work(struct work_struct *work);   // 处理接收到的 HCI 包
static void hci_cmd_work(struct work_struct *work);  // 发送 HCI 命令
static void hci_tx_work(struct work_struct *work);   // 发送 ACL/SCO/ISO 数据

6.2 HCI 命令发送流程

hci_send_cmd(hdev, opcode, plen, param)
    |
    v  分配 SKB,设置 bt_cb(skb)->pkt_type = HCI_COMMAND_PKT
    v  设置 hci_skb_opcode(skb) = opcode
    |
    v  skb 放入 hdev->cmd_q
    |
    v  queue_work(hdev->workqueue, &hdev->cmd_work)
    |
    v  hci_cmd_work():
          if (atomic_read(&hdev->cmd_cnt) > 0) {
              skb = skb_dequeue(&hdev->cmd_q);
              hdev->sent_cmd = skb;  // 保存以便匹配响应
              hdev->send(hdev, skb);
              atomic_dec(&hdev->cmd_cnt);
          }

6.3 ACL 数据接收流程

btusb_bulk_in_complete()  (URB 完成回调)
    |
    v  skb_queue_tail(&hdev->rx_q, skb)
    |
    v  queue_work(hdev->workqueue, &hdev->rx_work)
    |
    v  hci_rx_work():
          while ((skb = skb_dequeue(&hdev->rx_q))) {
              switch (bt_cb(skb)->pkt_type) {
              case HCI_EVENT_PKT:
                  hci_event_packet(hdev, skb);
                  break;
              case HCI_ACLDATA_PKT:
                  hci_acldata_packet(hdev, skb);
                  break;
              case HCI_SCODATA_PKT:
                  hci_scodata_packet(hdev, skb);
                  break;
              }
          }

7. HCI 事件处理:hci_event.c

7.1 事件分发架构

net/bluetooth/hci_event.c 使用静态分发表处理所有 HCI 事件,每个事件对应一个处理函数。

对于 BR/EDR 标准事件(如连接完成、断连完成、链接键通知等),在文件末尾的 hci_ev_table[] 数组中注册。

对于 LE Meta 事件,通过 hci_le_meta_evt()(第 7432 行)分发到 hci_le_ev_table[]

7.2 LE Meta 事件处理核心函数

// hci_event.c:7432
static void hci_le_meta_evt(struct hci_dev *hdev, void *data,
                            struct sk_buff *skb, u16 *opcode, u8 *status,
                            hci_req_complete_t *req_complete,
                            hci_req_complete_skb_t *req_complete_skb)
{
    struct hci_ev_le_meta *ev = data;
    const struct hci_le_ev *subev;

    // 从 hci_le_ev_table 中按 subevent 号查找处理函数
    subev = &hci_le_ev_table[ev->subevent];
    if (!subev->func)
        return;

    // 长度校验(min_len 和 max_len 均由表项指定)
    if (skb->len < subev->min_len) { ... return; }

    data = hci_le_ev_skb_pull(hdev, skb, ev->subevent, subev->min_len);
    subev->func(hdev, data, skb);  // 调用对应子事件处理函数
}

7.3 关键 LE 子事件处理函数

子事件 函数 行号
HCI_EV_LE_CONN_COMPLETE hci_le_conn_complete_evt() 5866
HCI_EV_LE_ADVERTISING_REPORT hci_le_adv_report_evt() 6381
HCI_EV_LE_CONN_UPDATE_COMPLETE hci_le_conn_update_complete_evt() 6052
HCI_EV_LE_META (总入口) hci_le_meta_evt() 7432

7.4 LE 连接完成事件处理

le_conn_complete_evt()(第 5703 行)是 LE 连接建立的关键路径:

static void le_conn_complete_evt(struct hci_dev *hdev, u8 status,
                                 bdaddr_t *bdaddr, u8 bdaddr_type,
                                 bdaddr_t *local_rpa, u8 role, u16 handle,
                                 u16 interval, u16 latency,
                                 u16 supervision_timeout)
{
    hci_dev_lock(hdev);

    // 广播停止:控制器建立连接后隐式停止广播
    hci_dev_clear_flag(hdev, HCI_LE_ADV);

    // 查找或创建 hci_conn 对象
    conn = hci_conn_hash_lookup_role(hdev, LE_LINK, role, bdaddr);
    if (!conn || ...) {
        conn = hci_conn_add_unset(hdev, LE_LINK, bdaddr, bdaddr_type, role);
    } else {
        cancel_delayed_work(&conn->le_conn_timeout);
    }

    // 防止重复处理:检查 handle 是否已设置
    if (!HCI_CONN_HANDLE_UNSET(conn->handle)) {
        bt_dev_err(hdev, "Ignoring HCI_Connection_Complete for existing connection");
        goto unlock;
    }

    // 设置连接 handle 和 LE 参数,通知 L2CAP 层
    ...
}

7.5 广播报告处理(LE 扫描)

hci_le_adv_report_evt()(第 6381 行)处理 HCI_EV_LE_ADVERTISING_REPORT 事件,将扫描结果转发给 mgmt_device_found(),最终通过 MGMT 事件 MGMT_EV_DEVICE_FOUND 通知用户态。

7.6 Command Complete / Command Status 处理

hci_event.c 中大量 hci_cc_* 函数处理 HCI 命令完成事件,例如(第 83-399 行):

  • hci_cc_inquiry_cancel():处理 Inquiry Cancel 的完成
  • hci_cc_reset():处理 HCI Reset 完成,清空广播数据、重置扫描类型
  • hci_cc_write_local_name():处理写本地名称完成,通知 MGMT 层
  • hci_cc_role_discovery():更新 hci_conn.role 字段

8. L2CAP 层:连接、信道与协议复用

8.1 L2CAP 协议概述

L2CAP(Logical Link Control and Adaptation Protocol)是蓝牙协议栈的多路复用层,位于 HCI 之上,为上层协议(RFCOMM、BNEP、SMP、ATT 等)提供统一的信道抽象。

核心数据结构有两个:struct l2cap_conn(连接级)和 struct l2cap_chan(信道级)。

8.2 struct l2cap_conn

定义于 include/net/bluetooth/l2cap.h 第 643-675 行:

struct l2cap_conn {
    struct hci_conn  *hcon;       // 关联的 HCI 连接
    struct hci_chan  *hchan;      // 关联的 HCI 逻辑信道

    unsigned int     mtu;         // 当前连接 MTU

    __u32  feat_mask;             // 对端的 L2CAP 扩展特性位图
    __u8   remote_fixed_chan;     // 对端支持的固定信道位图
    __u8   local_fixed_chan;      // 本地支持的固定信道位图

    __u8   info_state;            // Info Request 握手状态
    __u8   info_ident;

    struct delayed_work  info_timer;     // Info Request 超时定时器

    struct sk_buff      *rx_skb;         // 当前正在组装的 SDU
    __u32                rx_len;
    struct ida           tx_ida;         // 发送 PDU id 分配器

    struct sk_buff_head  pending_rx;     // 暂存的接收 SKB
    struct work_struct   pending_rx_work;

    struct delayed_work  id_addr_timer;  // LE 身份地址解析定时器

    __u8            disc_reason;
    struct l2cap_chan *smp;              // SMP 专用信道

    struct list_head chan_l;             // 挂载在本连接上的所有 l2cap_chan
    struct mutex     lock;
    struct kref      ref;
    struct list_head users;             // l2cap_user 回调(RFCOMM、BNEP 等)
};

8.3 struct l2cap_chan

定义于 include/net/bluetooth/l2cap.h 第 514 行,是单个 L2CAP 信道的完整描述:

struct l2cap_chan {
    struct l2cap_conn *conn;    // 所属 l2cap_conn
    struct kref        kref;    // 引用计数
    __u8               state;  // BT_CONNECTED, BT_OPEN 等

    /* 地址信息 */
    bdaddr_t  dst, src;
    __u8      dst_type, src_type;
    __le16    psm;              // Protocol/Service Multiplexer(服务端口)
    __le16    sport;            // 服务端 PSM(监听时使用)
    __u16     dcid, scid;       // 目标/源信道标识符(CID)

    /* MTU 与窗口 */
    __u16  imtu;                // 入方向 MTU
    __u16  omtu;                // 出方向 MTU
    __u8   mode;                // L2CAP_MODE_BASIC / ERTM / STREAMING / LE_FLOWCTL
    __u8   chan_type;           // L2CAP_CHAN_RAW / CONN_LESS / CONN_ORIENTED / FIXED

    /* 安全级别 */
    __u8   sec_level;

    /* ERTM 滑动窗口 */
    __u16  tx_win;              // 发送窗口大小
    __u16  tx_win_max;
    __u16  ack_win;
    __u8   max_tx;              // 最大重传次数
    __u16  retrans_timeout;
    __u16  monitor_timeout;
    __u16  mps;                 // Maximum PDU Payload Size

    /* LE 流量控制 */
    __u16  tx_credits;          // 剩余发送信用
    __u16  rx_credits;          // 剩余接收信用

    /* ERTM 序列号 */
    __u16  next_tx_seq;
    __u16  expected_ack_seq;
    __u16  expected_tx_seq;
    __u16  buffer_seq;
    __u16  last_acked_seq;

    /* 重传定时器 */
    struct delayed_work retrans_timer;
    struct delayed_work monitor_timer;
    struct delayed_work ack_timeout;
};

8.4 CID 分配

include/net/bluetooth/l2cap.h 定义了固定与动态 CID 范围(第 258-267 行):

/* 固定 CID(BR/EDR + LE) */
#define L2CAP_CID_SIGNALING     0x0001   // BR/EDR 信令
#define L2CAP_CID_CONN_LESS     0x0002   // 无连接数据
#define L2CAP_CID_ATT           0x0004   // ATT(GATT)
#define L2CAP_CID_LE_SIGNALING  0x0005   // LE 信令
#define L2CAP_CID_SMP           0x0006   // LE SMP
#define L2CAP_CID_SMP_BREDR     0x0007   // BR/EDR SMP

/* 动态 CID 范围 */
#define L2CAP_CID_DYN_START     0x0040
#define L2CAP_CID_LE_DYN_END    0x007f   // LE 动态 CID 上限
#define L2CAP_CID_DYN_END       0xffff   // BR/EDR 动态 CID 上限

8.5 PSM 分配

l2cap_core.c 第 182-224 行实现了 l2cap_add_psm(),为信道分配 PSM 值:

  • BR/EDR 动态 PSM:从 L2CAP_PSM_DYN_START (0x1001) 开始,步长 2(只用奇数)
  • LE 动态 PSM:从 L2CAP_PSM_LE_DYN_START (0x0080) 开始,步长 1

标准 PSM 值(第 246-250 行):

#define L2CAP_PSM_SDP    0x0001  // Service Discovery Protocol
#define L2CAP_PSM_RFCOMM 0x0003  // RFCOMM(串口模拟)
#define L2CAP_PSM_3DSP   0x0021  // 3D 同步
#define L2CAP_PSM_IPSP   0x0023  // 6LoWPAN

9. L2CAP 信道类型与传输模式

9.1 信道类型(chan_type

// include/net/bluetooth/l2cap.h:687-690
#define L2CAP_CHAN_RAW          1   // 原始 HCI 数据(HCI socket)
#define L2CAP_CHAN_CONN_LESS    2   // 无连接(G-Frames)
#define L2CAP_CHAN_CONN_ORIENTED 3  // 面向连接(标准 L2CAP 连接)
#define L2CAP_CHAN_FIXED        4   // 固定 CID(ATT、SMP、LE 信令)

9.2 传输模式(mode

// include/net/bluetooth/l2cap.h:348-359
#define L2CAP_MODE_BASIC      0x00  // 基础模式(默认)
#define L2CAP_MODE_RETRANS    0x01  // 重传模式(已废弃)
#define L2CAP_MODE_FLOWCTL    0x02  // 流控模式(已废弃)
#define L2CAP_MODE_ERTM       0x03  // 增强重传模式(ERTM)
#define L2CAP_MODE_STREAMING  0x04  // 流媒体模式
#define L2CAP_MODE_LE_FLOWCTL 0x80  // LE 基于信用的流控(内核内部使用)
#define L2CAP_MODE_EXT_FLOWCTL 0x81 // LE 扩展信用流控(ECRED)

对应用户空间 socket 选项(include/net/bluetooth/bluetooth.h,第 160-164 行):

#define BT_MODE_BASIC       0x00
#define BT_MODE_ERTM        0x01
#define BT_MODE_STREAMING   0x02
#define BT_MODE_LE_FLOWCTL  0x03
#define BT_MODE_EXT_FLOWCTL 0x04

9.3 ERTM(增强重传模式)状态机

ERTM 在 l2cap_core.c 中实现,使用三个定时器(第 280-294 行):

  • retrans_timer:重传超时(默认 2000ms,L2CAP_DEFAULT_RETRANS_TO
  • monitor_timer:监控超时(默认 12000ms,L2CAP_DEFAULT_MONITOR_TO
  • ack_timeout:延迟 ACK 定时器(默认 200ms,L2CAP_DEFAULT_ACK_TO

ERTM S 帧监督函数(include/net/bluetooth/l2cap.h 第 180-183 行):

#define L2CAP_SUPER_RR   0x00  // Receiver Ready(请求对端继续发)
#define L2CAP_SUPER_REJ  0x01  // Reject(请求从某序号重传)
#define L2CAP_SUPER_RNR  0x02  // Receiver Not Ready(流控暂停)
#define L2CAP_SUPER_SREJ 0x03  // Selective Reject(选择性重传)

9.4 LE 信用流控(LE_FLOWCTL / EXT_FLOWCTL)

LE 基于信用的流控使用 tx_creditsrx_credits 字段。接收方通过 L2CAP_LE_CREDITS(命令码 0x16)分配信用给发送方。

LE_FLOWCTL_MAX_CREDITS = 65535l2cap_core.c 第 43 行)。

ECRED(Enhanced Credit Based Flow Control)支持在单次请求中同时建立最多 L2CAP_ECRED_CONN_SCID_MAX = 5 个信道(include/net/bluetooth/l2cap.h 第 50 行)。

enable_ecred 标志(l2cap_core.c 第 46 行)由 Kconfig CONFIG_BT_LE_L2CAP_ECRED 控制:

bool enable_ecred = IS_ENABLED(CONFIG_BT_LE_L2CAP_ECRED);

9.5 L2CAP 信道查找函数

l2cap_core.c 提供了多种信道查找方式:

// 按 DCID(目标 CID)查找
static struct l2cap_chan *__l2cap_get_chan_by_dcid(
    struct l2cap_conn *conn, u16 cid)     // 行 90

// 按 SCID(源 CID)查找
static struct l2cap_chan *__l2cap_get_chan_by_scid(
    struct l2cap_conn *conn, u16 cid)     // 行 102

// 带引用锁的安全版本
static struct l2cap_chan *l2cap_get_chan_by_scid(
    struct l2cap_conn *conn, u16 cid)     // 行 117

// 按 PSM 查找全局监听信道
static struct l2cap_chan *__l2cap_global_chan_by_addr(
    __le16 psm, bdaddr_t *src, u8 src_type) // 行 164

10. 低功耗蓝牙(LE):扫描、广播与连接

10.1 LE 扫描参数

hci_dev 中维护多套 LE 扫描参数(第 407-417 行),针对不同场景动态切换:

__u16 le_scan_interval;              // 通用扫描间隔
__u16 le_scan_window;
__u16 le_scan_int_suspend;           // 挂起时的扫描参数
__u16 le_scan_window_suspend;
__u16 le_scan_int_discovery;         // 发现模式的扫描参数
__u16 le_scan_window_discovery;
__u16 le_scan_int_adv_monitor;       // 广播监控的扫描参数
__u16 le_scan_window_adv_monitor;
__u16 le_scan_int_connect;           // 连接发起前的扫描参数
__u16 le_scan_window_connect;

10.2 LE 发现状态机

struct discovery_stateinclude/net/bluetooth/hci_core.h 第 72-99 行)管理 LE/BR 发现过程:

struct discovery_state {
    int  type;
    enum {
        DISCOVERY_STOPPED,     // 已停止
        DISCOVERY_STARTING,    // 正在启动
        DISCOVERY_FINDING,     // 正在扫描/查询
        DISCOVERY_RESOLVING,   // 正在解析名称
        DISCOVERY_STOPPING,    // 正在停止
    } state;

    struct list_head all;      // 发现的所有设备
    struct list_head unknown;  // 名称未知的设备
    struct list_head resolve;  // 需要解析名称的设备

    bdaddr_t  last_adv_addr;
    u8        last_adv_addr_type;
    s8        last_adv_rssi;
    u32       last_adv_flags;
    u8        last_adv_data[HCI_MAX_EXT_AD_LENGTH];
    u8        last_adv_data_len;

    bool      result_filtering;      // 结果过滤(按 RSSI/UUID)
    bool      limited;               // 仅发现 Limited Discoverable
    s8        rssi;                  // RSSI 过滤阈值
    u16       uuid_count;
    u8        (*uuids)[16];          // UUID 过滤列表
};

状态转换由 hci_discovery_set_state()hci_core.c 第 122 行)驱动,切换时向 MGMT 层发送 MGMT_EV_DISCOVERING 事件。

10.3 LE 广播(Advertising)

hci_dev 支持多广播实例(adv_instances 链表),最多 HCI_MAX_ADV_INSTANCES = 5 个实例(第 279 行)。

每个广播实例由 struct adv_info(第 243-271 行)描述:

struct adv_info {
    bool     enabled;
    bool     periodic;           // 是否为 Periodic Advertising
    bool     periodic_enabled;
    __u8     instance;           // 实例 ID(0 = 默认)
    __u8     handle;             // 硬件 advertising set handle
    __u32    flags;
    __u16    timeout;
    __u16    duration;
    __u16    adv_data_len;
    __u8     adv_data[HCI_MAX_EXT_AD_LENGTH];
    __u16    scan_rsp_len;
    __u8     scan_rsp_data[HCI_MAX_EXT_AD_LENGTH];
    __u16    per_adv_data_len;
    __u8     per_adv_data[HCI_MAX_PER_AD_LENGTH];
    __s8     tx_power;
    __u32    min_interval;
    __u32    max_interval;
    bdaddr_t random_addr;
    bool     rpa_expired;
    struct delayed_work rpa_expired_cb;  // RPA 轮换定时器
};

默认 RPA 超时:HCI_DEFAULT_RPA_TIMEOUT = 15 * 60(900 秒,第 345 行)。

10.4 LE 连接参数

hci_conn 中的 LE 连接参数(第 721-725 行)在 HCI_LE_Connection_Update_Complete 事件时更新:

__u16 le_conn_min_interval;  // 请求的最小连接间隔
__u16 le_conn_max_interval;  // 请求的最大连接间隔
__u16 le_conn_interval;      // 当前实际间隔(单位 1.25ms)
__u16 le_conn_latency;       // Peripheral Latency(允许跳过的 event 数)
__u16 le_supv_timeout;       // 监督超时(单位 10ms)

10.5 Accept List(白名单)与地址解析

LE Accept List(原 Whitelist)和 Resolving List 由 hci_dev 中的链表管理:

struct list_head le_accept_list;   // Accept List 条目
struct list_head le_resolv_list;   // Resolving List(IRK 地址解析)

Privacy 模式下,本地 IRK 存储在 hdev->irk[16](第 610 行),用于生成和解析 RPA。

10.6 ISO 链路(LE Audio)

hci_conn 中的 ISO 支持(第 740-742 行):

struct bt_iso_qos iso_qos;        // CIG/CIS 或 BIG/BIS 的 QoS 参数
__u8 num_bis;                     // BIS 数量
__u8 bis[HCI_MAX_ISO_BIS];        // BIS 索引列表

struct bt_iso_qosinclude/net/bluetooth/bluetooth.h 第 217-222 行)联合体支持单播(ucast)和广播(bcast)两种模式。


11. AF_BLUETOOTH Socket 层

11.1 协议族注册

net/bluetooth/af_bluetooth.c 实现了 AF_BLUETOOTH 协议族的注册和 socket 创建:

// af_bluetooth.c:44-46
#define BT_MAX_PROTO   (BTPROTO_LAST + 1)   // = 9
static const struct net_proto_family *bt_proto[BT_MAX_PROTO];
static DEFINE_RWLOCK(bt_proto_lock);

各子协议通过 bt_sock_register() 注册(第 85-103 行):

int bt_sock_register(int proto, const struct net_proto_family *ops)
{
    if (proto < 0 || proto >= BT_MAX_PROTO)
        return -EINVAL;

    write_lock(&bt_proto_lock);
    if (bt_proto[proto])
        err = -EEXIST;
    else
        bt_proto[proto] = ops;
    write_unlock(&bt_proto_lock);
    return err;
}
EXPORT_SYMBOL(bt_sock_register);

11.2 Socket 创建流程

bt_sock_create()(第 116 行)是 socket(AF_BLUETOOTH, type, proto) 系统调用的内核入口:

static int bt_sock_create(struct net *net, struct socket *sock,
                          int proto, int kern)
{
    // 1. 网络命名空间检查:仅支持 init_net
    if (net != &init_net)
        return -EAFNOSUPPORT;

    // 2. 未加载时触发自动加载模块
    if (!bt_proto[proto])
        request_module("bt-proto-%d", proto);

    // 3. 调用子协议的 create() 回调
    read_lock(&bt_proto_lock);
    if (bt_proto[proto] && try_module_get(bt_proto[proto]->owner)) {
        err = bt_proto[proto]->create(net, sock, proto, kern);
        if (!err)
            bt_sock_reclassify_lock(sock->sk, proto);  // 重新分类锁
        module_put(bt_proto[proto]->owner);
    }
    read_unlock(&bt_proto_lock);
    return err;
}

11.3 bt_sock_alloc()

第 146 行的 bt_sock_alloc() 是所有子协议创建 socket 的通用函数:

struct sock *bt_sock_alloc(struct net *net, struct socket *sock,
                           struct proto *prot, int proto, gfp_t prio, int kern)
{
    sk = sk_alloc(net, PF_BLUETOOTH, prio, prot, kern);
    sock_init_data(sock, sk);
    INIT_LIST_HEAD(&bt_sk(sk)->accept_q);   // 初始化 accept 队列
    sock_reset_flag(sk, SOCK_ZAPPED);
    sk->sk_protocol = proto;
    sk->sk_state    = BT_OPEN;

    // 记录创建进程的 PID 和凭证(用于审计)
    if (!kern) {
        sk->sk_peer_pid  = get_pid(task_tgid(current));
        sk->sk_peer_cred = get_current_cred();
    }
    return sk;
}

11.4 锁类注册

每个协议有独立的锁类,用于 lockdep 检测(第 48-72 行):

static const char *const bt_key_strings[BT_MAX_PROTO] = {
    "sk_lock-AF_BLUETOOTH-BTPROTO_L2CAP",
    "sk_lock-AF_BLUETOOTH-BTPROTO_HCI",
    "sk_lock-AF_BLUETOOTH-BTPROTO_SCO",
    "sk_lock-AF_BLUETOOTH-BTPROTO_RFCOMM",
    "sk_lock-AF_BLUETOOTH-BTPROTO_BNEP",
    "sk_lock-AF_BLUETOOTH-BTPROTO_CMTP",
    "sk_lock-AF_BLUETOOTH-BTPROTO_HIDP",
    "sk_lock-AF_BLUETOOTH-BTPROTO_AVDTP",
    "sk_lock-AF_BLUETOOTH-BTPROTO_ISO",
};

11.5 Socket 选项

include/net/bluetooth/bluetooth.h 定义了丰富的 socket 选项(第 68-260 行):

选项名 含义
BT_SECURITY 4 获取/设置安全级别(struct bt_security
BT_DEFER_SETUP 7 延迟建立连接(用于授权)
BT_FLUSHABLE 8 允许 L2CAP flush
BT_POWER 9 控制连接功耗(struct bt_power
BT_CHANNEL_POLICY 10 AMP/BR 信道策略
BT_VOICE 11 SCO 语音格式(struct bt_voice
BT_PHY 14 PHY 能力查询(BR/EDR/LE PHY 位图)
BT_MODE 15 L2CAP 传输模式
BT_ISO_QOS 17 ISO QoS 参数(struct bt_iso_qos
BT_CODEC 19 编解码器选择(struct bt_codec

安全级别(第 73-77 行):

#define BT_SECURITY_SDP      0  // 仅 SDP 查询,无需认证
#define BT_SECURITY_LOW      1  // 低安全性,无需认证但允许加密
#define BT_SECURITY_MEDIUM   2  // 需要认证
#define BT_SECURITY_HIGH     3  // 需要认证和加密
#define BT_SECURITY_FIPS     4  // FIPS 级别(128-bit 密钥)

12. MGMT 接口:用户态与内核的管理桥梁

12.1 架构概述

MGMT(Management Interface)是 bluetoothd 与内核之间的专用控制通道,通过 HCI_DEV_NONE(设备无关)的 HCI socket 通信,路径为:

bluetoothd
    |
    | socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI)
    | bind({ dev_id = HCI_DEV_NONE, channel = HCI_CHANNEL_CONTROL })
    |
    v
hci_sock_sendmsg()  -->  hci_mgmt_cmd()  -->  mgmt_commands[] 分发表
    |
    v
mgmt.c 中对应的处理函数
    |
    v
HCI 命令发送 / 状态变更 / 事件上报
    |
    v
mgmt_event() / mgmt_event_skb()  -->  hci_sock 广播回用户态

12.2 MGMT 命令列表

net/bluetooth/mgmt.c 第 46-136 行列出了所有支持的 MGMT 命令(当前 MGMT_REVISION=23),代表性命令包括:

基础配置:

  • MGMT_OP_READ_INDEX_LIST:枚举所有 HCI 设备
  • MGMT_OP_READ_INFO:读取控制器详细信息
  • MGMT_OP_SET_POWERED:上下电控制器
  • MGMT_OP_SET_DISCOVERABLE:设置可发现性
  • MGMT_OP_SET_CONNECTABLE:设置可连接性
  • MGMT_OP_SET_LE:启用/禁用 LE 功能
  • MGMT_OP_SET_BREDR:启用/禁用 BR/EDR 功能

密钥管理:

  • MGMT_OP_LOAD_LINK_KEYS:加载 BR/EDR link key
  • MGMT_OP_LOAD_LONG_TERM_KEYS:加载 LE LTK
  • MGMT_OP_LOAD_IRKS:加载 LE IRK(用于隐私解析)

配对操作:

  • MGMT_OP_PAIR_DEVICE:发起配对
  • MGMT_OP_CANCEL_PAIR_DEVICE:取消配对
  • MGMT_OP_UNPAIR_DEVICE:解除配对
  • MGMT_OP_PIN_CODE_REPLY:回复 PIN 码
  • MGMT_OP_USER_CONFIRM_REPLY:确认数字比较
  • MGMT_OP_USER_PASSKEY_REPLY:回复 Passkey

发现:

  • MGMT_OP_START_DISCOVERY:启动设备发现
  • MGMT_OP_STOP_DISCOVERY:停止发现
  • MGMT_OP_START_LIMITED_DISCOVERY:仅发现 Limited Discoverable 设备
  • MGMT_OP_START_SERVICE_DISCOVERY:按 UUID 过滤发现

广播:

  • MGMT_OP_ADD_ADVERTISING:添加广播实例
  • MGMT_OP_REMOVE_ADVERTISING:移除广播实例
  • MGMT_OP_ADD_EXT_ADV_PARAMS:扩展广播参数

新增(高版本):

  • MGMT_OP_SET_MESH_RECEIVER:Mesh 广播接收
  • MGMT_OP_HCI_CMD_SYNC:直接同步发送任意 HCI 命令(调试用)

12.3 MGMT 事件列表

第 138-183 行的 mgmt_events[] 是内核主动推送给 bluetoothd 的事件集合:

关键事件:

事件 触发时机
MGMT_EV_DEVICE_CONNECTED 设备连接成功
MGMT_EV_DEVICE_DISCONNECTED 设备断连
MGMT_EV_DEVICE_FOUND LE 扫描发现设备
MGMT_EV_NEW_LINK_KEY 产生新 BR/EDR link key
MGMT_EV_NEW_LONG_TERM_KEY 产生新 LE LTK
MGMT_EV_NEW_IRK 产生新 LE IRK
MGMT_EV_NEW_CSRK 产生新 CSRK
MGMT_EV_PIN_CODE_REQUEST 需要输入 PIN
MGMT_EV_USER_CONFIRM_REQUEST 需要确认数字
MGMT_EV_PASSKEY_NOTIFY 显示 Passkey
MGMT_EV_CONTROLLER_SUSPEND 控制器挂起
MGMT_EV_CONTROLLER_RESUME 控制器恢复
MGMT_EV_ADV_MONITOR_DEVICE_FOUND 广播监控匹配到设备

12.4 错误码转换

mgmt.c 第 219-283 行维护 HCI 错误码到 MGMT 错误码的映射表 mgmt_status_table[],将底层 HCI 错误码翻译为用户态友好的高层错误码。

12.5 MGMT 通道认证

第 185-211 行的 mgmt_untrusted_commands[] 定义了非特权进程(无 CAP_NET_ADMIN)可以使用的命令子集(仅只读命令,如 MGMT_OP_READ_INDEX_LISTMGMT_OP_READ_INFO)。


13. SMP(Security Manager Protocol)

13.1 概述

SMP 是 BLE 的安全管理协议,运行在 L2CAP 固定信道 CID=0x0006(LE SMP)或 CID=0x0007(BR/EDR SMP)之上。

net/bluetooth/smp.c 实现了完整的 SMP 协议,包括传统配对(LE Legacy Pairing)和 LE Secure Connections(SC)。

13.2 核心数据结构

struct smp_devsmp.c 第 85-94 行):每个 HCI 设备的 SMP 全局状态。

struct smp_dev {
    bool   local_oob;           // 是否有本地 OOB 数据
    u8     local_pk[64];        // 本地 ECDH 公钥
    u8     local_rand[16];      // 本地随机数(OOB 用)
    bool   debug_key;           // 是否使用 debug 密钥

    struct crypto_shash *tfm_cmac;  // AES-CMAC 算法实例
    struct crypto_kpp   *tfm_ecdh;  // ECDH 密钥交换算法实例
};

struct smp_chan(第 96-132 行):单次配对会话的完整状态。

struct smp_chan {
    struct l2cap_conn   *conn;
    struct delayed_work  security_timer;   // 配对超时(30s)
    unsigned long        allow_cmd;        // 当前允许接收的 SMP 命令位图

    u8  preq[7];   // Pairing Request PDU 缓存
    u8  prsp[7];   // Pairing Response PDU 缓存
    u8  prnd[16];  // 本地配对随机数
    u8  rrnd[16];  // 对端配对随机数
    u8  pcnf[16];  // 配对 Confirm 值
    u8  tk[16];    // Temporary Key(Legacy 配对)

    u8  enc_key_size;         // 协商的加密密钥长度
    u8  remote_key_dist;      // 对端密钥分发掩码

    /* 密钥存储 */
    struct smp_csrk *csrk;
    struct smp_csrk *responder_csrk;
    struct smp_ltk  *ltk;
    struct smp_ltk  *responder_ltk;
    struct smp_irk  *remote_irk;
    u8              *link_key;

    /* LE SC 专用 */
    u8  local_pk[64];          // 本地临时公钥
    u8  remote_pk[64];         // 对端公钥
    u8  dhkey[32];             // Diffie-Hellman 共享密钥
    u8  mackey[16];            // MAC 密钥(f5 输出)

    struct crypto_shash *tfm_cmac;
    struct crypto_kpp   *tfm_ecdh;
};

13.3 LE SC 加密函数

smp.c 实现了 Bluetooth Core Spec 中规定的全套 LE SC 加密函数,均基于 AES-CMAC(crypto_shash 接口)和 ECDH(crypto_kpp 接口):

aes_cmac()(第 169 行):AES-CMAC 基础函数,消息最大 80 字节(CMAC_MSG_MAX)。

smp_f4()(第 209 行):Confirm 值生成函数。

f4(U, V, X, Z) = AES-CMAC_X(U || V || Z)

smp_f5()(第 232 行):LTK 和 MacKey 生成函数(LE SC 专用)。

f5(W, N1, N2, A1, A2) -> MacKey || LTK

使用盐值 salt 和标识符 "btle" 来派生密钥,通过两次 AES-CMAC 计算分别得到 MacKey(counter=0)和 LTK(counter=1)。

smp_f6()(第 285 行):DHKey Check 验证函数,防止中间人攻击。

Debug 密钥(第 138-155 行):Core Spec 定义的公开调试密钥对,当 smp_debug_mode 开启时使用,仅用于测试目的:

static const u8 debug_pk[64] = { 0xe6, 0x9d, 0x35, 0x0e, ... };  // 公钥
static const u8 debug_sk[32] = { 0xbd, 0x1a, 0x3c, 0xcd, ... };  // 私钥

13.4 SMP 配对状态机

  初始化
     |
     v
  Pairing Request / Response
     |
     v
  [Legacy 配对]              [SC 配对]
  Just Works / Passkey /      Public Key Exchange
  OOB                         |
     |                        v
     |                    DHKey 计算(ECDH)
     |                        |
     v                        v
  Confirm / Random 交换    Authentication Stage 1
     |                    (f4/f5/f6 验证)
     v                        |
  STK 计算                    v
  (AES-128)               LTK / MacKey 生成(f5)
     |                        |
     v                        v
  加密连接                DHKey Check(f6)
     |                        |
     v                        v
  密钥分发                加密连接
  (LTK/IRK/CSRK/LinkKey)      |
                               v
                           密钥分发

13.5 SMP 密钥存储结构

include/net/bluetooth/hci_core.h 中定义的密钥结构:

// LE Long Term Key(第 201-212 行)
struct smp_ltk {
    bdaddr_t bdaddr;
    u8  bdaddr_type;
    u8  authenticated;   // 是否通过 MITM 认证
    u8  type;            // SMP_LTK / SMP_LTK_RESPONDER / SMP_LTK_P256
    u8  enc_size;        // 密钥有效字节数
    __le16 ediv;         // 加密密钥分散器
    __le64 rand;         // 随机值
    u8  val[16];         // LTK 值
};

// Identity Resolving Key(第 214-221 行)
struct smp_irk {
    bdaddr_t rpa;        // 当前对应的 RPA 地址
    bdaddr_t bdaddr;     // 身份地址
    u8  addr_type;
    u8  val[16];         // IRK 值
};

最小加密密钥长度:HCI_MIN_ENC_KEY_SIZE = 7(第 342 行)。


14. 上层协议:RFCOMM / BNEP / HIDP / ISO

14.1 RFCOMM(串口模拟)

  • 注册协议号:BTPROTO_RFCOMM = 3
  • L2CAP PSM:L2CAP_PSM_RFCOMM = 0x0003
  • 源文件:net/bluetooth/rfcomm/(独立目录)
  • 功能:在 L2CAP 之上模拟 RS-232 串口,提供多路复用(最多 30 个 DLC)
  • 应用:蓝牙串口(SPP)、耳机(HSP)、HFP 控制信道

14.2 BNEP(蓝牙网络封装协议)

  • 注册协议号:BTPROTO_BNEP = 4
  • 源文件:net/bluetooth/bnep/
  • 功能:将以太网帧封装在 L2CAP 之上,实现蓝牙个人局域网(PAN)
  • 提供标准网络接口(bnepX 网络设备)

14.3 HIDP(HID 配置文件)

  • 注册协议号:BTPROTO_HIDP = 6
  • 源文件:net/bluetooth/hidp/
  • 功能:蓝牙 HID 设备(键盘、鼠标、游戏手柄)的内核驱动
  • 使用两条 L2CAP 信道:Control(PSM 0x0011)和 Interrupt(PSM 0x0013)

14.4 ISO(等时流,LE Audio)

  • 注册协议号:BTPROTO_ISO = 8
  • 源文件:net/bluetooth/iso.c
  • 功能:LE Audio 的 ISO 链路管理,支持 CIS(连接等时流)和 BIS(广播等时流)
  • QoS 由 struct bt_iso_ucast_qos / struct bt_iso_bcast_qos 描述
  • 每条 ISO 链路对应一个 hci_conn,类型为 ISO_LINK

14.5 SCO(同步连接面向)

  • 注册协议号:BTPROTO_SCO = 2
  • 源文件:net/bluetooth/sco.c
  • 用于 BR/EDR 语音通话(HFP AG/HF 角色)
  • 支持多种语音编解码参数(esco_param_cvsdesco_param_msbchci_conn.c 第 52-68 行)

15. 关键数据结构关系图

+------------------+
|    hci_dev       |  <-- 一个 HCI 控制器
|  (hci_core.h:355)|
|                  |
|  conn_hash ------+----> hci_conn (ACL) ---> l2cap_data --> l2cap_conn
|  link_keys       |                                              |
|  long_term_keys  |      hci_conn (LE)  ---> l2cap_data --> l2cap_conn
|  identity_...    |                                              |
|  adv_instances   |      hci_conn (SCO) ---> sco_data           |
|  discovery       |                                              |
|  smp_data -------+----> l2cap_chan (SMP 全局)                   |
|                  |                                              |
|  workqueue       |                          l2cap_chan (RFCOMM) |
|  req_workqueue   |                          l2cap_chan (BNEP)   |
|  rx_work         |                          l2cap_chan (ATT)    |
|  cmd_work        |                          l2cap_chan (SMP)    |
|  tx_work         |                          l2cap_chan (固定)   |
+------------------+

+------------------+         +------------------+
|   l2cap_conn     |-------->|   l2cap_chan     |
|  (l2cap.h:643)   | chan_l  |  (l2cap.h:514)   |
|                  |  链表   |                  |
|  hcon -----+     |         |  conn --> l2cap_conn
|  feat_mask  |    |         |  scid, dcid      |
|  chan_l      |   |         |  psm, mode       |
|  smp --------+---+-------> l2cap_chan (SMP CID)
|  users       |   |         |  tx/rx_credits   |
+------------------+         |  ops             |
                             +------------------+
                                      |
                             +--------v---------+
                             |  l2cap_pinfo     |
                             |  bt_sock         |
                             |  (socket 私有数据)|
                             +------------------+

+------------------+
|   smp_chan       |  <-- 一次配对会话
|  (smp.c:96)      |
|  conn            |
|  preq/prsp       |  Pairing Request/Response
|  prnd/rrnd       |  随机数
|  tk / ltk        |  密钥
|  local_pk        |  本地 ECDH 公钥(64 bytes)
|  remote_pk       |  对端 ECDH 公钥(64 bytes)
|  dhkey           |  DH 共享密钥(32 bytes)
|  mackey          |  f5 输出的 MacKey
|  tfm_cmac        |  AES-CMAC 实例
|  tfm_ecdh        |  ECDH 实例
+------------------+

16. 核心锁机制与并发模型

16.1 全局锁

类型 保护对象
hci_dev_list_lock rwlock_t 全局 hci_dev_list 链表
hci_cb_list_lock mutex HCI 回调链表
bt_proto_lock rwlock_t bt_proto[] 协议注册表
chan_list_lock rwlock_t L2CAP 全局 chan_list

16.2 设备级锁

类型 位置 保护对象
hdev->lock mutex hci_dev.lock 设备状态、连接哈希等
hdev->req_lock mutex hci_dev.req_lock HCI 请求同步
hdev->srcu srcu_struct hci_dev.srcu 设备访问的 SRCU 保护
conn->chan_list 通过 hdev->lock hci_conn.chan_list l2cap_chan 链表

16.3 L2CAP 信道锁

// l2cap_chan 使用 kref + mutex 管理生命周期
l2cap_chan_hold(chan);      // 引用计数 +1
l2cap_chan_lock(chan);      // 获取信道锁
l2cap_chan_unlock(chan);    // 释放信道锁
l2cap_chan_put(chan);       // 引用计数 -1,可能触发销毁

l2cap_get_chan_by_scid() 返回已加锁的信道引用(第 117-131 行),调用者需要显式解锁和释放。

16.4 工作队列并发模型

hci_dev 使用两个独立的有序工作队列(WQ_HIGHPRI):

  • workqueue:处理 RX 接收、TX 发送、发现超时等事件驱动任务
  • req_workqueue:处理需要等待 HCI 响应的同步请求(setup、shutdown 等)

两个工作队列都是有序(ordered)的,同一时刻只有一个 work item 在运行,避免并发。hdev->lock(mutex)用于保护从工作队列以外访问设备状态。

16.5 SMP 安全定时器

SMP 配对有严格的 30 秒超时(SMP_TIMEOUT = secs_to_jiffies(30)smp.c 第 58 行)。超时后,smp_chan 被销毁,对应的 L2CAP 信道被关闭。


17. 调试接口与工具

17.1 debugfs

hci_register_dev()/sys/kernel/debug/bluetooth/ 下为每个设备创建目录(hdev->debugfs)。

net/bluetooth/hci_debugfs.c 注册了大量 debugfs 文件,包括:

  • features:BR/EDR LMP 特性
  • le_features:LE 特性
  • connections:当前连接列表
  • blacklist / whitelist:设备黑/白名单
  • uuids:注册的 UUID 列表
  • adv_instances:广播实例状态
  • smp_debug_keys:SMP 调试密钥开关

17.2 日志宏

include/net/bluetooth/bluetooth.h 第 279-300 行定义了标准日志宏:

#define BT_INFO(fmt, ...)    bt_info(fmt "\n", ##__VA_ARGS__)
#define BT_WARN(fmt, ...)    bt_warn(fmt "\n", ##__VA_ARGS__)
#define BT_ERR(fmt, ...)     bt_err(fmt "\n", ##__VA_ARGS__)
#define BT_DBG(fmt, ...)     bt_dbg(...) / pr_debug(...)   // 取决于 CONFIG_BT_FEATURE_DEBUG

// 设备级别(自动加设备名前缀)
#define bt_dev_info(hdev, fmt, ...)  BT_INFO("%s: " fmt, bt_dev_name(hdev), ...)
#define bt_dev_warn(hdev, fmt, ...)  BT_WARN("%s: " fmt, ...)
#define bt_dev_err(hdev, fmt, ...)   BT_ERR("%s: " fmt, ...)
#define bt_dev_dbg(hdev, fmt, ...)   BT_DBG("%s: " fmt, ...)

17.3 rfkill 集成

hci_register_dev() 第 2628 行为每个 HCI 设备注册 rfkill 节点(RFKILL_TYPE_BLUETOOTH),支持通过 /sys/class/rfkill/ 软件关闭蓝牙。

17.4 Coredump 支持

include/net/bluetooth/coredump.hnet/bluetooth/coredump.c 提供控制器崩溃时的 coredump 收集机制,由 hdev->dump 字段(struct hci_devcoredump)管理。

17.5 MSFT 与 AOSP 扩展

  • MSFT 扩展net/bluetooth/msft.c):Microsoft 蓝牙扩展,支持广播监控的 RSSI 过滤卸载到硬件,hdev->msft_opcode 存储厂商特定操作码。
  • AOSP 扩展net/bluetooth/aosp.c):Android 开源项目蓝牙扩展,支持质量报告(hdev->aosp_quality_report)。

附录:关键常量速查

HCI 连接 Handle 范围

// include/net/bluetooth/hci_core.h:338-339
#define HCI_CONN_HANDLE_MAX     0x0eff
#define HCI_CONN_HANDLE_UNSET(_handle)  (_handle > HCI_CONN_HANDLE_MAX)

L2CAP 默认参数

// include/net/bluetooth/l2cap.h:34-60
#define L2CAP_DEFAULT_MTU           672
#define L2CAP_DEFAULT_TX_WINDOW     63
#define L2CAP_DEFAULT_MAX_TX        3
#define L2CAP_DEFAULT_RETRANS_TO    2000   // ms
#define L2CAP_DEFAULT_MONITOR_TO    12000  // ms
#define L2CAP_DEFAULT_ACK_TO        200    // ms
#define L2CAP_BREDR_MAX_PAYLOAD     1019   // 3-DH5 包的有效载荷
#define L2CAP_LE_MIN_MTU            23
#define LE_FLOWCTL_MAX_CREDITS      65535

LE PHY 类型

// include/net/bluetooth/bluetooth.h:133-156
#define BT_PHY_LE_1M_TX      BIT(9)
#define BT_PHY_LE_1M_RX      BIT(10)
#define BT_PHY_LE_2M_TX      BIT(11)
#define BT_PHY_LE_2M_RX      BIT(12)
#define BT_PHY_LE_CODED_TX   BIT(13)   // LE Coded PHY(长距离)
#define BT_PHY_LE_CODED_RX   BIT(14)

18. HCI 同步命令框架:hci_sync.c

18.1 框架概述

net/bluetooth/hci_sync.c(7522 行)是 2021 年 Intel 引入的 HCI 同步命令执行框架,旨在替代旧有的异步 hci_request 机制。它提供了一套可串行化的命令队列,使得初始化和配置流程可以以同步的方式描述,极大简化了状态机编写。

核心设计思路:将需要等待响应的 HCI 命令序列封装为可排队的工作项(work entry),在专用工作队列上顺序执行,通过 wait_event_interruptible 等待命令完成

18.2 命令同步执行机制

hci_sync.c 第 23-49 行实现了同步完成回调:

// hci_sync.c:23
static void hci_cmd_sync_complete(struct hci_dev *hdev, u8 result, u16 opcode,
                                  struct sk_buff *skb)
{
    if (hdev->req_status != HCI_REQ_PEND)
        return;

    hdev->req_result = result;
    hdev->req_status = HCI_REQ_DONE;

    // 释放请求 skb,避免作为响应被再次使用
    kfree_skb(hdev->req_skb);
    hdev->req_skb = NULL;

    if (skb) {
        // 保存响应 skb,供调用者读取返回值
        hdev->req_rsp = skb_get(skb);
    }

    wake_up_interruptible(&hdev->req_wait_q);  // 唤醒等待的同步调用者
}

hci_cmd_sync_alloc()(第 51-80 行)负责分配带完整 HCI 头的 SKB:

// hci_sync.c:51
struct sk_buff *hci_cmd_sync_alloc(struct hci_dev *hdev, u16 opcode, u32 plen,
                                   const void *param, struct sock *sk)
{
    int len = HCI_COMMAND_HDR_SIZE + plen;
    struct hci_command_hdr *hdr;
    struct sk_buff *skb;

    skb = bt_skb_alloc(len, GFP_ATOMIC);
    hdr = skb_put(skb, HCI_COMMAND_HDR_SIZE);
    hdr->opcode = cpu_to_le16(opcode);
    hdr->plen   = plen;
    if (plen)
        skb_put_data(skb, param, plen);

    hci_skb_pkt_type(skb) = HCI_COMMAND_PKT;
    hci_skb_opcode(skb) = opcode;

    // 绑定发起 socket(用于 MGMT 响应路由)
    if (sk) {
        hci_skb_sk(skb) = sk;
        sock_hold(sk);
    }
    return skb;
}

18.3 工作队列提交接口

hci_sync.c 提供了两级提交接口:

hci_cmd_sync_submit()(第 702-733 行):无条件提交,要求设备未注销:

// hci_sync.c:702
int hci_cmd_sync_submit(struct hci_dev *hdev, hci_cmd_sync_work_func_t func,
                        void *data, hci_cmd_sync_work_destroy_t destroy)
{
    mutex_lock(&hdev->unregister_lock);
    if (hci_dev_test_flag(hdev, HCI_UNREGISTER)) {
        err = -ENODEV;
        goto unlock;
    }
    entry = kmalloc_obj(*entry);
    entry->func    = func;
    entry->data    = data;
    entry->destroy = destroy;

    mutex_lock(&hdev->cmd_sync_work_lock);
    list_add_tail(&entry->list, &hdev->cmd_sync_work_list);
    mutex_unlock(&hdev->cmd_sync_work_lock);

    queue_work(hdev->req_workqueue, &hdev->cmd_sync_work);  // 触发工作队列
    ...
}

hci_cmd_sync_queue()(第 739-750 行):额外检查设备是否处于运行状态(HCI_RUNNING):

// hci_sync.c:739
int hci_cmd_sync_queue(struct hci_dev *hdev, hci_cmd_sync_work_func_t func,
                       void *data, hci_cmd_sync_work_destroy_t destroy)
{
    if (!test_bit(HCI_RUNNING, &hdev->flags))
        return -ENETDOWN;
    return hci_cmd_sync_submit(hdev, func, data, destroy);
}
EXPORT_SYMBOL(hci_cmd_sync_queue);

hci_cmd_sync_queue_once()(第 779-787 行):幂等版本,若相同函数已在队列中则不重复添加。

18.4 工作队列执行流程

hdev->cmd_sync_work (work_struct)
    |
    v  hci_cmd_sync_work()
       |
       v  mutex_lock(&hdev->cmd_sync_work_lock)
       v  取出下一个 entry(list_first_entry)
       v  mutex_unlock
       |
       v  entry->func(hdev, entry->data)
          (可在函数内部调用 __hci_cmd_sync、__hci_cmd_sync_status 等)
       |
       v  if (entry->destroy)
              entry->destroy(hdev, entry->data, err)
       |
       v  kfree(entry)
       |
       v  若队列非空,重新 queue_work

18.5 HCI 初始化序列宏

hci_sync.c 第 3645-3648 行定义了初始化阶段描述宏:

// hci_sync.c:3645
#define HCI_INIT(_func) \
    { .func = _func }

struct hci_init_stage {
    int (*func)(struct hci_dev *hdev);
};

利用这个宏,初始化阶段可以用清晰的数组格式描述:

// init1 阶段(基础版本读取,所有设备类型)
static const struct hci_init_stage hci_init1[] = {
    HCI_INIT(hci_read_local_version_sync),    // 读版本信息
    HCI_INIT(hci_read_bd_addr_sync),          // 读 BD 地址
    {}
};

// init2 阶段(LE 特性读取)
static const struct hci_init_stage le_init2[] = {
    HCI_INIT(hci_le_read_local_features_sync),    // LE 特性
    HCI_INIT(hci_le_read_buffer_size_sync),        // LE ACL 缓冲区大小
    HCI_INIT(hci_le_read_supported_states_sync),   // LE 状态支持
    {}
};

19. RFCOMM 层深度分析

19.1 协议概述

RFCOMM(Radio Frequency Communication)基于 TS 07.10 协议,在 L2CAP 之上模拟多路串行端口。它是蓝牙 SPP(Serial Port Profile)、HFP(Hands-Free Profile)和 HSP(Headset Profile)的传输基础。

源文件net/bluetooth/rfcomm/core.c(2286 行)、net/bluetooth/rfcomm/sock.cnet/bluetooth/rfcomm/tty.c(1151 行)

RFCOMM 版本(net/bluetooth/rfcomm/core.c:40):

#define VERSION "1.11"

19.2 核心数据结构

struct rfcomm_sessioninclude/net/bluetooth/rfcomm.h:154

struct rfcomm_session {
    struct list_head list;      // 挂在全局 session_list
    struct socket   *sock;      // 底层 L2CAP socket
    struct timer_list timer;    // 空闲超时定时器
    unsigned long    state;     // BT_LISTEN / BT_CONNECTED 等
    unsigned long    flags;     // RFCOMM_TIMED_OUT 等
    int              initiator; // 1 = 本端发起连接
    uint             mtu;       // 最大传输单元(默认 RFCOMM_DEFAULT_MTU=127)
    struct list_head dlcs;      // 挂载在本 session 上的 DLC 链表
};

struct rfcomm_dlcinclude/net/bluetooth/rfcomm.h:169

DLC(Data Link Connection)是 RFCOMM 上的单个逻辑信道,对应一个虚拟串口:

struct rfcomm_dlc {
    struct list_head      list;      // 挂在 rfcomm_session.dlcs
    struct rfcomm_session *session;
    struct sk_buff_head   tx_queue;  // 待发送数据队列
    struct timer_list     timer;     // 连接/断连超时

    struct mutex  lock;
    unsigned long state;    // BT_OPEN / BT_CONNECTED 等
    unsigned long flags;    // RFCOMM_RX_THROTTLED / RFCOMM_TX_THROTTLED 等

    u8  dlci;               // DLCI = (channel << 1) | direction
    u8  addr;               // 帧地址字节
    u8  priority;           // 优先级(默认 7)
    u8  sec_level;          // 安全级别

    uint  mtu;              // 本 DLC 的 MTU(默认 RFCOMM_DEFAULT_MTU=127)
    uint  rx_credits;       // 接收信用(Credit-based Flow Control)
    uint  tx_credits;       // 发送信用

    /* 回调函数 */
    void (*data_ready)(struct rfcomm_dlc *d, struct sk_buff *skb);
    void (*state_change)(struct rfcomm_dlc *d, int err);
    void (*modem_status)(struct rfcomm_dlc *d, u8 v24_sig);
};

19.3 帧类型与 FCS

include/net/bluetooth/rfcomm.h:43-51 定义了 RFCOMM 帧类型:

#define RFCOMM_SABM  0x2f   // Set Asynchronous Balanced Mode(连接建立)
#define RFCOMM_DISC  0x43   // Disconnect(断连)
#define RFCOMM_UA    0x63   // Unnumbered Acknowledgement(确认)
#define RFCOMM_DM    0x0f   // Disconnected Mode(拒绝)
#define RFCOMM_UIH   0xef   // Unnumbered Information with Header check(数据)

// Multiplexer Control Commands(在 DLCI 0 上传输)
#define RFCOMM_TEST  0x08   // 测试命令
#define RFCOMM_FCON  0x28   // 流量控制开(Flow Control On)

帧校验序列(FCS)使用反转 CRC-8 多项式(poly=0x07),rfcomm_crc_table[]core.c:114)是预计算表。

SABM/DISC/UA 帧使用 3 字节 FCS(__fcs2()),UIH 帧只使用 2 字节 FCS(__fcs()):

// core.c:160-168
static inline u8 __fcs(u8 *data)
{
    return 0xff - __crc(data);       // 2 字节
}

static inline u8 __fcs2(u8 *data)
{
    return 0xff - rfcomm_crc_table[__crc(data) ^ data[2]];  // 3 字节
}

19.4 DLCI 计算

DLCI(Data Link Connection Identifier)由通道号和方向位计算:

// core.c:87-88
#define __dlci(dir, chn)       (((chn & 0x1f) << 1) | dir)
#define __srv_channel(dlci)    (dlci >> 1)
  • dir__session_dir(s) — 发起方 dir=0,响应方 dir=1
  • chn:通道号(1-30,即 RFCOMM_DEFAULT_CHANNELS=30
  • DLCI 0 用于多路复用控制信道(MCC)

19.5 RFCOMM 线程与主循环

RFCOMM 使用专用内核线程(rfcomm_thread)而非工作队列:

// core.c:46
static struct task_struct *rfcomm_thread;

主循环(rfcomm_run(),第 2120 行):

static int rfcomm_run(void *unused)
{
    BT_DBG("started");

    set_user_nice(current, -10);    // 提升线程优先级

    while (!kthread_should_stop()) {
        set_current_state(TASK_INTERRUPTIBLE);
        rfcomm_process_sessions();  // 处理所有活动 session
        schedule();                 // 等待唤醒(rfcomm_schedule())
    }
    return 0;
}

rfcomm_schedule()(第 106-109 行)通过 wake_up_all(&rfcomm_wq) 唤醒线程:

static void rfcomm_schedule(void)
{
    wake_up_all(&rfcomm_wq);
}

19.6 Session 处理状态机

rfcomm_process_sessions()core.c:2016)遍历所有 session 并按状态分发:

rfcomm_process_sessions()
    |
    +-- BT_LISTEN  --> rfcomm_accept_connection(s)
    |                  (接受新的 L2CAP 连接)
    |
    +-- BT_BOUND   --> rfcomm_check_connection(s)
    |                  (发起 L2CAP 连接)
    |
    +-- 其他状态   --> rfcomm_process_rx(s)
                       (处理接收帧)
    |
    v  (所有状态)
    rfcomm_process_dlcs(s)
    (处理各 DLC 的发送、状态机转换)

19.7 MCC(Multiplexer Control Commands)

MCC 命令通过 DLCI 0 的 UIH 帧传输,在 core.c:1659rfcomm_recv_mcc() 中处理:

// core.c:1659
case RFCOMM_PN:    // Parameter Negotiation(协商 MTU、信用数等)
    rfcomm_recv_pn(s, cr, skb);
    break;
case RFCOMM_MSC:   // Modem Status Command(传递 V.24 信号)
    rfcomm_recv_msc(s, cr, skb);
    break;
case RFCOMM_RPN:   // Remote Port Negotiation(波特率、数据格式等)
    rfcomm_recv_rpn(s, cr, skb);
    break;
case RFCOMM_TEST:  // 测试连接质量
    rfcomm_recv_test(s, cr, skb);
    break;

19.8 DLC 建立完整流程

用户调用 connect()
    |
    v
rfcomm_dlc_open()  [core.c:425]
    |   rfcomm_lock() 保护
    v
__rfcomm_dlc_open()  [core.c:371]
    |
    +-- 1. 验证通道号(1-30)
    +-- 2. 查找或创建 rfcomm_session(rfcomm_session_get/create)
    +-- 3. 计算 DLCI = __dlci(__session_dir(s), channel)
    +-- 4. 检查 DLCI 不重复
    +-- 5. 将 DLC 链接到 session(rfcomm_dlc_link)
    +-- 6. 若 session 已连接:
    |       rfcomm_check_security() 成功 --> rfcomm_send_pn()
    |       否则                          --> 设 RFCOMM_AUTH_PENDING
    |
    v  等待 L2CAP 连接完成
rfcomm_session_add()  创建底层 L2CAP socket
    |
    v  L2CAP 连接成功后
rfcomm_send_sabm(s, dlci)  发送 SABM 帧建立 DLC
    |
    v  收到 UA 帧
DLC 进入 BT_CONNECTED 状态

19.9 TTY 层(rfcomm/tty.c)

rfcomm/tty.c 将每个 RFCOMM DLC 注册为标准 Linux TTY 设备(/dev/rfcommN),通过 tty_port_register_device() 创建设备节点。最多支持 RFCOMM_MAX_DEV = 256 个 TTY 设备。


20. BNEP 层深度分析

20.1 协议概述

BNEP(Bluetooth Network Encapsulation Protocol)在 L2CAP PSM=0x000F 上传输以太网帧,实现蓝牙个人局域网(PAN)。它支持三种角色:

  • PANU(Personal Area Networking User):点对点用户端
  • NAP(Network Access Point):网络接入点(类似 AP)
  • GN(Group ad-hoc Network):组网节点

源文件net/bluetooth/bnep/core.cnet/bluetooth/bnep/netdev.cnet/bluetooth/bnep/sock.c

20.2 struct bnep_sessionbnep/bnep.h:145

struct bnep_session {
    struct list_head list;          // 全局 bnep_session_list

    unsigned int  role;             // BNEP_ROLE_* (PANU/NAP/GN)
    unsigned long state;
    unsigned long flags;
    atomic_t      terminate;        // 会话终止标志

    struct task_struct *task;       // 处理线程

    struct ethhdr     eh;           // 以太网头缓存
    struct msghdr     msg;          // L2CAP 消息头

    struct bnep_proto_filter proto_filter[BNEP_MAX_PROTO_FILTERS];
    unsigned long long mc_filter;   // 多播地址过滤位图(64-bit)

    struct socket     *sock;        // 底层 L2CAP socket
    struct net_device *dev;         // bnep0 等网络设备
};

20.3 BNEP 帧格式与处理

BNEP 帧头中的类型字段区分以下包类型:

BNEP_GENERAL_ETHERNET      0x00  完整以太网帧
BNEP_CONTROL               0x01  控制命令
BNEP_COMPRESSED_ETHERNET   0x02  目的/源地址省略(仅在建立后可用)
BNEP_COMPRESSED_ETHERNET_SRC_ONLY 0x03
BNEP_COMPRESSED_ETHERNET_DST_ONLY 0x04

接收路径(bnep_rx_frame(),第 298 行):

L2CAP 数据到达
    |
    v  bnep_rx_frame()
       |
       +-- 控制帧 --> bnep_rx_control()
       |              (Setup / Filter 命令处理)
       |
       +-- 数据帧 --> 补全以太网头
                      --> netif_rx() 注入内核网络栈

20.4 网络设备注册

bnep/netdev.cbnep_net_setup() 设置以太网设备操作:

void bnep_net_setup(struct net_device *dev)
{
    memset(dev->broadcast, 0xff, ETH_ALEN);
    dev->hard_header_len = ETH_HLEN;
    dev->mtu             = ETH_DATA_LEN;
    dev->addr_len        = ETH_ALEN;
    dev->type            = ARPHRD_ETHER;

    dev->netdev_ops = &bnep_netdev_ops;
    dev->ethtool_ops = &bnep_ethtool_ops;
}

多播过滤使用 CRC32 哈希(bnep_mc_hash()bnep.h:168):

static inline int bnep_mc_hash(__u8 *addr)
{
    return crc32_be(~0, addr, ETH_ALEN) >> 26;  // 取高 6 位 -> 64-bit 位图索引
}

21. HIDP 层深度分析

21.1 协议概述

HIDP(Human Interface Device Profile)实现了蓝牙 HID 规范,在内核中注册为标准 input 设备或 hid 设备。它使用两条 L2CAP 信道:

  • Control 信道(PSM=0x0011):传递 HID 控制命令和报告
  • Interrupt 信道(PSM=0x0013):传递实时输入数据(键盘/鼠标事件)

源文件net/bluetooth/hidp/core.cnet/bluetooth/hidp/sock.c

21.2 HIDP 事务类型(hidp/hidp.h:37

#define HIDP_TRANS_HANDSHAKE     0x00  // 握手响应
#define HIDP_TRANS_HID_CONTROL   0x10  // HID 控制命令
#define HIDP_TRANS_GET_REPORT    0x40  // 获取报告
#define HIDP_TRANS_SET_REPORT    0x50  // 设置报告
#define HIDP_TRANS_GET_PROTOCOL  0x60  // 获取协议(Boot/Report)
#define HIDP_TRANS_SET_PROTOCOL  0x70  // 设置协议
#define HIDP_TRANS_DATA          0xa0  // 数据传输

握手响应码(第 48-55 行):

#define HIDP_HSHK_SUCCESSFUL          0x00  // 成功
#define HIDP_HSHK_NOT_READY           0x01  // 设备未就绪
#define HIDP_HSHK_ERR_INVALID_REPORT_ID  0x02
#define HIDP_HSHK_ERR_UNSUPPORTED_REQUEST 0x03
#define HIDP_HSHK_ERR_INVALID_PARAMETER  0x04
#define HIDP_HSHK_ERR_FATAL           0x0f  // 致命错误

21.3 struct hidp_sessionhidp/hidp.h:137

struct hidp_session {
    struct list_head list;

    struct bt_sock  *conn;          // 关联的 bt_sock

    struct hid_device *hid;         // 注册的 HID 设备
    struct input_dev  *input;       // 注册的 input 设备(Boot Protocol 时)

    struct timer_list timer;        // 空闲超时

    struct socket *ctrl_sock;       // Control 信道 socket
    struct socket *intr_sock;       // Interrupt 信道 socket

    struct sk_buff_head ctrl_transmit;  // Control 发送队列
    struct sk_buff_head intr_transmit;  // Interrupt 发送队列

    __u8   ctrl_id;                 // Control 信道连接 ID
    __u16  flags;                   // 会话标志
    __u32  idle_to;                 // 空闲超时时间
    ...
};

21.4 接收路径

L2CAP Control 信道数据到达
    |
    v  hidp_recv_ctrl_frame()  [core.c:550]
       |
       +-- HIDP_TRANS_HANDSHAKE  --> hidp_process_handshake()
       +-- HIDP_TRANS_HID_CONTROL --> hidp_process_hid_control()
       +-- HIDP_TRANS_DATA        --> hidp_process_data()

L2CAP Interrupt 信道数据到达
    |
    v  hidp_recv_intr_frame()  [core.c:587]
       |
       +-- HIDP_TRANS_DATA --> hidp_input_report()
                               (通过 hid_input_report() 注入 input 层)

hidp_input_report()core.c:178)将收到的 HID 报告通过 hid_input_report() 传递给内核 HID 子系统,最终触发 input_event()(键盘按键、鼠标移动等)。


22. ISO 层与 LE Audio

22.1 概述

LE Audio 是蓝牙 5.2 引入的核心特性,基于 ISO(Isochronous)链路提供低延迟、高质量音频传输。Linux 内核通过 BTPROTO_ISOnet/bluetooth/iso.c,2735 行)支持 ISO 层。

ISO 链路分两类:

  • CIS(Connected Isochronous Stream):点对点单播等时流,用于 TWS 耳机
  • BIS(Broadcast Isochronous Stream):广播等时流,用于广播音频(如广场舞音响)

22.2 ISO Socket 私有信息(iso.c:60

// iso.c:60
struct iso_pinfo {
    struct bt_sock  bt;
    bdaddr_t        src;
    __u8            src_type;
    bdaddr_t        dst;
    __u8            dst_type;
    __u8            bc_sid;                 // BIG 的 SID(Sync ID)
    __u8            bc_num_bis;             // BIS 数量
    __u8            bc_bis[ISO_MAX_NUM_BIS]; // BIS 索引列表
    __u16           sync_handle;            // PA Sync Handle
    unsigned long   flags;                  // BT_SK_BIG_SYNC / BT_SK_PA_SYNC
    struct bt_iso_qos qos;                  // QoS 参数
    bool            qos_user_set;           // 用户是否显式设置了 QoS
    __u8            base_len;
    __u8            base[BASE_MAX_LENGTH];  // BASE(Basic Audio Announcement)
    struct iso_conn *conn;
};

标志位定义(第 55-58 行):

enum {
    BT_SK_BIG_SYNC,   // 正在同步 BIG
    BT_SK_PA_SYNC,    // 正在同步 Periodic Advertising
};

22.3 struct iso_conniso.c:26

struct iso_conn {
    struct hci_conn *hcon;      // 关联的 HCI ISO 连接

    spinlock_t      lock;
    struct sock     *sk;

    struct delayed_work timeout_work;  // ISO_CONN_TIMEOUT=20s / ISO_DISCONN_TIMEOUT=2s

    struct sk_buff  *rx_skb;           // 正在组装的 SDU
    __u32            rx_len;
    __u16            tx_sn;            // 发送序列号(Sequence Number)
    struct kref      ref;
};

超时常量(第 95-96 行):

#define ISO_CONN_TIMEOUT    secs_to_jiffies(20)
#define ISO_DISCONN_TIMEOUT secs_to_jiffies(2)

22.4 ISO QoS 参数体系

struct bt_iso_qosinclude/net/bluetooth/bluetooth.h)是联合体,支持单播和广播两种模式:

bt_iso_qos
    ├── ucast (struct bt_iso_ucast_qos)
    │   ├── cig                  // CIG ID
    │   ├── cis                  // CIS ID
    │   ├── sca                  // Sleep Clock Accuracy
    │   ├── packing              // 顺序/交错打包
    │   ├── framing              // 非分帧/分帧
    │   ├── in  (struct bt_iso_io_qos)  // 入方向 QoS
    │   └── out (struct bt_iso_io_qos)  // 出方向 QoS
    │
    └── bcast (struct bt_iso_bcast_qos)
        ├── big                  // BIG ID
        ├── bis                  // BIS ID
        ├── sync_factor          // 同步因子
        ├── packing / framing / encryption
        ├── bcode[16]            // 广播加密码(Broadcast Code)
        └── in / out (struct bt_iso_io_qos)

struct bt_iso_io_qos {
    __u32 interval;    // SDU 间隔(微秒)
    __u16 latency;     // 最大传输延迟(毫秒)
    __u16 sdu;         // 最大 SDU 大小
    __u8  phy;         // PHY(BT_ISO_PHY_1M / 2M / CODED)
    __u8  rtn;         // 最大重传次数
};

22.5 CIG/BIG 建立流程

CIS(单播)建立流程

用户 bind() + connect()
    |
    v  iso_connect_cis()
       |
       v  hci_connect_cis() [hci_conn.c]
          |
          v  HCI_LE_Set_CIG_Parameters 命令
             (设置 CIG_ID、Sdu_Interval、Latency 等)
          |
          v  HCI_LE_Create_CIS 命令
             (创建 CIS 连接,需要 ACL 连接已建立)
          |
          v  LE CIS Established 事件
             --> hci_conn 进入 BT_CONNECTED
             --> iso_connect_cfm() 通知 socket 层

BIS(广播)建立流程

用户 bind() + connect()
    |
    v  iso_connect_bis()
       |
       v  hci_connect_bis() [hci_conn.c]
          |
          v  HCI_LE_Create_BIG 命令
             (设置 BIG_ID、Num_BIS、SDU_Interval、ISO_Interval 等)
          |
          v  LE Create BIG Complete 事件
             --> 创建多个 hci_conn(每个 BIS 一个)
             --> 广播开始发送 ISO 数据

22.6 BASE(Basic Audio Announcement)

BIS 广播包含 BASE 数据结构(iso.c:50-51):

#define EIR_SERVICE_DATA_LENGTH 4
#define BASE_MAX_LENGTH (HCI_MAX_PER_AD_LENGTH - EIR_SERVICE_DATA_LENGTH)
#define EIR_BAA_SERVICE_UUID    0x1851  // Basic Audio Announcement UUID

BASE 包含 Codec_ID、Codec_Config 等信息,接收端(如蓝牙音频头戴耳机)据此选择同步的 BIS 并配置解码器。


23. BLE 扫描与广播深度分析

23.1 扫描类型与参数

LE 扫描分为被动扫描(passive scan)和主动扫描(active scan):

LE_SCAN_PASSIVE = 0x00  仅接收广播包,不发送 SCAN_REQ
LE_SCAN_ACTIVE  = 0x01  对可扫描广播者发送 SCAN_REQ,获取 SCAN_RSP

扫描参数的单位为 0.625ms:

参数 常量 说明
快速扫描间隔 DISCOV_LE_SCAN_INT_FAST 0x0060 60ms
快速扫描窗口 DISCOV_LE_SCAN_WIN_FAST 0x0030 30ms
慢速扫描间隔 DISCOV_LE_SCAN_INT_SLOW1 0x0800 1280ms
慢速扫描窗口 DISCOV_LE_SCAN_WIN_SLOW1 0x0012 11.25ms
Coded PHY 快速 DISCOV_CODED_SCAN_INT_FAST 0x0120 180ms
Coded PHY 慢速 DISCOV_CODED_SCAN_INT_SLOW1 0x1800 3.84s

include/net/bluetooth/hci_core.h:2403-2408

23.2 扩展扫描参数设置

当控制器支持 use_ext_scan(hdev) 时,使用扩展扫描命令(BT 5.0+):

hci_le_set_ext_scan_param_sync()hci_sync.c:2919)可同时为多个 PHY 设置扫描参数:

// hci_sync.c:2919
static int hci_le_set_ext_scan_param_sync(struct hci_dev *hdev, u8 type,
                                           u16 interval, u16 window,
                                           u8 own_addr_type, u8 filter_policy)
{
    // 为 LE 1M PHY 设置扫描参数
    if (scan_1m(hdev) || scan_2m(hdev)) {
        cp->scanning_phys |= LE_SCAN_PHY_1M;
        hci_le_scan_phy_params(phy, type, interval, window);
        num_phy++;
        phy++;
    }

    // 为 LE Coded PHY 设置扫描参数(间隔和窗口扩大 3 倍)
    if (scan_coded(hdev)) {
        cp->scanning_phys |= LE_SCAN_PHY_CODED;
        hci_le_scan_phy_params(phy, type, interval * 3, window * 3);
        num_phy++;
        phy++;
    }

    return __hci_cmd_sync_status(hdev, HCI_OP_LE_SET_EXT_SCAN_PARAMS, ...);
}

Coded PHY 的扫描窗口扩大 3 倍是因为 Coded PHY 的符号速率是 1M PHY 的 1/8(S=8 编码),需要更长时间接收同样长度的广播包。

23.3 扫描流量交织(Interleave Scan)

hci_sync.c 中的 interleave_scan_work()(第 586 行)实现了 Accept List 扫描和无过滤扫描之间的交织调度:

// hci_sync.c:586
static void interleave_scan_work(struct work_struct *work)
{
    if (hdev->interleave_scan_state == INTERLEAVE_SCAN_ALLOWLIST) {
        timeout = msecs_to_jiffies(hdev->advmon_allowlist_duration);
    } else if (hdev->interleave_scan_state == INTERLEAVE_SCAN_NO_FILTER) {
        timeout = msecs_to_jiffies(hdev->advmon_no_filter_duration);
    }
    // 定时切换:ALLOWLIST <--> NO_FILTER
    queue_delayed_work(hdev->req_workqueue,
                       &hdev->interleave_scan, timeout);
}

这是为了在节能的同时兼顾广播监控(Advertising Monitor)功能:用大部分时间扫描白名单设备,少部分时间扫描所有设备以支持广播监控。

23.4 广播监控(Advertising Monitor)

通过 MSFT 扩展或 LE Advertising Filter HCI 命令可以将广播过滤下推到硬件:

用户空间 --> MGMT_OP_ADD_ADV_PATTERNS_MONITOR
    |
    v  mgmt.c 处理
    |
    v  msft_add_address_filter_sync() [msft.c:956]
       使用 Microsoft 厂商扩展命令将 RSSI 阈值、UUID 等过滤条件
       卸载到 HCI 控制器硬件,减少软件处理开销
    |
    v  匹配到设备时 --> MGMT_EV_ADV_MONITOR_DEVICE_FOUND 通知用户态

23.5 扩展广播参数配置

hci_setup_ext_adv_instance_sync()hci_sync.c:1330)处理扩展广播实例参数设置,核心是根据广播类型填充 hci_cp_le_set_ext_adv_params 结构:

// hci_sync.c:1397-1415
if (connectable) {
    if (secondary_adv)
        cp.evt_properties = cpu_to_le16(LE_EXT_ADV_CONN_IND);     // 可连接扩展广播
    else
        cp.evt_properties = cpu_to_le16(LE_LEGACY_ADV_IND);       // 传统可连接广播
} else if (hci_adv_instance_is_scannable(hdev, instance)) {
    if (secondary_adv)
        cp.evt_properties = cpu_to_le16(LE_EXT_ADV_SCAN_IND);     // 可扫描扩展广播
    else
        cp.evt_properties = cpu_to_le16(LE_LEGACY_ADV_SCAN_IND);  // 传统可扫描广播
} else {
    if (secondary_adv)
        cp.evt_properties = cpu_to_le16(LE_EXT_ADV_NON_CONN_IND); // 不可连接扩展广播
    else
        cp.evt_properties = cpu_to_le16(LE_LEGACY_NONCONN_IND);   // 传统不可连接广播
}

secondary_adv 为真时表示使用辅助广播信道(Secondary Advertising Channel),是蓝牙 5.0 扩展广播的核心特性。


24. 蓝牙 5.x 新特性

24.1 蓝牙 5.x 特性总览

特性 版本 内核支持位置
LE 2M PHY BT 5.0 hci_sync.c:4874le_2m_capable()
LE Coded PHY BT 5.0 hci_sync.c:4879le_coded_capable()
Extended Advertising BT 5.0 hci_sync.c:1330ext_adv_capable()
Extended Scanning BT 5.0 hci_sync.c:2919use_ext_scan()
Periodic Advertising BT 5.0 hci_sync.cper_adv_capable()
LL Privacy(地址解析) BT 4.2 ll_privacy_capable()
LE Audio (ISO/CIS/BIS) BT 5.2 net/bluetooth/iso.c
Enhanced ATT (EATT) BT 5.3 L2CAP ECRED 支持

24.2 LE Coded PHY(长距离 PHY)

LE Coded PHY 使用前向纠错(FEC)编码,以牺牲速率换取更远的传输距离(最远 ~1km):

  • S=2 编码:数据速率 500Kbps,距离约 2 倍于 1M PHY
  • S=8 编码:数据速率 125Kbps,距离约 4 倍于 1M PHY

内核中的能力检测(include/net/bluetooth/hci_core.h:1986):

// include/net/bluetooth/hci_core.h:1986
#define le_coded_capable(dev) (((dev)->le_features[1] & HCI_LE_PHY_CODED) && \
                               !hci_test_quirk((dev), HCI_QUIRK_BROKEN_LE_CODED))

HCI_QUIRK_BROKEN_LE_CODED 用于屏蔽报告支持 Coded PHY 但实际实现有缺陷的控制器。

扫描是否使用 Coded PHY 由 scan_coded() 决定(hci_core.h:1990):

#define scan_coded(dev) (((dev)->le_tx_def_phys & HCI_LE_SET_PHY_CODED) || \
                         ((dev)->le_rx_def_phys & HCI_LE_SET_PHY_CODED))

Coded PHY 扫描参数(快速发现模式,hci_core.h:2403):

#define DISCOV_CODED_SCAN_INT_FAST   0x0120  // 180ms 扫描间隔
#define DISCOV_CODED_SCAN_WIN_FAST   0x0090  // 90ms  扫描窗口
#define DISCOV_CODED_SCAN_INT_SLOW1  0x1800  // 3.84s 扫描间隔(慢速模式)
#define DISCOV_CODED_SCAN_WIN_SLOW1  0x0036  // 33.75ms 扫描窗口

24.3 LE 2M PHY

2M PHY 将 LE 数据速率从 1Mbps 提升到 2Mbps,降低空中延迟。

初始化时在 hci_le_set_default_phy_sync()hci_sync.c:4855)中配置默认 PHY:

// hci_sync.c:4855
static int hci_le_set_default_phy_sync(struct hci_dev *hdev)
{
    // 默认启用 1M PHY
    cp.tx_phys = HCI_LE_SET_PHY_1M;    // 0x01
    cp.rx_phys = HCI_LE_SET_PHY_1M;

    // 若支持 2M PHY,同时启用
    if (le_2m_capable(hdev)) {
        cp.tx_phys |= HCI_LE_SET_PHY_2M;  // 0x02
        cp.rx_phys |= HCI_LE_SET_PHY_2M;
    }

    // 若支持 Coded PHY,同时启用
    if (le_coded_capable(hdev)) {
        cp.tx_phys |= HCI_LE_SET_PHY_CODED;  // 0x04
        cp.rx_phys |= HCI_LE_SET_PHY_CODED;
    }

    return __hci_cmd_sync_status(hdev, HCI_OP_LE_SET_DEFAULT_PHY,
                                 sizeof(cp), &cp, HCI_CMD_TIMEOUT);
}

PHY 位定义(include/net/bluetooth/hci.h:1884):

#define HCI_LE_SET_PHY_1M      0x01
#define HCI_LE_SET_PHY_2M      0x02
#define HCI_LE_SET_PHY_CODED   0x04

24.4 动态 PHY 切换

连接建立后可以通过 hci_le_set_phy() 动态切换 PHY:

// hci_sync.c:7506
int hci_le_set_phy(struct hci_conn *conn, u8 tx_phys, u8 rx_phys)
{
    cp->handle  = cpu_to_le16(conn->handle);
    cp->tx_phys = tx_phys;
    cp->rx_phys = rx_phys;

    // 使用 queue_once 避免重复排队
    return hci_cmd_sync_queue_once(hdev, hci_le_set_phy_sync, cp,
                                   le_phy_update_complete);
}

内部通过 HCI_OP_LE_SET_PHY 命令发送,等待 HCI_EV_LE_PHY_UPDATE_COMPLETE 事件确认(hci_sync.c:7500)。

24.5 Extended Advertising 数据流

扩展广播(Extended Advertising)支持最大 254 字节广播数据(Legacy 广播只有 31 字节),且可在辅助信道(Secondary Advertising Channel)上传输,实现更灵活的广播场景。

传统广播包(Legacy):
  ADV_IND | ADV_NONCONN_IND | ADV_SCAN_IND (主信道,最大 31 字节)
       |
       v
扩展广播包(Extended,BT 5.0+):
  ADV_EXT_IND (主信道,包含 AuxPtr 指向辅助信道)
       |
       v  通过 AuxPtr 跳转
  AUX_ADV_IND (辅助信道,最大 254 字节)
       |
       v  若数据更长,通过 AuxPtr 链式传递
  AUX_CHAIN_IND (辅助信道后续帧)

hci_set_ext_adv_data_sync()hci_sync.c:1257):

// hci_sync.c:1257
static int hci_set_ext_adv_data_sync(struct hci_dev *hdev, u8 instance)
{
    DEFINE_FLEX(struct hci_cp_le_set_ext_adv_data, pdu, data, length,
                HCI_MAX_EXT_AD_LENGTH);
    // 分片操作:若数据超过单次传输长度,需要分多帧传输
    // Operation: 0x00=中间帧, 0x01=首帧, 0x02=末帧, 0x03=完整数据
    err = __hci_cmd_sync_status(hdev, HCI_OP_LE_SET_EXT_ADV_DATA, ...);
    return err;
}

ext_adv_capable() 宏(hci_core.h:2023):

#define ext_adv_capable(dev) (((dev)->le_features[1] & HCI_LE_EXT_ADV))

HCI_LE_EXT_ADV 位(include/net/bluetooth/hci.h:647):

#define HCI_LE_EXT_ADV     0x10   // le_features[1] 第 4 位

24.6 Periodic Advertising(周期广播)

周期广播允许广播者以固定周期发送数据,接收者通过同步流程加入:

  • 广播者:HCI_OP_LE_SET_PER_ADV_PARAMS + HCI_OP_LE_SET_PER_ADV_DATA + HCI_OP_LE_SET_PER_ADV_ENABLE
  • 接收者:HCI_OP_LE_PA_CREATE_SYNC(通过 Extended Scan 发现广播者后同步)

内核能力检测(hci_core.h:2040):

#define per_adv_capable(dev) (((dev)->le_features[1] & HCI_LE_PERIODIC_ADV))

24.7 隐私保护(Privacy/RPA)

LE 隐私保护通过可解析私有地址(RPA,Resolvable Private Address)实现,防止蓝牙地址被追踪:

RPA 生成:
  random_part = rand[22 bits]  (随机)
  hash        = ah(IRK, random_part)[24 bits]
  RPA         = hash[24 bits] || random_part[24 bits] || 0b11[2 bits]

RPA 解析:
  已知 IRK 时,验证 ah(IRK, random_part) == hash 即可确认是同一设备

LL Privacy(控制器层隐私)能力检测(hci_core.h:1993):

#define ll_privacy_capable(dev) ((dev)->le_features[0] & HCI_LE_LL_PRIVACY)
#define ll_privacy_enabled(dev) (le_enabled(dev) && ll_privacy_capable(dev))

ll_privacy_capable 时,地址解析和 RPA 生成卸载到控制器,通过 HCI_OP_LE_ADD_DEVICE_TO_RESOLV_LIST 命令管理 Resolving List。


25. SMP 配对深度分析

25.1 SMP 注册机制

smp_register()smp.c:3404)在每个支持 LE 的 HCI 设备初始化时被调用,创建对应的 L2CAP 固定信道:

// smp.c:3404
int smp_register(struct hci_dev *hdev)
{
    if (!lmp_le_capable(hdev))
        return 0;

    // 注册 LE SMP 信道(CID=0x0006)
    chan = smp_add_cid(hdev, L2CAP_CID_SMP);
    hdev->smp_data = chan;

    // 若支持 SC(Secure Connections)或强制启用 BR/EDR SMP,
    // 同时注册 BR/EDR SMP 信道(CID=0x0007)
    if (!lmp_sc_capable(hdev)) {
        if (!hci_dev_test_flag(hdev, HCI_FORCE_BREDR_SMP))
            return 0;
    }

    chan = smp_add_cid(hdev, L2CAP_CID_SMP_BREDR);
    hdev->smp_bredr_data = chan;

    return 0;
}

25.2 配对请求/响应 PDU 格式

SMP 配对请求(Pairing Request,命令码 0x01)和配对响应(Pairing Response,0x02)均为 7 字节:

字节 0:  命令码(0x01 / 0x02)
字节 1:  IO Capability
         0x00 = DisplayOnly
         0x01 = DisplayYesNo
         0x02 = KeyboardOnly
         0x03 = NoInputNoOutput
         0x04 = KeyboardDisplay
字节 2:  OOB 数据标志(0x00=无 / 0x01=有)
字节 3:  AuthReq 位域
         bit[0]   = Bonding_Flags[0]
         bit[1]   = Bonding_Flags[1](01=Bonding)
         bit[2]   = MITM
         bit[3]   = SC(Secure Connections)
         bit[4]   = Keypress
         bit[5]   = CT2(h7 函数)
字节 4:  Maximum Encryption Key Size(7-16)
字节 5:  Initiator Key Distribution
字节 6:  Responder Key Distribution

smp_chan->preq[7] / smp_chan->prsp[7] 分别缓存请求和响应 PDU(smp.c:96)。

25.3 关联模型选择

根据双方的 IO Capability 和 MITM 要求选择关联模型:

     响应方
     |  DisplayOnly | DisplayYesNo | KeyboardOnly | NoInputNoOutput | KeyboardDisplay
发起 |
方   |
-----+-------------------------------------------------------------------
DisplayOnly       | JW  | JW | Passkey | JW  | Passkey
DisplayYesNo      | JW  | NC | Passkey | JW  | NC/Passkey
KeyboardOnly      | PK  | PK | PK      | JW  | PK
NoInputNoOutput   | JW  | JW | JW      | JW  | JW
KeyboardDisplay   | PK  | NC | PK      | JW  | NC/PK

JW = Just Works, NC = Numeric Comparison, PK = Passkey Entry

MITM=0 时强制使用 Just Works;MITM=1 则按上表选择。

25.4 SC Passkey Entry 流程(f4 函数应用)

LE SC 的 Passkey Entry 不同于 Legacy 配对,需要对 20 位 passkey 的每一位进行独立的 Confirm/Random 交换:

for i in 0..19:
    发起方:
        ra = random()
        Confirm_a = f4(PKa, PKb, ra, passkey_bit_i)
        发送 SMP_CMD_PAIRING_CONFIRM(Confirm_a)

    响应方:
        rb = random()
        Confirm_b = f4(PKb, PKa, rb, passkey_bit_i)
        接收 Confirm_a,发送 SMP_CMD_PAIRING_CONFIRM(Confirm_b)

    双方交换 Random(SMP_CMD_PAIRING_RANDOM)后验证 Confirm 值
    若所有 20 位验证通过,继续 DHKey Check 流程

25.5 OOB 配对(Out-of-Band)

OOB 数据通过带外通道(如 NFC)传递,包含:

  • 本地随机数(smp_generate_oob() 第 538 行):16 字节
  • 本地 OOB 哈希:smp_f4(pk, pk, rand, 0) 结果
// smp.c:538
int smp_generate_oob(struct hci_dev *hdev, u8 hash[16], u8 rand[16])
{
    struct smp_dev *smp = hdev->smp_data;

    // 生成本地随机数
    get_random_bytes(smp->local_rand, 16);
    memcpy(rand, smp->local_rand, 16);

    // 计算哈希值:f4(local_pk, local_pk, local_rand, 0)
    err = smp_f4(smp->tfm_cmac, smp->local_pk, smp->local_pk,
                 smp->local_rand, 0, hash);
    return err;
}

25.6 密钥分发机制

配对完成后,双方按 Key Distribution 字段进行密钥交换:

密钥分发字段位:
  bit[0] = EncKey  -> LTK + EDIV + Rand(Legacy 配对)
  bit[1] = IdKey   -> IRK + Identity Address
  bit[2] = Sign    -> CSRK(Connection Signature Resolving Key)
  bit[3] = LinkKey -> BR/EDR Link Key(LE SC 跨传输密钥派生)

交叉传输密钥派生(SMP_LTK_P256 -> BR/EDR Link Key)使用 h6() / h7() 函数(由 CT2 标志控制),允许 LE SC 配对后同时获得 BR/EDR 密钥,无需再次配对。


26. MGMT Mesh 网络支持

26.1 概述

从 MGMT_REVISION 20 开始,内核蓝牙子系统通过 MGMT 接口为 Bluetooth Mesh 提供基础支持。Mesh 网络使用 LE 广播作为传输载体,通过 MGMT 层为用户态 Mesh 栈(如 BlueZ mesh daemon)提供收发接口。

相关 MGMT 命令(include/net/bluetooth/mgmt.h):

命令 操作码 说明
MGMT_OP_SET_MESH_RECEIVER 0x0057 启用/禁用 Mesh 广播接收
MGMT_OP_MESH_READ_FEATURES 0x0058 读取 Mesh 特性(最大句柄数等)
MGMT_OP_MESH_SEND 0x0059 发送 Mesh 广播包
MGMT_OP_MESH_SEND_CANCEL 0x005A 取消待发送的 Mesh 包

26.2 MGMT_OP_SET_MESH_RECEIVER 结构体

mgmt.h:852

// mgmt.h:852
#define MGMT_OP_SET_MESH_RECEIVER  0x0057
struct mgmt_cp_set_mesh {
    __u8   enable;         // 0=禁用,1=启用
    __le16 window;         // 扫描窗口(单位 0.625ms)
    __le16 period;         // 扫描周期(单位 0.625ms)
    __u8   num_ad_types;   // 过滤的 AD Type 数量
    __u8   ad_types[] __counted_by(num_ad_types);  // AD Type 列表
} __packed;

26.3 Mesh 发送参数

mgmt.h:872

// mgmt.h:872
#define MGMT_OP_MESH_SEND  0x0059
struct mgmt_cp_mesh_send {
    struct mgmt_addr_info addr;  // 目标地址(Mesh 中通常为广播)
    __le64  instant;             // 发送时刻(绝对时间)
    __le16  delay;               // 延迟(微秒)
    __u8    cnt;                 // 重复发送次数
    __u8    adv_data_len;
    __u8    adv_data[];          // 广播数据(包含 Mesh PDU)
} __packed;

26.4 Mesh 特性读取(MGMT_OP_MESH_READ_FEATURES

// mgmt.h:865
#define MESH_HANDLES_MAX  3      // 最多同时存在 3 个 Mesh 发送句柄
struct mgmt_rp_mesh_read_features {
    __le16 index;               // HCI 设备索引
    __u8   max_handles;         // 最大句柄数(= MESH_HANDLES_MAX = 3)
    __u8   used_handles;        // 当前使用的句柄数
    __u8   handles[MESH_HANDLES_MAX]; // 已分配的句柄列表
} __packed;

26.5 Mesh 发送完成事件

// mgmt.h:1194
#define MGMT_EV_MESH_PACKET_CMPLT  0x0032

// mgmt.c:1082
static void mesh_send_complete(struct hci_dev *hdev,
                               struct mgmt_mesh_tx *mesh_tx, bool silent)
{
    u8 handle = mesh_tx->handle;

    if (!silent)
        mgmt_event(MGMT_EV_MESH_PACKET_CMPLT, hdev, &handle,
                   sizeof(handle), NULL);

    mgmt_mesh_remove(mesh_tx);
}

silent=true 时不发送事件(如取消发送),silent=false 时发送 MGMT_EV_MESH_PACKET_CMPLT 通知用户态发送已完成。

26.6 Mesh 接收流程

启用 Mesh 接收后,匹配到指定 AD Type 的广播包会通过 MGMT_EV_MESH_DEVICE_FOUND(0x0031)事件上报给用户态 Mesh 栈,由用户态解析 Mesh PDU 并处理网络层逻辑(如中继、加密、分组等)。内核仅提供收发通道,不实现 Mesh 网络协议栈本身。


27. A2DP / AVDTP 音频配置文件

27.1 概述

A2DP(Advanced Audio Distribution Profile)是蓝牙立体声音频标准,使用 AVDTP(Audio/Video Distribution Transport Protocol)作为传输协议。

重要:A2DP/AVDTP 的核心逻辑在用户空间(PulseAudio/PipeWire + BlueZ 插件)实现,内核仅提供必要的 socket 原语。

用户空间通过以下接口与内核交互:

PipeWire / PulseAudio
    |
    v  socket(AF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP)
       connect() 到 PSM=0x0019 (AVDTP)
    |
    v  L2CAP 连接建立(BR/EDR ACL 链路)
       协商 MTU = 672 (AVDTP 默认)
    |
    v  AVDTP 信令(Discover / GetCapabilities / SetConfiguration / Open)
    |
    v  打开媒体传输信道(另一条 L2CAP 连接)
    |
    v  AVDTP_DATA(SBC/AAC/aptX 编码数据)通过媒体信道传输

BTPROTO_AVDTP = 7 在内核中注册锁类(af_bluetooth.c:57),但协议本身不在内核实现。

27.2 内核侧 A2DP 相关支持

虽然 AVDTP 协议在用户态实现,但以下内核功能为 A2DP 提供支撑:

  1. L2CAP 流媒体模式(Streaming Mode)L2CAP_MODE_STREAMING = 0x04,针对音频优化,无重传,低延迟
  2. HCI_CODEC 管理net/bluetooth/hci_codec.c 管理控制器支持的编解码器,通过 BT_CODEC socket 选项查询
  3. 宽带语音BTUSB_WIDEBAND_SPEECH 标志,支持 mSBC 16kHz 采样语音(HFP HD Voice)
  4. SCO/eSCO 链路:用于 HSP/HFP 语音通话,hci_conn.c 第 52-68 行定义了 esco_param_cvsd 等参数

27.3 编解码器枚举(hci_codec.c

// net/bluetooth/hci_codec.c
// 通过 HCI_OP_READ_LOCAL_CODEC_CAPABILITIES 读取控制器支持的编解码器
// 存储在 hdev->local_codecs 链表中
// 用户空间通过 BT_CODEC socket 选项(值=19)查询

27.4 A2DP 音频数据传输路径(用户空间视角)

PCM 音频数据(来自麦克风/音乐播放器)
    |
    v  编码(SBC / AAC / aptX / LC3)
    |
    v  AVDTP 媒体包格式封装
       RTP Header(2 字节)+ AVDTP Header(12 字节)+ 编码数据
    |
    v  write() -> L2CAP Streaming Mode socket
    |
    v  L2CAP Core -> HCI ACL 数据 -> btusb -> USB -> 蓝牙控制器
    |
    v  无线传输(BR/EDR 2.4GHz)
    |
    v  接收端蓝牙芯片 -> 解码 -> DAC -> 扬声器

28. HCI 初始化流程详解

28.1 四阶段初始化

hci_init_sync()hci_sync.c:4913)将 HCI 初始化分为四个阶段:

// hci_sync.c:4913
static int hci_init_sync(struct hci_dev *hdev)
{
    // Stage 1:基础信息读取(所有设备类型)
    err = hci_init1_sync(hdev);  // 行 4917

    // 创建基础 debugfs 文件
    if (hci_dev_test_flag(hdev, HCI_SETUP))
        hci_debugfs_create_basic(hdev);

    // Stage 2:LE / BR/EDR 特性扩展读取
    err = hci_init2_sync(hdev);  // 行 4924

    // Stage 3:进阶功能配置(SSP、EIR、事件掩码等)
    err = hci_init3_sync(hdev);  // 行 4928

    // Stage 4:LE 高级功能(PHY、数据长度扩展)
    err = hci_init4_sync(hdev);  // 行 4932
}

28.2 Stage 1:基础版本读取(hci_init1_sync,行 3742)

hci_init1_sync()
    |
    +-- hci_read_local_version_sync()     // HCI_OP_READ_LOCAL_VERSION
    +-- hci_read_bd_addr_sync()           // HCI_OP_READ_BD_ADDR

28.3 Stage 2:特性扩展(hci_init2_sync,行 4047)

hci_init2_sync()
    |
    +-- [LE 支持]
    |   +-- hci_le_read_local_features_sync()   // LE 特性位图
    |   +-- hci_le_read_buffer_size_sync()       // LE ACL 缓冲区大小
    |   +-- hci_le_read_supported_states_sync()  // LE 支持的状态
    |
    +-- [BR/EDR 支持]
    |   +-- hci_read_buffer_size_sync()          // ACL/SCO 缓冲区大小
    |   +-- hci_read_local_name_sync()           // 本地设备名
    |   +-- hci_read_voice_setting_sync()        // 语音设置
    |   +-- hci_read_local_ext_features_1_sync() // LMP 扩展特性 Page 1
    ...

28.4 Stage 3:进阶功能(hci_init3_sync,行 4642)

hci_init3_sync()
    |
    +-- hci_set_event_mask_sync()         // 设置 HCI 事件掩码
    +-- hci_read_local_cmds_sync()        // 读取支持的命令列表
    +-- hci_write_ssp_mode_1_sync()       // 启用 Simple Secure Pairing
    +-- hci_write_eir_sync()              // 写扩展查询响应数据
    +-- hci_write_inquiry_mode_sync()     // 设置查询模式(RSSI/EIR)
    +-- hci_write_auth_enable_sync()      // 设置认证模式
    +-- [LE 支持]
    |   +-- hci_le_set_event_mask_sync()  // LE 事件掩码
    |   +-- hci_le_read_adv_tx_power_sync()
    |   +-- hci_le_read_resolv_list_size_sync()
    ...

28.5 Stage 4:LE 高级特性(hci_init4_sync,行 4897)

hci_init4_sync()
    |
    +-- le_init4[]
    |   +-- hci_le_set_write_def_data_len_sync()  // LE 数据长度扩展(DLE)
    |   +-- hci_le_set_default_phy_sync()         // 设置默认 PHY(1M/2M/Coded)
    |
    +-- [支持 SC(Secure Connections)时]
    |   +-- hci_le_read_local_oob_ext_data()      // 读取 OOB 扩展数据
    ...

28.6 初始化阶段宏系统

HCI_INIT() 宏(hci_sync.c:3645)使初始化序列以声明式数组描述,每个元素是一个函数指针:

// hci_sync.c:3645
#define HCI_INIT(_func) \
    { .func = _func }

static const struct hci_init_stage le_init4[] = {
    HCI_INIT(hci_le_set_write_def_data_len_sync),
    HCI_INIT(hci_le_set_default_phy_sync),
    {}  // 哨兵元素(func=NULL 表示结束)
};

hci_init_stage_sync()hci_sync.c:3615)遍历数组并依次调用每个函数,任一函数失败则中止并返回错误。


29. 蓝牙子系统电源管理

29.1 控制器开关电

蓝牙控制器的开关电由 hci_dev.power_on / power_off 工作项驱动,最终调用 hdev->open() / hdev->close()

MGMT 通过 MGMT_OP_SET_POWERED 控制:

bluetoothd: MGMT_OP_SET_POWERED(enable=1)
    |
    v  set_powered_sync()  [mgmt.c]
    |
    v  hci_power_on_sync()  [hci_sync.c]
       |
       v  hdev->open()  [btusb_open / hci_uart_open 等]
       |
       v  hci_init_sync()  (四阶段初始化)
       |
       v  hci_dev_set_flag(hdev, HCI_UP)
       |
       v  mgmt_powered(hdev, 1)  通知 bluetoothd

29.2 自动挂起(auto-suspend)

btusb.c 通过 USB PM 机制支持自动挂起。当无活动连接时,USB 设备进入低功耗状态(usb_enable_autosuspend())。

29.3 系统挂起/恢复

系统休眠时,蓝牙子系统通过 hci_suspend_notifier 监听 PM 事件:

// hci_core.c
static int hci_suspend_notifier(struct notifier_block *nb,
                                unsigned long action, void *data)
{
    switch (action) {
    case PM_SUSPEND_PREPARE:
        // 停止发现、配置唤醒过滤器(Wakeup filter)
        // 仅保留允许唤醒系统的设备的扫描
        hci_suspend_dev(hdev);
        break;
    case PM_POST_SUSPEND:
        // 恢复正常扫描参数
        hci_resume_dev(hdev);
        break;
    }
}

MGMT 事件 MGMT_EV_CONTROLLER_SUSPEND / MGMT_EV_CONTROLLER_RESUME 通知用户态。

29.4 rfkill 软关闭

通过 /sys/class/rfkill/rfkillN/state 写 0 可软关闭蓝牙,效果等同于 MGMT_OP_SET_POWERED(0)

// hci_core.c(rfkill 回调)
static int hci_rfkill_set_block(void *data, bool blocked)
{
    struct hci_dev *hdev = data;

    if (!blocked)
        return 0;  // 解除软封锁:由 bluetoothd 决定是否上电

    // 软封锁:强制关闭控制器
    hci_dev_do_close(hdev);
    return 0;
}

30. 完整数据流追踪示例

本节通过一个完整的 LE 连接数据发送示例,追踪数据从用户空间到硬件的完整路径。

30.1 场景描述

应用程序通过 BTPROTO_L2CAP socket 向 LE 对端设备的 GATT 服务发送 ATT Write Command。

30.2 用户空间到内核的路径

应用程序:
    fd = socket(AF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP);
    connect(fd, &addr, sizeof(addr));  // LE 连接,CID=4(ATT)
    write(fd, data, len);

    |
    v  系统调用进入内核
    v  l2cap_sock_sendmsg()  [l2cap_sock.c]

30.3 L2CAP 层处理

l2cap_sock_sendmsg()
    |
    v  l2cap_chan_send()  [l2cap_core.c]
       |
       +-- LE_FLOWCTL 模式:
       |     检查 tx_credits > 0
       |     若 credits 耗尽,将 skb 挂入 l2cap_chan->tx_q
       |
       v  l2cap_create_le_flowctl_pdu()
          生成 LE Credit Based Frame(K-Frame)
          |
          v  l2cap_do_send()
             |
             v  hci_send_acl(conn->hcon, hchan, skb, flags)

30.4 HCI 层处理

hci_send_acl()
    |
    v  bt_cb(skb)->pkt_type = HCI_ACLDATA_PKT
    v  skb_queue_tail(&conn->data_q, skb)  // 入连接发送队列
    |
    v  hci_sched_acl()  或  queue_work(&hdev->tx_work)
    |
    v  hci_tx_work()  [hci_core.c]
       |
       v  while (acl_cnt > 0 && !skb_queue_empty(&conn->data_q)):
              skb = skb_dequeue(&conn->data_q)
              hdev->acl_cnt--
              hdev->send(hdev, skb)  // 调用传输层发送

30.5 传输层(btusb)处理

btusb_send_frame()  [drivers/bluetooth/btusb.c]
    |
    v  switch (hci_skb_pkt_type(skb)):
       case HCI_ACLDATA_PKT:
           usb_fill_bulk_urb(urb, data->udev,
                             usb_sndbulkpipe(data->udev, data->bulk_tx_ep->bEndpointAddress),
                             skb->data, skb->len,
                             btusb_bulk_out_complete, skb);
           |
           v  usb_submit_urb(urb, GFP_ATOMIC)
              提交到 USB Host Controller

30.6 接收完成与流控

USB 发送完成(URB complete callback):
    |
    v  btusb_bulk_out_complete()
       |
       v  若成功:hdev->acl_cnt++
                  queue_work(&hdev->tx_work)  // 继续发送队列中的下一个包

对端 LE 数据接收后发送 Number of Completed Packets 事件:
    |
    v  hci_event.c: hci_num_comp_pkts_evt()
       hdev->acl_cnt += num_completed   // 恢复发送配额
       hci_sched_acl(hdev)             // 调度更多数据发送

30.7 完整路径时序图

应用层              L2CAP              HCI Core          btusb          硬件
   |                  |                    |                |              |
   |-- write() -----> |                    |                |              |
   |                  |-- l2cap_do_send -->|                |              |
   |                  |                   |-- skb入data_q->|              |
   |                  |                   |                |              |
   |                  |               hci_tx_work          |              |
   |                  |                   |--hdev->send -->|              |
   |                  |                   |                |--URB submit->|
   |                  |                   |                |              |
   |                  |                   |                |<-URB done -- |
   |                  |                   |         acl_cnt++             |
   |                  |                   |                |              |
   |                  |          (对端返回 Num Completed Pkts 事件)        |
   |                  |                   |<-- HCI Event--|              |
   |                  |            acl_cnt+=completed     |              |
   |                  |          hci_sched_acl()          |              |

30.8 关键代码位置汇总

步骤 函数 文件:行号
用户 write() l2cap_sock_sendmsg() net/bluetooth/l2cap_sock.c
L2CAP 分帧 l2cap_create_le_flowctl_pdu() net/bluetooth/l2cap_core.c
HCI 排队 hci_send_acl() net/bluetooth/hci_core.c
HCI TX 调度 hci_tx_work() net/bluetooth/hci_core.c
USB 发送 btusb_send_frame() drivers/bluetooth/btusb.c
发送配额恢复 hci_num_comp_pkts_evt() net/bluetooth/hci_event.c

附录:关键常量速查

HCI 连接 Handle 范围

// include/net/bluetooth/hci_core.h:338-339
#define HCI_CONN_HANDLE_MAX     0x0eff
#define HCI_CONN_HANDLE_UNSET(_handle)  (_handle > HCI_CONN_HANDLE_MAX)

L2CAP 默认参数

// include/net/bluetooth/l2cap.h:34-60
#define L2CAP_DEFAULT_MTU           672
#define L2CAP_DEFAULT_TX_WINDOW     63
#define L2CAP_DEFAULT_MAX_TX        3
#define L2CAP_DEFAULT_RETRANS_TO    2000   // ms
#define L2CAP_DEFAULT_MONITOR_TO    12000  // ms
#define L2CAP_DEFAULT_ACK_TO        200    // ms
#define L2CAP_BREDR_MAX_PAYLOAD     1019   // 3-DH5 包的有效载荷
#define L2CAP_LE_MIN_MTU            23
#define LE_FLOWCTL_MAX_CREDITS      65535

LE PHY 类型

// include/net/bluetooth/bluetooth.h:133-156
#define BT_PHY_LE_1M_TX      BIT(9)
#define BT_PHY_LE_1M_RX      BIT(10)
#define BT_PHY_LE_2M_TX      BIT(11)
#define BT_PHY_LE_2M_RX      BIT(12)
#define BT_PHY_LE_CODED_TX   BIT(13)   // LE Coded PHY(长距离)
#define BT_PHY_LE_CODED_RX   BIT(14)

HCI LE Feature Bits(le_features[1],hci.h:644-648

// include/net/bluetooth/hci.h:644-648
#define HCI_LE_PHY_CODED    0x08  // le_features[1] 第 3 位:Coded PHY 支持
#define HCI_LE_EXT_ADV      0x10  // le_features[1] 第 4 位:扩展广播支持
#define HCI_LE_PERIODIC_ADV 0x20  // le_features[1] 第 5 位:周期广播支持

HCI LE PHY 位定义(hci.h:1884

// include/net/bluetooth/hci.h:1884
#define HCI_LE_SET_PHY_1M     0x01
#define HCI_LE_SET_PHY_2M     0x02
#define HCI_LE_SET_PHY_CODED  0x04

RFCOMM 超时常量(rfcomm.h:29-32

// include/net/bluetooth/rfcomm.h:29-32
#define RFCOMM_CONN_TIMEOUT (HZ * 30)   // 30 秒连接超时
#define RFCOMM_DISC_TIMEOUT (HZ * 20)   // 20 秒断连超时
#define RFCOMM_AUTH_TIMEOUT (HZ * 25)   // 25 秒认证超时
#define RFCOMM_IDLE_TIMEOUT (HZ * 2)    // 2 秒空闲后关闭 session

SMP 相关常量(smp.c:58

#define SMP_TIMEOUT  secs_to_jiffies(30)  // 配对超时 30 秒

ISO 超时常量(iso.c:95-96

#define ISO_CONN_TIMEOUT    secs_to_jiffies(20)   // CIS 连接超时 20 秒
#define ISO_DISCONN_TIMEOUT secs_to_jiffies(2)    // 断连确认超时 2 秒

Mesh MGMT 操作码(mgmt.h:852-887

#define MGMT_OP_SET_MESH_RECEIVER    0x0057
#define MGMT_OP_MESH_READ_FEATURES   0x0058
#define MGMT_OP_MESH_SEND            0x0059
#define MGMT_OP_MESH_SEND_CANCEL     0x005A
#define MGMT_EV_MESH_DEVICE_FOUND    0x0031
#define MGMT_EV_MESH_PACKET_CMPLT    0x0032
#define MESH_HANDLES_MAX             3

由 Claude Code 分析生成