新聞中心

USB枚舉流程分析

作者: 時(shí)間:2016-12-12 來源:網(wǎng)絡(luò) 收藏
USB連接拓?fù)浣Y(jié)構(gòu)
對于每個(gè)usb系統(tǒng)來說,都有一個(gè)稱為HOST控制器的設(shè)備,該Host控制器和一個(gè)根Hub作為一個(gè)整體。這個(gè)根HUb下可以接多級Hub,每個(gè)Hub又可以接子Hub。每個(gè)usb設(shè)備作為一個(gè)節(jié)點(diǎn)接在不同級別的Hub上。每條usb總線上最多可以接127個(gè)設(shè)備。
圖1 USB總線拓?fù)?/strong>結(jié)構(gòu)
usb主控制器:
負(fù)責(zé)處理主機(jī)與設(shè)備之間的電氣和協(xié)議層的互聯(lián)。常見的usb主控制器規(guī)格有:
OHCI:只要是非pc系統(tǒng)上的usb芯片
UHCI:usb1.1規(guī)格
EHCI: 兼容上面種規(guī)格,遵循usb2.0規(guī)范

每個(gè)usb host控制器都會自帶一個(gè)usb hub ,被稱為根Hub。這個(gè)根hub可以接子hub,每個(gè)hub上掛載usb設(shè)備。通過外接usb hub,可以插更多的usb設(shè)備。當(dāng)usb設(shè)備插入到usb Hub或從上面拔出時(shí),都會發(fā)出電信號通知系統(tǒng)。

usb設(shè)備就是插在usb總線上工作的設(shè)備,廣義的講usb Hub也算是usb設(shè)備。有的usb設(shè)備功能單一,直接掛載在usb hub上。而有的usb設(shè)備功能復(fù)雜,會將多個(gè)usb功能結(jié)合在一起,稱為一個(gè)復(fù)合設(shè)備。

usb設(shè)備邏輯結(jié)構(gòu)
圖2 USB總線邏輯結(jié)構(gòu)
在usb設(shè)備的邏輯組織中,包含設(shè)備,配置,接口,端點(diǎn)4個(gè)層次。
設(shè)備通常有一個(gè)或多個(gè)配置,配置通常有一個(gè)或多個(gè)接口,接口有零或多個(gè)端點(diǎn)。
每個(gè)usb設(shè)備都可以包含一個(gè)或多個(gè)配置,不同的配置使設(shè)備表現(xiàn)出不同的功能組合(在探測,連接期間需從其中選定一個(gè)),配置由多個(gè)接口組成。在usb協(xié)議中,接口由多個(gè)端點(diǎn)組成,代表一個(gè)基本的功能,是usb設(shè)備驅(qū)動程序控制的對象,一個(gè)功能復(fù)雜的usb設(shè)備可以具有多個(gè)接口,而接口是端點(diǎn)的匯集
例子
一個(gè)usb播放器帶有音頻,視頻功能,還有旋鈕和按鈕
配置1 音頻(接口)+旋鈕(接口)
配置2 視頻(接口)+音頻(接口)+按鈕(接口)
每個(gè)接口對應(yīng)需要一個(gè)驅(qū)動程序

usb設(shè)備中的唯一可尋址部分是設(shè)備的端點(diǎn)。它是位于usb設(shè)備或主機(jī)上的一個(gè)數(shù)據(jù)緩沖區(qū),用來存放和發(fā)送usb的各種數(shù)據(jù)。主機(jī)和設(shè)備的通信最終作用于設(shè)備上的各個(gè)端點(diǎn),它是主機(jī)與設(shè)備間通信流的一個(gè)邏輯終端

每個(gè)usb設(shè)備有一個(gè)唯一的地址,這個(gè)地址是在設(shè)備連上主機(jī)時(shí),由主機(jī)分配的,而設(shè)備中的每個(gè)端點(diǎn)在設(shè)備內(nèi)部有唯一的端點(diǎn)號,這個(gè)端點(diǎn)號是在設(shè)計(jì)設(shè)備時(shí)給定的。每個(gè)端點(diǎn)都是一個(gè)簡單的連接點(diǎn),或者支持?jǐn)?shù)據(jù)流進(jìn)設(shè)備,或者支持其流出設(shè)備,兩者不可兼得。

