USB描述符解析-->枚舉.

 枚舉能夠理解爲主機按不定的順序向USB設備討要設備信息,好給它分配資源,若枚舉不成功,就放棄分配資源,省得浪費資源。通常都是使用中斷傳輸方式通訊。異步

    經常使用的描述符有如下幾種:01H、設備描述符  02H、配置描述符  03H、字符串描述符  04H、接口描述符  05H、端點描述符工具

21H:HID描述符 22H:HID報告學習

    一個設備只能有一個設備描述符,而一個設備描述符能夠包含多個配置描述符(bNumConfigurations  ),一個配置描述符又能夠包含多個接口描述符,一個接口使用了幾個端點,就有幾個端點描述符。網站

如下爲HID描述:(一個USB設備同時包含鍵盤和鼠標,使用2個接口)編碼

1、設備描述符:Device descriptorspa

hid_device_descriptor =
{
操作系統

   0x12 ,                       // bLength   該段描述符總長18個,不可變
   0x01,                        // bDescriptorType:經常使用的以下0x01:設備  0x02配置 0x03字符 0x04接口 0x05端點 0x21HID
   0x0200,                    // bcdUSB  USB版本號: 1.1--0x0110   2.0--0x0200  3.0--0x0300
   0x00,                        // bDeviceClass  HID 不使用接口聯合描述字與下面一塊兒設置爲00H
   0x00,                        // bDeviceSubClass
   0x00,                        // bDeviceProtocol
   8,                              // bMaxPacketSize0 端點0最大包的大小  USB2.0:低速--8  全速:八、1六、3二、64  高速:64
   0x1223,                    // idVendor     VID
   0x3F07,                    // idProduct     PID
   0x1110,                     // bcdDevice   廠商指定的設備版本號
   0x01,                         // iManufacturer  指向描述製造商字符串的索引
   0x02,                         // iProduct           指向描述產品的字符串索引
   0x00,                         // iSerialNumber  指向設備序列號的字符串索引
   0x01                          // bNumConfigurations  定義配置描述符的數量
};
對象

2、配置描述符索引

hid_configuration_descriptor =接口

{
   0x09,                         // bLength  長度9個,不可變
   0x02,                         // bDescriptorType 配置描述符
   0x3b00,                     // wTotallength= 9+(9+9+7)+(9+9+7)  配置描述符+(接口描述符+HID描述符+端點描述符)*接口數

                     配置描述符信息總的大小,包括接口描述符、端點描述符等等
   0x02,                         // bNumInterfaces   接口數量=2(鍵盤+鼠標)
   0x01,                         // bConfigurationValue  Set_Configuration命令須要的參數值
   0x00,                         // iConfiguration 配置字符串索引
   0xa0,                         // bmAttributes bit7=1 bit6:1--自供電 0--總線供電 bit5:1--遠程喚起 0--不支持 bit[4:0]=0

   0x32                          // MaxPower (in 2mA units) 50*2mA=100mA
};

3、接口配置符

keyboard_interface_descriptor =
{  
   0x09,                               // bLength                長度9個,不可變
   0x04,                               // bDescriptorType   接口描述符
   0x00,                               // bInterfaceNumber  接口0  (接口從0開始,鍵盤定義0,鼠標定義1)
   0x00,                               // bAlternateSetting   接口索引值
   0x01,                               // bNumEndpoints     端點個數1(端點0不可用,好比EP1)
   0x03,                               // bInterfaceClass     (3 = HID)
   0x01,                               // bInterfaceSubClass  接口子類型:01爲Boot Device,鍵鼠在BIOS下就啓動
   0x01,                               // bInterfaceProcotol    接口協議:00--None  01--Keyboard  02--Mouse
   0x00                                // iInterface                  描述該接口的字符串索引
};

mouse_interface_descriptor =
{  
   0x09,                               // bLength   長度9個,不可變
   0x04,                               // bDescriptorType   接口描述符
   0x01,                               // bInterfaceNumber  接口1   不一樣接口
   0x00,                               // bAlternateSetting   接口索引值
   0x01,                               // bNumEndpoints     端點個數1(端點0不可用,好比EP2)
   0x03,                               // bInterfaceClass     (3 = HID)
   0x01,                               // bInterfaceSubClass  
接口子類型:01爲Boot Device,鍵鼠在BIOS下就啓動
   0x02,                               // bInterfaceProcotol    
接口協議:00--None  01--Keyboard  02--Mouse
   0x00                                // iInterface                  描述該接口的字符串索引
};

