1.LINUX USB架构
USB通信都是由host端发起的。USB设备驱动程序分配并初始化一个URB发给USB Core,USB Core改一改,发给USB主机控制器驱动,USB主机控制器驱动把它解析成包,在总线上进行传送。USB Core是由内核实现的,其实也就是把host control driver里的功能更集中的向上抽象了一层,它是用来对最上层的USB设备驱动屏蔽掉host control的不同。
2.在内核中的位置
USB驱动程序存在于不同的内核子系统和USB硬件控制器之中。USB核心为USB驱动程序提供了一个用于访问和控制USB硬件的接口。而不必考虑系统当前存在的各种不同类型的USB硬件控制器。
3.USB设备的构成,包括配置,接口和端点
上图描述了linux USB设备的结构层次。每一个interface代表一个功能,对应有一个驱动程序。
4.USB设备驱动描述
在linux内核中,使用structusb_driver结构描述一个USB驱动。
struct usb_driver {
const char *name; /* 驱动程序名 */
/* 当USB核心发现了该驱动能够处理的USB接口时,调用该函数 */
int (*probe) (structusb_interface *intf,
const struct usb_device_id *id);
/* 当相应的USB接口被移除时,调用该函数*/
void (*disconnect)(struct usb_interface *intf);
/* USB驱动能处理的设备列表 */
const structusb_device_id *id_table;
……
};
USB设备的枚举过程和我们通常看到设备稍有不同,比如I2C设备,我们需要在板文件中去注册I2C设备的信息(比如设备名和一些硬件配置信息),而USB总线会自动去枚举USB设备,只要能与id_table匹配,就能枚举成功,然后加载相应的驱动程序。
5.USB设备描述
Linux内核使用struct usb_device来描述一个USB设备
struct usb_device {
int devnum; /*USB设备号*/
char devpath[16]; /* 设备ID字符串 */
enum usb_device_state state; /* 设备状态:未连接,已配置*/
enum usb_device_speed speed; /* 高速,全速,低速*/
struct usb_device*parent;
struct usb_bus *bus;
structusb_host_endpoint ep0;
struct device dev;
structusb_device_descriptor descriptor; /* USB设备描述符,根据USB协议来定义的*/
struct usb_host_config*config;
struct usb_host_config*actconfig;
structusb_host_endpoint *ep_in[16];
structusb_host_endpoint *ep_out[16];
/* static strings fromthe device */
char *product; /* 产品号 */
char *manufacturer; /* 生产商 */
char *serial; /* 设备串号 */
};
6.USB描述符
在linux 内核中定义一下几种描述符结构体,都是严格按照USB协议来定义:
设备描述符:关于设备的通用信息,如生产商ID,产品ID等;
配置描述符:此配置中的接口数,支持的挂起和恢复能力以及功率要求;
接口描述符:接口类,子类和适用的协议,接口备用配置的数码和端点数目;
端点描述符:端点地址,方向和类型,支持的最大包大小,如果是中断类型的端点则还包括轮询频率。
字符串描述符:在其他描述符中会为某些字段提供字符串索引,他们可悲用来检索描述性字符串。
7.URB
USB请求块(USBrequest block,URB)是USB设备驱动中用来描述与USB设备通信所用的基本载体和核心数据结构,非常类似于网络设备驱动中的sk_buff结构体。
1. USB设备驱动程序创建并初始化一个访问特定USB设备特定端点的URB,并提交给USB core;
2. USB core提交该URB到USB主控制器驱动程序;
3. USB主控制器驱动程序根据该URB描述的信息,来访问USB设备;
4. 当设备访问结束后,USB主控制驱动程序通知USB设备驱动程序。