From 46d10dda338e657d6fac2dd5ec3de9659faf2db1 Mon Sep 17 00:00:00 2001 From: "Hairo R. Carela" Date: Tue, 5 Aug 2025 22:56:17 -0400 Subject: [PATCH] rgnano: Instant play support and proper system brightness/volume handling Instant play is a Funkey OS feature that allows it to relaunch at boot the last program it was running before shutting down, which means that if the handheld is powered off (holding the power button) while rockbox is running the next time it's powered on rockbox will launch at boot. This commit also handles system brightness/volume in rockbox itself instead of the launch script, so the values are properly reset when powering off the handheld while rockbox is running. Change-Id: Ie1adbf71069aeed5fbf6670971718a2f718716a3 --- firmware/SOURCES | 1 + .../target/hosted/anbernic/instant_play.c | 106 ++++++++++++++++++ .../target/hosted/anbernic/instant_play.h | 25 +++++ firmware/target/hosted/sdl/system-sdl.c | 22 ++++ packaging/rgnano/run.sh | 20 ++-- 5 files changed, 167 insertions(+), 7 deletions(-) create mode 100644 firmware/target/hosted/anbernic/instant_play.c create mode 100644 firmware/target/hosted/anbernic/instant_play.h diff --git a/firmware/SOURCES b/firmware/SOURCES index eb8ff78900..49cbdec081 100644 --- a/firmware/SOURCES +++ b/firmware/SOURCES @@ -230,6 +230,7 @@ target/hosted/maemo/maemo-thread.c target/hosted/sysfs.c target/hosted/power-linux.c target/hosted/backlight-unix.c +target/hosted/anbernic/instant_play.c target/hosted/anbernic/power-rgnano.c target/hosted/anbernic/button-rgnano.c target/hosted/anbernic/powermgmt-rgnano.c diff --git a/firmware/target/hosted/anbernic/instant_play.c b/firmware/target/hosted/anbernic/instant_play.c new file mode 100644 index 0000000000..0dab3c5b26 --- /dev/null +++ b/firmware/target/hosted/anbernic/instant_play.c @@ -0,0 +1,106 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * + * Copyright (C) 2025 Hairo R. Carela + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ + +#include +#include +#include +#include +#include +#include + +static int get_value(const char *cmd) +{ + /* Read values with the brightness/volume tools, stored in + bootloader variables */ + char line[4]; + int value; + + char full_cmd[18]; + snprintf(full_cmd, 18, "%s get", cmd); + + FILE* fp = popen(full_cmd, "r"); + + if (fp == NULL) { + value = -1; + } + + if (fgets(line, sizeof(line), fp) != NULL) + { + value = strtol(line, NULL, 10); + } + else + { + value = -1; + } + + pclose(fp); + return value; +} + +static void set_value(const char *cmd, const int value) +{ + /* Set values with the brightness/volume tools, stored in + bootloader variables. */ + char full_cmd[22]; + snprintf(full_cmd, 22, "%s set %d", cmd, value); + system(full_cmd); +} + +void ip_reset_values(void) +{ + /* Use the brightness/volume tools to reset to their previous + values before launching rockbox */ + int volume_level = get_value("volume"); + if (volume_level > -1) + { + set_value("volume", volume_level); + } + + int brightness_level = get_value("brightness"); + if (brightness_level > -1) + { + set_value("brightness", brightness_level); + } +} + +void ip_handle_sigusr1(int sig) +{ + if (sig == SIGUSR1) + { + /* Stop the powerdown countdown */ + system("powerdown handle"); + + /* Write the instant_play file */ + char buf[60]; + size_t nbytes; + int fd; + + fd = open("/mnt/instant_play", O_WRONLY | O_CREAT, 0640); + + strcpy(buf, "'/opk/rockbox' &\npid record $!\nwait $!\npid erase\n"); + nbytes = strlen(buf); + write(fd, buf, nbytes); + + close(fd); + + /* Powerdown the handheld after writting the file */ + system("powerdown now"); + } +} diff --git a/firmware/target/hosted/anbernic/instant_play.h b/firmware/target/hosted/anbernic/instant_play.h new file mode 100644 index 0000000000..97ce67907e --- /dev/null +++ b/firmware/target/hosted/anbernic/instant_play.h @@ -0,0 +1,25 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * + * Copyright (C) 2025 Hairo R. Carela + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ +#ifndef _INSTANT_PLAY_H_ +#define _INSTANT_PLAY_H_ + +void ip_handle_sigusr1(int sig); +void ip_reset_values(void); +#endif /* _INSTANT_PLAY_H_ */ diff --git a/firmware/target/hosted/sdl/system-sdl.c b/firmware/target/hosted/sdl/system-sdl.c index 56e797ac5b..6c514fcdf8 100644 --- a/firmware/target/hosted/sdl/system-sdl.c +++ b/firmware/target/hosted/sdl/system-sdl.c @@ -50,6 +50,11 @@ #include "maemo-thread.h" #endif +#ifdef RG_NANO +#include +#include "instant_play.h" +#endif + #define SIMULATOR_DEFAULT_ROOT "simdisk" #if SDL_MAJOR_VERSION == 1 @@ -193,6 +198,11 @@ void power_off(void) /* wait for event thread to finish */ SDL_WaitThread(evt_thread, NULL); +#ifdef RG_NANO + /* Reset volume/brightness to the values before launching rockbox */ + ip_reset_values(); +#endif + #ifdef HAVE_SDL_THREADS /* lock again before entering the scheduler */ sim_thread_lock(t); @@ -240,6 +250,13 @@ void system_init(void) g_type_init(); #endif +#ifdef RG_NANO + /* Instant play handling */ + struct sigaction ip_sa; + ip_sa.sa_handler = ip_handle_sigusr1; + sigaction(SIGUSR1, &ip_sa, NULL); +#endif + if (SDL_InitSubSystem(SDL_INIT_TIMER)) panicf("%s", SDL_GetError()); @@ -284,6 +301,11 @@ void system_init(void) void system_reboot(void) { +#ifdef RG_NANO + /* Reset volume/brightness to the values before launching rockbox */ + ip_reset_values(); +#endif + #ifdef HAVE_SDL_THREADS sim_thread_exception_wait(); #else diff --git a/packaging/rgnano/run.sh b/packaging/rgnano/run.sh index 41a92a21c4..0372f4d7ea 100755 --- a/packaging/rgnano/run.sh +++ b/packaging/rgnano/run.sh @@ -4,6 +4,11 @@ RBDIR=/mnt/FunKey/rockbox CFGFILE=$RBDIR/config.cfg BLPATH=/sys/class/backlight/backlight/brightness +_send_sigusr1() +{ + kill -s USR1 "$rb_pid" 2>/dev/null +} + # Install the rockbox folder if [ ! -d $RBDIR ]; then notif set 0 " Installing rockbox..." @@ -27,12 +32,13 @@ if [ ! -f $CFGFILE ]; then cp ./config.cfg $CFGFILE fi -# Get current volume/brightness -> launch rockbox -> restore previous values -CUR_VOL=$(volume get) -CUR_BL=$(cat $BLPATH) -volume set 100 +# Set volume to max with amixer so it's not permanent +amixer -q sset 'Headphone' 63 unmute -./rockbox +# Need to send SIGUSR1 to the rockbox process for instant play support +trap _send_sigusr1 SIGUSR1 -volume set $CUR_VOL -echo $CUR_BL > $BLPATH +./rockbox & + +rb_pid=$! +wait "$rb_pid" \ No newline at end of file