1. USB的特点
USB1.0 与 USB1.1 版本: 1.5Mb/s 的低速 ( low-speed )模式与 12Mb/s 的全速 ( full-speed )模式。
USB2.0 版本: 480Mb/s (即 60MB/s )的高速 ( high-speed )模式。
USB3.0 版本: 5.0Gb/s (即 500MB/s )的超速 ( super-speed )模式, 5Gb/s 的带宽并不是 5Gb/s 除以 8 得到的 625MB/s ,而是采用与 SATA 相同的 10 Bit 传输模式(在 USB2.0 的基础上新增了一对纠错码),因此其全速只有 500MB/s 。
全速与低速是电压模式 (3.3V) ,高速是电流模式。
USB 开发者论坛: www.usb.org
EDN USB 专区: archive.ednchina.com/group.ednch…
2. USB枚举
| 描述符 | 作用 | 备注 |
|---|---|---|
| 设备描述符 | 设备所使用的 USB 协议版本号、设备类型、端点 0 的最大包大小、 VID 、 PID 、设备版本号、厂商字符串索引、产品字符串索引、设备序列号索引、可能的配置数等 | 一个 USB 设备只有一个设备描述符,设备描述符里决定了该设备有多少种配置 |
| 配置描述符 | 配置所包含的接口数、配置的编号、供电方式、是否支持远程唤醒、电流需求量等 | 每种配置都有一个配置描述符,定义了该配置里有多少种接口 |
| 接口描述符 | 接口的编号、接口的端点数、接口所使用的类、子类、协议等 | 每个接口都有一个接口描述符,在接口描述符里又定义了该接口有多少个端点 |
| 端点描述符 | 端点号及方向、端点的传输类型、最大包长度、查询时间间隔等 | 每个端点都有一个端点描述符 |
| 字符串描述符 | 提供一些方便人们阅读的信息,不是必需的 |
一个 USB 设备只有一个设备描述符,设备描述符里决定了该设备有多少种配置,每种配置都有一个配置描述符。而每个配置描述符中,又定义了该配置里有多少种接口,每个接口都有一个接口描述符。在接口描述符里又定义了该接口有多少个端点,每个端点都有一个端点描述符。端点描述符定义了端点的大小、类型等。如果有类特殊描述符,它跟在相应的接口描述符之后。
描述符获取
在主机获取描述符时,首先获取设备描述符,接着再获取配置描述符,然后根据配置描述符中的配置集合的总长度,一次将配置描述符、接口描述符、类特殊描述符(如果有)、端点描述符一次读回。对于字符串描述符,是单独获取的。主机通过发送获取字符串描述符的请求以及描述符的索引号、语言 ID 来获取对应的字符串描述符。
3. USB包解析
USB 总线上传输数据是以包为基本单位的 ,一个包被分成不同的域。以 同步域开始 ,紧跟着一个 包标识符 PID ( Packet Identifier ),最终以 包结束符 EOP ( End Of acket )来结束这个包。
包标识符 PID 是用来标识一个包的类型的。USB 协议规定了 4 类包, 分别是:令牌包 (token packet , PID1-0 为 01) ,数据包 (data packet , PID1-0 为 11) ,握手包 (handshake packet , PID1-0 为 10) 和特殊包 (special packet , PID1-0 为 00) 。
3.1、令牌包
令牌包用来启动一次 USB 传输,所有的数据传输都是由主机发起的。令牌包有 4 种, 分别为输出 (OUT) 、输人 (IN) 、帧起始 (SOF Start Of Frame) 和建立 (SETUP) 。建立 (SETUP)令牌包只用在控制传输中,通知设备将要输出一个数据包。
OUT 、 IN 、 SETUP 令牌包的结构:
| 同步域 | 8 位包标识 PID | 7 位地址 | 4 位端点号 | 5 位 CRC5 校验 | EOP |
|---|
帧起始包在每帧 ( 或微帧 ) 开始时发送,它以广播的形式发送, 所有 USB 全速设备和高速设备都可以接收到 SOF 包。 USB 全速设备每毫秒产生一个帧,而高速设备每 125μs 产生一个微帧。帧起始包的结构:
| 同步域 | 8 位包标识 PID | 11 位帧号 | 5 位 CRC5 校验 | EOP |
|---|
3.2、数据包
数据包就是用来传输数据的,数据包都具有同样的结构:
| 同步域 | 8 位包标识 PID | 字节 0 | 字节 1 | ...... | 字节 N | 16 位 CRC16 校验 | EOP |
|---|
发送端按照 DATA0-DATA1-DATA0-… 的顺序发送数据包,只有成功的事务传输才会导致 PID 翻转,也就是说发送端只有在接收到 ACK 后才会翻转 PID ,发送下一个数据包,否则会重试本次事务传输。
3.3、握手包
握手包用来表示一个传输是否被对方确认。握手包是有同步域、 PID 和 EOP ,是最简单的一种数据包。握手包有 ACK 、 NAK 、 STALL 和 NYET 。
| 同步域 | 包标识 PID | EOP |
|---|
需要注意的是, 返回 NAK 并不表示数据出错, 只是说明设备暂时没有数据传输或者暂时没有能力接收数据。 STALL 表示设备无法执行这个请求, 或者端点已经被挂起了, 它表示一种错误的状态。
包处理
当 USB 接口芯片正确接收到数据时, 如果有空间保存, 则它将数据保存并返回 ACK 。 同时, 设置一个标志表示已经正确接收到数据; 如果没有空间保存数据, 则自动会返回 NAK 。收到输入请求时, 如果有数据需要发送, 则发送数据, 并等待接收 ACK 。只有当数据成功发送出去 ( 即接收到应答信号 ACK) 之后, 它才设置标志, 表示数据已成功发送; 如果无数据需要发送, 则它自动返回 NAK 。
4、USB 的四种传输类型
USB 定义了数据在总线上传输的基本单位是包,必须按照一定的关系把这些不同的包组织成事务( transaction )才能传输数据。
事务通常是由两个或者三个包组成:令牌包、数据包和握手包。
- 令牌包:启动一个事务,总是由主机发送。
- 数据包:传送数据,可以从主机到设备,也可以从设备到主机,方向由令牌包来指定。
- 握手包:发送者为数据接受者,当数据接收正确后,发送握手包。设备也可以使用 NAK 握手包来表示数据还未准备好。
USB 协议规定了四种传输类型:批量传输、等时传输、中断传输与控制传输。其中批量传输、等时传输、中断传输每一次传输都是一个事务;控制传输包括三个过程,建立过程和状态过程分别是一个事务,数据过程则可能包含多个事务。
批量传输:使用批量事务( bulk transaction )传输数据。一次批量事务有三个阶段:令牌包、数据包、握手包。主要用在数据量大、对数据实时性要求不高的场合。
中断传输:是一种保证查询频率的传输。通常用在数据量不大,但是对时间要求较严格的设备中,例如人机接口设备( HID )中的鼠标、键盘、触摸等。
等时传输:(同步传输)用在数据量大、对实时性要求高的场合,例如音频设备、视频设备等。等时传输是不保证数据 100% 正确的。
控制传输:分为三个过程:建立过程、可选的数据过程、状态过程。每个过程都是由令牌包、数据包、握手包组成的。
- 建立( setup )过程:都是由 USB 主机发起的。它开始于一个 SETUP 令牌包.
- 数据过程:如果是控制读传输, 那么数据过程就是输入数据;如果是控制写传输,那么数据过程是输出数据。如果在建立过程中,指定了数据长度为 0 ,则没有数据过程。
- 状态过程:与数据过程的数据传输方向相反:如果是控制读传输,则状态过程是一个输出数据包;如果是控制写传输,则状态过程是一个输入数据包。状态过程用来确认所有的数据是否都已经正确传输完成。
5、linux usb子系统
linux USB子系统包括USB core、USB主机控制器hcd、hub驱动、USB设备驱动、USB接口驱动(usbhid)、hid总线驱动等。
USB core:提供各种核心函数接口
USB主机控制器hcd:注册usb 主机控制器,注册roothub,协调主机和设备间的通信
hub驱动:中断轮询端口是否有变化,在回调函数hub_irq中就会向工作队列hub_wq中添加任务,在该任务中再去做hub端口检查,设置地址,获取新设备描述符等工作。生成一个usb设备,与usb设备驱动进行匹配。
USB设备驱动:从设备众多配置中选择一个合适的,然后去配置设备,让设备进入期待已久的Configured 状态。然后注册接口设备。
USB接口驱动:与接口设备匹配,如果是hid设备则匹配usbhid驱动,获取report描述符,解析hid描述符,添加hid_device到hid_bus_type。
linux USB子系统图解(右键另存为可获取清晰图片)
图片看不清的话可以看源文件:github.com/antsHub/lin…