分享好友

×
取消 复制
返回小栈
LINUX下USB1.1设备学习小记(2)_协议
飘絮絮絮丶2020-06-03 11:13:17

USB协议:
先看USB接口

可以看出,在USB使用了4根线,分别为电源线,地线,信号线和差分信号线
差分信号线用于检测信号线的传输是否正确
下面我们只关注信号线
然后是USB的串口传输

在串口传输中,由于所有的信号共用一根数据线,所以不仅有先来后到的问题,而且在一个设备和另一个设备进行通信的时候,如果别的设备也进来插一脚,就会导致信号的出错,所以这个时候需要一个管理者,他说好,A设备和我通信,A设备才和管理者通信,通信完成后,管理者说现在到B设备和我通信,A设备你歇一歇,于是B设备才能和管理者通信
在USB协议中,这个管理者称为host,在一个usb组成的括扑中只能存在一个管理者,也就是一个host
任何传输都是由host发起的,设备不能说host你注意了,我要和你通信这样
所以host是一个十分霸道的管理者 = 3=
呢host又如何发起于其它设备的通信呢?
现在介绍一下通信规范
在USB的通信中,分为4个大类
1. 控制传输
控制传输用于对设备的控制访问
2.中断传输
中断传输用于按一定的时间间隔访问设备(例如鼠标 键盘等)
3.等时传输
等时传输用于高流量的无间隔访问设备(视频 音频等)
4.块传输
块传输用于对流量的,对时间要求不高的设备(U盘 移动硬盘等)
这4大类由4种事务组成
1. IN事务
IN事务为host输入服务,当host需要从设备获得数据的时候,就需要in事务
2. OUT事务
OUT事务为host输出服务,host需要输出数据到设备的时候,就需要out事务
3. SETUP事务
SETUP事务为host控制服务,当host希望传输一些USB规范的默认操作的时候
就需要使用setup事务
4. SOF事务
这个规范上是写用于帧同步,但我没接触过SOF事务,所以也说不明白实际用途 Orz
然后这4个事务又由3种包构成
1. 令牌包
令牌包用于指明一次事务的类型
2. 数据包
数据包用于事务中数据的传输
3. 应答包
应答包用于事务传输完成的握手
令牌包由4种包组成
1. in包
in包用于指明当前的事务为in类型
2. out包
out包指明当前事务为out类型
3. setup包
setup包指明当前事务为setup类型
4. sof包
sof包指明当前事务为sof类型
数据包由2种包组成,在usb的数据传输中,每个事务的数据包的类型需要反转data0,data1,data0,data1......这样的顺序发送下去,以确保数据的完整性
1. data0包
该数据包的类型为0
2. data1包
该数据包的类型为1
应答包由3种握手包组成
1. ack包
ack握手包指明当前事务的数据包传输是成功的
2. nak包
nak握手包指明当前设备忙,不能处理数据包,请主机稍后再次发送
3. stall包
stall握手包指明当前设备不能接收或者传输数据,表示一个严重的错误


介绍一下事务的组成,除了SOF事务,其它事务都由3个包组成,令牌包,数据包和握手包(这里不介绍SOF事务,因为我用不上 = 3=)
黄色的包为主机发送,蓝色的包为设备发送
setup事务的组成如下:

主机先发送一个setup令牌包,再发送一个数据包(0),也就是data0,设备接收无误,则返回给主机一个ack握手包,表示数据传输成功
在setup事务的数据包中封装了一个8字节长度的数据,在LINUX中称为usb_ctrlrequest
该结构如下
struct usb_ctrlrequest {
__u8 bRequestType; //辅助请求类型
__u8 bRequest; //请求类型
__le16 wValue; //请求的辅助数值
__le16 wIndex; //请求的辅助数值,通常用于计算索引或者偏移
__le16 wLength; //如果控制传输有数据阶段,在这里定义数据的大小
} __attribute__ ((packed));
具体字段的值在主机控制器驱动中描述
这个数据包还有个特别的地方,就是他一定是data0类型的数据包
in事务的组成如下:

主机发送一个in令牌包给设备,告诉设备,给我传输数据,设备收到这个圣旨之后,马上填充一个数据包并传输到主机,主机收到这个数据包之后会发送一个握手包说明收到了
在in事务中数据包有data0和data1两种,具体由传输队列决定

out事务的组成如下

主机发送一个out令牌包之后,再发送一个数据包给设备,设备回应一个握手包表示我收到了
同样,在out事务中数据包也有data0和data1两种,具体由传输队列决定

在这里看出,所有的令牌包都是由主机发送的,符合我们之前所说的” 任何传输都是由host发起的”

现在看看传输类型
由于在这次试验中的目标是鼠标的模拟,只会接触到控制传输和中断传输,所以我只谈这两种传输,并且先说一下控制传输,中断传输等到主机发起控制传输的时候再解析
控制传输的组成如下


在控制传输中有3个阶段,分别是setup阶段,数据阶段和状态阶段
setup阶段指明了一次主机的请求类型
数据阶段为请求类型所需要传输的数据
最后的状态阶段用于表示一次控制传输的结束
setup阶段是由一个setup事务组成的,setup事务之前已经介绍过了

数据阶段是由1个或者多个连续的in事务或者out事务组成,在这些事务中,数据包的类型由data1开始,不断反转其类型组成一个data1,data0,data1,data0.....的队列
在控制事务中,数据阶段不是必须的,是否有数据阶段是由setup事务中的请求类型决定的

状态阶段是由一个in事务或者out事务组成的,有数据阶段的话,状态阶段的事务类型和数据阶段的事务相反,例如数据阶段为in事务则状态阶段的事务为out事务,如果没有数据阶段,则和setup包中bRequestType中的传输方向字段相反
并且状态字段中事务的数据包类型一定为data1

现在看USB软件模型中最基本的传输单位 – 包
包是由字段组成的
字段有7种,不同的包由不同的字段组成,现在先看看有哪7种字段
1. 同步字段
在USB1.1协议中同步字段为8位,用于包的数据同步,表明一个包的开始,这8位固定为1000 0000
2. PID字段
包ID字段为8位,前4位标识这个包的类别,后4位为效验,前4位的类别为
令牌包
0001:OUT包 1001:in包 0101:sof包 1101:setup包
握手包
0010:ack包 1010:nak包 1110:stall包
数据包
0011:data0包 1011:data1包
在2.0协议中规范了更多的包,我这里就不介绍了
3. 地址字段
地址字段用于标识usb设备的绝对位置,在一个usb主机的括扑中可以有128个设备,排除主机的0号地址位外,可以接127个设备,在usb的通信中,一个设备只有一个地址号,为什么是128个设备呢?因为这个地址字段只有7位......
4. 端点字段
端点字段为4位,用于标识传输类型,0号端点默认用于控制传输,在低速设备中只使用3个端点,而高速和全速设备则可以使用全部的16个端点
5. 帧号字段
帧号字段为11位,用于sof事务中的帧号表达
6. 数据字段
数据字段的最大长度由端点决定,对于低速,全速和高速设备有不同的定义
7. CRC字段
用于效验数据的正确性,检测数据传输是否有误,在令牌包中为5位,在数据包中为16位

令牌包,数据包和握手包的字段组成
setup包,in包和out包这3个令牌包的组成都一样

数据包的组成

握手包的组成


这里软件上的基本协议就介绍完了~ 详细部分在之后的详细中再慢慢介绍


文章来源CU社区:LINUX下USB1.1设备学习小记(2)_协议

0
0
戳我,来吐槽~