4、HID描述符

 keyboard_hid_descriptor =
{   
   0x09,                               // bLength                 長度9個,不可變
   0x21,                               // bDescriptorType    HID描述符
   0x0110,                           // bcdHID                   HID專屬版本號
   0x00,                               // bCountryCode       國家代碼
   0x01,                               // bNumDescriptors   附屬類描述字的數目1個
   0x22,                               // bDescriptorType    描述字類型:報告   
   HID_KEYBOARD_REPORT_DESCRIPTOR_SIZE  // 鍵盤HID報告描述字總字節數,好比:0x75,0x00,低字節在前      
};

 mouse_hid_descriptor =
{   
   0x09,                               // bLength                 長度9個,不可變
   0x21,                               // bDescriptorType    HID描述符
   0x0110,                           // bcdHID                   HID專屬版本號
   0x00,                               // bCountryCode       國家代碼
   0x01,                               // bNumDescriptors   附屬類描述字的數目1個
   0x22,                               // bDescriptorType    描述字類型:報告   
   HID_MOUSE_REPORT_DESCRIPTOR_SIZE  // 鼠標HID報告描述字總字節數,好比0x34, 0x00,低字節在前       
};

5、端點描述符

hid_keyboard_endpoint1_in_descriptor  = 
{   
   0x07,                               // bLength                   長度7個,不可變
   0x05,                               // bDescriptorType      端點描述符
   0x81,                               // bEndpointAddress   bit[7]:1--IN  0--OUT  地址爲EP1,輸入
   0x03,                               // bmAttributes            傳輸類型(中斷--03H)
   0x08,                               // MaxPacketSize_LSB   端點1最大信息包尺寸
   0x00,                               // MaxPacketSize_MSB               
   0x08,                               // bInterval                   輪詢間隔 一幀爲8箇中斷間隔

};

hid_mouse_endpoint2_in_descriptor  = 
{   
   0x07,                               // bLength                   長度7個,不可變
   0x05,                               // bDescriptorType      端點描述符
   0x82,                               // bEndpointAddress   bit[7]:1--IN  0--OUT  地址爲EP2,輸入
   0x03,                               // bmAttributes            傳輸類型(中斷--03H)
   0x08,                               // MaxPacketSize_LSB   端點1最大信息包尺寸
   0x00,                               // MaxPacketSize_MSB               
   0x08,                               // bInterval                   輪詢間隔 一幀爲8箇中斷間隔

};

說完上述幾個重要描述符後,咱們再來看字符串描述符.

在USB中,字符串描述符是可選的,也就是無關緊要的角色,USB並無強制規定必須有,可是通常產品是有的,至少能說明生產廠家,產品信息等,要否則這個產品看誰還敢用.哈哈哈...

若是設備沒有字符串描述符,那麼在設備描述符、配置描述符、接口描述符等處的字符串索引值必須爲0,要否則在枚舉過程當中,USB主機會嘗試去獲取字符串描述符,而恰好你又沒有,那麼枚舉就會失敗,因此必須指定爲0

字符串描述符使用UNICODE編碼,能夠支持多種語言,因此字符串描述符首先要指定語言ID,語言ID代碼能夠參考這個網站:http://www.usb.org/developers/docs/USB_LANGIDs.pdf,例如:簡體中文的ID值爲0x0804,美式英語ID值爲0x0409。

語言ID字符串描述符結構定義以下:

在枚舉過程當中,USB主機會向USB設備發送GET_DESCRIPTOR請求,同時wValue字段高字節爲描述符類型,字符串描述符的類型爲0x03,低字節爲字符串描述符索引值,對於語言ID的索引爲0,其它字符串描述符索引由設備描述符指定,wIndex字段爲語言ID。

 

字符串描述符結構定義以下:

