報告描述符(Report Descriptor),由設備端(Device)描述給主機端(Host),后續(xù)設備端通過中斷端點發(fā)送的數據的用途(Usage)說明或稱描述數據格式及意義。它在連接建立初期就發(fā)送給主機端,主機端依據報告描述符去解析來自中斷端點的數據。簡單來說,報告描述符就是描述連接建立之后,設備端發(fā)送給主機端的數據幀中每一字節(jié)(bytes)每一位(bits)所代表的意義。
要想了解HID設備描述符,不得不去細讀一下官方的兩個文檔,可以到官方下載:《Device Class Definition for human interface device (HID)》《Universal Serial Bus HID Usage Tables》這兩份文件,其中一份是HID 協(xié)議,另一個是HID報告描述符(USAGE_PAGE & USAGE)的內容定義。報告描述符的直管組織結構為:
HID報告描述符的解析器就是按照上面這個組織形式,一層一層的進行解析的。一個報告描述符可以由多個Report組成,當超過1個Report時,需要用collection去組合,collection可以嵌套collection,每個Report都可以有多個用途(Usage).其它Main item/Report size/Report count/Logical minium等都是用于修飾Usage。
我們把一個HID的報告描述符比喻成一個公司,那么Collection就是一個部門,部門可以嵌套部門,部門里面有很多人,這里的人就是描述符中的Report,而Usage就是這個人身上的技能。對于單獨的report,可以認為他就是一個光桿司令。
鼠標的報告描述符
uint8_t report_desc[] =
{
0x05, 0x01, //USAGE_PAGE (Generic Desktop)
0x09, 0x02, //USAGE (Mouse)
0xa1, 0x01, //COLLECTION (Application)
0x85, 0x01, //REPORT_ID (1)
0x09, 0x01, //USAGE (Pointer)
0xa1, 0x00, //COLLECTION (Physical)
0x05, 0x09, //Usage Page (Buttons)
0x19, 0x01, //Usage Minimum (01)
0x29, 0x03, //Usage Minimum (03)
0x15, 0x00, //Logical Minimum (0)
0x25, 0x01, //Logical Minimum (1)
0x95, 0x03, //Report Count (3)
0x75, 0x01, //Report Size (1)
0x81, 0x02, //Input (Data, Variable, Absolute)
0x95, 0x01, //Report Count (1)
0x75, 0x05, //Report Size (5)
0x81, 0x01, //Input (Constant)
0x05, 0x01, //USAGE_PAGE (Generic Desktop)
0x09, 0x30, //USAGE (x)
0x09, 0x31, //USAGE (y)
0x15, 0x00, //Logical Minimum (0)
0x26, 0x38, 0x04, //Logical Minimum (1080)
0x75, 0x10, //Report Size (16)
0x95, 0x03, //Report Count (2)
0x81, 0x02, //Input (Data, Variable, Relative)
0xc0, //END_COLLECTION
0xc0, //END_COLLECTION
};
上面的代碼是一個鼠標的報告描述符,看起來他就是一個大數組,為什么按照兩列來排列呢?這是由于他的結構導致的,這樣寫出來比較利于人來閱讀。他的每一行都是一個條目,其結構形式為:條目標簽(item tag) + 條目數據(item data)。
短條目
比如第一行的 0x05,0x01, 其中條目標簽就是0x05,數據就是0x01。在上面的這一個條目中,Tag大小固定,短條目(short item)為1Byte,長條目(long item tag)為3Byte(長條目不常用,暫時研究了)。對于一個短條目(short item),其 item tag部分又分三個部分:標簽(Tag)、數據大小(DataSize)和類型(type),bSize(2bits) + bType(2bits) + bTag(4bits) = 1byte。
bSize:描述數據內容的大小,占2bit,可以表示0-4個字節(jié)。bType:描述條目類型,占2bit,共3個選項以及1個保留項
b00 = Main (主要類型)
b01 = Global (全局類型)
b10 = Local (局部類型)
b11 = Reserved (保留)
bTag:描述各條目類型下的各細分條目,占4bit,最多15個選項。接下來,我們分別看Main,Global和Local三種類型。
短條目bTag選項 - Main項標簽
下面是對短條目的一個描述列表
Input/Output/Feature
Input/Output/Feature具有相通的選項數據定義(input/output都是相對主機端而言的)Input(e.g. 0x81 , 0x**),輸入報告 ,是設備端將設備操作發(fā)送到主機,這種報告通常通過中斷端點發(fā)送到主機,以此保障一個固定周期的輸入報告,它也可以控制端點的get report(input)來傳輸。Output(e.g. 0x91, 0x**),輸出報告,是主機端將軟件需求發(fā)送給設備,輸出報告通常以控制端點的set report(output)來傳輸,只需要響應軟件的實際需求即可,它也可以使用中斷端點來傳輸數據。Feature(e.g.0xb1, 0x**),特征報告,是主機端發(fā)送到設備端的數據組態(tài)格式,特征報告只能以get report()/set report()來獲取或設置設備的特征值。
Input、Output、Feature項可選值表
常用的是bit0和bit1兩個選項。比如上面鼠標報告符中的:0x81, 0x01, //Input (Constant) ?,其中0x01就表示bit0被置1了。
Collection/End Collection組合
項目實際應用中,一個設備通常不止一個功能點,以上述鼠標示例為例,具有3個按鈕(左鍵、右鍵、中鍵),X/Y軸方向位移,滾輪等。它們各自具有不同的數據格式,聚集組成鼠標各個功能,此時我們需要Collection/End Collection去集合組織這些數據格式。某些設備還可能具有多組Collection,表明它有多方面的功能集合,例如某些手繪板同時具有觸摸板、鍵鼠功能或某些鍵盤上有觸摸功能。Collection選項數據定義在下文有表格詳細列出說明,size為1個字節(jié)。End Collection通常不跟隨數據,0xC0既可,表明Collection作用域的結束。
Collection項可選值表
Collection 的數據名稱很難有一個準則來給定,《Universal Serial Bus HID Usage Tables》文檔中將各種用途種類(usage type)列出,使用者必須依據用途種類來指定Collection 的數據名稱。例如鼠標,鍵盤和游戲桿的用途種類為CA,所以要用Collection (Application),而指針為CP,所以用Collection (Physical)。我想原因應該是HID標準設備是逐步被發(fā)明定義出來的。
下一篇再學習 短條目bTag選項中的Global標簽。