基于嵌入式Linux的USB設備驅動(dòng)技術(shù)介紹
該函數的形參對應的就是總線(xiàn)兩條鏈表里的設備和驅動(dòng)。當總線(xiàn)上有新設備和驅動(dòng)時(shí),這個(gè)函數就會(huì )被調用。
3 USB驅動(dòng)程序的描述符
一個(gè)設備可以有多個(gè)接口,一個(gè)接口可代表一個(gè)功能,因此,每個(gè)接口都對應著(zhù)一個(gè)驅動(dòng)。例如一個(gè)USB設備有兩種功能,一個(gè)鍵盤(pán),上面還帶一個(gè)揚聲器,這就是兩個(gè)接口,就需要兩個(gè)驅動(dòng)程序,一個(gè)是鍵盤(pán)驅動(dòng)程序,一個(gè)是音頻流驅動(dòng)程序。
一個(gè)驅動(dòng)程序是否支持一個(gè)設備,要通過(guò)讀取設備的描述符來(lái)判斷。那么,什么是USB的描述符呢?USB的描述符是一個(gè)帶有預定義格式的數據結構,里面保存有USB設備的各種屬性和相關(guān)信息,可以通過(guò)向設備請求獲得它們的描述符內容來(lái)深刻了解和感知一個(gè)USB設備。主要有四種USB描述符,分別為:接口描述符、端點(diǎn)描述符、設備描述符和配置描述符。
協(xié)議規定:一個(gè)USB設備必須支持這四大描述符,還有些描述符不是必須包含的,有些特殊設備用來(lái)描述設備的不同特性,但這四大描述符是一個(gè)都不能少的。USB設備里有一個(gè)eeprom,可用來(lái)存儲設備本身信息,設備的描述符就存儲在這里。
上述四個(gè)描述符分別放在了include/linux/usb.h文件中的struct usb_host_interface、structusb_host_endpoint、struct usb_device、struetusb_host_config里,而描述符結構體本身定義在include/linux/usb/ch9.h里.并分別用struct usb_interface_descriptor、struct usb_host_endpoint、structusb_device_descriptor和struct usb_config_descriptor來(lái)表示。描述符結構體的定義應完全按照USB協(xié)議對描述符的規定來(lái)定義。
4 USB接口驅動(dòng)
4.1 接口結構
平時(shí)編寫(xiě)的USB驅動(dòng)通常指的是寫(xiě)USB接口的驅動(dòng),一個(gè)接口對應一個(gè)接口驅動(dòng)程序,需要以一個(gè)struct usb_driver結構的對象為中心,并以設備的接口提供的功能為基礎,來(lái)進(jìn)行USB驅動(dòng)程序的編寫(xiě)。struct usb_driver結構體一般定義在include/linux/usb.h文件里。具體如下:
struct usb_driver{
const char*name;
int(*probe) (struct usb_interface*intf,const
struct usb_device_jd*id);
void(*disconnect) (struct usb_interface*intf);
int(*ioctl) (struct usb_interface*intf,unsigned
int code,void*buf);
int (*suspend) (struct usb_interface*intf,
pm_message_t message);
int(*resume) (struct usb_interface*intf);
void(*pre_reset) (struct usb_interface*intf);
void(*post_reset)(struct usb_interface*intf);
const struct usb_device_id*id_table;
struct usb_dynids dynids;
struct usbdrv_wrap drvwrap;
unsigned int no_dynamic_id:1;
unsigned int supports_autosuspend:1;
};
Name為驅動(dòng)程序的名字,對應于/sys/bus/usb/drivers/下面的子目錄名稱(chēng)。它只是彼此區別的一個(gè)代號,這里的名字在所有的USB驅動(dòng)中必須是唯一的。probe用來(lái)看看這個(gè)USB驅動(dòng)是否愿意接受某個(gè)接口的函數。Disconnect函數將在接口失去聯(lián)系或使用rmmod卸載驅動(dòng)將它和接口強行分開(kāi)時(shí)被調用。Ioctl函數則用在驅動(dòng)通過(guò)usbfs和用戶(hù)空間進(jìn)行交流時(shí)使用。Suspend、esume分別在設備被掛起和喚醒時(shí)使用。pre_reset、post_reset分別在設備將要復位(reset)和已經(jīng)復位后使用。id_table的變量可用來(lái)判斷是否支持某個(gè)設備接口。Dynids是支持動(dòng)態(tài)id的。實(shí)際上,即使驅動(dòng)已經(jīng)加載了,也可以添加新的id給它。drvwrap是給USB core區分設備驅動(dòng)和接口驅動(dòng)用的。no_dynamic_id可以用來(lái)禁止動(dòng)態(tài)id。supports_autosuspend可對autosuspend提供支持,如果設置為0,則不再允許綁定到這個(gè)驅動(dòng)的接口autosuspend。
接口驅動(dòng)
當insmod或modprobe驅動(dòng)的時(shí)候,經(jīng)過(guò)一個(gè)曲折的過(guò)程,就會(huì )調用相應USB驅動(dòng)里的xxx_init函數,進(jìn)而去調用usb_register (),以將相應的USB驅動(dòng)提交給設備模型,添加到USB總線(xiàn)的驅動(dòng)鏈表里。當rmmod驅動(dòng)時(shí),同樣,在經(jīng)過(guò)一個(gè)曲折的過(guò)程之后,再調用相應驅動(dòng)里的xxx_cleanup函數,進(jìn)而調用usb_deregister ()將相應的USB驅動(dòng)從USB總線(xiàn)的驅動(dòng)鏈表里刪除。
5 結束語(yǔ)
本文介紹了Linux下USB core的工作原理,同時(shí)介紹了驅動(dòng)USB必須了解的四個(gè)描述符。此外,還介紹了Linux下usb接口驅動(dòng)的工作原理。本文介紹的方法能適應于Linux下各種不同的USB設備驅動(dòng)程序的開(kāi)發(fā)。本文引用地址:http://dyxdggzs.com/article/149534.htm linux操作系統文章專(zhuān)題:linux操作系統詳解(linux不再難懂)
評論