1. 程式人生 > >usb滑鼠列舉過程深度解析(上)

usb滑鼠列舉過程深度解析(上)

轉載自:

裝置列舉過程:

1.         獲取裝置描述符

2.         復位

3.         設定地址

4.         再次獲取裝置描述符

5.         獲取配置描述符

6.         獲取介面,端點描述符

7.         獲取字串描述符

8.         選擇裝置配置

下圖是USB規範中規定的USB的6種狀態。通過裝置列舉過程,USB可以進入Configured狀態。

這個是USB滑鼠插入Linux系統的列舉過程的抓包圖。

Transfer0:

 

從圖中可以看出,Transfer0由5個Transaction構成。這裡所說的USB主機是指USB主控制器。可以看出它是一個控制傳輸。Transaction0為SETUP Transaction,Transaction1~Transaction3是IN Transaction,Transaction4是OUT Transaction。

Transaction0:

Packet 134是由host發向device,指明是SETUP包。SETUP包的作用是指明當前Transaction為SETUP型別。Packet 134 的ADDR域為0,ENDP域為0,說明這次傳輸是在裝置驅動裡的緩衝區與地址為0的裝置的端點0之間進行的。地址0是在主機給裝置分配地址之前使用的預設地址,是不能分配給裝置的,端點0是專門用於控制傳輸的端點,每個裝置都必須有的。而且既是IN端點又是OUT端點,使用message管道。記住每個包必須由Sync欄位開始。Packet 135是資料包,是從host發向device,現在來分析它的Data域。對應USB spec Table9-2,80代表請求的資料需要從device發向host,06需要檢視Table9-4,說明請求的型別是GET_DESCRIPTION,01檢視Table9-5,說明請求的描述符的型別是DEVICE的。Packet136是device發向host的握手包,表示它接受到了這個請求。在Linux中,這個請求使用一個結構體來描述的——usb_ctrlrequest,對應這裡的Packet135的Data域。

struct usb_strlrequest{

       _u8 bRequestType;    //輔助的請求型別

       _u8 bRequest;        //請求型別

       _le16 wValue;        //請求的輔助數值

       _le16 wIndex;        //請求的輔助數值,通常用於計算索引或者偏移

       _le16 wLength;       //如果控制傳輸有資料階段,在這裡定義資料的大小

}_attribute_((packed)); 

Transaction1:

Transaction1是一個IN Transaction。首先host向device傳送令牌包IN包,注意IN包中的ADDR域為0,ENDP域為0。Packet 138是device發向host的DATA包,DATA的型別是DATA1。DATA包分兩種,DATA0和DATA1,在USB的資料傳輸中,每個Transaction的資料包的型別需要反轉data0,data1,data0,data……這樣的順序傳送下去,以保證資料的完整性。所以這裡是DATA1,上一個是DATA0。檢視DATA包的Data域。檢視一下這張表:

 

Transaction1~ Transaction3中的Data域得到的正好是這18個位元組。Transaction1中的資料域0x12為bLength(描述符的長度),0x01為bDescriptorType(描述符的型別,USB_DT_DEVICE),0x0200為bcdUSB(USB spec的版本號),0x00為bDeviceClass,0x00為bDeviceSubClass,0x00為bDeviceProtocol,0x08為bMaxPacketSize0(端點0一次可以處理的最大位元組數)。

Transaction2:

Transaction2的Data域:0x046D為idVendor(廠商ID號),0xc018(產品的ID號),0x4301(裝置的版本號),iManufacturer(廠商對應的字串描述符的索引值),iProduct(產品對應的字串描述符的索引值)。

Transaction3:

Transaction3的Data域:0x00為iSerialNumber(序列號對應的字串描述符的索引值),0x01為bNumConfigurations(裝置當前速度模式下支援的配置數量)。

Transaction4:

首先發送一個OUT包,注意令牌包主要是指明傳輸型別,這裡就為OUT型別。然後發一個大小為0的DATA包,device回一個ACK握手包。本次傳輸結束。這是個控制傳輸過程,在控制傳輸中有3個階段:setup階段,資料階段和狀態階段。Setup階段指明瞭一次主機的請求型別,資料階段為請求型別所需要傳輸的資料,最後的狀態階段用於表示一次控制傳輸的結束。

然後,host向device傳送了一個Reset訊號,由上邊的狀態圖可以看出,USB由powered模式進入了default模式。

Transfer1:

 

通過bRequest可以看出這是一個SET_ADDRESS的過程,一共包含兩個Transaction。注意這裡的ADDR域和ENDP域都是0。Packet275中的Data域,由於這是一個SETUP Transaction,所以這個域裡放的是host對device的請求。05表示bRequest為SET_ADDRESS,值為03,所以新地址為3。但是不會立即生效,需要等到這個請求的狀態階段完成地址更改才完成。Transaction6首先host向device傳送一個IN型別令牌包,然後device向host傳送一個位元組為0的DATA包,host回覆一個ACK握手包,這個結束。

Transfer 2:

 

Transfer 2完成的是獲得裝置描述符。與Transaction0的不同是,這次有了明確的地址。第一次獲得裝置描述符主要為了得到端點0可以傳送的資料的大小,所以只要一個Transaction1的8個位元組資料就可。Transfer 2完成了整個裝置描述符的讀取工作。