Linux下的USB裝置驅動

2021-07-24 08:41:52 字數 3396 閱讀 6876

usb是我們常用的介面,它有四條引腳線:5v、d+、d-、gnd。pc的usb口的d+、d-接有下拉電阻,平時處於低電平狀態。usb裝置的usb口內部,d-或d+接有1.5k的上拉電阻;它一接入pc,就會把pc的usb口的d-或d+拉高,從硬體的角度通知pc有新裝置接入。所以usb能夠自動監測裝置。

簡單來說,usb驅動分為兩塊,一塊是usb匯流排驅動,這個在linux核心裡已經給我們做好了。當接入usb裝置時,它能察覺到usb裝置的接入,給usb裝置分配編號(位址),並告訴usb裝置給它分配的編號(位址)是多少,和獲取usb裝置的描述符。然後通過裝置描述符的資訊找打對應的usb裝置驅動程式,並給usb裝置驅動程式提供讀寫函式。第二塊就是usb裝置驅動程式,我們需要做的就是這一塊。usb裝置驅動程式用通過usb匯流排驅動程式提供的讀寫函式,根據不同的資料做不同的事情。

其他的一些概念:

1、usb是主從結構的,所有的usb傳輸都是從usb主機這方發起的,usb裝置沒有」主動」通知usb主機的能力。例子:usb滑鼠滑動一下立刻產生資料,但是它沒有能力通知pc機來讀資料,只能被動地等得pc機來讀。

2、 usb的傳輸型別:

a. 控制傳輸:可靠,時間***,比如:usb裝置的識別過程

b. 批量傳輸: 可靠, 時間沒***, 比如:u盤

c. 中斷傳輸:可靠,實時,比如:usb滑鼠

d. 實時傳輸:不可靠,實時,比如:usb攝像頭

3、usb傳輸的物件:端點(endpoint)

我們說」讀u盤」、」寫u盤」,可以細化為:把資料寫到u盤的端點1,從u盤的端點2裡讀出資料。除了端點0外,每乙個端點只支援乙個方向的資料傳輸,端點0用於控制傳輸,既能輸出也能輸入。

4、 每乙個端點都有傳輸型別,傳輸方向。

5、 術語裡、程式裡說的輸入(in)、輸出(out) 「都是」 基於usb主機的立場說的。比如滑鼠的資料是從滑鼠傳到pc機, 對應的端點稱為」輸入端點」。

6、usb匯流排驅動程式的作用

a. 識別usb裝置

b. 查詢並安裝對應的裝置驅動程式

c. 提供usb讀寫函式

uhci: intel, 低速(1.5mbps)/全速(12mbps)

ohci: microsoft 低速/全速

ehci: 高速(480mbps)

從上面你的圖可知道當我們寫乙個usb 裝置驅動時,我們最主要的目的是解釋usb傳輸資料的含義(即要根據資料的內容去做事情)。在接受資料之前需要讓我們的usb裝置驅動程式和usb裝置建立乙個連線,它是怎麼連線的呢?通過向上註冊乙個usb_driver結構體,當裝置插入時,通過得到的裝置描述符與這個結構體進行比較匹配,當匹配時就建立聯絡,詳細的匹配過程很複雜,這裡就不深入了。當裝置和驅動建立連線時,將呼叫註冊的結構裡的probe函式。為了能完成驅動的一些事務,我們需要在這個函式內進行一些裝置相關操作。比如,設定資料傳輸的3要素(usb的源,資料長度,目的),使用3要素(urb),提交urb。

總結usb裝置的驅動的框架:

1、分配usb_driver結構體;

struct usb_driver ;
2、設定usb_driver結構體;

3、註冊usb_driver結構體;int usb_register(struct usb_driver *driver)

4、在插入時呼叫probe函式;在probe函式裡進行裝置相關的操作。比如:

a、設定資料傳輸3要素(usb的源,資料長度,目的)。

b、使用三要素:分配乙個urburb *usb_alloc_urb(int iso_packets, gfp_t mem_flags)

填充urb:

/*填充usb中斷型別urb*/

static

inline

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_fn,//接收到資料時呼叫的函式

void *context,

int interval)

完成這些步驟,我們就能寫出簡單的usb裝置驅動程式了。

usb滑鼠裝置驅動,將滑鼠當做按鍵,左鍵輸入l,右鍵輸入s,中間輸入回車。

#include 

#include

#include

#include

#include

#include

static

struct input_dev *uk_dev;

static

char *usb_buf;

static dma_addr_t usb_buf_phys;

static

int len;

static

struct urb *uk_urb;

static

void my_usb_mouse_irq(struct urb *urb)

if((pre_val & (1

<<1)) != (usb_buf[0] & (1

<<1)))

if((pre_val & (1

<<2)) != (usb_buf[0] & (1

<<2)))

pre_val = usb_buf[0];

usb_submit_urb(uk_urb, gfp_kernel);

}static

int my_usb_mouse_probe (struct usb_inte***ce *intf,const

struct usb_device_id *id)

static

void my_usb_mouse_disconnect (struct usb_inte***ce *intf)

static

struct usb_device_id my_usb_mouse_id_table = ,

/* terminating entry */

};static

struct usb_driver my_usb_mouse_driver = ;

static

int __init my_usb_mouse_init(void)

static

void __exit my_usb_mouse_exit(void)

module_init(my_usb_mouse_init);

module_exit(my_usb_mouse_exit);

module_license("gpl");

linux裝置驅動 USB

系統核心中有usb匯流排驅動程式,作用是識別裝置,查詢並安裝裝置驅動程式,提供讀寫函式 當乙個usb裝置插入時,會有以下操作 1.某條線被拉低,硬體感知有裝置接入 2.usb匯流排驅動程式為裝置分配新位址,並告訴usb裝置 3.獲取描述符 4.根據獲取的裝置描述符中的資訊在usb匯流排中新增devi...

USB裝置驅動

1.linux usb架構 usb通訊都是由host端發起的。usb裝置驅動程式分配並初始化乙個urb發給usb core,usb core改一改,發給usb主機控制器驅動,usb主機控制器驅動把它解析成包,在匯流排上進行傳送。usb core是由核心實現的,其實也就是把host control d...

USB裝置驅動

把usb裝置接到pc 右下角彈出 發現android phone 跳出乙個對話方塊,提示你安裝驅動程式 問1.既然還沒有 驅動程式 為何能知道是 android phone 答1.windows裡已經有了usb的匯流排驅動程式,接入usb裝置後,是 匯流排驅動程式 知道你是 android phon...