- 金錢
- 902
- 威望
- 352
- 貢獻值
- 0
- 推廣值
- 0
- 性別
- 保密
- 在線時間
- 0 小時
- 最後登錄
- 2023-7-4
- 主題
- 41
- 精華
- 0
- 閱讀權限
- 30
- 註冊時間
- 2013-1-3
- 帖子
- 0
TA的每日心情 | 奮斗 2019-5-13 14:36 |
---|
簽到天數: 68 天 [LV.6]常住居民II - 推廣值
- 0
- 貢獻值
- 0
- 金錢
- 902
- 威望
- 352
- 主題
- 41
|
樓主
發表於 2013-1-5 20:29:26
在内核中的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。
|
|