Linux USB總線驅(qū)動(dòng)框架分析

作者:論壇答疑助手楊老師
授權(quán)轉(zhuǎn)載于公眾號(hào):柒零玖嵌入式(id:fengyuwuzu0519)有刪減修改。
1、USB驅(qū)動(dòng)引入
USB(全稱(chēng) Universal Serial Bus,通用串行總線),已經(jīng)成為PC及嵌入式設(shè)備中最常用、最便捷的通信接口。Linux USB子系統(tǒng)較為龐大,本文主要對(duì)Linux系統(tǒng)下的USB總線驅(qū)動(dòng)框架進(jìn)行概述,重點(diǎn)的細(xì)節(jié)待后續(xù)文章展開(kāi)。
首先來(lái)看一個(gè)現(xiàn)象,插入U(xiǎn)SB設(shè)備后linux系統(tǒng)打印如下日志:

拔出后提示:usb 1-1: USB disconnect, address 2
1.1 USB的硬件結(jié)構(gòu)

如圖集線器(USB Root Hub)端兩條數(shù)據(jù)線(D+D-),都接有15K的下拉電阻,當(dāng)無(wú)設(shè)備接入時(shí),集線器數(shù)據(jù)線D+D-的電壓為低電平。當(dāng)設(shè)備接入時(shí),由于設(shè)備的數(shù)據(jù)線上接有1.5K上拉電阻,使得1根數(shù)據(jù)線被拉高。集線器根據(jù)數(shù)據(jù)線被拉高得知有設(shè)備接入,并根據(jù)D+為高還是D-為高來(lái)判斷所接入的設(shè)備是全速USB設(shè)備(D+為高)還是低速USB設(shè)備(D-為高)。
1.2 USB接入識(shí)別大致過(guò)程
當(dāng)識(shí)別出有USB設(shè)備插入后,linux內(nèi)的USB總線驅(qū)動(dòng)程序發(fā)出命令至該設(shè)備,與設(shè)備對(duì)話,并詢(xún)問(wèn)設(shè)備信息(描述符),設(shè)備收到請(qǐng)求后,回復(fù)設(shè)備描述符給總線驅(qū)動(dòng)程序。且總線驅(qū)動(dòng)程序會(huì)為該設(shè)備分配一個(gè)地址,如上地址為2,當(dāng)后期訪問(wèn)某個(gè)USB設(shè)備時(shí),均會(huì)通過(guò)這個(gè)地址編號(hào),當(dāng)新接入的USB設(shè)備被第一次訪問(wèn)時(shí),以地址0來(lái)訪問(wèn)。當(dāng)USB總線驅(qū)動(dòng)程序識(shí)別出設(shè)備后,會(huì)為其找到該USB設(shè)備驅(qū)動(dòng)程序,如鍵盤(pán),鼠標(biāo),U盤(pán)。
USB通信過(guò)程均為主從結(jié)構(gòu),USB主機(jī)發(fā)起通信請(qǐng)求,設(shè)備進(jìn)行數(shù)據(jù)回復(fù),USB設(shè)備不具備主動(dòng)向主機(jī)通信的能力。
2、USB總線驅(qū)動(dòng)框架
如上,我們大致了解了USB的簡(jiǎn)單通信過(guò)程,那么什么是USB總線驅(qū)動(dòng)程序?什么是USB設(shè)備驅(qū)動(dòng)呢?
2.1 USB的總線驅(qū)動(dòng)框架? ? ?
USB總線框架總結(jié)為如下圖:

2.2 USB Core
USB Core這個(gè)模塊是純軟件部分,并不代表一個(gè)設(shè)備,是獨(dú)立于硬件的協(xié)議棧,它是所有USB設(shè)備賴(lài)以生存的模塊,即USB子系統(tǒng)的核心。代碼位于kernel/drivers/usb/core目錄下。
USB Core為設(shè)備驅(qū)動(dòng)程序提供服務(wù),提供一個(gè)用于訪問(wèn)和控制USB硬件的接口,而不用考慮系統(tǒng)當(dāng)前使用的哪種HOST Controller。USB Core將用戶的請(qǐng)求映射到相關(guān)的HCD,用戶不能直接訪問(wèn)HCD。USB Core就是HCD與USB設(shè)備的橋梁。

其Makefile為:

USB的初始化函數(shù)在kernel/drivers/usb/core/usb.c中定義,主要完成bus_register(USB總線注冊(cè))、usb_major_init(注冊(cè)u(píng)sb主控器字符設(shè)備)、usb_register(注冊(cè)u(píng)sbfs驅(qū)動(dòng))、usb_hub_init(USB Hub初始化,注冊(cè)hub驅(qū)動(dòng)、創(chuàng)建內(nèi)核守護(hù)線程來(lái)監(jiān)測(cè)hub端口的狀態(tài)變化)等工作,后續(xù)具體分析。
2.3 USB HCD(Host Controller Driver)
硬件主機(jī)控制器Host Controller之上運(yùn)行的是HCD,是對(duì)主機(jī)控制器硬件的一個(gè)抽象,實(shí)現(xiàn)核心層與控制器之間的對(duì)話接口,USB HCD包含多種USB接口規(guī)范:
(1)UHCI:Intel提供,通用主機(jī)控制接口,USB1.0/1.1;
(2)OHCI:微軟提供,開(kāi)放主機(jī)控制接口,USB1.0/1.1;
(3)EHCI:增強(qiáng)主機(jī)控制接口,USB2.0;
2.4 USB Device Driver
USB設(shè)備驅(qū)動(dòng)框架如下圖所示:

