1. Linux USB驱动软件框架
应用程序有两种访问硬件的途径:通过设备驱动程序来访问和跳过设备驱动程序(直接使用host驱动程序)来访问。
当直接使用Host驱动程序时,可以调用libusb库中已经封装好的函数接口。
2. USB电气信号
一个USB设备,可能兼容低速、全速,也可能兼容全速、高速。但不会同时兼容低速、高速。
USB2.0设备由4根线组成,其中包括Vcc, GND, D+, D-。用于传输传输数据的只有两根线D+和D-。两根线的通过高低电平,可以组合成4种状态(00, 01, 10, 11)。根据USB2.0协议,对于低速和全速设备(高速设备类似)主要有四种状态,差分1,差分0,单端1,单端0。后面都是以这四种状态,根据需要产生的别名。
USB主机是如何检测到设备的插入?
USB集线器的每个下游端口的D+和D-上,分别接了一个15KΩ的下拉电阻到地,在端口悬空时,就被这两个下拉电阻拉到了低电平。而在USB设备端,在D+和D-端接了1.5K欧姆的上拉电阻。对于全速和高速设备,上拉电阻接在D+上,对于低速设备,上拉电阻接在D-上。当设备插入到集线器时,由1.5K的上拉电阻和15K的下拉电阻分压,就将差分数据线中的一条拉高了。集线器检测到这个状态后,就报告给USB主控制器(或者通过他上一层的集线器报告给USB主控制器),这样就检测到设备的插入了。USB告诉设备首先被识别为USB全速设备,然后通过HOST和DEVICE两者之间的确认,再切换到高速模式。
当USB设备插入时,USB主机控制器的D+或D-被拉高,在主机控制器端会产生一个中断发现一个新设备并通过端点0给新设备分配一个地址和获取USB设备的设备描述符,解析设备描述符并通过device_add()将其添加到usb_bus_type链表中,并且匹配链表上的driver程序,匹配成功后调用driver的probe函数,这部分过程类似Platform平台总线驱动。
对于低速设备,在连接期间D-管脚一直是高电平,当hub检测到D-被拉低,说明设备已经断开连接。
对于全速设备,在连接期间D+管脚一直是高电平,当hub检测到D+被拉低,说明设备已经断开连接。
对于高速设备,设备刚刚插入时,是通过将D+拉高来识别的,D+被拉高可认为是全速设备或者是高速设备,那么如何判断是否是高速设备呢?(速率识别)
Hub给Device发出复位信号,如果Device支持高速模式,就会回复一个K信号,Hub收到K信号后,如果自身也支持高速模式,就会发出一系列的KJ信号,Device收到后就知道Hub也支持高速模式,然后就会把自身D+的上拉电阻断开。
当高速设备断开后,Hub发出的信号,得到的反射信号法无衰减,Hub监测到这些信号以后就知道设备已经断开(此处涉及到比较深的与阻抗匹配相关的硬件知识)。
3. USB数据包
SOP(Start of Packet):起始信号;
SYNC:同步信号;
EOP(End of Packet):终止信号
上图中体现出的一种传输方式为,A要给B发送数据,只有一条线,那么就先发送一个同步信号,B根据同步信号计算出波特率,然后根据波特率设置采样时间,从而达到数据传输的目的。
在USB中就是用了这种思想传输数据,但是USB是使用D+与D-两根线的差分信号来表示逻辑0和逻辑1。
反向不归零编码:波形发生变化表示传输的是0,不发生变化表示传输的是1。
对于要发送很多个数据1的时候,理论上会保持很多个周期T波形不变,这个时候如果双方晶振误差等原因,就容易造成1的个数解析误差,所以在连续发送6个1后,就会发送一个0,即强制翻转发送信号(位填充技术)。
USB传输数据就是使用这种:反向不归零编码+位填充技术。
4. USB协议层数据格式
要达到传输数据的目的,USB数据包中至少包含地址信息、端点信息以及方向信息。
PID域:包含了方向信息和包类型信息等。PID域共8位,高4位是低4位的取反。使用bit0和bit1来表示包类型。
令牌类:01
数据类:11
握手类:10
特殊类:00
4个bit位是如何表示不同的包类型以及相关信息的,见下表:
事务:需要由令牌包,数据包,握手包共同组成。
事务由包组成,包由域组成(SOP, SYNC......这些搜属于域),域由bit位组成。
或者说事务由多个phase组成,包括:
token phase: Token packet
data phase: Data packet
hand shake phase: Hand packet
对于输入输出令牌包,PID后面的域的内容是地址和端点号。
对于数据包,PID后面的域的内容是具体的数据。
对于握手包,只包含SOP、SYNC、PID、EOP。
USB传输中,有四种传输方式:
中断传输:由中断事务组成。主机通过周期性轮巡的方式访问设备,定期向设备发出输入令牌包;
控制传输:由多种事务组成。
批量传输:由批量事务组成,实际上就是批量事务的一次或者多次重复;
实时传输:由实时事务组成,只有token阶段和data阶段,没有握手阶段。
总结一下:
上图表示一个USB包。
域:
包:
事务:
传输: