USB描述符 包括bus hound抓包

USB描述符

USB描述符信息存儲在USB設備中,在枚舉過程中,USB主機會向USB設備發送GetDescriptor請求,USB設備在收到這個請求之後,會將USB描述符信息返回給USB主機,USB主機分析返回來的數據,判斷出該設備是哪一種USB設備,建立相應的數據鏈接通道。那麼USB描述符信息到底是一個什麼樣的數據呢,USB協議中有詳細描述。


通用的USB描述符信息包括設備描述符、配置描述符、接口描述符和端點描述符,具體不同的USB設備還包括其它類型的描述符,例如,USB鼠標、鍵盤還包括HID描述符和報告描述符,還有可能包括字符串描述符,USB協議中對描述符類型定義如下:


所有的描述符信息都是通過發送GetDescriptor請求得到的,但是USB設備也不知道你要獲取的是哪種描述符,所以還需要在GetDescriptor請求中指定描述符的類型以及描述符的長度,這樣USB設備才能正確的返回描述符信息


設備描述符

Linux中對於設備描述符結構體定義如下:

216 /* USB_DT_DEVICE: Device descriptor */
217 struct usb_device_descriptor {
218         __u8  bLength;
219         __u8  bDescriptorType;
220     
221         __le16 bcdUSB;
222         __u8  bDeviceClass;
223         __u8  bDeviceSubClass;
224         __u8  bDeviceProtocol;
225         __u8  bMaxPacketSize0;
226         __le16 idVendor;
227         __le16 idProduct;
228         __le16 bcdDevice;
229         __u8  iManufacturer;
230         __u8  iProduct;
231         __u8  iSerialNumber;
232         __u8  bNumConfigurations;
233 } __attribute__ ((packed));
234 
235 #define USB_DT_DEVICE_SIZE              18

bLength: 描述符的長度,設備描述符的長度爲18個字節。

bDescriptorType: 描述符的類型,設備描述符的類型爲0x01

bcdUSB: USB設備所遵循的協議版本號,例如2.0協議爲0x0200

bDeviceClass: USB設備類代碼,由USB-IF分配,如果該字段爲0x00,表示由接口描述符來指定(有可能該USB設備是一個複合設備,USB設備的各個接口相互獨立,分別屬於不同的設備類)。如果是0x01~0xfe,表示爲USB-IF定義的設備類,例如0x03HID設備,0x09HUB設備。如果是0xff,表示由廠商自定義設備類型。

bDeviceSubClass: USB子類代碼,由USB-IF分配,如果bDeviceClass0x00,那麼該字段也必須爲 0x00,其它情況可以參考USB關於對於USB Device Class的定義。

bDeviceProtocol: 協議代碼,由USB-IF分配,如果bDeviceClassbDeviceSubClass定義爲0x00那麼該字段也必須爲0x00

bMaxPacketSize0: 端點0最大數據包長度,必須爲8163264

idVendor: 廠商ID,由USB-IF分配,需要向USB-IF組織申請。

idProduct: 產品ID,由廠商指定。

bcdDevice: 設備序列號,由廠商自行設置。

iManufacturer: 用於描述廠商的字符串描述符索引。

iProduct用於描述產品的字符串描述符索引。

iSerialNumber: 用於描述產品序列號的字符串描述符索引,注意,所有的字符串描述符是可選的,如果沒有字符串描述符,指定這些索引爲0x00

bNumConfigurations:配置描述符數量。

例如,我的USB鼠標設備描述符信息如下:


從中可以看出該USB設備符合USB1.1協議,在設備描述中並沒有指定該USB設備類型,端點0最大數據包長度爲8個字節,也就是說一次還不能獲取完全設備描述符,需要三次才能獲取完全。再看bMaxPacketSize0在設備描述符中的偏移,剛好是第8個字節,也就是說傳輸一次就能知道端點0一次能夠傳輸多長的數據,根據這個值才能判斷出是否繼續傳輸,來完整的獲取描述符信息。該USB設備的idVendor0x80eeidProduct0x0021,有一個配置等等信息。


配置描述符

一個USB設備只有一個USB設備描述符,可以有多個配置描述符,配置描述符定義如下:

265 /* USB_DT_CONFIG: Configuration descriptor information.
266  *
267  * USB_DT_OTHER_SPEED_CONFIG is the same descriptor, except that the
268  * descriptor type is different.  Highspeed-capable devices can look
269  * different depending on what speed they're currently running.  Only
270  * devices with a USB_DT_DEVICE_QUALIFIER have any OTHER_SPEED_CONFIG
271  * descriptors.
272  */
273 struct usb_config_descriptor {
274         __u8  bLength;
275         __u8  bDescriptorType;
276 
277         __le16 wTotalLength;
278         __u8  bNumInterfaces;
279         __u8  bConfigurationValue;
280         __u8  iConfiguration;
281         __u8  bmAttributes;
282         __u8  bMaxPower;
283 } __attribute__ ((packed));
284 
285 #define USB_DT_CONFIG_SIZE              9

bLength: 配置描述符長度,配置描述符長度爲9字節大小。

bDescriptorType: 描述符類型,配置描述符類型爲0x02

wTotalLength: 配置描述符信息總的大小,包括接口描述符、端點描述符等等。

bNumInterfaces: USB接口數量。

bConfigurationValue: 當使用SetConfigurationGetConfiguration請求時所指定的配置索引值。

iConfiguration: 描述配置的字符串描述符索引。

bmAttributes: 供電配置,位詳細定義如下:

                          D7              保留,必須置1

                          D6              自供電模式

                          D5              遠程喚醒

                          D4D0      保留

bMaxPower: 最大功耗,以2mA爲單位,例如0x3250*2=100mA

