標籤:
轉自:http://blog.csdn.net/myarrow/article/details/82700291. 枚舉是什麼? 枚舉就是從裝置讀取一些資訊,知道裝置是什麼樣的裝置,如何進行通訊,這樣主機就可以根據這些資訊來載入合適的驅動程式。調試USB裝置,很重要的一點就是USB的枚舉過程,只要枚舉成功了,那麼就已經成功大半了。 USB架構中, hub負責檢測裝置的串連和斷開,利用其中斷IN端點(Interrupt IN Endpoint)來向主機(Host)報告。在系統啟動時,主機輪詢它的根hub(Root Hub)的狀態看是否有裝置(包括子hub和子hub上的裝置)串連。USB匯流排拓撲結構見(最頂端為主機的Root Hub):
USB匯流排拓撲結構
一旦獲悉有新裝置串連上來,主機就會發送一系列的請求(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. 控制傳輸 控制傳輸是最重要和最複雜的一種傳輸類型,其中使用了一個8位元組大小的DATA0資料包,這8個位元組的資料包是主機用來發送
控制階段中的請求命令,而這些請求命令是主機配置USB裝置的關鍵。
1) bmRequestType(向誰請求)
D7:傳輸方向
0=主機至裝置;1=裝置至主機
D6..5:命令類型 D6D5=00:標準請求命令; D6D5=01:類請求命令; D6D5=10:使用者定義命令; D6D5=11:保留。
D4..0:接受者類型 0=裝置;1=介面 ;
2=端點;3=其它
4..31 保留 這個域表明此請求的特性。特別地,這個域表明了第二階段控制傳輸方向。如果wLength域被設作0的話,表明沒有資料傳送階段,那Direction位就會被忽略.
USB說明定義了一系列所有裝置必須支援的標準請求。這些請求見下面的表<Standard Device Requests>。另外,一個裝置類可定義更多的請求。裝置廠商也可定義裝置支援的請求.
請求可被導引到裝置,裝置介面,或某一個裝置端結點(endpoint)上。這個請求域也指定了接收者。當指定的是介面或端結點(endpoint)時,wIndex域指出那個介面或端節點。
2) bmRequest(什麼請求) 這個域標識特別的請求。bmRequestType域的Type欄位可修改此域的含義。本文僅定義Type 欄位為0即標準裝置請求時bRequest域值的含義。
3) wValue域
此域用來傳送當前請求的參數,隨請求不同而變。
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(讀取描述符) 這個請求返回存在的
描述符.
wValue域: 高一位元組:標識描述表類型(Descriptor Types) 低一位元組:表示描述符號的索引,將幾個類型相同的描述符應用到裝置中時,描述符索引用於選擇一個特定的描述符(只能是配置和字串描述符)。 例如:裝置可以用幾個配置描述符。對於其他可以通過GetDescriptor()請求取得的標準描述符來說,描述符的索引須為0。描述符索引值的範圍從0開始到裝置使用該類型描述元的數量減1。
wIndex域: 標識字串描述表的語言(Language ID),如果是其它語言的話就設為0。
wLength域: 表示要返回多少位元組。如果描述表長度大於wLength域值,那麼只有描述表的初始部分被返回。如果描述表比wLength域值小,則發送一個短包來標誌傳輸的結束。一個短包被定義成一個長度短於最大負載長度或一個空(NULL)包。 這個標準請求包括3種描述符:裝置(也就是裝置的限定符)、配置(也就是其他速度配置)、及字串。能進行高速操作的裝置支援裝置限定描述符返回有關裝置不支援的速度資訊(包括預設端點的wMaxPacketSize和其他速度配置的數量)。 其他速度配置用與配置描述符相同的結構返回資訊,但如果裝置在其他速度下操作則返回配置資訊。請求配置描述符將返回配置描述符,所有介面描述符和在這個請求中所有介面的端點描述符。 第一個介面描述符的裝置請求會一次返回配置描述表,所有的介面描述表和所有介面的端節點的描述表。第一個介面描述符緊跟著配置描述符號,第一個介面的端節點的描述符號隨後。如果有其它的介面與端節點,它們的描述符欲跟在第一個介面與端節點描述符之後。與類有關的描述符,和/或廠商定義的描述符跟在標準描述符之後.
所有的裝置必須提供一個裝置描述符並且至少一個配置描述符,如果一個裝置不支援一個請求的描述符,則返回請求錯誤。
•預設狀態:此請求合法。
•地址狀態:此請求合法。
•配置狀態:此請求合法。
3.5 GET_INTERFACE(取得介面) 這個請求向指定介面返回選中的備用裝置。
一些USB裝置有介面設定互斥的配置。這個請求允許主機確定當前選定的備用設定。如果wValue或者wLength的值與上面指定的不一致,那麼裝置的行為沒有定義;如果指定的介面不存在,那麼裝置將用請求錯誤響應。
•預設狀態:當裝置處於預設狀態時接收到這個請求,裝置的行為沒 有定義
•地址狀態:裝置給出請求錯誤
•配置狀態:當裝置處於配置狀態時,這是一個有效請求
USB枚舉過程【轉】