如何在USB HID报告中传输Unicode字符及实现细节
基于HID Unicode页的跨平台Unicode传输方案
根据《HID Usage Tables 1.5》中的Unicode页(0x10),确实存在跨操作系统的Unicode传输方案,直接映射UCS-2(与ISO/IEC 10646-1一致的16位Unicode编码),以下是具体实现细节:
一、8字节USB HID报告格式(UCS-2传输)
报告描述符设计
需定义使用Unicode页(0x05,0x10)的HID报告描述符,同时保留修饰键的比特掩码(兼容常规键盘的修饰键逻辑),示例描述符如下:
// 通用桌面页,定义设备为键盘类 0x05, 0x01, // Usage Page: Generic Desktop (0x01) 0x09, 0x06, // Usage: Keyboard (0x06) 0xA1, 0x01, // Collection: Application // 修饰键比特掩码(8位,对应左Ctrl/Shift/Alt/Gui、右Ctrl/Shift/Alt/Gui) 0x05, 0x07, // Usage Page: Keyboard/Keypad (0x07) 0x19, 0xE0, // Usage Minimum: Left Ctrl (0xE0) 0x29, 0xE7, // Usage Maximum: Right Gui (0xE7) 0x15, 0x00, // Logical Minimum: 0 0x25, 0x01, // Logical Maximum: 1 0x95, 0x08, // Report Count: 8 bits 0x75, 0x01, // Report Size: 1 bit per modifier 0x81, 0x02, // Input: Data, Variable, Absolute // 预留填充字节(保持报告对齐到8字节) 0x95, 0x01, // Report Count: 1 byte 0x75, 0x08, // Report Size: 8 bits 0x81, 0x03, // Input: Constant, Variable, Absolute // UCS-2 Unicode字符传输(2字节,小端/大端需与主机约定,通常小端) 0x05, 0x10, // Usage Page: Unicode (0x10) 0x19, 0x00, // Usage Minimum: U+0000 0x29, 0xFF, 0xFF, // Usage Maximum: U+FFFF 0x15, 0x00, // Logical Minimum: 0 0x26, 0xFF, 0xFF, // Logical Maximum: 0xFFFF 0x95, 0x02, // Report Count: 2 bytes (UCS-2) 0x75, 0x08, // Report Size: 8 bits per byte 0x81, 0x00, // Input: Data, Array, Absolute // 剩余填充字节(凑足8字节总长度) 0x95, 0x03, // Report Count: 3 bytes 0x75, 0x08, // Report Size: 8 bits 0x81, 0x03, // Input: Constant, Variable, Absolute 0xC0, // End Collection
报告示例(传输小写字母a,U+0061)
使用小端字节序存储UCS-2编码时,8字节报告如下:
uint8_t hid_report[8] = { 0x00, // 修饰键掩码:无修饰键 0x00, // 填充字节 0x61, // UCS-2低字节:0x61(对应U+0061的低8位) 0x00, // UCS-2高字节:0x00(对应U+0061的高8位) 0x00, // 填充字节 0x00, // 填充字节 0x00, // 填充字节 0x00 // 填充字节 };
二、比特掩码式报告中传输16位Unicode字符
如果采用按键状态比特掩码的布局(而非传统按键码数组),同时保留修饰键掩码,需调整报告描述符,将Unicode的16位编码作为独立变量字段:
调整后的报告描述符
0x05, 0x01, // Usage Page: Generic Desktop (0x01) 0x09, 0x06, // Usage: Keyboard (0x06) 0xA1, 0x01, // Collection: Application // 修饰键比特掩码(8位) 0x05, 0x07, // Usage Page: Keyboard/Keypad (0x07) 0x19, 0xE0, // Usage Minimum: Left Ctrl (0xE0) 0x29, 0xE7, // Usage Maximum: Right Gui (0xE7) 0x15, 0x00, // Logical Minimum: 0 0x25, 0x01, // Logical Maximum: 1 0x95, 0x08, // Report Count: 8 bits 0x75, 0x01, // Report Size: 1 bit 0x81, 0x02, // Input: Data, Variable, Absolute // Unicode字符按下状态掩码(1位:0=未按下,1=按下) 0x05, 0x10, // Usage Page: Unicode (0x10) 0x09, 0x01, // Usage: Unicode Character Select 0x15, 0x00, // Logical Minimum: 0 0x25, 0x01, // Logical Maximum: 1 0x95, 0x01, // Report Count: 1 bit 0x75, 0x01, // Report Size: 1 bit 0x81, 0x02, // Input: Data, Variable, Absolute // 填充位(凑足1字节) 0x95, 0x07, // Report Count: 7 bits 0x75, 0x01, // Report Size: 1 bit 0x81, 0x03, // Input: Constant, Variable, Absolute // UCS-2 Unicode编码(2字节,小端) 0x05, 0x10, // Usage Page: Unicode (0x10) 0x19, 0x00, // Usage Minimum: U+0000 0x29, 0xFF, 0xFF, // Usage Maximum: U+FFFF 0x15, 0x00, // Logical Minimum: 0 0x26, 0xFF, 0xFF, // Logical Maximum: 0xFFFF 0x95, 0x02, // Report Count: 2 bytes 0x75, 0x08, // Report Size: 8 bits 0x81, 0x00, // Input: Data, Array, Absolute // 剩余填充字节(凑足8字节) 0x95, 0x03, // Report Count: 3 bytes 0x75, 0x08, // Report Size: 8 bits 0x81, 0x03, // Input: Constant, Variable, Absolute 0xC0, // End Collection
报告示例(按下小写a,U+0061)
uint8_t hid_report[8] = { 0x00, // 修饰键掩码:无修饰键 0x01, // 第0位=1(Unicode字符按下),其余7位为填充0 0x61, // UCS-2低字节 0x00, // UCS-2高字节 0x00, // 填充字节 0x00, // 填充字节 0x00, // 填充字节 0x00 // 填充字节 };
释放时,将第1字节的第0位设为0即可。
三、传输UCS-2无法编码的Unicode字符
UCS-2仅覆盖U+0000到U+FFFF的字符,对于U+10000及以上的补充平面字符,需采用UTF-16代理对方案:
- 将目标Unicode字符拆分为高代理项(U+D800到U+DBFF)和低代理项(U+DC00到U+DFFF)两个16位编码单元
- 分两次发送HID报告,依次传输高代理项和低代理项
- 主机操作系统的HID驱动会自动将两个代理对组合为完整的补充平面字符
例如,传输字符𝄞(U+1D11E):
- 拆分后的代理对为U+D834(高代理)和U+DD1E(低代理)
- 先发送包含U+D834的报告,再发送包含U+DD1E的报告,主机将自动组合为原字符
内容的提问来源于stack exchange,提问作者'étale-cohomology
相关产品推荐
相关产品推荐

