USB 2.0
速度分类
低速:1.5Mb/s(USB 1.0 Low Speed)
全速:12Mb/s(USB 1.0 Full Speed、USB 1.1(即USB 1.0 Full Speed)、USB 2.0 Full Speed(兼容USB 1.1))
高速:480Mb/s(USB 2.0 Hi Speed)
超级速度:5Gb/s(USB 3.0)
......
设备检测
外围设备会通过拉高D+或D-告知主机设备插入

总线电流
完全配置前,允许从总线获取最大100mA电流,完全配置后,最大500mA电流。
总线状态
下图显示了USB低速和全速总线信号1、信号0、SE0状态、SE1状态、J状态、K状态、空闲IDLE状态下D+、D-线分别对应的电平信号范围。

J状态和空闲状态的总线电压一样,不过空闲状态的高电平是上拉电阻控制的,J状态是主机或设备控制的。
low speed和full/high spped J状态 / K状态相反。
枚举
设备插入主机后,主机获取设备信息、设置设备地址的过程叫枚举。
USB枚举过程用的 控制传输 方式与USB从机的端点0(只有端点0是支持双向通信)进行通信的。


描述符
设备通过描述符的形式存放设备的信息(设备类型、供应商字符串等)
数据收发格式
host 发给 device
struct usb_ctrlrequest { __u8 bRequestType; __u8 bRequest; __le16 wValue; __le16 wIndex; __le16 wLength; } __attribute__ ((packed));
抓包工具对每个字段的解析

设备描述符
每一个USB设备只有一个设备描述符,主要向主机说明设备类型、端点0最大包长、设备版本、配置数量等等;


字符串描述符
所有字符串都存储在字符串描述符中,需要哪个字符串,指定其索引即可。
端点描述符
先介绍下什么是端点,端点分为输入端点和输出端点,端点是实现USB设备功能的物理缓冲区实体,USB主机和设备是通过端点进行数据交互的。
方向 IN 和 OUT 是相对于主机来说


每个端点都有地址,存储于端点描述符中(bEndpointAddress)


接口描述符
每一个USB配置下至少有一个或者多个接口描述符,接口描述符主要说明设备类型、此接口下使用的端点数(不包括0号号端点),一个接口就是实现一种功能,实现这种功能可能需要端点0就够了,可能还需要其它的端点配合;

接口描述符中的class指定了该接口是什么类型设备,比如音频、打印机等,在 https://www.usb.org/defined-class-codes 有列出已定义的class码



配置描述符
每一个USB设备至少有一个或者多个配置描述符,但是主机同一时间只能选择某一种配置,标准配置描述符主要向主机描述当前配置下的设备属性、所需电流、支持的接口数、配置描述符集合长度等等;


以下是带有鼠标触摸屏的键盘设备

能看出配置描述符的一些特点:
上层描述符如果包含下层描述符,那么下层描述符的实现必须紧挨着上层描述符
一个上层描述符如果包含了多个下层描述符,那多个下层描述符的实现按照顺序紧挨着上层描述符
一个配置描述符中可以有多个接口描述符
一个接口描述符可以包含多个端点描述符
多个接口描述符通过接口关联描述符整合
主机会先读取9字节配置描述符,再根据配置描述符的第三、第四域读取随后的所有描述符(除设备描述符和字符串描述符)

功能描述符(function descriptor)
功能描述符是USB类规范中定义的类特殊接口描述符(Class-Specific Interface Descriptor),用于补充接口描述符,详细说明接口的具体功能。
功能描述符位于接口描述符之后、端点描述符之前,作为接口描述符的扩展部分。
对于HID设备,功能描述符类型是0x21,报告描述符(report descriptor)是0x22。
注:报告描述符并非在主机读取配置描述符时直接回复给主机,而是需要主机在获取配置描述符后,通过独立的HID类特定请求(如GET_DESCRIPTOR)来获取。

描述符之间的关系
顶层 → 底层:
设备描述符 → 配置描述符 → 接口描述符 → 端点描述符。
类特定描述符(如HID描述符、报告描述符)作为接口描述符的扩展,位于其之后
数据流示例
设备描述符 ↓ 配置描述符 ↓ 接口描述符 ↓ HID描述符(0x21) ↓ 报告描述符(0x22) ↓ 端点描述符
数据获取流程
主机通过GetDescriptor请求依次获取:
- 设备描述符:获取设备总体信息。
- 配置描述符:获取配置信息及关联的接口(包含类特定描述符)和端点描述符。
- 字符串描述符:获取人类可读信息(如厂商名称)。



