1. 程式人生 > >【轉】USB 協議分析 設定USB地址 和 配置-字串描述符

【轉】USB 協議分析 設定USB地址 和 配置-字串描述符

USB協議深入分析 設定USB地址

  前面已經解釋主控器怎麼樣傳送裝置描述符下來,然後裝置返回相應的裝置描述符。下一步主控器的動作是做什麼呢?由於在USB總線上的裝置有很多,為了區分不同的裝置通訊,就需要給每個裝置分配一個地址,這跟網路中的IP地址是一樣的,或者跟MAC地址也是一樣的。因而,接著下來就是主控器分配地址給裝置,USB的裝置地址是從1開始到127。下面就是接收到主控器發下來的資料包: 00 05 01 00 00 00 00 00USB_SETUP_PACKET定義具體地分析這個資料,就可以知道應做什麼樣的響應了。下面就來解釋這個操作。 先取得 bmRequestType
的型別,也就是第一個位元組,它是00。從USB協議裡檢視,它的方向位是主控器傳送給裝置,由D6D5位就知道它是USB協議裡定義的標準請求,由D4-D0位知道它是USB裝置接收這個包資料。 bRequest是05,從前面已經介紹的型別,就知道它是設定地址,如下: SET_ADDRESS             5 所以這個包需要按設定地址的格式去解釋後面的資料。   由於USB協議可以知道,USB的裝置地址放在欄位 wValue
裡,因它的值是01 00,按小端格式解釋就是0x0001了。其它相應的欄位 wIndexwLength應都是0,如果是其它非0的資料,是沒有定義的。   USB的序列引擎通過這個地址來判斷是否接收總線上的資料,如果傳送的地址跟它一致,就會接收主控器發過來的資料,當然從這個裝置傳送出去的資料也帶有這個地址,因此就可以讓主控器識別不同的USB裝置資料了。  

前面已經介紹設定USB的裝置地址,接著下來是做什麼呢?其實有了裝置地址後,主控器還會再次傳送獲取上面已經讀取的裝置描述符下來,如下:

80 06 00 01 00 00 12 00
然後USB裝置也再次迴應它,但這次傳送的長度是0x0012了,不再是第一次64個位元組長度了。 接著USB裝置就返回下面的描述符給主控器,也就是第一次已經發送的裝置描述符,如下: 12 01 10 01 00 00 00 40 00 80 00 80 00 01 04 2C 4A 01   這樣分配地址之後,再次獲取裝置描述符成功了,接著下來就是主控器獲取配置描述符。下面就是收到的配置描述符資料: 80 06 00 02 00 00 09 00 分析上面的資料如下: bmRequestType是80,表示方向USB裝置傳送給主控器,接收裝置是USB裝置。 bRequest是06,表示這是獲取描述符。 GET_DESCRIPTOR         6 wValue是00 02。低位元組表示偏移地址00,高位元組表示描述符的型別。如下: CONFIGURATION          2 所以這裡的返回的裝置描述符是配置描述符。 wIndex是00 00。 wLength是09 00。它表示返回描述符的長度。這裡是9個位元組。 接著下來,就是裝置返回配置描述符給主控器,傳送的資料如下: 09 02 22 00 01 01 00 01 32 傳送的資料是按下面的結構來定義,這也是在USB協議裡定義的格式。如下: typedef  struct _USB_CONFIGURATION_DESCRIPTOR {  BYTE bLength;  BYTE bDescriptorType;  WORD wTotalLength;  BYTE bNumInterfaces;  BYTE bConfigurationValue;  BYTE iConfiguration;  BYTE bmAttributes;  BYTE MaxPower; USB_CONFIGURATION_DESCRIPTOR;   bLength是配置的長度,也就是配置結構的整個長度。在這裡9個位元組。 bDescriptorType是描述符的型別,這裡配置描述符,所以設定為02。 wTotalLength是所有配置設定的結構長度。包括配置描述符、介面描述符、HID或者其它描述符和端點描述符的長度。這裡是22 00,也就是0x0022個位元組。 bNumInterfaces是介面個數,這裡一個。 bConfigurationValue是配置的個數,當設定配置時傳送的值。這時設定為1個配置。 iConfiguration是說明配置的字元的偏移值。這裡是0。 bmAttributes是配置特性,D7位保留。D6位是說明是否自供電。D5位是否支援遠端喚醒。D4—D0是保留,設定為0。 MaxPower是使用的功率,它採用電流來表示。每2mA為單位,比如它的值是50時就表示是100mA的電流消耗。 通過這樣說明,主控器就知道這個裝置是什麼樣的裝置,有多少功能。     USB協議深入分析 字串描述符 上一次說到把配置描述符返回給主控器那裡了,現在接著下來,就會收到主控器發來字串描述符。如果在裝置描述符那裡指定沒有字串描述的話,在這裡是不會收到字串描述符的。由於我在裝置描述符裡指定有字串描述符的偏移地址,因此,就收到主控器發出請求字串描述符。收到的資料如下: 80 06 00 03 00 00 FF 00 bmRequestType是80,表示方向USB裝置傳送給主控器,接收裝置是USB裝置。 bRequest是06,表示這是獲取描述符。 GET_DESCRIPTOR         6 wValue是00 03。低位元組表示偏移地址00,高位元組表示描述符的型別,如下: STRING                   3 wIndex是00 00。 wLength是FF 00。它表示返回描述符的長度。這裡是256個位元組。 因此,這個獲取字串描述符,就是從字串描述記憶體裡,0偏移地址開始的位置讀取第一個字串描述符返回給主控器。接著就返回下面的資料給主控器: 04 03 09 04 上面的資料是按字串描述符來組織的,它的結構,我定義結構如下: typedef  struct _USB_STRING_DESCRIPTOR {  BYTE bLength;  BYTE bDescriptorType;  WORD bString; USB_STRING_DESCRIPTOR;   bLength是所有資料的長度。在這裡是4。 bDescriptorType是描述型別,這裡字串描述符,所以它是3。 bString是可變的字元陣列。不超過254個應都可以的,並且它是使用UNICODE編碼的字串。在這裡是09 04,這是美國英語的標識,0x0409。如果想輸入中文的標識,只要改為0x0804就可以了。 通過這個字串描述符,主控器就知道字串描述符是使用什麼語言說明的了,這樣就可以支援全世界的語言標識。