Storage: remove LFS (#3577)

* Storage: drop internal storage

* Storage: rollback some unnecessary changes

* Storage: rollback some unnecessary changes part 2

* Storage: cleanup various defines and int handling. Ble: allow short connection interval if internal flash is not used.

* Storage: do not return storage if it is not ready

* Save PIN code to RTC, update settings

* Simplify the code, clean up includes

* Rearrange some code

* apps: storage_move_to_sd: conditionally enable with --extra-define=STORAGE_INT_ON_LFS

* Load Desktop settings automatically

* Redirect /any to /ext

* Abolish storage_move_to_sd app

* Remove as many mentions of ANY_PATH as possible

* Fix desktop settings wrongly not loading

* Improve desktop settings handling and strings

* Load BLE settings and keys automatically

* Improve BLE configuration procedure

* Do not load bluetooth keys twice if they were already loaded

* Load dolphin state automatically

* Fix merge artifact

* Load notification settings automatically

* Update desktop settings strings

* Load expansion settings automatically

* Do not use thread signals to reload desktop settings

* Load region data automatically, separate to its own hook

* Improve ble behaviour with no keys

* Fix Dolphin state not resetting correctly

* Add a status check

* Make Desktop save its own settings

* Check result when taking and releasing mutex

* Improve default thread signal handling in FuriEventLoop

* Make bt service in charge of saving settings, add settings api

* Fix a deadlock due to timer thread not receiving time

* Lock core2 when reinitialising bt

* Update clang-format

* Revert "Update clang-format"

This reverts commit d61295ac063c6ec879375ceeab54d6ff2c90a9a1.

* Format sources with clang-format

* Revert old stack size for desktop settings

* Allocate big struct dynamically

* Simplify PIN comparison

* Save pointer to storage in Desktop object

* Fix region provisioning for hardware regions

* Remove stale TODO + siimplify code

* Clean up region.c

* Use sizeof instead of macro define

* Limit PIN length to 10 for consistency

* Emit a warning upon usage of /any

* Add delay after finding flipper

* Remove unnecessary delay

* Remove all mentions of STORAGE_INT_ON_LFS

* Remove littlefs and internal storage

* Remove all possible LittleFS mentions

* Fix browser tab in Archive

* Ble: fix connection interval explanation

* Bump API Symbols

* BLE: Update comments interval connection comments

* Storage: clear FuriHalRtcFlagStorageFormatInternal if set

---------

Co-authored-by: Georgii Surkov <georgii.surkov@outlook.com>
Co-authored-by: hedger <hedger@nanode.su>
Co-authored-by: Georgii Surkov <37121527+gsurkov@users.noreply.github.com>
This commit is contained in:
あく
2024-08-04 18:54:02 +09:00
committed by GitHub
parent 4f46032d32
commit 4d985ba8f8
117 changed files with 1392 additions and 2125 deletions

View File

@@ -97,8 +97,11 @@ void animation_manager_set_interact_callback(
void animation_manager_set_dummy_mode_state(AnimationManager* animation_manager, bool enabled) {
furi_assert(animation_manager);
animation_manager->dummy_mode = enabled;
animation_manager_start_new_idle(animation_manager);
// Prevent change of animations if mode is the same
if(animation_manager->dummy_mode != enabled) {
animation_manager->dummy_mode = enabled;
animation_manager_start_new_idle(animation_manager);
}
}
static void animation_manager_check_blocking_callback(const void* message, void* context) {

View File

@@ -1,31 +1,24 @@
#include <storage/storage.h>
#include <assets_icons.h>
#include <gui/gui.h>
#include <gui/gui_i.h>
#include <gui/view_stack.h>
#include <notification/notification.h>
#include <notification/notification_messages.h>
#include <furi.h>
#include <furi_hal.h>
#include "desktop_i.h"
#include <cli/cli.h>
#include <cli/cli_vcp.h>
#include <locale/locale.h>
#include "animations/animation_manager.h"
#include "desktop/scenes/desktop_scene.h"
#include "desktop/scenes/desktop_scene_i.h"
#include "desktop/views/desktop_view_locked.h"
#include "desktop/views/desktop_view_pin_input.h"
#include "desktop/views/desktop_view_pin_timeout.h"
#include "desktop_i.h"
#include "helpers/pin.h"
#include "helpers/slideshow_filename.h"
#include <gui/gui_i.h>
#include <locale/locale.h>
#include <storage/storage.h>
#include <assets_icons.h>
#include "scenes/desktop_scene.h"
#include "scenes/desktop_scene_locked.h"
#define TAG "Desktop"
static void desktop_auto_lock_arm(Desktop*);
static void desktop_auto_lock_inhibit(Desktop*);
static void desktop_start_auto_lock_timer(Desktop*);
static void desktop_apply_settings(Desktop*);
static void desktop_loader_callback(const void* message, void* context) {
furi_assert(context);
@@ -42,6 +35,16 @@ static void desktop_loader_callback(const void* message, void* context) {
}
}
static void desktop_storage_callback(const void* message, void* context) {
furi_assert(context);
Desktop* desktop = context;
const StorageEvent* event = message;
if(event->type == StorageEventTypeCardMount) {
view_dispatcher_send_custom_event(desktop->view_dispatcher, DesktopGlobalReloadSettings);
}
}
static void desktop_lock_icon_draw_callback(Canvas* canvas, void* context) {
UNUSED(context);
furi_assert(canvas);
@@ -122,30 +125,39 @@ static bool desktop_custom_event_callback(void* context, uint32_t event) {
furi_assert(context);
Desktop* desktop = (Desktop*)context;
switch(event) {
case DesktopGlobalBeforeAppStarted:
if(event == DesktopGlobalBeforeAppStarted) {
if(animation_manager_is_animation_loaded(desktop->animation_manager)) {
animation_manager_unload_and_stall_animation(desktop->animation_manager);
}
desktop_auto_lock_inhibit(desktop);
desktop->app_running = true;
furi_semaphore_release(desktop->animation_semaphore);
return true;
case DesktopGlobalAfterAppFinished:
} else if(event == DesktopGlobalAfterAppFinished) {
animation_manager_load_and_continue_animation(desktop->animation_manager);
DESKTOP_SETTINGS_LOAD(&desktop->settings);
desktop_clock_reconfigure(desktop);
desktop_auto_lock_arm(desktop);
return true;
case DesktopGlobalAutoLock:
if(!loader_is_locked(desktop->loader) && !desktop->locked) {
desktop->app_running = false;
} else if(event == DesktopGlobalAutoLock) {
if(!desktop->app_running && !desktop->locked) {
desktop_lock(desktop);
}
return true;
} else if(event == DesktopGlobalSaveSettings) {
desktop_settings_save(&desktop->settings);
desktop_apply_settings(desktop);
} else if(event == DesktopGlobalReloadSettings) {
desktop_settings_load(&desktop->settings);
desktop_apply_settings(desktop);
} else {
return scene_manager_handle_custom_event(desktop->scene_manager, event);
}
return scene_manager_handle_custom_event(desktop->scene_manager, event);
return true;
}
static bool desktop_back_event_callback(void* context) {
@@ -205,84 +217,45 @@ static void desktop_clock_timer_callback(void* context) {
furi_assert(context);
Desktop* desktop = context;
if(gui_active_view_port_count(desktop->gui, GuiLayerStatusBarLeft) < 6) {
const bool clock_enabled = gui_active_view_port_count(desktop->gui, GuiLayerStatusBarLeft) < 6;
if(clock_enabled) {
desktop_clock_update(desktop);
view_port_enabled_set(desktop->clock_viewport, true);
} else {
view_port_enabled_set(desktop->clock_viewport, false);
}
}
void desktop_lock(Desktop* desktop) {
furi_assert(!desktop->locked);
furi_hal_rtc_set_flag(FuriHalRtcFlagLock);
if(desktop->settings.pin_code.length) {
Cli* cli = furi_record_open(RECORD_CLI);
cli_session_close(cli);
furi_record_close(RECORD_CLI);
}
desktop_auto_lock_inhibit(desktop);
scene_manager_set_scene_state(
desktop->scene_manager, DesktopSceneLocked, SCENE_LOCKED_FIRST_ENTER);
scene_manager_next_scene(desktop->scene_manager, DesktopSceneLocked);
DesktopStatus status = {.locked = true};
furi_pubsub_publish(desktop->status_pubsub, &status);
desktop->locked = true;
view_port_enabled_set(desktop->clock_viewport, clock_enabled);
}
void desktop_unlock(Desktop* desktop) {
furi_assert(desktop->locked);
view_port_enabled_set(desktop->lock_icon_viewport, false);
Gui* gui = furi_record_open(RECORD_GUI);
gui_set_lockdown(gui, false);
furi_record_close(RECORD_GUI);
desktop_view_locked_unlock(desktop->locked_view);
scene_manager_search_and_switch_to_previous_scene(desktop->scene_manager, DesktopSceneMain);
desktop_auto_lock_arm(desktop);
furi_hal_rtc_reset_flag(FuriHalRtcFlagLock);
furi_hal_rtc_set_pin_fails(0);
if(desktop->settings.pin_code.length) {
Cli* cli = furi_record_open(RECORD_CLI);
cli_session_open(cli, &cli_vcp);
furi_record_close(RECORD_CLI);
}
DesktopStatus status = {.locked = false};
furi_pubsub_publish(desktop->status_pubsub, &status);
desktop->locked = false;
}
void desktop_set_dummy_mode_state(Desktop* desktop, bool enabled) {
static void desktop_apply_settings(Desktop* desktop) {
desktop->in_transition = true;
view_port_enabled_set(desktop->dummy_mode_icon_viewport, enabled);
desktop_main_set_dummy_mode_state(desktop->main_view, enabled);
animation_manager_set_dummy_mode_state(desktop->animation_manager, enabled);
desktop->settings.dummy_mode = enabled;
DESKTOP_SETTINGS_SAVE(&desktop->settings);
desktop_clock_reconfigure(desktop);
view_port_enabled_set(desktop->dummy_mode_icon_viewport, desktop->settings.dummy_mode);
desktop_main_set_dummy_mode_state(desktop->main_view, desktop->settings.dummy_mode);
animation_manager_set_dummy_mode_state(
desktop->animation_manager, desktop->settings.dummy_mode);
if(!desktop->app_running && !desktop->locked) {
desktop_auto_lock_arm(desktop);
}
desktop->in_transition = false;
}
void desktop_set_stealth_mode_state(Desktop* desktop, bool enabled) {
desktop->in_transition = true;
if(enabled) {
furi_hal_rtc_set_flag(FuriHalRtcFlagStealthMode);
} else {
furi_hal_rtc_reset_flag(FuriHalRtcFlagStealthMode);
static void desktop_init_settings(Desktop* desktop) {
furi_pubsub_subscribe(storage_get_pubsub(desktop->storage), desktop_storage_callback, desktop);
if(storage_sd_status(desktop->storage) != FSE_OK) {
FURI_LOG_D(TAG, "SD Card not ready, skipping settings");
return;
}
view_port_enabled_set(desktop->stealth_mode_icon_viewport, enabled);
desktop->in_transition = false;
desktop_settings_load(&desktop->settings);
desktop_apply_settings(desktop);
}
Desktop* desktop_alloc(void) {
static Desktop* desktop_alloc(void) {
Desktop* desktop = malloc(sizeof(Desktop));
desktop->animation_semaphore = furi_semaphore_alloc(1, 0);
@@ -391,14 +364,13 @@ Desktop* desktop_alloc(void) {
}
gui_add_view_port(desktop->gui, desktop->stealth_mode_icon_viewport, GuiLayerStatusBarLeft);
// Unload animations before starting an application
desktop->loader = furi_record_open(RECORD_LOADER);
furi_pubsub_subscribe(loader_get_pubsub(desktop->loader), desktop_loader_callback, desktop);
desktop->storage = furi_record_open(RECORD_STORAGE);
desktop->notification = furi_record_open(RECORD_NOTIFICATION);
desktop->app_start_stop_subscription = furi_pubsub_subscribe(
loader_get_pubsub(desktop->loader), desktop_loader_callback, desktop);
desktop->input_events_pubsub = furi_record_open(RECORD_INPUT_EVENTS);
desktop->input_events_subscription = NULL;
desktop->auto_lock_timer =
furi_timer_alloc(desktop_auto_lock_timer_callback, FuriTimerTypeOnce, desktop);
@@ -408,19 +380,95 @@ Desktop* desktop_alloc(void) {
desktop->update_clock_timer =
furi_timer_alloc(desktop_clock_timer_callback, FuriTimerTypePeriodic, desktop);
desktop->app_running = loader_is_locked(desktop->loader);
furi_record_create(RECORD_DESKTOP, desktop);
return desktop;
}
static bool desktop_check_file_flag(const char* flag_path) {
Storage* storage = furi_record_open(RECORD_STORAGE);
bool exists = storage_common_stat(storage, flag_path, NULL) == FSE_OK;
furi_record_close(RECORD_STORAGE);
/*
* Private API
*/
return exists;
void desktop_lock(Desktop* desktop) {
furi_assert(!desktop->locked);
furi_hal_rtc_set_flag(FuriHalRtcFlagLock);
if(desktop_pin_code_is_set()) {
Cli* cli = furi_record_open(RECORD_CLI);
cli_session_close(cli);
furi_record_close(RECORD_CLI);
}
desktop_auto_lock_inhibit(desktop);
scene_manager_set_scene_state(
desktop->scene_manager, DesktopSceneLocked, DesktopSceneLockedStateFirstEnter);
scene_manager_next_scene(desktop->scene_manager, DesktopSceneLocked);
DesktopStatus status = {.locked = true};
furi_pubsub_publish(desktop->status_pubsub, &status);
desktop->locked = true;
}
void desktop_unlock(Desktop* desktop) {
furi_assert(desktop->locked);
view_port_enabled_set(desktop->lock_icon_viewport, false);
Gui* gui = furi_record_open(RECORD_GUI);
gui_set_lockdown(gui, false);
furi_record_close(RECORD_GUI);
desktop_view_locked_unlock(desktop->locked_view);
scene_manager_search_and_switch_to_previous_scene(desktop->scene_manager, DesktopSceneMain);
desktop_auto_lock_arm(desktop);
furi_hal_rtc_reset_flag(FuriHalRtcFlagLock);
furi_hal_rtc_set_pin_fails(0);
if(desktop_pin_code_is_set()) {
Cli* cli = furi_record_open(RECORD_CLI);
cli_session_open(cli, &cli_vcp);
furi_record_close(RECORD_CLI);
}
DesktopStatus status = {.locked = false};
furi_pubsub_publish(desktop->status_pubsub, &status);
desktop->locked = false;
}
void desktop_set_dummy_mode_state(Desktop* desktop, bool enabled) {
desktop->in_transition = true;
view_port_enabled_set(desktop->dummy_mode_icon_viewport, enabled);
desktop_main_set_dummy_mode_state(desktop->main_view, enabled);
animation_manager_set_dummy_mode_state(desktop->animation_manager, enabled);
desktop->settings.dummy_mode = enabled;
desktop->in_transition = false;
desktop_settings_save(&desktop->settings);
}
void desktop_set_stealth_mode_state(Desktop* desktop, bool enabled) {
desktop->in_transition = true;
if(enabled) {
furi_hal_rtc_set_flag(FuriHalRtcFlagStealthMode);
} else {
furi_hal_rtc_reset_flag(FuriHalRtcFlagStealthMode);
}
view_port_enabled_set(desktop->stealth_mode_icon_viewport, enabled);
desktop->in_transition = false;
}
/*
* Public API
*/
bool desktop_api_is_locked(Desktop* instance) {
furi_assert(instance);
return furi_hal_rtc_is_flag_set(FuriHalRtcFlagLock);
@@ -436,6 +484,30 @@ FuriPubSub* desktop_api_get_status_pubsub(Desktop* instance) {
return instance->status_pubsub;
}
void desktop_api_reload_settings(Desktop* instance) {
furi_assert(instance);
view_dispatcher_send_custom_event(instance->view_dispatcher, DesktopGlobalReloadSettings);
}
void desktop_api_get_settings(Desktop* instance, DesktopSettings* settings) {
furi_assert(instance);
furi_assert(settings);
*settings = instance->settings;
}
void desktop_api_set_settings(Desktop* instance, const DesktopSettings* settings) {
furi_assert(instance);
furi_assert(settings);
instance->settings = *settings;
view_dispatcher_send_custom_event(instance->view_dispatcher, DesktopGlobalSaveSettings);
}
/*
* Application thread
*/
int32_t desktop_srv(void* p) {
UNUSED(p);
@@ -448,31 +520,15 @@ int32_t desktop_srv(void* p) {
Desktop* desktop = desktop_alloc();
bool loaded = DESKTOP_SETTINGS_LOAD(&desktop->settings);
if(!loaded) {
memset(&desktop->settings, 0, sizeof(desktop->settings));
DESKTOP_SETTINGS_SAVE(&desktop->settings);
}
view_port_enabled_set(desktop->dummy_mode_icon_viewport, desktop->settings.dummy_mode);
desktop_clock_reconfigure(desktop);
desktop_main_set_dummy_mode_state(desktop->main_view, desktop->settings.dummy_mode);
animation_manager_set_dummy_mode_state(
desktop->animation_manager, desktop->settings.dummy_mode);
desktop_init_settings(desktop);
scene_manager_next_scene(desktop->scene_manager, DesktopSceneMain);
if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagLock)) {
desktop_lock(desktop);
} else {
if(!loader_is_locked(desktop->loader)) {
desktop_auto_lock_arm(desktop);
}
}
if(desktop_check_file_flag(SLIDESHOW_FS_PATH)) {
if(storage_file_exists(desktop->storage, SLIDESHOW_FS_PATH)) {
scene_manager_next_scene(desktop->scene_manager, DesktopSceneSlideshow);
}
@@ -496,14 +552,12 @@ int32_t desktop_srv(void* p) {
}
// Special case: autostart application is already running
if(loader_is_locked(desktop->loader) &&
animation_manager_is_animation_loaded(desktop->animation_manager)) {
if(desktop->app_running && animation_manager_is_animation_loaded(desktop->animation_manager)) {
animation_manager_unload_and_stall_animation(desktop->animation_manager);
}
view_dispatcher_run(desktop->view_dispatcher);
furi_crash("That was unexpected");
// Should never get here (a service thread will crash automatically if it returns)
return 0;
}

View File

@@ -2,16 +2,22 @@
#include <furi.h>
typedef struct Desktop Desktop;
#include "desktop_settings.h"
#define RECORD_DESKTOP "desktop"
bool desktop_api_is_locked(Desktop* instance);
void desktop_api_unlock(Desktop* instance);
typedef struct Desktop Desktop;
typedef struct {
bool locked;
} DesktopStatus;
bool desktop_api_is_locked(Desktop* instance);
void desktop_api_unlock(Desktop* instance);
FuriPubSub* desktop_api_get_status_pubsub(Desktop* instance);
void desktop_api_get_settings(Desktop* instance, DesktopSettings* settings);
void desktop_api_set_settings(Desktop* instance, const DesktopSettings* settings);

View File

@@ -1,6 +1,8 @@
#pragma once
#include "desktop.h"
#include "desktop_settings.h"
#include "animations/animation_manager.h"
#include "views/desktop_view_pin_timeout.h"
#include "views/desktop_view_pin_input.h"
@@ -9,9 +11,7 @@
#include "views/desktop_view_lock_menu.h"
#include "views/desktop_view_debug.h"
#include "views/desktop_view_slideshow.h"
#include <desktop/desktop_settings.h>
#include <furi.h>
#include <gui/gui.h>
#include <gui/view_stack.h>
#include <gui/view_dispatcher.h>
@@ -42,9 +42,8 @@ typedef struct {
} DesktopClock;
struct Desktop {
// Scene
FuriThread* scene_thread;
// GUI
Gui* gui;
ViewDispatcher* view_dispatcher;
SceneManager* scene_manager;
@@ -56,42 +55,38 @@ struct Desktop {
DesktopMainView* main_view;
DesktopViewPinTimeout* pin_timeout_view;
DesktopSlideshowView* slideshow_view;
DesktopViewPinInput* pin_input_view;
ViewStack* main_view_stack;
ViewStack* locked_view_stack;
DesktopSettings settings;
DesktopViewPinInput* pin_input_view;
ViewPort* lock_icon_viewport;
ViewPort* dummy_mode_icon_viewport;
ViewPort* clock_viewport;
ViewPort* stealth_mode_icon_viewport;
AnimationManager* animation_manager;
Loader* loader;
Storage* storage;
NotificationApp* notification;
FuriPubSubSubscription* app_start_stop_subscription;
FuriPubSub* status_pubsub;
FuriPubSub* input_events_pubsub;
FuriPubSubSubscription* input_events_subscription;
FuriTimer* auto_lock_timer;
FuriTimer* update_clock_timer;
FuriPubSub* status_pubsub;
AnimationManager* animation_manager;
FuriSemaphore* animation_semaphore;
DesktopClock clock;
DesktopSettings settings;
bool in_transition : 1;
bool locked : 1;
FuriSemaphore* animation_semaphore;
bool in_transition;
bool app_running;
bool locked;
};
Desktop* desktop_alloc(void);
void desktop_free(Desktop* desktop);
void desktop_lock(Desktop* desktop);
void desktop_unlock(Desktop* desktop);
void desktop_set_dummy_mode_state(Desktop* desktop, bool enabled);

View File

@@ -0,0 +1,79 @@
#include "desktop_settings.h"
#include "desktop_settings_filename.h"
#include <saved_struct.h>
#include <storage/storage.h>
#define TAG "DesktopSettings"
#define DESKTOP_SETTINGS_VER_10 (10)
#define DESKTOP_SETTINGS_VER (11)
#define DESKTOP_SETTINGS_PATH INT_PATH(DESKTOP_SETTINGS_FILE_NAME)
#define DESKTOP_SETTINGS_MAGIC (0x17)
typedef struct {
uint8_t reserved[11];
DesktopSettings settings;
} DesktopSettingsV10;
// Actual size of DesktopSettings v10
static_assert(sizeof(DesktopSettingsV10) == 1044);
void desktop_settings_load(DesktopSettings* settings) {
furi_assert(settings);
bool success = false;
do {
uint8_t version;
if(!saved_struct_get_metadata(DESKTOP_SETTINGS_PATH, NULL, &version, NULL)) break;
if(version == DESKTOP_SETTINGS_VER) {
success = saved_struct_load(
DESKTOP_SETTINGS_PATH,
settings,
sizeof(DesktopSettings),
DESKTOP_SETTINGS_MAGIC,
DESKTOP_SETTINGS_VER);
} else if(version == DESKTOP_SETTINGS_VER_10) {
DesktopSettingsV10* settings_v10 = malloc(sizeof(DesktopSettingsV10));
success = saved_struct_load(
DESKTOP_SETTINGS_PATH,
settings_v10,
sizeof(DesktopSettingsV10),
DESKTOP_SETTINGS_MAGIC,
DESKTOP_SETTINGS_VER_10);
if(success) {
*settings = settings_v10->settings;
}
free(settings_v10);
}
} while(false);
if(!success) {
FURI_LOG_W(TAG, "Failed to load file, using defaults");
memset(settings, 0, sizeof(DesktopSettings));
desktop_settings_save(settings);
}
}
void desktop_settings_save(const DesktopSettings* settings) {
furi_assert(settings);
const bool success = saved_struct_save(
DESKTOP_SETTINGS_PATH,
settings,
sizeof(DesktopSettings),
DESKTOP_SETTINGS_MAGIC,
DESKTOP_SETTINGS_VER);
if(!success) {
FURI_LOG_E(TAG, "Failed to save file");
}
}

View File

@@ -1,43 +1,9 @@
#pragma once
#include "desktop_settings_filename.h"
#include <furi_hal.h>
#include <stdint.h>
#include <stdbool.h>
#include <toolbox/saved_struct.h>
#include <storage/storage.h>
#define DESKTOP_SETTINGS_VER (10)
#define DESKTOP_SETTINGS_PATH INT_PATH(DESKTOP_SETTINGS_FILE_NAME)
#define DESKTOP_SETTINGS_MAGIC (0x17)
#define PIN_MAX_LENGTH 12
#define DESKTOP_SETTINGS_RUN_PIN_SETUP_ARG "run_pin_setup"
#define DESKTOP_SETTINGS_SAVE(x) \
saved_struct_save( \
DESKTOP_SETTINGS_PATH, \
(x), \
sizeof(DesktopSettings), \
DESKTOP_SETTINGS_MAGIC, \
DESKTOP_SETTINGS_VER)
#define DESKTOP_SETTINGS_LOAD(x) \
saved_struct_load( \
DESKTOP_SETTINGS_PATH, \
(x), \
sizeof(DesktopSettings), \
DESKTOP_SETTINGS_MAGIC, \
DESKTOP_SETTINGS_VER)
#define MAX_PIN_SIZE 10
#define MIN_PIN_SIZE 4
#define MAX_APP_LENGTH 128
typedef enum {
FavoriteAppLeftShort = 0,
FavoriteAppLeftShort,
FavoriteAppLeftLong,
FavoriteAppRightShort,
FavoriteAppRightLong,
@@ -45,7 +11,7 @@ typedef enum {
} FavoriteAppShortcut;
typedef enum {
DummyAppLeft = 0,
DummyAppLeft,
DummyAppRight,
DummyAppDown,
DummyAppOk,
@@ -53,19 +19,16 @@ typedef enum {
} DummyAppShortcut;
typedef struct {
InputKey data[MAX_PIN_SIZE];
uint8_t length;
} PinCode;
typedef struct {
char name_or_path[MAX_APP_LENGTH];
char name_or_path[128];
} FavoriteApp;
typedef struct {
PinCode pin_code;
uint32_t auto_lock_delay_ms;
uint8_t dummy_mode;
uint8_t display_clock;
FavoriteApp favorite_apps[FavoriteAppNumber];
FavoriteApp dummy_apps[DummyAppNumber];
} DesktopSettings;
void desktop_settings_load(DesktopSettings* settings);
void desktop_settings_save(const DesktopSettings* settings);

View File

@@ -1,72 +0,0 @@
#include "pin.h"
#include <notification/notification.h>
#include <notification/notification_messages.h>
#include <stddef.h>
#include <furi.h>
#include <furi_hal.h>
#include <gui/gui.h>
static const NotificationSequence sequence_pin_fail = {
&message_display_backlight_on,
&message_red_255,
&message_vibro_on,
&message_delay_100,
&message_vibro_off,
&message_red_0,
&message_delay_250,
&message_red_255,
&message_vibro_on,
&message_delay_100,
&message_vibro_off,
&message_red_0,
NULL,
};
static const uint8_t desktop_helpers_fails_timeout[] = {
0,
0,
0,
0,
30,
60,
90,
120,
150,
180,
/* +60 for every next fail */
};
void desktop_pin_lock_error_notify(void) {
NotificationApp* notification = furi_record_open(RECORD_NOTIFICATION);
notification_message(notification, &sequence_pin_fail);
furi_record_close(RECORD_NOTIFICATION);
}
uint32_t desktop_pin_lock_get_fail_timeout(void) {
uint32_t pin_fails = furi_hal_rtc_get_pin_fails();
uint32_t pin_timeout = 0;
uint32_t max_index = COUNT_OF(desktop_helpers_fails_timeout) - 1;
if(pin_fails <= max_index) {
pin_timeout = desktop_helpers_fails_timeout[pin_fails];
} else {
pin_timeout = desktop_helpers_fails_timeout[max_index] + (pin_fails - max_index) * 60;
}
return pin_timeout;
}
bool desktop_pin_compare(const PinCode* pin_code1, const PinCode* pin_code2) {
furi_assert(pin_code1);
furi_assert(pin_code2);
bool result = false;
if(pin_code1->length == pin_code2->length) {
result = !memcmp(pin_code1->data, pin_code2->data, pin_code1->length);
}
return result;
}

View File

@@ -1,11 +0,0 @@
#pragma once
#include <stdbool.h>
#include <stdint.h>
#include "../desktop.h"
#include <desktop/desktop_settings.h>
void desktop_pin_lock_error_notify(void);
uint32_t desktop_pin_lock_get_fail_timeout(void);
bool desktop_pin_compare(const PinCode* pin_code1, const PinCode* pin_code2);

View File

@@ -0,0 +1,103 @@
#include "pin_code.h"
#include <furi_hal_rtc.h>
#include <furi.h>
#include <notification/notification_messages.h>
#define DESKTOP_PIN_CODE_DIGIT_BIT_WIDTH (2)
#define DESKTOP_PIN_CODE_LENGTH_OFFSET (28)
static const NotificationSequence sequence_pin_fail = {
&message_display_backlight_on,
&message_red_255,
&message_vibro_on,
&message_delay_100,
&message_vibro_off,
&message_red_0,
&message_delay_250,
&message_red_255,
&message_vibro_on,
&message_delay_100,
&message_vibro_off,
&message_red_0,
NULL,
};
static const uint8_t desktop_helpers_fails_timeout[] = {
0,
0,
0,
0,
30,
60,
90,
120,
150,
180,
/* +60 for every next fail */
};
static uint32_t desktop_pin_code_pack(const DesktopPinCode* pin_code) {
furi_check(pin_code);
furi_check(pin_code->length <= sizeof(pin_code->data));
uint32_t reg_value = 0;
for(uint8_t i = 0; i < pin_code->length; ++i) {
furi_check(pin_code->data[i] < (1 << DESKTOP_PIN_CODE_DIGIT_BIT_WIDTH));
reg_value |= (uint32_t)pin_code->data[i] << (i * DESKTOP_PIN_CODE_DIGIT_BIT_WIDTH);
}
reg_value |= (uint32_t)pin_code->length << DESKTOP_PIN_CODE_LENGTH_OFFSET;
return reg_value;
}
bool desktop_pin_code_is_set(void) {
return furi_hal_rtc_get_pin_value() >> DESKTOP_PIN_CODE_LENGTH_OFFSET;
}
void desktop_pin_code_set(const DesktopPinCode* pin_code) {
furi_hal_rtc_set_pin_value(desktop_pin_code_pack(pin_code));
}
void desktop_pin_code_reset(void) {
furi_hal_rtc_set_pin_value(0);
}
bool desktop_pin_code_check(const DesktopPinCode* pin_code) {
return furi_hal_rtc_get_pin_value() == desktop_pin_code_pack(pin_code);
}
bool desktop_pin_code_is_equal(const DesktopPinCode* pin_code1, const DesktopPinCode* pin_code2) {
furi_check(pin_code1);
furi_check(pin_code1->length <= sizeof(pin_code1->data));
furi_check(pin_code2);
furi_check(pin_code2->length <= sizeof(pin_code2->data));
return pin_code1->length == pin_code2->length &&
memcmp(pin_code1->data, pin_code2->data, pin_code1->length) == 0;
}
void desktop_pin_lock_error_notify(void) {
NotificationApp* notification = furi_record_open(RECORD_NOTIFICATION);
notification_message(notification, &sequence_pin_fail);
furi_record_close(RECORD_NOTIFICATION);
}
uint32_t desktop_pin_lock_get_fail_timeout(void) {
uint32_t pin_fails = furi_hal_rtc_get_pin_fails();
uint32_t pin_timeout = 0;
uint32_t max_index = COUNT_OF(desktop_helpers_fails_timeout) - 1;
if(pin_fails <= max_index) {
pin_timeout = desktop_helpers_fails_timeout[pin_fails];
} else {
pin_timeout = desktop_helpers_fails_timeout[max_index] + (pin_fails - max_index) * 60;
}
return pin_timeout;
}

View File

@@ -0,0 +1,25 @@
#pragma once
#include <stdint.h>
#include <stdbool.h>
#define DESKTOP_PIN_CODE_MAX_LEN (10)
typedef struct {
uint8_t data[DESKTOP_PIN_CODE_MAX_LEN];
uint8_t length;
} DesktopPinCode;
bool desktop_pin_code_is_set(void);
void desktop_pin_code_set(const DesktopPinCode* pin_code);
void desktop_pin_code_reset(void);
bool desktop_pin_code_check(const DesktopPinCode* pin_code);
bool desktop_pin_code_is_equal(const DesktopPinCode* pin_code1, const DesktopPinCode* pin_code2);
void desktop_pin_lock_error_notify(void);
uint32_t desktop_pin_lock_get_fail_timeout(void);

View File

@@ -1,4 +0,0 @@
#pragma once
#define SCENE_LOCKED_FIRST_ENTER 0
#define SCENE_LOCKED_REPEAT_ENTER 1

View File

@@ -20,7 +20,6 @@ void desktop_scene_lock_menu_callback(DesktopEvent event, void* context) {
void desktop_scene_lock_menu_on_enter(void* context) {
Desktop* desktop = (Desktop*)context;
DESKTOP_SETTINGS_LOAD(&desktop->settings);
scene_manager_set_scene_state(desktop->scene_manager, DesktopSceneLockMenu, 0);
desktop_lock_menu_set_callback(desktop->lock_menu, desktop_scene_lock_menu_callback, desktop);
desktop_lock_menu_set_dummy_mode_state(desktop->lock_menu, desktop->settings.dummy_mode);
@@ -38,11 +37,8 @@ bool desktop_scene_lock_menu_on_event(void* context, SceneManagerEvent event) {
if(event.type == SceneManagerEventTypeTick) {
bool check_pin_changed =
scene_manager_get_scene_state(desktop->scene_manager, DesktopSceneLockMenu);
if(check_pin_changed) {
DESKTOP_SETTINGS_LOAD(&desktop->settings);
if(desktop->settings.pin_code.length > 0) {
scene_manager_set_scene_state(desktop->scene_manager, DesktopSceneLockMenu, 0);
}
if(check_pin_changed && desktop_pin_code_is_set()) {
scene_manager_set_scene_state(desktop->scene_manager, DesktopSceneLockMenu, 0);
}
} else if(event.type == SceneManagerEventTypeCustom) {
switch(event.event) {

View File

@@ -6,12 +6,12 @@
#include "../desktop.h"
#include "../desktop_i.h"
#include "../helpers/pin.h"
#include "../helpers/pin_code.h"
#include "../animations/animation_manager.h"
#include "../views/desktop_events.h"
#include "../views/desktop_view_locked.h"
#include "desktop_scene.h"
#include "desktop_scene_i.h"
#include "desktop_scene_locked.h"
#define WRONG_PIN_HEADER_TIMEOUT 3000
#define INPUT_PIN_VIEW_TIMEOUT 15000
@@ -42,15 +42,13 @@ void desktop_scene_locked_on_enter(void* context) {
bool switch_to_timeout_scene = false;
uint32_t state = scene_manager_get_scene_state(desktop->scene_manager, DesktopSceneLocked);
if(state == SCENE_LOCKED_FIRST_ENTER) {
bool pin_locked = desktop->settings.pin_code.length > 0;
if(state == DesktopSceneLockedStateFirstEnter) {
view_port_enabled_set(desktop->lock_icon_viewport, true);
Gui* gui = furi_record_open(RECORD_GUI);
gui_set_lockdown(gui, true);
furi_record_close(RECORD_GUI);
if(pin_locked) {
DESKTOP_SETTINGS_LOAD(&desktop->settings);
if(desktop_pin_code_is_set()) {
desktop_view_locked_lock(desktop->locked_view, true);
uint32_t pin_timeout = desktop_pin_lock_get_fail_timeout();
if(pin_timeout > 0) {
@@ -65,7 +63,7 @@ void desktop_scene_locked_on_enter(void* context) {
desktop_view_locked_close_doors(desktop->locked_view);
}
scene_manager_set_scene_state(
desktop->scene_manager, DesktopSceneLocked, SCENE_LOCKED_REPEAT_ENTER);
desktop->scene_manager, DesktopSceneLocked, DesktopSceneLockedStateRepeatEnter);
}
if(switch_to_timeout_scene) {

View File

@@ -0,0 +1,6 @@
#pragma once
typedef enum {
DesktopSceneLockedStateFirstEnter,
DesktopSceneLockedStateRepeatEnter,
} DesktopSceneLockedState;

View File

@@ -141,25 +141,21 @@ bool desktop_scene_main_on_event(void* context, SceneManagerEvent event) {
}
case DesktopMainEventOpenFavoriteLeftShort:
DESKTOP_SETTINGS_LOAD(&desktop->settings);
desktop_scene_main_start_favorite(
desktop, &desktop->settings.favorite_apps[FavoriteAppLeftShort]);
consumed = true;
break;
case DesktopMainEventOpenFavoriteLeftLong:
DESKTOP_SETTINGS_LOAD(&desktop->settings);
desktop_scene_main_start_favorite(
desktop, &desktop->settings.favorite_apps[FavoriteAppLeftLong]);
consumed = true;
break;
case DesktopMainEventOpenFavoriteRightShort:
DESKTOP_SETTINGS_LOAD(&desktop->settings);
desktop_scene_main_start_favorite(
desktop, &desktop->settings.favorite_apps[FavoriteAppRightShort]);
consumed = true;
break;
case DesktopMainEventOpenFavoriteRightLong:
DESKTOP_SETTINGS_LOAD(&desktop->settings);
desktop_scene_main_start_favorite(
desktop, &desktop->settings.favorite_apps[FavoriteAppRightLong]);
consumed = true;
@@ -175,7 +171,6 @@ bool desktop_scene_main_on_event(void* context, SceneManagerEvent event) {
break;
case DesktopAnimationEventInteractAnimation:
if(!animation_manager_interact_process(desktop->animation_manager)) {
DESKTOP_SETTINGS_LOAD(&desktop->settings);
if(!desktop->settings.dummy_mode) {
desktop_scene_main_open_app_or_profile(
desktop, &desktop->settings.favorite_apps[FavoriteAppRightShort]);

View File

@@ -10,7 +10,7 @@
#include "../desktop_i.h"
#include "../views/desktop_events.h"
#include "../views/desktop_view_pin_input.h"
#include "../helpers/pin.h"
#include "../helpers/pin_code.h"
#include "desktop_scene.h"
#define WRONG_PIN_HEADER_TIMEOUT 3000
@@ -49,10 +49,12 @@ static void desktop_scene_pin_input_back_callback(void* context) {
view_dispatcher_send_custom_event(desktop->view_dispatcher, DesktopPinInputEventBack);
}
static void desktop_scene_pin_input_done_callback(const PinCode* pin_code, void* context) {
static void desktop_scene_pin_input_done_callback(const DesktopPinCode* pin_code, void* context) {
Desktop* desktop = (Desktop*)context;
if(desktop_pin_compare(&desktop->settings.pin_code, pin_code)) {
if(desktop_pin_code_check(pin_code)) {
view_dispatcher_send_custom_event(desktop->view_dispatcher, DesktopPinInputEventUnlocked);
} else {
uint32_t pin_fails = furi_hal_rtc_get_pin_fails();
furi_hal_rtc_set_pin_fails(pin_fails + 1);

View File

@@ -45,9 +45,6 @@ bool desktop_scene_slideshow_on_event(void* context, SceneManagerEvent event) {
}
void desktop_scene_slideshow_on_exit(void* context) {
UNUSED(context);
Storage* storage = furi_record_open(RECORD_STORAGE);
storage_common_remove(storage, SLIDESHOW_FS_PATH);
furi_record_close(RECORD_STORAGE);
Desktop* desktop = context;
storage_common_remove(desktop->storage, SLIDESHOW_FS_PATH);
}

View File

@@ -55,4 +55,6 @@ typedef enum {
DesktopGlobalAfterAppFinished,
DesktopGlobalAutoLock,
DesktopGlobalApiUnlock,
DesktopGlobalSaveSettings,
DesktopGlobalReloadSettings,
} DesktopEvent;

View File

@@ -6,7 +6,6 @@
#include <stdint.h>
#include "desktop_view_pin_input.h"
#include <desktop/desktop_settings.h>
#define NO_ACTIVITY_TIMEOUT 15000
@@ -14,6 +13,9 @@
#define DEFAULT_PIN_X 64
#define DEFAULT_PIN_Y 32
#define MIN_PIN_LENGTH 4
#define MAX_PIN_LENGTH DESKTOP_PIN_CODE_MAX_LEN
struct DesktopViewPinInput {
View* view;
DesktopViewPinInputCallback back_callback;
@@ -24,7 +26,7 @@ struct DesktopViewPinInput {
};
typedef struct {
PinCode pin;
DesktopPinCode pin;
bool pin_hidden;
bool locked_input;
uint8_t pin_x;
@@ -50,7 +52,7 @@ static bool desktop_view_pin_input_input(InputEvent* event, void* context) {
bool call_back_callback = false;
bool call_done_callback = false;
PinCode pin_code = {0};
DesktopPinCode pin_code = {0};
if(event->type == InputTypeShort) {
switch(event->key) {
@@ -59,13 +61,13 @@ static bool desktop_view_pin_input_input(InputEvent* event, void* context) {
case InputKeyDown:
case InputKeyUp:
if(!model->locked_input) {
if(model->pin.length < MAX_PIN_SIZE) {
if(model->pin.length < MAX_PIN_LENGTH) {
model->pin.data[model->pin.length++] = event->key;
}
}
break;
case InputKeyOk:
if(model->pin.length >= MIN_PIN_SIZE) {
if(model->pin.length >= MIN_PIN_LENGTH) {
call_done_callback = true;
pin_code = model->pin;
}
@@ -102,7 +104,7 @@ static void desktop_view_pin_input_draw_cells(Canvas* canvas, DesktopViewPinInpu
furi_assert(model);
uint8_t draw_pin_size = MAX(4, model->pin.length + 1);
if(model->locked_input || (model->pin.length == MAX_PIN_SIZE)) {
if(model->locked_input || (model->pin.length == MAX_PIN_LENGTH)) {
draw_pin_size = model->pin.length;
}
@@ -155,7 +157,7 @@ static void desktop_view_pin_input_draw(Canvas* canvas, void* context) {
canvas_draw_str(canvas, 16, 60, "= clear");
}
if(model->button_label && ((model->pin.length >= MIN_PIN_SIZE) || model->locked_input)) {
if(model->button_label && ((model->pin.length >= MIN_PIN_LENGTH) || model->locked_input)) {
elements_button_center(canvas, model->button_label);
}
@@ -247,7 +249,7 @@ void desktop_view_pin_input_unlock_input(DesktopViewPinInput* pin_input) {
view_commit_model(pin_input->view, true);
}
void desktop_view_pin_input_set_pin(DesktopViewPinInput* pin_input, const PinCode* pin) {
void desktop_view_pin_input_set_pin(DesktopViewPinInput* pin_input, const DesktopPinCode* pin) {
furi_assert(pin_input);
furi_assert(pin);

View File

@@ -1,16 +1,17 @@
#pragma once
#include <gui/view.h>
#include <desktop/desktop_settings.h>
#include "../helpers/pin_code.h"
typedef void (*DesktopViewPinInputCallback)(void*);
typedef void (*DesktopViewPinInputDoneCallback)(const PinCode* pin_code, void*);
typedef void (*DesktopViewPinInputDoneCallback)(const DesktopPinCode* pin_code, void*);
typedef struct DesktopViewPinInput DesktopViewPinInput;
DesktopViewPinInput* desktop_view_pin_input_alloc(void);
void desktop_view_pin_input_free(DesktopViewPinInput*);
void desktop_view_pin_input_set_pin(DesktopViewPinInput* pin_input, const PinCode* pin);
void desktop_view_pin_input_set_pin(DesktopViewPinInput* pin_input, const DesktopPinCode* pin_code);
void desktop_view_pin_input_reset_pin(DesktopViewPinInput* pin_input);
void desktop_view_pin_input_hide_pin(DesktopViewPinInput* pin_input, bool pin_hidden);
void desktop_view_pin_input_set_label_button(DesktopViewPinInput* pin_input, const char* label);