Linux基础入门--驱动开发--USB
1.基本概念
USB设备由3个功能模块组成:USB总线接口、USB逻辑设备和功能单元:
a.USB总线接口——指的是USB设备中的串行接口引擎(SIE);
b.USB逻辑设备——被USB系统软件看作是一个端点的集合;
c.功能单元——被看作是一个接口的集合。
为了更好地描述USB设备的特征,USB提出了设备架构的概念。从这个角度来看,可以认为USB设备是由一些配置、接口和端点组成,即一个USB设备可以含有一个或多个配置,在每个配置中可含有一个或多个接口,在每个接口中可含有若干个端点。其中,配置和接口是对USB设备功能的抽象,实际的数据传输由端点来完成。在使用USB设备前,必须指明其采用的配置和接口。这个步骤一般是在设备接入主机时设备进行枚举时完成的。这些单元之间的关系如下:
USB设备使用各种描述符来说明其设备架构,包括设备描述符、配置描述符、接口描述符、端点描述符和字符串描述符,他们通常被保存在USB设备的固件程序中。
2.组成结构
2.1 设备描述符
设备代表一个USB设备,它由一个或多个配置组成。设备描述符用于说明设备的总体信息,并指明其所含的配置的个数。一个USB设备只能有一个设备描述符。
2.2 配置描述符
一个USB设备可以包含一个或多个配置,如USB设备的低功耗模式和高功耗模式可分别对应一个配置。在使用USB设备前,必须为其选择一个合适的配置。配置描述符用于说明USB设备中各个配置的特性,如配置所含接口的个数等。USB设备的每一个配置都必须有一个配置描述符。
2.3 接口描述符
一个配置可以包含一个或多个接口,例如对一个光驱来说,当用于文件传输时,使用其大容量存储接口;而当用于播放CD时,使用其音频接口。接口是端点的集合,可以包含一个或多个可替换设置,用户能够在USB处于配置状态时改变当前接口所含的个数和特性。接口描述符用于说明设备中各个接口的特性,如接口所属的设备类及其子类等。USB设备的每个接口都必须有一个接口描述符。
2.4 端点描述符
端点是USB设备中的实际物理单元,USB数据传输就是在主机和USB设备各个端点之间进行的。端点一般由USB接口芯片提供,USB设备中的每一个端点都有唯一的端点号,每个端点所支持的数据传输方向一般而言也是确定的:或是输入(IN),或是输出(OUT)。也有些芯片提供的端点的数据方向是可以配置的,包含有两个用于数据收发的端点:端点1和端点2。其中端点1只能用于数据发送,即支持输入(IN)操作;端点2既能用于数据发送,也可用于数据接收,即支持输入(IN)和输出(OUT)操作。
利用设备地址、端点号和传输方向就可以指定一个端点,并与它进行通信。端点的传输特性还决定了其与主机通信时所采用的传输类型,例如控制端点只能使用控制传输。根据端点的不同用途,可将端点分为两类:0号端点和非0号端点。
0号端点比较特殊,它有数据输入IN和数据输出OUT两个物理单元,且只能支持控制传输。所有的USB设备都必须含有一个0号端点,用作默认控制管道。USB系统软件就是使用该管道与USB逻辑设备进行配置通信的。0号端点在USB设备插上之后就可以使用,而非0号端点必须要在配置之后才可以使用。
根据具体应用的需要,USB设备还可以含有多个除0号端点以外的其他端点。对于低速设备,其附加的端点数最多为2个;对于全速/高速设备,其附加的端点数最多为15个。
2.5 字符串描述符
在USB设备中通常还含有字符串描述符,以说明一些专用信息,如制造商的名称、设备的序列号等。它的内容以UNICODE的形式给出,且可以被客户软件所读取。对USB设备来说,字符串描述符是可选的。
3.管道
在USB系统结构中,可以认为数据传输时在USB主机软件与USB设备的各个端点之间直接进行的,它们之间的连接称为管道。管道是在USB设备的配置过程中建立的。管道是对USB主机与USB设备间通信流的抽象,表示USB主机的数据缓冲区与USB设备的端点之间存在着逻辑数据传输,而实际的数据传输是由USB总线接口层来完成的。
管道与USB设备中的端点一一对应。一个USB设备含有多少个端点,其与USB主机进行通信时就可以使用多少条管道,且端点的类型决定了管道中数据的传输类型,例如中断端点对应中断管道,且该管道只能进行中断传输。不论存在着多少条管道,在各个管道中进行的数据传输都是相互独立的。
4.端点分类
USB通信的最基本形式是通过端点。一个USB端点只能向一个方向传输数据,从主机到设备(称为输出端点)或者从设备到主机(称为输入端点)。端点可被看作一个单向的管道。USB 端点有 4 种不同类型,分别具有不同的数据传送方式:
4.1 控制CONTROL
控制端点被用来控制对USB设备的不同部分访问。 通常用作配置设备、获取设备信息、发送命令到设备或获取设备状态报告。这些端点通常较小。每个 USB 设备都有一个控制端点称为"端点 0",被 USB 核心用来在插入时配置设备。USB协议保证总有足够的带宽留给控制端点传送数据到设备。
4.2 中断INTERRUPT
每当 USB 主机向设备请求数据时,中断端点以固定的速率传送小量的数据。此为USB 键盘和鼠标的主要的数据传送方法。它还用以传送数据到USB设备来控制设备。通常不用来传送大量数据。USB协议保证总有足够的带宽留给中断端点传送数据到设备。
4.3 批量BULK
批量端点用以传送大量数据。这些端点通常比中断端点大得多。它们普遍用于不能有任何数据丢失的情况。USB 协议不保证传输在特定时间范围内完成。如果总线上没有足够的空间来发送整个BULK包,它被分为多个包进行传输。这些端点普遍用于打印机、USB Mass Storage和USB网络设备上。
4.4 等时ISOCHRONOUS
等时端点也批量传送大量数据,但是这个数据不被保证能送达。这些端点用在可以处理数据丢失的设备中,并且更多依赖于保持持续的数据流,如音频和视频设备等等。
4.5 区别
控制和批量端点用于异步数据传送,而中断和等时端点是周期性的。这意味着这些端点被设置来在固定的时间连续传送数据,USB 核心为它们保留了相应的带宽。
5.总线
USB 主机控制器有 3 种规格:OHCI (Open Host Controller Interface),UHCI (Universal Host Controller Interface) 和 EHCI (Enhanced Host Controller Interface)。OHCI 驱动程序用来为非 PC 系统上以及带有 SiS 和 ALi 芯片组的 PC 主板上的 USB 芯片提供支持。 UHCI 驱动程序多用来为大多数其他 PC 主板(包括 Intel 和 Via)上的 USB 芯片提供支持。EHCI 由 USB 2.0 规范所提出,它兼容于 OHCI 和 UHCI。UHCI 的硬件线路比 OHCI 简单,所以成本较低,但需要较复杂的驱动程序,CPU 负荷稍重。
6.相关文件
文件 | 含义 |
---|---|
/sys/kernel/debug/usb/devices | 设备信息 |
/sys/bus/usb | 树形结构 |
lsusb | usb相关的设备信息 |
mount -t usbfs none /proc/bus/usb | 挂载 |
/proc/bus/usb/devices | 查看USB设备信息 |
6.1 设备信息
通过命令cat /sys/kernel/debug/usb/devices获取设备信息
至于信息的详细解析可以参照 Linux源代码中Documentation/usb/proc_usb_info.txt 文件。现摘录其中对该格式的详细解释:
T = 拓扑结构
B = 带宽(仅适用于USB主机控制器,它被虚拟化为根集线器)
D = 设备描述符信息
P = 产品ID信息
S = 字符串描述符
C = 配置描述符信息
I = 接口描述符信息
E = 端点描述符信息
说明:
d = 十进制数
x = 十六进制数
s = 字符串
拓扑结构:
T: Bus=dd Lev=dd Prnt=dd Port=dd Cnt=dd Dev#=ddd Spd=dddd MxCh=dd
| | | | | | | | |__MaxChildren
| | | | | | | |__Device Speed in Mbps
| | | | | | |__DeviceNumber
| | | | | |__Count of devices at this level
| | | | |__Connector/Port on Parent for this device
| | | |__Parent DeviceNumber
| | |__Level in topology for this bus
| |__Bus number
|__Topology info tag
Speed可能是:
1.5 Mbit/s for low speed USB
12 Mbit/s for full speed USB
480 Mbit/s for high speed USB (added for USB 2.0);
also used for Wireless USB, which has no fixed speed
5000 Mbit/s for SuperSpeed USB (added for USB 3.0)
Port号总是减去1显示。例如,插入Port 4的设备将显示“Port=03”。
带宽信息:
B: Alloc=ddd/ddd us (xx%), #Int=ddd, #Iso=ddd
| | | |__Number of isochronous requests
| | |__Number of interrupt requests
| |__Total Bandwidth allocated to this bus
|__Bandwidth info tag
带宽分配是一帧(毫秒)占用多少的近似值。它只反映周期性传输,这是唯一保留带宽的传输。控制和批量传输使用所有其他带宽,
包括不用于传输的保留带宽(例如用于短数据包)。
百分比是指有多少“预留”带宽是由这些传输计划的。对于一个低或全速总线(松散地,“USB 1.1”),90%的总线带宽被保留。
对于高速总线(松散地说,“usb2.0”)80%是保留的。
设备描述符信息:
D: Ver=x.xx Cls=xx(sssss) Sub=xx Prot=xx MxPS=dd #Cfgs=dd
| | | | | | |__NumberConfigurations
| | | | | |__MaxPacketSize of Default Endpoint
| | | | |__DeviceProtocol
| | | |__DeviceSubClass
| | |__DeviceClass
| |__Device USB version
|__Device info tag #1
产品ID信息:
P: Vendor=xxxx ProdID=xxxx Rev=xx.xx
| | | |__Product revision number
| | |__Product ID code
| |__Vendor ID code
|__Device info tag #2
字符串描述符:
S: Manufacturer=ssss
| |__Manufacturer of this device as read from the device.
|__String info tag
S: Product=ssss
| |__Product description of this device as read from the device.
|__String info tag
S: SerialNumber=ssss
| |__Serial Number of this device as read from the device.
|__String info tag
配置描述符信息:
C:* #Ifs=dd Cfg#=dd Atr=xx MPwr=dddmA
| | | | | |__MaxPower in mA
| | | | |__Attributes
| | | |__ConfiguratioNumber
| | |__NumberOfInterfaces
| |__ "*" indicates the active configuration (others are " ")
|__Config info tag
USB设备可能有多种配置,每一种都有不同的行为。例如,总线供电的配置可能比自供电的配置能力差得多。
一次只能有一个设备配置处于活动状态;大多数设备只有一种配置。
每个配置由一个或多个接口。每个接口服务一个不同的“功能”,这通常是绑定到一个不同的USB设备驱动程序。
一个常见的例子是带有用于回放的音频接口的USB扬声器,以及用于软件音量控制的HID接口。
接口描述符信息:
I:* If#=dd Alt=dd #EPs=dd Cls=xx(sssss) Sub=xx Prot=xx Driver=ssss
| | | | | | | | |__Driver name
| | | | | | | | or "(none)"
| | | | | | | |__InterfaceProtocol
| | | | | | |__InterfaceSubClass
| | | | | |__InterfaceClass
| | | | |__NumberOfEndpoints
| | | |__AlternateSettingNumber
| | |__InterfaceNumber
| |__ "*" indicates the active altsetting (others are " ")
|__Interface info tag
给定接口可能有一个或多个“备用”设置。例如,默认设置可能只使用少量的周期带宽。
为了使用总线带宽的重要部分,驱动程序必须选择一个非默认的alt配置。
一个接口一次只能有一个设置是活动的,而且一次只能有一个驱动程序绑定到一个接口。大多数设备每个接口只有一个备用设置。
端点描述符信息:
E: Ad=xx(s) Atr=xx(ssss) MxPS=dddd Ivl=dddss
| | | | |__Interval (max) between transfers
| | | |__EndpointMaxPacketSize
| | |__Attributes(EndpointType)
| |__EndpointAddress(I=In,O=Out)
|__Endpoint info tag
对于所有周期端点(中断或同步),时间间隔都是非零的。对于高速端点,传输间隔可以用微秒而不是毫秒来测量。
对于高速周期端点,“MaxPacketSize”反映每微帧的数据传输大小。
对于“高带宽”端点,每个端点可以反射2或3个数据包(每125 usec最多可反射3KBytes)。
对于Linux-USB堆栈,周期性带宽保留使用urb提供的传输间隔和大小,可以小于端点描述符中的传输间隔和大小。
7.框架
USB驱动可以从两个角度去观察,一个是主机侧,一个是设备侧。Linux USB驱动的总体框架如下图所示:
从主机侧看usb驱动可分为四层:usb主机控制器硬件底层、usb主机控制器驱动、usb核心和usb设备驱动。在主机侧要实现的驱动主要分为两类:usb主机控制器驱动和usb设备驱动。主机控制器驱动负责控制插入其中的usb设备,usb设备驱动主要负责usb设备和主机的通信。usb核心向上为设备驱动提供编程接口,向下为usb控制器驱动提供编程接口,维护整个usb设备信息,完成设备热插拔控制,总线数据传输控制。可以看到这种设备驱动、核心层、主机控制器驱动这种三层结构的驱动框架,Linux内核中将主机控制器的驱动和外设端的驱动分离,通过一个核心层将某种总线的协议进行抽象,外设端的驱动调用核心层API间接过渡到主机驱动传输函数的调用。
温馨提示:
以上文章描述如有不清晰之处,欢迎在评论区评论,如有时间,会第一时间回复,谢谢!