手头两份日志摆在一起看特别有意思。一份是立体声耳机的连接:链路建立后双方互探能力,特性集里明晃晃带着扩展同步传输的支持位,免提应用层的能力查询也有来有回,可从头到尾没有一条语音专线建立,音乐数据全部跑在异步逻辑传输上,双方还专门协商了 5 槽大包来喂饱它。另一份是免提通话的实录:编解码选定那一刻,外设立刻发起扩展同步传输请求,句柄填着 0;中央回填句柄和专用地址,专线开起来之后异步侧的多槽包当场从 5 槽降为 3 槽,通话一结束又升回 5 槽。同一对设备、同一套机制,音乐场景对专线视而不见,通话场景把专线用得明明白白。这个正反两面恰好是理解逻辑传输体系最好的入口——专线到底为谁而设、开线要付什么代价、怎么收场。这一篇把 SCO 和 eSCO 两条语音专线的开线流程掰开揉碎讲清楚。
目录
一、逻辑传输的家底与占座底线
二、SCO:固定时刻的专座专线
2.1 三个时间参数与包型的对应表
2.2 编码方式与加密禁令
2.3 四条流程:开线、被拒、改线、拆线
2.4 保留槽里的交通规则
三、eSCO:带重传窗口的语音专线
3.1 专用 LT_ADDR:独立收发通道的钥匙
3.2 重传窗口的运作
3.3 四条流程与拆线的绣花功夫
四、协商九规则:一场有纪律的讨价还价
五、两份抓包的正反面:拒绝专线的音乐与全程实录的通话
5.1 音乐场景:有能力也不开线
5.2 通话场景:专线从开到收的完整实录
5.3 数字互证:把抓包参数代回公式
六、测验
一、逻辑传输的家底与占座底线
先看规范给连接下的定义。两个设备连接刚建立时,家底是两条逻辑传输:ACL 异步传输,承载 ACL-C 逻辑链路跑链路管理消息、ACL-U 逻辑链路跑 L2CAP 数据;APB 广播传输,承载 APB-C 和 APB-U 两条链路处理广播。随后可以按需加入一条或多条同步逻辑传输——SCO 或者 eSCO,这就是语音专线的两种形态。
有一条底线规则值得先立起来,规范是:
A new logical transport shall not be created if it would cause all slots to be allocated to reserved slots on secondary LT_ADDRs.
如果新建逻辑传输会导致所有时槽都被次要 LT_ADDR 上的保留槽占满,就不允许创建。时槽是微微网的总资源,保留槽是专线占的座。这条规则说的是:专线可以开,占座可以占,但不能把整个会场占光——必须给主连接的异步传输留出活路。想象一个会议室,专线部门可以预订固定座位,但如果预订系统允许某个部门把所有座位全订走,日常办公(ACL 数据、广播、链路管理消息)就全瘫了。这条规则就是预订系统的兜底校验,多开一条专线前先算一遍总账。
二、SCO:固定时刻的专座专线
SCO 是最早出现的语音专线形态,设计哲学是电路交换式的死板但可靠:提前预约固定时刻的座位,到点必发,永不重传。理解了这份死板,后面 eSCO 的每一步演进才有对照。
2.1 三个时间参数与包型的对应表
开线消息 LMP_SCO_LINK_REQ 携带五个参数:SCO_Handle、Timing_Control_Flags、Dsco、Tsco、SCO_Packet,外加 Air_Mode 指定编码方式。Tsco 是专线的发车间隔,Dsco 是首班车的偏移,Timing_Control_Flags 还是老朋友——选择初始化方式 1 还是 2 来防时钟回绕,公式和嗅探锚点那套一模一样:
CLK27−1 mod Tsco = Dsco (initialization 1)
CLK27,CLK26−1 mod Tsco = Dsco (initialization 2)
规范里的推导逻辑值得展开。三种 HV 包型的能力差异如下:
HV1 每包载荷 10 字节,带三分之一前向纠错;HV2 每包 20 字节,三分之二纠错;HV3 每包 30 字节,完全不纠错。基带规范给出了推导链:HV1 一包能装 1.25ms 的 64kb/s 语音,所以每 2 槽必须发一包,Tsco 等于 2;HV2 装 2.5ms,每 4 槽一包;HV3 装 3.75ms,每 6 槽一包。这里藏着一个漂亮的恒等式:包越大、纠错越少、占座越稀,但三种包型最终速率都严格锁死在 64kb/s。专线卖的不是带宽,是恒定的时延和速率——这正是传统电话业务的命根子。纠错强度和发车密度是可以自由组合的成本结构:想要抗干扰就选 HV1 高频占座,想要省时槽就选 HV3 稀疏占座,账单总价一样。
2.2 编码方式与加密禁令
空口编码有四种:μ-law PCM、A-law PCM、CVSD、透明传输。规范要求发起方只能在对方支持的类型里选——特性交换阶段探明的能力集就是选型的依据。前两种是欧洲和北美电话网的压扩律,CVSD 是连续可变斜率增量调制、抗误码能力强,透明模式则把 64kb/s 同步数据原样搬运。
然后是 SCO 身上最著名的一道禁令:
The Link Manager shall not initiate a SCO connection, and shall reject any request for a SCO connection, while AES-CCM encryption is in use.
AES-CCM 加密启用期间,链路管理器不得发起 SCO 连接,收到请求也必须拒绝。原因在加密的机制层面:ACL 链路的 AES-CCM 加密靠加密计数器保证每包密文不重复,计数器跟着数据包走;而 HV 包型没有任何校验字段——没有 CRC、没有 MIC、没有重传机制,密文被干扰了接收方根本无从察觉,更没有重传兜底。在一个加着密的链路上跑一条既不能加密又不能验证完整性的语音通道,等于在保险库墙上开了扇不锁的窗。所以要么语音裸奔(早期规范确实允许),要么加密期间干脆禁开专线,新规范选了后者。这也是为什么如今有加密需求的通话产品清一色用 eSCO——它的包型带 CRC。
2.3 四条流程:开线、被拒、改线、拆线
开线的两个方向权力结构不同。中央发起是标准的一问一答:LMP_SCO_LINK_REQ 带全套参数,外设要么 LMP_ACCEPTED 要么 LMP_NOT_ACCEPTED,拒绝时可以在 Error_Code 里说明不接受哪一项,中央可以改了参数再试。
外设发起则要经过中央回填:外设先把 SCO_Handle 填 0 发出去,Dsco 建议填 0,Timing_Control_Flags 会被中央忽略——因为时序参考系是中央的时钟,外设没有资格定锚点。中央若愿意开线,回一条填好句柄、偏移和标志位的 LMP_SCO_LINK_REQ,外设再答 ACCEPTED 或 NOT_ACCEPTED。规范还贴心地补了一句:中央应尽量沿用外设请求里的参数,实在满足不了才允许换值。句柄的分配权始终在中央手里,这和微微网里中央的调度地位一脉相承。
有两个细节容易被问住。其一,SCO_Handle 零值被保留不用,所以外设发起时填 0 正好天然表示句柄待分配。其二,如果选了 HV1 包型,LMP_ACCEPTED 必须用 DM1 包发送——因为 HV1 每 2 槽一班车、把保留槽占得密不透风,链路管理消息再想挤 HV 包就无座可坐,只能靠 DM1 这种单槽 ACL 包在缝隙里穿行。
改线流程和开线同构:中央直接发新参数的 LMP_SCO_LINK_REQ 指名要改的句柄,外设答接受或拒绝,拒绝则原参数不变;外设要改则发请求、中央回填确认,时序标志位和偏移照例被中央接管。
拆线是 LMP_REMOVE_SCO_LINK_REQ 携带句柄加 Error_Code 说明拆除原因,对方必须回 ACCEPTED。注意 SCO 没有协商余地——它天生就是中央定参数、外设点头或摇头的单极世界,这份独裁在 eSCO 里会被协商状态机彻底取代。
2.4 保留槽里的交通规则
基带规范对 SCO 保留槽里的收发规则写得非常细,值得逐条过一遍。外设在自己的保留从发槽可以发射,除非前一个主发槽收到的包带正确接码但 LT_ADDR 不是自己——点了别人的名就闭嘴;如果 LT_ADDR 是自己但 HEC 校验错,也不应该发——头都错了,回复大概率也是鸡同鸭讲。DM1 包可以在 SCO 保留槽里发,但仅限携带 ACL-C 数据,也就是链路管理消息可以借专线的座走,普通用户数据不行。外设在保留槽里除了 HV 包,只有在前一槽解出自己的地址时才能发别的东西。这套规则的精神是:专线的座位优先给专线乘客,但允许调度指令在座位空闲时搭个便车,绝不允许普通乘客鸠占鹊巢。
三、eSCO:带重传窗口的语音专线
eSCO 的登场解决了 SCO 的两个历史遗留问题。规范用一句话概括了它和前辈的全部差异:
As opposed to SCO links, eSCO links have a configurable data rate that may be asymmetric, and can be set up to provide limited retransmissions of lost or damaged packets inside a retransmission window of size WeSCO.
可配置的速率、允许非对称、在大小为 WeSCO 的重传窗口内提供有限重传。三件事分别对应三个业务诉求:更宽的语音带宽(比如高清语音)、上下行不对称流量(静音抑制方向差异)、以及丢包时的挽救能力——SCO 丢了就丢了,eSCO 还有一次后悔药。时序骨架则和 SCO 完全同构:TeSCO 间隔、DeSCO 偏移、初始化 1/2 防回绕、独立句柄。
参数表从 SCO 的五个膨胀到十二个:句柄、专用 LT_ADDR、时序三件套、重传窗口、双向各自的包型和包长、空口编码、协商状态。DeSCO、TeSCO、WeSCO、双向包型、双向包长这七项被明确定义为可协商参数,其余是结构性的。
3.1 专用 LT_ADDR:独立收发通道的钥匙
eSCO 建立时,中央会给外设额外分配一个 LT_ADDR,规范强调这为 eSCO 提供了与 ACL 逻辑传输相互独立的 ARQ 机制——确认重传走各自的通道,互不干扰。所有 eSCO 流量、且只有 eSCO 流量走这个地址。这就是同步包类型表里 EV 系列包型的舞台:EV3 到 3-EV5,载荷从 30 字节一路到 540 字节,速率从 96kb/s 爬到 864kb/s,全部带 CRC。对比 HV 系列清一色 64kb/s 且无校验,代际差一目了然。
3.2 重传窗口的运作
eSCO 的时域结构是周期性的窗口序列:每个 TeSCO 一个 eSCO 瞬时点,随后是保留槽,再跟一个重传窗口。单槽包的窗口结构见下图:
首次传输在保留槽里进行;如果收到否定确认或者干脆没收到回复,重传窗口里的空位就用来补票。多槽包场景下,首次传输如果用 3 槽包,保留槽就是紧随瞬时点的 2、4 或 6 个槽,重传窗口从首个外设发包结束后的下一槽开始算。
窗口内的交通规则有几条硬约束。中央在某个 eSCO 地址的重传窗口里发包的前提是:上一组保留槽里要么点过这个地址的名、压根没发过任何包——自己上一班车刚发完还没确认,窗口里就不能再发。发之前还要做槽位充足性检查:如果发 NULL 包带确认只要 1 槽;发数据包且上一包未确认,就得留够自己包型加对方包型的槽位,保证这一来一回能在窗口内完整收尾,禁止把传输尾巴甩出窗外。没有数据可发时中央用 POLL、外设用 NULL 维持节奏。有一条优先级规则特别有工程味:eSCO 流量在重传窗口内应当优先于 ACL 流量——专线乘客的补票优先于散客进站。还有一条防呆设计:中央若用 POLL 代替了协商的 3 槽 eSCO 包,外设仍按协商包型的节奏推算自己的发射时刻,比如协商的是 EV5、中央却只发了 POLL,外设照旧在 3 槽之后开口,因为协议假定中央可能因为没数据而降格发 NULL/POLL,时序骨架不能跟着降格乱掉。窗口之间还有一条重叠禁令:窗口在中央侧可以互相重叠(中央同时服务多个外设时排班紧凑),但在单个外设身上绝不允许重叠——一个人不能同时赶两班重叠的车。
没收到外设的回复视为隐式否定确认,下个窗口继续补票。而窗口外的正常嗅探锚点、其他同步保留槽照旧运转,这就引出了下一节的冲突仲裁。
3.3 四条流程与拆线的绣花功夫
eSCO 的开线、改线、拆线流程表面上和 SCO 同构,但每一处细节都多了协商色彩。外设发起时句柄填零、LT_ADDR 字段保留不用,中央回填;重协商时句柄和 LT_ADDR 锁死为原始值——通道的身份标识一旦确定就不可动摇,能谈的只是班次和座位数。拒绝不再是一锤子买卖:LMP_NOT_ACCEPTED_EXT 终止本次协商后,可以另起一轮换参数重来。
拆线流程的细节最见功力,规范规定:外设拆除前必须先关停自己的 eSCO 逻辑传输再发拆除请求或确认;中央直到流程结束才可重新分配那个 eSCO LT_ADDR;如果流程走不完——比如外设已经超出通信范围——中央必须等到主 LT_ADDR 因监督超时变成可复用状态,才允许回收 eSCO 地址。这套绣花功夫防的是地址复用竞态:旧通道的残余传输还没死透,新通道就抢走了地址,接收方会把幽灵包当成新通道的数据收下,时序账本直接崩盘。监督超时是链路死亡的法定认定时刻,等它落地再回收,竞态窗口被结构性关闭。
四、协商九规则:一场有纪律的讨价还价
eSCO 参数协商是整个链路管理层里最接近状态机的谈判协议,九条规则配上协商状态字段的五种取值,构成一套完整的对话纪律。
先把 Negotiation_State 的语义摆出来:发起方首轮必填 0;此后每次还价,按还价原因填 1(一般性调参)、2(保留槽违例)、3(延迟违例)、4(配置不支持)。状态码是谈判语言里的病因声明——我不是不想答应你,是你的方案在我的系统里会犯哪种病。
九条规则里最核心的三条值得规范引用。规则二定义了带宽的算法:
if the bandwidth (defined as 1600 times the packet length in bytes divided by TeSCO in slots) for either RX or TX or the Air_Mode cannot be accepted the device shall send LMP_NOT_ACCEPTED_EXT with the appropriate Error_Code.
带宽等于 1600 乘以包长字节数除以 TeSCO。为什么是 1600:蓝牙时槽 625 微秒,每秒正好 1600 槽,包长除以间隔是每槽字节数,乘 1600 就是每秒字节数。这个公式把带宽从抽象需求翻译成包型和间隔的组合,收发双向各自算、任一方向不可接受就整体拒绝。规则三给谈判划了不可触碰的红线:
Bandwidth and Air_Mode are not negotiable and shall not be changed for the duration of the negotiation.
带宽和空口编码在协商期间不可谈。道理在于这两个参数是业务的立身之本:带宽是应用层给语音会话定下的硬指标,编码是双方语音编解码器的共同语言,在这两项上讨价还价等于换了门生意,不属于参数微调的范畴。谈崩了可以另起一轮新协商换带宽重谈,但本轮内谁都不许动它。规则四给出延迟违例的判定公式:
if the parameters will cause a latency violation (TeSCO + WeSCO + reserved synchronous slots > allowed local latency) the device should propose new parameters that shall not cause a reserved slot violation or latency violation for the device that is sending the parameters.
总延迟等于间隔加重传窗口加保留同步槽。三个成分各有含义:TeSCO 是一个完整周期的长度,WeSCO 是为重传预留的额外等待,保留槽是首次传输本身的耗时。语音是时延敏感业务,超出本地允许的延迟上限,声音就开始断续。规则四要求违例方必须给出一个对双方都无害的新方案——不能把病转嫁给对面。规则五接着上锁:一旦你被延迟违例坑过,后续还价就不许再提出等延迟或更高延迟的组合。这条单调性约束防止谈判在延迟维度上无限横跳,保证收敛。
三种违例的定义是理解这套状态机的钥匙,保留槽违例的定义规范尤其值得展开:
a reserved slot violation is when the receiving LM cannot setup the requested eSCO logical transport because the eSCO reserved slots would overlap with other regularly scheduled slots (e.g. other synchronous reserved slots or sniff anchor points).
保留槽违例就是新专线的座位和其他常规调度冲突——可能是已有的另一条同步专线的保留槽,也可能是嗅探锚点。注意这里直接点名了嗅探锚点:上一讲里省电模式的班表和这一讲的语音专线共享同一本时槽账本,开新线前必须查老班表。延迟违例和配置不支持则分别对应时延超限和参数超出设备支持范围。规则六处理复合病:保留槽违例叠加延迟违例、或者配置不支持叠加延迟违例,按延迟违例(状态 3)优先上报,因为延迟是最难让步的硬约束。
把这套纪律写成代码会比文字更清晰:
SLOTS_PER_SEC = 1600 # 每秒 1600 槽,每槽 625 微秒 def esco_bandwidth_bps(pkt_len_bytes, t_esco_slots): # 规则2 带宽公式:1600 × 包长 / TeSCO,单位字节每秒 return SLOTS_PER_SEC * pkt_len_bytes // t_esco_slots * 8 def check_esco_params(t_esco, w_esco, pkt_c2p, pkt_p2c, local_max_latency, occupied_slots): # 规则4 延迟校验:TeSCO + WeSCO + 保留同步槽 ≤ 本地允许延迟 latency = t_esco + w_esco + pkt_c2p + pkt_p2c if latency > local_max_latency: return 3, "延迟违例,需给出双方均无害的新组合" # 保留槽违例:与既有同步保留槽或嗅探锚点重叠 anchor = set(range(0, 4096, t_esco)) if anchor & occupied_slots: return 2, "保留槽与既有调度冲突" return 1, "可接受或一般性调参" def negotiate_demo(): # 外设还价示例:被 3-EV5(540B) 高带宽打穿延迟预算后的收敛路径 for pkt, t, w in [(540, 12, 12), (360, 12, 8), (180, 12, 6)]: state, msg = check_esco_params(t, w, 3 if pkt > 180 else 1, 3 if pkt > 180 else 1, 28, set(range(0, 4096, 24))) bw = esco_bandwidth_bps(pkt, t) print("包长%3dB TeSCO=%2d WeSCO=%2d → 带宽%6d bps 状态=%d %s" % (pkt, t, w, bw, state, msg))negotiate_demo 模拟了从激进配置逐级降档的还价过程:540 字节大包先撞延迟墙(状态 3),按规则五后续提案延迟只能降不能升,最终收敛到 180 字节包的可用组合。真实的链路管理器谈判逻辑骨架与此并无二致,只是还要叠加双向独立校验和射频调度器的实时占座表。
五、两份抓包的正反面:拒绝专线的音乐与全程实录的通话
5.1 音乐场景:有能力也不开线
有了完整图景,先看音乐日志的反面案例。音乐传输的诉求是大带宽、可容忍时延、要完整性校验——A2DP 把编码后的音频流切成 L2CAP 包走 ACL-U 逻辑链路,靠 ACL 的 CRC 加自动重传保证音质,靠多槽大包堆带宽。抓包里双方协商 5 槽包(3.125ms 载荷窗口),DH5 或 2-DH5 单包能装下 339 到 679 字节,吞吐轻松喂饱立体声。反过来若真开了 eSCO 专线,比如最常见的双向 64kb/s EV3 配置,带宽对立体声音乐杯水车薪,专线的恒定占座还会挤压数据流量的时槽。语音专线为 8 到 64kb/s 的实时窄带业务而生,让它扛音乐属于专业不对口。特性集里那个 eSCO 支持位是给免提通话预留的——日志里免提能力查询正常进行,通话需求真的到来时,专线才会在同一条 ACL 链路旁边开出来。
主机侧的对照图补齐了另一个视角:能力查询事件与空口特性交换一一对应;Max Slots Change 事件在协商完成时上报 5 槽。重连段还有个细节:角色切换完成后 326 毫秒,中央重新发起多槽包协商到 5 槽——这正是角色切换篇讲过的切换后参数复位,切换会重置 Max_Slots 等默认参数,容量相关的一切都要重新谈一遍。两讲内容在空口上完成了互证。
5.2 通话场景:专线从开到收的完整实录
通话日志把规范流程逐字演了一遍。免提层先走编解码协商:AG 上报可用编解码列表,主机选定宽带编解码(mSBC)后下发选择指令,外设应答确认。编解码一定,外设的链路管理器立刻发起扩展同步传输请求——注意这条请求的形态:句柄字段填 0、专用地址字段填 0,正是规范规定的外设发起形态,因为句柄和地址的分配权都在中央手里,外设只能递一张空白申请单。中央收到后回填完整参数:句柄 0x01、专用地址 2、初始化方式 1、透明传输模式,外设回接受。双向语音随即在专线上流动,空口能看到每隔一段固定间隔的双向音频帧。
最精彩的是专线建立前后的时槽账本变化。eSCO 建立后 28 毫秒内,双方的多槽包协商从 5 槽降为 3 槽——专线开始占座,异步传输的可用时槽被挤压,单包载荷上限被迫收缩。这不是巧合而是调度系统的必然:每个 TeSCO 周期里保留槽加重传窗口都被专线预订走了,剩下留给 ACL 的连续空位撑不起 5 槽包的长度,发一个 5 槽包中途撞上保留槽就得作废重来,干脆全体降档到 3 槽求个安稳。第一节那条不得占满所有时槽的底线规则,在这里变成了肉眼可见的容量再分配。
通话中段还有一处细节:中央尝试发起嗅探模式协商被外设拒绝,理由是 PDU 不允许。省电班表和语音专线在同一本时槽账本上天然打架——嗅探要求链路长期休眠,专线却要求每个周期准时到岗,两者只能选一。这正是嗅探篇的保留槽违例定义反过来在专线侧的体现:不是专线让路给嗅探,就是嗅探等专线收摊。
收尾同样干净利落。通话结束,外设发起拆除请求,理由码是远端用户终止连接,中央回接受。拆线完成 6 毫秒后,多槽包协商立刻回到 5 槽——专线退还座位,异步传输容量即刻恢复。开线降档、拆线升档,一降一升之间,时槽这本账算得明明白白。
5.3 数字互证:把抓包参数代回公式
主机侧日志把这次通话的 eSCO 参数完整亮了出来:间隔 7.5 毫秒、重传窗口 3.75 毫秒、双向包长各 60 字节、编码 mSBC。拿协商规则二的带宽公式验算一下:7.5 毫秒是 12 个时槽,1600 乘 60 除以 12 等于每秒 8000 字节,折合 64kb/s——正是 mSBC 宽带语音的标准速率,公式和实测严丝合缝。重传窗口 3.75 毫秒折合 6 槽,恰好是间隔的一半,给丢包留出了不短不长的后悔药窗口;延迟公式验算 TeSCO 加 WeSCO 加保留槽合计不到 20 槽即 12.5 毫秒,远低于任何通话产品的延迟上限。一次普普通通的免提通话,协商规则里的每一个公式都能在抓包数字里找到落点。
顺带一提,这份日志里的链路是全程加密的——配对完成后立即启动了 AES-CCM 加密,通话照样建立。这就是第二节那条加密禁令的现实注脚:禁的是 SCO(HV 包无校验无重传),eSCO 的 EV 包带 CRC 有重传,加密链路上通话毫无障碍。如今手机通话清一色 eSCO,禁令几乎不会被触发,但它是理解两种专线安全性差异最好的切口。
六、测验
问题一:为什么 AES-CCM 加密启用期间禁止建立 SCO 连接,而 eSCO 不受此限制?
参考答案:
禁令的根源在 HV 包型的结构缺陷。SCO 使用 HV1/HV2/HV3 包,这些包型没有 CRC 字段、没有 MIC、没有重传机制,无法承载 AES-CCM 加密所需的完整性保护,密文被干扰后接收方无法察觉更无法挽救;同时 SCO 是保留槽定时发送、永不重传的电路交换式通道,连事后补救的机会都没有。在加密链路上叠加这样一条既不能加密又不能验证完整性的通道,等于在安全边界上开洞。
eSCO 的 EV 系列包型全部带 CRC 和有限重传机制,链路层能对传输完整性负责,因此不受禁令约束。实际产品中带加密需求的通话场景(如手机通话)一律使用 eSCO。另一个常被追问的关联点:HV1 占座密度高(每 2 槽一班),链路管理消息只能靠 DM1 包在保留槽缝隙中传递,这也是 LMP_ACCEPTED 在 HV1 场景强制用 DM1 发送的原因。
问题二:eSCO 协商中 Negotiation_State 为 2 和 3 分别表示什么?规则五为什么规定被延迟违例拒绝后,后续提案不得出现等延迟或更高延迟的组合?
参考答案:
状态 2 表示保留槽违例——请求的 eSCO 保留槽与既有常规调度冲突,冲突源包括其他同步专线的保留槽和嗅探锚点;状态 3 表示延迟违例——TeSCO 加 WeSCO 加保留同步槽超出本地允许的最大延迟。规则五的单调性约束是为了保证协商收敛:如果没有这条限制,一方可以反复提出延迟相同甚至更高的组合(比如换包型但维持总延迟),双方可能在延迟维度上无限拉锯;加上单调递减约束后,每一轮还价在延迟轴上严格向下走,可行解空间单调收缩,谈判要么收敛到双方可接受的组合,要么在有限轮内以 NOT_ACCEPTED_EXT 终止。规则四还要求违例方提出的新参数必须对提案方自身也不构成违例,进一步保证每轮提案都是真诚可行的,这与规则五共同构成收敛的双重保险。
问题三:实测中发现,eSCO 通话建立后 ACL 侧的多槽包协商从 5 槽降为 3 槽,通话结束拆线后又回到 5 槽。为什么语音专线会影响异步传输的包长上限?
参考答案:
根因是同一本时槽账本上的容量再分配。eSCO 建立后,每个 TeSCO 周期里的保留槽(首次传输)加重传窗口都被专线预订,留给 ACL 的时槽不再是连续大片空位。5 槽包需要 5 个连续时槽(3.125ms)才能完整发送,中途撞上专线的保留槽就必须作废重发,效率反而暴跌;降档到 3 槽包虽然单包载荷变小,但能在碎片化的空位里安稳穿行,整体吞吐更优。通话结束专线拆除,保留槽全部归还,连续空位恢复,多槽包自然回升到 5 槽。这个一降一升是调度系统对占座底线的动态响应——规范规定新建逻辑传输不得占满所有时槽,正是为了保证 ACL 侧永远有活路。追问点还包括:通话中尝试进入嗅探模式会被拒绝,因为嗅探的休眠班表和专线的准时占座在同一本账本上无法共存;SCO 场景下这种挤压更极端,HV1 每 2 槽一班占座最密,链路管理消息只能靠 DM1 单槽包在缝隙里传递。