Skip to content

Commit 10cd2b9

Browse files
alstrzebonskirlubos
authored andcommitted
applications: nrf_desktop: Align behavior on USB disconnection
Adds power manager restriction and forces power down on USB disconnected event for consistency as it can also be done on disconnection by USB suspended event. Adds option to delay system off after USB disconnection by few seconds to allow user to take actions like restart advertising without going through reboot. Jira: NCSDK-17701 Signed-off-by: Aleksander Strzebonski <[email protected]>
1 parent c36e56e commit 10cd2b9

File tree

2 files changed

+58
-3
lines changed

2 files changed

+58
-3
lines changed

applications/nrf_desktop/src/modules/Kconfig.usb_state

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,21 @@ config DESKTOP_USB_PM_REQ_NO_PM_LATENCY
5757
latency and ensures high performance. While USB is active, application
5858
power down is blocked anyway.
5959

60+
config DESKTOP_USB_PM_RESTRICT_REMOVE_DELAY_MS
61+
int "Delay removing power manager restrictions after USB disconnection [ms]"
62+
range 0 60000
63+
default 3000
64+
depends on DESKTOP_USB_PM_ENABLE
65+
help
66+
Delay in milliseconds before removing power manager level restriction
67+
after USB is disconnected. This is used to delay the system off after
68+
USB disconnection. While disconnecting an USB cable, an USB suspended
69+
state might be reported. The USB suspended state triggers force power
70+
down sequence which makes CAF power manager instantly suspend the
71+
application. This option allows user to take actions, like e.g. restart
72+
BLE advertising, after disconnecting the USB cable without going through
73+
reboot.
74+
6075
config DESKTOP_USB_HID_REPORT_SENT_ON_SOF
6176
bool "Submit HID report sent event on USB Start of Frame (SOF) [EXPERIMENTAL]"
6277
default y if UDC_DRIVER_HAS_HIGH_SPEED_SUPPORT

applications/nrf_desktop/src/modules/usb_state_pm.c

Lines changed: 43 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,16 @@ LOG_MODULE_REGISTER(MODULE, CONFIG_DESKTOP_USB_STATE_LOG_LEVEL);
1919
#include <caf/events/force_power_down_event.h>
2020

2121

22+
static bool initialized;
23+
static struct k_work_delayable pm_restrict_remove_work;
24+
25+
static void pm_restrict_remove_work_fn(struct k_work *work)
26+
{
27+
ARG_UNUSED(work);
28+
29+
power_manager_restrict(MODULE_IDX(MODULE), POWER_MANAGER_LEVEL_MAX);
30+
}
31+
2232
static void update_pm_policy_latency_req(bool enable)
2333
{
2434
static bool enabled;
@@ -45,11 +55,18 @@ static bool app_event_handler(const struct app_event_header *aeh)
4555
const struct usb_state_event *event = cast_usb_state_event(aeh);
4656

4757
LOG_DBG("USB state change detected");
58+
__ASSERT_NO_MSG(initialized);
4859

4960
if (IS_ENABLED(CONFIG_DESKTOP_USB_PM_REQ_NO_PM_LATENCY)) {
5061
update_pm_policy_latency_req(event->state == USB_STATE_ACTIVE);
5162
}
5263

64+
if ((CONFIG_DESKTOP_USB_PM_RESTRICT_REMOVE_DELAY_MS > 0) &&
65+
(event->state != USB_STATE_DISCONNECTED)) {
66+
/* Cancel the work if it is scheduled. */
67+
(void)k_work_cancel_delayable(&pm_restrict_remove_work);
68+
}
69+
5370
switch (event->state) {
5471
case USB_STATE_POWERED:
5572
power_manager_restrict(MODULE_IDX(MODULE), POWER_MANAGER_LEVEL_SUSPENDED);
@@ -58,7 +75,28 @@ static bool app_event_handler(const struct app_event_header *aeh)
5875
power_manager_restrict(MODULE_IDX(MODULE), POWER_MANAGER_LEVEL_ALIVE);
5976
break;
6077
case USB_STATE_DISCONNECTED:
61-
power_manager_restrict(MODULE_IDX(MODULE), POWER_MANAGER_LEVEL_MAX);
78+
if (CONFIG_DESKTOP_USB_PM_RESTRICT_REMOVE_DELAY_MS > 0) {
79+
/* Remove the restriction after the delay to allow the user to
80+
* take actions like e.g. restart BLE advertising without going
81+
* through system off.
82+
*/
83+
(void)k_work_schedule(
84+
&pm_restrict_remove_work,
85+
K_MSEC(CONFIG_DESKTOP_USB_PM_RESTRICT_REMOVE_DELAY_MS));
86+
} else {
87+
power_manager_restrict(MODULE_IDX(MODULE), POWER_MANAGER_LEVEL_MAX);
88+
}
89+
/* When disconnecting USB cable, the USB_STATE_SUSPENDED event may
90+
* or may not appear before the USB_STATE_DISCONNECTED event. Add power
91+
* manager restriction and force power down for application to behave
92+
* consistently even if the USB_STATE_SUSPENDED event doesn't appear. Don't
93+
* add restriction if the restriction removal delay is set to 0.
94+
*/
95+
if (CONFIG_DESKTOP_USB_PM_RESTRICT_REMOVE_DELAY_MS > 0) {
96+
power_manager_restrict(MODULE_IDX(MODULE),
97+
POWER_MANAGER_LEVEL_SUSPENDED);
98+
}
99+
force_power_down();
62100
break;
63101
case USB_STATE_SUSPENDED:
64102
LOG_DBG("USB suspended");
@@ -76,9 +114,11 @@ static bool app_event_handler(const struct app_event_header *aeh)
76114
const struct module_state_event *event = cast_module_state_event(aeh);
77115

78116
if (check_state(event, MODULE_ID(main), MODULE_STATE_READY)) {
79-
static bool initialized;
80-
81117
__ASSERT_NO_MSG(!initialized);
118+
if (CONFIG_DESKTOP_USB_PM_RESTRICT_REMOVE_DELAY_MS > 0) {
119+
k_work_init_delayable(&pm_restrict_remove_work,
120+
pm_restrict_remove_work_fn);
121+
}
82122
initialized = true;
83123
}
84124
return false;

0 commit comments

Comments
 (0)