Linux蓝牙之内核中LE Audio的实现分析
Linux蓝牙之内核中LE Audio的实现分析
背景
分析参考:
内核版本: Linux Kernel v7.1.0-rc6
版本基准: Bluetooth Core Spec 5.3+
之前有简单地介绍过蓝牙 LE Audio:
- https://mp.weixin.qq.com/s/mNyc-dJw7qgS45NCEGyxQA
- https://notes.z-dd.online/2025/10/30/%E8%93%9D%E7%89%99%E4%B9%8B%E4%BD%8E%E5%8A%9F%E8%80%97%E9%9F%B3%E9%A2%91-LE%20Audio/
今天来看看 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)。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 DD'Notes!
评论







