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