USB设备驱动程序(二)

来源:互联网 发布:淘宝店铺怎么关联打印 编辑:程序博客网 时间:2024/06/08 17:12

USB设备驱动程序中的结构

Linux内核中,使用struct usb_driver结构描述一个USB驱动。

struct usb_driver {

int devnum; /*USB设备号*/

char devpath[16] ;  /*设置ID字符串*/

enum usb_device_state  state; /*设备状态:未连接,已配置*/

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

。。。。。。。。。。

struct usb_device_descriptor descriptor ; /*USB设备描述符*/

struct usb_host_config *config; /**/

。。。。。。。。。。

char *product; /*产品名*/

char *manufacture; /*厂商号*/

char *serial;  /*设备序列号*/

。。。。。。。。。

 

const char *name ;  /*驱动程序名*/

 

/*usb核心发现该驱动所能支持的USB接口时,调用该函数*/

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

 

/*当相应USB被移除时调用该函数*/

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

 

/*驱动所能支持的所有venderID 和 deviceID列表*/

const struct usb_device_id *id_table;  

}

 

Linux内核提供宏USB_DEVICE来定义一种USB设备:USB_DEVICE(vend, prod)

usb_register 注册USB驱动程序

Static inline int usb_register (struct usb_driver *driver);

 

Linux 内核使用struct usb_device_descriptor来描述USB描述符中的设备描述符,严格按照USB协议定义的:

struct usb_device_descriptor {

__u8 bLength;

…..

}__attribute__((packed)); /*按字节对齐*/

 

struct usb_host_config 用来描述一个USB配置,不是协议规定,而是Linux所特有的。

 

struct usb_host_config {

struct usb_config_descriptor desc ; /*配置描述符*/

char *string ; /*配置的字符串(如果存在)*/

……………………..

/*接口链表*/

struct usb_interface *interface[USB_MAXINTERFACE];

};

 

struct usb_config_descriptor 根据USB协议里面所配置的配置描述符的定义来制作的结构。

struct usb_config_descriptor  {

__u8 bLength;

__u8 bDescriptorType ;

……………………

}__attribute__((packed ));

 

struct usb_interface用来描述一个USB接口的设置。

 

struct usb_interface  {

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

 

struct usb_host_interface *cur_altsetting; /*当前设置*/

 

unsigned num_alsetting ; /*设置数*/

}

 

这里出现了新的概念设置,那么设置和配置有什么关系?

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

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

设置属于接口范畴里面的,配置比接口高一个层次。下面举个例子,手机可以有多个配置,比如可以作为电话,也可以接在PC上作为U盘,这里体现两种不同功能的组合,这里组合是属于配置的,配置就是一些功能的组合。那么把某一种功能选定,就把它作为一个手机,功能就定下来了,通话时可以调整一些通话模式(会议模式,室外模式),这就是在这个功能不变的前提下进行设置,还包括通话音量大小的设置,设置是在功能不变前提下的选择。

struct usb_host_interface用来描述USB接口设置。

 

struct usb_host_interface {

struct usb_interface_descriptor desc ; /*接口描述符*/

struct usb_host_endpoint *endpoint;  /*接口所包含的端点*/

}

 

 

struct usb_interface_descriptor对应USB协议当中的一个USB描述符,

 

struct usb_interface_descriptor {

__u8 bLenght;

__u8 bDescriptorType;

………………………….

} __attributte__((packed));

 

struct usb_device_endpoint用来描述USB端点:

 

struct usb_host_endpoint {

struct usb_endpoint_descriptor desc ; /*端点描述符*/

struct list_head  urb_list ; /*urb*/

}

struct usb_endpoint_descriptor 用来描述USB协议当中所对应的端点描述符。

 

本文讲了在Linux Kernel 中如何以特有的方式来描述设备、配置、接口、端点,同样Linux遵循协议规范所定义的一些描述符。 

下面是

USB中的URB

USB请求块(USB request block, urb)是USB设备驱动中用来描述与USB设备通信所用的基本载体和核心数据结构,承载USB通信中传输包的信息,是USB主机与设备通信的“电波”。

设备驱动程序是围绕URB展开的,下面为URB处理流程

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

2. USB core 提交该urbUSB主控制器驱动程序;

3. USB主控制程序根据URB描述的信息,来访问USB设备;

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

 

创建URB

创建函数struct urb*usb_alloc_urb(int iso_packets, gfp_t mem_flags)

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

mem_flags: 内存分配标志。

 

初始化URB ,对于不同有不同URB初始化函数。

如果这次访问是中断传输,则初始化中断URB使用usb_fill_int_urb函数初始化

static inline void usb_fill_int_urb(struct urb *urb,  //要初始化urb指针

    struct usb_device *dev,   //urb访问USB设备结构

    unsigned int pipe, //端点对应的管道,从端点(设备缓冲区)中取数据,放到驱动程序缓冲区,这两者之间虚拟通道

    void *transfer_buffer ,  //驱动程序缓冲区,读完数据后,从设备里读数据完成后,数据存放在transfer_buffer所指定的地方  

    int buffer_length,  //缓冲区长度

    usb_complete_t complete_fn,  //流程第四步,USB core 调用函数,通知USB设备驱动

    void *context,   //通常取值dev

    int interval   //urb被调度时间间隔,隔多长时间发起urb)

 

对于批量urb,使用usb_fill_bulk_urb 函数初始化;

对于控制urb,使用usb_fill_control_urb函数完成初始化;

 

创建并初始化urb后,就通过USB core 提交URB,开始真正的数据传输,通过

int usb_submit_urb(struct urb *urb, gfp_t mem_flags)函数提交给USB coreUSB core再将其交给主控制器,主控制器再根据里面的URB信息,访问USB设备的端点,将数据填到buffer里来,结束后USB core将控制权交给USB设备驱动。

参数:urb: 指向urb的指针。

处理URB

URB被提交给到USB核心后,USB核心将指定usb主控制器驱动来处理该URB,在3种情况下,urb被认为处理完成:

1. urb被成功送给设备,并且设备返回正确的确认,如果urb->status0,意味着对于一个成功输出的urb

2. 如果发送数据到设备或从设备接收数据时发生错误,urb->status将记录错误值。

3. urb被取消,驱动通过usb_unlink_urb()usb_kil_urb()函数取消urb

 

urb处理完成后,urb完成函数将被调用。


0 0