2. SCO连接建立流程:HCI_Setup_Synchronous_Connection命令详解

SCO(Synchronous Connection Oriented)链路是蓝牙音频传输的基础,用于承载等时(Isochronous)数据流,如HFP(Hands-Free Profile)和HSP(Headset Profile)中的语音数据。建立SCO连接的核心操作是Host Controller发送HCI_Setup_Synchronous_Connection命令。本章将深入解析该命令的构造、参数配置及其对音频质量的影响。

2.1 SCO连接建立流程概览

在ACL(Asynchronous Connection-Less)链路建立之后,Host通过HCI命令向Controller发起SCO连接请求。整个流程分为三个阶段:参数准备、命令下发、连接完成。

关键流程节点: Host构造命令 → Controller执行链路建立 → 返回Connection Complete事件。
SCO连接建立流程 Host 应用层 HCI Driver Controller ① 构造命令参数 ② 下发HCI命令 ③ 建立SCO链路 ④ 返回Complete事件

2.2 HCI_Setup_Synchronous_Connection命令结构

该命令属于HCI Command Group中的SCO Link Control命令,OpCode为0x0428。命令参数决定了SCO链路的传输特性。

参数名称 字节数 取值范围 说明
Connection_Handle 2 0x0000 - 0x0EFF 已建立的ACL连接句柄
Tx_Bandwidth 4 0x000000 - 0xFFFFFF 发送带宽(单位:B/s),通常设为8000
Rx_Bandwidth 4 0x000000 - 0xFFFFFF 接收带宽(单位:B/s),通常设为8000
Voice_Setting 2 Bitmask 编码格式、采样率、数据路径配置
Max_Latency 2 0x0004 - 0xFFFE 最大延迟(单位:0.625ms slots)
Retransmission_Effort 1 0x00 - 0x02 重传策略:0=无重传,1=尽力,2=强制
Packet_Type 2 Bitmask 允许的SCO/eSCO包类型
提示: 在Linux内核中,该命令通过hci_send_cmd()函数下发,参数封装在struct hci_cp_setup_sync_conn结构体中。

2.3 核心参数详解

2.3.1 Tx/Rx带宽配置

带宽参数以字节/秒为单位。对于标准的8kHz采样、16bit量化的PCM语音流,带宽计算如下:

带宽 = 采样率 × 量化位数 × 通道数 / 8
     = 8000 × 16 × 1 / 8
     = 16000 字节/秒

实际配置中,Tx_Bandwidth和Rx_Bandwidth通常设置为8000(对应8kHz采样率),因为蓝牙协议栈内部会进行带宽换算。若使用CVSD编码,带宽需求会降低。

2.3.2 Voice_Setting(语音编码配置)

Voice_Setting是一个16位的位掩码,控制编码格式、采样率、数据路径等。其结构如下:

Voice_Setting 位域结构 (16-bit) Bit 0-1 Bit 2-4 Bit 5 Bit 6-7 Bit 8-9 Bit 10-15 编码格式 采样率 数据路径 采样位数 保留/厂商 保留

常见的Voice_Setting配置值:

编码格式 采样率 采样位数 Voice_Setting值 典型应用
CVSD 8kHz 16bit 0x0060 HFP/HSP默认
PCM A-law 8kHz 8bit 0x0003 传统电话网络
PCM μ-law 8kHz 8bit 0x0007 北美/日本
Linear PCM 8kHz 16bit 0x0000 高质量音频
Linear PCM 16kHz 16bit 0x0010 WB语音(WBS)

2.3.3 重传机制(Retransmission_Effort)

重传机制是eSCO(Extended SCO)相对于传统SCO的核心改进。该参数控制链路层对丢失数据包的重传策略:

  • 0x00 (No Retransmission):不进行重传,适用于对延迟极度敏感的场景,如实时对讲。
  • 0x01 (Optimize for Power):尽力重传,在延迟和功耗之间平衡,最多重传1-2次。
  • 0x02 (Optimize for Quality):强制重传,尽可能保证数据完整性,适用于语音质量优先的场景。
