Linux·usb协议

目录

1、USB是什么 

1.1 USB特点:

1.2 USB设备供电方式:

1.3 USB总线信号:

1.4 USB插入检测和速度检测

1.5 数据编解码和位填充 

2. USB传输

2、1包

2.1.1 包的组成:

2.1.2 包的内容:

2、2 事件 

2、3  传输

2.3.1 批量传输

2.3.2 中断传输

2.3.3 等时传输

2.3.4 控制传输

3、USB标准请求

3.1 USB标准请求的数据结构 

​3.2 USB 设备枚举及描述符介绍 

 例程分析


1、USB是什么 

USB(Universal Serial Bus)全称通用串口总线,USB为解决即插即用需求而诞生,支持热插拔。USB协议版本有USB1.0、USB1.1、USB2.0、USB3.1等,USB2.0目前比较常用,以下以2.0为主介绍。由于USB是主从模式的结构,设备与设备之间、主机与主机之间不能互连,为解决这个问题,扩大USB的应用范围,出现了USB OTG,全拼 ON The Go。USB OTG 同一个设备,在不同的场合下可行在主机和从机之间切换。

1.1 USB特点:

USB1.0和USB1.1支持1.5Mb/s的低速模式和12Mb/bs的全速模式。在USB2.0以上支持480Mb/s的高速模式。应用如下:

1.2 USB设备供电方式:

USB设备有两种供电方式 

  • 自供电设备:设备从外部电源获取工作电压 
  • 总线供电设备:设备从VBUS(5v) 取电 
    • 对总线供电设备,区分低功耗和高功耗USB设备 
      • 低功耗总线供电设备:最大功耗不超过100mA 
      • 高功耗总线供电设备: 枚举时最大功耗不超过100mA,枚举完成配置结束后功耗不超过500mA 

设备在枚举过程中,通过设备的配置描述符向主机报告它的供电配置(自供电/总线供电)以及它的功耗要求
如下 USB 配置描述符(以Joystick为例),后面具体介绍:

1.3 USB总线信号:

USB使用的是差分传输模式,两个数据线D+和D- 

  • 差分信号1:D+ > VOH(min) (2.8V) 且D- < VOL(max)(0.3V) 
  • 差分信号0:D- > VOH and D+ < VOL
  • J状态(高电平):D+ 高,D- 低
  • K状态(低电平):D+低,D- 高
  • SEO状态:D+ 低,D- 高
  • Reset信号:D+ and D- < VOL for >= 10ms ,主机在要和设备通信之前会发送Reset信号来把设备设置到默认的未配置状态。即主机拉低两根信号线(SE0状态)并保持10ms 
  • Idle状态:J状态数据发、送前后总线的状态 
  • Suspend状态:3ms以上的J状态 
  • SYNC: 3个KJ状态切换,后跟随2位时间的K状态(看到的波形变化是总线上发送0000 0001经过NRZI编码后的波形)
  • Resume信号:20ms的K状态+低速EOP 主机在挂起设备后可通过翻转数据线上的极性并保持20ms来唤醒设备,并以低速EOP信号结尾带远程唤醒功能的设备还可自己发起该唤醒信号;前提是设备已进入idle状态至少5ms,然后发出唤醒K信号,维持1ms到15ms并由主机在1ms内接管来继续驱动唤醒信号 
  • SOP:从IDLE状态切换到K状态 
  • EOP:持续2位时间的SE0信号,后跟随1位时间的J状态 
  • Keep alive即低速EOP信号  

1.4 USB插入检测和速度检测

 主机通过设备在D+或D-上的1.5K上拉来检测设备的连接和断开事件,并由此判别设备的速度 
主机先把高速设备检测为全速设备,然后再通过“Chirp序列”的总线握手机制来识别高速和全速设备

  1. USB连接和断开连接:

设备连上主机时(连接)

  • 当主机检测到某一个数据线电平拉高并保持了一段时间,就认为有设备连上来了,主机必需在驱动SE0状态以复位设备之前,立刻采样总线状态来判断设备的速度 

 没有设备连上主机时(断开)

  • D+和D-数据线上的下拉电阻起作用,使得二者都在低电平;主机端看来就是个SE0状态;同样地,当数据线上的SE0状态持续一段时间了,就被主机认为是断开状态

