1. 枚舉是什么?
??????? 一旦獲悉有新設備連接上來,主機就會發送一系列的請求(Resqusts)給設備所掛載到的hub,再由hub建立起一條連接主機(Host)和設備(Device)之間的通信通道。然后主機以控制傳輸(Control Transfer)的方式,通過端點0(Endpoint 0)對設備發送各種請求,設備收到主機發來的請求后回復相應的信息,進行枚舉(Enumerate)操作。所有的USB設備必須支持標準請求(StandardRequests),控制傳輸方式(Control?Transfer)和端點0(Endpoint 0)。
?????? 在講解枚舉之前,先大概說說USB的一種傳輸模式——控制傳輸。這種傳輸在USB中是非常重要的,它要保證數據的正確性,在設備的枚舉過程中都是使用控制傳輸的。
控制傳輸分為三個階段:①建立階段。②數據階段。③確認階段。
??????? 建立(setup)階段:都是由USB主機發起,它是一個setup數據包,里面包含一些數據請求的命令以及一些數據。如果建立階段是輸入請求,那么數據階段就要輸入數據;如果建立階段是輸出請求,那么數據階段就要輸出數據。如果在數據階段,即便不需要傳送數據,也要發一個0長度的數據包。數據階段過后就是確認階段。確認階段剛好跟數據階段相反,如果是輸入請求,則它是一個輸出數據包;如果是輸出請求,則它是一個輸入數據包。確認階段用來確認數據的正確傳輸。
1.1 通信傳輸流
1.2 設備狀態圖
1.3 狀態詳解
? ??? ?1) 連接(Attached)
?????? 設備可以連接到USB或者從USB上拔出.USB設備從總線上撥出后的狀態在規范沒定義,只說明一旦USB連到總線要求的操作以及屬性.
?????? 2) 上電(Powered)
???????USB設備的電源可來自外部電源,也可從USB接口的集線器而來。
電源來自外部電源的USB設備被稱作自給電源式的(self-powered)。盡管自給電源式的USB設備可能在連接上USB接口以前可能已經帶電,但它們直到連線上USB接口后才能被看作是加電狀態(Powered state)。而這時候VBUS已經對設備產生作用了.
一個設備可能有既支持自給電源的,同時也支持總線電源式的配置。有一些支持其中的一種,而另一些設備配置可能只有在自給電源下才能被使用。設備對電源支持的能力是通過配置描述表(configuration descriptor)來反映的。當前的電源供給形式被作為設備狀態的一部分被反映出來。設備可在任何時候改變它們的供電來源,比如說:從自給式向總線式改變,如果一個配置同時支持兩種模式,那此狀態的最大電源需求就是指設備在兩種模式下從VBUS上獲取電能的最大值。設備必須以此最大電源作為參照,而究竟處于何狀態是不考慮的。如果有一配置僅支持一種電源模式,那么電源模式的改變會使得設備失去當前配置與地址,返回加電狀態。如果一個設備是自給電源式,并且當前配置需要大于100mA電流,那么如果此設備轉到了總線電源式,它必須返回地址狀態(Address state)。自給電源式集線器使用VBUS來為集線控制器(Hub controller)提供電源,因而可以仍然保持配置狀態(Configured state),盡管自給電源停止提供電源。
????? 3)默認狀態(Default)
????? 設備上電后,它不響應任何總線處理,直到總線接收到復位信號為止.接收到復位信號后,用默認的地址可以對設備尋址.
???????當用復位過程完成后,USB設備在正確的速度下操作(即低速/全速/高速).低速和全速的數據選擇由設備的終端電阻決定.能進行高速操作的設備決定它是否在復位的過程的一部分執行高速操作.
????????能進行高速操作的設備在全速的電氣環境中操作時,必須能以全速成功復位.設備成功復位后,設備必須成功響應設備和配置描述符請求,并且返回適當的信息.當在全速下工作時,設備可能或者不能支持預定義的功能.
??? ?? 4) 地址(Address)?
?????? 所有的USB設備在加電復位以后都使用缺省地址。每一設備在連接或復位后由主機分配一個唯一的地址。當USB設備處于掛起狀態時,它保持這個地址不變。
????????USB設備只對缺省通道(Pipe)請求發生響應,而不管設備是否已經被分配地址或在使用缺省地址。
????????5) 配置狀態( Configured )
??????? 在USB設備正常工作以前,設備必須被正確配置。從設備的角度來看,配置包括一個將非零值寫入設備配置寄存器的操作。配置一個設備或改變一個可變的設備設置會使得與這個相關接口的終端結點的所有的狀態與配置值被設成缺省值。這包括將正在使用(date toggle)的結點(end point)的 (Date toggle)被設置成DATA0。
??????? 6) 掛起狀態
????????為節省電源,USB設備在探測不到總線傳輸時自動進入中止狀態。當中止時,USB設備保持本身的內部狀態,包括它的地址及配置。
??????? 所有的設備在一段特定的時間內探測不到總線活動時必須進入中止態。不管設備是被分配了非缺省的地址或者是被配置了,已經連接的設備必須在任何加電的時刻隨時準備中止。總線活動的中止可能是因為主機本身進入了中止狀態。另外,USB設備必須在所連接的集線器端口失效時進入中止態。這就是所指的選擇性中止(Selective suspend)。
???????USB設備在總線活動來到時結束中止態。USB設備也可以遠程喚醒的電流信號來請求主機退出中止態或選擇性中止態。具體設備具有的遠程喚醒的能力是可選的,也就是說,如果一個設備有遠程喚醒的能力,此設備必須能讓主機控制此能力的有效與否。當設備復位時,遠程喚醒能力必須被禁止。
?
2. 枚舉步驟
?????? USB協議定義了設備的6種狀態,僅在枚舉過程中,設備就經歷了4個狀態的遷移:上電狀態(Powered),默認狀態(Default),地址狀態(Address)和配置狀態(Configured)(其他兩種是連接狀態和掛起狀態(Suspend))。
2.1 用戶把USB設備插入USB端口或給系統啟動時設備上電
????? 這里指的USB端口指的是主機下的根hub或主機下行端口上的hub端口。Hub給端口供電,連接著的設備處于上電狀態。此時,USB設備處于加電狀態,它所連接的端口是無效的。
2.2 Hub監測它各個端口數據線上(D+/D-)的電壓
???? ?在hub端,數據線D+和D-都有一個阻值在14.25k到24.8k的下拉電阻Rpd,而在設備端,D+(全速,高速)和D-(低速)上有一個1.5k的上拉電阻Rpu。當設備插入到hub端口時,有上拉電阻的一根數據線被拉高到幅值的90%的電壓(大致是3V)。hub檢測到它的一根數據線是高電平,就認為是有設備插入,并能根據是D+還是D-被拉高來判斷到底是什么設備(全速/低速)插入端口(全速、高速設備的區分在我將來的文章中描述)。如下圖。
???????????????????????????????? USB全速/高速設備上電連接
???????檢測到設備后,hub繼續給設備供電,但并不急于與設備進行USB傳輸。
USB接口定義如下圖所示:
2.3 Host了解連接的設備
?? ?? 每個hub利用它自己的中斷端點向主機報告它的各個端口的狀態(對于這個過程,設備是看不到的,也不必關心),報告的內容只是hub端口的設備連接/斷開的事件。如果有連接/斷開事件發生,那么host會發送一個 Get_Port_Status請求(request)給hub以了解此次狀態改變的確切含義。Get_Port_Status等請求屬于所有hub都要求支持的hub類標準請求(standard hub-class requests)。
2.4 Hub檢測所插入的設備是高速還是低速設備
??? hub通過檢測USB總線空閑(Idle)時差分線的高低電壓來判斷所連接設備的速度類型,當host發來Get_Port_Status請求時,hub就可以將此設備的速度類型信息回復給host。USB 2.0規范要求速度檢測要先于復位(Reset)操作。
2.5 hub復位設備
????? 主機一旦得知新設備已連上以后,它至少等待100ms以使得插入操作的完成以及設備電源穩定工作。然后主機控制器就向hub發出一個 Set_Port_Feature請求讓hub復位其管理的端口(剛才設備插上的端口)。hub通過驅動數據線到復位狀態(D+和D-全為低電平 ),并持續至少10ms。當然,hub不會把這樣的復位信號發送給其他已有設備連接的端口,所以其他連在該hub上的設備自然看不到復位信號,不受影響。
2.6 Host檢測所連接的全速設備是否是支持高速模式
??? ?? 因為根據USB 2.0協議,高速(High Speed)設備在初始時是默認全速(Full Speed )狀態運行,所以對于一個支持USB 2.0的高速hub,當它發現它的端口連接的是一個全速設備時,會進行高速檢測,看看目前這個設備是否還支持高速傳輸,如果是,那就切到高速信號模式,否則就一直在全速狀態下工作。
??? ?? 同樣的,從設備的角度來看,如果是一個高速設備,在剛連接bub或上電時只能用全速信號模式運行(根據USB 2.0協議,高速設備必須向下兼容USB 1.1的全速模式)。隨后hub會進行高速檢測,之后這個設備才會切換到高速模式下工作。假如所連接的hub不支持USB 2.0,即不是高速hub,不能進行高速檢測,設備將一直以全速工作。
2.7 Hub建立設備和主機之間的信息通道
?? ??? 主機不停地向hub發送Get_Port_Status請求,以查詢設備是否復位成功。Hub返回的報告信息中有專門的一位用來標志設備的復位狀態。
???? ? 當hub撤銷了復位信號,設備就處于默認/空閑狀態(Default state),準備接收主機發來的請求。設備和主機之間的通信通過控制傳輸,默認地址0,端點號0進行。此時,設備能從總線上得到的最大電流是100mA。(所有的USB設備在總線復位后其地址都為0,這樣主機就可以跟那些剛剛插入的設備通過地址0通信。)
2.8 主機發送Get_Descriptor請求獲取默認管道的最大包長度
?? ??? 默認管道(Default Pipe)在設備一端來看就是端點0。主機此時發送的請求是默認地址0,端點0,雖然所有未分配地址的設備都是通過地址0來獲取主機發來的請求,但由于枚舉過程不是多個設備并行處理,而是一次枚舉一個設備的方式進行,所以不會發生多個設備同時響應主機發來的請求。
???? ?設備描述符的第8字節代表設備端點0的最大包大小。雖然說設備所返回的設備描述符(Device Descriptor)長度只有18字節,但系統也不在乎,此時,描述符的長度信息對它來說是最重要的,其他的瞄一眼就過了。當完成第一次的控制傳輸后,也就是完成控制傳輸的狀態階段,系統會要求hub對設備進行再一次的復位操作(USB規范里面可沒這要求)。再次復位的目的是使設備進入一個確定的狀態。
2.9 主機給設備分配一個地址
?? ??? 主機控制器通過Set_Address請求向設備分配一個唯一的地址。在完成這次傳輸之后,設備進入地址狀態(Address state),之后就啟用新地址繼續與主機通信。這個地址對于設備來說是終生制的,設備在,地址在;設備消失(被拔出,復位,系統重啟),地址被收回。同一個設備當再次被枚舉后得到的地址不一定是上次那個了。
2.10 主機獲取設備的信息
?? ??? 主機發送 Get_Descriptor請求到新地址讀取設備描述符,這次主機發送Get_Descriptor請求可算是誠心,它會認真解析設備描述符的內容。設備描述符內信息包括端點0的最大包長度,設備所支持的配置(Configuration)個數,設備類型,VID(Vendor ID,由USB-IF分配), PID(Product ID,由廠商自己定制)等信息。Get_Descriptor請求(Device type)和設備描述符(已抹去VID,PID等信息)見下圖:
??標準Get_Descriptor請求
????????????????????????設備描述符(Device Descriptor)
????? 之后主機發送Get_Descriptor請求,讀取配置描述符(Configuration Descriptor),字符串等,逐一了解設備更詳細的信息。事實上,對于配置描述符的標準請求中,有時wLength一項會大于實際配置描述符的長度(9字節),比如255。這樣的效果便是:主機發送了一個Get_Descriptor_Configuration 的請求,設備會把接口描述符,端點描述符等后續描述符一并回給主機,主機則根據描述符頭部的標志判斷送上來的具體是何種描述符。
???? ?接下來,主機就會獲取配置描述符。配置描述符總共為9字節。主機在獲取到配置描述符后,根據里面的配置集合總長度,再獲取配置集合。配置集合包括配置描述符,接口描述符,端點描符等等。
??? ?如果有字符串描述符的話,還要獲取字符串描述符。另外HID設備還有HID描述符等。
2.11? 主機給設備掛載驅動(復合設備除外)
????? 主機通過解析描述符后對設備有了足夠的了解,會選擇一個最合適的驅動給設備。? 然后tell the world(announce_device)說明設備已經找到了,最后調用設備模型提供的接口device_add將設備添加到 usb 總線的設備列表里,然后 usb總線會遍歷驅動列表里的每個驅動,調用自己的 match(usb_device_match) 函數看它們和你的設備或接口是否匹配,匹配的話調用device_bind_driver函數,現在就將控制權交到設備驅動了。???
???? 對于復合設備,通常應該是不同的接口(Interface)配置給不同的驅動,因此,需要等到當設備被配置并把接口使能后才可以把驅動掛載上去。
???? 設備-配置-接口-端點關系見下圖:
?????????????????USB 設備-配置-接口-端點關系
??? 實際情況沒有上述關系復雜。一般來說,一個設備就一個配置,一個接口,如果設備是多功能符合設備,則有多個接口。端點一般都有好幾個,比如Mass Storage設備一般就有兩個端點(控制端點0除外)。
2.12 設備驅動選擇一個配置
???? 驅動(注意,這里是驅動,之后的事情都是有驅動來接管負責與設備的通信)根據前面設備回復的信息,發送Set_Configuration請求來正式確定選擇設備的哪個配置(Configuration)作為工作配置(對于大多數設備來說,一般只有一個配置被定義)。至此,設備處于配置狀態(Configured),當然,設備也應該使能它的各個接口(Interface)。
??? 對于復合設備,主機會在這個時候根據設備接口信息,給它們掛載驅動。
3. 控制傳輸
1) bmRequestType(向誰請求)
??????????? 0=主機至設備;1=設備至主機
??? D6..5:命令類型
??? D4..0:接受者類型
????????? 2=端點;3=其它
????????? 4..31 保留
???????USB說明定義了一系列所有設備必須支持的標準請求。這些請求見下面的表<Standard Device Requests>。另外,一個設備類可定義更多的請求。設備廠商也可定義設備支持的請求.
???????請求可被導引到設備,設備接口,或某一個設備端結點(endpoint)上。這個請求域也指定了接收者。當指定的是接口或端結點(endpoint)時,wIndex域指出那個接口或端節點。
?
??? 此域用來傳送當前請求的參數,隨請求不同而變。
4) wIndex域?
??? 當bmRequestType的Recipient字段為接口或端點時,wIndex域用來表明是哪一個接口或端結。
5) wLength域
??? 這個域表明第二階段的數據傳輸長度。傳輸方向由bmRequstType域的Direction位指出。wLength域為0則表明無數據傳輸。在輸入請求下,設備返回的數據長度不應多于wLength,但可以少于。在輸出請求下,wLength指出主機發出的確切數據量。如果主機發送多于wLength的數據,設備做出的響應是無定義的。
3.1 標準設備請求
3.2?標準請求碼(bRequest的值)
3.3 描述符類型
3.4 GET_DESCRIPTOR(讀取描述符)
???????wIndex域:
??????? 所有的設備必須提供一個設備描述符并且至少一個配置描述符,如果一個設備不支持一個請求的描述符,則返回請求錯誤。
??? ?缺省狀態:此請求合法。
??? ?地址狀態:此請求合法。
??? ?配置狀態:此請求合法。
?3.5 GET_INTERFACE(取得接口)
???? ?一些USB設備有接口設置互斥的配置。這個請求允許主機確定當前選定的備用設置。如果wValue或者wLength的值與上面指定的不一致,那么設備的行為沒有定義;如果指定的接口不存在,那么設備將用請求錯誤響應。
???? ?默認狀態:當設備處于默認狀態時接收到這個請求,設備的行為沒? 有定義
??????地址狀態:設備給出請求錯誤
???? ?配置狀態:當設備處于配置狀態時,這是一個有效的請求