传输类型
传输类型在端点描述符中指定
鼠标

音频

U盘


帧和调度
低速和全速USB设备
- 对于低速和全速USB设备,帧周期定义为1毫秒(ms)。在这个时间间隔内,USB总线上的通信被划分为多个微小的时间片,但并不细分为明确的子帧或时隙。
- 每个帧周期以一个Start Of Frame (SOF) 包开始,它包含了帧号,用于同步目的,并标志着新一帧数据传输的开始。
- 在每个帧内,设备可以根据需要发送和接收数据包,这些数据包按照令牌包、数据包和握手包的顺序进行。

中断和同步拥有优先获得传输的资格,如果没有中断和同步,批量占用所有时间片
高速USB设备
- 高速USB设备使用更复杂的帧结构。高速USB总线在一个微帧(microframe)的基础上组织其活动,而1个帧周期包含8个连续的微帧,即每个微帧持续时间为125微秒(μs)。
- 微帧内部进一步划分为若干个时间槽(slots),每个时间槽可以容纳一个或多个数据包的传输。
- 每个微帧的起始位置都有一个专门的时间槽用来发送SOF包(被称为微帧起始包Micro Start of Frame, MSOF),用于高速设备的精确同步。

无论是低速/全速设备还是高速设备,帧周期都是USB总线调度和同步数据传输的基本单位,确保所有连接到总线上的设备能够有序且高效地共享带宽资源。对于高速USB而言,通过将帧细化为微帧并分配时隙,实现了更高的数据传输速率和更精确的时间管理。
事务(transaction)

以传输 10KB 数据块为例,10KB被分到多个事务中传输

一个事务包含几个包


令牌包包括 IN、OUT、SETUP、PING 等。
host向device发送指令(读取设备描述符)是一次事务(数据包是host发给device)

device向host返回设备描述符是一次事务(数据包是device发给host)

在USB帧或微帧周期内,数据传输是以令牌包、数据包和握手包的形式进行的。令牌包指示数据传输的方向(IN或OUT)以及目标端点;数据包携带实际的数据内容;而握手包则用来确认数据传输的成功与否。
包是数据传输的最小单位,不能被打断或干扰,否则会引发错误;若干个包组成一次事务传输,一次事务传输也不能打断,属于一次事务传输的几个包必须连续,不能跨帧完成;一次传输由一次到多次事务传输构成,可以跨帧完成;
包(packet)
包的分类
根据 PID 区分

包的各个域分析





不同类型包详解




主机和设备都可以用ACK来确认,而NAK、STALL、NYET只有设备能够返回,主机不能使用这些握手包。
当主机收到NAK时,知道设备还没有准备好,主机会在以后合适的时机进行重试传输;
NYET只在USB2.0的高速设备输出事务中使用,它表示设备本次数据成功接收,但是没有足够的空间来接收下一次数据。主机在下一次输出数据时,将使用PING令牌包来试探设备是否有空间接收数据,以避免不必要的带宽浪费;
当USB主机或者设备检测到数据出错时(如CRC校验出错、PID校验出错、位填充出错等),将什么都不返回,这时等待接收握手包的一方就会收不到握手包从而等待超时;
PING包:
PING令牌包与OUT令牌包具有一样的结构,但是PING令牌包后并不发送数据,而是等待设备返回ACK或者NAK,以判断设备是否能够传送数据。只有在USB2.0高速环境中才会使用PING令牌包,它只被使用在批量传输和控制传输的输出事务中。直接使用OUT令牌包发送数据时,不管设备是否有空间接收数据,都会在OUT令牌包之后跟着发送一个数据包,如果设备没有空间接收数据,就会返回一个NAK。当设备返回NAK时,数据已经发送出去了,浪费了总线带宽,白白发送了数据,如果在发送数据前先发送一个小包来探测设备是否有空间来接收数据,然后主机再决定是否发送数据,这样就可以提供总线带宽的利用率。因此在高速USB总线中,增加PING机制,主机先用PING令牌包试试设备是否有空间接收数据,而不用事先把数据发送出去。

浙公网安备 33010602011771号