在LE Audio的广播音频接收体系中,BASS的两大核心服务特征是整个协议的落地核心,而Broadcast Audio Scan Control Point作为客户端向服务器下发 指令 的唯一入口,更是BASS交互逻辑的重中之重。如果把BASS服务器比作一台广播音频接收的智能终端,那这个控制点就是终端的中央指挥台------所有的委托扫描开关、广播源添加、同步配置修改、解密密钥传递、广播源移除等操作,都需要通过这个指挥台下发指令,服务器再根据指令完成对应的行为并反馈状态。
目录
[1.1 核心特征清单与硬性要求](#1.1 核心特征清单与硬性要求)
[1.2 实例限制:单指挥台+多显示屏的设计逻辑](#1.2 实例限制:单指挥台+多显示屏的设计逻辑)
[1.3 特征设计的底层逻辑:适配低功耗设备的轻量化](#1.3 特征设计的底层逻辑:适配低功耗设备的轻量化)
[二、Broadcast Audio Scan Control Point 核心设计:唯一指令入口的底层规则](#二、Broadcast Audio Scan Control Point 核心设计:唯一指令入口的底层规则)
[2.1 指令整体格式:8位操作码+可变参数字节](#2.1 指令整体格式:8位操作码+可变参数字节)
[2.2 操作码分类:必选+条件必选的层级设计](#2.2 操作码分类:必选+条件必选的层级设计)
[2.3 通用执行行为:操作码解析为核心的执行流程](#2.3 通用执行行为:操作码解析为核心的执行流程)
[3.1 指令长度错误:最基础也最易犯的格式错误](#3.1 指令长度错误:最基础也最易犯的格式错误)
[3.2 操作码不支持错误:未实现操作码的处理逻辑](#3.2 操作码不支持错误:未实现操作码的处理逻辑)
[3.3 Source_ID无效错误:基于唯一标识的匹配错误](#3.3 Source_ID无效错误:基于唯一标识的匹配错误)
[3.4 BIS_Sync参数错误:多子组同步的硬性校验](#3.4 BIS_Sync参数错误:多子组同步的硬性校验)
[3.5 错误处理规则总结:开发调试的核心依据](#3.5 错误处理规则总结:开发调试的核心依据)
[四、控制点6大操作码全解析:格式+行为 指令落地的核心细节](#四、控制点6大操作码全解析:格式+行为 指令落地的核心细节)
[4.1 Remote Scan Stopped(0x00):委托扫描关闭指令](#4.1 Remote Scan Stopped(0x00):委托扫描关闭指令)
[4.2 Remote Scan Started(0x01):委托扫描开启指令](#4.2 Remote Scan Started(0x01):委托扫描开启指令)
[4.3 Add Source(0x02):添加广播源+发起同步 核心复杂指令](#4.3 Add Source(0x02):添加广播源+发起同步 核心复杂指令)
[4.4 Modify Source(0x03):修改广播源同步配置,基于Source_ID的更新指令](#4.4 Modify Source(0x03):修改广播源同步配置,基于Source_ID的更新指令)
[4.5 Set Broadcast_Code(0x04):传递解密密钥 唯一必选操作](#4.5 Set Broadcast_Code(0x04):传递解密密钥 唯一必选操作)
[4.6 Remove Source(0x05):移除广播源 清理资源的收尾指令](#4.6 Remove Source(0x05):移除广播源 清理资源的收尾指令)
[5.1 场景前提](#5.1 场景前提)
[5.2 完整指令协同流程](#5.2 完整指令协同流程)
[5.3 流程核心解读](#5.3 流程核心解读)
[六、控制点开发实战要点:避坑指南 贴合实际开发](#六、控制点开发实战要点:避坑指南 贴合实际开发)
前面几讲我们已经梳理了BASS的服务声明与核心行为逻辑,这篇内容将聚焦BASS服务特征的整体规范与Broadcast Audio Scan Control Point的全量细节,从特征的基础要求、控制点的设计逻辑,到6大操作码的格式与执行行为、开发中极易踩坑的错误处理规则,再到实际场景中的指令协同流程,层层拆解讲透,同时结合开发视角补充实战要点,让你不仅能读懂协议规范,更能落地到实际开发中。
本文所有内容均围绕BASS的核心规范展开,涉及的参数格式、行为要求、错误处理规则均为协议硬性规定,是跨厂商设备互联互通的基础,也是嵌入式蓝牙开发、LE Audio设备开发的核心考点。
一、BASS服务特征核心概览:两大核心组件的基础规则
在深入解析控制点之前,首先要掌握BASS服务特征的整体规范要求,这是理解所有后续细节的基础。协议对BASS的服务特征做了明确的实例限制、属性要求、安全权限定义,所有实现BASS的设备都必须严格遵循,同时这些设计也充分体现了BASS低功耗、高适配的核心设计初衷。
1.1 核心特征清单与硬性要求
BASS仅定义了两个核心服务特征,二者分工明确、协同工作,构成了BASS的完整交互体系:一个是作为指挥台的Broadcast Audio Scan Control Point,负责指令接收;一个是作为状态显示屏的Broadcast Receive State,负责状态反馈。协议对这两个特征的必选属性、可选属性、安全权限做了强制定义,具体要求如下表所示:

从属性设计能看出协议的实用化考量:
控制点同时支持Write(带响应写)和Write Without Response(无响应写) ,兼顾了指令 可靠性 和传输效率------带响应写适合关键指令(如设置解密密钥),服务器会返回操作结果,客户端可确认指令是否执行;无响应写适合高频指令(如委托扫描状态通知),无需等待响应,降低交互延迟。
状态特征支持Read(读)和Notify(通知) ,实现了主动查询 和实时推送的结合------客户端可主动读取当前状态,也可订阅通知,服务器状态变化时主动推送,既保证了状态获取的灵活性,又能让客户端实时感知状态变化。
两个特征均要求加密连接,这是数据安全的硬性保障------广播音频可能涉及隐私内容(如私人通话、音乐),加密连接能避免指令被篡改、状态被窃取,尤其是解密密钥的传递,必须在加密连接下进行,防止密钥泄露。
1.2 实例限制:单指挥台+多显示屏的设计逻辑
协议对两个特征的实例数量 做了截然不同的限制,这一设计是为了适配广播音频接收的实际场景,核心逻辑可总结为单控制点实例+多状态特征实例:
Broadcast Audio Scan Control Point :服务器上仅能存在一个实例。作为客户端下发指令的唯一入口,单实例设计能避免多头指挥的混乱------如果存在多个控制点实例,客户端可能向不同实例下发冲突指令(如一个实例发开启扫描,一个发关闭扫描),导致服务器行为异常。单实例也简化了客户端的实现逻辑,扫描到BASS服务后,只需找到一个控制点即可完成所有指令交互,无需逐个匹配。
Broadcast Receive State :服务器上存在一个或多个实例 ,协议还推荐实例数量不小于服务器能同时同步的BIG数量。每个状态特征实例对应一个广播源,多实例设计让服务器能同时管理多个广播源的状态,实现多频道接收(如同时接收电视广播和手机广播)。推荐实例数量与最大同步BIG数匹配,是为了避免因状态特征不足导致无法添加新的广播源,保证设备的使用体验。
这种单指挥台+多显示屏的设计,既保证了指令交互的统一性,又满足了多广播源管理的实际需求,是协议设计中简洁性与实用性的平衡。
1.3 特征设计的底层逻辑:适配低功耗设备的轻量化
BASS的特征设计整体遵循轻量化原则,这一点与BASS面向助听器、TWS耳机等低功耗设备的定位高度契合:
仅定义两个核心特征,无多余的辅助特征,大幅降低了服务器的固件开发成本和硬件资源占用------助听器这类设备的芯片算力和存储资源有限,简单的特征体系能减少固件体积,提升运行效率。
特征属性仅保留核心功能,无冗余的可选属性------协议未为两个特征定义任何可选属性,所有实现均为强制要求,避免了厂商因可选属性的差异化实现导致的兼容性问题。
指令与状态分离,让服务器的处理逻辑更简洁------控制点仅负责接收指令,状态特征仅负责反馈状态,二者解耦,服务器无需在处理指令的同时处理状态查询,提升了指令执行的效率。
二、Broadcast Audio Scan Control Point 核心设计:唯一指令入口的底层规则
Broadcast Audio Scan Control Point(以下简称控制点 )是BASS的指令核心,协议对其做了全面的格式与行为定义,包括指令整体格式、 操作码 分类、通用执行行为,这些规则是所有指令交互的基础,也是开发中必须严格遵循的硬性标准。

2.1 指令整体格式:8位操作码+可变参数字节
控制点的指令采用固定头部+可变尾部 的格式,客户端向控制点写入的所有数据,都必须遵循这一格式,服务器也会按照这一格式解析指令,格式定义为:第一个字节为8位枚举操作码(Opcode),后跟0个或多个参数字节。
这一格式的设计有两大优势:
解析高效:服务器只需读取第一个字节即可确定指令类型,再根据操作码解析后续的参数字节,无需解析整个数据包,提升了服务器的指令处理效率,适合算力有限的低功耗设备。
扩展性强:操作码为8位,可定义256个指令,目前协议仅使用了0x00-0x05共6个操作码,0x06-0xFF均标记为RFU(未来保留),为协议后续升级预留了足够的指令空间,后续可新增操作码而无需修改整体格式。
需要注意的是,协议对操作码+参数的总长度做了严格规定,不同操作码对应固定的参数长度(部分参数为可变长度,如元数据),客户端写入的总长度必须与协议要求一致,否则服务器会判定为指令错误并按规则处理,这一点在错误处理部分会详细讲解。
2.2 操作码分类:必选+条件必选的层级设计
协议将控制点的8位操作码分为必选操作、条件必选操作、未来保留三类,不同类型的操作码有不同的实现要求,这一设计既保证了BASS的核心功能,又为厂商提供了一定的设计灵活性,具体分类如下表所示:
|-----------|---------------------|-----------|-------------------------|
| 操作码 | 操作名称 | 实现要求 | 核心描述 |
| 0x00 | Remote Scan Stopped | 条件必选(C.1) | 告知服务器客户端停止代为扫描广播源 |
| 0x01 | Remote Scan Started | 条件必选(C.1) | 告知服务器客户端开始代为扫描广播源 |
| 0x02 | Add Source | 条件必选(C.1) | 向服务器添加广播源信息并请求同步PA/BIS |
| 0x03 | Modify Source | 条件必选(C.1) | 根据Source_ID修改广播源的同步配置 |
| 0x04 | Set Broadcast_Code | 强制(M) | 向服务器传递解密加密BIS的16字节密钥 |
| 0x05 | Remove Source | 条件必选(C.1) | 根据Source_ID移除服务器中的广播源信息 |
| 0x06-0xFF | RFU | - | 未来保留,禁止使用 |
其中条件必选(C.1 )的要求为:如果服务器支持任意一个条件必选操作,就必须支持所有的条件必选操作。这一要求是为了保证BASS功能的完整性------如果服务器支持添加广播源,就必须同时支持修改、移除、委托扫描等操作,否则会出现能加不能改/删的问题,影响设备的实际使用。
而Set Broadcast_Code(0x04)是唯一的强制操作 ,这一设计体现了加密广播在LE Audio中的核心地位:LE Audio的广播音频支持加密传输,这是保护音频隐私的关键,而助听器、TWS耳机等核心设备必须支持解密加密广播,因此传递解密密钥的Set Broadcast_Code操作成为所有BASS服务器的必选功能,无论其他功能是否实现,该操作都必须支持。
2.3 通用执行行为:操作码解析为核心的执行流程
协议定义了控制点的通用执行行为,所有操作码的执行都遵循这一流程,这是服务器处理控制点指令的基础逻辑:
-
客户端通过GATT Write或Write Without Response向控制点写入指令数据;
-
服务器接收数据后,首先读取第一个字节并解析为操作码;
-
服务器判断该操作码是否为自身支持的类型(必选/条件必选);
-
若操作码支持,服务器再校验指令总长度、参数格式等是否符合协议要求;
-
若所有校验通过,服务器接受该操作并执行对应的行为(如添加广播源、设置密钥);
-
若操作码不支持或参数校验失败,服务器拒绝该操作并按错误处理规则反馈(带响应写)或直接忽略(无响应写)。
这一流程的核心是先解析操作码,后校验参数,这样的设计能让服务器快速过滤掉不支持的操作码,避免对无效指令做多余的参数校验,提升处理效率。
三、控制点核心行为:错误处理规则,开发中最易踩坑的核心点
错误处理是控制点行为规范的重要组成部分,也是实际开发中最容易出现问题、最需要重点关注 的部分。协议针对控制点的指令交互,定义了不同写入方式、不同错误类型的处理规则,所有规则均为硬性要求,是保证设备互联互通的基础,也是调试时定位问题的关键依据。
协议中定义的控制点错误均基于GATT写入方式 划分,核心分为Write(带响应写)和Write Without Response(无响应写)两种,服务器对两种写入方式的错误处理逻辑截然不同,同时错误类型主要包括指令长度错误、操作码不支持、Source_ID无效、BIS_Sync参数错误四类,以下逐类详解。
3.1 指令长度错误:最基础也最易犯的格式错误
指令长度错误指客户端写入的操作码+参数总长度,与协议为该操作码定义的总长度(固定参数长度+可变参数长度)不一致,这是开发中最基础也最易犯的错误,服务器的处理规则严格区分写入方式:
Write Without Response(无响应写) :服务器检测到长度错误后,直接忽略整个操作,不执行任何行为,也不向客户端返回任何反馈。这是因为无响应写的设计初衷是提升传输效率,无需服务器返回响应,因此长度错误也无反馈机制。
Write(带响应写) :服务器检测到长度错误后,向客户端返回ATT Error Response ,并将错误码设置为Write Request Rejected(写入请求被拒绝),客户端可通过该错误码快速定位到指令长度问题。
需要注意的是,协议中对总长度的定义包括固定参数 和可变参数,比如Add Source操作中的Metadata[i]为可变长度参数,其长度由Metadata_Length[i]定义,服务器会先解析Metadata_Length[i],再校验后续的Metadata[i]长度是否匹配,若不匹配仍判定为长度错误。
3.2 操作码不支持错误:未实现操作码的处理逻辑
操作码不支持错误指客户端写入的操作码为服务器未实现的类型(如服务器未实现条件必选操作,或写入了RFU的0x06-0xFF操作码),服务器的处理规则同样区分写入方式:
Write Without Response(无响应写):服务器直接忽略整个操作,无任何反馈;
Write(带响应写) :服务器返回ATT Error Response,错误码设置为BASS专属的Opcode Not Supported(0x80),这一错误码是协议为BASS定义的应用层错误码,专门用于标识操作码不支持问题。
这里需要注意,RFU的0x06-0xFF操作码均被视为不支持的操作码,无论服务器是否实现其他操作,写入这些操作码都会触发该错误,协议禁止任何设备使用RFU操作码。
3.3 Source_ID无效错误:基于唯一标识的匹配错误
Source_ID是服务器为每个Broadcast Receive State特征分配的唯一标识,是客户端操作指定广播源的核心依据(如Modify Source、Set Broadcast_Code、Remove Source均需要Source_ID)。Source_ID无效错误指客户端写入的Source_ID,与服务器中所有状态特征的Source_ID均不匹配,服务器的处理规则:
Write Without Response(无响应写):服务器直接忽略整个操作;
Write(带响应写) :服务器返回ATT Error Response,错误码设置为BASS专属的Invalid Source_ID(0x81),这是BASS定义的另一个应用层错误码,专门用于标识Source_ID匹配失败。
这一错误在开发中主要出现在两种场景:一是客户端写入了错误的Source_ID(如拼写错误);二是广播源已被移除,对应的Source_ID失效,客户端仍使用该Source_ID下发指令。因此在开发中,客户端需要实时同步服务器的Source_ID列表,避免使用无效的Source_ID。
3.4 BIS_Sync参数错误:多子组同步的硬性校验
BIS_Sync参数错误是针对Add Source和Modify Source操作的专属错误 ,仅在客户端写入的BIS_Sync参数违反协议硬性要求时触发。协议对BIS_Sync参数的核心要求为:如果BIS_Sync参数值不是0xFFFFFFFF(无偏好),则同一个BIS_index值不能在多个子组中被设置为0b1(同步)。
简单来说,就是一个BIS流只能被一个子组同步,不能被多个子组同时同步,这是因为BIS是实际承载音频数据的传输流,多个子组同步同一个BIS会导致服务器的音频解码逻辑混乱,同时造成功耗浪费。
服务器检测到该错误后,无论采用哪种写入方式,均直接忽略整个操作 ,且不返回任何错误码。这是因为该错误属于参数逻辑错误,而非格式错误,协议未为其定义专属错误码,因此服务器仅做忽略处理。
3.5 错误处理规则总结:开发调试的核心依据
为了方便开发中快速查阅,将上述所有错误处理规则整理为下表,这是调试BASS控制点指令交互的核心依据,能帮助开发者快速定位问题:
|--------------|-----------|----------------------|----------------------------|
| 错误类型 | 写入方式 | 服务器处理逻辑 | 错误码/标识 |
| 指令长度错误 | 无响应写 | 忽略整个操作 | 无 |
| 指令长度错误 | 带响应写 | 返回ATT Error Response | Write Request Rejected |
| 操作码不支持 | 无响应写 | 忽略整个操作 | 无 |
| 操作码不支持 | 带响应写 | 返回ATT Error Response | 0x80(Opcode Not Supported) |
| Source_ID无效 | 无响应写 | 忽略整个操作 | 无 |
| Source_ID无效 | 带响应写 | 返回ATT Error Response | 0x81(Invalid Source_ID) |
| BIS_Sync参数错误 | 无响应写/带响应写 | 忽略整个操作 | 无 |
四、控制点6大操作码全解析:格式+行为 指令落地的核心细节
协议为控制点定义的6大操作码,覆盖了广播音频接收的全流程 :从委托扫描的开启/关闭,到广播源的添加/修改/移除,再到解密密钥的传递,每个操作码都有明确的参数格式、执行行为要求,这部分是BASS协议落地的核心,也是开发中需要重点实现的内容。
以下按操作码顺序,逐一对每个操作的核心定位、参数格式、执行行为、关键细节做全面解析,其中Add Source和Modify Source为参数最复杂、行为最繁琐的操作,会做重点详解;Remote Scan Started/Stopped为无参数操作,做简洁解析;Set Broadcast_Code和Remove Source为基础操作,详解核心要求。
4.1 Remote Scan Stopped(0x00):委托扫描关闭指令
核心定位: 告知服务器客户端已停止代为扫描广播源,是委托扫描机制的关闭开关,无任何参数,操作码0x00即为完整指令。
执行行为:
服务器接收到该指令后,可根据自身的功耗策略和业务需求修改扫描行为------协议未强制要求服务器开启本地扫描,仅做柔性规定。比如:
低功耗设备(如助听器)可选择暂时不开启本地扫描,等待客户端再次开启代扫,继续保持低功耗状态;
普通设备(如蓝牙扬声器)可选择立即开启本地扫描,避免无法接收广播源,保证使用体验。
这一柔性设计体现了协议的设备适配性,不同设备可根据自身定位制定不同的扫描策略,无需统一执行。
关键细节:
该操作为条件必选操作 ,若服务器支持委托扫描机制,必须实现该操作;指令为单字节(0x00),无任何参数字节,客户端写入时若添加多余字节,会触发指令长度错误。

4.2 Remote Scan Started(0x01):委托扫描开启指令
核心定位: 告知服务器客户端已开始代为扫描广播源 ,是委托扫描机制的开启开关,也是BASS实现低功耗的核心指令,无任何参数,操作码0x01即为完整指令。
执行行为
服务器接收到该指令后,可选择关闭自身的本地扫描功能,这是BASS降低服务器功耗的关键设计------助听器、TWS耳机等设备的电池容量有限,持续的本地扫描会大幅消耗电量,委托客户端(手机、智能手表,续航更强)代为扫描,服务器关闭本地扫描,可大幅降低功耗。
与Remote Scan Stopped相同,协议对关闭本地扫描仅做推荐,不做强制要求,服务器可根据自身需求选择是否关闭,比如部分设备需要同时接收本地扫描和客户端代扫的广播源,可选择不关闭本地扫描。
关键细节
-
条件必选操作,与Remote Scan Stopped成对实现,支持其一则必须支持其二;
-
单字节指令(0x01),多余字节会触发长度错误;
-
该指令的执行仅为状态通知,客户端不会向服务器传递任何广播源信息,广播源信息需通过后续的Add Source操作传递。

4.3 Add Source(0x02):添加广播源+发起同步 核心复杂指令
核心定位: 向服务器添加广播源的完整信息 ,并请求服务器同步该广播源的PA(周期性广播序列)和/或BIS(广播等时流),是BASS中参数最复杂、执行行为最繁琐的操作,也是实现广播音频接收的核心指令------所有的广播源接收,都从该操作开始。

核心参数格式
Add Source操作的参数包含广播源标识、PA同步配置、子组与BIS同步配置、元数据四大类,部分参数为数组类型(如BIS_Sync[i]),遵循协议的数组参数传输规则(ParameterA[0]、ParameterB[0]、ParameterA[1]、ParameterB[1]),具体参数格式如下表所示(单位:字节):
|-------------------------|--------|---------------|--------------------------------------------------|
| 字段 | 长度 | 核心描述 | 取值要求 |
| Opcode | 1 | Add Source操作码 | 固定0x02 |
| Advertiser_Address_Type | 1 | 广播源地址类型 | 0x00=公有地址;0x01=随机地址;其他=RFU |
| Advertiser_Address | 6 | 广播源设备地址 | 符合蓝牙设备地址格式 |
| Advertising_SID | 1 | 广播源SID标识 | 0x00-0x0F;其他=RFU |
| Broadcast_ID | 3 | 广播源唯一ID | 符合BAP规范的Broadcast_ID定义 |
| PA_Sync | 1 | PA同步请求 | 0x00=不同步;0x01=同步(PAST可用);0x02=同步(PAST不可用);其他=RFU |
| PA_Interval | 2 | PA同步间隔 | 0xFFFF=未知间隔;其他=符合SyncInfo定义 |
| Num_Subgroups | 1 | BIG中子组数量 | 0x00-0xFF(实际由广播源决定) |
| BIS_Sync[i] | 4/个子组 | 子组BIS同步位图 | 4字节位域;0b0=不同步;0b1=同步;0xFFFFFFFF=无偏好 |
| Metadata_Length[i] | 1/个子组 | 子组元数据长度 | 0x00=无元数据;其他=实际元数据长度 |
| Metadata[i] | 可变/个子组 | 子组LTV格式元数据 | 长度与Metadata_Length[i]匹配 |
从参数能看出,Add Source操作几乎包含了服务器同步广播源所需的所有信息,客户端需要先扫描广播源,解析出这些信息后,再通过该操作传递给服务器,服务器无需再做任何扫描,直接根据参数发起同步。
核心执行行为
服务器接受Add Source操作后,会执行一系列连续的行为 ,最终完成广播源的添加和同步请求的处理,整个行为可分为状态特征分配、广播源信息写入、PA同步处理、BIS同步处理、加密状态处理五大步骤,每一步都有严格的协议要求:
步骤1:分配Broadcast Receive State特征
服务器首先选择一个空的状态特征实例,若没有空实例,则选择一个已存在的实例并清空其所有字段,为新的广播源分配状态存储空间,这是保证每个广播源对应一个状态特征的基础。
步骤2:写入广播源基础信息并分配Source_ID
服务器为该广播源分配一个唯一的Source_ID(0x00-0xFF),并将客户端传递的Advertiser_Address_Type、Advertiser_Address、Advertising_SID、Broadcast_ID写入状态特征的对应字段,完成广播源的身份注册,Source_ID成为后续操作该广播源的唯一标识。
步骤3:根据PA_Sync参数处理PA同步
PA是BIS同步的前提,服务器必须先同步PA才能获取BIS的同步信息,因此PA_Sync的处理是Add Source操作的核心,服务器会根据PA_Sync的不同取值执行不同行为:
PA_Sync=0x00(不同步PA) :服务器将状态特征的PA_Sync_State设为0x00(未同步PA),且不发起任何PA同步操作,该广播源仅做信息存储,不进行音频接收;
PA_Sync=0x01/0x02(同步PA) :服务器有两种处理方式------一是将PA_Sync_State设为0x01(SyncInfo请求),向客户端请求PA的同步信息;二是直接通过蓝牙核心规范的Periodic Advertising Synchronization Establishment流程发起PA同步。其中0x01表示PAST(周期性广播同步传输)可用,0x02表示PAST不可用,服务器仅在支持PAST时才能发起SyncInfo请求。
若服务器发起SyncInfo请求但未在规定时间内收到客户端的同步信息(时间由厂商实现或高层协议定义),会将PA_Sync_State设为0x04(No PAST),并停止PA同步尝试。若服务器成功同步PA,将PA_Sync_State设为0x02(已同步PA);同步失败则设为0x03(同步PA失败)。
步骤4:根据BIS_Sync参数处理BIS同步
BIS是实际承载音频数据的传输流,服务器仅在成功同步PA后,才会处理BIS_Sync参数,发起BIS同步,核心规则:
若BIS_Sync≠0xFFFFFFFF(无偏好):服务器仅同步BIS_index被设为0b1的BIS,且保证同一个BIS_index仅在一个子组中被同步(否则触发BIS_Sync参数错误);
若BIS_Sync=0xFFFFFFFF(无偏好):服务器可根据自身需求同步任意BIS,无强制限制;
服务器通过蓝牙核心规范的Broadcast Isochronous Synchronization Establishment流程发起BIS同步,同步成功后,将状态特征BIS_Sync_State中对应的BIS_index设为0b1;同步失败则设为0b0,若整个BIG同步失败,将BIS_Sync_State设为0xFFFFFFFF(BIG同步失败)。
步骤5:根据广播源加密状态处理加密字段
服务器同步PA/BIS后,会检测广播源的加密状态,并更新状态特征的BIG_Encryption字段,核心规则:
-
未加密:BIG_Encryption设为0x00(未加密),无需处理;
-
加密且无解密密钥:BIG_Encryption设为0x01(需要Broadcast_Code),向客户端请求解密密钥;
-
加密且有正确密钥:BIG_Encryption设为0x02(正在解密),服务器开始解密BIS并接收音频;
-
加密且密钥错误:BIG_Encryption设为0x03(Bad_Code),并将Bad_Code字段设为全F,告知客户端密钥错误。
关键细节
-
该操作的参数长度可能超过ATT的默认MTU(23字节),因此服务器若支持该操作,必须实现Write Long Characteristic Value(长写入)GATT子过程,客户端通过长写入传递参数;
-
数组参数(BIS_Sync[i]、Metadata_Length[i]、Metadata[i])必须遵循协议的传输规则,否则服务器会解析错误;
-
RFU字段必须设为0,否则服务器可能判定为参数错误并忽略操作;
-
服务器仅在接受操作后才会修改状态特征,若拒绝操作,状态特征无任何变化。
4.4 Modify Source(0x03):修改广播源同步配置,基于Source_ID的更新指令
核心定位: 根据Source_ID 修改已添加广播源的PA同步配置、BIS同步配置、元数据,是Add Source操作的后续更新指令,适用于广播源参数变化(如PA间隔修改、需要同步的BIS流变化)的场景。

核心参数格式:
Modify Source操作的参数基于Add Source做了简化,移除了广播源的基础标识字段(如地址、Broadcast_ID),新增了Source_ID字段用于定位广播源,具体参数格式如下表所示(单位:字节):
|----------------------|--------|------------------|-----------------------|
| 字段 | 长度 | 核心描述 | 取值要求 |
| Opcode | 1 | Modify Source操作码 | 固定0x03 |
| Source_ID | 1 | 广播源唯一标识 | 与服务器中状态特征的Source_ID匹配 |
| PA_Sync | 1 | PA同步请求 | 与Add Source一致 |
| PA_Interval | 2 | PA同步间隔 | 与Add Source一致 |
| Num_Subgroups | 1 | BIG中子组数量 | 与Add Source一致 |
| BIS_Sync[i] | 4/个子组 | 子组BIS同步位图 | 与Add Source一致 |
| Metadata_Length[i] | 1/个子组 | 子组元数据长度 | 与Add Source一致 |
| Metadata[i] | 可变/个子组 | 子组LTV格式元数据 | 与Add Source一致 |
与Add Source相比,Modify Source仅通过Source_ID定位广播源,无需重复传递基础标识字段,简化了指令长度,提升了传输效率。
核心执行行为
Modify Source的执行行为与Add Source高度相似,核心区别在于先匹配Source_ID,再更新配置,而非分配新的状态特征,整体流程为:
-
服务器根据客户端写入的Source_ID,匹配对应的Broadcast Receive State特征,若匹配失败则触发Source_ID无效错误;
-
服务器根据PA_Sync参数更新PA同步状态 ,若PA_Sync=0x00且服务器已同步PA,会停止PA同步,并将PA_Sync_State设为0x00;若PA_Sync=0x01/0x02,处理逻辑与Add Source一致;
-
服务器根据BIS_Sync参数更新BIS同步状态 ,若BIS_index被设为0b0且服务器已同步该BIS,会停止BIS同步,并将BIS_Sync_State中对应的位设为0b0;新增的BIS_index设为0b1则发起同步,处理逻辑与Add Source一致;
-
服务器根据新的元数据参数更新状态特征的Metadata_Length[i]和Metadata[i];
-
服务器根据更新后的同步状态重新处理加密字段,处理逻辑与Add Source一致。
关键细节
-
该操作的核心是更新而非新建,仅能修改已添加的广播源,无法添加新的广播源;
-
若服务器正在同步PA/BIS,修改PA_Sync/BIS_Sync为0x00,服务器会立即停止同步,这是开发中需要注意的实时性要求;
-
数组参数的传输规则、RFU字段要求、长写入要求均与Add Source一致。
4.5 Set Broadcast_Code(0x04):传递解密密钥 唯一必选操作
核心定位: 向服务器传递16字节的Broadcast_Code解密密钥 ,用于解密加密的BIS流,是BASS中唯一的强制操作,所有实现BASS的服务器都必须支持,也是接收加密广播音频的核心指令。

核心参数格式:
该操作的参数极为简洁,仅包含Source_ID 和16字节Broadcast_Code,无需其他参数,具体格式如下表所示(单位:字节):
|----------------|--------|-----------------------|-----------------------|
| 字段 | 长度 | 核心描述 | 取值要求 |
| Opcode | 1 | Set Broadcast_Code操作码 | 固定0x04 |
| Source_ID | 1 | 广播源唯一标识 | 与服务器中状态特征的Source_ID匹配 |
| Broadcast_Code | 16 | 加密BIS的解密密钥 | 16字节二进制数据,符合蓝牙核心规范定义 |
核心执行行为
服务器接收到该操作后,首先匹配Source_ID对应的广播源 ,若匹配失败则触发Source_ID无效错误;匹配成功后,使用该Broadcast_Code尝试解密对应的加密BIS流,并根据解密结果更新状态特征的BIG_Encryption字段:
-
解密成功:将BIG_Encryption设为0x02(正在解密),服务器开始接收并解码音频;
-
解密失败:将BIG_Encryption设为0x03(Bad_Code),并将Bad_Code字段设为全F,告知客户端密钥错误。
协议未要求服务器对Broadcast_Code做存储,是否存储由厂商实现,比如部分设备需要长期接收某个加密广播源,可将Broadcast_Code存储在本地,避免客户端重复传递。
关键细节
-
强制操作,所有BASS服务器必须实现,无任何例外;
-
16字节Broadcast_Code为固定长度,客户端写入时长度错误会触发指令长度错误;
-
该操作必须在加密GATT连接下进行,协议强制要求,防止密钥在传输过程中被窃取;
-
服务器可多次接收该操作的不同Broadcast_Code,直至解密成功,每次接收都会重新尝试解密。
4.6 Remove Source(0x05):移除广播源 清理资源的收尾指令
核心定位: 根据Source_ID移除服务器中的广播源信息,释放对应的Broadcast Receive State特征资源,是广播音频接收的收尾指令,适用于不再需要接收某个广播源的场景。

核心参数格式:
该操作的参数极为简洁,仅包含Source_ID,无其他参数,具体格式如下表所示(单位:字节):
|-----------|--------|------------------|-----------------------|
| 字段 | 长度 | 核心描述 | 取值要求 |
| Opcode | 1 | Remove Source操作码 | 固定0x05 |
| Source_ID | 1 | 广播源唯一标识 | 与服务器中状态特征的Source_ID匹配 |
核心执行行为
Remove Source的执行行为有严格的前置条件,服务器会先校验该广播源的同步状态,再决定是否接受操作,核心逻辑:
-
前置条件校验 :服务器检查该Source_ID对应的PA_Sync_State和BIS_Sync_State,若服务器正在同步该广播源的PA或BIS (PA_Sync_State=0x02,或BIS_Sync_State有位设为0b1),则拒绝该操作,不做任何处理;
-
操作接受处理 :若服务器未同步该广播源的PA/BIS,接受该操作 ,并清空该Source_ID对应的Broadcast Receive State特征的所有字段,释放该状态特征实例,用于后续添加新的广播源;
-
操作拒绝处理 :若服务器正在同步PA/BIS,拒绝该操作,不修改任何状态特征,客户端若需要移除,需先通过Modify Source操作停止同步。
这一前置条件校验的设计,是为了避免在音频接收过程中突然移除广播源,导致音频中断、服务器行为异常,保证了音频接收的稳定性。
关键细节
-
条件必选操作,与其他条件必选操作成对实现;
-
仅能移除未同步的广播源,同步中的广播源无法移除,这是开发中需要注意的核心限制;
-
操作成功后,对应的Source_ID失效,客户端后续不能再使用该Source_ID下发任何指令,否则触发Source_ID无效错误。
五、控制点指令协同流程:实际场景中的全流程调用
单独解析每个操作码的细节后,需要将其串联起来,结合实际的广播音频接收场景 ,看这些操作码在实际使用中是如何协同工作的。以下以手机(客户端)代助听器(服务器)接收电视广播音频 的场景为例,梳理控制点指令的完整调用流程,展示客户端-服务器-广播源三者的交互逻辑。
5.1 场景前提
-
助听器(服务器)开启BASS服务,广播BASS UUID,等待客户端连接;
-
手机(客户端)扫描到助听器,建立加密GATT连接,完成MTU交换(支持长写入);
-
电视(广播源)发送加密的广播音频流,包含PA、BIG、BIS,广播源信息可被手机扫描解析。
5.2 完整指令协同流程

5.3 流程核心解读
-
委托扫描开启:手机首先下发Remote Scan Started,助听器关闭本地扫描,实现低功耗,这是BASS的核心设计初衷;
-
广播源添加:手机解析广播源参数后,通过Add Source操作传递给助听器,助听器完成广播源注册并发起同步请求;
-
密钥传递与解密:助听器检测到加密广播后,向手机请求密钥,手机通过Set Broadcast_Code传递密钥,助听器解密成功后开始接收音频;
-
广播源移除:不再接收时,手机先通过Modify Source停止同步,再通过Remove Source移除广播源,最后关闭委托扫描,完成整个流程。
这一流程覆盖了控制点6大操作码的所有使用场景,也是实际开发中最典型的BASS交互流程,掌握这一流程,就能理解控制点指令在实际设备中的落地方式。
六、控制点开发实战要点:避坑指南 贴合实际开发
基于协议规范的要求,结合嵌入式蓝牙开发的实际经验,总结出控制点开发中的核心实战要点,这些要点能帮助开发者避开协议中的坑,保证设备的互联互通性和稳定性,也是实际开发中需要重点注意的细节。
6.1 严格遵循字节序要求:小端序(LSO first)
协议强制要求BASS所有特征的字节传输采用小端序(最低有效字节优先),控制点的多字节参数(如PA_Interval、BIS_Sync[i])必须按小端序传输,否则服务器会解析出错误的参数值。比如PA_Interval=0x1234,客户端需先传输0x34,再传输0x12,这是开发中最基础也最易忽略的点。
6.2 严格校验RFU字段:必须设为0
协议中所有标记为RFU的字段,客户端必须将其值设为0,服务器解析时会忽略RFU字段,但如果客户端将其设为非0值,部分服务器会判定为参数错误并忽略操作。比如Advertiser_Address_Type的RFU值、Advertising_SID的RFU值,均需设为0。
6.3 实现长写入功能:适配Add/Modify Source的长参数
Add Source和Modify Source的参数长度极有可能超过ATT默认MTU(23字节),因此服务器若支持这两个操作,必须实现Write Long Characteristic Value GATT子过程,客户端也需支持长写入,否则会出现指令长度错误,无法传递参数。
6.4 实时同步Source_ID列表:避免无效ID
Source_ID是服务器动态分配的唯一标识,客户端需要实时同步服务器的Source_ID列表,并监听状态特征的通知,当广播源被移除时,及时将对应的Source_ID标记为无效,避免后续使用无效ID下发指令,触发Source_ID无效错误。
6.5 加密连接的硬性保障:密钥传递的安全要求
控制点的所有操作均要求在加密GATT连接下进行,尤其是Set Broadcast_Code操作,必须保证连接加密,否则会导致密钥泄露。开发中需要实现蓝牙的配对绑定流程,建立加密连接后,再进行控制点的指令交互。
6.6 处理好同步状态的前置校验:Remove Source的核心限制
Remove Source操作有严格的前置条件,仅能移除未同步的广播源,开发中客户端需要先读取该广播源的同步状态,确认未同步后再下发Remove Source指令,避免操作被拒绝;若广播源正在同步,需先通过Modify Source停止同步,再执行移除。
七、测试
问题:BASS的Broadcast Audio Scan Control Point中,唯一的强制操作码是什么?为什么将其设为强制操作?该操作的核心参数和执行行为是什么?
答案:
-
唯一的强制操作码是0x04(Set Broadcast_Code);
-
设为强制的原因是LE Audio的广播音频支持加密传输,保护音频隐私是核心需求,而助听器、TWS耳机等BASS核心设备必须支持解密加密广播,因此传递解密密钥的Set Broadcast_Code成为必选操作;
-
核心参数为Source_ID(1字节)+16字节Broadcast_Code;
-
执行行为:服务器匹配Source_ID对应的广播源,使用Broadcast_Code尝试解密加密BIS,解密成功则设为正在解密并接收音频,解密失败则标记为Bad_Code并告知客户端。
问题:BASS控制点的错误处理中,协议定义了两个专属的应用层错误码,分别是什么?触发场景是什么?不同GATT写入方式下的处理逻辑有何不同?
答案:
-
两个专属应用层错误码为0x80(Opcode Not Supported)和0x81(Invalid Source_ID);
-
触发场景:0x80为客户端写入了服务器未支持的操作码,0x81为客户端写入的Source_ID与服务器所有状态特征的Source_ID均不匹配;
-
处理逻辑:无响应写时,服务器直接忽略整个操作,无任何反馈;带响应写时,服务器返回ATT Error Response,并设置对应的错误码。
问题:Add Source操作是BASS中最复杂的操作,简述服务器接受该操作后的核心执行流程?PA同步与BIS同步的处理有何前置关系?
答案:
1. 核心执行流程:
①分配空的Broadcast Receive State特征;
②分配唯一Source_ID并写入广播源基础信息;
③根据PA_Sync参数处理PA同步,发起同步或请求SyncInfo;
④成功同步PA后,根据BIS_Sync参数处理BIS同步,发起同步并更新状态;
⑤检测广播源加密状态,更新BIG_Encryption字段;
2. PA同步与BIS同步的前置关系:BIS同步的前置条件是服务器成功同步PA,服务器未同步PA时,不会处理任何BIS_Sync参数,也不会发起任何BIS同步操作。