HID 描述符 被用来告诉主机如何解析从设备接收到的数据。
HID 描述符示例
HID_INPUT_REPORT = bytes([
0x05, 0x0D, # Usage Page (Digitizer)
0x09, 0x01, # Usage (Digitizer)
0xA1, 0x01, # Collection (Application)
# Button Switches (4 bits)
0x09, 0x02, # Usage (Pen)
0xA1, 0x00, # Collection (Physical)
0x15, 0x00, # Logical Minimum (0)
0x25, 0x01, # Logical Maximum (1)
0x75, 0x01, # Report Size (1 bit)
0x95, 0x04, # Report Count (4 bits: Tip Switch, Barrel Switch, Eraser, Invert)
0x09, 0x42, # Usage (Tip Switch)
0x09, 0x44, # Usage (Barrel Switch)
0x09, 0x45, # Usage (Eraser)
0x09, 0x3C, # Usage (Invert)
0x81, 0x02, # Input (Data,Var,Abs)
# Pen In Range (1 bit)
0x95, 0x01, # Report Count (1)
0x09, 0x32, # Usage (In Range)
0x81, 0x02, # Input (Data,Var,Abs)
# X and Y Coordinates (16 bits each)
0x05, 0x01, # Usage Page (Generic Desktop Ctrls)
0x15, 0x00, # Logical Minimum (0)
0x26, 0xFF, 0x7F, # Logical Maximum (32767)
0x75, 0x10, # Report Size (16 bits)
0x95, 0x02, # Report Count (2: X, Y)
0x09, 0x30, # Usage (X)
0x09, 0x31, # Usage (Y)
0x81, 0x02, # Input (Data,Var,Abs)
# Pressure (16 bits)
0x05, 0x0D, # Usage Page (Digitizer)
0x09, 0x30, # Usage (Tip Pressure)
0x26, 0xFF, 0x1F, # Logical Maximum (8191)
0x95, 0x01, # Report Count (1)
0x81, 0x02, # Input (Data,Var,Abs)
# Tilt (X Tilt, Y Tilt, 16 bits each)
0x09, 0x3D, # Usage (X Tilt)
0x09, 0x3E, # Usage (Y Tilt)
0x16, 0xD8, 0xDC, # Logical Minimum (-9000)
0x26, 0x28, 0x23, # Logical Maximum (9000)
0x75, 0x10, # Report Size (16 bits)
0x95, 0x02, # Report Count (2: X Tilt, Y Tilt)
0x81, 0x02, # Input (Data,Var,Abs)
0xC0, # End Collection
0xC0 # End Collection
])
核心功能:
- 按钮开关:Tip Switch、Barrel Switch、Eraser、Invert。
- 笔尖位置:X 和 Y 坐标。
- 笔压检测。
- 倾斜角度:X Tilt 和 Y Tilt。
说明:
- 用途:该描述符定义了用于触控笔的输入报告结构,包含了常见的手写笔功能。
- 主要功能:
- 按钮状态:Tip Switch(笔尖按下)、Barrel Switch(侧键)、Eraser(橡皮擦模式)、Invert(反向模式)。
- 笔尖位置:X 和 Y 坐标,16 位精度(0 - 32767)。
- 笔压:检测笔的压力,范围为 0 - 8191。
- 倾斜检测:X 和 Y 轴的倾斜角度,范围为 -9000 到 9000。
适用场景:
- 数位板(Wacom 等):支持绘图、书写应用程序。
- Windows 或 Android 平板的手写笔:用于精确输入和绘图。
- BLE HID 设备:可用于 ESP32 等微控制器,作为 BLE HID 手写笔。
实际应用示例:Python 与 BLE HID 使用
假设你有一个 ESP32 BLE 设备,它作为手写板的 BLE HID 设备来模拟触控笔。以下是 Python 代码片段,演示如何使用这个 HID 描述符,向主机发送触控笔的输入数据:
from ble_hid import HIDService
import time
# 假设 ble_hid 是 BLE HID 的库
hid_service = HIDService(descriptor=HID_INPUT_REPORT) # 使用定义的 HID 描述符
hid_service.start()
# 发送模拟数据,比如 (X, Y) 坐标, 压力, 按钮状态
while True:
x_pos = 10000 # 模拟 X 坐标
y_pos = 5000 # 模拟 Y 坐标
pressure = 1024 # 模拟笔压
buttons = 0b0001 # 模拟按钮按下 (Tip Switch)
# 构建 HID 数据包
input_report = [
buttons, # 4 bits for buttons state
0b0001, # in range
(x_pos & 0xFF), (x_pos >> 8), # X 坐标, 低字节在前
(y_pos & 0xFF), (y_pos >> 8), # Y 坐标, 低字节在前
(pressure & 0xFF), (pressure >> 8), # 笔压, 低字节在前
0, 0 # Tilt 数据, 可以设置为 0
]
# 发送输入报告
hid_service.send_report(bytes(input_report))
time.sleep(0.01)
解释:
- HID 描述符 被用来告诉主机如何解析从设备接收到的数据。
- 构建数据包:
buttons
用于描述触控笔的按钮状态(例如 Tip Switch 是否按下)。x_pos
和y_pos
是 X 和 Y 的坐标位置。pressure
是笔的压力值。
- 发送数据:将构建好的数据包发送到主机,主机解析后可以显示触控笔的动作。
总结
这个 HID 描述符适用于任何需要高精度输入、压力感应和按钮功能的设备,如触控笔、手写板、数位板等。通过使用 HID 描述符,设备可以以标准化的方式与操作系统通信,从而支持多种绘图和书写应用。
按需增加以下功能内容
1. 报告 ID (Report ID)
0x85, 0x01, # Report ID (1)
原因:默认 HID 描述符在简单示例中可以省略 Report ID,尤其是单一报告时不需要特意指定。
2. 无用的常量输入位
0x95, 0x01, # Report Count (1)
0x81, 0x03, # Input (Const,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
0x95, 0x02, # Report Count (2)
0x81, 0x03, # Input (Const,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
原因:这些常量输入位用于填补报告字节对齐,对于精简版来说并非必需。
3. 单位和物理单位描述 (Unit, Unit Exponent)
0x65, 0x11, # Unit (System: SI Linear, Length: Centimeter)
0x55, 0x0F, # Unit Exponent (-1)
0x45, 0x73, # Physical Maximum (115)
0x65, 0x00, # Unit (None)
0x55, 0x00, # Unit Exponent (0)
原因:这些字段用于定义物理单位和单位指数。在大多数应用中,这些描述并不必要,尤其是在纯逻辑输入情况下。
4. 特定的 X 和 Y 坐标的物理最小值和最大值
0x35, 0x00, # Physical Minimum (0)
0x36, 0xD8, 0xDC, # Physical Minimum (-9000)
0x46, 0x28, 0x23, # Physical Maximum (9000)
原因:物理坐标最小和最大值对 HID 设备报告并非必要,因为实际输入软件通常会重新定义物理映射。
5. 部分开关和报告(如鼠标在范围内)
0x09, 0x32, # Usage (In Range)
0x95, 0x01, # Report Count (1)
0x81, 0x02, # Input (Data,Var,Abs)
原因:In Range 开关用来检测笔是否在设备感应范围内,这在简化版本中被整合为状态位。
6. 一些复杂的使用页和单位设置
0x65, 0x14, # Unit (System: English Rotation, Length: Centimeter)
0x55, 0x0E, # Unit Exponent (-2)
原因:这些字段用于描述物理单位和单位转换,通常在标准 HID 描述符中可以省略。
实际例子
1. Windows 触控屏设备中的手写笔
在 Windows 平板(如 Surface)上,用户经常使用带有多功能按钮的触控笔进行书写、绘画等操作。这种触控笔支持多种功能,如:
- 书写和绘图:通过检测 X、Y 坐标和笔尖压力来确定笔在屏幕上的位置和压力。
- 倾斜检测:在绘图应用(如 Photoshop、Krita)中,检测笔的倾斜角度,用于控制画笔的粗细和方向。
- 按钮功能:支持橡皮擦、快捷操作按钮(如翻转到橡皮擦模式、触发右键等)。
这些操作都需要依赖于 HID 描述符提供的标准化输入报告来告诉操作系统和应用程序如何解释从设备接收到的数据。
2. iPad 或 Android 平板中的手写笔(如 Apple Pencil、Samsung S Pen)
Apple Pencil 和 Samsung S Pen 等设备在 iPad 和 Galaxy Tab 中也使用类似的 HID 描述符。它们不仅检测到 X 和 Y 坐标,还支持:
- 压力感应:用于调节笔触的粗细。
- 按钮功能:支持多种操作,比如通过按钮切换绘图工具或启用橡皮擦模式。
- 倾斜感应:可以检测笔的倾斜角度,影响绘图效果,比如模拟真实铅笔的斜着画阴影的效果。
3. 数位板(如 Wacom 手绘板、XP-Pen、Huion)
Wacom、XP-Pen 和 Huion 等数位板设备使用类似的 HID 描述符与计算机进行通信。这些设备通常在绘画、设计、CAD 制图等领域广泛应用。设备的功能包括:
- 高精度绘图:根据 X、Y 坐标和笔压传感器的输入,实现精准的绘图和书写体验。
- 快捷按钮:许多触控笔带有按钮,可以模拟键盘快捷键(如 Ctrl+Z 撤销)。
- Tilt 支持:在某些高级型号中,支持笔的倾斜检测,用于增强绘画的表现力。