Linux USB基础

1、USB基础

USB(Universal Serial Bus),通用串行总线,是一种外部总线标准,用于规范电脑与外部设备的连接和通讯。

USB主要优点:

1)支持热插拔

2)携带方便

3)标准统一

4)可以连接多个设备

每条USB总线上最多可以接127个设备

 

USB主控制器:

负责处理主机与设备之间的电器和协议层的互联,常见的USB主控制器规格有:

1)OHCI:主要是非PC系统上的USB芯片,如ARM

2)UHCI:大多是Intel和Via主板上的USB控制器芯片,都是由USB1.1规格的

3)EHCI:由Intel等几个厂商研发,兼容OHCI,UHCI,遵循USB2.0规范

每个USB Host控制器都会自带一个USB Hub,称为根(Root)Hub。当USB设备插入到USB Hub或从上面拔出时,都会发出电信号通知系统

USB设备逻辑结构:

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

1)配置代表功能的集合(功能组合)

2)接口代表一个基本的功能,是USB设备驱动程序控制的对象,(一个接口需要一个USB驱动程序)一个功能复杂的USB设备可以具有多个接口

例如:

一个USB播放器带有音频、视频功能,还有旋钮和按钮

配置1:音频+旋钮

配置2:音频+视频+按钮

配置3:视频+旋钮

音频接口、视频接口、按钮接口和旋钮接口均需要一个驱动程序

USB设备中唯一可寻址部分是设备端点,它位于USB设备或主机上的一个数据缓冲区,用来存放和发送USB的各种数据。主机和涉笔的通信最终作用于设备上的哥哥端点,它是主机与设备间通信流的一个逻辑终端。

每个USB设备有一个唯一的地址,这个地址是在设备连上主机时,由主机分配的,而设备中的每个端点在设备内存有唯一的端点号,这个端点号时在设计设备时给定的。

每个端点都是一个简单的连接点,或者支持数据流进设备,或者支持数据流出设备,两者不可兼得

基于PnP机制,设备被枚举时,它必须 向主机报告各个端点的特性,包括端点号、通信方向、端点支持的最大包大小、带宽要求等(其中端点支持的最大包大小叫做数据有效负载)。

每个设备必须有端点0,它用于设备枚举和对设备进行一些基本的控制功能。除了端点0,其他端点在设备配置之前不能与主机通信,只有向主机报告这些端点的特性并被确认后才能被激活

USB描述符:

在每一个USB设备内部,都包含一组固定格式的数据,通过这些数据,USB主机就可以获取USB设备的类型、生产厂商等信息,称为USB描述符

标准的USB设备有5种USB描述符:设备描述符、配置描述符、接口描述符、端点描述符和字符串描述符

一个设备只有一个设备描述符,一个设备描述符可以包含多个配置描述符,一个配置描述符可以包含多个接口描述符,一个接口描述符使用几个端点就有几个端点描述符

1)设备描述符----Standard Device Descriptor,长度为18字节

bLength:描述符长度,固定为0x12

bDescriptorType:设备描述符类型,固定为0x01

bcdUSB:USB规范发布号,表示了本设备能适用于哪种协议,如2.0=0200

bDeviceClass:类型代码

bDeviceSubClass:子类型代码

bDeviceProtocol:协议代码

bMaxPacketSize0:端点0最大分组大小

idVendor:供应商ID

idProduct:产品ID(由厂商分配)

bcdDevice:设备出产编码,由厂家自行设置

iManufacturer:厂商描述符字符串索引,索引到对应的字符串描述符。为0则表示没有

iProduct:产品描述符字符串索引

iSerialNumber:设备序列号字符串索引

bNumConfigurations:可能的配置数

2)配置描述符----Standard Configuration Descriptor,长度为8字节

bLength:描述符长度,固定为0x09

bDescriptorType:设备描述符类型,固定为0x02

wTotalLength:返回整个数据的长度,指此配置返回的配置描述符,接口描述符以及端点描述符的全部大小

bNumInterface:配置所支持的接口数,指该配置配备的接口数量,也表示该配置下接口描述符数量

bConfigurationValue:作为Set Configuration的一个参数选择配置值

iConfiguration:用于描述该配置字符串描述符的索引

bmAttribute:供电模式选择,Bit4-0保留,D7:总线供电,D6:自供电, D5:远程唤醒

MaxPower:总线供电的USB设备的最大消耗电流,以2mA为单位

3)接口描述符-----Standard Interface Descriptor,长度为8字节

bLength:描述符长度,固定为0x09

bDescriptorType:接口描述符类型:固定为0x04

bInterfaceNumber:该接口的编号

bAlterfaceSetting:用于为上一次字段选择可供替换的设置

bNumEndpoint:使用的端点数目,端点0除外

bInterfaceClass:类型代码(由USB组织分配)

bInterfaceSubClass:子类型代码(由USB组织分配)

