You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何带17个按键的游戏手柄HID描述符无法正常工作?

HID游戏手柄报告描述符修改后连接异常排查

我当前使用的HID报告描述符如下:

static
unsigned char hid_report_descriptor[] __attribute__ ((aligned(64))) = {
    0x05, 0x01,     // Usage Page (Generic Desktop Ctrls)
    0x09, 0x05,     // Usage (Game Pad)
    0xA1, 0x01,     // Collection (Application)
    0xA1, 0x00,     //   Collection (Physical)
    0x85, 0x01,     //     Report ID (1)
    0x05, 0x09,     //     Usage Page (Button)
    0x19, 0x01,     //     Usage Minimum (0x01)
    0x29, 0x10,     //     Usage Maximum (0x10)
    0x15, 0x00,     //     Logical Minimum (0)
    0x25, 0x01,     //     Logical Maximum (1)
    0x95, 0x10,     //     Report Count (16)
    0x75, 0x01,     //     Report Size (1)
    0x81, 0x02,     //     Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
    0x05, 0x01,     //     Usage Page (Generic Desktop Ctrls)
    0x09, 0x30,     //     Usage (X)
    0x09, 0x31,     //     Usage (Y)
    0x09, 0x32,     //     Usage (Z)
    0x09, 0x33,     //     Usage (Rx)
    0x15, 0x81,     //     Logical Minimum (-127)
    0x25, 0x7F,     //     Logical Maximum (127)
    0x75, 0x08,     //     Report Size (8)
    0x95, 0x04,     //     Report Count (4)
    0x81, 0x02,     //     Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
    0xC0,           //   End Collection
    0xC0,           // End Collection
};

对应的结构体定义为:

struct GamepadReport {
    uint8_t report_id;
    uint16_t buttons;
    int8_t left_x;
    int8_t left_y;
    int8_t right_x;
    int8_t right_y;
} __attribute__((packed));

我想添加一个类似Xbox控制器Home键的额外按键,原本以为只要将描述符中的0x29, 0x10(Usage Maximum)改为0x29, 0x11,同时把0x95, 0x10(Report Count)改为0x95, 0x11即可,但修改后自定义控制器出现连接异常,求排查原因。


问题原因与解决方法

  • 核心问题:HID报告长度未对齐
    HID设备的输入/输出报告总位数必须是8的整数倍(即总长度为整数字节)。原描述符中按钮部分是16位(正好2字节),修改为17位后,总位数无法被8整除,主机解析报告时会判定设备格式无效,直接拒绝连接。同时对应的结构体仍用uint16_t buttons,也会导致数据错位,进一步加剧解析错误。
  • 修正步骤:
    1. 调整报告描述符:将按钮的Report Count从0x95, 0x11改为0x95, 0x18(24位,3字节),保留0x29, 0x11作为Usage Maximum。这样既包含了需要的17个按钮,剩余7位作为保留位,满足字节对齐要求。修改后的按钮段描述符如下:
      0x05, 0x09,     //     Usage Page (Button)
      0x19, 0x01,     //     Usage Minimum (0x01)
      0x29, 0x11,     //     Usage Maximum (0x11)
      0x15, 0x00,     //     Logical Minimum (0)
      0x25, 0x01,     //     Logical Maximum (1)
      0x95, 0x18,     //     Report Count (24)
      0x75, 0x01,     //     Report Size (1)
      0x81, 0x02,     //     Input (Data,Var,Abs,...)
      
    2. 更新对应结构体:将uint16_t buttons替换为uint32_t buttons(或3个连续的uint8_t),确保结构体的字节长度与描述符定义的报告长度匹配。修改后的结构体示例:
      struct GamepadReport {
          uint8_t report_id;
          uint32_t buttons;  // 用32位容纳24位按钮数据,高位空闲
          int8_t left_x;
          int8_t left_y;
          int8_t right_x;
          int8_t right_y;
      } __attribute__((packed));
      
    3. 验证报告总长度:修改后的报告总长度为1(report_id)+3(buttons)+4(轴数据)=8字节,对应描述符中总位数:18 +24 +48=8+24+32=64位,正好是8字节,符合HID规范要求。

内容的提问来源于stack exchange,提问作者Carlos Santos

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 19:35:23