本文将从USB的 插入检测、 身份识别、 数据传输三个方面对USB通信整个过程扫盲,其中有些知识点的详细信息会放在文章最下面的附录中供查看,从而保证文章的总体简洁。在进入主题以前,首先了解一下USB的一些基础知识
USB的分类 学习
按接口类型分spa
按照USB速度分3d
USB接口通常是4根线,VCC GND DM(D-) DP(D+)
Q:主机端将DM DP接入下拉电阻;设备端根据不一样速度,将DM DP的某一根接上拉电阻,插入时经过压差便可断定是否插入code
对于插入的USB设备,主机须要发送比较短的请求来确认设备的身份、类型、速度等信息,这个过程称之为 枚举
设备的“身份”信息存储在描述符中。每一个USB设备中都有以下描述符。须要注意的是blog
- 一个USB设备只能有一个设备描述符
- 其余描述符均可以有多个,对应复合设备,例如USB键鼠
设备描述符(device description)索引
配置描述符(config description)接口
接口描述符 (interface description)图片
接口描述符事务
配置描述符ip
接口描述符
80 06 01 00 00 00 12 00
00 05 01 00 00 00 00 00
80 06 01 00 00 00 12 00
80 06 02 00 00 00 09 00
搞懂了描述符,调好了枚举,就完成了USB通信的一大半,下面就对描述符进行详细的探索
设备描述符 | 18 | 配置描述符 | 9 | 接口描述符 | 9 | 终点描述符 | 7 |
bLength | 1 | bLength | 1 | bLength | 1 | bLength | 1 |
bDescriptorType | 1 | bDescriptorType | 1 | bDescriptorType | 1 | bDescriptorType | 1 |
bcdUSB | 2 | wTotalLength | 2 | bNumInterfaces | 1 | bEndpointAddress | 1 |
bDeviceClass | 1 | bNumInterfaces | 1 | bAlterateSetting | 1 | bmAttributes | 1 |
bDeviceSubClass | 1 | bConfigurationValue | 1 | bNumEndpoints | 1 | wMaxPacketSize | 2 |
bDeviceProtocol | 1 | iConfiguration | 1 | bInterfaceClass | 1 | bInterval | 1 |
bMaxPackeerSize0 | 1 | bmAttributes | 1 | bInterSubfaceClass | 1 | ||
idVendor | 2 | bMaxPower | 1 | bInterfaceProtocol | 1 | ||
idProduct | 2 | iInterface | 1 | ||||
bcdDevice | 2 | ||||||
iManufacturer | 1 | ||||||
iProduct | 1 | ||||||
iSerialNumber | 1 | ||||||
iNumConfigurations | 1 |
学习协议我我的以为应该仍是从总体流程向下详细到具体协议,上来就看最基本单元/协议会让人一头雾水,这段附录的大致流程也是如此。传输概念->传输流程->基础传输单元->传输流程控制->
- 在USB的通信中,有传输(transfer),事务(Transaction),包(packet)三级。包是最基础的传输单元,与TCP/IP协议中的MAC层协议做用相同。
- 在一次传输中,由屡次事务组成,每次的事务又由多个包组成
- 与众多协议相同,较高级别的协议的报文是基于/内嵌在低级协议的报文当中的,在USB中也不例外,例如,包中预留了DATA位,其目的就是填写报文
传输(transfer): 控制(control)、中断(interrupt)、批量(bulk),同步(Isochronous)
事务(transaction):传输方向、流程控制
包(packet):
下图为一次完整的获取设备描述符的过程
传输:获取设备描述符
设置事务:主机向设备下发 -> 80 06 00 01 00 00 40 00
输入事务:设备向主机上发 -> 12 01 00 01 DC 00 00 10 71 04 F0 FF 00 01 00 00
输出事务:无
不一样包的组成部分以下表所示,数字为每个字段所表明位数。结合上面的完整流程能够更输入的理解包的概念。
Token 令牌包 | SYNC | PID | ADDR | ENDP | CRC5 |
8/32 | 8 | 7 | 4 | 5 | |
Data 数据包 | SYNC | PID | DATA | CRC16 | |
8/32 | 8 | 0-1023 | 16 | ||
Handshake 握手包 | SYNC | PID | |||
8/32 | 8 | ||||
SOF 起始包 | SYNC | Frame Number | CRC5 | ||
8/32 | 11 | 5 |
SOF包:在Token包以前发送,Frame Number为主机内部自增序列号,不断循环
在分析那个设备描述符的流程时会发现,必须在每次事务的开始,要使用Token(令牌包)确认该次事务的传输“基调”。缘由在于,USB是半双工,DM DP并不是独立工做,因此采用"三段式"通信,保证总线不会冲突
- 令牌包(Token):主机发起
- 数据包(Data):根据令牌包中的方向,由主机发起(OUT/SETUP)或者设备发起(IN)数据包
- 握手包(Handshake):数据包接收方发起握手包,返回状态,包含ACK NAK STALL状态等。
终于说到顶层部分了,有点耐心立刻就说完了,首先传输分为如下几种方式,对应不一样需求
传输方式 | 令牌包 | 数据包 | 握手包 | 特色及医用 | 特殊性 |
控制 | ✔ | ✔ | ✔ | 枚举过程当中使用 | 屡次事务,简单的下发命令+回复须要2次事务6个包 |
批量 | ✔ | ✔ | ✔ | 数据量大,要求准确性,经常使用于U盘等设备 | 屡次事务,DATA0/DATA1交替 |
中断 | ✔ | ✔ | ✔ | 数据量小,要求固定频率,经常使用于USB键盘鼠标 | 与批量类似,主机会按照固定间隔向设备发令牌包 |
同步 | ✔ | ✔ | × | 数据量大,要求低延迟,经常使用于USB摄像头、声卡 | 无握手包的批量传输 |
控制传输经常使用于USB枚举阶段,读取设备描述符、设置地址等少许频繁的工做。上面举的获取完整设备描述符就是一个很是典型的控制传输过程,分为如下几个阶段
中断传输在数据传输方面与批量传输相同,重点在于,主机对中断传输设备必须 保持固定扫描间隔,在设备描述符中标注了该扫面间隔。USB总线即便被其余设备批量传输占用,也会在完成中间抽空向中断传输设备下发令牌
由于要求实时性,对数据准确性不是很敏感,因此同步传输中的事务是没有握手包的,以下图
命令 | bmRequestType | bRequest | wValue | wIndex | wLength | Data |
GET_STATUS | 0 | 无 | ||||
CLEAR_FEATURE | 1 | 无 | ||||
SET_FEATURE | 3 | |||||
SET_ADDRESS | 5 | 设备地址 | 0 | 0 | 无 | |
GET_DESCRIPTOR | 80H | 6 | 描述符类型+索引 | 0/languageID | 描述符长度 | 描述符 |
SET_DESCRIPTOR | 7 | |||||
GET_CONFIGURATION | 8 | |||||
SET_CONFIGURATION | 00H | 9 | 00xxH 配置值,高字节固定00 | 0 | 0 | 无 |
GET_INTERFACE | 10 | |||||
SET_INTERFACE | 11 | |||||
GET_STATUS | 12 |
D7 | D6-D5 | D4-D0 |
0:OUT 1:IN |
00:标准请求 01:类请求 10:用户自定义 |
00:设备01:接02:端03:其余 |