基于PnP機(jī)制,設(shè)備被枚舉時(shí),它必須向主機(jī)報(bào)告各個(gè)端點(diǎn)的特性,包括端點(diǎn)號,通信方向,端點(diǎn)支持的最大包大小,帶寬要求等(其中端點(diǎn)支持的最大包大小叫做數(shù)據(jù)有效負(fù)載)。每個(gè)設(shè)備必須有端點(diǎn)0,它用于設(shè)備枚舉和對設(shè)備進(jìn)行一些基本的控制功能。除了端點(diǎn)0,其余的端點(diǎn)在設(shè)備配置之前不能與主機(jī)通信,只有向主機(jī)報(bào)告這些端點(diǎn)的特性并被確認(rèn)后才能被激活。

LInux USB枚舉過程

USB架構(gòu)中, hub負(fù)責(zé)檢測設(shè)備的連接和斷開,利用其中斷IN端點(diǎn)(Interrupt IN Endpoint)來向主機(jī)(Host)報(bào)告。在系統(tǒng)啟動時(shí),主機(jī)輪詢它的根hub(Root Hub)的狀態(tài)看是否有設(shè)備(包括子hub和子hub上的設(shè)備)連接。USB總線拓?fù)浣Y(jié)構(gòu)見上圖(最頂端為主機(jī)的Root Hub)

一旦獲悉有新設(shè)備連接上來,主機(jī)就會發(fā)送一系列的請求(Resqusts)給設(shè)備所掛載到的hub,再由hub建立起一條連接主機(jī)(Host)和設(shè) 備(Device)之間的通信通道。然后主機(jī)以控制傳輸(ControlTransfer)的方式,通過端點(diǎn)0(Endpoint 0)對設(shè)備發(fā)送各種請求,設(shè)備收到主機(jī)發(fā)來的請求后回復(fù)相應(yīng)的信息,進(jìn)行枚舉(Enumerate)操作。所有的USB設(shè)備必須支持標(biāo)準(zhǔn)請求 (StandardRequests),控制傳輸方式(ControlTransfer)和端點(diǎn)0(Endpoint 0)。

從用戶角度來看,枚舉過程是自動完成并不可見的。但很多初次使用的設(shè)備連接時(shí),系統(tǒng)會彈出說新硬件檢測到,設(shè)備安裝成功,可以使用之類的消息提示框,而且有時(shí)還需要用戶配合選擇安裝相關(guān)的驅(qū)動。

當(dāng)枚舉完成后,這個(gè)新添加的設(shè)備可在Windows的設(shè)備管理器里面看到,當(dāng)用戶刪除這個(gè)設(shè)備/硬件時(shí),系統(tǒng)把這個(gè)設(shè)備從設(shè)備管理器里刪除。

對于一般的設(shè)備,固件(Firmware)內(nèi)包含主機(jī)所要請求的信息,而有些設(shè)備則是完全由硬件來負(fù)責(zé)響應(yīng)主機(jī)的請求。在主機(jī)方面則是由操作系統(tǒng)而非應(yīng)用程序負(fù)責(zé)處理相關(guān)枚舉操作。

枚舉步驟
USB協(xié)議定義了設(shè)備的6種狀態(tài),僅在枚舉過程種,設(shè)備就經(jīng)歷了4個(gè)狀態(tài)的遷移:上電狀態(tài)(Powered),默認(rèn)狀態(tài)(Default),地址狀態(tài)(Address)和配置狀態(tài)(Configured)(其他兩種是連接狀態(tài)和掛起狀態(tài)(Suspend))。

下面步驟是Windows系統(tǒng)下典型的枚舉過程,但是固件不能依此就認(rèn)為所有的枚舉操作都是按照這樣一個(gè)流程行進(jìn)。設(shè)備必須在任何時(shí)候都能正確處理所有的主機(jī)請求。

本文引用地址:http://m.butianyuan.cn/article/201612/328944.htm


1、用戶把USB設(shè)備插入U(xiǎn)SB端口或給系統(tǒng)啟動時(shí)設(shè)備上電
這里指的USB端口指的是主機(jī)下的根hub或主機(jī)下行端口上的hub端口。Hub給端口供電,連接著的設(shè)備處于上電狀態(tài)。

2、Hub監(jiān)測它各個(gè)端口數(shù)據(jù)線上(D+/D-)的電壓
在hub端,數(shù)據(jù)線D+和D-都有一個(gè)阻值在14.25k到24.8k的下拉電阻Rpd,而在設(shè)備端,D+(全速,高速)和D-(低速)上有一個(gè)1.5k 的上拉電阻Rpu。當(dāng)設(shè)備插入到hub端口時(shí),有上拉電阻的一根數(shù)據(jù)線被拉高到幅值的90%的電壓(大致是3V)。hub檢測到它的一根數(shù)據(jù)線是高電平, 就認(rèn)為是有設(shè)備插入,并能根據(jù)是D+還是D-被拉高來判斷到底是什么設(shè)備(全速/低速)插入端口。 檢測到設(shè)備后,hub繼續(xù)給設(shè)備供電,但并不急于與設(shè)備進(jìn)行USB傳輸。

