@@ -19,6 +19,16 @@ LOG_MODULE_REGISTER(MODULE, CONFIG_DESKTOP_USB_STATE_LOG_LEVEL);
19
19
#include <caf/events/force_power_down_event.h>
20
20
21
21
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
+
22
32
static void update_pm_policy_latency_req (bool enable )
23
33
{
24
34
static bool enabled ;
@@ -45,11 +55,18 @@ static bool app_event_handler(const struct app_event_header *aeh)
45
55
const struct usb_state_event * event = cast_usb_state_event (aeh );
46
56
47
57
LOG_DBG ("USB state change detected" );
58
+ __ASSERT_NO_MSG (initialized );
48
59
49
60
if (IS_ENABLED (CONFIG_DESKTOP_USB_PM_REQ_NO_PM_LATENCY )) {
50
61
update_pm_policy_latency_req (event -> state == USB_STATE_ACTIVE );
51
62
}
52
63
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
+
53
70
switch (event -> state ) {
54
71
case USB_STATE_POWERED :
55
72
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)
58
75
power_manager_restrict (MODULE_IDX (MODULE ), POWER_MANAGER_LEVEL_ALIVE );
59
76
break ;
60
77
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 ();
62
100
break ;
63
101
case USB_STATE_SUSPENDED :
64
102
LOG_DBG ("USB suspended" );
@@ -76,9 +114,11 @@ static bool app_event_handler(const struct app_event_header *aeh)
76
114
const struct module_state_event * event = cast_module_state_event (aeh );
77
115
78
116
if (check_state (event , MODULE_ID (main ), MODULE_STATE_READY )) {
79
- static bool initialized ;
80
-
81
117
__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
+ }
82
122
initialized = true;
83
123
}
84
124
return false;
0 commit comments