Rust USB HID描述符生成库usbd-hid-descriptors的使用,轻松创建符合规范的USB人机接口设备描述符
Rust USB HID描述符生成库usbd-hid-descriptors的使用,轻松创建符合规范的USB人机接口设备描述符
安装
在项目目录中运行以下Cargo命令:
cargo add usbd-hid-descriptors
或者在Cargo.toml中添加以下行:
usbd-hid-descriptors = "0.8.2"
基本使用
usbd-hid-descriptors
库可以帮助你轻松生成符合规范的USB HID描述符。以下是一个完整的示例demo:
use usbd_hid_descriptors::*;
// 定义HID报告描述符
#[gen_hid_descriptor(
(collection = APPLICATION, usage_page = GENERIC_DESKTOP, usage = KEYBOARD) = {
// 键盘修饰键 (Ctrl, Shift, Alt等)
(usage_page = KEYBOARD, usage_min = 0xE0, usage_max = 0xE7) = {
#[packed_bits 8] #[item_settings data,variable,absolute] modifier=input;
};
// 保留字节
(usage_page = KEYBOARD, usage_min = 0x00, usage_max = 0x00) = {
#[item_settings constant,variable,absolute] reserved=input;
};
// 键盘按键码
(usage_page = KEYBOARD, usage_min = 0x00, usage_max = 0xFF) = {
#[item_settings data,array,absolute] keycodes=input;
};
// LED输出报告 (Num Lock, Caps Lock等)
(usage_page = LEDS, usage_min = 0x01, usage_max = 0x05) = {
#[packed_bits 5] #[item_settings data,variable,absolute] leds=output;
#[item_settings constant,variable,absolute] padding=output;
};
}
)]
#[allow(dead_code)]
pub struct KeyboardReport {
pub modifier: u8,
pub reserved: u8,
pub keycodes: [u8; 6],
pub leds: u8,
}
fn main() {
// 获取生成的HID报告描述符
let descriptor = KeyboardReport::desc();
// 使用描述符初始化USB HID设备
// (实际使用中需要结合具体的USB设备库)
println!("HID描述符: {:?}", descriptor);
}
功能说明
- 使用
#[gen_hid_descriptor]
宏可以方便地定义HID报告描述符 - 支持定义输入(input)和输出(output)报告
- 可以指定使用情况页(usage_page)和使用情况(usage)
- 支持位打包(packed_bits)和数组类型的数据
- 自动生成符合HID规范的描述符字节
完整示例
下面是一个更完整的示例,展示如何定义鼠标HID报告:
use usbd_hid_descriptors::*;
// 定义鼠标HID报告描述符
#[gen_hid_descriptor(
(collection = APPLICATION, usage_page = GENERIC_DESKTOP, usage = MOUSE) = {
(usage_page = BUTTON, usage_min = 0x01, usage_max = 0x08) = {
#[packed_bits 8] #[item_settings data,variable,absolute] buttons=input;
};
(usage_page = GENERIC_DESKTOP,) = {
(usage = X,) = {
#[item_settings data,variable,relative] x=input;
};
(usage = Y,) = {
#[item_settings data,variable,relative] y=input;
};
(usage = WHEEL,) = {
#[item_settings data,variable,relative] wheel=input;
};
};
}
)]
#[allow(dead_code)]
pub struct MouseReport {
pub buttons: u8,
pub x: i8,
pub y: i8,
pub wheel: i8,
}
fn main() {
// 获取生成的鼠标HID报告描述符
let descriptor = MouseReport::desc();
println!("鼠标HID描述符: {:?}", descriptor);
// 创建鼠标报告实例
let report = MouseReport {
buttons: 0,
x: 10,
y: -5,
wheel: 0,
};
// 在实际应用中,这里会将报告发送给USB主机
println!("发送鼠标报告: 按钮={}, X={}, Y={}, 滚轮={}",
report.buttons, report.x, report.y, report.wheel);
}
这个库特别适合嵌入式开发,可以与usb-device
等Rust USB设备栈配合使用,轻松创建符合规范的USB HID设备。
1 回复
Rust USB HID描述符生成库usbd-hid-descriptors使用指南
简介
usbd-hid-descriptors
是一个Rust库,用于简化符合规范的USB人机接口设备(HID)描述符的创建过程。它提供了一种类型安全的方式来定义HID报告描述符,避免了手动编写二进制描述符的繁琐和容易出错的问题。
主要特性
- 类型安全的HID描述符构建
- 支持多种HID设备类型(键盘、鼠标、游戏控制器等)
- 自动计算描述符大小和报告长度
- 与
usb-device
生态系统良好集成
完整示例代码
下面是一个完整的USB HID键盘设备实现示例:
use usb_device::prelude::*;
use usbd_hid::hid_class::HIDClass;
use usbd_hid_descriptors::KeyboardReport;
// 定义键盘报告结构
#[repr(C)]
#[derive(Clone, Copy)]
struct KeyboardReport {
modifier: u8, // 修饰键状态 (Ctrl, Alt, Shift等)
reserved: u8, // 保留字节
keycodes: [u8; 6], // 当前按下的键码
}
impl KeyboardReport {
pub fn new() -> Self {
KeyboardReport {
modifier: 0,
reserved: 0,
keycodes: [0; 6],
}
}
}
impl Default for KeyboardReport {
fn default() -> Self {
Self::new()
}
}
// 实现HidReport trait
impl usbd_hid_descriptors::HidReport for KeyboardReport {
const ID: u8 = 1;
const DESCRIPTOR: &'static [u8] = usbd_hid_descriptors::gen_hid_descriptor!(
usage_page = GENERIC_DESKTOP,
usage = KEYBOARD,
collection = APPLICATION {
// 修饰键 (Ctrl, Alt, Shift等)
usage_page = KEYBOARD,
usage_min = 0xE0,
usage_max = 0xE7,
logical_min = 0,
logical_max = 1,
report_size = 1,
report_count = 8,
input = DATA_VAR_ABS,
// 保留位
report_size = 8,
report_count = 1,
input = CONSTANT,
// 普通按键
usage_page = KEYBOARD,
usage_min = 0,
usage_max = 101,
logical_min = 0,
logical_max = 101,
report_size = 8,
report_count = 6,
input = DATA_ARRAY,
}
);
}
fn main() -> Result<(), usb_device::UsbError> {
// 初始化USB总线 (具体实现取决于硬件平台)
let usb_bus = UsbBus::new(/* 硬件特定初始化 */);
// 创建HID类实例
let hid = HIDClass::new(&usb_bus, KeyboardReport::desc(), 10);
// 构建USB设备
let mut usb_dev = UsbDeviceBuilder::new(&usb_bus, UsbVidPid(0x1234, 0x5678))
.manufacturer("Rust HID Demo")
.product("HID Keyboard")
.serial_number("1.0")
.device_class(0)
.build();
// 主循环
loop {
// 处理USB事件
usb_dev.poll(&mut [&mut hid]);
// 模拟按下字母'a'键 (键码0x04)
let report = KeyboardReport {
modifier: 0,
reserved: 0,
keycodes: [0x04, 0, 0, 0, 0, 0],
};
// 发送键盘报告
hid.push_input(&report)?;
// 短暂延迟
cortex_m::asm::delay(1_000_000);
// 发送释放所有键的报告
let release_report = KeyboardReport::new();
hid.push_input(&release_report)?;
cortex_m::asm::delay(1_000_000);
}
}
代码说明
-
键盘报告结构:
modifier
字段表示修饰键状态reserved
是必须的保留字节keycodes
数组存储当前按下的键码
-
HID描述符:
- 使用
gen_hid_descriptor!
宏定义键盘的报告描述符 - 描述符定义了修饰键、保留位和普通按键的布局
- 自动生成符合USB HID规范的二进制描述符
- 使用
-
USB设备初始化:
- 创建USB总线实例(具体实现取决于硬件)
- 初始化HID类并指定键盘报告描述符
- 配置USB设备的基本信息(Vendor ID, Product ID等)
-
主循环:
- 定期调用
poll()
处理USB事件 - 构造键盘报告并发送
- 示例中模拟了按下和释放字母’a’键的操作
- 定期调用
注意事项
- 实际使用时需要根据具体硬件平台实现USB总线初始化
- 键码定义参考USB HID使用表
- 在嵌入式系统中使用时需考虑内存限制
- 复杂的HID设备可能需要定义多个报告描述符