免费视频淫片aa毛片_日韩高清在线亚洲专区vr_日韩大片免费观看视频播放_亚洲欧美国产精品完整版

打開APP
userphoto
未登錄

開通VIP,暢享免費(fèi)電子書等14項(xiàng)超值服

開通VIP
Linux下USB core的工作原理及設(shè)備驅(qū)動(dòng)技術(shù)|Linux

Linux下USB core的工作原理及設(shè)備驅(qū)動(dòng)技術(shù)

Linux下USB core的工作原理及設(shè)備驅(qū)動(dòng)技術(shù)

Linux下USB core的工作原理及設(shè)備驅(qū)動(dòng)技術(shù)


Linux以其穩(wěn)定、高效、易定制、硬件支持廣泛、源代碼開放等特點(diǎn),已在嵌入式領(lǐng)域迅速崛起,被國(guó)際上許多大型的跨國(guó)企業(yè)用作嵌入式產(chǎn)品的系統(tǒng)平臺(tái)。



USB是Universal Serial Bus (通用串行總線)的縮寫,是1995年由Microsoft、Compaq、IBM等公司聯(lián)合制定的一種新的PC串行通信協(xié)議。它是一種快速、靈活的總線接口。與其它通信接口相比較,USB接口的最大特點(diǎn)是易于使用,這也是USB的主要設(shè)計(jì)目標(biāo)。USB的成功得益于在USB標(biāo)準(zhǔn)中除定義了通信的物理層和電器層標(biāo)準(zhǔn)外。還定義了一套相對(duì)完整的軟件協(xié)議堆棧。這使得多數(shù)USB設(shè)備都很容易在各種平臺(tái)上工作。作為一種高速總線接口,USB適用于多種設(shè)備(如數(shù)碼相機(jī)、MP3播放器、高速數(shù)據(jù)采集設(shè)備等)。另外,USB接口還支持熱插拔,而且所有的配置過(guò)程都由系統(tǒng)自動(dòng)完成,無(wú)須用戶干預(yù)。



1 Linux下的USB設(shè)備驅(qū)動(dòng)



在Linux內(nèi)核的不斷升級(jí)過(guò)程中,驅(qū)動(dòng)程序的結(jié)構(gòu)相對(duì)穩(wěn)定。由于USB設(shè)備也是外圍設(shè)備的一種,因此,它的驅(qū)動(dòng)程序結(jié)構(gòu)與普通設(shè)備的驅(qū)動(dòng)程序相同。Linux系統(tǒng)的設(shè)備分為字符設(shè)備(CharDevice)和塊設(shè)備(BlockDevice)。字符設(shè)備支持面向塊字符的I/O操作,它不通過(guò)系統(tǒng)的快速緩存,而只支持順序存取。塊設(shè)備則支持面向塊的I/O操作,所有塊設(shè)備的I/O操作都通過(guò)在內(nèi)核地址空間的I/O緩沖區(qū)進(jìn)行,可以支持幾乎任意長(zhǎng)度和任意位置上的I/O請(qǐng)求。塊設(shè)備與字符設(shè)備還有一點(diǎn)不同,就是塊設(shè)備必須能夠隨機(jī)存取(RandomAccess),字符設(shè)備則沒(méi)有這個(gè)要求。典型的字符設(shè)備包括鼠標(biāo)、鍵盤、串行口等,而塊設(shè)備主要包括硬盤軟盤設(shè)備、CD-Rom等。由于USB設(shè)備主要都是通過(guò)快速串行通訊來(lái)讀寫數(shù)據(jù),因此一般都可作為字符設(shè)備來(lái)進(jìn)行處理。



2 Linux下的USB core



2.1 Linux中USB core與USB的結(jié)構(gòu)關(guān)系



Linux操作系統(tǒng)中有一個(gè)叫做“USB core”的子系統(tǒng),可提供支持USB設(shè)備驅(qū)動(dòng)程序的API和USB主機(jī)控制器的驅(qū)動(dòng)程序。同時(shí)提供有許多數(shù)據(jù)結(jié)構(gòu)、宏定義和功能函數(shù)來(lái)對(duì)硬件或設(shè)備進(jìn)行支持。在Linux下編寫USB設(shè)備的驅(qū)動(dòng)程序時(shí),從嚴(yán)格意義上講,就是使用這些USB core的子系統(tǒng)所定義的數(shù)據(jù)結(jié)構(gòu)、宏和函數(shù)來(lái)編寫數(shù)據(jù)的處理功能。在Linux下,core、host controller和driver三者之間的關(guān)系如圖1所示。







2.2 USB core的初始化



USB core從USB子系統(tǒng)的初始化開始。USB子系統(tǒng)的初始化則在文件drivers/usb/core/usb.c里。其代碼如下:



  subsys_initcall(usb_init);

  module_exit(usb_exit);