全速和低速識別
 根據(jù)規(guī)范,全速(Full Speed)和低速(Low Speed)很好區(qū)分,因?yàn)樵谠O(shè)備端有一個(gè)1.5k的上拉電阻,當(dāng)設(shè)備插入hub或上電(固定線纜的USB設(shè)備)時(shí),有上拉電阻的那根數(shù)據(jù)線就會被拉高,hub根據(jù)D+/D-上的電平判斷所掛載的是全速設(shè)備還是低速設(shè)備。如下兩圖:
(Full-speed Device Cable and Resistor Connections)
(Low-speed Device Cable and Resistor Connections)
高速識別
  USB全速/低速識別相當(dāng)簡單,但USB2.0,USB1.x就一對數(shù)據(jù)線,不能像全速/低速那樣僅依靠數(shù)據(jù)線上拉電阻位置就能識別USB第三種速度:高速。因此對于高速設(shè)備的識別就顯得稍微復(fù)雜些。
  高速設(shè)備初始是以一個(gè)全速設(shè)備的身份出現(xiàn)的,即和全速設(shè)備一樣,D+線上有一個(gè)1.5k的上拉電阻。USB2.0的hub把它當(dāng)作一個(gè)全速設(shè)備,之后,hub和設(shè)備通過一系列握手信號確認(rèn)雙方的身份。在這里對速度的檢測是雙向的,比如高速的hub需要檢測所掛上來的設(shè)備是高速、全速還是低速,高速的設(shè)備需要檢測所連上的hub是USB2.0的還是1.x的,如果是前者,就進(jìn)行一系列動作切到高速模式工作,如果是后者,就以全速模式工作。
下圖展示了一個(gè)高速設(shè)備連到USB2.0 hub上的情形:
hub檢測到有設(shè)備插入/上電時(shí),向主機(jī)通報(bào),主機(jī)發(fā)送Set_Port_Feature請求讓hub復(fù)位新插入的設(shè)備。設(shè)備復(fù)位操作是hub通過驅(qū)動數(shù)據(jù)線到復(fù)位狀態(tài)SE0(Single-ended 0,即D+和D-全為低電平),并持續(xù)至少10ms。當(dāng)然,hub不會把這樣的復(fù)位信號發(fā)送給其他已有設(shè)備連接的端口,所以其他連在該hub上的設(shè)備自然看不到復(fù)位信號,不受影響。

3、Host了解連接的設(shè)備
每個(gè)hub利用它自己的中斷端點(diǎn)向主機(jī)報(bào)告它的各個(gè)端口的狀態(tài)(對于這個(gè)過程,設(shè)備是看不到的,也不必關(guān)心),報(bào)告的內(nèi)容只是hub端口的設(shè)備連接/斷開 的事件。如果有連接/斷開事件發(fā)生,那么host會發(fā)送一個(gè) Get_Port_Status請求(request)以了解更多hub上的信息。Get_Port_Status等請求屬于所有hub都要求支持的 hub類標(biāo)準(zhǔn)請求(standard hub-classrequests)。

4、Hub檢測所插入的設(shè)備是高速還是低速設(shè)備
hub通過檢測USB總線空閑(Idle)時(shí)差分線的高低電壓來判斷所連接設(shè)備的速度類型,當(dāng)host發(fā)來Get_Port_Status請求時(shí),hub 就可以將此設(shè)備的速度類型信息回復(fù)給host。(USB 2.0規(guī)范要求速度檢測要先于復(fù)位(Reset)操作)。

5、hub復(fù)位設(shè)備
當(dāng)主機(jī)獲悉一個(gè)新的設(shè)備后,主機(jī)控制器就向hub發(fā)出一個(gè) Set_Port_Feature請求讓hub復(fù)位其管理的端口。hub通過驅(qū)動數(shù)據(jù)線到復(fù)位狀態(tài)(D+和D-全為低電平 ),并持續(xù)至少10ms。當(dāng)然,hub不會把這樣的復(fù)位信號發(fā)送給其他已有設(shè)備連接的端口,所以其他連在該hub上的設(shè)備自然看不到復(fù)位信號,不受影響。

