转自:http://blog.csdn.net/myarrow/article/details/7025065

版权声明:本文为博主原创文章,未经博主允许不得转载。

一、 transfer_flags

/*
 * urb->transfer_flags:
 *
 * Note: URB_DIR_IN/OUT is automatically set in usb_submit_urb().
 */
#define URB_SHORT_NOT_OK 0x0001   /* report short reads as errors */
#define URB_ISO_ASAP  0x0002            /* iso-only, urb->start_frame ignored */
#define URB_NO_TRANSFER_DMA_MAP 0x0004    /* urb->transfer_dma valid on submit */
#define URB_NO_SETUP_DMA_MAP 0x0008     /* urb->setup_dma valid on submit */
#define URB_NO_FSBR  0x0020      /* UHCI-specific */
#define URB_ZERO_PACKET  0x0040    /* Finish bulk OUT with short packet */
#define URB_NO_INTERRUPT 0x0080   /* HINT: no non-error interrupt  needed */
#define URB_FREE_BUFFER  0x0100   /* Free transfer buffer with the URB */

#define URB_DIR_IN  0x0200       /* Transfer from device to host */
#define URB_HCD_DRIVER_TEST 0xFFFF   /* Do NOT hand back or free this URB */
#define URB_DIR_OUT  0
#define URB_DIR_MASK  URB_DIR_IN

1. URB_SHORT_NOT_OK

这个标记只对用来从IN 端点读取数据的urb 有效,意思就是说如果从一个IN 端点那里读取了一个比较短的数据包,就可以认为是错误的。那么这里的

short 究竟short
到什么程度?之前说到端点的时候,就知道端点描述符里有一个叫wMaxPacketSize
这样的东东,指明了端点一次能够处理的最大字节数。每个端点描述符里的wMaxPacketSize
所表示的最大字节数都包括了哪些部分?是整个packet的长度么?我可以负责任的告诉你,它只包括了Data
包里面数据字段,俗称datapayload,其它那些七大姑八大姨什么的都是协议本身需要的信息,和TCP/IP 里的报头差不多。

wMaxPacketSize 与short 有什么关系? 关系还不小, short
不short 就是与wMaxPacketSize 相比的,如果从IN 端点那儿收到了一个比wMaxPacketSize
要短的包,同时也设置了URB_SHORT_NOT_OK
这个标志,那么就可以认为传输出错了。本来如果收到一个比较短的包是意味着这次传输到此为止就结束了,你想想data payload 的长度最
大必须为wMaxPacketSize
这个规定是不可违背的了,但是如果端点想给你的数据不止那么多,怎么办?就需要分成多个wMaxPacketSize 大小的data payload
来传输,事情有时不会那么凑巧,刚好能平分成多个整份,这时,最后一个data payload 的长度就会比wMaxPacketSize
要小,这种情况本来意味着端点已经传完了它想传的,释放完了自己的需求,这次传输就该结束了,不过如果你设置了URB_SHORT_NOT_OK
标志,HCD 这边就会认为错误发生了。

2. URB_ISO_ASAP
这个标志只是为了方便等时传输用的。等时传输和中断传输在spec 里都被认为是periodic
transfers,也就是周期传输,咱们都知道在usb
的世界里都是主机占主导地位,设备是没多少发言权的,但是对于等时传输和中断传输,端点可以对主机表达自己一种美好的期望,希望主机能够隔多长时间访问自己一次,这个期望的时间就是这里说的周期。当然,期望与现实是有一段距离的,如果期望的都能成为现实,咱们还研究usb干吗。端点的这个期望能不能得到满足,要看主机控制器答应不答应。对于等时传输,一般来说也就一帧(微帧)一次,主机那儿也很忙,再多也抽不出空儿来。那么如果你有个用于等时传输的urb,你提交给HCD
的时候,就得告诉HCD 它应该从哪一帧开始的,就要对下面要说的那个start_frame 赋值,也就是说告诉HCD
等时传输开始的那一帧(微帧)的帧号,如果你留心,应该还会记得前面说过在每帧或微帧(Mircoframe)的开始都会有个SOF Token
包,这个包里就含有个帧号字段,记录了那一帧的编号。这样的话,一是比较烦,还要去设置这个start_frame,你说烦不烦,二是到你设置的那一帧的时候,如果主机控制器没空开始等时传输,你说怎么办,要知道usb
的世界里它可是老大。于是,就出现了URB_ISO_ASAP,它的意思就是告诉HCD
啥时候不忙就啥时候开始,就不用指定什么开始的帧号了,是不是感觉特轻松?所以说,你如果想进行等时传输,又不想标新立异的话,就还是把它给设置了吧。

