天天看點

USB/HID裝置報告描述符詳解

USB/HID裝置報告描述符詳解

轉載自:http://www.lupaworld.com/273398/viewspace-130320.html

USB描述符即USB裝置的資訊,系統裝置列舉所要執行的工作之一,即是取得這些有關于設各的相關資訊,之後裝置才能被系統識别使用。

USB/HID裝置報告描述符詳解

在圖的描述符中,裝置描述符(device descriptor)、配置描述符(configurationdescriptor)、接口描述符(interface  descriptor)以及端點描述符(endpoint descriptor)是必須具有的。而其他的描述符,如字元串描述符(strtng descriptor)、 數種不同的群組描述符(class descriptor)以及報告描述符(report descriptor)則可以根據不同的裝置加以添加或删減。

報告描述符是HID用來 資料傳輸(data transfer),是對這些傳輸的資料作用途(usage)上的說明。

USB通訊協定的規範是以1ms産生一個USB幀(frame),USB裝置可以每一個幀中發送和接收一個交換(transaction)。交換是由幾個封包(packet)組成,而傳輸是由一個或幾個交換來完成傳送一口中有效的資料。在這裡,傳輸和報告的意思相類似。   傳輸方式有四種,初始學一般隻要了解控制型傳輸(control transfer)和中斷型傳輸(interrupt transfer)即可。控制型傳輸是當需要時才執行傳輸要求,是最一般的傳輸方式,組态、指令和狀态的通訊都可以使用控制型傳輸;控制型傳輸主要用于消 息型資料(message-type data)。中斷型傳輸目的在做重複的資料更新(recurring data)傳輸,精确一點而言,即是在每個有限有周期内(bounded period)作至少一次的小量資料發送或接收;是以适用于流動型資料(stream-type data),注意這裡所謂的周期時間就是在端點描述符中的輪詢間隔時間。   報告有三種:input,output,和Feature.後面将作進一步介紹。中 斷型輸入管線(interrupt in pipe)僅可以傳送input報告;中斷型輸出管線(interrupt out pipe)僅可以傳送output報告;但是控制型管線(control pipe)可以傳送input,output和feature報告。端點描述符有聲明所使用的端點為何種管線。   資料本身沒有任何意義,要賦于用途才能明确其為控制什麼(control);例如設 備上的按鈕訓示燈和X與Y軸的位移等都通稱控制,資料則為按鈕和訓示燈的開關狀态或X與Y軸的位移量。為了這個目的應運而生報告描述符,其将資料的操控與 它的用途作一對一的對應,是以解讀報告後就可以知道每個資料作何種操作。是以“傳輸的資料”和“操作”隻是一事件的兩種描述方式。用途是以一個32位卷标 (稱作usage tag)來表示,高16位稱作usage page(用途類頁),低16位稱為usage ID(用途識别名): Usage = (usage page:usage ID)   舉例說明:二個位元組分别為x和y軸的位移資料,是以第一個位元組的usage= (generic desktop:X),而第二個位元組的usage = (generic desktop:Y),其中generic desktop為用途的大類别(稱作用途類頁)之一,x和y軸的操作用途屬于此用途類頁。檔案universal serial Bus HID Usage Table完整列出所有的usage pages(用途類頁)和usage ID(用途識别名),使用者必須遵照檔案的規範來聲明操作的用途。該檔案的附錄A有十多個報告描述符的範例,值得研究下。   表1、報告描述符的标簽

