直播推薦
企業(yè)動(dòng)態(tài)
- 首都共享中央廚房首批項(xiàng)目在平谷區(qū)開(kāi)工 助力北京打造食品安全城市
- 深耕專業(yè)沃土:東莞皓天試驗(yàn)設(shè)備有限公司啟動(dòng)全員新款設(shè)備知識(shí)攻堅(jiān)行動(dòng)
- ?凌晨裝車(chē)、跨省奔襲:皓天試驗(yàn)設(shè)備技術(shù)團(tuán)隊(duì)的秦皇島交付記
- 中國(guó)石油和化工勘察設(shè)計(jì)協(xié)會(huì)電氣設(shè)計(jì)專業(yè)委員會(huì)2025年年中工作會(huì)議
- 從構(gòu)建方法論到服務(wù)加碼,華為加速釋放AI時(shí)代制造業(yè)數(shù)智潛能
- 銳呈NTP網(wǎng)絡(luò)時(shí)鐘在內(nèi)蒙滿洲里熱電廠成功投運(yùn)
- 柔性生產(chǎn)vs僵化成本,U9 cloud如何為智造企業(yè)重構(gòu)“成本基因”?
- 嚴(yán)苛測(cè)試護(hù)航半導(dǎo)體品質(zhì):浙江企業(yè)添TEE-408PF快速溫變箱
推薦展會(huì)
前言:Linux以其穩(wěn)定、、易定制、硬件支持廣泛、源代碼開(kāi)放等特點(diǎn),已在嵌入式領(lǐng)域迅速崛起,被上許多大型的跨國(guó)企業(yè)用作嵌入式產(chǎn)品的系統(tǒng)平臺(tái)。
USB是Universal Serial Bus (通用串行總線)的縮寫(xiě),是1995年由Microsoft、Compaq、IBM等公司聯(lián)合制定的一種新的PC串行通信協(xié)議。它是一種快速、靈活的總線接口。與其它通信接口相比較,USB接口的zui大特點(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ī)存?。≧andomAccess),字符設(shè)備則沒(méi)有這個(gè)要求。典型的字符設(shè)備包括鼠標(biāo)、鍵盤(pán)、串行口等,而塊設(shè)備主要包括硬盤(pán)軟盤(pán)設(shè)備、CD-Rom等。由于USB設(shè)備主要都是通過(guò)快速串行通訊來(lái)讀寫(xiě)數(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下編寫(xiě)USB設(shè)備的驅(qū)動(dòng)程序時(shí),從嚴(yán)格意義上講,就是使用這些USB core的子系統(tǒng)所定義的數(shù)據(jù)結(jié)構(gòu)、宏和函數(shù)來(lái)編寫(xiě)數(shù)據(jù)的處理功能。在Linux下,core、host controller和driver三者之間的關(guān)系如圖1所示。
2.2 USB core的初始化
USB core從USB子系統(tǒng)的初始化開(kāi)始。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)檫@部分代碼是核心,通常把它看作一個(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è)鍵盤(pán),上面還帶一個(gè)揚(yáng)聲器,這就是兩個(gè)接口,就需要兩個(gè)驅(qū)動(dòng)程序,一個(gè)是鍵盤(pán)驅(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í)編寫(xiě)的USB驅(qū)動(dòng)通常指的是寫(xiě)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)程序的編寫(xiě)。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ù)將在接口失去或使用rmmod卸載驅(qū)動(dòng)將它和接口強(qiáng)行分開(kāi)時(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。
當(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)程序的開(kāi)發(fā)。
免責(zé)聲明
- 凡本網(wǎng)注明"來(lái)源:智能制造網(wǎng)"的所有作品,版權(quán)均屬于智能制造網(wǎng),轉(zhuǎn)載請(qǐng)必須注明智能制造網(wǎng),http://www.decaoba.com。違反者本網(wǎng)將追究相關(guān)法律責(zé)任。
- 企業(yè)發(fā)布的公司新聞、技術(shù)文章、資料下載等內(nèi)容,如涉及侵權(quán)、違規(guī)遭投訴的,一律由發(fā)布企業(yè)自行承擔(dān)責(zé)任,本網(wǎng)有權(quán)刪除內(nèi)容并追溯責(zé)任。
- 本網(wǎng)轉(zhuǎn)載并注明自其它來(lái)源的作品,目的在于傳遞更多信息,并不代表本網(wǎng)贊同其觀點(diǎn)或證實(shí)其內(nèi)容的真實(shí)性,不承擔(dān)此類作品侵權(quán)行為的直接責(zé)任及連帶責(zé)任。其他媒體、網(wǎng)站或個(gè)人從本網(wǎng)轉(zhuǎn)載時(shí),必須保留本網(wǎng)注明的作品來(lái)源,并自負(fù)版權(quán)等法律責(zé)任。
- 如涉及作品內(nèi)容、版權(quán)等問(wèn)題,請(qǐng)?jiān)谧髌钒l(fā)表之日起一周內(nèi)與本網(wǎng)聯(lián)系,否則視為放棄相關(guān)權(quán)利。
2026杭州國(guó)際人形機(jī)器人與機(jī)器人技術(shù)展覽會(huì)
展會(huì)城市:杭州市展會(huì)時(shí)間:2026-05-14