diff --git a/applications/accessor/helpers/wiegand.cpp b/applications/accessor/helpers/wiegand.cpp index 0ab43f2d..3b2fcf96 100644 --- a/applications/accessor/helpers/wiegand.cpp +++ b/applications/accessor/helpers/wiegand.cpp @@ -31,9 +31,9 @@ int WIEGAND::getWiegandType() { bool WIEGAND::available() { bool ret; - __disable_irq(); + FURI_CRITICAL_ENTER(); ret = DoWiegandConversion(); - __enable_irq(); + FURI_CRITICAL_EXIT(); return ret; } @@ -221,4 +221,4 @@ bool WIEGAND::DoWiegandConversion() { } } else return false; -} \ No newline at end of file +} diff --git a/applications/accessor/scene/accessor_scene_start.cpp b/applications/accessor/scene/accessor_scene_start.cpp index 5f49666f..a82fc275 100644 --- a/applications/accessor/scene/accessor_scene_start.cpp +++ b/applications/accessor/scene/accessor_scene_start.cpp @@ -37,7 +37,7 @@ bool AccessorSceneStart::on_event(AccessorApp* app, AccessorEvent* event) { data[i] = wiegand->getCodeHigh() >> ((i - 4) * 8); } } else { - __disable_irq(); + FURI_CRITICAL_ENTER(); if(onewire->reset()) { type = 255; onewire->write(0x33); @@ -49,7 +49,7 @@ bool AccessorSceneStart::on_event(AccessorApp* app, AccessorEvent* event) { data[i] = data[i + 1]; } } - __enable_irq(); + FURI_CRITICAL_EXIT(); } if(type > 0) { @@ -85,4 +85,4 @@ void AccessorSceneStart::on_exit(AccessorApp* app) { Popup* popup = app->get_view_manager()->get_popup(); popup_set_header(popup, NULL, 0, 0, AlignCenter, AlignBottom); popup_set_text(popup, NULL, 0, 0, AlignCenter, AlignTop); -} \ No newline at end of file +} diff --git a/applications/archive/archive.c b/applications/archive/archive.c index 8b4918a5..c2fe4c6d 100644 --- a/applications/archive/archive.c +++ b/applications/archive/archive.c @@ -39,6 +39,10 @@ ArchiveApp* archive_alloc() { view_dispatcher_add_view( archive->view_dispatcher, ArchiveViewTextInput, text_input_get_view(archive->text_input)); + archive->widget = widget_alloc(); + view_dispatcher_add_view( + archive->view_dispatcher, ArchiveViewWidget, widget_get_view(archive->widget)); + return archive; } @@ -47,6 +51,8 @@ void archive_free(ArchiveApp* archive) { view_dispatcher_remove_view(archive->view_dispatcher, ArchiveViewBrowser); view_dispatcher_remove_view(archive->view_dispatcher, ArchiveViewTextInput); + view_dispatcher_remove_view(archive->view_dispatcher, ArchiveViewWidget); + widget_free(archive->widget); view_dispatcher_free(archive->view_dispatcher); scene_manager_free(archive->scene_manager); browser_free(archive->browser); diff --git a/applications/archive/archive_i.h b/applications/archive/archive_i.h index b450bb9c..c11a1803 100644 --- a/applications/archive/archive_i.h +++ b/applications/archive/archive_i.h @@ -7,6 +7,7 @@ #include #include #include +#include #include #include "views/archive_browser_view.h" @@ -15,6 +16,7 @@ typedef enum { ArchiveViewBrowser, ArchiveViewTextInput, + ArchiveViewWidget, ArchiveViewTotal, } ArchiveViewEnum; @@ -24,6 +26,7 @@ struct ArchiveApp { SceneManager* scene_manager; ArchiveBrowserView* browser; TextInput* text_input; + Widget* widget; char text_store[MAX_NAME_LEN]; char file_extension[MAX_EXT_LEN + 1]; }; diff --git a/applications/archive/helpers/archive_apps.c b/applications/archive/helpers/archive_apps.c new file mode 100644 index 00000000..9293d225 --- /dev/null +++ b/applications/archive/helpers/archive_apps.c @@ -0,0 +1,74 @@ +#include "archive_files.h" +#include "archive_apps.h" +#include "archive_browser.h" + +static const char* known_apps[] = { + [ArchiveAppTypeU2f] = "u2f", +}; + +ArchiveAppTypeEnum archive_get_app_type(const char* path) { + for(size_t i = 0; i < SIZEOF_ARRAY(known_apps); i++) { + if(strncmp(path, known_apps[i], strlen(known_apps[i])) != STRING_FAILURE) { + return i; + } + } + return ArchiveAppTypeUnknown; +} + +bool archive_app_is_available(void* context, const char* path) { + furi_assert(path); + + ArchiveAppTypeEnum app = archive_get_app_type(path); + + if(app == ArchiveAppTypeU2f) { + FileWorker* file_worker = file_worker_alloc(true); + bool file_exists = false; + file_worker_is_file_exist(file_worker, "/any/u2f/key.u2f", &file_exists); + if(file_exists) { + file_worker_is_file_exist(file_worker, "/any/u2f/cnt.u2f", &file_exists); + } + file_worker_free(file_worker); + return file_exists; + } else { + return false; + } +} + +bool archive_app_read_dir(void* context, const char* path) { + furi_assert(context); + furi_assert(path); + ArchiveBrowserView* browser = context; + + ArchiveAppTypeEnum app = archive_get_app_type(path); + + if(app == ArchiveAppTypeU2f) { + archive_add_app_item(browser, "/app:u2f/U2F Token"); + return true; + } else { + return false; + } +} + +void archive_app_delete_file(void* context, const char* path) { + furi_assert(context); + furi_assert(path); + ArchiveBrowserView* browser = context; + + ArchiveAppTypeEnum app = archive_get_app_type(path); + bool res = false; + + if(app == ArchiveAppTypeU2f) { + FileWorker* file_worker = file_worker_alloc(true); + res = file_worker_remove(file_worker, "/any/u2f/key.u2f"); + res |= file_worker_remove(file_worker, "/any/u2f/cnt.u2f"); + file_worker_free(file_worker); + + if(archive_is_favorite("/app:u2f/U2F Token")) { + archive_favorites_delete("/app:u2f/U2F Token"); + } + } + + if(res) { + archive_file_array_rm_selected(browser); + } +} diff --git a/applications/archive/helpers/archive_apps.h b/applications/archive/helpers/archive_apps.h new file mode 100644 index 00000000..5abc27a5 --- /dev/null +++ b/applications/archive/helpers/archive_apps.h @@ -0,0 +1,21 @@ +#pragma once + +typedef enum { + ArchiveAppTypeU2f, + ArchiveAppTypeUnknown, + ArchiveAppsTotal, +} ArchiveAppTypeEnum; + +static const ArchiveFileTypeEnum app_file_types[] = { + [ArchiveAppTypeU2f] = ArchiveFileTypeU2f, + [ArchiveAppTypeUnknown] = ArchiveFileTypeUnknown, +}; + +static inline const ArchiveFileTypeEnum archive_get_app_filetype(ArchiveAppTypeEnum app) { + return app_file_types[app]; +} + +ArchiveAppTypeEnum archive_get_app_type(const char* path); +bool archive_app_is_available(void* context, const char* path); +bool archive_app_read_dir(void* context, const char* path); +void archive_app_delete_file(void* context, const char* path); diff --git a/applications/archive/helpers/archive_browser.c b/applications/archive/helpers/archive_browser.c index eb316c1e..c1e9cacb 100644 --- a/applications/archive/helpers/archive_browser.c +++ b/applications/archive/helpers/archive_browser.c @@ -1,5 +1,7 @@ +#include "archive_files.h" +#include "archive_apps.h" #include "archive_browser.h" -#include "math.h" +#include void archive_update_offset(ArchiveBrowserView* browser) { furi_assert(browser); @@ -177,24 +179,53 @@ void archive_set_last_tab(ArchiveBrowserView* browser, ArchiveTabEnum tab) { }); } -void archive_add_item(ArchiveBrowserView* browser, FileInfo* file_info, const char* name) { +void archive_add_app_item(ArchiveBrowserView* browser, const char* name) { + furi_assert(browser); + furi_assert(name); + + ArchiveFile_t item; + + string_t full_name; + + string_init_set(full_name, browser->path); + string_cat_printf(full_name, "/%s", name); + + char* app_name = strchr(string_get_cstr(full_name), ':'); + if(app_name == NULL) { + string_clear(full_name); + return; + } + + ArchiveFile_t_init(&item); + string_init_set_str(item.name, name); + set_file_type(&item, NULL, app_name + 1, true); + + with_view_model( + browser->view, (ArchiveBrowserViewModel * model) { + files_array_push_back(model->files, item); + return false; + }); + ArchiveFile_t_clear(&item); + string_clear(full_name); +} + +void archive_add_file_item(ArchiveBrowserView* browser, FileInfo* file_info, const char* name) { furi_assert(browser); furi_assert(file_info); furi_assert(name); ArchiveFile_t item; - if(filter_by_extension(file_info, get_tab_ext(archive_get_tab(browser)), name)) { + if(filter_by_extension(file_info, archive_get_tab_ext(archive_get_tab(browser)), name)) { ArchiveFile_t_init(&item); string_init_set_str(item.name, name); - set_file_type(&item, file_info); + set_file_type(&item, file_info, archive_get_path(browser), false); with_view_model( browser->view, (ArchiveBrowserViewModel * model) { files_array_push_back(model->files, item); return false; }); - ArchiveFile_t_clear(&item); } } @@ -208,8 +239,7 @@ void archive_show_file_menu(ArchiveBrowserView* browser, bool show) { if(show) { ArchiveFile_t* selected = files_array_get(model->files, model->idx); - selected->fav = archive_is_favorite( - "%s/%s", string_get_cstr(browser->path), string_get_cstr(selected->name)); + selected->fav = archive_is_favorite("%s", string_get_cstr(selected->name)); } return true; @@ -245,12 +275,18 @@ void archive_switch_tab(ArchiveBrowserView* browser, InputKey key) { archive_set_tab(browser, tab); - if((tab != ArchiveTabFavorites && - !archive_dir_empty(browser, archive_get_default_path(tab))) || - (tab == ArchiveTabFavorites && !archive_favorites_count(browser))) { - if(tab != ArchiveTabBrowser) { - archive_switch_tab(browser, key); - } + const char* path = archive_get_default_path(tab); + bool tab_empty = true; + if(tab == ArchiveTabFavorites) { + if(archive_favorites_count(browser) > 0) tab_empty = false; + } else if(strncmp(path, "/app:", 5) == 0) { + if(archive_app_is_available(browser, path)) tab_empty = false; + } else { + if(archive_dir_not_empty(browser, archive_get_default_path(tab))) tab_empty = false; + } + + if((tab_empty) && (tab != ArchiveTabBrowser)) { + archive_switch_tab(browser, key); } else { with_view_model( browser->view, (ArchiveBrowserViewModel * model) { @@ -277,8 +313,7 @@ void archive_enter_dir(ArchiveBrowserView* browser, string_t name) { return false; }); - string_cat(browser->path, "/"); - string_cat(browser->path, name); + string_set(browser->path, name); archive_switch_dir(browser, string_get_cstr(browser->path)); } diff --git a/applications/archive/helpers/archive_browser.h b/applications/archive/helpers/archive_browser.h index 44bce914..6486967f 100644 --- a/applications/archive/helpers/archive_browser.h +++ b/applications/archive/helpers/archive_browser.h @@ -11,6 +11,8 @@ static const char* tab_default_paths[] = { [ArchiveTabSubGhz] = "/any/subghz", [ArchiveTabLFRFID] = "/any/lfrfid", [ArchiveTabIrda] = "/any/irda", + [ArchiveTabBadUsb] = "/any/badusb", + [ArchiveTabU2f] = "/app:u2f", [ArchiveTabBrowser] = "/any", }; @@ -20,30 +22,37 @@ static const char* known_ext[] = { [ArchiveFileTypeSubGhz] = ".sub", [ArchiveFileTypeLFRFID] = ".rfid", [ArchiveFileTypeIrda] = ".ir", + [ArchiveFileTypeBadUsb] = ".txt", + [ArchiveFileTypeU2f] = "?", + [ArchiveFileTypeFolder] = "?", + [ArchiveFileTypeUnknown] = "*", }; -static inline const char* get_tab_ext(ArchiveTabEnum tab) { - switch(tab) { - case ArchiveTabIButton: - return known_ext[ArchiveFileTypeIButton]; - case ArchiveTabNFC: - return known_ext[ArchiveFileTypeNFC]; - case ArchiveTabSubGhz: - return known_ext[ArchiveFileTypeSubGhz]; - case ArchiveTabLFRFID: - return known_ext[ArchiveFileTypeLFRFID]; - case ArchiveTabIrda: - return known_ext[ArchiveFileTypeIrda]; - default: - return "*"; - } +static const ArchiveFileTypeEnum known_type[] = { + [ArchiveTabFavorites] = ArchiveFileTypeUnknown, + [ArchiveTabIButton] = ArchiveFileTypeIButton, + [ArchiveTabNFC] = ArchiveFileTypeNFC, + [ArchiveTabSubGhz] = ArchiveFileTypeSubGhz, + [ArchiveTabLFRFID] = ArchiveFileTypeLFRFID, + [ArchiveTabIrda] = ArchiveFileTypeIrda, + [ArchiveTabBadUsb] = ArchiveFileTypeBadUsb, + [ArchiveTabU2f] = ArchiveFileTypeU2f, + [ArchiveTabBrowser] = ArchiveFileTypeUnknown, +}; + +static inline const ArchiveFileTypeEnum archive_get_tab_filetype(ArchiveTabEnum tab) { + return known_type[tab]; +} + +static inline const char* archive_get_tab_ext(ArchiveTabEnum tab) { + return known_ext[archive_get_tab_filetype(tab)]; } static inline const char* archive_get_default_path(ArchiveTabEnum tab) { return tab_default_paths[tab]; } -inline bool is_known_app(ArchiveFileTypeEnum type) { +inline bool archive_is_known_app(ArchiveFileTypeEnum type) { return (type != ArchiveFileTypeFolder && type != ArchiveFileTypeUnknown); } @@ -62,7 +71,8 @@ uint8_t archive_get_depth(ArchiveBrowserView* browser); const char* archive_get_path(ArchiveBrowserView* browser); const char* archive_get_name(ArchiveBrowserView* browser); -void archive_add_item(ArchiveBrowserView* browser, FileInfo* file_info, const char* name); +void archive_add_app_item(ArchiveBrowserView* browser, const char* name); +void archive_add_file_item(ArchiveBrowserView* browser, FileInfo* file_info, const char* name); void archive_show_file_menu(ArchiveBrowserView* browser, bool show); void archive_favorites_move_mode(ArchiveBrowserView* browser, bool active); diff --git a/applications/archive/helpers/archive_favorites.c b/applications/archive/helpers/archive_favorites.c index b622e76f..97bf9149 100644 --- a/applications/archive/helpers/archive_favorites.c +++ b/applications/archive/helpers/archive_favorites.c @@ -1,5 +1,7 @@ #include "archive_favorites.h" +#include "archive_files.h" +#include "archive_apps.h" #include "archive_browser.h" uint16_t archive_favorites_count(void* context) { @@ -46,10 +48,16 @@ static bool archive_favourites_rescan() { break; } - bool file_exists = false; - file_worker_is_file_exist(file_worker, string_get_cstr(buffer), &file_exists); - if(file_exists) { - archive_file_append(ARCHIVE_FAV_TEMP_PATH, "%s\n", string_get_cstr(buffer)); + if(string_search(buffer, "/app:") == 0) { + if(archive_app_is_available(NULL, string_get_cstr(buffer))) { + archive_file_append(ARCHIVE_FAV_TEMP_PATH, "%s\n", string_get_cstr(buffer)); + } + } else { + bool file_exists = false; + file_worker_is_file_exist(file_worker, string_get_cstr(buffer), &file_exists); + if(file_exists) { + archive_file_append(ARCHIVE_FAV_TEMP_PATH, "%s\n", string_get_cstr(buffer)); + } } } } @@ -88,13 +96,22 @@ bool archive_favorites_read(void* context) { break; } - bool file_exists = false; - file_worker_is_file_exist(file_worker, string_get_cstr(buffer), &file_exists); + if(string_search(buffer, "/app:") == 0) { + if(archive_app_is_available(browser, string_get_cstr(buffer))) { + archive_add_app_item(browser, string_get_cstr(buffer)); + } else { + need_refresh = true; + } + } else { + bool file_exists = false; + file_worker_is_file_exist(file_worker, string_get_cstr(buffer), &file_exists); + + if(file_exists) + archive_add_file_item(browser, &file_info, string_get_cstr(buffer)); + else + need_refresh = true; + } - if(file_exists) - archive_add_item(browser, &file_info, string_get_cstr(buffer)); - else - need_refresh = true; string_reset(buffer); } } @@ -185,8 +202,7 @@ bool archive_is_favorite(const char* format, ...) { return found; } -bool archive_favorites_rename(const char* file_path, const char* src, const char* dst) { - furi_assert(file_path); +bool archive_favorites_rename(const char* src, const char* dst) { furi_assert(src); furi_assert(dst); @@ -198,7 +214,7 @@ bool archive_favorites_rename(const char* file_path, const char* src, const char string_init(buffer); string_init(path); - string_printf(path, "%s/%s", file_path, src); + string_printf(path, "%s", src); bool result = file_worker_open(file_worker, ARCHIVE_FAV_PATH, FSAM_READ, FSOM_OPEN_EXISTING); if(result) { diff --git a/applications/archive/helpers/archive_favorites.h b/applications/archive/helpers/archive_favorites.h index c028bd2b..3a517f4b 100644 --- a/applications/archive/helpers/archive_favorites.h +++ b/applications/archive/helpers/archive_favorites.h @@ -8,6 +8,6 @@ uint16_t archive_favorites_count(void* context); bool archive_favorites_read(void* context); bool archive_favorites_delete(const char* format, ...); bool archive_is_favorite(const char* format, ...); -bool archive_favorites_rename(const char* file_path, const char* src, const char* dst); +bool archive_favorites_rename(const char* src, const char* dst); void archive_add_to_favorites(const char* file_path); void archive_favorites_save(void* context); diff --git a/applications/archive/helpers/archive_files.c b/applications/archive/helpers/archive_files.c index a5bd2eb9..08542bfe 100644 --- a/applications/archive/helpers/archive_files.c +++ b/applications/archive/helpers/archive_files.c @@ -1,8 +1,11 @@ #include "archive_files.h" +#include "archive_apps.h" #include "archive_browser.h" #define TAG "Archive" +#define ASSETS_DIR "assets" + bool filter_by_extension(FileInfo* file_info, const char* tab_ext, const char* name) { furi_assert(file_info); furi_assert(tab_ext); @@ -15,7 +18,11 @@ bool filter_by_extension(FileInfo* file_info, const char* tab_ext, const char* n } else if(strstr(name, tab_ext) != NULL) { result = true; } else if(file_info->flags & FSF_DIRECTORY) { - result = true; + if(strstr(name, ASSETS_DIR) != NULL) { + result = false; // Skip assets folder in all tabs except browser + } else { + result = true; + } } return result; @@ -38,21 +45,36 @@ void archive_get_file_extension(char* name, char* ext) { strncpy(ext, dot, MAX_EXT_LEN); } -void set_file_type(ArchiveFile_t* file, FileInfo* file_info) { +void set_file_type(ArchiveFile_t* file, FileInfo* file_info, const char* path, bool is_app) { furi_assert(file); - furi_assert(file_info); - for(size_t i = 0; i < SIZEOF_ARRAY(known_ext); i++) { - if(string_search_str(file->name, known_ext[i], 0) != STRING_FAILURE) { - file->type = i; - return; - } - } - - if(file_info->flags & FSF_DIRECTORY) { - file->type = ArchiveFileTypeFolder; + file->is_app = is_app; + if(is_app) { + file->type = archive_get_app_filetype(archive_get_app_type(path)); } else { - file->type = ArchiveFileTypeUnknown; + furi_assert(file_info); + + for(size_t i = 0; i < SIZEOF_ARRAY(known_ext); i++) { + if((known_ext[i][0] == '?') || (known_ext[i][0] == '*')) continue; + if(string_search_str(file->name, known_ext[i], 0) != STRING_FAILURE) { + if(i == ArchiveFileTypeBadUsb) { + if(string_search_str(file->name, archive_get_default_path(ArchiveTabBadUsb)) == + 0) { + file->type = i; + return; // *.txt file is a BadUSB script only if it is in BadUSB folder + } + } else { + file->type = i; + return; + } + } + } + + if(file_info->flags & FSF_DIRECTORY) { + file->type = ArchiveFileTypeFolder; + } else { + file->type = ArchiveFileTypeUnknown; + } } } @@ -63,17 +85,21 @@ bool archive_get_filenames(void* context, const char* path) { ArchiveBrowserView* browser = context; archive_file_array_rm_all(browser); - if(archive_get_tab(browser) != ArchiveTabFavorites) { - res = archive_read_dir(browser, path); - } else { + if(archive_get_tab(browser) == ArchiveTabFavorites) { res = archive_favorites_read(browser); + } else if(strncmp(path, "/app:", 5) == 0) { + res = archive_app_read_dir(browser, path); + } else { + res = archive_read_dir(browser, path); } return res; } -bool archive_dir_empty(void* context, const char* path) { // can be simpler? +bool archive_dir_not_empty(void* context, const char* path) { // can be simpler? furi_assert(context); + ArchiveBrowserView* browser = context; + FileInfo file_info; Storage* fs_api = furi_record_open("storage"); File* directory = storage_file_alloc(fs_api); @@ -92,8 +118,11 @@ bool archive_dir_empty(void* context, const char* path) { // can be simpler? } if(files_found) { break; - } else if(storage_file_get_error(directory) == FSE_OK) { - files_found = name[0]; + } else if((storage_file_get_error(directory) == FSE_OK) && (name[0])) { + if(filter_by_extension( + &file_info, archive_get_tab_ext(archive_get_tab(browser)), name)) { + files_found = true; + } } else { return false; } @@ -114,6 +143,8 @@ bool archive_read_dir(void* context, const char* path) { Storage* fs_api = furi_record_open("storage"); File* directory = storage_file_alloc(fs_api); char name[MAX_NAME_LEN]; + snprintf(name, MAX_NAME_LEN, "%s/", path); + size_t path_len = strlen(name); size_t files_cnt = 0; if(!storage_dir_open(directory, path)) { @@ -123,13 +154,14 @@ bool archive_read_dir(void* context, const char* path) { } while(1) { - if(!storage_dir_read(directory, &file_info, name, MAX_NAME_LEN)) { + if(!storage_dir_read(directory, &file_info, &name[path_len], MAX_NAME_LEN - path_len)) { break; } + if(files_cnt > MAX_FILES) { break; } else if(storage_file_get_error(directory) == FSE_OK) { - archive_add_item(browser, &file_info, name); + archive_add_file_item(browser, &file_info, name); ++files_cnt; } else { storage_dir_close(directory); diff --git a/applications/archive/helpers/archive_files.h b/applications/archive/helpers/archive_files.h index 12fde2fb..ff751d9b 100644 --- a/applications/archive/helpers/archive_files.h +++ b/applications/archive/helpers/archive_files.h @@ -9,29 +9,38 @@ typedef enum { ArchiveFileTypeSubGhz, ArchiveFileTypeLFRFID, ArchiveFileTypeIrda, + ArchiveFileTypeBadUsb, + ArchiveFileTypeU2f, ArchiveFileTypeFolder, ArchiveFileTypeUnknown, - AppIdTotal, + ArchiveFileTypesTotal, } ArchiveFileTypeEnum; typedef struct { string_t name; ArchiveFileTypeEnum type; bool fav; + bool is_app; } ArchiveFile_t; static void ArchiveFile_t_init(ArchiveFile_t* obj) { obj->type = ArchiveFileTypeUnknown; + obj->is_app = false; + obj->fav = false; string_init(obj->name); } static void ArchiveFile_t_init_set(ArchiveFile_t* obj, const ArchiveFile_t* src) { obj->type = src->type; + obj->is_app = src->is_app; + obj->fav = src->fav; string_init_set(obj->name, src->name); } static void ArchiveFile_t_set(ArchiveFile_t* obj, const ArchiveFile_t* src) { obj->type = src->type; + obj->is_app = src->is_app; + obj->fav = src->fav; string_set(obj->name, src->name); } @@ -48,11 +57,11 @@ ARRAY_DEF( CLEAR(API_2(ArchiveFile_t_clear)))) bool filter_by_extension(FileInfo* file_info, const char* tab_ext, const char* name); -void set_file_type(ArchiveFile_t* file, FileInfo* file_info); +void set_file_type(ArchiveFile_t* file, FileInfo* file_info, const char* path, bool is_app); void archive_trim_file_path(char* name, bool ext); void archive_get_file_extension(char* name, char* ext); bool archive_get_filenames(void* context, const char* path); -bool archive_dir_empty(void* context, const char* path); +bool archive_dir_not_empty(void* context, const char* path); bool archive_read_dir(void* context, const char* path); void archive_file_append(const char* path, const char* format, ...); void archive_delete_file(void* context, const char* format, ...); \ No newline at end of file diff --git a/applications/archive/scenes/archive_scene_browser.c b/applications/archive/scenes/archive_scene_browser.c index d33aa23e..228bb305 100644 --- a/applications/archive/scenes/archive_scene_browser.c +++ b/applications/archive/scenes/archive_scene_browser.c @@ -1,33 +1,41 @@ #include "../archive_i.h" #include "../helpers/archive_files.h" +#include "../helpers/archive_apps.h" #include "../helpers/archive_favorites.h" #include "../helpers/archive_browser.h" #include "../views/archive_browser_view.h" +#define TAG "ArchiveSceneBrowser" + static const char* flipper_app_name[] = { [ArchiveFileTypeIButton] = "iButton", [ArchiveFileTypeNFC] = "NFC", [ArchiveFileTypeSubGhz] = "Sub-GHz", [ArchiveFileTypeLFRFID] = "125 kHz RFID", [ArchiveFileTypeIrda] = "Infrared", + [ArchiveFileTypeBadUsb] = "Bad USB", + [ArchiveFileTypeU2f] = "U2F", }; -static void archive_run_in_app( - ArchiveBrowserView* browser, - ArchiveFile_t* selected, - bool full_path_provided) { +static void archive_run_in_app(ArchiveBrowserView* browser, ArchiveFile_t* selected) { Loader* loader = furi_record_open("loader"); - string_t full_path; - if(!full_path_provided) { - string_init_printf( - full_path, "%s/%s", string_get_cstr(browser->path), string_get_cstr(selected->name)); + LoaderStatus status; + if(selected->is_app) { + char* param = strrchr(string_get_cstr(selected->name), '/'); + if(param != NULL) { + param++; + } + status = loader_start(loader, flipper_app_name[selected->type], param); } else { - string_init_set(full_path, selected->name); + status = loader_start( + loader, flipper_app_name[selected->type], string_get_cstr(selected->name)); + } + + if(status != LoaderStatusOk) { + FURI_LOG_E(TAG, "loader_start failed: %d", status); } - loader_start(loader, flipper_app_name[selected->type], string_get_cstr(full_path)); - string_clear(full_path); furi_record_close("loader"); } @@ -50,9 +58,8 @@ bool archive_scene_browser_on_event(void* context, SceneManagerEvent event) { ArchiveBrowserView* browser = archive->browser; ArchiveFile_t* selected = archive_get_current_file(browser); - const char* path = archive_get_path(browser); const char* name = archive_get_name(browser); - bool known_app = is_known_app(selected->type); + bool known_app = archive_is_known_app(selected->type); bool favorites = archive_get_tab(browser) == ArchiveTabFavorites; bool consumed = false; @@ -68,7 +75,7 @@ bool archive_scene_browser_on_event(void* context, SceneManagerEvent event) { break; case ArchiveBrowserEventFileMenuRun: if(known_app) { - archive_run_in_app(browser, selected, favorites); + archive_run_in_app(browser, selected); } consumed = true; break; @@ -78,10 +85,10 @@ bool archive_scene_browser_on_event(void* context, SceneManagerEvent event) { archive_file_array_rm_selected(browser); archive_show_file_menu(browser, false); } else if(known_app) { - if(archive_is_favorite("%s/%s", path, name)) { - archive_favorites_delete("%s/%s", path, name); + if(archive_is_favorite("%s", name)) { + archive_favorites_delete("%s", name); } else { - archive_file_append(ARCHIVE_FAV_PATH, "%s/%s\n", path, name); + archive_file_append(ARCHIVE_FAV_PATH, "%s\n", name); } archive_show_file_menu(browser, false); } @@ -91,18 +98,13 @@ bool archive_scene_browser_on_event(void* context, SceneManagerEvent event) { case ArchiveBrowserEventFileMenuAction: if(favorites) { browser->callback(ArchiveBrowserEventEnterFavMove, browser->context); - } else if(known_app) { + } else if((known_app) && (selected->is_app == false)) { scene_manager_next_scene(archive->scene_manager, ArchiveAppSceneRename); } consumed = true; break; case ArchiveBrowserEventFileMenuDelete: - if(favorites) { - archive_delete_file(browser, "%s", name); - } else { - archive_delete_file(browser, "%s/%s", path, name); - } - archive_show_file_menu(browser, false); + scene_manager_next_scene(archive->scene_manager, ArchiveAppSceneDelete); consumed = true; break; case ArchiveBrowserEventEnterDir: diff --git a/applications/archive/scenes/archive_scene_config.h b/applications/archive/scenes/archive_scene_config.h index 2ed4e00c..4145f43d 100644 --- a/applications/archive/scenes/archive_scene_config.h +++ b/applications/archive/scenes/archive_scene_config.h @@ -1,2 +1,3 @@ ADD_SCENE(archive, browser, Browser) ADD_SCENE(archive, rename, Rename) +ADD_SCENE(archive, delete, Delete) diff --git a/applications/archive/scenes/archive_scene_delete.c b/applications/archive/scenes/archive_scene_delete.c new file mode 100644 index 00000000..04b37510 --- /dev/null +++ b/applications/archive/scenes/archive_scene_delete.c @@ -0,0 +1,70 @@ +#include "../archive_i.h" +#include "../helpers/archive_favorites.h" +#include "../helpers/archive_files.h" +#include "../helpers/archive_apps.h" +#include "../helpers/archive_browser.h" + +#define SCENE_DELETE_CUSTOM_EVENT (0UL) +#define MAX_TEXT_INPUT_LEN 22 + +void archive_scene_delete_widget_callback(GuiButtonType result, InputType type, void* context) { + furi_assert(context); + ArchiveApp* app = (ArchiveApp*)context; + if(type == InputTypeShort) { + view_dispatcher_send_custom_event(app->view_dispatcher, result); + } +} + +void archive_scene_delete_on_enter(void* context) { + furi_assert(context); + ArchiveApp* app = (ArchiveApp*)context; + + widget_add_button_element( + app->widget, GuiButtonTypeLeft, "Back", archive_scene_delete_widget_callback, app); + widget_add_button_element( + app->widget, GuiButtonTypeRight, "Delete", archive_scene_delete_widget_callback, app); + + ArchiveFile_t* current = archive_get_current_file(app->browser); + strlcpy(app->text_store, string_get_cstr(current->name), MAX_NAME_LEN); + char* name = strrchr(app->text_store, '/'); + if(name != NULL) { + name++; + } + + char delete_str[64]; + snprintf(delete_str, sizeof(delete_str), "\e#Delete %s?\e#", name); + widget_add_text_box_element(app->widget, 0, 0, 128, 23, AlignCenter, AlignCenter, delete_str); + + view_dispatcher_switch_to_view(app->view_dispatcher, ArchiveViewWidget); +} + +bool archive_scene_delete_on_event(void* context, SceneManagerEvent event) { + furi_assert(context); + ArchiveApp* app = (ArchiveApp*)context; + + ArchiveBrowserView* browser = app->browser; + ArchiveFile_t* selected = archive_get_current_file(browser); + const char* name = archive_get_name(browser); + + if(event.type == SceneManagerEventTypeCustom) { + if(event.event == GuiButtonTypeRight) { + if(selected->is_app) { + archive_app_delete_file(browser, name); + } else { + archive_delete_file(browser, "%s", name); + } + archive_show_file_menu(browser, false); + return scene_manager_previous_scene(app->scene_manager); + } else if(event.event == GuiButtonTypeLeft) { + return scene_manager_previous_scene(app->scene_manager); + } + } + return false; +} + +void archive_scene_delete_on_exit(void* context) { + furi_assert(context); + ArchiveApp* app = (ArchiveApp*)context; + + widget_reset(app->widget); +} diff --git a/applications/archive/scenes/archive_scene_rename.c b/applications/archive/scenes/archive_scene_rename.c index 8f32eb8a..9e573801 100644 --- a/applications/archive/scenes/archive_scene_rename.c +++ b/applications/archive/scenes/archive_scene_rename.c @@ -52,7 +52,8 @@ bool archive_scene_rename_on_event(void* context, SceneManagerEvent event) { const char* path = archive_get_path(archive->browser); const char* name = archive_get_name(archive->browser); - string_init_printf(buffer_src, "%s/%s", path, name); + string_init_printf(buffer_src, "%s", name); + //TODO: take path from src name string_init_printf(buffer_dst, "%s/%s", path, archive->text_store); // append extension @@ -64,7 +65,7 @@ bool archive_scene_rename_on_event(void* context, SceneManagerEvent event) { furi_record_close("storage"); if(file->fav) { - archive_favorites_rename(path, name, string_get_cstr(buffer_dst)); + archive_favorites_rename(name, string_get_cstr(buffer_dst)); } string_clear(buffer_src); diff --git a/applications/archive/views/archive_browser_view.c b/applications/archive/views/archive_browser_view.c index 525fbbcb..5e079436 100644 --- a/applications/archive/views/archive_browser_view.c +++ b/applications/archive/views/archive_browser_view.c @@ -10,6 +10,8 @@ static const char* ArchiveTabNames[] = { [ArchiveTabSubGhz] = "Sub-GHz", [ArchiveTabLFRFID] = "RFID LF", [ArchiveTabIrda] = "Infrared", + [ArchiveTabBadUsb] = "Bad USB", + [ArchiveTabU2f] = "U2F", [ArchiveTabBrowser] = "Browser"}; static const Icon* ArchiveItemIcons[] = { @@ -18,6 +20,8 @@ static const Icon* ArchiveItemIcons[] = { [ArchiveFileTypeSubGhz] = &I_sub1_10px, [ArchiveFileTypeLFRFID] = &I_125_10px, [ArchiveFileTypeIrda] = &I_ir_10px, + [ArchiveFileTypeBadUsb] = &I_badusb_10px, + [ArchiveFileTypeU2f] = &I_u2f_10px, [ArchiveFileTypeFolder] = &I_dir_10px, [ArchiveFileTypeUnknown] = &I_unknown_10px, }; @@ -47,15 +51,20 @@ static void render_item_menu(Canvas* canvas, ArchiveBrowserViewModel* model) { ArchiveFile_t* selected = files_array_get(model->files, model->idx); - if(!is_known_app(selected->type)) { + if(!archive_is_known_app(selected->type)) { string_set_str(menu[0], "---"); string_set_str(menu[1], "---"); string_set_str(menu[2], "---"); - } else if(selected->fav) { + } else { + if(model->tab_idx == ArchiveTabFavorites) { + string_set_str(menu[2], "Move"); + } else if(selected->is_app) { + string_set_str(menu[2], "---"); + } + } + + if((selected->fav) || (model->tab_idx == ArchiveTabFavorites)) { string_set_str(menu[1], "Unpin"); - } else if(model->tab_idx == ArchiveTabFavorites) { - string_set_str(menu[1], "Unpin"); - string_set_str(menu[2], "Move"); } for(size_t i = 0; i < MENU_ITEMS; i++) { @@ -102,7 +111,7 @@ static void draw_list(Canvas* canvas, ArchiveBrowserViewModel* model) { ArchiveFile_t* file = files_array_get(model->files, CLAMP(idx, array_size - 1, 0)); strlcpy(cstr_buff, string_get_cstr(file->name), string_size(file->name) + 1); - archive_trim_file_path(cstr_buff, is_known_app(file->type)); + archive_trim_file_path(cstr_buff, archive_is_known_app(file->type)); string_init_set_str(str_buff, cstr_buff); elements_string_fit_width( canvas, str_buff, (scrollbar ? MAX_LEN_PX - 6 : MAX_LEN_PX) - x_offset); diff --git a/applications/archive/views/archive_browser_view.h b/applications/archive/views/archive_browser_view.h index 634dec44..af4ed85e 100644 --- a/applications/archive/views/archive_browser_view.h +++ b/applications/archive/views/archive_browser_view.h @@ -24,6 +24,8 @@ typedef enum { ArchiveTabNFC, ArchiveTabIrda, ArchiveTabIButton, + ArchiveTabBadUsb, + ArchiveTabU2f, ArchiveTabBrowser, ArchiveTabTotal, } ArchiveTabEnum; diff --git a/applications/bad_usb/bad_usb_app.c b/applications/bad_usb/bad_usb_app.c index c4a3c930..49809562 100644 --- a/applications/bad_usb/bad_usb_app.c +++ b/applications/bad_usb/bad_usb_app.c @@ -2,6 +2,7 @@ #include #include #include +#include static bool bad_usb_app_custom_event_callback(void* context, uint32_t event) { furi_assert(context); @@ -39,27 +40,34 @@ static bool bad_usb_check_assets() { return ret; } -BadUsbApp* bad_usb_app_alloc() { +BadUsbApp* bad_usb_app_alloc(char* arg) { BadUsbApp* app = furi_alloc(sizeof(BadUsbApp)); + if(arg != NULL) { + string_t filename; + string_init(filename); + path_extract_filename_no_ext(arg, filename); + strncpy(app->file_name, string_get_cstr(filename), BAD_USB_FILE_NAME_LEN); + string_clear(filename); + } + app->gui = furi_record_open("gui"); app->notifications = furi_record_open("notification"); app->dialogs = furi_record_open("dialogs"); app->view_dispatcher = view_dispatcher_alloc(); - app->scene_manager = scene_manager_alloc(&bad_usb_scene_handlers, app); view_dispatcher_enable_queue(app->view_dispatcher); + + app->scene_manager = scene_manager_alloc(&bad_usb_scene_handlers, app); + view_dispatcher_set_event_callback_context(app->view_dispatcher, app); view_dispatcher_set_tick_event_callback( app->view_dispatcher, bad_usb_app_tick_event_callback, 500); - view_dispatcher_set_custom_event_callback( app->view_dispatcher, bad_usb_app_custom_event_callback); view_dispatcher_set_navigation_event_callback( app->view_dispatcher, bad_usb_app_back_event_callback); - view_dispatcher_attach_to_gui(app->view_dispatcher, app->gui, ViewDispatcherTypeFullscreen); - // Custom Widget app->widget = widget_alloc(); view_dispatcher_add_view( @@ -69,7 +77,11 @@ BadUsbApp* bad_usb_app_alloc() { view_dispatcher_add_view( app->view_dispatcher, BadUsbAppViewWork, bad_usb_get_view(app->bad_usb_view)); - if(bad_usb_check_assets()) { + view_dispatcher_attach_to_gui(app->view_dispatcher, app->gui, ViewDispatcherTypeFullscreen); + + if(*app->file_name != '\0') { + scene_manager_next_scene(app->scene_manager, BadUsbSceneWork); + } else if(bad_usb_check_assets()) { scene_manager_next_scene(app->scene_manager, BadUsbSceneFileSelect); } else { scene_manager_next_scene(app->scene_manager, BadUsbSceneError); @@ -106,7 +118,7 @@ int32_t bad_usb_app(void* p) { FuriHalUsbInterface* usb_mode_prev = furi_hal_usb_get_config(); furi_hal_usb_set_config(&usb_hid); - BadUsbApp* bad_usb_app = bad_usb_app_alloc(); + BadUsbApp* bad_usb_app = bad_usb_app_alloc((char*)p); view_dispatcher_run(bad_usb_app->view_dispatcher); diff --git a/applications/bad_usb/views/bad_usb_view.c b/applications/bad_usb/views/bad_usb_view.c index fecd2f7a..6d226ca7 100644 --- a/applications/bad_usb/views/bad_usb_view.c +++ b/applications/bad_usb/views/bad_usb_view.c @@ -144,7 +144,7 @@ void bad_usb_set_ok_callback(BadUsb* bad_usb, BadUsbOkCallback callback, void* c bad_usb->view, (BadUsbModel * model) { bad_usb->callback = callback; bad_usb->context = context; - return false; + return true; }); } @@ -153,7 +153,7 @@ void bad_usb_set_file_name(BadUsb* bad_usb, char* name) { with_view_model( bad_usb->view, (BadUsbModel * model) { model->file_name = name; - return false; + return true; }); } @@ -163,6 +163,6 @@ void bad_usb_set_state(BadUsb* bad_usb, BadUsbState* st) { bad_usb->view, (BadUsbModel * model) { memcpy(&(model->state), st, sizeof(BadUsbState)); model->anim_frame ^= 1; - return false; + return true; }); } diff --git a/applications/bt/bt_service/bt.c b/applications/bt/bt_service/bt.c index 32008f52..0015c08c 100755 --- a/applications/bt/bt_service/bt.c +++ b/applications/bt/bt_service/bt.c @@ -16,9 +16,9 @@ static void bt_draw_statusbar_callback(Canvas* canvas, void* context) { Bt* bt = context; if(bt->status == BtStatusAdvertising) { - canvas_draw_icon(canvas, 0, 0, &I_Bluetooth_5x8); + canvas_draw_icon(canvas, 0, 0, &I_Bluetooth_Idle_5x8); } else if(bt->status == BtStatusConnected) { - canvas_draw_icon(canvas, 0, 0, &I_BT_Pair_9x8); + canvas_draw_icon(canvas, 0, 0, &I_Bluetooth_Connected_16x8); } } @@ -199,13 +199,18 @@ static bool bt_on_gap_event_callback(GapEvent event, void* context) { furi_check(osMessageQueuePut(bt->message_queue, &message, 0, osWaitForever) == osOK); if(bt->profile == BtProfileSerial) { // Open RPC session - FURI_LOG_I(TAG, "Open RPC connection"); bt->rpc_session = rpc_session_open(bt->rpc); - rpc_session_set_send_bytes_callback(bt->rpc_session, bt_rpc_send_bytes_callback); - rpc_session_set_buffer_is_empty_callback( - bt->rpc_session, furi_hal_bt_serial_notify_buffer_is_empty); - rpc_session_set_context(bt->rpc_session, bt); - furi_hal_bt_serial_set_event_callback(RPC_BUFFER_SIZE, bt_serial_event_callback, bt); + if(bt->rpc_session) { + FURI_LOG_I(TAG, "Open RPC connection"); + rpc_session_set_send_bytes_callback(bt->rpc_session, bt_rpc_send_bytes_callback); + rpc_session_set_buffer_is_empty_callback( + bt->rpc_session, furi_hal_bt_serial_notify_buffer_is_empty); + rpc_session_set_context(bt->rpc_session, bt); + furi_hal_bt_serial_set_event_callback( + RPC_BUFFER_SIZE, bt_serial_event_callback, bt); + } else { + FURI_LOG_W(TAG, "RPC is busy, failed to open new session"); + } } // Update battery level PowerInfo info; @@ -257,10 +262,10 @@ static void bt_on_key_storage_change_callback(uint8_t* addr, uint16_t size, void static void bt_statusbar_update(Bt* bt) { if(bt->status == BtStatusAdvertising) { - view_port_set_width(bt->statusbar_view_port, icon_get_width(&I_Bluetooth_5x8)); + view_port_set_width(bt->statusbar_view_port, icon_get_width(&I_Bluetooth_Idle_5x8)); view_port_enabled_set(bt->statusbar_view_port, true); } else if(bt->status == BtStatusConnected) { - view_port_set_width(bt->statusbar_view_port, icon_get_width(&I_BT_Pair_9x8)); + view_port_set_width(bt->statusbar_view_port, icon_get_width(&I_Bluetooth_Connected_16x8)); view_port_enabled_set(bt->statusbar_view_port, true); } else { view_port_enabled_set(bt->statusbar_view_port, false); diff --git a/applications/bt/bt_service/bt_keys_storage.c b/applications/bt/bt_service/bt_keys_storage.c index c712b65b..74df1020 100644 --- a/applications/bt/bt_service/bt_keys_storage.c +++ b/applications/bt/bt_service/bt_keys_storage.c @@ -43,10 +43,11 @@ bool bt_save_key_storage(Bt* bt) { bool bt_delete_key_storage(Bt* bt) { furi_assert(bt); bool delete_succeed = false; + bool bt_is_active = furi_hal_bt_is_active(); furi_hal_bt_stop_advertising(); delete_succeed = furi_hal_bt_clear_white_list(); - if(bt->bt_settings.enabled) { + if(bt_is_active) { furi_hal_bt_start_advertising(); } 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 7faa50fe..f37ac6c6 100644 --- a/applications/desktop/scenes/desktop_scene_main.c +++ b/applications/desktop/scenes/desktop_scene_main.c @@ -4,12 +4,13 @@ #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 MAIN_VIEW_DEFAULT (0UL) +#define TAG "DesktopSrv" static void desktop_scene_main_app_started_callback(const void* message, void* context) { furi_assert(context); @@ -29,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) { @@ -78,34 +82,22 @@ 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"); desktop->app_start_stop_subscription = furi_pubsub_subscribe( loader_get_pubsub(loader), desktop_scene_main_app_started_callback, desktop); + + // Special case: application is already running (autostart application) + if(loader_is_locked(loader)) { + animation_manager_unload_and_stall_animation(desktop->animation_manager); + } + furi_record_close("loader"); 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) { @@ -142,23 +134,25 @@ bool desktop_scene_main_on_event(void* context, SceneManagerEvent event) { Loader* loader = furi_record_open("loader"); LoaderStatus status = loader_start(loader, FLIPPER_APPS[desktop->settings.favorite].name, NULL); - furi_check(status == LoaderStatusOk); + if(status != LoaderStatusOk) { + FURI_LOG_E(TAG, "loader_start failed: %d", status); + } furi_record_close("loader"); } else { - FURI_LOG_E("DesktopSrv", "Can't find favorite application"); + FURI_LOG_E(TAG, "Can't find favorite application"); } 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; @@ -171,16 +165,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; @@ -209,5 +195,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/gpio/views/gpio_usb_uart.c b/applications/gpio/views/gpio_usb_uart.c index 3b2d1f38..be80f019 100644 --- a/applications/gpio/views/gpio_usb_uart.c +++ b/applications/gpio/views/gpio_usb_uart.c @@ -151,6 +151,6 @@ void gpio_usb_uart_update_state(GpioUsbUart* instance, UsbUartConfig* cfg, UsbUa model->rx_active = (model->rx_cnt != st->rx_cnt); model->tx_cnt = st->tx_cnt; model->rx_cnt = st->rx_cnt; - return false; + return true; }); } 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/gui/view_dispatcher.c b/applications/gui/view_dispatcher.c index 549ee622..a32dde97 100644 --- a/applications/gui/view_dispatcher.c +++ b/applications/gui/view_dispatcher.c @@ -253,27 +253,26 @@ void view_dispatcher_handle_input(ViewDispatcher* view_dispatcher, InputEvent* e } // Deliver event - if(view_dispatcher->ongoing_input_view == view_dispatcher->current_view) { - bool is_consumed = false; - if(view_dispatcher->current_view) { - is_consumed = view_input(view_dispatcher->current_view, event); - } - if(!is_consumed && (event->type == InputTypeShort || event->type == InputTypeLong)) { - // TODO remove view navigation handlers - uint32_t view_id = VIEW_IGNORE; - if(event->key == InputKeyBack) { - view_id = view_previous(view_dispatcher->current_view); - if((view_id == VIEW_IGNORE) && (view_dispatcher->navigation_event_callback)) { - is_consumed = - view_dispatcher->navigation_event_callback(view_dispatcher->event_context); - if(!is_consumed) { - view_dispatcher_stop(view_dispatcher); - return; - } - } - } - if(!is_consumed) { + if(view_dispatcher->current_view && + view_dispatcher->ongoing_input_view == view_dispatcher->current_view) { + // Dispatch input to current view + bool is_consumed = view_input(view_dispatcher->current_view, event); + + // Navigate if input is not consumed + if(!is_consumed && (event->key == InputKeyBack) && + (event->type == InputTypeShort || event->type == InputTypeLong)) { + // Navigate to previous + uint32_t view_id = view_previous(view_dispatcher->current_view); + if(view_id != VIEW_IGNORE) { + // Switch to returned view view_dispatcher_switch_to_view(view_dispatcher, view_id); + } else if(view_dispatcher->navigation_event_callback) { + // Dispatch navigation event + if(!view_dispatcher->navigation_event_callback(view_dispatcher->event_context)) { + // TODO: should we allow view_dispatcher to stop without navigation_event_callback? + view_dispatcher_stop(view_dispatcher); + return; + } } } } else if(view_dispatcher->ongoing_input_view && event->type == InputTypeRelease) { diff --git a/applications/ibutton/helpers/key_reader.cpp b/applications/ibutton/helpers/key_reader.cpp index eea4abd6..9ed5b340 100644 --- a/applications/ibutton/helpers/key_reader.cpp +++ b/applications/ibutton/helpers/key_reader.cpp @@ -59,9 +59,8 @@ KeyReader::~KeyReader() { bool KeyReader::read_key(iButtonKeyType* key_type, uint8_t* data, uint8_t data_size) { bool readed = false; - switch(read_mode) { - case ReadMode::DALLAS: - __disable_irq(); + if(read_mode == ReadMode::DALLAS) { + FURI_CRITICAL_ENTER(); if(onewire_master->search(data)) { onewire_master->reset_search(); readed = true; @@ -69,9 +68,8 @@ bool KeyReader::read_key(iButtonKeyType* key_type, uint8_t* data, uint8_t data_s } else { onewire_master->reset_search(); } - __enable_irq(); - break; - case ReadMode::CYFRAL_METAKOM: + FURI_CRITICAL_EXIT(); + } else if(read_mode == ReadMode::CYFRAL_METAKOM) { if(cyfral_decoder.read(data, 2)) { readed = true; *key_type = iButtonKeyType::KeyCyfral; @@ -79,7 +77,6 @@ bool KeyReader::read_key(iButtonKeyType* key_type, uint8_t* data, uint8_t data_s readed = true; *key_type = iButtonKeyType::KeyMetakom; } - break; } return readed; @@ -88,10 +85,10 @@ bool KeyReader::read_key(iButtonKeyType* key_type, uint8_t* data, uint8_t data_s bool KeyReader::verify_key(iButtonKeyType key_type, const uint8_t* const data, uint8_t data_size) { bool result = true; - switch(key_type) { - case iButtonKeyType::KeyDallas: + if(key_type == iButtonKeyType::KeyDallas) { switch_to(ReadMode::DALLAS); - __disable_irq(); + + FURI_CRITICAL_ENTER(); if(onewire_master->reset()) { onewire_master->write(DS1990::CMD_READ_ROM); for(uint8_t i = 0; i < data_size; i++) { @@ -101,14 +98,11 @@ bool KeyReader::verify_key(iButtonKeyType key_type, const uint8_t* const data, u } } else { result = false; - break; } - __enable_irq(); - break; + FURI_CRITICAL_EXIT(); - default: + } else { result = false; - break; } return result; diff --git a/applications/ibutton/helpers/key_writer.cpp b/applications/ibutton/helpers/key_writer.cpp index 689517bb..39637b3a 100644 --- a/applications/ibutton/helpers/key_writer.cpp +++ b/applications/ibutton/helpers/key_writer.cpp @@ -74,7 +74,7 @@ bool KeyWriter::compare_key_ds1990(iButtonKey* key) { bool result = false; if(key->get_key_type() == iButtonKeyType::KeyDallas) { - __disable_irq(); + FURI_CRITICAL_ENTER(); bool presence = onewire_master->reset(); if(presence) { @@ -89,7 +89,7 @@ bool KeyWriter::compare_key_ds1990(iButtonKey* key) { } } - __enable_irq(); + FURI_CRITICAL_EXIT(); } return result; @@ -99,7 +99,7 @@ bool KeyWriter::write_1990_1(iButtonKey* key) { bool result = false; if(key->get_key_type() == iButtonKeyType::KeyDallas) { - __disable_irq(); + FURI_CRITICAL_ENTER(); // unlock onewire_master->reset(); @@ -120,7 +120,7 @@ bool KeyWriter::write_1990_1(iButtonKey* key) { onewire_master->write(RW1990_1::CMD_WRITE_RECORD_FLAG); onewire_write_one_bit(1); - __enable_irq(); + FURI_CRITICAL_EXIT(); if(compare_key_ds1990(key)) { result = true; @@ -134,7 +134,7 @@ bool KeyWriter::write_1990_2(iButtonKey* key) { bool result = false; if(key->get_key_type() == iButtonKeyType::KeyDallas) { - __disable_irq(); + FURI_CRITICAL_ENTER(); // unlock onewire_master->reset(); @@ -154,7 +154,7 @@ bool KeyWriter::write_1990_2(iButtonKey* key) { onewire_master->write(RW1990_2::CMD_WRITE_RECORD_FLAG); onewire_write_one_bit(0); - __enable_irq(); + FURI_CRITICAL_EXIT(); if(compare_key_ds1990(key)) { result = true; @@ -169,7 +169,7 @@ bool KeyWriter::write_TM2004(iButtonKey* key) { bool result = true; if(key->get_key_type() == iButtonKeyType::KeyDallas) { - __disable_irq(); + FURI_CRITICAL_ENTER(); // write rom, addr is 0x0000 onewire_master->reset(); @@ -204,7 +204,7 @@ bool KeyWriter::write_TM2004(iButtonKey* key) { onewire_master->reset(); - __enable_irq(); + FURI_CRITICAL_EXIT(); } else { result = false; } @@ -216,7 +216,7 @@ bool KeyWriter::write_TM01(iButtonKey* key) { /*bool result = true; // TODO test and encoding - __disable_irq(); + FURI_CRITICAL_ENTER(); // unlock onewire_master->reset(); @@ -240,13 +240,13 @@ bool KeyWriter::write_TM01(iButtonKey* key) { onewire_master->write(TM01::CMD_WRITE_RECORD_FLAG); onewire_write_one_bit(0, 10000); - __enable_irq(); + FURI_CRITICAL_EXIT(); if(!compare_key_ds1990(key)) { result = false; } - __disable_irq(); + FURI_CRITICAL_ENTER(); if(key->get_key_type() == iButtonKeyType::KeyMetakom || key->get_key_type() == iButtonKeyType::KeyCyfral) { @@ -258,7 +258,7 @@ bool KeyWriter::write_TM01(iButtonKey* key) { onewire_write_one_bit(1); } - __enable_irq(); + FURI_CRITICAL_EXIT(); return result;*/ return false; @@ -275,4 +275,4 @@ void KeyWriter::write_byte_ds1990(uint8_t data) { delay_us(5000); data = data >> 1; } -} \ No newline at end of file +} diff --git a/applications/lfrfid/helpers/rfid_writer.cpp b/applications/lfrfid/helpers/rfid_writer.cpp index 90fc1651..b3b221ee 100644 --- a/applications/lfrfid/helpers/rfid_writer.cpp +++ b/applications/lfrfid/helpers/rfid_writer.cpp @@ -121,12 +121,12 @@ void RfidWriter::write_em(const uint8_t em_data[5]) { em_card.encode(em_data, 5, reinterpret_cast(&em_encoded_data), sizeof(uint64_t)); const uint32_t em_config_block_data = 0b00000000000101001000000001000000; - __disable_irq(); + FURI_CRITICAL_ENTER(); write_block(0, 0, false, em_config_block_data); write_block(0, 1, false, em_encoded_data); write_block(0, 2, false, em_encoded_data >> 32); write_reset(); - __enable_irq(); + FURI_CRITICAL_EXIT(); } void RfidWriter::write_hid(const uint8_t hid_data[3]) { @@ -136,13 +136,13 @@ void RfidWriter::write_hid(const uint8_t hid_data[3]) { const uint32_t hid_config_block_data = 0b00000000000100000111000001100000; - __disable_irq(); + FURI_CRITICAL_ENTER(); write_block(0, 0, false, hid_config_block_data); write_block(0, 1, false, card_data[0]); write_block(0, 2, false, card_data[1]); write_block(0, 3, false, card_data[2]); write_reset(); - __enable_irq(); + FURI_CRITICAL_EXIT(); } void RfidWriter::write_indala(const uint8_t indala_data[3]) { @@ -153,10 +153,10 @@ void RfidWriter::write_indala(const uint8_t indala_data[3]) { const uint32_t indala_config_block_data = 0b00000000000010000001000001000000; - __disable_irq(); + FURI_CRITICAL_ENTER(); write_block(0, 0, false, indala_config_block_data); write_block(0, 1, false, card_data[0]); write_block(0, 2, false, card_data[1]); write_reset(); - __enable_irq(); + FURI_CRITICAL_EXIT(); } diff --git a/applications/loader/loader.c b/applications/loader/loader.c index d131de49..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" @@ -9,28 +10,46 @@ static Loader* loader_instance = NULL; +static bool + loader_start_application(const FlipperApplication* application, const char* arguments) { + loader_instance->application = application; + + furi_assert(loader_instance->application_arguments == NULL); + if(arguments && strlen(arguments) > 0) { + loader_instance->application_arguments = strdup(arguments); + } + + FURI_LOG_I(TAG, "Starting: %s", loader_instance->application->name); + + furi_thread_set_name(loader_instance->application_thread, loader_instance->application->name); + furi_thread_set_stack_size( + loader_instance->application_thread, loader_instance->application->stack_size); + furi_thread_set_context( + loader_instance->application_thread, loader_instance->application_arguments); + furi_thread_set_callback( + loader_instance->application_thread, loader_instance->application->app); + + bool result = furi_thread_start(loader_instance->application_thread); + + if(!result) { + loader_instance->application = NULL; + } + + return result; +} + static void loader_menu_callback(void* _ctx, uint32_t index) { - const FlipperApplication* flipper_app = _ctx; + const FlipperApplication* application = _ctx; - furi_assert(flipper_app->app); - furi_assert(flipper_app->name); + furi_assert(application->app); + furi_assert(application->name); - if(!loader_lock(loader_instance)) return; - - if(furi_thread_get_state(loader_instance->thread) != FuriThreadStateStopped) { - FURI_LOG_E(TAG, "Can't start app. %s is running", loader_instance->current_app->name); + if(!loader_lock(loader_instance)) { + FURI_LOG_E(TAG, "Loader is locked"); return; } - furi_hal_power_insomnia_enter(); - loader_instance->current_app = flipper_app; - - FURI_LOG_I(TAG, "Starting: %s", loader_instance->current_app->name); - furi_thread_set_name(loader_instance->thread, flipper_app->name); - furi_thread_set_stack_size(loader_instance->thread, flipper_app->stack_size); - furi_thread_set_context(loader_instance->thread, NULL); - furi_thread_set_callback(loader_instance->thread, flipper_app->app); - furi_thread_start(loader_instance->thread); + loader_start_application(application, NULL); } static void loader_submenu_callback(void* context, uint32_t index) { @@ -61,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) { @@ -73,32 +98,36 @@ const FlipperApplication* loader_find_application_by_name(const char* name) { } void loader_cli_open(Cli* cli, string_t args, Loader* instance) { - string_strim(args); + string_t application_name; + string_init(application_name); - if(string_size(args) == 0) { - printf("No application provided\r\n"); - return; - } + do { + if(!args_read_probably_quoted_string_and_trim(args, application_name)) { + printf("No application provided\r\n"); + break; + } - const FlipperApplication* application = loader_find_application_by_name(string_get_cstr(args)); - if(!application) { - printf("%s doesn't exists\r\n", string_get_cstr(args)); - return; - } + const FlipperApplication* application = + loader_find_application_by_name(string_get_cstr(application_name)); + if(!application) { + printf("%s doesn't exists\r\n", string_get_cstr(application_name)); + break; + } - if(furi_thread_get_state(instance->thread) != FuriThreadStateStopped) { - printf("Can't start, furi application is running"); - return; - } + string_strim(args); + if(!loader_start_application(application, string_get_cstr(args))) { + printf("Can't start, furi application is running"); + return; + } else { + // We must to increment lock counter to keep balance + // TODO: rewrite whole thing, it's complex as hell + FURI_CRITICAL_ENTER(); + instance->lock_count++; + FURI_CRITICAL_EXIT(); + } + } while(false); - instance->lock_semaphore++; - furi_hal_power_insomnia_enter(); - instance->current_app = application; - printf("Starting: %s\r\n", instance->current_app->name); - furi_thread_set_name(instance->thread, application->name); - furi_thread_set_stack_size(instance->thread, application->stack_size); - furi_thread_set_callback(instance->thread, application->app); - furi_thread_start(instance->thread); + string_clear(application_name); } void loader_cli_list(Cli* cli, string_t args, Loader* instance) { @@ -152,62 +181,44 @@ void loader_cli(Cli* cli, string_t args, void* _ctx) { LoaderStatus loader_start(Loader* instance, const char* name, const char* args) { furi_assert(name); - const FlipperApplication* flipper_app = loader_find_application_by_name(name); + const FlipperApplication* application = loader_find_application_by_name(name); - if(!flipper_app) { + if(!application) { FURI_LOG_E(TAG, "Can't find application with name %s", name); return LoaderStatusErrorUnknownApp; } - bool locked = loader_lock(instance); - - if(!locked || (furi_thread_get_state(instance->thread) != FuriThreadStateStopped)) { - FURI_LOG_E(TAG, "Can't start app. %s is running", instance->current_app->name); - /* no need to call loader_unlock() - it is called as soon as application stops */ + if(!loader_lock(loader_instance)) { + FURI_LOG_E(TAG, "Loader is locked"); return LoaderStatusErrorAppStarted; } - instance->current_app = flipper_app; - void* thread_args = NULL; - if(args) { - string_set_str(instance->args, args); - string_strim(instance->args); - thread_args = (void*)string_get_cstr(instance->args); - FURI_LOG_I(TAG, "Start %s app with args: %s", name, args); - } else { - string_reset(instance->args); - FURI_LOG_I(TAG, "Start %s app with no args", name); + if(!loader_start_application(application, args)) { + return LoaderStatusErrorInternal; } - furi_thread_set_name(instance->thread, flipper_app->name); - furi_thread_set_stack_size(instance->thread, flipper_app->stack_size); - furi_thread_set_context(instance->thread, thread_args); - furi_thread_set_callback(instance->thread, flipper_app->app); - - bool thread_started = furi_thread_start(instance->thread); - return thread_started ? LoaderStatusOk : LoaderStatusErrorInternal; + return LoaderStatusOk; } bool loader_lock(Loader* instance) { - bool ret = false; - furi_check(osMutexAcquire(instance->mutex, osWaitForever) == osOK); - if(instance->lock_semaphore == 0) { - instance->lock_semaphore++; - ret = true; + FURI_CRITICAL_ENTER(); + bool result = false; + if(instance->lock_count == 0) { + instance->lock_count++; + result = true; } - furi_check(osMutexRelease(instance->mutex) == osOK); - return ret; + FURI_CRITICAL_EXIT(); + return result; } void loader_unlock(Loader* instance) { - furi_check(osMutexAcquire(instance->mutex, osWaitForever) == osOK); - furi_check(instance->lock_semaphore > 0); - instance->lock_semaphore--; - furi_check(osMutexRelease(instance->mutex) == osOK); + FURI_CRITICAL_ENTER(); + if(instance->lock_count > 0) instance->lock_count--; + FURI_CRITICAL_EXIT(); } bool loader_is_locked(Loader* instance) { - return (instance->lock_semaphore > 0); + return instance->lock_count > 0; } static void loader_thread_state_callback(FuriThreadState thread_state, void* context) { @@ -219,6 +230,7 @@ static void loader_thread_state_callback(FuriThreadState thread_state, void* con if(thread_state == FuriThreadStateRunning) { event.type = LoaderEventTypeApplicationStarted; furi_pubsub_publish(loader_instance->pubsub, &event); + furi_hal_power_insomnia_enter(); // Snapshot current memory usage instance->free_heap_size = memmgr_get_free_heap(); @@ -239,7 +251,13 @@ static void loader_thread_state_callback(FuriThreadState thread_state, void* con TAG, "Application thread stopped. Heap allocation balance: %d. Thread allocation balance: %d.", heap_diff, - furi_thread_get_heap_size(instance->thread)); + furi_thread_get_heap_size(instance->application_thread)); + + if(loader_instance->application_arguments) { + free(loader_instance->application_arguments); + loader_instance->application_arguments = NULL; + } + furi_hal_power_insomnia_exit(); loader_unlock(instance); @@ -262,15 +280,12 @@ static uint32_t loader_back_to_primary_menu(void* context) { static Loader* loader_alloc() { Loader* instance = furi_alloc(sizeof(Loader)); - instance->thread = furi_thread_alloc(); - furi_thread_enable_heap_trace(instance->thread); - furi_thread_set_state_context(instance->thread, instance); - furi_thread_set_state_callback(instance->thread, loader_thread_state_callback); - - string_init(instance->args); + instance->application_thread = furi_thread_alloc(); + furi_thread_enable_heap_trace(instance->application_thread); + furi_thread_set_state_context(instance->application_thread, instance); + furi_thread_set_state_callback(instance->application_thread, loader_thread_state_callback); instance->pubsub = furi_pubsub_alloc(); - instance->mutex = osMutexNew(NULL); #ifdef SRV_CLI instance->cli = furi_record_open("cli"); @@ -327,13 +342,9 @@ static void loader_free(Loader* instance) { furi_record_close("cli"); } - osMutexDelete(instance->mutex); - furi_pubsub_free(instance->pubsub); - string_clear(instance->args); - - furi_thread_free(instance->thread); + furi_thread_free(instance->application_thread); menu_free(loader_instance->primary_menu); view_dispatcher_remove_view(loader_instance->view_dispatcher, LoaderMenuViewPrimary); diff --git a/applications/loader/loader_i.h b/applications/loader/loader_i.h index 3e628769..a8b8bfc0 100644 --- a/applications/loader/loader_i.h +++ b/applications/loader/loader_i.h @@ -16,9 +16,11 @@ struct Loader { osThreadId_t loader_thread; - FuriThread* thread; - const FlipperApplication* current_app; - string_t args; + + const FlipperApplication* application; + FuriThread* application_thread; + char* application_arguments; + Cli* cli; Gui* gui; @@ -29,8 +31,7 @@ struct Loader { Submenu* settings_menu; size_t free_heap_size; - osMutexId_t mutex; - volatile uint8_t lock_semaphore; + volatile uint8_t lock_count; FuriPubSub* pubsub; }; diff --git a/applications/power/power_cli.c b/applications/power/power_cli.c index 689a4e83..7550a006 100644 --- a/applications/power/power_cli.c +++ b/applications/power/power_cli.c @@ -1,28 +1,29 @@ #include "power_cli.h" -#include -#include #include +#include +#include +#include -void power_cli_poweroff(Cli* cli, string_t args, void* context) { +void power_cli_off(Cli* cli, string_t args) { Power* power = furi_record_open("power"); printf("It's now safe to disconnect USB from your flipper\r\n"); power_off(power); } -void power_cli_reboot(Cli* cli, string_t args, void* context) { +void power_cli_reboot(Cli* cli, string_t args) { power_reboot(PowerBootModeNormal); } -void power_cli_dfu(Cli* cli, string_t args, void* context) { +void power_cli_reboot2dfu(Cli* cli, string_t args) { power_reboot(PowerBootModeDfu); } -void power_cli_info(Cli* cli, string_t args, void* context) { +void power_cli_debug(Cli* cli, string_t args) { furi_hal_power_dump_state(); } -void power_cli_otg(Cli* cli, string_t args, void* context) { +void power_cli_5v(Cli* cli, string_t args) { if(!string_cmp(args, "0")) { furi_hal_power_disable_otg(); } else if(!string_cmp(args, "1")) { @@ -32,7 +33,7 @@ void power_cli_otg(Cli* cli, string_t args, void* context) { } } -void power_cli_ext(Cli* cli, string_t args, void* context) { +void power_cli_3v3(Cli* cli, string_t args) { if(!string_cmp(args, "0")) { furi_hal_power_disable_external_3_3v(); } else if(!string_cmp(args, "1")) { @@ -42,16 +43,70 @@ void power_cli_ext(Cli* cli, string_t args, void* context) { } } +static void power_cli_command_print_usage() { + printf("Usage:\r\n"); + printf("power \r\n"); + printf("Cmd list:\r\n"); + + printf("\toff\t - shutdown power\r\n"); + printf("\treboot\t - reboot\r\n"); + printf("\treboot2dfu\t - reboot to dfu bootloader\r\n"); + printf("\tdebug\t - show debug information\r\n"); + printf("\t5v <0 or 1>\t - enable or disable 5v ext\r\n"); + printf("\t3v3 <0 or 1>\t - enable or disable 3v3 ext\r\n"); +} + +void power_cli(Cli* cli, string_t args, void* context) { + string_t cmd; + string_init(cmd); + + do { + if(!args_read_string_and_trim(args, cmd)) { + power_cli_command_print_usage(); + break; + } + + if(string_cmp_str(cmd, "off") == 0) { + power_cli_off(cli, args); + break; + } + + if(string_cmp_str(cmd, "reboot") == 0) { + power_cli_reboot(cli, args); + break; + } + + if(string_cmp_str(cmd, "reboot2dfu") == 0) { + power_cli_reboot2dfu(cli, args); + break; + } + + if(string_cmp_str(cmd, "debug") == 0) { + power_cli_debug(cli, args); + break; + } + + if(string_cmp_str(cmd, "5v") == 0) { + power_cli_5v(cli, args); + break; + } + + if(string_cmp_str(cmd, "3v3") == 0) { + power_cli_3v3(cli, args); + break; + } + + power_cli_command_print_usage(); + } while(false); + + string_clear(cmd); +} + void power_on_system_start() { #ifdef SRV_CLI Cli* cli = furi_record_open("cli"); - cli_add_command(cli, "poweroff", CliCommandFlagParallelSafe, power_cli_poweroff, NULL); - cli_add_command(cli, "reboot", CliCommandFlagParallelSafe, power_cli_reboot, NULL); - cli_add_command(cli, "dfu", CliCommandFlagParallelSafe, power_cli_dfu, NULL); - cli_add_command(cli, "power_info", CliCommandFlagParallelSafe, power_cli_info, NULL); - cli_add_command(cli, "power_otg", CliCommandFlagParallelSafe, power_cli_otg, NULL); - cli_add_command(cli, "power_ext", CliCommandFlagParallelSafe, power_cli_ext, NULL); + cli_add_command(cli, "power", CliCommandFlagParallelSafe, power_cli, NULL); furi_record_close("cli"); #endif diff --git a/applications/power/power_service/power_api.c b/applications/power/power_service/power_api.c index 32407032..a92bfd00 100644 --- a/applications/power/power_service/power_api.c +++ b/applications/power/power_service/power_api.c @@ -10,7 +10,7 @@ void power_off(Power* power) { view_dispatcher_send_to_front(power->view_dispatcher); view_dispatcher_switch_to_view(power->view_dispatcher, PowerViewPopup); osDelay(10); - furi_crash("Disconnect USB for safe shutdown"); + furi_halt("Disconnect USB for safe shutdown"); } void power_reboot(PowerBootMode mode) { diff --git a/applications/subghz/helpers/subghz_custom_event.h b/applications/subghz/helpers/subghz_custom_event.h index 55363c41..5fee3541 100644 --- a/applications/subghz/helpers/subghz_custom_event.h +++ b/applications/subghz/helpers/subghz_custom_event.h @@ -3,6 +3,7 @@ typedef enum { SubghzCustomEventManagerNoSet = 0, SubghzCustomEventManagerSet, + SubghzCustomEventManagerSetRAW, SubghzCustomEventSceneDeleteSuccess = 100, SubghzCustomEventSceneDelete, diff --git a/applications/subghz/scenes/subghz_scene_read_raw.c b/applications/subghz/scenes/subghz_scene_read_raw.c index 170d3c7d..b8659057 100644 --- a/applications/subghz/scenes/subghz_scene_read_raw.c +++ b/applications/subghz/scenes/subghz_scene_read_raw.c @@ -261,7 +261,7 @@ bool subghz_scene_read_raw_on_event(void* context, SceneManagerEvent event) { case SubghzCustomEventViewReadRAWSave: if(subghz_scene_read_raw_update_filename(subghz)) { scene_manager_set_scene_state( - subghz->scene_manager, SubGhzSceneReadRAW, SubghzCustomEventManagerSet); + subghz->scene_manager, SubGhzSceneReadRAW, SubghzCustomEventManagerSetRAW); subghz->txrx->rx_key_state = SubGhzRxKeyStateBack; scene_manager_next_scene(subghz->scene_manager, SubGhzSceneSaveName); } diff --git a/applications/subghz/scenes/subghz_scene_save_name.c b/applications/subghz/scenes/subghz_scene_save_name.c index ee1df00f..27db3ca6 100644 --- a/applications/subghz/scenes/subghz_scene_save_name.c +++ b/applications/subghz/scenes/subghz_scene_save_name.c @@ -23,9 +23,13 @@ void subghz_scene_save_name_on_enter(void* context) { dev_name_empty = true; } else { strcpy(subghz->file_name_tmp, subghz->file_name); - if(scene_manager_get_scene_state(subghz->scene_manager, SubGhzSceneReadRAW) == - SubghzCustomEventManagerSet) { + if(scene_manager_get_scene_state(subghz->scene_manager, SubGhzSceneReadRAW) != + SubghzCustomEventManagerNoSet) { subghz_get_next_name_file(subghz); + if(scene_manager_get_scene_state(subghz->scene_manager, SubGhzSceneReadRAW) == + SubghzCustomEventManagerSetRAW) { + dev_name_empty = true; + } } } @@ -62,8 +66,8 @@ bool subghz_scene_save_name_on_event(void* context, SceneManagerEvent event) { subghz_save_protocol_to_file(subghz, subghz->file_name); } - if(scene_manager_get_scene_state(subghz->scene_manager, SubGhzSceneReadRAW) == - SubghzCustomEventManagerSet) { + if(scene_manager_get_scene_state(subghz->scene_manager, SubGhzSceneReadRAW) != + SubghzCustomEventManagerNoSet) { subghz_protocol_raw_set_last_file_name( (SubGhzProtocolRAW*)subghz->txrx->protocol_result, subghz->file_name); scene_manager_set_scene_state( diff --git a/applications/u2f/scenes/u2f_scene_main.c b/applications/u2f/scenes/u2f_scene_main.c index 4ff5e601..ede8e305 100644 --- a/applications/u2f/scenes/u2f_scene_main.c +++ b/applications/u2f/scenes/u2f_scene_main.c @@ -28,6 +28,8 @@ static void u2f_scene_main_event_callback(U2fNotifyEvent evt, void* context) { view_dispatcher_send_custom_event(app->view_dispatcher, U2fCustomEventConnect); else if(evt == U2fNotifyDisconnect) view_dispatcher_send_custom_event(app->view_dispatcher, U2fCustomEventDisconnect); + else if(evt == U2fNotifyError) + view_dispatcher_send_custom_event(app->view_dispatcher, U2fCustomEventDataError); } static void u2f_scene_main_timer_callback(void* context) { @@ -75,10 +77,13 @@ bool u2f_scene_main_on_event(void* context, SceneManagerEvent event) { if(app->event_cur != U2fCustomEventNone) { u2f_confirm_user_present(app->u2f_instance); } + } else if(event.event == U2fCustomEventDataError) { + osTimerStop(app->timer); + u2f_view_set_state(app->u2f_view, U2fMsgError); } consumed = true; - } else if(event.type == SceneManagerEventTypeTick) { } + return consumed; } diff --git a/applications/u2f/u2f.c b/applications/u2f/u2f.c index 4f952e68..2a1286ef 100644 --- a/applications/u2f/u2f.c +++ b/applications/u2f/u2f.c @@ -186,6 +186,13 @@ static uint16_t u2f_register(U2fData* U2F, uint8_t* buf) { uint8_t hash[32]; uint8_t signature[64]; + if(u2f_data_check(false) == false) { + U2F->ready = false; + if(U2F->callback != NULL) U2F->callback(U2fNotifyError, U2F->context); + memcpy(&buf[0], state_not_supported, 2); + return 2; + } + if(U2F->callback != NULL) U2F->callback(U2fNotifyRegister, U2F->context); if(U2F->user_present == false) { memcpy(&buf[0], state_user_missing, 2); @@ -250,6 +257,13 @@ static uint16_t u2f_authenticate(U2fData* U2F, uint8_t* buf) { uint8_t hash[32]; uint8_t signature[64]; + if(u2f_data_check(false) == false) { + U2F->ready = false; + if(U2F->callback != NULL) U2F->callback(U2fNotifyError, U2F->context); + memcpy(&buf[0], state_not_supported, 2); + return 2; + } + if(U2F->callback != NULL) U2F->callback(U2fNotifyAuth, U2F->context); if(U2F->user_present == true) { flags |= 1; diff --git a/applications/u2f/u2f.h b/applications/u2f/u2f.h index 4e10a3ea..dcd7c3ff 100644 --- a/applications/u2f/u2f.h +++ b/applications/u2f/u2f.h @@ -13,6 +13,7 @@ typedef enum { U2fNotifyWink, U2fNotifyConnect, U2fNotifyDisconnect, + U2fNotifyError, } U2fNotifyEvent; typedef struct U2fData U2fData; diff --git a/applications/u2f/u2f_app.c b/applications/u2f/u2f_app.c index f2e55730..9dde0f0d 100644 --- a/applications/u2f/u2f_app.c +++ b/applications/u2f/u2f_app.c @@ -48,7 +48,7 @@ U2fApp* u2f_app_alloc() { view_dispatcher_add_view( app->view_dispatcher, U2fAppViewMain, u2f_view_get_view(app->u2f_view)); - if(u2f_data_check()) { + if(u2f_data_check(true)) { scene_manager_next_scene(app->scene_manager, U2fSceneMain); } else { scene_manager_next_scene(app->scene_manager, U2fSceneError); diff --git a/applications/u2f/u2f_app_i.h b/applications/u2f/u2f_app_i.h index 33092ba3..41048b31 100644 --- a/applications/u2f/u2f_app_i.h +++ b/applications/u2f/u2f_app_i.h @@ -20,6 +20,7 @@ typedef enum { U2fCustomEventConnect, U2fCustomEventDisconnect, + U2fCustomEventDataError, U2fCustomEventRegister, U2fCustomEventAuth, diff --git a/applications/u2f/u2f_data.c b/applications/u2f/u2f_data.c index f517d222..e39eb95c 100644 --- a/applications/u2f/u2f_data.c +++ b/applications/u2f/u2f_data.c @@ -38,17 +38,25 @@ typedef struct { uint32_t control; } __attribute__((packed)) U2fCounterData; -bool u2f_data_check() { +bool u2f_data_check(bool cert_only) { bool state = false; Storage* fs_api = furi_record_open("storage"); File* file = storage_file_alloc(fs_api); - if(storage_file_open(file, U2F_CERT_FILE, FSAM_READ, FSOM_OPEN_EXISTING)) { + do { + if(!storage_file_open(file, U2F_CERT_FILE, FSAM_READ, FSOM_OPEN_EXISTING)) break; storage_file_close(file); - if(storage_file_open(file, U2F_CERT_KEY_FILE, FSAM_READ, FSOM_OPEN_EXISTING)) { + if(!storage_file_open(file, U2F_CERT_KEY_FILE, FSAM_READ, FSOM_OPEN_EXISTING)) break; + if(cert_only) { state = true; + break; } - } + storage_file_close(file); + if(!storage_file_open(file, U2F_KEY_FILE, FSAM_READ, FSOM_OPEN_EXISTING)) break; + storage_file_close(file); + if(!storage_file_open(file, U2F_CNT_FILE, FSAM_READ, FSOM_OPEN_EXISTING)) break; + state = true; + } while(0); storage_file_close(file); storage_file_free(file); diff --git a/applications/u2f/u2f_data.h b/applications/u2f/u2f_data.h index a96704eb..8d392346 100644 --- a/applications/u2f/u2f_data.h +++ b/applications/u2f/u2f_data.h @@ -6,7 +6,7 @@ extern "C" { #include -bool u2f_data_check(); +bool u2f_data_check(bool cert_only); bool u2f_data_cert_check(); diff --git a/applications/u2f/views/u2f_view.c b/applications/u2f/views/u2f_view.c index c810d141..8a6f441a 100644 --- a/applications/u2f/views/u2f_view.c +++ b/applications/u2f/views/u2f_view.c @@ -96,6 +96,6 @@ void u2f_view_set_state(U2fView* u2f, U2fViewMsg msg) { with_view_model( u2f->view, (U2fModel * model) { model->display_msg = msg; - return false; + return true; }); } diff --git a/assets/compiled/assets_icons.c b/assets/compiled/assets_icons.c index 409f7034..f45b0719 100644 --- a/assets/compiled/assets_icons.c +++ b/assets/compiled/assets_icons.c @@ -40,6 +40,9 @@ const uint8_t *_I_125_10px[] = {_I_125_10px_0}; const uint8_t _I_Nfc_10px_0[] = {0x00,0x80,0x00,0x00,0x01,0x22,0x02,0x43,0x02,0x45,0x02,0x49,0x02,0x31,0x02,0x22,0x02,0x00,0x01,0x80,0x00,}; const uint8_t *_I_Nfc_10px[] = {_I_Nfc_10px_0}; +const uint8_t _I_badusb_10px_0[] = {0x01,0x00,0x11,0x00,0x00,0x0f,0xe2,0x01,0xfc,0x80,0xdd,0x20,0x32,0x48,0x08,0x14,0x40,0x23,0xa8,0x08,0xa0,}; +const uint8_t *_I_badusb_10px[] = {_I_badusb_10px_0}; + const uint8_t _I_ble_10px_0[] = {0x00,0x04,0x00,0x8C,0x00,0x15,0x01,0x56,0x02,0x8C,0x02,0x8C,0x02,0x56,0x02,0x15,0x01,0x8C,0x00,0x04,0x00,}; const uint8_t *_I_ble_10px[] = {_I_ble_10px_0}; @@ -55,6 +58,9 @@ const uint8_t *_I_ir_10px[] = {_I_ir_10px_0}; const uint8_t _I_sub1_10px_0[] = {0x01,0x00,0x12,0x00,0x81,0x40,0x69,0x30,0x2c,0x2c,0x0b,0x6a,0x01,0x28,0x0c,0x0a,0x65,0x01,0x98,0x40,0x00,0x26,}; const uint8_t *_I_sub1_10px[] = {_I_sub1_10px_0}; +const uint8_t _I_u2f_10px_0[] = {0x00,0x00,0x00,0xFE,0x01,0x01,0x02,0x0C,0x00,0xF2,0x03,0x92,0x02,0x0C,0x00,0x01,0x02,0xFE,0x01,0x00,0x00,}; +const uint8_t *_I_u2f_10px[] = {_I_u2f_10px_0}; + const uint8_t _I_unknown_10px_0[] = {0x01,0x00,0x12,0x00,0xbc,0x40,0x39,0x90,0x0c,0x24,0x03,0x81,0x00,0xb0,0x40,0x26,0x00,0x12,0x00,0x08,0x14,0xc0,}; const uint8_t *_I_unknown_10px[] = {_I_unknown_10px_0}; @@ -199,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}; @@ -441,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}; @@ -525,9 +558,6 @@ const uint8_t *_I_Cry_dolph_55x52[] = {_I_Cry_dolph_55x52_0}; const uint8_t _I_Attention_5x8_0[] = {0x00,0x0E,0x0A,0x0A,0x0A,0x0E,0x04,0x00,0x0E,}; const uint8_t *_I_Attention_5x8[] = {_I_Attention_5x8_0}; -const uint8_t _I_BT_Pair_9x8_0[] = {0x00,0x11,0x01,0x35,0x00,0x58,0x01,0x31,0x00,0x30,0x01,0x59,0x00,0x34,0x01,0x11,0x01,}; -const uint8_t *_I_BT_Pair_9x8[] = {_I_BT_Pair_9x8_0}; - const uint8_t _I_Background_128x11_0[] = {0x01,0x00,0x70,0x00,0xff,0x40,0x40,0xc9,0xe0,0xff,0x80,0x06,0x1e,0x08,0x38,0x0c,0x0c,0x1e,0x93,0x00,0x19,0x46,0x01,0x07,0x7d,0x83,0x03,0xd2,0x31,0xff,0xdb,0xd5,0x66,0x20,0x83,0xc0,0xff,0x05,0x24,0x00,0x1c,0x78,0x28,0xbc,0x40,0x72,0xbf,0xcf,0x47,0xeb,0x40,0xdb,0x7a,0xbf,0xf0,0x40,0x39,0x60,0x28,0x3f,0xe0,0xa0,0xea,0x80,0x63,0x3f,0x0b,0x17,0xe4,0x3e,0x5a,0xbc,0xf9,0x99,0x70,0x1f,0x81,0x50,0xc0,0x80,0xe7,0x3e,0x1e,0x9d,0x57,0xfb,0x7f,0x23,0x15,0xb0,0x12,0x5b,0x5b,0x02,0x1d,0x8c,0xc3,0x80,0x24,0x9e,0x03,0x80,0x5e,0x40,0x00,0xa1,0x88,0x0e,0x98,0x00,0x7b,0x07,0x08,0xb2,0x44,0x41,}; const uint8_t *_I_Background_128x11[] = {_I_Background_128x11_0}; @@ -540,8 +570,11 @@ const uint8_t *_I_Battery_19x8[] = {_I_Battery_19x8_0}; const uint8_t _I_Battery_26x8_0[] = {0x01,0x00,0x13,0x00,0xff,0x7f,0xef,0xf0,0x08,0x0c,0x03,0x00,0x03,0x38,0x18,0x0c,0xa0,0x40,0x36,0x05,0x98,0x6d,0x00,}; const uint8_t *_I_Battery_26x8[] = {_I_Battery_26x8_0}; -const uint8_t _I_Bluetooth_5x8_0[] = {0x00,0x04,0x0D,0x16,0x0C,0x0C,0x16,0x0D,0x04,}; -const uint8_t *_I_Bluetooth_5x8[] = {_I_Bluetooth_5x8_0}; +const uint8_t _I_Bluetooth_Connected_16x8_0[] = {0x00,0x04,0x00,0x0D,0x00,0x16,0x60,0x4C,0x97,0x4C,0x97,0x16,0x60,0x0D,0x00,0x04,0x00,}; +const uint8_t *_I_Bluetooth_Connected_16x8[] = {_I_Bluetooth_Connected_16x8_0}; + +const uint8_t _I_Bluetooth_Idle_5x8_0[] = {0x00,0x04,0x0D,0x16,0x0C,0x0C,0x16,0x0D,0x04,}; +const uint8_t *_I_Bluetooth_Idle_5x8[] = {_I_Bluetooth_Idle_5x8_0}; const uint8_t _I_Charging_lightning_9x10_0[] = {0x00,0x40,0x01,0xA0,0x00,0x50,0x00,0xE8,0x01,0x84,0x00,0x42,0x00,0x2F,0x00,0x14,0x00,0x0A,0x00,0x05,0x00,}; const uint8_t *_I_Charging_lightning_9x10[] = {_I_Charging_lightning_9x10_0}; @@ -624,11 +657,13 @@ const Icon A_Levelup1_128x64 = {.width=128,.height=64,.frame_count=11,.frame_rat const Icon A_Levelup2_128x64 = {.width=128,.height=64,.frame_count=11,.frame_rate=2,.frames=_A_Levelup2_128x64}; const Icon I_125_10px = {.width=10,.height=10,.frame_count=1,.frame_rate=0,.frames=_I_125_10px}; const Icon I_Nfc_10px = {.width=10,.height=10,.frame_count=1,.frame_rate=0,.frames=_I_Nfc_10px}; +const Icon I_badusb_10px = {.width=10,.height=10,.frame_count=1,.frame_rate=0,.frames=_I_badusb_10px}; const Icon I_ble_10px = {.width=10,.height=10,.frame_count=1,.frame_rate=0,.frames=_I_ble_10px}; const Icon I_dir_10px = {.width=10,.height=10,.frame_count=1,.frame_rate=0,.frames=_I_dir_10px}; const Icon I_ibutt_10px = {.width=10,.height=10,.frame_count=1,.frame_rate=0,.frames=_I_ibutt_10px}; const Icon I_ir_10px = {.width=10,.height=10,.frame_count=1,.frame_rate=0,.frames=_I_ir_10px}; const Icon I_sub1_10px = {.width=10,.height=10,.frame_count=1,.frame_rate=0,.frames=_I_sub1_10px}; +const Icon I_u2f_10px = {.width=10,.height=10,.frame_count=1,.frame_rate=0,.frames=_I_u2f_10px}; const Icon I_unknown_10px = {.width=10,.height=10,.frame_count=1,.frame_rate=0,.frames=_I_unknown_10px}; const Icon I_BLE_Pairing_128x64 = {.width=128,.height=64,.frame_count=1,.frame_rate=0,.frames=_I_BLE_Pairing_128x64}; const Icon I_Ble_connected_38x34 = {.width=38,.height=34,.frame_count=1,.frame_rate=0,.frames=_I_Ble_connected_38x34}; @@ -677,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}; @@ -725,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}; @@ -753,12 +797,12 @@ const Icon I_SDError_43x35 = {.width=43,.height=35,.frame_count=1,.frame_rate=0, const Icon I_SDQuestion_35x43 = {.width=35,.height=43,.frame_count=1,.frame_rate=0,.frames=_I_SDQuestion_35x43}; const Icon I_Cry_dolph_55x52 = {.width=55,.height=52,.frame_count=1,.frame_rate=0,.frames=_I_Cry_dolph_55x52}; const Icon I_Attention_5x8 = {.width=5,.height=8,.frame_count=1,.frame_rate=0,.frames=_I_Attention_5x8}; -const Icon I_BT_Pair_9x8 = {.width=9,.height=8,.frame_count=1,.frame_rate=0,.frames=_I_BT_Pair_9x8}; const Icon I_Background_128x11 = {.width=128,.height=11,.frame_count=1,.frame_rate=0,.frames=_I_Background_128x11}; const Icon I_BadUsb_9x8 = {.width=9,.height=8,.frame_count=1,.frame_rate=0,.frames=_I_BadUsb_9x8}; const Icon I_Battery_19x8 = {.width=19,.height=8,.frame_count=1,.frame_rate=0,.frames=_I_Battery_19x8}; const Icon I_Battery_26x8 = {.width=26,.height=8,.frame_count=1,.frame_rate=0,.frames=_I_Battery_26x8}; -const Icon I_Bluetooth_5x8 = {.width=5,.height=8,.frame_count=1,.frame_rate=0,.frames=_I_Bluetooth_5x8}; +const Icon I_Bluetooth_Connected_16x8 = {.width=16,.height=8,.frame_count=1,.frame_rate=0,.frames=_I_Bluetooth_Connected_16x8}; +const Icon I_Bluetooth_Idle_5x8 = {.width=5,.height=8,.frame_count=1,.frame_rate=0,.frames=_I_Bluetooth_Idle_5x8}; const Icon I_Charging_lightning_9x10 = {.width=9,.height=10,.frame_count=1,.frame_rate=0,.frames=_I_Charging_lightning_9x10}; const Icon I_Charging_lightning_mask_9x10 = {.width=9,.height=10,.frame_count=1,.frame_rate=0,.frames=_I_Charging_lightning_mask_9x10}; const Icon I_Lock_8x8 = {.width=8,.height=8,.frame_count=1,.frame_rate=0,.frames=_I_Lock_8x8}; diff --git a/assets/compiled/assets_icons.h b/assets/compiled/assets_icons.h index 3b756c1b..26e26bef 100644 --- a/assets/compiled/assets_icons.h +++ b/assets/compiled/assets_icons.h @@ -7,11 +7,13 @@ extern const Icon A_Levelup1_128x64; extern const Icon A_Levelup2_128x64; extern const Icon I_125_10px; extern const Icon I_Nfc_10px; +extern const Icon I_badusb_10px; extern const Icon I_ble_10px; extern const Icon I_dir_10px; extern const Icon I_ibutt_10px; extern const Icon I_ir_10px; extern const Icon I_sub1_10px; +extern const Icon I_u2f_10px; extern const Icon I_unknown_10px; extern const Icon I_BLE_Pairing_128x64; extern const Icon I_Ble_connected_38x34; @@ -60,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; @@ -108,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; @@ -136,12 +147,12 @@ extern const Icon I_SDError_43x35; extern const Icon I_SDQuestion_35x43; extern const Icon I_Cry_dolph_55x52; extern const Icon I_Attention_5x8; -extern const Icon I_BT_Pair_9x8; extern const Icon I_Background_128x11; extern const Icon I_BadUsb_9x8; extern const Icon I_Battery_19x8; extern const Icon I_Battery_26x8; -extern const Icon I_Bluetooth_5x8; +extern const Icon I_Bluetooth_Connected_16x8; +extern const Icon I_Bluetooth_Idle_5x8; extern const Icon I_Charging_lightning_9x10; extern const Icon I_Charging_lightning_mask_9x10; extern const Icon I_Lock_8x8; diff --git a/assets/dolphin/external/L1_Boxing_128x64/frame_0.png b/assets/dolphin/external/L1_Boxing_128x64/frame_0.png new file mode 100644 index 00000000..b6b2c75b Binary files /dev/null and b/assets/dolphin/external/L1_Boxing_128x64/frame_0.png differ diff --git a/assets/dolphin/external/L1_Boxing_128x64/frame_1.png b/assets/dolphin/external/L1_Boxing_128x64/frame_1.png new file mode 100644 index 00000000..347d71cc Binary files /dev/null and b/assets/dolphin/external/L1_Boxing_128x64/frame_1.png differ diff --git a/assets/dolphin/external/L1_Boxing_128x64/frame_2.png b/assets/dolphin/external/L1_Boxing_128x64/frame_2.png new file mode 100644 index 00000000..51a7fd23 Binary files /dev/null and b/assets/dolphin/external/L1_Boxing_128x64/frame_2.png differ diff --git a/assets/dolphin/external/L1_Boxing_128x64/frame_3.png b/assets/dolphin/external/L1_Boxing_128x64/frame_3.png new file mode 100644 index 00000000..7004e10c Binary files /dev/null and b/assets/dolphin/external/L1_Boxing_128x64/frame_3.png differ diff --git a/assets/dolphin/external/L1_Boxing_128x64/frame_4.png b/assets/dolphin/external/L1_Boxing_128x64/frame_4.png new file mode 100644 index 00000000..556cb894 Binary files /dev/null and b/assets/dolphin/external/L1_Boxing_128x64/frame_4.png differ diff --git a/assets/dolphin/external/L1_Boxing_128x64/frame_5.png b/assets/dolphin/external/L1_Boxing_128x64/frame_5.png new file mode 100644 index 00000000..fd617034 Binary files /dev/null and b/assets/dolphin/external/L1_Boxing_128x64/frame_5.png differ diff --git a/assets/dolphin/external/L1_Boxing_128x64/frame_6.png b/assets/dolphin/external/L1_Boxing_128x64/frame_6.png new file mode 100644 index 00000000..34839517 Binary files /dev/null and b/assets/dolphin/external/L1_Boxing_128x64/frame_6.png differ diff --git a/assets/dolphin/external/L1_Boxing_128x64/meta.txt b/assets/dolphin/external/L1_Boxing_128x64/meta.txt new file mode 100644 index 00000000..c66998e7 --- /dev/null +++ b/assets/dolphin/external/L1_Boxing_128x64/meta.txt @@ -0,0 +1,32 @@ +Filetype: Flipper Animation +Version: 1 + +Width: 128 +Height: 64 +Passive frames: 9 +Active frames: 7 +Frames order: 0 1 2 1 3 1 2 3 1 4 5 6 5 6 5 4 +Active cycles: 1 +Frame rate: 2 +Duration: 3600 +Active cooldown: 7 + +Bubble slots: 2 + +Slot: 0 +X: 78 +Y: 16 +Text: F*&K!!! +AlignH: Left +AlignV: Bottom +StartFrame: 2 +EndFrame: 4 + +Slot: 1 +X: 78 +Y: 16 +Text: What ya\nlookin at?! +AlignH: Left +AlignV: Center +StartFrame: 10 +EndFrame: 15 diff --git a/assets/dolphin/external/L1_Cry_128x64/frame_0.png b/assets/dolphin/external/L1_Cry_128x64/frame_0.png new file mode 100644 index 00000000..b2636f00 Binary files /dev/null and b/assets/dolphin/external/L1_Cry_128x64/frame_0.png differ diff --git a/assets/dolphin/external/L1_Cry_128x64/frame_1.png b/assets/dolphin/external/L1_Cry_128x64/frame_1.png new file mode 100644 index 00000000..e73499e9 Binary files /dev/null and b/assets/dolphin/external/L1_Cry_128x64/frame_1.png differ diff --git a/assets/dolphin/external/L1_Cry_128x64/frame_2.png b/assets/dolphin/external/L1_Cry_128x64/frame_2.png new file mode 100644 index 00000000..16005a99 Binary files /dev/null and b/assets/dolphin/external/L1_Cry_128x64/frame_2.png differ diff --git a/assets/dolphin/external/L1_Cry_128x64/frame_3.png b/assets/dolphin/external/L1_Cry_128x64/frame_3.png new file mode 100644 index 00000000..02e833de Binary files /dev/null and b/assets/dolphin/external/L1_Cry_128x64/frame_3.png differ diff --git a/assets/dolphin/external/L1_Cry_128x64/frame_4.png b/assets/dolphin/external/L1_Cry_128x64/frame_4.png new file mode 100644 index 00000000..3f7dff4d Binary files /dev/null and b/assets/dolphin/external/L1_Cry_128x64/frame_4.png differ diff --git a/assets/dolphin/external/L1_Cry_128x64/frame_5.png b/assets/dolphin/external/L1_Cry_128x64/frame_5.png new file mode 100644 index 00000000..38510678 Binary files /dev/null and b/assets/dolphin/external/L1_Cry_128x64/frame_5.png differ diff --git a/assets/dolphin/external/L1_Cry_128x64/frame_6.png b/assets/dolphin/external/L1_Cry_128x64/frame_6.png new file mode 100644 index 00000000..7871674d Binary files /dev/null and b/assets/dolphin/external/L1_Cry_128x64/frame_6.png differ diff --git a/assets/dolphin/external/L1_Cry_128x64/frame_7.png b/assets/dolphin/external/L1_Cry_128x64/frame_7.png new file mode 100644 index 00000000..5865e91e Binary files /dev/null and b/assets/dolphin/external/L1_Cry_128x64/frame_7.png differ diff --git a/assets/dolphin/external/L1_Cry_128x64/meta.txt b/assets/dolphin/external/L1_Cry_128x64/meta.txt new file mode 100644 index 00000000..e96c8d7c --- /dev/null +++ b/assets/dolphin/external/L1_Cry_128x64/meta.txt @@ -0,0 +1,41 @@ +Filetype: Flipper Animation +Version: 1 + +Width: 128 +Height: 64 +Passive frames: 8 +Active frames: 4 +Frames order: 0 1 2 3 4 2 3 4 5 6 7 6 +Active cycles: 2 +Frame rate: 2 +Duration: 3600 +Active cooldown: 7 + +Bubble slots: 2 + +Slot: 0 +X: 22 +Y: 40 +Text: I miss you +AlignH: Right +AlignV: Bottom +StartFrame: 9 +EndFrame: 11 + +Slot: 0 +X: 17 +Y: 40 +Text: my friend... +AlignH: Right +AlignV: Bottom +StartFrame: 12 +EndFrame: 15 + +Slot: 1 +X: 2 +Y: 29 +Text: Why are you\nalways away? +AlignH: Right +AlignV: Bottom +StartFrame: 9 +EndFrame: 15 \ No newline at end of file diff --git a/assets/dolphin/external/L1_Read_books_128x64/frame_0.png b/assets/dolphin/external/L1_Read_books_128x64/frame_0.png new file mode 100644 index 00000000..fbf26528 Binary files /dev/null and b/assets/dolphin/external/L1_Read_books_128x64/frame_0.png differ diff --git a/assets/dolphin/external/L1_Read_books_128x64/frame_1.png b/assets/dolphin/external/L1_Read_books_128x64/frame_1.png new file mode 100644 index 00000000..be9c5dc1 Binary files /dev/null and b/assets/dolphin/external/L1_Read_books_128x64/frame_1.png differ diff --git a/assets/dolphin/external/L1_Read_books_128x64/frame_2.png b/assets/dolphin/external/L1_Read_books_128x64/frame_2.png new file mode 100644 index 00000000..eb8075ec Binary files /dev/null and b/assets/dolphin/external/L1_Read_books_128x64/frame_2.png differ diff --git a/assets/dolphin/external/L1_Read_books_128x64/frame_3.png b/assets/dolphin/external/L1_Read_books_128x64/frame_3.png new file mode 100644 index 00000000..0f1fd5c5 Binary files /dev/null and b/assets/dolphin/external/L1_Read_books_128x64/frame_3.png differ diff --git a/assets/dolphin/external/L1_Read_books_128x64/frame_4.png b/assets/dolphin/external/L1_Read_books_128x64/frame_4.png new file mode 100644 index 00000000..dd2d918a Binary files /dev/null and b/assets/dolphin/external/L1_Read_books_128x64/frame_4.png differ diff --git a/assets/dolphin/external/L1_Read_books_128x64/frame_5.png b/assets/dolphin/external/L1_Read_books_128x64/frame_5.png new file mode 100644 index 00000000..bfcc7bcd Binary files /dev/null and b/assets/dolphin/external/L1_Read_books_128x64/frame_5.png differ diff --git a/assets/dolphin/external/L1_Read_books_128x64/frame_6.png b/assets/dolphin/external/L1_Read_books_128x64/frame_6.png new file mode 100644 index 00000000..eabe9def Binary files /dev/null and b/assets/dolphin/external/L1_Read_books_128x64/frame_6.png differ diff --git a/assets/dolphin/external/L1_Read_books_128x64/frame_7.png b/assets/dolphin/external/L1_Read_books_128x64/frame_7.png new file mode 100644 index 00000000..3ff0aee0 Binary files /dev/null and b/assets/dolphin/external/L1_Read_books_128x64/frame_7.png differ diff --git a/assets/dolphin/external/L1_Read_books_128x64/frame_8.png b/assets/dolphin/external/L1_Read_books_128x64/frame_8.png new file mode 100644 index 00000000..ce663f75 Binary files /dev/null and b/assets/dolphin/external/L1_Read_books_128x64/frame_8.png differ diff --git a/assets/dolphin/external/L1_Read_books_128x64/meta.txt b/assets/dolphin/external/L1_Read_books_128x64/meta.txt new file mode 100644 index 00000000..7432507c --- /dev/null +++ b/assets/dolphin/external/L1_Read_books_128x64/meta.txt @@ -0,0 +1,23 @@ +Filetype: Flipper Animation +Version: 1 + +Width: 128 +Height: 64 +Passive frames: 13 +Active frames: 2 +Frames order: 0 1 0 2 3 3 4 0 1 5 6 1 1 7 8 +Active cycles: 2 +Frame rate: 2 +Duration: 3600 +Active cooldown: 5 + +Bubble slots: 1 + +Slot: 0 +X: 5 +Y: 28 +Text: Predictable twist +AlignH: Right +AlignV: Bottom +StartFrame: 14 +EndFrame: 16 diff --git a/assets/dolphin/external/L2_Hacking_pc_128x64/frame_0.png b/assets/dolphin/external/L2_Hacking_pc_128x64/frame_0.png new file mode 100644 index 00000000..d303aef0 Binary files /dev/null and b/assets/dolphin/external/L2_Hacking_pc_128x64/frame_0.png differ diff --git a/assets/dolphin/external/L2_Hacking_pc_128x64/frame_1.png b/assets/dolphin/external/L2_Hacking_pc_128x64/frame_1.png new file mode 100644 index 00000000..45aeb57b Binary files /dev/null and b/assets/dolphin/external/L2_Hacking_pc_128x64/frame_1.png differ diff --git a/assets/dolphin/external/L2_Hacking_pc_128x64/frame_2.png b/assets/dolphin/external/L2_Hacking_pc_128x64/frame_2.png new file mode 100644 index 00000000..a4508f14 Binary files /dev/null and b/assets/dolphin/external/L2_Hacking_pc_128x64/frame_2.png differ diff --git a/assets/dolphin/external/L2_Hacking_pc_128x64/frame_3.png b/assets/dolphin/external/L2_Hacking_pc_128x64/frame_3.png new file mode 100644 index 00000000..35000216 Binary files /dev/null and b/assets/dolphin/external/L2_Hacking_pc_128x64/frame_3.png differ diff --git a/assets/dolphin/external/L2_Hacking_pc_128x64/frame_4.png b/assets/dolphin/external/L2_Hacking_pc_128x64/frame_4.png new file mode 100644 index 00000000..7addbf93 Binary files /dev/null and b/assets/dolphin/external/L2_Hacking_pc_128x64/frame_4.png differ diff --git a/assets/dolphin/external/L2_Hacking_pc_128x64/meta.txt b/assets/dolphin/external/L2_Hacking_pc_128x64/meta.txt new file mode 100644 index 00000000..8ad8d42a --- /dev/null +++ b/assets/dolphin/external/L2_Hacking_pc_128x64/meta.txt @@ -0,0 +1,32 @@ +Filetype: Flipper Animation +Version: 1 + +Width: 128 +Height: 64 +Passive frames: 3 +Active frames: 2 +Frames order: 0 1 2 3 4 +Active cycles: 4 +Frame rate: 2 +Duration: 3600 +Active cooldown: 7 + +Bubble slots: 1 + +Slot: 0 +X: 22 +Y: 25 +Text: Mess with\nthe best, +AlignH: Right +AlignV: Center +StartFrame: 4 +EndFrame: 7 + +Slot: 0 +X: 31 +Y: 25 +Text: die like\nthe rest. +AlignH: Right +AlignV: Center +StartFrame: 8 +EndFrame: 10 diff --git a/assets/dolphin/external/manifest.txt b/assets/dolphin/external/manifest.txt index d5a8e2a1..d6e16dd1 100644 --- a/assets/dolphin/external/manifest.txt +++ b/assets/dolphin/external/manifest.txt @@ -1,7 +1,6 @@ Filetype: Flipper Animation Manifest Version: 1 -# Animation 1 Name: L1_Waves_128x50 Min butthurt: 0 Max butthurt: 5 @@ -9,7 +8,6 @@ Min level: 1 Max level: 3 Weight: 3 -# Animation 2 Name: L1_Laptop_128x51 Min butthurt: 0 Max butthurt: 9 @@ -17,7 +15,6 @@ Min level: 1 Max level: 3 Weight: 3 -# Animation 3 Name: L1_Sleep_128x64 Min butthurt: 0 Max butthurt: 10 @@ -25,7 +22,6 @@ Min level: 1 Max level: 3 Weight: 3 -# Animation 4 Name: L1_Recording_128x51 Min butthurt: 0 Max butthurt: 8 @@ -33,7 +29,6 @@ Min level: 1 Max level: 1 Weight: 3 -# Animation 5 Name: L1_Furippa1_128x64 Min butthurt: 0 Max butthurt: 6 @@ -41,7 +36,6 @@ Min level: 1 Max level: 1 Weight: 3 -# Animation 6 Name: L2_Furippa2_128x64 Min butthurt: 0 Max butthurt: 6 @@ -49,10 +43,37 @@ Min level: 2 Max level: 2 Weight: 3 -# Animation 7 Name: L3_Furippa3_128x64 Min butthurt: 0 Max butthurt: 6 Min level: 3 Max level: 3 Weight: 3 + +Name: L1_Read_books_128x64 +Min butthurt: 0 +Max butthurt: 8 +Min level: 1 +Max level: 1 +Weight: 3 + +Name: L2_Hacking_pc_128x64 +Min butthurt: 0 +Max butthurt: 8 +Min level: 2 +Max level: 2 +Weight: 3 + +Name: L1_Cry_128x64 +Min butthurt: 8 +Max butthurt: 13 +Min level: 1 +Max level: 3 +Weight: 3 + +Name: L1_Boxing_128x64 +Min butthurt: 10 +Max butthurt: 13 +Min level: 1 +Max level: 3 +Weight: 3 diff --git a/assets/icons/Archive/badusb_10px.png b/assets/icons/Archive/badusb_10px.png new file mode 100644 index 00000000..037474aa Binary files /dev/null and b/assets/icons/Archive/badusb_10px.png differ diff --git a/assets/icons/Archive/u2f_10px.png b/assets/icons/Archive/u2f_10px.png new file mode 100644 index 00000000..fcd87a2e Binary files /dev/null and b/assets/icons/Archive/u2f_10px.png differ 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/assets/icons/StatusBar/BT_Pair_9x8.png b/assets/icons/StatusBar/BT_Pair_9x8.png deleted file mode 100644 index 4382cc74..00000000 Binary files a/assets/icons/StatusBar/BT_Pair_9x8.png and /dev/null differ diff --git a/assets/icons/StatusBar/Bluetooth_Connected_16x8.png b/assets/icons/StatusBar/Bluetooth_Connected_16x8.png new file mode 100644 index 00000000..c77bc149 Binary files /dev/null and b/assets/icons/StatusBar/Bluetooth_Connected_16x8.png differ diff --git a/assets/icons/StatusBar/Bluetooth_5x8.png b/assets/icons/StatusBar/Bluetooth_Idle_5x8.png similarity index 100% rename from assets/icons/StatusBar/Bluetooth_5x8.png rename to assets/icons/StatusBar/Bluetooth_Idle_5x8.png diff --git a/assets/resources/dolphin/L1_Boxing_128x64/frame_0.bm b/assets/resources/dolphin/L1_Boxing_128x64/frame_0.bm new file mode 100644 index 00000000..46079c37 Binary files /dev/null and b/assets/resources/dolphin/L1_Boxing_128x64/frame_0.bm differ diff --git a/assets/resources/dolphin/L1_Boxing_128x64/frame_1.bm b/assets/resources/dolphin/L1_Boxing_128x64/frame_1.bm new file mode 100644 index 00000000..e12d7079 Binary files /dev/null and b/assets/resources/dolphin/L1_Boxing_128x64/frame_1.bm differ diff --git a/assets/resources/dolphin/L1_Boxing_128x64/frame_2.bm b/assets/resources/dolphin/L1_Boxing_128x64/frame_2.bm new file mode 100644 index 00000000..b416740f Binary files /dev/null and b/assets/resources/dolphin/L1_Boxing_128x64/frame_2.bm differ diff --git a/assets/resources/dolphin/L1_Boxing_128x64/frame_3.bm b/assets/resources/dolphin/L1_Boxing_128x64/frame_3.bm new file mode 100644 index 00000000..b7e15dde Binary files /dev/null and b/assets/resources/dolphin/L1_Boxing_128x64/frame_3.bm differ diff --git a/assets/resources/dolphin/L1_Boxing_128x64/frame_4.bm b/assets/resources/dolphin/L1_Boxing_128x64/frame_4.bm new file mode 100644 index 00000000..202ad6e3 Binary files /dev/null and b/assets/resources/dolphin/L1_Boxing_128x64/frame_4.bm differ diff --git a/assets/resources/dolphin/L1_Boxing_128x64/frame_5.bm b/assets/resources/dolphin/L1_Boxing_128x64/frame_5.bm new file mode 100644 index 00000000..cdc0a2a3 Binary files /dev/null and b/assets/resources/dolphin/L1_Boxing_128x64/frame_5.bm differ diff --git a/assets/resources/dolphin/L1_Boxing_128x64/frame_6.bm b/assets/resources/dolphin/L1_Boxing_128x64/frame_6.bm new file mode 100644 index 00000000..e8ea3aa6 Binary files /dev/null and b/assets/resources/dolphin/L1_Boxing_128x64/frame_6.bm differ diff --git a/assets/resources/dolphin/L1_Boxing_128x64/meta.txt b/assets/resources/dolphin/L1_Boxing_128x64/meta.txt new file mode 100644 index 00000000..c66998e7 --- /dev/null +++ b/assets/resources/dolphin/L1_Boxing_128x64/meta.txt @@ -0,0 +1,32 @@ +Filetype: Flipper Animation +Version: 1 + +Width: 128 +Height: 64 +Passive frames: 9 +Active frames: 7 +Frames order: 0 1 2 1 3 1 2 3 1 4 5 6 5 6 5 4 +Active cycles: 1 +Frame rate: 2 +Duration: 3600 +Active cooldown: 7 + +Bubble slots: 2 + +Slot: 0 +X: 78 +Y: 16 +Text: F*&K!!! +AlignH: Left +AlignV: Bottom +StartFrame: 2 +EndFrame: 4 + +Slot: 1 +X: 78 +Y: 16 +Text: What ya\nlookin at?! +AlignH: Left +AlignV: Center +StartFrame: 10 +EndFrame: 15 diff --git a/assets/resources/dolphin/L1_Cry_128x64/frame_0.bm b/assets/resources/dolphin/L1_Cry_128x64/frame_0.bm new file mode 100644 index 00000000..9147714c Binary files /dev/null and b/assets/resources/dolphin/L1_Cry_128x64/frame_0.bm differ diff --git a/assets/resources/dolphin/L1_Cry_128x64/frame_1.bm b/assets/resources/dolphin/L1_Cry_128x64/frame_1.bm new file mode 100644 index 00000000..789273d9 Binary files /dev/null and b/assets/resources/dolphin/L1_Cry_128x64/frame_1.bm differ diff --git a/assets/resources/dolphin/L1_Cry_128x64/frame_2.bm b/assets/resources/dolphin/L1_Cry_128x64/frame_2.bm new file mode 100644 index 00000000..a3c87e0a Binary files /dev/null and b/assets/resources/dolphin/L1_Cry_128x64/frame_2.bm differ diff --git a/assets/resources/dolphin/L1_Cry_128x64/frame_3.bm b/assets/resources/dolphin/L1_Cry_128x64/frame_3.bm new file mode 100644 index 00000000..ba3012b7 Binary files /dev/null and b/assets/resources/dolphin/L1_Cry_128x64/frame_3.bm differ diff --git a/assets/resources/dolphin/L1_Cry_128x64/frame_4.bm b/assets/resources/dolphin/L1_Cry_128x64/frame_4.bm new file mode 100644 index 00000000..1ce28c7a Binary files /dev/null and b/assets/resources/dolphin/L1_Cry_128x64/frame_4.bm differ diff --git a/assets/resources/dolphin/L1_Cry_128x64/frame_5.bm b/assets/resources/dolphin/L1_Cry_128x64/frame_5.bm new file mode 100644 index 00000000..4cbc4968 Binary files /dev/null and b/assets/resources/dolphin/L1_Cry_128x64/frame_5.bm differ diff --git a/assets/resources/dolphin/L1_Cry_128x64/frame_6.bm b/assets/resources/dolphin/L1_Cry_128x64/frame_6.bm new file mode 100644 index 00000000..cba81ef3 Binary files /dev/null and b/assets/resources/dolphin/L1_Cry_128x64/frame_6.bm differ diff --git a/assets/resources/dolphin/L1_Cry_128x64/frame_7.bm b/assets/resources/dolphin/L1_Cry_128x64/frame_7.bm new file mode 100644 index 00000000..da28419f Binary files /dev/null and b/assets/resources/dolphin/L1_Cry_128x64/frame_7.bm differ diff --git a/assets/resources/dolphin/L1_Cry_128x64/meta.txt b/assets/resources/dolphin/L1_Cry_128x64/meta.txt new file mode 100644 index 00000000..1b7d13dd --- /dev/null +++ b/assets/resources/dolphin/L1_Cry_128x64/meta.txt @@ -0,0 +1,41 @@ +Filetype: Flipper Animation +Version: 1 + +Width: 128 +Height: 64 +Passive frames: 8 +Active frames: 4 +Frames order: 0 1 2 3 4 2 3 4 5 6 7 6 +Active cycles: 2 +Frame rate: 2 +Duration: 3600 +Active cooldown: 7 + +Bubble slots: 2 + +Slot: 0 +X: 22 +Y: 40 +Text: I miss you +AlignH: Right +AlignV: Bottom +StartFrame: 9 +EndFrame: 11 + +Slot: 0 +X: 17 +Y: 40 +Text: my friend... +AlignH: Right +AlignV: Bottom +StartFrame: 12 +EndFrame: 15 + +Slot: 1 +X: 2 +Y: 29 +Text: Why are you\nalways away? +AlignH: Right +AlignV: Bottom +StartFrame: 9 +EndFrame: 15 diff --git a/assets/resources/dolphin/L1_Read_books_128x64/frame_0.bm b/assets/resources/dolphin/L1_Read_books_128x64/frame_0.bm new file mode 100644 index 00000000..1169e42d Binary files /dev/null and b/assets/resources/dolphin/L1_Read_books_128x64/frame_0.bm differ diff --git a/assets/resources/dolphin/L1_Read_books_128x64/frame_1.bm b/assets/resources/dolphin/L1_Read_books_128x64/frame_1.bm new file mode 100644 index 00000000..80e2f39b Binary files /dev/null and b/assets/resources/dolphin/L1_Read_books_128x64/frame_1.bm differ diff --git a/assets/resources/dolphin/L1_Read_books_128x64/frame_2.bm b/assets/resources/dolphin/L1_Read_books_128x64/frame_2.bm new file mode 100644 index 00000000..959b0255 Binary files /dev/null and b/assets/resources/dolphin/L1_Read_books_128x64/frame_2.bm differ diff --git a/assets/resources/dolphin/L1_Read_books_128x64/frame_3.bm b/assets/resources/dolphin/L1_Read_books_128x64/frame_3.bm new file mode 100644 index 00000000..8c106d90 Binary files /dev/null and b/assets/resources/dolphin/L1_Read_books_128x64/frame_3.bm differ diff --git a/assets/resources/dolphin/L1_Read_books_128x64/frame_4.bm b/assets/resources/dolphin/L1_Read_books_128x64/frame_4.bm new file mode 100644 index 00000000..389d2a8e Binary files /dev/null and b/assets/resources/dolphin/L1_Read_books_128x64/frame_4.bm differ diff --git a/assets/resources/dolphin/L1_Read_books_128x64/frame_5.bm b/assets/resources/dolphin/L1_Read_books_128x64/frame_5.bm new file mode 100644 index 00000000..4b65b6d9 Binary files /dev/null and b/assets/resources/dolphin/L1_Read_books_128x64/frame_5.bm differ diff --git a/assets/resources/dolphin/L1_Read_books_128x64/frame_6.bm b/assets/resources/dolphin/L1_Read_books_128x64/frame_6.bm new file mode 100644 index 00000000..451c80a2 Binary files /dev/null and b/assets/resources/dolphin/L1_Read_books_128x64/frame_6.bm differ diff --git a/assets/resources/dolphin/L1_Read_books_128x64/frame_7.bm b/assets/resources/dolphin/L1_Read_books_128x64/frame_7.bm new file mode 100644 index 00000000..41780907 Binary files /dev/null and b/assets/resources/dolphin/L1_Read_books_128x64/frame_7.bm differ diff --git a/assets/resources/dolphin/L1_Read_books_128x64/frame_8.bm b/assets/resources/dolphin/L1_Read_books_128x64/frame_8.bm new file mode 100644 index 00000000..4370393d Binary files /dev/null and b/assets/resources/dolphin/L1_Read_books_128x64/frame_8.bm differ diff --git a/assets/resources/dolphin/L1_Read_books_128x64/meta.txt b/assets/resources/dolphin/L1_Read_books_128x64/meta.txt new file mode 100644 index 00000000..7432507c --- /dev/null +++ b/assets/resources/dolphin/L1_Read_books_128x64/meta.txt @@ -0,0 +1,23 @@ +Filetype: Flipper Animation +Version: 1 + +Width: 128 +Height: 64 +Passive frames: 13 +Active frames: 2 +Frames order: 0 1 0 2 3 3 4 0 1 5 6 1 1 7 8 +Active cycles: 2 +Frame rate: 2 +Duration: 3600 +Active cooldown: 5 + +Bubble slots: 1 + +Slot: 0 +X: 5 +Y: 28 +Text: Predictable twist +AlignH: Right +AlignV: Bottom +StartFrame: 14 +EndFrame: 16 diff --git a/assets/resources/dolphin/L2_Hacking_pc_128x64/frame_0.bm b/assets/resources/dolphin/L2_Hacking_pc_128x64/frame_0.bm new file mode 100644 index 00000000..3ff70a91 Binary files /dev/null and b/assets/resources/dolphin/L2_Hacking_pc_128x64/frame_0.bm differ diff --git a/assets/resources/dolphin/L2_Hacking_pc_128x64/frame_1.bm b/assets/resources/dolphin/L2_Hacking_pc_128x64/frame_1.bm new file mode 100644 index 00000000..ed11583f Binary files /dev/null and b/assets/resources/dolphin/L2_Hacking_pc_128x64/frame_1.bm differ diff --git a/assets/resources/dolphin/L2_Hacking_pc_128x64/frame_2.bm b/assets/resources/dolphin/L2_Hacking_pc_128x64/frame_2.bm new file mode 100644 index 00000000..41850505 Binary files /dev/null and b/assets/resources/dolphin/L2_Hacking_pc_128x64/frame_2.bm differ diff --git a/assets/resources/dolphin/L2_Hacking_pc_128x64/frame_3.bm b/assets/resources/dolphin/L2_Hacking_pc_128x64/frame_3.bm new file mode 100644 index 00000000..d4b47960 Binary files /dev/null and b/assets/resources/dolphin/L2_Hacking_pc_128x64/frame_3.bm differ diff --git a/assets/resources/dolphin/L2_Hacking_pc_128x64/frame_4.bm b/assets/resources/dolphin/L2_Hacking_pc_128x64/frame_4.bm new file mode 100644 index 00000000..ee3a5f18 Binary files /dev/null and b/assets/resources/dolphin/L2_Hacking_pc_128x64/frame_4.bm differ diff --git a/assets/resources/dolphin/L2_Hacking_pc_128x64/meta.txt b/assets/resources/dolphin/L2_Hacking_pc_128x64/meta.txt new file mode 100644 index 00000000..8ad8d42a --- /dev/null +++ b/assets/resources/dolphin/L2_Hacking_pc_128x64/meta.txt @@ -0,0 +1,32 @@ +Filetype: Flipper Animation +Version: 1 + +Width: 128 +Height: 64 +Passive frames: 3 +Active frames: 2 +Frames order: 0 1 2 3 4 +Active cycles: 4 +Frame rate: 2 +Duration: 3600 +Active cooldown: 7 + +Bubble slots: 1 + +Slot: 0 +X: 22 +Y: 25 +Text: Mess with\nthe best, +AlignH: Right +AlignV: Center +StartFrame: 4 +EndFrame: 7 + +Slot: 0 +X: 31 +Y: 25 +Text: die like\nthe rest. +AlignH: Right +AlignV: Center +StartFrame: 8 +EndFrame: 10 diff --git a/assets/resources/dolphin/manifest.txt b/assets/resources/dolphin/manifest.txt index 8be65c11..d6e16dd1 100644 --- a/assets/resources/dolphin/manifest.txt +++ b/assets/resources/dolphin/manifest.txt @@ -49,3 +49,31 @@ Max butthurt: 6 Min level: 3 Max level: 3 Weight: 3 + +Name: L1_Read_books_128x64 +Min butthurt: 0 +Max butthurt: 8 +Min level: 1 +Max level: 1 +Weight: 3 + +Name: L2_Hacking_pc_128x64 +Min butthurt: 0 +Max butthurt: 8 +Min level: 2 +Max level: 2 +Weight: 3 + +Name: L1_Cry_128x64 +Min butthurt: 8 +Max butthurt: 13 +Min level: 1 +Max level: 3 +Weight: 3 + +Name: L1_Boxing_128x64 +Min butthurt: 10 +Max butthurt: 13 +Min level: 1 +Max level: 3 +Weight: 3 diff --git a/bootloader/targets/f6/furi_hal/furi_hal_gpio.c b/bootloader/targets/f6/furi_hal/furi_hal_gpio.c index 9cc991f3..9fd8f4f8 100644 --- a/bootloader/targets/f6/furi_hal/furi_hal_gpio.c +++ b/bootloader/targets/f6/furi_hal/furi_hal_gpio.c @@ -69,24 +69,36 @@ void hal_gpio_init_ex( // Configure gpio with interrupts disabled __disable_irq(); + // Set gpio speed - if(speed == GpioSpeedLow) { + switch(speed) { + case GpioSpeedLow: LL_GPIO_SetPinSpeed(gpio->port, gpio->pin, LL_GPIO_SPEED_FREQ_LOW); - } else if(speed == GpioSpeedMedium) { + break; + case GpioSpeedMedium: LL_GPIO_SetPinSpeed(gpio->port, gpio->pin, LL_GPIO_SPEED_FREQ_MEDIUM); - } else if(speed == GpioSpeedHigh) { + break; + case GpioSpeedHigh: LL_GPIO_SetPinSpeed(gpio->port, gpio->pin, LL_GPIO_SPEED_FREQ_HIGH); - } else { + break; + case GpioSpeedVeryHigh: LL_GPIO_SetPinSpeed(gpio->port, gpio->pin, LL_GPIO_SPEED_FREQ_VERY_HIGH); + break; } + // Set gpio pull mode - if(pull == GpioPullNo) { + switch(pull) { + case GpioPullNo: LL_GPIO_SetPinPull(gpio->port, gpio->pin, LL_GPIO_PULL_NO); - } else if(pull == GpioPullUp) { + break; + case GpioPullUp: LL_GPIO_SetPinPull(gpio->port, gpio->pin, LL_GPIO_PULL_UP); - } else { + break; + case GpioPullDown: LL_GPIO_SetPinPull(gpio->port, gpio->pin, LL_GPIO_PULL_DOWN); + break; } + // Set gpio mode if(mode >= GpioModeInterruptRise) { // Set pin in interrupt mode @@ -100,45 +112,59 @@ void hal_gpio_init_ex( LL_EXTI_EnableIT_0_31(exti_line); LL_EXTI_EnableFallingTrig_0_31(exti_line); } - if(mode == GpioModeEventRise || mode == GpioModeInterruptRiseFall) { + if(mode == GpioModeEventRise || mode == GpioModeEventRiseFall) { LL_EXTI_EnableEvent_0_31(exti_line); LL_EXTI_EnableRisingTrig_0_31(exti_line); } - if(mode == GpioModeEventFall || mode == GpioModeInterruptRiseFall) { + if(mode == GpioModeEventFall || mode == GpioModeEventRiseFall) { LL_EXTI_EnableEvent_0_31(exti_line); LL_EXTI_EnableFallingTrig_0_31(exti_line); } } else { - // Disable interrupt if it was set + // Disable interrupts if set if(LL_SYSCFG_GetEXTISource(sys_exti_line) == sys_exti_port && LL_EXTI_IsEnabledIT_0_31(exti_line)) { LL_EXTI_DisableIT_0_31(exti_line); LL_EXTI_DisableRisingTrig_0_31(exti_line); LL_EXTI_DisableFallingTrig_0_31(exti_line); } - // Set not interrupt pin modes - if(mode == GpioModeInput) { - LL_GPIO_SetPinMode(gpio->port, gpio->pin, LL_GPIO_MODE_INPUT); - } else if(mode == GpioModeOutputPushPull || mode == GpioModeAltFunctionPushPull) { - LL_GPIO_SetPinMode(gpio->port, gpio->pin, LL_GPIO_MODE_OUTPUT); - LL_GPIO_SetPinOutputType(gpio->port, gpio->pin, LL_GPIO_OUTPUT_PUSHPULL); - } else if(mode == GpioModeOutputOpenDrain || mode == GpioModeAltFunctionOpenDrain) { - LL_GPIO_SetPinMode(gpio->port, gpio->pin, LL_GPIO_MODE_OUTPUT); - LL_GPIO_SetPinOutputType(gpio->port, gpio->pin, LL_GPIO_OUTPUT_OPENDRAIN); - } else if(mode == GpioModeAnalog) { - LL_GPIO_SetPinMode(gpio->port, gpio->pin, LL_GPIO_MODE_ANALOG); + + // Prepare alternative part if any + if(mode == GpioModeAltFunctionPushPull || mode == GpioModeAltFunctionOpenDrain) { + // set alternate function + if(hal_gpio_get_pin_num(gpio) < 8) { + LL_GPIO_SetAFPin_0_7(gpio->port, gpio->pin, alt_fn); + } else { + LL_GPIO_SetAFPin_8_15(gpio->port, gpio->pin, alt_fn); + } } - } - if(mode == GpioModeAltFunctionPushPull || mode == GpioModeAltFunctionOpenDrain) { - // enable alternate mode - LL_GPIO_SetPinMode(gpio->port, gpio->pin, LL_GPIO_MODE_ALTERNATE); - - // set alternate function - if(hal_gpio_get_pin_num(gpio) < 8) { - LL_GPIO_SetAFPin_0_7(gpio->port, gpio->pin, alt_fn); - } else { - LL_GPIO_SetAFPin_8_15(gpio->port, gpio->pin, alt_fn); + // Set not interrupt pin modes + switch(mode) { + case GpioModeInput: + LL_GPIO_SetPinMode(gpio->port, gpio->pin, LL_GPIO_MODE_INPUT); + break; + case GpioModeOutputPushPull: + LL_GPIO_SetPinOutputType(gpio->port, gpio->pin, LL_GPIO_OUTPUT_PUSHPULL); + LL_GPIO_SetPinMode(gpio->port, gpio->pin, LL_GPIO_MODE_OUTPUT); + break; + case GpioModeAltFunctionPushPull: + LL_GPIO_SetPinOutputType(gpio->port, gpio->pin, LL_GPIO_OUTPUT_PUSHPULL); + LL_GPIO_SetPinMode(gpio->port, gpio->pin, LL_GPIO_MODE_ALTERNATE); + break; + case GpioModeOutputOpenDrain: + LL_GPIO_SetPinOutputType(gpio->port, gpio->pin, LL_GPIO_OUTPUT_OPENDRAIN); + LL_GPIO_SetPinMode(gpio->port, gpio->pin, LL_GPIO_MODE_OUTPUT); + break; + case GpioModeAltFunctionOpenDrain: + LL_GPIO_SetPinOutputType(gpio->port, gpio->pin, LL_GPIO_OUTPUT_OPENDRAIN); + LL_GPIO_SetPinMode(gpio->port, gpio->pin, LL_GPIO_MODE_ALTERNATE); + break; + case GpioModeAnalog: + LL_GPIO_SetPinMode(gpio->port, gpio->pin, LL_GPIO_MODE_ANALOG); + break; + default: + break; } } diff --git a/bootloader/targets/f7/furi_hal/furi_hal_gpio.c b/bootloader/targets/f7/furi_hal/furi_hal_gpio.c index 9cc991f3..a7c5c074 100644 --- a/bootloader/targets/f7/furi_hal/furi_hal_gpio.c +++ b/bootloader/targets/f7/furi_hal/furi_hal_gpio.c @@ -69,24 +69,36 @@ void hal_gpio_init_ex( // Configure gpio with interrupts disabled __disable_irq(); + // Set gpio speed - if(speed == GpioSpeedLow) { + switch(speed) { + case GpioSpeedLow: LL_GPIO_SetPinSpeed(gpio->port, gpio->pin, LL_GPIO_SPEED_FREQ_LOW); - } else if(speed == GpioSpeedMedium) { + break; + case GpioSpeedMedium: LL_GPIO_SetPinSpeed(gpio->port, gpio->pin, LL_GPIO_SPEED_FREQ_MEDIUM); - } else if(speed == GpioSpeedHigh) { + break; + case GpioSpeedHigh: LL_GPIO_SetPinSpeed(gpio->port, gpio->pin, LL_GPIO_SPEED_FREQ_HIGH); - } else { + break; + case GpioSpeedVeryHigh: LL_GPIO_SetPinSpeed(gpio->port, gpio->pin, LL_GPIO_SPEED_FREQ_VERY_HIGH); + break; } + // Set gpio pull mode - if(pull == GpioPullNo) { + switch(pull) { + case GpioPullNo: LL_GPIO_SetPinPull(gpio->port, gpio->pin, LL_GPIO_PULL_NO); - } else if(pull == GpioPullUp) { + break; + case GpioPullUp: LL_GPIO_SetPinPull(gpio->port, gpio->pin, LL_GPIO_PULL_UP); - } else { + break; + case GpioPullDown: LL_GPIO_SetPinPull(gpio->port, gpio->pin, LL_GPIO_PULL_DOWN); + break; } + // Set gpio mode if(mode >= GpioModeInterruptRise) { // Set pin in interrupt mode @@ -100,48 +112,61 @@ void hal_gpio_init_ex( LL_EXTI_EnableIT_0_31(exti_line); LL_EXTI_EnableFallingTrig_0_31(exti_line); } - if(mode == GpioModeEventRise || mode == GpioModeInterruptRiseFall) { + if(mode == GpioModeEventRise || mode == GpioModeEventRiseFall) { LL_EXTI_EnableEvent_0_31(exti_line); LL_EXTI_EnableRisingTrig_0_31(exti_line); } - if(mode == GpioModeEventFall || mode == GpioModeInterruptRiseFall) { + if(mode == GpioModeEventFall || mode == GpioModeEventRiseFall) { LL_EXTI_EnableEvent_0_31(exti_line); LL_EXTI_EnableFallingTrig_0_31(exti_line); } } else { - // Disable interrupt if it was set + // Disable interrupts if set if(LL_SYSCFG_GetEXTISource(sys_exti_line) == sys_exti_port && LL_EXTI_IsEnabledIT_0_31(exti_line)) { LL_EXTI_DisableIT_0_31(exti_line); LL_EXTI_DisableRisingTrig_0_31(exti_line); LL_EXTI_DisableFallingTrig_0_31(exti_line); } + + // Prepare alternative part if any + if(mode == GpioModeAltFunctionPushPull || mode == GpioModeAltFunctionOpenDrain) { + // set alternate function + if(hal_gpio_get_pin_num(gpio) < 8) { + LL_GPIO_SetAFPin_0_7(gpio->port, gpio->pin, alt_fn); + } else { + LL_GPIO_SetAFPin_8_15(gpio->port, gpio->pin, alt_fn); + } + } + // Set not interrupt pin modes - if(mode == GpioModeInput) { + switch(mode) { + case GpioModeInput: LL_GPIO_SetPinMode(gpio->port, gpio->pin, LL_GPIO_MODE_INPUT); - } else if(mode == GpioModeOutputPushPull || mode == GpioModeAltFunctionPushPull) { - LL_GPIO_SetPinMode(gpio->port, gpio->pin, LL_GPIO_MODE_OUTPUT); + break; + case GpioModeOutputPushPull: LL_GPIO_SetPinOutputType(gpio->port, gpio->pin, LL_GPIO_OUTPUT_PUSHPULL); - } else if(mode == GpioModeOutputOpenDrain || mode == GpioModeAltFunctionOpenDrain) { LL_GPIO_SetPinMode(gpio->port, gpio->pin, LL_GPIO_MODE_OUTPUT); + break; + case GpioModeAltFunctionPushPull: + LL_GPIO_SetPinOutputType(gpio->port, gpio->pin, LL_GPIO_OUTPUT_PUSHPULL); + LL_GPIO_SetPinMode(gpio->port, gpio->pin, LL_GPIO_MODE_ALTERNATE); + break; + case GpioModeOutputOpenDrain: LL_GPIO_SetPinOutputType(gpio->port, gpio->pin, LL_GPIO_OUTPUT_OPENDRAIN); - } else if(mode == GpioModeAnalog) { + LL_GPIO_SetPinMode(gpio->port, gpio->pin, LL_GPIO_MODE_OUTPUT); + break; + case GpioModeAltFunctionOpenDrain: + LL_GPIO_SetPinOutputType(gpio->port, gpio->pin, LL_GPIO_OUTPUT_OPENDRAIN); + LL_GPIO_SetPinMode(gpio->port, gpio->pin, LL_GPIO_MODE_ALTERNATE); + break; + case GpioModeAnalog: LL_GPIO_SetPinMode(gpio->port, gpio->pin, LL_GPIO_MODE_ANALOG); + break; + default: + break; } } - - if(mode == GpioModeAltFunctionPushPull || mode == GpioModeAltFunctionOpenDrain) { - // enable alternate mode - LL_GPIO_SetPinMode(gpio->port, gpio->pin, LL_GPIO_MODE_ALTERNATE); - - // set alternate function - if(hal_gpio_get_pin_num(gpio) < 8) { - LL_GPIO_SetAFPin_0_7(gpio->port, gpio->pin, alt_fn); - } else { - LL_GPIO_SetAFPin_8_15(gpio->port, gpio->pin, alt_fn); - } - } - __enable_irq(); } diff --git a/core/furi/check.c b/core/furi/check.c index e5f67f17..657e2905 100644 --- a/core/furi/check.c +++ b/core/furi/check.c @@ -4,7 +4,7 @@ #include #include -__attribute__((always_inline)) inline static void __furi_print_name() { +static void __furi_print_name() { if(task_is_isr_context()) { furi_hal_console_puts("[ISR] "); } else { @@ -19,9 +19,9 @@ __attribute__((always_inline)) inline static void __furi_print_name() { } } -__attribute__((always_inline)) inline static void __furi_halt() { - asm volatile("bkpt 0x00 \n" - "loop: \n" +static void __furi_halt() { + asm volatile("loop: \n" + "bkpt 0x00 \n" "wfi \n" "b loop \n" : @@ -50,3 +50,18 @@ void furi_crash(const char* message) { NVIC_SystemReset(); #endif } + +void furi_halt(const char* message) { + __disable_irq(); + + if(message == NULL) { + message = "System halt requested."; + } + + furi_hal_console_puts("\r\n\033[0;31m[HALT]"); + __furi_print_name(); + furi_hal_console_puts(message); + furi_hal_console_puts("\r\nSystem halted. Bye-bye!\r\n"); + furi_hal_console_puts("\033[0m\r\n"); + __furi_halt(); +} diff --git a/core/furi/check.h b/core/furi/check.h index 8abd9bbb..b4b66815 100644 --- a/core/furi/check.h +++ b/core/furi/check.h @@ -17,6 +17,9 @@ extern "C" { /** Crash system */ void furi_crash(const char* message); +/** Halt system */ +void furi_halt(const char* message); + #ifdef __cplusplus } #endif diff --git a/firmware/targets/f6/ble_glue/ble_glue.c b/firmware/targets/f6/ble_glue/ble_glue.c index c38c0731..6e55b368 100644 --- a/firmware/targets/f6/ble_glue/ble_glue.c +++ b/firmware/targets/f6/ble_glue/ble_glue.c @@ -116,6 +116,7 @@ void ble_glue_init() { bool ble_glue_wait_for_fus_start(WirelessFwInfo_t* info) { bool ret = false; + size_t countdown = 1000; while(countdown > 0) { if(ble_glue->status == BleGlueStatusFusStarted) { @@ -125,13 +126,14 @@ bool ble_glue_wait_for_fus_start(WirelessFwInfo_t* info) { countdown--; osDelay(1); } + if(ble_glue->status == BleGlueStatusFusStarted) { SHCI_GetWirelessFwInfo(info); } else { FURI_LOG_E(TAG, "Failed to start FUS"); ble_glue->status = BleGlueStatusBroken; } - furi_hal_power_insomnia_exit(); + return ret; } diff --git a/firmware/targets/f6/cube/startup_stm32wb55xx_cm4.s b/firmware/targets/f6/cube/startup_stm32wb55xx_cm4.s index c5c2b3fc..053db01e 100644 --- a/firmware/targets/f6/cube/startup_stm32wb55xx_cm4.s +++ b/firmware/targets/f6/cube/startup_stm32wb55xx_cm4.s @@ -1,48 +1,48 @@ /** - ****************************************************************************** - * @file startup_stm32wb55xx_cm4.s - * @author MCD Application Team - * @brief STM32WB55xx devices vector table GCC toolchain. - * This module performs: - * - Set the initial SP - * - Set the initial PC == Reset_Handler, - * - Set the vector table entries with the exceptions ISR address - * - Branches to main in the C library (which eventually - * calls main()). - * After Reset the Cortex-M4 processor is in Thread mode, - * priority is Privileged, and the Stack is set to Main. - ****************************************************************************** - * @attention - * - * Copyright (c) 2019-2021 STMicroelectronics. - * All rights reserved. - * - * This software is licensed under terms that can be found in the LICENSE file - * in the root directory of this software component. - * If no LICENSE file comes with this software, it is provided AS-IS. - * - ****************************************************************************** - */ + ****************************************************************************** + * @file startup_stm32wb55xx_cm4.s + * @author MCD Application Team + * @brief STM32WB55xx devices vector table GCC toolchain. + * This module performs: + * - Set the initial SP + * - Set the initial PC == Reset_Handler, + * - Set the vector table entries with the exceptions ISR address + * - Branches to main in the C library (which eventually + * calls main()). + * After Reset the Cortex-M4 processor is in Thread mode, + * priority is Privileged, and the Stack is set to Main. + ****************************************************************************** + * @attention + * + * Copyright (c) 2019-2021 STMicroelectronics. + * All rights reserved. + * + * This software is licensed under terms that can be found in the LICENSE file + * in the root directory of this software component. + * If no LICENSE file comes with this software, it is provided AS-IS. + * + ****************************************************************************** + */ - .syntax unified - .cpu cortex-m4 - .fpu softvfp - .thumb +.syntax unified +.cpu cortex-m4 +.fpu softvfp +.thumb -.global g_pfnVectors -.global Default_Handler +.global g_pfnVectors +.global Default_Handler /* start address for the initialization values of the .data section. defined in linker script */ -.word _sidata +.word _sidata /* start address for the .data section. defined in linker script */ -.word _sdata +.word _sdata /* end address for the .data section. defined in linker script */ -.word _edata +.word _edata /* start address for the .bss section. defined in linker script */ -.word _sbss +.word _sbss /* end address for the .bss section. defined in linker script */ -.word _ebss +.word _ebss /* start address for the .MB_MEM2 section. defined in linker script */ .word _sMB_MEM2 /* end address for the .MB_MEM2 section. defined in linker script */ @@ -50,67 +50,69 @@ defined in linker script */ /* INIT_BSS macro is used to fill the specified region [start : end] with zeros */ .macro INIT_BSS start, end - ldr r0, =\start - ldr r1, =\end - movs r3, #0 - bl LoopFillZerobss + ldr r0, =\start + ldr r1, =\end + movs r3, #0 + bl LoopFillZerobss .endm /* INIT_DATA macro is used to copy data in the region [start : end] starting from 'src' */ .macro INIT_DATA start, end, src - ldr r0, =\start - ldr r1, =\end - ldr r2, =\src - movs r3, #0 - bl LoopCopyDataInit + ldr r0, =\start + ldr r1, =\end + ldr r2, =\src + movs r3, #0 + bl LoopCopyDataInit .endm .section .text.data_initializers CopyDataInit: - ldr r4, [r2, r3] - str r4, [r0, r3] - adds r3, r3, #4 + ldr r4, [r2, r3] + str r4, [r0, r3] + adds r3, r3, #4 LoopCopyDataInit: - adds r4, r0, r3 - cmp r4, r1 - bcc CopyDataInit - bx lr + adds r4, r0, r3 + cmp r4, r1 + bcc CopyDataInit + bx lr FillZerobss: - str r3, [r0] - adds r0, r0, #4 + str r3, [r0] + adds r0, r0, #4 LoopFillZerobss: - cmp r0, r1 - bcc FillZerobss - bx lr + cmp r0, r1 + bcc FillZerobss + bx lr + + +.section .text.Reset_Handler +.weak Reset_Handler +.type Reset_Handler, %function - .section .text.Reset_Handler - .weak Reset_Handler - .type Reset_Handler, %function Reset_Handler: - ldr r0, =_estack - mov sp, r0 /* set stack pointer */ -/* Call the clock system intitialization function.*/ - bl SystemInit + ldr r0, =_estack + mov sp, r0 /* set stack pointer */ + /* Call the clock system intitialization function.*/ + bl SystemInit /* Copy the data segment initializers from flash to SRAM */ - INIT_DATA _sdata, _edata, _sidata + INIT_DATA _sdata, _edata, _sidata /* Zero fill the bss segments. */ - INIT_BSS _sbss, _ebss - INIT_BSS _sMB_MEM2, _eMB_MEM2 + INIT_BSS _sbss, _ebss + INIT_BSS _sMB_MEM2, _eMB_MEM2 /* Call static constructors */ - bl __libc_init_array + bl __libc_init_array /* Call the application s entry point.*/ - bl main + bl main LoopForever: - b LoopForever - -.size Reset_Handler, .-Reset_Handler + b LoopForever + +.size Reset_Handler, .-Reset_Handler /** * @brief This is the code that gets called when the processor receives an @@ -120,11 +122,11 @@ LoopForever: * @param None * @retval None */ - .section .text.Default_Handler,"ax",%progbits + .section .text.Default_Handler,"ax",%progbits Default_Handler: Infinite_Loop: - b Infinite_Loop - .size Default_Handler, .-Default_Handler + b Infinite_Loop + .size Default_Handler, .-Default_Handler /****************************************************************************** * * The minimal vector table for a Cortex-M4. Note that the proper constructs @@ -132,91 +134,91 @@ Infinite_Loop: * 0x0000.0000. * ******************************************************************************/ - .section .isr_vector,"a",%progbits - .type g_pfnVectors, %object - .size g_pfnVectors, .-g_pfnVectors + .section .isr_vector,"a",%progbits + .type g_pfnVectors, %object + .size g_pfnVectors, .-g_pfnVectors g_pfnVectors: - .word _estack - .word Reset_Handler - .word NMI_Handler - .word HardFault_Handler - .word MemManage_Handler - .word BusFault_Handler - .word UsageFault_Handler - .word 0 - .word 0 - .word 0 - .word 0 - .word SVC_Handler - .word DebugMon_Handler - .word 0 - .word PendSV_Handler - .word SysTick_Handler - .word WWDG_IRQHandler - .word PVD_PVM_IRQHandler - .word TAMP_STAMP_LSECSS_IRQHandler - .word RTC_WKUP_IRQHandler - .word FLASH_IRQHandler - .word RCC_IRQHandler - .word EXTI0_IRQHandler - .word EXTI1_IRQHandler - .word EXTI2_IRQHandler - .word EXTI3_IRQHandler - .word EXTI4_IRQHandler - .word DMA1_Channel1_IRQHandler - .word DMA1_Channel2_IRQHandler - .word DMA1_Channel3_IRQHandler - .word DMA1_Channel4_IRQHandler - .word DMA1_Channel5_IRQHandler - .word DMA1_Channel6_IRQHandler - .word DMA1_Channel7_IRQHandler - .word ADC1_IRQHandler - .word USB_HP_IRQHandler - .word USB_LP_IRQHandler - .word C2SEV_PWR_C2H_IRQHandler - .word COMP_IRQHandler - .word EXTI9_5_IRQHandler - .word TIM1_BRK_IRQHandler - .word TIM1_UP_TIM16_IRQHandler - .word TIM1_TRG_COM_TIM17_IRQHandler - .word TIM1_CC_IRQHandler - .word TIM2_IRQHandler - .word PKA_IRQHandler - .word I2C1_EV_IRQHandler - .word I2C1_ER_IRQHandler - .word I2C3_EV_IRQHandler - .word I2C3_ER_IRQHandler - .word SPI1_IRQHandler - .word SPI2_IRQHandler - .word USART1_IRQHandler - .word LPUART1_IRQHandler - .word SAI1_IRQHandler - .word TSC_IRQHandler - .word EXTI15_10_IRQHandler - .word RTC_Alarm_IRQHandler - .word CRS_IRQHandler - .word PWR_SOTF_BLEACT_802ACT_RFPHASE_IRQHandler - .word IPCC_C1_RX_IRQHandler - .word IPCC_C1_TX_IRQHandler - .word HSEM_IRQHandler - .word LPTIM1_IRQHandler - .word LPTIM2_IRQHandler - .word LCD_IRQHandler - .word QUADSPI_IRQHandler - .word AES1_IRQHandler - .word AES2_IRQHandler - .word RNG_IRQHandler - .word FPU_IRQHandler - .word DMA2_Channel1_IRQHandler - .word DMA2_Channel2_IRQHandler - .word DMA2_Channel3_IRQHandler - .word DMA2_Channel4_IRQHandler - .word DMA2_Channel5_IRQHandler - .word DMA2_Channel6_IRQHandler - .word DMA2_Channel7_IRQHandler - .word DMAMUX1_OVR_IRQHandler + .word _estack + .word Reset_Handler + .word NMI_Handler + .word HardFault_Handler + .word MemManage_Handler + .word BusFault_Handler + .word UsageFault_Handler + .word 0 + .word 0 + .word 0 + .word 0 + .word SVC_Handler + .word DebugMon_Handler + .word 0 + .word PendSV_Handler + .word SysTick_Handler + .word WWDG_IRQHandler + .word PVD_PVM_IRQHandler + .word TAMP_STAMP_LSECSS_IRQHandler + .word RTC_WKUP_IRQHandler + .word FLASH_IRQHandler + .word RCC_IRQHandler + .word EXTI0_IRQHandler + .word EXTI1_IRQHandler + .word EXTI2_IRQHandler + .word EXTI3_IRQHandler + .word EXTI4_IRQHandler + .word DMA1_Channel1_IRQHandler + .word DMA1_Channel2_IRQHandler + .word DMA1_Channel3_IRQHandler + .word DMA1_Channel4_IRQHandler + .word DMA1_Channel5_IRQHandler + .word DMA1_Channel6_IRQHandler + .word DMA1_Channel7_IRQHandler + .word ADC1_IRQHandler + .word USB_HP_IRQHandler + .word USB_LP_IRQHandler + .word C2SEV_PWR_C2H_IRQHandler + .word COMP_IRQHandler + .word EXTI9_5_IRQHandler + .word TIM1_BRK_IRQHandler + .word TIM1_UP_TIM16_IRQHandler + .word TIM1_TRG_COM_TIM17_IRQHandler + .word TIM1_CC_IRQHandler + .word TIM2_IRQHandler + .word PKA_IRQHandler + .word I2C1_EV_IRQHandler + .word I2C1_ER_IRQHandler + .word I2C3_EV_IRQHandler + .word I2C3_ER_IRQHandler + .word SPI1_IRQHandler + .word SPI2_IRQHandler + .word USART1_IRQHandler + .word LPUART1_IRQHandler + .word SAI1_IRQHandler + .word TSC_IRQHandler + .word EXTI15_10_IRQHandler + .word RTC_Alarm_IRQHandler + .word CRS_IRQHandler + .word PWR_SOTF_BLEACT_802ACT_RFPHASE_IRQHandler + .word IPCC_C1_RX_IRQHandler + .word IPCC_C1_TX_IRQHandler + .word HSEM_IRQHandler + .word LPTIM1_IRQHandler + .word LPTIM2_IRQHandler + .word LCD_IRQHandler + .word QUADSPI_IRQHandler + .word AES1_IRQHandler + .word AES2_IRQHandler + .word RNG_IRQHandler + .word FPU_IRQHandler + .word DMA2_Channel1_IRQHandler + .word DMA2_Channel2_IRQHandler + .word DMA2_Channel3_IRQHandler + .word DMA2_Channel4_IRQHandler + .word DMA2_Channel5_IRQHandler + .word DMA2_Channel6_IRQHandler + .word DMA2_Channel7_IRQHandler + .word DMAMUX1_OVR_IRQHandler /******************************************************************************* * @@ -225,220 +227,220 @@ g_pfnVectors: * this definition. * *******************************************************************************/ - .weak NMI_Handler - .thumb_set NMI_Handler,Default_Handler - - .weak HardFault_Handler - .thumb_set HardFault_Handler,Default_Handler + .weak NMI_Handler + .thumb_set NMI_Handler,Default_Handler + + .weak HardFault_Handler + .thumb_set HardFault_Handler,Default_Handler - .weak MemManage_Handler - .thumb_set MemManage_Handler,Default_Handler + .weak MemManage_Handler + .thumb_set MemManage_Handler,Default_Handler - .weak BusFault_Handler - .thumb_set BusFault_Handler,Default_Handler + .weak BusFault_Handler + .thumb_set BusFault_Handler,Default_Handler - .weak UsageFault_Handler - .thumb_set UsageFault_Handler,Default_Handler + .weak UsageFault_Handler + .thumb_set UsageFault_Handler,Default_Handler - .weak SVC_Handler - .thumb_set SVC_Handler,Default_Handler + .weak SVC_Handler + .thumb_set SVC_Handler,Default_Handler - .weak DebugMon_Handler - .thumb_set DebugMon_Handler,Default_Handler + .weak DebugMon_Handler + .thumb_set DebugMon_Handler,Default_Handler - .weak PendSV_Handler - .thumb_set PendSV_Handler,Default_Handler + .weak PendSV_Handler + .thumb_set PendSV_Handler,Default_Handler - .weak SysTick_Handler - .thumb_set SysTick_Handler,Default_Handler + .weak SysTick_Handler + .thumb_set SysTick_Handler,Default_Handler - .weak WWDG_IRQHandler - .thumb_set WWDG_IRQHandler,Default_Handler + .weak WWDG_IRQHandler + .thumb_set WWDG_IRQHandler,Default_Handler - .weak PVD_PVM_IRQHandler - .thumb_set PVD_PVM_IRQHandler,Default_Handler + .weak PVD_PVM_IRQHandler + .thumb_set PVD_PVM_IRQHandler,Default_Handler - .weak TAMP_STAMP_LSECSS_IRQHandler - .thumb_set TAMP_STAMP_LSECSS_IRQHandler,Default_Handler + .weak TAMP_STAMP_LSECSS_IRQHandler + .thumb_set TAMP_STAMP_LSECSS_IRQHandler,Default_Handler - .weak RTC_WKUP_IRQHandler - .thumb_set RTC_WKUP_IRQHandler,Default_Handler + .weak RTC_WKUP_IRQHandler + .thumb_set RTC_WKUP_IRQHandler,Default_Handler - .weak FLASH_IRQHandler - .thumb_set FLASH_IRQHandler,Default_Handler + .weak FLASH_IRQHandler + .thumb_set FLASH_IRQHandler,Default_Handler - .weak RCC_IRQHandler - .thumb_set RCC_IRQHandler,Default_Handler + .weak RCC_IRQHandler + .thumb_set RCC_IRQHandler,Default_Handler - .weak EXTI0_IRQHandler - .thumb_set EXTI0_IRQHandler,Default_Handler + .weak EXTI0_IRQHandler + .thumb_set EXTI0_IRQHandler,Default_Handler - .weak EXTI1_IRQHandler - .thumb_set EXTI1_IRQHandler,Default_Handler + .weak EXTI1_IRQHandler + .thumb_set EXTI1_IRQHandler,Default_Handler - .weak EXTI2_IRQHandler - .thumb_set EXTI2_IRQHandler,Default_Handler + .weak EXTI2_IRQHandler + .thumb_set EXTI2_IRQHandler,Default_Handler - .weak EXTI3_IRQHandler - .thumb_set EXTI3_IRQHandler,Default_Handler + .weak EXTI3_IRQHandler + .thumb_set EXTI3_IRQHandler,Default_Handler - .weak EXTI4_IRQHandler - .thumb_set EXTI4_IRQHandler,Default_Handler + .weak EXTI4_IRQHandler + .thumb_set EXTI4_IRQHandler,Default_Handler - .weak DMA1_Channel1_IRQHandler - .thumb_set DMA1_Channel1_IRQHandler,Default_Handler + .weak DMA1_Channel1_IRQHandler + .thumb_set DMA1_Channel1_IRQHandler,Default_Handler - .weak DMA1_Channel2_IRQHandler - .thumb_set DMA1_Channel2_IRQHandler,Default_Handler + .weak DMA1_Channel2_IRQHandler + .thumb_set DMA1_Channel2_IRQHandler,Default_Handler - .weak DMA1_Channel3_IRQHandler - .thumb_set DMA1_Channel3_IRQHandler,Default_Handler + .weak DMA1_Channel3_IRQHandler + .thumb_set DMA1_Channel3_IRQHandler,Default_Handler - .weak DMA1_Channel4_IRQHandler - .thumb_set DMA1_Channel4_IRQHandler,Default_Handler + .weak DMA1_Channel4_IRQHandler + .thumb_set DMA1_Channel4_IRQHandler,Default_Handler - .weak DMA1_Channel5_IRQHandler - .thumb_set DMA1_Channel5_IRQHandler,Default_Handler + .weak DMA1_Channel5_IRQHandler + .thumb_set DMA1_Channel5_IRQHandler,Default_Handler - .weak DMA1_Channel6_IRQHandler - .thumb_set DMA1_Channel6_IRQHandler,Default_Handler + .weak DMA1_Channel6_IRQHandler + .thumb_set DMA1_Channel6_IRQHandler,Default_Handler - .weak DMA1_Channel7_IRQHandler - .thumb_set DMA1_Channel7_IRQHandler,Default_Handler + .weak DMA1_Channel7_IRQHandler + .thumb_set DMA1_Channel7_IRQHandler,Default_Handler - .weak ADC1_IRQHandler - .thumb_set ADC1_IRQHandler,Default_Handler + .weak ADC1_IRQHandler + .thumb_set ADC1_IRQHandler,Default_Handler - .weak USB_HP_IRQHandler - .thumb_set USB_HP_IRQHandler,Default_Handler + .weak USB_HP_IRQHandler + .thumb_set USB_HP_IRQHandler,Default_Handler - .weak USB_LP_IRQHandler - .thumb_set USB_LP_IRQHandler,Default_Handler + .weak USB_LP_IRQHandler + .thumb_set USB_LP_IRQHandler,Default_Handler - .weak C2SEV_PWR_C2H_IRQHandler - .thumb_set C2SEV_PWR_C2H_IRQHandler,Default_Handler + .weak C2SEV_PWR_C2H_IRQHandler + .thumb_set C2SEV_PWR_C2H_IRQHandler,Default_Handler - .weak COMP_IRQHandler - .thumb_set COMP_IRQHandler,Default_Handler + .weak COMP_IRQHandler + .thumb_set COMP_IRQHandler,Default_Handler - .weak EXTI9_5_IRQHandler - .thumb_set EXTI9_5_IRQHandler,Default_Handler + .weak EXTI9_5_IRQHandler + .thumb_set EXTI9_5_IRQHandler,Default_Handler - .weak TIM1_BRK_IRQHandler - .thumb_set TIM1_BRK_IRQHandler,Default_Handler + .weak TIM1_BRK_IRQHandler + .thumb_set TIM1_BRK_IRQHandler,Default_Handler - .weak TIM1_UP_TIM16_IRQHandler - .thumb_set TIM1_UP_TIM16_IRQHandler,Default_Handler + .weak TIM1_UP_TIM16_IRQHandler + .thumb_set TIM1_UP_TIM16_IRQHandler,Default_Handler - .weak TIM1_TRG_COM_TIM17_IRQHandler - .thumb_set TIM1_TRG_COM_TIM17_IRQHandler,Default_Handler + .weak TIM1_TRG_COM_TIM17_IRQHandler + .thumb_set TIM1_TRG_COM_TIM17_IRQHandler,Default_Handler - .weak TIM1_CC_IRQHandler - .thumb_set TIM1_CC_IRQHandler,Default_Handler + .weak TIM1_CC_IRQHandler + .thumb_set TIM1_CC_IRQHandler,Default_Handler - .weak TIM2_IRQHandler - .thumb_set TIM2_IRQHandler,Default_Handler + .weak TIM2_IRQHandler + .thumb_set TIM2_IRQHandler,Default_Handler - .weak PKA_IRQHandler - .thumb_set PKA_IRQHandler,Default_Handler + .weak PKA_IRQHandler + .thumb_set PKA_IRQHandler,Default_Handler - .weak I2C1_EV_IRQHandler - .thumb_set I2C1_EV_IRQHandler,Default_Handler + .weak I2C1_EV_IRQHandler + .thumb_set I2C1_EV_IRQHandler,Default_Handler - .weak I2C1_ER_IRQHandler - .thumb_set I2C1_ER_IRQHandler,Default_Handler + .weak I2C1_ER_IRQHandler + .thumb_set I2C1_ER_IRQHandler,Default_Handler - .weak I2C3_EV_IRQHandler - .thumb_set I2C3_EV_IRQHandler,Default_Handler + .weak I2C3_EV_IRQHandler + .thumb_set I2C3_EV_IRQHandler,Default_Handler - .weak I2C3_ER_IRQHandler - .thumb_set I2C3_ER_IRQHandler,Default_Handler + .weak I2C3_ER_IRQHandler + .thumb_set I2C3_ER_IRQHandler,Default_Handler - .weak SPI1_IRQHandler - .thumb_set SPI1_IRQHandler,Default_Handler + .weak SPI1_IRQHandler + .thumb_set SPI1_IRQHandler,Default_Handler - .weak SPI2_IRQHandler - .thumb_set SPI2_IRQHandler,Default_Handler + .weak SPI2_IRQHandler + .thumb_set SPI2_IRQHandler,Default_Handler - .weak USART1_IRQHandler - .thumb_set USART1_IRQHandler,Default_Handler + .weak USART1_IRQHandler + .thumb_set USART1_IRQHandler,Default_Handler - .weak LPUART1_IRQHandler - .thumb_set LPUART1_IRQHandler,Default_Handler + .weak LPUART1_IRQHandler + .thumb_set LPUART1_IRQHandler,Default_Handler - .weak SAI1_IRQHandler - .thumb_set SAI1_IRQHandler,Default_Handler + .weak SAI1_IRQHandler + .thumb_set SAI1_IRQHandler,Default_Handler - .weak TSC_IRQHandler - .thumb_set TSC_IRQHandler,Default_Handler + .weak TSC_IRQHandler + .thumb_set TSC_IRQHandler,Default_Handler - .weak EXTI15_10_IRQHandler - .thumb_set EXTI15_10_IRQHandler,Default_Handler + .weak EXTI15_10_IRQHandler + .thumb_set EXTI15_10_IRQHandler,Default_Handler - .weak RTC_Alarm_IRQHandler - .thumb_set RTC_Alarm_IRQHandler,Default_Handler + .weak RTC_Alarm_IRQHandler + .thumb_set RTC_Alarm_IRQHandler,Default_Handler - .weak CRS_IRQHandler - .thumb_set CRS_IRQHandler,Default_Handler + .weak CRS_IRQHandler + .thumb_set CRS_IRQHandler,Default_Handler - .weak PWR_SOTF_BLEACT_802ACT_RFPHASE_IRQHandler - .thumb_set PWR_SOTF_BLEACT_802ACT_RFPHASE_IRQHandler,Default_Handler + .weak PWR_SOTF_BLEACT_802ACT_RFPHASE_IRQHandler + .thumb_set PWR_SOTF_BLEACT_802ACT_RFPHASE_IRQHandler,Default_Handler - .weak IPCC_C1_RX_IRQHandler - .thumb_set IPCC_C1_RX_IRQHandler,Default_Handler + .weak IPCC_C1_RX_IRQHandler + .thumb_set IPCC_C1_RX_IRQHandler,Default_Handler - .weak IPCC_C1_TX_IRQHandler - .thumb_set IPCC_C1_TX_IRQHandler,Default_Handler + .weak IPCC_C1_TX_IRQHandler + .thumb_set IPCC_C1_TX_IRQHandler,Default_Handler - .weak HSEM_IRQHandler - .thumb_set HSEM_IRQHandler,Default_Handler + .weak HSEM_IRQHandler + .thumb_set HSEM_IRQHandler,Default_Handler - .weak LPTIM1_IRQHandler - .thumb_set LPTIM1_IRQHandler,Default_Handler + .weak LPTIM1_IRQHandler + .thumb_set LPTIM1_IRQHandler,Default_Handler - .weak LPTIM2_IRQHandler - .thumb_set LPTIM2_IRQHandler,Default_Handler + .weak LPTIM2_IRQHandler + .thumb_set LPTIM2_IRQHandler,Default_Handler - .weak LCD_IRQHandler - .thumb_set LCD_IRQHandler,Default_Handler + .weak LCD_IRQHandler + .thumb_set LCD_IRQHandler,Default_Handler - .weak QUADSPI_IRQHandler - .thumb_set QUADSPI_IRQHandler,Default_Handler + .weak QUADSPI_IRQHandler + .thumb_set QUADSPI_IRQHandler,Default_Handler - .weak AES1_IRQHandler - .thumb_set AES1_IRQHandler,Default_Handler + .weak AES1_IRQHandler + .thumb_set AES1_IRQHandler,Default_Handler - .weak AES2_IRQHandler - .thumb_set AES2_IRQHandler,Default_Handler + .weak AES2_IRQHandler + .thumb_set AES2_IRQHandler,Default_Handler - .weak RNG_IRQHandler - .thumb_set RNG_IRQHandler,Default_Handler + .weak RNG_IRQHandler + .thumb_set RNG_IRQHandler,Default_Handler - .weak FPU_IRQHandler - .thumb_set FPU_IRQHandler,Default_Handler + .weak FPU_IRQHandler + .thumb_set FPU_IRQHandler,Default_Handler - .weak DMA2_Channel1_IRQHandler - .thumb_set DMA2_Channel1_IRQHandler,Default_Handler + .weak DMA2_Channel1_IRQHandler + .thumb_set DMA2_Channel1_IRQHandler,Default_Handler - .weak DMA2_Channel2_IRQHandler - .thumb_set DMA2_Channel2_IRQHandler,Default_Handler + .weak DMA2_Channel2_IRQHandler + .thumb_set DMA2_Channel2_IRQHandler,Default_Handler - .weak DMA2_Channel3_IRQHandler - .thumb_set DMA2_Channel3_IRQHandler,Default_Handler + .weak DMA2_Channel3_IRQHandler + .thumb_set DMA2_Channel3_IRQHandler,Default_Handler - .weak DMA2_Channel4_IRQHandler - .thumb_set DMA2_Channel4_IRQHandler,Default_Handler + .weak DMA2_Channel4_IRQHandler + .thumb_set DMA2_Channel4_IRQHandler,Default_Handler - .weak DMA2_Channel5_IRQHandler - .thumb_set DMA2_Channel5_IRQHandler,Default_Handler + .weak DMA2_Channel5_IRQHandler + .thumb_set DMA2_Channel5_IRQHandler,Default_Handler - .weak DMA2_Channel6_IRQHandler - .thumb_set DMA2_Channel6_IRQHandler,Default_Handler + .weak DMA2_Channel6_IRQHandler + .thumb_set DMA2_Channel6_IRQHandler,Default_Handler - .weak DMA2_Channel7_IRQHandler - .thumb_set DMA2_Channel7_IRQHandler,Default_Handler + .weak DMA2_Channel7_IRQHandler + .thumb_set DMA2_Channel7_IRQHandler,Default_Handler - .weak DMAMUX1_OVR_IRQHandler - .thumb_set DMAMUX1_OVR_IRQHandler,Default_Handler + .weak DMAMUX1_OVR_IRQHandler + .thumb_set DMAMUX1_OVR_IRQHandler,Default_Handler /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/firmware/targets/f6/furi_hal/furi_hal_bt.c b/firmware/targets/f6/furi_hal/furi_hal_bt.c index 4465f15e..1bd244a9 100755 --- a/firmware/targets/f6/furi_hal/furi_hal_bt.c +++ b/firmware/targets/f6/furi_hal/furi_hal_bt.c @@ -47,7 +47,7 @@ FuriHalBtProfileConfig profile_config[FuriHalBtProfileNumber] = { .conn_int_min = 0x08, .conn_int_max = 0x18, .slave_latency = 0, - .supervisor_timeout = 50, + .supervisor_timeout = 0, }, }, }, @@ -246,7 +246,7 @@ bool furi_hal_bt_change_app(FuriHalBtProfile profile, GapEventCallback event_cb, return ret; } -static bool furi_hal_bt_is_active() { +bool furi_hal_bt_is_active() { return gap_get_state() > GapStateIdle; } diff --git a/firmware/targets/f6/furi_hal/furi_hal_gpio.c b/firmware/targets/f6/furi_hal/furi_hal_gpio.c index 8c2aefe2..a6f25d10 100644 --- a/firmware/targets/f6/furi_hal/furi_hal_gpio.c +++ b/firmware/targets/f6/furi_hal/furi_hal_gpio.c @@ -68,25 +68,37 @@ void hal_gpio_init_ex( uint32_t exti_line = GET_EXTI_LINE(gpio->pin); // Configure gpio with interrupts disabled - __disable_irq(); + FURI_CRITICAL_ENTER(); + // Set gpio speed - if(speed == GpioSpeedLow) { + switch(speed) { + case GpioSpeedLow: LL_GPIO_SetPinSpeed(gpio->port, gpio->pin, LL_GPIO_SPEED_FREQ_LOW); - } else if(speed == GpioSpeedMedium) { + break; + case GpioSpeedMedium: LL_GPIO_SetPinSpeed(gpio->port, gpio->pin, LL_GPIO_SPEED_FREQ_MEDIUM); - } else if(speed == GpioSpeedHigh) { + break; + case GpioSpeedHigh: LL_GPIO_SetPinSpeed(gpio->port, gpio->pin, LL_GPIO_SPEED_FREQ_HIGH); - } else { + break; + case GpioSpeedVeryHigh: LL_GPIO_SetPinSpeed(gpio->port, gpio->pin, LL_GPIO_SPEED_FREQ_VERY_HIGH); + break; } + // Set gpio pull mode - if(pull == GpioPullNo) { + switch(pull) { + case GpioPullNo: LL_GPIO_SetPinPull(gpio->port, gpio->pin, LL_GPIO_PULL_NO); - } else if(pull == GpioPullUp) { + break; + case GpioPullUp: LL_GPIO_SetPinPull(gpio->port, gpio->pin, LL_GPIO_PULL_UP); - } else { + break; + case GpioPullDown: LL_GPIO_SetPinPull(gpio->port, gpio->pin, LL_GPIO_PULL_DOWN); + break; } + // Set gpio mode if(mode >= GpioModeInterruptRise) { // Set pin in interrupt mode @@ -100,93 +112,106 @@ void hal_gpio_init_ex( LL_EXTI_EnableIT_0_31(exti_line); LL_EXTI_EnableFallingTrig_0_31(exti_line); } - if(mode == GpioModeEventRise || mode == GpioModeInterruptRiseFall) { + if(mode == GpioModeEventRise || mode == GpioModeEventRiseFall) { LL_EXTI_EnableEvent_0_31(exti_line); LL_EXTI_EnableRisingTrig_0_31(exti_line); } - if(mode == GpioModeEventFall || mode == GpioModeInterruptRiseFall) { + if(mode == GpioModeEventFall || mode == GpioModeEventRiseFall) { LL_EXTI_EnableEvent_0_31(exti_line); LL_EXTI_EnableFallingTrig_0_31(exti_line); } } else { - // Disable interrupt if it was set + // Disable interrupts if set if(LL_SYSCFG_GetEXTISource(sys_exti_line) == sys_exti_port && LL_EXTI_IsEnabledIT_0_31(exti_line)) { LL_EXTI_DisableIT_0_31(exti_line); LL_EXTI_DisableRisingTrig_0_31(exti_line); LL_EXTI_DisableFallingTrig_0_31(exti_line); } + + // Prepare alternative part if any + if(mode == GpioModeAltFunctionPushPull || mode == GpioModeAltFunctionOpenDrain) { + // set alternate function + if(hal_gpio_get_pin_num(gpio) < 8) { + LL_GPIO_SetAFPin_0_7(gpio->port, gpio->pin, alt_fn); + } else { + LL_GPIO_SetAFPin_8_15(gpio->port, gpio->pin, alt_fn); + } + } + // Set not interrupt pin modes - if(mode == GpioModeInput) { + switch(mode) { + case GpioModeInput: LL_GPIO_SetPinMode(gpio->port, gpio->pin, LL_GPIO_MODE_INPUT); - } else if(mode == GpioModeOutputPushPull || mode == GpioModeAltFunctionPushPull) { - LL_GPIO_SetPinMode(gpio->port, gpio->pin, LL_GPIO_MODE_OUTPUT); + break; + case GpioModeOutputPushPull: LL_GPIO_SetPinOutputType(gpio->port, gpio->pin, LL_GPIO_OUTPUT_PUSHPULL); - } else if(mode == GpioModeOutputOpenDrain || mode == GpioModeAltFunctionOpenDrain) { LL_GPIO_SetPinMode(gpio->port, gpio->pin, LL_GPIO_MODE_OUTPUT); + break; + case GpioModeAltFunctionPushPull: + LL_GPIO_SetPinOutputType(gpio->port, gpio->pin, LL_GPIO_OUTPUT_PUSHPULL); + LL_GPIO_SetPinMode(gpio->port, gpio->pin, LL_GPIO_MODE_ALTERNATE); + break; + case GpioModeOutputOpenDrain: LL_GPIO_SetPinOutputType(gpio->port, gpio->pin, LL_GPIO_OUTPUT_OPENDRAIN); - } else if(mode == GpioModeAnalog) { + LL_GPIO_SetPinMode(gpio->port, gpio->pin, LL_GPIO_MODE_OUTPUT); + break; + case GpioModeAltFunctionOpenDrain: + LL_GPIO_SetPinOutputType(gpio->port, gpio->pin, LL_GPIO_OUTPUT_OPENDRAIN); + LL_GPIO_SetPinMode(gpio->port, gpio->pin, LL_GPIO_MODE_ALTERNATE); + break; + case GpioModeAnalog: LL_GPIO_SetPinMode(gpio->port, gpio->pin, LL_GPIO_MODE_ANALOG); + break; + default: + break; } } - - if(mode == GpioModeAltFunctionPushPull || mode == GpioModeAltFunctionOpenDrain) { - // enable alternate mode - LL_GPIO_SetPinMode(gpio->port, gpio->pin, LL_GPIO_MODE_ALTERNATE); - - // set alternate function - if(hal_gpio_get_pin_num(gpio) < 8) { - LL_GPIO_SetAFPin_0_7(gpio->port, gpio->pin, alt_fn); - } else { - LL_GPIO_SetAFPin_8_15(gpio->port, gpio->pin, alt_fn); - } - } - - __enable_irq(); + FURI_CRITICAL_EXIT(); } void hal_gpio_add_int_callback(const GpioPin* gpio, GpioExtiCallback cb, void* ctx) { furi_assert(gpio); furi_assert(cb); - __disable_irq(); + FURI_CRITICAL_ENTER(); uint8_t pin_num = hal_gpio_get_pin_num(gpio); furi_assert(gpio_interrupt[pin_num].callback == NULL); gpio_interrupt[pin_num].callback = cb; gpio_interrupt[pin_num].context = ctx; gpio_interrupt[pin_num].ready = true; - __enable_irq(); + FURI_CRITICAL_EXIT(); } void hal_gpio_enable_int_callback(const GpioPin* gpio) { furi_assert(gpio); - __disable_irq(); + FURI_CRITICAL_ENTER(); uint8_t pin_num = hal_gpio_get_pin_num(gpio); if(gpio_interrupt[pin_num].callback) { gpio_interrupt[pin_num].ready = true; } - __enable_irq(); + FURI_CRITICAL_EXIT(); } void hal_gpio_disable_int_callback(const GpioPin* gpio) { furi_assert(gpio); - __disable_irq(); + FURI_CRITICAL_ENTER(); uint8_t pin_num = hal_gpio_get_pin_num(gpio); gpio_interrupt[pin_num].ready = false; - __enable_irq(); + FURI_CRITICAL_EXIT(); } void hal_gpio_remove_int_callback(const GpioPin* gpio) { furi_assert(gpio); - __disable_irq(); + FURI_CRITICAL_ENTER(); uint8_t pin_num = hal_gpio_get_pin_num(gpio); gpio_interrupt[pin_num].callback = NULL; gpio_interrupt[pin_num].context = NULL; gpio_interrupt[pin_num].ready = false; - __enable_irq(); + FURI_CRITICAL_EXIT(); } static void hal_gpio_int_call(uint16_t pin_num) { diff --git a/firmware/targets/f6/furi_hal/furi_hal_irda.c b/firmware/targets/f6/furi_hal/furi_hal_irda.c index 070e3c16..cd984741 100644 --- a/firmware/targets/f6/furi_hal/furi_hal_irda.c +++ b/firmware/targets/f6/furi_hal/furi_hal_irda.c @@ -516,7 +516,7 @@ static void furi_hal_irda_tx_dma_set_polarity(uint8_t buf_num, uint8_t polarity_ IrdaTxBuf* buffer = &irda_tim_tx.buffer[buf_num]; furi_assert(buffer->polarity != NULL); - __disable_irq(); + FURI_CRITICAL_ENTER(); bool channel_enabled = LL_DMA_IsEnabledChannel(DMA1, LL_DMA_CHANNEL_1); if(channel_enabled) { LL_DMA_DisableChannel(DMA1, LL_DMA_CHANNEL_1); @@ -526,7 +526,7 @@ static void furi_hal_irda_tx_dma_set_polarity(uint8_t buf_num, uint8_t polarity_ if(channel_enabled) { LL_DMA_EnableChannel(DMA1, LL_DMA_CHANNEL_1); } - __enable_irq(); + FURI_CRITICAL_EXIT(); } static void furi_hal_irda_tx_dma_set_buffer(uint8_t buf_num) { @@ -536,7 +536,7 @@ static void furi_hal_irda_tx_dma_set_buffer(uint8_t buf_num) { furi_assert(buffer->data != NULL); /* non-circular mode requires disabled channel before setup */ - __disable_irq(); + FURI_CRITICAL_ENTER(); bool channel_enabled = LL_DMA_IsEnabledChannel(DMA1, LL_DMA_CHANNEL_2); if(channel_enabled) { LL_DMA_DisableChannel(DMA1, LL_DMA_CHANNEL_2); @@ -546,7 +546,7 @@ static void furi_hal_irda_tx_dma_set_buffer(uint8_t buf_num) { if(channel_enabled) { LL_DMA_EnableChannel(DMA1, LL_DMA_CHANNEL_2); } - __enable_irq(); + FURI_CRITICAL_EXIT(); } static void furi_hal_irda_async_tx_free_resources(void) { @@ -621,10 +621,10 @@ void furi_hal_irda_async_tx_start(uint32_t freq, float duty_cycle) { hal_gpio_init_ex( &gpio_irda_tx, GpioModeAltFunctionPushPull, GpioPullUp, GpioSpeedHigh, GpioAltFn1TIM1); - __disable_irq(); + FURI_CRITICAL_ENTER(); LL_TIM_GenerateEvent_UPDATE(TIM1); /* TIMx_RCR -> Repetition counter */ LL_TIM_EnableCounter(TIM1); - __enable_irq(); + FURI_CRITICAL_EXIT(); } void furi_hal_irda_async_tx_wait_termination(void) { @@ -642,9 +642,9 @@ void furi_hal_irda_async_tx_stop(void) { furi_assert(furi_hal_irda_state >= IrdaStateAsyncTx); furi_assert(furi_hal_irda_state < IrdaStateMAX); - __disable_irq(); + FURI_CRITICAL_ENTER(); if(furi_hal_irda_state == IrdaStateAsyncTx) furi_hal_irda_state = IrdaStateAsyncTxStopReq; - __enable_irq(); + FURI_CRITICAL_EXIT(); furi_hal_irda_async_tx_wait_termination(); } diff --git a/firmware/targets/f6/furi_hal/furi_hal_os.c b/firmware/targets/f6/furi_hal/furi_hal_os.c index 6ef5a9f4..3a6e5f38 100644 --- a/firmware/targets/f6/furi_hal/furi_hal_os.c +++ b/firmware/targets/f6/furi_hal/furi_hal_os.c @@ -115,11 +115,11 @@ void vPortSuppressTicksAndSleep(TickType_t expected_idle_ticks) { } // Stop IRQ handling, no one should disturb us till we finish - __disable_irq(); + FURI_CRITICAL_ENTER(); // Confirm OS that sleep is still possible if(eTaskConfirmSleepModeStatus() == eAbortSleep) { - __enable_irq(); + FURI_CRITICAL_EXIT(); return; } @@ -136,7 +136,7 @@ void vPortSuppressTicksAndSleep(TickType_t expected_idle_ticks) { } // Reenable IRQ - __enable_irq(); + FURI_CRITICAL_EXIT(); } void vApplicationStackOverflowHook(TaskHandle_t xTask, char* pcTaskName) { diff --git a/firmware/targets/f6/furi_hal/furi_hal_power.c b/firmware/targets/f6/furi_hal/furi_hal_power.c index 1dbdb3dd..e34ba46e 100644 --- a/firmware/targets/f6/furi_hal/furi_hal_power.c +++ b/firmware/targets/f6/furi_hal/furi_hal_power.c @@ -89,15 +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_uart.c b/firmware/targets/f6/furi_hal/furi_hal_uart.c index 1ebba5d3..2ee0cf85 100644 --- a/firmware/targets/f6/furi_hal/furi_hal_uart.c +++ b/firmware/targets/f6/furi_hal/furi_hal_uart.c @@ -5,6 +5,7 @@ #include #include +#include static void (*irq_cb[2])(uint8_t ev, uint8_t data, void* context); static void* irq_ctx[2]; @@ -33,13 +34,12 @@ static void furi_hal_usart_init(uint32_t baud) { USART_InitStruct.HardwareFlowControl = LL_USART_HWCONTROL_NONE; USART_InitStruct.OverSampling = LL_USART_OVERSAMPLING_16; LL_USART_Init(USART1, &USART_InitStruct); - LL_USART_SetTXFIFOThreshold(USART1, LL_USART_FIFOTHRESHOLD_1_2); LL_USART_EnableFIFO(USART1); LL_USART_ConfigAsyncMode(USART1); LL_USART_Enable(USART1); - while(!LL_USART_IsActiveFlag_TEACK(USART1)) + while(!LL_USART_IsActiveFlag_TEACK(USART1) || !LL_USART_IsActiveFlag_REACK(USART1)) ; LL_USART_EnableIT_RXNE_RXFNE(USART1); @@ -70,13 +70,11 @@ static void furi_hal_lpuart_init(uint32_t baud) { LPUART_InitStruct.TransferDirection = LL_LPUART_DIRECTION_TX_RX; LPUART_InitStruct.HardwareFlowControl = LL_LPUART_HWCONTROL_NONE; LL_LPUART_Init(LPUART1, &LPUART_InitStruct); - LL_LPUART_SetTXFIFOThreshold(LPUART1, LL_LPUART_FIFOTHRESHOLD_1_8); - LL_LPUART_SetRXFIFOThreshold(LPUART1, LL_LPUART_FIFOTHRESHOLD_1_8); LL_LPUART_EnableFIFO(LPUART1); LL_LPUART_Enable(LPUART1); - while((!(LL_LPUART_IsActiveFlag_TEACK(LPUART1))) || (!(LL_LPUART_IsActiveFlag_REACK(LPUART1)))) + while(!LL_LPUART_IsActiveFlag_TEACK(LPUART1) || !LL_LPUART_IsActiveFlag_REACK(LPUART1)) ; furi_hal_uart_set_br(FuriHalUartIdLPUART1, baud); 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/f6/target.mk b/firmware/targets/f6/target.mk index 0c9bd182..767cbfa0 100644 --- a/firmware/targets/f6/target.mk +++ b/firmware/targets/f6/target.mk @@ -14,7 +14,13 @@ FLASH_ADDRESS = 0x08000000 CFLAGS += -DNO_BOOTLOADER endif +DEBUG_RTOS_THREADS ?= 1 +ifeq ($(DEBUG_RTOS_THREADS), 1) OPENOCD_OPTS = -f interface/stlink.cfg -c "transport select hla_swd" -f ../debug/stm32wbx.cfg -c "stm32wbx.cpu configure -rtos auto" -c "init" +else +OPENOCD_OPTS = -f interface/stlink.cfg -c "transport select hla_swd" -f ../debug/stm32wbx.cfg -c "init" +endif + BOOT_CFLAGS = -DBOOT_ADDRESS=$(BOOT_ADDRESS) -DFW_ADDRESS=$(FW_ADDRESS) -DOS_OFFSET=$(OS_OFFSET) MCU_FLAGS = -mcpu=cortex-m4 -mthumb -mfpu=fpv4-sp-d16 -mfloat-abi=hard diff --git a/firmware/targets/f7/ble_glue/ble_glue.c b/firmware/targets/f7/ble_glue/ble_glue.c index c38c0731..6e55b368 100644 --- a/firmware/targets/f7/ble_glue/ble_glue.c +++ b/firmware/targets/f7/ble_glue/ble_glue.c @@ -116,6 +116,7 @@ void ble_glue_init() { bool ble_glue_wait_for_fus_start(WirelessFwInfo_t* info) { bool ret = false; + size_t countdown = 1000; while(countdown > 0) { if(ble_glue->status == BleGlueStatusFusStarted) { @@ -125,13 +126,14 @@ bool ble_glue_wait_for_fus_start(WirelessFwInfo_t* info) { countdown--; osDelay(1); } + if(ble_glue->status == BleGlueStatusFusStarted) { SHCI_GetWirelessFwInfo(info); } else { FURI_LOG_E(TAG, "Failed to start FUS"); ble_glue->status = BleGlueStatusBroken; } - furi_hal_power_insomnia_exit(); + return ret; } diff --git a/firmware/targets/f7/cube/startup_stm32wb55xx_cm4.s b/firmware/targets/f7/cube/startup_stm32wb55xx_cm4.s index c5c2b3fc..053db01e 100644 --- a/firmware/targets/f7/cube/startup_stm32wb55xx_cm4.s +++ b/firmware/targets/f7/cube/startup_stm32wb55xx_cm4.s @@ -1,48 +1,48 @@ /** - ****************************************************************************** - * @file startup_stm32wb55xx_cm4.s - * @author MCD Application Team - * @brief STM32WB55xx devices vector table GCC toolchain. - * This module performs: - * - Set the initial SP - * - Set the initial PC == Reset_Handler, - * - Set the vector table entries with the exceptions ISR address - * - Branches to main in the C library (which eventually - * calls main()). - * After Reset the Cortex-M4 processor is in Thread mode, - * priority is Privileged, and the Stack is set to Main. - ****************************************************************************** - * @attention - * - * Copyright (c) 2019-2021 STMicroelectronics. - * All rights reserved. - * - * This software is licensed under terms that can be found in the LICENSE file - * in the root directory of this software component. - * If no LICENSE file comes with this software, it is provided AS-IS. - * - ****************************************************************************** - */ + ****************************************************************************** + * @file startup_stm32wb55xx_cm4.s + * @author MCD Application Team + * @brief STM32WB55xx devices vector table GCC toolchain. + * This module performs: + * - Set the initial SP + * - Set the initial PC == Reset_Handler, + * - Set the vector table entries with the exceptions ISR address + * - Branches to main in the C library (which eventually + * calls main()). + * After Reset the Cortex-M4 processor is in Thread mode, + * priority is Privileged, and the Stack is set to Main. + ****************************************************************************** + * @attention + * + * Copyright (c) 2019-2021 STMicroelectronics. + * All rights reserved. + * + * This software is licensed under terms that can be found in the LICENSE file + * in the root directory of this software component. + * If no LICENSE file comes with this software, it is provided AS-IS. + * + ****************************************************************************** + */ - .syntax unified - .cpu cortex-m4 - .fpu softvfp - .thumb +.syntax unified +.cpu cortex-m4 +.fpu softvfp +.thumb -.global g_pfnVectors -.global Default_Handler +.global g_pfnVectors +.global Default_Handler /* start address for the initialization values of the .data section. defined in linker script */ -.word _sidata +.word _sidata /* start address for the .data section. defined in linker script */ -.word _sdata +.word _sdata /* end address for the .data section. defined in linker script */ -.word _edata +.word _edata /* start address for the .bss section. defined in linker script */ -.word _sbss +.word _sbss /* end address for the .bss section. defined in linker script */ -.word _ebss +.word _ebss /* start address for the .MB_MEM2 section. defined in linker script */ .word _sMB_MEM2 /* end address for the .MB_MEM2 section. defined in linker script */ @@ -50,67 +50,69 @@ defined in linker script */ /* INIT_BSS macro is used to fill the specified region [start : end] with zeros */ .macro INIT_BSS start, end - ldr r0, =\start - ldr r1, =\end - movs r3, #0 - bl LoopFillZerobss + ldr r0, =\start + ldr r1, =\end + movs r3, #0 + bl LoopFillZerobss .endm /* INIT_DATA macro is used to copy data in the region [start : end] starting from 'src' */ .macro INIT_DATA start, end, src - ldr r0, =\start - ldr r1, =\end - ldr r2, =\src - movs r3, #0 - bl LoopCopyDataInit + ldr r0, =\start + ldr r1, =\end + ldr r2, =\src + movs r3, #0 + bl LoopCopyDataInit .endm .section .text.data_initializers CopyDataInit: - ldr r4, [r2, r3] - str r4, [r0, r3] - adds r3, r3, #4 + ldr r4, [r2, r3] + str r4, [r0, r3] + adds r3, r3, #4 LoopCopyDataInit: - adds r4, r0, r3 - cmp r4, r1 - bcc CopyDataInit - bx lr + adds r4, r0, r3 + cmp r4, r1 + bcc CopyDataInit + bx lr FillZerobss: - str r3, [r0] - adds r0, r0, #4 + str r3, [r0] + adds r0, r0, #4 LoopFillZerobss: - cmp r0, r1 - bcc FillZerobss - bx lr + cmp r0, r1 + bcc FillZerobss + bx lr + + +.section .text.Reset_Handler +.weak Reset_Handler +.type Reset_Handler, %function - .section .text.Reset_Handler - .weak Reset_Handler - .type Reset_Handler, %function Reset_Handler: - ldr r0, =_estack - mov sp, r0 /* set stack pointer */ -/* Call the clock system intitialization function.*/ - bl SystemInit + ldr r0, =_estack + mov sp, r0 /* set stack pointer */ + /* Call the clock system intitialization function.*/ + bl SystemInit /* Copy the data segment initializers from flash to SRAM */ - INIT_DATA _sdata, _edata, _sidata + INIT_DATA _sdata, _edata, _sidata /* Zero fill the bss segments. */ - INIT_BSS _sbss, _ebss - INIT_BSS _sMB_MEM2, _eMB_MEM2 + INIT_BSS _sbss, _ebss + INIT_BSS _sMB_MEM2, _eMB_MEM2 /* Call static constructors */ - bl __libc_init_array + bl __libc_init_array /* Call the application s entry point.*/ - bl main + bl main LoopForever: - b LoopForever - -.size Reset_Handler, .-Reset_Handler + b LoopForever + +.size Reset_Handler, .-Reset_Handler /** * @brief This is the code that gets called when the processor receives an @@ -120,11 +122,11 @@ LoopForever: * @param None * @retval None */ - .section .text.Default_Handler,"ax",%progbits + .section .text.Default_Handler,"ax",%progbits Default_Handler: Infinite_Loop: - b Infinite_Loop - .size Default_Handler, .-Default_Handler + b Infinite_Loop + .size Default_Handler, .-Default_Handler /****************************************************************************** * * The minimal vector table for a Cortex-M4. Note that the proper constructs @@ -132,91 +134,91 @@ Infinite_Loop: * 0x0000.0000. * ******************************************************************************/ - .section .isr_vector,"a",%progbits - .type g_pfnVectors, %object - .size g_pfnVectors, .-g_pfnVectors + .section .isr_vector,"a",%progbits + .type g_pfnVectors, %object + .size g_pfnVectors, .-g_pfnVectors g_pfnVectors: - .word _estack - .word Reset_Handler - .word NMI_Handler - .word HardFault_Handler - .word MemManage_Handler - .word BusFault_Handler - .word UsageFault_Handler - .word 0 - .word 0 - .word 0 - .word 0 - .word SVC_Handler - .word DebugMon_Handler - .word 0 - .word PendSV_Handler - .word SysTick_Handler - .word WWDG_IRQHandler - .word PVD_PVM_IRQHandler - .word TAMP_STAMP_LSECSS_IRQHandler - .word RTC_WKUP_IRQHandler - .word FLASH_IRQHandler - .word RCC_IRQHandler - .word EXTI0_IRQHandler - .word EXTI1_IRQHandler - .word EXTI2_IRQHandler - .word EXTI3_IRQHandler - .word EXTI4_IRQHandler - .word DMA1_Channel1_IRQHandler - .word DMA1_Channel2_IRQHandler - .word DMA1_Channel3_IRQHandler - .word DMA1_Channel4_IRQHandler - .word DMA1_Channel5_IRQHandler - .word DMA1_Channel6_IRQHandler - .word DMA1_Channel7_IRQHandler - .word ADC1_IRQHandler - .word USB_HP_IRQHandler - .word USB_LP_IRQHandler - .word C2SEV_PWR_C2H_IRQHandler - .word COMP_IRQHandler - .word EXTI9_5_IRQHandler - .word TIM1_BRK_IRQHandler - .word TIM1_UP_TIM16_IRQHandler - .word TIM1_TRG_COM_TIM17_IRQHandler - .word TIM1_CC_IRQHandler - .word TIM2_IRQHandler - .word PKA_IRQHandler - .word I2C1_EV_IRQHandler - .word I2C1_ER_IRQHandler - .word I2C3_EV_IRQHandler - .word I2C3_ER_IRQHandler - .word SPI1_IRQHandler - .word SPI2_IRQHandler - .word USART1_IRQHandler - .word LPUART1_IRQHandler - .word SAI1_IRQHandler - .word TSC_IRQHandler - .word EXTI15_10_IRQHandler - .word RTC_Alarm_IRQHandler - .word CRS_IRQHandler - .word PWR_SOTF_BLEACT_802ACT_RFPHASE_IRQHandler - .word IPCC_C1_RX_IRQHandler - .word IPCC_C1_TX_IRQHandler - .word HSEM_IRQHandler - .word LPTIM1_IRQHandler - .word LPTIM2_IRQHandler - .word LCD_IRQHandler - .word QUADSPI_IRQHandler - .word AES1_IRQHandler - .word AES2_IRQHandler - .word RNG_IRQHandler - .word FPU_IRQHandler - .word DMA2_Channel1_IRQHandler - .word DMA2_Channel2_IRQHandler - .word DMA2_Channel3_IRQHandler - .word DMA2_Channel4_IRQHandler - .word DMA2_Channel5_IRQHandler - .word DMA2_Channel6_IRQHandler - .word DMA2_Channel7_IRQHandler - .word DMAMUX1_OVR_IRQHandler + .word _estack + .word Reset_Handler + .word NMI_Handler + .word HardFault_Handler + .word MemManage_Handler + .word BusFault_Handler + .word UsageFault_Handler + .word 0 + .word 0 + .word 0 + .word 0 + .word SVC_Handler + .word DebugMon_Handler + .word 0 + .word PendSV_Handler + .word SysTick_Handler + .word WWDG_IRQHandler + .word PVD_PVM_IRQHandler + .word TAMP_STAMP_LSECSS_IRQHandler + .word RTC_WKUP_IRQHandler + .word FLASH_IRQHandler + .word RCC_IRQHandler + .word EXTI0_IRQHandler + .word EXTI1_IRQHandler + .word EXTI2_IRQHandler + .word EXTI3_IRQHandler + .word EXTI4_IRQHandler + .word DMA1_Channel1_IRQHandler + .word DMA1_Channel2_IRQHandler + .word DMA1_Channel3_IRQHandler + .word DMA1_Channel4_IRQHandler + .word DMA1_Channel5_IRQHandler + .word DMA1_Channel6_IRQHandler + .word DMA1_Channel7_IRQHandler + .word ADC1_IRQHandler + .word USB_HP_IRQHandler + .word USB_LP_IRQHandler + .word C2SEV_PWR_C2H_IRQHandler + .word COMP_IRQHandler + .word EXTI9_5_IRQHandler + .word TIM1_BRK_IRQHandler + .word TIM1_UP_TIM16_IRQHandler + .word TIM1_TRG_COM_TIM17_IRQHandler + .word TIM1_CC_IRQHandler + .word TIM2_IRQHandler + .word PKA_IRQHandler + .word I2C1_EV_IRQHandler + .word I2C1_ER_IRQHandler + .word I2C3_EV_IRQHandler + .word I2C3_ER_IRQHandler + .word SPI1_IRQHandler + .word SPI2_IRQHandler + .word USART1_IRQHandler + .word LPUART1_IRQHandler + .word SAI1_IRQHandler + .word TSC_IRQHandler + .word EXTI15_10_IRQHandler + .word RTC_Alarm_IRQHandler + .word CRS_IRQHandler + .word PWR_SOTF_BLEACT_802ACT_RFPHASE_IRQHandler + .word IPCC_C1_RX_IRQHandler + .word IPCC_C1_TX_IRQHandler + .word HSEM_IRQHandler + .word LPTIM1_IRQHandler + .word LPTIM2_IRQHandler + .word LCD_IRQHandler + .word QUADSPI_IRQHandler + .word AES1_IRQHandler + .word AES2_IRQHandler + .word RNG_IRQHandler + .word FPU_IRQHandler + .word DMA2_Channel1_IRQHandler + .word DMA2_Channel2_IRQHandler + .word DMA2_Channel3_IRQHandler + .word DMA2_Channel4_IRQHandler + .word DMA2_Channel5_IRQHandler + .word DMA2_Channel6_IRQHandler + .word DMA2_Channel7_IRQHandler + .word DMAMUX1_OVR_IRQHandler /******************************************************************************* * @@ -225,220 +227,220 @@ g_pfnVectors: * this definition. * *******************************************************************************/ - .weak NMI_Handler - .thumb_set NMI_Handler,Default_Handler - - .weak HardFault_Handler - .thumb_set HardFault_Handler,Default_Handler + .weak NMI_Handler + .thumb_set NMI_Handler,Default_Handler + + .weak HardFault_Handler + .thumb_set HardFault_Handler,Default_Handler - .weak MemManage_Handler - .thumb_set MemManage_Handler,Default_Handler + .weak MemManage_Handler + .thumb_set MemManage_Handler,Default_Handler - .weak BusFault_Handler - .thumb_set BusFault_Handler,Default_Handler + .weak BusFault_Handler + .thumb_set BusFault_Handler,Default_Handler - .weak UsageFault_Handler - .thumb_set UsageFault_Handler,Default_Handler + .weak UsageFault_Handler + .thumb_set UsageFault_Handler,Default_Handler - .weak SVC_Handler - .thumb_set SVC_Handler,Default_Handler + .weak SVC_Handler + .thumb_set SVC_Handler,Default_Handler - .weak DebugMon_Handler - .thumb_set DebugMon_Handler,Default_Handler + .weak DebugMon_Handler + .thumb_set DebugMon_Handler,Default_Handler - .weak PendSV_Handler - .thumb_set PendSV_Handler,Default_Handler + .weak PendSV_Handler + .thumb_set PendSV_Handler,Default_Handler - .weak SysTick_Handler - .thumb_set SysTick_Handler,Default_Handler + .weak SysTick_Handler + .thumb_set SysTick_Handler,Default_Handler - .weak WWDG_IRQHandler - .thumb_set WWDG_IRQHandler,Default_Handler + .weak WWDG_IRQHandler + .thumb_set WWDG_IRQHandler,Default_Handler - .weak PVD_PVM_IRQHandler - .thumb_set PVD_PVM_IRQHandler,Default_Handler + .weak PVD_PVM_IRQHandler + .thumb_set PVD_PVM_IRQHandler,Default_Handler - .weak TAMP_STAMP_LSECSS_IRQHandler - .thumb_set TAMP_STAMP_LSECSS_IRQHandler,Default_Handler + .weak TAMP_STAMP_LSECSS_IRQHandler + .thumb_set TAMP_STAMP_LSECSS_IRQHandler,Default_Handler - .weak RTC_WKUP_IRQHandler - .thumb_set RTC_WKUP_IRQHandler,Default_Handler + .weak RTC_WKUP_IRQHandler + .thumb_set RTC_WKUP_IRQHandler,Default_Handler - .weak FLASH_IRQHandler - .thumb_set FLASH_IRQHandler,Default_Handler + .weak FLASH_IRQHandler + .thumb_set FLASH_IRQHandler,Default_Handler - .weak RCC_IRQHandler - .thumb_set RCC_IRQHandler,Default_Handler + .weak RCC_IRQHandler + .thumb_set RCC_IRQHandler,Default_Handler - .weak EXTI0_IRQHandler - .thumb_set EXTI0_IRQHandler,Default_Handler + .weak EXTI0_IRQHandler + .thumb_set EXTI0_IRQHandler,Default_Handler - .weak EXTI1_IRQHandler - .thumb_set EXTI1_IRQHandler,Default_Handler + .weak EXTI1_IRQHandler + .thumb_set EXTI1_IRQHandler,Default_Handler - .weak EXTI2_IRQHandler - .thumb_set EXTI2_IRQHandler,Default_Handler + .weak EXTI2_IRQHandler + .thumb_set EXTI2_IRQHandler,Default_Handler - .weak EXTI3_IRQHandler - .thumb_set EXTI3_IRQHandler,Default_Handler + .weak EXTI3_IRQHandler + .thumb_set EXTI3_IRQHandler,Default_Handler - .weak EXTI4_IRQHandler - .thumb_set EXTI4_IRQHandler,Default_Handler + .weak EXTI4_IRQHandler + .thumb_set EXTI4_IRQHandler,Default_Handler - .weak DMA1_Channel1_IRQHandler - .thumb_set DMA1_Channel1_IRQHandler,Default_Handler + .weak DMA1_Channel1_IRQHandler + .thumb_set DMA1_Channel1_IRQHandler,Default_Handler - .weak DMA1_Channel2_IRQHandler - .thumb_set DMA1_Channel2_IRQHandler,Default_Handler + .weak DMA1_Channel2_IRQHandler + .thumb_set DMA1_Channel2_IRQHandler,Default_Handler - .weak DMA1_Channel3_IRQHandler - .thumb_set DMA1_Channel3_IRQHandler,Default_Handler + .weak DMA1_Channel3_IRQHandler + .thumb_set DMA1_Channel3_IRQHandler,Default_Handler - .weak DMA1_Channel4_IRQHandler - .thumb_set DMA1_Channel4_IRQHandler,Default_Handler + .weak DMA1_Channel4_IRQHandler + .thumb_set DMA1_Channel4_IRQHandler,Default_Handler - .weak DMA1_Channel5_IRQHandler - .thumb_set DMA1_Channel5_IRQHandler,Default_Handler + .weak DMA1_Channel5_IRQHandler + .thumb_set DMA1_Channel5_IRQHandler,Default_Handler - .weak DMA1_Channel6_IRQHandler - .thumb_set DMA1_Channel6_IRQHandler,Default_Handler + .weak DMA1_Channel6_IRQHandler + .thumb_set DMA1_Channel6_IRQHandler,Default_Handler - .weak DMA1_Channel7_IRQHandler - .thumb_set DMA1_Channel7_IRQHandler,Default_Handler + .weak DMA1_Channel7_IRQHandler + .thumb_set DMA1_Channel7_IRQHandler,Default_Handler - .weak ADC1_IRQHandler - .thumb_set ADC1_IRQHandler,Default_Handler + .weak ADC1_IRQHandler + .thumb_set ADC1_IRQHandler,Default_Handler - .weak USB_HP_IRQHandler - .thumb_set USB_HP_IRQHandler,Default_Handler + .weak USB_HP_IRQHandler + .thumb_set USB_HP_IRQHandler,Default_Handler - .weak USB_LP_IRQHandler - .thumb_set USB_LP_IRQHandler,Default_Handler + .weak USB_LP_IRQHandler + .thumb_set USB_LP_IRQHandler,Default_Handler - .weak C2SEV_PWR_C2H_IRQHandler - .thumb_set C2SEV_PWR_C2H_IRQHandler,Default_Handler + .weak C2SEV_PWR_C2H_IRQHandler + .thumb_set C2SEV_PWR_C2H_IRQHandler,Default_Handler - .weak COMP_IRQHandler - .thumb_set COMP_IRQHandler,Default_Handler + .weak COMP_IRQHandler + .thumb_set COMP_IRQHandler,Default_Handler - .weak EXTI9_5_IRQHandler - .thumb_set EXTI9_5_IRQHandler,Default_Handler + .weak EXTI9_5_IRQHandler + .thumb_set EXTI9_5_IRQHandler,Default_Handler - .weak TIM1_BRK_IRQHandler - .thumb_set TIM1_BRK_IRQHandler,Default_Handler + .weak TIM1_BRK_IRQHandler + .thumb_set TIM1_BRK_IRQHandler,Default_Handler - .weak TIM1_UP_TIM16_IRQHandler - .thumb_set TIM1_UP_TIM16_IRQHandler,Default_Handler + .weak TIM1_UP_TIM16_IRQHandler + .thumb_set TIM1_UP_TIM16_IRQHandler,Default_Handler - .weak TIM1_TRG_COM_TIM17_IRQHandler - .thumb_set TIM1_TRG_COM_TIM17_IRQHandler,Default_Handler + .weak TIM1_TRG_COM_TIM17_IRQHandler + .thumb_set TIM1_TRG_COM_TIM17_IRQHandler,Default_Handler - .weak TIM1_CC_IRQHandler - .thumb_set TIM1_CC_IRQHandler,Default_Handler + .weak TIM1_CC_IRQHandler + .thumb_set TIM1_CC_IRQHandler,Default_Handler - .weak TIM2_IRQHandler - .thumb_set TIM2_IRQHandler,Default_Handler + .weak TIM2_IRQHandler + .thumb_set TIM2_IRQHandler,Default_Handler - .weak PKA_IRQHandler - .thumb_set PKA_IRQHandler,Default_Handler + .weak PKA_IRQHandler + .thumb_set PKA_IRQHandler,Default_Handler - .weak I2C1_EV_IRQHandler - .thumb_set I2C1_EV_IRQHandler,Default_Handler + .weak I2C1_EV_IRQHandler + .thumb_set I2C1_EV_IRQHandler,Default_Handler - .weak I2C1_ER_IRQHandler - .thumb_set I2C1_ER_IRQHandler,Default_Handler + .weak I2C1_ER_IRQHandler + .thumb_set I2C1_ER_IRQHandler,Default_Handler - .weak I2C3_EV_IRQHandler - .thumb_set I2C3_EV_IRQHandler,Default_Handler + .weak I2C3_EV_IRQHandler + .thumb_set I2C3_EV_IRQHandler,Default_Handler - .weak I2C3_ER_IRQHandler - .thumb_set I2C3_ER_IRQHandler,Default_Handler + .weak I2C3_ER_IRQHandler + .thumb_set I2C3_ER_IRQHandler,Default_Handler - .weak SPI1_IRQHandler - .thumb_set SPI1_IRQHandler,Default_Handler + .weak SPI1_IRQHandler + .thumb_set SPI1_IRQHandler,Default_Handler - .weak SPI2_IRQHandler - .thumb_set SPI2_IRQHandler,Default_Handler + .weak SPI2_IRQHandler + .thumb_set SPI2_IRQHandler,Default_Handler - .weak USART1_IRQHandler - .thumb_set USART1_IRQHandler,Default_Handler + .weak USART1_IRQHandler + .thumb_set USART1_IRQHandler,Default_Handler - .weak LPUART1_IRQHandler - .thumb_set LPUART1_IRQHandler,Default_Handler + .weak LPUART1_IRQHandler + .thumb_set LPUART1_IRQHandler,Default_Handler - .weak SAI1_IRQHandler - .thumb_set SAI1_IRQHandler,Default_Handler + .weak SAI1_IRQHandler + .thumb_set SAI1_IRQHandler,Default_Handler - .weak TSC_IRQHandler - .thumb_set TSC_IRQHandler,Default_Handler + .weak TSC_IRQHandler + .thumb_set TSC_IRQHandler,Default_Handler - .weak EXTI15_10_IRQHandler - .thumb_set EXTI15_10_IRQHandler,Default_Handler + .weak EXTI15_10_IRQHandler + .thumb_set EXTI15_10_IRQHandler,Default_Handler - .weak RTC_Alarm_IRQHandler - .thumb_set RTC_Alarm_IRQHandler,Default_Handler + .weak RTC_Alarm_IRQHandler + .thumb_set RTC_Alarm_IRQHandler,Default_Handler - .weak CRS_IRQHandler - .thumb_set CRS_IRQHandler,Default_Handler + .weak CRS_IRQHandler + .thumb_set CRS_IRQHandler,Default_Handler - .weak PWR_SOTF_BLEACT_802ACT_RFPHASE_IRQHandler - .thumb_set PWR_SOTF_BLEACT_802ACT_RFPHASE_IRQHandler,Default_Handler + .weak PWR_SOTF_BLEACT_802ACT_RFPHASE_IRQHandler + .thumb_set PWR_SOTF_BLEACT_802ACT_RFPHASE_IRQHandler,Default_Handler - .weak IPCC_C1_RX_IRQHandler - .thumb_set IPCC_C1_RX_IRQHandler,Default_Handler + .weak IPCC_C1_RX_IRQHandler + .thumb_set IPCC_C1_RX_IRQHandler,Default_Handler - .weak IPCC_C1_TX_IRQHandler - .thumb_set IPCC_C1_TX_IRQHandler,Default_Handler + .weak IPCC_C1_TX_IRQHandler + .thumb_set IPCC_C1_TX_IRQHandler,Default_Handler - .weak HSEM_IRQHandler - .thumb_set HSEM_IRQHandler,Default_Handler + .weak HSEM_IRQHandler + .thumb_set HSEM_IRQHandler,Default_Handler - .weak LPTIM1_IRQHandler - .thumb_set LPTIM1_IRQHandler,Default_Handler + .weak LPTIM1_IRQHandler + .thumb_set LPTIM1_IRQHandler,Default_Handler - .weak LPTIM2_IRQHandler - .thumb_set LPTIM2_IRQHandler,Default_Handler + .weak LPTIM2_IRQHandler + .thumb_set LPTIM2_IRQHandler,Default_Handler - .weak LCD_IRQHandler - .thumb_set LCD_IRQHandler,Default_Handler + .weak LCD_IRQHandler + .thumb_set LCD_IRQHandler,Default_Handler - .weak QUADSPI_IRQHandler - .thumb_set QUADSPI_IRQHandler,Default_Handler + .weak QUADSPI_IRQHandler + .thumb_set QUADSPI_IRQHandler,Default_Handler - .weak AES1_IRQHandler - .thumb_set AES1_IRQHandler,Default_Handler + .weak AES1_IRQHandler + .thumb_set AES1_IRQHandler,Default_Handler - .weak AES2_IRQHandler - .thumb_set AES2_IRQHandler,Default_Handler + .weak AES2_IRQHandler + .thumb_set AES2_IRQHandler,Default_Handler - .weak RNG_IRQHandler - .thumb_set RNG_IRQHandler,Default_Handler + .weak RNG_IRQHandler + .thumb_set RNG_IRQHandler,Default_Handler - .weak FPU_IRQHandler - .thumb_set FPU_IRQHandler,Default_Handler + .weak FPU_IRQHandler + .thumb_set FPU_IRQHandler,Default_Handler - .weak DMA2_Channel1_IRQHandler - .thumb_set DMA2_Channel1_IRQHandler,Default_Handler + .weak DMA2_Channel1_IRQHandler + .thumb_set DMA2_Channel1_IRQHandler,Default_Handler - .weak DMA2_Channel2_IRQHandler - .thumb_set DMA2_Channel2_IRQHandler,Default_Handler + .weak DMA2_Channel2_IRQHandler + .thumb_set DMA2_Channel2_IRQHandler,Default_Handler - .weak DMA2_Channel3_IRQHandler - .thumb_set DMA2_Channel3_IRQHandler,Default_Handler + .weak DMA2_Channel3_IRQHandler + .thumb_set DMA2_Channel3_IRQHandler,Default_Handler - .weak DMA2_Channel4_IRQHandler - .thumb_set DMA2_Channel4_IRQHandler,Default_Handler + .weak DMA2_Channel4_IRQHandler + .thumb_set DMA2_Channel4_IRQHandler,Default_Handler - .weak DMA2_Channel5_IRQHandler - .thumb_set DMA2_Channel5_IRQHandler,Default_Handler + .weak DMA2_Channel5_IRQHandler + .thumb_set DMA2_Channel5_IRQHandler,Default_Handler - .weak DMA2_Channel6_IRQHandler - .thumb_set DMA2_Channel6_IRQHandler,Default_Handler + .weak DMA2_Channel6_IRQHandler + .thumb_set DMA2_Channel6_IRQHandler,Default_Handler - .weak DMA2_Channel7_IRQHandler - .thumb_set DMA2_Channel7_IRQHandler,Default_Handler + .weak DMA2_Channel7_IRQHandler + .thumb_set DMA2_Channel7_IRQHandler,Default_Handler - .weak DMAMUX1_OVR_IRQHandler - .thumb_set DMAMUX1_OVR_IRQHandler,Default_Handler + .weak DMAMUX1_OVR_IRQHandler + .thumb_set DMAMUX1_OVR_IRQHandler,Default_Handler /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/firmware/targets/f7/furi_hal/furi_hal_bt.c b/firmware/targets/f7/furi_hal/furi_hal_bt.c index 4465f15e..1bd244a9 100755 --- a/firmware/targets/f7/furi_hal/furi_hal_bt.c +++ b/firmware/targets/f7/furi_hal/furi_hal_bt.c @@ -47,7 +47,7 @@ FuriHalBtProfileConfig profile_config[FuriHalBtProfileNumber] = { .conn_int_min = 0x08, .conn_int_max = 0x18, .slave_latency = 0, - .supervisor_timeout = 50, + .supervisor_timeout = 0, }, }, }, @@ -246,7 +246,7 @@ bool furi_hal_bt_change_app(FuriHalBtProfile profile, GapEventCallback event_cb, return ret; } -static bool furi_hal_bt_is_active() { +bool furi_hal_bt_is_active() { return gap_get_state() > GapStateIdle; } diff --git a/firmware/targets/f7/furi_hal/furi_hal_gpio.c b/firmware/targets/f7/furi_hal/furi_hal_gpio.c index 8c2aefe2..a6f25d10 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_gpio.c +++ b/firmware/targets/f7/furi_hal/furi_hal_gpio.c @@ -68,25 +68,37 @@ void hal_gpio_init_ex( uint32_t exti_line = GET_EXTI_LINE(gpio->pin); // Configure gpio with interrupts disabled - __disable_irq(); + FURI_CRITICAL_ENTER(); + // Set gpio speed - if(speed == GpioSpeedLow) { + switch(speed) { + case GpioSpeedLow: LL_GPIO_SetPinSpeed(gpio->port, gpio->pin, LL_GPIO_SPEED_FREQ_LOW); - } else if(speed == GpioSpeedMedium) { + break; + case GpioSpeedMedium: LL_GPIO_SetPinSpeed(gpio->port, gpio->pin, LL_GPIO_SPEED_FREQ_MEDIUM); - } else if(speed == GpioSpeedHigh) { + break; + case GpioSpeedHigh: LL_GPIO_SetPinSpeed(gpio->port, gpio->pin, LL_GPIO_SPEED_FREQ_HIGH); - } else { + break; + case GpioSpeedVeryHigh: LL_GPIO_SetPinSpeed(gpio->port, gpio->pin, LL_GPIO_SPEED_FREQ_VERY_HIGH); + break; } + // Set gpio pull mode - if(pull == GpioPullNo) { + switch(pull) { + case GpioPullNo: LL_GPIO_SetPinPull(gpio->port, gpio->pin, LL_GPIO_PULL_NO); - } else if(pull == GpioPullUp) { + break; + case GpioPullUp: LL_GPIO_SetPinPull(gpio->port, gpio->pin, LL_GPIO_PULL_UP); - } else { + break; + case GpioPullDown: LL_GPIO_SetPinPull(gpio->port, gpio->pin, LL_GPIO_PULL_DOWN); + break; } + // Set gpio mode if(mode >= GpioModeInterruptRise) { // Set pin in interrupt mode @@ -100,93 +112,106 @@ void hal_gpio_init_ex( LL_EXTI_EnableIT_0_31(exti_line); LL_EXTI_EnableFallingTrig_0_31(exti_line); } - if(mode == GpioModeEventRise || mode == GpioModeInterruptRiseFall) { + if(mode == GpioModeEventRise || mode == GpioModeEventRiseFall) { LL_EXTI_EnableEvent_0_31(exti_line); LL_EXTI_EnableRisingTrig_0_31(exti_line); } - if(mode == GpioModeEventFall || mode == GpioModeInterruptRiseFall) { + if(mode == GpioModeEventFall || mode == GpioModeEventRiseFall) { LL_EXTI_EnableEvent_0_31(exti_line); LL_EXTI_EnableFallingTrig_0_31(exti_line); } } else { - // Disable interrupt if it was set + // Disable interrupts if set if(LL_SYSCFG_GetEXTISource(sys_exti_line) == sys_exti_port && LL_EXTI_IsEnabledIT_0_31(exti_line)) { LL_EXTI_DisableIT_0_31(exti_line); LL_EXTI_DisableRisingTrig_0_31(exti_line); LL_EXTI_DisableFallingTrig_0_31(exti_line); } + + // Prepare alternative part if any + if(mode == GpioModeAltFunctionPushPull || mode == GpioModeAltFunctionOpenDrain) { + // set alternate function + if(hal_gpio_get_pin_num(gpio) < 8) { + LL_GPIO_SetAFPin_0_7(gpio->port, gpio->pin, alt_fn); + } else { + LL_GPIO_SetAFPin_8_15(gpio->port, gpio->pin, alt_fn); + } + } + // Set not interrupt pin modes - if(mode == GpioModeInput) { + switch(mode) { + case GpioModeInput: LL_GPIO_SetPinMode(gpio->port, gpio->pin, LL_GPIO_MODE_INPUT); - } else if(mode == GpioModeOutputPushPull || mode == GpioModeAltFunctionPushPull) { - LL_GPIO_SetPinMode(gpio->port, gpio->pin, LL_GPIO_MODE_OUTPUT); + break; + case GpioModeOutputPushPull: LL_GPIO_SetPinOutputType(gpio->port, gpio->pin, LL_GPIO_OUTPUT_PUSHPULL); - } else if(mode == GpioModeOutputOpenDrain || mode == GpioModeAltFunctionOpenDrain) { LL_GPIO_SetPinMode(gpio->port, gpio->pin, LL_GPIO_MODE_OUTPUT); + break; + case GpioModeAltFunctionPushPull: + LL_GPIO_SetPinOutputType(gpio->port, gpio->pin, LL_GPIO_OUTPUT_PUSHPULL); + LL_GPIO_SetPinMode(gpio->port, gpio->pin, LL_GPIO_MODE_ALTERNATE); + break; + case GpioModeOutputOpenDrain: LL_GPIO_SetPinOutputType(gpio->port, gpio->pin, LL_GPIO_OUTPUT_OPENDRAIN); - } else if(mode == GpioModeAnalog) { + LL_GPIO_SetPinMode(gpio->port, gpio->pin, LL_GPIO_MODE_OUTPUT); + break; + case GpioModeAltFunctionOpenDrain: + LL_GPIO_SetPinOutputType(gpio->port, gpio->pin, LL_GPIO_OUTPUT_OPENDRAIN); + LL_GPIO_SetPinMode(gpio->port, gpio->pin, LL_GPIO_MODE_ALTERNATE); + break; + case GpioModeAnalog: LL_GPIO_SetPinMode(gpio->port, gpio->pin, LL_GPIO_MODE_ANALOG); + break; + default: + break; } } - - if(mode == GpioModeAltFunctionPushPull || mode == GpioModeAltFunctionOpenDrain) { - // enable alternate mode - LL_GPIO_SetPinMode(gpio->port, gpio->pin, LL_GPIO_MODE_ALTERNATE); - - // set alternate function - if(hal_gpio_get_pin_num(gpio) < 8) { - LL_GPIO_SetAFPin_0_7(gpio->port, gpio->pin, alt_fn); - } else { - LL_GPIO_SetAFPin_8_15(gpio->port, gpio->pin, alt_fn); - } - } - - __enable_irq(); + FURI_CRITICAL_EXIT(); } void hal_gpio_add_int_callback(const GpioPin* gpio, GpioExtiCallback cb, void* ctx) { furi_assert(gpio); furi_assert(cb); - __disable_irq(); + FURI_CRITICAL_ENTER(); uint8_t pin_num = hal_gpio_get_pin_num(gpio); furi_assert(gpio_interrupt[pin_num].callback == NULL); gpio_interrupt[pin_num].callback = cb; gpio_interrupt[pin_num].context = ctx; gpio_interrupt[pin_num].ready = true; - __enable_irq(); + FURI_CRITICAL_EXIT(); } void hal_gpio_enable_int_callback(const GpioPin* gpio) { furi_assert(gpio); - __disable_irq(); + FURI_CRITICAL_ENTER(); uint8_t pin_num = hal_gpio_get_pin_num(gpio); if(gpio_interrupt[pin_num].callback) { gpio_interrupt[pin_num].ready = true; } - __enable_irq(); + FURI_CRITICAL_EXIT(); } void hal_gpio_disable_int_callback(const GpioPin* gpio) { furi_assert(gpio); - __disable_irq(); + FURI_CRITICAL_ENTER(); uint8_t pin_num = hal_gpio_get_pin_num(gpio); gpio_interrupt[pin_num].ready = false; - __enable_irq(); + FURI_CRITICAL_EXIT(); } void hal_gpio_remove_int_callback(const GpioPin* gpio) { furi_assert(gpio); - __disable_irq(); + FURI_CRITICAL_ENTER(); uint8_t pin_num = hal_gpio_get_pin_num(gpio); gpio_interrupt[pin_num].callback = NULL; gpio_interrupt[pin_num].context = NULL; gpio_interrupt[pin_num].ready = false; - __enable_irq(); + FURI_CRITICAL_EXIT(); } static void hal_gpio_int_call(uint16_t pin_num) { diff --git a/firmware/targets/f7/furi_hal/furi_hal_irda.c b/firmware/targets/f7/furi_hal/furi_hal_irda.c index 070e3c16..cd984741 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_irda.c +++ b/firmware/targets/f7/furi_hal/furi_hal_irda.c @@ -516,7 +516,7 @@ static void furi_hal_irda_tx_dma_set_polarity(uint8_t buf_num, uint8_t polarity_ IrdaTxBuf* buffer = &irda_tim_tx.buffer[buf_num]; furi_assert(buffer->polarity != NULL); - __disable_irq(); + FURI_CRITICAL_ENTER(); bool channel_enabled = LL_DMA_IsEnabledChannel(DMA1, LL_DMA_CHANNEL_1); if(channel_enabled) { LL_DMA_DisableChannel(DMA1, LL_DMA_CHANNEL_1); @@ -526,7 +526,7 @@ static void furi_hal_irda_tx_dma_set_polarity(uint8_t buf_num, uint8_t polarity_ if(channel_enabled) { LL_DMA_EnableChannel(DMA1, LL_DMA_CHANNEL_1); } - __enable_irq(); + FURI_CRITICAL_EXIT(); } static void furi_hal_irda_tx_dma_set_buffer(uint8_t buf_num) { @@ -536,7 +536,7 @@ static void furi_hal_irda_tx_dma_set_buffer(uint8_t buf_num) { furi_assert(buffer->data != NULL); /* non-circular mode requires disabled channel before setup */ - __disable_irq(); + FURI_CRITICAL_ENTER(); bool channel_enabled = LL_DMA_IsEnabledChannel(DMA1, LL_DMA_CHANNEL_2); if(channel_enabled) { LL_DMA_DisableChannel(DMA1, LL_DMA_CHANNEL_2); @@ -546,7 +546,7 @@ static void furi_hal_irda_tx_dma_set_buffer(uint8_t buf_num) { if(channel_enabled) { LL_DMA_EnableChannel(DMA1, LL_DMA_CHANNEL_2); } - __enable_irq(); + FURI_CRITICAL_EXIT(); } static void furi_hal_irda_async_tx_free_resources(void) { @@ -621,10 +621,10 @@ void furi_hal_irda_async_tx_start(uint32_t freq, float duty_cycle) { hal_gpio_init_ex( &gpio_irda_tx, GpioModeAltFunctionPushPull, GpioPullUp, GpioSpeedHigh, GpioAltFn1TIM1); - __disable_irq(); + FURI_CRITICAL_ENTER(); LL_TIM_GenerateEvent_UPDATE(TIM1); /* TIMx_RCR -> Repetition counter */ LL_TIM_EnableCounter(TIM1); - __enable_irq(); + FURI_CRITICAL_EXIT(); } void furi_hal_irda_async_tx_wait_termination(void) { @@ -642,9 +642,9 @@ void furi_hal_irda_async_tx_stop(void) { furi_assert(furi_hal_irda_state >= IrdaStateAsyncTx); furi_assert(furi_hal_irda_state < IrdaStateMAX); - __disable_irq(); + FURI_CRITICAL_ENTER(); if(furi_hal_irda_state == IrdaStateAsyncTx) furi_hal_irda_state = IrdaStateAsyncTxStopReq; - __enable_irq(); + FURI_CRITICAL_EXIT(); furi_hal_irda_async_tx_wait_termination(); } diff --git a/firmware/targets/f7/furi_hal/furi_hal_os.c b/firmware/targets/f7/furi_hal/furi_hal_os.c index 6ef5a9f4..3a6e5f38 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_os.c +++ b/firmware/targets/f7/furi_hal/furi_hal_os.c @@ -115,11 +115,11 @@ void vPortSuppressTicksAndSleep(TickType_t expected_idle_ticks) { } // Stop IRQ handling, no one should disturb us till we finish - __disable_irq(); + FURI_CRITICAL_ENTER(); // Confirm OS that sleep is still possible if(eTaskConfirmSleepModeStatus() == eAbortSleep) { - __enable_irq(); + FURI_CRITICAL_EXIT(); return; } @@ -136,7 +136,7 @@ void vPortSuppressTicksAndSleep(TickType_t expected_idle_ticks) { } // Reenable IRQ - __enable_irq(); + FURI_CRITICAL_EXIT(); } void vApplicationStackOverflowHook(TaskHandle_t xTask, char* pcTaskName) { diff --git a/firmware/targets/f7/furi_hal/furi_hal_power.c b/firmware/targets/f7/furi_hal/furi_hal_power.c index 1dbdb3dd..e34ba46e 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_power.c +++ b/firmware/targets/f7/furi_hal/furi_hal_power.c @@ -89,15 +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_uart.c b/firmware/targets/f7/furi_hal/furi_hal_uart.c index 1ebba5d3..2ee0cf85 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_uart.c +++ b/firmware/targets/f7/furi_hal/furi_hal_uart.c @@ -5,6 +5,7 @@ #include #include +#include static void (*irq_cb[2])(uint8_t ev, uint8_t data, void* context); static void* irq_ctx[2]; @@ -33,13 +34,12 @@ static void furi_hal_usart_init(uint32_t baud) { USART_InitStruct.HardwareFlowControl = LL_USART_HWCONTROL_NONE; USART_InitStruct.OverSampling = LL_USART_OVERSAMPLING_16; LL_USART_Init(USART1, &USART_InitStruct); - LL_USART_SetTXFIFOThreshold(USART1, LL_USART_FIFOTHRESHOLD_1_2); LL_USART_EnableFIFO(USART1); LL_USART_ConfigAsyncMode(USART1); LL_USART_Enable(USART1); - while(!LL_USART_IsActiveFlag_TEACK(USART1)) + while(!LL_USART_IsActiveFlag_TEACK(USART1) || !LL_USART_IsActiveFlag_REACK(USART1)) ; LL_USART_EnableIT_RXNE_RXFNE(USART1); @@ -70,13 +70,11 @@ static void furi_hal_lpuart_init(uint32_t baud) { LPUART_InitStruct.TransferDirection = LL_LPUART_DIRECTION_TX_RX; LPUART_InitStruct.HardwareFlowControl = LL_LPUART_HWCONTROL_NONE; LL_LPUART_Init(LPUART1, &LPUART_InitStruct); - LL_LPUART_SetTXFIFOThreshold(LPUART1, LL_LPUART_FIFOTHRESHOLD_1_8); - LL_LPUART_SetRXFIFOThreshold(LPUART1, LL_LPUART_FIFOTHRESHOLD_1_8); LL_LPUART_EnableFIFO(LPUART1); LL_LPUART_Enable(LPUART1); - while((!(LL_LPUART_IsActiveFlag_TEACK(LPUART1))) || (!(LL_LPUART_IsActiveFlag_REACK(LPUART1)))) + while(!LL_LPUART_IsActiveFlag_TEACK(LPUART1) || !LL_LPUART_IsActiveFlag_REACK(LPUART1)) ; furi_hal_uart_set_br(FuriHalUartIdLPUART1, baud); 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/f7/target.mk b/firmware/targets/f7/target.mk index 0c9bd182..767cbfa0 100644 --- a/firmware/targets/f7/target.mk +++ b/firmware/targets/f7/target.mk @@ -14,7 +14,13 @@ FLASH_ADDRESS = 0x08000000 CFLAGS += -DNO_BOOTLOADER endif +DEBUG_RTOS_THREADS ?= 1 +ifeq ($(DEBUG_RTOS_THREADS), 1) OPENOCD_OPTS = -f interface/stlink.cfg -c "transport select hla_swd" -f ../debug/stm32wbx.cfg -c "stm32wbx.cpu configure -rtos auto" -c "init" +else +OPENOCD_OPTS = -f interface/stlink.cfg -c "transport select hla_swd" -f ../debug/stm32wbx.cfg -c "init" +endif + BOOT_CFLAGS = -DBOOT_ADDRESS=$(BOOT_ADDRESS) -DFW_ADDRESS=$(FW_ADDRESS) -DOS_OFFSET=$(OS_OFFSET) MCU_FLAGS = -mcpu=cortex-m4 -mthumb -mfpu=fpv4-sp-d16 -mfloat-abi=hard diff --git a/firmware/targets/furi_hal_include/furi_hal_bt.h b/firmware/targets/furi_hal_include/furi_hal_bt.h index e10901b0..912132d2 100644 --- a/firmware/targets/furi_hal_include/furi_hal_bt.h +++ b/firmware/targets/furi_hal_include/furi_hal_bt.h @@ -84,6 +84,12 @@ bool furi_hal_bt_change_app(FuriHalBtProfile profile, GapEventCallback event_cb, */ void furi_hal_bt_update_battery_level(uint8_t battery_level); +/** Checks if BLE state is active + * + * @return true if device is connected or advertising, false otherwise + */ +bool furi_hal_bt_is_active(); + /** Start advertising */ void furi_hal_bt_start_advertising(); 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 diff --git a/lib/FreeRTOS-glue/cmsis_os2.c b/lib/FreeRTOS-glue/cmsis_os2.c index d1dcce86..0f0c0f6e 100644 --- a/lib/FreeRTOS-glue/cmsis_os2.c +++ b/lib/FreeRTOS-glue/cmsis_os2.c @@ -22,6 +22,8 @@ #include +#include + #include "cmsis_os2.h" // ::CMSIS:RTOS2 #include "cmsis_compiler.h" // Compiler agnostic definitions #include "os_tick.h" // OS Tick API @@ -455,11 +457,10 @@ uint32_t osKernelGetTickFreq (void) { Get the RTOS kernel system timer count. */ uint32_t osKernelGetSysTimerCount (void) { - uint32_t irqmask = IS_IRQ_MASKED(); TickType_t ticks; uint32_t val; - __disable_irq(); + FURI_CRITICAL_ENTER(); ticks = xTaskGetTickCount(); val = OS_Tick_GetCount(); @@ -471,9 +472,7 @@ uint32_t osKernelGetSysTimerCount (void) { } val += ticks * OS_Tick_GetInterval(); - if (irqmask == 0U) { - __enable_irq(); - } + FURI_CRITICAL_EXIT(); /* Return system timer count */ return (val); diff --git a/lib/cyfral/cyfral_emulator.h b/lib/cyfral/cyfral_emulator.h deleted file mode 100644 index 924198d4..00000000 --- a/lib/cyfral/cyfral_emulator.h +++ /dev/null @@ -1,96 +0,0 @@ -#pragma once - -#include -#include - -class CyfralTiming { -public: - constexpr static const uint8_t ZERO_HIGH = 50; - constexpr static const uint8_t ZERO_LOW = 70; - constexpr static const uint8_t ONE_HIGH = 100; - constexpr static const uint8_t ONE_LOW = 70; -}; - -class CyfralEmulator { -private: - void send_nibble(uint8_t nibble); - void send_byte(uint8_t data); - inline void send_bit(bool bit); - const GpioPin* emulate_pin_record; - -public: - CyfralEmulator(const GpioPin* emulate_pin); - ~CyfralEmulator(); - void send(uint8_t* data, uint8_t count = 1, uint8_t repeat = 1); - void start(void); - void stop(void); -}; - -// 7 = 0 1 1 1 -// B = 1 0 1 1 -// D = 1 1 0 1 -// E = 1 1 1 0 - -void CyfralEmulator::send_nibble(uint8_t nibble) { - for(uint8_t i = 0; i < 4; i++) { - bool bit = nibble & (0b1000 >> i); - send_bit(bit); - } -} - -void CyfralEmulator::send_byte(uint8_t data) { - for(uint8_t i = 0; i < 8; i++) { - bool bit = data & (0b10000000 >> i); - send_bit(bit); - } -} - -void CyfralEmulator::send_bit(bool bit) { - if(!bit) { - hal_gpio_write(&ibutton_gpio, false); - delay_us(CyfralTiming::ZERO_LOW); - hal_gpio_write(&ibutton_gpio, true); - delay_us(CyfralTiming::ZERO_HIGH); - hal_gpio_write(&ibutton_gpio, false); - delay_us(CyfralTiming::ZERO_LOW); - } else { - hal_gpio_write(&ibutton_gpio, true); - delay_us(CyfralTiming::ONE_HIGH); - hal_gpio_write(&ibutton_gpio, false); - delay_us(CyfralTiming::ONE_LOW); - } -} - -CyfralEmulator::CyfralEmulator(const GpioPin* emulate_pin) { - emulate_pin_record = emulate_pin; -} - -CyfralEmulator::~CyfralEmulator() { -} - -void CyfralEmulator::send(uint8_t* data, uint8_t count, uint8_t repeat) { - osKernelLock(); - __disable_irq(); - - for(uint8_t i = 0; i < repeat; i++) { - // start sequence - send_nibble(0x01); - - // send data - for(uint8_t i = 0; i < count; i++) { - send_byte(data[i]); - } - } - - __enable_irq(); - osKernelUnlock(); -} - -void CyfralEmulator::start(void) { - hal_gpio_init(emulate_pin_record, GpioModeOutputOpenDrain, GpioPullNo, GpioSpeedLow); - hal_gpio_write(emulate_pin_record, false); -} - -void CyfralEmulator::stop(void) { - hal_gpio_init(emulate_pin_record, GpioModeAnalog, GpioPullNo, GpioSpeedLow); -} \ No newline at end of file diff --git a/lib/cyfral/cyfral_reader.h b/lib/cyfral/cyfral_reader.h deleted file mode 100644 index 498a4920..00000000 --- a/lib/cyfral/cyfral_reader.h +++ /dev/null @@ -1,272 +0,0 @@ -#pragma once -#include - -enum class CyfralReaderError : uint8_t { - NO_ERROR = 0, - UNABLE_TO_DETECT = 1, - RAW_DATA_SIZE_ERROR = 2, - UNKNOWN_NIBBLE_VALUE = 3, - NO_START_NIBBLE = 4, -}; - -class CyfralReader { -private: - ADC_HandleTypeDef adc_config; - ADC_TypeDef* adc_instance; - uint32_t adc_channel; - - void get_line_minmax(uint16_t times, uint32_t* min_level, uint32_t* max_level); - void capture_data(bool* data, uint16_t capture_size, uint32_t line_min, uint32_t line_max); - bool parse_data(bool* raw_data, uint16_t capture_size, uint8_t* data, uint8_t count); - uint32_t search_array_in_array( - const bool* haystack, - const uint32_t haystack_size, - const bool* needle, - const uint32_t needle_size); - - // key is 9 nibbles - static const uint16_t bits_in_nibble = 4; - static const uint16_t key_length = 9; - static const uint32_t capture_size = key_length * bits_in_nibble * 2; - CyfralReaderError error; - -public: - CyfralReader(ADC_TypeDef* adc, uint32_t Channel); - ~CyfralReader(); - void start(void); - void stop(void); - bool read(uint8_t* data, uint8_t count); -}; - -void CyfralReader::get_line_minmax(uint16_t times, uint32_t* min_level, uint32_t* max_level) { - uint32_t in = 0; - uint32_t min = UINT_MAX; - uint32_t max = 0; - - for(uint32_t i = 0; i < 256; i++) { - HAL_ADC_Start(&adc_config); - HAL_ADC_PollForConversion(&adc_config, 100); - in = HAL_ADC_GetValue(&adc_config); - if(in < min) min = in; - if(in > max) max = in; - } - - *min_level = min; - *max_level = max; -} - -void CyfralReader::capture_data( - bool* data, - uint16_t capture_size, - uint32_t line_min, - uint32_t line_max) { - uint32_t input_value = 0; - bool last_input_value = 0; - - uint32_t diff = line_max - line_min; - uint32_t mid = line_min + diff / 2; - - uint32_t low_threshold = mid - (diff / 4); - uint32_t high_threshold = mid - (diff / 4); - - uint16_t capture_position = 0; - uint32_t instructions_per_us = (SystemCoreClock / 1000000.0f); - uint32_t time_threshold = 75 * instructions_per_us; - uint32_t capture_max_time = 140 * (capture_size * 2) * instructions_per_us; - - uint32_t start = DWT->CYCCNT; - uint32_t end = DWT->CYCCNT; - - memset(data, 0, capture_size); - - osKernelLock(); - - uint32_t capture_start = DWT->CYCCNT; - while((capture_position < capture_size) && - ((DWT->CYCCNT - capture_start) < capture_max_time)) { - // read adc - HAL_ADC_Start(&adc_config); - HAL_ADC_PollForConversion(&adc_config, 100); - input_value = HAL_ADC_GetValue(&adc_config); - - // low to high transition - if((input_value > high_threshold) && last_input_value == 0) { - last_input_value = 1; - start = DWT->CYCCNT; - } - - // high to low transition - if((input_value < low_threshold) && last_input_value == 1) { - last_input_value = 0; - end = DWT->CYCCNT; - - // check transition time - if(end - start < time_threshold) { - data[capture_position] = 1; - capture_position++; - } else { - data[capture_position] = 0; - capture_position++; - } - } - } - - osKernelUnlock(); -} - -uint32_t CyfralReader::search_array_in_array( - const bool* haystack, - const uint32_t haystack_size, - const bool* needle, - const uint32_t needle_size) { - uint32_t haystack_index = 0, needle_index = 0; - - while(haystack_index < haystack_size && needle_index < needle_size) { - if(haystack[haystack_index] == needle[needle_index]) { - haystack_index++; - needle_index++; - if(needle_index == needle_size) { - return (haystack_index - needle_size); - }; - } else { - haystack_index = haystack_index - needle_index + 1; - needle_index = 0; - } - } - - return haystack_index; -} - -bool CyfralReader::parse_data(bool* raw_data, uint16_t capture_size, uint8_t* data, uint8_t count) { - const bool start_nibble[bits_in_nibble] = {1, 1, 1, 0}; - uint32_t start_position = - search_array_in_array(raw_data, capture_size, start_nibble, bits_in_nibble); - uint32_t end_position = 0; - - memset(data, 0, count); - - if(start_position < capture_size) { - start_position = start_position + bits_in_nibble; - end_position = start_position + count * 2 * bits_in_nibble; - - if(end_position >= capture_size) { - error = CyfralReaderError::RAW_DATA_SIZE_ERROR; - return false; - } - - bool first_nibble = true; - uint8_t data_position = 0; - uint8_t nibble_value = 0; - - while(data_position < count) { - nibble_value = !raw_data[start_position] << 3 | !raw_data[start_position + 1] << 2 | - !raw_data[start_position + 2] << 1 | !raw_data[start_position + 3]; - - switch(nibble_value) { - case(0x7): - case(0xB): - case(0xD): - case(0xE): - break; - default: - error = CyfralReaderError::UNKNOWN_NIBBLE_VALUE; - return false; - break; - } - - if(first_nibble) { - data[data_position] |= nibble_value << 4; - } else { - data[data_position] |= nibble_value; - } - - first_nibble = !first_nibble; - - if(first_nibble) { - data_position++; - } - - start_position = start_position + bits_in_nibble; - } - - error = CyfralReaderError::NO_ERROR; - return true; - } - - error = CyfralReaderError::NO_START_NIBBLE; - return false; -} - -CyfralReader::CyfralReader(ADC_TypeDef* adc, uint32_t channel) { - adc_instance = adc; - adc_channel = channel; -} - -CyfralReader::~CyfralReader() { -} - -void CyfralReader::start(void) { - ADC_ChannelConfTypeDef sConfig = {0}; - - // init ADC - adc_config.Instance = adc_instance; - adc_config.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV1; - adc_config.Init.Resolution = ADC_RESOLUTION_12B; - adc_config.Init.DataAlign = ADC_DATAALIGN_RIGHT; - adc_config.Init.ScanConvMode = ADC_SCAN_DISABLE; - adc_config.Init.EOCSelection = ADC_EOC_SINGLE_CONV; - adc_config.Init.LowPowerAutoWait = DISABLE; - adc_config.Init.ContinuousConvMode = DISABLE; - adc_config.Init.NbrOfConversion = 1; - adc_config.Init.DiscontinuousConvMode = DISABLE; - adc_config.Init.ExternalTrigConv = ADC_SOFTWARE_START; - adc_config.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE; - adc_config.Init.DMAContinuousRequests = DISABLE; - adc_config.Init.Overrun = ADC_OVR_DATA_PRESERVED; - adc_config.Init.OversamplingMode = DISABLE; - if(HAL_ADC_Init(&adc_config) != HAL_OK) { - Error_Handler(); - } - - // init channel - sConfig.Channel = adc_channel; - sConfig.Rank = ADC_REGULAR_RANK_1; - sConfig.SamplingTime = ADC_SAMPLETIME_2CYCLES_5; - sConfig.SingleDiff = ADC_SINGLE_ENDED; - sConfig.OffsetNumber = ADC_OFFSET_NONE; - sConfig.Offset = 0; - if(HAL_ADC_ConfigChannel(&adc_config, &sConfig) != HAL_OK) { - Error_Handler(); - } -} - -void CyfralReader::stop(void) { - HAL_ADC_DeInit(&adc_config); -} - -bool CyfralReader::read(uint8_t* data, uint8_t count) { - uint32_t line_level_min, line_level_max; - bool raw_data[capture_size]; - bool result = false; - error = CyfralReaderError::NO_ERROR; - - // calibrate - get_line_minmax(256, &line_level_min, &line_level_max); - - // TODO think about other detection method - // key not on line - if(line_level_max > 2000) { - error = CyfralReaderError::UNABLE_TO_DETECT; - return false; - } - - // capturing raw data consisting of bits - capture_data(raw_data, capture_size, line_level_min, line_level_max); - - // parse captured data - if(parse_data(raw_data, capture_size, data, count)) { - result = true; - } - - return result; -} \ No newline at end of file diff --git a/lib/cyfral/cyfral_reader_comp.h b/lib/cyfral/cyfral_reader_comp.h deleted file mode 100644 index 023fadbf..00000000 --- a/lib/cyfral/cyfral_reader_comp.h +++ /dev/null @@ -1,283 +0,0 @@ -#pragma once -#include -#include "callback-connector.h" -#include - -enum class CyfralReaderCompError : uint8_t { - NO_ERROR = 0, - UNABLE_TO_DETECT = 1, - RAW_DATA_SIZE_ERROR = 2, - UNKNOWN_NIBBLE_VALUE = 3, - NO_START_NIBBLE = 4, - NOT_ENOUGH_DATA = 5, -}; - -extern COMP_HandleTypeDef hcomp1; - -typedef struct { - bool value; - uint32_t dwt_value; -} CompEvent; - -class CyfralReaderComp { -private: - bool capture_data(bool* data, uint16_t capture_size); - bool parse_data(bool* raw_data, uint16_t capture_size, uint8_t* data, uint8_t count); - uint32_t search_array_in_array( - const bool* haystack, - const uint32_t haystack_size, - const bool* needle, - const uint32_t needle_size); - - // key is 9 nibbles - static const uint16_t bits_in_nibble = 4; - static const uint16_t key_length = 9; - static const uint32_t capture_size = key_length * bits_in_nibble * 2; - CyfralReaderCompError error; - const GpioPin* pin_record; - - std::atomic ready_to_process; - void comparator_trigger_callback(void* hcomp, void* comp_ctx); - osMessageQueueId_t comp_event_queue; - -public: - CyfralReaderComp(const GpioPin* emulate_pin); - ~CyfralReaderComp(); - void start(void); - void stop(void); - bool read(uint8_t* data, uint8_t count); -}; - -bool CyfralReaderComp::capture_data(bool* data, uint16_t capture_size) { - uint32_t prev_timing = 0; - uint16_t data_index = 0; - CompEvent event_0, event_1; - osStatus_t status; - - // read first event to get initial timing - status = osMessageQueueGet(comp_event_queue, &event_0, NULL, 0); - - if(status != osOK) { - return false; - } - - prev_timing = event_0.dwt_value; - - // read second event until we get 0 - while(1) { - status = osMessageQueueGet(comp_event_queue, &event_0, NULL, 0); - if(status != osOK) { - return false; - } - prev_timing = event_0.dwt_value; - if(event_0.value == 0) break; - } - - while(1) { - // if event "zero" correct - if(status == osOK && event_0.value == 0) { - // get timing - event_0.dwt_value -= prev_timing; - prev_timing += event_0.dwt_value; - - // read next event - status = osMessageQueueGet(comp_event_queue, &event_1, NULL, 0); - - // if event "one" correct - if(status == osOK && event_1.value == 1) { - // get timing - event_1.dwt_value -= prev_timing; - prev_timing += event_1.dwt_value; - - // calculate percentage of event "one" to full timing - uint32_t full_timing = event_0.dwt_value + event_1.dwt_value; - uint32_t percentage_1 = 1000000 / full_timing * event_1.dwt_value; - - // write captured data - data[data_index] = percentage_1 > 500000 ? 0 : 1; - data_index++; - if(data_index >= capture_size) return true; - - status = osMessageQueueGet(comp_event_queue, &event_0, NULL, 0); - } else { - return false; - } - } else { - return false; - } - } - - osMessageQueueReset(comp_event_queue); -} - -uint32_t CyfralReaderComp::search_array_in_array( - const bool* haystack, - const uint32_t haystack_size, - const bool* needle, - const uint32_t needle_size) { - uint32_t haystack_index = 0, needle_index = 0; - - while(haystack_index < haystack_size && needle_index < needle_size) { - if(haystack[haystack_index] == needle[needle_index]) { - haystack_index++; - needle_index++; - if(needle_index == needle_size) { - return (haystack_index - needle_size); - }; - } else { - haystack_index = haystack_index - needle_index + 1; - needle_index = 0; - } - } - - return haystack_index; -} - -void CyfralReaderComp::comparator_trigger_callback(void* hcomp, void* comp_ctx) { - CyfralReaderComp* _this = static_cast(comp_ctx); - COMP_HandleTypeDef* _hcomp = static_cast(hcomp); - - // check that hw is comparator 1 - if(_hcomp != &hcomp1) return; - - // if queue if not full - if(_this->ready_to_process == false) { - // send event to queue - CompEvent event; - // TOOD F4 and F5 differ - event.value = (HAL_COMP_GetOutputLevel(_hcomp) == COMP_OUTPUT_LEVEL_LOW); - event.dwt_value = DWT->CYCCNT; - osStatus_t status = osMessageQueuePut(_this->comp_event_queue, &event, 0, 0); - - // queue is full, so we need to process data - if(status != osOK) { - _this->ready_to_process = true; - }; - } -} - -bool CyfralReaderComp::parse_data( - bool* raw_data, - uint16_t capture_size, - uint8_t* data, - uint8_t count) { - const bool start_nibble[bits_in_nibble] = {1, 1, 1, 0}; - uint32_t start_position = - search_array_in_array(raw_data, capture_size, start_nibble, bits_in_nibble); - uint32_t end_position = 0; - - memset(data, 0, count); - - if(start_position < capture_size) { - start_position = start_position + bits_in_nibble; - end_position = start_position + count * 2 * bits_in_nibble; - - if(end_position >= capture_size) { - error = CyfralReaderCompError::RAW_DATA_SIZE_ERROR; - return false; - } - - bool first_nibble = true; - uint8_t data_position = 0; - uint8_t nibble_value = 0; - - while(data_position < count) { - nibble_value = !raw_data[start_position] << 3 | !raw_data[start_position + 1] << 2 | - !raw_data[start_position + 2] << 1 | !raw_data[start_position + 3]; - - switch(nibble_value) { - case(0x7): - case(0xB): - case(0xD): - case(0xE): - break; - default: - error = CyfralReaderCompError::UNKNOWN_NIBBLE_VALUE; - return false; - break; - } - - if(first_nibble) { - data[data_position] |= nibble_value << 4; - } else { - data[data_position] |= nibble_value; - } - - first_nibble = !first_nibble; - - if(first_nibble) { - data_position++; - } - - start_position = start_position + bits_in_nibble; - } - - error = CyfralReaderCompError::NO_ERROR; - return true; - } - - error = CyfralReaderCompError::NO_START_NIBBLE; - return false; -} - -CyfralReaderComp::CyfralReaderComp(const GpioPin* gpio_pin) { - pin_record = gpio_pin; -} - -CyfralReaderComp::~CyfralReaderComp() { -} - -void CyfralReaderComp::start(void) { - // pulldown lf-rfid pins to prevent interference - // TODO open record - GpioPin rfid_pull_pin = {.port = RFID_PULL_GPIO_Port, .pin = RFID_PULL_Pin}; - hal_gpio_init((GpioPin*)&rfid_pull_pin, GpioModeOutputOpenDrain, GpioPullNo, GpioSpeedLow); - hal_gpio_write((GpioPin*)&rfid_pull_pin, false); - - // TODO open record - GpioPin rfid_out_pin = {.port = RFID_OUT_GPIO_Port, .pin = RFID_OUT_Pin}; - hal_gpio_init((GpioPin*)&rfid_out_pin, GpioModeOutputOpenDrain, GpioPullNo, GpioSpeedLow); - hal_gpio_write((GpioPin*)&rfid_out_pin, false); - - // connect comparator callback - void* comp_ctx = this; - comp_event_queue = osMessageQueueNew(capture_size * 2 + 2, sizeof(CompEvent), NULL); - ready_to_process = false; - - auto cmp_cb = cbc::obtain_connector(this, &CyfralReaderComp::comparator_trigger_callback); - api_interrupt_add(cmp_cb, InterruptTypeComparatorTrigger, comp_ctx); - - // start comaparator - HAL_COMP_Start(&hcomp1); -} - -void CyfralReaderComp::stop(void) { - // stop comaparator - HAL_COMP_Stop(&hcomp1); - - // disconnect comparator callback - auto cmp_cb = cbc::obtain_connector(this, &CyfralReaderComp::comparator_trigger_callback); - api_interrupt_remove(cmp_cb, InterruptTypeComparatorTrigger); - osMessageQueueDelete(comp_event_queue); -} - -bool CyfralReaderComp::read(uint8_t* data, uint8_t count) { - bool raw_data[capture_size]; - bool result = false; - error = CyfralReaderCompError::NO_ERROR; - - if(ready_to_process == false) { - error = CyfralReaderCompError::NOT_ENOUGH_DATA; - } else { - memset(raw_data, 0, sizeof(bool) * capture_size); - if(capture_data(raw_data, capture_size)) { - if(parse_data(raw_data, capture_size, data, count)) { - result = true; - } - } - - ready_to_process = false; - } - - return result; -} \ No newline at end of file diff --git a/lib/drivers/bq27220.c b/lib/drivers/bq27220.c index bcdf4535..a0401af7 100644 --- a/lib/drivers/bq27220.c +++ b/lib/drivers/bq27220.c @@ -44,7 +44,7 @@ bool bq27220_set_parameter_u16(FuriHalI2cBusHandle* handle, uint16_t address, ui delay_us(10000); - uint8_t checksum = bq27220_get_checksum(&buffer[1], 4); + uint8_t checksum = bq27220_get_checksum(buffer, 4); buffer[0] = checksum; buffer[1] = 6; ret = furi_hal_i2c_write_mem( diff --git a/lib/onewire/blanks_writer.cpp b/lib/onewire/blanks_writer.cpp deleted file mode 100644 index dc01cb34..00000000 --- a/lib/onewire/blanks_writer.cpp +++ /dev/null @@ -1,320 +0,0 @@ -#include "blanks_writer.h" - -class RW1990_1 { -public: - constexpr static const uint8_t CMD_WRITE_RECORD_FLAG = 0xD1; - constexpr static const uint8_t CMD_READ_RECORD_FLAG = 0xB5; - constexpr static const uint8_t CMD_WRITE_ROM = 0xD5; -}; - -class RW1990_2 { -public: - constexpr static const uint8_t CMD_WRITE_RECORD_FLAG = 0x1D; - constexpr static const uint8_t CMD_READ_RECORD_FLAG = 0x1E; - constexpr static const uint8_t CMD_WRITE_ROM = 0xD5; -}; - -class TM2004 { -public: - constexpr static const uint8_t CMD_READ_STATUS = 0xAA; - constexpr static const uint8_t CMD_READ_MEMORY = 0xF0; - constexpr static const uint8_t CMD_WRITE_ROM = 0x3C; - constexpr static const uint8_t CMD_FINALIZATION = 0x35; - - constexpr static const uint8_t ANSWER_READ_MEMORY = 0xF5; -}; - -class TM01 { -public: - constexpr static const uint8_t CMD_WRITE_RECORD_FLAG = 0xC1; - constexpr static const uint8_t CMD_WRITE_ROM = 0xC5; - constexpr static const uint8_t CMD_SWITCH_TO_CYFRAL = 0xCA; - constexpr static const uint8_t CMD_SWITCH_TO_METAKOM = 0xCB; -}; - -class DS1990 { -public: - constexpr static const uint8_t CMD_READ_ROM = 0x33; -}; - -#include -#include -#include -#include - -void BlanksWriter::onewire_release(void) { - hal_gpio_write(gpio, true); -} - -void BlanksWriter::onewire_write_one_bit(bool value, uint32_t delay = 10000) { - onewire->write_bit(value); - delay_us(delay); - onewire_release(); -} - -BlanksWriter::BlanksWriter(const GpioPin* one_wire_gpio) { - gpio = one_wire_gpio; - onewire = new OneWireMaster(gpio); -} - -BlanksWriter::~BlanksWriter() { - free(onewire); -} - -WriterResult BlanksWriter::write(KeyType type, const uint8_t* key, uint8_t key_length) { - uint8_t write_result = -1; - WriterResult result = WR_ERROR; - - bool same_key = false; - - osKernelLock(); - bool presence = onewire->reset(); - osKernelUnlock(); - - if(presence) { - switch(type) { - case KeyType::KEY_DS1990: - same_key = compare_key_ds1990(key, key_length); - - if(!same_key) { - // currently we can write: - // RW1990, TM08v2, TM08vi-2 by write_1990_1() - // RW2004, RW2004 with EEPROM by write_TM2004(); - - if(write_result != 1) { - write_result = write_1990_1(key, key_length); - } - if(write_result != 1) { - write_result = write_1990_2(key, key_length); - } - if(write_result != 1) { - write_result = write_TM2004(key, key_length); - } - - if(write_result == 1) { - result = WR_OK; - } else if(write_result == 0) { - result = WR_ERROR; - } - } else { - write_result = 0; - result = WR_SAME_KEY; - } - break; - - default: - break; - } - } - - return result; -} - -bool BlanksWriter::write_TM2004(const uint8_t* key, uint8_t key_length) { - uint8_t answer; - bool result = true; - - osKernelLock(); - __disable_irq(); - - // write rom, addr is 0x0000 - onewire->reset(); - onewire->write(TM2004::CMD_WRITE_ROM); - onewire->write(0x00); - onewire->write(0x00); - - // write key - for(uint8_t i = 0; i < key_length; i++) { - // write key byte - onewire->write(key[i]); - answer = onewire->read(); - // TODO: check answer CRC - - // pulse indicating that data is correct - delay_us(600); - onewire_write_one_bit(1, 50000); - - // read writed key byte - answer = onewire->read(); - - // check that writed and readed are same - if(key[i] != answer) { - result = false; - break; - } - } - - onewire->reset(); - - __enable_irq(); - osKernelUnlock(); - - return result; -} - -bool BlanksWriter::write_1990_1(const uint8_t* key, uint8_t key_length) { - bool result = true; - - osKernelLock(); - __disable_irq(); - - // unlock - onewire->reset(); - onewire->write(RW1990_1::CMD_WRITE_RECORD_FLAG); - delay_us(10); - onewire_write_one_bit(0, 5000); - - // write key - onewire->reset(); - onewire->write(RW1990_1::CMD_WRITE_ROM); - for(uint8_t i = 0; i < key_length; i++) { - // inverted key for RW1990.1 - write_byte_ds1990(~key[i]); - delay_us(30000); - } - - // lock - onewire->write(RW1990_1::CMD_WRITE_RECORD_FLAG); - onewire_write_one_bit(1); - - __enable_irq(); - osKernelUnlock(); - - if(!compare_key_ds1990(key, key_length)) { - result = false; - } - - return result; -} - -bool BlanksWriter::write_1990_2(const uint8_t* key, uint8_t key_length) { - bool result = true; - - osKernelLock(); - __disable_irq(); - - // unlock - onewire->reset(); - onewire->write(RW1990_2::CMD_WRITE_RECORD_FLAG); - delay_us(10); - onewire_write_one_bit(1, 5000); - - // write key - onewire->reset(); - onewire->write(RW1990_2::CMD_WRITE_ROM); - for(uint8_t i = 0; i < key_length; i++) { - write_byte_ds1990(key[i]); - delay_us(30000); - } - - // lock - onewire->write(RW1990_2::CMD_WRITE_RECORD_FLAG); - onewire_write_one_bit(0); - - __enable_irq(); - osKernelUnlock(); - - if(!compare_key_ds1990(key, key_length)) { - result = false; - } - - return result; -} - -// TODO: untested -bool BlanksWriter::write_TM01(KeyType type, const uint8_t* key, uint8_t key_length) { - bool result = true; - - osKernelLock(); - __disable_irq(); - - // unlock - onewire->reset(); - onewire->write(TM01::CMD_WRITE_RECORD_FLAG); - onewire_write_one_bit(1, 10000); - - // write key - onewire->reset(); - onewire->write(TM01::CMD_WRITE_ROM); - - // TODO: key types - //if(type == KEY_METAKOM || type == KEY_CYFRAL) { - //} else { - for(uint8_t i = 0; i < key_length; i++) { - write_byte_ds1990(key[i]); - delay_us(10000); - } - //} - - // lock - onewire->write(TM01::CMD_WRITE_RECORD_FLAG); - onewire_write_one_bit(0, 10000); - - __enable_irq(); - osKernelUnlock(); - - if(!compare_key_ds1990(key, key_length)) { - result = false; - } - - osKernelLock(); - __disable_irq(); - - if(type == KEY_METAKOM || type == KEY_CYFRAL) { - onewire->reset(); - if(type == KEY_CYFRAL) - onewire->write(TM01::CMD_SWITCH_TO_CYFRAL); - else - onewire->write(TM01::CMD_SWITCH_TO_METAKOM); - onewire_write_one_bit(1); - } - - __enable_irq(); - osKernelUnlock(); - - return result; -} - -void BlanksWriter::write_byte_ds1990(uint8_t data) { - for(uint8_t n_bit = 0; n_bit < 8; n_bit++) { - onewire->write_bit(data & 1); - onewire_release(); - delay_us(5000); - data = data >> 1; - } -} - -bool BlanksWriter::compare_key_ds1990(const uint8_t* key, uint8_t key_length) { - uint8_t buff[key_length]; - bool result = false; - - osKernelLock(); - bool presence = onewire->reset(); - osKernelUnlock(); - - if(presence) { - osKernelLock(); - __disable_irq(); - onewire->write(DS1990::CMD_READ_ROM); - onewire->read_bytes(buff, key_length); - __enable_irq(); - osKernelUnlock(); - - result = true; - for(uint8_t i = 0; i < 8; i++) { - if(key[i] != buff[i]) { - result = false; - break; - } - } - } - return result; -} - -void BlanksWriter::start() { - onewire->start(); -} - -void BlanksWriter::stop() { - onewire->stop(); -} \ No newline at end of file diff --git a/lib/onewire/blanks_writer.h b/lib/onewire/blanks_writer.h deleted file mode 100644 index 8b8f84cd..00000000 --- a/lib/onewire/blanks_writer.h +++ /dev/null @@ -1,40 +0,0 @@ -#pragma once -#include "one_wire_master.h" -#include "maxim_crc.h" - -typedef enum { - KEY_DS1990, /**< DS1990 */ - KEY_CYFRAL, /**< CYFRAL*/ - KEY_METAKOM, /**< METAKOM */ -} KeyType; - -typedef enum { - WR_OK, - WR_SAME_KEY, - WR_ERROR, -} WriterResult; - -class BlanksWriter { -private: - const GpioPin* gpio; - OneWireMaster* onewire; - - void onewire_release(void); - void onewire_write_one_bit(bool value, uint32_t delay); - - bool write_TM2004(const uint8_t* key, uint8_t key_length); - bool write_1990_1(const uint8_t* key, uint8_t key_length); - bool write_1990_2(const uint8_t* key, uint8_t key_length); - bool write_TM01(KeyType type, const uint8_t* key, uint8_t key_length); - - void write_byte_ds1990(uint8_t data); - bool compare_key_ds1990(const uint8_t* key, uint8_t key_length); - -public: - BlanksWriter(const GpioPin* one_wire_gpio); - ~BlanksWriter(); - - WriterResult write(KeyType type, const uint8_t* key, uint8_t key_length); - void start(); - void stop(); -}; diff --git a/lib/onewire/one_wire_slave.cpp b/lib/onewire/one_wire_slave.cpp index ac8abc62..c0f50caa 100644 --- a/lib/onewire/one_wire_slave.cpp +++ b/lib/onewire/one_wire_slave.cpp @@ -258,7 +258,7 @@ bool OneWireSlave::bus_start(void) { if(device == nullptr) { result = false; } else { - __disable_irq(); + FURI_CRITICAL_ENTER(); pin_init_opendrain_in_isr_ctx(); error = OneWireSlaveError::NO_ERROR; @@ -274,7 +274,7 @@ bool OneWireSlave::bus_start(void) { } pin_init_interrupt_in_isr_ctx(); - __enable_irq(); + FURI_CRITICAL_EXIT(); } return result; @@ -305,4 +305,4 @@ void OneWireSlave::exti_callback(void* _ctx) { //FALL event pulse_start = DWT->CYCCNT; } -} \ No newline at end of file +}