57.2
每个iAP2连接都始于通过受支持的传输方式在附件和设备之间建立连接。该链接协议提供了一种与传输无关的机制,用于可靠和有序地交付属于一个或多个iAP2会话的数据包化数据。该协议还可在每个连接的基础上进行配置,并可以在任何特定的传输和附件使用配置文件上被优化为最佳性能。某些协议特性有助于实现这些目标:
积极确认已收到的数据包。
重传输只需要重发送序列中未确认的数据包。
对iAP2会话的明确和有效的支持。
通过以下传输方式支持IAP2:
●蓝牙(第488页)。
●UART(第469页)。
●USB设备模式(第477页)。
●USB主机模式(第474页)。
●苹果闪电音频(第468页)。
支持一个或多个传输的所有设备都可用于与附件建立iAP2连接。有些运输比其他更适合各种特性,因此在附件设计过程的早期,运输选择应该高度优先考虑。
57.2.1数据包结构
每个链路包应该以一个固定大小的9字节报头开始,包括校验和,然后是一个可选的可变长度的数据负载。报头和有效负载都有它们自己的校验和。如果没有有效载荷数据,则没有有效载荷校验和。在iAP2链接包结构示例(第438页)。
表57-1 iAP2链路包结构
开始包MSB(0xFF)
开始包LSB(0x5A)
包长度MSB
包长度LSB
控制字节包
序列号包确认号
会话标识
符头校验和。
有效载荷数据。
。
有效载荷校验和
57.2.1.1数据包的开始
每个iAP2链路包的前两个字节总是FF 5A。如果在传输流中检测到这些字节,则附件和设备都应尝试将以下字节解析为一个有效的数据包。
57.2.1.2数据包长度
接下来的两个字节以字节表示包长度,总是表示为无符号的16位大整数整数。没有有效载荷数据的链接数据包的数据包长度始终为9字节(从数据包的开始到报头校验和)。否则,数据包长度将从数据包的开始测量到有效载荷数据的最后一个字节。例如,一个具有1字节有效载荷数据的链路包具有11字节的包长度。数据包的最大有效负载数据大小为65525字节;具有这种有效负载的数据包的数据包长度为65535字节。
57.2.1.3控制字节
控制字节中的位表示数据包中存在的内容
●SYN、EAK和RST位元是互斥的。
●ACK位可以与SYN位组合。
●EAK位总是与ACK位一起设置的。
●RST位永远不会与任何其他位一起设置。
●SLP位永远不会与任何其他位一起设置。
●所有未分配的位都应设置为0。
当设置了任何SYN、EAK或RST位时,就不能出现iAP2会话有效负载。相反,具有iAP2会话有效负载的链接数据包总是设置了ACK位。
表57-2 iAP2链路控制字节位
7 SYN 存在链接同步有效负载
6 ACK 数据包确认号有效,并且可能存在iAP2会话有效负载
5 EAK 存在扩展确认有效载荷
4 RST 链接重置
3 SLP 设备睡眠
在本规范的其余部分中,链路包可以用其控制字节位和有效负载来描述。例如,SYN包指在控制字节中设置SYN位的链路包,而SYN+ACK包指在控制字节中设置SYN和ACK位的链路包。
57.2.1.4数据包序列号
每个链路包包含一个包序列号,在所有正在传输中的所有其他包中唯一标识该包。当第一次创建链路时,设备和附件应在发送第一个SYN/SYN+ACK包之前随机选择一个初始序列号。每次发送带有iAP2会话或链路同步有效负载数据的数据包时,序列号将增加1。否则,当发送数据包时,序列号不会增加。先前发送的数据包的再传应保留相同的数据包序号。序号在达到255时被包装回0。
57.2.1.5数据包确认号
只有在设置了控制字节中的ACK位时,数据包确认号才有意义。如果未设置ACK,则发送方应将数据包确认号设置为0,而接收方应忽略它。
如果设置了ACK,则数据包确认号向发送方指示接收到的最后一个顺序内数据包的数据包序列号。例如,如果附件接收到包序号1、2、3和5,则附件的下一个输出包的包确认号将是3,因为5已超出顺序。
57.2.1.6会话标识符
只有在控制字节中的ACK位并且存在iAP2会话有效负载时,会话标识符才有意义。如果满足这两个条件,则会话标识符将是一个非零号,用来指定iAP2连接中的特定会话。否则,会话标识符应设置为0
57.2.1.7标题校验和
报头校验和是通过相加以下所有的数据包字节来计算的。如果报头校验和中的值与根据校验和计算(第421页)计算的值不匹配,接收方应从下一个检测到的包序列开始重新启动包解析。
●包开始MSB
●包开始LSB
●包长度MSB
●包长度LSB
●控制字节
●包序列号
●包确认号
●会话标识符
57.2.1.8有效载荷数据
本节是可选的,其存在应与控制字节中各位的状态相匹配。最大可能的有效载荷大小是65,525字节。
57.2.1.9有效载荷校验和
当且仅当有效负载数据存在时,有效负载校验和字节才存在。如果存在有效载荷数据,则对有效载荷数据的所有字节进行校验和。如果有效载荷校验和中的值与根据校验和计算(第421页)计算的值不匹配,接收方应从下一个检测到的包序列开始重新启动包解析。
57.2.1.10校验和计算
为发送的每个数据包计算iAP2使用的校验和字节。目的是将所有被校验和的(无符号8位)字节和校验和(无符号8位)字节的和,忽略任何无符号8位溢出,等于0x00。这允许快速验证数据包是否正确传输。校验和字节是通过取被校验和的(无符号8位)字节之和的最小有效字节,并取8位值的两个的补值来计算的。示例代码包括如下:
uint8_t
checksum_calculation(uint8_t buffer, uint16_t start, uint16_t length)
{
uint16_t i;
uint8_t sum = 0;
for (i = start; i < (start + length); i++) {
sum += buffer[i];
}
return (uint8_t)(0x100 - sum); / 2’s complement */
}
57.2.2链路同步有效负载
链路同步有效载荷(LSP)用于在设备和附件之间建立链路并同步数据包序列号。它还包含了可协商的链接参数。请参见iAP2链路同步有效负载示例(第438页)。
表57-3链接同步有效负载(版本1)
链接版本(0x01)
最大未完成包数
最大接收包长度MSB
最大接收包长度LSB
重传超时MSB
重传超时LSB
累计确认超时MSB
累计确认超时LSB
最大重传最大累计确认
会话1:会话标识符
会话1:会话类型
会话1:会话版本
…
会话N:会话标识符
会话N:会话类型
会话N:会话版本
57.2.2.1链接版本
●正在建立的链接的版本。所有数据包有效负载可能会根据链接版本而有所不同。
●此时链接版本的唯一有效值是1。
●这是一个可协商的参数。
●附件和设备均应安装
57.2.2.2最大未数据包数
●未接收确认而发送的最大数据包数。
●有效值为1到127。
●这不是一个可协商的参数。
●附件和设备可能会提出和使用不同的值。
●未等待设备的确认,附件不得发送超过设备建议的最大未完成数据包数量,反之亦然。
57.2.2.3最大接收数据包长度
●以字节为单位的最大可能的数据包长度。
●有效值为24到65535。
●这不是一个可协商的参数。
●附件和设备可能会提出和使用不同的值
57.2.2.4重传超时
●未确认数据包的重传输以毫秒为单位的超时值。这应该设置为近似于链路传输的包传输时间的值。
●有效值为20 ms到65535 ms.
●这是一个可协商的参数。
●附件和设备应商定相同的值。
57.2.2.5累积确认超时
●以毫秒为单位的超时值,如果没有发送另一个包,则应立即发送确认包。
●有效值为10 ms到一半的重传超时时间。
●这是一个可协商的参数。
●附件和设备应商定相同的值。
57.2.2.6最大重传次数
●在认为链路中断之前尝试的分组重传输的最大次数。
●有效值为1到30。
●这是一个可协商的参数。
●附件和设备应商定相同的值。
57.2.2.7最大累计确认数
●在确认前累积的最大接收序列数。请参见确认书(第429页)和流量控制书(第430页)。●有效值为0到127或最大未包数,以较小者为准。
●这是一个可协商的参数。
●附件和设备应商定相同的值。
57.2.2.8零焦/零重传链路配置
从iOS 8.3开始,配件可以选择尝试和协商一个ZeroACK/零重传链路配置,而不期望重传数据包或数据包确认。只有当底层运输有自己的可靠交付机制,并且附件充分利用了这些机制时,才建议这样做。通过USB主机模式(第474页)、USB设备模式(第477页)或蓝牙RFCOMM传输进行的iAP2连接是可能的候选对象。
设备仍然会使用数据包序列号检测丢失的链路数据包,并重置iAP2链路。如果在典型使用过程中经常出现丢包,附件不得使用此链路配置,并准备在不失去状态或影响用户功能的重置的情况下重新建立链路
●当设备检测到一个被丢弃的数据包时,一个RST将被发送到附件,链接层协商将与来自附件的SYN数据包重新启动。
●当附件使用包序列号检测到丢包时,附件应发送SYN包重新启动链路协商
要协商零确认/零重发链路配置,应将以下可协商的链路参数设置为0:
●重传超时
●累计确认超时
●最大重传次数
●最大累计确认次数
一些设备和/或iOS版本可能会拒绝协商ZeroACK/Zero重传链路配置的尝试。如果附件声称与这些设备/iOS版本兼容,则应保留与确认和再传输协商链接的能力。附件应发送一个SYN数据包,而不是SYN+ACK,与更新的参数继续协商
附件应通过管理其iAP2会话流量来解释链路层缺乏流量控制。例如,在启动文件传输之前,应该暂停发送停止媒体库更新消息,反之亦然,并在适当时恢复其他活动。同样的警告也适用于外部附件协议消息。
57.2.2.9 iAP2会话
●附件将用于与设备通信的iAP2会话。
●会话标识符对每个定义的会话都是唯一的。0不是一个有效的会话标识符。
●会话类型(440页)和版本(440页)应有效。
●这是一个可协商的参数。
●附件和设备应商定相同的值。
57.2.3 iAP2会话有效负载
iAP2会话有效负载是在iAP2会话中指定的(第439页)。当存在iAP2会话有效负载时,应设置控制字节中的ACK位。
57.2.4扩展确认有效载荷
扩展确认有效负载用于确认超出顺序接收到的数据包。该有效负载具有以下属性:
●应同时设置控制字节中的EAK位和ACK位。
●数据包确认号包含按顺序接收到的最后一个数据包的序列号。
●有效载荷数据部分包含意外收到的一个或多个数据包的序列号。它们并不是对这些数据包的确认。确认将在稍后的数据包中单独发送,并在ACK字段中带有相应的号码。
表57-4 EAK数据包有效载荷(链接v1)
序列确认号
…
序列确认号
57.2.5重置
控制字节中的RST位被设备用于重置连接。这样的链路包没有有效负载,只能由设备发送
57.2.6睡眠
本节仅适用于集成了以下闪电连接器的附件:
●闪电(C78-USBH)
●闪电(C79-USBH)
●闪电(C79-UART)
●闪电(C79-LA)
●闪电(C78频闪–USBH)
●闪电(C78频闪-UART)
●闪电(C78频闪-LA)
控制字节中的SLP位在设备在进入SLP状态时发出信号。这样的链路包没有有效负载,只能由设备发送。
一旦该设备进入休眠状态,该设备将停止提供附件电源。如果设备退出休眠状态,它将再次开始提供附件电源。
如果附件能够暂停和恢复链路层,附件应在附件电源返回后等待500 ms后再重新初始化链路。在此期间,附件可以从设备接收ACK,其信号是链路层恢复,并用于同步序号(最后从设备发送的最后号码)和ACK号码(设备接收的最后号码)。
如果附件不能暂停和恢复链路层,则附件电源返回后等待80 ms后重新初始化链路。
57.2.7操作
所有的链接实现都应将以下变量存储在一个特定于链接的记录中。这些变量将在描述iAP2 Link操作的后续章节中引用。
表57-5 iAP2链路操作记录变量
SentACKTimer 一个计时器,跟踪自最后一个ACK包发送以来经过的时间(ms)
NextSentPSN 下一个要发送的数据包的数据包序号
OldestSentUnacknowledgedPSN 最早的未确认数据包的数据包序号
InitialSentPSN 用于发送的第一个包的包序号
LastReceivedInSequencePSN 正确且按顺序接收到的最后一个包的包序号
InitialReceivedPSN 接收到的第一个包的包序号
ReceivedOutOfSequencePSNs[n] 接收和确认的超出序列的数据包序列号数组
57.2.7.2初始化
一旦建立了传输连接,附件应通过以1Hz(每秒一次)发送以下字节序列来确认是否存在支持iAP2的设备,直到从该设备收到响应: FF 55 02 00 EE 10。
如果设备支持iAP2,则附件将返回到相同的字节序列。
如果设备仅支持iAP1,则附件将接收到以下信息之一:
●55 04 00 02 04 EE 08
●55 02 00 00 FE
●FF 55 04 00 02 04 EE 08
●FF 55 02 00 00 FE
如果附件接收到其中一个响应,它应发送以下字节序列到设备,以表明缺乏兼容性:FF55 0E00 13 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEB。
附件应将设备的任何其他响应视为最终响应;不得重试或重传。
57.2.7.3同步
该链路的一个显著特性是支持在任何类型的传输方式上自动协商传输参数。这允许链接根据设备和附件的功能进行扩展。链接初始化主要有3个主要目标:
●确定设备和附件的相互可接受的链路配置参数。
●搜索配置参数中的错误。
●如果无法达成协议,则终止该链接。
当建立了底层传输连接和设备兼容性时,将启动一个链路。当出现这种情况发生时,附件首先发送包含链路同步负载中所需连接参数的SYN包,以及随机生成的包序列号。该设备将通过一个SYN+ACK包进行响应,确认接收到附件的SYN包、它自己想要的连接参数和它随机生成的包序列号。
如果设备和附件的所有可转让连接参数的建议值相同,附件应从设备发送最新SYN+ACK的最终ACK包,并认为连接已建立。否则,SYN+ACK数据包将继续交换多达10次,直到与所有可协商的连接参数达成一致为止。如果10次交换没有同意可协商的连接参数,设备将停止响应附件发送的任何进一步数据包
有时,一个设备将无法立即响应收到来自附件的SYN数据包。附件可以用相同的有效载荷数据和相同的包序列号重新发送SYN包。附件可以继续每秒钟一次这样做,直到设备发送一个SYN+ACK响应,确认之前发送的数据包序列号。一旦收到设备响应,附件应忽略任何后续输入的具有相同数据包序列号的SYN+ACK数据包。
如果附件的最终链路同步有效负载包含一个无效的不可协商的参数,则该设备将发送一个RST数据包来重置链路。
在同步过程中,在同步完成之前,假设有以下默认链路配置参数:
表57-6同步过程中的默认链路参数
下表包含了针对某些iAP2传输的推荐链路配置参数。这些值只是开发的起点,在没有验证对特定配件的适用性之前不得使用。
表57-9蓝牙传输的推荐链路参数
57.2.7.4确认
为了保证数据包的传递,链路协议同时使用了数据包的正确认和重传。当每个具有有效载荷数据和SYN包的包被接收方正确接收和接受时,它们都会被确认。ACK数据包不被确认。损坏的数据包将被丢弃,并且不被确认。当数据包没有在重传超时所指定的时间内被接收方确认时,发送方将对其进行重传。
有两种类型的数据包确认。累积确认用于确认接收到在指定包序列号为止的所有顺序包。扩展的确认允许接收方不按顺序确认数据包。所使用的确认类型只是数据包到达顺序的一个函数。只要有可能,链路实现应使用累积确认,并且仅在收到数据包异常时使用扩展确认。
一旦接收到一个或多个无序数据包,接收器应生成并发送扩展确认。
如果相应的ACK在传输过程中丢失,则可以多次接收到相同的有效负载数据。当发生这种情况时,接收器应重新发送有效载荷数据的ACK
57.2.7.5 重发
数据包可能在传输过程中丢失,因为在底层传输中丢失或损坏。它们也可以被接收器丢弃。包的积极确认要求接收方只在正确接收和接收包时确认包。
为了检测丢失的数据包,发送方应对每个输出数据包使用重传计时器。此计时器被设置为协商的重传超时值。当收到数据包的确认时,取消该包的计时器。如果计时器在收到确认之前过期,则数据包将被重新传输,计时器将被重新启动,直到在链路同步期间协商的最大重传输数。
57.2.7.6流量控制
iAP2链路采用基于发送的未确认数据包数和最大未完成数据包数链路配置参数的流控制机制。此参数在创建链路时由每一方指定,并应根据双方愿意分配给该链路的缓冲区的数量和大小来设置。设置后,参数在连接时保持不变。
该链接采用可接受的序列号窗口的概念。窗口的左边是最后一个已确认的数据包序列号加上1。窗口的右边等于最后一个序列中确认的包序列号加上未完成的最大包数。链路发送方发送数据包,直到达到接收方的最大未完成数据包数为止。一旦达到限制,发送方只能为每个确认的包发送一个新的包。
当接收到的包在窗口内有一个包序列号时,它将被确认。如果包序列编号等于左边(即,它是下一个预期的包序列编号),则以累积确认(ACK)确认该包,并且接受窗口的左右边增加1。如果接收到的数据包的数据包序列号在窗口内但在顺序之外,则通过扩展确认(EAK)进行确认。不调整该窗口,并记录对无序数据包的接收情况。窗口外收到的带有包序列号的链路包应丢弃,表示链路不稳定,可能需要重置。
当发送方收到扩展确认(EAK)时,发送方不得超出接收窗口。如果没有确认一个包,但接收并确认所有后续包,则可能发生这种情况。此要求将窗口的左边缘固定在未确认包的序列号。当发送额外的数据包时,下一个包序列号将接近并最终超过右边缘。此时,在确认未确认的包之前,可能不会发送更多的包。
57.2.7.7重置
该设备可以随时向该附件发送一个RST数据包。在收到一个RST包后,附件应在接收到该RST包后的1秒内向该设备发送一个SYN包,然后继续进行同步(第427页)。
如果附件希望重置链路,则应终止底层传输连接并重新连接。当UART传输在没有物理上断开和重新连接附件时,这是不可能的。必须重新启动链路是链路参数不佳的标志,在典型操作中不应该发生。
57.2.8示例
设备正忙时的57.2.8.2连接初始化
57.2.8.3连接需要多次协商尝试
当附件和设备对iAP2 Link参数不达成一致时,可能会发生多次协商尝试。
与协商失败时进行的57.2.8.4连接
57.2.8.5正常连接流量
在初始化/设置与附件的连接后,正常运行时流量由包含需要数据的常规ACK数据包组成。在任何时候,RST包都可以由设备发送到附件。附件应重置连接,并通过发送SYN数据包重新启动连接序列
57.2.8.7累积Ack超时已过期
在本例中,将最大累计确认链接参数设置为2。该设备已经发送了一个数据包,但此时不需要发送另一个数据包。在累积确认超时过期后,附件假设不需要等待第二个数据包并发送一个ACK包。
57.2.8.8与ack一起的连续数据传输
ACK数据包和带有ACK的数据数据包用于确认接收到先前发送的数据包并发送数据。在本例中,最大累积确认参数设置为4,设备在任何给定时间都不超过4包。
如果该附件有额外的数据包要发送,则该附件不需要等待累积确认超时过期。
57.2.8.9使用EAK重新发送丢失的数据包
EAK数据包用于指示丢失的数据包。接收方收到包EAK后,接收方应重新发送丢失的包。包传输接收方应等待所有达到最大累积确认参数的机上包的确认,或等待累积确认超时过期,然后发送EAK。
57.2.8.11 iAP2链接数据包结构示例
包长度MSB和包长度LSB是指包的大小(0x001A)。控制字节标识正在发送的有效负载的类型(0x80),SYN数据包。在这种情况下,是随机选择的数据包序列号(0x2B)。数据包确认号和会话标识符在此上下文中没有任何意义。报头校验和计算为0xE2。有效负载数据和有效负载校验和在iAP2链路同步有效负载示例(第438页)中有详细描述。
有关更多详细信息,请参见数据包结构(第418页)。
表57-11 iAP2链路数据包结构示例-附件SYN数据包
57.2.8.12 iAP2链路同步有效负载示例
有关详情,请参见链接同步有效负载(第421页)。
表57-12链路同步有效负载示例
57.3 iAP2会话
一旦建立了iAP2链路,附件和设备之间的高级通信就被构造成一个或多个会话。至少,所有附件应建立一个控制会议,以进行认证和识别。一旦完成了初始认证和识别,附件可能会使用额外的会话。
每个会话都有一个会话标识符、会话类型和会话版本。会话标识符用于唯一地标识iAP2连接中的会话。会话标识符0保留以供链接使用,附件使用的所有会话都应具有唯一的非零标识符。会话类型和会话版本的组合决定了会话中所有数据流量使用的会话协议变量。会话标识符是每个iAP2链路数据包报头的一部分
57.3.1属性
57.3.1.1类型
表57-13 iAP2会话类型
所有的链路实现都应该有一个控制会话。根据所实现的特性,所有其他会话都是可选的。不允许使用相同类型的多个会话
57.3.1.2版本
会话版本用于区分特定会话协议的不同变体。这些差异的确切性质取决于会话类型。有关更多细节,请参见规范中关于每个会话类型的部分。
57.3.2控制会话
控制会话有两个主要目标:
●通知设备和附件在其他设备的状态和/或配置中发生的变化。
●为附件提供请求更改设备状态和/或配置的方法。
控制会话协议是一个无状态协议。每个消息都是一个独立的实体,与任何先前的消息都没有关系。该设备不保留关于每个附件的任何信息或状态。附件应采取同样的行为。具体地说,对于更改设备状态和/或配置的附件请求应被视为请求,而不是命令。设备可能选择也可能不选择响应请求,并且将发送更新消息以确认状态/配置的更改,或者根本不发送任何消息
支持控制会话版本1的附件应在发送任何其他消息之前完成附件身份验证(第248页)
支持控制会话版本2的附件可以在验证完成之前发送附件标识(第253页)消息,但应该在发送任何其他消息之前完成验证。如果设备不支持控制会话2或不支持这些设备,则它们应退回到控制会话1。
USB主机模式(第474页)附件不应使用控制会话版本2。附件应为其指定的目的使用控制会话消息。依赖于未指定的行为可能会导致与未来的设备和/或iOS版本不兼容。附件应依靠iAP2链路层来保证消息的传递。附件不应该在控制会话层重新发送消息。
57.3.2.1消息结构
每个消息都有一个头,后面跟0或多个参数或参数组:
图57-1控制会话消息结构