Linux蓝牙之内核中LE Audio的实现分析

背景

分析参考:

内核版本: Linux Kernel v7.1.0-rc6
版本基准: Bluetooth Core Spec 5.3+

之前有简单地介绍过蓝牙 LE Audio

今天来看看 Linux kernel 中 LE Audio 的实现。


总体架构:

LE Audio 在 Linux 中的实现遵循清晰的分层设计,Kernel 仅提供传输层:

层级 位置 职责
Kernel (本仓库) net/bluetooth/ ISO 数据通道 (CIS/BIS sockets)、HCI 命令接口
Userspace (BlueZ) 外部项目 BAP、PACS、ASCS、MCP、CCP、VCP、TMAP 等 Profile
Codec 外部库 (如 liblc3) LC3 编解码

核心原则: Kernel 使用 codec = 0x03 (Transparent Data) 配置 ISO 数据路径,不参与任何编解码。

整体架构分层

┌────────────────────────────────────────────────────────────────┐
│                        Userspace (BlueZ)                       │
│  ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌──────────┐  │
│  │  BAP    │ │  PACS   │ │  ASCS   │ │  MCP    │ │ LC3 Codec│  │
│  │ Profile │ │ Profile │ │ Profile │ │  etc.   │ │ (liblc3) │  │
│  └────┬────┘ └────┬────┘ └────┬────┘ └────┬────┘ └────┬─────┘  │
│  ┌────┴───────────┴───────────┴───────────┴───────────┴─────┐  │
│  │           Socket API (PF_BLUETOOTH, SOCK_SEQPACKET)      │  │
│  └──────────────────────────┬───────────────────────────────┘  │
└─────────────────────────────┼──────────────────────────────────┘
                              │ BTPROTO_ISO
──────────────────────────────┼──────────────────────────────────
┌─────────────────────────────┼──────────────────────────────────┐
│  Kernel Space               │        Linux Bluetooth Stack     │
│  ┌──────────────────────────┴───────────────────────────────┐  │
│  │              ISO Socket Layer (net/bluetooth/iso.c)      │  │
│  │   iso_sock_connect / iso_sock_listen / iso_sock_sendmsg  │  │
│  │   iso_sock_recvmsg / iso_conn_big_sync                   │  │
│  └──────────────────────────┬───────────────────────────────┘  │
│  ┌──────────────────────────┴───────────────────────────────┐  │
│  │         HCI Connection Management (hci_conn.c)           │  │
│  │  ┌─────────────────┐      ┌─────────────────────────┐    │  │
│  │  │  Unicast (CIS)  │      │  Broadcast (BIS/BIG)    │    │  │
│  │  │  hci_connect_cis│      │  hci_connect_bis        │    │  │
│  │  │  hci_bind_cis   │      │  hci_bind_bis           │    │  │
│  │  │  hci_le_set_cig_│      │  hci_iso_setup_path     │    │  │
│  │  │    params       │      │  hci_past_bis           │    │  │
│  │  │  hci_iso_setup_ │      │                         │    │  │
│  │  │    path         │      │                         │    │  │
│  │  └────────┬────────┘      └───────────┬─────────────┘    │  │
│  └───────────┼───────────────────────────┼──────────────────┘  │
│  ┌───────────┴───────────────────────────┴──────────────────┐  │
│  │          Synchronous HCI Commands (hci_sync.c)           │  │
│  │  set_cig_params_sync / hci_le_create_cis / create_big    │  │
│  │  hci_le_big_create_sync / hci_le_big_terminate_sync      │  │
│  └──────────────────────────┬───────────────────────────────┘  │
│  ┌──────────────────────────┴───────────────────────────────┐  │
│  │           HCI Event Handlers (hci_event.c)               │  │
│  │  hci_le_cis_established_evt / hci_le_cis_req_evt         │  │
│  │  hci_le_create_big_complete_evt / hci_le_big_sync_est    │  │
│  │  hci_le_big_sync_lost_evt / hci_le_big_info_adv_report   │  │
│  └──────────────────────────┬───────────────────────────────┘  │
│  ┌──────────────────────────┴───────────────────────────────┐  │
│  │         MGMT Interface (mgmt.c)                          │  │
│  │    set_iso_socket_func (实验性功能开关)                    │  │
│  └──────────────────────────────────────────────────────────┘  │
└─────────────────────────────┬──────────────────────────────────┘
                              │ HCI (UART/USB/SDIO)
