HID 设备方案
概述
USB 人机接口设备 (Human Interface Device, HID) 协议是 USB-IF 定义的一套用于连接人机交互设备(如键盘、鼠标、游戏控制器、触摸屏等)的标准接口规范。
Ameba 平台基于 USB-IF 官方标准,实现了功能完备的 USB HID 设备端协议栈。该方案能够为系统提供稳定、低延迟的人机交互接口,并支持高度灵活的自定义配置。
特性
描述符全定制
支持 USB 热插拔
模拟支持基础的键盘按键与鼠标移动事件
支持单/双向通信:
鼠标:支持 HID 数据的单向上报 (Input Report)。
键盘:支持 HID 数据的双向通信 (Input & Output Report),可处理主机下发的 LED 状态控制(如 “Caps Lock” 指示灯)。
支持配置速度模式等参数
应用场景
作为 USB HID 设备,Ameba 可通过 USB 接口向 Host 主机(如 PC、平板电脑、智能电视)发送标准输入报告。结合其内置的 Wi-Fi 和 Bluetooth® 能力,Ameba 能够实现多种跨协议、跨介质的创新应用,例如:
无线外设适配器 (Dongle):Ameba 作为 USB 接收端 (Dongle) 插入主机,通过 Wi-Fi 或蓝牙接收远端无线键盘/鼠标的数据,并将其转换为标准的 USB HID 报文透传给主机,实现无线外设的即插即用。
IoT 智能控制网关:Ameba 可作为物理输入与数字控制的桥梁。它读取本地物理按键、旋钮或传感器信号,通过 USB HID 协议将其映射为标准输入指令,或转换为网络控制指令,从而实现对智能家居及工业设备的精准控制。
游戏控制器转接器:支持将非标准接口的游戏控制器(如老式游戏机手柄、自定义街机摇杆)的信号接入 Ameba,通过内部协议栈转换为标准 HID 游戏控制器报告,确保在 PC 或现代游戏主机上的兼容性。
协议简介
HID (Human Interface Device) 协议是 USB 规范框架下,专为实现人机交互设备而定义的标准接口与数据传输规范。该协议定义了主机(Host)与设备(Device)之间的数据交互格式及控制响应机制。
遵循 HID 标准的常见设备包括:
输入设备:键盘、鼠标、游戏手柄、数字转换器(触摸屏/绘图板)。
控制设备:消费类电子控制旋钮(如音量调节)、系统休眠按钮等。
协议文档
USB-IF 官方发布了 HID 核心协议规范及用于定义设备功能的用途表(Usage Tables)。开发者可参考以下核心文档:
规范类型 |
文档 |
|---|---|
HID 核心协议 |
|
HID 用途表 |
术语定义
本文档涉及的通用 HID 技术术语定义如下:
术语 |
描述 |
|---|---|
报告 (Report) |
HID 设备与主机之间传输数据的基本单元。数据包的结构由报告描述符定义。 |
用途 (Usage) |
描述数据具体含义的标识符。例如,定义某个数据位代表“左键点击”还是“X 轴坐标”。 |
集合 (Collection) |
将相关的输入/输出数据项分组的逻辑结构。例如,将鼠标的 X、Y 轴和按键组合在一个“鼠标”集。 |
项目 (Item) |
报告描述符的基本组成部分,分为主项目 (Main)、全局项目 (Global) 和局部项目 (Local)。 |
协议框架
HID 协议栈采用分层架构设计,旨在将底层的 USB 传输细节与上层的应用逻辑解耦。系统架构主要包含以下核心组件:USB 核心传输驱动、HID 类驱动以及特定类型的 HID 应用。
组件职责
HID 应用程序 (HID Application)
位于架构最上层,负责处理具体的业务逻辑。例如:采集传感器数据并打包成鼠标坐标报告,或接收键盘 LED 控制指令并驱动 GPIO 点亮指示灯。
HID 类驱动 (HID Class Driver)
实现了 Device Class Definition for HID 1.11 规范。其主要职责包括:解析和组织 HID 协议特有的数据包,管理报告描述符(Report Descriptor),并处理类特定请求(Class-Specific Requests)。
USB 核心与传输驱动 (USB Core & Transfer Driver)
负责处理标准的 USB 枚举流程、端点管理及底层的数据包调度,向上层屏蔽硬件控制器的差异。
通信机制
HID 设备通过特定的端点(Endpoint)配置来实现低延迟或低带宽要求的交互。从逻辑功能上,HID 接口主要依赖以下两种传输方式:
控制管道 (Control Pipe)
映射端点: 默认控制端点 0 (Endpoint 0)。
枚举与配置: 传输标准的 USB 描述符(设备、配置、接口描述符)以及 HID 特有的 HID 描述符和报告描述符。
类特定请求: 处理 HID 协议控制命令,例如 Set Idle (设置空闲率)。
低频数据传输: 当设备未配置中断输出端点时,主机通过控制传输(Control Transfer)发送输出报告(Output Report),例如设置键盘的大小写锁定灯状态。
中断管道 (Interrupt Pipe)
功能描述: 利用 USB 的轮询(Polling)机制,保证数据传输的实时性。
中断输入 (Interrupt IN): 必选。负责将设备产生的异步数据(如按键按下、鼠标位移、触摸屏坐标)实时传输给主机。
中断输出 (Interrupt OUT): 可选。负责主机向设备发送低延迟的下行数据。常见于需要高实时性反馈的场景,如游戏手柄的力反馈震动指令。若未定义此端点,下行数据将回退至控制管道传输。
描述符结构
HID 设备除遵循标准的 USB 描述符外,引入了其独有的描述符体系。最关键的是 HID 描述符(HID Descriptor)和报告描述符 (Report Descriptor)。
HID 描述符拓扑 (Descriptor Topology)
Device Descriptor
└── Identifies basic device information (USB Version 2.00)
Configuration Descriptor
├── Contains total length of the entire configuration, power supply information, etc.
│
└── Interface Descriptor (Interface 0)
├── Standard Interface Descriptor (Interface 0, Human Interface Device)
├── HID Descriptor(HID Version, bNumDescriptors, etc)
│ └── Report Descriptor()
├── Endpoint Descriptor(Interrupt In)
└── Endpoint Descriptor(Interrupt Out)
Device Qualifier Descriptor
└── Device information while running in another speed mode
Other Speed Configuration Descriptor
├── Configuration information while running in another speed mode.
│
└── Interface Descriptor (Interface 0)
├── Standard Interface Descriptor (Interface 0, Human Interface Device)
├── HID Descriptor(HID Version, bNumDescriptors, etc)
│ └── Report Descriptor()
├── Endpoint Descriptor(Interrupt In)
└── Endpoint Descriptor(Interrupt Out)
HID 描述符 (HID Descriptor)
位于配置描述符集合中,用于告知主机该接口包含哪些下级描述符(通常是报告描述符)及其长度。
HID Descriptor
├── bLength : 1 byte → Total descriptor length
├── bDescriptorType : 1 byte → 0x21 (HID Descriptor)
├── bcdADC : 2 bytes → HID Version
├── bCountryCode : 1 byte → Numeric expression identifying country code of the localized hardware
├── bNumDescriptors : 1 byte → Numeric expression specifying the number of class descriptors
│ └─ (always at least one i.e. Report descriptor.)
├── bDescriptorType : 1 byte → Constant name identifying type of class descriptor.
└── wDescriptorLength : 2 byte → Numeric expression that is the total size of the Report descriptor.
报告描述符 (Report Descriptor)
这是一个由特定项目(Item)组成的字符流,而非固定的结构体。
它灵活地定义了设备能够产生或接收的数据格式、长度、用途及物理范围。主机必须解析该描述符才能理解设备发送的数据。
Report Descriptor
├── Usage Page (Generic Desktop)
├── Usage (Keyboard)
├── Collection (Application)
│ ├── Usage Page (Key Codes)
│ ├── Usage Minimum (224)
| ├── Usage Maximum (231)
│ ├── Logical Minimum (0)
│ ├── Logical Maximum (1)
│ ├── Report Count (8)
│ ├── Report Size (1)
│ ├── Input (Data, Variable, Absolute) ; Modifier keys (8 bits, 1 per modifier)
│ ├── Report Count (1)
│ ├── Report Size (8)
│ ├── Input (Constant, Variable, Absolute) ; Reserved byte
| |
│ ├── Usage Page (LEDs)
│ ├── Logical Minimum (0)
│ ├── Logical Maximum (1)
│ ├── Report Count (5)
│ ├── Report Size (1)
│ ├── Usage Minimum (Num Lock)
│ ├── Usage Maximum (Kana)
│ ├── Output (Data, Variable, Absolute) ; 5 LED control bits
│ ├── Report Count (1)
│ ├── Report Size (3)
│ ├── Output (Constant, Variable, Absolute) ; Padding 3 bits
│ │
│ └── ....... Can configure multiple different setting as needed
│
└── End Collection
备注
HID 报告描述符的编写非常灵活且复杂,建议使用 USB-IF 提供的 HID Descriptor Tool 进行生成和校验。
类特定请求
HID 设备的控制请求分为 标准请求(Standard Requests) 和 类特定请求 (Class-Specific Requests) 。
本节主要介绍 HID 特有的 类特定请求,这些 HID 类特定请求主要用于管理报告状态和协议行为。不同类型的设备对类特定请求的支持要求如下表所示:
设备类型 |
Get Report |
Set Report |
Get Idle |
Set Idle |
Get Protocol |
Set Protocol |
|---|---|---|---|---|---|---|
Boot Mouse |
必选 |
可选 |
可选 |
可选 |
必选 |
必选 |
Non-Boot Mouse |
必选 |
可选 |
可选 |
可选 |
可选 |
可选 |
Boot Keyboard |
必选 |
可选 |
必选 |
必选 |
必选 |
必选 |
Non-Boot Keyboard |
必选 |
可选 |
必选 |
必选 |
可选 |
可选 |
Other Device |
必选 |
可选 |
可选 |
可选 |
可选 |
可选 |
数据传输格式
与 UAC (USB Audio Class) 固定的 PCM 流不同,HID 的数据格式完全由 报告描述符 动态定义。
以下为标准键盘的典型数据结构示例:
键盘输入报告 (Keyboard Input Report)
用于向主机发送按键数据。以下为按下 "Left Shift" + "A" 键的数据示例:
Filed |
Length(bits) |
Offset(bits) |
Value |
|---|---|---|---|
Left Ctrl |
1 |
0 |
0 |
Left Shift |
1 |
1 |
1 |
Left Alt |
1 |
2 |
0 |
Left GUI |
1 |
3 |
0 |
Right Ctrl |
1 |
4 |
0 |
Right Shift |
1 |
5 |
0 |
Right Alt |
1 |
6 |
0 |
Right GUI |
1 |
7 |
0 |
Pading |
8 |
8 |
0 |
Key |
48 |
16 |
0x04 |
键盘输出报告 (Keyboard Output Report)
用于主机控制键盘 LED 状态。以下为点亮 "Caps Lock" 灯的数据示例:
Filed |
Length(bits) |
Offset(bits) |
Value |
|---|---|---|---|
Num Lock |
1 |
0 |
0 |
Caps Lock |
1 |
1 |
1 |
Scroll Lock |
1 |
2 |
0 |
Compose |
1 |
3 |
0 |
Kana |
1 |
4 |
0 |
备注
报告 ID (Report ID):
如果一个 HID 接口支持多种不同格式的数据包,必须在每个数据包的起始位置添加一个字节的 Report ID 进行区分。如果设备仅定义了一种报告格式,则可以省略 Report ID,直接传输数据载荷。
类驱动
本节详细介绍了 HID 类驱动的内部实现细节,包括描述符的层级结构、类特定请求的支持情况以及端点配置方案。
驱动描述符结构
下文展示了 HID 类驱动中定义的描述符拓扑结构。这些结构体严格遵循 USB 2.0 协议规范与 HID 类定义。
Device Descriptor
└── Identifies basic device information (USB Version 2.00)
Configuration Descriptor
├── Contains total length of the entire configuration, power supply information, etc.
│
└── Interface Descriptor (Interface 0)
├── Standard Interface Descriptor (Interface 0, Human Interface Device)
├── HID Descriptor(HID Version, bNumDescriptors, etc)
│ └── Report Descriptor()
└── Endpoint Descriptor(Interrupt In)
Device Qualifier Descriptor
└── Device information while running in another speed mode
Other Speed Configuration Descriptor
├── Configuration information while running in another speed mode.
│
└── Interface Descriptor (Interface 0)
├── Standard Interface Descriptor (Interface 0, Human Interface Device)
├── HID Descriptor(HID Version, bNumDescriptors, etc)
│ └── Report Descriptor()
└── Endpoint Descriptor(Interrupt In)
Device Descriptor
└── Identifies basic device information (USB Version 2.00)
Configuration Descriptor
├── Contains total length of the entire configuration, power supply information, etc.
│
└── Interface Descriptor (Interface 0)
├── Standard Interface Descriptor (Interface 0, Human Interface Device)
├── HID Descriptor(HID Version, bNumDescriptors, etc)
│ └── Report Descriptor()
├── Endpoint Descriptor(Interrupt In)
└── Endpoint Descriptor(Interrupt Out)
Device Qualifier Descriptor
└── Device information while running in another speed mode
Other Speed Configuration Descriptor
├── Configuration information while running in another speed mode.
│
└── Interface Descriptor (Interface 0)
├── Standard Interface Descriptor (Interface 0, Human Interface Device)
├── HID Descriptor(HID Version, bNumDescriptors, etc)
│ └── Report Descriptor()
├── Endpoint Descriptor(Interrupt In)
└── Endpoint Descriptor(Interrupt Out)
类特定请求实现
本驱动栈遵循 USB HID 1.11 规范,已实现了核心 类特定请求 (Class-Specific Requests) 的基础框架。
驱动层已完成底层消息通信、协议解析及数据传输流程。开发者无需关注 USB 协议细节,仅需参考现有源码架构,在预留的接口中实现具体的业务逻辑。源码路径: {SDK}/component/usb/device/hid
类特定请求类型 |
备注 |
|---|---|
Get Report |
驱动已完成请求响应流程。注意:默认实现返回 0 数据,需在应用层填充具体的 Report 内容。 |
Set Report |
驱动已接收数据包,开发者需实现对主机下发数据(Output/Feature Report)的具体处理逻辑。 |
Get Idle |
标准实现。 |
Set Idle |
标准实现。 |
Get Protocol |
用于查询当前协议模式(Boot/Report)。 |
Set Protocol |
驱动已解析请求,开发者需根据主机下发的协议模式(Boot 或 Report)执行相应的状态切换处理。 |
端点配置
端点 |
数量 |
描述 |
|---|---|---|
控制 IN/OUT 端点 |
1 |
EP0,用于处理 USB 主机发送的标准枚举请求、描述符获取及 HID 类特定控制请求。 |
中断 IN 端点 |
1 |
用于设备向主机实时上报数据(如鼠标位移、按键键值等)。 |
端点 |
数量 |
描述 |
|---|---|---|
控制 IN/OUT 端点 |
1 |
EP0,用于处理 USB 主机发送的标准枚举请求、描述符获取及 HID 类特定控制请求。 |
中断 IN 端点 |
1 |
用于设备向主机实时上报数据(如鼠标位移、按键键值等)。 |
中断 OUT 端点 |
1 |
用于接收来自 USB 主机的下行键盘消息数据(如主机点亮 "Caps Lock" 灯)。 |
API 说明
应用示例
应用设计
本节详细介绍 HID 应用的完整开发流程,涵盖加载驱动、热插拔管理、数据收发机制以及资源释放。
加载驱动
使用 HID 驱动前,需定义配置结构体并注册回调函数,随后调用核心接口加载 USB 设备控制器及 HID 类驱动。步骤说明:
硬件配置:配置 USB 速度模式及中断优先级。
回调注册:定义用户回调结构体
usbd_hid_usr_cb_t,挂载各个阶段的处理函数。加载核心驱动:调用
usbd_init()加载 USB 核心驱动。加载类驱动:调用
usbd_hid_init()加载 HID 类驱动。
/*
* 1. Configure USB speed (High Speed or Full Speed) and interrupt priority.
*/
static usbd_config_t hid_cfg = {
.speed = CONFIG_USBD_HID_SPEED,
.isr_priority = INT_PRI_MIDDLE,
};
/*
* 2. Define user callbacks for HID events.
*/
static usbd_hid_usr_cb_t hid_usr_cb = {
.init = hid_cb_init, /* USB init callback */
.deinit = hid_cb_deinit, /* USB deinit callback */
.setup = hid_cb_setup, /* USB setup callback */
.transmitted = hid_cb_transmitted, /* Data transmission complet callback */
.received = hid_cb_received, /* Data reception callback */
.status_changed = hid_cb_status_changed, /* Connection status change callbac */
};
int ret = 0;
/**
* Initialize USB device core driver with configuration.
*/
ret = usbd_init(&hid_cfg);
if (ret != HAL_OK) {
return;
}
/*
* 4. Initialize HID class driver. 512 is the transfer buffer size.
*/
ret = usbd_hid_init(512, &hid_usr_cb);
if (ret != HAL_OK) {
/* If class driver init fails, clean up the core driver */
usbd_deinit();
return;
}
热插拔事件处理
为了确保系统的健壮性,建议通过注册 status_changed 回调函数来监听 USB 的连接与断开事件。
备注
不要在中断回调(ISR)中直接执行耗时的资源释放或重新加载操作。建议使用信号量(Semaphore)通知专用的任务线程进行处理。
参考 设备连接状态检测 获取更多细节,下面是示例代码:
/* USB status change callback */
static usbd_hid_usr_cb_t hid_usr_cb = {
.status_changed = hid_cb_status_changed,
};
/* Callback executed in ISR context */
static void hid_cb_status_changed(u8 old_status, u8 status)
{
hid_attach_status = status;
rtos_sema_give(hid_attach_status_changed_sema);
}
/* Thread Context: Handle the state machine */
static void hid_hotplug_thread(void *param)
{
int ret = 0;
UNUSED(param);
for (;;) {
/* Wait for status change signal */
if (rtos_sema_take(hid_attach_status_changed_sema, RTOS_SEMA_MAX_COUNT) == RTK_SUCCESS) {
if (hid_attach_status == USBD_ATTACH_STATUS_DETACHED) {
RTK_LOGS(TAG, RTK_LOG_INFO, "DETACHED\n");
/* 1. Clean up HID class resources */
usbd_hid_deinit();
/* 2. De-initialize USB core */
ret = usbd_deinit();
if (ret != 0) {
break;
}
/* 3. Re-initialize for next connection */
ret = usbd_init(&hid_cfg);
if (ret != 0) {
break;
}
ret = usbd_hid_init(512, &hid_usr_cb);
if (ret != 0) {
usbd_deinit();
break;
}
} else if (hid_attach_status == USBD_ATTACH_STATUS_ATTACHED) {
RTK_LOGS(TAG, RTK_LOG_INFO, "ATTACHED\n");
} else {
RTK_LOGS(TAG, RTK_LOG_INFO, "INIT\n");
}
}
}
rtos_task_delete(NULL);
}
HID 报告发送流程 (Input Report)
当设备作为数据生产者(如鼠标移动、键盘按键)时,需主动向主机发送输入报告。发送流程:
等待设备就绪:监听
hid_cb_setup()回调触发的信号量,确保主机已完成枚举。构造报告数据:根据 HID 报告描述符定义的格式填充数据缓冲区。
发送数据:使用
usbd_hid_send_data()发送数据。
/* Mouse data structure (Defined by Report Descriptor) */
typedef struct {
u8 left; //left button. 0: release, 1: press
u8 right; //right button. 0: release, 1: press
u8 middle; //wheel button. 0: release, 1: press
char x_axis; //x-axis pixels. relative value from -127 to 127, positive for right and negative for left
char y_axis; //y-axis pixels. relative value from -127 to 127, positive for up and negative for down
char wheel; //scrolling units. relative value from -127 to 127, positive for up and negative for down.
} usbd_hid_mouse_data_t;
/* Mouse moving data */
static usbd_hid_mouse_data_t mdata[] = {
{0, 0, 0, 50, 0, 0}, //move the cursor 50 pixels to the right
{0, 0, 0, 0, 50, 0}, //move the cursor down 50 pixels
{0, 0, 0, -50, 0, 0}, //move the cursor 50 pixels to the left
{0, 0, 0, 0, -50, 0}, //move the cursor up 50 pixels
{0, 0, 0, 0, 0, 5}, //scroll up for 5 units
{0, 0, 0, 0, 0, -5}, //scroll down for 5 units
{0, 0, 1, 0, 0, 0}, //middle button pressed
{0, 0, 0, 0, 0, 0}, //middle button released
{0, 1, 0, 0, 0, 0}, //right button pressed
{0, 0, 0, 0, 0, 0}, //right button released
{0, 0, 0, -5, 0, 0}, //move the cursor 5 pixels to the left
{1, 0, 0, 0, 0, 0}, //left button pressed
{0, 0, 0, 0, 0, 0}, //left button released
};
/* Callback when device is configured by Host */
static void hid_cb_setup(void)
{
rtos_sema_give(hid_connect_sema);
}
/* Send function */
static void hid_send_device_data(void *pdata)
{
u8 byte[4];
usbd_hid_mouse_data_t *data = (usbd_hid_mouse_data_t *)pdata;
memset(byte, 0, 4);
if (data->left != 0) {
byte[0] |= USBD_HID_MOUSE_BUTTON_LEFT;
}
if (data->right != 0) {
byte[0] |= USBD_HID_MOUSE_BUTTON_RIGHT;
}
if (data->middle != 0) {
byte[0] |= USBD_HID_MOUSE_BUTTON_MIDDLE;
}
byte[0] |= USBD_HID_MOUSE_BUTTON_RESERVED;
byte[1] = data->x_axis;
byte[2] = data->y_axis;
byte[3] = data->wheel;
usbd_hid_send_data(byte, 4);
}
static void hid_send_data_func(void)
{
/* Wait for USB configured */
rtos_sema_take(hid_connect_sema, RTOS_SEMA_MAX_COUNT);
u32 array_len = sizeof(mdata) / sizeof(usbd_hid_mouse_data_t);
do {
for (i = 0; i < array_len; i++) {
/* Wait for previous transfer to complete */
rtos_sema_take(hid_transmit_sema, RTOS_SEMA_MAX_COUNT);
/* Send the mouse data out */
hid_send_device_data(&mdata[i]);
/* Force 1000ms of sleep to slow down movement */
rtos_time_delay_ms(1000);
}
rtos_time_delay_ms(5 * 1000); //next loop
} while (++loop < CONFIG_USBD_HID_CONSTANT_LOOP);
}
HID 报告接收流程 (Output Report)
当主机向设备发送控制指令(如点亮键盘 CapsLock 灯、手柄震动)时,设备端需通过回调函数处理输出报告。处理流程:
注册回调:在加载驱动时注册
hid_cb_received()。解析数据:在回调函数中读取数据长度及内容,并解析对应的 HID 报告 ID(如果存在)。
执行动作:解析协议载荷并控制相应硬件。
/* Define callbacks for HID receive. */
static usbd_hid_usr_cb_t hid_usr_cb = {
.received = hid_cb_received,
};
/* Callback for received data (executed in ISR context) */
static void hid_cb_received(u8 *buf, u32 len)
{
/* Example: Parse Keyboard LED status */
if (len == 1) {
u8 led_status = buf[0];
/* Control GPIO based on led_status bits (NumLock, CapsLock, etc.) */
}
}
备注
如需测试输出报告功能,请确保在 {SDK}/component/usb/device/hid/usbd_hid.h 中将 USBD_HID_DEVICE_TYPE 配置为支持双向通信的设备类型(如 USBD_HID_KEYBOARD_DEVICE)。
卸载驱动
在系统关机或不再需要 HID 功能时,应按加载的反序释放资源,以防止内存泄漏。
/* 1. Deinitialize HID class driver first */
usbd_hid_deinit();
/* 2. Deinitialize USB device core driver */
usbd_deinit();
运行方式
本节以一个 USB 鼠标模拟器 为例,演示如何将 Ameba 开发板配置为 USB HID 设备。
功能描述
设备类型:标准 USB HID 鼠标。
行为:连接 PC 后,开发板会自动模拟鼠标移动轨迹。
源码路径:
{SDK}/example/usb/usbd_hid,可为开发者设计自定义 USB 键鼠、游戏手柄等产品提供完整的参考方案。
配置与编译
编译与烧录
在 SDK 根目录下执行以下命令以配置环境,选择目标 SoC,编译工程,然后将生成的
Image文件烧录至开发板:# Initialize environment (required for every new terminal) source env.sh or env.bat(Windows system) # Select Target SoC (replace xxx with your specific SoCs) ameba.py soc xxx ameba.py build -a usbd_hid -p
Menuconfig 配置认
若编译失败,请执行
ameba.py menuconfig,确认已选择USBD HID。- Choose `CONFIG USB --->`: [*] Enable USB USB Mode (Device) ---> [*] HID
结果验证
启动设备
重启开发板,观察串口日志,应显示如下启动信息:
[HID-I] USBD HID demo start
连接主机
使用 USB 线缆将开发板连接至 PC(如 Windows 电脑)
功能测试
默认示例代码将开发板配置为 USB 鼠标。
观察现象:连接成功后,PC 屏幕上的鼠标光标将自动开始移动(移动轨迹由 Example 代码中的数组定义)。
数据流向:此过程验证了 设备 -> 主机 (Device to Host) 的输入报告(Input Report)传输功能。
备注
若光标未移动,请检查:
硬件连接:确认 USB 线缆已插好,且线缆支持数据传输(非仅充电线)。
设备冲突:检查是否有其他物理鼠标或虚拟鼠标驱动干扰了光标移动。
枚举状态:检查 PC 设备管理器中是否有带黄色感叹号的 USB 设备。
若修改了示例代码配置(USBD_HID_DEVICE_TYPE)为键盘设备,可进行以下双向通信测试。
上行输入测试 (Input Report)
打开 PC 上的任意文本编辑器(如记事本)。
开发板将自动模拟键盘输入字符(如 "aA"),并循环输出。
备注
若记事本里没有"aA"输入,请检查:
硬件连接:确认 USB 线缆已插好,且线缆支持数据传输(非仅充电线)。
设备冲突:检查是否有其他物理鼠标或虚拟鼠标驱动干扰了光标移动。
枚举状态:检查 PC 设备管理器中是否有带黄色感叹号的 USB 设备。
输入模式:请切换为英文输入法。其它输入法可能会显示输入弹出框。
下行输出测试 (Output Report)
此测试验证 主机 -> 设备 (Host to Device) 的控制报文传输。
在 PC 键盘上按下 “Caps Lock”(大写锁定)键。
观察开发板的串口日志。
预期结果:日志应打印接收到的控制报文
RX 1 byte(s): 0x02,根据 键盘输出报告,解析可知,其对应的即是 “Caps Lock”,证明设备成功获取了主机的输出报告。
备注
目前仅支持鼠标和键盘两种 HID 设备,若需支持其他设备,需在代码中替换相应的报告描述符(Report Descriptor)。