linux下usb驱动头文件的usb.h(二)

http://blog.zol.com.cn/4494/article_4493001.html

#define URB_NO_FSBR 0x0020 /* UHCI-specific */

  #define URB_ZERO_PACKET 0x0040 /* 完成大块分解成小包输

  #define URB_NO_INTERRUPT 0x0080 /* HINT: no non-error interrupt needed */

  struct usb_iso_packet_decript:or {

  unsigned int offset;

  unsigned int length; /* expected length */

  unsigned int actual_length;

  unsigned int status;

  };

  struct urb;

  struct pt_regs;

  typedef void (*usb_complete_t)(struct urb *, struct pt_regs *);

  /**

  struct urb - USB 请求块

  ◎usb_list 给当前的urb拥有者使用

  ◎pipe 保持端点的数字,方向,类型,或更多。创建这些值要同时对八个macros可访问的。usb_{snd,rcv}TYPEpipe(dev,endpoint中的TYPE是"ctrl" (control), "bulk", "int" (interrupt), or "iso" (isochronous).同步。例如usb_sndbulkpipe() or usb_rcvintpipe().

  端点的数字从0到15。注意到in端点2和out端点2是不同的端点(管道)。当前的配置控制任何给定端点的存在,类型和最大的包大小

  ◎dev usb设备执行请求的标识符

  ◎status 在不同步的完成函数中被读取以获得特殊请求的状态。同步完成中只用它来区分urb是否被断开。每个帧的详细的状态在iso_freame-desc的域中

  ◎transfer_flag 一个变化的标志可能会被用在影响URB怎样提交,断开,或操作。不同的URB能用不同的flag

  ◎transfer_buffer 这个标识I/O请求从哪里的缓存开始执行,或者到那里完成。(除非URB_NO_TRANSFER_DMA_MAP 被置位)这个缓存不许对DMA有效的,它和kmalloc()或其等价物一起分配。这缓存被用来控制传输的数据进程。

  ◎trancfer_dma 当transfer_buffer包含有URB_NO_TRANSFER_DMA_MAP时,设备的驱动程序已经表示提供给DMA地址,那么主机端的主控制器的驱动程序会优先使用transfer_buffe作缓

  ◎trancfer_lengeh 在不同步的完成函数中被读取,它显示有多少bytes被传输了。一般它和请求的是一样的,除非出现错误或者发生short read 。这个The URB_SHORT_NOT_OK 传输标志被用来把这些报告的short read作为错误。

  ◎transfer_buffer_lengeh transfer_buffer的大小。传输可能会根据端点最大包的大小来把数据变成一个个包。(包的大小在配置中完成,并在管道中编码。当长度为零时transfer_buffer 和 trancfer_dma多无效。

  ◎setup_packet 只在控制传输中使用,setup数据包包含八个比特控制传输总是发送这个数据包到设备,然后对transfer_buffer进行必要的读写(如果需要的话)

  ◎setup_dma 和URB_NO_TRANSFER_DMA_MAP设置一起在控制传输中使用。设备的驱动程序为setup_packet提供DMA地址。主机控制器驱动程序应当优先使用它(相对于setup_packet包)

  ◎start_frame 为同步传输返回返回原始的帧

  ◎number_of_packets 列出同步传输的缓存数

  ◎interval 为中断或同步传输指定polling间隔。对于全速或低速设备它的单元是帧,对于高速,他的单元的微帧。

  ◎error_count 返回同步传输中报告的错误数

  ◎context 在完成状态函数中使用,它一般指向request-specific 驱动的上下

  ◎Complete 完成训练者。URB传递参数给完成状态函数。完成状态函数然后就会对URB进行操作,包括重新提交或释放它

  @iso_frame_desc: 用来给ISO transfer buffer提供数组,并收集每个缓存的传输状态

  @timeout: 如果设置为零的话,那么URB将永远不会超时,否则这就是URB超时的时间。

  这个结构表示usb的传输请求URB必须被calling usb_alloc_urb() 函数分配,用 usb_free_urb().函数来释放。用各种usb_fill_*_urb() 函数来做初始化. URBs使用usb_submit_urb()来提交请求, 并通过函数unlink_urb() or usb_kill_urb().来结束那些还没完成的的请求。

  数据传输缓存

  一般来说驱动程序用函数kmalloc()来提供I/O缓存,否则就从一般的页池中得到。那是由tranfer_buffer提供的(控制请求也使用setup_packet),主机控制器的驱动为每个用于传输的缓存执行一个dma对应操作(或不对应),这些对应的操作在某些平台上可能会花费巨大(可能使用一个dmabounce buffer或同一个IOMMU对话)

  作为选择的,驱动程序可能传递URB_NO_xxx_DMA_MAP传输标志,这个传输标志将会告诉主机控制器的驱动程序没有相应的DMA被需要,因为这个设备的驱动程序是知道DMA的。例如

  一个设备驱动程序用usb_buffer_alloc() or call usb_buffer_map()分配一个DMA缓存。当这些传输标志被提供了,主机驱动程序将会试着用DMA地址在transfer_dma 或(和)setup_dma域中去发现,而不是他们自己决定一个DMA地址。(注意到transfer_dma 或(和)setup_dma必须仍然被设置因为不是所有的主机控制器使用DMA,实际的根hub也不是多使用DMA)

  初始化

  所有的URBs提交必须初始化设备,管道,传输标志(可能是零),完成标志,超时标志(可能是零)。The URB_ASYNC_UNLINK 传输标志影响以后的 the usb_unlink_urb()路由。注意:如果用usb_unlink_urb()设置 URB_ASYNC_UNLINK 失败这被忽略。因为同步的断开连接使用

  usb_kill_urb() 代替。

  所有的URBs也必须初始化transfer_buffer 和transfer_buffer_length他们可能提供 URB_SHORT_NOT_OK 传输标志,他表明shor他 read 将会被认为是错误的,那个标志在写请求中是无效的。

  Bulk URBs may

  使用 URB_ZERO_PACKET传输标志,表明大的OUT传输应当总是以一个小的包作为结束。 即便是加上一个额外的零长度的包。

  控制URBs必须提供一个setup_packet。这个setup_packet 和transfer_buffer可能和 DMA一一对应或者不是,他们是相互独立的。这个传输标志 URB_NO_TRANSFER_DMA_MAP和 URB_NO_SETUP_DMA_MAP 表明已经被对应上了。对于不是URBs控制请求 URB_NO_SETUP_DMA_MAP 将被忽略。

  中断URBs必须提供一个时间间隔,表示间隔多久给传输投票。在URB提交提交以后,这个interval域实际反映了传输是如何被列成进度表的。这个投票间隔可能比请求更加的频繁。例如:某些控制器有最大的间隔为32微秒,而其他的可能为1024微秒。同步的UEBs也有传输间隔。(注意到对于同步端点和告诉的中断端点,在端点标识符的传输编码是对数的。设备驱动必须通过他们自己把这些值转化为线性单元。

  同步URBs一般使用URB_ISO_ASAP 传输标志,他表明主机控制器把传输列成表只要带宽利用允许,然后设置start_frame 以反映实际在提交期被选中的帧。否则这个驱动程序必须指定start_frame然后处理传输不能开始的情况。然而驱动程序不知道当前带宽是如何分配的,当他们用usb_get_current_frame_number () 找到当前帧,他们就不知道这个帧数字的变化(帧计数器值的变化范围从256―――)

  同步URBs有一个不同的数据传输模型,因为他的服务只是尽最大努力。发话方用iso_frame_desc 结构中的number_of_packets的值提供特殊的分配URBs,每个这样的包是独立的ISO传输。同步URBs一般被排成队列,驱动程序保证传输具有两倍的缓存后提交请求,然后在and then explicitly resubmitted in completion handlers 。所以那些视频(音频)数据流以恒定比特率传输因为主机控制器支持队列。

  Completion Callbacks:

  这个Completion Callbacks在in_interrupt() 中产生,其中完成处理的第一件事应该事检查状态域。

  这个状态域为所有的URBs提供。他被用来报告断开的urbs,和所有non-ISO 传输的状态。他不应该在URb被返回到完成处理(ompletion handler.)前被检验。

  这个context域一般用来连接URBs并返回相关的驱动和请求状态

  当这个Completion Callbacks: 为non-isochronous URB而被调用。这个actual_length 域表明有多少比特被传输。这个域被更新即使URb因为错误或断开终止。

  同步传输的状态在status and actual_length fields (包含在 iso_frame_desc array 数组中)。错误数包含在error_count 。而这个Completion callbacks 则是通过提交urb来保证一个恒定的传输比特率。

  struct urb

  {

  /* private, usb core and host controller only fields in the urb */

  struct kref kref; /* reference涉及count of the URB */

  spinlock_t lock; /* lock for the URB */

  void *hcpriv; /* private data for host controller */

  struct list_head urb_list; /* list pointer to all active urbs */

  int bandwidth; /* bandwidth for INT/ISO request */

  atomic_t use_count; /* concurrent submissions counter */

  u8 reject; /* submissions will fail */

  /* public, documented备有证明文件的fields in the urb that can be used by drivers *

  struct usb_device *dev; /* (in) pointer to associated关联的device */

  unsigned int pipe; /* (in) pipe information */

  int status; /* (return) non-ISO status */

  unsigned int transfer_flags; /* (in) URB_SHORT_NOT_OK | ...*/

  void *transfer_buffer; /* (in) associated data buffer */

  dma_addr_t transfer_dma; /* (in) dma addr for transfer_buffer */

  int transfer_buffer_length; /* (in) data buffer length */

  int actual_length; /* (return) actual实际的transfer length */

  unsigned char *setup_packet; /* (in) setup packet (control only) */

  dma_addr_t setup_dma; /* (in) dma addr for setup_packet */

  int start_frame; /* (modify修改) start frame (ISO) */

  int number_of_packets; /* (in) number of ISO packets */

  int interval; /* (modify) transfer interval (INT/ISO) */

  int error_count; /* (return) number of ISO errors */

  int timeout; /* (in) timeout, in jiffies */

  void *context; /* (in) context for completion */

  usb_complete_t complete; /* (in) completion routine */

  struct usb_iso_packet_decript:or iso_frame_desc[0]; /* (in) ISO ONLY */

  };

  * usb_fill_control_urb – 初始化一个控制URB

  * @urb: 指向要初始化的URB的指针

  * @dev: 指向对应这个URB的usb_devicce的结构的指针

  * @pipe: the endpoint pipe

  * @setup_packet: 指向setup_packet buffer的指针

  * @transfer_buffer: 指向 the transfer buffer 的指针

  * @buffer_length: the transfer buffer 的长度

  * @complete:指向 usb_complete_t 的指针

  * @context: what to set the urb context to.

  *

  * 初始化这个控制URBs进行适当的信息提交

  * it to a device.

  */

  static inline 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)

  {

  spin_lock_init(&urb->lock);

  urb->dev = dev;

  urb->pipe = pipe;

  urb->setup_packet = setup_packet;

  urb->transfer_buffer = transfer_buffer;

  urb->transfer_buffer_length = buffer_length;

  urb->complete = complete;

  urb->context = context;

  }

  /**

  * usb_fill_bulk_urb – 帮助初始化一个bulk urb(((((同上)))))

  * @urb: 指向要初始化的URB的指针

  * @dev: pointer to the struct usb_device for this urb.

  * @pipe: the endpoint pipe

  * @transfer_buffer: pointer to the transfer buffer

  * @buffer_length: length of the transfer buffer

  * @complete: pointer to the usb_complete_t function

  * @context: what to set the urb context to.

  *

  * Initializes a bulk urb with the proper information needed to submit it

  * to a device.

  */

  static inline 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)

  {

  spin_lock_init(&urb->lock);

  urb->dev = dev;

  urb->pipe = pipe;

  urb->transfer_buffer = transfer_buffer;

  urb->transfer_buffer_length = buffer_length;

  urb->complete = complete;

  urb->context = context;

  }

  /**

  * usb_fill_int_urb – 帮助初始化interrupt urb

  * @urb: pointer to the urb to initialize.

  * @dev: pointer to the struct usb_device for this urb.

  * @pipe: the endpoint pipe

  * @transfer_buffer: pointer to the transfer buffer

  * @buffer_length: length of the transfer buffer

  * @complete: pointer to the usb_complete_t function

  * @context: what to set the urb context to.

  * @interval: what to set the urb interval to, encoded like

  通过把适当的信息递交给设备来初始化一个interrupt urb

  注意到高速中断端点对端点间隔进行对数编码,在微帧中表达polling intervals (每毫秒8微帧)而在帧中为一帧每毫秒

  static inline 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)

  {

  spin_lock_init(&urb->lock);

  urb->dev = dev;

  urb->pipe = pipe;

  urb->transfer_buffer = transfer_buffer;

  urb->transfer_buffer_length = buffer_length;

  urb->complete = complete;

  urb->context = context;

  if (dev->speed == USB_SPEED_HIGH)

  urb->interval = 1 << (interval - 1);

  else

  urb->interval = interval;

  urb->start_frame = -1;

  }

  extern void usb_init_urb(struct urb *urb);

  extern struct urb *usb_alloc_urb(int iso_packets, int mem_flags);

  extern void usb_free_urb(struct urb *urb);

  #define usb_put_urb usb_free_urb

  extern struct urb *usb_get_urb(struct urb *urb);

  extern int usb_submit_urb(struct urb *urb, int mem_flags);

  extern int usb_unlink_urb(struct urb *urb);

  extern void usb_kill_urb(struct urb *urb);

  #define HAVE_USB_BUFFERS

  void *usb_buffer_alloc (struct usb_device *dev, size_t size,

  int mem_flags, dma_addr_t *dma);

  void usb_buffer_free (struct usb_device *dev, size_t size,

  void *addr, dma_addr_t dma);

  struct urb *usb_buffer_map (struct urb *urb);

  #if 0

  void usb_buffer_dmasync (struct urb *urb);

  #endif

  void usb_buffer_unmap (struct urb *urb);

  struct scalert::list;

  int usb_buffer_map_sg (struct usb_device *dev, unsigned pipe,

  struct scalert::list *sg, int nents);

  #if 0

  void usb_buffer_dmasync_sg (struct usb_device *dev, unsigned pipe,

  struct scalert::list *sg, int n_hw_ents);

  #endif

  /*------------------------------------------------ -------------------*

  * SYNCHRONOUS CALL SUPPORT *

  *------------------------------------------------- ------------------*/

  extern int usb_control_msg(struct usb_device *dev, unsigned int pipe,

  __u8 request, __u8 requesttype, __u16 value, __u16 index,

  void *data, __u16 size, int timeout);

  extern int usb_bulk_msg(struct usb_device *usb_dev, unsigned int pipe,

  void *data, int len, int *actual_length,

  int timeout);

  /* selective suspend/resume */

  extern int usb_suspend_device(struct usb_device *dev, u32 state);

  extern int usb_resume_device(struct usb_device *dev);

  /* wrappers around usb_control_msg() for the most common standard requests */

  extern int usb_get_decript:or(struct usb_device *dev, unsigned char desctype,

  unsigned char descindex, void *buf, int size);

  extern int usb_get_status(struct usb_device *dev,

  int type, int target, void *data);

  extern int usb_get_string(struct usb_device *dev,

  unsigned short langid, unsigned char index, void *buf, int size);

  extern int usb_string(struct usb_device *dev, int index,

  char *buf, size_t size);

  /* wrappers that also update important state inside usbcore */

  extern int usb_clear_halt(struct usb_device *dev, int pipe);

  extern int usb_reset_configuration(struct usb_device *dev);

  extern int usb_set_interface(struct usb_device *dev, int ifnum, int alert::nate);

  timeouts, in seconds,被用来发送或接收控制信息。具有代表性的他们一般在他们被声明后几个帧后完成。Usb标识5秒为超时,或者在某些时候多一点

  #define USB_CTRL_GET_TIMEOUT 5

  #define USB_CTRL_SET_TIMEOUT 5

  struct usb_sg_request 对分散/集中的I/O的支持

  * @status:0代表正确,其他代表错误

  * @bytes: 计算传输的比特

  这些请求被usb_sg_init() 初始化,然后被用作请求操作传递给usb_sg_wait() or usb_sg_cancel()。大多数请求目标的成员不是给驱动程序作为入口

  这个状态和比特数的值只在usb_sg_wait() 返回后有效。如果这status是零的话,那么bytecount就符合请求的总数。

  在一个错误完成以后,驱动程序就能够在端点处清除一个暂停的情形

  struct usb_sg_request {

  int status;

  size_t bytes;

  一以下的成员对usb核私有不对外开放

  spinlock_t lock;

  struct usb_device *dev;

  int pipe;

  struct scalert::list *sg;

  int nents;

  int entries;

  struct urb **urbs;

  int count;

  struct completion complete;

  };

  int usb_sg_init (

  struct usb_sg_request *io,

  struct usb_device *dev,

  unsigned pipe,

  unsigned period,

  struct scalert::list *sg,

  int nents,

  size_t length,

  int mem_flags

  );

  void usb_sg_cancel (struct usb_sg_request *io);

  void usb_sg_wait (struct usb_sg_request *io);

  /* -------------------------------------------------- ------------------------ */

  称这个实体为管道是形象化的说法,一个usb管道就是把一些阻碍简单化,它基本具备一以下条件:

  设备数字(7bit)

  端点数字(4bit)

  当前的Data0/1 的状态(1bit)在usb1.1时使用,现在没有了

  方向(1bit)

  速度(1bit)(历史的,在usb1.1时明确规定,现在没有了)

  最大的包尺寸(2 bits: 8, 16, 32 or 64) 在usb1.1时使用,现在没有了

  管道类型(2bit:控制,中断,块,同步)

  那是18比特,实际上,没有更多。Usb开发人员把这18个bit作为”光荣“的数据结构

  我们不要进入这个圈套,我们只要简单的认为他是一个unsigned int类型。它的编码就是

  * - max size: bits 0-1 [Historical; now gone.]

  * - direction: bit 7 (0 = Host-to-Device [Out],

  * 1 = Device-to-Host [In] ...

  * like endpoint bEndpointAddress)

  * - device: bits 8-14 ... bit position::s known to uhci-hcd

  * - endpoint: bits 15-18 ... bit position::s known to uhci-hcd

  * - Data0/1: bit 19 [Historical; now gone. ]

  * - lowspeed: bit 26 [Historical; now gone. ]

  * - pipe type: bits 30-31 (00 = isochronous, 01 = interrupt,

  * 10 = control, 11 = bulk)

  为什么呢?因为这是任意的,我们选择无论什么编码,多取决域我们自己。这个和那个UHCI规格有很多共享的比特,因此很多的UHCI驱动程序能够适当的掩盖比特位。

  注:这些不是标准的USB_ENDPOINT_XFER_*

  #define PIPE_ISOCHRONOUS 0

  #define PIPE_INTERRUPT 1

  #define PIPE_CONTROL 2

  #define PIPE_BULK 3

  #define usb_maxpacket(dev, pipe, out) (out \

  ? (dev)->epmaxpacketout[usb_pipeendpoint(pipe)] \

  : (dev)->epmaxpacketin [usb_pipeendpoint(pipe)] )

  #define usb_pipein(pipe) ((pipe) & USB_DIR_IN)

  #define usb_pipeout(pipe) (!usb_pipein(pipe))

  #define usb_pipedevice(pipe) (((pipe) >> 8) & 0x7f)

  #define usb_pipeendpoint(pipe) (((pipe) >> 15) & 0xf)

  #define usb_pipetype(pipe) (((pipe) >> 30) & 3)

  #define usb_pipeisoc(pipe) (usb_pipetype((pipe)) == PIPE_ISOCHRONOUS)

  #define usb_pipeint(pipe) (usb_pipetype((pipe)) == PIPE_INTERRUPT)

  #define usb_pipecontrol(pipe) (usb_pipetype((pipe)) == PIPE_CONTROL)

  #define usb_pipebulk(pipe) (usb_pipetype((pipe)) == PIPE_BULK)

  /* The D0/D1 toggle bits ... USE WITH CAUTION (they're almost hcd-internal) */

  #define usb_gettoggle(dev, ep, out) (((dev)->toggle[out] >> (ep)) & 1)

  #define usb_dotoggle(dev, ep, out) ((dev)->toggle[out] ^= (1 << (ep)))

  #define usb_settoggle(dev, ep, out, bit) ((dev)->toggle[out] = ((dev)->toggle[out] & ~(1 << (ep))) | ((bit) << (ep)))

  /* Endpoint halt control/status ... likewise USE WITH CAUTION */

  端点暂停 控制和状态 和USE WITH CAUTION 相似

  #define usb_endpoint_running(dev, ep, out) ((dev)->halted[out] &= ~(1 << (ep)))

  #define usb_endpoint_halted(dev, ep, out) ((dev)->halted[out] & (1 << (ep)))

  static inline unsigned int __calert::_pipe(struct usb_device *dev, unsigned int endpoint)

  {

  return (dev->devnum << 8) | (endpoint << 15);

  }

  /* Calert:: various pipes... */

  #define usb_sndctrlpipe(dev,endpoint) ((PIPE_CONTROL << 30) | __calert::_pipe(dev,endpoint))

  #define usb_rcvctrlpipe(dev,endpoint) ((PIPE_CONTROL << 30) | __calert::_pipe(dev,endpoint) | USB_DIR_IN)

  #define usb_sndisocpipe(dev,endpoint) ((PIPE_ISOCHRONOUS << 30) | __calert::_pipe(dev,endpoint))

  #define usb_rcvisocpipe(dev,endpoint) ((PIPE_ISOCHRONOUS << 30) | __calert::_pipe(dev,endpoint) | USB_DIR_IN)

  #define usb_sndbulkpipe(dev,endpoint) ((PIPE_BULK << 30) | __calert::_pipe(dev,endpoint))

  #define usb_rcvbulkpipe(dev,endpoint) ((PIPE_BULK << 30) | __calert::_pipe(dev,endpoint) | USB_DIR_IN)

  #define usb_sndintpipe(dev,endpoint) ((PIPE_INTERRUPT << 30) | __calert::_pipe(dev,endpoint))

  #define usb_rcvintpipe(dev,endpoint) ((PIPE_INTERRUPT << 30) | __calert::_pipe(dev,endpoint) | USB_DIR_IN)

  /* -------------------------------------

  #ifdef DEBUG

  #define dbg(format, arg...) printk(KERN_DEBUG "%s: " format "\n" , __FILE__ , ## arg)

  #else

  #define dbg(format, arg...) do {} while (0)

  #endif

  #define err(format, arg...) printk(KERN_ERR "%s: " format "\n" , __FILE__ , ## arg)

  #define info(format, arg...) printk(KERN_INFO "%s: " format "\n" , __FILE__ , ## arg)

  #define warn(format, arg...) printk(KERN_WARNING "%s: " format "\n" , __FILE__ , ## arg)

  #endif /* __KERNEL__ */

  #endif

  

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值