USB设备---URB请求快

来源:互联网 发布:java调用http接口json 编辑:程序博客网 时间:2024/05/17 02:31

1.urb 结构体

USB 请求块(USB request block,urb)是USB 设备驱动中用来描述与USB 设备通信所用的基本载体和核心数据结构,非常类似于网络设备驱动中的sk_buff 结构体。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
struct urb {
/* 私有的:只能由USB 核心和主机控制器访问的字段 */
struct kref kref; /*urb 引用计数 */
void *hcpriv; /* 主机控制器私有数据 */
atomic_t use_count; /* 并发传输计数 */
u8 reject; /* 传输将失败*/
int unlink; /* unlink 错误码 */
 /* 公共的: 可以被驱动使用的字段 */
 struct list_head urb_list; /* 链表头*/
struct usb_anchor *anchor;
 struct usb_device *dev; /* 关联的USB 设备 */
 struct usb_host_endpoint *ep;
unsigned int pipe; /* 管道信息 */
 int status; /* URB 的当前状态 */
 unsigned int transfer_flags; /* URB_SHORT_NOT_OK | ...*/
 void *transfer_buffer; /* 发送数据到设备或从设备接收数据的缓冲区 */
 dma_addr_t transfer_dma; /*用来以DMA 方式向设备传输数据的缓冲区 */
 int transfer_buffer_length;/*transfer_buffer 或transfer_dma 指向缓冲区的大小 */
 
 int actual_length; /* URB 结束后,发送或接收数据的实际长度 */
 unsigned char *setup_packet; /* 指向控制URB 的设置数据包的指针*/
 dma_addr_t setup_dma; /*控制URB 的设置数据包的DMA 缓冲区*/
 int start_frame; /*等时传输中用于设置或返回初始帧*/
 int number_of_packets; /*等时传输中等时缓冲区数量 */
 int interval; /* URB 被轮询到的时间间隔(对中断和等时urb 有效) */
 int error_count; /* 等时传输错误数量 */
 void *context; /* completion 函数上下文 */
 usb_complete_t complete; /* 当URB 被完全传输或发生错误时,被调用 */
 /*单个URB 一次可定义多个等时传输时,描述各个等时传输 */
 struct usb_iso_packet_descriptor iso_frame_desc[0];
};

2.urb 处理流程

USB 设备中的每个端点都处理一个urb 队列,在队列被清空之前,一个urb 的典型生命周期
如下。

(1)被一个USB 设备驱动创建。 (创建URB)

创建urb 结构体的函数为:
struct urb *usb_alloc_urb(int iso_packets, int mem_flags);
iso_packets 是这个urb 应当包含的等时数据包的数目,若为0 表示不创建等时数据包。
mem_flags 参数是分配内存的标志,和kmalloc()函数的分配标志参数含义相同。如果分配成功,该函数返回一个urb 结构体指针,否则返回0。
urb 结构体在驱动中不能静态创建,因为这可能破坏USB 核心给urb 使用的引用计数方法。

usb_alloc_urb()的“反函数”为:
void usb_free_urb(struct urb *urb);
该函数用于释放由usb_alloc_urb()分配的urb 结构体。

(2)初始化,被安排给一个特定USB 设备的特定端点。(填充URB)

对于中断urb,使用usb_fill_int_urb()函数来初始化urb,如下所示:
void usb_fill_int_urb(struct urb *urb, 
                                   struct usb_device *dev,
                                   unsigned int pipe, 
                                   void *transfer_buffer,
                                   int buffer_length,
                                   usb_complete_t complete,
                                   void *context, 
                                   int interval);
urb 参数指向要被初始化的urb 的指针;dev 指向这个urb 要被发送到的USB 设备;pipe 是这个urb 要被发送到的USB 设备的特定端点;transfer_buffer 是指向发送数据或接收数据的缓冲区的指针,和urb 一样,它也不能是静态缓冲区,必须使用kmalloc()来分配;buffer_length 是transfer_buffer 指针所指向缓冲区的大小;complete 指针指向当这个 urb 完成时被调用的完成处理函数;context 是完成处理函数的“上下文”;interval 是这个urb 应当被调度的间隔
上述函数参数中的pipe 使用usb_sndintpipe()或usb_rcvintpipe()创建。

对于批量urb,使用usb_fill_bulk_urb()函数来初始化urb,如下所示:
void usb_fill_bulk_urb(struct urb *urb, struct usb_device *dev,unsigned int pipe, void *transfer_buffer,int buffer_length, usb_complete_t complete,void *context);
除了没有对应于调度间隔的interval 参数以外,该函数的参数和usb_fill_int_urb()函数的参数含义相同。
上述函数参数中的pipe 使用usb_sndbulkpipe()或者usb_rcvbulkpipe()函数来创建。


