USB-HID学习笔记
USB的概念性知识
USB的特点
USB2.0 有高速、全速和低速三种工作速度,高速是480Mbit/s,全速是12Mbit/s, 低速是1.5Mbit/s。
USB传输距离短,开发、调式难度大
http://www.usb.org/
http://group.ednchina.com/93/
USB是一种主从结构系统,主机叫HOST,从机叫Device(设备)。USB的数据交换只能发生在主机与设备之间,所有的数据传输都是由主机主动发起的,设备只是被动的负责应答,在USB OTG中,一个设备可以在从机与主机之间切换,这样就实现了设备与设备之间的连接。USB OTG增加了一种MINI USB接头,比普通的USB4线多出一条ID标识线,来表明是主机还是设备。
PC上有多个USB主控制器和多个USB口,每个控制器下有一个跟集线器,USB集线器将一个USB口扩展为多个USB口,USB1.1最多为4层,USB2.0最多为6层。理论上,一个USB主控器最多可接入127个设备:协议规定USB设备具有一个7bit的地址(0~127).
USB传输过程:USB主控器发出命令和数据,通过跟集线器→USB设备,USB设备返回信息→上一层集线器(经历每层集线器)→USB主控制器→CPU。
USB的电气特性
标准USB连接线使用4芯电缆:5V电源线Vbus;差分数据线D-;差分数据线D+;地GND。USB OTG增加了一种MINI USB接头,比普通的USB4线多出一条ID标识线。在USB的低速和全速模式下,采用的是电压传输模式,在高速模式下,采用电流传输模式。
传输速度是指总线上每秒传输的位数,实际速率要低,因为USB有甚多的协议开销。
当数据为0时,电平翻转;数据为1时,电平不翻转。
VBUS电源线,SBU2:2.0设备可悬空,CC1:发电段配置上拉电阻,受电段下拉。DN、DP:差分数据线。
有设备:D+或者D-接一个1.5k的上拉电阻,(D+高速;D-低俗)
HUB集线器:没有设备:D+、D-接入15k的下拉电阻。
USB的描述符
USB1.1定义的标准描述符:设备描述符(Device Descriptor)、配置描述符(Configuration Descriptor)、接口描述符(Interface Descriptor)、端点描述符(Endpoint Descriptor)、字符串描述符(String Descriptor)。
USB2.0协议新增两个描述符(高速(High-Speed,480Mbps)):设备限定描述符(Device Qualifier Descriptor)、其他速度配置描述符(Other Speed Configuration Descriptor)。
特殊的描述符:类特殊描述符(HID描述符和音频接口描述符)、厂商自定义描述符。
一个USB设备只有一个设备描述符,
- 设备描述符:设备使用的USB协议版本号、设备类型、厂商ID、产品PID、版本号等
- 配置描述符:接口数、接口所使用的类、子类、协议等
- 端点描述符:端点号及方向、端点的传输类型、最大包长度、查询间隔等
- 字符串描述符:提供人们阅读的信息,不必需
- 设备限定描述符:用于描述设备在不同速度下的通用特性(如高速 / 全速),仅在设备支持多速度时存在,主机枚举时先读取此描述符,再获取对应速度的配置描述符。
- 其他速度配置描述符:与当前配置描述符一一对应,存储设备在非当前速度下的配置信息(比如设备当前工作在高速模式,此描述符则存储全速模式的配置参数)。
设备{配置{ ;配置{ };配置{接口{ };接口{ };接口{端点{ };端点{ };端点{ }}}}。
设备→配置→接口→端点。
如果一个设备的各种描述符成功返回,代表着成功一大半。(描述符不能出现错误,否则无法正常工作)
USB设备的枚举过程
枚举就是从设备读取各种描述符信息。得知设备是什么类型的设备
USB传输模式:控制传输:建立过程(都由主机发送)、可选的数据过程及状态过程。
建立过程:起始于SETUP令牌包→DATA0数据包→数据过程(读传输:输入数据,写传输:输出数据;数据长度为0:没有数据过程)→状态过程(读传输:输出数据包;写传输:输入数据包);状态过程用来确认数据是否正确传输完成。
- 复位与获取设备描述符(0 地址阶段)
- 设置地址:主机分配一个唯一的 7 位设备地址给该设备。设备收到新地址,必须等待主机发送ACK令牌包,才能启用新地址
- 再次获取设备描述符:主机切换新地址发送建立过程
- 获取配置描述符
- HID设备:报告描述符
USB是串行总线,数据是一位一位进行传输的,LSB在前,最先出来的是最低位,数据传输方向:从设备到主机称为输入,主机到从设备成为输出。
USB总线传输数据以包为单位,不同类型的包包含不同类型的域,包都以同步域开始,由一个包标识符PID,和包结束符EOP来结束这个包,同步域:开始传输数据,用来同步数据时钟,
- 同步域→标识符PID→结束符EOP
PID标识一个包的类型一共8位,其中USB协议使用的只有4位(0~3)另外4位是(0~3)的取反用来校验PID。
| PID 类型 | PID 名称 | PID[3:0] | 说明 |
|---|---|---|---|
| 令牌类 (Token) | OUT | 0001B | 通知设备将要执行输出传输(主机 → 设备) |
| IN | 1001B | 通知设备将要执行输入传输(设备 → 主机) | |
| SOF | 0101B | 帧起始包,用于同步 USB 总线时序(全速每 1ms、高速每 125μs 发送一次) | |
| SETUP | 1101B | 通知设备启动控制传输(用于设备枚举、配置等核心流程) | |
| 数据类 (Data) | DATA0 | 0011B | 基础数据包(与 DATA1 交替,保证传输可靠性) |
| DATA1 | 1011B | 基础数据包(与 DATA0 交替,用于传输同步) | |
| DATA2* | 0111B | 高速 / 等时传输专用数据包 | |
| MDATA* | 1111B | 多字节 / 等时传输专用数据包 | |
| 握手类 (Handshake) | ACK | 0010B | 确认(数据接收成功) |
| NAK | 1010B | 不确认(设备暂时无法发送 / 接收数据) | |
| STALL | 1110B | 挂起(设备端点错误 / 不支持当前请求) | |
| 特殊类 (Special) | NYET* | 0110B | 未准备好(高速设备批量传输专用,用于流量控制) |
| PRE | 1100B | 前导令牌包(用于低速 / 全速设备在高速总线上的兼容通信) | |
| ERR* | 1100B | 错误握手包(高速 / 分裂事务专用,用于错误通知) | |
| SPLIT* | 1000B | 分裂事务令牌包(用于高速主机与低速 / 全速设备通信) | |
| PING* | 0100B | PING 测试令牌包(用于批量传输流量控制,避免 NAK 风暴) | |
| — | 0000B | 保留,未使用 |
EOP大约为2个数据低位SE0,SE0:D+、D-都保持低电平状态
4种包
令牌包:用来启动USB传输,主机发送一个令牌包来通知那个设备响应;
- 输出令牌包(OUT):用来通知设备将要输出一个数据包
- 输入令牌包(IN):用来通知设备返回一个数据包
- 建立令牌包(SETUP):只用在控制传输中,用来通知设备将要输出一个数据包,设备必须要接收
- 帧起始包(SOF):以广播形式发送,所有的USB设备都可以接到到SOF包
| 令牌包类型 | 字段 1 | 字段 2 | 字段 3 | 字段 4 | 字段 5 | 字段 6 |
|---|---|---|---|---|---|---|
| SOF 令牌包 | 同步域 | 8 位包标识 PID | 11 位帧号 | 5 位 CRC5 校验 | EOP | |
| OUT/IN/SETUP 令牌包 | 同步域 | 8 位包标识 PID | 7 位地址域 | 4 位端点域 | 5 位 CRC5 校验 | EOP |
同步域:用于收发端时钟同步;帧号:USB帧编号,用于时间同步
数据包:传输数据
| USB数据包 | 同步域 | 8 位包标识 PID | 字节 0 | 字节 N | 16 位 CRC16 校验 | EOP |
|---|
8位标识PID:标识数据包类型(DATA0/DATA1/DATA2/DATA_M),用于传输同步、重传控制,自带 4 位取反校验,用在当握手包出错时纠错。
数据域:0~1024 字节(字节 0~ 字节 N);承载实际传输的有效业务数据,长度由 USB 传输类型(控制 / 批量 / 中断 / 等时)决定,
16位CRC16校验:仅对数据域内容做完整性校验,不包含PID。
握手包:用来表示一个传输是否被对方确认
| 握手包 | 同步域 | 包标识PID | EOP |
握手包有ACK、NAK、STALL、NYET。
- ACK:主机 / 设备;正确接收数据,且有足够空间容纳数据
- NAK:仅设备;无数据需要返回,或数据正确接收但无足够空间容纳
- STALL:仅设备;无法执行请求,或端点已挂起(错误状态)
- NYET:仅设备(USB2.0 高速),本次数据成功接收,但无足够空间接收下一次数据
特殊包:特殊场合使用的包
| 特殊包类型 | 横向结构字段 | 核心用途 / 适用场景 |
|---|---|---|
| PRE(前缀令牌包) | 同步域 + 8 位包标识 PID + EOP | 通知集线器打开低速端口;仅全速模式使用,以全速模式发送 |
| ERR(错误握手包) | 同步域 + 8 位包标识 PID + EOP | USB2.0 新增;在高速分裂事务中表示错误使用 |
| SPLIT(高速分裂令牌包) | 同步域 + 8 位包标识 PID + 附加控制域 + EOP | USB2.0 新增;高速事务分包,实现高速设备与全速 / 低速设备的交互 |
| PING(探测令牌包) | 同步域 + 8 位包标识 PID +7位地址域+4位端点域+ EOP | USB2.0 新增;仅批量 / 控制传输输出事务;不发数据,仅收 ACK/NAK 判断空间 |
如何处理数据包
USB 数据包处理由接口芯片自动化完成,软件仅需:
- 配置芯片,操作端点读写数据。
- 依据芯片标志判断传输状态(成功 / 失败 / 忙)。
- 无需关注 CRC、位填充、握手等底层协议细节。
USB的4种传输类型
USB定义了数据在总线上传输的基本单位是包,但是我们不能随意的使用包来传输数据,必须按照一定的关系把这些不同的包组织成事务(transaction)才能传输
USB事务:令牌包、数据包、握手包
- 令牌包:启动一个事务,由主机发送
- 数据包:传送数据,方向由令牌包来指定
- 握手包:通常由数据接收者发送,当数据接收正确后,发送握手包;或者没准备接受,发送NAK
批量传输:使用批量事务传输数据
一次批量事务有三个阶段:令牌包阶段、数据包阶段、握手包阶段。每个阶段都是一个独立的包。
批量传输分为批量读(批量输入事务)和批量写(批量输出事务),批量传输通常用在数据量大、对数据的实时性不高的场合。例如:USB打印机、扫描仪大容量存储设备等。
- 批量输出事务:主机先发出一个OUT令牌包,携带目标设备地址、端点号,发起数据传输请求,再发送DATA 数据包(DATA0/DATA1,由数据切换位决定),承载实际业务数据,主机切换为接收模式,等待设备响应;设备校验数据后,根据状态返回对应握手包。(由主机完全主导,设备被动响应)
- 批量输入事务:主机发送IN 令牌包,携带目标设备地址、端点号,主动请求设备返回数据,主机切换为接收模式,等待设备发送数据;设备校验地址 / 端点无误后,组装并发送DATA 数据包(DATA0/DATA1,由数据切换位决定);设备发送数据后,等待主机响应;主机校验数据后,根据状态返回对应握手包。
在批量输入事务中,主机检测到设备发送NCK或者STALL之后,主机不作回应(USB协议规定主机禁止使用NAK),设备等待超时,进入下一轮。
- USB2.0新增PING令牌机制:
| 特性 | 细节说明 |
|---|---|
| 核心目的 | 解决 USB 1.1 中 IN 事务无缓冲区反馈导致的带宽浪费 |
| 包结构 | 仅含同步域 + PID+EOP(无数据域),结构与 IN 令牌包一致 |
| 工作流程 | 主机先发 PING 包试探 → 设备返回 ACK/NAK/STALL → 确认有空间后再发 IN 包获取数据 |
| 适用场景 | 仅 USB 2.0 高速环境,用于批量 / 控制传输的输入事务,提升总线利用率 |
平时无数据传输时,总线处于空闲状态。当需要传输一次事务时,主机发送一个令牌包,可以是OUT令牌包,IN令牌包或者是PING令牌包。如果设备解码令牌包出错时,总线直接进入空闲状态
一次正确批量输入事务
| 发送主体 | 包类型 | ||||||
|---|---|---|---|---|---|---|---|
| 主机发送 | IN 令牌包 | 同步域 | IN PID | 7 位地址 | 4 位端点号 | 5 位 CRC5 校验 | EOP |
| 设备返回 | DATA0 数据包 | 同步域 | DATA0 PID | 字节 0 | 字节 1 | 16 位 CRC16 校验 | EOP |
| 主机应答 | ACK 握手包 | 同步域 | ACK PID | EOP |
DATA0和DATA1交替
一次批量输出事务
| 发送主体 | 包类型 | ||||||
|---|---|---|---|---|---|---|---|
| 主机发送 | OUT 令牌包 | 同步域 | OUT PID | 7 位地址 | 4 位端点号 | 5 位 CRC5 校验 | EOP |
| 主机发送 | DATA0 数据包 | 同步域 | DATA0 PID | 字节 0 | 字节 1 | 16 位 CRC16 校验 | EOP |
| 设备应答 | ACK 握手包 | 同步域 | ACK PID | EOP |
中断传输:周期传输、是一种保证查询频率的传输
主机保证在不大于某个时间间隔内安排一次传输,主机按端点描述符的查询间隔轮询(固定频率),中断传输用在数据量不大,对时间要求较严格的设备中,例如:人机接口设备(HID)中的鼠标、键盘等,中断传输还可以用来不断地检测某个状态,当条件满足后在使用批量传输来传送大量的数据。无PING、NYET
中断事务流程:
等时传输:周期传输、用在数据量大、实时性要求高的场合
对数据延迟很敏感例如:音频或者视频设备,对少量数据错可以容忍,但是不能停顿。当数据错误时,并不进行重传操作,因此等时传输没有应答包。
控制传输:分为三过程,建立过程、可选的数据过程、状态过程
建立过程使用一个建立事务,建立事务是一个输出数据的过程,数据包类型仅支持DATA0数据包,仅允许ACK应答,出错无响应。
数据过程是可选的,一个控制传输可能没有数据过程,如果有,一个数据过程可以包含一笔或者多笔数据事务。在数据传输过程中,所有的数据事务必须是同一个传输方向的(输入传输或者输出传输),一旦传输方向发生改变,就会认为进入到了下一个过程。
状态过程:是一笔批量事务,要保证数据传输过程的数据完整性,设备枚举过程中各种描述符的获取以及设置地址、设置配置等,都是通过控制传输来实现的。
| 阶段 | 必要性 | 核心作用 | 事务类型 | 数据包规则 | 数据方向 |
|---|---|---|---|---|---|
| 建立过程(Setup Stage) | 强制(必须有) | 发送控制请求(如设置地址、获取描述符等) | SETUP 事务(输出) | 仅用DATA0包 | 主机→设备(输出) |
| 数据过程(Data Stage) | 可选(可无) | 传输控制请求对应的业务数据 | 批量输入 / 输出事务 | 首包用DATA1,之后 DATA0/DATA1 交替;方向全程统一 | 控制读:设备→主机(输入);控制写:主机→设备(输出) |
| 状态过程(Status Stage) | 强制(必须有) | 确认传输完成,状态反馈 | 批量事务 | 仅用DATA1包 | 与数据阶段方向相反(控制写:输入 IN;控制读:输出 OUT) |
端点类型域传输类型的关系
一个具体的端点,只能工作在一种传输模式下。通常,我们把工作在什么模式下的端点,就叫做什么端点。例如,控制端点、批量端点等。 端点 0 是每个 USB 设备都必须具备的默认控制端点,它一上电就存在并且可用。设备的各种描述符以及主机发送的一些命令,都是通过端点 0 传输的。其他端点是可选的,需要根据具体的设备来决定。非 0 端点只有在 Set Config 之后才能使用。
每个 USB 端点的端点描述符中,会明确规定该端点支持的最大数据包长。主机向该端点发送数据时,单次发送的数据包长度绝对不能超过该端点的最大包长限制,否则会导致传输错误。
| 传输类型 | 低速模式 (Low-Speed) | 全速模式 (Full-Speed) | 高速模式 (High-Speed) | 核心适用场景 |
|---|---|---|---|---|
| 控制传输 | 固定为8 字节 | 可在8/16/32/64 字节中选择 | 固定为64 字节 | 设备枚举、配置、状态控制(所有 USB 设备必须支持) |
| 等时传输 | ❌ 不支持 | 最大上限1023 字节 | 最大上限1024 字节 | 实时低延迟数据(音频、视频流) |
| 中断传输 | 最大上限8 字节 | 最大上限64 字节 | 最大上限1024 字节 | 小数据量、低延迟交互(鼠标、键盘、HID 设备) |
| 批量传输 | ❌ 不支持 | 可在8/16/32/64 字节中选择 | 固定为512 字节 | 大容量非实时数据(U 盘、打印机、存储设备) |
在USB中,采用的是D+、D-两条线的电位差,重复发送规律的电平来进行时钟的同步
反向不归零编码:遇见0有电平的跳变,遇1没有电平的跳变。波形有跳变代表着传输的是0,波形无变化,代表传输的是1。要是发送很多1,发送方在发送6个1之后必须要插入1,位填充。
所有传输都是bit0先传输LSB,
事务→包→域→bit
D12芯片读取流程:拉低片选,A0地址线用于选择命令还是数据,WR-N写信号,上升沿稳定才可写入,RD-N读选通信号,拉低有效,拉高结束读信号,
写命令:A0设置命令状态,将写信号拉低,发送的数据,拉高写信号,写完后,将总线设置输入状态,避免总线冲突,
USB识别分为电气识别和协议识别,电气识别主要是识别设备是高速、全速还是低速设备,协议识别就是区分USB设备属于哪种USB的Class,比如CDC设备,MSC设备、HID设备