3. URB_NO_TRANSFER_DMA_MAP & URB_NO_SETUP_DMA_MAP
这两个标志都是有关DMA 的,什么是DMA?就是外设,比如咱们的usb 摄像头,和内存之间直接进行数据交换,把CPU 给撇一边儿了。

一般来说,都是驱动里提供了kmalloc 等分配的缓冲区,HCD 做一定的DMA
映射处理,DMA
映射是干吗的?外设和内存之间进行数据交换,总要互相认识吧,外设是通过各种总线连到主机里边儿的,使用的是总线地址,而内存使用的是虚拟地址,它们之间本来就是两条互不相交的平行线,要让它们中间产生连接点,必须得将一个地址转化为另一个地址,这样才能找得到对方,才能互通有无,而DMA
映射就是干这个的。为了分担点HCD 的压力,于是就有了这里的两个标志,告诉HCD
不要再自己做DMA 映射了,驱动提供的urb 里已经提供有DMA 缓冲区地址,为领导分忧解难是咱们这些小百姓应该做的事情。具体提供了哪些DMA
缓冲区?就涉及到下面的transfer_buffer,transfer_dma,还有setup_packet,setup_dma 这两对儿了。

4. URB_ZERO_PACKET
这个标志表示批量的OUT 传输必须使用一个short packet
来结束。批量传输的数据大于批量端点的wMaxPacketSize 时,需要分成多个Data 包来传输,最后一个data payload
的长度可能等于wMaxPacketSize,也可能小于,当等于wMaxPacketSize 时,如果同时设置了URB_ZERO_PACKET
标志,就需要再发送一个长度为0 的数据包来结束这次传输,如果小于wMaxPacketSize
就没必要多此一举了。你要问,当批量传输的数据小于wMaxPacketSize
时那?也没必要再发送0 长的数据包,因为此时发送的这个数据包本身就是一个short packet。

5. URB_NO_INTERRUPT
这个标志用来告诉HCD,在URB 完成后,不要请求一个硬件中断,当然这就意味着你的结束处理函数可能不会在urb 完成后立即被调用,而是在之后的某个时间被调用,咱们的usb core 会保证为每个urb 调用一次结束处理函数。

二、transfer_buffer & transfer_dma & transfer_buffer_length

管道的一端是主机上的缓冲区,一端是设备上的端点,这三个家伙就是描述主机上的那个缓冲区的。transfer_buffer 是使用kmalloc 分配的缓冲区,transfer_dma 是使用usb_buffer_alloc分配的dma
缓冲区,HCD 不会同时使用它们两个,如果你的urb
自带了transfer_dma,就要同时设置URB_NO_TRANSFER_DMA_MAP
来告诉HCD 一声,不用它再费心做DMA 映射了。transfer_buffer 是必须要设置的,因为不是所有的主机控制器都能够使用DMA
的,万一遇到这样的情况,也好有个备用。transfer_buffer_length指的就是transfer_buffer
或transfer_dma 的长度。

三、setup_packet & setup_dma

同样是两个缓冲区,一个是kmalloc分配的,一个是用usb_buffer_alloc分配的,不过,这两个缓冲区是控制传输专用的,记得struct
usb_ctrlrequest不?它们保存的就是一个struct
usb_ctrlrequest结构体,如果你的urb设置了setup_dma,同样要设置URB_NO_SETUP_DMA_MAP标志来告诉HCD。如果进行的是控制传输,setup_packet是必须要设置的,也是为了防止出现主机控制器不能使用DMA的情况。

四、start_frame