1.5 数据编解码和位填充 

USB采用NRZI(非归零编码)对发送的数据包进行编码 

  • 输入数据0, 编码成“电平翻转” 
  • 输入数据1, 编码成“电平不变” 

编码出来的序列,高电平:J状态;低电平:K状态 

 位填充是为了保证发送的数据序列中有足够多的电平变化,填充的对象是(输入数据),即先填充再编码 ,数据流中每6个连续的“1”,就要插入1个“0”,从而保证编码,数据出现电平变化,接收方赋值解码NRZI码流,然后识别出填充位,并丢弃它们

2. USB传输

一个transfer(传输)由一个或多个transaction(事务)构成,一个transaction(事务)由一个或多个packet(包)构成,一个packet(包)由一个或多个sync(域)构成。

1.传输数据通信

  • USB的数据通讯首先是基于传输(transfer)的,传输的类型有:中断传输、批量传输、同步传输、控制传输。

2.事务数据通讯

  • 一次传输由一个或多个事务(transaction)构成,事务可以分为:in事务、out事务、setup事务。

3.包数据通讯

  • 一个事务由一个或多个包(packet)构成,包可分为:令牌包(setup)、数据包(data)、握手包(ack)、特殊包。

4.域数据通讯

  • 一个包由多个域构成,域可分为:同步域(sync)、标识域(pid)、地址域(addr)、端点域(endp)、帧号域(fram)、数据域(data)、校验域(crc)。

 

 注意:USB传输数据先发数据低位再发高位数据

以下对其具体进行分析

因为传输涉及事务,而事务又涉及包,包又涉及域,所以我们先分析包和域,再分析事件和传输

2、1包

2.1.1 包的组成:

2.1.2 包的内容:

 Packet分四大类: 命令 (Token) 、Packet 帧首 (Start of Frame) 、Packet 数据 (Data) 、Packet 握手 (Handshake) Packet

不同类型包,以上的组成部件有所不同

  • PID:

这里只用(PID0~4),PID4~7是PID0~4的取反,用来校验PID
PID1~0:01 令牌包、11 数据包、10 握手包、00 特殊包

  •  地址:

  • 帧号: 

  • 数据: 

 

  • CRC: 

 Packet分四大类:

  • 命令 (Token) 
  • Packet 帧首 (Start of Frame) 
  • Packet 数据 (Data) 
  • Packet 握手 (Handshake) Packet

不同类型包,以上的组成部件有所不同

  • 四种Packet类型之令牌包(Token Packet):

令牌包用来启动一次USB传输。

  • 输出(OUT)令牌包:用来通知设备将要输出一个数据包
  • 输入(IN)令牌包:用来通知设备返回一个数据包
  • 建立(SETUP)令牌包:只用在控制传输中,和输出令牌包作用一样,也是通知设备将要输出一个数据包,两者区别在于:SETUP令牌包后只使用DATA0数据包,且只能发送到设备的控制端点,并且设备必须要接收,而OUT令牌包没有这些限制

 

  • Packet类型之SOF Packet

帧起始包:在每帧(或微帧)开始时发送,以广播的形式发送,所有USB全速设备和高速设备都可以接收到SOF包。 

 

 0xA5:1010 0101:对应上面PID表可知是帧起始包

  • Packet类型之Data Packet 

 

  • Packet类型之Handshake Packet 

 

2、2 事件 

Transaction可以分成三类 

  • Setup transaction:主机用来向设备发送控制命令 
  • Data IN transaction:主机用来从设备读取数据 
  • Data OUT transaction:主机用来向设备发送数据 

Transaction的packet组成 

  • Token packet:总是由主机发出 
  • Data packet:包含此次transaction的数据负载 
  • 可选的Handshake packet 

例子:

 

2、3  传输

USB协议定义了四种传输类型: 

  • 批量(大容量数据)传输(Bulk Transfers): 非周期性,突发  
    • 大容量数据的通信,数据可以占用任意带宽,并容忍延迟 。如USB打印机、扫描仪、大容量储存设备等 
  • 中断传输(Interrupt Transfers): 周期性,低频率
    • 允许有限延迟的通信 如人机接口设备(HID)中的鼠标、键盘、轨迹球等
  • 等时(同步)传输(Isochronous Transfers): 周期性 
    • 持续性的传输,用于传输与时效相关的信息,并且在数据中保存时间戳的信息 ,如音频视频设备
  • 控制传输(Control Transfers): 非周期性,突发
    • 用于命令和状态的传输