──────────────────────────────┼──────────────────────────────────
┌─────────────────────────────┼──────────────────────────────────┐
│        Bluetooth Controller (Firmware / Hardware)              │
│  ┌──────────────────────────┴───────────────────────────────┐  │
│  │         LE Audio HCI Commands & Events (BT 5.3+)         │  │
│  │                                                          │  │
│  │  CIS/CIG: Set CIG Params → Create CIS → Setup ISO        │  │
│  │           Path → CIS Established/Request Events          │  │
│  │                                                          │  │
│  │  BIS/BIG: Create BIG → BIG Complete → Terminate BIG      │  │
│  │           BIG Create Sync → BIG Sync Est/Lost Events     │  │
│  │                                                          │  │
│  │  ISO Data: ISO PDU fragments (START/CONT/END/SINGLE)     │  │
│  └──────────────────────────────────────────────────────────┘  │
└────────────────────────────────────────────────────────────────┘

现状:Unicast + Broadcast 全覆盖

Unicast (CIS/CIG)

HCI 命令/事件 Opcode/Event 状态
HCI_OP_LE_SET_CIG_PARAMS 0x2062 完整实现
HCI_OP_LE_CREATE_CIS 0x2064 完整实现
HCI_OP_LE_REMOVE_CIG 0x2065 完整实现
HCI_OP_LE_ACCEPT_CIS 0x2066 完整实现
HCI_OP_LE_REJECT_CIS 0x2067 完整实现
HCI_OP_LE_SETUP_ISO_PATH 0x206e 完整实现
HCI_OP_LE_READ_ISO_TX_SYNC 0x2061 完整实现
HCI_EVT_LE_CIS_ESTABLISHED 0x19 完整实现
HCI_EVT_LE_CIS_REQ 0x1a 完整实现

Broadcast (BIS/BIG)

HCI 命令/事件 Opcode/Event 状态
HCI_OP_LE_CREATE_BIG 0x2068 完整实现
HCI_OP_LE_TERM_BIG 0x206a 完整实现
HCI_OP_LE_BIG_CREATE_SYNC 0x206b 完整实现
HCI_OP_LE_BIG_TERM_SYNC 0x206c 完整实现
HCI_EVT_LE_CREATE_BIG_COMPLETE 0x1b 完整实现
HCI_EVT_LE_BIG_SYNC_ESTABLISHED 0x1d 完整实现
HCI_EVT_LE_BIG_SYNC_LOST 0x1e 完整实现
HCI_EVT_LE_BIG_INFO_ADV_REPORT 0x22 完整实现

MGMT 接口

ISO 作为实验性功能,需要 userspace 通过 MGMT_OP_SET_EXP_FEATURE 显式启用。

角色设置位:

Bits 含义
MGMT_SETTING_CIS_CENTRAL (bit 18) CIS Central 角色
MGMT_SETTING_CIS_PERIPHERAL (bit 19) CIS Peripheral 角色
MGMT_SETTING_ISO_BROADCASTER (bit 20) BIS Broadcaster
MGMT_SETTING_ISO_SYNC_RECEIVER (bit 21) BIS Sync Receiver
MGMT_SETTING_PAST_SENDER (bit 23) PAST Sender
MGMT_SETTING_PAST_RECEIVER (bit 24) PAST Receiver

Unicast (CIS/CIG) 连接建立流程

