一、urb:
usb请求块urb(usb request block,urb)是usb设备驱动中用来描述
与usb设备通信所用的基本载体和核心数据结构。类似网络设备驱动中的sk_buff结构体。
是usb主机和设备通信的“电波”。
//USB Request Block:usb请求块
struct urb
{
//* private: usb core and host controller only fields in the urb
struct kref kref;
//* urb引用计数
void *hcpriv;
//* 主控制器的私有数据
atomic_t use_count;
//* 并发的提交计数
atomic_t reject;
//* 提交将失败
int unlinked;
//* unlink的错误码
//* public: documented fields in the urb that can be used by drivers
struct list_head urb_list;
//* list head for use by the urb's * current owner
struct list_head anchor_list;
//* urb链表
struct usb_anchor *anchor;
struct usb_device *dev;
//* 指向usb设备
struct usb_host_endpoint *ep;
//* 指向端点的数据结构,最终将取代pipe
unsigned int pipe;
//* 持有端点的信息,如:端点号、方向、类型等等
unsigned int stream_id;
//* 对bluk流有效,指端点的流ID
int status;
//* 状态
unsigned int transfer_flags; //* 各种flags用来指示urb如何被提交、ublink以及操作
//* 传输缓冲区,对输入端口来说,该缓冲区存储输入的数据对于输出端口来说,数据从缓冲区输出
void *transfer_buffer;
//当transfer_flags 使用URB_NO_TRANSFER_DMA_MAP,优先使用transfer_dma,而不是transfer_buffer
dma_addr_t transfer_dma;
struct scatterlist *sg;
//* 分散/搜集buffer链表
int num_mapped_sgs;
//* (internal) 映射的sg的入口
int num_sgs;
//* (in) sg链表中入口的数量
u32 transfer_buffer_length;
//* (in) buffer的长度
u32 actual_length;
//* (return) 实际传输的长度
unsigned char *setup_packet;
//* (in)仅用于控制传输,指向8 byte,就是usb协议里面分析的那8个控制字节
dma_addr_t setup_dma;
//* (in) dma addr for setup_packet
int start_frame;
//* (modify)返回同步传输的首帧
int number_of_packets;
//* (in) 同步传输的包的数量
int interval;
//* (modify) 指定中断初始或者同步传输的查询周期(INT/ISO)
int error_count;
//* (return) 同步传输的错误数
void *context;
//* (in) context for completion
usb_complete_t complete;
//* (in) 完成函数
//用于提供同步传输缓冲区数组,并且搜集每个缓冲区的传输状态
struct usb_iso_packet_descriptor iso_frame_desc[0];
//* (in) ISO ONLY
};
urb处理流程:
1、usb设备驱动程序 创建 并 初始化 一个访问特定usb设备特定端点的urb,并提交给usb core; //usb设备驱动程序工作。
1)创建urb函数:struct urb *usb_alloc_urb(int iso_packets,gfp_t mem_flags);
参数:iso_packets:urb所包含的等时数据包的个数。
mem_flags
:内存分配标示(gfp_kernel);
2)初始化urb,对于中断urb,使用usb_fill_int_urb函数初始化:
static inline void usb_fill_int_urb(struct urb *urb, //要初始化的urb指针
struct usb_device *dev, //所以访问的设备
unsigned int pipe, //要访问的端点对应的管道,使用usb_sndintpipe()或usb_rcvintpipe()创建,
(管道:驱动程序的数据缓冲区与一个端点的连接,它代表一种在两者之间移动数据的能力)
void *transfer_buffer, //要传输的数据的缓冲区
int buffer_length, //缓冲区的长度
usb_complete_t complete_fn, //完成urb所请求的操作时要调用的回调函数
void *context, //complet_fn函数所需的上下文,通常取dev;
int interval) //urb被调度的时间间隔
3)对于批量urb用usb_fill_bulk_urb来初始化。
4)对于控制urb用usb_fill_control_urb函数来初始化
5)等时urb没有初始化函数,只能自己手动加入。
6)当 urb创建和初始化后urb通过 usb_submit_urb 函数提交给usb核心;
int usb_submit_urb(struct urb *urb,gfp_t mem_flags);
参数:urb指向urb的指针,mem_flags:内核分配标识,用于告知usb核心如何分配内存缓冲区。
7)urb被提交到usb核心后,usb核心指定usb主控制器驱动程序来处理urb,以下3中被认为处理完成。
7.1) urb被成功发送给设备,并且设备返回成功确认。如果urb->status为0,意味着对于一个输出urb,
数据被成功发送;对于一个输入urb,请求的数据被成功收到。
7.2)如果发送数据到设备或从设备接受数据时发生了错误,urb->status将记录错误值。
7.3)urb被“取消”,这发生在驱动通过usb_unlink_urb()或usb_kill_urb()函数取消urb,
或urb虽已提交,而usb设备被拔出的情况下当urb处理完成后,urb完成函数将被调用。
2、usb core提交该urb到usb主控制器驱动程序;
//由usb core工作。
3、usb 主控制器驱动程序根据该urb描述的信息,来访问usb设备。 //由主控制器工作
4、当设备访问结束后,usb主控制器驱动程序通知usb设备驱动程序。 //由主控制器工作