USB設(shè)備是由一些配置(configuration)、接口(interface)和端點(diǎn)(endpoint)組成,,即一個(gè)USB設(shè)備可以含有一個(gè)或多個(gè)配置,在每個(gè)配置中可含有一個(gè)或多個(gè)接口,在每個(gè)接口中可含有若干個(gè)端點(diǎn)。一個(gè)USB設(shè)備驅(qū)動(dòng)可能包含多個(gè)子驅(qū)動(dòng)。一個(gè)USB設(shè)備子驅(qū)動(dòng)程序?qū)?yīng)一個(gè)USB接口,而非整個(gè)USB設(shè)備。
USB設(shè)備使用各種描述符來(lái)說(shuō)明其設(shè)備架構(gòu),包括設(shè)備描述符、配置描述符、接口描述符、端點(diǎn)描述符、字符串描述符。后面單獨(dú)討論USB設(shè)備描述符。
USB傳輸?shù)膶?duì)象為端點(diǎn)(endpoint),每一個(gè)端點(diǎn)都有傳輸類(lèi)型,傳輸方向,除了端點(diǎn)0外,每一個(gè)端點(diǎn)只支持一個(gè)方向的數(shù)據(jù)傳輸,端點(diǎn)0用于控制傳輸,既能輸出也能輸入。輸入(IN)、輸出(OUT) "都是" 基于USB主機(jī)的立場(chǎng)說(shuō)的。比如鼠標(biāo)的數(shù)據(jù)是從鼠標(biāo)傳到PC機(jī), 對(duì)應(yīng)的端點(diǎn)稱(chēng)為"輸入端點(diǎn)"。
USB的傳輸類(lèi)型:
a. 控制傳輸:可靠,時(shí)間有保證,比如:USB設(shè)備的識(shí)別過(guò)程
b. 批量傳輸: 可靠, 時(shí)間沒(méi)有保證, 比如:U盤(pán)
c. 中斷傳輸:可靠,實(shí)時(shí),比如:USB鼠標(biāo)
d. 實(shí)時(shí)傳輸:不可靠,實(shí)時(shí),比如:USB攝像頭
針對(duì)不同類(lèi)型的USB設(shè)備,需要實(shí)現(xiàn)特定的USB驅(qū)動(dòng)程序。如HID(Human Interface Device), 屬于人機(jī)交互類(lèi)的設(shè)備,如USB鼠標(biāo),USB鍵盤(pán)等。該類(lèi)設(shè)備必須遵循HID設(shè)計(jì)規(guī)范。
在Linux內(nèi)核中,使用 struct usb_driver結(jié)構(gòu)體來(lái)描述一個(gè)USB驅(qū)動(dòng),通過(guò)usb_register在USB驅(qū)動(dòng)中注冊(cè)進(jìn)內(nèi)核。

因此USB設(shè)備驅(qū)動(dòng)開(kāi)發(fā),主要包含如下兩個(gè)部分:
分配/設(shè)置usb_driver結(jié)構(gòu)體,實(shí)現(xiàn)并填充結(jié)構(gòu)體內(nèi)容
注冊(cè)u(píng)sb_driver
后續(xù)將對(duì)USB鼠標(biāo)驅(qū)動(dòng)進(jìn)行詳細(xì)分析,其代碼在kernel/drivers/hid/usbhid/usbmouse.c
3、USB設(shè)備識(shí)別過(guò)程
通過(guò)以上分析,USB設(shè)備驅(qū)動(dòng)模型可以概括為如下圖。

主要包含三個(gè)部分:USB控制器驅(qū)動(dòng),USB核心,USB設(shè)備驅(qū)動(dòng)。如上圖khubd是USB守護(hù)進(jìn)程,當(dāng)USB設(shè)備插入的時(shí)候,守護(hù)進(jìn)程監(jiān)測(cè)到,USB主機(jī)控制器就會(huì)產(chǎn)生一個(gè)hub_irq中斷,控制器調(diào)用hub的探測(cè)函數(shù),來(lái)解析設(shè)備信息。
下面分析一下USB設(shè)備的識(shí)別過(guò)程。

以上顯示了設(shè)備插入到USB設(shè)備驅(qū)動(dòng)被調(diào)用的函數(shù)流程,后面將拿出一章具體分析函數(shù)內(nèi)部實(shí)現(xiàn)來(lái)進(jìn)一步分析USB設(shè)備識(shí)別中做了哪些事情。
4、總結(jié)
通過(guò)以上內(nèi)容,我們從整體上認(rèn)識(shí)了USB硬件識(shí)別過(guò)程,USB總線框架及USB設(shè)備驅(qū)動(dòng)框架。后續(xù)會(huì)針對(duì)一些重點(diǎn)知識(shí)進(jìn)行專(zhuān)題分析。主要包括:
USB設(shè)備描述符解析
USB四類(lèi)傳輸類(lèi)型
USB數(shù)據(jù)包格式分析
USB鼠標(biāo)設(shè)備驅(qū)動(dòng)代碼分析
USB初始化代碼分析
USB枚舉過(guò)程代碼分析
-END-
ps:韋東山2期視頻也講了USB設(shè)備驅(qū)動(dòng),感興趣的可以去看看。?

關(guān)注公眾號(hào)baiwenkeji第一時(shí)間獲得嵌入式干貨。? 技術(shù)交流加個(gè)人威信13266630429,驗(yàn)證:B站