我的USB鼠標配置描述符信息如下:


從中可以看出該設備配置信息總大小爲0x22=34字節大小,有一個接口,最大功耗爲100mA等信息。


接口描述符

一個配置中可以有一個或多個接口,一個接口中有0個或多個端點,接口描述符和端點描述符不能直接通過GetDescriptor請求返回,必須連同配置描述符一起返回,Linux中接口描述符定義如下:

309 /* USB_DT_INTERFACE: Interface descriptor */
310 struct usb_interface_descriptor {
311         __u8  bLength;
312         __u8  bDescriptorType;
313 
314         __u8  bInterfaceNumber;
315         __u8  bAlternateSetting;
316         __u8  bNumEndpoints;
317         __u8  bInterfaceClass;
318         __u8  bInterfaceSubClass;
319         __u8  bInterfaceProtocol;
320         __u8  iInterface;
321 } __attribute__ ((packed));
322 
323 #define USB_DT_INTERFACE_SIZE           9

bLength: 描述符長度,接口描述符長度爲9個字節。

bDescriptorType: 描述符類型,接口描述符的類型爲0x04

bInterfaceNumber: 該接口編號,接口編號從0開始分配,當一個配置有多個接口時,就用該字段來區分不同的接口。

bAlternateSetting:

bNumEndpoints:  端點數量,不包括端點0

bInterfaceClass

bInterfaceSubClass

bInterfaceProtocol:  和設備描述符中的bDeviceClassbDeviceSubClassbDeviceProtocol類似。

iInterface: 描述該接口的字符串描述符索引。

接口描述符實例如下:


前面9個字節是配置描述符,從中可以看出端點數量爲1bInterfaceClass0x03,即爲HID設備。


端點描述符

注意,端點0沒有端點描述符,Linux中端點描述符結構定義如下:

327 /* USB_DT_ENDPOINT: Endpoint descriptor */
328 struct usb_endpoint_descriptor {
329         __u8  bLength;
330         __u8  bDescriptorType;
331 
332         __u8  bEndpointAddress;
333         __u8  bmAttributes;
334         __le16 wMaxPacketSize;
335         __u8  bInterval;
336 
337         /* NOTE:  these two are _only_ in audio endpoints. */
338         /* use USB_DT_ENDPOINT*_SIZE in bLength, not sizeof. */
339         __u8  bRefresh;
340         __u8  bSynchAddress;
341 } __attribute__ ((packed));
342 
343 #define USB_DT_ENDPOINT_SIZE            7
344 #define USB_DT_ENDPOINT_AUDIO_SIZE      9       /* Audio extension */

bLength: 描述符長度,這裏有兩個值如果是audio設備的端點,那麼端點描述符長度就爲9個字節,對於其它設備端點,端點描述符長度就爲7個字節。

bDescriptorType: 描述符類型,端點描述符類型爲0x05

bEndpointAddress: 端點地址,詳細定義如下:

                                  D7 端點方向

                                  0                  OUT端點

                                  1                  IN端點

                                  D6D4       保留 

                                  D3D0       端點編號

bmAttributes: 端點類型,詳細定義如下:

                                  D5~D4 用途

                                  00     數據端點

                                  01     反饋端點

                                  10     隱式反饋數據端點

                                  11     保留

                                  D3~D2 同步類型

                                  00     非同步

                                  01     異步

                                  10     自適應

                                  11     同步

                                  D1~D0 傳輸類型

                                  00     控制傳輸

                                  01     同步傳輸

                                  10     塊傳輸

                                  11     中斷傳輸

                                  如果該端點不是同步端點,D5~D2保留且必須置0

wMaxPacketSize: 端點所支持最大數據包的長度,詳細定義如下:

                                D10~D0 最大數據包長度

                                D12~D11

                                其餘位保留且必須置0

bInterval:端點數據傳輸的訪問時間間隔。對於全速/低速的中斷端點,取值範圍爲 1~255,對於高速中斷端點,取值範圍爲1~16,詳細定義可以參考USB協議。

端點描述符實例如下:


因爲不能單獨的獲取接口和端點描述符,所以我將設備配置信息全獲取下來了,端點描述符從0x07處開始,0x07爲端點描述符長度,該端點是一個IN端點,端點地址爲1,該端點是一箇中斷端點,最大數據包長度爲6個字節,時間間隔爲10ms


5 HID描述符

從上圖可以看出,除了配置描述符、接口描述符、端點描述符之外、還有一個描述符,它就是HID描述符,HID描述符專用於HID類設備。Linux關於HID描述符結構定義如下:

537 struct hid_class_descriptor {
538         __u8  bDescriptorType;
539         __le16 wDescriptorLength;
540 } __attribute__ ((packed));
541 
542 struct hid_descriptor {
543         __u8  bLength;
544         __u8  bDescriptorType;
545         __le16 bcdHID;
546         __u8  bCountryCode;
547         __u8  bNumDescriptors;
548 
549         struct hid_class_descriptor desc[1];
550 } __attribute__ ((packed));

bLength: 描述符長度。

bDescriptorType:描述符類型,HID描述符的類型爲0x21

bcdHID: 所遵循的HID協議版本。

bCountryCode: 國家代碼。

bNumDescriptors: 下級描述符數量,通常至少需要一個報告描述符。

bDescriptorType: 下級描述符類型,例如報告描述符。

wDescriptorLength: 下級描述符長度。

從上面USB鼠標配置描述符中可以看出,該鼠標所遵循的HID協議版本爲1.1,有一個HIDclass描述符,描述符類型爲0x22,即報告描述符,描述符長度爲0x46

發佈了16 篇原創文章 · 獲贊 21 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章