USB 驅動程式開發之幾個重要函式分析

2021-05-25 00:27:23 字數 2407 閱讀 6502

下面介紹的函式都出自以下的linux原始碼檔案:

driver/usb/core/message.c

該檔案內包含許多關於同步資訊處理的函式,具體內容在檔案中都有注釋介紹,該處我只選擇在usb驅動程式設計中常用到的幾個函式進行分析,當然,都是我個人理解,有問題請指教。

另外,這裡我想說,美國人真的很喜歡遞迴,不論是makefile檔案的語法,還是程式設計習慣,幾乎無處不用遞迴。他們總是從問題的根源開始,慢慢告知你這些東西的用處,寫**的時候,也是最基礎的函式寫在前,最終的大型函式在後。這裡我就不再用這種方式去講了,我還是從大的開始講。

1. usb_get_device_descriptor(struct usb_device *dev,unsigned int size)

該函式的作用是:獲取裝置描述符,同時該函式是同步的,也就是說,不可用在中斷上下文。

函式主要做的事,就是內部呼叫了 usb_get_descriptor() 函式,下面會介紹。

2. usb_get_descriptor(struct usb_device *dev, unsigned char type, unsigned char index, void *buf, int size)

該函式的作用是:獲取裝置的描述符,置於是什麼型別的描述符,由 type 引數決定。

函式主要做的事,就是內部呼叫了 usb_control_msg() 函式,下面會介紹。

3. usb_control_msg(struct usb_device *dev, unsigned int pipe, __u8 request, __u8 requesttype, __u16 value, __u16 index, void *data, __u16 size, int timeout)

該函式的作用是:向裝置傳送控制資訊,置於什麼樣的控制資訊,由 request 和 requesttype 引數決定。

函式主要做的事,就是內部呼叫了 usb_internal_control_msg() 函式,下面會介紹。

4. static int usb_internal_control_msg(struct usb_device *usb_dev, unsigned int pipe, struct usb_ctrlrequest *cmd, void *data, int len, int timeout)

該函式的作用是:建立urb包,填充urb包,傳送並等待urb包。

從該函式開始,已經是比較底層的函式,不能隨意被其他程式隨意呼叫。一般的驅動程式 bulk 和 control 資料報的傳送只需要用到 usb_control_msg 和 usb_bulk_msg 就可以。但是,研究這個函式有個很大的好處,就是可以理解urb資料報的整個處理過程,對理解urb很有幫助。

該函式中在填充urb包時,在 usb_fill_control_urb 呼叫的時候,給 complete_t 引數賦值為乙個很簡單的 usb_api_blocking_completion 函式,該函式只是讓 urb 的成員變數 context 完成,但是這有什麼用呢?其實,這是整個 urb 操作的關鍵所在。

我這裡講的只是我自己的理解,必定有錯誤的地方,高手見了請不惜賜教。

我們知道整個處理 urb  包的過程是:建立,填充,傳送,釋放。

在傳送出urb包之後,貌似我們不需要做什麼處理,usb core就會幫我們將我們需要的資料返回到我們提交給它的buff裡。但是,在填充urb時,我嘗試給 complete_t 引數賦值為null,出現了許許多多錯誤。最終考慮到他的重要性認為是這麼乙個原因:我們填充完urb之後,給系統提交,提交的函式 usb_submit_urb 會立即返回,返回的結果只是告知我們是否傳送,大多情況下是0,即成功。但是,urb提交之後,未必就拿到了 usb core 給予的資料,我們需要等待urb真正傳輸完畢之後,才能對其進行操作,怎麼確定其是否真正傳輸完畢呢?就是利用 complete_t 引數,該引數指向乙個函式,也就是,在urb真正傳輸完畢後,會呼叫該函式,從上面知道,該函式只是簡單的讓 urb 的 context 成員完成。我們回到 usb_internal_control_msg 函式中,發現其呼叫了 usb_start_wait_urb 函式。

usb_start_wait_urb 函式初始化了 urb->context,並等待它的結束才進行對 urb 的真正處理,由此可見,如果我們沒有等到 urb 真正傳輸結束就對其進行操作,操作在大部分情況下都會返回錯誤,因為外設的速度遠遠比不上cpu的執行速度。

最終總結成一句話,傳送urb包後,要等待其真正處理完畢才能進行我們自己想要它實現的操作,利用 urb->context 對這個過程進行控制是一種非常好的方式。

初學的朋友可能還有疑問說是,usb_get_descriptor 等函式怎麼知道要獲取哪種描述符呢?這就利用到了引數 type 。這個引數的可選值很多,詳情參看以下linux原始碼,檔案中講述了很多巨集定義,與linux usb驅動程式設計有很大關聯,建議好好看看。

include/linux/usb_ch9.h

usb驅動程式開發技術總結

一 usb基礎知識 usb是英文universal serial bus 的縮寫,中文含義是 通用序列匯流排 1994 年,intel compaq digital ibm microsoft nec northern telecom 等七家世界著名的計算機和通訊公司成立了 usb論壇,花了近兩年的...

大話USB驅動之匯流排驅動程式

匯流排驅動是不用改的。核心都幫我們做好了。為了了解整個usb驅動的體系,我們來分析一下匯流排驅動程式。一.匯流排框圖 匯流排的圖畫的已經很清楚了,這篇部落格我們分析的是左邊的程式,在下篇我們想通過usb鍵盤這一實際樣例來解說。二.程式實現 1.因為 太多且關係複雜這裡僅僅列出呼叫的函式 沒有寫引數 ...

USB裝置驅動程式

一.usb載入式流介面驅動要點分析 為了支援不同型別的外圍裝置,wince平台提供了具有定製介面的流介面驅動程式模型。因為大部分usb外圍裝置由於功能性更適合流介面驅動的結構,所以一般都採用載入式流介面驅動程式模型來開發usb裝置驅動程式。1 usb系統結構分析 wince下usb系統軟體由兩層組成...