本文章主要来自《圈圈教你玩USB》的学习笔记
USB事务
事务通常由两个或者三个包组成:令牌包、数据包和握手包。
> 令牌包用来启动一个事务,总是由主机发起
> 数据包传递数据,可以是主机到设备,也可以从设备到主机,方向由令牌包来指定
> 握手包的发送者通常为数据接收者,当数据正确接收后,发送握手包。设备也可以使用NAK握手包表示数据还未准备好。
USB协议规定了4中传输类型:
批量传输、等时传输、中断传输和控制传输。其中批量传输、等时传输、中断传输每一次传输都是一个事务;控制传输,数据过程则可能包含多个事务。
一次批量事务有三个阶段:令牌包阶段、数据包阶段和握手包阶段。批量传输分为批量读和批量写,批量读使用批量输入事务,批量写使用批量输出事务。
批量传输没有规定数据包中的数据含义和结构,具体的数据结构要由设备自己定义。批量传世通常用于数据量大、对数据的实时性要求不高的场合。
批量输出事务:
> 主机先发出一个OUT令牌包,里面包含了设备地址、端点号
> 再发送一个DATA包(具体什么类型的DATA包,要看数据切换位)
> 这时地址和端点匹配的设备就会收下这个数据包
> 主机切换到接收模式,等待设备返回握手包
> 设备解码令牌包、数据包都准确无误,并且有足够的缓冲区来保存数据后,就会使用ACK握手包或者NYET握手包来应答主机。
如果没有足够的空间来保存数据,那么返回一个NAK握手包,告诉主机没有缓存区可用,主机会在稍后的时间重试该批量传输事务。
如果设备检测到数据正确,但端点处于挂起状态,则返回一个STALL握手包。
如果设备检测到错误(如检验错误、位填充错误等),则不做任何响应,让主机等待超时
批量输入事务:
> 主机首先发出IN令牌包(IN令牌包包含设备地址和端点号)
> 主机切换到接收数据状态,等待设备返回数据
> 设备如果检测到错误,则不作任何响应,主机等待超时;
如果设备有数据返回,那么它把一个数据包放到总线上(DATA0/DATA1切换);
如果设备没有数据需要返回,则它直接使用NAK握手包来响应主机;
如果设备该端点处于挂起状态,则会返回一个STALL握手包;
> 如果主机检测到错误,则不做任何响应,设备会检测到超时。USB协议规定,不允许主机使用NAK握手包来拒绝接收数据包;
主机在接收到NAK握手包后,知道设备暂无数据返回,主机会在稍后的事件重试该输入事务;
USB2.0高速设备中增加了一个PING令牌包,用来探测设备是否有空间接收数据,它没有数据,只有握手阶段,设备根据实际情况返回握手包。因此PING事务只有令牌包和握手包。
中断传输是一种保证查询频率的传输。中断端点在端点描述符中要报告它的查询间隔,主机会保证在小于这个时间间隔的范围内安排一次传输。
中断传输通常数据量不大,但是时间要求严格的设备中;中断传输也可以不断检测某个状态,当条件满足后再使用批量传输来传送大量的数据。
除了在对端点查询的策略不一样外,中断传输和批量传输的结构基本是一样的,只是中断传输没有PING和NYET两种包。
等时传输可以用在数据量大,对实时性要求高的场合,例如音频设备、视频设备等。这类数据对数据延迟很敏感。等时传输不能保证数据100%正确。当数据错误时并不进行重传操作。
因此等时传输也就没有应答包。数据是否正确,可以由数据包的CRC校验来确认。至于出错的数据如何处理,由软件来决定。
等时传输使用等时事务来传输数据:
控制传输分为三个过程:第一个过程是
建立过程;第二个过程是可选的
数据过程;第三个过程是
状态过程;
建立过程使用一个建立事务,是一个输出数据的过程。建立过程使用SETUP令牌包;其次数数据包,SETUP只能使用DATA0包;最后是握手包,设备只能使用ACK来应答。
除非出错不应答,设备必须接收建立事务的数据。
数据过程是可选的,即一个控制传输可能没有数据过程。如果有,一个数据过程可以包含一笔或者多笔数据事务。控制传输所使用的数据事务和批量传输中的批量
事务是一样的。要注意的是所有的数据传输必须是同一个传输方向的。在控制读传输中,数据过程所有的数据事务必须是输入的;在控制写传输中,数据过程中所有的事务都必须是
输出的。一旦数据传输方向发生了改变就会认为到了状态过程。
数据过程第一个包是DATA1包,然后每次正确传输一个数据包后就在DATA0和DATA1之间交替。
状态过程也是一笔批量事务,它的传输方向刚好和前面的数据阶段相反。状态过程只使用DATA1包。
控制传输之所以弄的比较复杂,是因为它要保证数据传输过程中数据完整性。设备枚举过程中各种描述符的获取以及设置地址、设置配置等,都是通过控制传输来实现的。
1. 设置阶段包详解(设置阶段由1个设置事务组成,SETUP事务由SETUP令牌包、DATA0数据包、ACK握手包组成)