2.3.1 批量传输

批量输出事务:

  • (1)主机先发出一个OUT令牌包(包含设备地址,端点号)
  • (2)然后再发送一个DATA包,这时地址和端点匹配的设备就会收下这个数据包,主机切换到接收模式,等待设备返回握手包
  • (3)设备解码令牌包,数据包都准确无误,并且有足够的缓冲区来保存数据后就会使用ACK/NYET握手包来应答主机(只有高速模式才有NYET握手包,他表示本次数据成功接收,但是没有能力接收下一次传输),如果没有足够的缓冲区来保存数据,就返回NAC,告诉主机目前没有缓冲区可用,主机会在稍后时间重新该批量传输事务。如果设备检查到数据正确,但端点处于挂起状态,返回STALL。如果检测到有错误(如校验错误,位填充错误),则不做任何响应,让主机等待超时。

批量输入事务:

  • (1)主机首先发送一个IN令牌包(包含设备地址,端点号)
  • (2)主机切换到接收数据状态等待设备返回数据。如果设备检测到错误,不做任何响应,主机等待超时。如果此时有地址和端点匹配的设备,并且没有检测到错误,则该设备作出反应:设备有数据需要返回,就将一个数据包放在总线上;如果没有数据需要返回,设备返回NAK响应主机;如果该端点处于挂起状态,设备返回STALL。如果主机收到设备发送的数据包并解码正确后,使用ACK握手包应答设备。如果主机检测到错误,则不做任何响应,设备会检测到超时。注意:USB协议规定,不允许主机使用NAK来拒绝接收数据包。主机收到NAK,知道设备暂时没有数据返回,主机会在稍后时间重新该批量输入事务。

PING令牌包,它不发送数据,直到等待设备的握手包。

 

2.3.2 中断传输

中断传输是一种保证查询频率的传输。中断端点在端点描述符中要报告它的查询间隔,主机会保证在小于
这个时间间隔的范围内安排一次传输。 

2.3.3 等时传输

等时(同步)传输用在数据量大、对实时性要求高的场合,如音频设备,视频设备等,这些设备对数据的延迟很敏感。对于音频或视频设备数据的100%正确性要求不高,少量的数据错误是可以容忍的,主要是保证数据不能停顿,所以等时传输是不保证数据100%正确的。当数据错误时,不再重传操作。因此等时传输没有应答包,数据是否正确,由数据的CRC校验来确认。

2.3.4 控制传输

控制传输可分为三个过程:

  • (1)建立过程
  • (2)数据过程(可选)
  • (3)状态过程

 特性:  
        每个USB设备都必须有控制端点,支持控制传输来进行命令和状态的传输。USB主机驱动将通过控制传输与USB设备的控制端点通信,完成USB设备的枚举和配置 
方向:  
        控制传输是双向的传输,必须有IN和OUT两个方向上的特定端点号的控制端点来完成两个方向上的控制传输 

数据的拆分和数据传输完毕的判定 :

        以高速设备的最大数据包长度64字节为例 ,要传输250字节,拆分成4个packet 

要传输正好256字节,通过最后一个0字节包告诉设备传输完成

 

 各种传输特性比较

3、USB标准请求

3.1 USB标准请求的数据结构 

 

 3.2 USB 设备枚举及描述符介绍 

当一个USB设备插入主机后,会有以下活动:  

 

在USB设备的逻辑组织中,包含设备、配置、接口和端点4个层次。设备通常有一个或多个配置,配置通常有一个或多个接口,接口通常有零个或多个端点。  

 

 

 

 

include/uapi/linux/usb/ch9.h
/* USB_DT_DEVICE: Device descriptor */
struct usb_device_descriptor {
    __u8  bLength;
    __u8  bDescriptorType;
 
    __le16 bcdUSB;
    __u8  bDeviceClass;
    __u8  bDeviceSubClass;
    __u8  bDeviceProtocol;
    __u8  bMaxPacketSize0;
    __le16 idVendor;
    __le16 idProduct;
    __le16 bcdDevice;
    __u8  iManufacturer;
    __u8  iProduct;
    __u8  iSerialNumber;
    __u8  bNumConfigurations;
} __attribute__ ((packed));
 
