做过BLE电竞外设、VR交互控制器、高精度工业手柄的开发者都有过这样的经历:明明把HID ISO的传输机制、时序参数、CIS通道配置都调通了,却还是遇到主机不认设备的低延迟能力、模式切换频繁失败、写操作一直返回未知错误、ISO通道建立后数据完全无法解析的问题。排查到最后会发现,90%的坑,都出在HID ISO Service的GATT实现不符合规范上。
目录
[一、HID ISO Service的核心定位:低延迟功能的GATT控制中枢](#一、HID ISO Service的核心定位:低延迟功能的GATT控制中枢)
[二、HID ISO Service的基础规则:开发前必须遵守的全局约束](#二、HID ISO Service的基础规则:开发前必须遵守的全局约束)
[2.1 服务声明与实例约束](#2.1 服务声明与实例约束)
[2.2 GATT子过程强制要求](#2.2 GATT子过程强制要求)
[2.3 标准ATT应用错误码](#2.3 标准ATT应用错误码)
[三、核心特征详解一:HID ISO Properties------设备的ISO能力说明书](#三、核心特征详解一:HID ISO Properties——设备的ISO能力说明书)
[3.1 特征基础属性](#3.1 特征基础属性)
[3.2 特征全字段解析与配置规则](#3.2 特征全字段解析与配置规则)
[3.3 特征的核心行为规则](#3.3 特征的核心行为规则)
[四、核心特征详解二:LE HID Operation Mode------模式切换的控制台](#四、核心特征详解二:LE HID Operation Mode——模式切换的控制台)
[4.1 特征基础属性](#4.1 特征基础属性)
[4.2 特征全字段解析与配置规则](#4.2 特征全字段解析与配置规则)
[4.3 特征的行为规则与附录B模式切换时序联动](#4.3 特征的行为规则与附录B模式切换时序联动)
如果说HID ISO传输机制是低延迟能力的发动机,那HID ISO Service就是控制这台发动机的驾驶舱。它是蓝牙SIG在HOGP v1.1规范中,专门为HID ISO低延迟功能定义的标准GATT服务,是主机和设备之间完成ISO能力协商、模式切换控制、传输参数配置的唯一官方接口。没有这个服务的正确实现,主机和设备根本无法完成ISO通道的标准化对接,所有低延迟的设计都无从落地。
本文从服务的核心定位、基础规则、两大核心特征的全字段解析、协议联动流程、开发避坑指南全维度,把HID ISO Service的所有规范细节拆解得明明白白,同时结合规范中的模式切换时序,彻底搞懂这个服务的设计逻辑,避开开发中90%的常见问题。
一、HID ISO Service的核心定位:低延迟功能的GATT控制中枢
在深入规范细节之前,我们先搞清楚一个核心问题:HID ISO Service在整个HOGP架构里,到底扮演什么角色?它和我们熟悉的HID Service是什么关系?
我们可以用一个非常形象的比喻来理解:
-
传统的HID Service,相当于BLE HID设备的基础驾驶系统,负责常规的油门、刹车、转向控制,也就是所有基于GATT的HID报告传输,满足普通办公键鼠的基础需求。
-
HID ISO Service,相当于这套系统的运动模式控制台,专门负责控制低延迟、高响应的运动模式切换,告诉主机这台车能跑多快、能承受多大的扭矩、支持哪些赛道模式,同时接收主机的模式切换指令,完成运动模式的激活和关闭。
规范里对这个服务的核心边界做了明确的定义:
The HID ISO Service defines one characteristic to describe the ISO-related properties of the HID Device, and one characteristic to configure the HID ISO behavior and the state changes between the Default Operation mode and Hybrid Operation mode.
这句话直接点明了这个服务的两大核心职责,也是整个服务的设计核心:
-
能力描述:向主机完整披露设备的HID ISO相关能力,包括支持的报告间隔、SDU大小、可走ISO通道的报告列表、可选功能支持情况,相当于设备给主机的一份官方规格说明书。
-
行为控制:接收主机的指令,完成默认模式和混合模式的切换,配置ISO传输的相关参数,同时支持设备向主机发起模式切换请求,是整个低延迟功能的控制开关。
和很多人理解的不同,HID ISO Service并不是HID Service的子服务,而是一个完全独立的主服务。规范里明确说明,这个服务不依赖任何其他GATT服务,哪怕没有HID Service,它也可以独立存在。但在实际的HOGP落地中,它必须和HID Service配合使用------HID Service负责基础的HID报告定义和常规传输,HID ISO Service负责低延迟ISO通道的控制,二者共同实现混合模式的双链路传输。
二、HID ISO Service的基础规则:开发前必须遵守的全局约束
在拆解核心特征之前,我们先把规范里定义的服务全局规则讲透。这些规则是服务实现的底线,只要有一条不符合,主机就可能完全不识别这个服务,甚至导致蓝牙认证失败。
2.1 服务声明与实例约束
首先是最基础的服务声明规则,也是开发中最容易踩的第一个坑:
-
服务类型 强制要求:HID ISO Service必须实例化为Primary Service,也就是主服务,绝对不能定义为Secondary Service次要服务。BLE协议里,只有主服务才能被主机在服务发现阶段主动识别,次要服务只能被主服务包含引用,一旦定义为次要服务,主机在标准服务发现流程中根本找不到这个服务,低延迟功能直接失效。
-
实例数量强制约束 :规范里明确要求Only one instance of the HID ISO Service shall be allowed on a Server. 也就是说,一个BLE设备上,只能有一个HID ISO Service实例,绝对不能创建多个实例。很多开发者为了区分多个HID接口,想做多实例服务,这是规范明确禁止的,主机发现多个实例后,会直接忽略所有实例,导致功能完全失效。
-
UUID 规范要求:服务必须使用蓝牙SIG官方分配的HID ISO Service标准UUID,绝对不能使用自定义UUID。只有使用官方分配的UUID,主机才能在服务发现阶段,识别出这是一个标准的HID ISO服务,从而按照规范流程进行能力读取和控制。
2.2 GATT子过程强制要求

规范里明确了服务端(也就是HID设备)必须支持的GATT子过程,这是主机和设备正常通信的基础,少一个都不行:
-
Write Characteristic Value:强制必选。主机需要通过写特征值的方式,向设备发送模式切换指令和配置参数,没有这个能力,主机根本无法控制设备的模式切换,这是整个服务的核心基础能力。
-
Indications:条件必选。只有当设备支持主动向主机发起模式切换请求时,才必须支持这个子过程;如果不支持主动请求,这个能力是可选的。这里要特别注意,一旦开启了设备主动模式切换的能力,就必须为对应的特征添加Client Characteristic Configuration Descriptor(CCCD)描述符,否则设备无法向主机发送Indication,主机也无法接收设备的模式切换请求。
2.3 标准ATT应用错误码
规范里专门为HID ISO Service定义了3个ATT层的应用错误码,这是开发中必须严格实现的部分。很多开发者遇到主机写操作失败,只会返回通用的ATT错误码,导致主机根本无法定位问题,只能报未知错误,这是非常不规范的实现。

这3个错误码的触发场景、返回时机和含义,我整理成了清晰的表格,每个场景都对应了开发中的实际情况:
|-----------------------------------|----------|-------------------------------------------------------------------------------------------------------------------------------------------------------------|
| 错误码名称 | 错误码值 | 触发场景与使用规则 |
| Opcode outside range | 0x81 | 主机写入的Opcode值不在规范定义的合法范围内,也就是除了0x01和0x02之外的其他RFU保留值。设备收到非法Opcode后,必须在写响应中返回这个错误码,不能用通用错误码替代。 |
| Device already in requested state | 0x82 | 主机请求切换的模式,设备已经处于该状态。最常见的场景:设备已经在混合模式下运行,主机又发送了切换混合模式的指令;或者已经在默认模式下,主机又发送了切换默认模式的指令。此时设备必须返回这个错误码,告知主机无需重复切换。 |
| Unsupported feature | 0x83 | 主机写入的配置参数中,包含了设备不支持的功能或参数。这是开发中最常触发的错误码,常见场景包括:主机选择了设备不支持的报告间隔、配置的SDU大小超过了设备的最大值、开启了设备不支持的确认/重复传输功能、选择的报告索引超出了设备的支持范围。只要主机的配置超出了设备在能力描述中声明的范围,设备就必须返回这个错误码。 |
这里要特别强调一个规范要求:只有当主机的写请求完全符合规范、所有参数都在设备的支持范围内时,设备才能返回成功响应;只要有任何一个参数不符合要求,就必须返回对应的错误码,绝对不能忽略非法参数,用默认值替代,否则会导致主机和设备的配置状态不一致,出现后续的传输异常。
三、核心特征详解一:HID ISO Properties------设备的ISO能力说明书
HID ISO Properties是HID ISO Service的第一个核心特征,也是主机连接设备后,第一个必须读取的特征。它就像设备给主机的一份完整、不可修改的官方规格说明书,主机所有的ISO配置、模式切换操作,都必须严格按照这份说明书里的内容来执行,一旦超出范围,设备就会返回不支持的错误。

3.1 特征基础属性
规范里对这个特征的基础属性做了严格的强制要求,没有任何可选项:
支持要求:强制必选,所有实现HID ISO Service的设备,都必须包含这个特征。
特征属性:仅支持Read只读属性,不支持写、通知、指示等任何其他属性。因为这是设备的能力声明,连接期间不能被主机修改,也不能动态变化。
安全权限:必须和HID Service的特征保持一致的安全级别,也就是需要加密的链路才能读取,防止未授权的设备读取设备的能力参数,符合HOGP的安全规范要求。
3.2 特征全字段解析与配置规则
这个特征的结构是固定的,除了最后一个可变长度的数组字段,前面的字段长度都是固定的,总长度在10字节到20字节之间。规范里对每个字段的长度、数据类型、含义、配置规则都做了明确的定义,我们逐个拆解,同时结合实际开发的例子,帮你彻底搞懂每个字段的配置方法。

3.2.1 Features字段:1字节,设备功能开关

这个字段是1字节的位域,共8个布尔位,用来声明设备的可选功能支持情况,目前规范里只定义了最低位,其他7位都是保留位,必须设置为0。
Bit0:Device Mode Change Supported,设备模式切换支持位。这个位设为1,代表设备支持主动向主机发起模式切换请求;设为0,代表设备不支持主动请求,只能被动等待主机发起模式切换。
Bit1~Bit7:RFU保留位,必须全部设置为0,不能用于自定义功能,否则会被主机判定为非法参数。
这里要特别注意:这个位是设备支持主动模式切换的唯一前提。如果这个位设为0,哪怕你在固件里实现了主动请求的逻辑,也是不符合规范的,主机有权直接忽略设备的所有Indication请求。
3.2.2 Supported Report Intervals字段:2字节,支持的报告间隔声明
这个字段是2字节的位域,共16个布尔位,每个bit对应一个设备支持的报告间隔,主机只能选择这个字段里设为1的报告间隔,否则设备会返回不支持的错误码。

规范里对每个bit对应的报告间隔做了明确的定义,我整理成了清晰的对应表:
|-------------|-------------|------------------------|
| Bit位 | 对应的报告间隔 | 支持要求 |
| Bit0 | 1ms | 可选支持 |
| Bit1 | 2ms | 可选支持 |
| Bit2 | 3ms | 可选支持 |
| Bit3 | 4ms | 可选支持 |
| Bit4 | 5ms | 强制必选,至少支持5ms或7.5ms中的一个 |
| Bit5 | 1.25ms | 可选支持 |
| Bit6 | 2.5ms | 可选支持 |
| Bit7 | 3.75ms | 可选支持 |
| Bit8 | 7.5ms | 强制必选,至少支持5ms或7.5ms中的一个 |
| Bit9~Bit15 | RFU保留位 | 必须全部设为0 |
这里有两个绝对不能违反的强制规则:
设备必须至少支持5ms和7.5ms中的一个,也就是Bit4和Bit8必须至少有一个设为1,否则设备不符合HOGP的基础规范要求,无法通过蓝牙认证。
主机后续配置报告间隔时,必须且只能选择这个字段里设为1的bit对应的间隔,不能选择设备不支持的间隔。
举个实际开发的例子:一个电竞鼠标,需要支持1ms、2ms、5ms、7.5ms四个报告间隔,那这个字段的Bit0、Bit1、Bit4、Bit8需要设为1,其他bit设为0。换算成16进制,就是0x0113,这个值就是这个字段需要填入的数值。
3.2.3 输入/输出报告的Max/Preferred SDU Size字段:共4字节,SDU长度声明
这四个字段都是1字节的uint8无符号整数,分为两组,分别对应设备到主机的输入报告,和主机到设备的输出报告,用来声明SDU的最大支持长度和推荐长度。
很多开发者在这里搞混了Max和Preferred的区别,导致配置错误,影响传输性能,我们分别讲清楚:
Max SDU Size for Input Reports:1字节,设备向主机发送ISO数据的最大SDU长度,单位是字节。规范里明确要求,这个值的计算方式是:最长的输入报告长度 + 3字节的HID ISO协议头 × 最大重复次数。这个值是设备能支持的绝对上限,主机配置的输入SDU长度,绝对不能超过这个值,否则设备会返回不支持的错误码。
Preferred SDU Size for Input Reports:1字节,设备推荐的输入报告SDU长度。这个值是设备在实际使用中,性能最好、功耗最优的长度,通常是设备最常用的核心报告长度 + 3字节协议头 × 常用重复次数。规范里明确要求,主机如果没有特殊的带宽限制,应该优先使用这个值,不会对设备的性能造成任何影响。
Max SDU Size for Output Reports:1字节,主机向设备发送ISO数据的最大SDU长度,计算规则和输入报告一致,是最长输出报告长度 + 3字节协议头 × 最大重复次数,是主机配置输出SDU的绝对上限。
Preferred SDU Size for Output Reports:1字节,设备推荐的输出报告SDU长度,主机无特殊限制时优先使用。
这里要特别注意:SDU长度的计算,必须包含3字节的HID ISO协议头,很多开发者只算了报告本身的长度,忘了加协议头,导致主机配置的SDU长度刚好卡在设备的实际上限上,长报告传输时出现丢包和截断。
3.2.4 Hybrid Mode ISO Reports字段:2~12字节,可走ISO的报告列表
这个字段是整个Properties特征里最复杂、最容易踩坑的部分,它定义了设备里哪些HID报告可以走ISO通道传输,每个报告的类型、支持的可选功能。主机后续只能从这个列表里选择要启用的ISO报告,不能选择列表之外的报告。
规范里明确要求,这个字段是一个结构体数组,每个结构体固定2字节,数组长度最少1个,最多6个,所以整个字段的长度在2字节到12字节之间。

每个结构体的结构是固定的,分为两个1字节的字段:
-
Report ID:1字节uint8,对应HID Service里Report Map中定义的HID报告ID,必须和Report Map里的报告ID完全一致,不能有任何偏差。如果报告没有ID,这个字段必须设为0。
-
Additional Info:1字节位域,共8个布尔位,用来声明这个报告的类型和支持的可选功能,每个bit的定义如下:
Bit0:Report Type,报告类型。0代表Input Report输入报告,1代表Output Report输出报告,必须和Report Map里的报告类型完全一致。
Bit1:Confirmation Supported,确认机制支持位。1代表这个报告支持接收确认机制,0代表不支持。
Bit2:Repetition Supported,重复传输支持位。1代表这个报告支持重复传输机制,0代表不支持。
Bit3~Bit7:RFU保留位,必须全部设为0。
这里有三个开发中必须遵守的核心规则,也是最容易踩坑的地方:
报告ID和类型必须和HID Service完全匹配:这个字段里的每个结构体的Report ID和Report Type,必须和HID Service中Report Map里定义的报告完全一致。如果不一致,主机就算选中了这个报告,也无法和实际的HID报告对应起来,导致ISO通道传输的数据完全无法解析,出现光标乱跳、按键无响应的问题。
数组长度最多6个:这个结构体数组最多只能有6个元素,也就是设备最多只能声明6个可走ISO通道的报告,不能超过这个数量。
混合模式会话最多选2个:虽然设备最多可以声明6个可选报告,但规范里明确要求,在一个混合模式会话中,主机最多只能选择1个输入报告和1个输出报告,也就是最多2个报告走ISO通道,其他报告依然走GATT链路。
举个实际的例子:一个电竞鼠标,有两个可走ISO的报告:
-
第一个是输入报告,Report ID 0x01,对应鼠标的XY轴移动和按键数据,支持确认机制和重复传输,所以Additional Info的Bit0=0,Bit1=1,Bit2=1,其他位0,换算成16进制是0x06。
-
第二个是输出报告,Report ID 0x02,对应鼠标的灯效控制数据,不支持确认和重复传输,所以Additional Info的Bit0=1,Bit1=0,Bit2=0,其他位0,换算成16进制是0x01。
那这个Hybrid Mode ISO Reports字段,就是两个结构体组成的数组,值为0x01060201,总长度4字节,完全符合规范要求。
3.3 特征的核心行为规则
规范里对这个特征的行为做了一个强制要求,很多开发者在这里踩了坑:
The value of the HID ISO Properties shall be static during a connection.
也就是说,这个特征的值,在整个BLE连接期间,必须是完全静态的,不能动态修改。
主机在连接后,只会读取一次这个特征的值,然后缓存下来,在整个连接期间都不会再重复读取。如果设备在连接期间动态修改了这个特征的值,会导致主机缓存的能力和设备的实际能力完全不匹配,后续的配置操作会频繁返回不支持的错误码,模式切换完全失败。
四、核心特征详解二:LE HID Operation Mode------模式切换的控制台
如果说HID ISO Properties是设备的能力说明书,那LE HID Operation Mode就是整个HID ISO Service的控制台。主机通过写这个特征,来发送模式切换指令、配置ISO传输参数;设备通过这个特征,向主机发起模式切换请求,是整个低延迟功能的核心控制入口。
4.1 特征基础属性
规范里对这个特征的基础属性做了明确的要求:
支持要求:强制必选,所有实现HID ISO Service的设备,都必须包含这个特征。
强制属性:Write,可写属性,必须支持,主机通过写操作发送控制指令。
可选属性:Indications,指示属性,条件必选。只有当Properties特征里的Device Mode Change Supported位设为1时,才必须支持这个属性,同时必须添加对应的CCCD描述符;否则这个属性是可选的。
安全权限:和Properties特征一致,必须和HID Service保持相同的安全级别,需要加密链路才能进行写操作和指示操作。
4.2 特征全字段解析与配置规则
这个特征的结构分为两个部分:固定1字节的Opcode字段,和可变长度的Parameters字段,总长度在1字节到18字节之间。

4.2.1 Opcode字段:1字节,操作指令码

这个字段是1字节的uint8无符号整数,定义了当前操作的类型,规范里只定义了两个合法的Opcode值,其他所有值都是RFU保留值,设备收到后必须返回0x81 Opcode outside range错误码。
两个合法的Opcode定义如下:
|-------------|-------------------------------|--------------------------------------------|---------------------------|
| Opcode值 | 指令名称 | 功能描述 | Parameters字段要求 |
| 0x01 | Select Hybrid Operation Mode | 选择混合操作模式,主机通过这个指令,让设备切换到混合模式,同时携带所有ISO配置参数 | 必须携带完整的Parameters字段,不能为空 |
| 0x02 | Select Default Operation Mode | 选择默认操作模式,主机通过这个指令,让设备切换回默认模式,关闭ISO传输 | Parameters字段必须为空,不能携带任何数据 |
这里要特别注意:Opcode 0x02切换默认模式时,Parameters字段必须为空。如果主机携带了参数,设备有权判定为非法请求,返回对应的错误码。
4.2.2 Parameters字段:0~17字节,混合模式配置参数
只有当Opcode是0x01切换混合模式时,这个字段才存在,总长度固定为17字节以内,结构是固定的,规范里对每个字段的顺序、长度、含义、配置规则都做了明确的定义,我们逐个拆解,同时结合之前的Properties特征,讲清楚每个字段的配置约束。

1. CIG ID:1字节uint8,CIG组ID
这个字段是主机创建的Connected Isochronous Group(CIG)的ID,由主机分配和管理,设备只需要透传这个ID,不需要做任何修改,也不需要校验,因为CIG是主机的蓝牙控制器创建和管理的,设备只是被动接受CIS通道的连接。
2. CIS ID:1字节uint8,CIS流ID
这个字段是主机创建的Connected Isochronous Stream(CIS)的ID,对应CIG组里的CIS流,同样由主机分配,设备被动接受,不需要修改和校验。
3. Report Interval:2字节位域,选定的报告间隔
这个字段的编码格式,和Properties特征里的Supported Report Intervals字段完全一致,每个bit对应一个报告间隔。这里有两个绝对不能违反的强制规则:
必须且只能有一个bit设为1,不能同时设置多个bit,否则设备会返回0x83不支持的错误码。
设为1的这个bit,必须在Properties特征的Supported Report Intervals字段里是设为1的,也就是必须是设备支持的报告间隔,否则设备会返回0x83错误码。
很多开发者在这里踩坑,设置了多个bit为1,或者选了设备不支持的报告间隔,导致写操作直接失败,模式切换无法完成。
4. Current SDU Size for Input Reports:1字节uint8,输入报告SDU长度
主机配置的、本次混合模式会话中使用的输入报告SDU长度,必须小于等于Properties特征里的Max SDU Size for Input Reports,否则设备会返回0x83错误码。规范里推荐,主机如果没有特殊限制,应该使用Properties里的Preferred SDU Size for Input Reports的值,保证设备的最佳性能。
5. Current SDU Size for Output Reports:1字节uint8,输出报告SDU长度
主机配置的、本次混合模式会话中使用的输出报告SDU长度,必须小于等于Properties特征里的Max SDU Size for Output Reports,否则设备会返回0x83错误码,同样推荐使用设备的Preferred值。
6. Hybrid Mode ISO Reports Enable:1~2字节,启用的ISO报告列表
这个字段是一个结构体数组,每个结构体固定1字节,数组长度最少1个,最多2个,对应主机本次会话中要启用的ISO报告,也就是最多1个输入报告和1个输出报告。

每个结构体是1字节的位域,分为四个部分,规范里的定义如下:
|---------------------|--------|-----------------------------------------------------------------------------------------------------------------|
| 位域部分 | 长度 | 含义与配置规则 |
| Report Info Index | 3bit | 对应Properties特征里Hybrid Mode ISO Reports数组的索引,第一个元素索引为0,第二个为1,以此类推。必须是Properties里存在的索引,不能超出数组的长度范围,否则设备返回0x83错误码。 |
| RFU | 3bit | 保留位,必须全部设为0。 |
| Confirmation Enable | 1bit | 确认机制启用位。1代表开启,0代表关闭。只有当对应报告的Additional Info里的Confirmation Supported位是1时,才能设为1,否则设备返回0x83错误码。 |
| Repetition Enable | 1bit | 重复传输启用位。1代表开启,0代表关闭。只有当对应报告的Additional Info里的Repetition Supported位是1时,才能设为1,否则设备返回0x83错误码。 |
这里的核心约束是:所有配置都必须和Properties里声明的能力完全匹配,不能开启设备不支持的功能,不能选择设备没有声明的报告,否则设备会直接返回不支持的错误码。
举个例子,还是之前的电竞鼠标,Properties里的Hybrid Mode ISO Reports数组有两个元素,索引0是输入报告,索引1是输出报告。主机要启用这两个报告,同时为输入报告开启确认和重复传输,输出报告都不开启,那这个字段的两个结构体分别是:
第一个结构体(索引0):Report Info Index=0(0b000),RFU=0(0b000),Confirmation Enable=1,Repetition Enable=1,组合起来是0b00000011,换算成16进制是0x03。
第二个结构体(索引1):Report Info Index=1(0b001),RFU=0(0b000),Confirmation Enable=0,Repetition Enable=0,组合起来是0b00100000,换算成16进制是0x20。
所以整个Hybrid Mode ISO Reports Enable字段的值是0x0320,总长度2字节,完全符合规范要求。
4.3 特征的行为规则与附录B模式切换时序联动
这个特征的行为规则,直接对应规范附录B里的模式切换时序,是整个HID ISO功能落地的核心。很多开发者模式切换失败,就是因为没有严格遵守规范里的行为顺序,导致设备和主机的状态不同步。
我结合附录B的模式切换时序,把这个特征的行为规则拆分成两个核心场景:
4.3.1 主机发起的模式切换行为
这是最常用的场景,规范里对主机和设备的行为顺序做了严格的定义,绝对不能颠倒顺序。
场景1:从默认模式切换到混合模式

-
主机向LE HID Operation Mode特征写入Opcode 0x01,携带完整的混合模式配置参数。
-
设备收到写请求后,先对所有参数进行全量校验,只要有一个参数不符合要求,就返回对应的错误码;所有参数都合法,就返回成功写响应。
-
主机收到成功响应后,开始配置CIG参数,发起CIS通道的创建流程,和设备完成CIS通道的链路层连接。
-
只有当CIS通道完全建立成功后,主机和设备才能同时切换到混合模式,启用的报告开始通过ISO通道传输,其他报告依然走GATT链路。
这里的核心铁律是:在CIS通道建立成功之前,主机和设备必须保持在默认模式,所有流量依然走GATT,绝对不能提前切换模式,否则会出现数据流中断,设备失控。
场景2:从混合模式切换回默认模式

-
主机向LE HID Operation Mode特征写入Opcode 0x02,Parameters字段为空。
-
主机写入完成后,立刻切换到默认模式,所有HID流量全部切回GATT链路,同时发起CIS通道的终止流程。
-
设备收到写请求后,立刻切换到默认模式,不需要等待CIS通道终止完成,所有流量切回GATT链路。
-
CIS通道终止完成后,整个切换流程结束。
这个顺序和切换混合模式完全相反,核心目的是保证数据流的无缝切换,不会出现真空期,用户完全感知不到模式的变化。
4.3.2 设备发起的模式切换请求行为

只有当Properties特征里的Device Mode Change Supported位设为1时,设备才能发起模式切换请求,行为规则如下:
-
设备通过Indication LE HID Operation Mode特征,向主机发送模式切换请求,内容格式和主机写的格式完全一致。比如设备请求切换混合模式,就Indication Opcode 0x01,携带自己期望的配置参数。
-
主机收到Indication后,不是必须执行,规范里只是推荐主机根据自身能力和场景,执行对应的主机发起模式切换流程。
-
设备不能自主切换模式,只能等待主机的写指令,只有主机写入对应的切换指令后,才能切换模式。

五、开发落地避坑指南:90%的问题都出在这里
结合我自己的开发经验和蓝牙认证测试的要求,整理了HID ISO Service开发中最常见的6个坑,帮大家提前避开:
-
服务实例数量错误:很多开发者为了适配多接口HID设备,创建了多个HID ISO Service实例,这是规范明确禁止的,主机发现多个实例后会直接忽略,导致功能失效。必须严格遵守单实例的要求。
-
特征属性配置错误:比如把HID ISO Properties特征设为可写,或者LE HID Operation Mode特征没设为可写,又或者支持主动模式切换但没加Indication属性和CCCD描述符,导致主机无法读写,设备无法发送请求。必须严格按照规范里的属性要求配置。
-
字段格式不符合规范:比如主机写的Report Interval字段里设了多个bit为1,或者Hybrid Mode ISO Reports Enable里的索引超出了Properties里的数组范围,又或者保留位没有设为0,导致参数校验失败,返回0x83错误码。必须严格按照位域定义配置,保留位必须清零。
-
报告ID和类型不匹配:Properties里的Hybrid Mode ISO Reports的Report ID和Report Type,和HID Service里的Report Map不一致,主机选中报告后,无法对应到实际的HID报告,导致ISO数据解析异常。必须保证两个服务里的报告定义完全一致。
-
错误码返回不规范:主机写参数错误时,没有返回规范里定义的3个应用错误码,而是返回了通用的ATT错误码,导致主机无法定位问题。必须严格按照触发场景返回对应的标准错误码。
-
安全权限配置错误:HID ISO Service的特征没有设置和HID Service一致的安全权限,主机在链路加密之前读写特征,导致访问失败,或者不符合蓝牙认证的安全要求。必须保证两个服务的安全级别完全一致。
六、检验
问题:HID ISO Service中,HID ISO Properties特征的核心作用是什么?其中Hybrid Mode ISO Reports字段的配置要求和注意事项有哪些?
答案:
HID ISO Properties特征的核心作用,是向主机完整披露设备的HID ISO相关能力,是主机进行ISO参数配置、模式切换的唯一依据,相当于设备的ISO能力官方说明书,连接期间必须保持静态,不可修改。
Hybrid Mode ISO Reports字段的配置要求和注意事项:
-
该字段是结构体数组,每个结构体固定2字节,数组长度最少1个、最多6个,对应设备可走ISO通道的报告列表;
-
每个结构体包含Report ID和Additional Info两个字段,Report ID必须和HID Service中Report Map定义的报告ID完全一致,Additional Info的Report Type位必须和实际报告类型匹配;
-
Additional Info的Bit1和Bit2分别声明报告是否支持确认机制和重复传输,保留位必须全部设为0;
-
主机后续只能从该数组中选择最多1个输入报告和1个输出报告启用ISO传输,不能选择数组外的报告。
问题:主机向LE HID Operation Mode特征写入切换混合模式的指令时,设备需要完成哪些参数校验?分别对应什么规范定义的错误码?
答案:
设备需要完成全量参数校验,具体校验项和对应错误码如下:
-
校验Opcode是否为规范定义的合法值,若为RFU保留值,返回0x81 Opcode outside range错误码;
-
校验设备当前是否已经处于混合模式,若已处于请求的状态,返回0x82 Device already in requested state错误码;
-
校验Report Interval字段是否仅设置了一个bit为1,且该bit在设备Supported Report Intervals中已声明支持,若不符合,返回0x83 Unsupported feature错误码;
-
校验配置的输入/输出SDU大小是否小于等于设备声明的Max SDU Size,若超出上限,返回0x83 Unsupported feature错误码;
-
校验Hybrid Mode ISO Reports Enable中的Report Info Index是否在设备声明的数组范围内,若超出范围,返回0x83 Unsupported feature错误码;
-
校验开启的确认/重复传输功能,是否在对应报告的Additional Info中已声明支持,若开启了不支持的功能,返回0x83 Unsupported feature错误码;
-
所有参数校验通过后,设备返回成功写响应,否则返回对应错误码。
问题:HID ISO Service的GATT子过程强制要求是什么?设备支持主动向主机发起模式切换请求的前提条件有哪些?
答案:
HID ISO Service的GATT子过程强制要求:
-
服务端必须强制支持Write Characteristic Value子过程,用于主机写入模式切换指令和配置参数;
-
Indications子过程为条件必选,当设备支持主动模式切换时,必须强制支持,否则为可选。
设备支持主动模式切换请求的前提条件:
-
HID ISO Properties特征的Features字段中,Device Mode Change Supported位必须设为1,向主机声明支持该功能;
-
LE HID Operation Mode特征必须配置Indications可选属性,同时添加对应的Client Characteristic Configuration Descriptor(CCCD)描述符,用于向主机发送指示;
-
设备只能通过Indication LE HID Operation Mode特征发起请求,不能自主切换模式,最终的模式切换控制权仍在主机手中。