我們都聽過USB下鍵盤只能做6鍵無沖的說法外臂,但是這種說法其實(shí)是錯(cuò)誤的坐儿,最近在做一個(gè)鍵盤正好看了下這方面的東西,網(wǎng)上相關(guān)資料好像不多宋光,我整理下放在這里貌矿。
USB下全鍵無沖
其實(shí)HID有兩種協(xié)議,一種是boot protocol罪佳,一種是report protocol逛漫。系統(tǒng)在bios時(shí)只支持boot protocol,這種協(xié)議是固定的8byte構(gòu)成赘艳,分別是ID尽楔、Modifiers和6個(gè)keycode,Modifiers就是功能按左右ctrl第练、shift之類的,剩下的keycode只能顯示最多6個(gè)按鍵玛荞,多了就不行了娇掏,以前很多的鍵盤只支持最多按下6個(gè)按鍵是因?yàn)槭褂昧诉@種協(xié)議。但是一旦進(jìn)入到系統(tǒng)勋眯,就可以使用report protocol來發(fā)送案件信息婴梧,report protocol可以用descriptor來描述自己發(fā)送按鍵信息的規(guī)則。
手上幾個(gè)鍵盤的解決方案
第一個(gè)
INFI75
infi75當(dāng)按鍵少于6個(gè)(最多5個(gè))的時(shí)候是用的boot protocol發(fā)送的客蹋,當(dāng)大于等于6個(gè)的時(shí)候塞蹭,會(huì)使用report protocol。
TMK/QMK
QMK使能NKRO后可以用shift+n來切換發(fā)送的協(xié)議
杜伽
杜伽的方案是虛擬出來好幾個(gè)鍵盤來發(fā)送讶坯。番电。。這種操作也在知乎上看到過。不過很奇怪的是他每個(gè)鍵盤的report其實(shí)也不是boot protocol的格式漱办。这刷。。不知道為什么要這么搞
FL980V2
這個(gè)我也是沒太看懂娩井,我按下很多個(gè)按鍵但是好像發(fā)送的位數(shù)不太對(duì)暇屋。
descriptor
這里主要是三個(gè)部分
Device Descriptor
0x12 //bLenght
0x01 //bDescriptorType
0x00,0x02 //bcdUSB
0xef //bDeviceClass
0x02 //bDeviceSubClass
0x01 //bDeviceProtocol
0x40 //bMaxPacketSize0
0x3a,0x30 //idVendor
0x01,0x10 //idProduct
0x01,0x01 //bcdDevice
0x01 //iManufacturer
0x02 //iProduct
0x03 //iSerialNumber
0x01 //bNumConfigurations
- 0x12:長(zhǎng)度(bLength)。描述符的長(zhǎng)度
- 0x01:描述符類型(bDescriptorType)洞辣。代表這段數(shù)據(jù)屬于設(shè)備描述符
- 0x00, 0x02:USB 版本號(hào)(bcdUSB)咐刨。代表USB2.0協(xié)議
- 0xef:設(shè)備類(bDeviceClass)。這是一個(gè)特定的類別代碼扬霜。
- 0x02:設(shè)備子類(bDeviceSubClass)定鸟。這個(gè)字段的值也需要根據(jù)實(shí)際的設(shè)備類型來定贮缅。
- 0x01:設(shè)備協(xié)議(bDeviceProtocol)医增。同樣恕齐,這個(gè)字段的值也需要根據(jù)實(shí)際的設(shè)備類型來定囊卜。
- 0x40:最大數(shù)據(jù)包大形鲈摇(bMaxPacketSize0)代虾。表示端點(diǎn)0的最大數(shù)據(jù)包大小栈戳,
- 0x3a, 0x30:供應(yīng)商ID(idVendor)安聘。由 USB Implementers Forum 分配的制造商標(biāo)識(shí)符华糖。
- 0x01, 0x10:產(chǎn)品ID(idProduct)麦向。制造商分配的產(chǎn)品標(biāo)識(shí)符。
- 0x01, 0x01:設(shè)備版本號(hào)(bcdDevice)客叉。設(shè)備的發(fā)布版本號(hào)诵竭。
- 0x01:制造商描述符索引(iManufacturer)。如果制造商字符串描述符存在兼搏,則這個(gè)字段應(yīng)該指向它卵慰。
- 0x02:產(chǎn)品描述符索引(iProduct)。如果產(chǎn)品字符串描述符存在佛呻,則這個(gè)字段應(yīng)該指向它裳朋。
- 0x03:序列號(hào)描述符索引(iSerialNumber)。如果序列號(hào)字符串描述符存在吓著,則這個(gè)字段應(yīng)該指向它鲤嫡。
- 0x01:配置數(shù)量(bNumConfigurations)。表示設(shè)備的配置數(shù)量绑莺。
Configuration Descriptor
//配置描述符
0x09, //bLenght
0x02, //bDescriptorType
0x22,0x00, //wTotalLength
0x01, //bNumInterfaces
0x01, //bConfigurationValue
0x00, //iConfiguration
0xa0, //bmAttributes
0x32, //MaxPower
//接口描述符,鍵盤功能
0x09, //bLenght
0x04, //bDescriptorType
0x00, //bInterfaceNumber
0x00, //bAlternateSetting
0x01, //bNumbEndpoints
0x03, //bInterfaceClass
0x01, //bInterfaceSubClass
0x01, //bInterfaceProtocol
0x00, //iInterface
//HID類描述符
0x09, //bLenght
0x21, //bDescriptorType
0x11,0x01, //bcdHID
0x00, //bCountryCode
0x01, //bNumDescriptors
0x22, //bDescriptorType
0x43,0x00, //wDescriptorLength
//端點(diǎn)描述符
0x07, //bLenght
0x05, //bDescriptorType
0x81, //bEndpointAddres
0x03, //bmAttributes
0x40,0x00, //wMaxPacketSize
0x01 //bInterval
-
配置描述符(Configuration Descriptor):
- 長(zhǎng)度(bLenght): 0x09 (9字節(jié))
- 描述符類型(bDescriptorType): 0x02 (配置描述符)
- 總長(zhǎng)度(wTotalLength): 0x0022 (整個(gè)descriptor有 34字節(jié)暖眼,小端)
- 接口數(shù)(bNumInterfaces): 0x01 (1接口)
- 配置值(bConfigurationValue): 0x01
- 配置描述符(iConfiguration): 0x00 (沒有關(guān)聯(lián)的描述符字符串)
- 配置特性(bmAttributes): 0xa0 (總線供電,支持遠(yuǎn)程喚醒)
- 最大功率(MaxPower): 0x32 (100mA纺裁,1代表2ma)
-
接口描述符(Interface Descriptor):
- 長(zhǎng)度(bLenght): 0x09 (9字節(jié))
- 描述符類型(bDescriptorType): 0x04 (接口描述符)
- 接口號(hào)(bInterfaceNumber): 0x00 (接口0)
- 替代設(shè)置(bAlternateSetting): 0x00
- 端點(diǎn)數(shù)(bNumbEndpoints): 0x01 (端點(diǎn)0以外的端點(diǎn)數(shù)1)
- 接口類(bInterfaceClass): 0x03 (HID)
- 接口子類(bInterfaceSubClass): 0x01 (1是 0否 支持BIOS)
- 接口協(xié)議(bInterfaceProtocol): 0x01 (00其他诫肠,01鍵盤,02鼠標(biāo))
- 接口(iInterface): 0x00 (沒有關(guān)聯(lián)的描述符字符串)
-
HID描述符(HID Descriptor):
- 長(zhǎng)度(bLenght): 0x09 (9字節(jié))
- 描述符類型(bDescriptorType): 0x21 (HID描述符)
- HID版本(bcdHID): 0x0111 (HID 1.11 小端)
- 國(guó)家代碼(bCountryCode): 0x00 (沒有特定的國(guó)家代碼)
- HID描述符數(shù)(bNumDescriptors): 0x01
- 描述符類型(bDescriptorType): 0x22 (報(bào)告描述符)
- 描述符長(zhǎng)度(wDescriptorLength): 0x0043 (67字節(jié))
-
端點(diǎn)描述符(Endpoint Descriptor):
- 長(zhǎng)度(bLenght): 0x07 (7字節(jié))
- 描述符類型(bDescriptorType): 0x05 (端點(diǎn)描述符)
- 端點(diǎn)地址(bEndpointAddres): 0x81 (Bits 3…0是端點(diǎn)號(hào),低速設(shè)備(Low-speed devices)最多擁有3個(gè)端點(diǎn)號(hào)(0–2)区赵,其他設(shè)備則最多擁有16個(gè)端點(diǎn)號(hào)(0–15)惭缰。,Bit 7是方向笼才,OUT = 0 漱受,IN = 1,控制端點(diǎn)(control endpoints)忽略這個(gè)位骡送。)
- 屬性(bmAttributes): 0x03 (Bits 1…0表示傳輸類型昂羡,00b表示控制(control),01b表示等時(shí)(isochronous)摔踱, 10b表示批量(bulk)虐先,11b表示中斷(interrupt)。)
- 最大包長(zhǎng)度(wMaxPacketSize):0x0040(64字節(jié))
- 傳輸間隔(bInterval): 0x01(每幀傳輸)
HID報(bào)表描述符
最關(guān)鍵的是這里
05 01 // Usage Page (Generic Desktop),
09 06 // Usage (Keyboard),
a1 01 // Collection (Application),
85 01 // Report ID(01),
// bitmap of modifiers(功能按鍵)
05 07 // Usage Page (Keyboard),
19 e0 // Usage Minimum (Keyboard LeftControl),
29 e7 // Usage Maximum (Keyboard Right GUI),
15 00 // Logical Minimum (0),
25 01 // Logical Maximum (1),
95 08 // Report Count (8),
75 01 // Report Size (1),
81 02 // Input (Data, Variable, Absolute),
// LED output report
05 08 // Usage Page (LEDs)
19 01 // Usage Minimum (Num Lock 1)
29 05 // Usage Maximum (Kana 3)
95 05 // Report Count (5)
75 01 // Report Size (1)
91 02 // Output (Data,Var,Abs)
//湊齊LED 5bit后面的3個(gè)bit 為1byte
95 01 // Report Count (1)
75 03 // Report Size (3)
91 01 // Output (Cnst,Var,Abs)
// bitmap of keys(普通按鍵)
05 07 // Usage Page (Keyboard),
19 00 // Usage Minimum (0),
29 77 // Usage Maximum (119),
15 00 // Logical Minimum (0),
25 01 // Logical Maximum (1),
75 01 // Report Size (1),
95 78 // Report Count (120),
81 02 // Input (Data, Variable, Absolute),
c0 // End Collection
主要說明后面的report派敷,會(huì)先發(fā)送1byte 的report ID蛹批,然后1byte的功能按鍵,然后1byte的LED篮愉,15byte的普通按鍵腐芍。然后每次發(fā)送report時(shí)按照這個(gè)規(guī)則給電腦發(fā)送就行了。