主項目 全域項目 區域項目
标簽 代碼 标簽 代碼 标簽 代碼
Input X08? Usage Page 0x0? Usage 0x0?
Output 0x9? Logical Minimum 0x1? Usage Minimum 0x1?
Feature 0x0b? Logical Maximum 0x2? Usage Maximum 0x2?
Physical Minimum 0x3? Designator Minimum 0x3?
Collection 0xa1 Physical Maximum 0x4? Designator Minimum 0x4?
End Collection 0xc0 Unit Exponent 0x5? Designator Maximum 0x5?
Unit 0x6? String 0x7?
Report Size 0x7? Sreing Minimum 0x8?
Report ID 0x8? String Maximum 0x9?
Report Coumt 0x9? Delimiter 0xa?
Push 0xA?
Pop 0xb?

  标簽: 用途卷标隻是報告描述符諸多标簽的一個。表1列出所有的卷标,利用這些卷标取可以清 楚完整的描述符操作的用途。報告描述符的文法不同于USB标準描述符,它是以項目(items)方式排列而成,無一定的長度;項目有一個前辍 (prefix),然後跟着一個括号,内為該項目的資料:item = prefix(data)。   項目分成三種類别:主項目,全局項目,區域項目。主項目中的input,ouput,feature三個卷标用來表示報告中資料的種類,這些是報告描述符中最主要的項目,其他項目都是用來修飾這三種項目。主要項目中其他二個卷标後面再作詳細的介紹。   >> Input 項:表示裝置操作輸入到主機的資料模式。這個資料格式就形成一個輸入報告,雖然輸入報告可以用控制型管線以get report(input)來傳輸,但是通常用中斷型輸入管線來傳輸以確定在每一固定周期内都能将更新的輸入報告傳給主機。 >> Output 項:表示由主機輸出到裝置操作的資料格式。這個資料格式就形成一個輸出報告。輸出報告通常不适用輪詢的方式來傳送給裝置,而是由應用軟體依實際需求以傳令 方式要求送出輸出報告,是以大多用控制型管線以set report(output)指令來将報告送到裝置。當然也可以選擇用中斷型輸出管線來傳送,隻是通常不建議這樣用。 >> Feature項:表示由主機送到裝置的組态所需資料的資料格式。這個資料模式就形成一個特征報告。特征報告隻能用控制型管線以get report(feature)和set report(feature)指令分别來取得和設定裝置的特征值。 >> 範 例:考慮一個2X16字的顯示裝置,它的列數、行數、字寬、和字高為固定值屬于feature報告;顯示狀态例如“就緒”和“輸入字錯誤”則屬于 input報告;光标位置和顯示的字需可讀寫,是以屬于另一個feature報告;更新顯示的字則為output報告。為了差別兩個deatures,要 用到全局項目中的report ID,每個feature報告有一個不同的report ID,因而主機請求指令要加上report ID的值:get report(feature,report ID)和Set report(feature,report ID)。   主項目用來定義報告中資料的種類和格式,而說明主項目之意義與用途為全局 項 目和區域項目。顧名思義,區域性項目隻能适用于列于其下的第一個主項目,不适用于其他主項目,若一個主項目之上有幾個不同的卷标的區域性項目,則這些區域 性項目皆适用于描述該主項目。相反,全局性項目适用于其下方的所有主項目,除非另一個相同卷标的全局性項目出現。為了清楚說明報告描述符,将使用“項目狀 态表”(item state table)用來表示在某位址處适用的全局性項目的組合。圖1顯示全局性項目和區域性項目與所描述的主項目之對應關系。   區域性項目卷标: 簡單地說,區域性項目(見表1)隻是說明用途而已。Designator是要搭配實體描述符使用的,這裡不對實體描述符進行介紹,是以略過這些designator标簽。   标簽Usage 實際上應該稱作Usage ID,它搭配全域項目的Usage Page 卷标才形成前文所定義的用途{usage}﹔但是報告描述符允許在區域項目的Usage 卷标直接用32位的方式來指定用途,這種方式稱作擴充式用途指定法(extended usage)以示差別。   例如:Usage(Generic Desktop:Mouse),Usage Minimum(Keyboard:0),和Usage Maximum(Keyboard:101)。很明顯的,擴充式用途指定法會取代『項目狀态表』中的Usage Page。還有,使用擴充式用途指定法時,資料的高16 個位為用途類頁Usage Page,低16 個位則為用途識别名Usage ID。往往一個報告資料會對應到幾個操作,因而會有幾個用途,例如101 按鍵的鍵盤利用不同代碼代表不同的鍵,每一個鍵是一個操作,有自己的用途,要将所有Usage ID 列出不太現實,是以就需要Usage Minimum 和Usage Maximum 二個标簽。以鍵盤為例,主項目之上隻要二個區域項目:Usage Minimum (0), Usage Maximum (101)。如此一來,則無鍵按下(Usage ID 為0)和101 鍵中任一鍵被按下(Usage ID 為1 至101)的用途都被賦于到一個報告資料上,後面會有一個範例進一步解說。   卷标String Index 類似卷标Usage,而卷标String Minimum 和String Maximum 則類似标簽Usage Minimum 和Usage Maximum。如果希望某個操作對應到一個字串,則用String Index 來描述該操控的報告資料,這個字元串在字元串描述符中,StringIndex (data)項目中的data 是這個字元串在字元串描述符中的位置索引。如果需要用到幾個字元串,則可以使用String Minimum 來指向字元串描述符中被用到字元串的最先位置索引,和String Maximum 來指向最後位置索引。   标簽Delimiter 很少用到,請參考Universal Serial Bus HID Usage Tables 檔案中Appendix B 的範例詳細說明。