Userspace (BlueZ)              Kernel                        Controller
      │                          │                              │
      │ socket(PF_BLUETOOTH,     │                              │
      │   SOCK_SEQPACKET,        │                              │
      │   BTPROTO_ISO)           │                              │
      │ ───────────────────────> │                              │
      │                          │                              │
      │ setsockopt(BT_ISO_QOS)   │                              │
      │ ───────────────────────> │                              │
      │                          │                              │
      │ connect()                │                              │
      │ ───────────────────────> │                              │
      │                          │ hci_connect_cis()            │
      │                          │   ├ hci_connect_le()         │
      │                          │   │   (先建立 LE ACL 连接)    │
      │                          │   ├ hci_bind_cis()           │
      │                          │   │   └ hci_le_set_cig_params│
      │                          │   │      ────────────────>   │
      │                          │   │      <── CC              │
      │                          │   │                          │
      │                          │   └ hci_le_create_cis_pending│
      │                          │      └ HCI_OP_LE_CREATE_CIS  │
      │                          │       ──────────────────>    │
      │                          │                              │
      │                          │    <── CIS ESTABLISHED EVT   │
      │                          │                              │
      │                          │ hci_iso_setup_path()         │
      │                          │   ├ direction=0 (H→C)       │
      │                          │   │   codec=3 (透明)         │
      │                          │   │   ──────────────>        │
      │                          │   │   <── CC                 │
      │                          │   ├ direction=1 (C→H)        │
      │                          │   │   ──────────────>        │
      │                          │   │   <── CC                 │
      │                          │                              │
      │ <──── connect  返回 ──────│                              │
      │                          │                              │
      │ sendmsg(audio_data)      │                              │
      │ ───────────────────────> │ HCI ISO Data  ─────────────> │
      │                          │                              │
      │ recvmsg(audio_data)      │                              │
      │ <─────────────────────── │ <──  HCI ISO Data ────────── │

Broadcast (BIS/BIG) 流程

Broadcaster 端

US(Broadcaster)                Kernel                      Controller
      │                          │                            │
      │ connect(BIS, BIG=1,      │                            │
      │        BIS=1, BASE)      │                            │
      │ ───────────────────────> │                            │
      │                          │ hci_connect_bis()          │
      │                          │   ├ hci_bind_bis()         │
      │                          │   │   (分配 SID/BIG/BIS)   │
      │                          │   ├ start_per_adv_sync()   │
      │                          │   │   ───────────> Periodic│
      │                          │   │         Advertising    │
      │                          │   └ create_big_sync()      │
      │                          │      ────────────> HCI_OP_ │
      │                          │          LE_CREATE_BIG     │
      │                          │                            │
      │                          │  <── CREATE BIG COMPLETE   │
      │                          │                            │
      │ sendmsg(audio_data)      │                            │
      │ ───────────────────────> │ HCI ISO Data ────────────> │

Receiver (Sink) 端

US(Receiver)                   Kernel                      Controller
      │                          │                            │
      │ socket() + set QoS +     │                            │
      │ bind() + listen()        │                            │
      │ ───────────────────────> │                            │
      │                          │                            │
      │                   收到 BIG Info Adv Report            │
      │                       <── HCI_EVT (0x22)              │
      │                          │                            │
      │                   收到 PA 数据 (Periodic Adv)          │
      │                       <──                             │
      │                          │ iso.c 解析 PA 数据          │
      │                          │ 提取 BASE (BAA 0x1851)     │
      │                          │                            │
      │ accept()                 │                            │
      │ ───────────────────────> │ iso_conn_big_sync()        │
      │                          │   └ hci_le_big_create_sync │
      │                          │      ────────────> HCI_OP_ │
      │                          │         LE_BIG_CREATE_SYNC │
      │                          │                            │
      │                          │  <── BIG SYNC ESTABLISHED  │
      │                          │                            │
      │ recvmsg()                │                            │
      │ <─────────────────────── │ <──  HCI ISO Data ──────── │

ISO 数据帧分片 / 重组 (PDU)

发送端 (iso_sock_sendmsg):
  ┌──────────┐
  │ 完整 PDU │
  └────┬─────┘
       │ 根据 HCI Max Data Length 分片
       ├── PDU ≤ Max → ISO_SINGLE (0x30)
       │
       └── PDU > Max → ISO_START (0x10) + ISO_CONT(0x20)×N + ISO_END(0x30)

