3. eSCO 增强特性:与 SCO 的差异及数据包选择策略

eSCO(Enhanced Synchronous Connection-Oriented)是蓝牙核心规范 v1.2 引入的增强同步面向连接逻辑传输。与经典 SCO 相比,eSCO 在重传机制、数据包类型和链路质量监控方面做了根本性改进,是高质量音频传输(如宽频语音、A2DP 同步通道)的基础。

3.1 eSCO 与 SCO 的核心差异

下表从链路层机制、重传能力、数据包类型和典型应用四个维度对比 eSCO 与 SCO:

对比维度 SCO eSCO
重传机制 无重传;数据包丢失即丢弃 支持有限次重传(Retransmission Window)
数据包类型 HV1 / HV2 / HV3(固定长度) EV3 / EV4 / EV5 / 2-EV3 / 2-EV5 / 3-EV3 / 3-EV5
时隙占用 固定时隙,无弹性 可配置时隙间隔(Tsco)和重传窗口(W)
链路质量反馈 无 通过 Link Supervision 和 RSSI 动态调整
典型应用 传统窄带语音(CVSD) 宽频语音(mSBC)、A2DP 同步、LE Audio
Linux 驱动支持 hci_conn->type == SCO_LINK hci_conn->type == ESCO_LINK
关键结论: eSCO 通过引入重传窗口和更灵活的数据包类型,将 SCO 的“尽力交付”升级为“有限可靠交付”,这是蓝牙音频从窄带(8 kHz)向宽频(16 kHz)演进的核心推动力。

3.2 重传窗口(Retransmission Window)

重传窗口是 eSCO 区别于 SCO 最关键的链路层参数。它定义了一次 eSCO 交互中,主从设备之间允许进行数据包重传的最大时隙数。

3.2.1 窗口机制原理

在 eSCO 链路中,每个 eSCO 间隔(Tsco)被划分为:

  • 初始传输时隙: 主设备发送第一个数据包,从设备回复确认。
  • 重传窗口(W 时隙): 如果初始传输失败(NACK 或超时),主/从设备在窗口内重传数据包。
  • 空闲时隙: 窗口关闭后,剩余时隙保持空闲,直到下一个 Tsco 开始。
窗口大小影响: W 值越大,抗干扰能力越强,但链路带宽利用率降低,且增加端到端延迟。典型配置 W = 2 ~ 6 时隙。
eSCO 重传窗口(Retransmission Window)时序图 时隙 0 1 2 3 4 5 6 主→从 ACK 重传窗口(W = 4 时隙) 重传1 ACK 空闲时隙(Idle) 下一个 Tsco 开始 初始传输成功 重传窗口内完成重传 剩余时隙空闲

3.2.2 Linux 内核中的重传窗口配置

在 Linux 蓝牙子系统中,eSCO 重传窗口通过 hci_conn 结构体的 attempt 和 interval 字段间接控制。驱动开发者通过 hci_setup_esco_conn() 函数设置参数:

/* 内核 eSCO 连接参数结构体 */
struct hci_conn_params_esco {
    __u8     tx_packet_type;   /* 发送数据包类型 */
    __u8     rx_packet_type;   /* 接收数据包类型 */
    __u16    tx_interval;      /* 发送间隔(微秒) */
    __u16    rx_interval;      /* 接收间隔(微秒) */
    __u16    retransmission_window; /* 重传窗口(时隙数) */
    __u16    tx_packet_length; /* 发送数据包长度 */
    __u16    rx_packet_length; /* 接收数据包长度 */
};

/* 典型配置:宽频语音 mSBC 16kHz */
struct hci_conn_params_esco msbc_params = {
    .tx_packet_type        = ESCO_EV3,
    .rx_packet_type        = ESCO_EV3,
    .tx_interval           = 7500,   /* 7.5ms 间隔 */
    .rx_interval           = 7500,
    .retransmission_window = 2,      /* 2 时隙重传窗口 */
    .tx_packet_length      = 30,     /* 30 字节负载 */
    .rx_packet_length      = 30,
};
调试注意: 重传窗口设置过大(W > 6)可能导致链路调度冲突,尤其是在多连接场景下。建议在驱动初始化阶段通过 hci_dev->esco_config 读取控制器能力,动态调整窗口大小。

