From d55dceff371c4080d179fb26e6f175927cc48768 Mon Sep 17 00:00:00 2001 From: Aidan MacDonald Date: Sat, 16 Apr 2022 14:25:49 +0100 Subject: apps: Add ability to do a clean reboot Allow a clean shutdown to end in either power off or reboot. Add a new event SYS_REBOOT to signal it and sys_reboot() to trigger the event. SYS_REBOOT signals a reboot request and should be listened for alongside SYS_POWEROFF events. Change-Id: I99ba7fb5feed2bb5a0a40a274e8466ad74fe3a43 --- apps/iap/iap-core.c | 1 + apps/misc.c | 18 ++++++++++++++---- apps/plugins/battery_bench.c | 1 + apps/plugins/chessbox/chessbox.c | 3 +++ apps/plugins/lastfm_scrobbler.c | 1 + apps/plugins/lua/rocklib.c | 1 + apps/plugins/mpegplayer/mpeg_misc.c | 1 + apps/plugins/plugin_crt0.c | 3 ++- apps/plugins/solitaire.c | 1 + apps/recorder/recording.c | 3 ++- apps/tagcache.c | 2 ++ firmware/backlight.c | 1 + firmware/export/powermgmt.h | 9 ++++++++- firmware/kernel/include/queue.h | 1 + firmware/powermgmt.c | 38 +++++++++++++++++++++++++++++++------ 15 files changed, 71 insertions(+), 13 deletions(-) diff --git a/apps/iap/iap-core.c b/apps/iap/iap-core.c index 885ba2c188..ae05806ae9 100644 --- a/apps/iap/iap-core.c +++ b/apps/iap/iap-core.c @@ -364,6 +364,7 @@ static void iap_thread(void) /* Handle poweroff message */ case SYS_POWEROFF: + case SYS_REBOOT: { iap_shutdown = true; break; diff --git a/apps/misc.c b/apps/misc.c index 4d8c2e975a..d5e8bb5d98 100644 --- a/apps/misc.c +++ b/apps/misc.c @@ -288,7 +288,8 @@ static void system_restore(void) tree_restore(); } -static bool clean_shutdown(void (*callback)(void *), void *parameter) +static bool clean_shutdown(enum shutdown_type sd_type, + void (*callback)(void *), void *parameter) { long msg_id = -1; @@ -392,7 +393,7 @@ static bool clean_shutdown(void (*callback)(void *), void *parameter) voice_wait(); } - shutdown_hw(); + shutdown_hw(sd_type); } return false; } @@ -605,8 +606,17 @@ long default_event_handler_ex(long event, void (*callback)(void *), void *parame return SYS_USB_CONNECTED; case SYS_POWEROFF: - if (!clean_shutdown(callback, parameter)) - return SYS_POWEROFF; + case SYS_REBOOT: + { + enum shutdown_type sd_type; + if (event == SYS_POWEROFF) + sd_type = SHUTDOWN_POWER_OFF; + else + sd_type = SHUTDOWN_REBOOT; + + if (!clean_shutdown(sd_type, callback, parameter)) + return event; + } break; #if CONFIG_CHARGING case SYS_CHARGER_CONNECTED: diff --git a/apps/plugins/battery_bench.c b/apps/plugins/battery_bench.c index d8e29d73ca..17d3b918cf 100644 --- a/apps/plugins/battery_bench.c +++ b/apps/plugins/battery_bench.c @@ -462,6 +462,7 @@ static void thread(void) in_usb_mode = false; break; case SYS_POWEROFF: + case SYS_REBOOT: exit_reason = "power off"; exit = true; break; diff --git a/apps/plugins/chessbox/chessbox.c b/apps/plugins/chessbox/chessbox.c index 13df4f177e..089cf7c400 100644 --- a/apps/plugins/chessbox/chessbox.c +++ b/apps/plugins/chessbox/chessbox.c @@ -222,6 +222,7 @@ static void cb_wt_callback ( void ) { button = rb->button_get(false); switch (button) { case SYS_POWEROFF: + case SYS_REBOOT: cb_sysevent = button; #ifdef CB_RC_QUIT case CB_RC_QUIT: @@ -585,6 +586,7 @@ static struct cb_command cb_get_viewer_command (void) { button = rb->button_get(true); switch (button) { case SYS_POWEROFF: + case SYS_REBOOT: cb_sysevent = button; #ifdef CB_RC_QUIT case CB_RC_QUIT: @@ -848,6 +850,7 @@ static struct cb_command cb_getcommand (void) { button = rb->button_get(true); switch (button) { case SYS_POWEROFF: + case SYS_REBOOT: cb_sysevent = button; #ifdef CB_RC_QUIT case CB_RC_QUIT: diff --git a/apps/plugins/lastfm_scrobbler.c b/apps/plugins/lastfm_scrobbler.c index 4d4940945d..7bd213b6d2 100644 --- a/apps/plugins/lastfm_scrobbler.c +++ b/apps/plugins/lastfm_scrobbler.c @@ -490,6 +490,7 @@ void thread(void) rb->beep_play(1500, 100, 1000); break; case SYS_POWEROFF: + case SYS_REBOOT: gCache.force_flush = true; /*fall through*/ case EV_EXIT: diff --git a/apps/plugins/lua/rocklib.c b/apps/plugins/lua/rocklib.c index 6131a479db..cadc8be6ac 100644 --- a/apps/plugins/lua/rocklib.c +++ b/apps/plugins/lua/rocklib.c @@ -1090,6 +1090,7 @@ LUALIB_API int luaopen_rock(lua_State *L) RB_CONSTANT(SYS_USB_DISCONNECTED), RB_CONSTANT(SYS_TIMEOUT), RB_CONSTANT(SYS_POWEROFF), + RB_CONSTANT(SYS_REBOOT), RB_CONSTANT(SYS_CHARGER_CONNECTED), RB_CONSTANT(SYS_CHARGER_DISCONNECTED), diff --git a/apps/plugins/mpegplayer/mpeg_misc.c b/apps/plugins/mpegplayer/mpeg_misc.c index c85285f4f8..31f0644212 100644 --- a/apps/plugins/mpegplayer/mpeg_misc.c +++ b/apps/plugins/mpegplayer/mpeg_misc.c @@ -192,6 +192,7 @@ int mpeg_sysevent_callback(int btn, { case SYS_USB_CONNECTED: case SYS_POWEROFF: + case SYS_REBOOT: mpeg_sysevent_id = btn; return ACTION_STD_CANCEL; } diff --git a/apps/plugins/plugin_crt0.c b/apps/plugins/plugin_crt0.c index 680bb0723d..5564c5575f 100644 --- a/apps/plugins/plugin_crt0.c +++ b/apps/plugins/plugin_crt0.c @@ -141,6 +141,7 @@ void exit_on_usb(int button) long result = rb->default_event_handler_ex(button, cleanup_wrapper, NULL); if (result == SYS_USB_CONNECTED) _exit(PLUGIN_USB_CONNECTED); - else if (result == SYS_POWEROFF) + else if (result == SYS_POWEROFF || result == SYS_REBOOT) + /* note: nobody actually pays attention to this exit code */ _exit(PLUGIN_POWEROFF); } diff --git a/apps/plugins/solitaire.c b/apps/plugins/solitaire.c index b1ede16f90..ebc042f6db 100644 --- a/apps/plugins/solitaire.c +++ b/apps/plugins/solitaire.c @@ -2149,6 +2149,7 @@ static int solitaire( int skipmenu ) break; case SYS_POWEROFF: + case SYS_REBOOT: return SOLITAIRE_SAVE_AND_QUIT; default: diff --git a/apps/recorder/recording.c b/apps/recorder/recording.c index b973d9750c..a54b762566 100644 --- a/apps/recorder/recording.c +++ b/apps/recorder/recording.c @@ -1534,7 +1534,8 @@ bool recording_screen(bool no_source) break; case SYS_POWEROFF: - default_event_handler(SYS_POWEROFF); + case SYS_REBOOT: + default_event_handler(button); done = true; break; diff --git a/apps/tagcache.c b/apps/tagcache.c index 8bc742112b..c18380854e 100644 --- a/apps/tagcache.c +++ b/apps/tagcache.c @@ -3989,6 +3989,7 @@ static bool check_event_queue(void) { case Q_STOP_SCAN: case SYS_POWEROFF: + case SYS_REBOOT: case SYS_USB_CONNECTED: return true; } @@ -4944,6 +4945,7 @@ static void tagcache_thread(void) break ; case SYS_POWEROFF: + case SYS_REBOOT: break ; case SYS_USB_CONNECTED: diff --git a/firmware/backlight.c b/firmware/backlight.c index 1284db4659..9575ecdc22 100644 --- a/firmware/backlight.c +++ b/firmware/backlight.c @@ -668,6 +668,7 @@ void backlight_thread(void) #endif /* HAVE_BUTTONLIGHT_BRIGHTNESS */ #endif /* HAVE_BUTTON_LIGHT */ + case SYS_REBOOT: case SYS_POWEROFF: /* Lock backlight on poweroff so it doesn't */ locked = true; /* go off before power is actually cut. */ #if !defined(BOOTLOADER) diff --git a/firmware/export/powermgmt.h b/firmware/export/powermgmt.h index 3095d2c97b..6ae5ccfd13 100644 --- a/firmware/export/powermgmt.h +++ b/firmware/export/powermgmt.h @@ -70,6 +70,12 @@ extern unsigned int power_thread_inputs; #endif /* CONFIG_CHARGING */ +enum shutdown_type +{ + SHUTDOWN_POWER_OFF, + SHUTDOWN_REBOOT, +}; + #if CONFIG_CHARGING == CHARGING_TARGET /* Include target-specific definitions */ #include "powermgmt-target.h" @@ -164,8 +170,9 @@ void handle_auto_poweroff(void); void set_car_adapter_mode(bool setting); void reset_poweroff_timer(void); void cancel_shutdown(void); -void shutdown_hw(void); +void shutdown_hw(enum shutdown_type sd_type); void sys_poweroff(void); +void sys_reboot(void); /* Returns true if the system should force shutdown for some reason - * eg. low battery */ bool query_force_shutdown(void); diff --git a/firmware/kernel/include/queue.h b/firmware/kernel/include/queue.h index 515a7e43a8..6740b88760 100644 --- a/firmware/kernel/include/queue.h +++ b/firmware/kernel/include/queue.h @@ -58,6 +58,7 @@ #define SYS_CHARGER_CONNECTED MAKE_SYS_EVENT(SYS_EVENT_CLS_POWER, 1) #define SYS_CHARGER_DISCONNECTED MAKE_SYS_EVENT(SYS_EVENT_CLS_POWER, 2) #define SYS_BATTERY_UPDATE MAKE_SYS_EVENT(SYS_EVENT_CLS_POWER, 3) +#define SYS_REBOOT MAKE_SYS_EVENT(SYS_EVENT_CLS_POWER, 4) #define SYS_FS_CHANGED MAKE_SYS_EVENT(SYS_EVENT_CLS_FILESYS, 0) #define SYS_HOTSWAP_INSERTED MAKE_SYS_EVENT(SYS_EVENT_CLS_PLUG, 0) #define SYS_HOTSWAP_EXTRACTED MAKE_SYS_EVENT(SYS_EVENT_CLS_PLUG, 1) diff --git a/firmware/powermgmt.c b/firmware/powermgmt.c index 2cafd4b759..c33ad387ae 100644 --- a/firmware/powermgmt.c +++ b/firmware/powermgmt.c @@ -823,7 +823,7 @@ void powermgmt_init(void) } /* Various hardware housekeeping tasks relating to shutting down the player */ -void shutdown_hw(void) +void shutdown_hw(enum shutdown_type sd_type) { charging_algorithm_close(); audio_stop(); @@ -863,7 +863,17 @@ void shutdown_hw(void) eeprom chips are quite slow and might be still writing the last byte. */ sleep(HZ/4); - power_off(); + + switch (sd_type) { + case SHUTDOWN_POWER_OFF: + default: + power_off(); + break; + + case SHUTDOWN_REBOOT: + system_reboot(); + break; + } } void set_poweroff_timeout(int timeout) @@ -878,10 +888,9 @@ void reset_poweroff_timer(void) set_sleep_timer(sleeptimer_duration); } -void sys_poweroff(void) -{ #ifndef BOOTLOADER - logf("sys_poweroff()"); +static void sys_shutdown_common(void) +{ /* If the main thread fails to shut down the system, we will force a power off after an 20 second timeout - 28 seconds if recording */ if (shutdown_timeout == 0) { @@ -899,9 +908,26 @@ void sys_poweroff(void) shutdown_timeout += HZ*20; #endif } +} +#endif /* BOOTLOADER */ +void sys_poweroff(void) +{ +#ifndef BOOTLOADER + logf("sys_poweroff()"); + sys_shutdown_common(); queue_broadcast(SYS_POWEROFF, 0); -#endif /* BOOTLOADER */ +#endif +} + +/* not to be confused with system_reboot... :( */ +void sys_reboot(void) +{ +#ifndef BOOTLOADER + logf("sys_reboot()"); + sys_shutdown_common(); + queue_broadcast(SYS_REBOOT, 0); +#endif } void cancel_shutdown(void) -- cgit v1.2.3