分类: LINUX
2008-11-27 14:16:07
在内核中的USB代码和USB设备进行通信,使用的是Urb(USB request block)。Urb可以看成是一个USB的驱动和USB 的endpoint通信的桥梁。有两种方式
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 */
void
*context; /* (in) context
for completion */
usb_complete_t
complete; /* (in) completion routine
*/
struct
usb_iso_packet_descriptor iso_frame_desc[0]; /*
(in) ISO ONLY */
};
一个Urb的生命周期
1、 USB 设备驱动创建Urb
为了不破坏USB core中Urb的引用计数器,Urb不能静态创建。或者在另一个结构中。只能通过对usb_alloc_urb的调用来创建。函数原型为:
struct urb *usb_alloc_urb(int iso_packets, int mem_flags);
2、 分配一个Endpoint,由于Endpoint有四种类型,所以在分配的时候也有4个方法:
Interrupt EndPoint
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);
Bulk EndPoint
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);
Control EndPoint
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);
Isochronous EndPoint
Isochronous EndPoint的Urb无法像Interrupt EndPoint 、Bulk EndPoint 、Control EndPoint一样被初始化,只能通过编写驱动者进行初始化。
3、 通过USB设备驱动程序,提交给USB core
当Urb被创建并且初始化完成之后就可以通过usb_submit_urb提交给Usb core 了
int usb_submit_urb(struct urb *urb, int mem_flags);
4、 当Urb完成数据传输任务后,释放该Urb
通过int usb_kill_urb(struct urb *urb); 或者int usb_unlink_urb(struct urb *urb);来释放Urb。usb_kill_urb常常在设备从系统中移除的时候使用,终止该Urb的生命周期
usb_unlink_urb这个函数在返回到调用者之前不等待这个 urb 完全停止。因为要完全停止一个Urb,必须要USB core能够睡眠当前进程。当然,Urb的transfer_flags需要一个URB_ASYNC_UNLINK。