美文网首页
USB下无冲键盘的实现

USB下无冲键盘的实现

作者: 剑山 | 来源:发表于2023-05-27 15:26 被阅读0次

    我们都听过USB下键盘只能做6键无冲的说法,但是这种说法其实是错误的,最近在做一个键盘正好看了下这方面的东西,网上相关资料好像不多,我整理下放在这里。

    USB下全键无冲

    其实HID有两种协议,一种是boot protocol,一种是report protocol。系统在bios时只支持boot protocol,这种协议是固定的8byte构成,分别是ID、Modifiers和6个keycode,Modifiers就是功能按左右ctrl、shift之类的,剩下的keycode只能显示最多6个按键,多了就不行了,以前很多的键盘只支持最多按下6个按键是因为使用了这种协议。但是一旦进入到系统,就可以使用report protocol来发送案件信息,report protocol可以用descriptor来描述自己发送按键信息的规则。

    手上几个键盘的解决方案

    第一个

    INFI75

    infi75当按键少于6个(最多5个)的时候是用的boot protocol发送的,当大于等于6个的时候,会使用report protocol。

    TMK/QMK

    QMK使能NKRO后可以用shift+n来切换发送的协议

    杜伽

    杜伽的方案是虚拟出来好几个键盘来发送。。。这种操作也在知乎上看到过。不过很奇怪的是他每个键盘的report其实也不是boot protocol的格式。。。不知道为什么要这么搞


    可以看到选中的两行是由不同device发送的

    FL980V2

    这个我也是没太看懂,我按下很多个按键但是好像发送的位数不太对。


    descriptor

    这里主要是三个部分

    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:长度(bLength)。描述符的长度
    • 0x01:描述符类型(bDescriptorType)。代表这段数据属于设备描述符
    • 0x00, 0x02:USB 版本号(bcdUSB)。代表USB2.0协议
    • 0xef:设备类(bDeviceClass)。这是一个特定的类别代码。
    • 0x02:设备子类(bDeviceSubClass)。这个字段的值也需要根据实际的设备类型来定。
    • 0x01:设备协议(bDeviceProtocol)。同样,这个字段的值也需要根据实际的设备类型来定。
    • 0x40:最大数据包大小(bMaxPacketSize0)。表示端点0的最大数据包大小,
    • 0x3a, 0x30:供应商ID(idVendor)。由 USB Implementers Forum 分配的制造商标识符。
    • 0x01, 0x10:产品ID(idProduct)。制造商分配的产品标识符。
    • 0x01, 0x01:设备版本号(bcdDevice)。设备的发布版本号。
    • 0x01:制造商描述符索引(iManufacturer)。如果制造商字符串描述符存在,则这个字段应该指向它。
    • 0x02:产品描述符索引(iProduct)。如果产品字符串描述符存在,则这个字段应该指向它。
    • 0x03:序列号描述符索引(iSerialNumber)。如果序列号字符串描述符存在,则这个字段应该指向它。
    • 0x01:配置数量(bNumConfigurations)。表示设备的配置数量。

    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
    //端点描述符
    0x07,              //bLenght
    0x05,              //bDescriptorType
    0x81,              //bEndpointAddres
    0x03,              //bmAttributes
    0x40,0x00,         //wMaxPacketSize
    0x01               //bInterval
    
    1. 配置描述符(Configuration Descriptor):

      • 长度(bLenght): 0x09 (9字节)
      • 描述符类型(bDescriptorType): 0x02 (配置描述符)
      • 总长度(wTotalLength): 0x0022 (整个descriptor有 34字节,小端)
      • 接口数(bNumInterfaces): 0x01 (1接口)
      • 配置值(bConfigurationValue): 0x01
      • 配置描述符(iConfiguration): 0x00 (没有关联的描述符字符串)
      • 配置特性(bmAttributes): 0xa0 (总线供电,支持远程唤醒)
      • 最大功率(MaxPower): 0x32 (100mA,1代表2ma)
    2. 接口描述符(Interface Descriptor):

      • 长度(bLenght): 0x09 (9字节)
      • 描述符类型(bDescriptorType): 0x04 (接口描述符)
      • 接口号(bInterfaceNumber): 0x00 (接口0)
      • 替代设置(bAlternateSetting): 0x00
      • 端点数(bNumbEndpoints): 0x01 (端点0以外的端点数1)
      • 接口类(bInterfaceClass): 0x03 (HID)
      • 接口子类(bInterfaceSubClass): 0x01 (1是 0否 支持BIOS)
      • 接口协议(bInterfaceProtocol): 0x01 (00其他,01键盘,02鼠标)
      • 接口(iInterface): 0x00 (没有关联的描述符字符串)
    3. HID描述符(HID Descriptor):

      • 长度(bLenght): 0x09 (9字节)
      • 描述符类型(bDescriptorType): 0x21 (HID描述符)
      • HID版本(bcdHID): 0x0111 (HID 1.11 小端)
      • 国家代码(bCountryCode): 0x00 (没有特定的国家代码)
      • HID描述符数(bNumDescriptors): 0x01
      • 描述符类型(bDescriptorType): 0x22 (报告描述符)
      • 描述符长度(wDescriptorLength): 0x0043 (67字节)
    4. 端点描述符(Endpoint Descriptor):

      • 长度(bLenght): 0x07 (7字节)
      • 描述符类型(bDescriptorType): 0x05 (端点描述符)
      • 端点地址(bEndpointAddres): 0x81 (Bits 3…0是端点号,低速设备(Low-speed devices)最多拥有3个端点号(0–2),其他设备则最多拥有16个端点号(0–15)。,Bit 7是方向,OUT = 0 ,IN = 1,控制端点(control endpoints)忽略这个位。)
      • 属性(bmAttributes): 0x03 (Bits 1…0表示传输类型,00b表示控制(control),01b表示等时(isochronous), 10b表示批量(bulk),11b表示中断(interrupt)。)
      • 最大包长度(wMaxPacketSize):0x0040(64字节)
      • 传输间隔(bInterval): 0x01(每帧传输)

    HID报表描述符

    最关键的是这里

    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个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,会先发送1byte 的report ID,然后1byte的功能按键,然后1byte的LED,15byte的普通按键。然后每次发送report时按照这个规则给电脑发送就行了。

    相关文章

      网友评论

          本文标题:USB下无冲键盘的实现

          本文链接:https://www.haomeiwen.com/subject/wfqkedtx.html