转自: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 *);

urb数据结构【转】的更多相关文章

  1. 20.Linux-USB鼠标驱动

    在上一章分析完USB总线驱动程序后, 接下来开始写一个USB驱动: 本节目的: 将USB鼠标的左键当作L按键,将USB鼠标的右键当作S按键,中键当作回车按键 参考/drivers/hid/usbhid ...

  2. USB设备驱动概述

    USB设备驱动 ·  )USB Hub:每个USBHost控制器都会自带一个USB Hub,被称为根(Root)Hub.这个根Hub可以接子(Sub)Hub,每个Hub上挂载USB设备.一般PC有8个 ...

  3. 8.1 编写USB鼠标驱动程序,并测试

    学习目标:编写USB鼠标驱动程序,并测试(将USB鼠标的左键当作L按键,将USB鼠标的右键当作S按键,中键当作回车按键). 一.怎么写USB设备驱动程序?步骤如下: 1. 首先先定义全局变量usb_d ...

  4. Linux usb 3. Host 详解

    文章目录 1. 简介 2. Usb Core 驱动设备模型 2.1 Usb Device Layer 2.1.1 device (struct usb_device) 2.1.2 driver (st ...

  5. USB设备---URB请求快

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

  6. urb的处理流程

      USB分析 2013年11月11日 16:06:24 阅读数:1807 转载自:http://blog.csdn.net/aaa6695798/article/details/4776202 很久 ...

  7. urb传输的代码分析【转】

    转自:http://blog.csdn.net/zkami/article/details/2503829 urb传输的代码分析 如需引用,请注明出处blog.csdn.net/zkami 作者Zhe ...

  8. USB设备---URB请求块

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

  9. 12.1、USB驱动——描述符、URB、管道

    大家常说,一个设备通常有多个配置,配置通常有多个接口,接口通常有多个端点.接口代表逻辑上的设备,比如声卡分为 录音和播放.访问设备时,访问的是某个接口(逻辑设备).除了端点0之外,每个端点只支持一个传 ...

随机推荐

  1. ABAP CDS - SELECT, association

    ABAP CDS - SELECT, association Syntax ... ASSOCIATION [ [min..max] ] TO target [AS _assoc] ON cond_e ...

  2. dfs序线段树

    dfs序+线段树,啥?如果在一棵树上,需要你修改一些节点和查询一些节点,如果直接dfs搜的话肯定超时,那用线段树?树结构不是区间啊,怎么用?用dfs序将树结构转化为一个区间,就能用线段树进行维护了. ...

  3. Python os.walk() 简介

    Table of Contents 1. os.walk目录遍历 1.1. os.walk 1.2. 例子 1.2.1. 测试topdown 1.2.2. 运行时修改遍历目录 2. 参考资料 os.w ...

  4. GItHub 建立仓库克隆仓库

    Linux环境 建立本地仓库 mkdir git cd git git init 获取仓库地址 找到你的仓库,Clone or download,复制 克隆仓库到本地 git clone https: ...

  5. WPF里ItemsControl的分组实现

    我们在用到ItemsControl时,有时会用到分组,如ListBox,ListView,DataGrid.WPF的ItemsControl可以实现分组,是依托于GroupStyle,以ListBox ...

  6. 启动zookeeper报错:JAVA_HOME is not set

    启动zookeeper时报错JAVA_HOME is not set 看了环境变量,确实配置好了,但是zookeeper竟然没找到 修改bin目录下的zkEnv.cmd关于jdk的一部分 set JA ...

  7. MyEclipse - 问题集 - maven update project 后,项目jdk的版本变化

    解决方法: 进入maven安装根目录,conf/settings.xml <profiles> <profile> <id>jdk-1.7</id> & ...

  8. Pascal小游戏 随机函数

    一个被人写滥了的小程序,新手学习,Pascal By Chaobs 初学者可以用它来学习随机函数的运用,当然你完全可以自己写一个随机函数. var   player1,player2:longint; ...

  9. 【转载】Unity3D研究院之IOS触摸屏手势控制镜头旋转与缩放

    前几篇文章介绍了很多Unity3D引擎自身的一些问题, 今天我们在回到IOS设备上讨论一些触摸屏幕手势,本章的目标是通过触摸iPhone屏幕手势 实现模型左右的旋转,与模型的缩放. 大家想一想模型的旋 ...

  10. NOIP2018 集训(三)

    A题 Tree 问题描述 给定一颗 \(n\) 个点的树,树边带权,试求一个排列 \(P\) ,使下式的值最大 \[\sum_{i=1}^{n-1} maxflow(P_i, P_{i+1}) \] ...