代碼中的subsys_initcall是一個(gè)宏,相當(dāng)于module_init,只不過(guò)因?yàn)檫@部分代碼是核心,開發(fā)者通常把它看作一個(gè)子系統(tǒng),而不僅僅是一個(gè)模塊。因?yàn)閁SB core模塊代表的不是某一個(gè)設(shè)備,而是所有USB設(shè)備賴以生存的模塊。因此,在Linux中,像這樣把一個(gè)類別的設(shè)備驅(qū)動(dòng)歸結(jié)為一個(gè)子系統(tǒng)(比如PCI子系統(tǒng)、scsi子系統(tǒng)等)?;旧?,drivers/目錄下面第一層的每個(gè)目錄都可算作一個(gè)子系統(tǒng),因?yàn)樗鼈兇砹艘活愒O(shè)備。一般地,usb_init是真正的初始化函數(shù),而usb_exit()則是整個(gè)USB子系統(tǒng)結(jié)束時(shí)的清理函數(shù):







函數(shù)usb_init主要完成初始化和注冊(cè)設(shè)備。



2.3 USB里的設(shè)備模型



Linux里一個(gè)很重要的概念是設(shè)備模型。對(duì)于驅(qū)動(dòng)來(lái)說(shuō),設(shè)備的概念就是總線和與其相連的各種設(shè)備。在內(nèi)核里,總線、設(shè)備、驅(qū)動(dòng)也就是bus、device、driver是設(shè)備模型很重要的三個(gè)概念,它們都有自己專屬的結(jié)構(gòu)。在include/linux/devide.h里的定義為:



struct bus_type {……};

struct device {……);

struct device_driver {……};



每次出現(xiàn)一個(gè)設(shè)備都要向總線注冊(cè),每次出現(xiàn)一個(gè)驅(qū)動(dòng),也要向總線注冊(cè)。系統(tǒng)初始化時(shí),應(yīng)掃描連接許多設(shè)備,并為每一個(gè)設(shè)備建立一個(gè)struct device的變量。每一次都應(yīng)有一個(gè)驅(qū)動(dòng)程序,并要準(zhǔn)備一個(gè)struct device_driver結(jié)構(gòu)的變量。還要把這些變量加入相應(yīng)的鏈表(如把device插入devices鏈表,driver插入drivers鏈表)。這樣,通過(guò)總線就能找到每一個(gè)設(shè)備和每一個(gè)驅(qū)動(dòng)。然而,假如計(jì)算機(jī)里只有設(shè)備卻沒(méi)有對(duì)應(yīng)的驅(qū)動(dòng),那么設(shè)備將無(wú)法工作。反過(guò)來(lái),倘若只有驅(qū)動(dòng)卻沒(méi)有設(shè)備,驅(qū)動(dòng)也起不了任何作用。對(duì)于USB設(shè)備,它可以在計(jì)算機(jī)啟動(dòng)以后再插入或者拔出計(jì)算機(jī)。由于device可以在任何時(shí)刻出現(xiàn),而driver也可以在任何時(shí)刻被加載,所以,每當(dāng)一個(gè)struct device誕生時(shí),它就會(huì)去BUS的drivers鏈表中尋找自己的另一半。如果找到了匹配的設(shè)備,就調(diào)用device_bind_driver,并綁定好。



Linux設(shè)備模型中的總線落實(shí)在USB子系統(tǒng)里就是usb_bus_type,它在usb_init函數(shù)中可用retval=bus_register(&usb_bus_type)語(yǔ)句注冊(cè),而在driver.c文件里的定義如下:







該函數(shù)的形參對(duì)應(yīng)的就是總線兩條鏈表里的設(shè)備和驅(qū)動(dòng)。當(dāng)總線上有新設(shè)備和驅(qū)動(dòng)時(shí),這個(gè)函數(shù)就會(huì)被調(diào)用。



3 USB驅(qū)動(dòng)程序的描述符



一個(gè)設(shè)備可以有多個(gè)接口,一個(gè)接口可代表一個(gè)功能,因此,每個(gè)接口都對(duì)應(yīng)著一個(gè)驅(qū)動(dòng)。例如一個(gè)USB設(shè)備有兩種功能,一個(gè)鍵盤,上面還帶一個(gè)揚(yáng)聲器,這就是兩個(gè)接口,就需要兩個(gè)驅(qū)動(dòng)程序,一個(gè)是鍵盤驅(qū)動(dòng)程序,一個(gè)是音頻流驅(qū)動(dòng)程序。



一個(gè)驅(qū)動(dòng)程序是否支持一個(gè)設(shè)備,要通過(guò)讀取設(shè)備的描述符來(lái)判斷。那么,什么是USB的描述符呢?USB的描述符是一個(gè)帶有預(yù)定義格式的數(shù)據(jù)結(jié)構(gòu),里面保存有USB設(shè)備的各種屬性和相關(guān)信息,可以通過(guò)向設(shè)備請(qǐng)求獲得它們的描述符內(nèi)容來(lái)深刻了解和感知一個(gè)USB設(shè)備。主要有四種USB描述符,分別為:接口描述符、端點(diǎn)描述符、設(shè)備描述符和配置描述符。