iInterface:字符串描述符的索引

4)端点描述符-----Standard Endpoint Descriptor,长度为7字节

USB传输:

1)等时传输

用来连接对数据的正确性要求不高而对时间极为敏感的外部设备,如麦克风、音箱及电话等。

等时传输以固定的传输速率,连续不断地在主机与USB设备之间传输数据,在传输数据发生错误时,USB并不处理这些错误,而是继续传送新的数据

2)中断传输

传输的数据量小,但是这些数据需要及时处理以达到实时效果,此方式主要用在键盘、鼠标以及游戏手柄等外部设备上。当USB宿主要求设备传输数据时,中断端点会以一个固定的速率传输数据。由CPU主动发起

3)控制传输

用于传输设备控制指令、设备状态查询及确认命令

4)批量传输

该方式用来传输要求正确无误的数据,通常打印机,扫描仪和数码相机以这种方式与主机连接

事务:

一次传输由一个或多个事务(transaction)构成,事务可分为In事务、Out事务,Setup事务

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

一个包由多个域构成,域可分为同步域(SYNC)、标识域(PID)、地址域(ADDR)、端点域(ENDP)、帧号域(FRAM)、数据域(DATA)以及校验域(CRC).

设备枚举:

枚举是让HOST认得这个USB设备,并且为该设备准备资源,建立好主机和设备之间的数据传递机制

1)获取设备描述符

2)复位

3)设置地址

4)再次获取设备描述符

5)获取配置描述符

6)获取接口、端点描述符

7)获取字符串描述符

8)选择设备配置

2、Linux usb驱动

主控制器驱动、设备驱动、UDC驱动(设备控制器)、gadget驱动(小模块)

在linux内核中,使用struct usb_driver结构来描述一个USB驱动

struct usb_driver

{

const char *name;

/* 当USB核心发现该驱动能够处理的USB接口时,调用该函数 */

int (*probe) (struct usb_interface *intf,const struct usb_device_id *id);

/* 当相应的USB接口被移除时,调用该函数 */

void (*distconnect) (struct usb_interface *intf);

/* USB驱动能够处理的设备列表 */

const struct usb_device_id *id_table;

};

Linux内核提供了宏USB_DEVICE来定义一种USB设备的USB_DEVICE(Vend,prod); //Vend: USB Vendor ID ,prod: USB Product ID

//注册USB驱动

usb_register(struct usb_driver *driver);

Linux内核使用struct usb_device 来描述一个USB设备

struct usb_device

{

int devnum;

enum usb_device_state; //设备状态

enum usb_device_speed speed; //高速,全速,低速

......

struct usb_device_descriptor descriptor; //USB设备描述符,和协议一致

.......

char *product;

....

};

Linux内核使用struct usb_host_config来描述一个USB配置

struct usb_host_config

{

struct usb_config_descriptor desc; //配置描述符

.......

};

一个配置包含多个接口,一个接口包含一个或多个设置

Linux内核使用struct usb_host_endpoint来描述USB端点:

struct usb_host_endpoint

{

struct usb_endpoint_descriptor desc; //端点描述符

struct list_head *usr_list ;

};

3、URB

USB请求块(USB request block,URB),USB设备驱动中用来描述与USB设备通信所用的基本载体和核心数据结构。

URB处理流程:

1)USB设备驱动程序创建并初始化一个访问特定USB设备特定端点的urb,并提交给USB Core

2)USB Core提交该urb到USB主控制器驱动程序

3)USB主控制器驱动程序根据该URB描述的信息来访问USB设备

4)当设备访问结束后,USB主控制器驱动程序通知USB设备驱动程序

//创建URB

struct urb *usb_alloc_urb(int iso_packets,gfp_t mem_flags);

iso_packets:urb所包含的等时数据包的个数

mem_flags: 内存分配标识

//初始化URB

对于中断URB,使用usb_fill_int_urb函数来初始化

对于批量URB,使用usb_fill_bulk_urb函数来初始化

对于控制URB,使用usb_fill_control_urb函数来初始化

等时urb,只能手动初始化urb

//处理URB

urb被提交到USB核心后,USB核心指定USB主控制器驱动程序来处理该urb。在3种情况下,urb会被认为为处理完成。

1)urb被成功发送到设备,并且设备返回正确的确认,urb->status = 0,表示成功

2)发送数据到设备或从设备接受数据时发生错误时,urb->status将记录错误值

3)urb被“取消”,发生在驱动通过usb_unlink_urb()或usb_kill_urb()函数取消urb,或urb虽已提交,而USB设备被拔出的情况下

Linux 内核使用struct usb_interface 来藐视一个USB接口

struct usb_interface

{

struct usb_host_interface *alsetting; //接口设置数组

struct usb_host_interface * cur_altsetting; //当前设置

unsigned num_altsetting; //设置数

};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值