如果你没有指定URB_ISO_ASAP 标志,就必须自己设置start_frame,指定等时传输在哪帧或微帧开始。如果指定了URB_ISO_ASAP,urb 结束时会使用这个值返回实际的开始帧号。

五、interval

等时和中断传输专用。interval
间隔时间的意思,什么的间隔时间?就是上面说的端点希望主机轮询自己的时间间隔。这个值和端点描述符里的bInterval
是一样的,你不能随便儿的指定一个,协议里对你能指定的值是有范围限制的,对于中断传输,全速时,这个范围为1~255ms,低速是为10~255ms,高速时为1~16,这个1~16
只是bInterval 可以取的值,实际的间隔时间需要计算一下,为2 的(bInterval-1)次方乘以125 微妙,也就是2

的(bInterval-1)次方个微帧。对于等时传输,没有低速了,等时传输根本就不是低速端点负担得起的,有多大能耐就做多大事,人有多大胆地有多大产的时代早就已经过去了,对于全速和高速,这个范围也是为1~16,间隔时间由2

的(bInterval-1)次方算出来,单位为帧或微帧。这样看来,每一帧或微帧里,你最多只能期望有一次等时和中断传输,不能再多了,你只能期望房价涨的慢点,要是希望它跌下去,那要求就太过分了,它可是经济的柱子,要是倒了,那不是陷国人的生活于困境么,所以咱们要爱国啊,要送钱给ZF
还有任小强们啊同志们。

六、context
驱动设置了给下面的结束处理函数用的。比如可以将自己驱动里描述自己设备的结构体放在里边儿,在结束处理函数里就可以取出来。

complete
一个指向结束处理函数的指针,传输成功完成,或者中间发生错误的时候就会调用它,驱动可以在这里边儿检查urb
的状态,并做一些处理,比如可以释放这个urb,或者重新提交给HCD。就说摄像头吧,你向HCD 提交了个等时的urb
从摄像头那里读取视频数据,传输完成的时候调用了你指定的这个结束处理函数,并在里面取出了urb
里面获得的数据进行解码等处理,然后怎么着?总不会这一个urb 读取的数据就够你向mm
表白了吧,你的爱慕之情可是犹如滔滔江水连绵不绝,所以需要获得更多的数据,那你也总不会再去创建、初始化一个等时的urb
吧,即使再穷极无聊的人也不会那么做,明显刚刚的那个可以继续用的,只要将它再次提交给HCD
就可以了。这个函数指针的定义在include/linux/usb.h
typedef void (*usb_complete_t)(struct urb *);

最新文章

  1. STL-<queue>-priority queue的使用
  2. form表单action提交表单,页面不跳转且表单数据含文件的处理方法
  3. Myeclipse6.0 在线安装svn插件
  4. bower 基本应用
  5. 使用安卓读取sqlite数据库方法记录
  6. CentOS 安装jdk1.7 64位
  7. HDU1510 White rectangles
  8. 并发编程:c++11 多线程中随机数重复问题
  9. C# socket编程实践
  10. Javascript面对对象. 第三篇
  11. 3.WP8.1开发_为控件增加动画
  12. Numpy入门 - 行列式转置
  13. linkin大话数据结构--字符串,数组,list之间的互转
  14. Docker快速搭建LNMP环境
  15. SpringMVC学习(一)———— springmvc框架原理分析和简单入门程序
  16. python-基础数据类型,集合及深浅copy
  17. ReactiveCocoa基础
  18. mysql报错:1130 -host 'localhost' is not allowed to connect to this mysql server
  19. PHP面试准备
  20. java 基础功能

热门文章

  1. Java从后台重定向(redirect)到另一个项目的方法
  2. Java - ArrayList List 等迭代集合执行移除(remove) 的正确方法
  3. Hyper-V在线调整虚拟硬盘大小
  4. 《Cracking the Coding Interview》——第16章:线程与锁——题目5
  5. Nuget.config格式错误,请检查nuget.config配置文件
  6. scp 将数据从一台linux服务器复制到另一台linux服务器
  7. Mybatis基本用法
  8. Python 爬取网页中JavaScript动态添加的内容(一)
  9. maven常用命令 与语法
  10. 开源api文档