diff --git a/applications/desktop/animations/views/one_shot_animation_view.c b/applications/desktop/animations/views/one_shot_animation_view.c index 106cef55..d7e9915a 100644 --- a/applications/desktop/animations/views/one_shot_animation_view.c +++ b/applications/desktop/animations/views/one_shot_animation_view.c @@ -81,7 +81,7 @@ OneShotView* one_shot_view_alloc(void) { OneShotView* view = furi_alloc(sizeof(OneShotView)); view->view = view_alloc(); view->update_timer = - xTimerCreate("Update timer", 1000, pdTRUE, view, one_shot_view_update_timer_callback); + xTimerCreate(NULL, 1000, pdTRUE, view, one_shot_view_update_timer_callback); view_allocate_model(view->view, ViewModelTypeLocking, sizeof(OneShotViewModel)); view_set_context(view->view, view); diff --git a/applications/desktop/desktop.c b/applications/desktop/desktop.c index 5d9b7b80..29e17a88 100644 --- a/applications/desktop/desktop.c +++ b/applications/desktop/desktop.c @@ -1,9 +1,3 @@ -#include "animations/animation_manager.h" -#include "desktop/scenes/desktop_scene.h" -#include "desktop/scenes/desktop_scene_i.h" -#include "desktop/views/desktop_locked.h" -#include "desktop_i.h" - #include #include #include @@ -12,23 +6,38 @@ #include #include +#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 "desktop_helpers.h" + static void desktop_lock_icon_callback(Canvas* canvas, void* context) { furi_assert(canvas); canvas_draw_icon(canvas, 0, 0, &I_Lock_8x8); } -bool desktop_custom_event_callback(void* context, uint32_t event) { +static bool desktop_custom_event_callback(void* context, uint32_t event) { furi_assert(context); Desktop* desktop = (Desktop*)context; return scene_manager_handle_custom_event(desktop->scene_manager, event); } -bool desktop_back_event_callback(void* context) { +static bool desktop_back_event_callback(void* context) { furi_assert(context); Desktop* desktop = (Desktop*)context; return scene_manager_handle_back_event(desktop->scene_manager); } +static void desktop_tick_event_callback(void* context) { + furi_assert(context); + Desktop* app = context; + scene_manager_handle_tick_event(app->scene_manager); +} + Desktop* desktop_alloc() { Desktop* desktop = furi_alloc(sizeof(Desktop)); @@ -42,6 +51,8 @@ Desktop* desktop_alloc() { view_dispatcher_enable_queue(desktop->view_dispatcher); view_dispatcher_attach_to_gui( desktop->view_dispatcher, desktop->gui, ViewDispatcherTypeDesktop); + view_dispatcher_set_tick_event_callback( + desktop->view_dispatcher, desktop_tick_event_callback, 500); view_dispatcher_set_event_callback_context(desktop->view_dispatcher, desktop); view_dispatcher_set_custom_event_callback( @@ -49,37 +60,60 @@ Desktop* desktop_alloc() { view_dispatcher_set_navigation_event_callback( desktop->view_dispatcher, desktop_back_event_callback); - desktop->locked_view = desktop_locked_alloc(); desktop->lock_menu = desktop_lock_menu_alloc(); desktop->debug_view = desktop_debug_alloc(); desktop->first_start_view = desktop_first_start_alloc(); desktop->hw_mismatch_popup = popup_alloc(); - desktop->code_input = code_input_alloc(); + desktop->locked_view = desktop_view_locked_alloc(); + desktop->pin_input_view = desktop_view_pin_input_alloc(); + desktop->pin_timeout_view = desktop_view_pin_timeout_alloc(); + desktop->main_view_stack = view_stack_alloc(); desktop->main_view = desktop_main_alloc(); View* dolphin_view = animation_manager_get_animation_view(desktop->animation_manager); view_stack_add_view(desktop->main_view_stack, desktop_main_get_view(desktop->main_view)); view_stack_add_view(desktop->main_view_stack, dolphin_view); - view_stack_add_view(desktop->main_view_stack, desktop_locked_get_view(desktop->locked_view)); + view_stack_add_view( + desktop->main_view_stack, desktop_view_locked_get_view(desktop->locked_view)); + + /* locked view (as animation view) attends in 2 scenes: main & locked, + * because it has to draw "Unlocked" label on main scene */ + desktop->locked_view_stack = view_stack_alloc(); + view_stack_add_view(desktop->locked_view_stack, dolphin_view); + view_stack_add_view( + desktop->locked_view_stack, desktop_view_locked_get_view(desktop->locked_view)); view_dispatcher_add_view( - desktop->view_dispatcher, DesktopViewMain, view_stack_get_view(desktop->main_view_stack)); + desktop->view_dispatcher, + DesktopViewIdMain, + view_stack_get_view(desktop->main_view_stack)); view_dispatcher_add_view( desktop->view_dispatcher, - DesktopViewLockMenu, + DesktopViewIdLocked, + view_stack_get_view(desktop->locked_view_stack)); + view_dispatcher_add_view( + desktop->view_dispatcher, + DesktopViewIdLockMenu, desktop_lock_menu_get_view(desktop->lock_menu)); view_dispatcher_add_view( - desktop->view_dispatcher, DesktopViewDebug, desktop_debug_get_view(desktop->debug_view)); + desktop->view_dispatcher, DesktopViewIdDebug, desktop_debug_get_view(desktop->debug_view)); view_dispatcher_add_view( desktop->view_dispatcher, - DesktopViewFirstStart, + DesktopViewIdFirstStart, desktop_first_start_get_view(desktop->first_start_view)); view_dispatcher_add_view( desktop->view_dispatcher, - DesktopViewHwMismatch, + DesktopViewIdHwMismatch, popup_get_view(desktop->hw_mismatch_popup)); view_dispatcher_add_view( - desktop->view_dispatcher, DesktopViewPinSetup, code_input_get_view(desktop->code_input)); + desktop->view_dispatcher, + DesktopViewIdPinTimeout, + desktop_view_pin_timeout_get_view(desktop->pin_timeout_view)); + view_dispatcher_add_view( + desktop->view_dispatcher, + DesktopViewIdPinInput, + desktop_view_pin_input_get_view(desktop->pin_input_view)); + // Lock icon desktop->lock_viewport = view_port_alloc(); view_port_set_width(desktop->lock_viewport, icon_get_width(&I_Lock_8x8)); @@ -93,27 +127,29 @@ Desktop* desktop_alloc() { void desktop_free(Desktop* desktop) { furi_assert(desktop); - view_dispatcher_remove_view(desktop->view_dispatcher, DesktopViewMain); - view_dispatcher_remove_view(desktop->view_dispatcher, DesktopViewLockMenu); - view_dispatcher_remove_view(desktop->view_dispatcher, DesktopViewLocked); - view_dispatcher_remove_view(desktop->view_dispatcher, DesktopViewDebug); - view_dispatcher_remove_view(desktop->view_dispatcher, DesktopViewFirstStart); - view_dispatcher_remove_view(desktop->view_dispatcher, DesktopViewHwMismatch); - view_dispatcher_remove_view(desktop->view_dispatcher, DesktopViewPinSetup); + view_dispatcher_remove_view(desktop->view_dispatcher, DesktopViewIdMain); + view_dispatcher_remove_view(desktop->view_dispatcher, DesktopViewIdLockMenu); + view_dispatcher_remove_view(desktop->view_dispatcher, DesktopViewIdLocked); + view_dispatcher_remove_view(desktop->view_dispatcher, DesktopViewIdDebug); + view_dispatcher_remove_view(desktop->view_dispatcher, DesktopViewIdFirstStart); + view_dispatcher_remove_view(desktop->view_dispatcher, DesktopViewIdHwMismatch); + view_dispatcher_remove_view(desktop->view_dispatcher, DesktopViewIdPinInput); + view_dispatcher_remove_view(desktop->view_dispatcher, DesktopViewIdPinTimeout); view_dispatcher_free(desktop->view_dispatcher); scene_manager_free(desktop->scene_manager); animation_manager_free(desktop->animation_manager); view_stack_free(desktop->main_view_stack); - view_stack_free(desktop->locked_view_stack); desktop_main_free(desktop->main_view); + view_stack_free(desktop->locked_view_stack); + desktop_view_locked_free(desktop->locked_view); desktop_lock_menu_free(desktop->lock_menu); - desktop_locked_free(desktop->locked_view); + desktop_view_locked_free(desktop->locked_view); desktop_debug_free(desktop->debug_view); desktop_first_start_free(desktop->first_start_view); popup_free(desktop->hw_mismatch_popup); - code_input_free(desktop->code_input); + desktop_view_pin_timeout_free(desktop->pin_timeout_view); osSemaphoreDelete(desktop->unload_animation_semaphore); @@ -145,14 +181,18 @@ int32_t desktop_srv(void* p) { SAVE_DESKTOP_SETTINGS(&desktop->settings); } - if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagLock)) { - furi_hal_usb_disable(); - scene_manager_set_scene_state( - desktop->scene_manager, DesktopSceneMain, DesktopMainSceneStateLockedWithPin); - } - scene_manager_next_scene(desktop->scene_manager, DesktopSceneMain); + if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagLock)) { + if(desktop->settings.pin_code.length > 0) { + scene_manager_set_scene_state( + desktop->scene_manager, DesktopSceneLocked, SCENE_LOCKED_FIRST_ENTER); + scene_manager_next_scene(desktop->scene_manager, DesktopSceneLocked); + } else { + furi_hal_rtc_reset_flag(FuriHalRtcFlagLock); + } + } + if(desktop_is_first_start()) { scene_manager_next_scene(desktop->scene_manager, DesktopSceneFirstStart); } diff --git a/applications/desktop/desktop_helpers.c b/applications/desktop/desktop_helpers.c new file mode 100644 index 00000000..c3025ae1 --- /dev/null +++ b/applications/desktop/desktop_helpers.c @@ -0,0 +1,82 @@ +#include +#include +#include +#include +#include +#include + +#include "desktop_helpers.h" +#include "desktop_i.h" + +static const NotificationSequence sequence_pin_fail = { + &message_display_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_helpers_emit_error_notification() { + NotificationApp* notification = furi_record_open("notification"); + notification_message(notification, &sequence_pin_fail); + furi_record_close("notification"); +} + +void desktop_helpers_lock_system(Desktop* desktop, bool hard_lock) { + view_port_enabled_set(desktop->lock_viewport, true); + if(hard_lock) { + furi_hal_rtc_set_flag(FuriHalRtcFlagLock); + furi_hal_usb_disable(); + } + + Gui* gui = furi_record_open("gui"); + gui_set_lockdown(gui, true); + furi_record_close("gui"); +} + +void desktop_helpers_unlock_system(Desktop* desktop) { + furi_hal_rtc_reset_flag(FuriHalRtcFlagLock); + furi_hal_usb_enable(); + view_port_enabled_set(desktop->lock_viewport, false); + + Gui* gui = furi_record_open("gui"); + gui_set_lockdown(gui, false); + furi_record_close("gui"); +} + +uint32_t desktop_helpers_get_pin_fail_timeout(uint32_t 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; +} diff --git a/applications/desktop/desktop_helpers.h b/applications/desktop/desktop_helpers.h new file mode 100644 index 00000000..f8393df8 --- /dev/null +++ b/applications/desktop/desktop_helpers.h @@ -0,0 +1,9 @@ +#pragma once +#include +#include +#include "desktop.h" + +void desktop_helpers_emit_error_notification(); +void desktop_helpers_lock_system(Desktop* desktop, bool hard_lock); +void desktop_helpers_unlock_system(Desktop* desktop); +uint32_t desktop_helpers_get_pin_fail_timeout(uint32_t pin_fails); diff --git a/applications/desktop/desktop_i.h b/applications/desktop/desktop_i.h index b6d0d923..fb15dbd7 100644 --- a/applications/desktop/desktop_i.h +++ b/applications/desktop/desktop_i.h @@ -2,11 +2,13 @@ #include "desktop.h" #include "animations/animation_manager.h" -#include "views/desktop_main.h" -#include "views/desktop_first_start.h" -#include "views/desktop_lock_menu.h" -#include "views/desktop_locked.h" -#include "views/desktop_debug.h" +#include "views/desktop_view_pin_timeout.h" +#include "views/desktop_view_pin_input.h" +#include "views/desktop_view_locked.h" +#include "views/desktop_view_main.h" +#include "views/desktop_view_first_start.h" +#include "views/desktop_view_lock_menu.h" +#include "views/desktop_view_debug.h" #include "desktop/desktop_settings/desktop_settings.h" #include @@ -14,21 +16,21 @@ #include #include #include -#include #include #define STATUS_BAR_Y_SHIFT 13 typedef enum { - DesktopViewMain, - DesktopViewLockMenu, - DesktopViewLocked, - DesktopViewDebug, - DesktopViewFirstStart, - DesktopViewHwMismatch, - DesktopViewPinSetup, - DesktopViewTotal, -} DesktopViewEnum; + DesktopViewIdMain, + DesktopViewIdLockMenu, + DesktopViewIdLocked, + DesktopViewIdDebug, + DesktopViewIdFirstStart, + DesktopViewIdHwMismatch, + DesktopViewIdPinInput, + DesktopViewIdPinTimeout, + DesktopViewIdTotal, +} DesktopViewId; struct Desktop { // Scene @@ -42,16 +44,15 @@ struct Desktop { Popup* hw_mismatch_popup; DesktopLockMenuView* lock_menu; DesktopDebugView* debug_view; - CodeInput* code_input; - + DesktopViewLocked* locked_view; DesktopMainView* main_view; - DesktopLockedView* locked_view; + DesktopViewPinTimeout* pin_timeout_view; ViewStack* main_view_stack; ViewStack* locked_view_stack; DesktopSettings settings; - PinCode pincode_buffer; + DesktopViewPinInput* pin_input_view; ViewPort* lock_viewport; diff --git a/applications/desktop/desktop_settings/desktop_settings.h b/applications/desktop/desktop_settings/desktop_settings.h index 27ded715..24165fe2 100644 --- a/applications/desktop/desktop_settings/desktop_settings.h +++ b/applications/desktop/desktop_settings/desktop_settings.h @@ -1,5 +1,6 @@ #pragma once +#include #include #include #include @@ -9,6 +10,8 @@ #define DESKTOP_SETTINGS_MAGIC (0x17) #define PIN_MAX_LENGTH 12 +#define DESKTOP_SETTINGS_RUN_PIN_SETUP_ARG "run_pin_setup" + #define SAVE_DESKTOP_SETTINGS(x) \ saved_struct_save( \ DESKTOP_SETTINGS_PATH, \ @@ -25,12 +28,27 @@ DESKTOP_SETTINGS_MAGIC, \ DESKTOP_SETTINGS_VER) +#define MAX_PIN_SIZE 10 +#define MIN_PIN_SIZE 4 + typedef struct { + InputKey data[MAX_PIN_SIZE]; uint8_t length; - uint8_t data[PIN_MAX_LENGTH]; } PinCode; typedef struct { uint16_t favorite; - PinCode pincode; + PinCode pin_code; } DesktopSettings; + +static inline bool pins_are_equal(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; +} diff --git a/applications/desktop/desktop_settings/desktop_settings_app.c b/applications/desktop/desktop_settings/desktop_settings_app.c index 1c65f58b..ca078ccd 100644 --- a/applications/desktop/desktop_settings/desktop_settings_app.c +++ b/applications/desktop/desktop_settings/desktop_settings_app.c @@ -1,6 +1,10 @@ -#include "desktop_settings_app.h" #include +#include +#include + +#include "desktop_settings_app.h" #include "scenes/desktop_settings_scene.h" +#include "../views/desktop_view_pin_input.h" static bool desktop_settings_custom_event_callback(void* context, uint32_t event) { furi_assert(context); @@ -30,17 +34,28 @@ DesktopSettingsApp* desktop_settings_app_alloc() { view_dispatcher_attach_to_gui(app->view_dispatcher, app->gui, ViewDispatcherTypeFullscreen); + app->popup = popup_alloc(); app->submenu = submenu_alloc(); + app->pin_input_view = desktop_view_pin_input_alloc(); + app->pin_setup_howto_view = desktop_settings_view_pin_setup_howto_alloc(); + app->pin_setup_howto2_view = desktop_settings_view_pin_setup_howto2_alloc(); + view_dispatcher_add_view( app->view_dispatcher, DesktopSettingsAppViewMenu, submenu_get_view(app->submenu)); - - app->code_input = code_input_alloc(); + view_dispatcher_add_view( + app->view_dispatcher, DesktopSettingsAppViewIdPopup, popup_get_view(app->popup)); view_dispatcher_add_view( app->view_dispatcher, - DesktopSettingsAppViewPincodeInput, - code_input_get_view(app->code_input)); - - scene_manager_next_scene(app->scene_manager, DesktopSettingsAppSceneStart); + DesktopSettingsAppViewIdPinInput, + desktop_view_pin_input_get_view(app->pin_input_view)); + view_dispatcher_add_view( + app->view_dispatcher, + DesktopSettingsAppViewIdPinSetupHowto, + desktop_settings_view_pin_setup_howto_get_view(app->pin_setup_howto_view)); + view_dispatcher_add_view( + app->view_dispatcher, + DesktopSettingsAppViewIdPinSetupHowto2, + desktop_settings_view_pin_setup_howto2_get_view(app->pin_setup_howto2_view)); return app; } @@ -48,9 +63,15 @@ void desktop_settings_app_free(DesktopSettingsApp* app) { furi_assert(app); // Variable item list view_dispatcher_remove_view(app->view_dispatcher, DesktopSettingsAppViewMenu); + view_dispatcher_remove_view(app->view_dispatcher, DesktopSettingsAppViewIdPopup); + view_dispatcher_remove_view(app->view_dispatcher, DesktopSettingsAppViewIdPinInput); + view_dispatcher_remove_view(app->view_dispatcher, DesktopSettingsAppViewIdPinSetupHowto); + view_dispatcher_remove_view(app->view_dispatcher, DesktopSettingsAppViewIdPinSetupHowto2); submenu_free(app->submenu); - view_dispatcher_remove_view(app->view_dispatcher, DesktopSettingsAppViewPincodeInput); - code_input_free(app->code_input); + popup_free(app->popup); + desktop_view_pin_input_free(app->pin_input_view); + desktop_settings_view_pin_setup_howto_free(app->pin_setup_howto_view); + desktop_settings_view_pin_setup_howto2_free(app->pin_setup_howto2_view); // View dispatcher view_dispatcher_free(app->view_dispatcher); scene_manager_free(app->scene_manager); @@ -62,6 +83,12 @@ 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); + if(!strcmp(p, DESKTOP_SETTINGS_RUN_PIN_SETUP_ARG)) { + scene_manager_next_scene(app->scene_manager, DesktopSettingsAppScenePinSetupHowto); + } else { + scene_manager_next_scene(app->scene_manager, DesktopSettingsAppSceneStart); + } + view_dispatcher_run(app->view_dispatcher); desktop_settings_app_free(app); return 0; diff --git a/applications/desktop/desktop_settings/desktop_settings_app.h b/applications/desktop/desktop_settings/desktop_settings_app.h index 9c37a154..6297e42d 100644 --- a/applications/desktop/desktop_settings/desktop_settings_app.h +++ b/applications/desktop/desktop_settings/desktop_settings_app.h @@ -1,22 +1,22 @@ #pragma once #include +#include #include #include #include -#include #include "desktop_settings.h" - -typedef enum { - CodeEventsSetPin, - CodeEventsChangePin, - CodeEventsDisablePin, -} CodeEventsEnum; +#include "desktop/views/desktop_view_pin_input.h" +#include "views/desktop_settings_view_pin_setup_howto.h" +#include "views/desktop_settings_view_pin_setup_howto2.h" typedef enum { DesktopSettingsAppViewMenu, - DesktopSettingsAppViewPincodeInput, + DesktopSettingsAppViewIdPopup, + DesktopSettingsAppViewIdPinInput, + DesktopSettingsAppViewIdPinSetupHowto, + DesktopSettingsAppViewIdPinSetupHowto2, } DesktopSettingsAppView; typedef struct { @@ -26,7 +26,13 @@ typedef struct { SceneManager* scene_manager; ViewDispatcher* view_dispatcher; Submenu* submenu; - CodeInput* code_input; + Popup* popup; + DesktopViewPinInput* pin_input_view; + DesktopSettingsViewPinSetupHowto* pin_setup_howto_view; + DesktopSettingsViewPinSetupHowto2* pin_setup_howto2_view; + + PinCode pincode_buffer; + bool pincode_buffer_filled; uint8_t menu_idx; diff --git a/applications/desktop/desktop_settings/scenes/desktop_settings_scene_config.h b/applications/desktop/desktop_settings/scenes/desktop_settings_scene_config.h index 126873db..5bc52172 100644 --- a/applications/desktop/desktop_settings/scenes/desktop_settings_scene_config.h +++ b/applications/desktop/desktop_settings/scenes/desktop_settings_scene_config.h @@ -1,4 +1,11 @@ ADD_SCENE(desktop_settings, start, Start) ADD_SCENE(desktop_settings, favorite, Favorite) -ADD_SCENE(desktop_settings, pincode_menu, PinCodeMenu) -ADD_SCENE(desktop_settings, pincode_input, PinCodeInput) +ADD_SCENE(desktop_settings, pin_menu, PinMenu) + +ADD_SCENE(desktop_settings, pin_auth, PinAuth) +ADD_SCENE(desktop_settings, pin_error, PinError) +ADD_SCENE(desktop_settings, pin_disable, PinDisable) +ADD_SCENE(desktop_settings, pin_setup, PinSetup) +ADD_SCENE(desktop_settings, pin_setup_howto, PinSetupHowto) +ADD_SCENE(desktop_settings, pin_setup_howto2, PinSetupHowto2) +ADD_SCENE(desktop_settings, pin_setup_done, PinSetupDone) diff --git a/applications/desktop/desktop_settings/scenes/desktop_settings_scene_i.h b/applications/desktop/desktop_settings/scenes/desktop_settings_scene_i.h new file mode 100644 index 00000000..230fec87 --- /dev/null +++ b/applications/desktop/desktop_settings/scenes/desktop_settings_scene_i.h @@ -0,0 +1,7 @@ +#pragma once + +#define SCENE_STATE_PIN_AUTH_DISABLE (0) +#define SCENE_STATE_PIN_AUTH_CHANGE_PIN (1) + +#define SCENE_STATE_PIN_ERROR_MISMATCH (0) +#define SCENE_STATE_PIN_ERROR_WRONG (1) diff --git a/applications/desktop/desktop_settings/scenes/desktop_settings_scene_pin_auth.c b/applications/desktop/desktop_settings/scenes/desktop_settings_scene_pin_auth.c new file mode 100644 index 00000000..c57506f9 --- /dev/null +++ b/applications/desktop/desktop_settings/scenes/desktop_settings_scene_pin_auth.c @@ -0,0 +1,95 @@ +#include +#include +#include + +#include "../desktop_settings_app.h" +#include "desktop/desktop_settings/desktop_settings.h" +#include "desktop/views/desktop_view_pin_input.h" +#include "desktop_settings_scene.h" +#include "desktop_settings_scene_i.h" + +#define SCENE_EVENT_EXIT (0U) +#define SCENE_EVENT_PINS_EQUAL (1U) +#define SCENE_EVENT_PINS_DIFFERENT (2U) + +static void pin_auth_done_callback(const PinCode* pin_code, void* context) { + furi_assert(pin_code); + furi_assert(context); + DesktopSettingsApp* app = context; + + app->pincode_buffer = *pin_code; + if(pins_are_equal(&app->settings.pin_code, pin_code)) { + view_dispatcher_send_custom_event(app->view_dispatcher, SCENE_EVENT_PINS_EQUAL); + } else { + view_dispatcher_send_custom_event(app->view_dispatcher, SCENE_EVENT_PINS_DIFFERENT); + } +} + +static void pin_auth_back_callback(void* context) { + DesktopSettingsApp* app = context; + view_dispatcher_send_custom_event(app->view_dispatcher, SCENE_EVENT_EXIT); +} + +void desktop_settings_scene_pin_auth_on_enter(void* context) { + DesktopSettingsApp* app = context; + + LOAD_DESKTOP_SETTINGS(&app->settings); + furi_assert(app->settings.pin_code.length > 0); + + desktop_view_pin_input_set_context(app->pin_input_view, app); + desktop_view_pin_input_set_back_callback(app->pin_input_view, pin_auth_back_callback); + desktop_view_pin_input_set_done_callback(app->pin_input_view, pin_auth_done_callback); + desktop_view_pin_input_set_label_button(app->pin_input_view, "OK"); + desktop_view_pin_input_set_label_primary(app->pin_input_view, 0, 0, NULL); + desktop_view_pin_input_set_label_secondary( + app->pin_input_view, 0, 8, "Enter your current PIN:"); + desktop_view_pin_input_reset_pin(app->pin_input_view); + desktop_view_pin_input_unlock_input(app->pin_input_view); + view_dispatcher_switch_to_view(app->view_dispatcher, DesktopSettingsAppViewIdPinInput); +} + +bool desktop_settings_scene_pin_auth_on_event(void* context, SceneManagerEvent event) { + DesktopSettingsApp* app = context; + bool consumed = false; + + if(event.type == SceneManagerEventTypeCustom) { + switch(event.event) { + case SCENE_EVENT_PINS_DIFFERENT: + scene_manager_set_scene_state( + app->scene_manager, DesktopSettingsAppScenePinError, SCENE_STATE_PIN_ERROR_WRONG); + scene_manager_next_scene(app->scene_manager, DesktopSettingsAppScenePinError); + consumed = true; + break; + case SCENE_EVENT_PINS_EQUAL: { + uint32_t state = + scene_manager_get_scene_state(app->scene_manager, DesktopSettingsAppScenePinAuth); + if(state == SCENE_STATE_PIN_AUTH_CHANGE_PIN) { + scene_manager_next_scene(app->scene_manager, DesktopSettingsAppScenePinSetupHowto); + } else if(state == SCENE_STATE_PIN_AUTH_DISABLE) { + scene_manager_next_scene(app->scene_manager, DesktopSettingsAppScenePinDisable); + } else { + furi_assert(0); + } + consumed = true; + break; + } + case SCENE_EVENT_EXIT: + scene_manager_search_and_switch_to_previous_scene( + app->scene_manager, DesktopSettingsAppScenePinMenu); + consumed = true; + break; + + default: + consumed = true; + break; + } + } + return consumed; +} + +void desktop_settings_scene_pin_auth_on_exit(void* context) { + furi_assert(context); + DesktopSettingsApp* app = context; + desktop_view_pin_input_set_back_callback(app->pin_input_view, NULL); + desktop_view_pin_input_set_done_callback(app->pin_input_view, NULL); +} diff --git a/applications/desktop/desktop_settings/scenes/desktop_settings_scene_pin_disable.c b/applications/desktop/desktop_settings/scenes/desktop_settings_scene_pin_disable.c new file mode 100644 index 00000000..7486d4aa --- /dev/null +++ b/applications/desktop/desktop_settings/scenes/desktop_settings_scene_pin_disable.c @@ -0,0 +1,56 @@ +#include +#include +#include +#include + +#include "../desktop_settings_app.h" +#include "../desktop_settings.h" +#include "desktop/desktop_settings/desktop_settings.h" +#include "desktop_settings_scene.h" + +#define SCENE_EVENT_EXIT (0U) + +static void pin_disable_back_callback(void* context) { + furi_assert(context); + DesktopSettingsApp* app = context; + view_dispatcher_send_custom_event(app->view_dispatcher, SCENE_EVENT_EXIT); +} + +void desktop_settings_scene_pin_disable_on_enter(void* context) { + furi_assert(context); + DesktopSettingsApp* app = context; + app->settings.pin_code.length = 0; + memset(app->settings.pin_code.data, '0', sizeof(app->settings.pin_code.data)); + SAVE_DESKTOP_SETTINGS(&app->settings); + + popup_set_context(app->popup, app); + popup_set_callback(app->popup, pin_disable_back_callback); + popup_set_icon(app->popup, 0, 2, &I_DolphinMafia_115x62); + popup_set_header(app->popup, "PIN\ndeleted!", 95, 9, AlignCenter, AlignCenter); + popup_set_timeout(app->popup, 1500); + popup_enable_timeout(app->popup); + view_dispatcher_switch_to_view(app->view_dispatcher, DesktopSettingsAppViewIdPopup); +} + +bool desktop_settings_scene_pin_disable_on_event(void* context, SceneManagerEvent event) { + DesktopSettingsApp* app = context; + bool consumed = false; + + if(event.type == SceneManagerEventTypeCustom) { + switch(event.event) { + case SCENE_EVENT_EXIT: + scene_manager_search_and_switch_to_previous_scene( + app->scene_manager, DesktopSettingsAppScenePinMenu); + consumed = true; + break; + + default: + consumed = true; + break; + } + } + return consumed; +} + +void desktop_settings_scene_pin_disable_on_exit(void* context) { +} diff --git a/applications/desktop/desktop_settings/scenes/desktop_settings_scene_pin_error.c b/applications/desktop/desktop_settings/scenes/desktop_settings_scene_pin_error.c new file mode 100644 index 00000000..07bba4a8 --- /dev/null +++ b/applications/desktop/desktop_settings/scenes/desktop_settings_scene_pin_error.c @@ -0,0 +1,76 @@ +#include +#include +#include + +#include "desktop/desktop_settings/desktop_settings.h" +#include "desktop/views/desktop_view_pin_input.h" +#include "desktop_settings_scene.h" +#include "desktop_settings_scene_i.h" +#include "../../desktop_helpers.h" +#include "../desktop_settings_app.h" + +#define SCENE_EVENT_EXIT (0U) + +static void pin_error_back_callback(void* context) { + furi_assert(context); + DesktopSettingsApp* app = context; + view_dispatcher_send_custom_event(app->view_dispatcher, SCENE_EVENT_EXIT); +} + +static void pin_error_done_callback(const PinCode* pin_code, void* context) { + furi_assert(context); + DesktopSettingsApp* app = context; + view_dispatcher_send_custom_event(app->view_dispatcher, SCENE_EVENT_EXIT); +} + +void desktop_settings_scene_pin_error_on_enter(void* context) { + DesktopSettingsApp* app = context; + desktop_helpers_emit_error_notification(); + + desktop_view_pin_input_set_context(app->pin_input_view, app); + desktop_view_pin_input_set_back_callback(app->pin_input_view, pin_error_back_callback); + desktop_view_pin_input_set_done_callback(app->pin_input_view, pin_error_done_callback); + + uint32_t state = + scene_manager_get_scene_state(app->scene_manager, DesktopSettingsAppScenePinError); + if(state == SCENE_STATE_PIN_ERROR_MISMATCH) { + desktop_view_pin_input_set_label_primary(app->pin_input_view, 29, 8, "PIN mismatch!"); + } else if(state == SCENE_STATE_PIN_ERROR_WRONG) { + desktop_view_pin_input_set_label_primary(app->pin_input_view, 35, 8, "Wrong PIN!"); + } else { + furi_assert(0); + } + desktop_view_pin_input_set_label_secondary(app->pin_input_view, 0, 8, NULL); + desktop_view_pin_input_set_label_button(app->pin_input_view, "Retry"); + desktop_view_pin_input_lock_input(app->pin_input_view); + desktop_view_pin_input_set_pin(app->pin_input_view, &app->pincode_buffer); + + view_dispatcher_switch_to_view(app->view_dispatcher, DesktopSettingsAppViewIdPinInput); +} + +bool desktop_settings_scene_pin_error_on_event(void* context, SceneManagerEvent event) { + DesktopSettingsApp* app = context; + bool consumed = false; + + if(event.type == SceneManagerEventTypeCustom) { + switch(event.event) { + case SCENE_EVENT_EXIT: + scene_manager_previous_scene(app->scene_manager); + consumed = true; + break; + + default: + consumed = true; + break; + } + } + return consumed; +} + +void desktop_settings_scene_pin_error_on_exit(void* context) { + furi_assert(context); + DesktopSettingsApp* app = context; + desktop_view_pin_input_unlock_input(app->pin_input_view); + desktop_view_pin_input_set_back_callback(app->pin_input_view, NULL); + desktop_view_pin_input_set_done_callback(app->pin_input_view, NULL); +} diff --git a/applications/desktop/desktop_settings/scenes/desktop_settings_scene_pincode_menu.c b/applications/desktop/desktop_settings/scenes/desktop_settings_scene_pin_menu.c similarity index 54% rename from applications/desktop/desktop_settings/scenes/desktop_settings_scene_pincode_menu.c rename to applications/desktop/desktop_settings/scenes/desktop_settings_scene_pin_menu.c index 9e72f52a..d226181d 100644 --- a/applications/desktop/desktop_settings/scenes/desktop_settings_scene_pincode_menu.c +++ b/applications/desktop/desktop_settings/scenes/desktop_settings_scene_pin_menu.c @@ -1,38 +1,45 @@ -#include "../desktop_settings_app.h" -#include "applications.h" -#include "desktop_settings_scene.h" +#include +#include -static void desktop_settings_scene_pincode_menu_submenu_callback(void* context, uint32_t index) { +#include "../desktop_settings_app.h" +#include "desktop_settings_scene.h" +#include "desktop_settings_scene_i.h" + +#define SCENE_EVENT_SET_PIN 0 +#define SCENE_EVENT_CHANGE_PIN 1 +#define SCENE_EVENT_DISABLE_PIN 2 + +static void desktop_settings_scene_pin_menu_submenu_callback(void* context, uint32_t index) { DesktopSettingsApp* app = context; view_dispatcher_send_custom_event(app->view_dispatcher, index); } -void desktop_settings_scene_pincode_menu_on_enter(void* context) { +void desktop_settings_scene_pin_menu_on_enter(void* context) { DesktopSettingsApp* app = context; Submenu* submenu = app->submenu; submenu_reset(submenu); - if(!app->settings.pincode.length) { + if(!app->settings.pin_code.length) { submenu_add_item( submenu, "Set Pin", - CodeEventsSetPin, - desktop_settings_scene_pincode_menu_submenu_callback, + SCENE_EVENT_SET_PIN, + desktop_settings_scene_pin_menu_submenu_callback, app); } else { submenu_add_item( submenu, "Change Pin", - CodeEventsChangePin, - desktop_settings_scene_pincode_menu_submenu_callback, + SCENE_EVENT_CHANGE_PIN, + desktop_settings_scene_pin_menu_submenu_callback, app); submenu_add_item( submenu, "Disable", - CodeEventsDisablePin, - desktop_settings_scene_pincode_menu_submenu_callback, + SCENE_EVENT_DISABLE_PIN, + desktop_settings_scene_pin_menu_submenu_callback, app); } @@ -41,28 +48,28 @@ void desktop_settings_scene_pincode_menu_on_enter(void* context) { view_dispatcher_switch_to_view(app->view_dispatcher, DesktopSettingsAppViewMenu); } -bool desktop_settings_scene_pincode_menu_on_event(void* context, SceneManagerEvent event) { +bool desktop_settings_scene_pin_menu_on_event(void* context, SceneManagerEvent event) { DesktopSettingsApp* app = context; bool consumed = false; if(event.type == SceneManagerEventTypeCustom) { switch(event.event) { - case CodeEventsSetPin: - scene_manager_set_scene_state( - app->scene_manager, DesktopSettingsAppScenePinCodeInput, event.event); - scene_manager_next_scene(app->scene_manager, DesktopSettingsAppScenePinCodeInput); + case SCENE_EVENT_SET_PIN: + scene_manager_next_scene(app->scene_manager, DesktopSettingsAppScenePinSetupHowto); consumed = true; break; - case CodeEventsChangePin: + case SCENE_EVENT_CHANGE_PIN: scene_manager_set_scene_state( - app->scene_manager, DesktopSettingsAppScenePinCodeInput, event.event); - scene_manager_next_scene(app->scene_manager, DesktopSettingsAppScenePinCodeInput); + app->scene_manager, + DesktopSettingsAppScenePinAuth, + SCENE_STATE_PIN_AUTH_CHANGE_PIN); + scene_manager_next_scene(app->scene_manager, DesktopSettingsAppScenePinAuth); consumed = true; break; - case CodeEventsDisablePin: + case SCENE_EVENT_DISABLE_PIN: scene_manager_set_scene_state( - app->scene_manager, DesktopSettingsAppScenePinCodeInput, event.event); - scene_manager_next_scene(app->scene_manager, DesktopSettingsAppScenePinCodeInput); + app->scene_manager, DesktopSettingsAppScenePinAuth, SCENE_STATE_PIN_AUTH_DISABLE); + scene_manager_next_scene(app->scene_manager, DesktopSettingsAppScenePinAuth); consumed = true; break; default: @@ -73,7 +80,7 @@ bool desktop_settings_scene_pincode_menu_on_event(void* context, SceneManagerEve return consumed; } -void desktop_settings_scene_pincode_menu_on_exit(void* context) { +void desktop_settings_scene_pin_menu_on_exit(void* context) { DesktopSettingsApp* app = context; submenu_reset(app->submenu); } diff --git a/applications/desktop/desktop_settings/scenes/desktop_settings_scene_pin_setup.c b/applications/desktop/desktop_settings/scenes/desktop_settings_scene_pin_setup.c new file mode 100644 index 00000000..5659684f --- /dev/null +++ b/applications/desktop/desktop_settings/scenes/desktop_settings_scene_pin_setup.c @@ -0,0 +1,107 @@ +#include +#include +#include + +#include "../desktop_settings_app.h" +#include "desktop/desktop_settings/desktop_settings.h" +#include "desktop/views/desktop_view_pin_input.h" +#include "desktop_settings_scene.h" +#include "desktop_settings_scene_i.h" + +#define SCENE_EVENT_EXIT (0U) +#define SCENE_EVENT_1ST_PIN_ENTERED (1U) +#define SCENE_EVENT_PINS_EQUAL (2U) +#define SCENE_EVENT_PINS_DIFFERENT (3U) + +static void pin_setup_done_callback(const PinCode* pin_code, void* context) { + furi_assert(pin_code); + furi_assert(context); + DesktopSettingsApp* app = context; + + if(!app->pincode_buffer_filled) { + app->pincode_buffer = *pin_code; + app->pincode_buffer_filled = true; + view_dispatcher_send_custom_event(app->view_dispatcher, SCENE_EVENT_1ST_PIN_ENTERED); + } else { + app->pincode_buffer_filled = false; + if(pins_are_equal(&app->pincode_buffer, pin_code)) { + view_dispatcher_send_custom_event(app->view_dispatcher, SCENE_EVENT_PINS_EQUAL); + } else { + view_dispatcher_send_custom_event(app->view_dispatcher, SCENE_EVENT_PINS_DIFFERENT); + } + } +} + +static void pin_setup_back_callback(void* context) { + DesktopSettingsApp* app = context; + view_dispatcher_send_custom_event(app->view_dispatcher, SCENE_EVENT_EXIT); +} + +void desktop_settings_scene_pin_setup_on_enter(void* context) { + DesktopSettingsApp* app = context; + + app->pincode_buffer_filled = false; + desktop_view_pin_input_set_context(app->pin_input_view, app); + desktop_view_pin_input_set_back_callback(app->pin_input_view, pin_setup_back_callback); + desktop_view_pin_input_set_done_callback(app->pin_input_view, pin_setup_done_callback); + desktop_view_pin_input_set_label_button(app->pin_input_view, "OK"); + desktop_view_pin_input_set_label_primary(app->pin_input_view, 0, 0, NULL); + desktop_view_pin_input_set_label_secondary( + app->pin_input_view, 0, 8, "Enter from 4 to 10 arrows:"); + desktop_view_pin_input_reset_pin(app->pin_input_view); + desktop_view_pin_input_unlock_input(app->pin_input_view); + view_dispatcher_switch_to_view(app->view_dispatcher, DesktopSettingsAppViewIdPinInput); +} + +bool desktop_settings_scene_pin_setup_on_event(void* context, SceneManagerEvent event) { + DesktopSettingsApp* app = context; + bool consumed = false; + + if(event.type == SceneManagerEventTypeCustom) { + switch(event.event) { + case SCENE_EVENT_1ST_PIN_ENTERED: + desktop_view_pin_input_set_label_button(app->pin_input_view, "OK"); + desktop_view_pin_input_set_label_primary(app->pin_input_view, 0, 0, NULL); + desktop_view_pin_input_set_label_secondary( + app->pin_input_view, 0, 8, "Confirm your PIN:"); + desktop_view_pin_input_reset_pin(app->pin_input_view); + desktop_view_pin_input_unlock_input(app->pin_input_view); + consumed = true; + break; + case SCENE_EVENT_PINS_DIFFERENT: + scene_manager_set_scene_state( + app->scene_manager, + DesktopSettingsAppScenePinError, + SCENE_STATE_PIN_ERROR_MISMATCH); + scene_manager_next_scene(app->scene_manager, DesktopSettingsAppScenePinError); + consumed = true; + break; + case SCENE_EVENT_PINS_EQUAL: + scene_manager_next_scene(app->scene_manager, DesktopSettingsAppScenePinSetupHowto2); + consumed = true; + break; + case SCENE_EVENT_EXIT: { + uint32_t scene_found; + scene_found = scene_manager_search_and_switch_to_previous_scene( + app->scene_manager, DesktopSettingsAppScenePinMenu); + if(!scene_found) { + view_dispatcher_stop(app->view_dispatcher); + } + consumed = true; + break; + } + + default: + consumed = true; + break; + } + } + return consumed; +} + +void desktop_settings_scene_pin_setup_on_exit(void* context) { + furi_assert(context); + DesktopSettingsApp* app = context; + desktop_view_pin_input_set_back_callback(app->pin_input_view, NULL); + desktop_view_pin_input_set_done_callback(app->pin_input_view, NULL); +} diff --git a/applications/desktop/desktop_settings/scenes/desktop_settings_scene_pin_setup_done.c b/applications/desktop/desktop_settings/scenes/desktop_settings_scene_pin_setup_done.c new file mode 100644 index 00000000..7be0e51c --- /dev/null +++ b/applications/desktop/desktop_settings/scenes/desktop_settings_scene_pin_setup_done.c @@ -0,0 +1,77 @@ +#include +#include +#include +#include +#include +#include + +#include "../desktop_settings_app.h" +#include "desktop/desktop_settings/desktop_settings.h" +#include "desktop/views/desktop_view_pin_input.h" +#include "desktop_settings_scene.h" + +#define SCENE_EVENT_DONE (0U) + +static void pin_setup_done_callback(const PinCode* pin_code, void* context) { + furi_assert(pin_code); + furi_assert(context); + DesktopSettingsApp* app = context; + + view_dispatcher_send_custom_event(app->view_dispatcher, SCENE_EVENT_DONE); +} + +void desktop_settings_scene_pin_setup_done_on_enter(void* context) { + DesktopSettingsApp* app = context; + + app->settings.pin_code = app->pincode_buffer; + SAVE_DESKTOP_SETTINGS(&app->settings); + NotificationApp* notification = furi_record_open("notification"); + notification_message(notification, &sequence_single_vibro); + furi_record_close("notification"); + + desktop_view_pin_input_set_context(app->pin_input_view, app); + desktop_view_pin_input_set_back_callback(app->pin_input_view, NULL); + desktop_view_pin_input_set_done_callback(app->pin_input_view, pin_setup_done_callback); + desktop_view_pin_input_set_pin(app->pin_input_view, &app->settings.pin_code); + desktop_view_pin_input_set_label_button(app->pin_input_view, "Done"); + desktop_view_pin_input_set_label_primary(app->pin_input_view, 29, 8, "PIN activated!"); + desktop_view_pin_input_set_label_secondary( + app->pin_input_view, 7, 45, "Remember or write it down"); + desktop_view_pin_input_lock_input(app->pin_input_view); + desktop_view_pin_input_set_pin_position(app->pin_input_view, 64, 24); + view_dispatcher_switch_to_view(app->view_dispatcher, DesktopSettingsAppViewIdPinInput); +} + +bool desktop_settings_scene_pin_setup_done_on_event(void* context, SceneManagerEvent event) { + DesktopSettingsApp* app = context; + bool consumed = false; + + if(event.type == SceneManagerEventTypeCustom) { + switch(event.event) { + case SCENE_EVENT_DONE: { + bool scene_found = false; + scene_found = scene_manager_search_and_switch_to_previous_scene( + app->scene_manager, DesktopSettingsAppScenePinMenu); + if(!scene_found) { + view_dispatcher_stop(app->view_dispatcher); + } + consumed = true; + break; + } + default: + consumed = true; + break; + } + } else if(event.type == SceneManagerEventTypeBack) { + consumed = true; + } + return consumed; +} + +void desktop_settings_scene_pin_setup_done_on_exit(void* context) { + furi_assert(context); + DesktopSettingsApp* app = context; + desktop_view_pin_input_set_pin_position(app->pin_input_view, 64, 32); + desktop_view_pin_input_set_back_callback(app->pin_input_view, NULL); + desktop_view_pin_input_set_done_callback(app->pin_input_view, NULL); +} diff --git a/applications/desktop/desktop_settings/scenes/desktop_settings_scene_pin_setup_howto.c b/applications/desktop/desktop_settings/scenes/desktop_settings_scene_pin_setup_howto.c new file mode 100644 index 00000000..22727a7a --- /dev/null +++ b/applications/desktop/desktop_settings/scenes/desktop_settings_scene_pin_setup_howto.c @@ -0,0 +1,44 @@ +#include +#include +#include + +#include "desktop_settings_scene.h" +#include "../desktop_settings_app.h" +#include "../views/desktop_settings_view_pin_setup_howto.h" + +#define SCENE_EXIT_EVENT (0U) + +static void desktop_settings_scene_pin_lock_done_callback(void* context) { + DesktopSettingsApp* app = context; + view_dispatcher_send_custom_event(app->view_dispatcher, SCENE_EXIT_EVENT); +} + +void desktop_settings_scene_pin_setup_howto_on_enter(void* context) { + DesktopSettingsApp* app = context; + + desktop_settings_view_pin_setup_howto_set_callback( + app->pin_setup_howto_view, desktop_settings_scene_pin_lock_done_callback, app); + view_dispatcher_switch_to_view(app->view_dispatcher, DesktopSettingsAppViewIdPinSetupHowto); +} + +bool desktop_settings_scene_pin_setup_howto_on_event(void* context, SceneManagerEvent event) { + DesktopSettingsApp* app = context; + bool consumed = false; + + if(event.type == SceneManagerEventTypeCustom) { + switch(event.event) { + case SCENE_EXIT_EVENT: + scene_manager_next_scene(app->scene_manager, DesktopSettingsAppScenePinSetup); + consumed = true; + break; + default: + furi_assert(0); + consumed = true; + break; + } + } + return consumed; +} + +void desktop_settings_scene_pin_setup_howto_on_exit(void* context) { +} diff --git a/applications/desktop/desktop_settings/scenes/desktop_settings_scene_pin_setup_howto2.c b/applications/desktop/desktop_settings/scenes/desktop_settings_scene_pin_setup_howto2.c new file mode 100644 index 00000000..477d1f27 --- /dev/null +++ b/applications/desktop/desktop_settings/scenes/desktop_settings_scene_pin_setup_howto2.c @@ -0,0 +1,67 @@ +#include +#include +#include + +#include "desktop_settings_scene.h" +#include "../desktop_settings_app.h" +#include "../views/desktop_settings_view_pin_setup_howto2.h" + +#define SCENE_EXIT_EVENT (0U) +#define SCENE_DONE_EVENT (1U) + +static void desktop_settings_scene_pin_setup_howto2_done_callback(void* context) { + DesktopSettingsApp* app = context; + view_dispatcher_send_custom_event(app->view_dispatcher, SCENE_DONE_EVENT); +} + +static void desktop_settings_scene_pin_setup_howto2_exit_callback(void* context) { + DesktopSettingsApp* app = context; + view_dispatcher_send_custom_event(app->view_dispatcher, SCENE_EXIT_EVENT); +} + +void desktop_settings_scene_pin_setup_howto2_on_enter(void* context) { + DesktopSettingsApp* app = context; + + desktop_settings_view_pin_setup_howto2_set_context(app->pin_setup_howto2_view, app); + desktop_settings_view_pin_setup_howto2_set_ok_callback( + app->pin_setup_howto2_view, desktop_settings_scene_pin_setup_howto2_done_callback); + desktop_settings_view_pin_setup_howto2_set_cancel_callback( + app->pin_setup_howto2_view, desktop_settings_scene_pin_setup_howto2_exit_callback); + view_dispatcher_switch_to_view(app->view_dispatcher, DesktopSettingsAppViewIdPinSetupHowto2); +} + +bool desktop_settings_scene_pin_setup_howto2_on_event(void* context, SceneManagerEvent event) { + DesktopSettingsApp* app = context; + bool consumed = false; + + if(event.type == SceneManagerEventTypeCustom) { + switch(event.event) { + case SCENE_DONE_EVENT: { + scene_manager_next_scene(app->scene_manager, DesktopSettingsAppScenePinSetupDone); + consumed = true; + break; + } + case SCENE_EXIT_EVENT: { + bool scene_found = false; + scene_found = scene_manager_search_and_switch_to_previous_scene( + app->scene_manager, DesktopSettingsAppScenePinMenu); + if(!scene_found) { + view_dispatcher_stop(app->view_dispatcher); + } + consumed = true; + break; + } + default: + furi_assert(0); + consumed = true; + break; + } + } + return consumed; +} + +void desktop_settings_scene_pin_setup_howto2_on_exit(void* context) { + DesktopSettingsApp* app = context; + desktop_settings_view_pin_setup_howto2_set_ok_callback(app->pin_setup_howto2_view, NULL); + desktop_settings_view_pin_setup_howto2_set_cancel_callback(app->pin_setup_howto2_view, NULL); +} 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 deleted file mode 100644 index a24551c4..00000000 --- a/applications/desktop/desktop_settings/scenes/desktop_settings_scene_pincode_input.c +++ /dev/null @@ -1,64 +0,0 @@ -#include "../desktop_settings_app.h" -#include "desktop_settings_scene.h" - -#define SCENE_EXIT_EVENT (0U) - -void desktop_settings_scene_ok_callback(void* context) { - DesktopSettingsApp* app = context; - uint32_t state = - scene_manager_get_scene_state(app->scene_manager, DesktopSettingsAppScenePinCodeInput); - - if(state == CodeEventsDisablePin) { - memset(app->settings.pincode.data, 0, app->settings.pincode.length * sizeof(uint8_t)); - app->settings.pincode.length = 0; - } - - view_dispatcher_send_custom_event(app->view_dispatcher, SCENE_EXIT_EVENT); -} - -void desktop_settings_scene_pincode_input_on_enter(void* context) { - DesktopSettingsApp* app = context; - CodeInput* code_input = app->code_input; - - uint32_t state = - scene_manager_get_scene_state(app->scene_manager, DesktopSettingsAppScenePinCodeInput); - bool update = state != CodeEventsDisablePin; - - code_input_set_header_text(code_input, "PIN Code Setup"); - code_input_set_result_callback( - code_input, - desktop_settings_scene_ok_callback, - NULL, - app, - app->settings.pincode.data, - &app->settings.pincode.length, - update); - - view_dispatcher_switch_to_view(app->view_dispatcher, DesktopSettingsAppViewPincodeInput); -} - -bool desktop_settings_scene_pincode_input_on_event(void* context, SceneManagerEvent event) { - DesktopSettingsApp* app = context; - bool consumed = false; - - if(event.type == SceneManagerEventTypeCustom) { - switch(event.event) { - case SCENE_EXIT_EVENT: - scene_manager_previous_scene(app->scene_manager); - consumed = true; - break; - - default: - consumed = true; - break; - } - } - return consumed; -} - -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/desktop_settings/scenes/desktop_settings_scene_start.c b/applications/desktop/desktop_settings/scenes/desktop_settings_scene_start.c index 4ea7e0cc..8f856b6a 100644 --- a/applications/desktop/desktop_settings/scenes/desktop_settings_scene_start.c +++ b/applications/desktop/desktop_settings/scenes/desktop_settings_scene_start.c @@ -1,11 +1,10 @@ +#include + #include "../desktop_settings_app.h" -#include "applications.h" #include "desktop_settings_scene.h" -enum DesktopSettingsStartSubmenuIndex { - DesktopSettingsStartSubmenuIndexFavorite, - DesktopSettingsStartSubmenuIndexPinSetup, -}; +#define SCENE_EVENT_SELECT_FAVORITE 0 +#define SCENE_EVENT_SELECT_PIN_SETUP 1 static void desktop_settings_scene_start_submenu_callback(void* context, uint32_t index) { DesktopSettingsApp* app = context; @@ -19,14 +18,14 @@ void desktop_settings_scene_start_on_enter(void* context) { submenu_add_item( submenu, "Favorite App", - DesktopSettingsStartSubmenuIndexFavorite, + SCENE_EVENT_SELECT_FAVORITE, desktop_settings_scene_start_submenu_callback, app); submenu_add_item( submenu, "PIN Setup", - DesktopSettingsStartSubmenuIndexPinSetup, + SCENE_EVENT_SELECT_PIN_SETUP, desktop_settings_scene_start_submenu_callback, app); @@ -39,12 +38,12 @@ bool desktop_settings_scene_start_on_event(void* context, SceneManagerEvent even if(event.type == SceneManagerEventTypeCustom) { switch(event.event) { - case DesktopSettingsStartSubmenuIndexFavorite: + case SCENE_EVENT_SELECT_FAVORITE: scene_manager_next_scene(app->scene_manager, DesktopSettingsAppSceneFavorite); consumed = true; break; - case DesktopSettingsStartSubmenuIndexPinSetup: - scene_manager_next_scene(app->scene_manager, DesktopSettingsAppScenePinCodeMenu); + case SCENE_EVENT_SELECT_PIN_SETUP: + scene_manager_next_scene(app->scene_manager, DesktopSettingsAppScenePinMenu); consumed = true; break; } diff --git a/applications/desktop/desktop_settings/views/desktop_settings_view_pin_setup_howto.c b/applications/desktop/desktop_settings/views/desktop_settings_view_pin_setup_howto.c new file mode 100644 index 00000000..c87de756 --- /dev/null +++ b/applications/desktop/desktop_settings/views/desktop_settings_view_pin_setup_howto.c @@ -0,0 +1,78 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "desktop_settings_view_pin_setup_howto.h" + +struct DesktopSettingsViewPinSetupHowto { + View* view; + DesktopSettingsViewPinSetupHowtoDoneCallback callback; + void* context; +}; + +static void desktop_settings_view_pin_setup_howto_draw(Canvas* canvas, void* model) { + furi_assert(canvas); + furi_assert(model); + + canvas_draw_icon(canvas, 16, 18, &I_Pin_attention_dpad_29x29); + elements_button_right(canvas, "Next"); + + canvas_set_font(canvas, FontPrimary); + elements_multiline_text_aligned(canvas, 64, 0, AlignCenter, AlignTop, "Setting up PIN"); + + canvas_set_font(canvas, FontSecondary); + elements_multiline_text(canvas, 58, 24, "Prepare to use\narrows as\nPIN symbols"); +} + +static bool desktop_settings_view_pin_setup_howto_input(InputEvent* event, void* context) { + furi_assert(event); + furi_assert(context); + + DesktopSettingsViewPinSetupHowto* instance = context; + bool consumed = false; + + if((event->key == InputKeyRight) && (event->type == InputTypeShort)) { + instance->callback(instance->context); + consumed = true; + } + + return consumed; +} + +void desktop_settings_view_pin_setup_howto_set_callback( + DesktopSettingsViewPinSetupHowto* instance, + DesktopSettingsViewPinSetupHowtoDoneCallback callback, + void* context) { + furi_assert(instance); + furi_assert(callback); + instance->callback = callback; + instance->context = context; +} + +DesktopSettingsViewPinSetupHowto* desktop_settings_view_pin_setup_howto_alloc() { + DesktopSettingsViewPinSetupHowto* view = furi_alloc(sizeof(DesktopSettingsViewPinSetupHowto)); + view->view = view_alloc(); + view_allocate_model(view->view, ViewModelTypeLockFree, 1); + view_set_context(view->view, view); + view_set_draw_callback(view->view, desktop_settings_view_pin_setup_howto_draw); + view_set_input_callback(view->view, desktop_settings_view_pin_setup_howto_input); + + return view; +} + +void desktop_settings_view_pin_setup_howto_free(DesktopSettingsViewPinSetupHowto* instance) { + furi_assert(instance); + + view_free(instance->view); + free(instance); +} + +View* desktop_settings_view_pin_setup_howto_get_view(DesktopSettingsViewPinSetupHowto* instance) { + furi_assert(instance); + return instance->view; +} diff --git a/applications/desktop/desktop_settings/views/desktop_settings_view_pin_setup_howto.h b/applications/desktop/desktop_settings/views/desktop_settings_view_pin_setup_howto.h new file mode 100644 index 00000000..0f62cb43 --- /dev/null +++ b/applications/desktop/desktop_settings/views/desktop_settings_view_pin_setup_howto.h @@ -0,0 +1,15 @@ +#pragma once + +#include + +typedef struct DesktopSettingsViewPinSetupHowto DesktopSettingsViewPinSetupHowto; + +typedef void (*DesktopSettingsViewPinSetupHowtoDoneCallback)(void*); + +void desktop_settings_view_pin_setup_howto_set_callback( + DesktopSettingsViewPinSetupHowto* instance, + DesktopSettingsViewPinSetupHowtoDoneCallback callback, + void* context); +DesktopSettingsViewPinSetupHowto* desktop_settings_view_pin_setup_howto_alloc(); +void desktop_settings_view_pin_setup_howto_free(DesktopSettingsViewPinSetupHowto* instance); +View* desktop_settings_view_pin_setup_howto_get_view(DesktopSettingsViewPinSetupHowto* instance); diff --git a/applications/desktop/desktop_settings/views/desktop_settings_view_pin_setup_howto2.c b/applications/desktop/desktop_settings/views/desktop_settings_view_pin_setup_howto2.c new file mode 100644 index 00000000..3ef22b46 --- /dev/null +++ b/applications/desktop/desktop_settings/views/desktop_settings_view_pin_setup_howto2.c @@ -0,0 +1,101 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "desktop_settings_view_pin_setup_howto2.h" + +struct DesktopSettingsViewPinSetupHowto2 { + View* view; + DesktopSettingsViewPinSetupHowto2Callback cancel_callback; + DesktopSettingsViewPinSetupHowto2Callback ok_callback; + void* context; +}; + +static void desktop_settings_view_pin_setup_howto2_draw(Canvas* canvas, void* model) { + furi_assert(canvas); + furi_assert(model); + + canvas_set_font(canvas, FontSecondary); + elements_multiline_text_aligned( + canvas, + 64, + 24, + AlignCenter, + AlignCenter, + "Forgotten PIN can only be\n" + "reset with entire device.\n" + "Read docs How to reset PIN."); + + elements_button_right(canvas, "OK"); + elements_button_left(canvas, "Cancel"); +} + +static bool desktop_settings_view_pin_setup_howto2_input(InputEvent* event, void* context) { + furi_assert(event); + furi_assert(context); + + DesktopSettingsViewPinSetupHowto2* instance = context; + bool consumed = false; + + if(event->type == InputTypeShort) { + if(event->key == InputKeyRight) { + instance->ok_callback(instance->context); + consumed = true; + } else if(event->key == InputKeyLeft) { + instance->cancel_callback(instance->context); + consumed = true; + } + } + + return consumed; +} + +void desktop_settings_view_pin_setup_howto2_set_context( + DesktopSettingsViewPinSetupHowto2* instance, + void* context) { + furi_assert(instance); + instance->context = context; +} + +void desktop_settings_view_pin_setup_howto2_set_cancel_callback( + DesktopSettingsViewPinSetupHowto2* instance, + DesktopSettingsViewPinSetupHowto2Callback callback) { + furi_assert(instance); + instance->cancel_callback = callback; +} + +void desktop_settings_view_pin_setup_howto2_set_ok_callback( + DesktopSettingsViewPinSetupHowto2* instance, + DesktopSettingsViewPinSetupHowto2Callback callback) { + furi_assert(instance); + instance->ok_callback = callback; +} + +DesktopSettingsViewPinSetupHowto2* desktop_settings_view_pin_setup_howto2_alloc() { + DesktopSettingsViewPinSetupHowto2* view = + furi_alloc(sizeof(DesktopSettingsViewPinSetupHowto2)); + view->view = view_alloc(); + view_allocate_model(view->view, ViewModelTypeLockFree, 1); + view_set_context(view->view, view); + view_set_draw_callback(view->view, desktop_settings_view_pin_setup_howto2_draw); + view_set_input_callback(view->view, desktop_settings_view_pin_setup_howto2_input); + + return view; +} + +void desktop_settings_view_pin_setup_howto2_free(DesktopSettingsViewPinSetupHowto2* instance) { + furi_assert(instance); + + view_free(instance->view); + free(instance); +} + +View* desktop_settings_view_pin_setup_howto2_get_view(DesktopSettingsViewPinSetupHowto2* instance) { + furi_assert(instance); + return instance->view; +} diff --git a/applications/desktop/desktop_settings/views/desktop_settings_view_pin_setup_howto2.h b/applications/desktop/desktop_settings/views/desktop_settings_view_pin_setup_howto2.h new file mode 100644 index 00000000..8e3018d9 --- /dev/null +++ b/applications/desktop/desktop_settings/views/desktop_settings_view_pin_setup_howto2.h @@ -0,0 +1,20 @@ +#pragma once + +#include + +typedef struct DesktopSettingsViewPinSetupHowto2 DesktopSettingsViewPinSetupHowto2; + +typedef void (*DesktopSettingsViewPinSetupHowto2Callback)(void*); + +DesktopSettingsViewPinSetupHowto2* desktop_settings_view_pin_setup_howto2_alloc(); +void desktop_settings_view_pin_setup_howto2_free(DesktopSettingsViewPinSetupHowto2* instance); +View* desktop_settings_view_pin_setup_howto2_get_view(DesktopSettingsViewPinSetupHowto2* instance); +void desktop_settings_view_pin_setup_howto2_set_context( + DesktopSettingsViewPinSetupHowto2* instance, + void* context); +void desktop_settings_view_pin_setup_howto2_set_cancel_callback( + DesktopSettingsViewPinSetupHowto2* instance, + DesktopSettingsViewPinSetupHowto2Callback callback); +void desktop_settings_view_pin_setup_howto2_set_ok_callback( + DesktopSettingsViewPinSetupHowto2* instance, + DesktopSettingsViewPinSetupHowto2Callback callback); diff --git a/applications/desktop/scenes/desktop_scene_config.h b/applications/desktop/scenes/desktop_scene_config.h index b4e39dd3..c84d6ff8 100644 --- a/applications/desktop/scenes/desktop_scene_config.h +++ b/applications/desktop/scenes/desktop_scene_config.h @@ -3,5 +3,7 @@ ADD_SCENE(desktop, lock_menu, LockMenu) ADD_SCENE(desktop, debug, Debug) ADD_SCENE(desktop, first_start, FirstStart) ADD_SCENE(desktop, hw_mismatch, HwMismatch) -ADD_SCENE(desktop, pinsetup, PinSetup) ADD_SCENE(desktop, fault, Fault) +ADD_SCENE(desktop, locked, Locked) +ADD_SCENE(desktop, pin_input, PinInput) +ADD_SCENE(desktop, pin_timeout, PinTimeout) diff --git a/applications/desktop/scenes/desktop_scene_debug.c b/applications/desktop/scenes/desktop_scene_debug.c index bf8607f8..99fcad87 100644 --- a/applications/desktop/scenes/desktop_scene_debug.c +++ b/applications/desktop/scenes/desktop_scene_debug.c @@ -3,7 +3,7 @@ #include #include "../desktop_i.h" -#include "../views/desktop_debug.h" +#include "../views/desktop_view_debug.h" #include "desktop_scene.h" void desktop_scene_debug_callback(DesktopEvent event, void* context) { @@ -17,7 +17,7 @@ void desktop_scene_debug_on_enter(void* context) { desktop_debug_get_dolphin_data(desktop->debug_view); desktop_debug_set_callback(desktop->debug_view, desktop_scene_debug_callback, desktop); - view_dispatcher_switch_to_view(desktop->view_dispatcher, DesktopViewDebug); + view_dispatcher_switch_to_view(desktop->view_dispatcher, DesktopViewIdDebug); } bool desktop_scene_debug_on_event(void* context, SceneManagerEvent event) { diff --git a/applications/desktop/scenes/desktop_scene_fault.c b/applications/desktop/scenes/desktop_scene_fault.c index a2555e64..b75b32aa 100644 --- a/applications/desktop/scenes/desktop_scene_fault.c +++ b/applications/desktop/scenes/desktop_scene_fault.c @@ -25,7 +25,7 @@ void desktop_scene_fault_on_enter(void* context) { char* message = (char*)furi_hal_rtc_get_fault_data(); popup_set_text(popup, message, 60, 37 + STATUS_BAR_Y_SHIFT, AlignCenter, AlignCenter); popup_set_callback(popup, desktop_scene_fault_callback); - view_dispatcher_switch_to_view(desktop->view_dispatcher, DesktopViewHwMismatch); + view_dispatcher_switch_to_view(desktop->view_dispatcher, DesktopViewIdHwMismatch); } bool desktop_scene_fault_on_event(void* context, SceneManagerEvent event) { diff --git a/applications/desktop/scenes/desktop_scene_first_start.c b/applications/desktop/scenes/desktop_scene_first_start.c index 8dfc96dc..9563094c 100644 --- a/applications/desktop/scenes/desktop_scene_first_start.c +++ b/applications/desktop/scenes/desktop_scene_first_start.c @@ -2,7 +2,7 @@ #include #include "../desktop_i.h" -#include "../views/desktop_first_start.h" +#include "../views/desktop_view_first_start.h" #include "../views/desktop_events.h" void desktop_scene_first_start_callback(DesktopEvent event, void* context) { @@ -17,7 +17,7 @@ void desktop_scene_first_start_on_enter(void* context) { desktop_first_start_set_callback( first_start_view, desktop_scene_first_start_callback, desktop); - view_dispatcher_switch_to_view(desktop->view_dispatcher, DesktopViewFirstStart); + view_dispatcher_switch_to_view(desktop->view_dispatcher, DesktopViewIdFirstStart); } bool desktop_scene_first_start_on_event(void* context, SceneManagerEvent event) { diff --git a/applications/desktop/scenes/desktop_scene_hw_mismatch.c b/applications/desktop/scenes/desktop_scene_hw_mismatch.c index 7ca090b9..05a6fd68 100644 --- a/applications/desktop/scenes/desktop_scene_hw_mismatch.c +++ b/applications/desktop/scenes/desktop_scene_hw_mismatch.c @@ -1,5 +1,5 @@ #include -#include +#include #include "desktop_scene.h" #include "../desktop_i.h" @@ -31,7 +31,7 @@ void desktop_scene_hw_mismatch_on_enter(void* context) { popup, "!!!! HW Mismatch !!!!", 60, 14 + STATUS_BAR_Y_SHIFT, AlignCenter, AlignCenter); popup_set_text(popup, text_buffer, 60, 37 + STATUS_BAR_Y_SHIFT, AlignCenter, AlignCenter); popup_set_callback(popup, desktop_scene_hw_mismatch_callback); - view_dispatcher_switch_to_view(desktop->view_dispatcher, DesktopViewHwMismatch); + view_dispatcher_switch_to_view(desktop->view_dispatcher, DesktopViewIdHwMismatch); } bool desktop_scene_hw_mismatch_on_event(void* context, SceneManagerEvent event) { diff --git a/applications/desktop/scenes/desktop_scene_i.h b/applications/desktop/scenes/desktop_scene_i.h index f459eb4a..953f8c83 100644 --- a/applications/desktop/scenes/desktop_scene_i.h +++ b/applications/desktop/scenes/desktop_scene_i.h @@ -1,7 +1,4 @@ #pragma once -typedef enum { - DesktopMainSceneStateUnlocked, - DesktopMainSceneStateLockedWithPin, - DesktopMainSceneStateLockedNoPin, -} DesktopMainSceneState; +#define SCENE_LOCKED_FIRST_ENTER 0 +#define SCENE_LOCKED_REPEAT_ENTER 1 diff --git a/applications/desktop/scenes/desktop_scene_lock_menu.c b/applications/desktop/scenes/desktop_scene_lock_menu.c index 7a3d51bb..c329af59 100644 --- a/applications/desktop/scenes/desktop_scene_lock_menu.c +++ b/applications/desktop/scenes/desktop_scene_lock_menu.c @@ -1,8 +1,13 @@ +#include +#include +#include #include #include +#include #include "../desktop_i.h" -#include "../views/desktop_lock_menu.h" +#include "../desktop_settings/desktop_settings.h" +#include "../views/desktop_view_lock_menu.h" #include "desktop_scene_i.h" #include "desktop_scene.h" @@ -15,36 +20,50 @@ void desktop_scene_lock_menu_on_enter(void* context) { Desktop* desktop = (Desktop*)context; LOAD_DESKTOP_SETTINGS(&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_pin_set(desktop->lock_menu, desktop->settings.pincode.length > 0); + desktop_lock_menu_pin_set(desktop->lock_menu, desktop->settings.pin_code.length > 0); + desktop_lock_menu_set_idx(desktop->lock_menu, 0); - uint8_t idx = scene_manager_get_scene_state(desktop->scene_manager, DesktopSceneLockMenu); - desktop_lock_menu_set_idx(desktop->lock_menu, idx); - view_dispatcher_switch_to_view(desktop->view_dispatcher, DesktopViewLockMenu); + view_dispatcher_switch_to_view(desktop->view_dispatcher, DesktopViewIdLockMenu); } bool desktop_scene_lock_menu_on_event(void* context, SceneManagerEvent event) { Desktop* desktop = (Desktop*)context; bool consumed = false; - if(event.type == SceneManagerEventTypeCustom) { + if(event.type == SceneManagerEventTypeTick) { + bool check_pin_changed = + scene_manager_get_scene_state(desktop->scene_manager, DesktopSceneLockMenu); + if(check_pin_changed) { + LOAD_DESKTOP_SETTINGS(&desktop->settings); + if(desktop->settings.pin_code.length > 0) { + desktop_lock_menu_pin_set(desktop->lock_menu, 1); + scene_manager_set_scene_state(desktop->scene_manager, DesktopSceneLockMenu, 0); + } + } + } else if(event.type == SceneManagerEventTypeCustom) { switch(event.event) { case DesktopLockMenuEventLock: - scene_manager_set_scene_state( - desktop->scene_manager, DesktopSceneMain, DesktopMainSceneStateLockedNoPin); scene_manager_set_scene_state(desktop->scene_manager, DesktopSceneLockMenu, 0); - scene_manager_next_scene(desktop->scene_manager, DesktopSceneMain); + scene_manager_set_scene_state( + desktop->scene_manager, DesktopSceneLocked, SCENE_LOCKED_FIRST_ENTER); + scene_manager_next_scene(desktop->scene_manager, DesktopSceneLocked); consumed = true; break; case DesktopLockMenuEventPinLock: - if(desktop->settings.pincode.length > 0) { + if(desktop->settings.pin_code.length > 0) { + furi_hal_rtc_set_flag(FuriHalRtcFlagLock); scene_manager_set_scene_state( - desktop->scene_manager, DesktopSceneMain, DesktopMainSceneStateLockedWithPin); - scene_manager_next_scene(desktop->scene_manager, DesktopSceneMain); + desktop->scene_manager, DesktopSceneLocked, SCENE_LOCKED_FIRST_ENTER); + scene_manager_next_scene(desktop->scene_manager, DesktopSceneLocked); } else { scene_manager_set_scene_state(desktop->scene_manager, DesktopSceneLockMenu, 1); - scene_manager_next_scene(desktop->scene_manager, DesktopScenePinSetup); + Loader* loader = furi_record_open("loader"); + LoaderStatus status = + loader_start(loader, "Desktop", DESKTOP_SETTINGS_RUN_PIN_SETUP_ARG); + furi_check(status == LoaderStatusOk); + furi_record_close("loader"); } consumed = true; diff --git a/applications/desktop/scenes/desktop_scene_locked.c b/applications/desktop/scenes/desktop_scene_locked.c new file mode 100644 index 00000000..98d5fa0a --- /dev/null +++ b/applications/desktop/scenes/desktop_scene_locked.c @@ -0,0 +1,109 @@ +#include +#include +#include +#include +#include +#include + +#include "../desktop.h" +#include "../desktop_i.h" +#include "../desktop_helpers.h" +#include "../animations/animation_manager.h" +#include "../views/desktop_events.h" +#include "../views/desktop_view_pin_input.h" +#include "../views/desktop_view_locked.h" +#include "desktop_scene.h" +#include "desktop_scene_i.h" + +#define WRONG_PIN_HEADER_TIMEOUT 3000 +#define INPUT_PIN_VIEW_TIMEOUT 15000 + +static void desktop_scene_locked_callback(DesktopEvent event, void* context) { + Desktop* desktop = (Desktop*)context; + view_dispatcher_send_custom_event(desktop->view_dispatcher, event); +} + +static void desktop_scene_locked_new_idle_animation_callback(void* context) { + furi_assert(context); + Desktop* desktop = context; + view_dispatcher_send_custom_event( + desktop->view_dispatcher, DesktopAnimationEventNewIdleAnimation); +} + +void desktop_scene_locked_on_enter(void* context) { + Desktop* desktop = (Desktop*)context; + + // callbacks for 1-st layer + animation_manager_set_new_idle_callback( + desktop->animation_manager, desktop_scene_locked_new_idle_animation_callback); + animation_manager_set_check_callback(desktop->animation_manager, NULL); + animation_manager_set_interact_callback(desktop->animation_manager, NULL); + + // callbacks for 2-nd layer + desktop_view_locked_set_callback(desktop->locked_view, desktop_scene_locked_callback, desktop); + + 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 = furi_hal_rtc_is_flag_set(FuriHalRtcFlagLock); + desktop_helpers_lock_system(desktop, pin_locked); + if(pin_locked) { + LOAD_DESKTOP_SETTINGS(&desktop->settings); + desktop_view_locked_lock(desktop->locked_view, true); + uint32_t pin_fails = furi_hal_rtc_get_pin_fails(); + uint32_t pin_timeout = desktop_helpers_get_pin_fail_timeout(pin_fails); + if(pin_timeout) { + scene_manager_set_scene_state( + desktop->scene_manager, DesktopScenePinTimeout, pin_timeout); + switch_to_timeout_scene = true; + } else { + desktop_view_locked_close_doors(desktop->locked_view); + } + } else { + desktop_view_locked_lock(desktop->locked_view, false); + desktop_view_locked_close_doors(desktop->locked_view); + } + scene_manager_set_scene_state( + desktop->scene_manager, DesktopSceneLocked, SCENE_LOCKED_REPEAT_ENTER); + } + + if(switch_to_timeout_scene) { + scene_manager_next_scene(desktop->scene_manager, DesktopScenePinTimeout); + } else { + view_dispatcher_switch_to_view(desktop->view_dispatcher, DesktopViewIdLocked); + } +} + +bool desktop_scene_locked_on_event(void* context, SceneManagerEvent event) { + Desktop* desktop = (Desktop*)context; + bool consumed = false; + + if(event.type == SceneManagerEventTypeCustom) { + switch(event.event) { + case DesktopLockedEventUnlocked: + furi_hal_rtc_set_pin_fails(0); + desktop_helpers_unlock_system(desktop); + scene_manager_search_and_switch_to_previous_scene( + desktop->scene_manager, DesktopSceneMain); + consumed = true; + break; + case DesktopLockedEventUpdate: + desktop_view_locked_update(desktop->locked_view); + consumed = true; + break; + case DesktopLockedEventShowPinInput: + scene_manager_next_scene(desktop->scene_manager, DesktopScenePinInput); + consumed = true; + break; + case DesktopAnimationEventNewIdleAnimation: + animation_manager_new_idle_process(desktop->animation_manager); + consumed = true; + break; + } + } + + return consumed; +} + +void desktop_scene_locked_on_exit(void* context) { +} diff --git a/applications/desktop/scenes/desktop_scene_main.c b/applications/desktop/scenes/desktop_scene_main.c index 0db7508d..8131d0c3 100644 --- a/applications/desktop/scenes/desktop_scene_main.c +++ b/applications/desktop/scenes/desktop_scene_main.c @@ -4,15 +4,14 @@ #include #include -#include "desktop/desktop_i.h" -#include "desktop/views/desktop_main.h" +#include "../desktop_i.h" +#include "../views/desktop_events.h" +#include "../views/desktop_view_main.h" #include "desktop_scene.h" #include "desktop_scene_i.h" #define TAG "DesktopSrv" -#define MAIN_VIEW_DEFAULT (0UL) - static void desktop_scene_main_app_started_callback(const void* message, void* context) { furi_assert(context); Desktop* desktop = context; @@ -31,19 +30,22 @@ static void desktop_scene_main_app_started_callback(const void* message, void* c static void desktop_scene_main_new_idle_animation_callback(void* context) { furi_assert(context); Desktop* desktop = context; - view_dispatcher_send_custom_event(desktop->view_dispatcher, DesktopMainEventNewIdleAnimation); + view_dispatcher_send_custom_event( + desktop->view_dispatcher, DesktopAnimationEventNewIdleAnimation); } static void desktop_scene_main_check_animation_callback(void* context) { furi_assert(context); Desktop* desktop = context; - view_dispatcher_send_custom_event(desktop->view_dispatcher, DesktopMainEventCheckAnimation); + view_dispatcher_send_custom_event( + desktop->view_dispatcher, DesktopAnimationEventCheckAnimation); } static void desktop_scene_main_interact_animation_callback(void* context) { furi_assert(context); Desktop* desktop = context; - view_dispatcher_send_custom_event(desktop->view_dispatcher, DesktopMainEventInteractAnimation); + view_dispatcher_send_custom_event( + desktop->view_dispatcher, DesktopAnimationEventInteractAnimation); } static void desktop_switch_to_app(Desktop* desktop, const FlipperApplication* flipper_app) { @@ -80,7 +82,6 @@ void desktop_scene_main_on_enter(void* context) { desktop->animation_manager, desktop_scene_main_check_animation_callback); animation_manager_set_interact_callback( desktop->animation_manager, desktop_scene_main_interact_animation_callback); - desktop_locked_set_callback(desktop->locked_view, desktop_scene_main_callback, desktop); furi_assert(osSemaphoreGetCount(desktop->unload_animation_semaphore) == 0); Loader* loader = furi_record_open("loader"); @@ -90,24 +91,7 @@ void desktop_scene_main_on_enter(void* context) { desktop_main_set_callback(main_view, desktop_scene_main_callback, desktop); - DesktopMainSceneState state = - scene_manager_get_scene_state(desktop->scene_manager, DesktopSceneMain); - if(state == DesktopMainSceneStateLockedNoPin) { - desktop_locked_lock(desktop->locked_view); - view_port_enabled_set(desktop->lock_viewport, true); - } else if(state == DesktopMainSceneStateLockedWithPin) { - LOAD_DESKTOP_SETTINGS(&desktop->settings); - furi_assert(desktop->settings.pincode.length > 0); - desktop_locked_lock_pincode(desktop->locked_view, desktop->settings.pincode); - view_port_enabled_set(desktop->lock_viewport, true); - furi_hal_rtc_set_flag(FuriHalRtcFlagLock); - furi_hal_usb_disable(); - } else { - furi_assert(state == DesktopMainSceneStateUnlocked); - view_port_enabled_set(desktop->lock_viewport, false); - } - - view_dispatcher_switch_to_view(desktop->view_dispatcher, DesktopViewMain); + view_dispatcher_switch_to_view(desktop->view_dispatcher, DesktopViewIdMain); } bool desktop_scene_main_on_event(void* context, SceneManagerEvent event) { @@ -154,15 +138,15 @@ bool desktop_scene_main_on_event(void* context, SceneManagerEvent event) { consumed = true; break; - case DesktopMainEventCheckAnimation: + case DesktopAnimationEventCheckAnimation: animation_manager_check_blocking_process(desktop->animation_manager); consumed = true; break; - case DesktopMainEventNewIdleAnimation: + case DesktopAnimationEventNewIdleAnimation: animation_manager_new_idle_process(desktop->animation_manager); consumed = true; break; - case DesktopMainEventInteractAnimation: + case DesktopAnimationEventInteractAnimation: animation_manager_interact_process(desktop->animation_manager); consumed = true; break; @@ -175,16 +159,8 @@ bool desktop_scene_main_on_event(void* context, SceneManagerEvent event) { animation_manager_load_and_continue_animation(desktop->animation_manager); consumed = true; break; - case DesktopMainEventUnlocked: - consumed = true; - furi_hal_rtc_reset_flag(FuriHalRtcFlagLock); - furi_hal_usb_enable(); - view_port_enabled_set(desktop->lock_viewport, false); - scene_manager_set_scene_state( - desktop->scene_manager, DesktopSceneMain, DesktopMainSceneStateUnlocked); - break; - case DesktopMainEventUpdate: - desktop_locked_update(desktop->locked_view); + case DesktopLockedEventUpdate: + desktop_view_locked_update(desktop->locked_view); consumed = true; break; @@ -213,5 +189,4 @@ void desktop_scene_main_on_exit(void* context) { animation_manager_set_check_callback(desktop->animation_manager, NULL); animation_manager_set_interact_callback(desktop->animation_manager, NULL); animation_manager_set_context(desktop->animation_manager, desktop); - scene_manager_set_scene_state(desktop->scene_manager, DesktopSceneMain, MAIN_VIEW_DEFAULT); } diff --git a/applications/desktop/scenes/desktop_scene_pin_input.c b/applications/desktop/scenes/desktop_scene_pin_input.c new file mode 100644 index 00000000..8d714ff9 --- /dev/null +++ b/applications/desktop/scenes/desktop_scene_pin_input.c @@ -0,0 +1,162 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../desktop.h" +#include "../desktop_i.h" +#include "../animations/animation_manager.h" +#include "../views/desktop_events.h" +#include "../views/desktop_view_pin_input.h" +#include "../desktop_helpers.h" +#include "desktop_scene.h" +#include "desktop_scene_i.h" + +#define WRONG_PIN_HEADER_TIMEOUT 3000 +#define INPUT_PIN_VIEW_TIMEOUT 15000 + +typedef struct { + TimerHandle_t timer; +} DesktopScenePinInputState; + +static void desktop_scene_locked_light_red(bool value) { + NotificationApp* app = furi_record_open("notification"); + if(value) { + notification_message(app, &sequence_set_only_red_255); + } else { + notification_message(app, &sequence_reset_red); + } + furi_record_close("notification"); +} + +static void + desktop_scene_pin_input_set_timer(Desktop* desktop, bool enable, TickType_t new_period) { + furi_assert(desktop); + + DesktopScenePinInputState* state = (DesktopScenePinInputState*)scene_manager_get_scene_state( + desktop->scene_manager, DesktopScenePinInput); + furi_assert(state); + if(enable) { + xTimerChangePeriod(state->timer, new_period, portMAX_DELAY); + } else { + xTimerStop(state->timer, portMAX_DELAY); + } +} + +static void desktop_scene_pin_input_back_callback(void* context) { + Desktop* desktop = (Desktop*)context; + view_dispatcher_send_custom_event(desktop->view_dispatcher, DesktopPinInputEventBack); +} + +static void desktop_scene_pin_input_done_callback(const PinCode* pin_code, void* context) { + Desktop* desktop = (Desktop*)context; + if(pins_are_equal(&desktop->settings.pin_code, pin_code)) { + view_dispatcher_send_custom_event(desktop->view_dispatcher, DesktopPinInputEventUnlocked); + } else { + view_dispatcher_send_custom_event( + desktop->view_dispatcher, DesktopPinInputEventUnlockFailed); + } +} + +static void desktop_scene_pin_input_timer_callback(TimerHandle_t timer) { + Desktop* desktop = pvTimerGetTimerID(timer); + + view_dispatcher_send_custom_event( + desktop->view_dispatcher, DesktopPinInputEventResetWrongPinLabel); +} + +void desktop_scene_pin_input_on_enter(void* context) { + Desktop* desktop = (Desktop*)context; + + desktop_view_pin_input_set_context(desktop->pin_input_view, desktop); + desktop_view_pin_input_set_back_callback( + desktop->pin_input_view, desktop_scene_pin_input_back_callback); + desktop_view_pin_input_set_timeout_callback( + desktop->pin_input_view, desktop_scene_pin_input_back_callback); + desktop_view_pin_input_set_done_callback( + desktop->pin_input_view, desktop_scene_pin_input_done_callback); + + DesktopScenePinInputState* state = furi_alloc(sizeof(DesktopScenePinInputState)); + state->timer = + xTimerCreate(NULL, 10000, pdFALSE, desktop, desktop_scene_pin_input_timer_callback); + scene_manager_set_scene_state(desktop->scene_manager, DesktopScenePinInput, (uint32_t)state); + + desktop_view_pin_input_hide_pin(desktop->pin_input_view, true); + desktop_view_pin_input_set_label_button(desktop->pin_input_view, "OK"); + desktop_view_pin_input_set_label_secondary(desktop->pin_input_view, 44, 25, "Enter PIN:"); + desktop_view_pin_input_set_pin_position(desktop->pin_input_view, 64, 37); + desktop_view_pin_input_reset_pin(desktop->pin_input_view); + + view_dispatcher_switch_to_view(desktop->view_dispatcher, DesktopViewIdPinInput); +} + +bool desktop_scene_pin_input_on_event(void* context, SceneManagerEvent event) { + Desktop* desktop = (Desktop*)context; + bool consumed = false; + uint32_t pin_fails = 0; + + if(event.type == SceneManagerEventTypeCustom) { + switch(event.event) { + case DesktopPinInputEventUnlockFailed: + pin_fails = furi_hal_rtc_get_pin_fails(); + pin_fails++; + furi_hal_rtc_set_pin_fails(pin_fails); + uint32_t pin_timeout = desktop_helpers_get_pin_fail_timeout(pin_fails); + if(pin_timeout > 0) { + desktop_helpers_emit_error_notification(); + scene_manager_set_scene_state( + desktop->scene_manager, DesktopScenePinTimeout, pin_timeout); + scene_manager_next_scene(desktop->scene_manager, DesktopScenePinTimeout); + } else { + desktop_scene_locked_light_red(true); + desktop_view_pin_input_set_label_primary(desktop->pin_input_view, 0, 0, NULL); + desktop_view_pin_input_set_label_secondary( + desktop->pin_input_view, 25, 25, "Wrong PIN try again:"); + desktop_scene_pin_input_set_timer(desktop, true, WRONG_PIN_HEADER_TIMEOUT); + desktop_view_pin_input_reset_pin(desktop->pin_input_view); + } + consumed = true; + break; + case DesktopPinInputEventResetWrongPinLabel: + desktop_scene_locked_light_red(false); + desktop_view_pin_input_set_label_primary(desktop->pin_input_view, 0, 0, NULL); + desktop_view_pin_input_set_label_secondary( + desktop->pin_input_view, 44, 25, "Enter PIN:"); + consumed = true; + break; + case DesktopPinInputEventUnlocked: + desktop_view_locked_unlock(desktop->locked_view); + furi_hal_rtc_set_pin_fails(0); + desktop_helpers_unlock_system(desktop); + scene_manager_search_and_switch_to_previous_scene( + desktop->scene_manager, DesktopSceneMain); + consumed = true; + break; + case DesktopPinInputEventBack: + scene_manager_search_and_switch_to_previous_scene( + desktop->scene_manager, DesktopSceneLocked); + consumed = true; + break; + } + } + + return consumed; +} + +void desktop_scene_pin_input_on_exit(void* context) { + Desktop* desktop = (Desktop*)context; + desktop_scene_locked_light_red(false); + + DesktopScenePinInputState* state = (DesktopScenePinInputState*)scene_manager_get_scene_state( + desktop->scene_manager, DesktopScenePinInput); + xTimerStop(state->timer, portMAX_DELAY); + while(xTimerIsTimerActive(state->timer)) { + delay(1); + } + xTimerDelete(state->timer, portMAX_DELAY); + free(state); +} diff --git a/applications/desktop/scenes/desktop_scene_pin_timeout.c b/applications/desktop/scenes/desktop_scene_pin_timeout.c new file mode 100644 index 00000000..3c267a0d --- /dev/null +++ b/applications/desktop/scenes/desktop_scene_pin_timeout.c @@ -0,0 +1,46 @@ +#include +#include +#include +#include +#include + +#include "../desktop_i.h" +#include "../views/desktop_view_pin_timeout.h" +#include "desktop_scene.h" +#include "desktop_scene_i.h" + +static void desktop_scene_pin_timeout_callback(void* context) { + Desktop* desktop = (Desktop*)context; + view_dispatcher_send_custom_event(desktop->view_dispatcher, DesktopPinTimeoutExit); +} + +void desktop_scene_pin_timeout_on_enter(void* context) { + Desktop* desktop = (Desktop*)context; + + uint32_t timeout = + scene_manager_get_scene_state(desktop->scene_manager, DesktopScenePinTimeout); + desktop_view_pin_timeout_start(desktop->pin_timeout_view, timeout); + desktop_view_pin_timeout_set_callback( + desktop->pin_timeout_view, desktop_scene_pin_timeout_callback, desktop); + + view_dispatcher_switch_to_view(desktop->view_dispatcher, DesktopViewIdPinTimeout); +} + +bool desktop_scene_pin_timeout_on_event(void* context, SceneManagerEvent event) { + Desktop* desktop = (Desktop*)context; + bool consumed = false; + + if(event.type == SceneManagerEventTypeCustom) { + switch(event.event) { + case DesktopPinTimeoutExit: + scene_manager_previous_scene(desktop->scene_manager); + consumed = true; + break; + } + } + + return consumed; +} + +void desktop_scene_pin_timeout_on_exit(void* context) { +} diff --git a/applications/desktop/scenes/desktop_scene_pinsetup.c b/applications/desktop/scenes/desktop_scene_pinsetup.c deleted file mode 100644 index 6b1c9686..00000000 --- a/applications/desktop/scenes/desktop_scene_pinsetup.c +++ /dev/null @@ -1,50 +0,0 @@ -#include "../desktop_i.h" - -#define SCENE_EXIT_EVENT (0U) - -void desktop_scene_ok_callback(void* context) { - Desktop* app = context; - view_dispatcher_send_custom_event(app->view_dispatcher, SCENE_EXIT_EVENT); -} - -void desktop_scene_pinsetup_on_enter(void* context) { - Desktop* app = context; - CodeInput* code_input = app->code_input; - - code_input_set_result_callback( - code_input, - desktop_scene_ok_callback, - NULL, - app, - app->settings.pincode.data, - &app->settings.pincode.length, - true); - - view_dispatcher_switch_to_view(app->view_dispatcher, DesktopViewPinSetup); -} - -bool desktop_scene_pinsetup_on_event(void* context, SceneManagerEvent event) { - Desktop* app = context; - bool consumed = false; - - if(event.type == SceneManagerEventTypeCustom) { - switch(event.event) { - case SCENE_EXIT_EVENT: - scene_manager_previous_scene(app->scene_manager); - consumed = true; - break; - - default: - consumed = true; - break; - } - } - return consumed; -} - -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_events.h b/applications/desktop/views/desktop_events.h index 56d9729f..49d6f81e 100644 --- a/applications/desktop/views/desktop_events.h +++ b/applications/desktop/views/desktop_events.h @@ -6,24 +6,35 @@ typedef enum { DesktopMainEventOpenFavorite, DesktopMainEventOpenMenu, DesktopMainEventOpenDebug, - DesktopMainEventUpdate, - DesktopMainEventUnlocked, DesktopMainEventRightShort, - DesktopMainEventCheckAnimation, - DesktopMainEventNewIdleAnimation, - DesktopMainEventInteractAnimation, DesktopMainEventBeforeAppStarted, DesktopMainEventAfterAppFinished, - DesktopLockedEventUnlock, - DesktopLockedEventCheckAnimation, - DesktopLockedEventMax, + + DesktopLockedEventUnlocked, + DesktopLockedEventUpdate, + DesktopLockedEventShowPinInput, + + DesktopPinInputEventResetWrongPinLabel, + DesktopPinInputEventUnlocked, + DesktopPinInputEventUnlockFailed, + DesktopPinInputEventBack, + + DesktopPinTimeoutExit, + DesktopDebugEventDeed, DesktopDebugEventWrongDeed, DesktopDebugEventSaveState, DesktopDebugEventExit, + DesktopFirstStartCompleted, DesktopFirstStartPoweroff, + DesktopLockMenuEventLock, DesktopLockMenuEventPinLock, DesktopLockMenuEventExit, + + DesktopAnimationEventCheckAnimation, + DesktopAnimationEventNewIdleAnimation, + DesktopAnimationEventInteractAnimation, + } DesktopEvent; diff --git a/applications/desktop/views/desktop_locked.c b/applications/desktop/views/desktop_locked.c deleted file mode 100644 index d8102f57..00000000 --- a/applications/desktop/views/desktop_locked.c +++ /dev/null @@ -1,247 +0,0 @@ -#include "desktop/desktop_settings/desktop_settings.h" -#include "furi/check.h" -#include "gui/view.h" -#include "portmacro.h" -#include -#include -#include -#include "../desktop_i.h" -#include "desktop_locked.h" -#include - -#define DOOR_MOVING_INTERVAL_MS (1000 / 16) -#define UNLOCKED_HINT_TIMEOUT_MS (2000) - -struct DesktopLockedView { - View* view; - DesktopLockedViewCallback callback; - void* context; - - TimerHandle_t timer; - uint8_t lock_count; - uint32_t lock_lastpress; - - PinCode pincode; - PinCode pincode_input; -}; - -typedef struct { - uint32_t hint_icon_expire_at; - bool unlocked_hint; - bool locked; - bool pin_locked; - - int8_t door_left_x; - int8_t door_right_x; - bool animation_seq_end; -} DesktopLockedViewModel; - -static void desktop_locked_unlock(DesktopLockedView* locked_view); - -void desktop_locked_set_callback( - DesktopLockedView* locked_view, - DesktopLockedViewCallback callback, - void* context) { - furi_assert(locked_view); - furi_assert(callback); - locked_view->callback = callback; - locked_view->context = context; -} - -void locked_view_timer_callback(TimerHandle_t timer) { - DesktopLockedView* locked_view = pvTimerGetTimerID(timer); - locked_view->callback(DesktopMainEventUpdate, locked_view->context); -} - -static void desktop_locked_update_hint_icon_timeout(DesktopLockedView* locked_view) { - DesktopLockedViewModel* model = view_get_model(locked_view->view); - model->hint_icon_expire_at = osKernelGetTickCount() + osKernelGetTickFreq(); - view_commit_model(locked_view->view, true); -} - -static void desktop_locked_reset_door_pos(DesktopLockedView* locked_view) { - DesktopLockedViewModel* model = view_get_model(locked_view->view); - model->animation_seq_end = false; - model->door_left_x = DOOR_L_POS; - model->door_right_x = DOOR_R_POS; - view_commit_model(locked_view->view, true); -} - -void desktop_locked_update(DesktopLockedView* locked_view) { - bool stop_timer = false; - - DesktopLockedViewModel* model = view_get_model(locked_view->view); - if(model->locked) { - if(model->door_left_x != DOOR_L_POS_MAX) { - model->door_left_x = CLAMP(model->door_left_x + 5, DOOR_L_POS_MAX, DOOR_L_POS); - model->door_right_x = CLAMP(model->door_right_x - 5, DOOR_R_POS, DOOR_R_POS_MIN); - } else { - model->animation_seq_end = true; - } - stop_timer = model->animation_seq_end; - } else { - model->unlocked_hint = false; - stop_timer = true; - } - view_commit_model(locked_view->view, true); - - if(stop_timer) { - xTimerStop(locked_view->timer, portMAX_DELAY); - } -} - -void desktop_locked_draw(Canvas* canvas, void* model) { - DesktopLockedViewModel* m = model; - uint32_t now = osKernelGetTickCount(); - canvas_set_color(canvas, ColorBlack); - - if(m->locked) { - if(!m->animation_seq_end) { - canvas_draw_icon(canvas, m->door_left_x, 0 + STATUS_BAR_Y_SHIFT, &I_DoorLeft_70x55); - canvas_draw_icon(canvas, m->door_right_x, 0 + STATUS_BAR_Y_SHIFT, &I_DoorRight_70x55); - canvas_set_font(canvas, FontPrimary); - elements_multiline_text_framed(canvas, 42, 30 + STATUS_BAR_Y_SHIFT, "Locked"); - } else if((now < m->hint_icon_expire_at) && !m->pin_locked) { - canvas_set_font(canvas, FontSecondary); - canvas_draw_icon(canvas, 13, 2 + STATUS_BAR_Y_SHIFT, &I_LockPopup_100x49); - elements_multiline_text(canvas, 65, 20 + STATUS_BAR_Y_SHIFT, "To unlock\npress:"); - } - } else { - if(m->unlocked_hint) { - canvas_set_font(canvas, FontPrimary); - elements_multiline_text_framed(canvas, 42, 30 + STATUS_BAR_Y_SHIFT, "Unlocked"); - } - } -} - -View* desktop_locked_get_view(DesktopLockedView* locked_view) { - furi_assert(locked_view); - return locked_view->view; -} - -bool desktop_locked_input(InputEvent* event, void* context) { - furi_assert(event); - furi_assert(context); - DesktopLockedView* locked_view = context; - bool locked = false; - bool locked_with_pin = false; - uint32_t press_time = xTaskGetTickCount(); - - { - DesktopLockedViewModel* model = view_get_model(locked_view->view); - bool changed = false; - locked = model->locked; - locked_with_pin = model->pin_locked; - if(!locked && model->unlocked_hint && event->type == InputTypePress) { - model->unlocked_hint = false; - changed = true; - } - view_commit_model(locked_view->view, changed); - } - - if(!locked || (event->type != InputTypeShort)) { - return locked; - } - - if(press_time - locked_view->lock_lastpress > UNLOCK_RST_TIMEOUT) { - locked_view->lock_lastpress = press_time; - locked_view->lock_count = 0; - locked_view->pincode_input.length = 0; - } - - if(locked_with_pin) { - locked_view->pincode_input.length = code_input_push( - locked_view->pincode_input.data, locked_view->pincode_input.length, event->key); - bool match = code_input_compare( - locked_view->pincode_input.data, - locked_view->pincode_input.length, - locked_view->pincode.data, - locked_view->pincode.length); - - if(match) { - desktop_locked_unlock(locked_view); - } - } else { - if(event->key == InputKeyBack) { - locked_view->lock_lastpress = press_time; - locked_view->lock_count++; - if(locked_view->lock_count == UNLOCK_CNT) { - desktop_locked_unlock(locked_view); - } - } else { - desktop_locked_update_hint_icon_timeout(locked_view); - locked_view->lock_count = 0; - } - } - - locked_view->lock_lastpress = press_time; - - return locked; -} - -DesktopLockedView* desktop_locked_alloc() { - DesktopLockedView* locked_view = furi_alloc(sizeof(DesktopLockedView)); - locked_view->view = view_alloc(); - locked_view->timer = - xTimerCreate("Locked view", 1000 / 16, pdTRUE, locked_view, locked_view_timer_callback); - - view_allocate_model(locked_view->view, ViewModelTypeLocking, sizeof(DesktopLockedViewModel)); - view_set_context(locked_view->view, locked_view); - view_set_draw_callback(locked_view->view, (ViewDrawCallback)desktop_locked_draw); - view_set_input_callback(locked_view->view, desktop_locked_input); - - return locked_view; -} - -void desktop_locked_free(DesktopLockedView* locked_view) { - furi_assert(locked_view); - osTimerDelete(locked_view->timer); - view_free(locked_view->view); - free(locked_view); -} - -void desktop_locked_lock(DesktopLockedView* locked_view) { - locked_view->pincode.length = 0; - DesktopLockedViewModel* model = view_get_model(locked_view->view); - model->locked = true; - model->pin_locked = false; - view_commit_model(locked_view->view, true); - desktop_locked_reset_door_pos(locked_view); - xTimerChangePeriod(locked_view->timer, DOOR_MOVING_INTERVAL_MS, portMAX_DELAY); - - Gui* gui = furi_record_open("gui"); - gui_set_lockdown(gui, true); - furi_record_close("gui"); -} - -void desktop_locked_lock_pincode(DesktopLockedView* locked_view, PinCode pincode) { - locked_view->pincode = pincode; - locked_view->pincode_input.length = 0; - DesktopLockedViewModel* model = view_get_model(locked_view->view); - model->locked = true; - model->pin_locked = true; - view_commit_model(locked_view->view, true); - desktop_locked_reset_door_pos(locked_view); - xTimerChangePeriod(locked_view->timer, DOOR_MOVING_INTERVAL_MS, portMAX_DELAY); - - Gui* gui = furi_record_open("gui"); - gui_set_lockdown(gui, true); - furi_record_close("gui"); -} - -static void desktop_locked_unlock(DesktopLockedView* locked_view) { - furi_assert(locked_view); - - locked_view->lock_count = 0; - DesktopLockedViewModel* model = view_get_model(locked_view->view); - model->locked = false; - model->pin_locked = false; - model->unlocked_hint = true; - view_commit_model(locked_view->view, true); - locked_view->callback(DesktopMainEventUnlocked, locked_view->context); - xTimerChangePeriod(locked_view->timer, UNLOCKED_HINT_TIMEOUT_MS, portMAX_DELAY); - - Gui* gui = furi_record_open("gui"); - gui_set_lockdown(gui, false); - furi_record_close("gui"); -} diff --git a/applications/desktop/views/desktop_locked.h b/applications/desktop/views/desktop_locked.h deleted file mode 100644 index 61e91e4e..00000000 --- a/applications/desktop/views/desktop_locked.h +++ /dev/null @@ -1,36 +0,0 @@ -#pragma once - -#include -#include -#include "desktop_events.h" - -#define UNLOCK_RST_TIMEOUT 300 -#define UNLOCK_CNT 3 - -#define DOOR_L_POS -57 -#define DOOR_L_POS_MAX 0 -#define DOOR_R_POS 115 -#define DOOR_R_POS_MIN 60 - -typedef enum { - DesktopLockedWithPin, - DesktopLockedNoPin, -} DesktopLockedSceneState; - -typedef struct DesktopLockedView DesktopLockedView; - -typedef void (*DesktopLockedViewCallback)(DesktopEvent event, void* context); - -void desktop_locked_set_callback( - DesktopLockedView* locked_view, - DesktopLockedViewCallback callback, - void* context); - -void desktop_locked_update(DesktopLockedView* locked_view); - -View* desktop_locked_get_view(DesktopLockedView* locked_view); -DesktopLockedView* desktop_locked_alloc(); -void desktop_locked_free(DesktopLockedView* locked_view); - -void desktop_locked_lock_pincode(DesktopLockedView* locked_view, PinCode pincode); -void desktop_locked_lock(DesktopLockedView* locked_view); diff --git a/applications/desktop/views/desktop_debug.c b/applications/desktop/views/desktop_view_debug.c similarity index 98% rename from applications/desktop/views/desktop_debug.c rename to applications/desktop/views/desktop_view_debug.c index 0d793dca..0ffd8d17 100644 --- a/applications/desktop/views/desktop_debug.c +++ b/applications/desktop/views/desktop_view_debug.c @@ -1,11 +1,11 @@ #include #include #include +#include +#include #include "../desktop_i.h" -#include "desktop_debug.h" -#include "dolphin/helpers/dolphin_state.h" -#include "dolphin/dolphin.h" +#include "desktop_view_debug.h" void desktop_debug_set_callback( DesktopDebugView* debug_view, diff --git a/applications/desktop/views/desktop_debug.h b/applications/desktop/views/desktop_view_debug.h similarity index 100% rename from applications/desktop/views/desktop_debug.h rename to applications/desktop/views/desktop_view_debug.h diff --git a/applications/desktop/views/desktop_first_start.c b/applications/desktop/views/desktop_view_first_start.c similarity index 99% rename from applications/desktop/views/desktop_first_start.c rename to applications/desktop/views/desktop_view_first_start.c index c0ef3a5f..5408dac0 100644 --- a/applications/desktop/views/desktop_first_start.c +++ b/applications/desktop/views/desktop_view_first_start.c @@ -1,8 +1,9 @@ #include #include #include + #include "../desktop_i.h" -#include "desktop_first_start.h" +#include "desktop_view_first_start.h" #define DESKTOP_FIRST_START_POWEROFF_SHORT 5000 #define DESKTOP_FIRST_START_POWEROFF_LONG (60 * 60 * 1000) diff --git a/applications/desktop/views/desktop_first_start.h b/applications/desktop/views/desktop_view_first_start.h similarity index 100% rename from applications/desktop/views/desktop_first_start.h rename to applications/desktop/views/desktop_view_first_start.h diff --git a/applications/desktop/views/desktop_lock_menu.c b/applications/desktop/views/desktop_view_lock_menu.c similarity index 99% rename from applications/desktop/views/desktop_lock_menu.c rename to applications/desktop/views/desktop_view_lock_menu.c index d65aa30d..005512cf 100644 --- a/applications/desktop/views/desktop_lock_menu.c +++ b/applications/desktop/views/desktop_view_lock_menu.c @@ -2,7 +2,7 @@ #include #include "../desktop_i.h" -#include "desktop_lock_menu.h" +#include "desktop_view_lock_menu.h" #define LOCK_MENU_ITEMS_NB 3 diff --git a/applications/desktop/views/desktop_lock_menu.h b/applications/desktop/views/desktop_view_lock_menu.h similarity index 100% rename from applications/desktop/views/desktop_lock_menu.h rename to applications/desktop/views/desktop_view_lock_menu.h diff --git a/applications/desktop/views/desktop_view_locked.c b/applications/desktop/views/desktop_view_locked.c new file mode 100644 index 00000000..8e3f22ee --- /dev/null +++ b/applications/desktop/views/desktop_view_locked.c @@ -0,0 +1,233 @@ +#include +#include +#include +#include +#include +#include +#include + +#include "../desktop_settings/desktop_settings.h" +#include "../desktop_i.h" +#include "desktop_view_locked.h" + +#define DOOR_MOVING_INTERVAL_MS (1000 / 16) +#define UNLOCKED_HINT_TIMEOUT_MS (2000) + +#define DOOR_OFFSET_START -55 +#define DOOR_OFFSET_END 0 + +#define DOOR_L_FINAL_POS 0 +#define DOOR_R_FINAL_POS 60 + +#define UNLOCK_CNT 3 +#define UNLOCK_RST_TIMEOUT 600 + +struct DesktopViewLocked { + View* view; + DesktopViewLockedCallback callback; + void* context; + + TimerHandle_t timer; + uint8_t lock_count; + uint32_t lock_lastpress; +}; + +typedef struct { + uint32_t hint_icon_expire_at; + bool unlocked_hint; + bool locked; + bool pin_locked; + + int8_t door_offset; + bool doors_closing; +} DesktopViewLockedModel; + +void desktop_view_locked_set_callback( + DesktopViewLocked* locked_view, + DesktopViewLockedCallback callback, + void* context) { + furi_assert(locked_view); + furi_assert(callback); + locked_view->callback = callback; + locked_view->context = context; +} + +static void locked_view_timer_callback(TimerHandle_t timer) { + DesktopViewLocked* locked_view = pvTimerGetTimerID(timer); + locked_view->callback(DesktopLockedEventUpdate, locked_view->context); +} + +static void desktop_view_locked_doors_draw(Canvas* canvas, DesktopViewLockedModel* model) { + int8_t offset = model->door_offset; + uint8_t door_left_x = DOOR_L_FINAL_POS + offset; + uint8_t door_right_x = DOOR_R_FINAL_POS - offset; + uint8_t height = icon_get_height(&I_DoorLeft_70x55); + canvas_draw_icon(canvas, door_left_x, canvas_height(canvas) - height, &I_DoorLeft_70x55); + canvas_draw_icon(canvas, door_right_x, canvas_height(canvas) - height, &I_DoorRight_70x55); +} + +static bool desktop_view_locked_doors_move(DesktopViewLockedModel* model) { + bool stop = false; + if(model->door_offset < DOOR_OFFSET_END) { + model->door_offset = CLAMP(model->door_offset + 5, DOOR_OFFSET_END, DOOR_OFFSET_START); + stop = true; + } + + return stop; +} + +static void desktop_view_locked_update_hint_icon_timeout(DesktopViewLocked* locked_view) { + DesktopViewLockedModel* model = view_get_model(locked_view->view); + model->hint_icon_expire_at = osKernelGetTickCount() + osKernelGetTickFreq(); + view_commit_model(locked_view->view, true); +} + +void desktop_view_locked_update(DesktopViewLocked* locked_view) { + bool stop_timer = false; + + DesktopViewLockedModel* model = view_get_model(locked_view->view); + if(model->locked) { + model->doors_closing = desktop_view_locked_doors_move(model); + stop_timer = !model->doors_closing; + } else { + model->unlocked_hint = false; + stop_timer = true; + } + view_commit_model(locked_view->view, true); + + if(stop_timer) { + xTimerStop(locked_view->timer, portMAX_DELAY); + } +} + +static void desktop_view_locked_draw(Canvas* canvas, void* model) { + DesktopViewLockedModel* m = model; + uint32_t now = osKernelGetTickCount(); + canvas_set_color(canvas, ColorBlack); + + if(m->locked) { + if(m->doors_closing) { + desktop_view_locked_doors_draw(canvas, m); + canvas_set_font(canvas, FontPrimary); + elements_multiline_text_framed(canvas, 42, 30 + STATUS_BAR_Y_SHIFT, "Locked"); + } else if((now < m->hint_icon_expire_at) && !m->pin_locked) { + canvas_set_font(canvas, FontSecondary); + elements_bold_rounded_frame(canvas, 14, 2 + STATUS_BAR_Y_SHIFT, 99, 48); + elements_multiline_text(canvas, 65, 20 + STATUS_BAR_Y_SHIFT, "To unlock\npress:"); + canvas_draw_icon(canvas, 65, 36 + STATUS_BAR_Y_SHIFT, &I_Back3_45x8); + canvas_draw_icon(canvas, 16, 7 + STATUS_BAR_Y_SHIFT, &I_WarningDolphin_45x42); + canvas_draw_dot(canvas, 17, 61); + } + } else { + if(m->unlocked_hint) { + canvas_set_font(canvas, FontPrimary); + elements_multiline_text_framed(canvas, 42, 30 + STATUS_BAR_Y_SHIFT, "Unlocked"); + } + } +} + +View* desktop_view_locked_get_view(DesktopViewLocked* locked_view) { + furi_assert(locked_view); + return locked_view->view; +} + +static bool desktop_view_locked_input(InputEvent* event, void* context) { + furi_assert(event); + furi_assert(context); + DesktopViewLocked* locked_view = context; + bool locked = false; + bool locked_with_pin = false; + bool doors_closing = false; + uint32_t press_time = xTaskGetTickCount(); + + { + DesktopViewLockedModel* model = view_get_model(locked_view->view); + bool changed = false; + locked = model->locked; + locked_with_pin = model->pin_locked; + doors_closing = model->doors_closing; + if(!locked && model->unlocked_hint && event->type == InputTypePress) { + model->unlocked_hint = false; + changed = true; + } + view_commit_model(locked_view->view, changed); + } + + if(!locked || doors_closing || (event->type != InputTypeShort)) { + return locked; + } + + if(locked_with_pin) { + locked_view->callback(DesktopLockedEventShowPinInput, locked_view->context); + } else { + if(press_time - locked_view->lock_lastpress > UNLOCK_RST_TIMEOUT) { + locked_view->lock_lastpress = press_time; + locked_view->lock_count = 0; + } + + desktop_view_locked_update_hint_icon_timeout(locked_view); + if(event->key == InputKeyBack) { + locked_view->lock_lastpress = press_time; + locked_view->lock_count++; + if(locked_view->lock_count == UNLOCK_CNT) { + desktop_view_locked_unlock(locked_view); + locked_view->callback(DesktopLockedEventUnlocked, locked_view->context); + } + } else { + locked_view->lock_count = 0; + } + + locked_view->lock_lastpress = press_time; + } + + return locked; +} + +DesktopViewLocked* desktop_view_locked_alloc() { + DesktopViewLocked* locked_view = furi_alloc(sizeof(DesktopViewLocked)); + locked_view->view = view_alloc(); + locked_view->timer = + xTimerCreate(NULL, 1000 / 16, pdTRUE, locked_view, locked_view_timer_callback); + + locked_view->view = view_alloc(); + view_allocate_model(locked_view->view, ViewModelTypeLocking, sizeof(DesktopViewLockedModel)); + view_set_context(locked_view->view, locked_view); + view_set_draw_callback(locked_view->view, desktop_view_locked_draw); + view_set_input_callback(locked_view->view, desktop_view_locked_input); + + return locked_view; +} + +void desktop_view_locked_free(DesktopViewLocked* locked_view) { + furi_assert(locked_view); + osTimerDelete(locked_view->timer); + view_free(locked_view->view); + free(locked_view); +} + +void desktop_view_locked_close_doors(DesktopViewLocked* locked_view) { + DesktopViewLockedModel* model = view_get_model(locked_view->view); + model->doors_closing = true; + model->door_offset = DOOR_OFFSET_START; + view_commit_model(locked_view->view, true); + xTimerChangePeriod(locked_view->timer, pdMS_TO_TICKS(DOOR_MOVING_INTERVAL_MS), portMAX_DELAY); +} + +void desktop_view_locked_lock(DesktopViewLocked* locked_view, bool pin_locked) { + DesktopViewLockedModel* model = view_get_model(locked_view->view); + model->locked = true; + model->pin_locked = pin_locked; + view_commit_model(locked_view->view, true); +} + +void desktop_view_locked_unlock(DesktopViewLocked* locked_view) { + furi_assert(locked_view); + + locked_view->lock_count = 0; + DesktopViewLockedModel* model = view_get_model(locked_view->view); + model->locked = false; + model->pin_locked = false; + model->unlocked_hint = true; + view_commit_model(locked_view->view, true); + xTimerChangePeriod(locked_view->timer, pdMS_TO_TICKS(UNLOCKED_HINT_TIMEOUT_MS), portMAX_DELAY); +} diff --git a/applications/desktop/views/desktop_view_locked.h b/applications/desktop/views/desktop_view_locked.h new file mode 100644 index 00000000..60fe791b --- /dev/null +++ b/applications/desktop/views/desktop_view_locked.h @@ -0,0 +1,21 @@ +#pragma once + +#include "../desktop_settings/desktop_settings.h" +#include "../views/desktop_events.h" +#include + +typedef struct DesktopViewLocked DesktopViewLocked; + +typedef void (*DesktopViewLockedCallback)(DesktopEvent event, void* context); + +void desktop_view_locked_set_callback( + DesktopViewLocked* locked_view, + DesktopViewLockedCallback callback, + void* context); +void desktop_view_locked_update(DesktopViewLocked* locked_view); +View* desktop_view_locked_get_view(DesktopViewLocked* locked_view); +DesktopViewLocked* desktop_view_locked_alloc(); +void desktop_view_locked_free(DesktopViewLocked* locked_view); +void desktop_view_locked_lock(DesktopViewLocked* locked_view, bool pin_locked); +void desktop_view_locked_unlock(DesktopViewLocked* locked_view); +void desktop_view_locked_close_doors(DesktopViewLocked* locked_view); diff --git a/applications/desktop/views/desktop_main.c b/applications/desktop/views/desktop_view_main.c similarity index 98% rename from applications/desktop/views/desktop_main.c rename to applications/desktop/views/desktop_view_main.c index 83d561df..51520863 100644 --- a/applications/desktop/views/desktop_main.c +++ b/applications/desktop/views/desktop_view_main.c @@ -7,7 +7,7 @@ #include #include "../desktop_i.h" -#include "desktop_main.h" +#include "desktop_view_main.h" struct DesktopMainView { View* view; diff --git a/applications/desktop/views/desktop_main.h b/applications/desktop/views/desktop_view_main.h similarity index 100% rename from applications/desktop/views/desktop_main.h rename to applications/desktop/views/desktop_view_main.h diff --git a/applications/desktop/views/desktop_view_pin_input.c b/applications/desktop/views/desktop_view_pin_input.c new file mode 100644 index 00000000..b8976ca2 --- /dev/null +++ b/applications/desktop/views/desktop_view_pin_input.c @@ -0,0 +1,340 @@ +#include +#include +#include +#include +#include +#include + +#include "desktop_view_pin_input.h" +#include "../desktop_settings/desktop_settings.h" + +#define NO_ACTIVITY_TIMEOUT 15000 + +#define PIN_CELL_WIDTH 13 +#define DEFAULT_PIN_X 64 +#define DEFAULT_PIN_Y 32 + +struct DesktopViewPinInput { + View* view; + DesktopViewPinInputCallback back_callback; + DesktopViewPinInputCallback timeout_callback; + DesktopViewPinInputDoneCallback done_callback; + void* context; + TimerHandle_t timer; +}; + +typedef struct { + PinCode pin; + bool pin_hidden; + bool locked_input; + uint8_t pin_x; + uint8_t pin_y; + const char* primary_str; + uint8_t primary_str_x; + uint8_t primary_str_y; + const char* secondary_str; + uint8_t secondary_str_x; + uint8_t secondary_str_y; + const char* button_label; +} DesktopViewPinInputModel; + +static bool desktop_view_pin_input_input(InputEvent* event, void* context) { + furi_assert(event); + furi_assert(context); + + DesktopViewPinInput* pin_input = context; + DesktopViewPinInputModel* model = view_get_model(pin_input->view); + + bool call_back_callback = false; + bool call_done_callback = false; + PinCode pin_code = {0}; + + if(event->type == InputTypeShort) { + switch(event->key) { + case InputKeyRight: + case InputKeyLeft: + case InputKeyDown: + case InputKeyUp: + if(!model->locked_input) { + if(model->pin.length < MAX_PIN_SIZE) { + model->pin.data[model->pin.length++] = event->key; + } + } + break; + case InputKeyOk: + if(model->pin.length >= MIN_PIN_SIZE) { + call_done_callback = true; + pin_code = model->pin; + } + break; + case InputKeyBack: + if(!model->locked_input) { + if(model->pin.length > 0) { + model->pin.length = 0; + } else { + call_back_callback = true; + } + } + break; + default: + furi_assert(0); + break; + } + } + view_commit_model(pin_input->view, true); + + if(call_done_callback && pin_input->done_callback) { + pin_input->done_callback(&pin_code, pin_input->context); + } else if(call_back_callback && pin_input->back_callback) { + pin_input->back_callback(pin_input->context); + } + + xTimerStart(pin_input->timer, 0); + + return true; +} + +static void desktop_view_pin_input_draw_cells(Canvas* canvas, DesktopViewPinInputModel* model) { + furi_assert(canvas); + furi_assert(model); + + uint8_t draw_pin_size = MAX(4, model->pin.length + 1); + if(model->locked_input || (model->pin.length == MAX_PIN_SIZE)) { + draw_pin_size = model->pin.length; + } + + uint8_t x = model->pin_x - (draw_pin_size * (PIN_CELL_WIDTH - 1)) / 2; + uint8_t y = model->pin_y - (PIN_CELL_WIDTH / 2); + + for(int i = 0; i < draw_pin_size; ++i) { + canvas_draw_frame(canvas, x, y, PIN_CELL_WIDTH, PIN_CELL_WIDTH); + if(i < model->pin.length) { + if(model->pin_hidden) { + canvas_draw_icon(canvas, x + 3, y + 3, &I_Pin_star_7x7); + } else { + switch(model->pin.data[i]) { + case InputKeyDown: + canvas_draw_icon(canvas, x + 3, y + 2, &I_Pin_arrow_down_7x9); + break; + case InputKeyUp: + canvas_draw_icon(canvas, x + 3, y + 2, &I_Pin_arrow_up7x9); + break; + case InputKeyLeft: + canvas_draw_icon(canvas, x + 2, y + 3, &I_Pin_arrow_left_9x7); + break; + case InputKeyRight: + canvas_draw_icon(canvas, x + 2, y + 3, &I_Pin_arrow_right_9x7); + break; + default: + furi_assert(0); + break; + } + } + } else if(i == model->pin.length) { + canvas_draw_icon(canvas, x + 4, y + PIN_CELL_WIDTH + 1, &I_Pin_pointer_5x3); + } + x += PIN_CELL_WIDTH - 1; + } +} + +static void desktop_view_pin_input_draw(Canvas* canvas, void* context) { + furi_assert(canvas); + furi_assert(context); + + canvas_set_font(canvas, FontSecondary); + DesktopViewPinInputModel* model = context; + desktop_view_pin_input_draw_cells(canvas, model); + + if((model->pin.length > 0) && !model->locked_input) { + canvas_draw_icon(canvas, 4, 53, &I_Pin_back_full_40x8); + } + + if(model->button_label && ((model->pin.length >= MIN_PIN_SIZE) || model->locked_input)) { + elements_button_center(canvas, model->button_label); + } + + if(model->primary_str) { + canvas_set_font(canvas, FontPrimary); + canvas_draw_str(canvas, model->primary_str_x, model->primary_str_y, model->primary_str); + canvas_set_font(canvas, FontSecondary); + } + + if(model->secondary_str) { + canvas_set_font(canvas, FontSecondary); + canvas_draw_str( + canvas, model->secondary_str_x, model->secondary_str_y, model->secondary_str); + } +} + +void desktop_view_pin_input_timer_callback(TimerHandle_t timer) { + DesktopViewPinInput* pin_input = pvTimerGetTimerID(timer); + + if(pin_input->timeout_callback) { + pin_input->timeout_callback(pin_input->context); + } +} + +static void desktop_view_pin_input_enter(void* context) { + DesktopViewPinInput* pin_input = context; + xTimerStart(pin_input->timer, portMAX_DELAY); +} + +static void desktop_view_pin_input_exit(void* context) { + DesktopViewPinInput* pin_input = context; + xTimerStop(pin_input->timer, portMAX_DELAY); +} + +DesktopViewPinInput* desktop_view_pin_input_alloc(void) { + DesktopViewPinInput* pin_input = furi_alloc(sizeof(DesktopViewPinInput)); + pin_input->view = view_alloc(); + view_allocate_model(pin_input->view, ViewModelTypeLocking, sizeof(DesktopViewPinInputModel)); + view_set_context(pin_input->view, pin_input); + view_set_draw_callback(pin_input->view, desktop_view_pin_input_draw); + view_set_input_callback(pin_input->view, desktop_view_pin_input_input); + pin_input->timer = xTimerCreate( + NULL, + pdMS_TO_TICKS(NO_ACTIVITY_TIMEOUT), + pdFALSE, + pin_input, + desktop_view_pin_input_timer_callback); + view_set_enter_callback(pin_input->view, desktop_view_pin_input_enter); + view_set_exit_callback(pin_input->view, desktop_view_pin_input_exit); + + DesktopViewPinInputModel* model = view_get_model(pin_input->view); + model->pin_x = DEFAULT_PIN_X; + model->pin_y = DEFAULT_PIN_Y; + model->pin.length = 0; + view_commit_model(pin_input->view, false); + + return pin_input; +} + +void desktop_view_pin_input_free(DesktopViewPinInput* pin_input) { + furi_assert(pin_input); + + xTimerStop(pin_input->timer, portMAX_DELAY); + while(xTimerIsTimerActive(pin_input->timer)) { + delay(1); + } + xTimerDelete(pin_input->timer, portMAX_DELAY); + + view_free(pin_input->view); + free(pin_input); +} + +void desktop_view_pin_input_lock_input(DesktopViewPinInput* pin_input) { + furi_assert(pin_input); + + DesktopViewPinInputModel* model = view_get_model(pin_input->view); + model->locked_input = true; + view_commit_model(pin_input->view, true); +} + +void desktop_view_pin_input_unlock_input(DesktopViewPinInput* pin_input) { + furi_assert(pin_input); + + DesktopViewPinInputModel* model = view_get_model(pin_input->view); + model->locked_input = false; + view_commit_model(pin_input->view, true); +} + +void desktop_view_pin_input_set_pin(DesktopViewPinInput* pin_input, const PinCode* pin) { + furi_assert(pin_input); + furi_assert(pin); + + DesktopViewPinInputModel* model = view_get_model(pin_input->view); + model->pin = *pin; + view_commit_model(pin_input->view, true); +} + +void desktop_view_pin_input_reset_pin(DesktopViewPinInput* pin_input) { + furi_assert(pin_input); + + DesktopViewPinInputModel* model = view_get_model(pin_input->view); + model->pin.length = 0; + view_commit_model(pin_input->view, true); +} + +void desktop_view_pin_input_hide_pin(DesktopViewPinInput* pin_input, bool pin_hidden) { + furi_assert(pin_input); + + DesktopViewPinInputModel* model = view_get_model(pin_input->view); + model->pin_hidden = pin_hidden; + view_commit_model(pin_input->view, true); +} + +void desktop_view_pin_input_set_label_button(DesktopViewPinInput* pin_input, const char* label) { + furi_assert(pin_input); + + DesktopViewPinInputModel* model = view_get_model(pin_input->view); + model->button_label = label; + view_commit_model(pin_input->view, true); +} + +void desktop_view_pin_input_set_label_primary( + DesktopViewPinInput* pin_input, + uint8_t x, + uint8_t y, + const char* label) { + furi_assert(pin_input); + + DesktopViewPinInputModel* model = view_get_model(pin_input->view); + model->primary_str = label; + model->primary_str_x = x; + model->primary_str_y = y; + view_commit_model(pin_input->view, true); +} + +void desktop_view_pin_input_set_label_secondary( + DesktopViewPinInput* pin_input, + uint8_t x, + uint8_t y, + const char* label) { + furi_assert(pin_input); + + DesktopViewPinInputModel* model = view_get_model(pin_input->view); + model->secondary_str = label; + model->secondary_str_x = x; + model->secondary_str_y = y; + view_commit_model(pin_input->view, true); +} + +void desktop_view_pin_input_set_pin_position(DesktopViewPinInput* pin_input, uint8_t x, uint8_t y) { + furi_assert(pin_input); + + DesktopViewPinInputModel* model = view_get_model(pin_input->view); + model->pin_x = x; + model->pin_y = y; + view_commit_model(pin_input->view, true); +} + +void desktop_view_pin_input_set_context(DesktopViewPinInput* pin_input, void* context) { + furi_assert(pin_input); + pin_input->context = context; +} + +void desktop_view_pin_input_set_timeout_callback( + DesktopViewPinInput* pin_input, + DesktopViewPinInputCallback callback) { + furi_assert(pin_input); + pin_input->timeout_callback = callback; +} + +void desktop_view_pin_input_set_back_callback( + DesktopViewPinInput* pin_input, + DesktopViewPinInputCallback callback) { + furi_assert(pin_input); + pin_input->back_callback = callback; +} + +void desktop_view_pin_input_set_done_callback( + DesktopViewPinInput* pin_input, + DesktopViewPinInputDoneCallback callback) { + furi_assert(pin_input); + pin_input->done_callback = callback; +} + +View* desktop_view_pin_input_get_view(DesktopViewPinInput* pin_input) { + furi_assert(pin_input); + return pin_input->view; +} diff --git a/applications/desktop/views/desktop_view_pin_input.h b/applications/desktop/views/desktop_view_pin_input.h new file mode 100644 index 00000000..3e39fd20 --- /dev/null +++ b/applications/desktop/views/desktop_view_pin_input.h @@ -0,0 +1,40 @@ +#pragma once + +#include +#include "desktop/desktop_settings/desktop_settings.h" + +typedef void (*DesktopViewPinInputCallback)(void*); +typedef void (*DesktopViewPinInputDoneCallback)(const PinCode* 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_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); +void desktop_view_pin_input_set_label_primary( + DesktopViewPinInput* pin_input, + uint8_t x, + uint8_t y, + const char* label); +void desktop_view_pin_input_set_label_secondary( + DesktopViewPinInput* pin_input, + uint8_t x, + uint8_t y, + const char* label); +void desktop_view_pin_input_set_pin_position(DesktopViewPinInput* pin_input, uint8_t x, uint8_t y); +View* desktop_view_pin_input_get_view(DesktopViewPinInput*); +void desktop_view_pin_input_set_done_callback( + DesktopViewPinInput* pin_input, + DesktopViewPinInputDoneCallback callback); +void desktop_view_pin_input_set_back_callback( + DesktopViewPinInput* pin_input, + DesktopViewPinInputCallback callback); +void desktop_view_pin_input_set_timeout_callback( + DesktopViewPinInput* pin_input, + DesktopViewPinInputCallback callback); +void desktop_view_pin_input_set_context(DesktopViewPinInput* pin_input, void* context); +void desktop_view_pin_input_lock_input(DesktopViewPinInput* pin_input); +void desktop_view_pin_input_unlock_input(DesktopViewPinInput* pin_input); diff --git a/applications/desktop/views/desktop_view_pin_setup_done.c b/applications/desktop/views/desktop_view_pin_setup_done.c new file mode 100644 index 00000000..a90903e9 --- /dev/null +++ b/applications/desktop/views/desktop_view_pin_setup_done.c @@ -0,0 +1,80 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../desktop_i.h" +#include "desktop_view_pin_setup_done.h" + +struct DesktopViewPinSetupDone { + View* view; + DesktopViewPinSetupDoneDoneCallback callback; + void* context; +}; + +static void desktop_view_pin_done_draw(Canvas* canvas, void* model) { + furi_assert(canvas); + furi_assert(model); + + canvas_set_font(canvas, FontPrimary); + elements_multiline_text_aligned( + canvas, 64, 0, AlignCenter, AlignTop, "Prepare to use\narrows as\nPIN symbols"); + + canvas_set_font(canvas, FontSecondary); + elements_multiline_text(canvas, 58, 24, "Prepare to use\narrows as\nPIN symbols"); + + canvas_draw_icon(canvas, 16, 18, &I_Pin_attention_dpad_29x29); + elements_button_right(canvas, "Next"); +} + +static bool desktop_view_pin_done_input(InputEvent* event, void* context) { + furi_assert(event); + furi_assert(context); + + DesktopViewPinSetupDone* instance = context; + bool consumed = false; + + if((event->key == InputKeyRight) && (event->type == InputTypeShort)) { + instance->callback(instance->context); + consumed = true; + } + + return consumed; +} + +void desktop_view_pin_done_set_callback( + DesktopViewPinSetupDone* instance, + DesktopViewPinSetupDoneDoneCallback callback, + void* context) { + furi_assert(instance); + furi_assert(callback); + instance->callback = callback; + instance->context = context; +} + +DesktopViewPinSetupDone* desktop_view_pin_done_alloc() { + DesktopViewPinSetupDone* view = furi_alloc(sizeof(DesktopViewPinSetupDone)); + view->view = view_alloc(); + view_allocate_model(view->view, ViewModelTypeLockFree, 1); + view_set_context(view->view, view); + view_set_draw_callback(view->view, desktop_view_pin_done_draw); + view_set_input_callback(view->view, desktop_view_pin_done_input); + + return view; +} + +void desktop_view_pin_done_free(DesktopViewPinSetupDone* instance) { + furi_assert(instance); + + view_free(instance->view); + free(instance); +} + +View* desktop_view_pin_done_get_view(DesktopViewPinSetupDone* instance) { + furi_assert(instance); + return instance->view; +} diff --git a/applications/desktop/views/desktop_view_pin_setup_done.h b/applications/desktop/views/desktop_view_pin_setup_done.h new file mode 100644 index 00000000..b55677dc --- /dev/null +++ b/applications/desktop/views/desktop_view_pin_setup_done.h @@ -0,0 +1,15 @@ +#pragma once + +#include + +typedef struct DesktopViewPinSetupDone DesktopViewPinSetupDone; + +typedef void (*DesktopViewPinSetupDoneDoneCallback)(void*); + +void desktop_view_pin_done_set_callback( + DesktopViewPinSetupDone* instance, + DesktopViewPinSetupDoneDoneCallback callback, + void* context); +DesktopViewPinSetupDone* desktop_view_pin_done_alloc(); +void desktop_view_pin_done_free(DesktopViewPinSetupDone* instance); +View* desktop_view_pin_done_get_view(DesktopViewPinSetupDone* instance); diff --git a/applications/desktop/views/desktop_view_pin_timeout.c b/applications/desktop/views/desktop_view_pin_timeout.c new file mode 100644 index 00000000..7cc0860f --- /dev/null +++ b/applications/desktop/views/desktop_view_pin_timeout.c @@ -0,0 +1,109 @@ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "desktop_view_pin_timeout.h" + +struct DesktopViewPinTimeout { + View* view; + TimerHandle_t timer; + DesktopViewPinTimeoutDoneCallback callback; + void* context; +}; + +typedef struct { + uint32_t time_left; +} DesktopViewPinTimeoutModel; + +void desktop_view_pin_timeout_set_callback( + DesktopViewPinTimeout* instance, + DesktopViewPinTimeoutDoneCallback callback, + void* context) { + furi_assert(instance); + + instance->callback = callback; + instance->context = context; +} + +static void desktop_view_pin_timeout_timer_callback(TimerHandle_t timer) { + DesktopViewPinTimeout* instance = pvTimerGetTimerID(timer); + bool stop = false; + + DesktopViewPinTimeoutModel* model = view_get_model(instance->view); + if(model->time_left > 0) { + --model->time_left; + } else { + stop = true; + } + view_commit_model(instance->view, true); + + if(stop) { + xTimerStop(instance->timer, portMAX_DELAY); + instance->callback(instance->context); + } +} + +static bool desktop_view_pin_timeout_input(InputEvent* event, void* context) { + return true; +} + +static void desktop_view_pin_timeout_draw(Canvas* canvas, void* _model) { + furi_assert(canvas); + furi_assert(_model); + + DesktopViewPinTimeoutModel* model = _model; + + canvas_set_font(canvas, FontPrimary); + canvas_draw_str(canvas, 36, 31, "Wrong PIN!"); + + canvas_set_font(canvas, FontSecondary); + char str[30] = {0}; + snprintf(str, sizeof(str), "Timeout: %lds", model->time_left); + canvas_draw_str_aligned(canvas, 64, 38, AlignCenter, AlignCenter, str); +} + +void desktop_view_pin_timeout_free(DesktopViewPinTimeout* instance) { + view_free(instance->view); + xTimerDelete(instance->timer, portMAX_DELAY); + + free(instance); +} + +DesktopViewPinTimeout* desktop_view_pin_timeout_alloc(void) { + DesktopViewPinTimeout* instance = furi_alloc(sizeof(DesktopViewPinTimeout)); + instance->timer = xTimerCreate( + NULL, pdMS_TO_TICKS(1000), pdTRUE, instance, desktop_view_pin_timeout_timer_callback); + + instance->view = view_alloc(); + view_allocate_model(instance->view, ViewModelTypeLockFree, sizeof(DesktopViewPinTimeoutModel)); + + view_set_context(instance->view, instance); + view_set_draw_callback(instance->view, desktop_view_pin_timeout_draw); + view_set_input_callback(instance->view, desktop_view_pin_timeout_input); + + return instance; +} + +void desktop_view_pin_timeout_start(DesktopViewPinTimeout* instance, uint32_t time_left) { + furi_assert(instance); + + DesktopViewPinTimeoutModel* model = view_get_model(instance->view); + // no race - always called when timer is stopped + model->time_left = time_left; + view_commit_model(instance->view, true); + + xTimerStart(instance->timer, portMAX_DELAY); +} + +View* desktop_view_pin_timeout_get_view(DesktopViewPinTimeout* instance) { + furi_assert(instance); + + return instance->view; +} diff --git a/applications/desktop/views/desktop_view_pin_timeout.h b/applications/desktop/views/desktop_view_pin_timeout.h new file mode 100644 index 00000000..76d84ba5 --- /dev/null +++ b/applications/desktop/views/desktop_view_pin_timeout.h @@ -0,0 +1,16 @@ +#pragma once + +#include +#include + +typedef void (*DesktopViewPinTimeoutDoneCallback)(void*); +typedef struct DesktopViewPinTimeout DesktopViewPinTimeout; + +void desktop_view_pin_timeout_set_callback( + DesktopViewPinTimeout* instance, + DesktopViewPinTimeoutDoneCallback callback, + void* context); +DesktopViewPinTimeout* desktop_view_pin_timeout_alloc(void); +void desktop_view_pin_timeout_free(DesktopViewPinTimeout*); +void desktop_view_pin_timeout_start(DesktopViewPinTimeout* instance, uint32_t time_left); +View* desktop_view_pin_timeout_get_view(DesktopViewPinTimeout* instance); diff --git a/applications/dolphin/dolphin.c b/applications/dolphin/dolphin.c index 2213ebb9..92c6d7a7 100644 --- a/applications/dolphin/dolphin.c +++ b/applications/dolphin/dolphin.c @@ -80,15 +80,11 @@ Dolphin* dolphin_alloc() { dolphin->event_queue = osMessageQueueNew(8, sizeof(DolphinEvent), NULL); dolphin->pubsub = furi_pubsub_alloc(); dolphin->butthurt_timer = xTimerCreate( - "Butthurt timer", HOURS_IN_TICKS(2 * 24), pdTRUE, dolphin, dolphin_butthurt_timer_callback); + NULL, HOURS_IN_TICKS(2 * 24), pdTRUE, dolphin, dolphin_butthurt_timer_callback); dolphin->flush_timer = - xTimerCreate("Flush timer", 30 * 1000, pdFALSE, dolphin, dolphin_flush_timer_callback); + xTimerCreate(NULL, 30 * 1000, pdFALSE, dolphin, dolphin_flush_timer_callback); dolphin->clear_limits_timer = xTimerCreate( - "Clear limits timer", - HOURS_IN_TICKS(24), - pdTRUE, - dolphin, - dolphin_clear_limits_timer_callback); + NULL, HOURS_IN_TICKS(24), pdTRUE, dolphin, dolphin_clear_limits_timer_callback); return dolphin; } diff --git a/applications/gui/elements.c b/applications/gui/elements.c index 0cd341b3..2b874ec1 100644 --- a/applications/gui/elements.c +++ b/applications/gui/elements.c @@ -1,4 +1,7 @@ #include "elements.h" +#include +#include "furi_hal_resources.h" +#include #include "gui/canvas.h" #include @@ -337,6 +340,47 @@ void elements_slightly_rounded_box( canvas_draw_rbox(canvas, x, y, width, height, 1); } +void elements_bold_rounded_frame( + Canvas* canvas, + uint8_t x, + uint8_t y, + uint8_t width, + uint8_t height) { + furi_assert(canvas); + + canvas_set_color(canvas, ColorWhite); + canvas_draw_box(canvas, x + 2, y + 2, width - 3, height - 3); + canvas_set_color(canvas, ColorBlack); + + canvas_draw_line(canvas, x + 3, y, x + width - 3, y); + canvas_draw_line(canvas, x + 2, y + 1, x + width - 2, y + 1); + + canvas_draw_line(canvas, x, y + 3, x, y + height - 3); + canvas_draw_line(canvas, x + 1, y + 2, x + 1, y + height - 2); + + canvas_draw_line(canvas, x + width, y + 3, x + width, y + height - 3); + canvas_draw_line(canvas, x + width - 1, y + 2, x + width - 1, y + height - 2); + + canvas_draw_line(canvas, x + 3, y + height, x + width - 3, y + height); + canvas_draw_line(canvas, x + 2, y + height - 1, x + width - 2, y + height - 1); + + canvas_draw_dot(canvas, x + 2, y + 2); + canvas_draw_dot(canvas, x + 3, y + 2); + canvas_draw_dot(canvas, x + 2, y + 3); + + canvas_draw_dot(canvas, x + width - 2, y + 2); + canvas_draw_dot(canvas, x + width - 3, y + 2); + canvas_draw_dot(canvas, x + width - 2, y + 3); + + canvas_draw_dot(canvas, x + 2, y + height - 2); + canvas_draw_dot(canvas, x + 3, y + height - 2); + canvas_draw_dot(canvas, x + 2, y + height - 3); + + canvas_draw_dot(canvas, x + width - 2, y + height - 2); + canvas_draw_dot(canvas, x + width - 3, y + height - 2); + canvas_draw_dot(canvas, x + width - 2, y + height - 3); +} + void elements_bubble(Canvas* canvas, uint8_t x, uint8_t y, uint8_t width, uint8_t height) { furi_assert(canvas); canvas_draw_rframe(canvas, x + 4, y, width, height, 3); diff --git a/applications/gui/elements.h b/applications/gui/elements.h index 2d576e5b..28010b36 100644 --- a/applications/gui/elements.h +++ b/applications/gui/elements.h @@ -150,6 +150,19 @@ void elements_slightly_rounded_box( uint8_t width, uint8_t height); +/** Draw bold rounded frame + * + * @param canvas Canvas instance + * @param x, y top left corner coordinates + * @param width, height size of frame + */ +void elements_bold_rounded_frame( + Canvas* canvas, + uint8_t x, + uint8_t y, + uint8_t width, + uint8_t height); + /** Draw bubble frame for text * * @param canvas Canvas instance diff --git a/applications/gui/modules/code_input.c b/applications/gui/modules/code_input.c deleted file mode 100644 index 988742f9..00000000 --- a/applications/gui/modules/code_input.c +++ /dev/null @@ -1,478 +0,0 @@ -#include "code_input.h" -#include -#include - -#define MAX_CODE_LEN 10 - -struct CodeInput { - View* view; -}; - -typedef enum { - CodeInputStateVerify, - CodeInputStateUpdate, - CodeInputStateTotal, -} CodeInputStateEnum; - -typedef enum { - CodeInputFirst, - CodeInputSecond, - CodeInputTotal, -} CodeInputsEnum; - -typedef struct { - uint8_t state; - uint8_t current; - bool ext_update; - - uint8_t input_length[CodeInputTotal]; - uint8_t local_buffer[CodeInputTotal][MAX_CODE_LEN]; - - CodeInputOkCallback ok_callback; - CodeInputFailCallback fail_callback; - void* callback_context; - - const char* header; - - uint8_t* ext_buffer; - uint8_t* ext_buffer_length; -} CodeInputModel; - -static const Icon* keys_assets[] = { - [InputKeyUp] = &I_ButtonUp_7x4, - [InputKeyDown] = &I_ButtonDown_7x4, - [InputKeyRight] = &I_ButtonRight_4x7, - [InputKeyLeft] = &I_ButtonLeft_4x7, -}; - -/** - * @brief Compare buffers - * - * @param in Input buffer pointer - * @param len_in Input array length - * @param src Source buffer pointer - * @param len_src Source array length - */ - -bool code_input_compare(uint8_t* in, size_t len_in, uint8_t* src, size_t len_src) { - bool result = false; - do { - result = (len_in && len_src); - if(!result) { - break; - } - result = (len_in == len_src); - if(!result) { - break; - } - for(size_t i = 0; i < len_in; i++) { - result = (in[i] == src[i]); - if(!result) { - break; - } - } - } while(false); - - return result; -} - -/** - * @brief Compare local buffers - * - * @param model - */ -static bool code_input_compare_local(CodeInputModel* model) { - uint8_t* source = model->local_buffer[CodeInputFirst]; - size_t source_length = model->input_length[CodeInputFirst]; - - uint8_t* input = model->local_buffer[CodeInputSecond]; - size_t input_length = model->input_length[CodeInputSecond]; - - return code_input_compare(input, input_length, source, source_length); -} - -/** - * @brief Compare ext with local - * - * @param model - */ -static bool code_input_compare_ext(CodeInputModel* model) { - uint8_t* input = model->local_buffer[CodeInputFirst]; - size_t input_length = model->input_length[CodeInputFirst]; - - uint8_t* source = model->ext_buffer; - size_t source_length = *model->ext_buffer_length; - - return code_input_compare(input, input_length, source, source_length); -} - -/** - * @brief Set ext buffer - * - * @param model - */ -static void code_input_set_ext(CodeInputModel* model) { - *model->ext_buffer_length = model->input_length[CodeInputFirst]; - for(size_t i = 0; i <= model->input_length[CodeInputFirst]; i++) { - model->ext_buffer[i] = model->local_buffer[CodeInputFirst][i]; - } -} - -/** - * @brief Draw input sequence - * - * @param canvas - * @param buffer - * @param length - * @param x - * @param y - * @param active - */ -static void code_input_draw_sequence( - Canvas* canvas, - uint8_t* buffer, - uint8_t length, - uint8_t x, - uint8_t y, - bool active) { - uint8_t pos_x = x + 6; - uint8_t pos_y = y + 3; - - if(active) canvas_draw_icon(canvas, x - 4, y + 5, &I_ButtonRightSmall_3x5); - - elements_slightly_rounded_frame(canvas, x, y, 116, 15); - - for(size_t i = 0; i < length; i++) { - // maybe symmetrical assets? :-/ - uint8_t offset_y = buffer[i] < 2 ? 2 + (buffer[i] * 2) : 1; - canvas_draw_icon(canvas, pos_x, pos_y + offset_y, keys_assets[buffer[i]]); - pos_x += buffer[i] > 1 ? 9 : 11; - } -} - -/** - * @brief Reset input count - * - * @param model - */ -static void code_input_reset_count(CodeInputModel* model) { - model->input_length[model->current] = 0; -} - -/** - * @brief Call input callback - * - * @param model - */ -static void code_input_call_ok_callback(CodeInputModel* model) { - if(model->ok_callback != NULL) { - model->ok_callback(model->callback_context); - } -} - -/** - * @brief Call changed callback - * - * @param model - */ -static void code_input_call_fail_callback(CodeInputModel* model) { - if(model->fail_callback != NULL) { - model->fail_callback(model->callback_context); - } -} - -/** - * @brief Handle Back button - * - * @param model - */ -static bool code_input_handle_back(CodeInputModel* model) { - if(model->current && !model->input_length[model->current]) { - --model->current; - return true; - } - - if(model->input_length[model->current]) { - code_input_reset_count(model); - return true; - } - - code_input_call_fail_callback(model); - return false; -} - -/** - * @brief Handle OK button - * - * @param model - */ -static void code_input_handle_ok(CodeInputModel* model) { - switch(model->state) { - case CodeInputStateVerify: - - if(code_input_compare_ext(model)) { - if(model->ext_update) { - model->state = CodeInputStateUpdate; - } else { - code_input_call_ok_callback(model); - } - } - code_input_reset_count(model); - break; - - case CodeInputStateUpdate: - - if(!model->current && model->input_length[model->current]) { - model->current++; - } else { - if(code_input_compare_local(model)) { - if(model->ext_update) { - code_input_set_ext(model); - } - code_input_call_ok_callback(model); - } else { - code_input_reset_count(model); - } - } - - break; - default: - break; - } -} - -/** - * @brief Handle input - * - * @param model - * @param key - */ - -size_t code_input_push(uint8_t* buffer, size_t length, InputKey key) { - buffer[length] = key; - length = CLAMP(length + 1, MAX_CODE_LEN, 0); - return length; -} - -/** - * @brief Handle D-pad keys - * - * @param model - * @param key - */ -static void code_input_handle_dpad(CodeInputModel* model, InputKey key) { - uint8_t at = model->current; - size_t new_length = code_input_push(model->local_buffer[at], model->input_length[at], key); - model->input_length[at] = new_length; -} - -/** - * @brief Draw callback - * - * @param canvas - * @param _model - */ -static void code_input_view_draw_callback(Canvas* canvas, void* _model) { - CodeInputModel* model = _model; - uint8_t y_offset = 0; - canvas_clear(canvas); - canvas_set_color(canvas, ColorBlack); - - if(model->header && strlen(model->header)) { - canvas_draw_str(canvas, 2, 9, model->header); - } else { - y_offset = 4; - } - - canvas_set_font(canvas, FontSecondary); - - switch(model->state) { - case CodeInputStateVerify: - code_input_draw_sequence( - canvas, - model->local_buffer[CodeInputFirst], - model->input_length[CodeInputFirst], - 6, - 30 + y_offset, - true); - break; - case CodeInputStateUpdate: - code_input_draw_sequence( - canvas, - model->local_buffer[CodeInputFirst], - model->input_length[CodeInputFirst], - 6, - 14 + y_offset, - !model->current); - code_input_draw_sequence( - canvas, - model->local_buffer[CodeInputSecond], - model->input_length[CodeInputSecond], - 6, - 44 + y_offset, - model->current); - - if(model->current) canvas_draw_str(canvas, 2, 39 + y_offset, "Repeat code"); - - break; - default: - break; - } -} - -/** - * @brief Input callback - * - * @param event - * @param context - * @return true - * @return false - */ -static bool code_input_view_input_callback(InputEvent* event, void* context) { - CodeInput* code_input = context; - furi_assert(code_input); - bool consumed = false; - - if(event->type == InputTypeShort || event->type == InputTypeRepeat) { - switch(event->key) { - case InputKeyBack: - with_view_model( - code_input->view, (CodeInputModel * model) { - consumed = code_input_handle_back(model); - return true; - }); - break; - - case InputKeyOk: - with_view_model( - code_input->view, (CodeInputModel * model) { - code_input_handle_ok(model); - return true; - }); - consumed = true; - break; - default: - - with_view_model( - code_input->view, (CodeInputModel * model) { - code_input_handle_dpad(model, event->key); - return true; - }); - consumed = true; - break; - } - } - - return consumed; -} - -/** - * @brief Reset all input-related data in model - * - * @param model CodeInputModel - */ -static void code_input_reset_model_input_data(CodeInputModel* model) { - model->current = 0; - model->input_length[CodeInputFirst] = 0; - model->input_length[CodeInputSecond] = 0; - model->ext_buffer = NULL; - model->ext_update = false; - model->state = 0; -} - -/** - * @brief Allocate and initialize code input. This code input is used to enter codes. - * - * @return CodeInput instance pointer - */ -CodeInput* code_input_alloc() { - CodeInput* code_input = furi_alloc(sizeof(CodeInput)); - code_input->view = view_alloc(); - view_set_context(code_input->view, code_input); - view_allocate_model(code_input->view, ViewModelTypeLocking, sizeof(CodeInputModel)); - view_set_draw_callback(code_input->view, code_input_view_draw_callback); - view_set_input_callback(code_input->view, code_input_view_input_callback); - - with_view_model( - code_input->view, (CodeInputModel * model) { - model->header = ""; - model->ok_callback = NULL; - model->fail_callback = NULL; - model->callback_context = NULL; - code_input_reset_model_input_data(model); - return true; - }); - - return code_input; -} - -/** - * @brief Deinitialize and free code input - * - * @param code_input Code input instance - */ -void code_input_free(CodeInput* code_input) { - furi_assert(code_input); - view_free(code_input->view); - free(code_input); -} - -/** - * @brief Get code input view - * - * @param code_input code input instance - * @return View instance that can be used for embedding - */ -View* code_input_get_view(CodeInput* code_input) { - furi_assert(code_input); - return code_input->view; -} - -/** - * @brief Set code input callbacks - * - * @param code_input code input instance - * @param ok_callback input callback fn - * @param fail_callback code match callback fn - * @param callback_context callback context - * @param buffer buffer - * @param buffer_length ptr to buffer length uint - * @param ext_update true to update buffer - */ -void code_input_set_result_callback( - CodeInput* code_input, - CodeInputOkCallback ok_callback, - CodeInputFailCallback fail_callback, - void* callback_context, - uint8_t* buffer, - uint8_t* buffer_length, - bool ext_update) { - with_view_model( - code_input->view, (CodeInputModel * model) { - code_input_reset_model_input_data(model); - model->ok_callback = ok_callback; - model->fail_callback = fail_callback; - model->callback_context = callback_context; - - model->ext_buffer = buffer; - model->ext_buffer_length = buffer_length; - model->state = (*buffer_length == 0) ? 1 : 0; - model->ext_update = ext_update; - - return true; - }); -} - -/** - * @brief Set code input header text - * - * @param code_input code input instance - * @param text text to be shown - */ -void code_input_set_header_text(CodeInput* code_input, const char* text) { - with_view_model( - code_input->view, (CodeInputModel * model) { - model->header = text; - return true; - }); -} diff --git a/applications/gui/modules/code_input.h b/applications/gui/modules/code_input.h deleted file mode 100644 index d6a43fc1..00000000 --- a/applications/gui/modules/code_input.h +++ /dev/null @@ -1,91 +0,0 @@ -/** - * @file code_input.h - * GUI: CodeInput keyboard view module API - */ - -#pragma once - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/** Code input anonymous structure */ -typedef struct CodeInput CodeInput; - -/** callback that is executed when entered code matches ext buffer */ -typedef void (*CodeInputOkCallback)(void* context); - -/** callback that is executed when entered code does not matches ext buffer */ -typedef void (*CodeInputFailCallback)(void* context); - -/** Allocate and initialize code input. This code input is used to enter codes. - * - * @return CodeInput instance pointer - */ -CodeInput* code_input_alloc(); - -/** Deinitialize and free code input - * - * @param code_input Code input instance - */ -void code_input_free(CodeInput* code_input); - -/** Get code input view - * - * @param code_input code input instance - * - * @return View instance that can be used for embedding - */ -View* code_input_get_view(CodeInput* code_input); - -/** Set code input result callback - * - * @param code_input code input instance - * @param ok_callback ok callback fn - * @param fail_callback fail callback fn - * @param callback_context callback context - * @param buffer buffer to use - * @param buffer_length buffer length - * @param update set true to update buffer - */ -void code_input_set_result_callback( - CodeInput* code_input, - CodeInputOkCallback ok_callback, - CodeInputFailCallback fail_callback, - void* callback_context, - uint8_t* buffer, - uint8_t* buffer_length, - bool update); - -/** Set code input header text - * - * @param code_input code input instance - * @param text text to be shown - */ -void code_input_set_header_text(CodeInput* code_input, const char* text); - -/** Compare two buffers - * - * @param in buffer to compare to source - * @param len_in length of input buffer - * @param src source buffer - * @param len_src length of insourceput buffer - * @return true if buffers match - */ - -bool code_input_compare(uint8_t* in, size_t len_in, uint8_t* src, size_t len_src); - -/** Push input into the end of array - * - * @param buffer buffer - * @param length length of buffer - * @param key input key - * @return new length of input buffer - */ -size_t code_input_push(uint8_t* buffer, size_t length, InputKey key); - -#ifdef __cplusplus -} -#endif \ No newline at end of file diff --git a/applications/loader/loader.c b/applications/loader/loader.c index 95beab45..b8f67a59 100644 --- a/applications/loader/loader.c +++ b/applications/loader/loader.c @@ -1,3 +1,4 @@ +#include "applications.h" #include #include "loader/loader.h" #include "loader_i.h" @@ -79,6 +80,12 @@ const FlipperApplication* loader_find_application_by_name(const char* name) { } } + for(size_t i = 0; i < FLIPPER_SETTINGS_APPS_COUNT; i++) { + if(strcmp(name, FLIPPER_SETTINGS_APPS[i].name) == 0) { + application = &FLIPPER_SETTINGS_APPS[i]; + } + } + if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug)) { for(size_t i = 0; i < FLIPPER_DEBUG_APPS_COUNT; i++) { if(strcmp(name, FLIPPER_DEBUG_APPS[i].name) == 0) { diff --git a/assets/compiled/assets_icons.c b/assets/compiled/assets_icons.c index 4a779743..f45b0719 100644 --- a/assets/compiled/assets_icons.c +++ b/assets/compiled/assets_icons.c @@ -205,9 +205,6 @@ const uint8_t *_I_DoorLocked_10x56[] = {_I_DoorLocked_10x56_0}; const uint8_t _I_DoorRight_70x55_0[] = {0x01,0x00,0x16,0x01,0x81,0xcc,0x01,0x0f,0x60,0x04,0x3f,0x00,0x10,0xf8,0x08,0x0c,0x02,0x05,0x01,0x84,0x02,0x06,0x26,0x0a,0x10,0x8a,0xcc,0xe0,0x1d,0x68,0xe0,0x18,0xab,0xd0,0x0b,0x18,0x10,0x46,0xe6,0x16,0x1e,0x18,0x10,0x46,0xe4,0x28,0x2c,0x98,0x14,0x68,0x00,0x21,0x1d,0x10,0x8c,0x40,0x02,0x0e,0x10,0xa1,0x08,0xc8,0x40,0x42,0x62,0x11,0x94,0x03,0xfd,0xff,0x00,0x0c,0xff,0x0c,0x08,0x28,0x60,0xe4,0xc0,0x85,0x00,0x83,0x00,0x87,0xf1,0x00,0x8c,0x02,0x0b,0x07,0x24,0x84,0xff,0x04,0xc7,0x80,0xa0,0xe4,0xa0,0x81,0x41,0x04,0x17,0x02,0x41,0x49,0x81,0x0e,0x10,0xb2,0xa0,0x82,0x0e,0x9f,0xfc,0x0a,0x62,0xf2,0xc0,0x03,0x92,0xf0,0x08,0x2d,0x78,0x20,0xff,0x02,0x01,0x08,0xae,0x60,0x64,0x38,0x0d,0xb0,0x8d,0x08,0x82,0x11,0x58,0xc4,0x13,0xc0,0x35,0x68,0x62,0x68,0x81,0x09,0x08,0x84,0x40,0x81,0x0d,0x18,0x69,0x10,0x47,0x44,0x66,0x5f,0x21,0xa9,0x29,0x94,0x10,0x2f,0x23,0x53,0x14,0x60,0x42,0x3c,0x08,0xfc,0x02,0x2c,0x62,0x23,0x58,0xd0,0x22,0x00,0x83,0x3e,0x98,0x44,0x43,0x46,0x22,0x30,0x89,0xce,0x01,0x0f,0x70,0x04,0x3f,0x81,0x8a,0x3c,0x21,0xaa,0x70,0x1a,0xe3,0x44,0x1a,0xa6,0x01,0xd2,0x38,0x90,0x8a,0x40,0x20,0xe5,0x96,0x80,0x43,0x81,0x06,0x6b,0x28,0x07,0xf3,0xfe,0x00,0x19,0xf9,0x34,0xc1,0x08,0x8f,0x20,0xf1,0x3e,0x16,0x00,0xa8,0x19,0x00,0x10,0x76,0x03,0xe2,0x3e,0x90,0x45,0x38,0x01,0x42,0x05,0x88,0x44,0x67,0x15,0x70,0x41,0x38,0x04,0x10,0x24,0x03,0x00,0x10,0x20,0x4a,0x46,0xe9,0x46,0xe1,0x04,0x50,0x66,0x40,0x85,0x19,0x98,0x00,0xc0,}; const uint8_t *_I_DoorRight_70x55[] = {_I_DoorRight_70x55_0}; -const uint8_t _I_LockPopup_100x49_0[] = {0x01,0x00,0x37,0x01,0xfc,0x7f,0xc0,0x13,0x01,0xfe,0x03,0x2a,0x07,0x06,0x12,0xd4,0x1a,0x06,0x0c,0xa8,0x60,0x33,0xe0,0x12,0x08,0x40,0x32,0x3f,0xd0,0x70,0x64,0xe0,0x20,0x31,0x8a,0x00,0x32,0x2c,0x10,0x0b,0x00,0x32,0x62,0x10,0x0c,0x06,0x00,0x19,0x00,0x82,0xc0,0x83,0x22,0x08,0x04,0x18,0x11,0x6a,0x01,0x25,0x02,0x84,0x83,0x1e,0x02,0x04,0x10,0xe1,0x03,0x1e,0x3c,0x0c,0x9c,0x1c,0x02,0x43,0x00,0x84,0x4f,0xc1,0x8f,0x80,0xaf,0x40,0x39,0x14,0x00,0x63,0xd0,0x36,0xf0,0x09,0xc6,0x00,0x18,0xd4,0x3a,0x06,0x9c,0x08,0x20,0xc9,0xdf,0xc0,0x20,0x7f,0x00,0x65,0x40,0x3f,0x80,0xc7,0xd0,0x10,0x06,0x01,0x7f,0x06,0x34,0x8e,0xa1,0x3d,0x80,0x70,0x0b,0x4f,0x23,0xd0,0x50,0xa0,0x1f,0x08,0x78,0x66,0x11,0xe3,0xfc,0x83,0x83,0x1e,0x40,0x0c,0x1f,0xfb,0xec,0x41,0x8c,0x03,0x1e,0x07,0x00,0x4d,0x10,0x0a,0x04,0xc0,0x9b,0x30,0x0c,0x1f,0xff,0xff,0x9f,0x06,0x3e,0x01,0x80,0x48,0xe7,0x99,0x83,0x0d,0x6a,0xe0,0xc4,0x90,0x03,0x1a,0x76,0x0c,0x38,0xe0,0x34,0x45,0x25,0x02,0x06,0x0d,0xe0,0x18,0x3c,0x08,0x19,0x40,0x78,0x00,0xc1,0x81,0xc3,0x27,0xf8,0x48,0x26,0x82,0x7d,0x00,0xfc,0x40,0xfc,0x10,0xfc,0x04,0xfc,0x18,0x30,0x28,0x7d,0x02,0x3f,0x00,0x98,0x41,0x38,0x31,0x08,0x25,0x0e,0x19,0x1f,0x81,0x42,0x70,0x11,0xa2,0x08,0xe2,0x30,0x72,0x08,0x76,0x0a,0x19,0x0f,0x85,0x42,0x60,0x11,0x51,0x78,0xc2,0x20,0x32,0x08,0x26,0x00,0x18,0x91,0x00,0x60,0x91,0x44,0x08,0x34,0x08,0x64,0x1f,0xe4,0x07,0x3f,0x84,0x0d,0x58,0x44,0x01,0x83,0xdc,0x60,0x43,0xe1,0x39,0xa9,0xd0,0x60,0x70,0x16,0x78,0xca,0x01,0x8f,0x83,0x3d,0x10,0x33,0x29,0x00,0xc7,0xa1,0x83,0x3f,0x10,0x0c,0x79,0x30,0x32,0xa0,0xdf,0xc7,0xa0,0x80,0x22,0x07,0xf8,0x06,0x54,0x04,}; -const uint8_t *_I_LockPopup_100x49[] = {_I_LockPopup_100x49_0}; - const uint8_t _I_PassportBottom_128x17_0[] = {0x01,0x00,0x5e,0x00,0x96,0x01,0x97,0xe1,0xff,0x00,0x2e,0x3e,0x68,0x0f,0x5a,0xc5,0x54,0x00,0xb9,0x50,0xfb,0x6a,0x35,0x40,0x05,0xcd,0x4e,0x03,0xfd,0x30,0x0f,0xf8,0x7f,0xa0,0x81,0xfe,0xf9,0x1b,0xfb,0xf3,0x01,0x47,0x66,0x02,0x1b,0x03,0x07,0xe7,0x02,0x0b,0x02,0x07,0xe5,0x82,0x0b,0xf2,0x1c,0xb0,0x01,0x67,0xf0,0x5f,0xd0,0x3f,0x23,0xf0,0x9b,0xc9,0xe5,0x80,0x03,0xd5,0xc0,0x00,0x86,0x01,0xf3,0xe6,0x1e,0x58,0x00,0x36,0xa8,0x06,0xac,0x04,0x30,0x6c,0x30,0xee,0x60,0x1f,0xe0,0x10,0xff,0x0d,0xfb,0x00,}; const uint8_t *_I_PassportBottom_128x17[] = {_I_PassportBottom_128x17_0}; @@ -447,6 +444,36 @@ const uint8_t *_I_Detailed_chip_17x13[] = {_I_Detailed_chip_17x13_0}; const uint8_t _I_Medium_chip_22x21_0[] = {0x01,0x00,0x35,0x00,0xfe,0x7f,0xe1,0xf0,0x28,0x04,0x43,0xf3,0xff,0x93,0xe1,0x6a,0x52,0x8e,0x2f,0xfe,0x51,0x25,0x80,0x4a,0x72,0xb6,0x79,0x55,0x76,0xc1,0x2e,0xaa,0xc0,0x25,0x51,0xdc,0x00,0x14,0x70,0x00,0x56,0xae,0x81,0x47,0x2b,0x7d,0x95,0x07,0x48,0x46,0x42,0x92,0x17,0x90,0xd4,0x87,0x64,}; const uint8_t *_I_Medium_chip_22x21[] = {_I_Medium_chip_22x21_0}; +const uint8_t _I_Pin_arrow_down_7x9_0[] = {0x00,0x1C,0x1C,0x1C,0x1C,0x1C,0x7F,0x3E,0x1C,0x08,}; +const uint8_t *_I_Pin_arrow_down_7x9[] = {_I_Pin_arrow_down_7x9_0}; + +const uint8_t _I_Pin_arrow_left_9x7_0[] = {0x00,0x08,0x00,0x0C,0x00,0xFE,0x01,0xFF,0x01,0xFE,0x01,0x0C,0x00,0x08,0x00,}; +const uint8_t *_I_Pin_arrow_left_9x7[] = {_I_Pin_arrow_left_9x7_0}; + +const uint8_t _I_Pin_arrow_right_9x7_0[] = {0x00,0x20,0x00,0x60,0x00,0xFF,0x00,0xFF,0x01,0xFF,0x00,0x60,0x00,0x20,0x00,}; +const uint8_t *_I_Pin_arrow_right_9x7[] = {_I_Pin_arrow_right_9x7_0}; + +const uint8_t _I_Pin_arrow_up7x9_0[] = {0x00,0x08,0x1C,0x3E,0x7F,0x1C,0x1C,0x1C,0x1C,0x1C,}; +const uint8_t *_I_Pin_arrow_up7x9[] = {_I_Pin_arrow_up7x9_0}; + +const uint8_t _I_Pin_attention_dpad_29x29_0[] = {0x01,0x00,0x56,0x00,0x80,0x7f,0x20,0xe0,0x31,0x81,0xc6,0x20,0x1c,0x08,0x05,0x82,0x01,0x20,0xa0,0x60,0x20,0x11,0x0f,0x04,0x02,0x03,0x08,0xf8,0x40,0x60,0x50,0x4f,0xc4,0x0e,0x09,0x04,0x05,0x8c,0x12,0x04,0x03,0x18,0x44,0x08,0x42,0x30,0x88,0x08,0x0c,0x62,0x14,0x18,0x05,0x02,0x21,0x61,0x14,0x8c,0x43,0xe3,0x01,0xf8,0x44,0x7f,0x20,0x31,0x89,0x81,0xcc,0x1e,0x61,0x73,0x0f,0x98,0x9c,0xc5,0xe6,0x37,0x31,0xf9,0x91,0xcc,0x9e,0x65,0x73,0x2f,0x99,0x9c,0xcd,0xe6,}; +const uint8_t *_I_Pin_attention_dpad_29x29[] = {_I_Pin_attention_dpad_29x29_0}; + +const uint8_t _I_Pin_back_arrow_10x8_0[] = {0x00,0x04,0x00,0x06,0x00,0xFF,0x00,0x06,0x01,0x04,0x02,0x00,0x02,0x00,0x01,0xF8,0x00,}; +const uint8_t *_I_Pin_back_arrow_10x8[] = {_I_Pin_back_arrow_10x8_0}; + +const uint8_t _I_Pin_back_full_40x8_0[] = {0x01,0x00,0x26,0x00,0x82,0x01,0x0e,0x0c,0x02,0x18,0x14,0x03,0xfe,0x04,0x38,0x37,0xc6,0xc3,0x32,0xf7,0x41,0x20,0x59,0x0a,0x54,0xa6,0x01,0xf2,0x88,0xde,0x80,0x83,0x01,0xc8,0x42,0xa5,0x3f,0x88,0x05,0x82,0x65,0x2e,}; +const uint8_t *_I_Pin_back_full_40x8[] = {_I_Pin_back_full_40x8_0}; + +const uint8_t _I_Pin_cell_13x13_0[] = {0x01,0x00,0x0a,0x00,0xff,0xc7,0xe0,0x31,0x00,0x0f,0x80,0x4c,0x2e,0x20,}; +const uint8_t *_I_Pin_cell_13x13[] = {_I_Pin_cell_13x13_0}; + +const uint8_t _I_Pin_pointer_5x3_0[] = {0x00,0x04,0x0E,0x1F,}; +const uint8_t *_I_Pin_pointer_5x3[] = {_I_Pin_pointer_5x3_0}; + +const uint8_t _I_Pin_star_7x7_0[] = {0x00,0x49,0x2A,0x1C,0x7F,0x1C,0x2A,0x49,}; +const uint8_t *_I_Pin_star_7x7[] = {_I_Pin_star_7x7_0}; + const uint8_t _I_passport_bad1_46x49_0[] = {0x01,0x00,0xd2,0x00,0xff,0x7f,0xc0,0x05,0x1f,0x02,0x1f,0xfe,0x7e,0x02,0x18,0x0f,0xe0,0x0a,0x57,0xff,0xf7,0x9c,0x0a,0x59,0xf8,0x0e,0x60,0x0a,0x56,0xf8,0x05,0x83,0xfc,0x05,0x18,0xbc,0x03,0x01,0xfd,0x02,0x8c,0x2c,0x5a,0x3f,0xa0,0x28,0xc1,0x40,0xa3,0xf4,0x02,0x8c,0x08,0x0a,0x77,0xf8,0x08,0x14,0x7d,0x13,0xfd,0xf9,0x14,0x80,0xab,0xd0,0x9f,0xd7,0xe0,0x10,0x60,0x2a,0x42,0x20,0x1a,0x09,0xfc,0xbe,0x01,0x10,0x02,0xa5,0x9c,0x0a,0x78,0x0e,0x74,0x04,0x0a,0x31,0x7a,0x06,0x7a,0x06,0x05,0x39,0xb0,0x44,0x80,0xa3,0x7e,0x02,0xa5,0xf0,0x0a,0x78,0x0a,0x00,0x14,0xf8,0x13,0xf0,0x29,0xc8,0x07,0x66,0x70,0x11,0xd8,0xea,0xa7,0xf1,0xb2,0x99,0x4c,0x00,0xa9,0xc0,0x9f,0x01,0x4e,0x01,0x3d,0x02,0x8c,0x38,0x0a,0x33,0xa8,0x6c,0x02,0x62,0x05,0x19,0xa0,0x14,0x78,0x00,0x51,0x94,0x01,0x46,0x01,0x03,0x02,0xa4,0x30,0x0a,0x2a,0x02,0x98,0x7c,0x25,0x60,0x52,0xe0,0x43,0xe5,0x80,0x51,0xc0,0x27,0x46,0x51,0x09,0x05,0x88,0xc0,0x66,0x80,0x52,0xfe,0x40,0x27,0x60,0x52,0xf8,0x7f,0xe7,0xa0,0x52,0xe0,0x5f,0xe7,0xc0,0x52,0x80,0x6f,0xe7,0xe0,0x53,0xde,0x01,0x50,0xe2,0x20,0x5f,0x02,0xbf,0xfb,0xfe,0x00,0x28,0xf8,}; const uint8_t *_I_passport_bad1_46x49[] = {_I_passport_bad1_46x49_0}; @@ -685,7 +712,6 @@ const Icon I_Back3_45x8 = {.width=45,.height=8,.frame_count=1,.frame_rate=0,.fra const Icon I_DoorLeft_70x55 = {.width=70,.height=55,.frame_count=1,.frame_rate=0,.frames=_I_DoorLeft_70x55}; const Icon I_DoorLocked_10x56 = {.width=10,.height=56,.frame_count=1,.frame_rate=0,.frames=_I_DoorLocked_10x56}; const Icon I_DoorRight_70x55 = {.width=70,.height=55,.frame_count=1,.frame_rate=0,.frames=_I_DoorRight_70x55}; -const Icon I_LockPopup_100x49 = {.width=100,.height=49,.frame_count=1,.frame_rate=0,.frames=_I_LockPopup_100x49}; const Icon I_PassportBottom_128x17 = {.width=128,.height=17,.frame_count=1,.frame_rate=0,.frames=_I_PassportBottom_128x17}; const Icon I_PassportLeft_6x47 = {.width=6,.height=47,.frame_count=1,.frame_rate=0,.frames=_I_PassportLeft_6x47}; const Icon I_WarningDolphin_45x42 = {.width=45,.height=42,.frame_count=1,.frame_rate=0,.frames=_I_WarningDolphin_45x42}; @@ -733,6 +759,16 @@ const Icon A_U2F_14 = {.width=14,.height=14,.frame_count=4,.frame_rate=3,.frames const Icon A_iButton_14 = {.width=14,.height=14,.frame_count=7,.frame_rate=3,.frames=_A_iButton_14}; const Icon I_Detailed_chip_17x13 = {.width=17,.height=13,.frame_count=1,.frame_rate=0,.frames=_I_Detailed_chip_17x13}; const Icon I_Medium_chip_22x21 = {.width=22,.height=21,.frame_count=1,.frame_rate=0,.frames=_I_Medium_chip_22x21}; +const Icon I_Pin_arrow_down_7x9 = {.width=7,.height=9,.frame_count=1,.frame_rate=0,.frames=_I_Pin_arrow_down_7x9}; +const Icon I_Pin_arrow_left_9x7 = {.width=9,.height=7,.frame_count=1,.frame_rate=0,.frames=_I_Pin_arrow_left_9x7}; +const Icon I_Pin_arrow_right_9x7 = {.width=9,.height=7,.frame_count=1,.frame_rate=0,.frames=_I_Pin_arrow_right_9x7}; +const Icon I_Pin_arrow_up7x9 = {.width=7,.height=9,.frame_count=1,.frame_rate=0,.frames=_I_Pin_arrow_up7x9}; +const Icon I_Pin_attention_dpad_29x29 = {.width=29,.height=29,.frame_count=1,.frame_rate=0,.frames=_I_Pin_attention_dpad_29x29}; +const Icon I_Pin_back_arrow_10x8 = {.width=10,.height=8,.frame_count=1,.frame_rate=0,.frames=_I_Pin_back_arrow_10x8}; +const Icon I_Pin_back_full_40x8 = {.width=40,.height=8,.frame_count=1,.frame_rate=0,.frames=_I_Pin_back_full_40x8}; +const Icon I_Pin_cell_13x13 = {.width=13,.height=13,.frame_count=1,.frame_rate=0,.frames=_I_Pin_cell_13x13}; +const Icon I_Pin_pointer_5x3 = {.width=5,.height=3,.frame_count=1,.frame_rate=0,.frames=_I_Pin_pointer_5x3}; +const Icon I_Pin_star_7x7 = {.width=7,.height=7,.frame_count=1,.frame_rate=0,.frames=_I_Pin_star_7x7}; const Icon I_passport_bad1_46x49 = {.width=46,.height=49,.frame_count=1,.frame_rate=0,.frames=_I_passport_bad1_46x49}; const Icon I_passport_bad2_46x49 = {.width=46,.height=49,.frame_count=1,.frame_rate=0,.frames=_I_passport_bad2_46x49}; const Icon I_passport_bad3_46x49 = {.width=46,.height=49,.frame_count=1,.frame_rate=0,.frames=_I_passport_bad3_46x49}; diff --git a/assets/compiled/assets_icons.h b/assets/compiled/assets_icons.h index 8f53bc36..26e26bef 100644 --- a/assets/compiled/assets_icons.h +++ b/assets/compiled/assets_icons.h @@ -62,7 +62,6 @@ extern const Icon I_Back3_45x8; extern const Icon I_DoorLeft_70x55; extern const Icon I_DoorLocked_10x56; extern const Icon I_DoorRight_70x55; -extern const Icon I_LockPopup_100x49; extern const Icon I_PassportBottom_128x17; extern const Icon I_PassportLeft_6x47; extern const Icon I_WarningDolphin_45x42; @@ -110,6 +109,16 @@ extern const Icon A_U2F_14; extern const Icon A_iButton_14; extern const Icon I_Detailed_chip_17x13; extern const Icon I_Medium_chip_22x21; +extern const Icon I_Pin_arrow_down_7x9; +extern const Icon I_Pin_arrow_left_9x7; +extern const Icon I_Pin_arrow_right_9x7; +extern const Icon I_Pin_arrow_up7x9; +extern const Icon I_Pin_attention_dpad_29x29; +extern const Icon I_Pin_back_arrow_10x8; +extern const Icon I_Pin_back_full_40x8; +extern const Icon I_Pin_cell_13x13; +extern const Icon I_Pin_pointer_5x3; +extern const Icon I_Pin_star_7x7; extern const Icon I_passport_bad1_46x49; extern const Icon I_passport_bad2_46x49; extern const Icon I_passport_bad3_46x49; diff --git a/assets/icons/Interface/LockPopup_100x49.png b/assets/icons/Interface/LockPopup_100x49.png deleted file mode 100644 index f30d88a9..00000000 Binary files a/assets/icons/Interface/LockPopup_100x49.png and /dev/null differ diff --git a/assets/icons/PIN/Pin_arrow_down_7x9.png b/assets/icons/PIN/Pin_arrow_down_7x9.png new file mode 100644 index 00000000..9687397a Binary files /dev/null and b/assets/icons/PIN/Pin_arrow_down_7x9.png differ diff --git a/assets/icons/PIN/Pin_arrow_left_9x7.png b/assets/icons/PIN/Pin_arrow_left_9x7.png new file mode 100644 index 00000000..fb4ded78 Binary files /dev/null and b/assets/icons/PIN/Pin_arrow_left_9x7.png differ diff --git a/assets/icons/PIN/Pin_arrow_right_9x7.png b/assets/icons/PIN/Pin_arrow_right_9x7.png new file mode 100644 index 00000000..97648d17 Binary files /dev/null and b/assets/icons/PIN/Pin_arrow_right_9x7.png differ diff --git a/assets/icons/PIN/Pin_arrow_up7x9.png b/assets/icons/PIN/Pin_arrow_up7x9.png new file mode 100644 index 00000000..a91a6fd5 Binary files /dev/null and b/assets/icons/PIN/Pin_arrow_up7x9.png differ diff --git a/assets/icons/PIN/Pin_attention_dpad_29x29.png b/assets/icons/PIN/Pin_attention_dpad_29x29.png new file mode 100644 index 00000000..984db9cc Binary files /dev/null and b/assets/icons/PIN/Pin_attention_dpad_29x29.png differ diff --git a/assets/icons/PIN/Pin_back_arrow_10x8.png b/assets/icons/PIN/Pin_back_arrow_10x8.png new file mode 100644 index 00000000..3bafabd1 Binary files /dev/null and b/assets/icons/PIN/Pin_back_arrow_10x8.png differ diff --git a/assets/icons/PIN/Pin_back_full_40x8.png b/assets/icons/PIN/Pin_back_full_40x8.png new file mode 100644 index 00000000..cd130151 Binary files /dev/null and b/assets/icons/PIN/Pin_back_full_40x8.png differ diff --git a/assets/icons/PIN/Pin_cell_13x13.png b/assets/icons/PIN/Pin_cell_13x13.png new file mode 100644 index 00000000..1b1ff0c2 Binary files /dev/null and b/assets/icons/PIN/Pin_cell_13x13.png differ diff --git a/assets/icons/PIN/Pin_pointer_5x3.png b/assets/icons/PIN/Pin_pointer_5x3.png new file mode 100644 index 00000000..edf3d41b Binary files /dev/null and b/assets/icons/PIN/Pin_pointer_5x3.png differ diff --git a/assets/icons/PIN/Pin_star_7x7.png b/assets/icons/PIN/Pin_star_7x7.png new file mode 100644 index 00000000..42fdea86 Binary files /dev/null and b/assets/icons/PIN/Pin_star_7x7.png differ diff --git a/firmware/targets/f6/furi_hal/furi_hal_power.c b/firmware/targets/f6/furi_hal/furi_hal_power.c index a211b8c5..e34ba46e 100644 --- a/firmware/targets/f6/furi_hal/furi_hal_power.c +++ b/firmware/targets/f6/furi_hal/furi_hal_power.c @@ -89,17 +89,17 @@ uint16_t furi_hal_power_insomnia_level() { } void furi_hal_power_insomnia_enter() { - vTaskSuspendAll(); + FURI_CRITICAL_ENTER(); furi_assert(furi_hal_power.insomnia < UINT8_MAX); furi_hal_power.insomnia++; - xTaskResumeAll(); + FURI_CRITICAL_EXIT(); } void furi_hal_power_insomnia_exit() { - vTaskSuspendAll(); + FURI_CRITICAL_ENTER(); furi_assert(furi_hal_power.insomnia > 0); furi_hal_power.insomnia--; - xTaskResumeAll(); + FURI_CRITICAL_EXIT(); } bool furi_hal_power_sleep_available() { diff --git a/firmware/targets/f6/furi_hal/furi_hal_rtc.c b/firmware/targets/f6/furi_hal/furi_hal_rtc.c index 4d45c748..1f262692 100644 --- a/firmware/targets/f6/furi_hal/furi_hal_rtc.c +++ b/firmware/targets/f6/furi_hal/furi_hal_rtc.c @@ -163,3 +163,11 @@ void furi_hal_rtc_set_fault_data(uint32_t value) { uint32_t furi_hal_rtc_get_fault_data() { return furi_hal_rtc_get_register(FuriHalRtcRegisterFaultData); } + +void furi_hal_rtc_set_pin_fails(uint32_t value) { + furi_hal_rtc_set_register(FuriHalRtcRegisterPinFails, value); +} + +uint32_t furi_hal_rtc_get_pin_fails() { + return furi_hal_rtc_get_register(FuriHalRtcRegisterPinFails); +} diff --git a/firmware/targets/f6/furi_hal/furi_hal_usb.c b/firmware/targets/f6/furi_hal/furi_hal_usb.c index 881081b6..7ca8ffdf 100644 --- a/firmware/targets/f6/furi_hal/furi_hal_usb.c +++ b/firmware/targets/f6/furi_hal/furi_hal_usb.c @@ -1,6 +1,7 @@ #include "furi_hal_version.h" #include "furi_hal_usb_i.h" #include "furi_hal_usb.h" +#include #include #include "usb.h" @@ -189,6 +190,8 @@ static void susp_evt(usbd_device* dev, uint8_t event, uint8_t ep) { if((usb_if_cur != NULL) && (usb_config.connected == true)) { usb_config.connected = false; usb_if_cur->suspend(&udev); + + furi_hal_power_insomnia_exit(); } if(callback != NULL) { callback(FuriHalUsbStateEventSuspend, cb_ctx); @@ -199,6 +202,8 @@ static void wkup_evt(usbd_device* dev, uint8_t event, uint8_t ep) { if((usb_if_cur != NULL) && (usb_config.connected == false)) { usb_config.connected = true; usb_if_cur->wakeup(&udev); + + furi_hal_power_insomnia_enter(); } if(callback != NULL) { callback(FuriHalUsbStateEventWakeup, cb_ctx); diff --git a/firmware/targets/f7/furi_hal/furi_hal_power.c b/firmware/targets/f7/furi_hal/furi_hal_power.c index a211b8c5..e34ba46e 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_power.c +++ b/firmware/targets/f7/furi_hal/furi_hal_power.c @@ -89,17 +89,17 @@ uint16_t furi_hal_power_insomnia_level() { } void furi_hal_power_insomnia_enter() { - vTaskSuspendAll(); + FURI_CRITICAL_ENTER(); furi_assert(furi_hal_power.insomnia < UINT8_MAX); furi_hal_power.insomnia++; - xTaskResumeAll(); + FURI_CRITICAL_EXIT(); } void furi_hal_power_insomnia_exit() { - vTaskSuspendAll(); + FURI_CRITICAL_ENTER(); furi_assert(furi_hal_power.insomnia > 0); furi_hal_power.insomnia--; - xTaskResumeAll(); + FURI_CRITICAL_EXIT(); } bool furi_hal_power_sleep_available() { diff --git a/firmware/targets/f7/furi_hal/furi_hal_rtc.c b/firmware/targets/f7/furi_hal/furi_hal_rtc.c index 4d45c748..1f262692 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_rtc.c +++ b/firmware/targets/f7/furi_hal/furi_hal_rtc.c @@ -163,3 +163,11 @@ void furi_hal_rtc_set_fault_data(uint32_t value) { uint32_t furi_hal_rtc_get_fault_data() { return furi_hal_rtc_get_register(FuriHalRtcRegisterFaultData); } + +void furi_hal_rtc_set_pin_fails(uint32_t value) { + furi_hal_rtc_set_register(FuriHalRtcRegisterPinFails, value); +} + +uint32_t furi_hal_rtc_get_pin_fails() { + return furi_hal_rtc_get_register(FuriHalRtcRegisterPinFails); +} diff --git a/firmware/targets/f7/furi_hal/furi_hal_usb.c b/firmware/targets/f7/furi_hal/furi_hal_usb.c index 881081b6..7ca8ffdf 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_usb.c +++ b/firmware/targets/f7/furi_hal/furi_hal_usb.c @@ -1,6 +1,7 @@ #include "furi_hal_version.h" #include "furi_hal_usb_i.h" #include "furi_hal_usb.h" +#include #include #include "usb.h" @@ -189,6 +190,8 @@ static void susp_evt(usbd_device* dev, uint8_t event, uint8_t ep) { if((usb_if_cur != NULL) && (usb_config.connected == true)) { usb_config.connected = false; usb_if_cur->suspend(&udev); + + furi_hal_power_insomnia_exit(); } if(callback != NULL) { callback(FuriHalUsbStateEventSuspend, cb_ctx); @@ -199,6 +202,8 @@ static void wkup_evt(usbd_device* dev, uint8_t event, uint8_t ep) { if((usb_if_cur != NULL) && (usb_config.connected == false)) { usb_config.connected = true; usb_if_cur->wakeup(&udev); + + furi_hal_power_insomnia_enter(); } if(callback != NULL) { callback(FuriHalUsbStateEventWakeup, cb_ctx); diff --git a/firmware/targets/furi_hal_include/furi_hal_rtc.h b/firmware/targets/furi_hal_include/furi_hal_rtc.h index 8e79c95a..ee8eb1bb 100644 --- a/firmware/targets/furi_hal_include/furi_hal_rtc.h +++ b/firmware/targets/furi_hal_include/furi_hal_rtc.h @@ -38,6 +38,7 @@ typedef enum { FuriHalRtcRegisterSystemVersion, FuriHalRtcRegisterLfsFingerprint, FuriHalRtcRegisterFaultData, + FuriHalRtcRegisterPinFails, } FuriHalRtcRegister; /** Initialize RTC subsystem */ @@ -67,6 +68,10 @@ void furi_hal_rtc_set_fault_data(uint32_t value); uint32_t furi_hal_rtc_get_fault_data(); +void furi_hal_rtc_set_pin_fails(uint32_t value); + +uint32_t furi_hal_rtc_get_pin_fails(); + #ifdef __cplusplus } #endif