6、Host檢測所連接的全速設(shè)備是否是支持高速模式
因?yàn)楦鶕?jù)USB 2.0協(xié)議,高速(High Speed)設(shè)備在初始時(shí)是默認(rèn)全速(Full Speed )狀態(tài)運(yùn)行,所以對于一個(gè)支持USB 2.0的高速hub,當(dāng)它發(fā)現(xiàn)它的端口連接的是一個(gè)全速設(shè)備時(shí),會進(jìn)行高速檢測,看看目前這個(gè)設(shè)備是否還支持高速傳輸,如果是,那就切到高速信號模式,否 則就一直在全速狀態(tài)下工作。

同樣的,從設(shè)備的角度來看,如果是一個(gè)高速設(shè)備,在剛連接bub或上電時(shí)只能用全速信號模式運(yùn)行(根據(jù)USB 2.0協(xié)議,高速設(shè)備必須向下兼容USB 1.1的全速模式)。隨后hub會進(jìn)行高速檢測,之后這個(gè)設(shè)備才會切換到告訴模式下工作。假如所連接的hub不支持USB 2.0,即不是高速hub,不能進(jìn)行高速檢測,設(shè)備將一直以全速工作。

7、Hub建立設(shè)備和主機(jī)之間的信息通道
主機(jī)不停得向hub發(fā)送 Get_Port_Status請求,以查詢設(shè)備是否復(fù)位成功。Hub返回的報(bào)告信息中有專門的一位用來標(biāo)志設(shè)備的復(fù)位狀態(tài)。
當(dāng)hub撤銷了復(fù)位信號,設(shè)備就處于默認(rèn)/空閑狀態(tài)(Default state),準(zhǔn)備著主機(jī)發(fā)來的請求。設(shè)備和主機(jī)之間的通信通過控制傳輸,默認(rèn)地址0,端點(diǎn)號0進(jìn)行。在此時(shí),設(shè)備能從總線上得到的最大電流是100mA。(所有的USB設(shè)備在總線復(fù)位后其地址都為0,這樣主機(jī)就可以跟那些剛剛插入的設(shè)備通過地址0通信。)

8、主機(jī)發(fā)送Get_Descriptor請求獲取默認(rèn)管道的最大包長度
默認(rèn)管道(Default Pipe)在設(shè)備一端來看就是端點(diǎn)0。主機(jī)此時(shí)發(fā)送的請求是默認(rèn)地址0,端點(diǎn)0,雖然所有位分配地址的設(shè)備都是通過地址0來獲取主機(jī)發(fā)來的信息,但由于枚 舉過程不是多個(gè)設(shè)備并行處理,而是一次枚舉一個(gè)設(shè)備的方式進(jìn)行,所以不會發(fā)生多個(gè)設(shè)備同時(shí)響應(yīng)主機(jī)發(fā)來的請求。
設(shè)備描述符的第8字節(jié)代表設(shè)備端點(diǎn)0的最大包大小。對于Windows系統(tǒng)來說,Get_Descriptor請求中的wLength一項(xiàng)都會設(shè)為64, 雖然說設(shè)備所返回的設(shè)備描述符(DeviceDescriptor)長度只有18字節(jié),但系統(tǒng)也不在乎,此時(shí),描述符的長度信息對它來說是最重要的,其他 的瞄一眼就過了。Windows系統(tǒng)還有個(gè)怪癖,當(dāng)完成第一次的控制傳輸后,也就是完成控制傳輸?shù)臓顟B(tài)階段,系統(tǒng)會要求hub對設(shè)備進(jìn)行再一次的復(fù)位操作 (USB規(guī)范里面可沒這要求)。再次復(fù)位的目的是使設(shè)備進(jìn)入一個(gè)確定的狀態(tài)。

9、主機(jī)給設(shè)備分配一個(gè)地址
主機(jī)控制器通過Set_Address請求向設(shè)備分配一個(gè)唯一的地址。在完成這次傳輸之后,設(shè)備進(jìn)入地址狀態(tài)(Address state),之后就啟用新地址繼續(xù)與主機(jī)通信。這個(gè)地址對于設(shè)備來說是終生制的,設(shè)備在,地址在;設(shè)備消失(被拔出,復(fù)位,系統(tǒng)重啟),地址被收回。同 一個(gè)設(shè)備當(dāng)再次被枚舉后得到的地址不一定是上次那個(gè)了。

