要实现带指示灯的键盘,有两种方式
set_report
类特殊请求实现。set_report
类特殊请求实现typedef enum
{
HID_REQ_CONTROL_GET_REPORT = 0x01, ///< Get Report
HID_REQ_CONTROL_GET_IDLE = 0x02, ///< Get Idle
HID_REQ_CONTROL_GET_PROTOCOL = 0x03, ///< Get Protocol
HID_REQ_CONTROL_SET_REPORT = 0x09, ///< Set Report
HID_REQ_CONTROL_SET_IDLE = 0x0a, ///< Set Idle
HID_REQ_CONTROL_SET_PROTOCOL = 0x0b ///< Set Protocol
}hid_request_enum_t;
发送到接口的类特殊请求 SET_REPORT
的 bRequest
,为 0x09,对应的 wValue 有不同的含义
报告类型有如下几种形式
typedef enum
{
HID_REPORT_TYPE_INVALID = 0,
HID_REPORT_TYPE_INPUT, ///< Input
HID_REPORT_TYPE_OUTPUT, ///< Output
HID_REPORT_TYPE_FEATURE ///< Feature
}hid_report_type_t;
0x21 0x9 0x0 0x2 0x0 0x0 0x1 0x0
此类特殊请求表示主机有一次 OUT 事务,主机输出一个字节的数据。需要注意的是,这里主机输出的数据传输到了控制端点上
。
这一个字节的数据各个位的含义如下:
typedef enum
{
KEYBOARD_LED_NUMLOCK = BIT(0), ///< Num Lock LED
KEYBOARD_LED_CAPSLOCK = BIT(1), ///< Caps Lock LED
KEYBOARD_LED_SCROLLLOCK = BIT(2), ///< Scroll Lock LED
KEYBOARD_LED_COMPOSE = BIT(3), ///< Composition Mode
KEYBOARD_LED_KANA = BIT(4) ///< Kana mode
}hid_keyboard_led_bm_t;
根据控制端点的数据,解析相应的位,控制 LED 灯的亮灭即可。
除控制端点和输入端点外,额外增加一个输出端点实现,那么端点描述符需要增加一个输出端点的描述符,相应的配置描述符集合需要修改。
增加一个输出端点之后,配置描述符集合的结构就变为
{
配置描述符,
接口描述符,
类特殊描述符(HID 描述符),
输入端点描述符,
输出端点描述符
}
设备描述符,字符串描述符等保持不变。
则设备返回的配置描述符集合为:
0x9 0x2 0x29 0x0 0x1 0x1 0x0 0xa0 0x32 0x9 0x4 0x0 0x0 0x2 0x3 0x1 0x1 0x0 0x9 0x21 0x11 0x1 0x0 0x1 0x22 0x41 0x0 0x7 0x5 0x81 0x3 0x8 0x0 0xa 0x7 0x5 0x1 0x3 0x8 0x0 0xa
键盘代码为 0x01
,鼠标代码为 0x02。0x1 0x0 0x0 0x0 0x0 0x0 0x0 0x0
最低位各个 bit 的含义
typedef enum
{
KEYBOARD_LED_NUMLOCK = BIT(0), ///< Num Lock LED
KEYBOARD_LED_CAPSLOCK = BIT(1), ///< Caps Lock LED
KEYBOARD_LED_SCROLLLOCK = BIT(2), ///< Scroll Lock LED
KEYBOARD_LED_COMPOSE = BIT(3), ///< Composition Mode
KEYBOARD_LED_KANA = BIT(4) ///< Kana mode
}hid_keyboard_led_bm_t;
上面设置输出端点的最大包长为 8 ,这里输出端点收到的数据有 8 个字节,最低为即为有效位。根据第一个字节的各个 bit 判断类型,设置相应的 LED 即可。