#define USB_DT_DEVICE_SIZE        18

 

 

struct usb_config_descriptor {
    __u8  bLength;
    __u8  bDescriptorType;
 
    __le16 wTotalLength;
    __u8  bNumInterfaces;
    __u8  bConfigurationValue;
    __u8  iConfiguration;
    __u8  bmAttributes;
    __u8  bMaxPower;
} __attribute__ ((packed));
 
#define USB_DT_CONFIG_SIZE        9

 

/* USB_DT_INTERFACE: Interface descriptor */
struct usb_interface_descriptor {
    __u8  bLength;
    __u8  bDescriptorType;
 
    __u8  bInterfaceNumber;
    __u8  bAlternateSetting;
    __u8  bNumEndpoints;
    __u8  bInterfaceClass;
    __u8  bInterfaceSubClass;
    __u8  bInterfaceProtocol;
    __u8  iInterface;
} __attribute__ ((packed));
 
#define USB_DT_INTERFACE_SIZE        9

 

 

/* USB_DT_ENDPOINT: Endpoint descriptor */
struct usb_endpoint_descriptor {
    __u8  bLength;
    __u8  bDescriptorType;
 
    __u8  bEndpointAddress;
    __u8  bmAttributes;
    __le16 wMaxPacketSize;
    __u8  bInterval;
 
    /* NOTE:  these two are _only_ in audio endpoints. */
    /* use USB_DT_ENDPOINT*_SIZE in bLength, not sizeof. */
    __u8  bRefresh;
    __u8  bSynchAddress;
} __attribute__ ((packed));
 
#define USB_DT_ENDPOINT_SIZE        7
#define USB_DT_ENDPOINT_AUDIO_SIZE    9    /* Audio extension */

 

 

/* USB_DT_STRING: String descriptor */
struct usb_string_descriptor {
    __u8  bLength;
    __u8  bDescriptorType;
 
    __le16 wData[1];        /* UTF-16LE encoded */
} __attribute__ ((packed));
 
/* note that "string" zero is special, it holds language codes that
 * the device supports, not Unicode characters.
 */

 

 例程分析

我们插上鼠标后后出现如下的信息,我们先来分析第一个传输:

我们看到第一个是控制传输,它包含了4个事物,分别是:1个setup事务,3个in事务,1个out事务,我们先打开setup事务: 我们看到这个事务里包含了3个包

  • 第一个包是令牌包,它由主控制器发送给目标设备的0号端口,用于设置目标设备的地址和端口号,我们看到后面两个包都缺省了地址与端口号。在usb系统中,所有的通信都是由主机发出相应的令牌所引起的。
  • 第二个是数据包,由主控器发送给目标设备,其中数据的内容表示:
    • 80:表示要求设备向主机发送信息
    • 06:表示GET_DESCRIPTOR,即设备向主机发送设备描述符
    • 00与01:Word-sized field that varies according to request
    • 00与40:Word-sized field that varies according to request; typically used to pass an index or offset
    • 00:Number of bytes to transfer if there is a:Data stage
    • 总结一下第二个包就是向默认地址0 发送GET_DESCRIPTOR 指令包,请求设备发送设备描述符
  • 第三个是应答包:设备接收到主机发送的数据后会给出应答

接着我们看第一个in事务

 我们看到这个事务里也有三个包

  • 第一个是in包:由主机发送给设备,表示要设备向主机发送上面请求的设备描述符
  • 第二个是数据包:由设备发送给主机,当然是发送设备描述符,我们来分析一下:
    • 12:表示接下来要求主机向设备发送信息
    • 01:CLEAR_FEATURE、
  • 第三个是应答包,由主机发送给设备

接着我们来看第二个in事务

 

这个事务里依旧是3个包

  • 第一个是in包:由主机发送给设备,表示需要输入
  • 第二个是数据包:由设备发送给主机,我们来解析一下:
    • 6D:表示要求主机发给设备数据
    • 04:Reserved for future use
  • 第三个是主机给设备的应答包

最后来看out事务

  • 第一个是out包:由主机发给设备
  • 第二个是数据包:由主机发给设备,无数据
  • 第三个包是设备给主机的应答包

 

  • 4
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值