bLength爲描述符長度,bDescriptorType爲描述符類型,字符編碼統一採用UNICODE編碼,UNICODE採用兩個字節字節表示一個字符,若是是英語字符的話,那就很簡單了,直接在ASCII碼前面補上一個爲0x00的字節數據就組成UNICODE編碼了,若是是其它語言的話,網上有不少的UNICODE編碼轉換工具,能夠直接拿來使用就好了。

 

最後補上個人USB鼠標字符串描述符信息。

語言ID信息:

廠商字符串描述符以下:

我在Virtual Box中捕獲的信息,因此廠商字符串爲VirtualBox。

產品字符串描述符信息以下:

 

主機經過標準請求命令來得到以上HID描述符和HID報告:

     標準USB設備請求命令共有11個,大小都是8個字節,具備相同的結構,由5 個字段構成(字段是標準請求命令的數據部分),結構以下(括號中的數字表示字節數,首字母bm,b,w分別表示位圖、字節,雙字節):
bmRequestType(1) +bRequest(1) +wvalue(2) +wIndex(2) +wLength(2)
1、bmRequestType:

        bit[7]: 說明請求的傳輸方向  1--設備到主機(IN)   0--主機到設備(OUT)

        bit[6:5]:00--標準請求命令    01--專門類請求   10--用戶定義的請求    11--保留

        bit[4:0]:00000--接收者爲設備   00001--接收者爲接口   00010--接收者爲端點  00011--接收者爲其餘元件 其餘設置保留

2、bRequest:

      請求命令代碼,在標準的USB命令中,每個命令都定義了編號,編號的值就爲字段的值,編號與命令名稱以下(要注意這裏的命令代碼要與其餘字段結合使用,能夠說命令代碼是標準請求命令代碼的核心,正是由於這些命令代碼而決定了11個USB標準請求命令):
    一、Get Status (00H)  獲取狀態 

       wValue:0000H    wIndex:0000H(設備)、接口號或端點號  wLength:0002H
       A:[To Device]獲取設備的狀態:
          位0:自供電(0表示總線供電;1表示自供電).
          位1:遠程喚醒(0表示不支持遠程喚醒;1表示遠程喚醒).
          位2~15:保留.
          通常選擇總線供電,不支持遠程喚醒,因此返回數據就是0x0000.
       B:[To Interface]獲取接口的狀態:
          接口狀態的16位字節所有保留,因此返回數據就是0x0000.
       C:[To Endpoint]獲取端點的狀態:
          位0:Halt(0表示端點容許;1表示端點禁止).
          位1~15:保留(復位爲0).

      
    二、Clear Feature (01H) 清除特性 

      wValue:所要禁用的特徵   wIndex:0000H(設備)、接口號或端點號  wLength:0000H
       A:[To Device]清除設備的遠程喚醒功能,並返回一個空包.
       B:[To Endpoint]解禁端點.
   
    3、Set Feature (03H) 設置特性 

     wValue:所要使能的特徵   wIndex:0000H(設備)、接口號或端點號  wLength:0000H

       A:[To Device]設置設備的遠程喚醒功能,並返回一個空包.
       B:[To Endpoint]禁止端點.


    四、Set Address (05H) 設置地址 

      wValue:新的設備地址,範圍0001H到007FH   wIndex:0000H  wLength:0000H
       A:設置設備地址.


    五、Get Descriptor (06H) 獲取描述符 

     wValue:高字節--描述符類型  低字節--描述符索引   wIndex:0000H或ID  wLength:需返回的字節數
       A:[To Device]獲取設備描述符:
          描述當前USB協議的版本號.設備端點0的FIFO大小.USB設備的ID號等.
       B:[To Configuration]獲取配置描述符:
          描述USB設備接口個數及是否有自供電能力等.
       C:[To Interface]獲取接口描述符:
          描述端點0之外的物理端點個數等信息.
       D:[To Endpoint]獲取端點描述符:
          描述端點0各端點的傳輸類型和最大信息包大小和端點的傳輸方向(IN/OUT).


    六、Set Descriptor (07H) 設置描述符(可選,沒法更新) 

    wValue:高字節--描述符類型  低字節--描述符索引   wIndex:0000H或ID  wLength:需傳輸給設備的字節數


    七、Get Configuration (08H) 獲取配置信息 

    wValue:0000H   wIndex:0000H   wLength:0001H


    八、Set Configuration (09H) 設置配置 

    wValue:低字節規定了一個配置,若此值與設備支持的配置匹配,設備將實現所請求配置   wIndex:0000H  wLength:0000H
       A:[To Configuration]設置配置描述符.
       B:[To Interface]設置接口描述符.
       C:[To Endpoint]設置端點描述符.


    九、Get Interface (0AH) 獲取接口信息    
    wValue:0000H   wIndex:接口號(bInterfaceNumber)  wLength:0001H


    十、Set Interface (0BH) 設置接口 

    wValue:要選擇的替代設置(bAlternateSetting)   wIndex:接口號(bInterfaceNumber)  wLength:0000H


    十一、SYNCH_FRAME(0CH)

    wValue:0000H   wIndex:0000H  wLength:0006H
        用於設備設置和報告一個端點的同步幀.

