diff --git a/headers/storagemanager.h b/headers/storagemanager.h index 8778e5842..bed769283 100644 --- a/headers/storagemanager.h +++ b/headers/storagemanager.h @@ -49,6 +49,7 @@ class Storage { void init(); bool save(); + bool save(const bool force); // Perform saves that were enqueued from core1 void performEnqueuedSaves(); diff --git a/proto/enums.proto b/proto/enums.proto index db76de54b..7fa979950 100644 --- a/proto/enums.proto +++ b/proto/enums.proto @@ -300,6 +300,7 @@ enum GamepadHotkey HOTKEY_DPAD_LEFT = 40; HOTKEY_DPAD_RIGHT = 41; HOTKEY_PREVIOUS_PROFILE = 42; + HOTKEY_SAVE_CONFIG = 43; } // This has to be kept in sync with LEDFormat in NeoPico.hpp diff --git a/src/configmanager.cpp b/src/configmanager.cpp index 62592d3d4..3adc315c2 100644 --- a/src/configmanager.cpp +++ b/src/configmanager.cpp @@ -1,8 +1,6 @@ #include "configmanager.h" -#include "addonmanager.h" #include "configs/webconfig.h" -#include "addons/neopicoleds.h" void ConfigManager::setup(ConfigType config) { if (config == CONFIG_TYPE_WEB) @@ -19,7 +17,3 @@ void ConfigManager::setupConfig(GPConfig * gpconfig) { gpconfig->setup(); this->config = gpconfig; } - -void ConfigManager::setGamepadOptions(Gamepad* gamepad) { - gamepad->save(); -} diff --git a/src/configs/webconfig.cpp b/src/configs/webconfig.cpp index a77fdae53..ab78f607c 100644 --- a/src/configs/webconfig.cpp +++ b/src/configs/webconfig.cpp @@ -469,7 +469,7 @@ std::string setDisplayOptions(DisplayOptions& displayOptions) std::string setDisplayOptions() { std::string response = setDisplayOptions(Storage::getInstance().getDisplayOptions()); - Storage::getInstance().save(); + Storage::getInstance().save(true); return response; } @@ -533,7 +533,7 @@ std::string setSplashImage() memcpy(displayOptions.splashImage.bytes, decoded.data(), length); displayOptions.splashImage.size = length; - Storage::getInstance().save(); + Storage::getInstance().save(true); return serialize_json(doc); } @@ -578,7 +578,7 @@ std::string setProfileOptions() if (altsIndex > 2) break; } - Storage::getInstance().save(); + Storage::getInstance().save(true); return serialize_json(doc); } @@ -688,7 +688,7 @@ std::string setGamepadOptions() ForcedSetupOptions& forcedSetupOptions = Storage::getInstance().getForcedSetupOptions(); readDoc(forcedSetupOptions.mode, doc, "forcedSetupMode"); - Storage::getInstance().save(); + Storage::getInstance().save(true); return serialize_json(doc); } @@ -800,7 +800,7 @@ std::string setLedOptions() readDoc(ledOptions.pledIndex4, doc, "pledIndex4"); readDoc(ledOptions.pledColor, doc, "pledColor"); - Storage::getInstance().save(); + Storage::getInstance().save(true); return serialize_json(doc); } @@ -1005,7 +1005,7 @@ std::string setCustomTheme() options.buttonPressColorCooldownTimeInMs = pressCooldown; AnimationStation::SetOptions(options); - AnimationStore.save(); + Storage::getInstance().save(true); return serialize_json(doc); } @@ -1081,7 +1081,7 @@ std::string setPinMappings() gpioMappings.profileLabel[profileLabelSize - 1] = '\0'; gpioMappings.enabled = doc["enabled"]; - Storage::getInstance().save(); + Storage::getInstance().save(true); return serialize_json(doc); } @@ -1175,7 +1175,7 @@ std::string setKeyMappings() readDoc(keyboardMapping.keyButtonE11, doc, "E11"); readDoc(keyboardMapping.keyButtonE12, doc, "E12"); - Storage::getInstance().save(); + Storage::getInstance().save(true); return serialize_json(doc); } @@ -1335,7 +1335,7 @@ std::string setPeripheralOptions() profiles.gpioMappingsSets[2].pins[oldPinDplus+adjacent].action = GpioAction::NONE; } - Storage::getInstance().save(); + Storage::getInstance().save(true); return serialize_json(doc); } @@ -1401,7 +1401,7 @@ std::string setExpansionPins() } Storage::getInstance().getAddonOptions().pcf8575Options.pins_count = 16; - Storage::getInstance().save(); + Storage::getInstance().save(true); return serialize_json(doc); } @@ -1435,7 +1435,7 @@ std::string setReactiveLEDs() } Storage::getInstance().getAddonOptions().reactiveLEDOptions.leds_count = 10; - Storage::getInstance().save(); + Storage::getInstance().save(true); return serialize_json(doc); } @@ -1628,7 +1628,7 @@ std::string setAddonOptions() docToValue(drv8833RumbleOptions.dutyMin, doc, "drv8833RumbleDutyMin"); docToValue(drv8833RumbleOptions.dutyMax, doc, "drv8833RumbleDutyMax"); - Storage::getInstance().save(); + Storage::getInstance().save(true); return serialize_json(doc); } @@ -1701,7 +1701,7 @@ std::string setPS4Options() if (ps4Options.rsaQP.size != 0) ps4Options.rsaQP.size = 0; if (ps4Options.rsaRN.size != 0) ps4Options.rsaRN.size = 0; - Storage::getInstance().save(); + Storage::getInstance().save(true); return "{\"success\":true}"; } @@ -1784,7 +1784,7 @@ std::string setWiiControls() readDoc(wiiOptions.controllers.turntable.effects.axisType, doc, "turntable.analogEffects.axisType"); readDoc(wiiOptions.controllers.turntable.fader.axisType, doc, "turntable.analogFader.axisType"); - Storage::getInstance().save(); + Storage::getInstance().save(true); return "{\"success\":true}"; } @@ -2106,7 +2106,7 @@ std::string setMacroAddonOptions() macroOptions.macroList_count = MAX_MACRO_LIMIT; - Storage::getInstance().save(); + Storage::getInstance().save(true); return serialize_json(doc); } @@ -2254,7 +2254,7 @@ DataAndStatusCode setConfig() { Storage::getInstance().getConfig() = *config.get(); config.reset(); - if (Storage::getInstance().save()) + if (Storage::getInstance().save(true)) { return DataAndStatusCode(getConfig(), HttpStatusCode::_200); } diff --git a/src/gamepad.cpp b/src/gamepad.cpp index 3a1ffce8e..c98b8b586 100644 --- a/src/gamepad.cpp +++ b/src/gamepad.cpp @@ -323,11 +323,6 @@ void Gamepad::read() state.rt = 0; } -void Gamepad::save() -{ - Storage::getInstance().save(); -} - void Gamepad::hotkey() { if (options.lockHotkeys) @@ -500,6 +495,9 @@ void Gamepad::processHotkeyAction(GamepadHotkey action) { case HOTKEY_REBOOT_DEFAULT: System::reboot(System::BootMode::DEFAULT); break; + case HOTKEY_SAVE_CONFIG: + Storage::getInstance().save(true); + break; case HOTKEY_CAPTURE_BUTTON: state.buttons |= GAMEPAD_MASK_A2; break; @@ -583,6 +581,6 @@ void Gamepad::processHotkeyAction(GamepadHotkey action) { // only save if requested if (reqSave) { - save(); + Storage::getInstance().save(); } } diff --git a/src/gp2040.cpp b/src/gp2040.cpp index ed76528e6..6566ceb2a 100644 --- a/src/gp2040.cpp +++ b/src/gp2040.cpp @@ -177,7 +177,9 @@ void GP2040::setup() { // Save the changed input mode if (inputMode != gamepad->getOptions().inputMode) { gamepad->setInputMode(inputMode); - gamepad->save(); + // save to match user expectations on choosing mode at boot, and this is + // before USB host will be used so we can force it to ignore the check + Storage::getInstance().save(true); } } diff --git a/src/storagemanager.cpp b/src/storagemanager.cpp index c8d2121fe..68d7de338 100644 --- a/src/storagemanager.cpp +++ b/src/storagemanager.cpp @@ -7,29 +7,38 @@ #include "BoardConfig.h" #include "AnimationStorage.hpp" -#include "Effects/StaticColor.hpp" #include "FlashPROM.h" +#include "peripheralmanager.h" #include "config.pb.h" #include "hardware/watchdog.h" -#include "Animation.hpp" #include "CRC32.h" #include "types.h" #include "config_utils.h" -#include "bitmaps.h" - -#include "helper.h" - void Storage::init() { EEPROM.start(); critical_section_init(&animationOptionsCs); ConfigUtils::load(config); } +/** + * @brief Save the config, but only if it is safe to (as in USB host is not being used.) + */ bool Storage::save() { - return ConfigUtils::save(config); + return save(false); +} + +/** + * @brief Save the config; if forcing a save is requested, or if USB host is not enabled, this will write to flash. + */ +bool Storage::save(const bool force) { + if (!PeripheralManager::getInstance().isUSBEnabled(0) || force) { + return ConfigUtils::save(config); + } else { + return false; + } } static void updateAnimationOptionsProto(const AnimationOptions& options) diff --git a/www/src/Locales/en/SettingsPage.jsx b/www/src/Locales/en/SettingsPage.jsx index 1a5955902..6c6a0cf9c 100644 --- a/www/src/Locales/en/SettingsPage.jsx +++ b/www/src/Locales/en/SettingsPage.jsx @@ -127,6 +127,7 @@ export default { 'load-profile-3': 'Load Profile #3', 'load-profile-4': 'Load Profile #4', 'reboot-default': 'Reboot GP2040-CE', + 'save-config': 'Save Config', 'next-profile': 'Next Profile', 'previous-profile': 'Previous Profile', }, diff --git a/www/src/Pages/SettingsPage.jsx b/www/src/Pages/SettingsPage.jsx index 443f01eca..5fffdea7d 100644 --- a/www/src/Pages/SettingsPage.jsx +++ b/www/src/Pages/SettingsPage.jsx @@ -266,6 +266,7 @@ const HOTKEY_ACTIONS = [ { labelKey: 'hotkey-actions.r3-button', value: 20 }, { labelKey: 'hotkey-actions.touchpad-button', value: 21 }, { labelKey: 'hotkey-actions.reboot-default', value: 22 }, + { labelKey: 'hotkey-actions.save-config', value: 43 }, { labelKey: 'hotkey-actions.b1-button', value: 23 }, { labelKey: 'hotkey-actions.b2-button', value: 24 }, { labelKey: 'hotkey-actions.b3-button', value: 25 },