feat(usb_hid): 重构USB HID模块状态管理并优化电源管理
- 修改USB HID事件结构,将enable字段替换为stack_state枚举, 区分VBUS连接状态和协议栈启用状态 - 更新日志和分析器中的字段映射,正确显示栈状态而非布尔使能值 - 添加电源管理限制功能,在USB连接时保持系统活跃状态 - 重构LED输入报告处理逻辑,支持引导和NKRO设备的报告解析 - 调整USB连接状态变更逻辑,仅反映VBUS连接情况 - 将power_manager超时配置从300秒调整为30秒以优化响应速度 BREAKING CHANGE: USB HID事件结构中的enable字段已替换为stack_state枚举类型
This commit is contained in:
@@ -5,9 +5,13 @@ static const char *const usb_hid_evt_type_name[] = {
|
||||
};
|
||||
|
||||
static const char *const usb_hid_usbd_state_name[] = {
|
||||
[USB_HID_USBD_DISCONNECTED] = "DISCONNECTED",
|
||||
[USB_HID_USBD_CONNECTED] = "CONNECTED",
|
||||
[USB_HID_USBD_SUSPENDED] = "SUSPENDED",
|
||||
[USB_HID_USBD_VBUS_DISCONNECTED] = "VBUS_DISCONNECTED",
|
||||
[USB_HID_USBD_VBUS_CONNECTED] = "VBUS_CONNECTED",
|
||||
};
|
||||
|
||||
static const char *const usb_hid_stack_state_name[] = {
|
||||
[USB_HID_STACK_DISABLED] = "DISABLED",
|
||||
[USB_HID_STACK_ENABLED] = "ENABLED",
|
||||
};
|
||||
|
||||
static void log_usb_hid_event(const struct app_event_header *aeh)
|
||||
@@ -16,10 +20,11 @@ static void log_usb_hid_event(const struct app_event_header *aeh)
|
||||
|
||||
__ASSERT_NO_MSG(event->evt_type < ARRAY_SIZE(usb_hid_evt_type_name));
|
||||
__ASSERT_NO_MSG(event->usbd_state < ARRAY_SIZE(usb_hid_usbd_state_name));
|
||||
__ASSERT_NO_MSG(event->stack_state < ARRAY_SIZE(usb_hid_stack_state_name));
|
||||
|
||||
APP_EVENT_MANAGER_LOG(aeh, "type=%s en=%u usbd=%s",
|
||||
APP_EVENT_MANAGER_LOG(aeh, "type=%s stack=%s usbd=%s",
|
||||
usb_hid_evt_type_name[event->evt_type],
|
||||
event->enable,
|
||||
usb_hid_stack_state_name[event->stack_state],
|
||||
usb_hid_usbd_state_name[event->usbd_state]);
|
||||
}
|
||||
|
||||
@@ -29,7 +34,7 @@ static void profile_usb_hid_event(struct log_event_buf *buf,
|
||||
const struct usb_hid_event *event = cast_usb_hid_event(aeh);
|
||||
|
||||
nrf_profiler_log_encode_uint8(buf, (uint8_t)event->evt_type);
|
||||
nrf_profiler_log_encode_uint8(buf, (uint8_t)event->enable);
|
||||
nrf_profiler_log_encode_uint8(buf, (uint8_t)event->stack_state);
|
||||
nrf_profiler_log_encode_uint8(buf, (uint8_t)event->usbd_state);
|
||||
}
|
||||
|
||||
@@ -37,7 +42,7 @@ APP_EVENT_INFO_DEFINE(usb_hid_event,
|
||||
ENCODE(NRF_PROFILER_ARG_U8,
|
||||
NRF_PROFILER_ARG_U8,
|
||||
NRF_PROFILER_ARG_U8),
|
||||
ENCODE("evt_type", "enable", "usbd"),
|
||||
ENCODE("evt_type", "stack", "usbd"),
|
||||
profile_usb_hid_event);
|
||||
|
||||
APP_EVENT_TYPE_DEFINE(usb_hid_event,
|
||||
|
||||
@@ -11,18 +11,23 @@ enum usb_hid_event_type {
|
||||
USB_HID_EVT_STATE_REPORT = 0,
|
||||
};
|
||||
|
||||
/* USB 连接层状态(偏“链路可用性”) */
|
||||
/* 仅反映 VBUS 连接状态。 */
|
||||
enum usb_hid_usbd_state {
|
||||
USB_HID_USBD_DISCONNECTED = 0,
|
||||
USB_HID_USBD_CONNECTED,
|
||||
USB_HID_USBD_SUSPENDED,
|
||||
USB_HID_USBD_VBUS_DISCONNECTED = 0,
|
||||
USB_HID_USBD_VBUS_CONNECTED,
|
||||
};
|
||||
|
||||
/* USB HID 协议栈启停状态。 */
|
||||
enum usb_hid_stack_state {
|
||||
USB_HID_STACK_DISABLED = 0,
|
||||
USB_HID_STACK_ENABLED,
|
||||
};
|
||||
|
||||
struct usb_hid_event {
|
||||
struct app_event_header header;
|
||||
|
||||
enum usb_hid_event_type evt_type;
|
||||
bool enable;
|
||||
enum usb_hid_stack_state stack_state;
|
||||
enum usb_hid_usbd_state usbd_state;
|
||||
};
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
#include <app_event_manager.h>
|
||||
#include <caf/events/power_event.h>
|
||||
#include <caf/events/power_manager_event.h>
|
||||
|
||||
#define MODULE usb_hid
|
||||
#include <caf/events/module_state_event.h>
|
||||
@@ -56,13 +57,13 @@ struct usb_hid_ctx {
|
||||
|
||||
enum usb_hid_usbd_state usbd_state;
|
||||
enum hid_protocol_type current_protocol;
|
||||
bool num_lock_known;
|
||||
bool num_lock_on;
|
||||
enum power_manager_level pm_restrict_level;
|
||||
};
|
||||
|
||||
static struct usb_hid_ctx g_usb_hid = {
|
||||
.usbd_state = USB_HID_USBD_DISCONNECTED,
|
||||
.usbd_state = USB_HID_USBD_VBUS_DISCONNECTED,
|
||||
.current_protocol = HID_PROTO_REPORT,
|
||||
.pm_restrict_level = POWER_MANAGER_LEVEL_MAX,
|
||||
};
|
||||
|
||||
USBD_DEVICE_DEFINE(new_kbd_usbd,
|
||||
@@ -83,40 +84,88 @@ static void publish_usb_hid_state(void)
|
||||
struct usb_hid_event *event = new_usb_hid_event();
|
||||
|
||||
event->evt_type = USB_HID_EVT_STATE_REPORT;
|
||||
event->enable = g_usb_hid.stack_enabled;
|
||||
event->stack_state = g_usb_hid.stack_enabled ?
|
||||
USB_HID_STACK_ENABLED : USB_HID_STACK_DISABLED;
|
||||
event->usbd_state = g_usb_hid.usbd_state;
|
||||
APP_EVENT_SUBMIT(event);
|
||||
}
|
||||
|
||||
/* 从主机输出报告同步 Num Lock 位,并在状态变化时发布事件。 */
|
||||
static void publish_num_lock_state_from_led_mask(uint8_t led_mask)
|
||||
/* 统一入口仅处理单字节 LED 报告并发布事件。 */
|
||||
static void process_usb_led_input_report(uint8_t led_report)
|
||||
{
|
||||
bool new_num_lock = (led_mask & BIT(0)) != 0U;
|
||||
|
||||
if (g_usb_hid.num_lock_known && (g_usb_hid.num_lock_on == new_num_lock)) {
|
||||
return;
|
||||
}
|
||||
|
||||
g_usb_hid.num_lock_known = true;
|
||||
g_usb_hid.num_lock_on = new_num_lock;
|
||||
|
||||
struct keyboard_led_state_event *event = new_keyboard_led_state_event();
|
||||
|
||||
event->led_mask = led_mask;
|
||||
event->num_lock = new_num_lock;
|
||||
event->led_mask = led_report;
|
||||
event->num_lock = (led_report & BIT(0)) != 0U;
|
||||
APP_EVENT_SUBMIT(event);
|
||||
}
|
||||
|
||||
static bool should_handle_led_input_from_dev(const struct device *dev)
|
||||
{
|
||||
if (g_usb_hid.current_protocol == HID_PROTO_BOOT)
|
||||
return (dev == g_usb_hid.boot_dev);
|
||||
|
||||
return (dev == g_usb_hid.nkro_dev);
|
||||
}
|
||||
|
||||
static bool try_extract_led_mask(const struct device *dev,
|
||||
uint16_t len,
|
||||
const uint8_t *buf,
|
||||
uint8_t *led_mask)
|
||||
{
|
||||
if ((buf == NULL) || (len == 0U))
|
||||
return false;
|
||||
|
||||
if (dev == g_usb_hid.boot_dev) {
|
||||
*led_mask = buf[0];
|
||||
return true;
|
||||
}
|
||||
|
||||
if (dev != g_usb_hid.nkro_dev)
|
||||
return false;
|
||||
|
||||
if (len >= 2U) {
|
||||
if (buf[0] != REPORT_ID_KEYBOARD)
|
||||
return false;
|
||||
|
||||
*led_mask = buf[1];
|
||||
return true;
|
||||
}
|
||||
|
||||
*led_mask = buf[0];
|
||||
return true;
|
||||
}
|
||||
|
||||
static void recompute_hid_state(void)
|
||||
{
|
||||
/* 兼容现有调用点:对外仅发布 enable + usbd 状态。 */
|
||||
publish_usb_hid_state();
|
||||
}
|
||||
|
||||
/*
|
||||
* USB 自动休眠策略:
|
||||
* - 只要检测到 USB 线已连接(USBD 状态非 DISCONNECTED),限制系统保持 ALIVE;
|
||||
* - USB 线断开后,恢复为 MAX,允许系统按原有超时策略自动休眠。
|
||||
*/
|
||||
static void refresh_usb_power_restrict(void)
|
||||
{
|
||||
enum power_manager_level target =
|
||||
(g_usb_hid.usbd_state == USB_HID_USBD_VBUS_DISCONNECTED) ?
|
||||
POWER_MANAGER_LEVEL_MAX : POWER_MANAGER_LEVEL_ALIVE;
|
||||
|
||||
if (g_usb_hid.pm_restrict_level == target) {
|
||||
return;
|
||||
}
|
||||
|
||||
g_usb_hid.pm_restrict_level = target;
|
||||
power_manager_restrict(MODULE_IDX(MODULE), target);
|
||||
}
|
||||
|
||||
static void set_usbd_state(enum usb_hid_usbd_state state)
|
||||
{
|
||||
if (g_usb_hid.usbd_state != state) {
|
||||
g_usb_hid.usbd_state = state;
|
||||
refresh_usb_power_restrict();
|
||||
publish_usb_hid_state();
|
||||
}
|
||||
}
|
||||
@@ -137,14 +186,22 @@ static int hid_stub_set_report(const struct device *dev,
|
||||
uint8_t type, uint8_t id,
|
||||
uint16_t len, const uint8_t *buf)
|
||||
{
|
||||
ARG_UNUSED(dev);
|
||||
ARG_UNUSED(type);
|
||||
ARG_UNUSED(id);
|
||||
|
||||
if ((len > 0U) && (buf != NULL)) {
|
||||
publish_num_lock_state_from_led_mask(buf[0]);
|
||||
if (!should_handle_led_input_from_dev(dev)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t led_mask;
|
||||
|
||||
if (!try_extract_led_mask(dev, len, buf, &led_mask)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
LOG_INF("hid_stub_set_report led_mask=0x%02x", led_mask);
|
||||
process_usb_led_input_report(led_mask);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -212,11 +269,18 @@ static void hid_stub_input_done(const struct device *dev, const uint8_t *report)
|
||||
|
||||
static void hid_stub_output_report(const struct device *dev, uint16_t len, const uint8_t *buf)
|
||||
{
|
||||
ARG_UNUSED(dev);
|
||||
|
||||
if ((len > 0U) && (buf != NULL)) {
|
||||
publish_num_lock_state_from_led_mask(buf[0]);
|
||||
if (!should_handle_led_input_from_dev(dev)) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t led_mask;
|
||||
|
||||
if (!try_extract_led_mask(dev, len, buf, &led_mask)) {
|
||||
return;
|
||||
}
|
||||
|
||||
LOG_INF("hid_stub_output_report led_mask=0x%02x", led_mask);
|
||||
process_usb_led_input_report(led_mask);
|
||||
}
|
||||
|
||||
static void hid_iface_ready_cb(const struct device *dev, bool ready)
|
||||
@@ -236,7 +300,6 @@ static void hid_iface_ready_cb(const struct device *dev, bool ready)
|
||||
}
|
||||
|
||||
if (ready) {
|
||||
set_usbd_state(USB_HID_USBD_CONNECTED);
|
||||
/* 连接可用后同步一次当前协议,让 keyboard_module 与传输侧编码一致。 */
|
||||
struct hid_protocol_event *event = new_hid_protocol_event();
|
||||
|
||||
@@ -285,7 +348,7 @@ static void usbd_msg_cb(struct usbd_context *const usbd_ctx,
|
||||
{
|
||||
switch (msg->type) {
|
||||
case USBD_MSG_VBUS_READY:
|
||||
set_usbd_state(USB_HID_USBD_CONNECTED);
|
||||
set_usbd_state(USB_HID_USBD_VBUS_CONNECTED);
|
||||
/*
|
||||
* 只有在 USB 模式下才允许拉起 USB 栈。
|
||||
* 这样即使插着线,只要用户切到 BLE/2.4G,也不会强制进入 USB HID。
|
||||
@@ -296,19 +359,19 @@ static void usbd_msg_cb(struct usbd_context *const usbd_ctx,
|
||||
break;
|
||||
|
||||
case USBD_MSG_VBUS_REMOVED:
|
||||
set_usbd_state(USB_HID_USBD_DISCONNECTED);
|
||||
set_usbd_state(USB_HID_USBD_VBUS_DISCONNECTED);
|
||||
break;
|
||||
|
||||
case USBD_MSG_SUSPEND:
|
||||
set_usbd_state(USB_HID_USBD_SUSPENDED);
|
||||
publish_usb_hid_state();
|
||||
break;
|
||||
|
||||
case USBD_MSG_RESUME:
|
||||
set_usbd_state(USB_HID_USBD_CONNECTED);
|
||||
publish_usb_hid_state();
|
||||
break;
|
||||
|
||||
case USBD_MSG_CONFIGURATION:
|
||||
set_usbd_state(USB_HID_USBD_CONNECTED);
|
||||
publish_usb_hid_state();
|
||||
break;
|
||||
|
||||
case USBD_MSG_UDC_ERROR:
|
||||
@@ -493,7 +556,7 @@ static int usb_hid_set_enabled(bool enable)
|
||||
g_usb_hid.raw_iface_ready = false;
|
||||
g_usb_hid.boot_in_flight = false;
|
||||
g_usb_hid.nkro_in_flight = false;
|
||||
set_usbd_state(USB_HID_USBD_DISCONNECTED);
|
||||
publish_usb_hid_state();
|
||||
}
|
||||
|
||||
if (err && (err != -EALREADY)) {
|
||||
@@ -504,7 +567,6 @@ static int usb_hid_set_enabled(bool enable)
|
||||
}
|
||||
|
||||
recompute_hid_state();
|
||||
publish_usb_hid_state();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -538,6 +600,7 @@ static bool handle_module_state_event(const struct module_state_event *event)
|
||||
return false;
|
||||
}
|
||||
|
||||
refresh_usb_power_restrict();
|
||||
module_set_state(MODULE_STATE_READY);
|
||||
publish_usb_hid_state();
|
||||
return false;
|
||||
@@ -596,14 +659,9 @@ static bool handle_hid_report_event(const struct hid_report_event *event)
|
||||
const uint8_t *payload = event->dyndata.data;
|
||||
size_t payload_len = event->dyndata.size;
|
||||
|
||||
report_id = REPORT_ID_KEYBOARD;
|
||||
|
||||
if (!g_usb_hid.boot_iface_ready || !g_usb_hid.boot_dev) {
|
||||
return false;
|
||||
}
|
||||
if (report_id != REPORT_ID_KEYBOARD) {
|
||||
return false;
|
||||
}
|
||||
if (g_usb_hid.boot_in_flight) {
|
||||
LOG_WRN("Drop boot report: previous report not sent");
|
||||
return false;
|
||||
|
||||
Reference in New Issue
Block a user