一個描述設備描述符和描述配置描述符過程以下圖:

USB學習之描述符篇--枚舉 - lastnight1034 - lastnight1034的博客
能夠看到80  06  00  01  00  00  12  00主機發給設備的請求:
bmRequestType=80H說明這是主機發給設備的標準請求;
bRequest=06H說明這句的做用是Get Descriptor
wValue=0100H(注意這是小端模式,高字節在圖片裏顯示在後)說明須要設備上傳設備描述符(01)
wLength=0012H(注意這是小端模式,高字節在圖片裏顯示在後)說明設備必須上傳12H個字節長度的數據
因而設備上傳了0012H長的設備描述符:12  01  00  02  00  00  00  08  23  12  07  3f  10  11  01  02  00  01
第四行80  06  00  02  00  00  09  00主機發給設備請求:
按上面的解釋,說明這是主機要求設備上傳配置描述符(02H),由於主機沒法得知配置描述符裏的wTotallength多大,因此先發個標準長度0009H來試探。
因而設備上傳了09H長的配置描述符:09  02  3b  00  02  01  00  a0  32
主機得知配置總的含有003bH個字節,因而再次發給設備上傳配置描述符的請求:80  06 00 02 00 00 3b  00,要求的總字節長度爲003bH
以後設備上傳了003bH的數據:9個配置描述符+9個接口0描述符+9個HID描述符+7個端點1描述符+9個接口1描述符+9個HID描述符+7個端點1描述符
後主機進行設置配置:00  09  01  00  00  00  00  00 設置了配置描述符,使能端點1和端點2

 

USB學習之描述符篇--枚舉 - lastnight1034 - lastnight1034的博客
由於有2個接口,因此分2次分別設置:
EP1:讀取設備描述符,試探性配置描述符,返回鍵盤的配置描述符長度0022H,再次以0022H長度讀取配置描述符。設置配置描述符,掛起等配置完成。
配置完成後讀取HID報告:81  06  00  22  00  00  b5  00
81表明主機發給設備的接口   06表明Get Descriptor   22H爲HID報告  wIndex:00爲接口0  長度爲75H+40H=b5H(?)
設備上傳接口0的0075H長度字節HID報告。
開始設置接口1,仍然繼續讀取設備描述符試探性配置描述符,返回鍵盤的配置描述符長度0022H,再次以0022H長度讀取配置描述符。設置配置描述符,掛起等配置完成。
配置完成後讀取HID報告:不一樣的是wIndex:0001H 配置接口1,長度爲34H+40H=74H(?)
設備上傳接口1的0034H長度字節HID報告。結束後SET REPORT,結束,等待設備上傳端點鍵盤鼠標數據。
 

HID設備描述符

溫習了以上內容,咱們再來看看HID協議與這些描述符之間的關係。

當插入USB設備後,主機會向設備請求各類描述符來識別設備。

爲了把一個設備識別爲HID類別,設備在定義描述符的時候必須遵照HID規範。

從框圖中,能夠看出除了USB標準定義的一些描述符外,HID設備還必須定義HID描述符。另外設備和主機的通訊是經過報告的形式來實現的,因此還必須定義報告描述符;而物理描述符不是必需的。還有就是HID描述符是關聯於接口(而不是端點)的,因此設備不須要爲每一個端點都提供一個HID描述符。

