嵌入式Linux驅(qū)動(dòng)程序開(kāi)發(fā)(五)-基于libusb的USB驅(qū)動(dòng)開(kāi)發(fā)

姓名:薛紹宏? ? ?學(xué)號(hào):19020100016? ? 學(xué)院:電子工程學(xué)院

轉(zhuǎn)自:https://blog.csdn.net/su1041168096/article/details/78989835?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522162722361816780265466801%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fall.%2522%257D&request_id=162722361816780265466801&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~first_rank_v2~rank_v29-18-78989835.pc_search_result_control_group&utm_term=%E5%B5%8C%E5%85%A5%E5%BC%8Flinux%E9%A9%B1%E5%8A%A8%E5%BC%80%E5%8F%91&spm=1018.2226.3001.4449

【嵌牛導(dǎo)讀】本文介紹了嵌入式Linux基于libusb的USB驅(qū)動(dòng)開(kāi)發(fā)

【嵌牛鼻子】嵌入式Linux驅(qū)動(dòng)程序開(kāi)發(fā)

【嵌牛提問(wèn)】嵌入式Linux的USB驅(qū)動(dòng)如何基于libusb進(jìn)行開(kāi)發(fā)示惊?

【嵌牛正文】

由于usb設(shè)備的普遍性及其多樣性究西,大量的usb設(shè)備的驅(qū)動(dòng)開(kāi)發(fā)也就成為開(kāi)發(fā)者做的最多的事情。Linux平臺(tái)上蘸炸,內(nèi)核驅(qū)動(dòng)的開(kāi)發(fā)由于內(nèi)核的復(fù)雜和版本問(wèn)題慕购,初學(xué)者難以入手聊疲,驅(qū)動(dòng)程序也不易升級(jí)和維護(hù)。本文主要介紹Linux平臺(tái)下使用libusb庫(kù)基于usb文件系統(tǒng)的驅(qū)動(dòng)開(kāi)發(fā)脓钾,并將其應(yīng)用到嵌入式系統(tǒng)中售睹,可顯著降低開(kāi)發(fā)難度,提高工作效率

1.前言

Linux內(nèi)核經(jīng)過(guò)開(kāi)發(fā)人員的不斷努力可训,已經(jīng)變得十分地完善和強(qiáng)大昌妹。其中,設(shè)備驅(qū)動(dòng)占據(jù)了內(nèi)核的很大一部分握截,內(nèi)核都能夠高效飞崖、穩(wěn)定地驅(qū)動(dòng)大部分設(shè)備。而另外一些設(shè)備谨胞,注入自己設(shè)計(jì)的硬件產(chǎn)品固歪。這些驅(qū)動(dòng)就需要驅(qū)動(dòng)工程師開(kāi)發(fā)出相關(guān)的內(nèi)核設(shè)備驅(qū)動(dòng)了。內(nèi)核驅(qū)動(dòng)有他的優(yōu)點(diǎn),然而在內(nèi)核驅(qū)動(dòng)開(kāi)發(fā)過(guò)程中會(huì)遇到如下的一些問(wèn)題:

對(duì)于不用的Linux內(nèi)核版本牢裳,驅(qū)動(dòng)程序也會(huì)有不同的版本逢防。不利于升級(jí)和維護(hù)。

Linux自帶的驅(qū)動(dòng)程序開(kāi)發(fā)蒲讯,需要對(duì)內(nèi)核的重新編譯忘朝,而且開(kāi)發(fā)出來(lái)的驅(qū)動(dòng)模塊比較大。

所以判帮,如果我們能夠找到一個(gè)為用戶(hù)空間提供與內(nèi)核版本無(wú)關(guān)的通用接口的方法局嘁,就能夠不必重新改變編譯好的內(nèi)核,也不必為內(nèi)核版本兼容性問(wèn)題而頭痛晦墙,只需在用戶(hù)空間開(kāi)發(fā)程序悦昵。這樣就極大地提高了開(kāi)發(fā)效率,縮短了開(kāi)發(fā)周期晌畅。

USB協(xié)議是目前使用最廣泛的外部總線(xiàn)協(xié)議但指,Linux對(duì)usb控制器、usb核心和常用的usb設(shè)備驅(qū)動(dòng)有了比較完善的支持抗楔。但由于usb所支持的設(shè)備的多樣性枚赡,一些特殊的usb設(shè)備的驅(qū)動(dòng)還需要開(kāi)發(fā)人員自行編寫(xiě)。而libusb為開(kāi)發(fā)人員提供了在用戶(hù)空間操作usb設(shè)備的API函數(shù)庫(kù)谓谦,使usb驅(qū)動(dòng)開(kāi)發(fā)變得極為方便贫橙。

2.實(shí)現(xiàn)原理

2.1USB簡(jiǎn)介

