diff --git a/skeleton/SYSTEM/tg5040/bin/suspend b/skeleton/SYSTEM/tg5040/bin/suspend old mode 100755 new mode 100644 index d0771fa35..4a384d4c7 --- a/skeleton/SYSTEM/tg5040/bin/suspend +++ b/skeleton/SYSTEM/tg5040/bin/suspend @@ -1,5 +1,6 @@ #!/bin/sh -set -euo pipefail +set -uo pipefail +set +e exec 0<&- #logfile="/mnt/SDCARD/.userdata/tg5040/logs/suspend_$(date +%Y%m%d_%H%M%S).log" @@ -8,6 +9,8 @@ exec 0<&- wifid_running= bluetoothd_running= +sleep_retval= + asound_state_dir=/tmp/asound-suspend before() { @@ -51,7 +54,41 @@ after() { before >&2 echo "Suspending..." -echo mem >/sys/power/state +sleep_max_tries=5 +for i in $(seq 1 $sleep_max_tries); do + >&2 echo "Deep sleep attempt $i of $sleep_max_tries" + + sleep_time=$(date +%s) + echo mem >/sys/power/state + sleep_retval=$? + + >&2 echo "Deep sleep: kernel returned $sleep_retval" + if [ $sleep_retval -eq 0 ]; then + break + fi + + wake_time=$(date +%s) + time_asleep=$(($wake_time-$sleep_time)) + + # Workaround for a strange false negative case where + # the device sleeps properly but still returns non-zero. + # If unaddressed, the device would sleep again immediately + # after the user tried to wake it. + + # If device has been asleep for longer than a set period, + # ignore the retval and continue with waking the device. + if [ $time_asleep -gt 5 ]; then + >&2 echo "Deep sleep: averting false negative retval - (sleep for $time_asleep secs)" + sleep_retval=0 + break + fi + + + >&2 echo "Deep sleep failed: retrying in 3 seconds" + sleep 3 +done # Resume services in background to reduce UI latency after & + +exit $sleep_retval diff --git a/skeleton/SYSTEM/tg5050/bin/suspend b/skeleton/SYSTEM/tg5050/bin/suspend index 27e0283f5..9062b84ef 100644 --- a/skeleton/SYSTEM/tg5050/bin/suspend +++ b/skeleton/SYSTEM/tg5050/bin/suspend @@ -1,5 +1,6 @@ #!/bin/sh -set -euo pipefail +set -uo pipefail +set +e exec 0<&- #logfile="/mnt/SDCARD/.userdata/tg5040/logs/suspend_$(date +%Y%m%d_%H%M%S).log" @@ -8,6 +9,8 @@ exec 0<&- wifid_running= bluetoothd_running= +sleep_retval= + asound_state_dir=/tmp/asound-suspend before() { @@ -51,7 +54,23 @@ after() { before >&2 echo "Suspending..." -echo mem >/sys/power/state +sleep_max_tries=5 +for i in $(seq 1 $sleep_max_tries); do + >&2 echo "Deep sleep attempt $i of $sleep_max_tries" + + echo mem >/sys/power/state + sleep_retval=$? + + >&2 echo "Deep sleep: kernel returned $sleep_retval" + if [ $sleep_retval -eq 0 ]; then + break + fi + + >&2 echo "Deep sleep failed: retrying in 3 seconds" + sleep 3 +done # Resume services in background to reduce UI latency after & + +exit $sleep_retval diff --git a/workspace/all/common/api.c b/workspace/all/common/api.c index 18c947d45..daa4dd6d3 100644 --- a/workspace/all/common/api.c +++ b/workspace/all/common/api.c @@ -3267,27 +3267,51 @@ FALLBACK_IMPLEMENTATION int PLAT_supportsDeepSleep(void) { return 0; } FALLBACK_IMPLEMENTATION int PLAT_deepSleep(void) { const char *state_path = "/sys/power/state"; + int state_fd = 0; - int state_fd = open(state_path, O_WRONLY); - if (state_fd < 0) - { - LOG_error("failed to open %s: %d\n", state_path, errno); - return -1; - } + for (int i = 0; i < 5; i++) { - LOG_info("suspending to RAM\n"); - int ret = write(state_fd, "mem", 3); - if (ret < 0) - { - // Can fail shortly after resuming with EBUSY - LOG_error("failed to set power state: %d\n", errno); + // Check for power button press while waiting to retry + uint32_t attempt_ticks = SDL_GetTicks(); + if (i > 0) { // Don't wait on first attempt + while (1) { + if (pwr.requested_wake || PAD_wake()) { + pwr.requested_wake = 0; + return 0; + } + SDL_Delay(200); + if (SDL_GetTicks() - attempt_ticks >= 2000) { + break; + } + } + } + + state_fd = open(state_path, O_WRONLY); + if (state_fd < 0) + { + LOG_error("failed to open %s: %d\n", state_path, errno); + LOG_info("retrying suspend in 2 seconds...\n"); + close(state_fd); + continue; + } + + LOG_info("suspending to RAM\n"); + int ret = write(state_fd, "mem", 3); + if (ret < 0) + { + // Can fail shortly after resuming with EBUSY + LOG_error("failed to set power state: %d\n", errno); + LOG_info("retrying suspend in 2 seconds...\n"); + close(state_fd); + continue; + } + + LOG_info("returned from suspend\n"); close(state_fd); - return -1; + return 0; } - LOG_info("returned from suspend\n"); - close(state_fd); - return 0; + return -1; } int PAD_anyJustPressed(void) { return pad.just_pressed != BTN_NONE; } @@ -3796,13 +3820,6 @@ static void PWR_waitForWake(void) { return; } - else if (deep_sleep_attempts < 3) - { - LOG_warn("failed to enter deep sleep - retrying in 5 seconds\n"); - sleep_ticks += 5000; - deep_sleep_attempts++; - continue; - } else { LOG_warn("failed to enter deep sleep - powering off\n");