1. 程式人生 > >【轉】USB協議深入分析 裝置描述符配置包 和 返回裝置描述符

【轉】USB協議深入分析 裝置描述符配置包 和 返回裝置描述符

USB協議深入分析 裝置描述符配置包 和 返回裝置描述符

  (2012-08-14 16:55:52) 轉載
標籤: 

描述符

 

主控器

 

字串

 

裝置

 

位元組

 

it

分類: 外圍器件介面

 裝置描述符配置包 和 返回裝置描述符

 

USB協議深入分析 裝置描述符配置包

裝置描述符配置包 在USB通訊裡,從主控器發出來的第一個配置包就是裝置描述符配置包,目的只有一個,就是獲取插入的USB屬性,以便載入合適的驅動程式。現在就來詳細地分析一下裝置描述符包的定義。 在USB2.0的協議裡找到9.3 USB Device Requests裡就找到這個結構的定義,這裡我使用C的定義結構如下: typedef
  struct _USB_SETUP_PACKET {  REQUEST_TYPE bmRequestType;  BYTE         bRequest;  WORD_BYTE    wValue;  WORD_BYTE    wIndex
;
 WORD         wLength; USB_SETUP_PACKET;   bmRequestType是包含有下面幾方面的內容: D7 D6 D5 D4 D3 D2 D1 D0 在這一個位元組裡,又按位分為: D7位是表示後面傳送資料的方向位。 當D7等於0時,表示後面的資料是從主控器傳送到USB裝置。在PC裡,就是從PC機發送到USB的裝置。 當D7等於1時,表示後面的資料是從USB裝置傳送到主控器。在PC裡,就是從USB裝置傳送到USB裝置。在上次裡,我收到並顯示出來的資料是80,就表示從USB裝置裡傳送資料給PC。在這裡再次給出上一次的包資料: 80 06 00 01 00 00 40 00
這裡的80,就是D7位為1。   D6-D5位是請求主分型別 0 是表示標準的請求。 1 是表示類別的請求。 2 是表示廠商的請求。 3 是保留。   D4-D0位是表求接收這個包的介面。 0 是表示USB裝置接收。 1 是表示介面接收。 2 是表示端點接收。 3 是表示其它接收,不知道的。 4-31是保留。   bRequest是本描述符的請求型別,也就是後面傳送的資料是什麼樣的東西。由於USB裡有很多配置資訊,比如獲取裝置描述符,又有設定USB地址等等,就是通過這個位元組來區分的。 從USB協議裡查詢表9-4,就可看到如下的編碼: GET_STATUS              0 CLEAR_FEATURE          1 Reserved for future use      2 SET_FEATURE             3 Reserved for future use      4 SET_ADDRESS             5 GET_DESCRIPTOR         6 SET_DESCRIPTOR          7 GET_CONFIGURATION      8 SET_CONFIGURATION      9 GET_INTERFACE           10 SET_INTERFACE            11 SYNCH_FRAME              12 在上面的資料包裡,看到它的內容是06,那麼它就是 GET_DESCRIPTOR型別。也就是主控器想讀取USB裝置的描述符,到這裡就已經分析出來的意思,就是主控器想讀取USB描述符,但還不知道是什麼描述符的內容。


 

wValue是根據不同的請求而設定不同的值。一般就是傳送引數給裝置標明這是什麼請求。在上面 GET_DESCRIPTOR獲取裝置描述符裡,它的值是00 01。在 GET_DESCRIPTOR裡這個欄位的低位元組表示描述符的索引,高位元組表示描述符的型別。高位元組的型別如下: DEVICE                   1 CONFIGURATION          2 STRING                   3 INTERFACE                4 ENDPOINT                5 DEVICE_QUALIFIER         6 OTHER_SPEED_CONFIGURATION             7 INTERFACE_POWER 1                   8 wValue值在這裡的高位元組是01,那麼它就是裝置描述符了。低位元組是00,那麼它就是表示從偏移地址0開始讀取裝置描述符。由於在配置描述符裡有很多配置,所以低位元組在那裡就可以用來識別獲取同樣型別的描述符不同的配置。   wIndex是根據不同的請求而設定不同的值。一般用來說明端點號或者說明介面標識。在獲取描述符裡,設定為0,或者是語言ID。在這個傳送的描述符裡,它是設定為00 00。   wLength是根據請求來決定下一階段傳送資料的長度。前面請求第一個位元組裡,已經說明下一階段資料傳送的方向,這裡說明了傳送資料的長度。不管是傳送資料,還是接收資料,都不要超過這個資料長度,否則主機會出問題,或者裝置有問題。在這個獲取裝置描述裡,它的長度是40 00,按小端格式去解釋,就是64個位元組。   到這裡,就把主控器發下來的資料解釋完成了,知道去做什麼的事情和迴應。下一次就去分析怎麼樣返回裝置描述符。     迴應裝置描述符 上一次已經介紹怎麼樣收到主控器的獲取裝置描述符的資料,這裡就解釋怎麼樣傳送迴應資料給主控器。 先從USB協議裡找到標準裝置的定義,我把它用C語言定義如下: typedef  struct _USB_DEVICE_DESCRIPTOR {  BYTE bLength;  BYTE bDescriptorType;  WORD bcdUSB;  BYTE bDeviceClass;  BYTE bDeviceSubClass;  BYTE bDeviceProtocol;  BYTE bMaxPacketSize0;  WORD idVendor;  WORD idProduct;  WORD bcdDevice;  BYTE iManufacturer;  BYTE iProduct;  BYTE iSerialNumber;  BYTE bNumConfigurations; USB_DEVICE_DESCRIPTOR; 返回給主控器的資料結構就是上面的內容,只要把上面的結構填寫合適的內容,就可以傳送回去給主控器。在我的USB裝置裡,我把它填寫如下的資料: 12 01 10 01 00 00 00 40 00 80 00 80 00 01 04 2C 4A 01   看到這串資料是不明白是什麼東西的,現在就來仔細地分析它的具體定義。下面就按著一個欄位一個欄位地分析它。 bLength是本結構的資料長度,這樣可以方便以後相容不同的版本協議。因為不同的結構是不同的長度,這樣就可以區分不同的協議了。比如有一天想新增一個欄位,那麼它的長度就會改變,這時就可以根據不同的長度進行解釋不同的協議了。這次返回的結構長度是0x12,也就是18個位元組,它的長度是從 bLength長度開始,也就是說是完全整個結構的長度。   bDescriptorType是描述符的型別。它的定義跟主控器發下來描述符的型別是一樣的,如下: DEVICE                   1 CONFIGURATION          2 STRING                   3 INTERFACE                4 ENDPOINT                5 DEVICE_QUALIFIER         6 OTHER_SPEED_CONFIGURATION             7 INTERFACE_POWER 1                   8 由於返回的是裝置描述符,所以就選擇了1,也就是包裡顯示的第二個位元組01。用這個型別來區分不同的描述符。

 

USB協議深入分析 返回裝置描述符

  bcdUSB是USB釋出的協議版本。也就是本裝置能適用於那種協議,目前USB主要有兩個版本,一個是1.10,一個是2.10版本。在本裝置裡,採用了1.10的協議版本。由於這個欄位是採用BCD編碼,所以1.10的表示為0x0110的格式,按小端格式輸出來,就變成10 01的顯示了。   bDeviceClass是裝置分類。當它的值是0時,表示所有介面在配置描述符裡,並且所有介面是獨立的。當它的值是1到FEH時,表示不同的介面關聯的。當它的值是FFH時,它是廠商自己定義的。在這個裝置裡,是定義為0。   bDeviceSubClass是裝置子分類碼。當前面的 bDeviceClass值是0時,這裡一定要設定為0。其它就跟據USB-IF組織定義的編碼。   bDeviceProtocol是裝置使用的協議。如果使用USB-IF組織定義的協議,就需要設定這裡的值。如果不使用,就直接設定為0。如果廠商自己定義的可以設定為FFH。 以上三個值,在本裝置裡全部設定為0。   bMaxPacketSize0是端點0收發最大的包大小。僅允許設定8,16,32,64中的任何一個大小。在本裝置裡是設定為64個位元組大小。所以看到這個欄位是40 的大小。 12 01 10 01 00 00 00 40 00 80 00 80 00 01 04 2C 4A 01   idVendor是廠商標識。由USB-IF分配的編碼。在這裡使用0x8000。   idProduct是廠商定義的產品標識。由廠家和產品標識,就可以讓作業系統載入不同的驅動程式。如下: 12 01 10 01 00 00 00 40 00 80 00 80 00 01 04 2C 4A 01   bcdDevice是用BCD表示的裝置釋出的版本號。這裡是1.00。 12 01 10 01 00 00 00 40 00 80 00 80 00 01 04 2C 4A 01   iManufacturer是廠商字串的偏移值。這值主要說明了它在字串描述符裡的偏移位置。如果它設定為0,表示沒有廠商字串。在這裡是0x04,就是從字串描述符開始位置算起第4個位元組位置讀取字串。   iProduct是產品字串的偏移值。這值主要說明了它在字串描述符裡的偏移位置。如果它設定為0,表示沒有產品字串。在這裡是0x2C,就是從字串描述符開始位置算起第2C個位元組位置讀取字串。   iSerialNumber是序列號字串的偏移值。這值主要說明了它在字串描述符裡的偏移位置。如果它設定為0,表示沒有序列號字串。在這裡是0x4A,就是從字串描述符開始位置算起第4A個位元組位置讀取字串。 所有字串,都是採有UNICODE編碼。   bNumConfigurations是配置描述符的個數。在這裡只使用了一個配置,所以設定為1。