20.3.2 USB請求塊(URB)(1)
1.urb結構體
USB請求塊(USB request block,urb)是USB設備驅動中用來描述與USB設備通信所用的基本載體和核心數據結構,非常類似於網絡設備驅動中的sk_buff結構體,是USB主機與設備通信的"電波"。
代碼清單20.13 urb結構體
1 struct urb2 {3 /* 私有的:只能由USB核心和主機控制器訪問的字段 */4 struct kref kref; /*urb引用計數 */5 spinlock_t lock; /* urb鎖 */6 void *hcpriv; /* 主機控制器私有數據 */7 int bandwidth; /* INT/ISO請求的帶寬 */8 atomic_t use_count; /* 並發傳輸計數 */9 u8 reject; /* 傳輸將失敗*/10 11 /* 公共的: 可以被驅動使用的字段 */12 struct list_head urb_list; /* 鏈表頭*/13 struct usb_device *dev; /* 關聯的USB設備 */14 unsigned int pipe; /* 管道信息 */15 int status; /* URB的當前狀態 */16 unsigned int transfer_flags; /* URB_SHORT_NOT_OK ...*/17 void *transfer_buffer; /* 發送數據到設備或從設備接收數據的緩衝區 */18 dma_addr_t transfer_dma; /*用來以DMA方式向設備傳輸數據的緩衝區 */19 int transfer_buffer_length;/*transfer_buffer或transfer_dma 指向緩衝區的大小 */20 21 int actual_length; /* URB結束後,發送或接收數據的實際長度 */22 unsigned char *setup_packet; /* 指向控制URB的設置數據包的指針*/23 dma_addr_t setup_dma; /*控制URB的設置數據包的DMA緩衝區*/24 int start_frame; /*等時傳輸中用於設置或返回初始幀*/25 int number_of_packets; /*等時傳輸中等時緩衝區數據 */26 int interval; /* URB被輪詢到的時間間隔(對中斷和等時urb有效) */27 int error_count; /* 等時傳輸錯誤數量 */28 void *context; /* completion函數上下文 */29 usb_complete_t complete; /* 當URB被完全傳輸或發生錯誤時,被調用 */30 struct usb_iso_packet_descriptor iso_frame_desc[0];31 /*單個URB一次可定義多個等時傳輸時,描述各個等時傳輸 */32 };
當transfer_flags標誌中的URB_NO_TRANSFER_DMA_MAP被置位時,USB核心將使用transfer_dma指向的緩衝區而非transfer_buffer指向的緩衝區,意味著即將傳輸DMA緩衝區。
當transfer_flags標誌中的URB_NO_SETUP_DMA_MAP被置位時,對於有DMA緩衝區的控制urb而言,USB核心將使用setup_dma指向的緩衝區而非setup_packet指向的緩衝區。
2.urb處理流程
USB設備中的每個端點都處理一個urb隊列,在隊列被清空之前,一個urb的典型生命週期如下:
(1)被一個 USB 設備驅動創建。
創建urb結構體的函數為:
struct urb *usb_alloc_urb(int iso_packets, int mem_flags);
iso_packets是這個urb應當包含的等時數據包的數目,若為0表示不創建等時數據包。 mem_flags參數是分配內存的標誌,和kmalloc()函數的分配標誌參數含義相同。如果分配成功,該函數返回一個urb結構體指針,否則返回0。
urb結構體在驅動中不能靜態創建,因為這可能破壞USB核心給urb使用的引用計數方法。
usb_alloc_urb()的"反函數"為:
void usb_free_urb(struct urb *urb);
該函數用於釋放由usb_alloc_urb()分配的urb結構體。
(2)初始化,被安排給一個特定USB設備的特定端點。
對於中斷urb,使用usb_fill_int_urb()函數來初始化urb,如下所示:
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);
urb參數指向要被初始化的urb的指針;dev指向這個urb要被發送到的USB設備;pipe是這個urb要被發送到的USB設備的特定端點;transfer_buffer是指向發送數據或接收數據的緩衝區的指針,和urb一樣,它也不能是靜態緩衝區,必須使用kmalloc()來分配;buffer_length是transfer_buffer指針所指向緩衝區的大小;complete指針指向當這個 urb完成時被調用的完成處理函數;context是完成處理函數的"上下文";interval是這個urb應當被調度的間隔。
上述函數參數中的pipe使用usb_sndintpipe()或usb_rcvintpipe()創建。
對於批量urb,使用usb_fill_bulk_urb()函數來初始化urb,如下所示:
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);
除了沒有對應於調度間隔的interval參數以外,該函數的參數和usb_fill_int_urb()函數的參數含義相同。
上述函數參數中的pipe使用usb_sndbulkpipe()或者usb_rcvbulkpipe()函數來創建。
對於控制 urb,使用usb_fill_control_urb()函數來初始化urb,如下所示:
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);
除了增加了新的setup_packet參數以外,該函數的參數和usb_fill_bulk_urb()函數的參數含義相同。setup_packet參數指向即將被發送到端點的設置數據包。
上述函數參數中的pipe使用usb_sndctrlpipe()或usb_rcvictrlpipe()函數來創建。
沒有留言:
張貼留言