对于控制 urb,使用usb_fill_control_urb()函数来初始化urb,如下所示:
void usb_fill_control_urb(struct urb *urb, struct usb_device *dev,unsigned int pipe, unsigned char *setup_packet,void *transfer_buffer, int buffer_length,usb_complete_t complete, void *context);
除了增加了新的setup_packet 参数以外,该函数的参数和usb_fill_bulk_urb()函数的参数含义相同。setup_packet 参数指向即将被发送到端点的设置数据包。
上述函数参数中的pipe 使用usb_sndctrlpipe()或usb_rcvictrlpipe()函数来创建。

(3)被USB 设备驱动提交给USB 核心。(提交URB)

在完成第(1)、(2)步的创建和初始化urb 后,urb 便可以提交给USB 核心,通过usb_submit_urb()函数来完成,如下所示:
int usb_submit_urb(struct urb *urb, int mem_flags);
urb 参数是指向urb 的指针,mem_flags 参数与传递给kmalloc()函数参数的意义相同,它用于告知USB 核心如何在此时分配内存缓冲区。
在提交urb 到USB 核心后,直到完成函数被调用之前,不要访问urb 中的任何成员。


usb_submit_urb()在原子上下文和进程上下文中都可以被调用,mem_flags 变量需根据调用环
境进行相应的设置,如下所示。
GFP_ATOMIC:在中断处理函数、底半部、tasklet、定时器处理函数以及urb 完成函数中,在调用者持有自旋锁或者读写锁时以及当驱动将current→state 修改为非 TASK_RUNNING 时,应使用此标志。
GFP_NOIO:在存储设备的块I/O 和错误处理路径中,应使用此标志;
GFP_KERNEL:如果没有任何理由使用GFP_ATOMIC 和GFP_NOIO,就使用GFP_KERNEL。

如果usb_submit_urb()调用成功,即urb 的控制权被移交给USB 核心,该函数返回0;否则,
返回错误号。

(4)提交由USB 核心指定的USB 主机控制器驱动。
(5)被USB 主机控制器处理,进行一次到USB 设备的传送。

第(4)~(5)步由USB 核心和主机控制器完成,不受USB 设备驱动的控制。

(6)当urb 完成,USB 主机控制器驱动通知USB 设备驱动。

(处理URB)

在如下3 种情况下,urb 将结束,urb 完成函数将被调用
1、urb 被成功发送给设备,并且设备返回正确的确认。如果urb→status 为0,意味着对于一个输出urb,数据被成功发送;对于一个输入urb,请求的数据被成功收到。
2、如果发送数据到设备或从设备接收数据时发生了错误,urb→status 将记录错误值。
3、urb 被从USB 核心“去除连接”,这发生在驱动通过usb_unlink_urb()或usb_kill_urb()函数取消urb,或urb 虽已提交,而USB 设备被拔出的情况下。

当urb 生命结束时(处理完成或被解除链接),通过urb 结构体的status 成员可以获知其原因
如0 表示传输成功,-ENOENT 表示被usb_kill_urb()杀死,-ECONNRESET 表示被usb_unlink_urb()
杀死,-EPROTO 表示传输中发生了bitstuff 错误或者硬件未能及时收到响应数据包,-ENODEV
表示USB 设备已被移除,-EXDEV 表示等时传输仅完成了一部分等。


对以上urb 的处理步骤进行一个总结,图20.5 给出了一个urb 的整个处理流程,虚线框的usb_unlink_urb()和usb_kill_urb()并非一定会发生,它只是在urb 正在被USB 核心和主机控制器处理时,被驱动程序取消的情况下才发生。

转自:https://www.cnblogs.com/chd-zhangbo/p/5261045.html
阅读全文
'); })();
0 0
原创粉丝点击
热门IT博客
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 韩式刘海男 没有刘海的男发型 两边短中间刘海男发型 没有刘海的发型男 发型男图片刘海 刘海科 刘海粟书法价格 刘海粟山水画 刘海粟小学 刘海粟取自什么成语 刘海吕红一家人 网红空气刘海图片 网红齐刘海 网红刘海怎么卷 2018网红刘海 网红刘海发型图片 刘海若事件 刘海若现在的真实状况 刘海蓝 刘海戏金蟾寓意 刘海戏金蟾在线播放 刘海戏金蟾免费观看 刘海戏金蟾图片 花鼓戏刘海戏金蟾 刘海不贴额头 刘海贴怎么用图解 凯立德导航家园版 波西米亚风刘海编发 刘海鹰 刘海龙被砍后照片 龙须刘海图片 龙须刘海怎么剪 如何剪龙须刘海 龙须刘海剪法配图 柳海龙打死人事件 自己在家怎么弄龙须刘海 刘润东 刘润南 刘润潼 刘温暖君涵轩 君涵轩刘温暖全文免费