接口描述符中bInterfaceClass的值必須爲0x03,bInterfaceSubClass的值爲0或1,爲1表示HID設備符是一個啓動設備(Boot Device,通常對PC機而言纔有意義,意思是BIOS啓動時能識別並使用您的HID設備,且只有標準鼠標或鍵盤類設備才能成爲Boot Device。若是爲0則只有在操做系統啓動後才能識別並使用您的HID設備)。

 

USB HID類描述符的結構

偏移量

大小

描述

0

bLength

1

數字

此描述符的長度(以字節爲單位)

1

bDescriptorType

1

常量

描述符種類(此處爲0x21即HID類描述符)

2

bcdHID

2

數字

HID規範版本號(BCD碼),採用4個16進制的BCD格式編碼,如版本1.0的BCD碼爲0x0100,版本爲1.1的BCD碼爲0x0110

4

bCountryCode

1

數字

硬件目的國家的識別碼(BCD碼)(見表3)

5

bNumDescritors

1

數字

支持的附屬描述符數目

6

bDescriptorType

1

常量

HID相關描述符的類型

0x21:HID描述符

0x22:報告描述符

0x23:物理描述符

7

wDescriptorLength

2

數字

報告描述符總長度

9

bDescriptorType

1

常量

用於識別描述符類型的常量,使用在有一個以上描述符的設備

10

wDescriptorLength

2

數字

描述符總長度,使用在有一個以上描述符的設備

 

 

報告描述符

報告描述符比較複雜,它是以item形式排列組合而成,無固定長途,用戶能夠自定義長度以及每一bit的含義。item類型分三種:main,global和local,其中main類型又可分爲5種tag:

  • input item tag:指的是從設備的一個或多個相似控制管道獲得的數據
  • output item tag:指的是發送給一個或多個相似控制管道的數據
  • feature item tag:表示設備的輸入輸出不面向最終用戶
  • collection item tag:一個有意義的input,output和feature的組合項目
  • end collection item tag:指定一個collectionitem的終止

每個main item tag(input,output,feature)都代表了來自一個特定管道的數據的大小,數據相對仍是獨立,以及其餘相關信息。在此以前,global和local item定義了數據的最大值和最小值,等等。local item僅僅描述下一個main item定義的數據域,而global item是這一個報告描述符中全部後續數據段的默認屬性。

 一個報告描述符可能包含多個main item,爲了準確描述來自一個控制管道的數據,一個報告描述符必須包括如下內容:

  • input(output,feature)
  • usage
  • usage page
  • Logical Minimum
  • Logical Maximum
  • Report Size
  • Report Count

下面用一個三鍵鼠標舉例說明:

Usage Page (Generic Desktop);    //global item

Usage (Mouse);    //global item 
Collection (Application);    //Start Mouse collection
Usage (Pointer);    //
Collection (Physical);    //Start Pointer collection
Usage Page (Buttons)
Usage Minimum (1),
Usage Maximum (3),
Logical Minimum (0),
Logical Maximum (1) ;   //Fields return values from 0 to 1
Report Count (3),
Report Size (1);   //Create three 1 bit fields (button 1, 2, & 3)
Input (Data, Variable, Absolute);   //Add fields to the input report.
Report Count (1),
Report Size (5);   //Create 5 bit constant field
Input (Constant), ;Add field to the input report
Usage Page (Generic Desktop),
Usage (X),
Usage (Y),
Logical Minimum (-127),
Logical Maximum (127);    //Fields return values from -127 to 127
Report Size (8),
Report Count (2);    //Create two 8 bit fields (X & Y position)
Input (Data, Variable, Relative);   //Add fields to the input report
End Collection;   //Close Pointer collection
End Collection;   //Close Mouse collection

 

item的數據格式有兩種,分別是短item和長item。

短item格式

 

bSize

0:0個字節

1:1個字節

2:2個字節

3:4個字節

bType

0:main

1:global

2:local

3:保留

bTag

item類型

8:input

9:output

A:collection

B:feature

C:end collection

 

 

長item,其bType位值爲3,bTag值爲F

 

bDataSize

0:0個字節

1:1個字節

2:2個字節

3:4個字節

bLongItemTag

0:main

1:global

2:local

3:保留

data 數據

 

 

物理描述符用來描述行爲特性,是可選的。

USB HID類可採用的通訊管道