2. 可选的数据阶段包详解(数据阶段由0个或者多个IN/OUT事务组成)
2.1 如果第一阶段指定数据传输方向为设备到主机
如果第一阶段指定读(传输方向为设备到主机),则数据阶段会由连续的多个IN事务组成,事务和包协议结构如下图。

2.2 如果第一阶段数据传输方向为主机到设备(数据长度大于0)
如果第一阶段指定写(传输方向为主机到设备),则数据阶段会由连续的多个OUT事务组成,事务和包协议结构如下图。

2.3 如果第一阶段数据传输方向为主机到设备(数据长度为0)
如果第一阶段指定数据传输方向为主机到设备,并且长度为0,则无第二数据阶段。
3. 状态阶段包详解(状态阶段由1个OUT/IN事务组成)
3.1 如果第二阶段指定数据传输方向为设备到主机
如果第二阶段指定数据传输方向为设备到主机,则主机接收完毕数据后,主机请求一个OUT事务告诉设备数据的接收状态。

3.2 如果第二阶段指定数据传输方向为主机到设备(数据长度大于0)
如果第二阶段指定数据传输方向为主机到设备,则主机发送完毕数据后,主机请求一个IN事务请求设备数据接收状态。

3.3 如果第二阶段指定数据传输方向为主机到设备(数据长度为0)
如果第二阶段指定数据传输方向为主机到设备,请求传输数据长度为0,则主机发送完令牌包后,主机请求一个IN事务请求设备数据接收状态。

(由上可以看到,状态阶段DATA1数据包的数据长度为0)
来自https://www.cnblogs.com/linhaostudy/p/18512554
一个具体的端点,只能工作在一种传输模式下,通常,我们把在什么模式下的端点就叫什么端点。例如,控制端点、批量端点。
端点0是每个USB设备都必须具备的默认控制器端点,它一上电就存在并且可用。设备的各种描述符以及主机发送的一些命令,都是通过端点0传输的。其它端点是可选的。
非0端点只有在Set Config之后才能使用。
各个端点描述符中都规定了端点所支持的最大数据包长。主机每次发送数据包,都不能超过端点的最大包长。
> 对于控制传输的端点,低速模式最大包长固定为8字节,高速模式最大包长固定为64字节,而全速模式可在8,16,32,64字节中选择。
> 对于等时传输端点,全速模式最大包长上限为1023字节,高速模式最大包长上限为1024字节,低速模式不支持等时传输。
> 对于中断传输端点,低速模式最大包长上限为8字节,全速模式最大包长上限为64字节,高速模式最大包上限为1024字节。
> 对于批量传输的端点,高速模式固定为512字节,全速模式最大包长可在8,16,32,64字节中选择,低速模式不支持批量传输。