赞
踩
USB 的数据由 包(Packet)
组成 事务(Transaction)
,事务组成 传输(Transfer)
,不同传输类型每 帧(Frame)
占用带宽的特性不同。
我们可以看到,一个传输(Transfer)是可以拆分成事务(Transaction)的,并且一个事务(Transaction)又可以拆分为包(Packet)。
包由以下几部分组成:
同步字段(SYNC)
包标识符字段(PID)
设备地址和端点地址(ADDR)
帧号(Frame Number)
数据字段(DATA)
循环冗余校验字段(CRC)
结尾字段(EOP)
不同种类的 Packet 所含字段是上面字段的子集,并不会包含所有的字段。
USB 总线上的数据传输是以包(Packet)为基本单位的。一个包被分成不同的域(Filed,也称为字段)。根据不同类型的包,所包含的域是不一样的。但是不同的包有一个共同的特点。就是都要以同步域(SYNC)开始
,紧跟着一个包标识符PID(Packet Identifiter)
,最后以包结束符EOP(End Of Pactet)来结束这个包
。
所有数据包都以 同步(SYNC)字段
开始,该字段是生成最大边缘过渡密度的编码序列。
下图为USB1.1设备的同步域数据包。
Packet 的分类:
1. 令牌包 token
PID + ADDR(设备地址,端点地址) + CRC5;
2. 帧首包 SOF(Start of frame)
PID + 帧号 + CRC5;
3. 数据包 DATA
PID + 数据 + CRC16;
4. 握手包 Handshake
PID;
相应的 PID 域的分类
Token
SETUP, IN, OUT, SOF
Data
DATA0, DATA1, DATA2, MDATA
Handshake
ACK, NAK, STALL, NYET
Packet 的构成
举例:
举例:
数据包 DATA
PID + 数据 + CRC16;
握手包 Handshake
PID;
举例:数据包后面就跟随有握手包。
在 USB 上数据信息的一次接收或发送的处理过程称为事务处理,一个事务(Transaction)由若干个包(Packet)组成
,取决于具体的事务类型,可能由以下包组成:一个令牌包 token packet;可选的数据包 data packet;可选的握手包 handshake packet;可选的特殊包 special packet。
事务分为 3 类 :SETUP 事务,IN 事务和 OUT 事务
,如下所示
用于描述端点(Endpoint)或通道(Pipe)的特性,传输分为以下四类:
同步传输,每帧占用固定带宽;
中断传输,每帧都占用带宽,但所占带宽不固定;
控制传输和批量传输,在需要时才占用帧带宽,批量传输将会占用帧的所有剩余带宽。
除同步传输外,一个事务(Transaction)由一个令牌包,若干个数据包,一个握手包构成。
而同步传输没有握手包,所以接收端接收完同步传输数据包,计算出 CRC,即使发现数据有错,也不能发送握手包给发送端,让发送端重发。
一般而言一个 USB 中断完成一个事务(Transaction),令牌包和握手包的传输由硬件完成,数据包由应用程序完成。
控制传输用于主机枚举设备时从设备获取信息或配置信息。
控制传输由 建立阶段(SETUP),数据阶段(DATA),状态阶段(STATUS)
组成。其中数据阶段是可选的,数据阶段可以包含多个 IN 事务或 OUT 事务,且在一次控制传输中,只能包含 IN 事务或 OUT 事务,不能既包含 IN 事务也包含 OUT 事务。状态阶段包含 1 个事务,事务的方向一定跟数据阶段相反,如果数据阶段包含 IN 事务,那么状态阶段就会包含 OUT 事务,反之亦然。如果没有数据阶段,状态字段所包含的事务方向与建立阶段相反,即包含 IN 事务。
可以看到,控制传输(Transfer)包含的事务(Transaction)类型有:SETUP 事务,IN 事务和 OUT 事务
。
建立阶段(SETUP STAGE)
建立阶段由 1 个 SETUP 事务组成,而 SETUP 事务由 PID 为 SETUP 的 token 包,PID 为 DATA0 的 data 包,PID 为 ACK/NAK/STALL 的 handshake 包组成。控制传输的建立阶段的 data 包用于主机给设备发送 请求(Request),相当于发送命令给设备。
数据阶段(DATA STAGE)
数据阶段是用来传输建立阶段的 请求(Request) 所跟随的数据的,如果 1 个事务不能传输完所需数据,就会分多个事务传输
。 根据请求里的 bmRquestType 字段,数据阶段能获悉需要 IN 事务还是 OUT 事务,为了确保没有丢失 data 包,data 包的 PID 会不停地切换,即 DATA0,DATA1, DATA0…
状态阶段(STATUS STAGE)
状态阶段用来表示整个控制传输过程已经结束。状态阶段的 token 包的 PID 必定与数据阶段相反,即数据阶段是 IN token包,状态阶段就是 OUT token 包。
跟随其后的是数据域长度为 0 的 PID 为 DATA1 的数据包。最后是 handshake 包,根据响应情况分为以下三类:响应返回 ACK 包,未响应返回 NAK 包,不支持该请求返回 STALL 包。
举例:
有的控制传输中无数据,则在 SETUP 事务后面跟一个 IN 状态事务就可以。
用于传输突发的大量数据,要求数据不能出错,但对时间没有要求,适用于存储设备、打印机等。
批量传输是可靠的传输,需要握手包来表明传输的结果。若数据量比较大,将采用多次批量事务传输来完成全部数据的传输,传输过程中数据包的 PID 按照 DATA0-DATA1-DATA0-…的方式翻转,以保证发送端和接收端的同步。
它通过在硬件级执行 “错误检测”和“重传”
来确保 host 与 device 之间“准确无误”地传输数据,即可靠传输。
它由三种包组成(即 IN 事务或 OUT 事务):
对于 IN Transaction
ACK:表示 host 准确无误地接收到数据包
NAK:表示 device 暂时不能返回数据(如:设备忙)
STALL:表示 device 拒绝了请求
对于 OUT Transaction
ACK:表示 device 准确无误地接收到数据包
NAK:表示 device 暂时不能接收数据(如:设备忙)
STALL:表示 device 端点已经停止,且通知 host 不再重传
举例:
上面列出了一个批量写传输和批量的读传输。
和控制传输相比就简单很多了,只有数据传输,没有SETUP事务和状态事务。
在事务中,也分为三个阶段,即令牌阶段(令牌包)、数据传输阶段(数据包)、握手阶段(握手包)。
当然,上面这两个批量传输的数据很少分别是31和36个字节,一个传输就传完了。
下面这个全速设备,每次最多传输64字节,传输4096个字节,就需要很多个传输了。
中断传输每一帧(Frame)最多 传输 1 次事务
,而批量传输可以在总线空闲时在帧内传输多次事务,中断传输不支持 PING,优先级更高,最大包长与批量传输不同,其他的与批量传输相同。主机在排定中断传输任务时,会根据对应中断端点描述符中指定的查询间隔发起中断传输。中断传输有较高的优先级,仅次于同步传输。
中断传输是一种保证查询频率的传输。中断端点在端点描述符中要报告它的查询时间,主机会保证在小于这个时间间隔的范围内安排一次传输。
这里所说的中断,和我们硬件 CPU 上的中断是不一样的。他不是由设备主动的发出一个设备请求,而是由主机保证不大于某个时间间隔内安排一次传输。 中断传输通常用在数据量不大,但是对时间要求较严格的设备中,例如人机接口设备(HID)中的鼠标,键盘,轨迹球。中断传输也可以用来不停的检查某个状态,当条件满足后再用批量传输来传送大量的设备。除了对端点查询的策略上不一样之外,中断传输和批量传输的结构基本上是一样的
。只是中断传输中没有 PING 和 NYET 两种包。中断传输使用中断事务(Interrupt Transactions)。中断事务的流程图如下。
举例:下图给出了 USB 鼠标在按键中断事务中一次输入传输。可以看到格式和批量传输是一样的。
举例2:
上图给出了中断 IN 传输的数据过程。
在中断事务中,也分为三个阶段,即令牌阶段(令牌包)、数据传输阶段(数据包)(有则返回数据,没准备好则不返回数据)、握手阶段(握手包)(从机正常返回数据,主机解析成功,则主机给从机应答。从机没准备好数据,则从机给主机返回 NAK)。
可以看到主机对设备进行定期查询。
如果设备有数据,则对 IN 事务进行响应,返回数据,主机解析成功数据,返回 ACK 应答。
如果设备没数据,则返回 NAK 表示没准备好数据。
同步传输是不可靠传输,它没有握手包,也没有 PID 翻转,不支持重传。主机在安排事务传输时,同步传输具有最高优先级
。同步传输适用于固定速率抵达或指定时刻抵达的场合,可以容忍偶然错误的数据上。一般用于喇叭,麦克风,摄像头等实时性要求高的设备。它由令牌包和数据包组成,没有握手包。
同步传输用在数据量大、对实时性要求高的场合,例如音频设备、视屏设备等,这些设备对数据延时敏感。对音频或者视屏设备来说,对数据的100%正确要求不高,少量数据的错误还是能够容忍的,主要是要保证不能停顿;所以同步传输是不保证数据100%正确的。当数据错误时,并不能进行重传操作。因此同步传输也就没有应答包,并不进行重传操作。数据是否正确,可以由数据包的 CRC 校验来确认。至于出错的数据如何处理,由软件来决定。同步传输使用同步事务(Isochronous Transactions)来传输数据。下图是同步事务的流程图。
暂时没同步传输的抓包信息,就不分析了。只需要知道同步传输是没应答包的。其它和上面几种没大的差异。
请求是控制传输中,usb host 向 usb device 发送的用于配置属性,发送数据或者接收数据的命令。
请求通过控制传输的 SETUP 事务的 DATA0 包发送出去
。请求分为标准请求(Standard Request)和类特定请求(Class-Specified Request),USB 规范定义了 11 个标准请求,它们分别是:Clear_Feature、Get_Configuration、Get_Descriptor、Get_Interface、Get_Status、Set_Address、Set_Configuration、Set_Descriptor、Set_Interface、Set_Feature、Synch_Frame。所有 USB 设备都必须支持这些请求(个别请求除外,如Set_Descriptor、Synch_Frame)。
主机负责建立表 9-2 中列出的字段中传递的值。 每个 Setup 数据包都有 8 个字节。
如下图所示,是 SETUP DATA 包的数据格式,为 8 个字节。
D7:传输方向
D6…5:命令类型
D4…0:接受者类型
这个域表明此请求的特性。特别地,这个域表明了第二阶段控制传输方向。如果 wLength 域被设作 0 的话,表明没有数据传送阶段,那 Direction 位就会被忽略.
USB 说明定义了一系列所有设备必须支持的标准请求。这些请求见下面的表。另外,一个设备类可定义更多的请求。设备厂商也可定义设备支持的请求.
请求可被导引到设备,设备接口,或某一个设备端点(endpoint)上。这个请求域也指定了接收者。当指定的是接口或端结点(endpoint)时,wIndex 域指出哪个接口或端节点。
这个域标识特别的请求。bmRequestType 域的 Type 字段可修改此域的含义。协议中仅定义 Type 字段为 0 即标准设备请求时 bRequest 域值的含义。
此域用来传送当前请求的参数,随请求不同而变。
该字段的内容根据请求而有所不同。它用于将参数传递给设备,特定于请求。
当 bmRequestType 的 Recipient 字段为接口或端点时,wIndex 域用来表明是哪一个接口或端结。
图 9-2 显示了用于指定端点时的wIndex格式。
Direction 位(bit7)设置为零以指示具有指定端点编号的 OUT 端点,并指定一个以指示IN端点。 对于控制管道,请求应将Direction 位设置为零,但设备可以接受 Direction 位的任一值。
图 9-3 显示了用于指定接口时的 wIndex 格式.
这个域表明第二阶段的数据传输长度。传输方向由 bmRequstType 域的 Direction 位指出。wLength 域为0,则表明无数据传输。在输入请求下,设备返回的数据长度不应多于 wLength,但可以少于。在输出请求下,wLength 指出主机发出的确切数据量。如果主机发送多于 wLength 的数据,设备做出的响应是无定义的。
本节介绍为所有 USB 设备定义的标准设备请求。 表 9-3 概述了标准设备请求,而表 9-4 和表 9-5 分别给出了标准请求代码和描述符类型。
USB设备必须响应标准设备请求,即使设备尚未分配地址或尚未配置。
下面说明几种常见的设备请求
1. 清除特性(clear Feature)
该请求时用来取消一个特性,其格式如下:
该请求中的 wVlaue 表示特性选择器,它对应的值为:0 = 端点,1 = 设备。当某个特点不允许取消,或者特性根本不存在,或者是指向一个根本不存在的接口或端点时,该请求将会导致设备请求失败,如果一个端点被固件设置为停止状态,主机软件也可以发送一个值为 0 的 CLEAR_FEATURE 命令清除该端点的停止状态。
2.获得描述符(GetDescriptor)
该请求可以获得 USB 设备中存在的特定的描述符,其格式如下:
该请求中的 wValue 的高字节表示要取的设备描述符,低字节表示描述符的索引值,描述的类型见上面 9-5 表。
wIndex 的值为 0 或语言 ID;当要取的值为字符串描述符时,该域的值为语言 ID;当为其它的描述符时,该域为 0。
wLength 表示要返回的数据长度,如果 SETUP 阶段的地址使用的是预设地址 0,(ENDP 字段为 0),这时 wLength 值会大于实际的描述的值。这是为什么? 原因是用户预设的地址 0 来取得设备描述符时,不管多少个字节,用户最多只能取前 8 个字节,即在控制传输过程只有一次数据阶段。但是,如果用户新的地址(ENDP字段不为0)来取得设备描述符时。这时 wLength 的值就要注意了。
该请求给 USB 设备设置值地址,从而可以对该 USB 设备进行下一步的访问,其格式如下:
该请求与其他请求有一个重要的不同点,该请求下,USB 设备一直不改变它的地址,直到该请求的状态阶段被成功的完成,而其他请求的操作都是在状态阶段之前完成。
该请求对设备进行设备值。其格式如下:
该请求中的 wValue 域的低字节表示设置的值,该值必须为 0 或者与配置描述符中的配置值相匹配。如果设置值等于 0,表示设备在地址状态。如果 wIndex 或 wLength 为非 0 值,那么该请求不执行。
此请求返回指定接口的选定备用设置。
某些 USB 设备的配置具有互斥设置的接口。 此请求允许主机确定当前选择的备用设置。
如果 wValue 或 wLength 不是上面指定的,则不指定设备行为。如果指定的接口不存在,则设备将响应请求错误。
默认状态:未指定在设备处于“默认”状态时收到此请求时的设备行为。
地址状态:设备给出了请求错误响应。
已配置状态:当设备处于已配置状态时,这是一个有效请求
bmRequestType 字段的 Recipient 位指定所需的收件人。 返回的数据是指定收件人的当前状态。
如果 wValue 或 wLength 不是上面指定的,或者如果设备状态请求的 wIndex 不为零,则不指定设备的行为。
如果指定的接口或端点不存在,则设备将响应请求错误。
默认状态:未指定在设备处于“默认”状态时收到此请求时的设备行为。
地址状态:如果指定了端点0以外的接口或端点,则设备将响应请求错误。
已配置状态:如果指定了不存在的接口或端点,则设备将响应请求错误。
对设备的GetStatus()请求返回如图9-4所示的信息.
自供电字段指示设备当前是否为自供电。 如果D0复位为零,则器件由总线供电。 如果D0设置为1,则设备是自供电的。 SetFeature()或ClearFeature()请求不能更改Self Powered字段。
“远程唤醒”字段指示设备当前是否已启用以请求远程唤醒。 禁用支持远程唤醒的设备的默认模式。 如果D1复位为零,则禁用设备发出远程唤醒信号的能力。 如果D1设置为1,则启用设备发出远程唤醒信号的能力。 可以使用DEVICE_REMOTE_WAKEUP功能选择器通过SetFeature()和ClearFeature()请求修改远程唤醒字段。 器件复位时,该字段复位为零。
对接口的GetStatus()请求返回如图9-5所示的信息。
对端点的GetStatus()请求返回如图9-6所示的信息。
结合上面的格式我们分析一下下面的 SETUP 令牌事务的作用。
结合前面的学习,我们知道了,host 发给 device 的数据 SETUP 数据是 HEX: 80 06 00 01 00 00 40 00.
第一个字节 0x80 拆分可以得到,这是一个主机发给设备(bit0 ~ bit4)的一个标准(bit5 ~ bit6)的请求命令,请求的结果是要求设备给 Host 返回(bit7 == 1)。
第二个字节 0x06 查看表 9-4 可以得到这是一个 GET_DESCRIPTOR,即获取描述符的请求。
第三四字节传的是 0x0100 ,查看描述符表,得知高字节表示描述符类型,01表示设备,02表示配置;低字节表示索引。比如设备有多个配置,那需要读取不同配置的时候就通过低字节。或者一个配置下有多个接口,通过索引选择不同的接口。所以这里高字节的 1 代表设备,低字节在本设备没用到。
第五六字节为 0x0,这个参数如果为0,则不关心;如果为非零,则表示Langurage ID,每一位都有对应的意义。
第七八字节为 0x40,即代表返回的数据不应该多于 64 字节。
分析总结:该 SETUP 事务为主机获取从机的设备描述符。
接下来再看一个例子:
结合前面的学习,我们知道了,host 发给 device 的数据 SETUP 数据是 HEX: 00 05 03 00 00 00 00 00 。
第一个字节 0x0,这是一个主机发给设备(bit0 ~ bit4)的一个标准(bit5~bit6)的请求命令,请求的结果是主机和设备发送(bit7 == 0)信息。
第二个字节 0x05,从 table 9-4 可以看到,SET_ADDRESS,是主机给从机设置地址。
第三四个字节合起来是0x03,对照标准的设备请求表,可以知道,这是就是主机给设备分配的设备地址 3。
第五六字节合起来是 0x0,从标准的设备请求表可以看到,这里没任何作用,只是为了满足标准的 SETUP 令牌请求格式。
第七八字节同上。
分析总结:该请求为,主机给设备设置从机地址为 3。
接下来看最后一个例子:
结合前面的学习,我们知道了,host 发给 device 的数据 SETUP 数据是 HEX: 80 06 02 03 09 04 FF 00 。
第一个字节 0x80,这是一个主机发给设备(bit0 ~ bit4)的一个标准(bit5~bit6)的请求命令,请求的结果是设备给Host返回(bit7 == 1)信息。
第二个字节0x06,从 table 9-4 可以看到,Get_DESCRIPTOR,是主机获取从机描述符。
第三四个字节合起来是0x03 02,对照标准的设备请求表,可以知道,这是就是主机请求获取设备的字符串描述符,且为第二个索引。
第五六字节合起来是 0x04 09,对照标准的设备请求表,可以知道,这里是指定字符串描述符的语言ID。
第七八字节合起来是 0xFF,表示即代表返回的字符串长度不应该多于 255 个字节。
分析总结:该请求为主机获取设备的字符串描述符。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。