usb(Universal Serial Bus)是用于將適用usb的外圍設(shè)備連接到主機(jī)的外部總線(xiàn)結(jié)構(gòu)。目前usb接口規(guī)范主要有:USB1.1(低速1.5Mb/s反粥,全速12Mb/s)和USB2.0(高速480Mb/s)卢肃,能夠滿(mǎn)足大部分外圍設(shè)備的傳輸速度要求。usb同時(shí)又是一種通信協(xié)議才顿,他支持主系統(tǒng)(host)和usb的外圍設(shè)備(device)之間的數(shù)據(jù)傳輸莫湘。當(dāng)前流行的USB Host規(guī)范有:OHCI、UHCI和EHCI郑气。嵌入式系統(tǒng)主要是使用OHCI規(guī)范幅垮。

usb驅(qū)動(dòng)分為usb主機(jī)端驅(qū)動(dòng)程序和usb設(shè)備端驅(qū)動(dòng)程序,本文重點(diǎn)分析usb主機(jī)端驅(qū)動(dòng)程序的開(kāi)發(fā)過(guò)程尾组。USB主機(jī)(host)驅(qū)動(dòng)結(jié)構(gòu)如圖:

開(kāi)發(fā)人員主要關(guān)注usb設(shè)備驅(qū)動(dòng)部分忙芒。usb設(shè)備的邏輯組織中,包含設(shè)備(device)讳侨、配置(config)呵萨、接口(interface)和端口(endpoint)四個(gè)層次:

每個(gè)usb設(shè)備可以有一個(gè)或多個(gè)配置,但一次只能選中其中一個(gè)跨跨。接口經(jīng)捆綁為配置潮峦。接口代表了一個(gè)基本功能。

每個(gè)usb驅(qū)動(dòng)程序控制一個(gè)接口,而一個(gè)接口有不同的設(shè)置(setting)忱嘹,但同一時(shí)間只能有一種活躍配置(cur_altsetting)嘱腥。設(shè)備接口是端點(diǎn)的集合(collection),端點(diǎn)是usb通信的最基本形式拘悦。usb主機(jī)(host)通過(guò)端點(diǎn)與usb設(shè)備進(jìn)行通信爹橱。

usb端點(diǎn)有以下四種傳輸方式:控制(Control),等待(iso)窄做、中斷(interrupt)、批量(bulk)慰技⊥终担控制和批量端點(diǎn)用于異步的少量數(shù)據(jù)傳輸,而批量和等時(shí)端點(diǎn)是周期性的吻商√图眨控制和中斷端點(diǎn)是用于少量數(shù)據(jù)傳輸,而批量和等時(shí)端點(diǎn)用于大量數(shù)據(jù)傳輸艾帐。

控制端點(diǎn)同城用于配置設(shè)備乌叶、獲取設(shè)備信息、發(fā)送命令到設(shè)備柒爸、或者獲取設(shè)備的狀態(tài)報(bào)告准浴,“端點(diǎn)0”為默認(rèn)的控制端點(diǎn),usb核心使用該端點(diǎn)在設(shè)備插入時(shí)進(jìn)行設(shè)備的配置捎稚。批量端點(diǎn)它要求數(shù)據(jù)傳輸?shù)臏?zhǔn)確性乐横,但不保證固定時(shí)間內(nèi)的完成。中斷端點(diǎn)是例如usb鍵盤(pán)和鼠標(biāo)所使用的的主要傳輸方式今野。libusb主要提供控制葡公、批量和中斷的傳輸方式的API函數(shù)。

2.2usb文件系統(tǒng)(usbfs)

Linux內(nèi)核提供了usb文件系統(tǒng)条霜,他需要編寫(xiě)內(nèi)核時(shí)選中相關(guān)編譯選項(xiàng)催什。并在系統(tǒng)啟動(dòng)運(yùn)行時(shí)動(dòng)態(tài)掛載≡姿可在/etc/fstab文件中添加如下一行:

nonc /proc/bus/usb usbfs defaults 0 0

或者輸入命令:

mount -t usbfs none /proc/bus/usb

usbfs動(dòng)態(tài)跟蹤總線(xiàn)上插入和移除的設(shè)備蒲凶,通過(guò)它可以查看系統(tǒng)中usb的設(shè)備信息,包括拓?fù)洳鹉凇挶⒃O(shè)備描述符、產(chǎn)品ID矛纹、配置描述符臂聋、接口描述符、端點(diǎn)描述符等。usbfs還允許用戶(hù)空間的程序直接訪(fǎng)問(wèn)usb設(shè)備孩等,這使得容易維護(hù)和調(diào)試艾君。

usbfs也至此各種ioctl的調(diào)用。有了這些ioctl我們就可以編寫(xiě)用戶(hù)空間的usb驅(qū)動(dòng)程序肄方,而libusb做的工作就是把這些ioctl開(kāi)發(fā)成一個(gè)庫(kù)冰垄。