接收端 (iso_sock_recvmsg):
  ISO_START → alloc_skb(len), skb_put(data)
  ISO_CONT  → skb_put(skb, data)
  ISO_END   → skb_put(skb, data); iso_recv_frame()  ← 完整 PDU 上报
  ISO_SINGLE→ iso_recv_frame()                       ← 直接上报

关键数据结构关系

struct sock ──→ struct iso_pinfo          (per-socket)
                  ├── src / dst 地址
                  ├── qos (struct bt_iso_qos)
                  ├── base / base_len      (广播 BASE 数据)
                  ├── flags                (BIG_SYNC / PA_SYNC)
                  ├── sync_handle          (PA 句柄)
                  └── conn ──→ struct iso_conn  (per-connection)
                                 ├── hcon ──→ struct hci_conn
                                 │              ├── type: CIS_LINK/BIS_LINK
                                 │              ├── iso_qos
                                 │              ├── handle (Connection Handle)
                                 │              ├── state
                                 │              ├── parent (指向 ACL LE conn)
                                 │              └── flags
                                 ├── rx_skb / rx_len  (分片重组缓冲区)
                                 └── tx_sn            (发送序列号)

QoS 结构体层次

struct bt_iso_qos (union)
  ├── ucast (struct bt_iso_ucast_qos)
  │     ├── cig (CIG ID, 0x00-0xEF)
  │     ├── cis (CIS ID, 0x00-0xEF)
  │     ├── out (struct bt_iso_io_qos)    // Host→Controller
  │     │     ├── sdu (SDU size)
  │     │     ├── phys (PHY)
  │     │     ├── rtn (retransmissions)
  │     │     ├── latency
  │     │     └── interval
  │     └── in  (struct bt_iso_io_qos)    // Controller→Host
  │
  └── bcast (struct bt_iso_bcast_qos)
        ├── big (BIG ID)
        ├── bis (BIS ID)
        ├── encryption
        ├── bcode (16 bytes 广播码)
        ├── out (struct bt_iso_io_qos)
        ├── sync_timeout
        ├── sync_cte_type
        ├── mse
        └── iso_interval

代码调用链概览

Userspace Socket API
 │
 ├─ Unicast: connect()
 │   iso_sock_connect()                     [iso.c]
 │   └→ hci_connect_cis()                  [hci_conn.c]
 │       ├→ hci_connect_le() / hci_connect_le_scan()
 │       ├→ hci_bind_cis()
 │       │   └→ hci_le_set_cig_params()
 │       │       └→ set_cig_params_sync()
 │       │           └→ HCI_OP_LE_SET_CIG_PARAMS
 │       └→ hci_le_create_cis_pending()
 │           └→ hci_le_create_cis_sync()
 │               └→ HCI_OP_LE_CREATE_CIS
 │
 ├─ Broadcast (Source): connect()
 │   iso_sock_connect()                     [iso.c]
 │   └→ hci_connect_bis()                  [hci_conn.c]
 │       ├→ hci_bind_bis()
 │       ├→ hci_start_per_adv_sync()
 │       └→ create_big_sync()
 │           └→ HCI_OP_LE_CREATE_BIG
 │
 ├─ Broadcast (Sink): listen() + PA Sync
 │   iso_conn_big_sync()                    [iso.c]
 │   └→ hci_le_big_create_sync()           [hci_sync.c]
 │       └→ HCI_OP_LE_BIG_CREATE_SYNC
 │
 └─ Data Path: sendmsg() / recvmsg()
     iso_sock_sendmsg()                     [iso.c]
     └→ hci_send_iso()
     iso_recv()                             [iso.c]
     └→ iso_recv_frame()

LC3 Codec

Kernel 中不存在 LC3 定义或实现。

已定义的 Codec ID 仅包括:

Codec ID
BT_CODEC_CVSD 0x02
BT_CODEC_TRANSPARENT 0x03
BT_CODEC_MSBC 0x05

LC3 (ID 0x06) 完全由 userspace 端处理 (BlueZ 集成 liblc3)。