Merge remote-tracking branch 'ofw/dev' into mntm-dev

This commit is contained in:
Willy-JL
2024-08-05 01:50:20 +02:00
109 changed files with 1115 additions and 1860 deletions

View File

@@ -3,18 +3,24 @@
#include <furi.h>
#include <input/input.h>
typedef struct Desktop Desktop;
#include "desktop_settings.h"
#define RECORD_DESKTOP "desktop"
bool desktop_api_is_locked(Desktop* instance);
void desktop_api_unlock(Desktop* instance);
typedef struct Desktop Desktop;
typedef struct {
bool locked;
} DesktopStatus;
bool desktop_api_is_locked(Desktop* instance);
void desktop_api_unlock(Desktop* instance);
FuriPubSub* desktop_api_get_status_pubsub(Desktop* instance);
void desktop_api_get_settings(Desktop* instance, DesktopSettings* settings);
void desktop_api_set_settings(Desktop* instance, const DesktopSettings* settings);
void desktop_run_keybind(Desktop* instance, InputType _type, InputKey _key);

View File

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

View File

@@ -1,67 +0,0 @@
#include "pin.h"
#include <notification/notification.h>
#include <notification/notification_messages.h>
#include <stddef.h>
#include <furi.h>
#include <furi_hal.h>
#include <gui/gui.h>
static const NotificationSequence sequence_pin_fail = {
&message_display_backlight_on,
&message_red_255,
&message_vibro_on,
&message_delay_100,
&message_vibro_off,
&message_red_0,
&message_delay_250,
&message_red_255,
&message_vibro_on,
&message_delay_100,
&message_vibro_off,
&message_red_0,
NULL,
};
void desktop_pin_lock_error_notify(void) {
NotificationApp* notification = furi_record_open(RECORD_NOTIFICATION);
notification_message(notification, &sequence_pin_fail);
furi_record_close(RECORD_NOTIFICATION);
}
uint32_t desktop_pin_lock_get_fail_timeout(void) {
uint32_t pin_fails = furi_hal_rtc_get_pin_fails();
if(pin_fails < 3) {
return 0;
}
// Use for loop to avoid including pow() function (4kb of dfu flash)
uint32_t mult = 1;
for(size_t i = 0; i < pin_fails - 3; i++) {
mult *= 2;
}
return 30 * mult;
}
bool desktop_pin_compare(const PinCode* pin_code1, const PinCode* pin_code2) {
furi_assert(pin_code1);
furi_assert(pin_code2);
bool result = false;
if(pin_code1->length == pin_code2->length) {
result = !memcmp(pin_code1->data, pin_code2->data, pin_code1->length);
}
return result;
}
bool desktop_pin_is_valid(const PinCode* pin_code) {
bool ok = pin_code->length >= MIN_PIN_SIZE && pin_code->length <= MAX_PIN_SIZE;
for(size_t i = 0; ok && i < pin_code->length; i++) {
ok = ok && (pin_code->data[i] == InputKeyUp || pin_code->data[i] == InputKeyDown ||
pin_code->data[i] == InputKeyRight || pin_code->data[i] == InputKeyLeft);
}
return ok;
}

View File

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

View File

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

View File

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

View File

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

View File

@@ -59,17 +59,15 @@ bool desktop_scene_lock_menu_on_event(void* context, SceneManagerEvent event) {
if(event.type == SceneManagerEventTypeTick) {
int check_pin_changed =
scene_manager_get_scene_state(desktop->scene_manager, DesktopSceneLockMenu);
if(check_pin_changed) {
if(desktop_pin_is_valid(&desktop->settings.pin_code)) {
desktop_lock_menu_set_pin_state(desktop->lock_menu, true);
scene_manager_set_scene_state(desktop->scene_manager, DesktopSceneLockMenu, 0);
desktop_lock(desktop, true);
if(check_pin_changed == 2) {
Power* power = furi_record_open(RECORD_POWER);
furi_delay_ms(500);
power_off(power);
furi_record_close(RECORD_POWER);
}
if(check_pin_changed && desktop_pin_code_is_set()) {
desktop_lock_menu_set_pin_state(desktop->lock_menu, true);
scene_manager_set_scene_state(desktop->scene_manager, DesktopSceneLockMenu, 0);
desktop_lock(desktop, true);
if(check_pin_changed == 2) {
Power* power = furi_record_open(RECORD_POWER);
furi_delay_ms(500);
power_off(power);
furi_record_close(RECORD_POWER);
}
}
} else if(event.type == SceneManagerEventTypeCustom) {

View File

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

View File

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

View File

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

View File

@@ -46,10 +46,7 @@ bool desktop_scene_slideshow_on_event(void* context, SceneManagerEvent event) {
}
void desktop_scene_slideshow_on_exit(void* context) {
Desktop* desktop = (Desktop*)context;
Desktop* desktop = context;
gui_set_hide_statusbar(desktop->gui, false);
Storage* storage = furi_record_open(RECORD_STORAGE);
storage_common_remove(storage, SLIDESHOW_FS_PATH);
furi_record_close(RECORD_STORAGE);
storage_common_remove(desktop->storage, SLIDESHOW_FS_PATH);
}

View File

@@ -56,6 +56,8 @@ typedef enum {
DesktopGlobalAfterAppFinished,
DesktopGlobalAutoLock,
DesktopGlobalApiUnlock,
DesktopGlobalSaveSettings,
DesktopGlobalReloadSettings,
DesktopMainEventLockKeypad,
DesktopLockedEventOpenPowerOff,

View File

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

View File

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