全部的HID設備經過USB的控制管道(默認管道,即端點0)和中斷管道與主機通訊。

控制管道主要用於如下3個方面:

接收/響應USB主機的控制請示及相關的類數據

在USB主機查詢時傳輸數據(如響應Get_Report請求等)

接收USB主機的數據

中斷管道主要用於如下兩個方面:

USB主機接收USB設備的異步傳輸數據

USB主機發送有實時性要求的數據給USB設備

從USB主機到USB設備的中斷輸出數據傳輸是可選的,當不支持中斷輸出數據傳輸時,USB主機經過控制管道將數據傳輸給USB設備。

 

表一、USB HID規範定義的HID設備可用端點

管道

要求

說明

控制(端點0)

必須

傳輸USB描述符、類請求代碼以及供查詢的消息數據等

中斷輸入

必須

傳輸從設備到主機的輸入數據

中斷輸出

可選

傳輸從主機到設備的輸出數據

 

 

HID設備6種特定請求

 

HID類請求(命令)包格式

偏移量

大小

說明

0

bmRequestType

1

HID設備類請求特性以下:
位7:
0=從USB HOST到USB設備
1=從USB設備到USB HOST
位6~5:
01=請求類型爲設備類請求
位4~0:
0001=請求對象爲接口(interface)

於是,針對HID的設備類請求,僅僅10100001和00100001有效

1

bRequest

1

HID類請求(參考下表)

2

wValue

2

高字節說明描述符的類型

0x21:HID描述符

0x22:報告描述符

0x23:物理描述符

低字節爲非0值時被用來選定實體描述符。

4

wIndex

2

2字節數值,根據不一樣的bRequest有不一樣的意義

6

wLength

2

該請求的數據段長度

HID類請求

數值

HID類請求描述符

註釋

0x01

GET_REPORT

 主機用控制傳輸從設備接收數據,全部HID類設備都要支持這個請求;

0x02

GET_IDLE

 主機讀取設備當前的空閒速率,設備能夠不支持此請求;

0x03

GET_PROTOCOL

僅僅適應於支持啓動功能的HID設備(Boot Device)

0x09

SET_REPORT

 設備用控制傳輸接收主機的數據,設備能夠不支持此請求;

0x0A

SET_IDLE

 設置閒置狀態,設備可不支持此請求;

0x0B

SET_PROTOCOL

僅僅適應於支持啓動功能的HID設備(Boot Device)

 

GET_REPORT:主機經過控制端點獲取一個Report

 

描述

bmRequestType

0xA1

 

bRequest

0x01

 

wValue

高字節表示報告類型

0x01:input

0x02:output

0x03:feature

other:reserved

低字節表示ReportID,如不使用設爲0

 

wIndex

HID的interface索引值

 

wLength

Report長度

 

Data

Report內容

 

 

 

SET_REPORT:主機發送一個Report給設備,用以設置input,output或者feature

 

描述

bmRequestType

0x21

 

bRequest

0x09

 

wValue

高字節表示報告類型

0x01:input

0x02:output

0x03:feature

other:reserved

低字節表示ReportID,如不使用設爲0

 

wIndex

HID的interface索引值

 

wLength

Report長度

 

Data

Report內容

 

 

 

GET_IDLE

 

描述

bmRequestType

0xA1

 

bRequest

0x02

 

wValue

高字節0

低字節表示ReportID,如不使用設爲0

 

wIndex

HID的interface索引值

 

wLength

1

 

Data

空閒速率

 

 

 

SET_IDLE

 

描述

bmRequestType

0x21

 

bRequest

0x0A

 

wValue

新的速率

低字節表示ReportID,如不使用設爲0

 

wIndex

HID的interface索引值

 

wLength

0

 

Data

 

 

 

GET_PROTOCOL

 

描述

bmRequestType

0xA1

 

bRequest

0x03

 

wValue

0

 

wIndex

HID的interface索引值

 

wLength

1

 

Data

0 = Boot Protocol

1 = Report Protocol

 

 

 

SET_PROTOCOL

 

描述

bmRequestType

0x21

 

bRequest

0x0B

 

wValue

0 = Boot Protocol

1 = Report Protocol

 

wIndex

HID的interface索引值

 

wLength

0

 

Data

相關文章
相關標籤/搜索