HID是一種USB通信協議,無需安裝驅動就能進行交互,在學習HID之前,先來複習一下USB協議的相關內容。 USB設備描述符-概述 當插入USB設備後,主機會向設備請求各種描述符來識別設備。那什麼是設備描述符呢? Descriptor即描述符,是一個完整的數據結構,可以通過C語言等編程實現,並存儲在 ...
HID是一種USB通信協議,無需安裝驅動就能進行交互,在學習HID之前,先來複習一下USB協議的相關內容。
USB設備描述符-概述
當插入USB設備後,主機會向設備請求各種描述符來識別設備。那什麼是設備描述符呢?
Descriptor即描述符,是一個完整的數據結構,可以通過C語言等編程實現,並存儲在USB設備中,用於描述一個USB設備的所有屬性,USB主機是通過一系列命令來要求設備發送這些信息的。
描述符的作用就是通過命令操作作來給主機傳遞信息,從而讓主機知道設備具有什麼功能、屬於哪一類設備、要占用多少帶寬、使用哪類傳輸方式及數據量的大小,只有主機確定了這些信息之後,設備才能真正開始工作。
USB有那些標準描述符?
USB有5種標準描述符:
- 設備描述符
- 配置描述符
- 字元描述符
- 介面描述符
- 端點描述符
描述符之間有一定的關係,一個設備只有一個設備描述符,而一個設備描述符可以包含多個配置描述符,而一個配置描述符可以包含多個介面描述符,一個介面使用了幾個端點,就有幾個端點描述符。
由此我們可以看出,USB的描述符之間的關係是一層一層的,最上一層是設備描述符,下麵是配置描述符,再下麵是介面描述符,再下麵是端點描述符。
在獲取描述符時,先獲取設備描述符,然後再獲取配置描述符,根據配置描述符中的配置集合長度,一次將配置描述符、介面描述符、端點描述符一起一次讀回。其中可能還會有獲取設備序列號,廠商字元串,產品字元串等。
設備描述符
struct _DEVICE_DEscriptOR_STRUCT
{
BYTE bLength; //設備描述符的位元組數大小
BYTE bDescriptorType; //描述符類型編號,為0x01
WORD bcdUSB; //USB版本號
BYTE bDeviceClass; //USB分配的設備類代碼,0x01~0xfe為標準設備類,0xff為廠商自定義類型,0x00不是在設備描述符中定義的,如HID
BYTE bDeviceSubClass; //usb分配的子類代碼,同上,值由USB規定和分配的,HID設備此值為0
BYTE bDeviceProtocl; //USB分配的設備協議代碼,同上HID設備此值為0
BYTE bMaxPacketSize0; //端點0的最大包的大小
WORD idVendor; //廠商編號
WORD idProduct; //產品編號
WORD bcdDevice; //設備出廠編號
BYTE iManufacturer; //描述廠商字元串的索引
BYTE iProduct; //描述產品字元串的索引
BYTE iSerialNumber; //描述設備序列號字元串的索引
BYTE bNumConfiguration; //可能的配置數量
}
配置描述符
struct _CONFIGURATION_DEscriptOR_STRUCT
{
BYTE bLength; //配置描述符的位元組數大小
BYTE bDescriptorType; //描述符類型編號,為0x02
WORD wTotalLength; //配置所返回的所有數量的大小
BYTE bNumInterface; //此配置所支持的介面數量
BYTE bConfigurationVale; //Set_Configuration命令需要的參數值
BYTE iConfiguration; //描述該配置的字元串的索引值
BYTE bmAttribute; //供電模式的選擇
BYTE MaxPower; //設備從匯流排提取的最大電流
}
字元描述符
struct _STRING_DEscriptOR_STRUCT
{
BYTE bLength; //字元串描述符的位元組數大小
BYTE bDescriptorType; //描述符類型編號,為0x03
BYTE SomeDescriptor[36]; //UNICODE編碼的字元串
}
介面描述符
struct _INTERFACE_DEscriptOR_STRUCT
{
BYTE bLength; //介面描述符的位元組數大小
BYTE bDescriptorType; //描述符類型編號,為0x04
BYTE bInterfaceNunber; //介面的編號
BYTE bAlternateSetting;//備用的介面描述符編號
BYTE bNumEndpoints; //該介面使用端點數,不包括端點0
BYTE bInterfaceClass; //介面類型 HID設備此值為0x03
BYTE bInterfaceSubClass;//介面子類型 HID設備此值為0或者1
BYTE bInterfaceProtocol;//介面所遵循的協議
BYTE iInterface; //描述該介面的字元串索引值
}
端點描述符
struct _ENDPOIN_DEscriptOR_STRUCT
{
BYTE bLength; //端點描述符的位元組數大小
BYTE bDescriptorType; //描述符類型編號,為0x05
BYTE bEndpointAddress; //端點地址及輸入輸出屬性
BYTE bmAttribute; //端點的傳輸類型屬性
WORD wMaxPacketSize; //端點收、發的最大包的大小
BYTE bInterval; //主機查詢端點的時間間隔
}
HID設備描述符
溫習了以上內容,我們再來看看HID協議與這些描述符之間的關係。
當插入USB設備後,主機會向設備請求各種描述符來識別設備。
為了把一個設備識別為HID類別,設備在定義描述符的時候必須遵守HID規範。
從框圖中,可以看出除了USB標准定義的一些描述符外,HID設備還必須定義HID描述符。另外設備和主機的通信是通過報告的形式來實現的,所以還必須定義報告描述符;而物理描述符不是必需的。還有就是HID描述符是關聯於介面(而不是端點)的,所以設備不需要為每個端點都提供一個HID描述符。
設備描述符中:bDeviceClass, bDeviceSubClass, bDeviceProtocol三個值必須為0
介面描述符中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 | bLongItemTag 0:main 1:global 2:local 3:保留 |
data | 數據 |
物理描述符
物理描述符被用來描述設備的行為特性,物理描述符是可選的,HID設備可以根據其本體的設備特性選擇是否包含物理描述符。下表是HID的物理描述符結構。
HID物理描述符的結構
物理描述符用來描述行為特性,是可選的。
偏移量 | 域 | 大小 | 描述 |
---|---|---|---|
0 | bDesignator | 1 | 用來指定本體的哪一部分影響項目 |
1 | bFlags | 1 | 位指定標誌 位0~4:Effort 位5~7:Qualifier |
bDesignator取值含義表
取值 | 含義 | 取值 | 含義 |
---|---|---|---|
0x00 | 無 | 0x15 | 小指 |
0x01 | 手 | 0x16 | 頭 |
0x02 | 眼球 | 0x17 | 肩 |
0x03 | 眉 | 0x18 | 腰骨 |
0x04 | 眼皮 | 0x19 | 腰 |
0x05 | 耳 | 0x1A | 大腿 |
0x06 | 鼻 | 0x1B | 膝蓋 |
0x07 | 嘴 | 0x1C | 小腿 |
0x08 | 上唇 | 0x1D | 足 |
0x09 | 下唇 | 0x1E | 腳 |
0x0A | 顎 | 0x1F | 腳跟 |
0x0B | 頸 | 0x20 | 拇指 |
0x0C | 上臂 | 0x21 | 大拇指 |
0x0D | 手肘 | 0x22 | 第二指 |
0x0E | 前臂 | 0x23 | 第三指 |
0x0F | 手腕 | 0x24 | 第四指 |
0x10 | 手掌 | 0x25 | 小拇指 |
0x11 | 拇指 | 0x26 | 眉 |
0x12 | 食指 | 0x27 | 臉 |
0x13 | 中指 | 0x28~0xFF | 保留 |
0x14 | 無名指 | - | - |
Qualifier取值含義
取值 | 含義 | 取值 | 含義 |
---|---|---|---|
0x00 | 無 | 0x04 | 其中之一 |
0x01 | 右 | 0x05 | 中間 |
0x02 | 左 | 0x06 | 保留 |
0x03 | 同時 | 0x07 | 保留 |
USB HID類可採用的通信管道
所有的HID設備通過USB的控制管道(預設管道,即端點0)和中斷管道與主機通信。
控制管道主要用於以下3個方面:
接收/響應USB主機的控制請示及相關的類數據
在USB主機查詢時傳輸數據(如響應Get_Report請求等)
接收USB主機的數據
中斷管道主要用於以下兩個方面:
USB主機接收USB設備的非同步傳輸數據
USB主機發送有實時性要求的數據給USB設備
從USB主機到USB設備的中斷輸出數據傳輸是可選的,當不支持中斷輸出數據傳輸時,USB主機通過控制管道將數據傳輸給USB設備。
表1、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有不同的意義 |
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 | 無 |