協(xié)議規(guī)定:一個(gè)USB設(shè)備必須支持這四大描述符,還有些描述符不是必須包含的,有些特殊設(shè)備用來(lái)描述設(shè)備的不同特性,但這四大描述符是一個(gè)都不能少的。USB設(shè)備里有一個(gè)eeprom,可用來(lái)存儲(chǔ)設(shè)備本身信息,設(shè)備的描述符就存儲(chǔ)在這里。



上述四個(gè)描述符分別放在了include/linux/usb.h文件中的struct usb_host_interface、structusb_host_endpoint、struct usb_device、struetusb_host_config里,而描述符結(jié)構(gòu)體本身定義在include/linux/usb/ch9.h里.并分別用struct usb_interface_descriptor、struct usb_host_endpoint、structusb_device_descriptor和struct usb_config_descriptor來(lái)表示。描述符結(jié)構(gòu)體的定義應(yīng)完全按照USB協(xié)議對(duì)描述符的規(guī)定來(lái)定義。



4 USB接口驅(qū)動(dòng)



4.1 接口結(jié)構(gòu)



平時(shí)編寫的USB驅(qū)動(dòng)通常指的是寫USB接口的驅(qū)動(dòng),一個(gè)接口對(duì)應(yīng)一個(gè)接口驅(qū)動(dòng)程序,需要以一個(gè)struct usb_driver結(jié)構(gòu)的對(duì)象為中心,并以設(shè)備的接口提供的功能為基礎(chǔ),來(lái)進(jìn)行USB驅(qū)動(dòng)程序的編寫。struct usb_driver結(jié)構(gòu)體一般定義在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為驅(qū)動(dòng)程序的名字,對(duì)應(yīng)于/sys/bus/usb/drivers/下面的子目錄名稱。它只是彼此區(qū)別的一個(gè)代號(hào),這里的名字在所有的USB驅(qū)動(dòng)中必須是唯一的。probe用來(lái)看看這個(gè)USB驅(qū)動(dòng)是否愿意接受某個(gè)接口的函數(shù)。Disconnect函數(shù)將在接口失去聯(lián)系或使用rmmod卸載驅(qū)動(dòng)將它和接口強(qiáng)行分開時(shí)被調(diào)用。Ioctl函數(shù)則用在驅(qū)動(dòng)通過(guò)usbfs和用戶空間進(jìn)行交流時(shí)使用。Suspend、esume分別在設(shè)備被掛起和喚醒時(shí)使用。pre_reset、post_reset分別在設(shè)備將要復(fù)位(reset)和已經(jīng)復(fù)位后使用。id_table的變量可用來(lái)判斷是否支持某個(gè)設(shè)備接口。Dynids是支持動(dòng)態(tài)id的。實(shí)際上,即使驅(qū)動(dòng)已經(jīng)加載了,也可以添加新的id給它。drvwrap是給USB core區(qū)分設(shè)備驅(qū)動(dòng)和接口驅(qū)動(dòng)用的。no_dynamic_id可以用來(lái)禁止動(dòng)態(tài)id。supports_autosuspend可對(duì)autosuspend提供支持,如果設(shè)置為0,則不再允許綁定到這個(gè)驅(qū)動(dòng)的接口autosuspend。



接口驅(qū)動(dòng)



當(dāng)insmod或modprobe驅(qū)動(dòng)的時(shí)候,經(jīng)過(guò)一個(gè)曲折的過(guò)程,就會(huì)調(diào)用相應(yīng)USB驅(qū)動(dòng)里的xxx_init函數(shù),進(jìn)而去調(diào)用usb_register (),以將相應(yīng)的USB驅(qū)動(dòng)提交給設(shè)備模型,添加到USB總線的驅(qū)動(dòng)鏈表里。當(dāng)rmmod驅(qū)動(dòng)時(shí),同樣,在經(jīng)過(guò)一個(gè)曲折的過(guò)程之后,再調(diào)用相應(yīng)驅(qū)動(dòng)里的xxx_cleanup函數(shù),進(jìn)而調(diào)用usb_deregister ()將相應(yīng)的USB驅(qū)動(dòng)從USB總線的驅(qū)動(dòng)鏈表里刪除。



5 結(jié)束語(yǔ)



本文介紹了Linux下USB core的工作原理,同時(shí)介紹了驅(qū)動(dòng)USB必須了解的四個(gè)描述符。此外,還介紹了Linux下usb接口驅(qū)動(dòng)的工作原理。本文介紹的方法能適應(yīng)于Linux下各種不同的USB設(shè)備驅(qū)動(dòng)程序的開發(fā)。





本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊舉報(bào)。
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
Linux內(nèi)核USB驅(qū)動(dòng)框架
Linux設(shè)備驅(qū)動(dòng)子系統(tǒng)終極彈 - USB
Linux usb子系統(tǒng)(一):子系統(tǒng)架構(gòu)
USB驅(qū)動(dòng)分析(一)
Linux驅(qū)動(dòng)開發(fā)方法論
轉(zhuǎn):Linux I2C 驅(qū)動(dòng)分析
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長(zhǎng)圖 關(guān)注 下載文章
綁定賬號(hào)成功
后續(xù)可登錄賬號(hào)暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服