3.libusb實(shí)現(xiàn)驅(qū)動(dòng)開(kāi)發(fā)

3.1libusb簡(jiǎn)介

libusb是一種高級(jí)別的API,它封裝了低級(jí)別的內(nèi)核與USB模塊的交互权她,并提供了一系列適合在用戶(hù)空間進(jìn)行usb驅(qū)動(dòng)開(kāi)發(fā)的函數(shù)虹茶。libusb基于usb文件系統(tǒng)提供的usb接口,端點(diǎn)等信息隅要,與usb設(shè)備進(jìn)行通信蝴罪。顯然,只要開(kāi)發(fā)平臺(tái)上的內(nèi)核支持usb文件系統(tǒng)步清,我們就可以利用libusb進(jìn)行usb驅(qū)動(dòng)開(kāi)發(fā)要门。

libusb可以跨平臺(tái)實(shí)現(xiàn),開(kāi)發(fā)的程序很容易在不同操作系統(tǒng)上一直廓啊。對(duì)于Linux操作系統(tǒng)欢搜,也很容易在不同的CPU架構(gòu)間進(jìn)行移植,而且不低擔(dān)心內(nèi)核版本造成的種種問(wèn)題谴轮。相對(duì)于Linux內(nèi)核驅(qū)動(dòng)開(kāi)發(fā)炒瘟,libusb無(wú)疑是一種省時(shí)省力而又行之有效的開(kāi)發(fā)工具。

libusb定義了struct usb_bus第步,struct usb_device 和usb_xxx_descriptor來(lái)對(duì)usb總線(xiàn)唧领、設(shè)備、配置和端點(diǎn)等進(jìn)行描述雌续。

一般可通過(guò)libusb提供的一些初始化函數(shù)斩个,在usb文件系統(tǒng)中查找先關(guān)的總線(xiàn)和設(shè)備,并保存在幾個(gè)對(duì)應(yīng)的數(shù)據(jù)結(jié)構(gòu)中:

usb_init()函數(shù)檢查環(huán)境變量USB_DEVFS_PATH驯杜,目錄/dev/bus/usb或目錄/proc/bus/usb,若指定路徑下含有usb文件系統(tǒng)信息受啥,則將路徑保存在全局變量usb_path[PATH_MAX+1]中。

usb_find_busses()函數(shù)會(huì)根據(jù)usb_path[]找到系統(tǒng)中所有的usb bus,并組成鏈表鸽心,由全局結(jié)構(gòu)指針usb_busses指向滚局。

usb_find_devices()函數(shù)則遍歷usb_busses指向的鏈表,尋找所有bus上的所有usb設(shè)備顽频。每個(gè)bus上的所有devices列表由usb_bus結(jié)構(gòu)成員struct usb_device *devices指向藤肢。

我們可用兩層的for循環(huán),遍歷usb_busses指向的鏈表糯景,找到與指定描述符相符的usb_device嘁圈。如通常是通過(guò)IDVender和IDProduct查找省骂。

usb_dev_handle是一個(gè)十分重要的句柄結(jié)構(gòu),如果要對(duì)usb設(shè)備最住、接口钞澳、端點(diǎn)等操作,都離不開(kāi)它涨缚,結(jié)構(gòu)如下:

struct usb_dev_handle{

int fd;

struct usb_bus *bus;

struct usb_device *device;

int config;

int interface;

int altsetting;

void *impl_info;

1

2

3

4

5

6

7

8

域fd為文件描述符轧粟,與文件系統(tǒng)關(guān)聯(lián):域bus和device則指向要處理的usb設(shè)備。

開(kāi)發(fā)人員可以使用usb_open()脓魏,打開(kāi)指定的usb設(shè)備Dev兰吟,并返回相應(yīng)的句柄結(jié)構(gòu):

usb_dev_handle *dev_handle = usb_open(dev);

之后,dev_handle便貫穿于對(duì)應(yīng)usb設(shè)備的操作過(guò)程中茂翔,直至最后調(diào)用usb_close()關(guān)閉指定的usb設(shè)備混蔼,釋放該句柄。

開(kāi)放人員可使用usb_set_configuration()檩电,usb_setaltinterface()等函數(shù)對(duì)usb設(shè)備的配置,接口和端點(diǎn)等進(jìn)行設(shè)定府树。然后調(diào)用usb_control_msg()進(jìn)行控制傳輸俐末,或usb_bulk_write(),usb_bulk_read()進(jìn)行大批量的端點(diǎn)讀寫(xiě)奄侠。

3.2開(kāi)發(fā)實(shí)例

libusb要應(yīng)用到嵌入式系統(tǒng)中卓箫,需要交叉編譯;開(kāi)發(fā)代碼中要包含libusb的頭文件usb.h垄潮,并在編譯時(shí)烹卒,要是用-I和-L選項(xiàng)指定libusb的頭文件和庫(kù)文件的路徑,和-lusb指定libusb.a靜態(tài)庫(kù)文件弯洗。

下面的偽代碼在系統(tǒng)中按廠(chǎng)商號(hào)和產(chǎn)品號(hào)找到usb圖像采集設(shè)備并讀bulk端點(diǎn)到緩沖中旅急,

int main(void)

{

? ? //...一些初始化工作

? ? dev_usbdev_probe();//找到usb設(shè)備

? ? dev_hanle = usb_open(dev); //打開(kāi)設(shè)備

? ? //發(fā)送控制信息,請(qǐng)求傳輸

? ? usb_control_msg(dev_handle,0x40,0xb5,2,0,buffer,sizeof(buffer),1000);

? ? if(dev_handle){

? ? //若請(qǐng)求成功牡整,從端點(diǎn)6傳輸數(shù)據(jù)到image_buffer中

? ? ? ? usb_bulk_read(dev_handle,6,&image_buffer[64],64,1000);

? ? }

}

1

2

3

4

5

6

7

8

9

10

11

12

4.總結(jié)

本文實(shí)現(xiàn)基礎(chǔ)是usbfs允許用戶(hù)空間的程序直接訪(fǎng)問(wèn)usb設(shè)備藐吮,這使得許多內(nèi)核驅(qū)動(dòng)程序可以遷移到用戶(hù)空間,通過(guò)libusb庫(kù)提供的API函數(shù)實(shí)現(xiàn)嵌入式Linux驅(qū)動(dòng)開(kāi)發(fā)的方法逃贝,使得開(kāi)發(fā)人員無(wú)需被底層的usb協(xié)議所困谣辞,無(wú)需區(qū)分不同版本內(nèi)核驅(qū)動(dòng)開(kāi)發(fā),從而使得usb的驅(qū)動(dòng)開(kāi)發(fā)更容易維護(hù)和調(diào)試沐扳,從而可以提高開(kāi)發(fā)效率并縮短開(kāi)發(fā)周期泥从。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市沪摄,隨后出現(xiàn)的幾起案子躯嫉,更是在濱河造成了極大的恐慌纱烘,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,682評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件和敬,死亡現(xiàn)場(chǎng)離奇詭異凹炸,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)昼弟,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,277評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén)啤它,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人舱痘,你說(shuō)我怎么就攤上這事变骡。” “怎么了芭逝?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,083評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵塌碌,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我旬盯,道長(zhǎng)台妆,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,763評(píng)論 1 295
  • 正文 為了忘掉前任胖翰,我火速辦了婚禮接剩,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘萨咳。我一直安慰自己懊缺,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,785評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布培他。 她就那樣靜靜地躺著鹃两,像睡著了一般。 火紅的嫁衣襯著肌膚如雪舀凛。 梳的紋絲不亂的頭發(fā)上俊扳,一...
    開(kāi)封第一講書(shū)人閱讀 51,624評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音猛遍,去河邊找鬼拣度。 笑死,一個(gè)胖子當(dāng)著我的面吹牛螃壤,可吹牛的內(nèi)容都是我干的抗果。 我是一名探鬼主播,決...
    沈念sama閱讀 40,358評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼奸晴,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼冤馏!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起寄啼,我...
    開(kāi)封第一講書(shū)人閱讀 39,261評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤逮光,失蹤者是張志新(化名)和其女友劉穎代箭,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體涕刚,經(jīng)...
    沈念sama閱讀 45,722評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡嗡综,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了杜漠。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片极景。...
    茶點(diǎn)故事閱讀 40,030評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖驾茴,靈堂內(nèi)的尸體忽然破棺而出盼樟,到底是詐尸還是另有隱情,我是刑警寧澤锈至,帶...
    沈念sama閱讀 35,737評(píng)論 5 346
  • 正文 年R本政府宣布晨缴,位于F島的核電站,受9級(jí)特大地震影響峡捡,放射性物質(zhì)發(fā)生泄漏击碗。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,360評(píng)論 3 330
  • 文/蒙蒙 一们拙、第九天 我趴在偏房一處隱蔽的房頂上張望稍途。 院中可真熱鬧,春花似錦睛竣、人聲如沸晰房。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,941評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至与境,卻和暖如春验夯,著一層夾襖步出監(jiān)牢的瞬間摔刁,已是汗流浹背挥转。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,057評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留共屈,地道東北人绑谣。 一個(gè)月前我還...
    沈念sama閱讀 48,237評(píng)論 3 371
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像拗引,于是被迫代替她去往敵國(guó)和親借宵。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,976評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容