diff --git a/applications/desktop/desktop.c b/applications/desktop/desktop.c index aa9b4ed5..374a5f09 100644 --- a/applications/desktop/desktop.c +++ b/applications/desktop/desktop.c @@ -1,4 +1,5 @@ #include "desktop_i.h" +#include static void desktop_lock_icon_callback(Canvas* canvas, void* context) { furi_assert(canvas); @@ -117,9 +118,23 @@ static bool desktop_is_first_start() { int32_t desktop_srv(void* p) { Desktop* desktop = desktop_alloc(); + bool loaded = LOAD_DESKTOP_SETTINGS(&desktop->settings); + if(!loaded) { + furi_hal_lock_set(false); + memset(&desktop->settings, 0, sizeof(desktop->settings)); + bool saved = SAVE_DESKTOP_SETTINGS(&desktop->settings); + furi_check(saved); + } scene_manager_next_scene(desktop->scene_manager, DesktopSceneMain); + if(furi_hal_lock_get()) { + furi_hal_usb_disable(); + scene_manager_set_scene_state( + desktop->scene_manager, DesktopSceneLocked, DesktopLockedWithPin); + scene_manager_next_scene(desktop->scene_manager, DesktopSceneLocked); + } + if(desktop_is_first_start()) { scene_manager_next_scene(desktop->scene_manager, DesktopSceneFirstStart); } diff --git a/applications/desktop/desktop_settings/desktop_settings.c b/applications/desktop/desktop_settings/desktop_settings.c deleted file mode 100644 index 5e170a09..00000000 --- a/applications/desktop/desktop_settings/desktop_settings.c +++ /dev/null @@ -1,49 +0,0 @@ -#include -#include -#include "desktop_settings.h" - -#define DESKTOP_SETTINGS_TAG "Desktop settings" -#define DESKTOP_SETTINGS_PATH "/int/desktop.settings" - -bool desktop_settings_load(DesktopSettings* desktop_settings) { - furi_assert(desktop_settings); - bool file_loaded = false; - DesktopSettings settings = {}; - - FURI_LOG_I(DESKTOP_SETTINGS_TAG, "Loading settings from \"%s\"", DESKTOP_SETTINGS_PATH); - FileWorker* file_worker = file_worker_alloc(true); - if(file_worker_open(file_worker, DESKTOP_SETTINGS_PATH, FSAM_READ, FSOM_OPEN_EXISTING)) { - if(file_worker_read(file_worker, &settings, sizeof(settings))) { - file_loaded = true; - } - } - file_worker_free(file_worker); - - if(file_loaded) { - if(settings.version != DESKTOP_SETTINGS_VER) { - FURI_LOG_E(DESKTOP_SETTINGS_TAG, "Settings version mismatch"); - } else { - osKernelLock(); - *desktop_settings = settings; - osKernelUnlock(); - } - } else { - FURI_LOG_E(DESKTOP_SETTINGS_TAG, "Settings load failed"); - } - return file_loaded; -} - -bool desktop_settings_save(DesktopSettings* desktop_settings) { - furi_assert(desktop_settings); - bool result = false; - - FileWorker* file_worker = file_worker_alloc(true); - if(file_worker_open(file_worker, DESKTOP_SETTINGS_PATH, FSAM_WRITE, FSOM_OPEN_ALWAYS)) { - if(file_worker_write(file_worker, desktop_settings, sizeof(DesktopSettings))) { - FURI_LOG_I(DESKTOP_SETTINGS_TAG, "Settings saved to \"%s\"", DESKTOP_SETTINGS_PATH); - result = true; - } - } - file_worker_free(file_worker); - return result; -} diff --git a/applications/desktop/desktop_settings/desktop_settings.h b/applications/desktop/desktop_settings/desktop_settings.h index c8f324a1..27ded715 100644 --- a/applications/desktop/desktop_settings/desktop_settings.h +++ b/applications/desktop/desktop_settings/desktop_settings.h @@ -2,23 +2,35 @@ #include #include +#include #define DESKTOP_SETTINGS_VER (1) +#define DESKTOP_SETTINGS_PATH "/int/desktop.settings" +#define DESKTOP_SETTINGS_MAGIC (0x17) #define PIN_MAX_LENGTH 12 +#define SAVE_DESKTOP_SETTINGS(x) \ + saved_struct_save( \ + DESKTOP_SETTINGS_PATH, \ + (x), \ + sizeof(DesktopSettings), \ + DESKTOP_SETTINGS_MAGIC, \ + DESKTOP_SETTINGS_VER) + +#define LOAD_DESKTOP_SETTINGS(x) \ + saved_struct_load( \ + DESKTOP_SETTINGS_PATH, \ + (x), \ + sizeof(DesktopSettings), \ + DESKTOP_SETTINGS_MAGIC, \ + DESKTOP_SETTINGS_VER) + typedef struct { uint8_t length; uint8_t data[PIN_MAX_LENGTH]; } PinCode; typedef struct { - uint8_t version; uint16_t favorite; - PinCode pincode; - bool locked; } DesktopSettings; - -bool desktop_settings_load(DesktopSettings* desktop_settings); - -bool desktop_settings_save(DesktopSettings* desktop_settings); diff --git a/applications/desktop/desktop_settings/desktop_settings_app.c b/applications/desktop/desktop_settings/desktop_settings_app.c index e284ff80..c8a5f2b7 100644 --- a/applications/desktop/desktop_settings/desktop_settings_app.c +++ b/applications/desktop/desktop_settings/desktop_settings_app.c @@ -15,9 +15,6 @@ static bool desktop_settings_back_event_callback(void* context) { DesktopSettingsApp* desktop_settings_app_alloc() { DesktopSettingsApp* app = furi_alloc(sizeof(DesktopSettingsApp)); - app->settings.version = DESKTOP_SETTINGS_VER; - desktop_settings_load(&app->settings); - app->gui = furi_record_open("gui"); app->view_dispatcher = view_dispatcher_alloc(); app->scene_manager = scene_manager_alloc(&desktop_settings_scene_handlers, app); @@ -62,8 +59,8 @@ void desktop_settings_app_free(DesktopSettingsApp* app) { extern int32_t desktop_settings_app(void* p) { DesktopSettingsApp* app = desktop_settings_app_alloc(); + LOAD_DESKTOP_SETTINGS(&app->settings); view_dispatcher_run(app->view_dispatcher); - desktop_settings_save(&app->settings); desktop_settings_app_free(app); return 0; } diff --git a/applications/desktop/desktop_settings/scenes/desktop_settings_scene_favorite.c b/applications/desktop/desktop_settings/scenes/desktop_settings_scene_favorite.c index 1fead1f7..0b9bb580 100644 --- a/applications/desktop/desktop_settings/scenes/desktop_settings_scene_favorite.c +++ b/applications/desktop/desktop_settings/scenes/desktop_settings_scene_favorite.c @@ -1,5 +1,6 @@ #include "../desktop_settings_app.h" #include "applications.h" +#include "desktop/desktop_settings/desktop_settings.h" static void desktop_settings_scene_favorite_submenu_callback(void* context, uint32_t index) { DesktopSettingsApp* app = context; @@ -43,5 +44,6 @@ bool desktop_settings_scene_favorite_on_event(void* context, SceneManagerEvent e void desktop_settings_scene_favorite_on_exit(void* context) { DesktopSettingsApp* app = context; + SAVE_DESKTOP_SETTINGS(&app->settings); submenu_clean(app->submenu); } diff --git a/applications/desktop/desktop_settings/scenes/desktop_settings_scene_pincode_input.c b/applications/desktop/desktop_settings/scenes/desktop_settings_scene_pincode_input.c index d809f999..70b059a4 100644 --- a/applications/desktop/desktop_settings/scenes/desktop_settings_scene_pincode_input.c +++ b/applications/desktop/desktop_settings/scenes/desktop_settings_scene_pincode_input.c @@ -1,4 +1,5 @@ #include "../desktop_settings_app.h" +#include "desktop/desktop_settings/desktop_settings.h" #define SCENE_EXIT_EVENT (0U) @@ -57,6 +58,7 @@ bool desktop_settings_scene_pincode_input_on_event(void* context, SceneManagerEv void desktop_settings_scene_pincode_input_on_exit(void* context) { DesktopSettingsApp* app = context; + SAVE_DESKTOP_SETTINGS(&app->settings); code_input_set_result_callback(app->code_input, NULL, NULL, NULL, NULL, NULL, 0); code_input_set_header_text(app->code_input, ""); } diff --git a/applications/desktop/scenes/desktop_scene_lock_menu.c b/applications/desktop/scenes/desktop_scene_lock_menu.c index 46561e47..8a73739f 100644 --- a/applications/desktop/scenes/desktop_scene_lock_menu.c +++ b/applications/desktop/scenes/desktop_scene_lock_menu.c @@ -1,5 +1,8 @@ #include "../desktop_i.h" #include "../views/desktop_lock_menu.h" +#include +#include +#include void desktop_scene_lock_menu_callback(DesktopLockMenuEvent event, void* context) { Desktop* desktop = (Desktop*)context; @@ -9,7 +12,7 @@ void desktop_scene_lock_menu_callback(DesktopLockMenuEvent event, void* context) void desktop_scene_lock_menu_on_enter(void* context) { Desktop* desktop = (Desktop*)context; - desktop_settings_load(&desktop->settings); + LOAD_DESKTOP_SETTINGS(&desktop->settings); desktop_lock_menu_set_callback(desktop->lock_menu, desktop_scene_lock_menu_callback, desktop); desktop_lock_menu_pin_set(desktop->lock_menu, desktop->settings.pincode.length > 0); @@ -29,10 +32,9 @@ bool desktop_scene_lock_menu_on_event(void* context, SceneManagerEvent event) { consumed = true; break; case DesktopLockMenuEventPinLock: - if(desktop->settings.pincode.length > 0) { - desktop->settings.locked = true; - desktop_settings_save(&desktop->settings); + furi_hal_lock_set(true); + furi_hal_usb_disable(); scene_manager_set_scene_state( desktop->scene_manager, DesktopSceneLocked, DesktopLockedWithPin); scene_manager_next_scene(desktop->scene_manager, DesktopSceneLocked); @@ -43,10 +45,10 @@ bool desktop_scene_lock_menu_on_event(void* context, SceneManagerEvent event) { consumed = true; break; case DesktopLockMenuEventExit: - scene_manager_next_scene(desktop->scene_manager, DesktopSceneMain); + scene_manager_search_and_switch_to_previous_scene( + desktop->scene_manager, DesktopSceneMain); consumed = true; break; - default: break; } diff --git a/applications/desktop/scenes/desktop_scene_locked.c b/applications/desktop/scenes/desktop_scene_locked.c index ad436212..b8111ed7 100644 --- a/applications/desktop/scenes/desktop_scene_locked.c +++ b/applications/desktop/scenes/desktop_scene_locked.c @@ -1,5 +1,6 @@ #include "../desktop_i.h" #include "../views/desktop_locked.h" +#include void desktop_scene_locked_callback(DesktopLockedEvent event, void* context) { Desktop* desktop = (Desktop*)context; @@ -40,8 +41,8 @@ static bool desktop_scene_locked_check_pin(Desktop* desktop, DesktopMainEvent ev if(match) { desktop->pincode_buffer.length = 0; - desktop->settings.locked = false; - desktop_settings_save(&desktop->settings); + furi_hal_usb_enable(); + furi_hal_lock_set(false); desktop_main_unlocked(desktop->main_view); } diff --git a/applications/desktop/scenes/desktop_scene_main.c b/applications/desktop/scenes/desktop_scene_main.c index 4065b51c..36c8bdee 100644 --- a/applications/desktop/scenes/desktop_scene_main.c +++ b/applications/desktop/scenes/desktop_scene_main.c @@ -34,8 +34,6 @@ void desktop_scene_main_on_enter(void* context) { desktop_main_set_callback(main_view, desktop_scene_main_callback, desktop); view_port_enabled_set(desktop->lock_viewport, false); - desktop_settings_load(&desktop->settings); - if(scene_manager_get_scene_state(desktop->scene_manager, DesktopSceneMain) == DesktopMainEventUnlocked) { desktop_main_unlocked(desktop->main_view); @@ -72,7 +70,7 @@ bool desktop_scene_main_on_event(void* context, SceneManagerEvent event) { break; case DesktopMainEventOpenFavorite: - desktop_settings_load(&desktop->settings); + LOAD_DESKTOP_SETTINGS(&desktop->settings); desktop_switch_to_app(desktop, &FLIPPER_APPS[desktop->settings.favorite]); consumed = true; break; diff --git a/applications/desktop/scenes/desktop_scene_pinsetup.c b/applications/desktop/scenes/desktop_scene_pinsetup.c index 78515d7e..6b1c9686 100644 --- a/applications/desktop/scenes/desktop_scene_pinsetup.c +++ b/applications/desktop/scenes/desktop_scene_pinsetup.c @@ -4,7 +4,6 @@ void desktop_scene_ok_callback(void* context) { Desktop* app = context; - desktop_settings_save(&app->settings); view_dispatcher_send_custom_event(app->view_dispatcher, SCENE_EXIT_EVENT); } @@ -45,6 +44,7 @@ bool desktop_scene_pinsetup_on_event(void* context, SceneManagerEvent event) { void desktop_scene_pinsetup_on_exit(void* context) { Desktop* app = context; + SAVE_DESKTOP_SETTINGS(&app->settings); code_input_set_result_callback(app->code_input, NULL, NULL, NULL, NULL, NULL, 0); code_input_set_header_text(app->code_input, ""); } diff --git a/applications/desktop/views/desktop_lock_menu.h b/applications/desktop/views/desktop_lock_menu.h index f86b5d74..73f4f203 100644 --- a/applications/desktop/views/desktop_lock_menu.h +++ b/applications/desktop/views/desktop_lock_menu.h @@ -10,7 +10,6 @@ typedef enum { DesktopLockMenuEventLock, - DesktopLockMenuEventUnlock, DesktopLockMenuEventPinLock, DesktopLockMenuEventExit, } DesktopLockMenuEvent; diff --git a/applications/dolphin/dolphin.c b/applications/dolphin/dolphin.c index f1f1e5e5..1415f435 100644 --- a/applications/dolphin/dolphin.c +++ b/applications/dolphin/dolphin.c @@ -81,12 +81,7 @@ static void dolphin_check_butthurt(DolphinState* state) { furi_assert(state); float diff_time = difftime(dolphin_state_get_timestamp(state), dolphin_state_timestamp()); -#if 0 - FURI_LOG_I("dolphin-state", "Butthurt check, time since deed %.0f", fabs(diff_time)); -#endif - if((fabs(diff_time)) > DOLPHIN_TIMEGATE) { - // increase butthurt FURI_LOG_I("dolphin-state", "Increasing butthurt"); dolphin_state_butthurted(state); } diff --git a/applications/dolphin/helpers/dolphin_state.c b/applications/dolphin/helpers/dolphin_state.c index 240b7d95..450add29 100644 --- a/applications/dolphin/helpers/dolphin_state.c +++ b/applications/dolphin/helpers/dolphin_state.c @@ -2,20 +2,13 @@ #include #include #include +#include -#define DOLPHIN_STORE_KEY "/int/dolphin.state" +#define DOLPHIN_STORE_PATH "/int/dolphin.state" #define DOLPHIN_STORE_HEADER_MAGIC 0xD0 #define DOLPHIN_STORE_HEADER_VERSION 0x01 #define DOLPHIN_LVL_THRESHOLD 20.0f -typedef struct { - uint8_t magic; - uint8_t version; - uint8_t checksum; - uint8_t flags; - uint32_t timestamp; -} DolphinStoreHeader; - typedef struct { uint32_t limit_ibutton; uint32_t limit_nfc; @@ -28,148 +21,42 @@ typedef struct { uint64_t timestamp; } DolphinStoreData; -typedef struct { - DolphinStoreHeader header; - DolphinStoreData data; -} DolphinStore; - struct DolphinState { - Storage* fs_api; DolphinStoreData data; bool dirty; }; DolphinState* dolphin_state_alloc() { - DolphinState* dolphin_state = furi_alloc(sizeof(DolphinState)); - dolphin_state->fs_api = furi_record_open("storage"); - return dolphin_state; + return furi_alloc(sizeof(DolphinState)); } void dolphin_state_free(DolphinState* dolphin_state) { - furi_record_close("storage"); free(dolphin_state); } bool dolphin_state_save(DolphinState* dolphin_state) { - if(!dolphin_state->dirty) { - return true; - } - - FURI_LOG_I("dolphin-state", "State is dirty, saving to \"%s\"", DOLPHIN_STORE_KEY); - DolphinStore store; - // Calculate checksum - uint8_t* source = (uint8_t*)&dolphin_state->data; - uint8_t checksum = 0; - for(size_t i = 0; i < sizeof(DolphinStoreData); i++) { - checksum += source[i]; - } - // Set header - store.header.magic = DOLPHIN_STORE_HEADER_MAGIC; - store.header.version = DOLPHIN_STORE_HEADER_VERSION; - store.header.checksum = checksum; - store.header.flags = 0; - store.header.timestamp = 0; - // Set data - store.data = dolphin_state->data; - - // Store - File* file = storage_file_alloc(dolphin_state->fs_api); - bool save_result = storage_file_open(file, DOLPHIN_STORE_KEY, FSAM_WRITE, FSOM_CREATE_ALWAYS); - - if(save_result) { - uint16_t bytes_count = storage_file_write(file, &store, sizeof(DolphinStore)); - - if(bytes_count != sizeof(DolphinStore)) { - save_result = false; - } - } - - if(!save_result) { - FURI_LOG_E( - "dolphin-state", - "Save failed. Storage returned: %s", - storage_file_get_error_desc(file)); - } - - storage_file_close(file); - storage_file_free(file); - - dolphin_state->dirty = !save_result; - - FURI_LOG_I("dolphin-state", "Saved"); - - return save_result; + return saved_struct_save( + DOLPHIN_STORE_PATH, + &dolphin_state->data, + sizeof(DolphinStoreData), + DOLPHIN_STORE_HEADER_MAGIC, + DOLPHIN_STORE_HEADER_VERSION); } bool dolphin_state_load(DolphinState* dolphin_state) { - DolphinStore store; - // Read Dolphin State Store - FURI_LOG_I("dolphin-state", "Loading state from \"%s\"", DOLPHIN_STORE_KEY); - - File* file = storage_file_alloc(dolphin_state->fs_api); - bool load_result = storage_file_open(file, DOLPHIN_STORE_KEY, FSAM_READ, FSOM_OPEN_EXISTING); - if(!load_result) { - FURI_LOG_E( - "dolphin-state", - "Load failed. Storage returned: %s", - storage_file_get_error_desc(file)); - } else { - uint16_t bytes_count = storage_file_read(file, &store, sizeof(DolphinStore)); - - if(bytes_count != sizeof(DolphinStore)) { - load_result = false; - } + bool loaded = saved_struct_load( + DOLPHIN_STORE_PATH, + &dolphin_state->data, + sizeof(DolphinStoreData), + DOLPHIN_STORE_HEADER_MAGIC, + DOLPHIN_STORE_HEADER_VERSION); + if(!loaded) { + FURI_LOG_W("dolphin-state", "Reset dolphin-state"); + memset(dolphin_state, 0, sizeof(*dolphin_state)); + dolphin_state_save(dolphin_state); } - if(!load_result) { - FURI_LOG_E("dolphin-state", "DolphinStore size mismatch"); - } else { - if(store.header.magic == DOLPHIN_STORE_HEADER_MAGIC && - store.header.version == DOLPHIN_STORE_HEADER_VERSION) { - FURI_LOG_I( - "dolphin-state", - "Magic(%d) and Version(%d) match", - store.header.magic, - store.header.version); - uint8_t checksum = 0; - const uint8_t* source = (const uint8_t*)&store.data; - for(size_t i = 0; i < sizeof(DolphinStoreData); i++) { - checksum += source[i]; - } - - if(store.header.checksum == checksum) { - FURI_LOG_I("dolphin-state", "Checksum(%d) match", store.header.checksum); - dolphin_state->data = store.data; - } else { - FURI_LOG_E( - "dolphin-state", - "Checksum(%d != %d) mismatch", - store.header.checksum, - checksum); - load_result = false; - } - } else { - FURI_LOG_E( - "dolphin-state", - "Magic(%d != %d) or Version(%d != %d) mismatch", - store.header.magic, - DOLPHIN_STORE_HEADER_MAGIC, - store.header.version, - DOLPHIN_STORE_HEADER_VERSION); - load_result = false; - } - } - - storage_file_close(file); - storage_file_free(file); - - dolphin_state->dirty = !load_result; - - return load_result; -} - -void dolphin_state_clear(DolphinState* dolphin_state) { - memset(&dolphin_state->data, 0, sizeof(DolphinStoreData)); + return true; } uint64_t dolphin_state_timestamp() { @@ -229,4 +116,4 @@ uint32_t dolphin_state_get_level(uint32_t icounter) { uint32_t dolphin_state_xp_to_levelup(uint32_t icounter, uint32_t level, bool remaining) { return (DOLPHIN_LVL_THRESHOLD * level * (level + 1) / 2) - (remaining ? icounter : 0); -} \ No newline at end of file +} diff --git a/firmware/targets/f6/furi-hal/furi-hal-lock.c b/firmware/targets/f6/furi-hal/furi-hal-lock.c new file mode 100644 index 00000000..0f519380 --- /dev/null +++ b/firmware/targets/f6/furi-hal/furi-hal-lock.c @@ -0,0 +1,17 @@ +#include "furi-hal-lock.h" +#include + +#define FLIPPER_LOCKED_VALUE 0x5432FAFA + +bool furi_hal_lock_get() { + return FLIPPER_LOCKED_VALUE == LL_RTC_BAK_GetRegister(RTC, LL_RTC_BKP_DR3); +} + +void furi_hal_lock_set(bool locked) { + if (locked) { + LL_RTC_BAK_SetRegister(RTC, LL_RTC_BKP_DR3, FLIPPER_LOCKED_VALUE); + } else { + LL_RTC_BAK_SetRegister(RTC, LL_RTC_BKP_DR3, 0); + } +} + diff --git a/firmware/targets/f7/furi-hal/furi-hal-lock.c b/firmware/targets/f7/furi-hal/furi-hal-lock.c new file mode 100644 index 00000000..0f519380 --- /dev/null +++ b/firmware/targets/f7/furi-hal/furi-hal-lock.c @@ -0,0 +1,17 @@ +#include "furi-hal-lock.h" +#include + +#define FLIPPER_LOCKED_VALUE 0x5432FAFA + +bool furi_hal_lock_get() { + return FLIPPER_LOCKED_VALUE == LL_RTC_BAK_GetRegister(RTC, LL_RTC_BKP_DR3); +} + +void furi_hal_lock_set(bool locked) { + if (locked) { + LL_RTC_BAK_SetRegister(RTC, LL_RTC_BKP_DR3, FLIPPER_LOCKED_VALUE); + } else { + LL_RTC_BAK_SetRegister(RTC, LL_RTC_BKP_DR3, 0); + } +} + diff --git a/firmware/targets/furi-hal-include/furi-hal-lock.h b/firmware/targets/furi-hal-include/furi-hal-lock.h new file mode 100644 index 00000000..d07ce571 --- /dev/null +++ b/firmware/targets/furi-hal-include/furi-hal-lock.h @@ -0,0 +1,5 @@ +#pragma once +#include + +bool furi_hal_lock_get(); +void furi_hal_lock_set(bool locked); diff --git a/lib/toolbox/saved_struct.c b/lib/toolbox/saved_struct.c new file mode 100644 index 00000000..61b5bdc6 --- /dev/null +++ b/lib/toolbox/saved_struct.c @@ -0,0 +1,149 @@ +#include "saved_struct.h" +#include +#include +#include + +#define SAVED_STRUCT_TAG "SAVED_STRUCT" + +typedef struct { + uint8_t magic; + uint8_t version; + uint8_t checksum; + uint8_t flags; + uint32_t timestamp; +} SavedStructHeader; + +bool saved_struct_save(const char* path, + void* data, + size_t size, + uint8_t magic, + uint8_t version) { + furi_assert(path); + furi_assert(data); + furi_assert(size); + SavedStructHeader header; + + FURI_LOG_I(SAVED_STRUCT_TAG, "Saving \"%s\"", path); + + // Store + Storage* storage = furi_record_open("storage"); + File* file = storage_file_alloc(storage); + bool result = true; + bool saved = storage_file_open(file, path, FSAM_WRITE, FSOM_CREATE_ALWAYS); + if(!saved) { + FURI_LOG_E( + SAVED_STRUCT_TAG, + "Open failed \"%s\". Error: \'%s\'", + path, + storage_file_get_error_desc(file)); + result = false; + } + + if(result) { + // Calculate checksum + uint8_t checksum = 0; + uint8_t* source = data; + for(size_t i = 0; i < size; i++) { + checksum += source[i]; + } + // Set header + header.magic = magic; + header.version = version; + header.checksum = checksum; + header.flags = 0; + header.timestamp = 0; + + uint16_t bytes_count = storage_file_write(file, &header, sizeof(header)); + bytes_count += storage_file_write(file, data, size); + + if(bytes_count != (size + sizeof(header))) { + FURI_LOG_E( + SAVED_STRUCT_TAG, + "Write failed \"%s\". Error: \'%s\'", + path, + storage_file_get_error_desc(file)); + result = false; + } + } + + storage_file_close(file); + storage_file_free(file); + furi_record_close("storage"); + return result; +} + +bool saved_struct_load(const char* path, + void* data, + size_t size, + uint8_t magic, + uint8_t version) { + FURI_LOG_I(SAVED_STRUCT_TAG, "Loading \"%s\"", path); + + SavedStructHeader header; + + uint8_t* data_read = furi_alloc(size); + Storage* storage = furi_record_open("storage"); + File* file = storage_file_alloc(storage); + bool result = true; + bool loaded = storage_file_open(file, path, FSAM_READ, FSOM_OPEN_EXISTING); + if (!loaded) { + FURI_LOG_E( + SAVED_STRUCT_TAG, + "Failed to read \"%s\". Error: %s", + path, + storage_file_get_error_desc(file)); + result = false; + } + + if (result) { + uint16_t bytes_count = storage_file_read(file, &header, sizeof(SavedStructHeader)); + bytes_count += storage_file_read(file, data_read, size); + + if(bytes_count != (sizeof(SavedStructHeader) + size)) { + FURI_LOG_E(SAVED_STRUCT_TAG, "Size mismatch of file \"%s\"", path); + result = false; + } + } + + if(result && (header.magic != magic || header.version != version)) { + FURI_LOG_E( + SAVED_STRUCT_TAG, + "Magic(%d != %d) or Version(%d != %d) mismatch of file \"%s\"", + header.magic, + magic, + header.version, + version, + path); + result = false; + } + + if(result) { + uint8_t checksum = 0; + const uint8_t* source = (const uint8_t*)data_read; + for(size_t i = 0; i < size; i++) { + checksum += source[i]; + } + + if(header.checksum != checksum) { + FURI_LOG_E( + SAVED_STRUCT_TAG, + "Checksum(%d != %d) mismatch of file \"%s\"", + header.checksum, + checksum, + path); + result = false; + } + } + + if (result) { + memcpy(data, data_read, size); + } + + storage_file_close(file); + storage_file_free(file); + furi_record_close("storage"); + free(data_read); + + return result; +} + diff --git a/lib/toolbox/saved_struct.h b/lib/toolbox/saved_struct.h new file mode 100644 index 00000000..09b7024f --- /dev/null +++ b/lib/toolbox/saved_struct.h @@ -0,0 +1,18 @@ +#pragma once + +#include +#include +#include + +bool saved_struct_load(const char* path, + void* data, + size_t size, + uint8_t magic, + uint8_t version); + +bool saved_struct_save(const char* path, + void* data, + size_t size, + uint8_t magic, + uint8_t version); +