全局項目卷标 全局項目的卷标事實上隻要Usage Page,Logical Minimum,Logical Maximum, Report Size,Report ID,Report Count 就足夠了。表2 列了二個音量操作的例子(音量增減鍵和音量旋鈕)将用來輔助說明這些卷标,不過主項目括号内的資料會在後文中再做說明。 表2、音量操作舉例

音量減鍵 音量旋鈕
Usage Page(consumer) Usage Page(Consumer)
Usage(Volume) Usage(Volume)
Logical Minimum(-1) Logical Minimum(0)
Logical Maximum(-1) Logical Maximum(100)
Report Size(2) Report Size(7)
Report Count(1) Report Count(1)
Input(Data,Variable,Relative) Input(Data,Variable,Absolute,No Wrap,Linear,No Relative)

  查閱Universal Serial Bus HID Usage Tables 文 檔,這兩個例子的用途需要令為(Consumer: Volume)。Usage Page 前面已經介紹過了。   Report Size 用來設定主項目(Input,Output,Feature)的報告字段大小,它的機關是位。主項目會對每個操作産生一個報告字段,字段大小則由 Report Size 決定。   而Report Count 用來設定主項目之報告字段的數目,其等于操作的數目。音量增減鍵的例子中ReportCount (1)表示主項目Input 隻産生一個字段,是以可知隻有一個音量增減鍵﹔而Report Size (2)表示這個字段為2 位。另一個音量旋鈕例子也是隻有一個旋鈕,是以用Report Count (1)﹔但是因為Report Size (7),是以該旋鈕的資料字段為7位,可以表示0到127之數值。再舉一例,如果是滑鼠的三個按鍵,每個按鍵占用一個一位的字段,則Report Size (1), Report Count (3)﹔那麼這個報告長度為三個位,可以同時呈現出三個按鍵的狀态(原狀或被按下)。   Logical Minimum 和Logical Maximum 在說明每個報告字段的數值範圍,這是純數值是以稱為邏輯數值(logical value)。音量增減鍵的例子中Logical Minimum (-1),Logical Maximum (1)表示隻會出現-1, 0, 1 三種數值,是以用到二位(即ReportSize(2)),0b11 代表-1,0b00 代表0,0b01 代表1。在音量旋鈕例子中,雖然用7 位作一字段,但是旋鈕僅會産生0 到100 的數值,因為Logical Minimum (0)和Logical Maximum (100)。假如實體程式錯誤産生超出邏輯數值的範圍,則主機将會忽略該數值,這種數值稱作null value。   當要将同一種報告分成數個部分,則每一個部分要給予一個識别值,這時就需用到卷标 Report ID,其資料值必須從1起算,不可使用0。沒有賦予Report ID 标簽的報告,主機有可能會将其Report ID 視為0,是以Report ID (0)被要求不能使用。這個标簽對控制型管線才有意義,因為它可以在請求報告時指定Report ID的值。對于中斷型管線,其為周期性傳輸報告,是以每次都會将所屬報告傳完,沒有僅傳輸部分之必要,是以Report ID 标簽就無意義。   其它的全局項目卷标可分為輔助工具(Push 和Pop)和實體量說明(Physical Minimum,Physical Maximum,Unit Exponent,和Unit)。Push 卷标将『項目狀态表』存放到緩存器(stack),而Pop 卷标反過來将緩存器最頂層的『項目狀态表』取回來取代目前之狀态表。這二個标簽對很長的報告描述符才有用處,因為其可以節省多列一些全局項目。讀者當要使 用到時,參考Universal Serial Bus HIDUsage Tables 檔案的Appendix A.7 節中範例則可獲得正确使用方式。   不同廠家的滑鼠有不同的分辨率,若要讓主機知道滑鼠的分辨率,就必須用到實體量的标簽。不使用也不會影響到滑鼠的功能,隻是使用者無法由主機的驅動程式得知分辨率而已。但是量測裝置(例如溫度計)的應用程式必須知道實體量,則這些标簽就必備了。分辨率r 的算法如下      r = ((lM-lm)/(PM-Pm))X10i Unit 其中lm = Logical Minimum,lM = Logical Maximum, pm = Physical Minimum,pM = Physical Maximum, i = Unit Exponent。以400-dpi 的滑鼠為例如表3。 表3:解析度的範例