10、主機(jī)獲取設(shè)備的信息
主機(jī)發(fā)送 Get_Descriptor請求到新地址讀取設(shè)備描述符,這次主機(jī)發(fā)送Get_Descriptor請求可算是誠心,它會認(rèn)真解析設(shè)備描述符的內(nèi)容。設(shè) 備描述符內(nèi)信息包括端點(diǎn)0的最大包長度,設(shè)備所支持的配置(Configuration)個(gè)數(shù),設(shè)備類型,VID(Vendor ID,由USB-IF分配), PID(Product ID,由廠商自己定制)等信息。Get_Descriptor請求(Device type)和設(shè)備描述符(已抹去VID,PID等信息)見下圖:

標(biāo)準(zhǔn)Get_Descriptor請求(Get_DescriptorRequest)
設(shè)備描述符(DeviceDescriptor)

之后主機(jī)發(fā)送Get_Descriptor請求,讀取配置描述符(ConfigurationDescriptor),字符串等,逐一了解設(shè)備更詳細(xì)的信 息。事實(shí)上,對于配置描述符的標(biāo)準(zhǔn)請求中,有時(shí)wLength一項(xiàng)會大于實(shí)際配置描述符的長度(9字節(jié)),比如255。這樣的效果便是:主機(jī)發(fā)送了一個(gè) Get_Descriptor_Configuration的請求,設(shè)備會把接口描述符,端點(diǎn)描述符等后續(xù)描述符一并回給主機(jī),主機(jī)則根據(jù)描述符頭部的標(biāo) 志判斷送上來的具體是何種描述符。

接下來,主機(jī)就會獲取配置描述符。配置描述符總共為9字節(jié)。主機(jī)在獲取到配置描述符后,根據(jù)里面的配置集合總長度,再獲取配置集合。配置集合包括配置描述符,接口描述符,端點(diǎn)描符等等。
如果有字符串描述符的話,還要獲取字符串描述符。另外HID設(shè)備還有HID描述符等。

11、主機(jī)給設(shè)備掛載驅(qū)動(復(fù)合設(shè)備除外)
主機(jī)通過解析描述符后對設(shè)備有了足夠的了解,會選擇一個(gè)最合適的驅(qū)動給設(shè)備。在驅(qū)動的選擇過程中,Windows系統(tǒng)會和系統(tǒng)inf文件里的廠商 ID,產(chǎn)品ID,有時(shí)甚至用到設(shè)備返回來的產(chǎn)品版本號進(jìn)行匹配。如果沒有匹配的選項(xiàng),Windows會根據(jù)設(shè)備返回來的類,子類,協(xié)議值信息選擇。如果該 設(shè)備以前在系統(tǒng)上成功枚舉過,操作系統(tǒng)會根據(jù)以前記錄的登記信息而非inf文件掛載驅(qū)動。當(dāng)操作系統(tǒng)給設(shè)備指定了驅(qū)動之后,就由驅(qū)動來負(fù)責(zé)對設(shè)備的訪問。
對于復(fù)合設(shè)備,通常應(yīng)該是不同的接口(Interface)配置給不同的驅(qū)動,因此,需要等到當(dāng)設(shè)備被配置并把接口使能后才可以把驅(qū)動掛載上去。
設(shè)備-配置-接口-端點(diǎn)關(guān)系見下圖:

USB 設(shè)備-配置-接口-端點(diǎn)關(guān)系

實(shí)際情況沒有上述關(guān)系復(fù)雜。一般來說,一個(gè)設(shè)備就一個(gè)配置,一個(gè)接口,如果設(shè)備是多功能符合設(shè)備,則有多個(gè)接口。端點(diǎn)一般都有好幾個(gè),比如Mass Storage設(shè)備一般就有兩個(gè)端點(diǎn)(控制端點(diǎn)0除外)。

12. 設(shè)備驅(qū)動選擇一個(gè)配置
驅(qū)動(注意,這里是驅(qū)動,之后的事情都是有驅(qū)動來接管負(fù)責(zé)與設(shè)備的通信)根據(jù)前面設(shè)備回復(fù)的信息,發(fā)送Set_Configuration請求來正式確定 選擇設(shè)備的哪個(gè)配置(Configuration)作為工作配置(對于大多數(shù)設(shè)備來說,一般只有一個(gè)配置被定義)。至此,設(shè)備處于配置狀態(tài),當(dāng)然,設(shè)備也 應(yīng)該使能它的各個(gè)接口(Interface)。
對于復(fù)合設(shè)備,主機(jī)會在這個(gè)時(shí)候根據(jù)設(shè)備接口信息,給它們掛載驅(qū)動。




關(guān)鍵詞: USB枚舉流

評論


技術(shù)專區(qū)

關(guān)閉