3.3 eSCO 数据包类型与选择策略

eSCO 定义了多种数据包类型,它们在时隙占用、负载长度、FEC 保护和重传能力上各有不同。正确选择数据包类型是音频传输优化的第一步。

3.3.1 数据包类型对比

数据包类型 时隙数 负载长度(字节) FEC 保护 重传支持 典型比特率
EV3 1 30 无 是 64 kbps
EV4 1 120 2/3 比例 否 128 kbps
EV5 1 180 无 是 192 kbps
2-EV3 2 60 无 是 128 kbps
2-EV5 2 360 无 是 384 kbps
3-EV3 3 90 无 是 192 kbps
3-EV5 3 540 无 是 576 kbps

3.3.2 选择策略与决策流程

数据包类型的选择需要综合考虑以下因素:

  1. 音频编码格式: CVSD 窄带语音通常使用 EV3;mSBC 宽频语音推荐 2-EV3 或 EV5。
  2. 链路质量(RSSI / BER): 在低质量链路下优先选择带 FEC 的 EV4,或缩小重传窗口。
  3. 延迟预算: 多时隙包(2-EV5、3-EV5)增加延迟,不适合对延迟敏感的场景。
  4. 控制器能力: 部分蓝牙控制器不支持 3 时隙包,需通过 HCI_Read_ESCO_Parameters 命令查询。
eSCO 数据包类型选择决策流程 开始 eSCO 连接 音频编码格式? 窄带 EV3(CVSD) 宽频 链路质量(RSSI/BER)? 好 2-EV5 / EV5(高吞吐) 差 EV4(FEC 保护) 配置重传窗口 W = 2~4 提示:实际选择需通过 HCI 命令查询控制器支持的包类型,并动态调整

3.3.3 内核驱动中的包类型选择实现

在 Linux 内核蓝牙驱动中,数据包类型选择通常发生在 hci_conn_params_esco 初始化阶段。以下是一个基于链路质量动态调整的示例:

/* 动态选择 eSCO 数据包类型 */
static u8 select_esco_packet_type(struct hci_conn *conn, s8 rssi)
{
    /* RSSI 阈值:-70 dBm 以上视为链路质量好 */
    if (rssi > -70) {
        /* 高质量链路:使用高吞吐 EV5 或 2-EV5 */
        if (conn->features & LMP_ESCO_2EV5)
            return ESCO_2EV5;
        else
            return ESCO_EV5;
    } else if (rssi > -85) {
        /* 中等质量链路:使用 EV3 配合重传 */
        return ESCO_EV3;
    } else {
        /* 低质量链路:使用带 FEC 的 EV4 */
        return ESCO_EV4;
    }
}

/* 在 eSCO 连接建立前调用 */
static void setup_esco_params(struct hci_conn *conn)
{
    struct hci_conn_params_esco params;
    s8 rssi = hci_conn_get_rssi(conn);

    params.tx_packet_type = select_esco_packet_type(conn, rssi);
    params.rx_packet_type = params.tx_packet_type;
    params.retransmission_window = (rssi > -70) ? 2 : 4;
    /* 其他参数根据包类型填充 */

    hci_setup_esco_conn(conn, &params);
}
优化建议: 在音频传输过程中,可以通过 HCI_Connection_Quality_Report 事件监控链路质量,并触发 hci_conn_change_esco_params() 动态切换数据包类型,实现自适应传输。

3.4 本章小结

  • eSCO 核心增强: 重传窗口(W)使蓝牙音频从无重传的 SCO 升级为有限可靠传输,是宽频语音的基础。
  • 数据包类型选择: EV3/EV4/EV5 及多时隙变体(2-EV3、2-EV5、3-EV5)覆盖了从 64 kbps 到 576 kbps 的速率范围,选择需平衡吞吐、延迟和链路质量。
  • Linux 驱动实践: 通过 hci_conn_params_esco 结构体配置参数,结合 RSSI 反馈实现动态包类型切换,是音频传输优化的关键手段。