Logical Minimum(-127) R = ((127-(-127))/(3175-(-3175))X10 -4 = 400counts per inch
Logical Minimum(127)
Physical Minimum(-3175)
Physical Minimum(3175) 給定Logical值,計算出physical值: ((PM-Pm)/2)/10 i =((127-(-127))/400)/2=0.3173 à|PM|=|Pm|=3175,i=4
Unit Exponent(-4)
Unit(inch)

注意,若是Unit Exponent 未定義,則視為i = 0﹔若是Physical Minimum和Physical Maximum有一個以上未定義,則視為PM=lM 和pm=lm 。 是以标簽Physical Minimum和Physical Maximum 一定要同時定義,否則無意義。這些卷标的括号内數字為有符号的整數,可以是一個位元組或二至四個位元組,位元組數目會在卷标代碼的最低二位定義,詳情後文會叙 述。卷标Unit 的括号内資料比較複雜,總共用了7 個四位(nibbles)來描述,各個四位之意義如表4,其中第8 個四位 未被使用到。   表4:标簽Unit的資訊格式

Nibbe 7 6 5 4 3 2 1
Luminous Intensity Current Temperature Time Mass Length System

HID 共享了四種機關系統,最低的四位就是決定使用的機關系統(System),不同的系統中當然實體量的機關也不一樣。機關和系統間的對應關系如表5。 表5:實體量的機關之編碼法

None SI Linear SI Rotation English Linear English Rotation
System 0x0 0x1 0x2 0x3 0x4
Length None 公分 徑度 英寸 角度
Mass None 公克 公克 Slug Slug
Time None
Temperature None 凱氏(絕對溫度) 凱氏(絕對溫度) 華氏 華氏
Current None 安培 安培 安培 安培
Luminous intensity None Candela Candela Candela Candela

除了最低四位的值用來選擇機關系統外,其餘每個四位皆表示該機關的幂次方,每個四位(nibble)都是有符号的整數,可表示的範圍為-8 至+7:

-8 -7 -6 -5 -4 -3 -2 -1 1 2 3 4 5 6 7
08h 09h 0ah 0bh 0ch 0dh 0eh 0fh 00h 01h 02h 03h 04h 05h 06h 07h

是以長度的機關若為公分則Unit (data)中data 的碼為0x11,若為英吋則為0x13,這二者中Length 的四位值皆為1 表示幕次方為1,即cm1 或in1 。品質機關為公克之碼為0x0101,加速度機關為公分除以平方秒之碼為0xE011,其中E 代表-2。是以力量機關為品質(公克)乘于加速度(公分/平方秒)的碼為0xE111。能量機關焦爾為力量乘于長度之碼為0xE121,其等義于s?2g cm2 和機關系統為SI Linear。   主項目 主項目中産生報告資料格式的三個卷标(Input,Output,和 Feature)具有共通的資料定義,這些資料和其代碼列于表6中。   目前用到9個位來表示這些資料。如果第九位(bit 8)為0,則僅需用一個位元組來表示該資料,即忽略第九位。如果第九位為1,就需用到二個位元組來表示該資料。   表6:主項目的資訊代碼

Bit 8 7 6 5 4 3 2 1
Bit Field Non Volatile No Null Position Preferred State Linear No Wrap Absolute Array Data
1 Buffered Bytes Volatile Null State No Preferred Non Linear Wrap Relative Variable Constant

Data/Constant:主項目之資料為可變值(設為Data),或為固定不可變值(設為Constant)。Constant 都用于Feature 的報告,或是用于填充位(padding),使報告長度以位元組為機關。   Array/Variable:主項目之資料的每個字段可以表示幾個不同的操作的其 中一個被觸發(設為Array),或是每個字段僅表示一個操作(設為Variable)。如果是Variable,則Report Count 的資料值等于報告資料的字段數。若是Array,則Report Count 的資料值表示可以同時被觸發的最多操作數目。後文中鍵盤之例會解說Array 的用法。   Absolute/Relative:主項目的資料是以相對于固定的基準點方式提供絕對數值(設為Absolute),或是提供相對于前次報告的相對值(設為Relative)。   【範例說明】前文中的音量操控範例,因為都是Data 和Variable,二者的操作值皆為變化值,且一個字段僅表示一個操作。但是音量增減鍵的例子為Relative,是以若報告值由0 變成+1,則音量增大一個刻度,反之由0 變作-1 則音量減小一個刻度,因而音量大小因輸入值而作相對的變化。然而音量旋鈕的例子為Absolute,當輸入值為最小值0 時,為靜音,而輸入值為最大值100 時,為最大音量,其餘值作百分比的音量調整,輸入值和音量成絕對關系。   No Wrap/Wrap:主項目的資料值達到極值後會轉為極低值,反之亦同,稱作卷繞(設為Wrap)。例如一個轉鈕可以做360°旋轉,輸出值從0 至10,若設定為Wrap,則值達10 後,在同方向旋轉則值變為0,反之若達到0,再轉就得到10。   Linear/Nonlinear:主項目的資料與操作刻度為線性關系(設為Linear),或為非線性(設為Nonlinear)。   Preferred State/No Preferred:主項目對應的操作再不被觸發時會自動恢複到初始狀态(設為Preferred State),或是不會恢複原狀(設為No Preferred)。例如鍵盤的按鍵和會自動置中(self-centering)的遊戲杆,皆為Preferred State。   【範例說明】再以音量操作為例,音量增減鍵的例子都沒标注No Wrap,Linear,Preferred State,但是沒有标注即認定其屬于預設值,是以等同于是這些設定,隻是這些設定對此例的操作無意義,是以不标出。音量旋鈕的例子明确指出其為No Wrap, Linear, No Preferred,可見旋鈕不是循環旋轉,輸出值與旋轉角呈線性關系,旋鈕釋放開時會停留在釋放前位置(因為No Preferred)。   No Null Position/Null State:主項目對應的操和有一個狀态,其不會送出有意義的資料,即資料将不在Logical Minimum 和Logical Maximum 之間,這種操控要标注Null State,否則為No Null Position。例如幾個按鍵,而無鍵被按下的用途沒有聲明在Usage 之列,則可以在主項目的資料中設Null State,将無鍵被按下的狀态排除在Logical Minimum 和Logical Maximum區間之外,進一步請參看Universal Serial Bus HID Usage Tables 檔案的Appendix A.3 節中範例。   Non Volatile/Volatile:主項目Feature 的資料不允許被主機改變(設為Non Volatile),或是允許被主機改變(設為Volatile)。注意主項目Input 和Output,此标注設定無意義,是以bit 7 的代碼必須為0。   Bit Field/Buffered Bytes:主項目的資料格式要以位元組為機關,不足構成位元組時自動填充成位元組則設Buffered Bytes。   最後來談談主項目的其它二個卷标:Collection 和End Collection。以滑鼠而言,在實體上是一個指針(pointer),隻是應用為計算機滑鼠﹔而這個指針含有三個按鍵和二個平移軸X 和Y。是以指針的報告是由不同格式的資料所構成,因而需要用到Collection 和End Collection 将幾個Input 項目集結成一組,其用途為指針,再用Collection 和End Collection 将指針括起來說明其應用為滑鼠。   卷标End Collection 沒有跟随任何資料。但是卷标Collection 跟随一個位元組的資料,例如指針的資料名為Physical,而滑鼠的為Application。所有Collection的資料名稱與代碼如表7: 表7:報告集合的名稱與代碼

Physical Application Logical Report Named Arrary Usage Modifier Usage Switch Reserved Vendor-defined
代碼 0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07-0x7f 0x80-0xff
用途 CP CA CL Nary US UM

Collection 的資料名稱很難有一個準則來給定,Universal Serial Bus HID Usage Tables 文 檔 中将各種用途的用途種類(usage type)列出,使用者必須依據用途種類來指定Collection 的資料名稱,例如滑鼠,鍵盤和遊戲杆的用途種類為CA,是以要用Collection (Application),而指針為CP,是以用Collection (Physical)。   編碼 報告描述符的項目編碼有二種:短項目和長項目。長項目僅是保留給未來使用,是以不作介紹。短項目的編碼形式如下: Bits 23 22 21 20 19 18 17 16  15 14 13 12 11 10 9 8  7 6 5 4         3 2         1 0

[data] [data] bTag bType bSize

Bytes        2                    1                        0   最低位元組分别标注項目大小(bSize),項目類别(bType),和項目卷标(bTag)﹔ 其中bTag 占4個位,其餘二者各占2個位。BSize 用來指出項目的資料所需位元組的數目,該數目僅可以為0(當bSize=0),1(當bSize=1),2(當bSize=2),和4(當 bSize="3")﹔注意不可以為3個位元組。大部分的卷标僅需一個位元組的資料﹔全局項目的卷标Unit 比較特殊有可能最多用到4 個位元組來表示其資料。 标簽代碼bTag 已經于前章的表1 中描述,例如Input 的标簽代碼『0x8?』中8 即為bTag 之值﹔再如标簽Feature 之bTag=11,而Unit 之bTag=6。主項目之bType=0,全局項目之bType=1,而區域項目之bType= 2。是以在前章的表1 中的主項目卷标代碼中的『?』可以改為『00nnB』,全局項目的可以改為『01nnB』,而區域項目的可以改為『10nnB』,其中nn 代表bSize。   實際範例 這裡舉一個Device Class Definition for Human Interface Device 文 件的附錄E 中的整合滑鼠的鍵盤裝置的範例。這個裝置隻有一個組态描述符,但是這個組态具有二個接口,一個為鍵盤接口(接口編号為0x00),另一個為滑鼠接口(接口 編号為0x01)。每一個接口都有一個自己的中斷型輸入端點,輸出則都靠内定的控制型端點0。這個整合滑鼠的鍵盤裝置的标準描述符,請參考附件中的 『USB 标準描述符之技巧』檔案。在該文中所使用的範例即為整合滑鼠的鍵盤裝置,隻是僅列出一個接口描述符(即編号為0x00 的鍵盤接口),另一個編号為0x01 的滑鼠接口在該文中沒有列出,讀者可以自行參考本文所附的描述符程式代碼descriptor.asm(即在标記為 interface_descriptor01,hid_descriptor01,和endpoint_descriptor01 處)。   表8:範例的輸入報告格式

鍵盤(輸入報告) 滑鼠(輸入報告)
Byte 7 6 5 4 3 2 1 Byte 7 6 5 4 3 2 1
Modifier keys Pad Buttons
1 Reserved 1 X displacement
2 Keycode 1 2 Y displacement
3 Keycode 2
4 Keycode 3
5 Keycode 4
6 Keycode 5
7 Keycode 6

表9:範例的輸出報告格式

鍵盤輸出報告
Byte 7 6 5 4 3 2 1
Pad LED’s

這個範例有輸入報告和輸出報告,其中輸入報告有二組,一組屬于鍵盤接口,另一組屬于 滑鼠接口。表8 列出輸入報告的資料格式。而輸出報告隻有鍵盤接口需要,表9 為輸出報告的資料格式。因為有二個接口,是以有二個報告描述符,分屬于不同的界面,二個報告描述元都列于表10 中。鍵盤的報告描述元中整個報告集合的用途為(Generic Desktop: Keyboard),由于鍵盤用途屬于應用性,是以标簽Collection 的資料名為Application。由于單獨鍵本身的用途類頁不再是Generic Destop,而是Keyboard(注意Keyboard 也可為用途類頁),是以在項目Collection(Application)下重新聲明用途頁Usage Page (Keyboard)。根據Universal Serial Bus HID Usage Tables 文 件,滑鼠是指針的一種,隻是應用為計算機的滑鼠,是以報告的内層集合的用途為(Generic Desktop: Pointer),外層的應用性集合的用途為(Generic Desktop: Mouse)。注意滑鼠的按鈕和位移軸又分屬不同的用途類頁,是以在内層集合中還要重新聲明用途類頁。按鈕的用途類業為Buttons,而二個位移軸所屬 的用途類業為Generic Desktop。   表 10 :報告描述符範例

鍵     盤 鼠      标
項  目 編 碼 項   目 編 碼
Usage Page (Generic Desktop), 0x0105 Usage Page (Generic Desktop), 0x0105
Usage ( Keyboard ), 0x0609 Usage ( Mouse ), 0x0209
Collection (Application), 0x01A1 Collection (Application), 0x01A1
Usage Page (Keyboard), 0x0705 Usage ( Pointer ), 0x0109
Usage Minimum (224), 0xE019 Collection (Physical), 0x00A1
Usage Maximum (231), 0xE729 Usage Page (Buttons), 0x0905
Logical Minimum (0), 0x0015 Usage Minimum (1), 0x0119
Logical Maximum (1), 0x0125 Usage Maximum (3), 0x0329
Report Size (1), 0x0175 Logical Minimum (0), 0x0015
Report Count (8), 0x0895 Logical Maximum (1), 0x0125
Input (Data, Variable, Absolute), 0x0281 Report Size (1), 0x0175
Report Size (8), 0x0875 Report Count (3), 0x0395
Report Count (1), 0x0195 Input (Data, Variable, bsolute), 0x0281
Input (Constant), 0x0181 Report Size (5), 0x0575
Usage Minimum (0), 0x0019 Report Count (1), 0x0195
Usage Maximum (101), 0x6529 Input (Constant), 0x0181
Logical Minimum (0), 0x0015 Usage Page (Generic Desktop), 0x0105
Logical Maximum (101), 0x6525 Usage (X), 0x3009
Report Size (8), 0x0875 Usage (Y), 0x3109
Report Count (6), 0x0695 Logical Minimum (-127), 0x8115
Input (Data, Array), 0x0081 Logical Maximum (127), 0x7F25
Usage Page (LEDs), 0x0805 Report Size (8), 0x0875
Usage Minimum (1), 0x0119 Report Count (2), 0x0295
Usage Maximum (5), 0x0529 Input (Data, Variable, Relative), 0x0681
Logical Minimum (0), 0x0015 End Collection, 0xC0
Logical Maximum (1), 0x0125 End Collection 0xC0
Report Size (1), 0x0175
Report Count (5), 0x0595
Output (Data, Variable,Absolute), 0x0291
Report Size (3), 0x0375
Report Count (1), 0x0195
Output (Constant), 0x0191
End Collection 0xC0

  從表8 看出,鍵盤的輸入報告中最低的8位分别代表鍵盤上的8個修飾鍵(亦即左和右邊的Control 鍵、Shift 鍵、Alt 鍵、和Windows 鍵),平常每位的值為0,當對應的修飾鍵被壓下時則位值為1。鍵盤報告描述符中第一個Input 項目必須聲明這8位的格式。這8個修飾鍵為用途類頁Key Codes 中的第224 個鍵到第231 鍵,是以用Usage Minimum (224)和Usage Maximum (231)來聲明。每一個按鍵的邏輯值不是0 就是1,是以用Logical Minimum(0)和Logical Maximum (1) 來聲明。   很顯然的,每一個鍵占用一個資料位,而共需8個位,是以 ReportSize ( 1),而Report Count (8)。請特别注意,最低位對應到Usage Minimum 的聲明,而最高位所對應的為Usage Maximum 的資料内容。這8 個位值是可變的資料,每一個位是獨立的變量,提供的值不須與前次的值有相對關系。總結而言,該8位的主項目必須為Input (Data, Variable, Absolute)。   鍵盤的輸入報告中次高的位元組被保留,該位元組的值無意義,也不需更新,是以用 Input (Constant)來填充(padding)。而最高的6 個位元組則是最近同時被壓下的6 個按鍵之代碼。這個鍵盤裝置有101 個鍵,而報告格式的最高的6 個位組中任何一個位元組都可以代表101 個鍵之任一鍵,是以這101 鍵再加上無鍵被壓下狀态(代碼為0x00)構成一組操作數組,這個裝置允許同時壓下6個鍵。   鍵盤報告描述符中Input (Data, Array)即在聲明這6個位元組的資料格式,注意這個資料格式的邏輯值聲明和用途代碼聲明具有相同的資料值(即0 和101)。 鍵盤有一個輸出報告,長度為1個位元組,但是隻用到最低5個位來代表五個LED 的操控,是以最高的3個位需要用Output (Constant)項目來填充。輸出報告的用途類頁不再是Key Codes,而是Page of LEDs,是以要重新聲明Usage Page,而主項目為Output (Data, Variable, Absolute)。這個項目的資料内容如同輸入報告的最低8位所聲明的主項目之資料内容,不再作說明。因為鍵盤接口的端點描述符隻有聲明一個中斷型輸入 端點,是以輸出報告需要依賴内定控制型端點0來傳送。輸入報告由聲明的輸入端點作中斷型輸入傳輸,當然也可以依需要用内定控制型端點0來作控制型讀入傳 輸。   滑鼠的報告描述符的輸入資料格式中最低的一個位元組隻有最低3個位有意義,其分别對應 到滑鼠上的三個按鈕,用途類頁為Buttons。其它二個位元組的用途為(Generic Desktop: X)和(Generic Desktop: X),分别對應到滑鼠X 軸和Y 軸的位移操控。這二個位移值得邏輯範圍為-127 到127,即一個位元組可以表示最大範圍。位移的數值是相對值,是以主項目為Input (Data, Variable, Relative)。   HID 描述符編輯工具 USB 協會提供了一個HID 描述符編輯工具稱作HID Descriptor Tool,其執行程式為DT.exe。這個工具軟體可以在USB 網站上取得。雖然稱作HID 描述符工具,事實上,僅提供編撰報告描述符之用。執行DT.exe 後會出現如圖2 之視窗,小内視窗HID Items 列出所有報告描述符的标簽。以前面所舉的實際範例中鍵盤的報告描述符為例,首先點選[USAGE_PAGE],後會出現一個次視窗列出所有的Usage Page 的選項,這個例子要選[Generic Desktop],按[OK]後則次視窗消失,DT 的主視窗中的右邊小内視窗Report Descriptor 就出現Usage Page(Generic Desktop)并跟随着該項目的編碼05 01(低位元組在左邊),也就是這個工具可以幫助作自動編碼的工作。   程式員隻要輸入項目的卷标和内容,則可以由這個工具軟體提供報告描述符的程式代碼。 接着,當點選第二個項目[USAGE]時,DT 軟體會根據前面的編簽Usage Page 的内容Generic Desktop,而産生一個次視窗列出Generic Desktop 包含的所有Usage 選項。同樣道理,當選完Usage Page (Keyboard), 再要編撰Usage Minimum 和Usage Maximum 時,所出現的次視窗則為Usage Page (Keyboard)所包含的全部Usage 選項,選第224 個為Left Control鍵當用途範圍的最小者,再選第231 個為Right GUI 鍵當用途範圍的最大者。其他項目的編撰以此類推。   在主視窗下,點選下拉選項[File]中的[Info],則會出現訊息視窗,告知編 撰的描述符中項目的個數和描述符長度所需位元組的數目。編撰報告描述符完成後,還要做文法檢驗,這時點選下拉選項[Parse Descriptor],則DT 軟體會告知檢查的結果,并提供錯誤原因與更改的建議。  

USB/HID裝置報告描述符詳解

  總結 最後一個問題是如何将報告描述符加入微控器的彙程式設計式。對于任何一種描述符,都是以 彙編語言中的一個标記來分辨,例如第一個接口的報告描述符的标記就稱作hid_report_descriptor00;同樣的,第二個界面的就稱作 hid_report_descriptor01。記得在報告描述符結束處也加上一個标記,如end_hid_report_descriptor00 和end_ hid_report_descriptor01。這個結束标記除了有助于閱讀程式外,其最主要的用處是可以用來計算描述符的長度(即位元組數)。例如使用 dwl end_hid_report_descriptor00 - hid_report_descriptor00組譯器就會自動算出第一個報告描述符的長度,這個長度以二個位元組來記載。“dwl”為彙編語言的訓示,在 于儲存二個位元組的資料,儲存的方式為little Endian。所謂little Endian 方法,就是将低位元組的值存于低位址值的記憶體空間,高位元組之值存于高位址值處。

繼續閱讀