注意: 重传次数增加会直接增大链路延迟。在HFP协议中,Max_Latency参数必须与重传策略配合调整,否则可能导致连接建立失败。

2.4 包类型选择(Packet_Type)

Packet_Type参数决定SCO/eSCO链路上允许使用的数据包格式。不同包类型对应不同的负载大小和抗干扰能力。

包类型 负载(字节) FEC 重传 典型延迟
HV1 10 1/3 不支持 3.75ms
HV2 20 2/3 不支持 5ms
HV3 30 无 不支持 3.75ms
EV3 30 无 支持 3.75ms
EV4 120 2/3 支持 5ms
EV5 180 无 支持 3.75ms
实践建议: 在Linux内核蓝牙驱动中,推荐使用EV5包类型配合Retransmission_Effort=0x02,以获得最佳语音质量。若对延迟敏感,可选用EV3并设置重传为0x01。

2.5 Linux内核中的命令构造示例

以下代码展示了在Linux蓝牙驱动中构造HCI_Setup_Synchronous_Connection命令的典型实现:

/* 构造SCO连接参数 */
struct hci_cp_setup_sync_conn cp;

memset(&cp, 0, sizeof(cp));

/* 设置ACL连接句柄 */
cp.handle = cpu_to_le16(conn->handle);

/* 设置Tx/Rx带宽(8kHz采样,16bit,单声道) */
cp.tx_bandwidth = cpu_to_le32(0x00001f40);  /* 8000 B/s */
cp.rx_bandwidth = cpu_to_le32(0x00001f40);  /* 8000 B/s */

/* 设置语音编码:CVSD,8kHz,16bit */
cp.voice_setting = cpu_to_le16(0x0060);

/* 设置最大延迟:16个slot(10ms) */
cp.max_latency = cpu_to_le16(0x0010);

/* 设置重传策略:尽力重传 */
cp.retransmission_effort = 0x01;

/* 设置包类型:允许EV3/EV4/EV5 */
cp.pkt_type = cpu_to_le16(EV3_PKT | EV4_PKT | EV5_PKT);

/* 下发命令 */
hci_send_cmd(hdev, HCI_OP_SETUP_SYNC_CONN, sizeof(cp), &cp);

2.6 连接建立后的状态验证

命令下发后,Controller会返回HCI_Connection_Complete事件。通过检查事件参数可以确认SCO链路是否成功建立:

  • Status = 0x00:连接建立成功。
  • Connection_Handle:新分配的SCO连接句柄(范围0x0000-0x0EFF)。
  • Link_Type = 0x01:表示SCO链路。
  • Encryption_Mode:加密模式,通常为0x00(不加密)。
调试技巧: 使用btmon或hcidump工具可以实时捕获HCI命令和事件,验证SCO连接参数是否按预期下发。重点关注HCI_Command_Status和HCI_Connection_Complete事件。
SCO连接命令与事件交互时序 Host HCI Transport Controller HCI_Setup_Sync_Conn HCI_Command_Status HCI_Connection_Complete 链路建立处理

2.7 常见配置问题与调试

问题现象 可能原因 解决方案
连接建立失败(Status=0x0E) Max_Latency与重传策略冲突 增大Max_Latency或降低重传等级
音频断续/丢包 Packet_Type选择不当或重传不足 启用EV4/EV5并设置重传为0x02
延迟过高 重传次数过多或包类型负载过大 使用EV3包类型并限制重传
编码不匹配 Voice_Setting与远端设备不兼容 协商使用双方都支持的编码格式
内核调试入口: 在/sys/kernel/debug/bluetooth/hci0/目录下可以查看SCO连接状态。使用echo "1" > sco_dbg可以开启SCO调试日志,输出到dmesg。