USB URB

URB定义:

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

  1. struct urb {  
  2.     /* private: usb core and host controller only fields in the urb */  
  3.     struct kref kref;        /* URB引用计数 */  
  4.     void *hcpriv;            /* host控制器的私有数据 */  
  5.     atomic_t use_count;        /* 当前提交计数 */  
  6.     atomic_t reject;        /* 提交失败计数 */  
  7.     int unlinked;            /* 连接失败代码 */  
  8.     /* public: documented fields in the urb that can be used by drivers */  
  9.     struct list_head urb_list;    /* list head for use by the urb's 
  10.                      * current owner */  
  11.     struct list_head anchor_list;    /* the URB may be anchored */  
  12.     struct usb_anchor *anchor;  
  13.     struct usb_device *dev;     /* 指向这个 urb 要发送的目标 struct usb_device 的指针,这个变量必须在这个 urb 被发送到 USB 核心之前被 USB 驱动初始化.*/  
  14.     struct usb_host_endpoint *ep;    /* (internal) pointer to endpoint */  
  15.     unsigned int pipe;        
  16.     int status;           
  17.     unsigned int transfer_flags;    /* 传输设置*/  
  18.     void *transfer_buffer;        /* 指向用于发送数据到设备(OUT urb)或者从设备接收数据(IN urb)的缓冲区指针。为了主机控制器驱动正确访问这个缓冲, 它必须使用 kmalloc 调用来创建, 不是在堆栈或者静态内存中。 对控制端点, 这个缓冲区用于数据中转*/  
  19.     dma_addr_t transfer_dma;    /* 用于以 DMA 方式传送数据到 USB 设备的缓冲区*/  
  20.     int transfer_buffer_length;    /* transfer_buffer 或者 transfer_dma 变量指向的缓冲区大小。如果这是 0, 传送缓冲没有被 USB 核心所使用。对于一个 OUT 端点, 如果这个端点大小比这个变量指定的值小, 对这个 USB 设备的传输将被分成更小的块,以正确地传送数据。这种大的传送以连续的 USB 帧进行。在一个 urb 中提交一个大块数据, 并且使 USB 主机控制器去划分为更小的块, 比以连续地顺序发送小缓冲的速度快得多*/  
  21.     int actual_length;        /* 当这个 urb 完成后, 该变量被设置为这个 urb (对于 OUT urb)发送或(对于 IN urb)接受数据的真实长度.对于 IN urb, 必须是用此变量而非 transfer_buffer_length , 因为接收的数据可能比整个缓冲小*/  
  22.     unsigned char *setup_packet;    /* 指向控制urb的设置数据包指针.它在传送缓冲中的数据之前被传送(用于控制 urb)*/  
  23.     dma_addr_t setup_dma;        /* 控制 urb 用于设置数据包的 DMA 缓冲区地址,它在传送普通缓冲区中的数据之前被传送(用于控制 urb)*/  
  24.     int start_frame;        /* 设置或返回初始的帧数量(用于等时urb) */  
  25.     int number_of_packets;          
  26.     int interval;            
  27.     int error_count;        /* 等时urb的错误计数,由USB核心设置 */  
  28.     void *context;            /* 指向一个可以被USB驱动模块设置的数据块. 当 urb 被返回到驱动时,可在结束处理例程中使用. */  
  29.     usb_complete_t complete;    /* 结束处理例程函数指针, 当 urb 被完全传送或发生错误,它将被 USB 核心调用. 此函数检查这个 urb, 并决定释放它或重新提交给另一个传输中*/  
  30.     struct usb_iso_packet_descriptor iso_frame_desc[0];  
  31.     };     



URB 处理流程

1, usb设备驱动程序创建初始化一个访问特定usb设备特定端点的urb,并提交给usb core

2, usb core提交该urb到usb主控制器驱动程序

3, usb主控制器驱动程序根据urb描述的信息,来访问usb设

4,当设备访问结束后,usb主控制器驱动程序通知usb core(调用这个函数usb_complete_t complete;然后其再通知usb设备驱动程序


创建URB

struct urb *usb_alloc_urb(int iso_packets, int mem_flags)
参数:

iso_packets: urb 所包含的等时数据包的个数,若不是等时传输,则为0.

mem_flags: 内存分配标识(如GFP_KERNEL),参考kmalloc

初始化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被调度的时间间隔

管道:驱动程序的数据缓冲区与一个端点的连接,它代表了一种在两者之间移动数据的能力

对于批量urb,使用usb_fill_bulk_urb函数来初始化。

对于控制urb,使用usb_fill_control_urb函数来初始化。

等时urb没有像中断,控制和批量urb那样的初始化函数,我们只能手动的初始化urb

提交URB

在完成urb的创建和初始化后,urb便可以通过usb_submit_urb函数来提交给usb核心:

int usb_submit_urb(struct urb *urb,gfp_t mem_flags)

参数:

urb:指向urb的指针;

mem_flags:内存分配标识,它用于告知usb核心如何分配内存缓冲区。

处理URB:

URB被提交到USB核心后,usb核心指定usb主控制器驱动程序来处理该urb,在3种情况下,urb会被认为处理完成:

1 urb被成功发送给设备,并且设备返回成功确认。如果urb->status为0,意味着对于一个输出urb,数据被成功发送;对于一个输入urb,请求的数据被成功收到。

2如果发送数据到设备或从设备接受数据时发生了错误,urb->status将记录错误值。

3 urb被“取消”,这发生在驱动通过usb_unlink_urb()或usb_kill_urb()函数取消urb,或urb虽已提交,而usb设备被拔出的情况下

当urb处理完成后,urb完成函数将被调用。






你可能感兴趣的:(usb)