USB HID(Human Interface Device)是 USB 设备类规范之一,最初设计用于键盘、鼠标等人机交互设备,现在广泛应用于各种自定义设备。
设备描述符
├── 配置描述符
│ ├── 接口描述符 (HID)
│ │ ├── HID 描述符
│ │ ├── 端点描述符 (中断输入)
│ │ └── 端点描述符 (中断输出,可选)
│ └── ...
└── ...
/* HID 接口描述符 */
struct usb_if_descriptor {
uint8_t bLength; /* 9 */
uint8_t bDescriptorType; /* INTERFACE */
uint8_t bInterfaceNumber; /* 接口编号 */
uint8_t bAlternateSetting; /* 0 */
uint8_t bNumEndpoints; /* 1 (输入) 或 2 (输入+输出) */
uint8_t bInterfaceClass; /* 0x03 (HID) */
uint8_t bInterfaceSubClass; /* 0x00 或 0x01 */
uint8_t bInterfaceProtocol; /* 0x00 / 0x01 / 0x02 */
uint8_t iInterface; /* 字符串索引 */
};
/* HID 类描述符 */
struct usb_hid_descriptor {
uint8_t bLength; /* 9 */
uint8_t bDescriptorType; /* 0x21 (HID) */
uint16_t bcdHID; /* HID 版本:1.11 = 0x0111 */
uint8_t bCountryCode; /* 国家代码:0 = 不支持 */
uint8_t bNumDescriptors; /* 描述符数量:通常 1 */
uint8_t bReportDescriptorType; /* 0x22 (报告) */
uint16_t wReportDescriptorLength; /* 报告描述符长度 */
};
HID 报告描述符定义设备发送/接收的数据格式。
/* 简单键盘报告描述符示例 */
const uint8_t hid_report_descriptor[] = {
/* Usage Page (Generic Desktop) */
HID_GI_USAGE_PAGE, HID_USAGE_GEN_DESKTOP,
/* Usage (Keyboard) */
HID_LI_USAGE, HID_USAGE_GEN_DESKTOP_KEYBOARD,
/* Collection (Application) */
HID_MI_COLLECTION, HID_COLLECTION_APPLICATION,
/* Usage Page (Keyboard/Keypad) */
HID_GI_USAGE_PAGE, HID_USAGE_GEN_KEYBOARD,
/* Usage Minimum (Keyboard Left Control) */
HID_LI_USAGE_MIN(1), 0xE0,
/* Usage Maximum (Keyboard Right GUI) */
HID_LI_USAGE_MAX(1), 0xE7,
/* Logical Minimum (0) */
HID_GI_LOGICAL_MIN(1), 0x00,
/* Logical Maximum (1) */
HID_GI_LOGICAL_MAX(1), 0x01,
/* Report Size (1) */
HID_GI_REPORT_SIZE, 0x01,
/* Report Count (8) */
HID_GI_REPORT_COUNT, 0x08,
/* Input (Data, Var, Abs) - 修饰键 */
HID_MI_INPUT, 0x02,
/* Report Size (8) */
HID_GI_REPORT_SIZE, 0x08,
/* Report Count (1) */
HID_GI_REPORT_COUNT, 0x01,
/* Input (Const, Var, Abs) - 填充字节 */
HID_MI_INPUT, 0x03,
/* Report Size (8) */
HID_GI_REPORT_SIZE, 0x08,
/* Report Count (6) */
HID_GI_REPORT_COUNT, 0x06,
/* Logical Maximum (101) */
HID_GI_LOGICAL_MAX(1), 0x65,
/* Usage Maximum (101) */
HID_LI_USAGE_MAX(1), 0x65,
/* Input (Data, Array) - 按键码 */
HID_MI_INPUT, 0x00,
/* End Collection */
HID_MI_COLLECTION_END,
};
const uint8_t mouse_report_descriptor[] = {
HID_GI_USAGE_PAGE, HID_USAGE_GEN_DESKTOP,
HID_LI_USAGE, HID_USAGE_GEN_DESKTOP_MOUSE,
HID_MI_COLLECTION, HID_COLLECTION_APPLICATION,
HID_LI_USAGE, HID_USAGE_GEN_DESKTOP_POINTER,
HID_MI_COLLECTION, HID_COLLECTION_PHYSICAL,
HID_GI_USAGE_PAGE, HID_USAGE_GEN_BUTTON,
HID_LI_USAGE_MIN(1), 0x01,
HID_LI_USAGE_MAX(1), 0x03,
HID_GI_LOGICAL_MIN(1), 0x00,
HID_GI_LOGICAL_MAX(1), 0x01,
HID_GI_REPORT_SIZE, 0x01,
HID_GI_REPORT_COUNT, 0x03,
HID_MI_INPUT, 0x02, /* 按键 */
HID_GI_REPORT_SIZE, 0x05,
HID_GI_REPORT_COUNT, 0x01,
HID_MI_INPUT, 0x03, /* 填充 */
HID_GI_USAGE_PAGE, HID_USAGE_GEN_DESKTOP,
HID_LI_USAGE, HID_USAGE_GEN_DESKTOP_X,
HID_LI_USAGE, HID_USAGE_GEN_DESKTOP_Y,
HID_GI_LOGICAL_MIN(1), 0x81, /* -127 */
HID_GI_LOGICAL_MAX(1), 0x7F, /* 127 */
HID_GI_REPORT_SIZE, 0x08,
HID_GI_REPORT_COUNT, 0x02,
HID_MI_INPUT, 0x06, /* X, Y 相对位置 */
HID_MI_COLLECTION_END,
HID_MI_COLLECTION_END,
};
/* 标准键盘报告 */
struct hid_keyboard_report {
uint8_t modifiers; /* 修饰键位图 */
uint8_t reserved; /* 保留(填充) */
uint8_t keycodes[6]; /* 最多6个按键码 */
};
/* 修饰键位图 */
#define HID_MOD_LCTRL (1 << 0)
#define HID_MOD_LSHIFT (1 << 1)
#define HID_MOD_LALT (1 << 2)
#define HID_MOD_LGUI (1 << 3)
#define HID_MOD_RCTRL (1 << 4)
#define HID_MOD_RSHIFT (1 << 5)
#define HID_MOD_RALT (1 << 6)
#define HID_MOD_RGUI (1 << 7)
/* 常用按键码 */
#define HID_KEY_A 0x04
#define HID_KEY_B 0x05
#define HID_KEY_C 0x06
#define HID_KEY_1 0x1E
#define HID_KEY_2 0x1F
#define HID_KEY_ENTER 0x28
#define HID_KEY_SPACE 0x2C
#define HID_KEY_LEFT 0x50
#define HID_KEY_RIGHT 0x4F
#define HID_KEY_UP 0x52
#define HID_KEY_DOWN 0x51
struct hid_mouse_report {
uint8_t buttons; /* 按键位图 (bit0=左, bit1=右, bit2=中) */
int8_t x; /* X 相对位移 (-127 ~ 127) */
int8_t y; /* Y 相对位移 (-127 ~ 127) */
};
| 项目 | 标签 | 说明 |
|---|---|---|
| Usage Page | 0x04 | 用途页面 |
| Logical Minimum | 0x14 | 逻辑最小值 |
| Logical Maximum | 0x24 | 逻辑最大值 |
| Physical Minimum | 0x34 | 物理最小值 |
| Physical Maximum | 0x44 | 物理最大值 |
| Report Size | 0x74 | 报告字段位数 |
| Report Count | 0x94 | 报告字段数量 |
| Report ID | 0x84 | 报告标识 |
| 项目 | 标签 | 说明 |
|---|---|---|
| Usage | 0x08 | 用途 |
| Usage Minimum | 0x18 | 用途最小值 |
| Usage Maximum | 0x28 | 用途最大值 |
| 项目 | 标签 | 说明 |
|---|---|---|
| Input | 0x80 | 输入报告 |
| Output | 0x90 | 输出报告 |
| Feature | 0xB0 | 特性报告 |
| Collection | 0xA0 | 集合开始 |
| End Collection | 0xC0 | 集合结束 |
HID 设备使用中断传输:
主机 ←── IN 端点 ── 设备
主机 ── OUT 端点 ──→ 设备
特点:
[Report ID (可选)] [报告数据]
# 列出 HID 设备
ls /dev/hidraw*
# 查看设备信息
cat /sys/class/hidraw/hidraw0/device/uevent
# 读取 HID 报告
hexdump -C /dev/hidraw0
*学习笔记创建时间: 2026-03-19*