From 544b6fea8a076cd218093bbb9f262147f8367874 Mon Sep 17 00:00:00 2001 From: gid9798 <30450294+gid9798@users.noreply.github.com> Date: Mon, 22 May 2023 11:42:27 +0300 Subject: [PATCH 01/28] clock port --- applications/services/desktop/desktop.c | 58 +++++++++++++++++++++++ applications/services/desktop/desktop_i.h | 1 + 2 files changed, 59 insertions(+) diff --git a/applications/services/desktop/desktop.c b/applications/services/desktop/desktop.c index 77999dfcc..6d9db3b5d 100644 --- a/applications/services/desktop/desktop.c +++ b/applications/services/desktop/desktop.c @@ -48,6 +48,57 @@ static void desktop_dummy_mode_icon_draw_callback(Canvas* canvas, void* context) canvas_draw_icon(canvas, 0, 0, &I_GameMode_11x8); } +static void desktop_clock_draw_callback(Canvas* canvas, void* context) { + //UNUSED(context); + furi_assert(context); + furi_assert(canvas); + + Desktop* desktop = context; + // canvas_draw_icon(canvas, 0, 0, &I_GameMode_11x8); + + const char* s[4]; + + s[0] = "4"; + s[1] = "4"; + s[2] = "4"; + s[3] = "1"; + + canvas_set_font(canvas, FontPrimary); + + uint8_t new_w = ((strcmp(s[0], "1") == 0) ? 3 : 5) + //c1 + ((strcmp(s[1], "1") == 0) ? 3 : 5) + //c2 + ((strcmp(s[2], "1") == 0) ? 3 : 5) + //c3 + ((strcmp(s[3], "1") == 0) ? 3 : 5) + //c4 + 2 + 4; // ":" + 4 separators + + view_port_set_width(desktop->clock_viewport, new_w); + uint8_t x = new_w; + + uint8_t y = 8; + uint8_t offset_r; + + canvas_draw_str_aligned(canvas, x, y, AlignRight, AlignBottom, s[0]); + offset_r = (strcmp(s[0], "1") == 0) ? 3 : 5; + + canvas_draw_str_aligned(canvas, x -= (offset_r + 1), y, AlignRight, AlignBottom, s[1]); + offset_r = (strcmp(s[1], "1") == 0) ? 3 : 5; + + canvas_draw_str_aligned(canvas, x -= (offset_r + 1), y - 1, AlignRight, AlignBottom, ":"); + offset_r = 2; + + canvas_draw_str_aligned(canvas, x -= (offset_r + 1), y, AlignRight, AlignBottom, s[2]); + offset_r = (strcmp(s[2], "1") == 0) ? 3 : 5; + + canvas_draw_str_aligned(canvas, x -= (offset_r + 1), y, AlignRight, AlignBottom, s[3]); + offset_r = (strcmp(s[3], "1") == 0) ? 3 : 5; + + x -= (offset_r + 1); + + // canvas_set_font(canvas, FontSecondary); + + // canvas_draw_str_aligned(canvas, 14, y - 1, AlignRight, AlignBottom, ":"); +} + static void desktop_stealth_mode_icon_draw_callback(Canvas* canvas, void* context) { UNUSED(context); furi_assert(canvas); @@ -279,6 +330,13 @@ Desktop* desktop_alloc() { view_port_enabled_set(desktop->dummy_mode_icon_viewport, false); gui_add_view_port(desktop->gui, desktop->dummy_mode_icon_viewport, GuiLayerStatusBarLeft); + // Clock + desktop->clock_viewport = view_port_alloc(); + view_port_set_width(desktop->clock_viewport, 26); + view_port_draw_callback_set(desktop->clock_viewport, desktop_clock_draw_callback, desktop); + view_port_enabled_set(desktop->clock_viewport, true); + gui_add_view_port(desktop->gui, desktop->clock_viewport, GuiLayerStatusBarRight); + // Stealth mode icon desktop->stealth_mode_icon_viewport = view_port_alloc(); view_port_set_width(desktop->stealth_mode_icon_viewport, icon_get_width(&I_Muted_8x8)); diff --git a/applications/services/desktop/desktop_i.h b/applications/services/desktop/desktop_i.h index ede6bbcc3..1d9df7c85 100644 --- a/applications/services/desktop/desktop_i.h +++ b/applications/services/desktop/desktop_i.h @@ -59,6 +59,7 @@ struct Desktop { ViewPort* lock_icon_viewport; ViewPort* dummy_mode_icon_viewport; + ViewPort* clock_viewport; ViewPort* stealth_mode_icon_viewport; AnimationManager* animation_manager; From e40620fd108d63b03e07e3e0a1e4900727b0ed63 Mon Sep 17 00:00:00 2001 From: gid9798 <30450294+gid9798@users.noreply.github.com> Date: Mon, 22 May 2023 22:45:16 +0300 Subject: [PATCH 02/28] clock --- applications/services/desktop/desktop.c | 72 +++++++++++++++++------ applications/services/desktop/desktop_i.h | 4 ++ 2 files changed, 58 insertions(+), 18 deletions(-) diff --git a/applications/services/desktop/desktop.c b/applications/services/desktop/desktop.c index 6d9db3b5d..050f6bcbd 100644 --- a/applications/services/desktop/desktop.c +++ b/applications/services/desktop/desktop.c @@ -48,6 +48,16 @@ static void desktop_dummy_mode_icon_draw_callback(Canvas* canvas, void* context) canvas_draw_icon(canvas, 0, 0, &I_GameMode_11x8); } +static uint8_t desktop_clock_get_num_w(uint8_t num) { + if(num == 1) { + return 3; + } else { + return 5; + } +} + +static const char* digit[10] = {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9"}; + static void desktop_clock_draw_callback(Canvas* canvas, void* context) { //UNUSED(context); furi_assert(context); @@ -56,19 +66,19 @@ static void desktop_clock_draw_callback(Canvas* canvas, void* context) { Desktop* desktop = context; // canvas_draw_icon(canvas, 0, 0, &I_GameMode_11x8); - const char* s[4]; - - s[0] = "4"; - s[1] = "4"; - s[2] = "4"; - s[3] = "1"; + uint8_t d[4] = { + desktop->minute % 10, + desktop->minute / 10, + desktop->hour % 10, + desktop->hour / 10, + }; canvas_set_font(canvas, FontPrimary); - uint8_t new_w = ((strcmp(s[0], "1") == 0) ? 3 : 5) + //c1 - ((strcmp(s[1], "1") == 0) ? 3 : 5) + //c2 - ((strcmp(s[2], "1") == 0) ? 3 : 5) + //c3 - ((strcmp(s[3], "1") == 0) ? 3 : 5) + //c4 + uint8_t new_w = desktop_clock_get_num_w(d[0]) + //c1 + desktop_clock_get_num_w(d[1]) + //c2 + desktop_clock_get_num_w(d[2]) + //c3 + desktop_clock_get_num_w(d[3]) + //c4 2 + 4; // ":" + 4 separators view_port_set_width(desktop->clock_viewport, new_w); @@ -77,20 +87,20 @@ static void desktop_clock_draw_callback(Canvas* canvas, void* context) { uint8_t y = 8; uint8_t offset_r; - canvas_draw_str_aligned(canvas, x, y, AlignRight, AlignBottom, s[0]); - offset_r = (strcmp(s[0], "1") == 0) ? 3 : 5; + canvas_draw_str_aligned(canvas, x, y, AlignRight, AlignBottom, digit[d[0]]); + offset_r = desktop_clock_get_num_w(d[0]); - canvas_draw_str_aligned(canvas, x -= (offset_r + 1), y, AlignRight, AlignBottom, s[1]); - offset_r = (strcmp(s[1], "1") == 0) ? 3 : 5; + canvas_draw_str_aligned(canvas, x -= (offset_r + 1), y, AlignRight, AlignBottom, digit[d[1]]); + offset_r = desktop_clock_get_num_w(d[1]); canvas_draw_str_aligned(canvas, x -= (offset_r + 1), y - 1, AlignRight, AlignBottom, ":"); offset_r = 2; - canvas_draw_str_aligned(canvas, x -= (offset_r + 1), y, AlignRight, AlignBottom, s[2]); - offset_r = (strcmp(s[2], "1") == 0) ? 3 : 5; + canvas_draw_str_aligned(canvas, x -= (offset_r + 1), y, AlignRight, AlignBottom, digit[d[2]]); + offset_r = desktop_clock_get_num_w(d[2]); - canvas_draw_str_aligned(canvas, x -= (offset_r + 1), y, AlignRight, AlignBottom, s[3]); - offset_r = (strcmp(s[3], "1") == 0) ? 3 : 5; + canvas_draw_str_aligned(canvas, x -= (offset_r + 1), y, AlignRight, AlignBottom, digit[d[3]]); + offset_r = desktop_clock_get_num_w(d[3]); x -= (offset_r + 1); @@ -184,6 +194,20 @@ static void desktop_auto_lock_inhibit(Desktop* desktop) { } } +static void desktop_update_clock_timer_callback(void* context) { + furi_assert(context); + Desktop* desktop = context; + + FuriHalRtcDateTime curr_dt; + furi_hal_rtc_get_datetime(&curr_dt); + + desktop->hour = curr_dt.hour; + desktop->minute = curr_dt.minute; + view_port_update(desktop->clock_viewport); + + // view_dispatcher_send_custom_event(desktop->view_dispatcher, DesktopGlobalAutoLock); +} + void desktop_lock(Desktop* desktop) { furi_hal_rtc_set_flag(FuriHalRtcFlagLock); @@ -366,6 +390,17 @@ Desktop* desktop_alloc() { desktop->auto_lock_timer = furi_timer_alloc(desktop_auto_lock_timer_callback, FuriTimerTypeOnce, desktop); + desktop->update_clock_timer = + furi_timer_alloc(desktop_update_clock_timer_callback, FuriTimerTypePeriodic, desktop); + + FuriHalRtcDateTime curr_dt; + furi_hal_rtc_get_datetime(&curr_dt); + + desktop->hour = curr_dt.hour; + desktop->minute = curr_dt.minute; + + furi_timer_start(desktop->update_clock_timer, furi_ms_to_ticks(1000)); + furi_record_create(RECORD_DESKTOP, desktop); return desktop; @@ -419,6 +454,7 @@ void desktop_free(Desktop* desktop) { furi_record_close("menu"); furi_timer_free(desktop->auto_lock_timer); + furi_timer_free(desktop->update_clock_timer); free(desktop); } diff --git a/applications/services/desktop/desktop_i.h b/applications/services/desktop/desktop_i.h index 1d9df7c85..0fac0f34c 100644 --- a/applications/services/desktop/desktop_i.h +++ b/applications/services/desktop/desktop_i.h @@ -71,6 +71,10 @@ struct Desktop { FuriPubSub* input_events_pubsub; FuriPubSubSubscription* input_events_subscription; FuriTimer* auto_lock_timer; + FuriTimer* update_clock_timer; + + uint8_t hour; + uint8_t minute; bool in_transition; }; From a821a2fcc0eaa72a96f2a48c0424287e7f688e06 Mon Sep 17 00:00:00 2001 From: hedger Date: Tue, 23 May 2023 14:51:21 +0400 Subject: [PATCH 03/28] [FL-3328] Removed user-specific data from tar artifacts (#2691) --- scripts/sconsdist.py | 2 ++ scripts/update.py | 3 +++ 2 files changed, 5 insertions(+) diff --git a/scripts/sconsdist.py b/scripts/sconsdist.py index 461781136..23f9526a0 100644 --- a/scripts/sconsdist.py +++ b/scripts/sconsdist.py @@ -275,6 +275,8 @@ class Main(App): # Strip uid and gid in case of overflow def tar_filter(tarinfo): tarinfo.uid = tarinfo.gid = 0 + tarinfo.mtime = 0 + tarinfo.uname = tarinfo.gname = "furippa" return tarinfo tar.add(bundle_dir, arcname=bundle_dir_name, filter=tar_filter) diff --git a/scripts/update.py b/scripts/update.py index 0f3ee6ea8..9f0d95d94 100755 --- a/scripts/update.py +++ b/scripts/update.py @@ -211,6 +211,9 @@ class Main(App): f"Cannot package resource: name '{tarinfo.name}' too long" ) raise ValueError("Resource name too long") + tarinfo.gid = tarinfo.uid = 0 + tarinfo.mtime = 0 + tarinfo.uname = tarinfo.gname = "furippa" return tarinfo def package_resources(self, srcdir: str, dst_name: str): From c82ed71b6f77a66e939879e7596cf8c3563bae5a Mon Sep 17 00:00:00 2001 From: gid9798 <30450294+gid9798@users.noreply.github.com> Date: Tue, 23 May 2023 16:41:57 +0300 Subject: [PATCH 04/28] cleanup --- applications/services/desktop/desktop.c | 25 ++++++++++--------------- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/applications/services/desktop/desktop.c b/applications/services/desktop/desktop.c index 050f6bcbd..31e53f3f2 100644 --- a/applications/services/desktop/desktop.c +++ b/applications/services/desktop/desktop.c @@ -51,6 +51,8 @@ static void desktop_dummy_mode_icon_draw_callback(Canvas* canvas, void* context) static uint8_t desktop_clock_get_num_w(uint8_t num) { if(num == 1) { return 3; + } else if(num == 4) { + return 6; } else { return 5; } @@ -59,12 +61,10 @@ static uint8_t desktop_clock_get_num_w(uint8_t num) { static const char* digit[10] = {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9"}; static void desktop_clock_draw_callback(Canvas* canvas, void* context) { - //UNUSED(context); furi_assert(context); furi_assert(canvas); Desktop* desktop = context; - // canvas_draw_icon(canvas, 0, 0, &I_GameMode_11x8); uint8_t d[4] = { desktop->minute % 10, @@ -81,7 +81,8 @@ static void desktop_clock_draw_callback(Canvas* canvas, void* context) { desktop_clock_get_num_w(d[3]) + //c4 2 + 4; // ":" + 4 separators - view_port_set_width(desktop->clock_viewport, new_w); + view_port_set_width(desktop->clock_viewport, new_w - 1); + uint8_t x = new_w; uint8_t y = 8; @@ -100,13 +101,6 @@ static void desktop_clock_draw_callback(Canvas* canvas, void* context) { offset_r = desktop_clock_get_num_w(d[2]); canvas_draw_str_aligned(canvas, x -= (offset_r + 1), y, AlignRight, AlignBottom, digit[d[3]]); - offset_r = desktop_clock_get_num_w(d[3]); - - x -= (offset_r + 1); - - // canvas_set_font(canvas, FontSecondary); - - // canvas_draw_str_aligned(canvas, 14, y - 1, AlignRight, AlignBottom, ":"); } static void desktop_stealth_mode_icon_draw_callback(Canvas* canvas, void* context) { @@ -200,10 +194,11 @@ static void desktop_update_clock_timer_callback(void* context) { FuriHalRtcDateTime curr_dt; furi_hal_rtc_get_datetime(&curr_dt); - - desktop->hour = curr_dt.hour; - desktop->minute = curr_dt.minute; - view_port_update(desktop->clock_viewport); + if(desktop->minute != curr_dt.minute) { + desktop->hour = curr_dt.hour; + desktop->minute = curr_dt.minute; + view_port_update(desktop->clock_viewport); + } // view_dispatcher_send_custom_event(desktop->view_dispatcher, DesktopGlobalAutoLock); } @@ -356,7 +351,7 @@ Desktop* desktop_alloc() { // Clock desktop->clock_viewport = view_port_alloc(); - view_port_set_width(desktop->clock_viewport, 26); + view_port_set_width(desktop->clock_viewport, 25); view_port_draw_callback_set(desktop->clock_viewport, desktop_clock_draw_callback, desktop); view_port_enabled_set(desktop->clock_viewport, true); gui_add_view_port(desktop->gui, desktop->clock_viewport, GuiLayerStatusBarRight); From 711f0fef405fefc51d08fdafd942423a6aba9bcc Mon Sep 17 00:00:00 2001 From: Sergey Gavrilov Date: Tue, 23 May 2023 07:59:32 -0700 Subject: [PATCH 05/28] [FL-3327] Storage: common_rename is now POSIX compliant (#2693) * Storage: common_rename is now POSIX compliant * storage: check for success on storage_common_remove in file rename --------- Co-authored-by: hedger --- applications/services/storage/storage.h | 2 +- applications/services/storage/storage_external_api.c | 11 ++++++++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/applications/services/storage/storage.h b/applications/services/storage/storage.h index a1267575f..dccf29592 100644 --- a/applications/services/storage/storage.h +++ b/applications/services/storage/storage.h @@ -226,7 +226,7 @@ FS_Error storage_common_stat(Storage* storage, const char* path, FileInfo* filei */ FS_Error storage_common_remove(Storage* storage, const char* path); -/** Renames file/directory, file/directory must not be open +/** Renames file/directory, file/directory must not be open. Will overwrite existing file. * @param app pointer to the api * @param old_path old path * @param new_path new path diff --git a/applications/services/storage/storage_external_api.c b/applications/services/storage/storage_external_api.c index bf474bc9d..549397c87 100644 --- a/applications/services/storage/storage_external_api.c +++ b/applications/services/storage/storage_external_api.c @@ -422,7 +422,16 @@ FS_Error storage_common_remove(Storage* storage, const char* path) { } FS_Error storage_common_rename(Storage* storage, const char* old_path, const char* new_path) { - FS_Error error = storage_common_copy(storage, old_path, new_path); + FS_Error error; + + if(storage_file_exists(storage, new_path)) { + error = storage_common_remove(storage, new_path); + if(error != FSE_OK) { + return error; + } + } + + error = storage_common_copy(storage, old_path, new_path); if(error == FSE_OK) { if(!storage_simply_remove_recursive(storage, old_path)) { error = FSE_INTERNAL; From 3217f286f03da119398586daf94c0723d28b872a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=81=82=E3=81=8F?= Date: Wed, 24 May 2023 00:17:12 +0900 Subject: [PATCH 06/28] Services: remove deallocator for persistent services (#2692) Co-authored-by: hedger --- applications/services/desktop/desktop.c | 55 +------------------ applications/services/dolphin/dolphin.c | 11 +--- applications/services/dolphin/dolphin_i.h | 2 - .../services/power/power_service/power.c | 26 +-------- 4 files changed, 4 insertions(+), 90 deletions(-) diff --git a/applications/services/desktop/desktop.c b/applications/services/desktop/desktop.c index 77999dfcc..36589aed4 100644 --- a/applications/services/desktop/desktop.c +++ b/applications/services/desktop/desktop.c @@ -313,58 +313,6 @@ Desktop* desktop_alloc() { return desktop; } -void desktop_free(Desktop* desktop) { - furi_assert(desktop); - furi_check(furi_record_destroy(RECORD_DESKTOP)); - - furi_pubsub_unsubscribe( - loader_get_pubsub(desktop->loader), desktop->app_start_stop_subscription); - - if(desktop->input_events_subscription) { - furi_pubsub_unsubscribe(desktop->input_events_pubsub, desktop->input_events_subscription); - desktop->input_events_subscription = NULL; - } - - desktop->loader = NULL; - desktop->input_events_pubsub = NULL; - furi_record_close(RECORD_LOADER); - furi_record_close(RECORD_NOTIFICATION); - furi_record_close(RECORD_INPUT_EVENTS); - - 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, 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); - 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_view_locked_free(desktop->locked_view); - desktop_debug_free(desktop->debug_view); - popup_free(desktop->hw_mismatch_popup); - desktop_view_pin_timeout_free(desktop->pin_timeout_view); - - furi_record_close(RECORD_GUI); - desktop->gui = NULL; - - furi_thread_free(desktop->scene_thread); - - furi_record_close("menu"); - - furi_timer_free(desktop->auto_lock_timer); - - free(desktop); -} - static bool desktop_check_file_flag(const char* flag_path) { Storage* storage = furi_record_open(RECORD_STORAGE); bool exists = storage_common_stat(storage, flag_path, NULL) == FSE_OK; @@ -427,7 +375,8 @@ int32_t desktop_srv(void* p) { } view_dispatcher_run(desktop->view_dispatcher); - desktop_free(desktop); + + furi_crash("That was unexpected"); return 0; } diff --git a/applications/services/dolphin/dolphin.c b/applications/services/dolphin/dolphin.c index dd8b7105f..93a9b3095 100644 --- a/applications/services/dolphin/dolphin.c +++ b/applications/services/dolphin/dolphin.c @@ -89,15 +89,6 @@ Dolphin* dolphin_alloc() { return dolphin; } -void dolphin_free(Dolphin* dolphin) { - furi_assert(dolphin); - - dolphin_state_free(dolphin->state); - furi_message_queue_free(dolphin->event_queue); - - free(dolphin); -} - void dolphin_event_send_async(Dolphin* dolphin, DolphinEvent* event) { furi_assert(dolphin); furi_assert(event); @@ -204,7 +195,7 @@ int32_t dolphin_srv(void* p) { } } - dolphin_free(dolphin); + furi_crash("That was unexpected"); return 0; } diff --git a/applications/services/dolphin/dolphin_i.h b/applications/services/dolphin/dolphin_i.h index 4bb0df08e..ceeff1e1a 100644 --- a/applications/services/dolphin/dolphin_i.h +++ b/applications/services/dolphin/dolphin_i.h @@ -37,8 +37,6 @@ struct Dolphin { Dolphin* dolphin_alloc(); -void dolphin_free(Dolphin* dolphin); - void dolphin_event_send_async(Dolphin* dolphin, DolphinEvent* event); void dolphin_event_send_wait(Dolphin* dolphin, DolphinEvent* event); diff --git a/applications/services/power/power_service/power.c b/applications/services/power/power_service/power.c index 56dbd0f87..72dc8f3f1 100644 --- a/applications/services/power/power_service/power.c +++ b/applications/services/power/power_service/power.c @@ -85,30 +85,6 @@ Power* power_alloc() { return power; } -void power_free(Power* power) { - furi_assert(power); - - // Gui - view_dispatcher_remove_view(power->view_dispatcher, PowerViewOff); - power_off_free(power->power_off); - view_dispatcher_remove_view(power->view_dispatcher, PowerViewUnplugUsb); - power_unplug_usb_free(power->power_unplug_usb); - - view_port_free(power->battery_view_port); - - // State - furi_mutex_free(power->api_mtx); - - // FuriPubSub - furi_pubsub_free(power->event_pubsub); - - // Records - furi_record_close(RECORD_NOTIFICATION); - furi_record_close(RECORD_GUI); - - free(power); -} - static void power_check_charging_state(Power* power) { if(furi_hal_power_is_charging()) { if((power->info.charge == 100) || (furi_hal_power_is_charging_done())) { @@ -252,7 +228,7 @@ int32_t power_srv(void* p) { furi_delay_ms(1000); } - power_free(power); + furi_crash("That was unexpected"); return 0; } From 1d5a4240b9dc63508d12746bafd8ab0a68b34a00 Mon Sep 17 00:00:00 2001 From: gid9798 <30450294+gid9798@users.noreply.github.com> Date: Tue, 23 May 2023 22:47:15 +0300 Subject: [PATCH 07/28] Clock: some improvements --- applications/services/desktop/desktop.c | 62 +++++++++++++++---- applications/services/desktop/desktop_i.h | 3 +- .../services/desktop/desktop_settings.h | 1 + applications/services/gui/gui.c | 17 +++++ applications/services/gui/gui.h | 2 + .../scenes/desktop_settings_scene_start.c | 34 +++++++++- firmware/targets/f7/api_symbols.csv | 1 + 7 files changed, 105 insertions(+), 15 deletions(-) diff --git a/applications/services/desktop/desktop.c b/applications/services/desktop/desktop.c index 31e53f3f2..c25af0da5 100644 --- a/applications/services/desktop/desktop.c +++ b/applications/services/desktop/desktop.c @@ -8,6 +8,7 @@ #include #include #include +#include #include "animations/animation_manager.h" #include "desktop/scenes/desktop_scene.h" @@ -48,6 +49,21 @@ static void desktop_dummy_mode_icon_draw_callback(Canvas* canvas, void* context) canvas_draw_icon(canvas, 0, 0, &I_GameMode_11x8); } +static void desktop_togle_clock_view(Desktop* desktop, bool is_enabled) { + furi_assert(desktop); + + // clock type upd after 1 minute + desktop->clock_type = (locale_get_time_format() == LocaleTimeFormat24h); + + if(is_enabled) { // && !furi_timer_is_running(desktop->update_clock_timer)) { + furi_timer_start(desktop->update_clock_timer, furi_ms_to_ticks(1000)); + } else if(!is_enabled) { //&& furi_timer_is_running(desktop->update_clock_timer)) { + furi_timer_stop(desktop->update_clock_timer); + } + + view_port_enabled_set(desktop->clock_viewport, is_enabled); +} + static uint8_t desktop_clock_get_num_w(uint8_t num) { if(num == 1) { return 3; @@ -81,7 +97,8 @@ static void desktop_clock_draw_callback(Canvas* canvas, void* context) { desktop_clock_get_num_w(d[3]) + //c4 2 + 4; // ":" + 4 separators - view_port_set_width(desktop->clock_viewport, new_w - 1); + // further away from the battery charge indicator, if the smallest minute is 1 + view_port_set_width(desktop->clock_viewport, new_w - !(d[0] == 1)); uint8_t x = new_w; @@ -123,6 +140,9 @@ static bool desktop_custom_event_callback(void* context, uint32_t event) { // TODO: Implement a message mechanism for loading settings and (optionally) // locking and unlocking DESKTOP_SETTINGS_LOAD(&desktop->settings); + + desktop_togle_clock_view(desktop, desktop->settings.display_clock); + desktop_auto_lock_arm(desktop); return true; case DesktopGlobalAutoLock: @@ -192,15 +212,25 @@ static void desktop_update_clock_timer_callback(void* context) { furi_assert(context); Desktop* desktop = context; - FuriHalRtcDateTime curr_dt; - furi_hal_rtc_get_datetime(&curr_dt); - if(desktop->minute != curr_dt.minute) { - desktop->hour = curr_dt.hour; - desktop->minute = curr_dt.minute; - view_port_update(desktop->clock_viewport); - } + if(gui_get_count_of_enabled_view_port_in_layer(desktop->gui, GuiLayerStatusBarLeft) < 6) { + FuriHalRtcDateTime curr_dt; + furi_hal_rtc_get_datetime(&curr_dt); - // view_dispatcher_send_custom_event(desktop->view_dispatcher, DesktopGlobalAutoLock); + if(desktop->minute != curr_dt.minute) { + if(desktop->clock_type) { + desktop->hour = curr_dt.hour; + } else { + desktop->hour = (curr_dt.hour > 12) ? curr_dt.hour - 12 : + ((curr_dt.hour == 0) ? 12 : curr_dt.hour); + } + desktop->minute = curr_dt.minute; + view_port_update(desktop->clock_viewport); + } + + view_port_enabled_set(desktop->clock_viewport, true); + } else { + view_port_enabled_set(desktop->clock_viewport, false); + } } void desktop_lock(Desktop* desktop) { @@ -353,7 +383,7 @@ Desktop* desktop_alloc() { desktop->clock_viewport = view_port_alloc(); view_port_set_width(desktop->clock_viewport, 25); view_port_draw_callback_set(desktop->clock_viewport, desktop_clock_draw_callback, desktop); - view_port_enabled_set(desktop->clock_viewport, true); + view_port_enabled_set(desktop->clock_viewport, false); gui_add_view_port(desktop->gui, desktop->clock_viewport, GuiLayerStatusBarRight); // Stealth mode icon @@ -391,11 +421,14 @@ Desktop* desktop_alloc() { FuriHalRtcDateTime curr_dt; furi_hal_rtc_get_datetime(&curr_dt); - desktop->hour = curr_dt.hour; + if(desktop->clock_type) { + desktop->hour = curr_dt.hour; + } else { + desktop->hour = (curr_dt.hour > 12) ? curr_dt.hour - 12 : + ((curr_dt.hour == 0) ? 12 : curr_dt.hour); + } desktop->minute = curr_dt.minute; - furi_timer_start(desktop->update_clock_timer, furi_ms_to_ticks(1000)); - furi_record_create(RECORD_DESKTOP, desktop); return desktop; @@ -489,6 +522,9 @@ int32_t desktop_srv(void* p) { } view_port_enabled_set(desktop->dummy_mode_icon_viewport, desktop->settings.dummy_mode); + + desktop_togle_clock_view(desktop, desktop->settings.display_clock); + desktop_main_set_dummy_mode_state(desktop->main_view, desktop->settings.dummy_mode); animation_manager_set_dummy_mode_state( desktop->animation_manager, desktop->settings.dummy_mode); diff --git a/applications/services/desktop/desktop_i.h b/applications/services/desktop/desktop_i.h index 0fac0f34c..2d033c196 100644 --- a/applications/services/desktop/desktop_i.h +++ b/applications/services/desktop/desktop_i.h @@ -75,8 +75,9 @@ struct Desktop { uint8_t hour; uint8_t minute; + bool clock_type : 1; // true - 24h false - 12h - bool in_transition; + bool in_transition : 1; }; Desktop* desktop_alloc(); diff --git a/applications/services/desktop/desktop_settings.h b/applications/services/desktop/desktop_settings.h index e750c696c..49291b371 100644 --- a/applications/services/desktop/desktop_settings.h +++ b/applications/services/desktop/desktop_settings.h @@ -63,4 +63,5 @@ typedef struct { uint32_t auto_lock_delay_ms; uint8_t displayBatteryPercentage; uint8_t dummy_mode; + uint8_t display_clock; } DesktopSettings; diff --git a/applications/services/gui/gui.c b/applications/services/gui/gui.c index 392011620..87cc962ca 100644 --- a/applications/services/gui/gui.c +++ b/applications/services/gui/gui.c @@ -17,6 +17,23 @@ ViewPort* gui_view_port_find_enabled(ViewPortArray_t array) { return NULL; } +uint8_t gui_get_count_of_enabled_view_port_in_layer(Gui* gui, GuiLayer layer) { + furi_assert(gui); + furi_check(layer < GuiLayerMAX); + uint8_t ret = 0; + + ViewPortArray_it_t it; + ViewPortArray_it_last(it, gui->layers[layer]); + while(!ViewPortArray_end_p(it)) { + ViewPort* view_port = *ViewPortArray_ref(it); + if(view_port_is_enabled(view_port)) { + ret++; + } + ViewPortArray_previous(it); + } + return ret; +} + void gui_update(Gui* gui) { furi_assert(gui); if(!gui->direct_draw) furi_thread_flags_set(gui->thread_id, GUI_THREAD_FLAG_DRAW); diff --git a/applications/services/gui/gui.h b/applications/services/gui/gui.h index 1b5987eda..a59a4ff6a 100644 --- a/applications/services/gui/gui.h +++ b/applications/services/gui/gui.h @@ -132,6 +132,8 @@ Canvas* gui_direct_draw_acquire(Gui* gui); */ void gui_direct_draw_release(Gui* gui); +uint8_t gui_get_count_of_enabled_view_port_in_layer(Gui* gui, GuiLayer layer); + #ifdef __cplusplus } #endif diff --git a/applications/settings/desktop_settings/scenes/desktop_settings_scene_start.c b/applications/settings/desktop_settings/scenes/desktop_settings_scene_start.c index 9d63f6628..b9233a0fa 100644 --- a/applications/settings/desktop_settings/scenes/desktop_settings_scene_start.c +++ b/applications/settings/desktop_settings/scenes/desktop_settings_scene_start.c @@ -11,7 +11,8 @@ #define SCENE_EVENT_SELECT_PIN_SETUP 3 #define SCENE_EVENT_SELECT_AUTO_LOCK_DELAY 4 #define SCENE_EVENT_SELECT_BATTERY_DISPLAY 5 -#define SCENE_EVENT_SELECT_CHANGE_NAME 6 +#define SCENE_EVENT_SELECT_CLOCK_DISPLAY 6 +#define SCENE_EVENT_SELECT_CHANGE_NAME 7 #define AUTO_LOCK_DELAY_COUNT 9 const char* const auto_lock_delay_text[AUTO_LOCK_DELAY_COUNT] = { @@ -29,6 +30,14 @@ const char* const auto_lock_delay_text[AUTO_LOCK_DELAY_COUNT] = { const uint32_t auto_lock_delay_value[AUTO_LOCK_DELAY_COUNT] = {0, 10000, 15000, 30000, 60000, 90000, 120000, 300000, 600000}; +#define CLOCK_ENABLE_COUNT 2 +const char* const clock_enable_text[CLOCK_ENABLE_COUNT] = { + "OFF", + "ON", +}; + +const uint32_t clock_enable_value[CLOCK_ENABLE_COUNT] = {0, 1}; + #define BATTERY_VIEW_COUNT 6 const char* const battery_view_count_text[BATTERY_VIEW_COUNT] = @@ -55,6 +64,14 @@ static void desktop_settings_scene_start_battery_view_changed(VariableItem* item app->settings.displayBatteryPercentage = index; } +static void desktop_settings_scene_start_clock_enable_changed(VariableItem* item) { + DesktopSettingsApp* app = variable_item_get_context(item); + uint8_t index = variable_item_get_current_value_index(item); + + variable_item_set_current_value_text(item, clock_enable_text[index]); + app->settings.display_clock = index; +} + static void desktop_settings_scene_start_auto_lock_delay_changed(VariableItem* item) { DesktopSettingsApp* app = variable_item_get_context(item); uint8_t index = variable_item_get_current_value_index(item); @@ -106,6 +123,18 @@ void desktop_settings_scene_start_on_enter(void* context) { variable_item_set_current_value_index(item, value_index); variable_item_set_current_value_text(item, battery_view_count_text[value_index]); + item = variable_item_list_add( + variable_item_list, + "Clock on desktop", + CLOCK_ENABLE_COUNT, + desktop_settings_scene_start_clock_enable_changed, // + app); + + value_index = + value_index_uint32(app->settings.display_clock, clock_enable_value, CLOCK_ENABLE_COUNT); + variable_item_set_current_value_index(item, value_index); + variable_item_set_current_value_text(item, clock_enable_text[value_index]); + variable_item_list_add(variable_item_list, "Change Flipper Name", 0, NULL, app); view_dispatcher_switch_to_view(app->view_dispatcher, DesktopSettingsAppViewVarItemList); @@ -142,6 +171,9 @@ bool desktop_settings_scene_start_on_event(void* context, SceneManagerEvent even case SCENE_EVENT_SELECT_BATTERY_DISPLAY: consumed = true; break; + case SCENE_EVENT_SELECT_CLOCK_DISPLAY: + consumed = true; + break; case SCENE_EVENT_SELECT_CHANGE_NAME: scene_manager_next_scene(app->scene_manager, DesktopSettingsAppSceneChangeName); consumed = true; diff --git a/firmware/targets/f7/api_symbols.csv b/firmware/targets/f7/api_symbols.csv index cd79ebb23..2f9cf5314 100644 --- a/firmware/targets/f7/api_symbols.csv +++ b/firmware/targets/f7/api_symbols.csv @@ -1658,6 +1658,7 @@ Function,+,gui_add_framebuffer_callback,void,"Gui*, GuiCanvasCommitCallback, voi Function,+,gui_add_view_port,void,"Gui*, ViewPort*, GuiLayer" Function,+,gui_direct_draw_acquire,Canvas*,Gui* Function,+,gui_direct_draw_release,void,Gui* +Function,-,gui_get_count_of_enabled_view_port_in_layer,uint8_t,"Gui*, GuiLayer" Function,+,gui_get_framebuffer_size,size_t,const Gui* Function,+,gui_remove_framebuffer_callback,void,"Gui*, GuiCanvasCommitCallback, void*" Function,+,gui_remove_view_port,void,"Gui*, ViewPort*" From bce12a40486ffc184126d50e16145668000fad9a Mon Sep 17 00:00:00 2001 From: MX <10697207+xMasterX@users.noreply.github.com> Date: Wed, 24 May 2023 07:24:01 +0300 Subject: [PATCH 08/28] Update GPS UART --- .../external/gps_nmea_uart/gps_uart.c | 41 ++++++++++++++++--- 1 file changed, 36 insertions(+), 5 deletions(-) diff --git a/applications/external/gps_nmea_uart/gps_uart.c b/applications/external/gps_nmea_uart/gps_uart.c index ada8f04f9..d44cf22ef 100644 --- a/applications/external/gps_nmea_uart/gps_uart.c +++ b/applications/external/gps_nmea_uart/gps_uart.c @@ -66,6 +66,19 @@ static void gps_uart_parse_nmea(GpsUart* gps_uart, char* line) { } } break; + case MINMEA_SENTENCE_GLL: { + struct minmea_sentence_gll frame; + if(minmea_parse_gll(&frame, line)) { + gps_uart->status.latitude = minmea_tocoord(&frame.latitude); + gps_uart->status.longitude = minmea_tocoord(&frame.longitude); + gps_uart->status.time_hours = frame.time.hours; + gps_uart->status.time_minutes = frame.time.minutes; + gps_uart->status.time_seconds = frame.time.seconds; + + notification_message_block(gps_uart->notifications, &sequence_blink_red_10); + } + } break; + default: break; } @@ -88,35 +101,53 @@ static int32_t gps_uart_worker(void* context) { if(events & WorkerEvtRxDone) { size_t len = 0; do { + // receive serial bytes into rx_buf, starting at rx_offset from the start of the buffer + // the maximum we can receive is RX_BUF_SIZE - 1 - rx_offset len = furi_stream_buffer_receive( gps_uart->rx_stream, gps_uart->rx_buf + rx_offset, RX_BUF_SIZE - 1 - rx_offset, 0); if(len > 0) { + // increase rx_offset by the number of bytes received, and null-terminate rx_buf rx_offset += len; gps_uart->rx_buf[rx_offset] = '\0'; + // look for strings ending in newlines, starting at the start of rx_buf char* line_current = (char*)gps_uart->rx_buf; while(1) { + // skip null characters while(*line_current == '\0' && line_current < (char*)gps_uart->rx_buf + rx_offset - 1) { line_current++; } + // find the next newline char* newline = strchr(line_current, '\n'); - if(newline) { + if(newline) // newline found + { + // put a null terminator in place of the newline, to delimit the line string *newline = '\0'; + + // attempt to parse the line as a NMEA sentence gps_uart_parse_nmea(gps_uart, line_current); + + // move the cursor to the character after the newline line_current = newline + 1; - } else { - if(line_current > (char*)gps_uart->rx_buf) { + } else // no more newlines found + { + if(line_current > + (char*)gps_uart->rx_buf) // at least one line was found + { + // clear parsed lines, and move any leftover bytes to the start of rx_buf rx_offset = 0; - while(*line_current) { + while( + *line_current) // stop when the original rx_offset terminator is reached + { gps_uart->rx_buf[rx_offset++] = *(line_current++); } } - break; + break; // go back to receiving bytes from the serial stream } } } From b12fc114c709c32924a8e5fcd0133f095d975e65 Mon Sep 17 00:00:00 2001 From: MX <10697207+xMasterX@users.noreply.github.com> Date: Wed, 24 May 2023 07:42:03 +0300 Subject: [PATCH 09/28] Update WiFi Marauder plugin Added PR by justcallmekoko https://github.com/justcallmekoko/flipperzero-firmware-with-wifi-marauder-companion --- .../wifi_marauder_companion/scenes/wifi_marauder_scene_start.c | 1 + .../external/wifi_marauder_companion/wifi_marauder_app.h | 2 +- .../external/wifi_marauder_companion/wifi_marauder_app_i.h | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/applications/external/wifi_marauder_companion/scenes/wifi_marauder_scene_start.c b/applications/external/wifi_marauder_companion/scenes/wifi_marauder_scene_start.c index 28a3ed2a9..b2bd39d3e 100644 --- a/applications/external/wifi_marauder_companion/scenes/wifi_marauder_scene_start.c +++ b/applications/external/wifi_marauder_companion/scenes/wifi_marauder_scene_start.c @@ -97,6 +97,7 @@ const WifiMarauderItem items[NUM_MENU_ITEMS] = { NO_ARGS, FOCUS_CONSOLE_END, SHOW_STOPSCAN_TIP}, + {"Signal Monitor", {""}, 1, {"sigmon"}, NO_ARGS, FOCUS_CONSOLE_END, SHOW_STOPSCAN_TIP}, {"Channel", {"get", "set"}, 2, diff --git a/applications/external/wifi_marauder_companion/wifi_marauder_app.h b/applications/external/wifi_marauder_companion/wifi_marauder_app.h index 7e3856059..5457f89d8 100644 --- a/applications/external/wifi_marauder_companion/wifi_marauder_app.h +++ b/applications/external/wifi_marauder_companion/wifi_marauder_app.h @@ -4,7 +4,7 @@ extern "C" { #endif -#define WIFI_MARAUDER_APP_VERSION "v0.3.6" +#define WIFI_MARAUDER_APP_VERSION "v0.3.7" typedef struct WifiMarauderApp WifiMarauderApp; diff --git a/applications/external/wifi_marauder_companion/wifi_marauder_app_i.h b/applications/external/wifi_marauder_companion/wifi_marauder_app_i.h index 45e1e5920..2a16522bb 100644 --- a/applications/external/wifi_marauder_companion/wifi_marauder_app_i.h +++ b/applications/external/wifi_marauder_companion/wifi_marauder_app_i.h @@ -26,7 +26,7 @@ #include #include -#define NUM_MENU_ITEMS (17) +#define NUM_MENU_ITEMS (18) #define WIFI_MARAUDER_TEXT_BOX_STORE_SIZE (4096) #define WIFI_MARAUDER_TEXT_INPUT_STORE_SIZE (512) From 5c234c21069635fb00f8738a6cda0bba683e52c6 Mon Sep 17 00:00:00 2001 From: MX <10697207+xMasterX@users.noreply.github.com> Date: Wed, 24 May 2023 07:48:33 +0300 Subject: [PATCH 10/28] Update changelog --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5dc889d2f..23e815ba9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,7 +7,12 @@ * Misc: Name changer code moved to proper place, load after system startup + extra checks * Plugins: NMEA GPS UART - stability fix * Plugins: Port XFW keyboard with extra symbols to WiFi Marauder instead of using UART Term keyboard (thanks to @Willy-JL) +* Plugins: Update NMEA GPS UART [(by ezod)](https://github.com/ezod/flipperzero-gps) * Plugins: Update WiFi Marauder [(by 0xchocolate)](https://github.com/0xchocolate/flipperzero-firmware-with-wifi-marauder-companion) +* OFW: Services: remove deallocator for persistent services +* OFW: Storage: common_rename is now POSIX compliant +* OFW: Removed user-specific data from tar artifacts +* OFW: fbt: Fix tar uid overflow when packaging * OFW: fbt: Use union for old py (Fix builds if using older python versions) * OFW PR 2682: USB HID report timeout (by nminaylov) From 977c9e706e189333665ceadfdda1bd81baafdda7 Mon Sep 17 00:00:00 2001 From: MX <10697207+xMasterX@users.noreply.github.com> Date: Wed, 24 May 2023 07:50:13 +0300 Subject: [PATCH 11/28] Fix typos --- applications/services/desktop/desktop.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/applications/services/desktop/desktop.c b/applications/services/desktop/desktop.c index 33a99b07e..ebc13ec9d 100644 --- a/applications/services/desktop/desktop.c +++ b/applications/services/desktop/desktop.c @@ -49,7 +49,7 @@ static void desktop_dummy_mode_icon_draw_callback(Canvas* canvas, void* context) canvas_draw_icon(canvas, 0, 0, &I_GameMode_11x8); } -static void desktop_togle_clock_view(Desktop* desktop, bool is_enabled) { +static void desktop_toggle_clock_view(Desktop* desktop, bool is_enabled) { furi_assert(desktop); // clock type upd after 1 minute @@ -141,7 +141,7 @@ static bool desktop_custom_event_callback(void* context, uint32_t event) { // locking and unlocking DESKTOP_SETTINGS_LOAD(&desktop->settings); - desktop_togle_clock_view(desktop, desktop->settings.display_clock); + desktop_toggle_clock_view(desktop, desktop->settings.display_clock); desktop_auto_lock_arm(desktop); return true; @@ -470,7 +470,7 @@ int32_t desktop_srv(void* p) { view_port_enabled_set(desktop->dummy_mode_icon_viewport, desktop->settings.dummy_mode); - desktop_togle_clock_view(desktop, desktop->settings.display_clock); + desktop_toggle_clock_view(desktop, desktop->settings.display_clock); desktop_main_set_dummy_mode_state(desktop->main_view, desktop->settings.dummy_mode); animation_manager_set_dummy_mode_state( From 035bb57c56bdcceaf8f1d78b570d59220d2eb8fe Mon Sep 17 00:00:00 2001 From: MX <10697207+xMasterX@users.noreply.github.com> Date: Wed, 24 May 2023 07:50:45 +0300 Subject: [PATCH 12/28] bump version!!! --- applications/services/desktop/desktop_settings.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/applications/services/desktop/desktop_settings.h b/applications/services/desktop/desktop_settings.h index 49291b371..fb63f26f5 100644 --- a/applications/services/desktop/desktop_settings.h +++ b/applications/services/desktop/desktop_settings.h @@ -8,7 +8,7 @@ #include #include -#define DESKTOP_SETTINGS_VER (9) +#define DESKTOP_SETTINGS_VER (10) #define DESKTOP_SETTINGS_PATH INT_PATH(DESKTOP_SETTINGS_FILE_NAME) #define DESKTOP_SETTINGS_MAGIC (0x17) From d83d898cdc206b920b7b12d1a4937751f296f0ea Mon Sep 17 00:00:00 2001 From: MX <10697207+xMasterX@users.noreply.github.com> Date: Wed, 24 May 2023 08:26:17 +0300 Subject: [PATCH 13/28] Rename --- .../desktop_settings/scenes/desktop_settings_scene_start.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/applications/settings/desktop_settings/scenes/desktop_settings_scene_start.c b/applications/settings/desktop_settings/scenes/desktop_settings_scene_start.c index b9233a0fa..43e86cdc6 100644 --- a/applications/settings/desktop_settings/scenes/desktop_settings_scene_start.c +++ b/applications/settings/desktop_settings/scenes/desktop_settings_scene_start.c @@ -125,7 +125,7 @@ void desktop_settings_scene_start_on_enter(void* context) { item = variable_item_list_add( variable_item_list, - "Clock on desktop", + "Show Clock", CLOCK_ENABLE_COUNT, desktop_settings_scene_start_clock_enable_changed, // app); From 88f0b635774afe76f15bb72a469e22d4449d7e35 Mon Sep 17 00:00:00 2001 From: Sergey Gavrilov Date: Thu, 25 May 2023 06:44:32 -0700 Subject: [PATCH 14/28] Storage, common_rename: check that old path is exists (#2698) * Storage, common_rename: check that old path is exists * Storage, common_rename: return correct status --- .../services/storage/storage_external_api.c | 22 ++++++++++++------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/applications/services/storage/storage_external_api.c b/applications/services/storage/storage_external_api.c index 549397c87..5fcaa5921 100644 --- a/applications/services/storage/storage_external_api.c +++ b/applications/services/storage/storage_external_api.c @@ -424,19 +424,25 @@ FS_Error storage_common_remove(Storage* storage, const char* path) { FS_Error storage_common_rename(Storage* storage, const char* old_path, const char* new_path) { FS_Error error; - if(storage_file_exists(storage, new_path)) { - error = storage_common_remove(storage, new_path); - if(error != FSE_OK) { - return error; + do { + if(!storage_common_exists(storage, old_path)) { + error = FSE_INVALID_NAME; + break; + } + + if(storage_file_exists(storage, new_path)) { + storage_common_remove(storage, new_path); + } + + error = storage_common_copy(storage, old_path, new_path); + if(error != FSE_OK) { + break; } - } - error = storage_common_copy(storage, old_path, new_path); - if(error == FSE_OK) { if(!storage_simply_remove_recursive(storage, old_path)) { error = FSE_INTERNAL; } - } + } while(false); return error; } From 080324f7e0b28283fd4da5b24b1efb41a0c9af0b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=81=82=E3=81=8F?= Date: Thu, 25 May 2023 23:22:31 +0900 Subject: [PATCH 15/28] [FL-3315] Desktop,Rpc: desktop status subscription (#2696) * Desktop,Rpc: desktop status subscription * Desktop,RPC: properly handle unsubscribe Co-authored-by: Sergey Gavrilov --- applications/services/desktop/desktop.c | 13 +++++ applications/services/desktop/desktop.h | 8 +++ applications/services/desktop/desktop_i.h | 2 + applications/services/rpc/rpc_desktop.c | 64 +++++++++++++++++++++++ assets/protobuf | 2 +- 5 files changed, 88 insertions(+), 1 deletion(-) diff --git a/applications/services/desktop/desktop.c b/applications/services/desktop/desktop.c index 36589aed4..e1da64940 100644 --- a/applications/services/desktop/desktop.c +++ b/applications/services/desktop/desktop.c @@ -147,6 +147,9 @@ void desktop_lock(Desktop* desktop) { desktop->scene_manager, DesktopSceneLocked, SCENE_LOCKED_FIRST_ENTER); scene_manager_next_scene(desktop->scene_manager, DesktopSceneLocked); notification_message(desktop->notification, &sequence_display_backlight_off_delay_1000); + + DesktopStatus status = {.locked = true}; + furi_pubsub_publish(desktop->status_pubsub, &status); } void desktop_unlock(Desktop* desktop) { @@ -165,6 +168,9 @@ void desktop_unlock(Desktop* desktop) { cli_session_open(cli, &cli_vcp); furi_record_close(RECORD_CLI); } + + DesktopStatus status = {.locked = false}; + furi_pubsub_publish(desktop->status_pubsub, &status); } void desktop_set_dummy_mode_state(Desktop* desktop, bool enabled) { @@ -308,6 +314,8 @@ Desktop* desktop_alloc() { desktop->auto_lock_timer = furi_timer_alloc(desktop_auto_lock_timer_callback, FuriTimerTypeOnce, desktop); + desktop->status_pubsub = furi_pubsub_alloc(); + furi_record_create(RECORD_DESKTOP, desktop); return desktop; @@ -331,6 +339,11 @@ void desktop_api_unlock(Desktop* instance) { view_dispatcher_send_custom_event(instance->view_dispatcher, DesktopLockedEventUnlocked); } +FuriPubSub* desktop_api_get_status_pubsub(Desktop* instance) { + furi_assert(instance); + return instance->status_pubsub; +} + int32_t desktop_srv(void* p) { UNUSED(p); diff --git a/applications/services/desktop/desktop.h b/applications/services/desktop/desktop.h index 5b12647b8..4eab24fcc 100644 --- a/applications/services/desktop/desktop.h +++ b/applications/services/desktop/desktop.h @@ -1,5 +1,7 @@ #pragma once +#include + typedef struct Desktop Desktop; #define RECORD_DESKTOP "desktop" @@ -7,3 +9,9 @@ typedef struct Desktop Desktop; bool desktop_api_is_locked(Desktop* instance); void desktop_api_unlock(Desktop* instance); + +typedef struct { + bool locked; +} DesktopStatus; + +FuriPubSub* desktop_api_get_status_pubsub(Desktop* instance); diff --git a/applications/services/desktop/desktop_i.h b/applications/services/desktop/desktop_i.h index ede6bbcc3..0b3d56801 100644 --- a/applications/services/desktop/desktop_i.h +++ b/applications/services/desktop/desktop_i.h @@ -71,6 +71,8 @@ struct Desktop { FuriPubSubSubscription* input_events_subscription; FuriTimer* auto_lock_timer; + FuriPubSub* status_pubsub; + bool in_transition; }; diff --git a/applications/services/rpc/rpc_desktop.c b/applications/services/rpc/rpc_desktop.c index dbf9796ec..0d72b43d5 100644 --- a/applications/services/rpc/rpc_desktop.c +++ b/applications/services/rpc/rpc_desktop.c @@ -8,6 +8,8 @@ typedef struct { RpcSession* session; Desktop* desktop; + FuriPubSub* status_pubsub; + FuriPubSubSubscription* status_subscription; } RpcDesktop; static void rpc_desktop_on_is_locked_request(const PB_Main* request, void* context) { @@ -39,11 +41,63 @@ static void rpc_desktop_on_unlock_request(const PB_Main* request, void* context) rpc_send_and_release_empty(session, request->command_id, PB_CommandStatus_OK); } +static void rpc_desktop_on_desktop_pubsub(const void* message, void* context) { + RpcDesktop* rpc_desktop = context; + RpcSession* session = rpc_desktop->session; + const DesktopStatus* status = message; + + PB_Main rpc_message = { + .command_id = 0, + .command_status = PB_CommandStatus_OK, + .has_next = false, + .which_content = PB_Main_desktop_status_tag, + .content.desktop_status.locked = status->locked, + }; + rpc_send_and_release(session, &rpc_message); +} + +static void rpc_desktop_on_status_subscribe_request(const PB_Main* request, void* context) { + furi_assert(request); + furi_assert(context); + furi_assert(request->which_content == PB_Main_desktop_status_subscribe_request_tag); + + FURI_LOG_D(TAG, "StatusSubscribeRequest"); + RpcDesktop* rpc_desktop = context; + RpcSession* session = rpc_desktop->session; + + if(rpc_desktop->status_subscription) { + rpc_send_and_release_empty(session, request->command_id, PB_CommandStatus_ERROR); + } else { + rpc_desktop->status_subscription = furi_pubsub_subscribe( + rpc_desktop->status_pubsub, rpc_desktop_on_desktop_pubsub, rpc_desktop); + rpc_send_and_release_empty(session, request->command_id, PB_CommandStatus_OK); + } +} + +static void rpc_desktop_on_status_unsubscribe_request(const PB_Main* request, void* context) { + furi_assert(request); + furi_assert(context); + furi_assert(request->which_content == PB_Main_desktop_status_unsubscribe_request_tag); + + FURI_LOG_D(TAG, "StatusUnsubscribeRequest"); + RpcDesktop* rpc_desktop = context; + RpcSession* session = rpc_desktop->session; + + if(rpc_desktop->status_subscription) { + furi_pubsub_unsubscribe(rpc_desktop->status_pubsub, rpc_desktop->status_subscription); + rpc_desktop->status_subscription = NULL; + rpc_send_and_release_empty(session, request->command_id, PB_CommandStatus_OK); + } else { + rpc_send_and_release_empty(session, request->command_id, PB_CommandStatus_ERROR); + } +} + void* rpc_desktop_alloc(RpcSession* session) { furi_assert(session); RpcDesktop* rpc_desktop = malloc(sizeof(RpcDesktop)); rpc_desktop->desktop = furi_record_open(RECORD_DESKTOP); + rpc_desktop->status_pubsub = desktop_api_get_status_pubsub(rpc_desktop->desktop); rpc_desktop->session = session; RpcHandler rpc_handler = { @@ -58,6 +112,12 @@ void* rpc_desktop_alloc(RpcSession* session) { rpc_handler.message_handler = rpc_desktop_on_unlock_request; rpc_add_handler(session, PB_Main_desktop_unlock_request_tag, &rpc_handler); + rpc_handler.message_handler = rpc_desktop_on_status_subscribe_request; + rpc_add_handler(session, PB_Main_desktop_status_subscribe_request_tag, &rpc_handler); + + rpc_handler.message_handler = rpc_desktop_on_status_unsubscribe_request; + rpc_add_handler(session, PB_Main_desktop_status_unsubscribe_request_tag, &rpc_handler); + return rpc_desktop; } @@ -65,6 +125,10 @@ void rpc_desktop_free(void* context) { furi_assert(context); RpcDesktop* rpc_desktop = context; + if(rpc_desktop->status_subscription) { + furi_pubsub_unsubscribe(rpc_desktop->status_pubsub, rpc_desktop->status_subscription); + } + furi_assert(rpc_desktop->desktop); furi_record_close(RECORD_DESKTOP); diff --git a/assets/protobuf b/assets/protobuf index a13c5ddd0..f71c4b7f7 160000 --- a/assets/protobuf +++ b/assets/protobuf @@ -1 +1 @@ -Subproject commit a13c5ddd0397511bd4c6de4afdd1031a5b6f5bca +Subproject commit f71c4b7f750f2539a1fed08925d8da3abdc80ff9 From faa14cfa1c7f48481d0165776ff320993853fa68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A9lix=20Legrelle?= Date: Thu, 25 May 2023 16:30:07 +0200 Subject: [PATCH 16/28] :sparkles: Add fr-FR-mac key layout (#2666) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: あく --- .../resources/badusb/assets/layouts/fr-FR-mac.kl | Bin 0 -> 256 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 assets/resources/badusb/assets/layouts/fr-FR-mac.kl diff --git a/assets/resources/badusb/assets/layouts/fr-FR-mac.kl b/assets/resources/badusb/assets/layouts/fr-FR-mac.kl new file mode 100644 index 0000000000000000000000000000000000000000..0906936547cd3c8accd9632bac82cb4193a24c25 GIT binary patch literal 256 zcmaLLM{dGU007a^2*c-7jOjgKAVDOih=6?{?tg}?*<^Na;Jp*y9N*W!`r*KahgW`G zvn8kCYGsczPfNdC`{Bl|xjXkB{IulBi;9;$9}G>b+c4NP+OloOuBmr3`wpx*a_q#Z zGgmHLIyaAHEaHW;H-;qCX%J` Date: Thu, 25 May 2023 17:38:56 +0300 Subject: [PATCH 17/28] [FL-3322] Infrared: respect carrier frequency and duty cycle settings (#2677) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Make infrared_worker respect carrier frequency and duty cycle * Update comments Co-authored-by: あく --- applications/main/infrared/infrared.c | 3 +- firmware/targets/f18/api_symbols.csv | 2 +- firmware/targets/f7/api_symbols.csv | 4 +-- .../targets/f7/furi_hal/furi_hal_infrared.c | 14 +++----- lib/infrared/worker/infrared_worker.c | 32 ++++++++++++------- lib/infrared/worker/infrared_worker.h | 10 ++++-- 6 files changed, 38 insertions(+), 27 deletions(-) diff --git a/applications/main/infrared/infrared.c b/applications/main/infrared/infrared.c index 4f450496d..685dd57ec 100644 --- a/applications/main/infrared/infrared.c +++ b/applications/main/infrared/infrared.c @@ -312,7 +312,8 @@ void infrared_tx_start_signal(Infrared* infrared, InfraredSignal* signal) { if(infrared_signal_is_raw(signal)) { InfraredRawSignal* raw = infrared_signal_get_raw_signal(signal); - infrared_worker_set_raw_signal(infrared->worker, raw->timings, raw->timings_size); + infrared_worker_set_raw_signal( + infrared->worker, raw->timings, raw->timings_size, raw->frequency, raw->duty_cycle); } else { InfraredMessage* message = infrared_signal_get_message(signal); infrared_worker_set_decoded_signal(infrared->worker, message); diff --git a/firmware/targets/f18/api_symbols.csv b/firmware/targets/f18/api_symbols.csv index ee1ae1154..b7abdfc05 100644 --- a/firmware/targets/f18/api_symbols.csv +++ b/firmware/targets/f18/api_symbols.csv @@ -1,5 +1,5 @@ entry,status,name,type,params -Version,+,26.3,, +Version,+,27.0,, Header,+,applications/services/bt/bt_service/bt.h,, Header,+,applications/services/cli/cli.h,, Header,+,applications/services/cli/cli_vcp.h,, diff --git a/firmware/targets/f7/api_symbols.csv b/firmware/targets/f7/api_symbols.csv index e2bedffb7..15c19091e 100644 --- a/firmware/targets/f7/api_symbols.csv +++ b/firmware/targets/f7/api_symbols.csv @@ -1,5 +1,5 @@ entry,status,name,type,params -Version,+,26.3,, +Version,+,27.0,, Header,+,applications/services/bt/bt_service/bt.h,, Header,+,applications/services/cli/cli.h,, Header,+,applications/services/cli/cli_vcp.h,, @@ -1715,7 +1715,7 @@ Function,+,infrared_worker_rx_set_received_signal_callback,void,"InfraredWorker* Function,+,infrared_worker_rx_start,void,InfraredWorker* Function,+,infrared_worker_rx_stop,void,InfraredWorker* Function,+,infrared_worker_set_decoded_signal,void,"InfraredWorker*, const InfraredMessage*" -Function,+,infrared_worker_set_raw_signal,void,"InfraredWorker*, const uint32_t*, size_t" +Function,+,infrared_worker_set_raw_signal,void,"InfraredWorker*, const uint32_t*, size_t, uint32_t, float" Function,+,infrared_worker_signal_is_decoded,_Bool,const InfraredWorkerSignal* Function,+,infrared_worker_tx_get_signal_steady_callback,InfraredWorkerGetSignalResponse,"void*, InfraredWorker*" Function,+,infrared_worker_tx_set_get_signal_callback,void,"InfraredWorker*, InfraredWorkerGetSignalCallback, void*" diff --git a/firmware/targets/f7/furi_hal/furi_hal_infrared.c b/firmware/targets/f7/furi_hal/furi_hal_infrared.c index 2598e5fa3..7b4f17084 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_infrared.c +++ b/firmware/targets/f7/furi_hal/furi_hal_infrared.c @@ -1,7 +1,6 @@ #include #include #include "stm32wbxx_ll_dma.h" -#include "sys/_stdint.h" #include #include @@ -13,11 +12,10 @@ #include #include -#define INFRARED_TX_DEBUG 0 +// #define INFRARED_TX_DEBUG -#if INFRARED_TX_DEBUG == 1 -#define gpio_infrared_tx gpio_infrared_tx_debug -const GpioPin gpio_infrared_tx_debug = {.port = GPIOA, .pin = GpioModeAnalog}; +#if defined INFRARED_TX_DEBUG +#define gpio_infrared_tx gpio_ext_pa7 #endif #define INFRARED_TIM_TX_DMA_BUFFER_SIZE 200 @@ -330,8 +328,6 @@ static void furi_hal_infrared_tx_dma_isr() { } static void furi_hal_infrared_configure_tim_pwm_tx(uint32_t freq, float duty_cycle) { - /* LL_DBGMCU_APB2_GRP1_FreezePeriph(LL_DBGMCU_APB2_GRP1_TIM1_STOP); */ - LL_TIM_DisableCounter(TIM1); LL_TIM_SetRepetitionCounter(TIM1, 0); LL_TIM_SetCounter(TIM1, 0); @@ -340,7 +336,7 @@ static void furi_hal_infrared_configure_tim_pwm_tx(uint32_t freq, float duty_cyc LL_TIM_EnableARRPreload(TIM1); LL_TIM_SetAutoReload( TIM1, __LL_TIM_CALC_ARR(SystemCoreClock, LL_TIM_GetPrescaler(TIM1), freq)); -#if INFRARED_TX_DEBUG == 1 +#if defined INFRARED_TX_DEBUG LL_TIM_OC_SetCompareCH1(TIM1, ((LL_TIM_GetAutoReload(TIM1) + 1) * (1 - duty_cycle))); LL_TIM_OC_EnablePreload(TIM1, LL_TIM_CHANNEL_CH1); /* LL_TIM_OCMODE_PWM2 set by DMA */ @@ -370,7 +366,7 @@ static void furi_hal_infrared_configure_tim_pwm_tx(uint32_t freq, float duty_cyc static void furi_hal_infrared_configure_tim_cmgr2_dma_tx(void) { LL_DMA_InitTypeDef dma_config = {0}; -#if INFRARED_TX_DEBUG == 1 +#if defined INFRARED_TX_DEBUG dma_config.PeriphOrM2MSrcAddress = (uint32_t) & (TIM1->CCMR1); #else dma_config.PeriphOrM2MSrcAddress = (uint32_t) & (TIM1->CCMR2); diff --git a/lib/infrared/worker/infrared_worker.c b/lib/infrared/worker/infrared_worker.c index 5add1413e..46effd420 100644 --- a/lib/infrared/worker/infrared_worker.c +++ b/lib/infrared/worker/infrared_worker.c @@ -40,8 +40,12 @@ struct InfraredWorkerSignal { size_t timings_cnt; union { InfraredMessage message; - /* +1 is for pause we add at the beginning */ - uint32_t timings[MAX_TIMINGS_AMOUNT + 1]; + struct { + /* +1 is for pause we add at the beginning */ + uint32_t timings[MAX_TIMINGS_AMOUNT + 1]; + uint32_t frequency; + float duty_cycle; + } raw; }; }; @@ -146,7 +150,7 @@ static void } if(instance->signal.timings_cnt < MAX_TIMINGS_AMOUNT) { - instance->signal.timings[instance->signal.timings_cnt] = duration; + instance->signal.raw.timings[instance->signal.timings_cnt] = duration; ++instance->signal.timings_cnt; } else { uint32_t flags_set = furi_thread_flags_set( @@ -300,7 +304,7 @@ void infrared_worker_get_raw_signal( furi_assert(timings); furi_assert(timings_cnt); - *timings = signal->timings; + *timings = signal->raw.timings; *timings_cnt = signal->timings_cnt; } @@ -390,8 +394,8 @@ static bool infrared_get_new_signal(InfraredWorker* instance) { infrared_get_protocol_duty_cycle(instance->signal.message.protocol); } else { furi_assert(instance->signal.timings_cnt > 1); - new_tx_frequency = INFRARED_COMMON_CARRIER_FREQUENCY; - new_tx_duty_cycle = INFRARED_COMMON_DUTY_CYCLE; + new_tx_frequency = instance->signal.raw.frequency; + new_tx_duty_cycle = instance->signal.raw.duty_cycle; } instance->tx.tx_raw_cnt = 0; @@ -426,7 +430,7 @@ static bool infrared_worker_tx_fill_buffer(InfraredWorker* instance) { if(instance->signal.decoded) { status = infrared_encode(instance->infrared_encoder, &timing.duration, &timing.level); } else { - timing.duration = instance->signal.timings[instance->tx.tx_raw_cnt]; + timing.duration = instance->signal.raw.timings[instance->tx.tx_raw_cnt]; /* raw always starts from Mark, but we fill it with space delay at start */ timing.level = (instance->tx.tx_raw_cnt % 2); ++instance->tx.tx_raw_cnt; @@ -597,15 +601,21 @@ void infrared_worker_set_decoded_signal(InfraredWorker* instance, const Infrared void infrared_worker_set_raw_signal( InfraredWorker* instance, const uint32_t* timings, - size_t timings_cnt) { + size_t timings_cnt, + uint32_t frequency, + float duty_cycle) { furi_assert(instance); furi_assert(timings); furi_assert(timings_cnt > 0); - size_t max_copy_num = COUNT_OF(instance->signal.timings) - 1; + furi_assert((frequency <= INFRARED_MAX_FREQUENCY) && (frequency >= INFRARED_MIN_FREQUENCY)); + furi_assert((duty_cycle < 1.0f) && (duty_cycle > 0.0f)); + size_t max_copy_num = COUNT_OF(instance->signal.raw.timings) - 1; furi_check(timings_cnt <= max_copy_num); - instance->signal.timings[0] = INFRARED_RAW_TX_TIMING_DELAY_US; - memcpy(&instance->signal.timings[1], timings, timings_cnt * sizeof(uint32_t)); + instance->signal.raw.frequency = frequency; + instance->signal.raw.duty_cycle = duty_cycle; + instance->signal.raw.timings[0] = INFRARED_RAW_TX_TIMING_DELAY_US; + memcpy(&instance->signal.raw.timings[1], timings, timings_cnt * sizeof(uint32_t)); instance->signal.decoded = false; instance->signal.timings_cnt = timings_cnt + 1; } diff --git a/lib/infrared/worker/infrared_worker.h b/lib/infrared/worker/infrared_worker.h index 1a8cd9a76..e0e861983 100644 --- a/lib/infrared/worker/infrared_worker.h +++ b/lib/infrared/worker/infrared_worker.h @@ -130,9 +130,9 @@ void infrared_worker_tx_set_signal_sent_callback( /** Callback to pass to infrared_worker_tx_set_get_signal_callback() if signal * is steady and will not be changed between infrared_worker start and stop. * Before starting transmission, desired steady signal must be set with - * infrared_worker_make_decoded_signal() or infrared_worker_make_raw_signal(). + * infrared_worker_set_decoded_signal() or infrared_worker_set_raw_signal(). * - * This function should not be implicitly called. + * This function should not be called directly. * * @param[in] context - context * @param[out] instance - InfraredWorker instance @@ -172,11 +172,15 @@ void infrared_worker_set_decoded_signal(InfraredWorker* instance, const Infrared * @param[out] instance - InfraredWorker instance * @param[in] timings - array of raw timings * @param[in] timings_cnt - size of array of raw timings + * @param[in] frequency - carrier frequency in Hertz + * @param[in] duty_cycle - carrier duty cycle (0.0 - 1.0) */ void infrared_worker_set_raw_signal( InfraredWorker* instance, const uint32_t* timings, - size_t timings_cnt); + size_t timings_cnt, + uint32_t frequency, + float duty_cycle); #ifdef __cplusplus } From 12dc5b186f49dde06b1d11effacd08ba3f55612b Mon Sep 17 00:00:00 2001 From: Nikolay Minaylov Date: Thu, 25 May 2023 17:50:13 +0300 Subject: [PATCH 18/28] USB HID report timeout (#2682) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: あく --- firmware/targets/f7/furi_hal/furi_hal_usb_hid.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/firmware/targets/f7/furi_hal/furi_hal_usb_hid.c b/firmware/targets/f7/furi_hal/furi_hal_usb_hid.c index d27613410..334aa0102 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_usb_hid.c +++ b/firmware/targets/f7/furi_hal/furi_hal_usb_hid.c @@ -436,7 +436,11 @@ static bool hid_send_report(uint8_t report_id) { if((hid_semaphore == NULL) || (hid_connected == false)) return false; if((boot_protocol == true) && (report_id != ReportIdKeyboard)) return false; - furi_check(furi_semaphore_acquire(hid_semaphore, FuriWaitForever) == FuriStatusOk); + FuriStatus status = furi_semaphore_acquire(hid_semaphore, HID_INTERVAL * 2); + if(status == FuriStatusErrorTimeout) { + return false; + } + furi_check(status == FuriStatusOk); if(hid_connected == false) { return false; } From a472ff7a0fbff7c42682e1aa9e2afdfaa3732e4d Mon Sep 17 00:00:00 2001 From: minchogaydarov <134236905+minchogaydarov@users.noreply.github.com> Date: Thu, 25 May 2023 16:00:13 +0100 Subject: [PATCH 19/28] Add Airwell Prime DCI Series and match file style (#2686) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: あく --- assets/resources/infrared/assets/ac.ir | 41 ++++++++++++++++++++++++-- 1 file changed, 39 insertions(+), 2 deletions(-) diff --git a/assets/resources/infrared/assets/ac.ir b/assets/resources/infrared/assets/ac.ir index 96a2a0f38..cfa62f6a2 100644 --- a/assets/resources/infrared/assets/ac.ir +++ b/assets/resources/infrared/assets/ac.ir @@ -297,8 +297,8 @@ type: raw frequency: 38000 duty_cycle: 0.330000 data: 2320 634 837 637 838 637 838 640 835 642 832 1378 836 645 826 670 809 667 808 1406 806 672 803 674 802 1412 802 1412 800 676 801 675 802 1412 802 674 802 1413 801 1412 801 1413 802 1412 802 50937 2285 671 801 1411 802 51225 2280 696 775 1412 801 51212 2283 671 775 1412 802 -# Model: Daikin FTXM20M. # +# Model: Daikin FTXM20M. name: Off type: raw frequency: 38000 @@ -334,8 +334,8 @@ type: raw frequency: 38000 duty_cycle: 0.330000 data: 503 365 500 364 501 366 499 365 500 364 502 25049 3535 1660 504 1228 503 390 474 391 473 393 471 1261 469 397 468 397 469 397 469 397 469 1264 468 398 468 1264 468 1264 468 398 468 1265 467 1265 467 1265 467 1265 467 1265 467 399 467 399 467 1266 466 399 467 400 466 400 466 400 466 423 443 423 443 401 465 423 442 424 442 424 442 1290 442 424 442 1290 442 424 442 424 441 424 442 1290 442 1291 441 425 441 424 442 425 441 425 441 1291 441 425 440 425 441 425 441 425 441 425 441 425 440 425 441 425 441 425 441 425 441 426 440 1292 440 1292 440 1292 440 426 440 426 440 1292 440 1293 439 1293 439 35480 3503 1696 467 1264 468 398 468 398 467 398 468 1265 467 398 467 399 467 399 466 399 467 1265 467 399 467 1266 466 1267 465 400 466 1290 442 1290 442 1290 442 1290 442 1290 442 424 442 424 442 1290 442 424 441 424 442 424 442 424 442 424 442 424 441 424 442 425 441 424 442 425 441 425 441 1291 441 425 441 425 441 425 441 425 440 1292 440 425 441 425 440 426 440 426 440 426 440 426 440 426 440 426 440 426 440 426 439 427 439 426 440 426 440 1293 439 427 439 427 439 427 438 427 439 428 438 1294 438 428 437 428 438 1295 437 1319 413 453 413 35480 3503 1696 468 1265 467 398 468 398 468 398 468 1265 467 398 468 399 466 399 467 399 467 1266 466 399 466 1267 465 1290 442 401 465 1290 442 1290 442 1290 442 1290 442 1290 442 424 442 424 441 1291 441 424 442 424 442 424 442 424 442 424 441 424 442 425 441 424 442 424 441 425 441 425 441 425 440 425 441 425 441 425 441 425 441 425 441 425 441 1292 440 426 440 426 440 1292 440 426 440 426 440 1293 439 426 440 426 440 1293 439 1293 439 1293 439 427 439 1294 438 427 438 427 439 427 438 428 438 428 438 428 438 428 438 453 413 429 437 453 413 1319 413 1320 412 1320 412 1320 412 454 412 1320 412 454 412 1321 411 1321 411 1321 411 1321 411 1321 411 455 410 455 411 455 411 455 410 456 410 456 410 456 410 481 384 481 385 482 383 482 383 483 358 507 359 1374 358 1374 358 508 358 508 358 508 358 509 357 509 357 535 331 535 331 535 330 535 330 536 330 1403 329 1403 329 563 302 564 301 564 302 564 301 565 301 591 274 619 246 593 273 620 245 620 245 621 245 673 189 -# Model: Mitsubishi SRK63HE. # +# Model: Mitsubishi SRK63HE. name: Off type: raw frequency: 38000 @@ -371,3 +371,40 @@ type: raw frequency: 38000 duty_cycle: 0.330000 data: 3234 1525 463 333 462 1127 465 332 462 333 436 1153 518 307 488 1073 518 307 488 308 434 1131 459 1155 435 1156 434 362 433 1159 432 363 432 1159 432 1159 432 1159 433 363 432 363 432 363 433 363 432 1159 433 1159 432 363 432 1159 433 1159 432 363 432 363 432 1159 432 363 433 363 432 1159 432 363 432 363 432 1159 432 1159 432 363 432 1160 432 1160 431 1160 432 1160 431 1160 431 1160 431 364 431 1160 431 1160 431 1160 431 364 431 364 431 364 431 364 431 1160 431 364 431 364 431 364 431 1160 432 1160 431 1160 432 364 431 1160 431 1160 431 1161 431 1161 430 364 431 364 431 364 431 1160 432 364 431 364 431 364 432 364 431 1161 431 1161 431 364 431 364 431 1161 430 364 432 364 431 1161 430 365 431 365 431 1161 430 1161 430 365 431 1161 430 1161 430 365 430 +# +# Model: Airwell Prime DCI Series +name: Off +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 3078 3852 2004 888 1054 1824 1045 894 1051 865 2062 861 1078 860 1080 865 1046 894 1015 1883 1945 899 1013 901 1013 901 1012 902 1012 900 1042 927 986 902 1012 927 987 901 1012 902 1012 927 986 903 1011 902 1012 931 1011 931 1011 904 1010 933 1009 928 985 928 986 1885 1944 927 3017 3943 1943 927 985 1915 984 929 985 929 1943 957 984 929 985 928 985 929 985 1886 1943 899 984 930 983 930 984 957 986 929 985 929 985 930 984 930 983 930 984 930 1013 930 984 959 983 931 982 931 983 930 984 930 984 930 984 960 1011 931 984 1918 1939 929 3016 3917 1940 930 982 1916 954 959 954 959 1913 957 955 933 981 959 928 1015 954 1916 1913 959 953 960 957 986 927 1015 928 1015 953 961 927 987 927 986 927 987 927 986 927 1016 927 987 927 1016 926 1044 928 987 926 1015 928 988 926 987 926 988 926 1946 1883 987 3974 +# +name: Dh +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 3060 3870 1026 888 1984 886 1026 888 1053 888 1026 887 1055 858 1055 858 1052 860 1024 891 1044 1854 1016 897 1975 1853 1975 925 1015 898 1015 898 1016 897 1016 898 1015 898 1016 898 1015 898 1015 898 1015 899 1015 899 1014 899 1014 899 1016 927 1014 900 1014 899 1014 1856 1974 926 3048 3883 1015 898 1975 897 1014 899 1015 899 1014 900 1014 899 1015 900 1013 900 1014 899 1014 1857 1014 900 1973 1855 1973 899 1012 901 1013 902 1011 926 987 927 987 926 987 927 987 955 987 926 988 926 987 927 1015 927 987 927 987 926 988 926 1016 927 1015 1884 1945 925 3020 3911 986 928 1946 925 986 927 986 928 986 928 986 927 987 927 987 928 986 928 986 1884 987 956 1946 1882 1946 925 986 928 986 927 986 928 985 928 986 928 986 928 986 928 985 928 985 929 959 954 984 930 984 987 931 955 959 956 958 955 959 1968 1891 980 3982 +# +name: Cool_hi +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 3054 3879 1977 892 1020 1846 1083 838 1073 840 2031 859 1051 864 1047 864 1077 896 1014 927 986 928 986 928 986 1885 1943 927 985 929 1013 928 986 929 985 928 985 928 985 928 985 929 985 929 985 957 985 928 1015 928 1015 928 985 929 984 929 985 929 985 1886 1943 927 3017 3914 1943 928 984 1886 985 958 984 929 1972 957 984 958 984 929 984 930 984 929 984 930 984 930 983 1887 1942 929 983 930 984 930 984 930 983 959 984 930 984 930 983 930 984 930 984 930 984 930 983 931 983 931 983 959 984 931 983 931 983 1888 1941 930 3014 3943 1914 931 981 1915 955 959 955 959 1913 958 955 959 954 959 955 959 955 959 955 988 955 960 953 1917 1941 959 953 960 953 961 953 961 953 961 927 987 927 987 927 987 926 987 927 1017 926 988 926 988 925 988 925 988 926 988 925 1018 925 1972 1857 1014 3946 +# +name: Cool_lo +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 3080 3850 2007 863 1049 1851 1048 888 1054 887 2012 886 1026 887 1025 888 1050 865 1045 1854 2029 871 1041 872 1040 873 1042 899 1043 899 1043 872 1015 898 1016 899 1041 872 1042 872 1015 926 1017 898 1016 927 1016 926 1016 899 1014 898 1015 926 1016 899 1015 898 1015 1856 1973 897 3048 3910 1947 898 1015 1884 1015 925 988 899 2003 953 988 900 1014 954 988 926 987 1857 1972 896 988 899 1014 900 1014 900 1013 927 987 929 1014 929 1013 926 987 927 986 927 987 927 987 927 987 927 986 927 987 927 986 985 958 928 986 927 986 927 1012 1860 1943 927 3018 3914 1943 955 986 1914 986 929 984 928 1944 955 957 930 984 957 985 956 958 1913 1915 956 957 957 956 957 931 1012 957 930 983 958 955 931 982 958 956 960 983 958 956 958 955 958 930 984 930 984 930 984 930 984 930 1013 930 984 930 985 928 1942 1887 983 3977 +# +name: Heat_hi +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 3083 3873 2012 1843 2013 1873 1054 888 2011 887 1025 887 1025 887 1052 890 1048 1852 1017 896 1018 895 1018 896 1976 895 1017 898 1016 898 1015 898 1016 897 1016 897 1016 897 1017 897 1016 897 1017 900 1043 899 1014 897 1016 897 1016 898 1016 898 1015 898 1015 1857 1972 896 3048 3911 1947 1853 1975 1854 1015 898 1973 897 1016 927 1015 926 987 926 1016 1857 1014 926 987 899 1015 901 1970 926 987 927 987 926 988 955 988 1013 958 900 1014 926 987 900 1014 900 1014 900 1013 927 986 927 987 927 1016 955 987 927 987 955 987 1884 1946 928 3045 3912 1974 1883 1974 1883 987 927 1974 926 986 927 987 928 987 956 987 1942 986 956 986 928 986 928 1944 926 986 928 985 929 984 929 985 928 986 956 987 928 986 958 984 929 984 930 984 930 983 929 985 958 984 930 984 957 957 956 957 1887 1971 956 4003 +# +name: Heat_lo +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 3108 3851 2062 1793 2006 1821 1103 839 2031 859 1085 829 1081 833 1079 836 1045 1911 1973 897 1015 898 1016 899 1041 871 1016 899 1014 898 1015 899 1015 899 1014 899 1041 872 1015 899 1041 872 1041 872 1015 899 1015 899 1041 873 1014 899 1041 873 1014 899 1014 1883 1975 900 3045 3886 1997 1856 1945 1857 1012 927 1945 900 1013 901 1012 901 1013 901 1012 1859 1999 901 1012 930 1012 903 1011 903 1010 903 1011 902 1012 960 1011 928 986 932 1010 903 1011 928 1015 928 985 929 985 928 1014 928 985 929 985 929 984 929 985 928 986 1915 1971 928 3017 3915 1942 1885 1943 1885 985 930 1971 929 984 930 983 930 984 930 984 1887 1942 929 983 960 983 931 982 931 983 932 981 958 985 958 956 958 984 959 954 931 983 932 981 959 955 932 982 959 954 960 982 961 983 933 955 988 955 985 929 1943 1915 958 4003 From 77bb997b0b4bc73a53624af3d1b9391856f70c98 Mon Sep 17 00:00:00 2001 From: Yukai Li Date: Thu, 25 May 2023 10:16:41 -0600 Subject: [PATCH 20/28] desktop: Refactor favorites settings and allow app browser in selection (#2687) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * desktop: Refactor favorites settings and allow app browser in selection * desktop: Gate app browser entry add, just in case * Desktop: simplify favorite application selection * Desktop: refactor favorite application opening routine and cleanup code * Desktop: handle exit from external application selection Co-authored-by: hedger Co-authored-by: あく --- .../services/desktop/desktop_settings.h | 2 - .../desktop/scenes/desktop_scene_main.c | 49 ++++------ .../scenes/desktop_settings_scene_favorite.c | 94 +++++++++---------- 3 files changed, 61 insertions(+), 84 deletions(-) diff --git a/applications/services/desktop/desktop_settings.h b/applications/services/desktop/desktop_settings.h index 5d1b6126f..7ab39094d 100644 --- a/applications/services/desktop/desktop_settings.h +++ b/applications/services/desktop/desktop_settings.h @@ -36,8 +36,6 @@ #define MIN_PIN_SIZE 4 #define MAX_APP_LENGTH 128 -#define FAP_LOADER_APP_NAME "Applications" - typedef struct { InputKey data[MAX_PIN_SIZE]; uint8_t length; diff --git a/applications/services/desktop/scenes/desktop_scene_main.c b/applications/services/desktop/scenes/desktop_scene_main.c index 053ac56f1..d19b5560f 100644 --- a/applications/services/desktop/scenes/desktop_scene_main.c +++ b/applications/services/desktop/scenes/desktop_scene_main.c @@ -16,6 +16,8 @@ #define SNAKE_GAME_APP EXT_PATH("/apps/Games/snake_game.fap") #define CLOCK_APP EXT_PATH("/apps/Tools/clock.fap") +#define FAP_LOADER_APP_NAME "Applications" + static void desktop_scene_main_new_idle_animation_callback(void* context) { furi_assert(context); Desktop* desktop = context; @@ -77,6 +79,21 @@ static void desktop_scene_main_open_app_or_profile(Desktop* desktop, const char* } while(false); } +static void desktop_scene_main_start_favorite(Desktop* desktop, FavoriteApp* application) { + LoaderStatus status = LoaderStatusErrorInternal; + if(application->is_external) { + status = loader_start(desktop->loader, FAP_LOADER_APP_NAME, application->name_or_path); + } else if(strlen(application->name_or_path) > 0) { + status = loader_start(desktop->loader, application->name_or_path, NULL); + } else { + status = loader_start(desktop->loader, FAP_LOADER_APP_NAME, NULL); + } + + if(status != LoaderStatusOk) { + FURI_LOG_E(TAG, "loader_start failed: %d", status); + } +} + void desktop_scene_main_callback(DesktopEvent event, void* context) { Desktop* desktop = (Desktop*)context; if(desktop->in_transition) return; @@ -141,40 +158,12 @@ bool desktop_scene_main_on_event(void* context, SceneManagerEvent event) { case DesktopMainEventOpenFavoritePrimary: DESKTOP_SETTINGS_LOAD(&desktop->settings); - if(desktop->settings.favorite_primary.is_external) { - LoaderStatus status = loader_start( - desktop->loader, - FAP_LOADER_APP_NAME, - desktop->settings.favorite_primary.name_or_path); - if(status != LoaderStatusOk) { - FURI_LOG_E(TAG, "loader_start failed: %d", status); - } - } else { - LoaderStatus status = loader_start( - desktop->loader, desktop->settings.favorite_primary.name_or_path, NULL); - if(status != LoaderStatusOk) { - FURI_LOG_E(TAG, "loader_start failed: %d", status); - } - } + desktop_scene_main_start_favorite(desktop, &desktop->settings.favorite_primary); consumed = true; break; case DesktopMainEventOpenFavoriteSecondary: DESKTOP_SETTINGS_LOAD(&desktop->settings); - if(desktop->settings.favorite_secondary.is_external) { - LoaderStatus status = loader_start( - desktop->loader, - FAP_LOADER_APP_NAME, - desktop->settings.favorite_secondary.name_or_path); - if(status != LoaderStatusOk) { - FURI_LOG_E(TAG, "loader_start failed: %d", status); - } - } else { - LoaderStatus status = loader_start( - desktop->loader, desktop->settings.favorite_secondary.name_or_path, NULL); - if(status != LoaderStatusOk) { - FURI_LOG_E(TAG, "loader_start failed: %d", status); - } - } + desktop_scene_main_start_favorite(desktop, &desktop->settings.favorite_secondary); consumed = true; break; case DesktopAnimationEventCheckAnimation: diff --git a/applications/settings/desktop_settings/scenes/desktop_settings_scene_favorite.c b/applications/settings/desktop_settings/scenes/desktop_settings_scene_favorite.c index 94c5ee9f0..4b5c47921 100644 --- a/applications/settings/desktop_settings/scenes/desktop_settings_scene_favorite.c +++ b/applications/settings/desktop_settings/scenes/desktop_settings_scene_favorite.c @@ -5,6 +5,9 @@ #include #include +#define EXTERNAL_APPLICATION_NAME ("[External Application]") +#define EXTERNAL_APPLICATION_INDEX (FLIPPER_APPS_COUNT + 1) + static bool favorite_fap_selector_item_callback( FuriString* file_path, void* context, @@ -44,6 +47,8 @@ void desktop_settings_scene_favorite_on_enter(void* context) { uint32_t primary_favorite = scene_manager_get_scene_state(app->scene_manager, DesktopSettingsAppSceneFavorite); uint32_t pre_select_item = 0; + FavoriteApp* curr_favorite_app = primary_favorite ? &app->settings.favorite_primary : + &app->settings.favorite_secondary; for(size_t i = 0; i < FLIPPER_APPS_COUNT; i++) { submenu_add_item( @@ -53,21 +58,25 @@ void desktop_settings_scene_favorite_on_enter(void* context) { desktop_settings_scene_favorite_submenu_callback, app); - if(primary_favorite) { // Select favorite item in submenu - if((app->settings.favorite_primary.is_external && - !strcmp(FLIPPER_APPS[i].name, FAP_LOADER_APP_NAME)) || - (!strcmp(FLIPPER_APPS[i].name, app->settings.favorite_primary.name_or_path))) { - pre_select_item = i; - } - } else { - if((app->settings.favorite_secondary.is_external && - !strcmp(FLIPPER_APPS[i].name, FAP_LOADER_APP_NAME)) || - (!strcmp(FLIPPER_APPS[i].name, app->settings.favorite_secondary.name_or_path))) { - pre_select_item = i; - } + // Select favorite item in submenu + if(!curr_favorite_app->is_external && + !strcmp(FLIPPER_APPS[i].name, curr_favorite_app->name_or_path)) { + pre_select_item = i; } } +#ifdef APP_FAP_LOADER + submenu_add_item( + submenu, + EXTERNAL_APPLICATION_NAME, + EXTERNAL_APPLICATION_INDEX, + desktop_settings_scene_favorite_submenu_callback, + app); + if(curr_favorite_app->is_external) { + pre_select_item = EXTERNAL_APPLICATION_INDEX; + } +#endif + submenu_set_header( submenu, primary_favorite ? "Primary favorite app:" : "Secondary favorite app:"); submenu_set_selected_item(submenu, pre_select_item); // If set during loop, visual glitch. @@ -82,23 +91,11 @@ bool desktop_settings_scene_favorite_on_event(void* context, SceneManagerEvent e uint32_t primary_favorite = scene_manager_get_scene_state(app->scene_manager, DesktopSettingsAppSceneFavorite); + FavoriteApp* curr_favorite_app = primary_favorite ? &app->settings.favorite_primary : + &app->settings.favorite_secondary; if(event.type == SceneManagerEventTypeCustom) { - if(strcmp(FLIPPER_APPS[event.event].name, FAP_LOADER_APP_NAME) != 0) { - if(primary_favorite) { - app->settings.favorite_primary.is_external = false; - strncpy( - app->settings.favorite_primary.name_or_path, - FLIPPER_APPS[event.event].name, - MAX_APP_LENGTH); - } else { - app->settings.favorite_secondary.is_external = false; - strncpy( - app->settings.favorite_secondary.name_or_path, - FLIPPER_APPS[event.event].name, - MAX_APP_LENGTH); - } - } else { + if(event.event == EXTERNAL_APPLICATION_INDEX) { const DialogsFileBrowserOptions browser_options = { .extension = ".fap", .icon = &I_unknown_10px, @@ -109,36 +106,29 @@ bool desktop_settings_scene_favorite_on_event(void* context, SceneManagerEvent e .base_path = EXT_PATH("apps"), }; - if(primary_favorite) { // Select favorite fap in file browser - if(favorite_fap_selector_file_exists( - app->settings.favorite_primary.name_or_path)) { - furi_string_set_str(temp_path, app->settings.favorite_primary.name_or_path); - } - } else { - if(favorite_fap_selector_file_exists( - app->settings.favorite_secondary.name_or_path)) { - furi_string_set_str(temp_path, app->settings.favorite_secondary.name_or_path); - } + // Select favorite fap in file browser + if(favorite_fap_selector_file_exists(curr_favorite_app->name_or_path)) { + furi_string_set_str(temp_path, curr_favorite_app->name_or_path); } - submenu_reset(app->submenu); if(dialog_file_browser_show(app->dialogs, temp_path, temp_path, &browser_options)) { - if(primary_favorite) { - app->settings.favorite_primary.is_external = true; - strncpy( - app->settings.favorite_primary.name_or_path, - furi_string_get_cstr(temp_path), - MAX_APP_LENGTH); - } else { - app->settings.favorite_secondary.is_external = true; - strncpy( - app->settings.favorite_secondary.name_or_path, - furi_string_get_cstr(temp_path), - MAX_APP_LENGTH); - } + submenu_reset(app->submenu); // Prevent menu from being shown when we exiting scene + curr_favorite_app->is_external = true; + strncpy( + curr_favorite_app->name_or_path, + furi_string_get_cstr(temp_path), + MAX_APP_LENGTH); + consumed = true; } + } else { + curr_favorite_app->is_external = false; + strncpy( + curr_favorite_app->name_or_path, FLIPPER_APPS[event.event].name, MAX_APP_LENGTH); + consumed = true; } - scene_manager_previous_scene(app->scene_manager); + if(consumed) { + scene_manager_previous_scene(app->scene_manager); + }; consumed = true; } From 490447bbd482126063bce3e5378198365b580963 Mon Sep 17 00:00:00 2001 From: Avery <30564701+nullableVoidPtr@users.noreply.github.com> Date: Fri, 26 May 2023 03:01:02 +1000 Subject: [PATCH 21/28] NFC: Add support for Gen4 "ultimate card" in Magic app (#2238) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * NFC: gen4 gtu detect in magic app * NFC: more support for GTU card * NFC: Fix Gen1 in Magic * Allow double UIDs for MFClassic on GTU cards * NFC: Small magic app tweaks * nfc magic: notify card event on wiping * nfc magic: fix power consumption * nfc magic: disable i2c writing and fix wipe loop * NfcMagic: correct formatting in printf * NfcMagic: correct formatting in printf, proper version * nfc_magic: rework card found notification and gen4 wiping Co-authored-by: あく --- .../nfc_magic/lib/magic/classic_gen1.c | 175 ++++++++ .../nfc_magic/lib/magic/classic_gen1.h | 13 + .../external/nfc_magic/lib/magic/common.c | 33 ++ .../external/nfc_magic/lib/magic/common.h | 19 + .../external/nfc_magic/lib/magic/gen4.c | 199 ++++++++++ .../external/nfc_magic/lib/magic/gen4.h | 48 +++ .../external/nfc_magic/lib/magic/magic.c | 52 +-- .../external/nfc_magic/lib/magic/magic.h | 15 - .../external/nfc_magic/lib/magic/types.c | 23 ++ .../external/nfc_magic/lib/magic/types.h | 5 + applications/external/nfc_magic/nfc_magic.c | 22 +- applications/external/nfc_magic/nfc_magic.h | 2 + applications/external/nfc_magic/nfc_magic_i.h | 20 +- .../external/nfc_magic/nfc_magic_worker.c | 372 +++++++++++++++--- .../external/nfc_magic/nfc_magic_worker.h | 4 + .../external/nfc_magic/nfc_magic_worker_i.h | 5 + .../scenes/nfc_magic_scene_actions.c | 50 +++ .../nfc_magic/scenes/nfc_magic_scene_check.c | 4 +- .../nfc_magic/scenes/nfc_magic_scene_config.h | 6 + .../scenes/nfc_magic_scene_file_select.c | 60 ++- .../scenes/nfc_magic_scene_gen4_actions.c | 70 ++++ .../scenes/nfc_magic_scene_key_input.c | 45 +++ .../scenes/nfc_magic_scene_magic_info.c | 14 + .../scenes/nfc_magic_scene_new_key_input.c | 45 +++ .../nfc_magic/scenes/nfc_magic_scene_rekey.c | 95 +++++ .../scenes/nfc_magic_scene_rekey_fail.c | 50 +++ .../nfc_magic/scenes/nfc_magic_scene_start.c | 25 +- .../nfc_magic/scenes/nfc_magic_scene_wipe.c | 11 +- .../nfc_magic/scenes/nfc_magic_scene_write.c | 11 +- .../scenes/nfc_magic_scene_wrong_card.c | 2 +- 30 files changed, 1345 insertions(+), 150 deletions(-) create mode 100644 applications/external/nfc_magic/lib/magic/classic_gen1.c create mode 100644 applications/external/nfc_magic/lib/magic/classic_gen1.h create mode 100644 applications/external/nfc_magic/lib/magic/common.c create mode 100644 applications/external/nfc_magic/lib/magic/common.h create mode 100644 applications/external/nfc_magic/lib/magic/gen4.c create mode 100644 applications/external/nfc_magic/lib/magic/gen4.h delete mode 100644 applications/external/nfc_magic/lib/magic/magic.h create mode 100644 applications/external/nfc_magic/lib/magic/types.c create mode 100644 applications/external/nfc_magic/lib/magic/types.h create mode 100644 applications/external/nfc_magic/scenes/nfc_magic_scene_actions.c create mode 100644 applications/external/nfc_magic/scenes/nfc_magic_scene_gen4_actions.c create mode 100644 applications/external/nfc_magic/scenes/nfc_magic_scene_key_input.c create mode 100644 applications/external/nfc_magic/scenes/nfc_magic_scene_new_key_input.c create mode 100644 applications/external/nfc_magic/scenes/nfc_magic_scene_rekey.c create mode 100644 applications/external/nfc_magic/scenes/nfc_magic_scene_rekey_fail.c diff --git a/applications/external/nfc_magic/lib/magic/classic_gen1.c b/applications/external/nfc_magic/lib/magic/classic_gen1.c new file mode 100644 index 000000000..ebd2b0805 --- /dev/null +++ b/applications/external/nfc_magic/lib/magic/classic_gen1.c @@ -0,0 +1,175 @@ +#include "classic_gen1.h" + +#include + +#define TAG "Magic" + +#define MAGIC_CMD_WUPA (0x40) +#define MAGIC_CMD_WIPE (0x41) +#define MAGIC_CMD_ACCESS (0x43) + +#define MAGIC_MIFARE_READ_CMD (0x30) +#define MAGIC_MIFARE_WRITE_CMD (0xA0) + +#define MAGIC_ACK (0x0A) + +#define MAGIC_BUFFER_SIZE (32) + +bool magic_gen1_wupa() { + bool magic_activated = false; + uint8_t tx_data[MAGIC_BUFFER_SIZE] = {}; + uint8_t rx_data[MAGIC_BUFFER_SIZE] = {}; + uint16_t rx_len = 0; + FuriHalNfcReturn ret = 0; + + do { + // Start communication + tx_data[0] = MAGIC_CMD_WUPA; + ret = furi_hal_nfc_ll_txrx_bits( + tx_data, + 7, + rx_data, + sizeof(rx_data), + &rx_len, + FURI_HAL_NFC_LL_TXRX_FLAGS_CRC_TX_MANUAL | FURI_HAL_NFC_LL_TXRX_FLAGS_AGC_ON | + FURI_HAL_NFC_LL_TXRX_FLAGS_CRC_RX_KEEP, + furi_hal_nfc_ll_ms2fc(20)); + if(ret != FuriHalNfcReturnIncompleteByte) break; + if(rx_len != 4) break; + if(rx_data[0] != MAGIC_ACK) break; + magic_activated = true; + } while(false); + + return magic_activated; +} + +bool magic_gen1_data_access_cmd() { + bool write_cmd_success = false; + uint8_t tx_data[MAGIC_BUFFER_SIZE] = {}; + uint8_t rx_data[MAGIC_BUFFER_SIZE] = {}; + uint16_t rx_len = 0; + FuriHalNfcReturn ret = 0; + + do { + tx_data[0] = MAGIC_CMD_ACCESS; + ret = furi_hal_nfc_ll_txrx_bits( + tx_data, + 8, + rx_data, + sizeof(rx_data), + &rx_len, + FURI_HAL_NFC_LL_TXRX_FLAGS_CRC_TX_MANUAL | FURI_HAL_NFC_LL_TXRX_FLAGS_AGC_ON | + FURI_HAL_NFC_LL_TXRX_FLAGS_CRC_RX_KEEP, + furi_hal_nfc_ll_ms2fc(20)); + if(ret != FuriHalNfcReturnIncompleteByte) break; + if(rx_len != 4) break; + if(rx_data[0] != MAGIC_ACK) break; + + write_cmd_success = true; + } while(false); + + return write_cmd_success; +} + +bool magic_gen1_read_block(uint8_t block_num, MfClassicBlock* data) { + furi_assert(data); + + bool read_success = false; + + uint8_t tx_data[MAGIC_BUFFER_SIZE] = {}; + uint8_t rx_data[MAGIC_BUFFER_SIZE] = {}; + uint16_t rx_len = 0; + FuriHalNfcReturn ret = 0; + + do { + tx_data[0] = MAGIC_MIFARE_READ_CMD; + tx_data[1] = block_num; + ret = furi_hal_nfc_ll_txrx_bits( + tx_data, + 2 * 8, + rx_data, + sizeof(rx_data), + &rx_len, + FURI_HAL_NFC_LL_TXRX_FLAGS_AGC_ON, + furi_hal_nfc_ll_ms2fc(20)); + + if(ret != FuriHalNfcReturnOk) break; + if(rx_len != 16 * 8) break; + memcpy(data->value, rx_data, sizeof(data->value)); + read_success = true; + } while(false); + + return read_success; +} + +bool magic_gen1_write_blk(uint8_t block_num, MfClassicBlock* data) { + furi_assert(data); + + bool write_success = false; + uint8_t tx_data[MAGIC_BUFFER_SIZE] = {}; + uint8_t rx_data[MAGIC_BUFFER_SIZE] = {}; + uint16_t rx_len = 0; + FuriHalNfcReturn ret = 0; + + do { + tx_data[0] = MAGIC_MIFARE_WRITE_CMD; + tx_data[1] = block_num; + ret = furi_hal_nfc_ll_txrx_bits( + tx_data, + 2 * 8, + rx_data, + sizeof(rx_data), + &rx_len, + FURI_HAL_NFC_LL_TXRX_FLAGS_AGC_ON | FURI_HAL_NFC_LL_TXRX_FLAGS_CRC_RX_KEEP, + furi_hal_nfc_ll_ms2fc(20)); + if(ret != FuriHalNfcReturnIncompleteByte) break; + if(rx_len != 4) break; + if(rx_data[0] != MAGIC_ACK) break; + + memcpy(tx_data, data->value, sizeof(data->value)); + ret = furi_hal_nfc_ll_txrx_bits( + tx_data, + 16 * 8, + rx_data, + sizeof(rx_data), + &rx_len, + FURI_HAL_NFC_LL_TXRX_FLAGS_AGC_ON | FURI_HAL_NFC_LL_TXRX_FLAGS_CRC_RX_KEEP, + furi_hal_nfc_ll_ms2fc(20)); + if(ret != FuriHalNfcReturnIncompleteByte) break; + if(rx_len != 4) break; + if(rx_data[0] != MAGIC_ACK) break; + + write_success = true; + } while(false); + + return write_success; +} + +bool magic_gen1_wipe() { + bool wipe_success = false; + uint8_t tx_data[MAGIC_BUFFER_SIZE] = {}; + uint8_t rx_data[MAGIC_BUFFER_SIZE] = {}; + uint16_t rx_len = 0; + FuriHalNfcReturn ret = 0; + + do { + tx_data[0] = MAGIC_CMD_WIPE; + ret = furi_hal_nfc_ll_txrx_bits( + tx_data, + 8, + rx_data, + sizeof(rx_data), + &rx_len, + FURI_HAL_NFC_LL_TXRX_FLAGS_CRC_TX_MANUAL | FURI_HAL_NFC_LL_TXRX_FLAGS_AGC_ON | + FURI_HAL_NFC_LL_TXRX_FLAGS_CRC_RX_KEEP, + furi_hal_nfc_ll_ms2fc(2000)); + + if(ret != FuriHalNfcReturnIncompleteByte) break; + if(rx_len != 4) break; + if(rx_data[0] != MAGIC_ACK) break; + + wipe_success = true; + } while(false); + + return wipe_success; +} \ No newline at end of file diff --git a/applications/external/nfc_magic/lib/magic/classic_gen1.h b/applications/external/nfc_magic/lib/magic/classic_gen1.h new file mode 100644 index 000000000..6d4ff6dcd --- /dev/null +++ b/applications/external/nfc_magic/lib/magic/classic_gen1.h @@ -0,0 +1,13 @@ +#pragma once + +#include + +bool magic_gen1_wupa(); + +bool magic_gen1_read_block(uint8_t block_num, MfClassicBlock* data); + +bool magic_gen1_data_access_cmd(); + +bool magic_gen1_write_blk(uint8_t block_num, MfClassicBlock* data); + +bool magic_gen1_wipe(); \ No newline at end of file diff --git a/applications/external/nfc_magic/lib/magic/common.c b/applications/external/nfc_magic/lib/magic/common.c new file mode 100644 index 000000000..0ea3cb218 --- /dev/null +++ b/applications/external/nfc_magic/lib/magic/common.c @@ -0,0 +1,33 @@ +#include "common.h" + +#include + +#define REQA (0x26) +#define CL1_PREFIX (0x93) +#define SELECT (0x70) + +#define MAGIC_BUFFER_SIZE (32) + +bool magic_activate() { + FuriHalNfcReturn ret = 0; + + // Setup nfc poller + furi_hal_nfc_exit_sleep(); + furi_hal_nfc_ll_txrx_on(); + furi_hal_nfc_ll_poll(); + ret = furi_hal_nfc_ll_set_mode( + FuriHalNfcModePollNfca, FuriHalNfcBitrate106, FuriHalNfcBitrate106); + if(ret != FuriHalNfcReturnOk) return false; + + furi_hal_nfc_ll_set_fdt_listen(FURI_HAL_NFC_LL_FDT_LISTEN_NFCA_POLLER); + furi_hal_nfc_ll_set_fdt_poll(FURI_HAL_NFC_LL_FDT_POLL_NFCA_POLLER); + furi_hal_nfc_ll_set_error_handling(FuriHalNfcErrorHandlingNfc); + furi_hal_nfc_ll_set_guard_time(FURI_HAL_NFC_LL_GT_NFCA); + + return true; +} + +void magic_deactivate() { + furi_hal_nfc_ll_txrx_off(); + furi_hal_nfc_sleep(); +} \ No newline at end of file diff --git a/applications/external/nfc_magic/lib/magic/common.h b/applications/external/nfc_magic/lib/magic/common.h new file mode 100644 index 000000000..bef166c8f --- /dev/null +++ b/applications/external/nfc_magic/lib/magic/common.h @@ -0,0 +1,19 @@ +#pragma once + +#include +#include + +typedef enum { + MagicTypeClassicGen1, + MagicTypeClassicDirectWrite, + MagicTypeClassicAPDU, + MagicTypeUltralightGen1, + MagicTypeUltralightDirectWrite, + MagicTypeUltralightC_Gen1, + MagicTypeUltralightC_DirectWrite, + MagicTypeGen4, +} MagicType; + +bool magic_activate(); + +void magic_deactivate(); \ No newline at end of file diff --git a/applications/external/nfc_magic/lib/magic/gen4.c b/applications/external/nfc_magic/lib/magic/gen4.c new file mode 100644 index 000000000..31be649a0 --- /dev/null +++ b/applications/external/nfc_magic/lib/magic/gen4.c @@ -0,0 +1,199 @@ +#include "gen4.h" + +#include +#include + +#define TAG "Magic" + +#define MAGIC_CMD_PREFIX (0xCF) + +#define MAGIC_CMD_GET_CFG (0xC6) +#define MAGIC_CMD_WRITE (0xCD) +#define MAGIC_CMD_READ (0xCE) +#define MAGIC_CMD_SET_CFG (0xF0) +#define MAGIC_CMD_FUSE_CFG (0xF1) +#define MAGIC_CMD_SET_PWD (0xFE) + +#define MAGIC_BUFFER_SIZE (40) + +const uint8_t MAGIC_DEFAULT_CONFIG[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x09, 0x78, 0x00, 0x91, 0x02, 0xDA, 0xBC, 0x19, 0x10, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x04, 0x00, 0x08, 0x00 +}; + +const uint8_t MAGIC_DEFAULT_BLOCK0[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x04, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +const uint8_t MAGIC_EMPTY_BLOCK[16] = { 0 }; + +const uint8_t MAGIC_DEFAULT_SECTOR_TRAILER[] = { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x80, 0x69, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF +}; + +static bool magic_gen4_is_block_num_trailer(uint8_t n) { + n++; + if (n < 32 * 4) { + return (n % 4 == 0); + } + + return (n % 16 == 0); +} + +bool magic_gen4_get_cfg(uint32_t pwd, uint8_t* config) { + bool is_valid_config_len = false; + uint8_t tx_data[MAGIC_BUFFER_SIZE] = {}; + uint8_t rx_data[MAGIC_BUFFER_SIZE] = {}; + uint16_t rx_len = 0; + FuriHalNfcReturn ret = 0; + + do { + // Start communication + tx_data[0] = MAGIC_CMD_PREFIX; + tx_data[1] = (uint8_t)(pwd >> 24); + tx_data[2] = (uint8_t)(pwd >> 16); + tx_data[3] = (uint8_t)(pwd >> 8); + tx_data[4] = (uint8_t)pwd; + tx_data[5] = MAGIC_CMD_GET_CFG; + ret = furi_hal_nfc_ll_txrx( + tx_data, + 6, + rx_data, + sizeof(rx_data), + &rx_len, + FURI_HAL_NFC_TXRX_DEFAULT, + furi_hal_nfc_ll_ms2fc(20)); + if(ret != FuriHalNfcReturnOk) break; + if(rx_len != 30 && rx_len != 32) break; + memcpy(config, rx_data, rx_len); + is_valid_config_len = true; + } while(false); + + return is_valid_config_len; +} + +bool magic_gen4_set_cfg(uint32_t pwd, const uint8_t* config, uint8_t config_length, bool fuse) { + bool write_success = false; + uint8_t tx_data[MAGIC_BUFFER_SIZE] = {}; + uint8_t rx_data[MAGIC_BUFFER_SIZE] = {}; + uint16_t rx_len = 0; + FuriHalNfcReturn ret = 0; + + do { + // Start communication + tx_data[0] = MAGIC_CMD_PREFIX; + tx_data[1] = (uint8_t)(pwd >> 24); + tx_data[2] = (uint8_t)(pwd >> 16); + tx_data[3] = (uint8_t)(pwd >> 8); + tx_data[4] = (uint8_t)pwd; + tx_data[5] = fuse ? MAGIC_CMD_FUSE_CFG : MAGIC_CMD_SET_CFG; + memcpy(tx_data + 6, config, config_length); + ret = furi_hal_nfc_ll_txrx( + tx_data, + 6 + config_length, + rx_data, + sizeof(rx_data), + &rx_len, + FURI_HAL_NFC_TXRX_DEFAULT, + furi_hal_nfc_ll_ms2fc(20)); + if(ret != FuriHalNfcReturnOk) break; + if(rx_len != 2) break; + write_success = true; + } while(false); + + return write_success; +} + +bool magic_gen4_set_pwd(uint32_t old_pwd, uint32_t new_pwd) { + bool change_success = false; + uint8_t tx_data[MAGIC_BUFFER_SIZE] = {}; + uint8_t rx_data[MAGIC_BUFFER_SIZE] = {}; + uint16_t rx_len = 0; + FuriHalNfcReturn ret = 0; + + do { + // Start communication + tx_data[0] = MAGIC_CMD_PREFIX; + tx_data[1] = (uint8_t)(old_pwd >> 24); + tx_data[2] = (uint8_t)(old_pwd >> 16); + tx_data[3] = (uint8_t)(old_pwd >> 8); + tx_data[4] = (uint8_t)old_pwd; + tx_data[5] = MAGIC_CMD_SET_PWD; + tx_data[6] = (uint8_t)(new_pwd >> 24); + tx_data[7] = (uint8_t)(new_pwd >> 16); + tx_data[8] = (uint8_t)(new_pwd >> 8); + tx_data[9] = (uint8_t)new_pwd; + ret = furi_hal_nfc_ll_txrx( + tx_data, + 10, + rx_data, + sizeof(rx_data), + &rx_len, + FURI_HAL_NFC_TXRX_DEFAULT, + furi_hal_nfc_ll_ms2fc(20)); + FURI_LOG_I(TAG, "ret %d, len %d", ret, rx_len); + if(ret != FuriHalNfcReturnOk) break; + if(rx_len != 2) break; + change_success = true; + } while(false); + + return change_success; +} + +bool magic_gen4_write_blk(uint32_t pwd, uint8_t block_num, const uint8_t* data) { + bool write_success = false; + uint8_t tx_data[MAGIC_BUFFER_SIZE] = {}; + uint8_t rx_data[MAGIC_BUFFER_SIZE] = {}; + uint16_t rx_len = 0; + FuriHalNfcReturn ret = 0; + + do { + // Start communication + tx_data[0] = MAGIC_CMD_PREFIX; + tx_data[1] = (uint8_t)(pwd >> 24); + tx_data[2] = (uint8_t)(pwd >> 16); + tx_data[3] = (uint8_t)(pwd >> 8); + tx_data[4] = (uint8_t)pwd; + tx_data[5] = MAGIC_CMD_WRITE; + tx_data[6] = block_num; + memcpy(tx_data + 7, data, 16); + ret = furi_hal_nfc_ll_txrx( + tx_data, + 23, + rx_data, + sizeof(rx_data), + &rx_len, + FURI_HAL_NFC_TXRX_DEFAULT, + furi_hal_nfc_ll_ms2fc(200)); + if(ret != FuriHalNfcReturnOk) break; + if(rx_len != 2) break; + write_success = true; + } while(false); + + return write_success; +} + +bool magic_gen4_wipe(uint32_t pwd) { + if(!magic_gen4_set_cfg(pwd, MAGIC_DEFAULT_CONFIG, sizeof(MAGIC_DEFAULT_CONFIG), false)) { + FURI_LOG_E(TAG, "Set config failed"); + return false; + } + if(!magic_gen4_write_blk(pwd, 0, MAGIC_DEFAULT_BLOCK0)) { + FURI_LOG_E(TAG, "Block 0 write failed"); + return false; + } + for(size_t i = 1; i < 64; i++) { + const uint8_t* block = magic_gen4_is_block_num_trailer(i) ? MAGIC_DEFAULT_SECTOR_TRAILER : MAGIC_EMPTY_BLOCK; + if(!magic_gen4_write_blk(pwd, i, block)) { + FURI_LOG_E(TAG, "Block %d write failed", i); + return false; + } + } + for(size_t i = 65; i < 256; i++) { + if(!magic_gen4_write_blk(pwd, i, MAGIC_EMPTY_BLOCK)) { + FURI_LOG_E(TAG, "Block %d write failed", i); + return false; + } + } + + return true; +} \ No newline at end of file diff --git a/applications/external/nfc_magic/lib/magic/gen4.h b/applications/external/nfc_magic/lib/magic/gen4.h new file mode 100644 index 000000000..c515af820 --- /dev/null +++ b/applications/external/nfc_magic/lib/magic/gen4.h @@ -0,0 +1,48 @@ +#pragma once + +#include + +#define MAGIC_GEN4_DEFAULT_PWD 0x00000000 +#define MAGIC_GEN4_CONFIG_LEN 32 + +#define NFCID1_SINGLE_SIZE 4 +#define NFCID1_DOUBLE_SIZE 7 +#define NFCID1_TRIPLE_SIZE 10 + +typedef enum { + MagicGen4UIDLengthSingle = 0x00, + MagicGen4UIDLengthDouble = 0x01, + MagicGen4UIDLengthTriple = 0x02 +} MagicGen4UIDLength; + +typedef enum { + MagicGen4UltralightModeUL_EV1 = 0x00, + MagicGen4UltralightModeNTAG = 0x01, + MagicGen4UltralightModeUL_C = 0x02, + MagicGen4UltralightModeUL = 0x03 +} MagicGen4UltralightMode; + +typedef enum { + // for writing original (shadow) data + MagicGen4ShadowModePreWrite = 0x00, + // written data can be read once before restored to original + MagicGen4ShadowModeRestore = 0x01, + // written data is discarded + MagicGen4ShadowModeIgnore = 0x02, + // apparently for UL? + MagicGen4ShadowModeHighSpeedIgnore = 0x03 +} MagicGen4ShadowMode; + +bool magic_gen4_get_cfg(uint32_t pwd, uint8_t* config); + +bool magic_gen4_set_cfg(uint32_t pwd, const uint8_t* config, uint8_t config_length, bool fuse); + +bool magic_gen4_set_pwd(uint32_t old_pwd, uint32_t new_pwd); + +bool magic_gen4_read_blk(uint32_t pwd, uint8_t block_num, uint8_t* data); + +bool magic_gen4_write_blk(uint32_t pwd, uint8_t block_num, const uint8_t* data); + +bool magic_gen4_wipe(uint32_t pwd); + +void magic_gen4_deactivate(); diff --git a/applications/external/nfc_magic/lib/magic/magic.c b/applications/external/nfc_magic/lib/magic/magic.c index 9a71daaa0..ebd2b0805 100644 --- a/applications/external/nfc_magic/lib/magic/magic.c +++ b/applications/external/nfc_magic/lib/magic/magic.c @@ -1,4 +1,4 @@ -#include "magic.h" +#include "classic_gen1.h" #include @@ -15,7 +15,7 @@ #define MAGIC_BUFFER_SIZE (32) -bool magic_wupa() { +bool magic_gen1_wupa() { bool magic_activated = false; uint8_t tx_data[MAGIC_BUFFER_SIZE] = {}; uint8_t rx_data[MAGIC_BUFFER_SIZE] = {}; @@ -23,19 +23,6 @@ bool magic_wupa() { FuriHalNfcReturn ret = 0; do { - // Setup nfc poller - furi_hal_nfc_exit_sleep(); - furi_hal_nfc_ll_txrx_on(); - furi_hal_nfc_ll_poll(); - ret = furi_hal_nfc_ll_set_mode( - FuriHalNfcModePollNfca, FuriHalNfcBitrate106, FuriHalNfcBitrate106); - if(ret != FuriHalNfcReturnOk) break; - - furi_hal_nfc_ll_set_fdt_listen(FURI_HAL_NFC_LL_FDT_LISTEN_NFCA_POLLER); - furi_hal_nfc_ll_set_fdt_poll(FURI_HAL_NFC_LL_FDT_POLL_NFCA_POLLER); - furi_hal_nfc_ll_set_error_handling(FuriHalNfcErrorHandlingNfc); - furi_hal_nfc_ll_set_guard_time(FURI_HAL_NFC_LL_GT_NFCA); - // Start communication tx_data[0] = MAGIC_CMD_WUPA; ret = furi_hal_nfc_ll_txrx_bits( @@ -53,15 +40,10 @@ bool magic_wupa() { magic_activated = true; } while(false); - if(!magic_activated) { - furi_hal_nfc_ll_txrx_off(); - furi_hal_nfc_start_sleep(); - } - return magic_activated; } -bool magic_data_access_cmd() { +bool magic_gen1_data_access_cmd() { bool write_cmd_success = false; uint8_t tx_data[MAGIC_BUFFER_SIZE] = {}; uint8_t rx_data[MAGIC_BUFFER_SIZE] = {}; @@ -86,15 +68,10 @@ bool magic_data_access_cmd() { write_cmd_success = true; } while(false); - if(!write_cmd_success) { - furi_hal_nfc_ll_txrx_off(); - furi_hal_nfc_start_sleep(); - } - return write_cmd_success; } -bool magic_read_block(uint8_t block_num, MfClassicBlock* data) { +bool magic_gen1_read_block(uint8_t block_num, MfClassicBlock* data) { furi_assert(data); bool read_success = false; @@ -122,15 +99,10 @@ bool magic_read_block(uint8_t block_num, MfClassicBlock* data) { read_success = true; } while(false); - if(!read_success) { - furi_hal_nfc_ll_txrx_off(); - furi_hal_nfc_start_sleep(); - } - return read_success; } -bool magic_write_blk(uint8_t block_num, MfClassicBlock* data) { +bool magic_gen1_write_blk(uint8_t block_num, MfClassicBlock* data) { furi_assert(data); bool write_success = false; @@ -170,15 +142,10 @@ bool magic_write_blk(uint8_t block_num, MfClassicBlock* data) { write_success = true; } while(false); - if(!write_success) { - furi_hal_nfc_ll_txrx_off(); - furi_hal_nfc_start_sleep(); - } - return write_success; } -bool magic_wipe() { +bool magic_gen1_wipe() { bool wipe_success = false; uint8_t tx_data[MAGIC_BUFFER_SIZE] = {}; uint8_t rx_data[MAGIC_BUFFER_SIZE] = {}; @@ -205,9 +172,4 @@ bool magic_wipe() { } while(false); return wipe_success; -} - -void magic_deactivate() { - furi_hal_nfc_ll_txrx_off(); - furi_hal_nfc_sleep(); -} +} \ No newline at end of file diff --git a/applications/external/nfc_magic/lib/magic/magic.h b/applications/external/nfc_magic/lib/magic/magic.h deleted file mode 100644 index 64c60a0a7..000000000 --- a/applications/external/nfc_magic/lib/magic/magic.h +++ /dev/null @@ -1,15 +0,0 @@ -#pragma once - -#include - -bool magic_wupa(); - -bool magic_read_block(uint8_t block_num, MfClassicBlock* data); - -bool magic_data_access_cmd(); - -bool magic_write_blk(uint8_t block_num, MfClassicBlock* data); - -bool magic_wipe(); - -void magic_deactivate(); diff --git a/applications/external/nfc_magic/lib/magic/types.c b/applications/external/nfc_magic/lib/magic/types.c new file mode 100644 index 000000000..77c6c0a4e --- /dev/null +++ b/applications/external/nfc_magic/lib/magic/types.c @@ -0,0 +1,23 @@ +#include "types.h" + +const char* nfc_magic_type(MagicType type) { + if(type == MagicTypeClassicGen1) { + return "Classic Gen 1A/B"; + } else if(type == MagicTypeClassicDirectWrite) { + return "Classic DirectWrite"; + } else if(type == MagicTypeClassicAPDU) { + return "Classic APDU"; + } else if(type == MagicTypeUltralightGen1) { + return "Ultralight Gen 1"; + } else if(type == MagicTypeUltralightDirectWrite) { + return "Ultralight DirectWrite"; + } else if(type == MagicTypeUltralightC_Gen1) { + return "Ultralight-C Gen 1"; + } else if(type == MagicTypeUltralightC_DirectWrite) { + return "Ultralight-C DirectWrite"; + } else if(type == MagicTypeGen4) { + return "Gen 4 GTU"; + } else { + return "Unknown"; + } +} diff --git a/applications/external/nfc_magic/lib/magic/types.h b/applications/external/nfc_magic/lib/magic/types.h new file mode 100644 index 000000000..dbf554063 --- /dev/null +++ b/applications/external/nfc_magic/lib/magic/types.h @@ -0,0 +1,5 @@ +#pragma once + +#include "common.h" + +const char* nfc_magic_type(MagicType type); \ No newline at end of file diff --git a/applications/external/nfc_magic/nfc_magic.c b/applications/external/nfc_magic/nfc_magic.c index 1805f35ed..68c9a65b5 100644 --- a/applications/external/nfc_magic/nfc_magic.c +++ b/applications/external/nfc_magic/nfc_magic.c @@ -48,8 +48,9 @@ NfcMagic* nfc_magic_alloc() { nfc_magic->view_dispatcher, nfc_magic_tick_event_callback, 100); // Nfc device - nfc_magic->nfc_dev = nfc_device_alloc(); - furi_string_set(nfc_magic->nfc_dev->folder, NFC_APP_FOLDER); + nfc_magic->dev = malloc(sizeof(NfcMagicDevice)); + nfc_magic->source_dev = nfc_device_alloc(); + furi_string_set(nfc_magic->source_dev->folder, NFC_APP_FOLDER); // Open GUI record nfc_magic->gui = furi_record_open(RECORD_GUI); @@ -81,6 +82,13 @@ NfcMagic* nfc_magic_alloc() { NfcMagicViewTextInput, text_input_get_view(nfc_magic->text_input)); + // Byte Input + nfc_magic->byte_input = byte_input_alloc(); + view_dispatcher_add_view( + nfc_magic->view_dispatcher, + NfcMagicViewByteInput, + byte_input_get_view(nfc_magic->byte_input)); + // Custom Widget nfc_magic->widget = widget_alloc(); view_dispatcher_add_view( @@ -93,7 +101,8 @@ void nfc_magic_free(NfcMagic* nfc_magic) { furi_assert(nfc_magic); // Nfc device - nfc_device_free(nfc_magic->nfc_dev); + free(nfc_magic->dev); + nfc_device_free(nfc_magic->source_dev); // Submenu view_dispatcher_remove_view(nfc_magic->view_dispatcher, NfcMagicViewMenu); @@ -107,10 +116,14 @@ void nfc_magic_free(NfcMagic* nfc_magic) { view_dispatcher_remove_view(nfc_magic->view_dispatcher, NfcMagicViewLoading); loading_free(nfc_magic->loading); - // TextInput + // Text Input view_dispatcher_remove_view(nfc_magic->view_dispatcher, NfcMagicViewTextInput); text_input_free(nfc_magic->text_input); + // Byte Input + view_dispatcher_remove_view(nfc_magic->view_dispatcher, NfcMagicViewByteInput); + byte_input_free(nfc_magic->byte_input); + // Custom Widget view_dispatcher_remove_view(nfc_magic->view_dispatcher, NfcMagicViewWidget); widget_free(nfc_magic->widget); @@ -164,6 +177,7 @@ int32_t nfc_magic_app(void* p) { view_dispatcher_run(nfc_magic->view_dispatcher); + magic_deactivate(); nfc_magic_free(nfc_magic); return 0; diff --git a/applications/external/nfc_magic/nfc_magic.h b/applications/external/nfc_magic/nfc_magic.h index 1abf1371e..f9cf395d8 100644 --- a/applications/external/nfc_magic/nfc_magic.h +++ b/applications/external/nfc_magic/nfc_magic.h @@ -1,3 +1,5 @@ #pragma once +typedef struct NfcMagicDevice NfcMagicDevice; + typedef struct NfcMagic NfcMagic; diff --git a/applications/external/nfc_magic/nfc_magic_i.h b/applications/external/nfc_magic/nfc_magic_i.h index 378912e5b..4d6b89103 100644 --- a/applications/external/nfc_magic/nfc_magic_i.h +++ b/applications/external/nfc_magic/nfc_magic_i.h @@ -3,7 +3,10 @@ #include "nfc_magic.h" #include "nfc_magic_worker.h" -#include "lib/magic/magic.h" +#include "lib/magic/common.h" +#include "lib/magic/types.h" +#include "lib/magic/classic_gen1.h" +#include "lib/magic/gen4.h" #include #include @@ -15,6 +18,7 @@ #include #include #include +#include #include #include @@ -39,14 +43,22 @@ enum NfcMagicCustomEvent { NfcMagicCustomEventTextInputDone, }; +struct NfcMagicDevice { + MagicType type; + uint32_t cuid; + uint32_t password; +}; + struct NfcMagic { NfcMagicWorker* worker; ViewDispatcher* view_dispatcher; Gui* gui; NotificationApp* notifications; SceneManager* scene_manager; - // NfcMagicDevice* dev; - NfcDevice* nfc_dev; + struct NfcMagicDevice* dev; + NfcDevice* source_dev; + + uint32_t new_password; FuriString* text_box_store; @@ -55,6 +67,7 @@ struct NfcMagic { Popup* popup; Loading* loading; TextInput* text_input; + ByteInput* byte_input; Widget* widget; }; @@ -63,6 +76,7 @@ typedef enum { NfcMagicViewPopup, NfcMagicViewLoading, NfcMagicViewTextInput, + NfcMagicViewByteInput, NfcMagicViewWidget, } NfcMagicView; diff --git a/applications/external/nfc_magic/nfc_magic_worker.c b/applications/external/nfc_magic/nfc_magic_worker.c index 92eb793a7..dc22b5d3e 100644 --- a/applications/external/nfc_magic/nfc_magic_worker.c +++ b/applications/external/nfc_magic/nfc_magic_worker.c @@ -1,6 +1,9 @@ #include "nfc_magic_worker_i.h" -#include "lib/magic/magic.h" +#include "nfc_magic_i.h" +#include "lib/magic/common.h" +#include "lib/magic/classic_gen1.h" +#include "lib/magic/gen4.h" #define TAG "NfcMagicWorker" @@ -43,15 +46,20 @@ void nfc_magic_worker_stop(NfcMagicWorker* nfc_magic_worker) { void nfc_magic_worker_start( NfcMagicWorker* nfc_magic_worker, NfcMagicWorkerState state, + NfcMagicDevice* magic_dev, NfcDeviceData* dev_data, + uint32_t new_password, NfcMagicWorkerCallback callback, void* context) { furi_assert(nfc_magic_worker); + furi_assert(magic_dev); furi_assert(dev_data); nfc_magic_worker->callback = callback; nfc_magic_worker->context = context; + nfc_magic_worker->magic_dev = magic_dev; nfc_magic_worker->dev_data = dev_data; + nfc_magic_worker->new_password = new_password; nfc_magic_worker_change_state(nfc_magic_worker, state); furi_thread_start(nfc_magic_worker->thread); } @@ -63,6 +71,8 @@ int32_t nfc_magic_worker_task(void* context) { nfc_magic_worker_check(nfc_magic_worker); } else if(nfc_magic_worker->state == NfcMagicWorkerStateWrite) { nfc_magic_worker_write(nfc_magic_worker); + } else if(nfc_magic_worker->state == NfcMagicWorkerStateRekey) { + nfc_magic_worker_rekey(nfc_magic_worker); } else if(nfc_magic_worker->state == NfcMagicWorkerStateWipe) { nfc_magic_worker_wipe(nfc_magic_worker); } @@ -74,59 +84,245 @@ int32_t nfc_magic_worker_task(void* context) { void nfc_magic_worker_write(NfcMagicWorker* nfc_magic_worker) { bool card_found_notified = false; + bool done = false; FuriHalNfcDevData nfc_data = {}; - MfClassicData* src_data = &nfc_magic_worker->dev_data->mf_classic_data; + NfcMagicDevice* magic_dev = nfc_magic_worker->magic_dev; + NfcDeviceData* dev_data = nfc_magic_worker->dev_data; + NfcProtocol dev_protocol = dev_data->protocol; while(nfc_magic_worker->state == NfcMagicWorkerStateWrite) { - if(furi_hal_nfc_detect(&nfc_data, 200)) { - if(!card_found_notified) { - nfc_magic_worker->callback( - NfcMagicWorkerEventCardDetected, nfc_magic_worker->context); - card_found_notified = true; - } - furi_hal_nfc_sleep(); - if(!magic_wupa()) { - FURI_LOG_E(TAG, "No card response to WUPA (not a magic card)"); - nfc_magic_worker->callback( - NfcMagicWorkerEventWrongCard, nfc_magic_worker->context); - break; - } - furi_hal_nfc_sleep(); - } - if(magic_wupa()) { - if(!magic_data_access_cmd()) { - FURI_LOG_E(TAG, "No card response to data access command (not a magic card)"); - nfc_magic_worker->callback( - NfcMagicWorkerEventWrongCard, nfc_magic_worker->context); - break; - } - for(size_t i = 0; i < 64; i++) { - FURI_LOG_D(TAG, "Writing block %d", i); - if(!magic_write_blk(i, &src_data->block[i])) { - FURI_LOG_E(TAG, "Failed to write %d block", i); - nfc_magic_worker->callback(NfcMagicWorkerEventFail, nfc_magic_worker->context); + do { + if(furi_hal_nfc_detect(&nfc_data, 200)) { + if(nfc_data.cuid != magic_dev->cuid) break; + if(!card_found_notified) { + nfc_magic_worker->callback( + NfcMagicWorkerEventCardDetected, nfc_magic_worker->context); + card_found_notified = true; + } + furi_hal_nfc_sleep(); + + magic_activate(); + if(magic_dev->type == MagicTypeClassicGen1) { + if(dev_protocol != NfcDeviceProtocolMifareClassic) break; + MfClassicData* mfc_data = &dev_data->mf_classic_data; + + if(mfc_data->type != MfClassicType1k) break; + if(!magic_gen1_wupa()) { + FURI_LOG_E(TAG, "Not Magic card"); + nfc_magic_worker->callback( + NfcMagicWorkerEventWrongCard, nfc_magic_worker->context); + done = true; + break; + } + if(!magic_gen1_data_access_cmd()) { + FURI_LOG_E(TAG, "Not Magic card"); + nfc_magic_worker->callback( + NfcMagicWorkerEventWrongCard, nfc_magic_worker->context); + done = true; + break; + } + for(size_t i = 0; i < 64; i++) { + FURI_LOG_D(TAG, "Writing block %d", i); + if(!magic_gen1_write_blk(i, &mfc_data->block[i])) { + FURI_LOG_E(TAG, "Failed to write %d block", i); + nfc_magic_worker->callback( + NfcMagicWorkerEventFail, nfc_magic_worker->context); + done = true; + break; + } + } + + nfc_magic_worker->callback( + NfcMagicWorkerEventSuccess, nfc_magic_worker->context); + done = true; + break; + } else if(magic_dev->type == MagicTypeGen4) { + uint8_t gen4_config[28]; + uint32_t password = magic_dev->password; + + uint32_t cuid; + if(dev_protocol == NfcDeviceProtocolMifareClassic) { + gen4_config[0] = 0x00; + gen4_config[27] = 0x00; + } else if(dev_protocol == NfcDeviceProtocolMifareUl) { + MfUltralightData* mf_ul_data = &dev_data->mf_ul_data; + gen4_config[0] = 0x01; + switch(mf_ul_data->type) { + case MfUltralightTypeUL11: + case MfUltralightTypeUL21: + // UL-C? + // UL? + default: + gen4_config[27] = MagicGen4UltralightModeUL_EV1; + break; + case MfUltralightTypeNTAG203: + case MfUltralightTypeNTAG213: + case MfUltralightTypeNTAG215: + case MfUltralightTypeNTAG216: + case MfUltralightTypeNTAGI2C1K: + case MfUltralightTypeNTAGI2C2K: + case MfUltralightTypeNTAGI2CPlus1K: + case MfUltralightTypeNTAGI2CPlus2K: + gen4_config[27] = MagicGen4UltralightModeNTAG; + break; + } + } + + if(dev_data->nfc_data.uid_len == 4) { + gen4_config[1] = MagicGen4UIDLengthSingle; + } else if(dev_data->nfc_data.uid_len == 7) { + gen4_config[1] = MagicGen4UIDLengthDouble; + } else { + FURI_LOG_E(TAG, "Unexpected UID length %d", dev_data->nfc_data.uid_len); + nfc_magic_worker->callback( + NfcMagicWorkerEventFail, nfc_magic_worker->context); + done = true; + break; + } + + gen4_config[2] = (uint8_t)(password >> 24); + gen4_config[3] = (uint8_t)(password >> 16); + gen4_config[4] = (uint8_t)(password >> 8); + gen4_config[5] = (uint8_t)password; + + if(dev_protocol == NfcDeviceProtocolMifareUl) { + gen4_config[6] = MagicGen4ShadowModeHighSpeedIgnore; + } else { + gen4_config[6] = MagicGen4ShadowModeIgnore; + } + gen4_config[7] = 0x00; + memset(gen4_config + 8, 0, 16); + gen4_config[24] = dev_data->nfc_data.atqa[0]; + gen4_config[25] = dev_data->nfc_data.atqa[1]; + gen4_config[26] = dev_data->nfc_data.sak; + + furi_hal_nfc_activate_nfca(200, &cuid); + if(!magic_gen4_set_cfg(password, gen4_config, sizeof(gen4_config), false)) { + nfc_magic_worker->callback( + NfcMagicWorkerEventFail, nfc_magic_worker->context); + done = true; + break; + } + if(dev_protocol == NfcDeviceProtocolMifareClassic) { + MfClassicData* mfc_data = &dev_data->mf_classic_data; + size_t block_count = 64; + if(mfc_data->type == MfClassicType4k) block_count = 256; + for(size_t i = 0; i < block_count; i++) { + FURI_LOG_D(TAG, "Writing block %d", i); + if(!magic_gen4_write_blk(password, i, mfc_data->block[i].value)) { + FURI_LOG_E(TAG, "Failed to write %d block", i); + nfc_magic_worker->callback( + NfcMagicWorkerEventFail, nfc_magic_worker->context); + done = true; + break; + } + } + } else if(dev_protocol == NfcDeviceProtocolMifareUl) { + MfUltralightData* mf_ul_data = &dev_data->mf_ul_data; + for(size_t i = 0; (i * 4) < mf_ul_data->data_read; i++) { + size_t data_offset = i * 4; + FURI_LOG_D( + TAG, + "Writing page %zu (%zu/%u)", + i, + data_offset, + mf_ul_data->data_read); + uint8_t* block = mf_ul_data->data + data_offset; + if(!magic_gen4_write_blk(password, i, block)) { + FURI_LOG_E(TAG, "Failed to write %zu page", i); + nfc_magic_worker->callback( + NfcMagicWorkerEventFail, nfc_magic_worker->context); + done = true; + break; + } + } + + uint8_t buffer[16] = {0}; + + for(size_t i = 0; i < 8; i++) { + memcpy(buffer, &mf_ul_data->signature[i * 4], 4); //-V1086 + if(!magic_gen4_write_blk(password, 0xF2 + i, buffer)) { + FURI_LOG_E(TAG, "Failed to write signature block %d", i); + nfc_magic_worker->callback( + NfcMagicWorkerEventFail, nfc_magic_worker->context); + done = true; + break; + } + } + + buffer[0] = mf_ul_data->version.header; + buffer[1] = mf_ul_data->version.vendor_id; + buffer[2] = mf_ul_data->version.prod_type; + buffer[3] = mf_ul_data->version.prod_subtype; + if(!magic_gen4_write_blk(password, 0xFA, buffer)) { + FURI_LOG_E(TAG, "Failed to write version block 0"); + nfc_magic_worker->callback( + NfcMagicWorkerEventFail, nfc_magic_worker->context); + done = true; + break; + } + + buffer[0] = mf_ul_data->version.prod_ver_major; + buffer[1] = mf_ul_data->version.prod_ver_minor; + buffer[2] = mf_ul_data->version.storage_size; + buffer[3] = mf_ul_data->version.protocol_type; + if(!magic_gen4_write_blk(password, 0xFB, buffer)) { + FURI_LOG_E(TAG, "Failed to write version block 1"); + nfc_magic_worker->callback( + NfcMagicWorkerEventFail, nfc_magic_worker->context); + done = true; + break; + } + } + + nfc_magic_worker->callback( + NfcMagicWorkerEventSuccess, nfc_magic_worker->context); + done = true; break; } } - nfc_magic_worker->callback(NfcMagicWorkerEventSuccess, nfc_magic_worker->context); - break; - } else { - if(card_found_notified) { - nfc_magic_worker->callback( - NfcMagicWorkerEventNoCardDetected, nfc_magic_worker->context); - card_found_notified = false; - } + } while(false); + + if(done) break; + + if(card_found_notified) { + nfc_magic_worker->callback( + NfcMagicWorkerEventNoCardDetected, nfc_magic_worker->context); + card_found_notified = false; } + furi_delay_ms(300); } magic_deactivate(); } void nfc_magic_worker_check(NfcMagicWorker* nfc_magic_worker) { + NfcMagicDevice* magic_dev = nfc_magic_worker->magic_dev; bool card_found_notified = false; + uint8_t gen4_config[MAGIC_GEN4_CONFIG_LEN]; while(nfc_magic_worker->state == NfcMagicWorkerStateCheck) { - if(magic_wupa()) { + magic_activate(); + if(magic_gen1_wupa()) { + magic_dev->type = MagicTypeClassicGen1; + if(!card_found_notified) { + nfc_magic_worker->callback( + NfcMagicWorkerEventCardDetected, nfc_magic_worker->context); + card_found_notified = true; + } + + furi_hal_nfc_activate_nfca(200, &magic_dev->cuid); + nfc_magic_worker->callback(NfcMagicWorkerEventSuccess, nfc_magic_worker->context); + break; + } + + magic_deactivate(); + furi_delay_ms(300); + magic_activate(); + + furi_hal_nfc_activate_nfca(200, &magic_dev->cuid); + if(magic_gen4_get_cfg(magic_dev->password, gen4_config)) { + magic_dev->type = MagicTypeGen4; if(!card_found_notified) { nfc_magic_worker->callback( NfcMagicWorkerEventCardDetected, nfc_magic_worker->context); @@ -135,12 +331,56 @@ void nfc_magic_worker_check(NfcMagicWorker* nfc_magic_worker) { nfc_magic_worker->callback(NfcMagicWorkerEventSuccess, nfc_magic_worker->context); break; - } else { + } + + if(card_found_notified) { + nfc_magic_worker->callback( + NfcMagicWorkerEventNoCardDetected, nfc_magic_worker->context); + card_found_notified = false; + } + + magic_deactivate(); + furi_delay_ms(300); + } + + magic_deactivate(); +} + +void nfc_magic_worker_rekey(NfcMagicWorker* nfc_magic_worker) { + NfcMagicDevice* magic_dev = nfc_magic_worker->magic_dev; + bool card_found_notified = false; + + if(magic_dev->type != MagicTypeGen4) { + nfc_magic_worker->callback(NfcMagicWorkerEventCardDetected, nfc_magic_worker->context); + return; + } + + while(nfc_magic_worker->state == NfcMagicWorkerStateRekey) { + magic_activate(); + uint32_t cuid; + furi_hal_nfc_activate_nfca(200, &cuid); + if(cuid != magic_dev->cuid) { if(card_found_notified) { nfc_magic_worker->callback( NfcMagicWorkerEventNoCardDetected, nfc_magic_worker->context); card_found_notified = false; } + continue; + } + + nfc_magic_worker->callback(NfcMagicWorkerEventCardDetected, nfc_magic_worker->context); + card_found_notified = true; + + if(magic_gen4_set_pwd(magic_dev->password, nfc_magic_worker->new_password)) { + magic_dev->password = nfc_magic_worker->new_password; + nfc_magic_worker->callback(NfcMagicWorkerEventSuccess, nfc_magic_worker->context); + break; + } + + if(card_found_notified) { //-V547 + nfc_magic_worker->callback( + NfcMagicWorkerEventNoCardDetected, nfc_magic_worker->context); + card_found_notified = false; } furi_delay_ms(300); } @@ -148,6 +388,10 @@ void nfc_magic_worker_check(NfcMagicWorker* nfc_magic_worker) { } void nfc_magic_worker_wipe(NfcMagicWorker* nfc_magic_worker) { + NfcMagicDevice* magic_dev = nfc_magic_worker->magic_dev; + bool card_found_notified = false; + bool card_wiped = false; + MfClassicBlock block; memset(&block, 0, sizeof(MfClassicBlock)); block.value[0] = 0x01; @@ -159,14 +403,48 @@ void nfc_magic_worker_wipe(NfcMagicWorker* nfc_magic_worker) { block.value[6] = 0x04; while(nfc_magic_worker->state == NfcMagicWorkerStateWipe) { - magic_deactivate(); - furi_delay_ms(300); - if(!magic_wupa()) continue; - if(!magic_wipe()) continue; - if(!magic_data_access_cmd()) continue; - if(!magic_write_blk(0, &block)) continue; - nfc_magic_worker->callback(NfcMagicWorkerEventSuccess, nfc_magic_worker->context); - break; + do { + magic_deactivate(); + furi_delay_ms(300); + if(!magic_activate()) break; + if(magic_dev->type == MagicTypeClassicGen1) { + if(!magic_gen1_wupa()) break; + if(!card_found_notified) { + nfc_magic_worker->callback( + NfcMagicWorkerEventCardDetected, nfc_magic_worker->context); + card_found_notified = true; + } + + if(!magic_gen1_wipe()) break; + if(!magic_gen1_data_access_cmd()) break; + if(!magic_gen1_write_blk(0, &block)) break; + + card_wiped = true; + nfc_magic_worker->callback(NfcMagicWorkerEventSuccess, nfc_magic_worker->context); + } else if(magic_dev->type == MagicTypeGen4) { + uint32_t cuid; + if(!furi_hal_nfc_activate_nfca(200, &cuid)) break; + if(cuid != magic_dev->cuid) break; + if(!card_found_notified) { + nfc_magic_worker->callback( + NfcMagicWorkerEventCardDetected, nfc_magic_worker->context); + card_found_notified = true; + } + + if(!magic_gen4_wipe(magic_dev->password)) break; + + card_wiped = true; + nfc_magic_worker->callback(NfcMagicWorkerEventSuccess, nfc_magic_worker->context); + } + } while(false); + + if(card_wiped) break; + + if(card_found_notified) { + nfc_magic_worker->callback( + NfcMagicWorkerEventNoCardDetected, nfc_magic_worker->context); + card_found_notified = false; + } } magic_deactivate(); } diff --git a/applications/external/nfc_magic/nfc_magic_worker.h b/applications/external/nfc_magic/nfc_magic_worker.h index 9d29bb3a8..51ff4ee43 100644 --- a/applications/external/nfc_magic/nfc_magic_worker.h +++ b/applications/external/nfc_magic/nfc_magic_worker.h @@ -1,6 +1,7 @@ #pragma once #include +#include "nfc_magic.h" typedef struct NfcMagicWorker NfcMagicWorker; @@ -9,6 +10,7 @@ typedef enum { NfcMagicWorkerStateCheck, NfcMagicWorkerStateWrite, + NfcMagicWorkerStateRekey, NfcMagicWorkerStateWipe, NfcMagicWorkerStateStop, @@ -33,6 +35,8 @@ void nfc_magic_worker_stop(NfcMagicWorker* nfc_magic_worker); void nfc_magic_worker_start( NfcMagicWorker* nfc_magic_worker, NfcMagicWorkerState state, + NfcMagicDevice* magic_dev, NfcDeviceData* dev_data, + uint32_t new_password, NfcMagicWorkerCallback callback, void* context); diff --git a/applications/external/nfc_magic/nfc_magic_worker_i.h b/applications/external/nfc_magic/nfc_magic_worker_i.h index 0cde2e712..a354f8047 100644 --- a/applications/external/nfc_magic/nfc_magic_worker_i.h +++ b/applications/external/nfc_magic/nfc_magic_worker_i.h @@ -3,11 +3,14 @@ #include #include "nfc_magic_worker.h" +#include "lib/magic/common.h" struct NfcMagicWorker { FuriThread* thread; + NfcMagicDevice* magic_dev; NfcDeviceData* dev_data; + uint32_t new_password; NfcMagicWorkerCallback callback; void* context; @@ -21,4 +24,6 @@ void nfc_magic_worker_check(NfcMagicWorker* nfc_magic_worker); void nfc_magic_worker_write(NfcMagicWorker* nfc_magic_worker); +void nfc_magic_worker_rekey(NfcMagicWorker* nfc_magic_worker); + void nfc_magic_worker_wipe(NfcMagicWorker* nfc_magic_worker); diff --git a/applications/external/nfc_magic/scenes/nfc_magic_scene_actions.c b/applications/external/nfc_magic/scenes/nfc_magic_scene_actions.c new file mode 100644 index 000000000..675262a9b --- /dev/null +++ b/applications/external/nfc_magic/scenes/nfc_magic_scene_actions.c @@ -0,0 +1,50 @@ +#include "../nfc_magic_i.h" +enum SubmenuIndex { + SubmenuIndexWrite, + SubmenuIndexWipe, +}; + +void nfc_magic_scene_actions_submenu_callback(void* context, uint32_t index) { + NfcMagic* nfc_magic = context; + view_dispatcher_send_custom_event(nfc_magic->view_dispatcher, index); +} + +void nfc_magic_scene_actions_on_enter(void* context) { + NfcMagic* nfc_magic = context; + + Submenu* submenu = nfc_magic->submenu; + submenu_add_item( + submenu, "Write", SubmenuIndexWrite, nfc_magic_scene_actions_submenu_callback, nfc_magic); + submenu_add_item( + submenu, "Wipe", SubmenuIndexWipe, nfc_magic_scene_actions_submenu_callback, nfc_magic); + + submenu_set_selected_item( + submenu, scene_manager_get_scene_state(nfc_magic->scene_manager, NfcMagicSceneActions)); + view_dispatcher_switch_to_view(nfc_magic->view_dispatcher, NfcMagicViewMenu); +} + +bool nfc_magic_scene_actions_on_event(void* context, SceneManagerEvent event) { + NfcMagic* nfc_magic = context; + bool consumed = false; + + if(event.type == SceneManagerEventTypeCustom) { + if(event.event == SubmenuIndexWrite) { + scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneFileSelect); + consumed = true; + } else if(event.event == SubmenuIndexWipe) { + scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneWipe); + consumed = true; + } + scene_manager_set_scene_state(nfc_magic->scene_manager, NfcMagicSceneActions, event.event); + } else if(event.type == SceneManagerEventTypeBack) { + consumed = scene_manager_search_and_switch_to_previous_scene( + nfc_magic->scene_manager, NfcMagicSceneStart); + } + + return consumed; +} + +void nfc_magic_scene_actions_on_exit(void* context) { + NfcMagic* nfc_magic = context; + submenu_reset(nfc_magic->submenu); +} diff --git a/applications/external/nfc_magic/scenes/nfc_magic_scene_check.c b/applications/external/nfc_magic/scenes/nfc_magic_scene_check.c index d51797242..90b43d7d3 100644 --- a/applications/external/nfc_magic/scenes/nfc_magic_scene_check.c +++ b/applications/external/nfc_magic/scenes/nfc_magic_scene_check.c @@ -42,7 +42,9 @@ void nfc_magic_scene_check_on_enter(void* context) { nfc_magic_worker_start( nfc_magic->worker, NfcMagicWorkerStateCheck, - &nfc_magic->nfc_dev->dev_data, + nfc_magic->dev, + &nfc_magic->source_dev->dev_data, + nfc_magic->new_password, nfc_magic_check_worker_callback, nfc_magic); nfc_magic_blink_start(nfc_magic); diff --git a/applications/external/nfc_magic/scenes/nfc_magic_scene_config.h b/applications/external/nfc_magic/scenes/nfc_magic_scene_config.h index 557e26914..2f9860d96 100644 --- a/applications/external/nfc_magic/scenes/nfc_magic_scene_config.h +++ b/applications/external/nfc_magic/scenes/nfc_magic_scene_config.h @@ -1,4 +1,8 @@ ADD_SCENE(nfc_magic, start, Start) +ADD_SCENE(nfc_magic, key_input, KeyInput) +ADD_SCENE(nfc_magic, actions, Actions) +ADD_SCENE(nfc_magic, gen4_actions, Gen4Actions) +ADD_SCENE(nfc_magic, new_key_input, NewKeyInput) ADD_SCENE(nfc_magic, file_select, FileSelect) ADD_SCENE(nfc_magic, write_confirm, WriteConfirm) ADD_SCENE(nfc_magic, wrong_card, WrongCard) @@ -8,5 +12,7 @@ ADD_SCENE(nfc_magic, success, Success) ADD_SCENE(nfc_magic, check, Check) ADD_SCENE(nfc_magic, not_magic, NotMagic) ADD_SCENE(nfc_magic, magic_info, MagicInfo) +ADD_SCENE(nfc_magic, rekey, Rekey) +ADD_SCENE(nfc_magic, rekey_fail, RekeyFail) ADD_SCENE(nfc_magic, wipe, Wipe) ADD_SCENE(nfc_magic, wipe_fail, WipeFail) diff --git a/applications/external/nfc_magic/scenes/nfc_magic_scene_file_select.c b/applications/external/nfc_magic/scenes/nfc_magic_scene_file_select.c index d78422eeb..baa6bcccc 100644 --- a/applications/external/nfc_magic/scenes/nfc_magic_scene_file_select.c +++ b/applications/external/nfc_magic/scenes/nfc_magic_scene_file_select.c @@ -1,22 +1,60 @@ #include "../nfc_magic_i.h" -static bool nfc_magic_scene_file_select_is_file_suitable(NfcDevice* nfc_dev) { - return (nfc_dev->format == NfcDeviceSaveFormatMifareClassic) && - (nfc_dev->dev_data.mf_classic_data.type == MfClassicType1k) && - (nfc_dev->dev_data.nfc_data.uid_len == 4); +static bool nfc_magic_scene_file_select_is_file_suitable(NfcMagic* nfc_magic) { + NfcDevice* nfc_dev = nfc_magic->source_dev; + if(nfc_dev->format == NfcDeviceSaveFormatMifareClassic) { + switch(nfc_magic->dev->type) { + case MagicTypeClassicGen1: + case MagicTypeClassicDirectWrite: + case MagicTypeClassicAPDU: + if((nfc_dev->dev_data.mf_classic_data.type != MfClassicType1k) || + (nfc_dev->dev_data.nfc_data.uid_len != 4)) { + return false; + } + return true; + + case MagicTypeGen4: + return true; + default: + return false; + } + } else if( + (nfc_dev->format == NfcDeviceSaveFormatMifareUl) && + (nfc_dev->dev_data.nfc_data.uid_len == 7)) { + switch(nfc_magic->dev->type) { + case MagicTypeUltralightGen1: + case MagicTypeUltralightDirectWrite: + case MagicTypeUltralightC_Gen1: + case MagicTypeUltralightC_DirectWrite: + case MagicTypeGen4: + switch(nfc_dev->dev_data.mf_ul_data.type) { + case MfUltralightTypeNTAGI2C1K: + case MfUltralightTypeNTAGI2C2K: + case MfUltralightTypeNTAGI2CPlus1K: + case MfUltralightTypeNTAGI2CPlus2K: + return false; + default: + return true; + } + default: + return false; + } + } + + return false; } void nfc_magic_scene_file_select_on_enter(void* context) { NfcMagic* nfc_magic = context; // Process file_select return - nfc_device_set_loading_callback(nfc_magic->nfc_dev, nfc_magic_show_loading_popup, nfc_magic); + nfc_device_set_loading_callback( + nfc_magic->source_dev, nfc_magic_show_loading_popup, nfc_magic); - if(!furi_string_size(nfc_magic->nfc_dev->load_path)) { - furi_string_set_str(nfc_magic->nfc_dev->load_path, NFC_APP_FOLDER); + if(!furi_string_size(nfc_magic->source_dev->load_path)) { + furi_string_set_str(nfc_magic->source_dev->load_path, NFC_APP_FOLDER); } - - if(nfc_file_select(nfc_magic->nfc_dev)) { - if(nfc_magic_scene_file_select_is_file_suitable(nfc_magic->nfc_dev)) { + if(nfc_file_select(nfc_magic->source_dev)) { + if(nfc_magic_scene_file_select_is_file_suitable(nfc_magic)) { scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneWriteConfirm); } else { scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneWrongCard); @@ -34,5 +72,5 @@ bool nfc_magic_scene_file_select_on_event(void* context, SceneManagerEvent event void nfc_magic_scene_file_select_on_exit(void* context) { NfcMagic* nfc_magic = context; - nfc_device_set_loading_callback(nfc_magic->nfc_dev, NULL, nfc_magic); + nfc_device_set_loading_callback(nfc_magic->source_dev, NULL, nfc_magic); } diff --git a/applications/external/nfc_magic/scenes/nfc_magic_scene_gen4_actions.c b/applications/external/nfc_magic/scenes/nfc_magic_scene_gen4_actions.c new file mode 100644 index 000000000..ceaa33e29 --- /dev/null +++ b/applications/external/nfc_magic/scenes/nfc_magic_scene_gen4_actions.c @@ -0,0 +1,70 @@ +#include "../nfc_magic_i.h" +enum SubmenuIndex { + SubmenuIndexWrite, + SubmenuIndexChangePassword, + SubmenuIndexWipe, +}; + +void nfc_magic_scene_gen4_actions_submenu_callback(void* context, uint32_t index) { + NfcMagic* nfc_magic = context; + view_dispatcher_send_custom_event(nfc_magic->view_dispatcher, index); +} + +void nfc_magic_scene_gen4_actions_on_enter(void* context) { + NfcMagic* nfc_magic = context; + + Submenu* submenu = nfc_magic->submenu; + submenu_add_item( + submenu, + "Write", + SubmenuIndexWrite, + nfc_magic_scene_gen4_actions_submenu_callback, + nfc_magic); + submenu_add_item( + submenu, + "Change password", + SubmenuIndexChangePassword, + nfc_magic_scene_gen4_actions_submenu_callback, + nfc_magic); + submenu_add_item( + submenu, + "Wipe", + SubmenuIndexWipe, + nfc_magic_scene_gen4_actions_submenu_callback, + nfc_magic); + + submenu_set_selected_item( + submenu, + scene_manager_get_scene_state(nfc_magic->scene_manager, NfcMagicSceneGen4Actions)); + view_dispatcher_switch_to_view(nfc_magic->view_dispatcher, NfcMagicViewMenu); +} + +bool nfc_magic_scene_gen4_actions_on_event(void* context, SceneManagerEvent event) { + NfcMagic* nfc_magic = context; + bool consumed = false; + + if(event.type == SceneManagerEventTypeCustom) { + if(event.event == SubmenuIndexWrite) { + scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneFileSelect); + consumed = true; + } else if(event.event == SubmenuIndexChangePassword) { + scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneNewKeyInput); + consumed = true; + } else if(event.event == SubmenuIndexWipe) { + scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneWipe); + consumed = true; + } + scene_manager_set_scene_state( + nfc_magic->scene_manager, NfcMagicSceneGen4Actions, event.event); + } else if(event.type == SceneManagerEventTypeBack) { + consumed = scene_manager_search_and_switch_to_previous_scene( + nfc_magic->scene_manager, NfcMagicSceneStart); + } + + return consumed; +} + +void nfc_magic_scene_gen4_actions_on_exit(void* context) { + NfcMagic* nfc_magic = context; + submenu_reset(nfc_magic->submenu); +} diff --git a/applications/external/nfc_magic/scenes/nfc_magic_scene_key_input.c b/applications/external/nfc_magic/scenes/nfc_magic_scene_key_input.c new file mode 100644 index 000000000..58b487a09 --- /dev/null +++ b/applications/external/nfc_magic/scenes/nfc_magic_scene_key_input.c @@ -0,0 +1,45 @@ +#include "../nfc_magic_i.h" + +void nfc_magic_scene_key_input_byte_input_callback(void* context) { + NfcMagic* nfc_magic = context; + + view_dispatcher_send_custom_event( + nfc_magic->view_dispatcher, NfcMagicCustomEventByteInputDone); +} + +void nfc_magic_scene_key_input_on_enter(void* context) { + NfcMagic* nfc_magic = context; + + // Setup view + ByteInput* byte_input = nfc_magic->byte_input; + byte_input_set_header_text(byte_input, "Enter the password in hex"); + byte_input_set_result_callback( + byte_input, + nfc_magic_scene_key_input_byte_input_callback, + NULL, + nfc_magic, + (uint8_t*)&nfc_magic->dev->password, + 4); + view_dispatcher_switch_to_view(nfc_magic->view_dispatcher, NfcMagicViewByteInput); +} + +bool nfc_magic_scene_key_input_on_event(void* context, SceneManagerEvent event) { + NfcMagic* nfc_magic = context; + bool consumed = false; + + if(event.type == SceneManagerEventTypeCustom) { + if(event.event == NfcMagicCustomEventByteInputDone) { + scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneCheck); + consumed = true; + } + } + return consumed; +} + +void nfc_magic_scene_key_input_on_exit(void* context) { + NfcMagic* nfc_magic = context; + + // Clear view + byte_input_set_result_callback(nfc_magic->byte_input, NULL, NULL, NULL, NULL, 0); + byte_input_set_header_text(nfc_magic->byte_input, ""); +} diff --git a/applications/external/nfc_magic/scenes/nfc_magic_scene_magic_info.c b/applications/external/nfc_magic/scenes/nfc_magic_scene_magic_info.c index e9b226b3a..c147ac438 100644 --- a/applications/external/nfc_magic/scenes/nfc_magic_scene_magic_info.c +++ b/applications/external/nfc_magic/scenes/nfc_magic_scene_magic_info.c @@ -1,4 +1,5 @@ #include "../nfc_magic_i.h" +#include "../lib/magic/types.h" void nfc_magic_scene_magic_info_widget_callback( GuiButtonType result, @@ -13,14 +14,18 @@ void nfc_magic_scene_magic_info_widget_callback( void nfc_magic_scene_magic_info_on_enter(void* context) { NfcMagic* nfc_magic = context; Widget* widget = nfc_magic->widget; + const char* card_type = nfc_magic_type(nfc_magic->dev->type); notification_message(nfc_magic->notifications, &sequence_success); widget_add_icon_element(widget, 73, 17, &I_DolphinCommon_56x48); widget_add_string_element( widget, 3, 4, AlignLeft, AlignTop, FontPrimary, "Magic card detected"); + widget_add_string_element(widget, 3, 17, AlignLeft, AlignTop, FontSecondary, card_type); widget_add_button_element( widget, GuiButtonTypeLeft, "Retry", nfc_magic_scene_magic_info_widget_callback, nfc_magic); + widget_add_button_element( + widget, GuiButtonTypeRight, "More", nfc_magic_scene_magic_info_widget_callback, nfc_magic); // Setup and start worker view_dispatcher_switch_to_view(nfc_magic->view_dispatcher, NfcMagicViewWidget); @@ -33,6 +38,15 @@ bool nfc_magic_scene_magic_info_on_event(void* context, SceneManagerEvent event) if(event.type == SceneManagerEventTypeCustom) { if(event.event == GuiButtonTypeLeft) { consumed = scene_manager_previous_scene(nfc_magic->scene_manager); + } else if(event.event == GuiButtonTypeRight) { + MagicType type = nfc_magic->dev->type; + if(type == MagicTypeGen4) { + scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneGen4Actions); + consumed = true; + } else { + scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneActions); + consumed = true; + } } } return consumed; diff --git a/applications/external/nfc_magic/scenes/nfc_magic_scene_new_key_input.c b/applications/external/nfc_magic/scenes/nfc_magic_scene_new_key_input.c new file mode 100644 index 000000000..b5247f6c5 --- /dev/null +++ b/applications/external/nfc_magic/scenes/nfc_magic_scene_new_key_input.c @@ -0,0 +1,45 @@ +#include "../nfc_magic_i.h" + +void nfc_magic_scene_new_key_input_byte_input_callback(void* context) { + NfcMagic* nfc_magic = context; + + view_dispatcher_send_custom_event( + nfc_magic->view_dispatcher, NfcMagicCustomEventByteInputDone); +} + +void nfc_magic_scene_new_key_input_on_enter(void* context) { + NfcMagic* nfc_magic = context; + + // Setup view + ByteInput* byte_input = nfc_magic->byte_input; + byte_input_set_header_text(byte_input, "Enter the password in hex"); + byte_input_set_result_callback( + byte_input, + nfc_magic_scene_new_key_input_byte_input_callback, + NULL, + nfc_magic, + (uint8_t*)&nfc_magic->new_password, + 4); + view_dispatcher_switch_to_view(nfc_magic->view_dispatcher, NfcMagicViewByteInput); +} + +bool nfc_magic_scene_new_key_input_on_event(void* context, SceneManagerEvent event) { + NfcMagic* nfc_magic = context; + bool consumed = false; + + if(event.type == SceneManagerEventTypeCustom) { + if(event.event == NfcMagicCustomEventByteInputDone) { + scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneRekey); + consumed = true; + } + } + return consumed; +} + +void nfc_magic_scene_new_key_input_on_exit(void* context) { + NfcMagic* nfc_magic = context; + + // Clear view + byte_input_set_result_callback(nfc_magic->byte_input, NULL, NULL, NULL, NULL, 0); + byte_input_set_header_text(nfc_magic->byte_input, ""); +} diff --git a/applications/external/nfc_magic/scenes/nfc_magic_scene_rekey.c b/applications/external/nfc_magic/scenes/nfc_magic_scene_rekey.c new file mode 100644 index 000000000..259dc78ea --- /dev/null +++ b/applications/external/nfc_magic/scenes/nfc_magic_scene_rekey.c @@ -0,0 +1,95 @@ +#include "../nfc_magic_i.h" + +enum { + NfcMagicSceneRekeyStateCardSearch, + NfcMagicSceneRekeyStateCardFound, +}; + +bool nfc_magic_rekey_worker_callback(NfcMagicWorkerEvent event, void* context) { + furi_assert(context); + + NfcMagic* nfc_magic = context; + view_dispatcher_send_custom_event(nfc_magic->view_dispatcher, event); + + return true; +} + +static void nfc_magic_scene_rekey_setup_view(NfcMagic* nfc_magic) { + Popup* popup = nfc_magic->popup; + popup_reset(popup); + uint32_t state = scene_manager_get_scene_state(nfc_magic->scene_manager, NfcMagicSceneRekey); + + if(state == NfcMagicSceneRekeyStateCardSearch) { + popup_set_text( + nfc_magic->popup, + "Apply the\nsame card\nto the back", + 128, + 32, + AlignRight, + AlignCenter); + popup_set_icon(nfc_magic->popup, 0, 8, &I_NFC_manual_60x50); + } else { + popup_set_icon(popup, 12, 23, &I_Loading_24); + popup_set_header(popup, "Writing\nDon't move...", 52, 32, AlignLeft, AlignCenter); + } + + view_dispatcher_switch_to_view(nfc_magic->view_dispatcher, NfcMagicViewPopup); +} + +void nfc_magic_scene_rekey_on_enter(void* context) { + NfcMagic* nfc_magic = context; + + scene_manager_set_scene_state( + nfc_magic->scene_manager, NfcMagicSceneRekey, NfcMagicSceneRekeyStateCardSearch); + nfc_magic_scene_rekey_setup_view(nfc_magic); + + // Setup and start worker + nfc_magic_worker_start( + nfc_magic->worker, + NfcMagicWorkerStateRekey, + nfc_magic->dev, + &nfc_magic->source_dev->dev_data, + nfc_magic->new_password, + nfc_magic_rekey_worker_callback, + nfc_magic); + nfc_magic_blink_start(nfc_magic); +} + +bool nfc_magic_scene_rekey_on_event(void* context, SceneManagerEvent event) { + NfcMagic* nfc_magic = context; + bool consumed = false; + + if(event.type == SceneManagerEventTypeCustom) { + if(event.event == NfcMagicWorkerEventSuccess) { + nfc_magic->dev->password = nfc_magic->new_password; + scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneSuccess); + consumed = true; + } else if(event.event == NfcMagicWorkerEventFail) { + scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneRekeyFail); + consumed = true; + } else if(event.event == NfcMagicWorkerEventCardDetected) { + scene_manager_set_scene_state( + nfc_magic->scene_manager, NfcMagicSceneRekey, NfcMagicSceneRekeyStateCardFound); + nfc_magic_scene_rekey_setup_view(nfc_magic); + consumed = true; + } else if(event.event == NfcMagicWorkerEventNoCardDetected) { + scene_manager_set_scene_state( + nfc_magic->scene_manager, NfcMagicSceneRekey, NfcMagicSceneRekeyStateCardSearch); + nfc_magic_scene_rekey_setup_view(nfc_magic); + consumed = true; + } + } + return consumed; +} + +void nfc_magic_scene_rekey_on_exit(void* context) { + NfcMagic* nfc_magic = context; + + nfc_magic_worker_stop(nfc_magic->worker); + scene_manager_set_scene_state( + nfc_magic->scene_manager, NfcMagicSceneRekey, NfcMagicSceneRekeyStateCardSearch); + // Clear view + popup_reset(nfc_magic->popup); + + nfc_magic_blink_stop(nfc_magic); +} diff --git a/applications/external/nfc_magic/scenes/nfc_magic_scene_rekey_fail.c b/applications/external/nfc_magic/scenes/nfc_magic_scene_rekey_fail.c new file mode 100644 index 000000000..d30ee57bc --- /dev/null +++ b/applications/external/nfc_magic/scenes/nfc_magic_scene_rekey_fail.c @@ -0,0 +1,50 @@ +#include "../nfc_magic_i.h" + +void nfc_magic_scene_rekey_fail_widget_callback( + GuiButtonType result, + InputType type, + void* context) { + NfcMagic* nfc_magic = context; + if(type == InputTypeShort) { + view_dispatcher_send_custom_event(nfc_magic->view_dispatcher, result); + } +} + +void nfc_magic_scene_rekey_fail_on_enter(void* context) { + NfcMagic* nfc_magic = context; + Widget* widget = nfc_magic->widget; + + notification_message(nfc_magic->notifications, &sequence_error); + + widget_add_icon_element(widget, 72, 17, &I_DolphinCommon_56x48); + widget_add_string_element( + widget, 7, 4, AlignLeft, AlignTop, FontPrimary, "Can't change password!"); + + widget_add_button_element( + widget, GuiButtonTypeLeft, "Finish", nfc_magic_scene_rekey_fail_widget_callback, nfc_magic); + + // Setup and start worker + view_dispatcher_switch_to_view(nfc_magic->view_dispatcher, NfcMagicViewWidget); +} + +bool nfc_magic_scene_rekey_fail_on_event(void* context, SceneManagerEvent event) { + NfcMagic* nfc_magic = context; + bool consumed = false; + + if(event.type == SceneManagerEventTypeCustom) { + if(event.event == GuiButtonTypeLeft) { + consumed = scene_manager_search_and_switch_to_previous_scene( + nfc_magic->scene_manager, NfcMagicSceneStart); + } + } else if(event.type == SceneManagerEventTypeBack) { + consumed = scene_manager_search_and_switch_to_previous_scene( + nfc_magic->scene_manager, NfcMagicSceneStart); + } + return consumed; +} + +void nfc_magic_scene_rekey_fail_on_exit(void* context) { + NfcMagic* nfc_magic = context; + + widget_reset(nfc_magic->widget); +} diff --git a/applications/external/nfc_magic/scenes/nfc_magic_scene_start.c b/applications/external/nfc_magic/scenes/nfc_magic_scene_start.c index a70eb8acc..b5861629e 100644 --- a/applications/external/nfc_magic/scenes/nfc_magic_scene_start.c +++ b/applications/external/nfc_magic/scenes/nfc_magic_scene_start.c @@ -1,8 +1,7 @@ #include "../nfc_magic_i.h" enum SubmenuIndex { SubmenuIndexCheck, - SubmenuIndexWriteGen1A, - SubmenuIndexWipe, + SubmenuIndexAuthenticateGen4, }; void nfc_magic_scene_start_submenu_callback(void* context, uint32_t index) { @@ -22,12 +21,10 @@ void nfc_magic_scene_start_on_enter(void* context) { nfc_magic); submenu_add_item( submenu, - "Write Gen1A", - SubmenuIndexWriteGen1A, + "Authenticate Gen4", + SubmenuIndexAuthenticateGen4, nfc_magic_scene_start_submenu_callback, nfc_magic); - submenu_add_item( - submenu, "Wipe", SubmenuIndexWipe, nfc_magic_scene_start_submenu_callback, nfc_magic); submenu_set_selected_item( submenu, scene_manager_get_scene_state(nfc_magic->scene_manager, NfcMagicSceneStart)); @@ -40,23 +37,13 @@ bool nfc_magic_scene_start_on_event(void* context, SceneManagerEvent event) { if(event.type == SceneManagerEventTypeCustom) { if(event.event == SubmenuIndexCheck) { + nfc_magic->dev->password = MAGIC_GEN4_DEFAULT_PWD; scene_manager_set_scene_state( nfc_magic->scene_manager, NfcMagicSceneStart, SubmenuIndexCheck); scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneCheck); consumed = true; - } else if(event.event == SubmenuIndexWriteGen1A) { - // Explicitly save state in each branch so that the - // correct option is reselected if the user cancels - // loading a file. - scene_manager_set_scene_state( - nfc_magic->scene_manager, NfcMagicSceneStart, SubmenuIndexWriteGen1A); - scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneFileSelect); - consumed = true; - } else if(event.event == SubmenuIndexWipe) { - scene_manager_set_scene_state( - nfc_magic->scene_manager, NfcMagicSceneStart, SubmenuIndexWipe); - scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneWipe); - consumed = true; + } else if(event.event == SubmenuIndexAuthenticateGen4) { + scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneKeyInput); } } diff --git a/applications/external/nfc_magic/scenes/nfc_magic_scene_wipe.c b/applications/external/nfc_magic/scenes/nfc_magic_scene_wipe.c index 1ca194286..29640f89c 100644 --- a/applications/external/nfc_magic/scenes/nfc_magic_scene_wipe.c +++ b/applications/external/nfc_magic/scenes/nfc_magic_scene_wipe.c @@ -22,7 +22,12 @@ static void nfc_magic_scene_wipe_setup_view(NfcMagic* nfc_magic) { if(state == NfcMagicSceneWipeStateCardSearch) { popup_set_icon(nfc_magic->popup, 0, 8, &I_NFC_manual_60x50); popup_set_text( - nfc_magic->popup, "Apply card to\nthe back", 128, 32, AlignRight, AlignCenter); + nfc_magic->popup, + "Apply the\nsame card\nto the back", + 128, + 32, + AlignRight, + AlignCenter); } else { popup_set_icon(popup, 12, 23, &I_Loading_24); popup_set_header(popup, "Wiping\nDon't move...", 52, 32, AlignLeft, AlignCenter); @@ -42,7 +47,9 @@ void nfc_magic_scene_wipe_on_enter(void* context) { nfc_magic_worker_start( nfc_magic->worker, NfcMagicWorkerStateWipe, - &nfc_magic->nfc_dev->dev_data, + nfc_magic->dev, + &nfc_magic->source_dev->dev_data, + nfc_magic->new_password, nfc_magic_wipe_worker_callback, nfc_magic); nfc_magic_blink_start(nfc_magic); diff --git a/applications/external/nfc_magic/scenes/nfc_magic_scene_write.c b/applications/external/nfc_magic/scenes/nfc_magic_scene_write.c index c3e6f962a..45c54557f 100644 --- a/applications/external/nfc_magic/scenes/nfc_magic_scene_write.c +++ b/applications/external/nfc_magic/scenes/nfc_magic_scene_write.c @@ -21,7 +21,12 @@ static void nfc_magic_scene_write_setup_view(NfcMagic* nfc_magic) { if(state == NfcMagicSceneWriteStateCardSearch) { popup_set_text( - nfc_magic->popup, "Apply card to\nthe back", 128, 32, AlignRight, AlignCenter); + nfc_magic->popup, + "Apply the\nsame card\nto the back", + 128, + 32, + AlignRight, + AlignCenter); popup_set_icon(nfc_magic->popup, 0, 8, &I_NFC_manual_60x50); } else { popup_set_icon(popup, 12, 23, &I_Loading_24); @@ -42,7 +47,9 @@ void nfc_magic_scene_write_on_enter(void* context) { nfc_magic_worker_start( nfc_magic->worker, NfcMagicWorkerStateWrite, - &nfc_magic->nfc_dev->dev_data, + nfc_magic->dev, + &nfc_magic->source_dev->dev_data, + nfc_magic->new_password, nfc_magic_write_worker_callback, nfc_magic); nfc_magic_blink_start(nfc_magic); diff --git a/applications/external/nfc_magic/scenes/nfc_magic_scene_wrong_card.c b/applications/external/nfc_magic/scenes/nfc_magic_scene_wrong_card.c index 4b8089693..857d50c1f 100644 --- a/applications/external/nfc_magic/scenes/nfc_magic_scene_wrong_card.c +++ b/applications/external/nfc_magic/scenes/nfc_magic_scene_wrong_card.c @@ -26,7 +26,7 @@ void nfc_magic_scene_wrong_card_on_enter(void* context) { AlignLeft, AlignTop, FontSecondary, - "Writing is supported\nonly for 4 bytes UID\nMifare Classic 1k"); + "Writing this file is\nnot supported for\nthis magic card."); widget_add_button_element( widget, GuiButtonTypeLeft, "Retry", nfc_magic_scene_wrong_card_widget_callback, nfc_magic); From 12f9b6a89e8a57b818c7139fb3ebb77ee0ac8a4e Mon Sep 17 00:00:00 2001 From: MX <10697207+xMasterX@users.noreply.github.com> Date: Fri, 26 May 2023 13:13:46 +0300 Subject: [PATCH 22/28] Apply desktop favourite apps refactoring --- .../services/desktop/desktop_settings.h | 2 - .../desktop/scenes/desktop_scene_main.c | 115 +++++-------- .../scenes/desktop_settings_scene_favorite.c | 162 ++++++++---------- 3 files changed, 109 insertions(+), 170 deletions(-) diff --git a/applications/services/desktop/desktop_settings.h b/applications/services/desktop/desktop_settings.h index fb63f26f5..5946873f0 100644 --- a/applications/services/desktop/desktop_settings.h +++ b/applications/services/desktop/desktop_settings.h @@ -43,8 +43,6 @@ #define DISPLAY_BATTERY_RETRO_5 4 #define DISPLAY_BATTERY_BAR_PERCENT 5 -#define FAP_LOADER_APP_NAME "Applications" - typedef struct { InputKey data[MAX_PIN_SIZE]; uint8_t length; diff --git a/applications/services/desktop/scenes/desktop_scene_main.c b/applications/services/desktop/scenes/desktop_scene_main.c index f504646bf..79f17fee7 100644 --- a/applications/services/desktop/scenes/desktop_scene_main.c +++ b/applications/services/desktop/scenes/desktop_scene_main.c @@ -12,6 +12,8 @@ #define TAG "DesktopSrv" +#define FAP_LOADER_APP_NAME "Applications" + static void desktop_scene_main_new_idle_animation_callback(void* context) { furi_assert(context); Desktop* desktop = context; @@ -60,6 +62,34 @@ static void desktop_switch_to_app(Desktop* desktop, const FlipperApplication* fl } #endif +static void desktop_scene_main_open_app_or_profile(Desktop* desktop, const char* path) { + do { + LoaderStatus status = loader_start(desktop->loader, FAP_LOADER_APP_NAME, path); + if(status == LoaderStatusOk) break; + FURI_LOG_E(TAG, "loader_start failed: %d", status); + + status = loader_start(desktop->loader, "Passport", NULL); + if(status != LoaderStatusOk) { + FURI_LOG_E(TAG, "loader_start failed: %d", status); + } + } while(false); +} + +static void desktop_scene_main_start_favorite(Desktop* desktop, FavoriteApp* application) { + LoaderStatus status = LoaderStatusErrorInternal; + if(application->is_external) { + status = loader_start(desktop->loader, FAP_LOADER_APP_NAME, application->name_or_path); + } else if(strlen(application->name_or_path) > 0) { + status = loader_start(desktop->loader, application->name_or_path, NULL); + } else { + status = loader_start(desktop->loader, FAP_LOADER_APP_NAME, NULL); + } + + if(status != LoaderStatusOk) { + FURI_LOG_E(TAG, "loader_start failed: %d", status); + } +} + void desktop_scene_main_callback(DesktopEvent event, void* context) { Desktop* desktop = (Desktop*)context; if(desktop->in_transition) return; @@ -130,59 +160,17 @@ bool desktop_scene_main_on_event(void* context, SceneManagerEvent event) { case DesktopMainEventOpenFavoritePrimary: DESKTOP_SETTINGS_LOAD(&desktop->settings); - if(desktop->settings.favorite_primary.is_external) { - LoaderStatus status = loader_start( - desktop->loader, - FAP_LOADER_APP_NAME, - desktop->settings.favorite_primary.name_or_path); - if(status != LoaderStatusOk) { - FURI_LOG_E(TAG, "loader_start failed: %d", status); - } - } else { - LoaderStatus status = loader_start( - desktop->loader, desktop->settings.favorite_primary.name_or_path, NULL); - if(status != LoaderStatusOk) { - FURI_LOG_E(TAG, "loader_start failed: %d", status); - } - } + desktop_scene_main_start_favorite(desktop, &desktop->settings.favorite_primary); consumed = true; break; case DesktopMainEventOpenFavoriteSecondary: DESKTOP_SETTINGS_LOAD(&desktop->settings); - if(desktop->settings.favorite_secondary.is_external) { - LoaderStatus status = loader_start( - desktop->loader, - FAP_LOADER_APP_NAME, - desktop->settings.favorite_secondary.name_or_path); - if(status != LoaderStatusOk) { - FURI_LOG_E(TAG, "loader_start failed: %d", status); - } - } else { - LoaderStatus status = loader_start( - desktop->loader, desktop->settings.favorite_secondary.name_or_path, NULL); - if(status != LoaderStatusOk) { - FURI_LOG_E(TAG, "loader_start failed: %d", status); - } - } + desktop_scene_main_start_favorite(desktop, &desktop->settings.favorite_secondary); consumed = true; break; case DesktopMainEventOpenFavoriteTertiary: DESKTOP_SETTINGS_LOAD(&desktop->settings); - if(desktop->settings.favorite_tertiary.is_external) { - LoaderStatus status = loader_start( - desktop->loader, - FAP_LOADER_APP_NAME, - desktop->settings.favorite_tertiary.name_or_path); - if(status != LoaderStatusOk) { - FURI_LOG_E(TAG, "loader_start failed: %d", status); - } - } else { - LoaderStatus status = loader_start( - desktop->loader, desktop->settings.favorite_tertiary.name_or_path, NULL); - if(status != LoaderStatusOk) { - FURI_LOG_E(TAG, "loader_start failed: %d", status); - } - } + desktop_scene_main_start_favorite(desktop, &desktop->settings.favorite_tertiary); consumed = true; break; case DesktopAnimationEventCheckAnimation: @@ -210,51 +198,28 @@ bool desktop_scene_main_on_event(void* context, SceneManagerEvent event) { break; } case DesktopMainEventOpenGameMenu: { - LoaderStatus status = loader_start( - desktop->loader, FAP_LOADER_APP_NAME, EXT_PATH("/apps/Games/Snake.fap")); - if(status != LoaderStatusOk) { - FURI_LOG_E(TAG, "loader_start failed: %d", status); - } + desktop_scene_main_open_app_or_profile(desktop, EXT_PATH("/apps/Games/Snake.fap")); break; } case DesktopMainEventOpenTetris: { - LoaderStatus status = loader_start( - desktop->loader, FAP_LOADER_APP_NAME, EXT_PATH("/apps/Games/Tetris.fap")); - if(status != LoaderStatusOk) { - FURI_LOG_E(TAG, "loader_start failed: %d", status); - } + desktop_scene_main_open_app_or_profile(desktop, EXT_PATH("/apps/Games/Tetris.fap")); break; } case DesktopMainEventOpenArkanoid: { - LoaderStatus status = loader_start( - desktop->loader, FAP_LOADER_APP_NAME, EXT_PATH("/apps/Games/Arkanoid.fap")); - if(status != LoaderStatusOk) { - FURI_LOG_E(TAG, "loader_start failed: %d", status); - } + desktop_scene_main_open_app_or_profile(desktop, EXT_PATH("/apps/Games/Arkanoid.fap")); break; } case DesktopMainEventOpenDOOM: { - LoaderStatus status = loader_start( - desktop->loader, FAP_LOADER_APP_NAME, EXT_PATH("/apps/Games/DOOM.fap")); - if(status != LoaderStatusOk) { - FURI_LOG_E(TAG, "loader_start failed: %d", status); - } + desktop_scene_main_open_app_or_profile(desktop, EXT_PATH("/apps/Games/DOOM.fap")); break; } case DesktopMainEventOpenZombiez: { - LoaderStatus status = loader_start( - desktop->loader, FAP_LOADER_APP_NAME, EXT_PATH("/apps/Games/Zombiez.fap")); - if(status != LoaderStatusOk) { - FURI_LOG_E(TAG, "loader_start failed: %d", status); - } + desktop_scene_main_open_app_or_profile(desktop, EXT_PATH("/apps/Games/Zombiez.fap")); break; } case DesktopMainEventOpenHeap: { - LoaderStatus status = loader_start( - desktop->loader, FAP_LOADER_APP_NAME, EXT_PATH("/apps/Games/heap_defence.fap")); - if(status != LoaderStatusOk) { - FURI_LOG_E(TAG, "loader_start failed: %d", status); - } + desktop_scene_main_open_app_or_profile( + desktop, EXT_PATH("/apps/Games/heap_defence.fap")); break; } case DesktopLockedEventUpdate: diff --git a/applications/settings/desktop_settings/scenes/desktop_settings_scene_favorite.c b/applications/settings/desktop_settings/scenes/desktop_settings_scene_favorite.c index c014c97f7..25bab6dd6 100644 --- a/applications/settings/desktop_settings/scenes/desktop_settings_scene_favorite.c +++ b/applications/settings/desktop_settings/scenes/desktop_settings_scene_favorite.c @@ -5,6 +5,9 @@ #include #include +#define EXTERNAL_APPLICATION_NAME ("[External Application]") +#define EXTERNAL_APPLICATION_INDEX (FLIPPER_APPS_COUNT + 1) + static bool favorite_fap_selector_item_callback( FuriString* file_path, void* context, @@ -44,6 +47,20 @@ void desktop_settings_scene_favorite_on_enter(void* context) { uint32_t primary_favorite = scene_manager_get_scene_state(app->scene_manager, DesktopSettingsAppSceneFavorite); uint32_t pre_select_item = 0; + FavoriteApp* curr_favorite_app = NULL; + if(primary_favorite == 0) { + curr_favorite_app = &app->settings.favorite_primary; + } else if(primary_favorite == 1) { + curr_favorite_app = &app->settings.favorite_secondary; + } else if(primary_favorite == 2) { + curr_favorite_app = &app->settings.favorite_tertiary; + } else { + curr_favorite_app = &app->settings.favorite_primary; + } + if(curr_favorite_app == NULL) { + // This should not happen! + return; + } for(size_t i = 0; i < FLIPPER_APPS_COUNT; i++) { submenu_add_item( @@ -53,30 +70,29 @@ void desktop_settings_scene_favorite_on_enter(void* context) { desktop_settings_scene_favorite_submenu_callback, app); - if(primary_favorite == 0) { // Select favorite item in submenu - if((app->settings.favorite_primary.is_external && - !strcmp(FLIPPER_APPS[i].name, FAP_LOADER_APP_NAME)) || - (!strcmp(FLIPPER_APPS[i].name, app->settings.favorite_primary.name_or_path))) { - pre_select_item = i; - } - } else if(primary_favorite == 1) { - if((app->settings.favorite_secondary.is_external && - !strcmp(FLIPPER_APPS[i].name, FAP_LOADER_APP_NAME)) || - (!strcmp(FLIPPER_APPS[i].name, app->settings.favorite_secondary.name_or_path))) { - pre_select_item = i; - } - } else if(primary_favorite == 2) { - if((app->settings.favorite_tertiary.is_external && - !strcmp(FLIPPER_APPS[i].name, FAP_LOADER_APP_NAME)) || - (!strcmp(FLIPPER_APPS[i].name, app->settings.favorite_tertiary.name_or_path))) { - pre_select_item = i; - } + // Select favorite item in submenu + if(!curr_favorite_app->is_external && + !strcmp(FLIPPER_APPS[i].name, curr_favorite_app->name_or_path)) { + pre_select_item = i; } } + +#ifdef APP_FAP_LOADER + submenu_add_item( + submenu, + EXTERNAL_APPLICATION_NAME, + EXTERNAL_APPLICATION_INDEX, + desktop_settings_scene_favorite_submenu_callback, + app); + if(curr_favorite_app->is_external) { + pre_select_item = EXTERNAL_APPLICATION_INDEX; + } +#endif + submenu_add_item( submenu, "None (disable)", - FLIPPER_APPS_COUNT + 1, + FLIPPER_APPS_COUNT + 2, desktop_settings_scene_favorite_submenu_callback, app); @@ -99,46 +115,24 @@ bool desktop_settings_scene_favorite_on_event(void* context, SceneManagerEvent e uint32_t primary_favorite = scene_manager_get_scene_state(app->scene_manager, DesktopSettingsAppSceneFavorite); + FavoriteApp* curr_favorite_app = NULL; + if(primary_favorite == 0) { + curr_favorite_app = &app->settings.favorite_primary; + } else if(primary_favorite == 1) { + curr_favorite_app = &app->settings.favorite_secondary; + } else if(primary_favorite == 2) { + curr_favorite_app = &app->settings.favorite_tertiary; + } else { + curr_favorite_app = &app->settings.favorite_primary; + } + if(curr_favorite_app == NULL) { + // This should not happen! + furi_string_free(temp_path); + return consumed; + } if(event.type == SceneManagerEventTypeCustom) { - if(event.event >= (FLIPPER_APPS_COUNT + 1)) { - if(primary_favorite == 0) { - app->settings.favorite_primary.is_external = false; - strncpy(app->settings.favorite_primary.name_or_path, "", MAX_APP_LENGTH); - } else if(primary_favorite == 1) { - app->settings.favorite_secondary.is_external = false; - strncpy(app->settings.favorite_secondary.name_or_path, "", MAX_APP_LENGTH); - } else if(primary_favorite == 2) { - app->settings.favorite_tertiary.is_external = false; - strncpy(app->settings.favorite_tertiary.name_or_path, "", MAX_APP_LENGTH); - } - - scene_manager_previous_scene(app->scene_manager); - consumed = true; - furi_string_free(temp_path); - return consumed; - } - if(strcmp(FLIPPER_APPS[event.event].name, FAP_LOADER_APP_NAME) != 0) { - if(primary_favorite == 0) { - app->settings.favorite_primary.is_external = false; - strncpy( - app->settings.favorite_primary.name_or_path, - FLIPPER_APPS[event.event].name, - MAX_APP_LENGTH); - } else if(primary_favorite == 1) { - app->settings.favorite_secondary.is_external = false; - strncpy( - app->settings.favorite_secondary.name_or_path, - FLIPPER_APPS[event.event].name, - MAX_APP_LENGTH); - } else if(primary_favorite == 2) { - app->settings.favorite_tertiary.is_external = false; - strncpy( - app->settings.favorite_tertiary.name_or_path, - FLIPPER_APPS[event.event].name, - MAX_APP_LENGTH); - } - } else { + if(event.event == EXTERNAL_APPLICATION_INDEX) { const DialogsFileBrowserOptions browser_options = { .extension = ".fap", .icon = &I_unknown_10px, @@ -149,47 +143,29 @@ bool desktop_settings_scene_favorite_on_event(void* context, SceneManagerEvent e .base_path = EXT_PATH("apps"), }; - if(primary_favorite == 0) { // Select favorite fap in file browser - if(favorite_fap_selector_file_exists( - app->settings.favorite_primary.name_or_path)) { - furi_string_set_str(temp_path, app->settings.favorite_primary.name_or_path); - } - } else if(primary_favorite == 1) { - if(favorite_fap_selector_file_exists( - app->settings.favorite_secondary.name_or_path)) { - furi_string_set_str(temp_path, app->settings.favorite_secondary.name_or_path); - } - } else if(primary_favorite == 2) { - if(favorite_fap_selector_file_exists( - app->settings.favorite_tertiary.name_or_path)) { - furi_string_set_str(temp_path, app->settings.favorite_tertiary.name_or_path); - } + // Select favorite fap in file browser + if(favorite_fap_selector_file_exists(curr_favorite_app->name_or_path)) { + furi_string_set_str(temp_path, curr_favorite_app->name_or_path); } - submenu_reset(app->submenu); if(dialog_file_browser_show(app->dialogs, temp_path, temp_path, &browser_options)) { - if(primary_favorite == 0) { - app->settings.favorite_primary.is_external = true; - strncpy( - app->settings.favorite_primary.name_or_path, - furi_string_get_cstr(temp_path), - MAX_APP_LENGTH); - } else if(primary_favorite == 1) { - app->settings.favorite_secondary.is_external = true; - strncpy( - app->settings.favorite_secondary.name_or_path, - furi_string_get_cstr(temp_path), - MAX_APP_LENGTH); - } else if(primary_favorite == 2) { - app->settings.favorite_tertiary.is_external = true; - strncpy( - app->settings.favorite_tertiary.name_or_path, - furi_string_get_cstr(temp_path), - MAX_APP_LENGTH); - } + submenu_reset(app->submenu); // Prevent menu from being shown when we exiting scene + curr_favorite_app->is_external = true; + strncpy( + curr_favorite_app->name_or_path, + furi_string_get_cstr(temp_path), + MAX_APP_LENGTH); + consumed = true; } + } else { + curr_favorite_app->is_external = false; + strncpy( + curr_favorite_app->name_or_path, FLIPPER_APPS[event.event].name, MAX_APP_LENGTH); + consumed = true; } - scene_manager_previous_scene(app->scene_manager); + if(consumed) { + scene_manager_previous_scene(app->scene_manager); + }; consumed = true; } From 24ad48d3908194c92aa20dc139f76cb3feb0ac46 Mon Sep 17 00:00:00 2001 From: MX <10697207+xMasterX@users.noreply.github.com> Date: Fri, 26 May 2023 13:22:06 +0300 Subject: [PATCH 23/28] Update TOTP --- .../totp/ui/fonts/712serif/712serif.c | 940 +++++++++++++ .../totp/ui/fonts/712serif/712serif.h | 8 + .../external/totp/ui/fonts/active_font.h | 27 + .../totp/ui/fonts/bedstead/bedstead.c | 1056 +++++++++++++++ .../totp/ui/fonts/bedstead/bedstead.h | 8 + .../totp/ui/fonts/graph35pix/graph35pix.c | 940 +++++++++++++ .../totp/ui/fonts/graph35pix/graph35pix.h | 8 + .../totp/ui/fonts/karma_future/karma_future.c | 1172 +++++++++++++++++ .../totp/ui/fonts/karma_future/karma_future.h | 8 + .../{mode-nine => mode_nine}/mode_nine.c | 0 .../{mode-nine => mode_nine}/mode_nine.h | 0 .../totp/ui/fonts/redhat_mono/redhat_mono.c | 1057 +++++++++++++++ .../totp/ui/fonts/redhat_mono/redhat_mono.h | 8 + .../external/totp/ui/fonts/zector/zector.c | 1056 +++++++++++++++ .../external/totp/ui/fonts/zector/zector.h | 8 + .../ui/scenes/add_new_token/totp_input_text.c | 2 +- .../add_new_token/totp_scene_add_new_token.c | 144 +- .../scenes/app_settings/totp_app_settings.c | 215 +-- .../authenticate/totp_scene_authenticate.c | 79 +- .../totp_scene_generate_token.c | 107 +- .../scenes/token_menu/totp_scene_token_menu.c | 81 +- .../generate_totp_code/generate_totp_code.c | 15 +- .../external/totp/workers/type_code_common.c | 7 +- 23 files changed, 6631 insertions(+), 315 deletions(-) create mode 100644 applications/external/totp/ui/fonts/712serif/712serif.c create mode 100644 applications/external/totp/ui/fonts/712serif/712serif.h create mode 100644 applications/external/totp/ui/fonts/active_font.h create mode 100644 applications/external/totp/ui/fonts/bedstead/bedstead.c create mode 100644 applications/external/totp/ui/fonts/bedstead/bedstead.h create mode 100644 applications/external/totp/ui/fonts/graph35pix/graph35pix.c create mode 100644 applications/external/totp/ui/fonts/graph35pix/graph35pix.h create mode 100644 applications/external/totp/ui/fonts/karma_future/karma_future.c create mode 100644 applications/external/totp/ui/fonts/karma_future/karma_future.h rename applications/external/totp/ui/fonts/{mode-nine => mode_nine}/mode_nine.c (100%) rename applications/external/totp/ui/fonts/{mode-nine => mode_nine}/mode_nine.h (100%) create mode 100644 applications/external/totp/ui/fonts/redhat_mono/redhat_mono.c create mode 100644 applications/external/totp/ui/fonts/redhat_mono/redhat_mono.h create mode 100644 applications/external/totp/ui/fonts/zector/zector.c create mode 100644 applications/external/totp/ui/fonts/zector/zector.h diff --git a/applications/external/totp/ui/fonts/712serif/712serif.c b/applications/external/totp/ui/fonts/712serif/712serif.c new file mode 100644 index 000000000..0fe73378c --- /dev/null +++ b/applications/external/totp/ui/fonts/712serif/712serif.c @@ -0,0 +1,940 @@ +#include "712serif.h" + +/* GENERATED BY https://github.com/pavius/the-dot-factory */ + +/* +** Font data for 7:12 Serif 24pt +*/ + +/* Character bitmaps for 7:12 Serif 24pt */ +const uint8_t _712Serif_24ptBitmaps[] = { + /* @0 '-' (14 pixels wide) */ + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xFC, + 0x0F, + 0xFC, + 0x0F, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + + /* @28 '0' (14 pixels wide) */ + 0xF0, + 0x03, + 0xF0, + 0x03, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0xF0, + 0x03, + 0xF0, + 0x03, + + /* @56 '1' (14 pixels wide) */ + 0xC0, + 0x00, + 0xC0, + 0x00, + 0xFC, + 0x00, + 0xFC, + 0x00, + 0xC0, + 0x00, + 0xC0, + 0x00, + 0xC0, + 0x00, + 0xC0, + 0x00, + 0xC0, + 0x00, + 0xC0, + 0x00, + 0xC0, + 0x00, + 0xC0, + 0x00, + 0xFC, + 0x0F, + 0xFC, + 0x0F, + + /* @84 '2' (14 pixels wide) */ + 0xF0, + 0x03, + 0xF0, + 0x03, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x00, + 0x0C, + 0x00, + 0x0C, + 0xC0, + 0x03, + 0xC0, + 0x03, + 0x30, + 0x00, + 0x30, + 0x00, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0xFC, + 0x0F, + 0xFC, + 0x0F, + + /* @112 '3' (14 pixels wide) */ + 0xF0, + 0x03, + 0xF0, + 0x03, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x00, + 0x0C, + 0x00, + 0x0C, + 0xC0, + 0x03, + 0xC0, + 0x03, + 0x00, + 0x0C, + 0x00, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0xF0, + 0x03, + 0xF0, + 0x03, + + /* @140 '4' (14 pixels wide) */ + 0x30, + 0x03, + 0x30, + 0x03, + 0x30, + 0x03, + 0x30, + 0x03, + 0x0C, + 0x03, + 0x0C, + 0x03, + 0x0C, + 0x03, + 0x0C, + 0x03, + 0xFC, + 0x0F, + 0xFC, + 0x0F, + 0x00, + 0x03, + 0x00, + 0x03, + 0xC0, + 0x0F, + 0xC0, + 0x0F, + + /* @168 '5' (14 pixels wide) */ + 0xFC, + 0x0F, + 0xFC, + 0x0F, + 0x0C, + 0x00, + 0x0C, + 0x00, + 0xFC, + 0x03, + 0xFC, + 0x03, + 0x00, + 0x0C, + 0x00, + 0x0C, + 0x00, + 0x0C, + 0x00, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0xF0, + 0x03, + 0xF0, + 0x03, + + /* @196 '6' (14 pixels wide) */ + 0xF0, + 0x03, + 0xF0, + 0x03, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x00, + 0x0C, + 0x00, + 0xFC, + 0x03, + 0xFC, + 0x03, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0xF0, + 0x03, + 0xF0, + 0x03, + + /* @224 '7' (14 pixels wide) */ + 0xFC, + 0x0F, + 0xFC, + 0x0F, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x00, + 0x03, + 0x00, + 0x03, + 0x00, + 0x03, + 0x00, + 0x03, + 0xC0, + 0x00, + 0xC0, + 0x00, + 0xC0, + 0x00, + 0xC0, + 0x00, + 0xC0, + 0x00, + 0xC0, + 0x00, + + /* @252 '8' (14 pixels wide) */ + 0xF0, + 0x03, + 0xF0, + 0x03, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0xF0, + 0x03, + 0xF0, + 0x03, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0xF0, + 0x03, + 0xF0, + 0x03, + + /* @280 '9' (14 pixels wide) */ + 0xF0, + 0x03, + 0xF0, + 0x03, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0xF0, + 0x0F, + 0xF0, + 0x0F, + 0x00, + 0x0C, + 0x00, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0xF0, + 0x03, + 0xF0, + 0x03, + + /* @308 'B' (14 pixels wide) */ + 0xFF, + 0x00, + 0xFF, + 0x00, + 0x0C, + 0x03, + 0x0C, + 0x03, + 0x0C, + 0x03, + 0x0C, + 0x03, + 0xFC, + 0x0F, + 0xFC, + 0x0F, + 0x0C, + 0x30, + 0x0C, + 0x30, + 0x0C, + 0x30, + 0x0C, + 0x30, + 0xFF, + 0x0F, + 0xFF, + 0x0F, + + /* @336 'C' (14 pixels wide) */ + 0xF0, + 0x33, + 0xF0, + 0x33, + 0x0C, + 0x3C, + 0x0C, + 0x3C, + 0x03, + 0x00, + 0x03, + 0x00, + 0x03, + 0x00, + 0x03, + 0x00, + 0x03, + 0x30, + 0x03, + 0x30, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0xF0, + 0x03, + 0xF0, + 0x03, + + /* @364 'D' (14 pixels wide) */ + 0xFF, + 0x03, + 0xFF, + 0x03, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x30, + 0x0C, + 0x30, + 0x0C, + 0x30, + 0x0C, + 0x30, + 0x0C, + 0x30, + 0x0C, + 0x30, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0xFF, + 0x03, + 0xFF, + 0x03, + + /* @392 'F' (14 pixels wide) */ + 0xFF, + 0x3F, + 0xFF, + 0x3F, + 0x0C, + 0x30, + 0x0C, + 0x30, + 0x0C, + 0x03, + 0x0C, + 0x03, + 0xFC, + 0x03, + 0xFC, + 0x03, + 0x0C, + 0x03, + 0x0C, + 0x03, + 0x0C, + 0x00, + 0x0C, + 0x00, + 0x3F, + 0x00, + 0x3F, + 0x00, + + /* @420 'G' (14 pixels wide) */ + 0xF0, + 0x33, + 0xF0, + 0x33, + 0x0C, + 0x3C, + 0x0C, + 0x3C, + 0x03, + 0x00, + 0x03, + 0x00, + 0x03, + 0x3F, + 0x03, + 0x3F, + 0x03, + 0x30, + 0x03, + 0x30, + 0x0C, + 0x3C, + 0x0C, + 0x3C, + 0xF0, + 0x33, + 0xF0, + 0x33, + + /* @448 'H' (14 pixels wide) */ + 0x3F, + 0x3F, + 0x3F, + 0x3F, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0xFC, + 0x0F, + 0xFC, + 0x0F, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x3F, + 0x3F, + 0x3F, + 0x3F, + + /* @476 'J' (14 pixels wide) */ + 0x00, + 0x3F, + 0x00, + 0x3F, + 0x00, + 0x0C, + 0x00, + 0x0C, + 0x00, + 0x0C, + 0x00, + 0x0C, + 0x00, + 0x0C, + 0x00, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0xF0, + 0x03, + 0xF0, + 0x03, + + /* @504 'K' (14 pixels wide) */ + 0x3F, + 0x3F, + 0x3F, + 0x3F, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x03, + 0x0C, + 0x03, + 0xFC, + 0x00, + 0xFC, + 0x00, + 0x0C, + 0x03, + 0x0C, + 0x03, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x3F, + 0x3F, + 0x3F, + 0x3F, + + /* @532 'M' (14 pixels wide) */ + 0x0F, + 0x3C, + 0x0F, + 0x3C, + 0x3C, + 0x0F, + 0x3C, + 0x0F, + 0xCC, + 0x0C, + 0xCC, + 0x0C, + 0xCC, + 0x0C, + 0xCC, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x3F, + 0x3F, + 0x3F, + 0x3F, + + /* @560 'N' (14 pixels wide) */ + 0x0F, + 0x3F, + 0x0F, + 0x3F, + 0x3C, + 0x0C, + 0x3C, + 0x0C, + 0xCC, + 0x0C, + 0xCC, + 0x0C, + 0xCC, + 0x0C, + 0xCC, + 0x0C, + 0xCC, + 0x0C, + 0xCC, + 0x0C, + 0x0C, + 0x0F, + 0x0C, + 0x0F, + 0x3F, + 0x0C, + 0x3F, + 0x0C, + + /* @588 'P' (14 pixels wide) */ + 0xFF, + 0x0F, + 0xFF, + 0x0F, + 0x0C, + 0x30, + 0x0C, + 0x30, + 0x0C, + 0x30, + 0x0C, + 0x30, + 0x3C, + 0x30, + 0x3C, + 0x30, + 0xCC, + 0x0F, + 0xCC, + 0x0F, + 0x0C, + 0x00, + 0x0C, + 0x00, + 0x3F, + 0x00, + 0x3F, + 0x00, + + /* @616 'Q' (14 pixels wide) */ + 0xF0, + 0x03, + 0xF0, + 0x03, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x03, + 0x30, + 0x03, + 0x30, + 0xF3, + 0x30, + 0xF3, + 0x30, + 0x03, + 0x33, + 0x03, + 0x33, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0xF0, + 0x33, + 0xF0, + 0x33, + + /* @644 'R' (14 pixels wide) */ + 0xFF, + 0x0F, + 0xFF, + 0x0F, + 0x0C, + 0x30, + 0x0C, + 0x30, + 0x0C, + 0x30, + 0x0C, + 0x30, + 0xFC, + 0x0F, + 0xFC, + 0x0F, + 0x0C, + 0x03, + 0x0C, + 0x03, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x3F, + 0x3F, + 0x3F, + 0x3F, + + /* @672 'T' (14 pixels wide) */ + 0xFF, + 0x3F, + 0xFF, + 0x3F, + 0xC3, + 0x30, + 0xC3, + 0x30, + 0xC0, + 0x00, + 0xC0, + 0x00, + 0xC0, + 0x00, + 0xC0, + 0x00, + 0xC0, + 0x00, + 0xC0, + 0x00, + 0xC0, + 0x00, + 0xC0, + 0x00, + 0xF0, + 0x03, + 0xF0, + 0x03, + + /* @700 'V' (14 pixels wide) */ + 0x3F, + 0x3F, + 0x3F, + 0x3F, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x30, + 0x03, + 0x30, + 0x03, + 0x30, + 0x03, + 0x30, + 0x03, + 0xC0, + 0x00, + 0xC0, + 0x00, + + /* @728 'W' (14 pixels wide) */ + 0x3F, + 0x3F, + 0x3F, + 0x3F, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0xCC, + 0x0C, + 0xCC, + 0x0C, + 0xCC, + 0x0C, + 0xCC, + 0x0C, + 0x30, + 0x03, + 0x30, + 0x03, + 0x30, + 0x03, + 0x30, + 0x03, + + /* @756 'X' (14 pixels wide) */ + 0x3F, + 0x3F, + 0x3F, + 0x3F, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x30, + 0x03, + 0x30, + 0x03, + 0xC0, + 0x00, + 0xC0, + 0x00, + 0x30, + 0x03, + 0x30, + 0x03, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x3F, + 0x3F, + 0x3F, + 0x3F, + + /* @784 'Y' (14 pixels wide) */ + 0x3F, + 0x3F, + 0x3F, + 0x3F, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x30, + 0x03, + 0x30, + 0x03, + 0xC0, + 0x00, + 0xC0, + 0x00, + 0xC0, + 0x00, + 0xC0, + 0x00, + 0xC0, + 0x00, + 0xC0, + 0x00, + 0xF0, + 0x03, + 0xF0, + 0x03, +}; + +/* Character descriptors for 7:12 Serif 24pt */ +/* { [Char width in bits], [Offset into _712Serif_24ptCharBitmaps in bytes] } */ +const FONT_CHAR_INFO _712Serif_24ptDescriptors[] = { + {14, 0}, /* - */ + {0, 0}, /* . */ + {0, 0}, /* / */ + {14, 28}, /* 0 */ + {14, 56}, /* 1 */ + {14, 84}, /* 2 */ + {14, 112}, /* 3 */ + {14, 140}, /* 4 */ + {14, 168}, /* 5 */ + {14, 196}, /* 6 */ + {14, 224}, /* 7 */ + {14, 252}, /* 8 */ + {14, 280}, /* 9 */ + {0, 0}, /* : */ + {0, 0}, /* ; */ + {0, 0}, /* < */ + {0, 0}, /* = */ + {0, 0}, /* > */ + {0, 0}, /* ? */ + {0, 0}, /* @ */ + {0, 0}, /* A */ + {14, 308}, /* B */ + {14, 336}, /* C */ + {14, 364}, /* D */ + {0, 0}, /* E */ + {14, 392}, /* F */ + {14, 420}, /* G */ + {14, 448}, /* H */ + {0, 0}, /* I */ + {14, 476}, /* J */ + {14, 504}, /* K */ + {0, 0}, /* L */ + {14, 532}, /* M */ + {14, 560}, /* N */ + {0, 0}, /* O */ + {14, 588}, /* P */ + {14, 616}, /* Q */ + {14, 644}, /* R */ + {0, 0}, /* S */ + {14, 672}, /* T */ + {0, 0}, /* U */ + {14, 700}, /* V */ + {14, 728}, /* W */ + {14, 756}, /* X */ + {14, 784}, /* Y */ +}; + +/* Font information for 7:12 Serif 24pt */ +const FONT_INFO _712Serif_24ptFontInfo = { + 14, /* Character height */ + '-', /* Start character */ + 'Y', /* End character */ + 2, /* Width, in pixels, of space character */ + _712Serif_24ptDescriptors, /* Character descriptor array */ + _712Serif_24ptBitmaps, /* Character bitmap array */ +}; diff --git a/applications/external/totp/ui/fonts/712serif/712serif.h b/applications/external/totp/ui/fonts/712serif/712serif.h new file mode 100644 index 000000000..81959064d --- /dev/null +++ b/applications/external/totp/ui/fonts/712serif/712serif.h @@ -0,0 +1,8 @@ +#pragma once + +/* GENERATED BY https://github.com/pavius/the-dot-factory */ + +#include "../font_info.h" + +/* Font data for 7:12 Serif 24pt */ +extern const FONT_INFO _712Serif_24ptFontInfo; diff --git a/applications/external/totp/ui/fonts/active_font.h b/applications/external/totp/ui/fonts/active_font.h new file mode 100644 index 000000000..58c1e2d17 --- /dev/null +++ b/applications/external/totp/ui/fonts/active_font.h @@ -0,0 +1,27 @@ +#pragma once + +#include "../../features_config.h" +#include "font_info.h" + +#if TOTP_FONT == TOTP_FONT_MODENINE +#include "mode_nine/mode_nine.h" +#define TOTP_CODE_FONT_INFO modeNine_15ptFontInfo +#elif TOTP_FONT == TOTP_FONT_REDHATMONO +#include "redhat_mono/redhat_mono.h" +#define TOTP_CODE_FONT_INFO redHatMono_16ptFontInfo +#elif TOTP_FONT == TOTP_FONT_BEDSTEAD +#include "bedstead/bedstead.h" +#define TOTP_CODE_FONT_INFO bedstead_17ptFontInfo +#elif TOTP_FONT == TOTP_FONT_ZECTOR +#include "zector/zector.h" +#define TOTP_CODE_FONT_INFO zector_18ptFontInfo +#elif TOTP_FONT == TOTP_FONT_712SERIF +#include "712serif/712serif.h" +#define TOTP_CODE_FONT_INFO _712Serif_24ptFontInfo +#elif TOTP_FONT == TOTP_FONT_GRAPH35PIX +#include "graph35pix/graph35pix.h" +#define TOTP_CODE_FONT_INFO graph35pix_12ptFontInfo +#elif TOTP_FONT == TOTP_FONT_KARMAFUTURE +#include "karma_future/karma_future.h" +#define TOTP_CODE_FONT_INFO karmaFuture_14ptFontInfo +#endif \ No newline at end of file diff --git a/applications/external/totp/ui/fonts/bedstead/bedstead.c b/applications/external/totp/ui/fonts/bedstead/bedstead.c new file mode 100644 index 000000000..ec6680fab --- /dev/null +++ b/applications/external/totp/ui/fonts/bedstead/bedstead.c @@ -0,0 +1,1056 @@ +#include "bedstead.h" + +/* GENERATED BY https://github.com/pavius/the-dot-factory */ + +/* +** Font data for Bedstead 17pt +*/ + +/* Character bitmaps for Bedstead 17pt */ +const uint8_t bedstead_17ptBitmaps[] = { + /* @0 '-' (13 pixels wide) */ + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xF8, + 0x07, + 0xF8, + 0x07, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + + /* @32 '0' (13 pixels wide) */ + 0xE0, + 0x00, + 0xF0, + 0x01, + 0xF8, + 0x03, + 0xBC, + 0x07, + 0x1E, + 0x0F, + 0x0F, + 0x1E, + 0x07, + 0x1C, + 0x07, + 0x1C, + 0x07, + 0x1C, + 0x07, + 0x1C, + 0x0F, + 0x1E, + 0x1E, + 0x0F, + 0xBC, + 0x07, + 0xF8, + 0x03, + 0xF0, + 0x01, + 0xE0, + 0x00, + + /* @64 '1' (13 pixels wide) */ + 0xE0, + 0x00, + 0xE0, + 0x00, + 0xF8, + 0x00, + 0xF8, + 0x00, + 0xE0, + 0x00, + 0xE0, + 0x00, + 0xE0, + 0x00, + 0xE0, + 0x00, + 0xE0, + 0x00, + 0xE0, + 0x00, + 0xE0, + 0x00, + 0xE0, + 0x00, + 0xE0, + 0x00, + 0xE0, + 0x00, + 0xF8, + 0x03, + 0xF8, + 0x03, + + /* @96 '2' (13 pixels wide) */ + 0xF0, + 0x07, + 0xFC, + 0x0F, + 0x1E, + 0x1E, + 0x1E, + 0x1C, + 0x0E, + 0x1C, + 0x00, + 0x1C, + 0x00, + 0x1E, + 0xC0, + 0x0F, + 0xE0, + 0x07, + 0xF0, + 0x00, + 0x7C, + 0x00, + 0x3E, + 0x00, + 0x1E, + 0x00, + 0x0E, + 0x00, + 0xFE, + 0x1F, + 0xFE, + 0x1F, + + /* @128 '3' (13 pixels wide) */ + 0xFE, + 0x1F, + 0xFE, + 0x1F, + 0x00, + 0x1C, + 0x00, + 0x1E, + 0x00, + 0x0F, + 0x00, + 0x0F, + 0x00, + 0x07, + 0xE0, + 0x07, + 0xE0, + 0x0F, + 0x00, + 0x1E, + 0x00, + 0x1C, + 0x0E, + 0x1C, + 0x1E, + 0x1C, + 0x3E, + 0x0E, + 0xFC, + 0x0F, + 0xF8, + 0x07, + + /* @160 '4' (13 pixels wide) */ + 0x80, + 0x03, + 0x80, + 0x03, + 0xE0, + 0x03, + 0xF0, + 0x03, + 0xF8, + 0x03, + 0xBC, + 0x03, + 0x9E, + 0x03, + 0x8F, + 0x03, + 0x87, + 0x03, + 0xFF, + 0x0F, + 0xFF, + 0x0F, + 0x80, + 0x03, + 0x80, + 0x03, + 0x80, + 0x03, + 0x80, + 0x03, + 0x80, + 0x03, + + /* @192 '5' (13 pixels wide) */ + 0xFF, + 0x1F, + 0xFF, + 0x1F, + 0x07, + 0x00, + 0x07, + 0x00, + 0xFF, + 0x07, + 0xFF, + 0x0F, + 0x00, + 0x1E, + 0x00, + 0x1C, + 0x00, + 0x1C, + 0x00, + 0x1C, + 0x00, + 0x1C, + 0x07, + 0x1C, + 0x0F, + 0x1E, + 0xFE, + 0x0F, + 0xFC, + 0x07, + 0xFC, + 0x07, + + /* @224 '6' (13 pixels wide) */ + 0xE0, + 0x07, + 0xF0, + 0x07, + 0x78, + 0x00, + 0x3C, + 0x00, + 0x1E, + 0x00, + 0x0F, + 0x00, + 0x07, + 0x00, + 0xFF, + 0x07, + 0xFF, + 0x0F, + 0x07, + 0x1E, + 0x07, + 0x1C, + 0x07, + 0x1C, + 0x0F, + 0x1E, + 0x1E, + 0x0F, + 0xFE, + 0x0F, + 0xFC, + 0x07, + + /* @256 '7' (13 pixels wide) */ + 0xFE, + 0x1F, + 0xFE, + 0x1F, + 0x00, + 0x1C, + 0x00, + 0x1E, + 0x00, + 0x0F, + 0x80, + 0x07, + 0xC0, + 0x03, + 0xE0, + 0x01, + 0xF0, + 0x00, + 0x78, + 0x00, + 0x38, + 0x00, + 0x38, + 0x00, + 0x38, + 0x00, + 0x38, + 0x00, + 0x38, + 0x00, + 0x38, + 0x00, + + /* @288 '8' (13 pixels wide) */ + 0xFC, + 0x07, + 0xFE, + 0x0F, + 0x0F, + 0x1E, + 0x07, + 0x1C, + 0x07, + 0x1C, + 0x07, + 0x1C, + 0x0F, + 0x1E, + 0xFE, + 0x0F, + 0xFE, + 0x0F, + 0x0F, + 0x1E, + 0x07, + 0x1C, + 0x07, + 0x1C, + 0x0F, + 0x1E, + 0x1E, + 0x0F, + 0xFE, + 0x0F, + 0xFC, + 0x07, + + /* @320 '9' (13 pixels wide) */ + 0xFC, + 0x07, + 0xFE, + 0x0F, + 0x0F, + 0x1E, + 0x07, + 0x1C, + 0x07, + 0x1C, + 0x07, + 0x1C, + 0x0F, + 0x1C, + 0xFE, + 0x1F, + 0xFC, + 0x1F, + 0x00, + 0x1C, + 0x00, + 0x1E, + 0x00, + 0x0F, + 0x80, + 0x07, + 0xC0, + 0x03, + 0xFC, + 0x01, + 0xFC, + 0x00, + + /* @352 'B' (13 pixels wide) */ + 0xFF, + 0x07, + 0xFF, + 0x0F, + 0x07, + 0x1E, + 0x07, + 0x1C, + 0x07, + 0x1C, + 0x07, + 0x1C, + 0x07, + 0x1E, + 0xFF, + 0x0F, + 0xFF, + 0x0F, + 0x07, + 0x1E, + 0x07, + 0x1C, + 0x07, + 0x1C, + 0x07, + 0x1E, + 0x07, + 0x0F, + 0xFF, + 0x0F, + 0xFF, + 0x07, + + /* @384 'C' (13 pixels wide) */ + 0xFC, + 0x01, + 0xFE, + 0x07, + 0x0F, + 0x0F, + 0x07, + 0x0F, + 0x07, + 0x0E, + 0x07, + 0x00, + 0x07, + 0x00, + 0x07, + 0x00, + 0x07, + 0x00, + 0x07, + 0x00, + 0x07, + 0x00, + 0x07, + 0x00, + 0x07, + 0x0F, + 0x8F, + 0x0F, + 0xFE, + 0x07, + 0xFC, + 0x03, + + /* @416 'D' (13 pixels wide) */ + 0xFF, + 0x07, + 0xFF, + 0x0F, + 0x07, + 0x1E, + 0x07, + 0x1C, + 0x07, + 0x1C, + 0x07, + 0x1C, + 0x07, + 0x1C, + 0x07, + 0x1C, + 0x07, + 0x1C, + 0x07, + 0x1C, + 0x07, + 0x1C, + 0x07, + 0x1C, + 0x07, + 0x1E, + 0x07, + 0x0F, + 0xFF, + 0x0F, + 0xFF, + 0x07, + + /* @448 'F' (13 pixels wide) */ + 0xFF, + 0x0F, + 0xFF, + 0x0F, + 0x07, + 0x00, + 0x07, + 0x00, + 0x07, + 0x00, + 0x07, + 0x00, + 0x07, + 0x00, + 0xFF, + 0x03, + 0xFF, + 0x03, + 0x07, + 0x00, + 0x07, + 0x00, + 0x07, + 0x00, + 0x07, + 0x00, + 0x07, + 0x00, + 0x07, + 0x00, + 0x07, + 0x00, + + /* @480 'G' (13 pixels wide) */ + 0xFC, + 0x07, + 0xFE, + 0x0F, + 0x0F, + 0x1F, + 0x0F, + 0x1E, + 0x07, + 0x1C, + 0x07, + 0x00, + 0x07, + 0x00, + 0x07, + 0x00, + 0x07, + 0x00, + 0x87, + 0x1F, + 0x87, + 0x1F, + 0x07, + 0x1C, + 0x0F, + 0x1C, + 0xFE, + 0x1F, + 0xFC, + 0x1F, + 0xFC, + 0x1F, + + /* @512 'H' (13 pixels wide) */ + 0x07, + 0x1C, + 0x07, + 0x1C, + 0x07, + 0x1C, + 0x07, + 0x1C, + 0x07, + 0x1C, + 0x07, + 0x1C, + 0x07, + 0x1C, + 0xFF, + 0x1F, + 0xFF, + 0x1F, + 0x07, + 0x1C, + 0x07, + 0x1C, + 0x07, + 0x1C, + 0x07, + 0x1C, + 0x07, + 0x1C, + 0x07, + 0x1C, + 0x07, + 0x1C, + + /* @544 'J' (13 pixels wide) */ + 0x00, + 0x1C, + 0x00, + 0x1C, + 0x00, + 0x1C, + 0x00, + 0x1C, + 0x00, + 0x1C, + 0x00, + 0x1C, + 0x00, + 0x1C, + 0x00, + 0x1C, + 0x00, + 0x1C, + 0x00, + 0x1C, + 0x00, + 0x1C, + 0x0E, + 0x1C, + 0x1E, + 0x1C, + 0x3E, + 0x1E, + 0xFC, + 0x0F, + 0xF8, + 0x07, + + /* @576 'K' (13 pixels wide) */ + 0x07, + 0x0E, + 0x07, + 0x0F, + 0x87, + 0x07, + 0xC7, + 0x03, + 0xE7, + 0x01, + 0xF7, + 0x00, + 0x7F, + 0x00, + 0x3F, + 0x00, + 0x3F, + 0x00, + 0x7F, + 0x00, + 0xF7, + 0x00, + 0xE7, + 0x01, + 0xC7, + 0x03, + 0x87, + 0x07, + 0x07, + 0x0F, + 0x07, + 0x0E, + + /* @608 'M' (13 pixels wide) */ + 0x07, + 0x1C, + 0x07, + 0x1C, + 0xBF, + 0x1F, + 0xFF, + 0x1F, + 0xFF, + 0x1F, + 0xE7, + 0x1C, + 0xE7, + 0x1C, + 0xE7, + 0x1C, + 0xE7, + 0x1C, + 0x07, + 0x1C, + 0x07, + 0x1C, + 0x07, + 0x1C, + 0x07, + 0x1C, + 0x07, + 0x1C, + 0x07, + 0x1C, + 0x07, + 0x1C, + + /* @640 'N' (13 pixels wide) */ + 0x07, + 0x1C, + 0x07, + 0x1C, + 0x07, + 0x1C, + 0x07, + 0x1C, + 0x07, + 0x1C, + 0x3F, + 0x1C, + 0x7F, + 0x1C, + 0xFF, + 0x1C, + 0xE7, + 0x1F, + 0xC7, + 0x1F, + 0x87, + 0x1F, + 0x07, + 0x1C, + 0x07, + 0x1C, + 0x07, + 0x1C, + 0x07, + 0x1C, + 0x07, + 0x1C, + + /* @672 'P' (13 pixels wide) */ + 0xFF, + 0x07, + 0xFF, + 0x0F, + 0x07, + 0x1E, + 0x07, + 0x1C, + 0x07, + 0x1C, + 0x07, + 0x1C, + 0x07, + 0x1E, + 0xFF, + 0x0F, + 0xFF, + 0x07, + 0x07, + 0x00, + 0x07, + 0x00, + 0x07, + 0x00, + 0x07, + 0x00, + 0x07, + 0x00, + 0x07, + 0x00, + 0x07, + 0x00, + + /* @704 'Q' (13 pixels wide) */ + 0xFC, + 0x07, + 0xFE, + 0x0F, + 0x0F, + 0x1E, + 0x07, + 0x1C, + 0x07, + 0x1C, + 0x07, + 0x1C, + 0x07, + 0x1C, + 0x07, + 0x1C, + 0x07, + 0x1C, + 0xE7, + 0x1C, + 0xE7, + 0x1F, + 0xC7, + 0x0F, + 0x8F, + 0x07, + 0xDE, + 0x0F, + 0xFE, + 0x1F, + 0xFC, + 0x1C, + + /* @736 'R' (13 pixels wide) */ + 0xFF, + 0x07, + 0xFF, + 0x0F, + 0x07, + 0x1E, + 0x07, + 0x1C, + 0x07, + 0x1C, + 0x07, + 0x1C, + 0x07, + 0x1E, + 0xFF, + 0x0F, + 0xFF, + 0x07, + 0xE7, + 0x00, + 0xE7, + 0x01, + 0xC7, + 0x03, + 0x87, + 0x07, + 0x07, + 0x0F, + 0x07, + 0x1E, + 0x07, + 0x1C, + + /* @768 'T' (13 pixels wide) */ + 0xFF, + 0x1F, + 0xFF, + 0x1F, + 0xE0, + 0x00, + 0xE0, + 0x00, + 0xE0, + 0x00, + 0xE0, + 0x00, + 0xE0, + 0x00, + 0xE0, + 0x00, + 0xE0, + 0x00, + 0xE0, + 0x00, + 0xE0, + 0x00, + 0xE0, + 0x00, + 0xE0, + 0x00, + 0xE0, + 0x00, + 0xE0, + 0x00, + 0xE0, + 0x00, + + /* @800 'V' (13 pixels wide) */ + 0x07, + 0x1C, + 0x07, + 0x1C, + 0x07, + 0x1C, + 0x07, + 0x1C, + 0x07, + 0x1C, + 0x07, + 0x1C, + 0x1F, + 0x1F, + 0xBC, + 0x07, + 0xB8, + 0x03, + 0xB8, + 0x03, + 0xF8, + 0x07, + 0xF0, + 0x03, + 0xE0, + 0x01, + 0xE0, + 0x00, + 0xE0, + 0x00, + 0xE0, + 0x00, + + /* @832 'W' (13 pixels wide) */ + 0x07, + 0x1C, + 0x07, + 0x1C, + 0x07, + 0x1C, + 0x07, + 0x1C, + 0x07, + 0x1C, + 0x07, + 0x1C, + 0x07, + 0x1C, + 0xE7, + 0x1C, + 0xE7, + 0x1C, + 0xE7, + 0x1C, + 0xE7, + 0x1C, + 0xE7, + 0x1C, + 0xFF, + 0x1F, + 0xFE, + 0x0F, + 0xFE, + 0x0F, + 0xBC, + 0x07, + + /* @864 'X' (13 pixels wide) */ + 0x07, + 0x1C, + 0x07, + 0x1C, + 0x07, + 0x1C, + 0x0F, + 0x1E, + 0x1E, + 0x0F, + 0xBC, + 0x07, + 0xF8, + 0x03, + 0xF0, + 0x01, + 0xF0, + 0x01, + 0xF8, + 0x03, + 0xBC, + 0x07, + 0x1E, + 0x0F, + 0x0F, + 0x1E, + 0x07, + 0x1C, + 0x07, + 0x1C, + 0x07, + 0x1C, + + /* @896 'Y' (13 pixels wide) */ + 0x07, + 0x1C, + 0x07, + 0x1C, + 0x07, + 0x1C, + 0x0F, + 0x1E, + 0x1E, + 0x0F, + 0xBC, + 0x07, + 0xF8, + 0x03, + 0xF0, + 0x01, + 0xE0, + 0x00, + 0xE0, + 0x00, + 0xE0, + 0x00, + 0xE0, + 0x00, + 0xE0, + 0x00, + 0xE0, + 0x00, + 0xE0, + 0x00, + 0xE0, + 0x00, +}; + +/* Character descriptors for Bedstead 17pt */ +/* { [Char width in bits], [Offset into bedstead_17ptCharBitmaps in bytes] } */ +const FONT_CHAR_INFO bedstead_17ptDescriptors[] = { + {13, 0}, /* - */ + {0, 0}, /* . */ + {0, 0}, /* / */ + {13, 32}, /* 0 */ + {13, 64}, /* 1 */ + {13, 96}, /* 2 */ + {13, 128}, /* 3 */ + {13, 160}, /* 4 */ + {13, 192}, /* 5 */ + {13, 224}, /* 6 */ + {13, 256}, /* 7 */ + {13, 288}, /* 8 */ + {13, 320}, /* 9 */ + {0, 0}, /* : */ + {0, 0}, /* ; */ + {0, 0}, /* < */ + {0, 0}, /* = */ + {0, 0}, /* > */ + {0, 0}, /* ? */ + {0, 0}, /* @ */ + {0, 0}, /* A */ + {13, 352}, /* B */ + {13, 384}, /* C */ + {13, 416}, /* D */ + {0, 0}, /* E */ + {13, 448}, /* F */ + {13, 480}, /* G */ + {13, 512}, /* H */ + {0, 0}, /* I */ + {13, 544}, /* J */ + {13, 576}, /* K */ + {0, 0}, /* L */ + {13, 608}, /* M */ + {13, 640}, /* N */ + {0, 0}, /* O */ + {13, 672}, /* P */ + {13, 704}, /* Q */ + {13, 736}, /* R */ + {0, 0}, /* S */ + {13, 768}, /* T */ + {0, 0}, /* U */ + {13, 800}, /* V */ + {13, 832}, /* W */ + {13, 864}, /* X */ + {13, 896}, /* Y */ +}; + +/* Font information for Bedstead 17pt */ +const FONT_INFO bedstead_17ptFontInfo = { + 16, /* Character height */ + '-', /* Start character */ + 'Y', /* End character */ + 2, /* Width, in pixels, of space character */ + bedstead_17ptDescriptors, /* Character descriptor array */ + bedstead_17ptBitmaps, /* Character bitmap array */ +}; diff --git a/applications/external/totp/ui/fonts/bedstead/bedstead.h b/applications/external/totp/ui/fonts/bedstead/bedstead.h new file mode 100644 index 000000000..0f4c10949 --- /dev/null +++ b/applications/external/totp/ui/fonts/bedstead/bedstead.h @@ -0,0 +1,8 @@ +#pragma once + +/* GENERATED BY https://github.com/pavius/the-dot-factory */ + +#include "../font_info.h" + +/* Font data for Bedstead 17pt */ +extern const FONT_INFO bedstead_17ptFontInfo; diff --git a/applications/external/totp/ui/fonts/graph35pix/graph35pix.c b/applications/external/totp/ui/fonts/graph35pix/graph35pix.c new file mode 100644 index 000000000..fd93d4de9 --- /dev/null +++ b/applications/external/totp/ui/fonts/graph35pix/graph35pix.c @@ -0,0 +1,940 @@ +#include "graph35pix.h" + +/* GENERATED BY https://github.com/pavius/the-dot-factory */ + +/* +** Font data for Graph 35+ pix 12pt +*/ + +/* Character bitmaps for Graph 35+ pix 12pt */ +const uint8_t graph35pix_12ptBitmaps[] = { + /* @0 '-' (10 pixels wide) */ + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xFF, + 0x03, + 0xFF, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + + /* @28 '0' (10 pixels wide) */ + 0xFC, + 0x00, + 0xFC, + 0x00, + 0x03, + 0x03, + 0x03, + 0x03, + 0xC3, + 0x03, + 0xC3, + 0x03, + 0x33, + 0x03, + 0x33, + 0x03, + 0x0F, + 0x03, + 0x0F, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0xFC, + 0x00, + 0xFC, + 0x00, + + /* @56 '1' (10 pixels wide) */ + 0x30, + 0x00, + 0x30, + 0x00, + 0x3C, + 0x00, + 0x3C, + 0x00, + 0x30, + 0x00, + 0x30, + 0x00, + 0x30, + 0x00, + 0x30, + 0x00, + 0x30, + 0x00, + 0x30, + 0x00, + 0x30, + 0x00, + 0x30, + 0x00, + 0xFC, + 0x00, + 0xFC, + 0x00, + + /* @84 '2' (10 pixels wide) */ + 0xFC, + 0x00, + 0xFC, + 0x00, + 0x03, + 0x03, + 0x03, + 0x03, + 0x00, + 0x03, + 0x00, + 0x03, + 0xC0, + 0x00, + 0xC0, + 0x00, + 0x30, + 0x00, + 0x30, + 0x00, + 0x0C, + 0x00, + 0x0C, + 0x00, + 0xFF, + 0x03, + 0xFF, + 0x03, + + /* @112 '3' (10 pixels wide) */ + 0xFF, + 0x03, + 0xFF, + 0x03, + 0xC0, + 0x00, + 0xC0, + 0x00, + 0x30, + 0x00, + 0x30, + 0x00, + 0xC0, + 0x00, + 0xC0, + 0x00, + 0x00, + 0x03, + 0x00, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0xFC, + 0x00, + 0xFC, + 0x00, + + /* @140 '4' (10 pixels wide) */ + 0xC0, + 0x00, + 0xC0, + 0x00, + 0xF0, + 0x00, + 0xF0, + 0x00, + 0xCC, + 0x00, + 0xCC, + 0x00, + 0xC3, + 0x00, + 0xC3, + 0x00, + 0xFF, + 0x03, + 0xFF, + 0x03, + 0xC0, + 0x00, + 0xC0, + 0x00, + 0xC0, + 0x00, + 0xC0, + 0x00, + + /* @168 '5' (10 pixels wide) */ + 0xFF, + 0x03, + 0xFF, + 0x03, + 0x03, + 0x00, + 0x03, + 0x00, + 0xFF, + 0x00, + 0xFF, + 0x00, + 0x00, + 0x03, + 0x00, + 0x03, + 0x00, + 0x03, + 0x00, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0xFC, + 0x00, + 0xFC, + 0x00, + + /* @196 '6' (10 pixels wide) */ + 0xF0, + 0x00, + 0xF0, + 0x00, + 0x0C, + 0x00, + 0x0C, + 0x00, + 0x03, + 0x00, + 0x03, + 0x00, + 0xFF, + 0x00, + 0xFF, + 0x00, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0xFC, + 0x00, + 0xFC, + 0x00, + + /* @224 '7' (10 pixels wide) */ + 0xFF, + 0x03, + 0xFF, + 0x03, + 0x00, + 0x03, + 0x00, + 0x03, + 0xC0, + 0x00, + 0xC0, + 0x00, + 0x30, + 0x00, + 0x30, + 0x00, + 0x30, + 0x00, + 0x30, + 0x00, + 0x30, + 0x00, + 0x30, + 0x00, + 0x30, + 0x00, + 0x30, + 0x00, + + /* @252 '8' (10 pixels wide) */ + 0xFC, + 0x00, + 0xFC, + 0x00, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0xFC, + 0x00, + 0xFC, + 0x00, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0xFC, + 0x00, + 0xFC, + 0x00, + + /* @280 '9' (10 pixels wide) */ + 0xFC, + 0x00, + 0xFC, + 0x00, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0xFC, + 0x03, + 0xFC, + 0x03, + 0x00, + 0x03, + 0x00, + 0x03, + 0xC0, + 0x00, + 0xC0, + 0x00, + 0x3C, + 0x00, + 0x3C, + 0x00, + + /* @308 'B' (10 pixels wide) */ + 0xFF, + 0x00, + 0xFF, + 0x00, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0xFF, + 0x00, + 0xFF, + 0x00, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0xFF, + 0x00, + 0xFF, + 0x00, + + /* @336 'C' (10 pixels wide) */ + 0xFC, + 0x00, + 0xFC, + 0x00, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x00, + 0x03, + 0x00, + 0x03, + 0x00, + 0x03, + 0x00, + 0x03, + 0x00, + 0x03, + 0x00, + 0x03, + 0x03, + 0x03, + 0x03, + 0xFC, + 0x00, + 0xFC, + 0x00, + + /* @364 'D' (10 pixels wide) */ + 0x3F, + 0x00, + 0x3F, + 0x00, + 0xC3, + 0x00, + 0xC3, + 0x00, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0xC3, + 0x00, + 0xC3, + 0x00, + 0x3F, + 0x00, + 0x3F, + 0x00, + + /* @392 'F' (10 pixels wide) */ + 0xFF, + 0x03, + 0xFF, + 0x03, + 0x03, + 0x00, + 0x03, + 0x00, + 0x03, + 0x00, + 0x03, + 0x00, + 0xFF, + 0x00, + 0xFF, + 0x00, + 0x03, + 0x00, + 0x03, + 0x00, + 0x03, + 0x00, + 0x03, + 0x00, + 0x03, + 0x00, + 0x03, + 0x00, + + /* @420 'G' (10 pixels wide) */ + 0xFC, + 0x00, + 0xFC, + 0x00, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x00, + 0x03, + 0x00, + 0xF3, + 0x03, + 0xF3, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0xFC, + 0x03, + 0xFC, + 0x03, + + /* @448 'H' (10 pixels wide) */ + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0xFF, + 0x03, + 0xFF, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + + /* @476 'J' (10 pixels wide) */ + 0xF0, + 0x03, + 0xF0, + 0x03, + 0xC0, + 0x00, + 0xC0, + 0x00, + 0xC0, + 0x00, + 0xC0, + 0x00, + 0xC0, + 0x00, + 0xC0, + 0x00, + 0xC0, + 0x00, + 0xC0, + 0x00, + 0xC3, + 0x00, + 0xC3, + 0x00, + 0x3C, + 0x00, + 0x3C, + 0x00, + + /* @504 'K' (10 pixels wide) */ + 0x03, + 0x03, + 0x03, + 0x03, + 0xC3, + 0x00, + 0xC3, + 0x00, + 0x33, + 0x00, + 0x33, + 0x00, + 0x0F, + 0x00, + 0x0F, + 0x00, + 0x33, + 0x00, + 0x33, + 0x00, + 0xC3, + 0x00, + 0xC3, + 0x00, + 0x03, + 0x03, + 0x03, + 0x03, + + /* @532 'M' (10 pixels wide) */ + 0x03, + 0x03, + 0x03, + 0x03, + 0xCF, + 0x03, + 0xCF, + 0x03, + 0x33, + 0x03, + 0x33, + 0x03, + 0x33, + 0x03, + 0x33, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + + /* @560 'N' (10 pixels wide) */ + 0x03, + 0x03, + 0x03, + 0x03, + 0x0F, + 0x03, + 0x0F, + 0x03, + 0x0F, + 0x03, + 0x0F, + 0x03, + 0x33, + 0x03, + 0x33, + 0x03, + 0xC3, + 0x03, + 0xC3, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + + /* @588 'P' (10 pixels wide) */ + 0xFF, + 0x00, + 0xFF, + 0x00, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0xFF, + 0x00, + 0xFF, + 0x00, + 0x03, + 0x00, + 0x03, + 0x00, + 0x03, + 0x00, + 0x03, + 0x00, + 0x03, + 0x00, + 0x03, + 0x00, + + /* @616 'Q' (10 pixels wide) */ + 0xFC, + 0x00, + 0xFC, + 0x00, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x33, + 0x03, + 0x33, + 0x03, + 0xC3, + 0x00, + 0xC3, + 0x00, + 0x3C, + 0x03, + 0x3C, + 0x03, + + /* @644 'R' (10 pixels wide) */ + 0xFF, + 0x00, + 0xFF, + 0x00, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0xFF, + 0x00, + 0xFF, + 0x00, + 0x33, + 0x00, + 0x33, + 0x00, + 0xC3, + 0x00, + 0xC3, + 0x00, + 0x03, + 0x03, + 0x03, + 0x03, + + /* @672 'T' (10 pixels wide) */ + 0xFF, + 0x03, + 0xFF, + 0x03, + 0x30, + 0x00, + 0x30, + 0x00, + 0x30, + 0x00, + 0x30, + 0x00, + 0x30, + 0x00, + 0x30, + 0x00, + 0x30, + 0x00, + 0x30, + 0x00, + 0x30, + 0x00, + 0x30, + 0x00, + 0x30, + 0x00, + 0x30, + 0x00, + + /* @700 'V' (10 pixels wide) */ + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0xCC, + 0x00, + 0xCC, + 0x00, + 0x30, + 0x00, + 0x30, + 0x00, + + /* @728 'W' (10 pixels wide) */ + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x33, + 0x03, + 0x33, + 0x03, + 0x33, + 0x03, + 0x33, + 0x03, + 0x33, + 0x03, + 0x33, + 0x03, + 0xCC, + 0x00, + 0xCC, + 0x00, + + /* @756 'X' (10 pixels wide) */ + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0xCC, + 0x00, + 0xCC, + 0x00, + 0x30, + 0x00, + 0x30, + 0x00, + 0xCC, + 0x00, + 0xCC, + 0x00, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + + /* @784 'Y' (10 pixels wide) */ + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0xCC, + 0x00, + 0xCC, + 0x00, + 0x30, + 0x00, + 0x30, + 0x00, + 0x30, + 0x00, + 0x30, + 0x00, + 0x30, + 0x00, + 0x30, + 0x00, +}; + +/* Character descriptors for Graph 35+ pix 12pt */ +/* { [Char width in bits], [Offset into graph35pix_12ptCharBitmaps in bytes] } */ +const FONT_CHAR_INFO graph35pix_12ptDescriptors[] = { + {10, 0}, /* - */ + {0, 0}, /* . */ + {0, 0}, /* / */ + {10, 28}, /* 0 */ + {10, 56}, /* 1 */ + {10, 84}, /* 2 */ + {10, 112}, /* 3 */ + {10, 140}, /* 4 */ + {10, 168}, /* 5 */ + {10, 196}, /* 6 */ + {10, 224}, /* 7 */ + {10, 252}, /* 8 */ + {10, 280}, /* 9 */ + {0, 0}, /* : */ + {0, 0}, /* ; */ + {0, 0}, /* < */ + {0, 0}, /* = */ + {0, 0}, /* > */ + {0, 0}, /* ? */ + {0, 0}, /* @ */ + {0, 0}, /* A */ + {10, 308}, /* B */ + {10, 336}, /* C */ + {10, 364}, /* D */ + {0, 0}, /* E */ + {10, 392}, /* F */ + {10, 420}, /* G */ + {10, 448}, /* H */ + {0, 0}, /* I */ + {10, 476}, /* J */ + {10, 504}, /* K */ + {0, 0}, /* L */ + {10, 532}, /* M */ + {10, 560}, /* N */ + {0, 0}, /* O */ + {10, 588}, /* P */ + {10, 616}, /* Q */ + {10, 644}, /* R */ + {0, 0}, /* S */ + {10, 672}, /* T */ + {0, 0}, /* U */ + {10, 700}, /* V */ + {10, 728}, /* W */ + {10, 756}, /* X */ + {10, 784}, /* Y */ +}; + +/* Font information for Graph 35+ pix 12pt */ +const FONT_INFO graph35pix_12ptFontInfo = { + 14, /* Character height */ + '-', /* Start character */ + 'Y', /* End character */ + 2, /* Width, in pixels, of space character */ + graph35pix_12ptDescriptors, /* Character descriptor array */ + graph35pix_12ptBitmaps, /* Character bitmap array */ +}; diff --git a/applications/external/totp/ui/fonts/graph35pix/graph35pix.h b/applications/external/totp/ui/fonts/graph35pix/graph35pix.h new file mode 100644 index 000000000..07838e3ba --- /dev/null +++ b/applications/external/totp/ui/fonts/graph35pix/graph35pix.h @@ -0,0 +1,8 @@ +#pragma once + +/* GENERATED BY https://github.com/pavius/the-dot-factory */ + +#include "../font_info.h" + +/* Font data for Graph 35+ pix 12pt */ +extern const FONT_INFO graph35pix_12ptFontInfo; diff --git a/applications/external/totp/ui/fonts/karma_future/karma_future.c b/applications/external/totp/ui/fonts/karma_future/karma_future.c new file mode 100644 index 000000000..ed6201441 --- /dev/null +++ b/applications/external/totp/ui/fonts/karma_future/karma_future.c @@ -0,0 +1,1172 @@ +#include "karma_future.h" + +/* GENERATED BY https://github.com/pavius/the-dot-factory */ + +/* +** Font data for Karma Future 14pt +*/ + +/* Character bitmaps for Karma Future 14pt */ +const uint8_t karmaFuture_14ptBitmaps[] = { + /* @0 '-' (12 pixels wide) */ + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xFE, + 0x03, + 0x02, + 0x02, + 0x02, + 0x02, + 0xFE, + 0x03, + 0xFC, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + + /* @36 '0' (12 pixels wide) */ + 0xF8, + 0x01, + 0x0E, + 0x03, + 0x02, + 0x06, + 0xF3, + 0x06, + 0xF9, + 0x0C, + 0x79, + 0x0C, + 0x39, + 0x0D, + 0x99, + 0x0C, + 0xC9, + 0x0C, + 0xE9, + 0x0C, + 0xF1, + 0x0C, + 0xF1, + 0x0C, + 0xF1, + 0x0C, + 0xF3, + 0x0E, + 0x02, + 0x0E, + 0x0E, + 0x07, + 0xFC, + 0x07, + 0xF8, + 0x01, + + /* @72 '1' (12 pixels wide) */ + 0x70, + 0x00, + 0xD8, + 0x00, + 0xCE, + 0x00, + 0xC2, + 0x00, + 0xC2, + 0x00, + 0xDE, + 0x00, + 0xDC, + 0x00, + 0xDC, + 0x00, + 0xD0, + 0x00, + 0xD0, + 0x00, + 0xD0, + 0x00, + 0xD0, + 0x00, + 0xD0, + 0x00, + 0xDE, + 0x03, + 0x02, + 0x02, + 0x02, + 0x02, + 0xFE, + 0x03, + 0xFC, + 0x03, + + /* @108 '2' (12 pixels wide) */ + 0xFC, + 0x03, + 0x06, + 0x03, + 0x03, + 0x06, + 0xF1, + 0x04, + 0xF9, + 0x0C, + 0xF9, + 0x0C, + 0x7F, + 0x0E, + 0x3E, + 0x0F, + 0x1E, + 0x0F, + 0x90, + 0x07, + 0xC8, + 0x03, + 0xE4, + 0x01, + 0xE6, + 0x00, + 0xF3, + 0x07, + 0x01, + 0x0C, + 0x01, + 0x0C, + 0xFF, + 0x0F, + 0xFE, + 0x0F, + + /* @144 '3' (12 pixels wide) */ + 0xFC, + 0x03, + 0x06, + 0x03, + 0x03, + 0x06, + 0xF1, + 0x04, + 0xF9, + 0x0C, + 0xFF, + 0x0C, + 0xFE, + 0x0C, + 0x0E, + 0x0E, + 0x08, + 0x0F, + 0xF8, + 0x0E, + 0xF8, + 0x04, + 0xFF, + 0x0C, + 0xF9, + 0x0C, + 0xF1, + 0x0C, + 0x03, + 0x0E, + 0x06, + 0x0F, + 0xFC, + 0x07, + 0xFC, + 0x03, + + /* @180 '4' (12 pixels wide) */ + 0xE0, + 0x03, + 0x30, + 0x03, + 0x10, + 0x03, + 0x08, + 0x03, + 0x4C, + 0x03, + 0x64, + 0x03, + 0x72, + 0x03, + 0x73, + 0x03, + 0x79, + 0x03, + 0x01, + 0x04, + 0x01, + 0x0C, + 0x7F, + 0x0F, + 0x7E, + 0x0F, + 0x7E, + 0x0F, + 0x40, + 0x03, + 0x40, + 0x03, + 0xC0, + 0x03, + 0x80, + 0x03, + + /* @216 '5' (12 pixels wide) */ + 0xFF, + 0x07, + 0x01, + 0x0C, + 0x01, + 0x0C, + 0xF9, + 0x0F, + 0xF9, + 0x0F, + 0xF9, + 0x0F, + 0x01, + 0x03, + 0x03, + 0x06, + 0xFE, + 0x04, + 0xFE, + 0x0C, + 0xFC, + 0x0C, + 0xFF, + 0x0C, + 0xF9, + 0x0C, + 0xF1, + 0x0C, + 0x03, + 0x0E, + 0x06, + 0x0F, + 0xFC, + 0x07, + 0xF8, + 0x03, + + /* @252 '6' (12 pixels wide) */ + 0xF0, + 0x03, + 0x10, + 0x03, + 0x08, + 0x03, + 0xCC, + 0x03, + 0xE6, + 0x03, + 0xF2, + 0x03, + 0xF2, + 0x00, + 0x01, + 0x03, + 0x01, + 0x06, + 0xF1, + 0x04, + 0xF9, + 0x0C, + 0xF9, + 0x0C, + 0xF9, + 0x0C, + 0xF1, + 0x0C, + 0x03, + 0x0E, + 0x06, + 0x0F, + 0xFC, + 0x07, + 0xF8, + 0x03, + + /* @288 '7' (12 pixels wide) */ + 0xFF, + 0x07, + 0x01, + 0x0C, + 0x01, + 0x0C, + 0xFF, + 0x0E, + 0xFE, + 0x0E, + 0x7E, + 0x0F, + 0x40, + 0x07, + 0x60, + 0x07, + 0x20, + 0x03, + 0x30, + 0x03, + 0x90, + 0x01, + 0x90, + 0x01, + 0xD0, + 0x00, + 0xC8, + 0x00, + 0xE8, + 0x00, + 0xE8, + 0x00, + 0x78, + 0x00, + 0x78, + 0x00, + + /* @324 '8' (12 pixels wide) */ + 0xF8, + 0x01, + 0x0C, + 0x01, + 0x06, + 0x03, + 0x72, + 0x06, + 0xF2, + 0x06, + 0xF2, + 0x06, + 0x72, + 0x06, + 0x06, + 0x07, + 0x02, + 0x06, + 0xF1, + 0x04, + 0xF9, + 0x0C, + 0xF9, + 0x0C, + 0xF9, + 0x0C, + 0xF1, + 0x0C, + 0x03, + 0x0E, + 0x06, + 0x0F, + 0xFC, + 0x07, + 0xF8, + 0x03, + + /* @360 '9' (12 pixels wide) */ + 0xFC, + 0x03, + 0x06, + 0x03, + 0x03, + 0x06, + 0xF1, + 0x04, + 0xF9, + 0x0C, + 0xF9, + 0x0C, + 0xF1, + 0x0C, + 0x03, + 0x0C, + 0x06, + 0x0C, + 0xFE, + 0x0E, + 0x7C, + 0x0E, + 0x38, + 0x0F, + 0x30, + 0x07, + 0x1C, + 0x07, + 0x84, + 0x03, + 0xC4, + 0x01, + 0xFC, + 0x00, + 0xF8, + 0x00, + + /* @396 'B' (12 pixels wide) */ + 0xFE, + 0x01, + 0x02, + 0x03, + 0x02, + 0x02, + 0x72, + 0x06, + 0xF2, + 0x06, + 0xF2, + 0x06, + 0x72, + 0x06, + 0x02, + 0x06, + 0x02, + 0x06, + 0xF2, + 0x0C, + 0xF2, + 0x0D, + 0xF2, + 0x0D, + 0xF2, + 0x0D, + 0xF2, + 0x0C, + 0x02, + 0x0E, + 0x02, + 0x0E, + 0xFE, + 0x07, + 0xFC, + 0x03, + + /* @432 'C' (12 pixels wide) */ + 0xF0, + 0x03, + 0x18, + 0x02, + 0x0C, + 0x06, + 0xE4, + 0x0C, + 0xE6, + 0x0D, + 0xF2, + 0x0F, + 0x72, + 0x0F, + 0x32, + 0x0F, + 0x12, + 0x00, + 0x12, + 0x00, + 0x12, + 0x00, + 0x32, + 0x07, + 0xA6, + 0x0D, + 0xE4, + 0x0C, + 0x08, + 0x0E, + 0x18, + 0x0E, + 0xF0, + 0x07, + 0xF0, + 0x03, + + /* @468 'D' (12 pixels wide) */ + 0xFE, + 0x01, + 0x02, + 0x03, + 0x02, + 0x02, + 0x72, + 0x06, + 0xF2, + 0x06, + 0xF2, + 0x0D, + 0xF2, + 0x0D, + 0xF2, + 0x0D, + 0xF2, + 0x0D, + 0xF2, + 0x0D, + 0xF2, + 0x0D, + 0xF2, + 0x0E, + 0xF2, + 0x0E, + 0x72, + 0x0E, + 0x02, + 0x06, + 0x02, + 0x07, + 0xFE, + 0x03, + 0xFC, + 0x01, + + /* @504 'F' (12 pixels wide) */ + 0xFE, + 0x07, + 0x02, + 0x0C, + 0x02, + 0x0C, + 0xF2, + 0x0F, + 0xF2, + 0x0F, + 0xF2, + 0x0F, + 0x12, + 0x00, + 0xF2, + 0x03, + 0x02, + 0x02, + 0xF2, + 0x03, + 0xF2, + 0x03, + 0xF2, + 0x03, + 0x12, + 0x00, + 0x12, + 0x00, + 0x12, + 0x00, + 0x12, + 0x00, + 0x1E, + 0x00, + 0x1C, + 0x00, + + /* @540 'G' (12 pixels wide) */ + 0xF0, + 0x07, + 0x18, + 0x06, + 0x0C, + 0x0C, + 0xE4, + 0x0D, + 0xE6, + 0x0F, + 0xF2, + 0x0F, + 0xF2, + 0x0F, + 0x32, + 0x04, + 0x32, + 0x0C, + 0xF2, + 0x0D, + 0xF2, + 0x0D, + 0xE6, + 0x0D, + 0xE6, + 0x0D, + 0xE4, + 0x0D, + 0x08, + 0x0C, + 0x18, + 0x0C, + 0xF0, + 0x0F, + 0xF0, + 0x0F, + + /* @576 'H' (12 pixels wide) */ + 0x1E, + 0x07, + 0x12, + 0x0D, + 0x12, + 0x0D, + 0x12, + 0x0D, + 0x12, + 0x0D, + 0x12, + 0x0D, + 0x12, + 0x0D, + 0xF2, + 0x0D, + 0x02, + 0x0C, + 0xF2, + 0x0D, + 0xF2, + 0x0D, + 0xF2, + 0x0D, + 0x12, + 0x0D, + 0x12, + 0x0D, + 0x12, + 0x0D, + 0x12, + 0x0D, + 0x1E, + 0x0F, + 0x1C, + 0x0F, + + /* @612 'J' (12 pixels wide) */ + 0x80, + 0x03, + 0x80, + 0x06, + 0x80, + 0x06, + 0x80, + 0x06, + 0x80, + 0x06, + 0x80, + 0x06, + 0x80, + 0x06, + 0x80, + 0x06, + 0x80, + 0x06, + 0x80, + 0x06, + 0x8E, + 0x06, + 0x8A, + 0x06, + 0xDA, + 0x06, + 0x72, + 0x06, + 0x02, + 0x06, + 0x06, + 0x03, + 0xFC, + 0x03, + 0xF8, + 0x01, + + /* @648 'K' (12 pixels wide) */ + 0x1E, + 0x07, + 0x92, + 0x0D, + 0xD2, + 0x0C, + 0x72, + 0x0E, + 0x32, + 0x0E, + 0x12, + 0x0F, + 0x92, + 0x07, + 0xC2, + 0x03, + 0xC2, + 0x01, + 0x92, + 0x01, + 0x12, + 0x01, + 0x32, + 0x02, + 0x32, + 0x02, + 0x72, + 0x06, + 0xD2, + 0x0C, + 0x92, + 0x0D, + 0x9E, + 0x0F, + 0x1C, + 0x0F, + + /* @684 'M' (12 pixels wide) */ + 0x1E, + 0x07, + 0x92, + 0x0D, + 0xA2, + 0x0C, + 0xE2, + 0x0C, + 0x62, + 0x0C, + 0x62, + 0x0C, + 0x12, + 0x0D, + 0x12, + 0x0D, + 0x92, + 0x0D, + 0x92, + 0x0D, + 0xF2, + 0x0D, + 0xF2, + 0x0D, + 0xF2, + 0x0D, + 0x12, + 0x0D, + 0x12, + 0x0D, + 0x12, + 0x0D, + 0x1E, + 0x0F, + 0x1C, + 0x0F, + + /* @720 'N' (12 pixels wide) */ + 0x1E, + 0x07, + 0x12, + 0x0D, + 0x22, + 0x0D, + 0x62, + 0x0D, + 0x62, + 0x0D, + 0xD2, + 0x0D, + 0xD2, + 0x0D, + 0x92, + 0x0D, + 0x92, + 0x0D, + 0x32, + 0x0D, + 0x32, + 0x0D, + 0x72, + 0x0C, + 0x52, + 0x0C, + 0xD2, + 0x0C, + 0x92, + 0x0C, + 0x92, + 0x0D, + 0x1E, + 0x0F, + 0x1C, + 0x0F, + + /* @756 'P' (12 pixels wide) */ + 0xFE, + 0x03, + 0x02, + 0x02, + 0x02, + 0x06, + 0xF2, + 0x0C, + 0xF2, + 0x0D, + 0xF2, + 0x0D, + 0xF2, + 0x0D, + 0xF2, + 0x0C, + 0x02, + 0x0E, + 0x02, + 0x0E, + 0xF2, + 0x0F, + 0xF2, + 0x07, + 0xF2, + 0x03, + 0x12, + 0x00, + 0x12, + 0x00, + 0x12, + 0x00, + 0x1E, + 0x00, + 0x1C, + 0x00, + + /* @792 'Q' (12 pixels wide) */ + 0xF0, + 0x01, + 0x18, + 0x03, + 0x0C, + 0x02, + 0x64, + 0x06, + 0xE6, + 0x06, + 0xF2, + 0x0D, + 0xF2, + 0x0D, + 0xF2, + 0x0D, + 0xF2, + 0x0D, + 0xF2, + 0x0D, + 0x32, + 0x0D, + 0x26, + 0x0E, + 0x26, + 0x0E, + 0x64, + 0x0E, + 0x08, + 0x0C, + 0x18, + 0x0D, + 0xF0, + 0x0F, + 0xF0, + 0x0F, + + /* @828 'R' (12 pixels wide) */ + 0xFE, + 0x03, + 0x02, + 0x02, + 0x02, + 0x06, + 0xF2, + 0x0C, + 0xF2, + 0x0D, + 0xF2, + 0x0D, + 0xF2, + 0x0D, + 0xF2, + 0x0C, + 0x02, + 0x0E, + 0x02, + 0x0E, + 0x12, + 0x0F, + 0x32, + 0x06, + 0x32, + 0x06, + 0x72, + 0x06, + 0xD2, + 0x0C, + 0x92, + 0x0D, + 0x9E, + 0x0F, + 0x1C, + 0x0F, + + /* @864 'T' (12 pixels wide) */ + 0xFE, + 0x03, + 0x02, + 0x02, + 0x02, + 0x02, + 0xDE, + 0x03, + 0xDC, + 0x03, + 0xDC, + 0x03, + 0xD0, + 0x00, + 0xD0, + 0x00, + 0xD0, + 0x00, + 0xD0, + 0x00, + 0xD0, + 0x00, + 0xD0, + 0x00, + 0xD0, + 0x00, + 0xD0, + 0x00, + 0xD0, + 0x00, + 0xD0, + 0x00, + 0xF0, + 0x00, + 0xF0, + 0x00, + + /* @900 'V' (12 pixels wide) */ + 0x1E, + 0x07, + 0x12, + 0x0D, + 0x12, + 0x0D, + 0x92, + 0x0D, + 0xA6, + 0x0E, + 0xA4, + 0x0E, + 0xA4, + 0x0E, + 0xE4, + 0x06, + 0x6C, + 0x06, + 0x68, + 0x06, + 0x68, + 0x02, + 0x18, + 0x03, + 0x10, + 0x03, + 0x10, + 0x01, + 0x90, + 0x01, + 0x90, + 0x01, + 0xE0, + 0x01, + 0xE0, + 0x01, + + /* @936 'W' (12 pixels wide) */ + 0x1E, + 0x07, + 0x12, + 0x0D, + 0x12, + 0x0D, + 0x12, + 0x0D, + 0x12, + 0x0D, + 0x12, + 0x0D, + 0x12, + 0x0D, + 0x12, + 0x0D, + 0xF2, + 0x0D, + 0x92, + 0x0D, + 0x12, + 0x0D, + 0x62, + 0x0C, + 0x62, + 0x0C, + 0xE2, + 0x0C, + 0xE2, + 0x0C, + 0xB2, + 0x0D, + 0x3E, + 0x0F, + 0x1C, + 0x0F, + + /* @972 'X' (12 pixels wide) */ + 0x1E, + 0x07, + 0x12, + 0x0D, + 0xB2, + 0x0D, + 0xA6, + 0x0E, + 0xE4, + 0x0E, + 0x6C, + 0x0E, + 0x18, + 0x07, + 0x98, + 0x07, + 0x90, + 0x03, + 0x10, + 0x01, + 0x68, + 0x02, + 0xE4, + 0x02, + 0xE4, + 0x06, + 0xE6, + 0x06, + 0xB2, + 0x0D, + 0x32, + 0x0D, + 0x1E, + 0x0F, + 0x1C, + 0x0E, + + /* @1008 'Y' (12 pixels wide) */ + 0x1E, + 0x07, + 0x12, + 0x0D, + 0xB2, + 0x0D, + 0xA6, + 0x0E, + 0xE4, + 0x0E, + 0x6C, + 0x0E, + 0x68, + 0x06, + 0x18, + 0x07, + 0x18, + 0x03, + 0x90, + 0x03, + 0x90, + 0x01, + 0x90, + 0x01, + 0xA0, + 0x01, + 0xA0, + 0x01, + 0xA0, + 0x01, + 0xE0, + 0x01, + 0xE0, + 0x01, + 0xE0, + 0x01, +}; + +/* Character descriptors for Karma Future 14pt */ +/* { [Char width in bits], [Offset into karmaFuture_14ptCharBitmaps in bytes] } */ +const FONT_CHAR_INFO karmaFuture_14ptDescriptors[] = { + {12, 0}, /* - */ + {0, 0}, /* . */ + {0, 0}, /* / */ + {12, 36}, /* 0 */ + {12, 72}, /* 1 */ + {12, 108}, /* 2 */ + {12, 144}, /* 3 */ + {12, 180}, /* 4 */ + {12, 216}, /* 5 */ + {12, 252}, /* 6 */ + {12, 288}, /* 7 */ + {12, 324}, /* 8 */ + {12, 360}, /* 9 */ + {0, 0}, /* : */ + {0, 0}, /* ; */ + {0, 0}, /* < */ + {0, 0}, /* = */ + {0, 0}, /* > */ + {0, 0}, /* ? */ + {0, 0}, /* @ */ + {0, 0}, /* A */ + {12, 396}, /* B */ + {12, 432}, /* C */ + {12, 468}, /* D */ + {0, 0}, /* E */ + {12, 504}, /* F */ + {12, 540}, /* G */ + {12, 576}, /* H */ + {0, 0}, /* I */ + {12, 612}, /* J */ + {12, 648}, /* K */ + {0, 0}, /* L */ + {12, 684}, /* M */ + {12, 720}, /* N */ + {0, 0}, /* O */ + {12, 756}, /* P */ + {12, 792}, /* Q */ + {12, 828}, /* R */ + {0, 0}, /* S */ + {12, 864}, /* T */ + {0, 0}, /* U */ + {12, 900}, /* V */ + {12, 936}, /* W */ + {12, 972}, /* X */ + {12, 1008}, /* Y */ +}; + +/* Font information for Karma Future 14pt */ +const FONT_INFO karmaFuture_14ptFontInfo = { + 18, /* Character height */ + '-', /* Start character */ + 'Y', /* End character */ + 2, /* Width, in pixels, of space character */ + karmaFuture_14ptDescriptors, /* Character descriptor array */ + karmaFuture_14ptBitmaps, /* Character bitmap array */ +}; diff --git a/applications/external/totp/ui/fonts/karma_future/karma_future.h b/applications/external/totp/ui/fonts/karma_future/karma_future.h new file mode 100644 index 000000000..3a6352ef1 --- /dev/null +++ b/applications/external/totp/ui/fonts/karma_future/karma_future.h @@ -0,0 +1,8 @@ +#pragma once + +/* GENERATED BY https://github.com/pavius/the-dot-factory */ + +#include "../font_info.h" + +/* Font data for Karma Future 14pt */ +extern const FONT_INFO karmaFuture_14ptFontInfo; diff --git a/applications/external/totp/ui/fonts/mode-nine/mode_nine.c b/applications/external/totp/ui/fonts/mode_nine/mode_nine.c similarity index 100% rename from applications/external/totp/ui/fonts/mode-nine/mode_nine.c rename to applications/external/totp/ui/fonts/mode_nine/mode_nine.c diff --git a/applications/external/totp/ui/fonts/mode-nine/mode_nine.h b/applications/external/totp/ui/fonts/mode_nine/mode_nine.h similarity index 100% rename from applications/external/totp/ui/fonts/mode-nine/mode_nine.h rename to applications/external/totp/ui/fonts/mode_nine/mode_nine.h diff --git a/applications/external/totp/ui/fonts/redhat_mono/redhat_mono.c b/applications/external/totp/ui/fonts/redhat_mono/redhat_mono.c new file mode 100644 index 000000000..77f639d4a --- /dev/null +++ b/applications/external/totp/ui/fonts/redhat_mono/redhat_mono.c @@ -0,0 +1,1057 @@ +#include "redhat_mono.h" +#include + +/* GENERATED BY https://github.com/pavius/the-dot-factory */ + +/* +** Font data for Red Hat Mono 16pt +*/ + +/* Character bitmaps for Red Hat Mono 16pt */ +const uint8_t redHatMono_16ptBitmaps[] = { + /* @0 '-' (12 pixels wide) */ + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xF8, + 0x03, + 0xF8, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + + /* @32 '0' (12 pixels wide) */ + 0xF0, + 0x00, + 0xF8, + 0x03, + 0x1C, + 0x07, + 0x0E, + 0x07, + 0x8E, + 0x07, + 0x86, + 0x0E, + 0xC6, + 0x0C, + 0x66, + 0x0C, + 0x66, + 0x0C, + 0x36, + 0x0E, + 0x36, + 0x0E, + 0x1E, + 0x06, + 0x1C, + 0x07, + 0xF8, + 0x03, + 0xF0, + 0x01, + 0x00, + 0x00, + + /* @64 '1' (12 pixels wide) */ + 0x40, + 0x00, + 0x78, + 0x00, + 0x7E, + 0x00, + 0x66, + 0x00, + 0x60, + 0x00, + 0x60, + 0x00, + 0x60, + 0x00, + 0x60, + 0x00, + 0x60, + 0x00, + 0x60, + 0x00, + 0x60, + 0x00, + 0x60, + 0x00, + 0x60, + 0x00, + 0xFE, + 0x07, + 0xFE, + 0x07, + 0x00, + 0x00, + + /* @96 '2' (12 pixels wide) */ + 0xF0, + 0x01, + 0xFC, + 0x03, + 0x0E, + 0x07, + 0x04, + 0x06, + 0x00, + 0x06, + 0x00, + 0x07, + 0x00, + 0x03, + 0x80, + 0x03, + 0xC0, + 0x01, + 0xE0, + 0x00, + 0x70, + 0x00, + 0x38, + 0x00, + 0x1C, + 0x00, + 0xFE, + 0x07, + 0xFE, + 0x07, + 0x00, + 0x00, + + /* @128 '3' (12 pixels wide) */ + 0xF0, + 0x00, + 0xFC, + 0x03, + 0x0E, + 0x07, + 0x04, + 0x06, + 0x00, + 0x06, + 0x00, + 0x06, + 0x80, + 0x03, + 0xE0, + 0x00, + 0xE0, + 0x03, + 0x00, + 0x06, + 0x00, + 0x06, + 0x00, + 0x0E, + 0x06, + 0x07, + 0xFE, + 0x07, + 0xF8, + 0x01, + 0x00, + 0x00, + + /* @160 '4' (12 pixels wide) */ + 0x00, + 0x03, + 0x80, + 0x03, + 0xC0, + 0x03, + 0xE0, + 0x03, + 0x70, + 0x03, + 0x30, + 0x03, + 0x18, + 0x03, + 0x0C, + 0x03, + 0x0E, + 0x03, + 0xFF, + 0x0F, + 0xFF, + 0x0F, + 0x00, + 0x03, + 0x00, + 0x03, + 0x00, + 0x03, + 0x00, + 0x03, + 0x00, + 0x00, + + /* @192 '5' (12 pixels wide) */ + 0xFC, + 0x07, + 0xFC, + 0x07, + 0x0C, + 0x00, + 0x0C, + 0x00, + 0x0C, + 0x00, + 0x0C, + 0x00, + 0xFC, + 0x01, + 0xFE, + 0x07, + 0x00, + 0x07, + 0x00, + 0x06, + 0x00, + 0x06, + 0x00, + 0x06, + 0x06, + 0x07, + 0xFE, + 0x03, + 0xF8, + 0x01, + 0x00, + 0x00, + + /* @224 '6' (12 pixels wide) */ + 0xE0, + 0x03, + 0xF8, + 0x07, + 0x3C, + 0x06, + 0x0C, + 0x00, + 0x0E, + 0x00, + 0x06, + 0x00, + 0xE6, + 0x03, + 0xFE, + 0x07, + 0x0E, + 0x0E, + 0x06, + 0x0C, + 0x06, + 0x0C, + 0x0E, + 0x0E, + 0x1C, + 0x06, + 0xF8, + 0x07, + 0xF0, + 0x03, + 0x00, + 0x00, + + /* @256 '7' (12 pixels wide) */ + 0xFE, + 0x0F, + 0xFE, + 0x0F, + 0x00, + 0x0E, + 0x00, + 0x06, + 0x00, + 0x07, + 0x00, + 0x03, + 0x80, + 0x01, + 0xC0, + 0x01, + 0xC0, + 0x00, + 0xE0, + 0x00, + 0x60, + 0x00, + 0x70, + 0x00, + 0x30, + 0x00, + 0x38, + 0x00, + 0x1C, + 0x00, + 0x00, + 0x00, + + /* @288 '8' (12 pixels wide) */ + 0xF0, + 0x01, + 0xFC, + 0x03, + 0x1C, + 0x07, + 0x0E, + 0x06, + 0x0E, + 0x06, + 0x0C, + 0x06, + 0xBC, + 0x03, + 0xF0, + 0x01, + 0x1C, + 0x07, + 0x0E, + 0x06, + 0x06, + 0x0E, + 0x06, + 0x0E, + 0x0E, + 0x06, + 0xFC, + 0x07, + 0xF8, + 0x03, + 0x00, + 0x00, + + /* @320 '9' (12 pixels wide) */ + 0xF8, + 0x01, + 0xFC, + 0x03, + 0x0C, + 0x07, + 0x0E, + 0x0E, + 0x06, + 0x0C, + 0x06, + 0x0C, + 0x0E, + 0x0E, + 0xFC, + 0x0F, + 0xF8, + 0x0C, + 0x00, + 0x0C, + 0x00, + 0x0E, + 0x00, + 0x06, + 0x8C, + 0x07, + 0xFC, + 0x03, + 0xF8, + 0x00, + 0x00, + 0x00, + + /* @352 'B' (12 pixels wide) */ + 0xFC, + 0x00, + 0xFC, + 0x03, + 0x8C, + 0x07, + 0x0C, + 0x06, + 0x0C, + 0x06, + 0x0C, + 0x07, + 0xFC, + 0x03, + 0xFC, + 0x01, + 0x8C, + 0x07, + 0x0C, + 0x06, + 0x0C, + 0x0E, + 0x0C, + 0x0E, + 0x0C, + 0x07, + 0xFC, + 0x07, + 0xFC, + 0x01, + 0x00, + 0x00, + + /* @384 'C' (12 pixels wide) */ + 0xF0, + 0x01, + 0xF8, + 0x03, + 0xBC, + 0x07, + 0x0C, + 0x06, + 0x0E, + 0x0E, + 0x0E, + 0x00, + 0x06, + 0x00, + 0x06, + 0x00, + 0x06, + 0x00, + 0x06, + 0x00, + 0x0E, + 0x0E, + 0x0E, + 0x0E, + 0x1C, + 0x07, + 0xF8, + 0x03, + 0xF0, + 0x01, + 0x00, + 0x00, + + /* @416 'D' (12 pixels wide) */ + 0x7E, + 0x00, + 0xFE, + 0x01, + 0xCE, + 0x03, + 0x0E, + 0x07, + 0x0E, + 0x06, + 0x0E, + 0x0E, + 0x0E, + 0x0E, + 0x0E, + 0x0E, + 0x0C, + 0x0E, + 0x0C, + 0x0E, + 0x0C, + 0x06, + 0x0C, + 0x07, + 0x8C, + 0x07, + 0xFC, + 0x03, + 0xFC, + 0x00, + 0x00, + 0x00, + + /* @448 'F' (12 pixels wide) */ + 0xFC, + 0x0F, + 0xFC, + 0x0F, + 0x0C, + 0x00, + 0x0C, + 0x00, + 0x0C, + 0x00, + 0x0C, + 0x00, + 0x0C, + 0x00, + 0xFC, + 0x01, + 0xFC, + 0x01, + 0x0C, + 0x00, + 0x0C, + 0x00, + 0x0C, + 0x00, + 0x0C, + 0x00, + 0x0C, + 0x00, + 0x0C, + 0x00, + 0x00, + 0x00, + + /* @480 'G' (12 pixels wide) */ + 0xF0, + 0x01, + 0xF8, + 0x03, + 0xBC, + 0x07, + 0x0C, + 0x06, + 0x0E, + 0x0E, + 0x06, + 0x00, + 0x06, + 0x00, + 0x86, + 0x0F, + 0x86, + 0x0F, + 0x06, + 0x0C, + 0x0E, + 0x0E, + 0x0E, + 0x06, + 0x1C, + 0x07, + 0xF8, + 0x03, + 0xF0, + 0x01, + 0x00, + 0x00, + + /* @512 'H' (12 pixels wide) */ + 0x0E, + 0x06, + 0x0E, + 0x06, + 0x0E, + 0x06, + 0x0E, + 0x06, + 0x0E, + 0x06, + 0x0E, + 0x06, + 0x0E, + 0x06, + 0xFE, + 0x07, + 0xFE, + 0x07, + 0x0E, + 0x06, + 0x0E, + 0x06, + 0x0E, + 0x06, + 0x0E, + 0x06, + 0x0E, + 0x06, + 0x0E, + 0x06, + 0x00, + 0x00, + + /* @544 'J' (12 pixels wide) */ + 0x00, + 0x06, + 0x00, + 0x06, + 0x00, + 0x06, + 0x00, + 0x06, + 0x00, + 0x06, + 0x00, + 0x06, + 0x00, + 0x06, + 0x00, + 0x06, + 0x00, + 0x06, + 0x00, + 0x06, + 0x04, + 0x06, + 0x07, + 0x07, + 0x8E, + 0x07, + 0xFC, + 0x03, + 0xF8, + 0x01, + 0x00, + 0x00, + + /* @576 'K' (12 pixels wide) */ + 0x0E, + 0x0E, + 0x0E, + 0x07, + 0x0E, + 0x03, + 0x8E, + 0x01, + 0xCE, + 0x01, + 0xEE, + 0x00, + 0x7E, + 0x00, + 0x3E, + 0x00, + 0x7E, + 0x00, + 0xEE, + 0x00, + 0xCE, + 0x01, + 0x8E, + 0x03, + 0x8E, + 0x03, + 0x0E, + 0x07, + 0x0E, + 0x0E, + 0x00, + 0x00, + + /* @608 'M' (12 pixels wide) */ + 0x0E, + 0x0E, + 0x0E, + 0x0F, + 0x1E, + 0x0F, + 0x9E, + 0x0F, + 0xB6, + 0x0F, + 0xB6, + 0x0F, + 0xF6, + 0x0E, + 0xE6, + 0x0E, + 0x66, + 0x0E, + 0x46, + 0x0E, + 0x26, + 0x0E, + 0x06, + 0x0E, + 0x06, + 0x0E, + 0x06, + 0x0E, + 0x06, + 0x0E, + 0x00, + 0x00, + + /* @640 'N' (12 pixels wide) */ + 0x0E, + 0x06, + 0x0E, + 0x06, + 0x1E, + 0x06, + 0x3E, + 0x06, + 0x3E, + 0x06, + 0x76, + 0x06, + 0x66, + 0x06, + 0xE6, + 0x06, + 0xC6, + 0x06, + 0xC6, + 0x07, + 0x86, + 0x07, + 0x86, + 0x07, + 0x06, + 0x07, + 0x06, + 0x07, + 0x06, + 0x06, + 0x00, + 0x00, + + /* @672 'P' (12 pixels wide) */ + 0xFC, + 0x00, + 0xFC, + 0x03, + 0x8C, + 0x07, + 0x0C, + 0x0E, + 0x0C, + 0x0E, + 0x0C, + 0x0E, + 0x0C, + 0x06, + 0xFC, + 0x07, + 0xFC, + 0x03, + 0x0C, + 0x00, + 0x0C, + 0x00, + 0x0C, + 0x00, + 0x0C, + 0x00, + 0x0C, + 0x00, + 0x0C, + 0x00, + 0x00, + 0x00, + + /* @704 'Q' (12 pixels wide) */ + 0xF0, + 0x00, + 0xF8, + 0x03, + 0x9C, + 0x07, + 0x0E, + 0x07, + 0x0E, + 0x0E, + 0x06, + 0x0E, + 0x06, + 0x0E, + 0x06, + 0x0E, + 0x06, + 0x0E, + 0x06, + 0x0E, + 0xEE, + 0x0E, + 0xCE, + 0x07, + 0x9C, + 0x07, + 0xFC, + 0x07, + 0xF0, + 0x07, + 0x00, + 0x0A, + + /* @736 'R' (12 pixels wide) */ + 0xFC, + 0x00, + 0xFC, + 0x03, + 0x8C, + 0x07, + 0x0C, + 0x06, + 0x0C, + 0x0E, + 0x0C, + 0x0E, + 0x0C, + 0x07, + 0xFC, + 0x07, + 0xFC, + 0x01, + 0x8C, + 0x01, + 0x8C, + 0x03, + 0x0C, + 0x03, + 0x0C, + 0x07, + 0x0C, + 0x06, + 0x0C, + 0x0E, + 0x00, + 0x00, + + /* @768 'T' (12 pixels wide) */ + 0xFF, + 0x0F, + 0xFF, + 0x0F, + 0xE0, + 0x00, + 0xE0, + 0x00, + 0xE0, + 0x00, + 0xE0, + 0x00, + 0xE0, + 0x00, + 0xE0, + 0x00, + 0xE0, + 0x00, + 0xE0, + 0x00, + 0xE0, + 0x00, + 0xE0, + 0x00, + 0xE0, + 0x00, + 0xE0, + 0x00, + 0xE0, + 0x00, + 0x00, + 0x00, + + /* @800 'V' (12 pixels wide) */ + 0x07, + 0x0C, + 0x06, + 0x0C, + 0x06, + 0x0E, + 0x0E, + 0x06, + 0x0C, + 0x06, + 0x0C, + 0x07, + 0x1C, + 0x03, + 0x1C, + 0x03, + 0x98, + 0x03, + 0x98, + 0x03, + 0xB8, + 0x01, + 0xB0, + 0x01, + 0xF0, + 0x01, + 0xF0, + 0x00, + 0xE0, + 0x00, + 0x00, + 0x00, + + /* @832 'W' (12 pixels wide) */ + 0x67, + 0x0C, + 0xE6, + 0x0C, + 0xE6, + 0x0C, + 0xE6, + 0x0C, + 0xE6, + 0x0C, + 0xF6, + 0x0C, + 0xB6, + 0x0E, + 0xB6, + 0x07, + 0xB6, + 0x07, + 0x96, + 0x07, + 0x9C, + 0x07, + 0x1C, + 0x07, + 0x1C, + 0x07, + 0x1C, + 0x07, + 0x0C, + 0x07, + 0x00, + 0x00, + + /* @864 'X' (12 pixels wide) */ + 0x0E, + 0x0E, + 0x0E, + 0x06, + 0x1C, + 0x07, + 0x98, + 0x03, + 0xB8, + 0x01, + 0xF0, + 0x01, + 0xF0, + 0x00, + 0xE0, + 0x00, + 0xF0, + 0x00, + 0xF0, + 0x01, + 0xB8, + 0x03, + 0x9C, + 0x03, + 0x0C, + 0x07, + 0x0E, + 0x06, + 0x07, + 0x0E, + 0x00, + 0x00, + + /* @896 'Y' (12 pixels wide) */ + 0x07, + 0x0C, + 0x0E, + 0x0E, + 0x0E, + 0x06, + 0x1C, + 0x07, + 0x18, + 0x03, + 0xB8, + 0x03, + 0xF0, + 0x01, + 0xF0, + 0x00, + 0xE0, + 0x00, + 0xE0, + 0x00, + 0xE0, + 0x00, + 0xE0, + 0x00, + 0xE0, + 0x00, + 0xE0, + 0x00, + 0xE0, + 0x00, + 0x00, + 0x00, +}; + +/* Character descriptors for Red Hat Mono 16pt */ +/* { [Char width in bits], [Offset into redHatMono_16ptCharBitmaps in bytes] } */ +const FONT_CHAR_INFO redHatMono_16ptDescriptors[] = { + {12, 0}, /* - */ + {0, 0}, /* . */ + {0, 0}, /* / */ + {12, 32}, /* 0 */ + {12, 64}, /* 1 */ + {12, 96}, /* 2 */ + {12, 128}, /* 3 */ + {12, 160}, /* 4 */ + {12, 192}, /* 5 */ + {12, 224}, /* 6 */ + {12, 256}, /* 7 */ + {12, 288}, /* 8 */ + {12, 320}, /* 9 */ + {0, 0}, /* : */ + {0, 0}, /* ; */ + {0, 0}, /* < */ + {0, 0}, /* = */ + {0, 0}, /* > */ + {0, 0}, /* ? */ + {0, 0}, /* @ */ + {0, 0}, /* A */ + {12, 352}, /* B */ + {12, 384}, /* C */ + {12, 416}, /* D */ + {0, 0}, /* E */ + {12, 448}, /* F */ + {12, 480}, /* G */ + {12, 512}, /* H */ + {0, 0}, /* I */ + {12, 544}, /* J */ + {12, 576}, /* K */ + {0, 0}, /* L */ + {12, 608}, /* M */ + {12, 640}, /* N */ + {0, 0}, /* O */ + {12, 672}, /* P */ + {12, 704}, /* Q */ + {12, 736}, /* R */ + {0, 0}, /* S */ + {12, 768}, /* T */ + {0, 0}, /* U */ + {12, 800}, /* V */ + {12, 832}, /* W */ + {12, 864}, /* X */ + {12, 896}, /* Y */ +}; + +/* Font information for Red Hat Mono 16pt */ +const FONT_INFO redHatMono_16ptFontInfo = { + 16, /* Character height */ + '-', /* Start character */ + 'Y', /* End character */ + 2, /* Width, in pixels, of space character */ + redHatMono_16ptDescriptors, /* Character descriptor array */ + redHatMono_16ptBitmaps, /* Character bitmap array */ +}; diff --git a/applications/external/totp/ui/fonts/redhat_mono/redhat_mono.h b/applications/external/totp/ui/fonts/redhat_mono/redhat_mono.h new file mode 100644 index 000000000..ac9214d6b --- /dev/null +++ b/applications/external/totp/ui/fonts/redhat_mono/redhat_mono.h @@ -0,0 +1,8 @@ +#pragma once + +/* GENERATED BY https://github.com/pavius/the-dot-factory */ + +#include "../font_info.h" + +/* Font data for Redhat Mono 16pt */ +extern const FONT_INFO redHatMono_16ptFontInfo; \ No newline at end of file diff --git a/applications/external/totp/ui/fonts/zector/zector.c b/applications/external/totp/ui/fonts/zector/zector.c new file mode 100644 index 000000000..f49d8b306 --- /dev/null +++ b/applications/external/totp/ui/fonts/zector/zector.c @@ -0,0 +1,1056 @@ +#include "zector.h" + +/* GENERATED BY https://github.com/pavius/the-dot-factory */ + +/* +** Font data for Zector 18pt +*/ + +/* Character bitmaps for Zector 18pt */ +const uint8_t zector_18ptBitmaps[] = { + /* @0 '-' (9 pixels wide) */ + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xFF, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + + /* @32 '0' (9 pixels wide) */ + 0x3C, + 0x00, + 0xC2, + 0x00, + 0x83, + 0x00, + 0x85, + 0x00, + 0x85, + 0x00, + 0x89, + 0x00, + 0x89, + 0x00, + 0x91, + 0x00, + 0x91, + 0x00, + 0xA1, + 0x00, + 0xA1, + 0x00, + 0xC1, + 0x00, + 0xC1, + 0x00, + 0x81, + 0x00, + 0x42, + 0x00, + 0x3C, + 0x00, + + /* @64 '1' (9 pixels wide) */ + 0x10, + 0x00, + 0x18, + 0x00, + 0x18, + 0x00, + 0x14, + 0x00, + 0x14, + 0x00, + 0x12, + 0x00, + 0x12, + 0x00, + 0x11, + 0x00, + 0x10, + 0x00, + 0x10, + 0x00, + 0x10, + 0x00, + 0x10, + 0x00, + 0x10, + 0x00, + 0x10, + 0x00, + 0x10, + 0x00, + 0xFF, + 0x00, + + /* @96 '2' (9 pixels wide) */ + 0x3C, + 0x00, + 0x42, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x80, + 0x00, + 0x80, + 0x00, + 0x40, + 0x00, + 0x20, + 0x00, + 0x20, + 0x00, + 0x10, + 0x00, + 0x08, + 0x00, + 0x08, + 0x00, + 0x04, + 0x00, + 0x02, + 0x00, + 0x02, + 0x00, + 0xFF, + 0x00, + + /* @128 '3' (9 pixels wide) */ + 0xFF, + 0x01, + 0x80, + 0x00, + 0x80, + 0x00, + 0x40, + 0x00, + 0x40, + 0x00, + 0x20, + 0x00, + 0x20, + 0x00, + 0x10, + 0x00, + 0x60, + 0x00, + 0x80, + 0x00, + 0x80, + 0x00, + 0x00, + 0x01, + 0x01, + 0x01, + 0x81, + 0x00, + 0x42, + 0x00, + 0x3C, + 0x00, + + /* @160 '4' (9 pixels wide) */ + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0xFF, + 0x00, + 0x80, + 0x00, + 0x80, + 0x00, + 0x80, + 0x00, + 0x80, + 0x00, + 0x80, + 0x00, + 0x80, + 0x00, + 0x80, + 0x00, + + /* @192 '5' (9 pixels wide) */ + 0xFF, + 0x00, + 0x01, + 0x00, + 0x01, + 0x00, + 0x01, + 0x00, + 0x01, + 0x00, + 0x01, + 0x00, + 0x01, + 0x00, + 0x01, + 0x00, + 0x3F, + 0x00, + 0x40, + 0x00, + 0x80, + 0x00, + 0x80, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0xC2, + 0x00, + 0x3C, + 0x00, + + /* @224 '6' (9 pixels wide) */ + 0x3C, + 0x00, + 0x42, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x01, + 0x00, + 0x01, + 0x00, + 0x01, + 0x00, + 0x01, + 0x00, + 0x3D, + 0x00, + 0x43, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0xC2, + 0x00, + 0x3C, + 0x00, + + /* @256 '7' (9 pixels wide) */ + 0xFF, + 0x01, + 0x80, + 0x00, + 0x80, + 0x00, + 0x40, + 0x00, + 0x40, + 0x00, + 0x20, + 0x00, + 0x20, + 0x00, + 0x10, + 0x00, + 0x10, + 0x00, + 0x08, + 0x00, + 0x08, + 0x00, + 0x04, + 0x00, + 0x04, + 0x00, + 0x02, + 0x00, + 0x02, + 0x00, + 0x01, + 0x00, + + /* @288 '8' (9 pixels wide) */ + 0x3C, + 0x00, + 0xC2, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x42, + 0x00, + 0x3C, + 0x00, + 0x42, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x42, + 0x00, + 0x3C, + 0x00, + + /* @320 '9' (9 pixels wide) */ + 0x3C, + 0x00, + 0x42, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0xC2, + 0x00, + 0xBC, + 0x00, + 0x80, + 0x00, + 0x80, + 0x00, + 0x80, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x42, + 0x00, + 0x3C, + 0x00, + + /* @352 'B' (9 pixels wide) */ + 0x3F, + 0x00, + 0xC1, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x41, + 0x00, + 0x3F, + 0x00, + 0x41, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x41, + 0x00, + 0x3F, + 0x00, + + /* @384 'C' (9 pixels wide) */ + 0x3C, + 0x00, + 0x42, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x01, + 0x00, + 0x01, + 0x00, + 0x01, + 0x00, + 0x01, + 0x00, + 0x01, + 0x00, + 0x01, + 0x00, + 0x01, + 0x00, + 0x01, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x42, + 0x00, + 0x3C, + 0x00, + + /* @416 'D' (9 pixels wide) */ + 0x3F, + 0x00, + 0x41, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x41, + 0x00, + 0x3F, + 0x00, + + /* @448 'F' (9 pixels wide) */ + 0xFF, + 0x00, + 0x01, + 0x00, + 0x01, + 0x00, + 0x01, + 0x00, + 0x01, + 0x00, + 0x01, + 0x00, + 0x01, + 0x00, + 0x01, + 0x00, + 0xFF, + 0x00, + 0x01, + 0x00, + 0x01, + 0x00, + 0x01, + 0x00, + 0x01, + 0x00, + 0x01, + 0x00, + 0x01, + 0x00, + 0x01, + 0x00, + + /* @480 'G' (9 pixels wide) */ + 0x3C, + 0x00, + 0xC2, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x01, + 0x00, + 0x01, + 0x00, + 0x01, + 0x00, + 0xF1, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x42, + 0x00, + 0x3C, + 0x00, + + /* @512 'H' (9 pixels wide) */ + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0xFF, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + + /* @544 'J' (9 pixels wide) */ + 0x80, + 0x00, + 0x80, + 0x00, + 0x80, + 0x00, + 0x80, + 0x00, + 0x80, + 0x00, + 0x80, + 0x00, + 0x80, + 0x00, + 0x80, + 0x00, + 0x80, + 0x00, + 0x80, + 0x00, + 0x80, + 0x00, + 0x80, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x42, + 0x00, + 0x3C, + 0x00, + + /* @576 'K' (9 pixels wide) */ + 0x81, + 0x00, + 0xC1, + 0x00, + 0x61, + 0x00, + 0x21, + 0x00, + 0x11, + 0x00, + 0x09, + 0x00, + 0x05, + 0x00, + 0x03, + 0x00, + 0x01, + 0x00, + 0x03, + 0x00, + 0x05, + 0x00, + 0x09, + 0x00, + 0x11, + 0x00, + 0x21, + 0x00, + 0x41, + 0x00, + 0x81, + 0x00, + + /* @608 'M' (9 pixels wide) */ + 0x81, + 0x00, + 0x81, + 0x00, + 0x83, + 0x00, + 0xC3, + 0x00, + 0xC5, + 0x00, + 0xA5, + 0x00, + 0xA9, + 0x00, + 0x91, + 0x00, + 0x91, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + + /* @640 'N' (9 pixels wide) */ + 0x81, + 0x00, + 0x81, + 0x00, + 0x83, + 0x00, + 0x83, + 0x00, + 0x85, + 0x00, + 0x85, + 0x00, + 0x89, + 0x00, + 0x89, + 0x00, + 0x91, + 0x00, + 0xA1, + 0x00, + 0xA1, + 0x00, + 0xC1, + 0x00, + 0xC1, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + + /* @672 'P' (9 pixels wide) */ + 0x3F, + 0x00, + 0x41, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x41, + 0x00, + 0x3F, + 0x00, + 0x01, + 0x00, + 0x01, + 0x00, + 0x01, + 0x00, + 0x01, + 0x00, + 0x01, + 0x00, + 0x01, + 0x00, + 0x01, + 0x00, + + /* @704 'Q' (9 pixels wide) */ + 0x3C, + 0x00, + 0x42, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x91, + 0x00, + 0xA1, + 0x00, + 0xC2, + 0x00, + 0xBC, + 0x00, + + /* @736 'R' (9 pixels wide) */ + 0x3F, + 0x00, + 0x41, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x41, + 0x00, + 0x3F, + 0x00, + 0x03, + 0x00, + 0x05, + 0x00, + 0x09, + 0x00, + 0x11, + 0x00, + 0x21, + 0x00, + 0x41, + 0x00, + 0x81, + 0x00, + + /* @768 'T' (9 pixels wide) */ + 0xFF, + 0x00, + 0x10, + 0x00, + 0x10, + 0x00, + 0x10, + 0x00, + 0x10, + 0x00, + 0x10, + 0x00, + 0x10, + 0x00, + 0x10, + 0x00, + 0x10, + 0x00, + 0x10, + 0x00, + 0x10, + 0x00, + 0x10, + 0x00, + 0x10, + 0x00, + 0x10, + 0x00, + 0x10, + 0x00, + 0x10, + 0x00, + + /* @800 'V' (9 pixels wide) */ + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x82, + 0x00, + 0x42, + 0x00, + 0x44, + 0x00, + 0x24, + 0x00, + 0x28, + 0x00, + 0x18, + 0x00, + 0x10, + 0x00, + + /* @832 'W' (9 pixels wide) */ + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x91, + 0x00, + 0x91, + 0x00, + 0x99, + 0x00, + 0xA9, + 0x00, + 0xA5, + 0x00, + 0xC5, + 0x00, + 0x83, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + + /* @864 'X' (9 pixels wide) */ + 0x81, + 0x00, + 0x82, + 0x00, + 0x82, + 0x00, + 0x44, + 0x00, + 0x44, + 0x00, + 0x28, + 0x00, + 0x28, + 0x00, + 0x10, + 0x00, + 0x10, + 0x00, + 0x28, + 0x00, + 0x28, + 0x00, + 0x44, + 0x00, + 0x44, + 0x00, + 0x82, + 0x00, + 0x82, + 0x00, + 0x81, + 0x00, + + /* @896 'Y' (9 pixels wide) */ + 0x81, + 0x00, + 0x82, + 0x00, + 0x82, + 0x00, + 0x44, + 0x00, + 0x44, + 0x00, + 0x28, + 0x00, + 0x28, + 0x00, + 0x10, + 0x00, + 0x10, + 0x00, + 0x10, + 0x00, + 0x10, + 0x00, + 0x10, + 0x00, + 0x10, + 0x00, + 0x10, + 0x00, + 0x10, + 0x00, + 0x10, + 0x00, +}; + +/* Character descriptors for Zector 18pt */ +/* { [Char width in bits], [Offset into zector_18ptCharBitmaps in bytes] } */ +const FONT_CHAR_INFO zector_18ptDescriptors[] = { + {9, 0}, /* - */ + {0, 0}, /* . */ + {0, 0}, /* / */ + {9, 32}, /* 0 */ + {9, 64}, /* 1 */ + {9, 96}, /* 2 */ + {9, 128}, /* 3 */ + {9, 160}, /* 4 */ + {9, 192}, /* 5 */ + {9, 224}, /* 6 */ + {9, 256}, /* 7 */ + {9, 288}, /* 8 */ + {9, 320}, /* 9 */ + {0, 0}, /* : */ + {0, 0}, /* ; */ + {0, 0}, /* < */ + {0, 0}, /* = */ + {0, 0}, /* > */ + {0, 0}, /* ? */ + {0, 0}, /* @ */ + {0, 0}, /* A */ + {9, 352}, /* B */ + {9, 384}, /* C */ + {9, 416}, /* D */ + {0, 0}, /* E */ + {9, 448}, /* F */ + {9, 480}, /* G */ + {9, 512}, /* H */ + {0, 0}, /* I */ + {9, 544}, /* J */ + {9, 576}, /* K */ + {0, 0}, /* L */ + {9, 608}, /* M */ + {9, 640}, /* N */ + {0, 0}, /* O */ + {9, 672}, /* P */ + {9, 704}, /* Q */ + {9, 736}, /* R */ + {0, 0}, /* S */ + {9, 768}, /* T */ + {0, 0}, /* U */ + {9, 800}, /* V */ + {9, 832}, /* W */ + {9, 864}, /* X */ + {9, 896}, /* Y */ +}; + +/* Font information for Zector 18pt */ +const FONT_INFO zector_18ptFontInfo = { + 16, /* Character height */ + '-', /* Start character */ + 'Y', /* End character */ + 2, /* Width, in pixels, of space character */ + zector_18ptDescriptors, /* Character descriptor array */ + zector_18ptBitmaps, /* Character bitmap array */ +}; diff --git a/applications/external/totp/ui/fonts/zector/zector.h b/applications/external/totp/ui/fonts/zector/zector.h new file mode 100644 index 000000000..2a5cf5907 --- /dev/null +++ b/applications/external/totp/ui/fonts/zector/zector.h @@ -0,0 +1,8 @@ +#pragma once + +/* GENERATED BY https://github.com/pavius/the-dot-factory */ + +#include "../font_info.h" + +/* Font information for Zector 18pt */ +extern const FONT_INFO zector_18ptFontInfo; \ No newline at end of file diff --git a/applications/external/totp/ui/scenes/add_new_token/totp_input_text.c b/applications/external/totp/ui/scenes/add_new_token/totp_input_text.c index bbe0b7726..5eb1231d9 100644 --- a/applications/external/totp/ui/scenes/add_new_token/totp_input_text.c +++ b/applications/external/totp/ui/scenes/add_new_token/totp_input_text.c @@ -29,7 +29,7 @@ void view_unlock_model(View* view) { static void commit_text_input_callback(void* context) { InputTextSceneState* text_input_state = (InputTextSceneState*)context; - if(text_input_state->callback != 0) { + if(text_input_state->callback != NULL) { InputTextSceneCallbackResult* result = malloc(sizeof(InputTextSceneCallbackResult)); furi_check(result != NULL); result->user_input_length = diff --git a/applications/external/totp/ui/scenes/add_new_token/totp_scene_add_new_token.c b/applications/external/totp/ui/scenes/add_new_token/totp_scene_add_new_token.c index d525e3399..327185cf7 100644 --- a/applications/external/totp/ui/scenes/add_new_token/totp_scene_add_new_token.c +++ b/applications/external/totp/ui/scenes/add_new_token/totp_scene_add_new_token.c @@ -36,7 +36,7 @@ typedef struct { InputTextSceneContext* token_name_input_context; InputTextSceneContext* token_secret_input_context; InputTextSceneState* input_state; - uint32_t input_started_at; + bool text_input_mode; int16_t screen_y_offset; TokenHashAlgo algo; uint8_t digits_count_index; @@ -56,7 +56,7 @@ static void on_token_name_user_comitted(InputTextSceneCallbackResult* result) { free(scene_state->token_name); scene_state->token_name = result->user_input; scene_state->token_name_length = result->user_input_length; - scene_state->input_started_at = 0; + scene_state->text_input_mode = false; free(result); } @@ -65,7 +65,7 @@ static void on_token_secret_user_comitted(InputTextSceneCallbackResult* result) free(scene_state->token_secret); scene_state->token_secret = result->user_input; scene_state->token_secret_length = result->user_input_length; - scene_state->input_started_at = 0; + scene_state->text_input_mode = false; free(result); } @@ -127,8 +127,8 @@ void totp_scene_add_new_token_activate(PluginState* plugin_state) { } void totp_scene_add_new_token_render(Canvas* const canvas, PluginState* plugin_state) { - SceneState* scene_state = (SceneState*)plugin_state->current_scene_state; - if(scene_state->input_started_at > 0) { + SceneState* scene_state = plugin_state->current_scene_state; + if(scene_state->text_input_mode) { totp_input_text_render(canvas, scene_state->input_state); return; } @@ -200,63 +200,81 @@ bool totp_scene_add_new_token_handle_event(PluginEvent* const event, PluginState return true; } - SceneState* scene_state = (SceneState*)plugin_state->current_scene_state; - if(scene_state->input_started_at > 0 && - furi_get_tick() - scene_state->input_started_at > 300) { + SceneState* scene_state = plugin_state->current_scene_state; + + if(event->input.type == InputTypeLong && event->input.key == InputKeyBack) { + if(scene_state->text_input_mode) { + scene_state->text_input_mode = false; + } else { + return false; + } + } + + if(scene_state->text_input_mode) { + if(event->input.type == InputTypeShort && event->input.key == InputKeyBack) { + PluginEvent long_back_cb_evt = { + .type = event->type, .input.key = InputKeyBack, .input.type = InputTypeLong}; + return totp_input_text_handle_event(&long_back_cb_evt, scene_state->input_state); + } + return totp_input_text_handle_event(event, scene_state->input_state); } - if(event->input.type == InputTypeLong && event->input.key == InputKeyBack) { - return false; - } - - if(event->input.type != InputTypePress) { - return true; - } - - switch(event->input.key) { - case InputKeyUp: - totp_roll_value_uint8_t( - &scene_state->selected_control, - -1, - TokenNameTextBox, - ConfirmButton, - RollOverflowBehaviorStop); - update_screen_y_offset(scene_state); - break; - case InputKeyDown: - totp_roll_value_uint8_t( - &scene_state->selected_control, - 1, - TokenNameTextBox, - ConfirmButton, - RollOverflowBehaviorStop); - update_screen_y_offset(scene_state); - break; - case InputKeyRight: - if(scene_state->selected_control == TokenAlgoSelect) { - totp_roll_value_uint8_t(&scene_state->algo, 1, SHA1, STEAM, RollOverflowBehaviorRoll); - } else if(scene_state->selected_control == TokenLengthSelect) { + if(event->input.type == InputTypePress) { + switch(event->input.key) { + case InputKeyUp: totp_roll_value_uint8_t( - &scene_state->digits_count_index, 1, 0, 2, RollOverflowBehaviorRoll); - } else if(scene_state->selected_control == TokenDurationSelect) { - totp_roll_value_uint8_t(&scene_state->duration, 15, 15, 255, RollOverflowBehaviorStop); - update_duration_text(scene_state); + &scene_state->selected_control, + -1, + TokenNameTextBox, + ConfirmButton, + RollOverflowBehaviorStop); + update_screen_y_offset(scene_state); + break; + case InputKeyDown: + totp_roll_value_uint8_t( + &scene_state->selected_control, + 1, + TokenNameTextBox, + ConfirmButton, + RollOverflowBehaviorStop); + update_screen_y_offset(scene_state); + break; + case InputKeyRight: + if(scene_state->selected_control == TokenAlgoSelect) { + totp_roll_value_uint8_t( + &scene_state->algo, 1, SHA1, STEAM, RollOverflowBehaviorRoll); + } else if(scene_state->selected_control == TokenLengthSelect) { + totp_roll_value_uint8_t( + &scene_state->digits_count_index, 1, 0, 2, RollOverflowBehaviorRoll); + } else if(scene_state->selected_control == TokenDurationSelect) { + totp_roll_value_uint8_t( + &scene_state->duration, 15, 15, 255, RollOverflowBehaviorStop); + update_duration_text(scene_state); + } + break; + case InputKeyLeft: + if(scene_state->selected_control == TokenAlgoSelect) { + totp_roll_value_uint8_t( + &scene_state->algo, -1, SHA1, STEAM, RollOverflowBehaviorRoll); + } else if(scene_state->selected_control == TokenLengthSelect) { + totp_roll_value_uint8_t( + &scene_state->digits_count_index, -1, 0, 2, RollOverflowBehaviorRoll); + } else if(scene_state->selected_control == TokenDurationSelect) { + totp_roll_value_uint8_t( + &scene_state->duration, -15, 15, 255, RollOverflowBehaviorStop); + update_duration_text(scene_state); + } + break; + case InputKeyOk: + break; + case InputKeyBack: + totp_scene_director_activate_scene(plugin_state, TotpSceneGenerateToken); + break; + default: + break; } - break; - case InputKeyLeft: - if(scene_state->selected_control == TokenAlgoSelect) { - totp_roll_value_uint8_t(&scene_state->algo, -1, SHA1, STEAM, RollOverflowBehaviorRoll); - } else if(scene_state->selected_control == TokenLengthSelect) { - totp_roll_value_uint8_t( - &scene_state->digits_count_index, -1, 0, 2, RollOverflowBehaviorRoll); - } else if(scene_state->selected_control == TokenDurationSelect) { - totp_roll_value_uint8_t( - &scene_state->duration, -15, 15, 255, RollOverflowBehaviorStop); - update_duration_text(scene_state); - } - break; - case InputKeyOk: + } else if(event->input.type == InputTypeRelease && event->input.key == InputKeyOk) { switch(scene_state->selected_control) { case TokenNameTextBox: if(scene_state->input_state != NULL) { @@ -264,7 +282,8 @@ bool totp_scene_add_new_token_handle_event(PluginEvent* const event, PluginState } scene_state->input_state = totp_input_text_activate(scene_state->token_name_input_context); - scene_state->input_started_at = furi_get_tick(); + + scene_state->text_input_mode = true; break; case TokenSecretTextBox: if(scene_state->input_state != NULL) { @@ -272,7 +291,8 @@ bool totp_scene_add_new_token_handle_event(PluginEvent* const event, PluginState } scene_state->input_state = totp_input_text_activate(scene_state->token_secret_input_context); - scene_state->input_started_at = furi_get_tick(); + + scene_state->text_input_mode = true; break; case TokenAlgoSelect: break; @@ -313,12 +333,6 @@ bool totp_scene_add_new_token_handle_event(PluginEvent* const event, PluginState default: break; } - break; - case InputKeyBack: - totp_scene_director_activate_scene(plugin_state, TotpSceneGenerateToken); - break; - default: - break; } return true; diff --git a/applications/external/totp/ui/scenes/app_settings/totp_app_settings.c b/applications/external/totp/ui/scenes/app_settings/totp_app_settings.c index 6dcf0dbc9..54659946d 100644 --- a/applications/external/totp/ui/scenes/app_settings/totp_app_settings.c +++ b/applications/external/totp/ui/scenes/app_settings/totp_app_settings.c @@ -60,17 +60,17 @@ void totp_scene_app_settings_activate(PluginState* plugin_state) { } static void two_digit_to_str(int8_t num, char* str) { - uint8_t index = 0; + char* s = str; if(num < 0) { - str[index++] = '-'; + *(s++) = '-'; num = -num; } uint8_t d1 = (num / 10) % 10; uint8_t d2 = num % 10; - str[index++] = CONVERT_DIGIT_TO_CHAR(d1); - str[index++] = CONVERT_DIGIT_TO_CHAR(d2); - str[index++] = '\0'; + *(s++) = CONVERT_DIGIT_TO_CHAR(d1); + *(s++) = CONVERT_DIGIT_TO_CHAR(d2); + *(s++) = '\0'; } void totp_scene_app_settings_render(Canvas* const canvas, const PluginState* plugin_state) { @@ -183,116 +183,117 @@ bool totp_scene_app_settings_handle_event( } SceneState* scene_state = (SceneState*)plugin_state->current_scene_state; - if(event->input.type != InputTypePress && event->input.type != InputTypeRepeat) { - return true; - } - - switch(event->input.key) { - case InputKeyUp: - totp_roll_value_uint8_t( - &scene_state->selected_control, - -1, - HoursInput, - ConfirmButton, - RollOverflowBehaviorStop); - if(scene_state->selected_control > Vibro) { - scene_state->y_offset = 128; - } else if(scene_state->selected_control > MinutesInput) { - scene_state->y_offset = 64; - } else { - scene_state->y_offset = 0; - } - break; - case InputKeyDown: - totp_roll_value_uint8_t( - &scene_state->selected_control, 1, HoursInput, ConfirmButton, RollOverflowBehaviorStop); - if(scene_state->selected_control > Vibro) { - scene_state->y_offset = 128; - } else if(scene_state->selected_control > MinutesInput) { - scene_state->y_offset = 64; - } else { - scene_state->y_offset = 0; - } - break; - case InputKeyRight: - if(scene_state->selected_control == HoursInput) { - totp_roll_value_int8_t( - &scene_state->tz_offset_hours, 1, -12, 12, RollOverflowBehaviorStop); - } else if(scene_state->selected_control == MinutesInput) { + if(event->input.type == InputTypePress || event->input.type == InputTypeRepeat) { + switch(event->input.key) { + case InputKeyUp: totp_roll_value_uint8_t( - &scene_state->tz_offset_minutes, 15, 0, 45, RollOverflowBehaviorRoll); - } else if(scene_state->selected_control == Sound) { - scene_state->notification_sound = !scene_state->notification_sound; - } else if(scene_state->selected_control == Vibro) { - scene_state->notification_vibro = !scene_state->notification_vibro; - } else if(scene_state->selected_control == BadUsb) { - scene_state->badusb_enabled = !scene_state->badusb_enabled; - } -#ifdef TOTP_BADBT_TYPE_ENABLED - else if(scene_state->selected_control == BadBt) { - scene_state->badbt_enabled = !scene_state->badbt_enabled; - } -#endif - break; - case InputKeyLeft: - if(scene_state->selected_control == HoursInput) { - totp_roll_value_int8_t( - &scene_state->tz_offset_hours, -1, -12, 12, RollOverflowBehaviorStop); - } else if(scene_state->selected_control == MinutesInput) { - totp_roll_value_uint8_t( - &scene_state->tz_offset_minutes, -15, 0, 45, RollOverflowBehaviorRoll); - } else if(scene_state->selected_control == Sound) { - scene_state->notification_sound = !scene_state->notification_sound; - } else if(scene_state->selected_control == Vibro) { - scene_state->notification_vibro = !scene_state->notification_vibro; - } else if(scene_state->selected_control == BadUsb) { - scene_state->badusb_enabled = !scene_state->badusb_enabled; - } -#ifdef TOTP_BADBT_TYPE_ENABLED - else if(scene_state->selected_control == BadBt) { - scene_state->badbt_enabled = !scene_state->badbt_enabled; - } -#endif - break; - case InputKeyOk: - if(scene_state->selected_control == ConfirmButton) { - plugin_state->timezone_offset = (float)scene_state->tz_offset_hours + - (float)scene_state->tz_offset_minutes / 60.0f; - - plugin_state->notification_method = - (scene_state->notification_sound ? NotificationMethodSound : - NotificationMethodNone) | - (scene_state->notification_vibro ? NotificationMethodVibro : - NotificationMethodNone); - - plugin_state->automation_method = - scene_state->badusb_enabled ? AutomationMethodBadUsb : AutomationMethodNone; -#ifdef TOTP_BADBT_TYPE_ENABLED - plugin_state->automation_method |= scene_state->badbt_enabled ? AutomationMethodBadBt : - AutomationMethodNone; -#endif - - if(!totp_config_file_update_user_settings(plugin_state)) { - totp_dialogs_config_updating_error(plugin_state); - return false; + &scene_state->selected_control, + -1, + HoursInput, + ConfirmButton, + RollOverflowBehaviorStop); + if(scene_state->selected_control > Vibro) { + scene_state->y_offset = 128; + } else if(scene_state->selected_control > MinutesInput) { + scene_state->y_offset = 64; + } else { + scene_state->y_offset = 0; + } + break; + case InputKeyDown: + totp_roll_value_uint8_t( + &scene_state->selected_control, + 1, + HoursInput, + ConfirmButton, + RollOverflowBehaviorStop); + if(scene_state->selected_control > Vibro) { + scene_state->y_offset = 128; + } else if(scene_state->selected_control > MinutesInput) { + scene_state->y_offset = 64; + } else { + scene_state->y_offset = 0; + } + break; + case InputKeyRight: + if(scene_state->selected_control == HoursInput) { + totp_roll_value_int8_t( + &scene_state->tz_offset_hours, 1, -12, 12, RollOverflowBehaviorStop); + } else if(scene_state->selected_control == MinutesInput) { + totp_roll_value_uint8_t( + &scene_state->tz_offset_minutes, 15, 0, 45, RollOverflowBehaviorRoll); + } else if(scene_state->selected_control == Sound) { + scene_state->notification_sound = !scene_state->notification_sound; + } else if(scene_state->selected_control == Vibro) { + scene_state->notification_vibro = !scene_state->notification_vibro; + } else if(scene_state->selected_control == BadUsb) { + scene_state->badusb_enabled = !scene_state->badusb_enabled; } - #ifdef TOTP_BADBT_TYPE_ENABLED - if(!scene_state->badbt_enabled && plugin_state->bt_type_code_worker_context != NULL) { - totp_bt_type_code_worker_free(plugin_state->bt_type_code_worker_context); - plugin_state->bt_type_code_worker_context = NULL; + else if(scene_state->selected_control == BadBt) { + scene_state->badbt_enabled = !scene_state->badbt_enabled; } #endif - + break; + case InputKeyLeft: + if(scene_state->selected_control == HoursInput) { + totp_roll_value_int8_t( + &scene_state->tz_offset_hours, -1, -12, 12, RollOverflowBehaviorStop); + } else if(scene_state->selected_control == MinutesInput) { + totp_roll_value_uint8_t( + &scene_state->tz_offset_minutes, -15, 0, 45, RollOverflowBehaviorRoll); + } else if(scene_state->selected_control == Sound) { + scene_state->notification_sound = !scene_state->notification_sound; + } else if(scene_state->selected_control == Vibro) { + scene_state->notification_vibro = !scene_state->notification_vibro; + } else if(scene_state->selected_control == BadUsb) { + scene_state->badusb_enabled = !scene_state->badusb_enabled; + } +#ifdef TOTP_BADBT_TYPE_ENABLED + else if(scene_state->selected_control == BadBt) { + scene_state->badbt_enabled = !scene_state->badbt_enabled; + } +#endif + break; + case InputKeyOk: + break; + case InputKeyBack: { totp_scene_director_activate_scene(plugin_state, TotpSceneTokenMenu); + break; } - break; - case InputKeyBack: { + default: + break; + } + } else if( + event->input.type == InputTypeRelease && event->input.key == InputKeyOk && + scene_state->selected_control == ConfirmButton) { + plugin_state->timezone_offset = + (float)scene_state->tz_offset_hours + (float)scene_state->tz_offset_minutes / 60.0f; + + plugin_state->notification_method = + (scene_state->notification_sound ? NotificationMethodSound : NotificationMethodNone) | + (scene_state->notification_vibro ? NotificationMethodVibro : NotificationMethodNone); + + plugin_state->automation_method = scene_state->badusb_enabled ? AutomationMethodBadUsb : + AutomationMethodNone; +#ifdef TOTP_BADBT_TYPE_ENABLED + plugin_state->automation_method |= scene_state->badbt_enabled ? AutomationMethodBadBt : + AutomationMethodNone; +#endif + + if(!totp_config_file_update_user_settings(plugin_state)) { + totp_dialogs_config_updating_error(plugin_state); + return false; + } + +#ifdef TOTP_BADBT_TYPE_ENABLED + if(!scene_state->badbt_enabled && plugin_state->bt_type_code_worker_context != NULL) { + totp_bt_type_code_worker_free(plugin_state->bt_type_code_worker_context); + plugin_state->bt_type_code_worker_context = NULL; + } +#endif + totp_scene_director_activate_scene(plugin_state, TotpSceneTokenMenu); - break; - } - default: - break; } return true; diff --git a/applications/external/totp/ui/scenes/authenticate/totp_scene_authenticate.c b/applications/external/totp/ui/scenes/authenticate/totp_scene_authenticate.c index 86e1e8e2b..218e5e397 100644 --- a/applications/external/totp/ui/scenes/authenticate/totp_scene_authenticate.c +++ b/applications/external/totp/ui/scenes/authenticate/totp_scene_authenticate.c @@ -83,38 +83,45 @@ bool totp_scene_authenticate_handle_event( return false; } - if(event->input.type != InputTypePress) { - return true; - } - - SceneState* scene_state = (SceneState*)plugin_state->current_scene_state; - - switch(event->input.key) { - case InputKeyUp: - if(scene_state->code_length < MAX_CODE_LENGTH) { - scene_state->code_input[scene_state->code_length] = PinCodeArrowUp; - scene_state->code_length++; + SceneState* scene_state = plugin_state->current_scene_state; + if(event->input.type == InputTypePress) { + switch(event->input.key) { + case InputKeyUp: + if(scene_state->code_length < MAX_CODE_LENGTH) { + scene_state->code_input[scene_state->code_length] = PinCodeArrowUp; + scene_state->code_length++; + } + break; + case InputKeyDown: + if(scene_state->code_length < MAX_CODE_LENGTH) { + scene_state->code_input[scene_state->code_length] = PinCodeArrowDown; + scene_state->code_length++; + } + break; + case InputKeyRight: + if(scene_state->code_length < MAX_CODE_LENGTH) { + scene_state->code_input[scene_state->code_length] = PinCodeArrowRight; + scene_state->code_length++; + } + break; + case InputKeyLeft: + if(scene_state->code_length < MAX_CODE_LENGTH) { + scene_state->code_input[scene_state->code_length] = PinCodeArrowLeft; + scene_state->code_length++; + } + break; + case InputKeyOk: + break; + case InputKeyBack: + if(scene_state->code_length > 0) { + scene_state->code_input[scene_state->code_length - 1] = 0; + scene_state->code_length--; + } + break; + default: + break; } - break; - case InputKeyDown: - if(scene_state->code_length < MAX_CODE_LENGTH) { - scene_state->code_input[scene_state->code_length] = PinCodeArrowDown; - scene_state->code_length++; - } - break; - case InputKeyRight: - if(scene_state->code_length < MAX_CODE_LENGTH) { - scene_state->code_input[scene_state->code_length] = PinCodeArrowRight; - scene_state->code_length++; - } - break; - case InputKeyLeft: - if(scene_state->code_length < MAX_CODE_LENGTH) { - scene_state->code_input[scene_state->code_length] = PinCodeArrowLeft; - scene_state->code_length++; - } - break; - case InputKeyOk: { + } else if(event->input.type == InputTypeRelease && event->input.key == InputKeyOk) { CryptoSeedIVResult seed_result = totp_crypto_seed_iv( plugin_state, &scene_state->code_input[0], scene_state->code_length); @@ -145,16 +152,6 @@ bool totp_scene_authenticate_handle_event( dialog_message_show(plugin_state->dialogs_app, message); dialog_message_free(message); } - break; - } - case InputKeyBack: - if(scene_state->code_length > 0) { - scene_state->code_input[scene_state->code_length - 1] = 0; - scene_state->code_length--; - } - break; - default: - break; } return true; diff --git a/applications/external/totp/ui/scenes/generate_token/totp_scene_generate_token.c b/applications/external/totp/ui/scenes/generate_token/totp_scene_generate_token.c index b111242dc..9b7b282d6 100644 --- a/applications/external/totp/ui/scenes/generate_token/totp_scene_generate_token.c +++ b/applications/external/totp/ui/scenes/generate_token/totp_scene_generate_token.c @@ -16,7 +16,7 @@ #ifdef TOTP_BADBT_TYPE_ENABLED #include "../../../workers/bt_type_code/bt_type_code.h" #endif -#include "../../fonts/mode-nine/mode_nine.h" +#include "../../fonts/active_font.h" #define PROGRESS_BAR_MARGIN (3) #define PROGRESS_BAR_HEIGHT (4) @@ -142,19 +142,19 @@ static void draw_totp_code(Canvas* const canvas, const PluginState* const plugin totp_config_get_token_iterator_context(plugin_state); uint8_t code_length = totp_token_info_iterator_get_current_token(iterator_context)->digits; uint8_t offset_x = scene_state->ui_precalculated_dimensions.code_offset_x; - uint8_t char_width = modeNine_15ptFontInfo.charInfo[0].width; + uint8_t char_width = TOTP_CODE_FONT_INFO.charInfo[0].width; uint8_t offset_x_inc = scene_state->ui_precalculated_dimensions.code_offset_x_inc; for(uint8_t i = 0; i < code_length; i++) { char ch = scene_state->last_code[i]; - if(ch >= modeNine_15ptFontInfo.startChar && ch <= modeNine_15ptFontInfo.endChar) { - uint8_t char_index = ch - modeNine_15ptFontInfo.startChar; + if(ch >= TOTP_CODE_FONT_INFO.startChar && ch <= TOTP_CODE_FONT_INFO.endChar) { + uint8_t char_index = ch - TOTP_CODE_FONT_INFO.startChar; canvas_draw_xbm( canvas, offset_x, scene_state->ui_precalculated_dimensions.code_offset_y, char_width, - modeNine_15ptFontInfo.height, - &modeNine_15ptFontInfo.data[modeNine_15ptFontInfo.charInfo[char_index].offset]); + TOTP_CODE_FONT_INFO.height, + &TOTP_CODE_FONT_INFO.data[TOTP_CODE_FONT_INFO.charInfo[char_index].offset]); } offset_x += offset_x_inc; @@ -172,15 +172,15 @@ static void on_new_token_code_generated(bool time_left, void* context) { SceneState* scene_state = plugin_state->current_scene_state; const TokenInfo* current_token = totp_token_info_iterator_get_current_token(iterator_context); - uint8_t char_width = modeNine_15ptFontInfo.charInfo[0].width; + uint8_t char_width = TOTP_CODE_FONT_INFO.charInfo[0].width; scene_state->ui_precalculated_dimensions.code_total_length = - current_token->digits * (char_width + modeNine_15ptFontInfo.spacePixels); + current_token->digits * (char_width + TOTP_CODE_FONT_INFO.spacePixels); scene_state->ui_precalculated_dimensions.code_offset_x = (SCREEN_WIDTH - scene_state->ui_precalculated_dimensions.code_total_length) >> 1; scene_state->ui_precalculated_dimensions.code_offset_x_inc = - char_width + modeNine_15ptFontInfo.spacePixels; + char_width + TOTP_CODE_FONT_INFO.spacePixels; scene_state->ui_precalculated_dimensions.code_offset_y = - SCREEN_HEIGHT_CENTER - (modeNine_15ptFontInfo.height >> 1); + SCREEN_HEIGHT_CENTER - (TOTP_CODE_FONT_INFO.height >> 1); if(time_left) { notification_message( @@ -381,54 +381,51 @@ bool totp_scene_generate_token_handle_event( return true; } #endif - } + } else if(event->input.type == InputTypePress || event->input.type == InputTypeRepeat) { + switch(event->input.key) { + case InputKeyUp: + break; + case InputKeyDown: + break; + case InputKeyRight: { + const TokenInfoIteratorContext* iterator_context = + totp_config_get_token_iterator_context(plugin_state); + size_t current_token_index = + totp_token_info_iterator_get_current_token_index(iterator_context); + totp_roll_value_size_t( + ¤t_token_index, + 1, + 0, + totp_token_info_iterator_get_total_count(iterator_context) - 1, + RollOverflowBehaviorRoll); - if(event->input.type != InputTypePress && event->input.type != InputTypeRepeat) { - return true; - } + update_totp_params(plugin_state, current_token_index); + break; + } + case InputKeyLeft: { + const TokenInfoIteratorContext* iterator_context = + totp_config_get_token_iterator_context(plugin_state); + size_t current_token_index = + totp_token_info_iterator_get_current_token_index(iterator_context); + totp_roll_value_size_t( + ¤t_token_index, + -1, + 0, + totp_token_info_iterator_get_total_count(iterator_context) - 1, + RollOverflowBehaviorRoll); - switch(event->input.key) { - case InputKeyUp: - break; - case InputKeyDown: - break; - case InputKeyRight: { - const TokenInfoIteratorContext* iterator_context = - totp_config_get_token_iterator_context(plugin_state); - size_t current_token_index = - totp_token_info_iterator_get_current_token_index(iterator_context); - totp_roll_value_size_t( - ¤t_token_index, - 1, - 0, - totp_token_info_iterator_get_total_count(iterator_context) - 1, - RollOverflowBehaviorRoll); - - update_totp_params(plugin_state, current_token_index); - break; - } - case InputKeyLeft: { - const TokenInfoIteratorContext* iterator_context = - totp_config_get_token_iterator_context(plugin_state); - size_t current_token_index = - totp_token_info_iterator_get_current_token_index(iterator_context); - totp_roll_value_size_t( - ¤t_token_index, - -1, - 0, - totp_token_info_iterator_get_total_count(iterator_context) - 1, - RollOverflowBehaviorRoll); - - update_totp_params(plugin_state, current_token_index); - break; - } - case InputKeyOk: + update_totp_params(plugin_state, current_token_index); + break; + } + case InputKeyOk: + break; + case InputKeyBack: + break; + default: + break; + } + } else if(event->input.type == InputTypeRelease && event->input.key == InputKeyOk) { totp_scene_director_activate_scene(plugin_state, TotpSceneTokenMenu); - break; - case InputKeyBack: - break; - default: - break; } return true; diff --git a/applications/external/totp/ui/scenes/token_menu/totp_scene_token_menu.c b/applications/external/totp/ui/scenes/token_menu/totp_scene_token_menu.c index a8c8de28a..1340b5a8e 100644 --- a/applications/external/totp/ui/scenes/token_menu/totp_scene_token_menu.c +++ b/applications/external/totp/ui/scenes/token_menu/totp_scene_token_menu.c @@ -82,38 +82,52 @@ bool totp_scene_token_menu_handle_event(const PluginEvent* const event, PluginSt } SceneState* scene_state = (SceneState*)plugin_state->current_scene_state; - if(event->input.type != InputTypePress) { - return true; - } - - switch(event->input.key) { - case InputKeyUp: { - const TokenInfoIteratorContext* iterator_context = - totp_config_get_token_iterator_context(plugin_state); - totp_roll_value_uint8_t( - &scene_state->selected_control, -1, AddNewToken, AppSettings, RollOverflowBehaviorRoll); - if(scene_state->selected_control == DeleteToken && - totp_token_info_iterator_get_total_count(iterator_context) == 0) { - scene_state->selected_control--; + if(event->input.type == InputTypePress) { + switch(event->input.key) { + case InputKeyUp: { + const TokenInfoIteratorContext* iterator_context = + totp_config_get_token_iterator_context(plugin_state); + totp_roll_value_uint8_t( + &scene_state->selected_control, + -1, + AddNewToken, + AppSettings, + RollOverflowBehaviorRoll); + if(scene_state->selected_control == DeleteToken && + totp_token_info_iterator_get_total_count(iterator_context) == 0) { + scene_state->selected_control--; + } + break; } - break; - } - case InputKeyDown: { - const TokenInfoIteratorContext* iterator_context = - totp_config_get_token_iterator_context(plugin_state); - totp_roll_value_uint8_t( - &scene_state->selected_control, 1, AddNewToken, AppSettings, RollOverflowBehaviorRoll); - if(scene_state->selected_control == DeleteToken && - totp_token_info_iterator_get_total_count(iterator_context) == 0) { - scene_state->selected_control++; + case InputKeyDown: { + const TokenInfoIteratorContext* iterator_context = + totp_config_get_token_iterator_context(plugin_state); + totp_roll_value_uint8_t( + &scene_state->selected_control, + 1, + AddNewToken, + AppSettings, + RollOverflowBehaviorRoll); + if(scene_state->selected_control == DeleteToken && + totp_token_info_iterator_get_total_count(iterator_context) == 0) { + scene_state->selected_control++; + } + break; } - break; - } - case InputKeyRight: - break; - case InputKeyLeft: - break; - case InputKeyOk: + case InputKeyRight: + break; + case InputKeyLeft: + break; + case InputKeyOk: + break; + case InputKeyBack: { + totp_scene_director_activate_scene(plugin_state, TotpSceneGenerateToken); + break; + } + default: + break; + } + } else if(event->input.type == InputTypeRelease && event->input.key == InputKeyOk) { switch(scene_state->selected_control) { case AddNewToken: { totp_scene_director_activate_scene(plugin_state, TotpSceneAddNewToken); @@ -153,13 +167,6 @@ bool totp_scene_token_menu_handle_event(const PluginEvent* const event, PluginSt default: break; } - break; - case InputKeyBack: { - totp_scene_director_activate_scene(plugin_state, TotpSceneGenerateToken); - break; - } - default: - break; } return true; diff --git a/applications/external/totp/workers/generate_totp_code/generate_totp_code.c b/applications/external/totp/workers/generate_totp_code/generate_totp_code.c index 7e9356c45..6dbe329fd 100644 --- a/applications/external/totp/workers/generate_totp_code/generate_totp_code.c +++ b/applications/external/totp/workers/generate_totp_code/generate_totp_code.c @@ -25,18 +25,21 @@ static const char* STEAM_ALGO_ALPHABET = "23456789BCDFGHJKMNPQRTVWXY"; static void int_token_to_str(uint64_t i_token_code, char* str, TokenDigitsCount len, TokenHashAlgo algo) { - str[len] = '\0'; + char* last_char = str + len; + *last_char = '\0'; if(i_token_code == OTP_ERROR) { - memset(&str[0], '-', len); + memset(str, '-', len); } else { if(algo == STEAM) { - for(uint8_t i = 0; i < len; i++) { - str[i] = STEAM_ALGO_ALPHABET[i_token_code % 26]; + char* s = str; + for(uint8_t i = 0; i < len; i++, s++) { + *s = STEAM_ALGO_ALPHABET[i_token_code % 26]; i_token_code = i_token_code / 26; } } else { - for(int8_t i = len - 1; i >= 0; i--) { - str[i] = CONVERT_DIGIT_TO_CHAR(i_token_code % 10); + char* s = --last_char; + for(int8_t i = len - 1; i >= 0; i--, s--) { + *s = CONVERT_DIGIT_TO_CHAR(i_token_code % 10); i_token_code = i_token_code / 10; } } diff --git a/applications/external/totp/workers/type_code_common.c b/applications/external/totp/workers/type_code_common.c index bf5818ab2..bc42fadaa 100644 --- a/applications/external/totp/workers/type_code_common.c +++ b/applications/external/totp/workers/type_code_common.c @@ -47,11 +47,12 @@ void totp_type_code_worker_execute_automation( TokenAutomationFeature features) { furi_delay_ms(500); uint8_t i = 0; + char cb_char; - while(i < code_buffer_size && code_buffer[i] != 0) { - uint8_t char_index = CONVERT_CHAR_TO_DIGIT(code_buffer[i]); + while(i < code_buffer_size && (cb_char = code_buffer[i]) != 0) { + uint8_t char_index = CONVERT_CHAR_TO_DIGIT(cb_char); if(char_index > 9) { - char_index = code_buffer[i] - 0x41 + 10; + char_index = cb_char - 0x41 + 10; } if(char_index > 35) break; From b9397693a2d7d781126f77535938ad6148193f5f Mon Sep 17 00:00:00 2001 From: MX <10697207+xMasterX@users.noreply.github.com> Date: Fri, 26 May 2023 15:09:10 +0300 Subject: [PATCH 24/28] Setting to change fonts in TOTP opensource != selling plugin builds / do you agree? If you don't agree - and you think I did a bad thing here by allowing users to select fonts without payment, let me know Why I did that? - cuz I'm not making private "donation only" builds myself, while having no main job, and living only on donations, so I don't like stuff like that in opensource projects You should support author if you like this plugin here: https://github.com/akopachov/flipper-zero_authenticator --- applications/external/totp/features_config.h | 4 +- .../external/totp/services/config/config.c | 38 ++++++++++ .../external/totp/services/config/config.h | 7 ++ .../external/totp/services/config/constants.h | 1 + .../config/migrations/common_migration.c | 9 +++ applications/external/totp/totp_app.c | 1 + .../external/totp/types/plugin_state.h | 5 ++ .../external/totp/ui/fonts/active_font.h | 15 ---- .../scenes/app_settings/totp_app_settings.c | 37 ++++++++-- .../totp_scene_generate_token.c | 73 ++++++++++++++++--- .../totp/workers/bt_type_code/bt_type_code.c | 12 +-- 11 files changed, 163 insertions(+), 39 deletions(-) diff --git a/applications/external/totp/features_config.h b/applications/external/totp/features_config.h index 683eff2fc..c789af27b 100644 --- a/applications/external/totp/features_config.h +++ b/applications/external/totp/features_config.h @@ -7,8 +7,8 @@ // List of compatible firmwares #define TOTP_FIRMWARE_OFFICIAL_STABLE 1 #define TOTP_FIRMWARE_OFFICIAL_DEV 2 -#define TOTP_FIRMWARE_XTREME 3 +#define TOTP_FIRMWARE_UL_XFW 3 // XFW and UL now has same bluetooth mac/advname changing API // End of list // Target firmware to build for -#define TOTP_TARGET_FIRMWARE TOTP_FIRMWARE_XTREME \ No newline at end of file +#define TOTP_TARGET_FIRMWARE TOTP_FIRMWARE_UL_XFW diff --git a/applications/external/totp/services/config/config.c b/applications/external/totp/services/config/config.c index f97bc6b26..7b935e1ea 100644 --- a/applications/external/totp/services/config/config.c +++ b/applications/external/totp/services/config/config.c @@ -177,6 +177,10 @@ static bool totp_open_config_file(Storage* storage, FlipperFormat** file) { flipper_format_write_uint32( fff_data_file, TOTP_CONFIG_KEY_AUTOMATION_METHOD, &tmp_uint32, 1); + // Default Font = 0 + tmp_uint32 = 0; + flipper_format_write_uint32(fff_data_file, TOTP_CONFIG_KEY_SELECTED_FONT, &tmp_uint32, 1); + if(!flipper_format_rewind(fff_data_file)) { totp_close_config_file(fff_data_file); FURI_LOG_E(LOGGING_TAG, "Rewind error"); @@ -259,6 +263,24 @@ bool totp_config_file_update_automation_method(const PluginState* plugin_state) return update_result; } +bool totp_config_file_update_selected_font(const PluginState* plugin_state) { + FlipperFormat* file = plugin_state->config_file_context->config_file; + flipper_format_rewind(file); + bool update_result = false; + + do { + uint32_t tmp_uint32 = plugin_state->selected_font; + if(!flipper_format_insert_or_update_uint32( + file, TOTP_CONFIG_KEY_SELECTED_FONT, &tmp_uint32, 1)) { + break; + } + + update_result = true; + } while(false); + + return update_result; +} + bool totp_config_file_update_user_settings(const PluginState* plugin_state) { FlipperFormat* file = plugin_state->config_file_context->config_file; flipper_format_rewind(file); @@ -280,6 +302,12 @@ bool totp_config_file_update_user_settings(const PluginState* plugin_state) { break; } + tmp_uint32 = plugin_state->selected_font; + if(!flipper_format_insert_or_update_uint32( + file, TOTP_CONFIG_KEY_SELECTED_FONT, &tmp_uint32, 1)) { + break; + } + update_result = true; } while(false); @@ -428,6 +456,16 @@ bool totp_config_file_load(PluginState* const plugin_state) { plugin_state->automation_method = tmp_uint32; + // Load selected font + flipper_format_rewind(fff_data_file); + + if(!flipper_format_read_uint32( + fff_data_file, TOTP_CONFIG_KEY_SELECTED_FONT, &tmp_uint32, 1)) { + tmp_uint32 = 0; + } + + plugin_state->selected_font = tmp_uint32; + plugin_state->config_file_context = malloc(sizeof(ConfigFileContext)); furi_check(plugin_state->config_file_context != NULL); plugin_state->config_file_context->storage = storage; diff --git a/applications/external/totp/services/config/config.h b/applications/external/totp/services/config/config.h index d2fe957c6..cc278ab5a 100644 --- a/applications/external/totp/services/config/config.h +++ b/applications/external/totp/services/config/config.h @@ -44,6 +44,13 @@ bool totp_config_file_update_notification_method(const PluginState* plugin_state */ bool totp_config_file_update_automation_method(const PluginState* plugin_state); +/** + * @brief Updates selected font in an application config file + * @param plugin_state application state + * @return Config file update result + */ +bool totp_config_file_update_selected_font(const PluginState* plugin_state); + /** * @brief Updates application user settings * @param plugin_state application state diff --git a/applications/external/totp/services/config/constants.h b/applications/external/totp/services/config/constants.h index 3a33c80b3..27a4f56c4 100644 --- a/applications/external/totp/services/config/constants.h +++ b/applications/external/totp/services/config/constants.h @@ -18,3 +18,4 @@ #define TOTP_CONFIG_KEY_PINSET "PinIsSet" #define TOTP_CONFIG_KEY_NOTIFICATION_METHOD "NotificationMethod" #define TOTP_CONFIG_KEY_AUTOMATION_METHOD "AutomationMethod" +#define TOTP_CONFIG_KEY_SELECTED_FONT "SelectedFont" diff --git a/applications/external/totp/services/config/migrations/common_migration.c b/applications/external/totp/services/config/migrations/common_migration.c index 07026fb1f..9cee422a5 100644 --- a/applications/external/totp/services/config/migrations/common_migration.c +++ b/applications/external/totp/services/config/migrations/common_migration.c @@ -58,6 +58,15 @@ bool totp_config_migrate_to_latest( flipper_format_rewind(fff_backup_data_file); + // Font + + if(flipper_format_read_string( + fff_backup_data_file, TOTP_CONFIG_KEY_SELECTED_FONT, temp_str)) { + flipper_format_write_string(fff_data_file, TOTP_CONFIG_KEY_SELECTED_FONT, temp_str); + } + + flipper_format_rewind(fff_backup_data_file); + while(true) { if(!flipper_format_read_string( fff_backup_data_file, TOTP_CONFIG_KEY_TOKEN_NAME, temp_str)) { diff --git a/applications/external/totp/totp_app.c b/applications/external/totp/totp_app.c index f620a3b48..8b0a8c1fa 100644 --- a/applications/external/totp/totp_app.c +++ b/applications/external/totp/totp_app.c @@ -107,6 +107,7 @@ static bool totp_activate_initial_scene(PluginState* const plugin_state) { } static bool totp_plugin_state_init(PluginState* const plugin_state) { + plugin_state->selected_font = 0; plugin_state->gui = furi_record_open(RECORD_GUI); plugin_state->notification_app = furi_record_open(RECORD_NOTIFICATION); plugin_state->dialogs_app = furi_record_open(RECORD_DIALOGS); diff --git a/applications/external/totp/types/plugin_state.h b/applications/external/totp/types/plugin_state.h index c20594f37..97d126330 100644 --- a/applications/external/totp/types/plugin_state.h +++ b/applications/external/totp/types/plugin_state.h @@ -80,6 +80,11 @@ typedef struct { */ NotificationMethod notification_method; + /** + * @brief Numbers Font + */ + uint8_t selected_font; + /** * @brief Main rendering loop mutex */ diff --git a/applications/external/totp/ui/fonts/active_font.h b/applications/external/totp/ui/fonts/active_font.h index 58c1e2d17..054fa4a55 100644 --- a/applications/external/totp/ui/fonts/active_font.h +++ b/applications/external/totp/ui/fonts/active_font.h @@ -3,25 +3,10 @@ #include "../../features_config.h" #include "font_info.h" -#if TOTP_FONT == TOTP_FONT_MODENINE #include "mode_nine/mode_nine.h" -#define TOTP_CODE_FONT_INFO modeNine_15ptFontInfo -#elif TOTP_FONT == TOTP_FONT_REDHATMONO #include "redhat_mono/redhat_mono.h" -#define TOTP_CODE_FONT_INFO redHatMono_16ptFontInfo -#elif TOTP_FONT == TOTP_FONT_BEDSTEAD #include "bedstead/bedstead.h" -#define TOTP_CODE_FONT_INFO bedstead_17ptFontInfo -#elif TOTP_FONT == TOTP_FONT_ZECTOR #include "zector/zector.h" -#define TOTP_CODE_FONT_INFO zector_18ptFontInfo -#elif TOTP_FONT == TOTP_FONT_712SERIF #include "712serif/712serif.h" -#define TOTP_CODE_FONT_INFO _712Serif_24ptFontInfo -#elif TOTP_FONT == TOTP_FONT_GRAPH35PIX #include "graph35pix/graph35pix.h" -#define TOTP_CODE_FONT_INFO graph35pix_12ptFontInfo -#elif TOTP_FONT == TOTP_FONT_KARMAFUTURE #include "karma_future/karma_future.h" -#define TOTP_CODE_FONT_INFO karmaFuture_14ptFontInfo -#endif \ No newline at end of file diff --git a/applications/external/totp/ui/scenes/app_settings/totp_app_settings.c b/applications/external/totp/ui/scenes/app_settings/totp_app_settings.c index 54659946d..0bdc7aee3 100644 --- a/applications/external/totp/ui/scenes/app_settings/totp_app_settings.c +++ b/applications/external/totp/ui/scenes/app_settings/totp_app_settings.c @@ -22,6 +22,7 @@ typedef enum { MinutesInput, Sound, Vibro, + FontSelector, BadUsb, #ifdef TOTP_BADBT_TYPE_ENABLED BadBt, @@ -34,6 +35,7 @@ typedef struct { uint8_t tz_offset_minutes; bool notification_sound; bool notification_vibro; + uint8_t selected_font; bool badusb_enabled; #ifdef TOTP_BADBT_TYPE_ENABLED bool badbt_enabled; @@ -54,6 +56,7 @@ void totp_scene_app_settings_activate(PluginState* plugin_state) { scene_state->notification_sound = plugin_state->notification_method & NotificationMethodSound; scene_state->notification_vibro = plugin_state->notification_method & NotificationMethodVibro; scene_state->badusb_enabled = plugin_state->automation_method & AutomationMethodBadUsb; + scene_state->selected_font = plugin_state->selected_font; #ifdef TOTP_BADBT_TYPE_ENABLED scene_state->badbt_enabled = plugin_state->automation_method & AutomationMethodBadBt; #endif @@ -111,27 +114,38 @@ void totp_scene_app_settings_render(Canvas* const canvas, const PluginState* plu canvas_set_font(canvas, FontPrimary); canvas_draw_str_aligned( - canvas, 0, 64 - scene_state->y_offset, AlignLeft, AlignTop, "Notifications"); + canvas, 0, 64 - scene_state->y_offset, AlignLeft, AlignTop, "Notifications / UI"); canvas_set_font(canvas, FontSecondary); - canvas_draw_str_aligned(canvas, 0, 81 - scene_state->y_offset, AlignLeft, AlignTop, "Sound:"); + canvas_draw_str_aligned(canvas, 0, 78 - scene_state->y_offset, AlignLeft, AlignTop, "Sound:"); ui_control_select_render( canvas, 36, - 74 - scene_state->y_offset, + 71 - scene_state->y_offset, SCREEN_WIDTH - 36, YES_NO_LIST[scene_state->notification_sound], scene_state->selected_control == Sound); - canvas_draw_str_aligned(canvas, 0, 99 - scene_state->y_offset, AlignLeft, AlignTop, "Vibro:"); + canvas_draw_str_aligned(canvas, 0, 94 - scene_state->y_offset, AlignLeft, AlignTop, "Vibro:"); ui_control_select_render( canvas, 36, - 92 - scene_state->y_offset, + 87 - scene_state->y_offset, SCREEN_WIDTH - 36, YES_NO_LIST[scene_state->notification_vibro], scene_state->selected_control == Vibro); + two_digit_to_str(scene_state->selected_font, &tmp_str[0]); + canvas_draw_str_aligned( + canvas, 0, 110 - scene_state->y_offset, AlignLeft, AlignTop, "UI Font:"); + ui_control_select_render( + canvas, + 36, + 103 - scene_state->y_offset, + SCREEN_WIDTH - 36, + &tmp_str[0], + scene_state->selected_control == FontSelector); + canvas_draw_icon( canvas, SCREEN_WIDTH_CENTER - 5, 123 - scene_state->y_offset, &I_totp_arrow_bottom_10x5); @@ -192,7 +206,7 @@ bool totp_scene_app_settings_handle_event( HoursInput, ConfirmButton, RollOverflowBehaviorStop); - if(scene_state->selected_control > Vibro) { + if(scene_state->selected_control > FontSelector) { scene_state->y_offset = 128; } else if(scene_state->selected_control > MinutesInput) { scene_state->y_offset = 64; @@ -207,7 +221,7 @@ bool totp_scene_app_settings_handle_event( HoursInput, ConfirmButton, RollOverflowBehaviorStop); - if(scene_state->selected_control > Vibro) { + if(scene_state->selected_control > FontSelector) { scene_state->y_offset = 128; } else if(scene_state->selected_control > MinutesInput) { scene_state->y_offset = 64; @@ -234,6 +248,10 @@ bool totp_scene_app_settings_handle_event( scene_state->badbt_enabled = !scene_state->badbt_enabled; } #endif + else if(scene_state->selected_control == FontSelector) { + totp_roll_value_uint8_t( + &scene_state->selected_font, 1, 0, 6, RollOverflowBehaviorStop); + } break; case InputKeyLeft: if(scene_state->selected_control == HoursInput) { @@ -254,6 +272,10 @@ bool totp_scene_app_settings_handle_event( scene_state->badbt_enabled = !scene_state->badbt_enabled; } #endif + else if(scene_state->selected_control == FontSelector) { + totp_roll_value_uint8_t( + &scene_state->selected_font, -1, 0, 6, RollOverflowBehaviorStop); + } break; case InputKeyOk: break; @@ -280,6 +302,7 @@ bool totp_scene_app_settings_handle_event( plugin_state->automation_method |= scene_state->badbt_enabled ? AutomationMethodBadBt : AutomationMethodNone; #endif + plugin_state->selected_font = scene_state->selected_font; if(!totp_config_file_update_user_settings(plugin_state)) { totp_dialogs_config_updating_error(plugin_state); diff --git a/applications/external/totp/ui/scenes/generate_token/totp_scene_generate_token.c b/applications/external/totp/ui/scenes/generate_token/totp_scene_generate_token.c index 9b7b282d6..e55f34ea2 100644 --- a/applications/external/totp/ui/scenes/generate_token/totp_scene_generate_token.c +++ b/applications/external/totp/ui/scenes/generate_token/totp_scene_generate_token.c @@ -142,19 +142,46 @@ static void draw_totp_code(Canvas* const canvas, const PluginState* const plugin totp_config_get_token_iterator_context(plugin_state); uint8_t code_length = totp_token_info_iterator_get_current_token(iterator_context)->digits; uint8_t offset_x = scene_state->ui_precalculated_dimensions.code_offset_x; - uint8_t char_width = TOTP_CODE_FONT_INFO.charInfo[0].width; + const FONT_INFO* current_font; + switch(plugin_state->selected_font) { + case 0: + current_font = &modeNine_15ptFontInfo; + break; + case 1: + current_font = &redHatMono_16ptFontInfo; + break; + case 2: + current_font = &bedstead_17ptFontInfo; + break; + case 3: + current_font = &zector_18ptFontInfo; + break; + case 4: + current_font = &_712Serif_24ptFontInfo; + break; + case 5: + current_font = &graph35pix_12ptFontInfo; + break; + case 6: + current_font = &karmaFuture_14ptFontInfo; + break; + default: + current_font = &modeNine_15ptFontInfo; + break; + } + uint8_t char_width = current_font->charInfo[0].width; uint8_t offset_x_inc = scene_state->ui_precalculated_dimensions.code_offset_x_inc; for(uint8_t i = 0; i < code_length; i++) { char ch = scene_state->last_code[i]; - if(ch >= TOTP_CODE_FONT_INFO.startChar && ch <= TOTP_CODE_FONT_INFO.endChar) { - uint8_t char_index = ch - TOTP_CODE_FONT_INFO.startChar; + if(ch >= current_font->startChar && ch <= current_font->endChar) { + uint8_t char_index = ch - current_font->startChar; canvas_draw_xbm( canvas, offset_x, scene_state->ui_precalculated_dimensions.code_offset_y, char_width, - TOTP_CODE_FONT_INFO.height, - &TOTP_CODE_FONT_INFO.data[TOTP_CODE_FONT_INFO.charInfo[char_index].offset]); + current_font->height, + ¤t_font->data[current_font->charInfo[char_index].offset]); } offset_x += offset_x_inc; @@ -172,15 +199,43 @@ static void on_new_token_code_generated(bool time_left, void* context) { SceneState* scene_state = plugin_state->current_scene_state; const TokenInfo* current_token = totp_token_info_iterator_get_current_token(iterator_context); - uint8_t char_width = TOTP_CODE_FONT_INFO.charInfo[0].width; + const FONT_INFO* current_font; + switch(plugin_state->selected_font) { + case 0: + current_font = &modeNine_15ptFontInfo; + break; + case 1: + current_font = &redHatMono_16ptFontInfo; + break; + case 2: + current_font = &bedstead_17ptFontInfo; + break; + case 3: + current_font = &zector_18ptFontInfo; + break; + case 4: + current_font = &_712Serif_24ptFontInfo; + break; + case 5: + current_font = &graph35pix_12ptFontInfo; + break; + case 6: + current_font = &karmaFuture_14ptFontInfo; + break; + default: + current_font = &modeNine_15ptFontInfo; + break; + } + + uint8_t char_width = current_font->charInfo[0].width; scene_state->ui_precalculated_dimensions.code_total_length = - current_token->digits * (char_width + TOTP_CODE_FONT_INFO.spacePixels); + current_token->digits * (char_width + current_font->spacePixels); scene_state->ui_precalculated_dimensions.code_offset_x = (SCREEN_WIDTH - scene_state->ui_precalculated_dimensions.code_total_length) >> 1; scene_state->ui_precalculated_dimensions.code_offset_x_inc = - char_width + TOTP_CODE_FONT_INFO.spacePixels; + char_width + current_font->spacePixels; scene_state->ui_precalculated_dimensions.code_offset_y = - SCREEN_HEIGHT_CENTER - (TOTP_CODE_FONT_INFO.height >> 1); + SCREEN_HEIGHT_CENTER - (current_font->height >> 1); if(time_left) { notification_message( diff --git a/applications/external/totp/workers/bt_type_code/bt_type_code.c b/applications/external/totp/workers/bt_type_code/bt_type_code.c index bf55dba6a..8024dba78 100644 --- a/applications/external/totp/workers/bt_type_code/bt_type_code.c +++ b/applications/external/totp/workers/bt_type_code/bt_type_code.c @@ -13,7 +13,7 @@ #include "../type_code_common.h" #include "../../features_config.h" -#if TOTP_TARGET_FIRMWARE == TOTP_FIRMWARE_XTREME +#if TOTP_TARGET_FIRMWARE == TOTP_FIRMWARE_UL_XFW #define TOTP_BT_WORKER_BT_ADV_NAME_MAX_LEN FURI_HAL_BT_ADV_NAME_LENGTH #define TOTP_BT_WORKER_BT_MAC_ADDRESS_LEN GAP_MAC_ADDR_SIZE #endif @@ -29,7 +29,7 @@ struct TotpBtTypeCodeWorkerContext { Bt* bt; bool is_advertising; bool is_connected; -#if TOTP_TARGET_FIRMWARE == TOTP_FIRMWARE_XTREME +#if TOTP_TARGET_FIRMWARE == TOTP_FIRMWARE_UL_XFW char previous_bt_name[TOTP_BT_WORKER_BT_ADV_NAME_MAX_LEN]; uint8_t previous_bt_mac[TOTP_BT_WORKER_BT_MAC_ADDRESS_LEN]; #endif @@ -39,7 +39,7 @@ static inline bool totp_type_code_worker_stop_requested() { return furi_thread_flags_get() & TotpBtTypeCodeWorkerEventStop; } -#if TOTP_TARGET_FIRMWARE == TOTP_FIRMWARE_XTREME +#if TOTP_TARGET_FIRMWARE == TOTP_FIRMWARE_UL_XFW static void totp_type_code_worker_bt_set_app_mac(uint8_t* mac) { uint8_t max_i; size_t uid_size = furi_hal_version_uid_size(); @@ -161,7 +161,7 @@ TotpBtTypeCodeWorkerContext* totp_bt_type_code_worker_init() { furi_delay_ms(200); bt_keys_storage_set_storage_path(context->bt, HID_BT_KEYS_STORAGE_PATH); -#if TOTP_TARGET_FIRMWARE == TOTP_FIRMWARE_XTREME +#if TOTP_TARGET_FIRMWARE == TOTP_FIRMWARE_UL_XFW memcpy( &context->previous_bt_name[0], furi_hal_bt_get_profile_adv_name(FuriHalBtProfileHidKeyboard), @@ -184,7 +184,7 @@ TotpBtTypeCodeWorkerContext* totp_bt_type_code_worker_init() { furi_hal_bt_start_advertising(); -#if TOTP_TARGET_FIRMWARE == TOTP_FIRMWARE_XTREME +#if TOTP_TARGET_FIRMWARE == TOTP_FIRMWARE_UL_XFW bt_enable_peer_key_update(context->bt); #endif @@ -211,7 +211,7 @@ void totp_bt_type_code_worker_free(TotpBtTypeCodeWorkerContext* context) { furi_delay_ms(200); bt_keys_storage_set_default_path(context->bt); -#if TOTP_TARGET_FIRMWARE == TOTP_FIRMWARE_XTREME +#if TOTP_TARGET_FIRMWARE == TOTP_FIRMWARE_UL_XFW furi_hal_bt_set_profile_adv_name(FuriHalBtProfileHidKeyboard, context->previous_bt_name); furi_hal_bt_set_profile_mac_addr(FuriHalBtProfileHidKeyboard, context->previous_bt_mac); #endif From 5a7cd203cdfeef9dd26fe14e89990ab0ef482a9c Mon Sep 17 00:00:00 2001 From: Yukai Li Date: Fri, 26 May 2023 06:50:59 -0600 Subject: [PATCH 25/28] nfc: Fix MFUL tearing flags read (#2669) Co-authored-by: gornekich --- lib/nfc/protocols/mifare_ultralight.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/nfc/protocols/mifare_ultralight.c b/lib/nfc/protocols/mifare_ultralight.c index 0e28c0074..6960bd2a1 100644 --- a/lib/nfc/protocols/mifare_ultralight.c +++ b/lib/nfc/protocols/mifare_ultralight.c @@ -702,7 +702,7 @@ bool mf_ultralight_read_tearing_flags(FuriHalNfcTxRxContext* tx_rx, MfUltralight FURI_LOG_D(TAG, "Reading tearing flags"); for(size_t i = 0; i < 3; i++) { tx_rx->tx_data[0] = MF_UL_CHECK_TEARING; - tx_rx->rx_data[1] = i; + tx_rx->tx_data[1] = i; tx_rx->tx_bits = 16; tx_rx->tx_rx_type = FuriHalNfcTxRxTypeDefault; if(!furi_hal_nfc_tx_rx(tx_rx, 50)) { From 4f054ed53595d901b5fa755eb3402ae1e0231fd1 Mon Sep 17 00:00:00 2001 From: hedger Date: Fri, 26 May 2023 16:57:24 +0400 Subject: [PATCH 26/28] api: added toolbox/api_lock.h (#2702) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: あく --- firmware/targets/f18/api_symbols.csv | 3 ++- firmware/targets/f7/api_symbols.csv | 1 + lib/toolbox/SConscript | 1 + 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/firmware/targets/f18/api_symbols.csv b/firmware/targets/f18/api_symbols.csv index b7abdfc05..68248a6d2 100644 --- a/firmware/targets/f18/api_symbols.csv +++ b/firmware/targets/f18/api_symbols.csv @@ -129,6 +129,7 @@ Header,+,lib/one_wire/maxim_crc.h,, Header,+,lib/one_wire/one_wire_host.h,, Header,+,lib/one_wire/one_wire_slave.h,, Header,+,lib/print/wrappers.h,, +Header,+,lib/pulse_reader/pulse_reader.h,, Header,+,lib/stm32wb_hal/Inc/stm32wbxx_ll_adc.h,, Header,+,lib/stm32wb_hal/Inc/stm32wbxx_ll_bus.h,, Header,+,lib/stm32wb_hal/Inc/stm32wbxx_ll_comp.h,, @@ -156,7 +157,7 @@ Header,+,lib/stm32wb_hal/Inc/stm32wbxx_ll_tim.h,, Header,+,lib/stm32wb_hal/Inc/stm32wbxx_ll_usart.h,, Header,+,lib/stm32wb_hal/Inc/stm32wbxx_ll_utils.h,, Header,+,lib/stm32wb_hal/Inc/stm32wbxx_ll_wwdg.h,, -Header,+,lib/pulse_reader/pulse_reader.h,, +Header,+,lib/toolbox/api_lock.h,, Header,+,lib/toolbox/args.h,, Header,+,lib/toolbox/crc32_calc.h,, Header,+,lib/toolbox/dir_walk.h,, diff --git a/firmware/targets/f7/api_symbols.csv b/firmware/targets/f7/api_symbols.csv index 15c19091e..aebfc9072 100644 --- a/firmware/targets/f7/api_symbols.csv +++ b/firmware/targets/f7/api_symbols.csv @@ -190,6 +190,7 @@ Header,+,lib/subghz/subghz_setting.h,, Header,+,lib/subghz/subghz_tx_rx_worker.h,, Header,+,lib/subghz/subghz_worker.h,, Header,+,lib/subghz/transmitter.h,, +Header,+,lib/toolbox/api_lock.h,, Header,+,lib/toolbox/args.h,, Header,+,lib/toolbox/crc32_calc.h,, Header,+,lib/toolbox/dir_walk.h,, diff --git a/lib/toolbox/SConscript b/lib/toolbox/SConscript index 4e158e30e..6084969c4 100644 --- a/lib/toolbox/SConscript +++ b/lib/toolbox/SConscript @@ -8,6 +8,7 @@ env.Append( "#/lib/toolbox", ], SDK_HEADERS=[ + File("api_lock.h"), File("manchester_decoder.h"), File("manchester_encoder.h"), File("path.h"), From cce0485e75f39c3a7ef504054f15b819deeb7e0a Mon Sep 17 00:00:00 2001 From: technobulb <84107091+technobulb@users.noreply.github.com> Date: Fri, 26 May 2023 09:12:21 -0400 Subject: [PATCH 27/28] Update ac.ir (#2701) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: あく --- assets/resources/infrared/assets/ac.ir | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/assets/resources/infrared/assets/ac.ir b/assets/resources/infrared/assets/ac.ir index cfa62f6a2..e06c95f71 100644 --- a/assets/resources/infrared/assets/ac.ir +++ b/assets/resources/infrared/assets/ac.ir @@ -408,3 +408,29 @@ type: raw frequency: 38000 duty_cycle: 0.330000 data: 3108 3851 2062 1793 2006 1821 1103 839 2031 859 1085 829 1081 833 1079 836 1045 1911 1973 897 1015 898 1016 899 1041 871 1016 899 1014 898 1015 899 1015 899 1014 899 1041 872 1015 899 1041 872 1041 872 1015 899 1015 899 1041 873 1014 899 1041 873 1014 899 1014 1883 1975 900 3045 3886 1997 1856 1945 1857 1012 927 1945 900 1013 901 1012 901 1013 901 1012 1859 1999 901 1012 930 1012 903 1011 903 1010 903 1011 902 1012 960 1011 928 986 932 1010 903 1011 928 1015 928 985 929 985 928 1014 928 985 929 985 929 984 929 985 928 986 1915 1971 928 3017 3915 1942 1885 1943 1885 985 930 1971 929 984 930 983 930 984 930 984 1887 1942 929 983 960 983 931 982 931 983 932 981 958 985 958 956 958 984 959 954 931 983 932 981 959 955 932 982 959 954 960 982 961 983 933 955 988 955 985 929 1943 1915 958 4003 +# +# Model: Danby DAC060EB7WDB +name: Off +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 4402 4442 527 1629 529 549 529 1628 530 550 529 548 531 549 530 550 529 1630 528 549 530 549 529 549 530 1630 527 1629 529 1630 528 548 530 550 529 547 531 1628 530 1629 529 1628 530 1628 529 1628 530 1628 530 549 530 1628 530 1628 530 1627 531 1628 530 1627 531 1631 527 1629 529 1628 530 1627 531 1628 530 1628 530 1629 529 1627 531 1627 531 1628 529 1627 531 1627 531 1629 529 1627 530 549 529 549 530 549 530 1628 529 1627 530 5234 4401 4440 530 550 528 1628 529 549 530 1628 529 1629 528 1626 531 1628 529 550 529 1628 530 1627 531 1629 529 549 529 548 530 549 530 1628 529 1628 530 1627 530 547 532 547 532 547 531 548 531 548 530 548 531 1626 531 549 530 547 531 547 531 548 530 548 530 549 530 548 531 546 532 578 500 547 532 548 531 548 531 548 530 548 531 548 530 548 531 547 531 547 532 547 531 1627 531 1627 530 1626 532 547 531 547 532 +# +name: Dh +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 4454 4387 586 1573 585 494 584 1571 586 494 584 493 585 524 554 493 531 1626 586 1573 585 494 585 492 586 492 586 494 585 493 585 493 586 1571 586 493 585 1572 531 1627 530 549 584 494 586 1571 587 1572 529 1628 529 1628 530 1627 530 1626 532 1627 531 1626 532 1628 529 1627 531 1626 531 1627 531 1627 587 1569 532 1625 533 1626 532 1626 532 1627 531 1627 530 548 531 1626 532 1627 531 548 531 1627 531 548 531 546 532 547 531 5233 4401 4443 530 548 530 1627 530 547 531 1627 531 1626 531 1626 531 1627 530 549 530 548 530 1627 531 1627 531 1627 530 1627 531 1627 531 1626 531 548 530 1627 530 547 532 547 532 1627 531 1627 532 546 531 547 531 548 530 548 530 548 531 548 531 548 530 548 530 549 530 548 531 548 531 548 530 547 532 549 529 548 530 548 531 547 532 548 530 548 531 1627 530 548 530 548 531 1626 533 546 531 1627 530 1627 532 1626 530 +# +name: Cool_hi +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 4492 4354 619 1537 619 459 621 1537 622 455 623 456 623 457 622 456 623 1535 622 1536 622 458 621 456 623 1536 621 1535 623 456 622 456 623 457 621 456 531 1627 621 1536 622 456 622 457 622 455 623 458 621 458 621 1537 621 1536 620 1539 618 1538 531 1628 531 1627 530 1628 530 1628 530 1627 531 1628 530 1628 530 1628 531 1627 530 1629 529 1628 529 1628 530 549 530 1627 531 1628 530 1628 530 1627 586 494 530 1627 530 549 530 5232 4400 4443 586 492 587 1571 587 493 585 1572 530 1628 586 1572 586 1572 586 492 587 493 586 1572 586 1571 586 492 587 493 585 1572 531 1627 585 1573 585 1572 585 492 586 494 585 1572 586 1571 531 1627 531 1628 530 1627 587 491 531 548 587 492 530 548 530 547 532 548 531 547 532 547 531 548 531 547 532 547 531 548 588 491 530 547 589 490 531 547 532 1626 532 548 531 548 531 547 532 547 532 1627 531 548 531 1626 532 +# +name: Cool_lo +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 4401 4441 528 1629 529 550 528 1628 529 551 528 550 528 551 527 551 528 1629 529 1629 529 550 529 1630 528 551 528 549 530 550 529 551 528 549 529 550 529 1629 529 1628 530 549 530 1629 529 550 529 1628 529 1629 529 1631 527 1628 530 1628 529 1629 528 1628 530 1629 529 1629 529 1629 529 1629 528 1629 529 1629 529 1630 528 1629 529 1629 529 1628 529 1629 528 551 528 1629 529 550 529 550 530 548 529 1631 527 551 528 1629 529 5235 4402 4439 530 550 528 1629 529 549 530 1628 529 1629 529 1628 530 1629 529 549 530 550 529 1628 530 552 526 1628 529 1628 530 1628 530 1627 531 1628 529 1629 528 551 528 550 529 1628 530 550 528 1628 529 549 529 550 528 550 529 549 530 548 530 551 528 550 528 578 500 550 529 550 529 551 527 549 530 549 529 549 529 550 528 548 530 550 528 549 529 1629 528 550 529 1630 528 1628 530 1628 530 549 530 1628 529 549 529 +# From 5f52382098855e05b4239966cbe274551abdf538 Mon Sep 17 00:00:00 2001 From: Yukai Li Date: Fri, 26 May 2023 07:19:10 -0600 Subject: [PATCH 28/28] nfc: Mifare Ultralight C detection (#2668) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * nfc: Add Mifare Ultralight C detection * nfc: Add display name for MFUL C and hide menu items MFUL C unlock and emulation currently not supported, so hide from menu if current card is MFUL C * nfc: Also check response when probing 3DES auth * nfc: Hide emulate option in saved menu for MFUL if not supported * nfc: Remove unlock options from saved menu if Ultralight C Co-authored-by: gornekich Co-authored-by: あく --- .../nfc/scenes/nfc_scene_mf_ultralight_menu.c | 16 ++++---- .../main/nfc/scenes/nfc_scene_saved_menu.c | 4 +- firmware/targets/f7/api_symbols.csv | 1 + lib/nfc/nfc_types.c | 2 + lib/nfc/protocols/mifare_ultralight.c | 40 ++++++++++++++++--- lib/nfc/protocols/mifare_ultralight.h | 7 +++- 6 files changed, 56 insertions(+), 14 deletions(-) diff --git a/applications/main/nfc/scenes/nfc_scene_mf_ultralight_menu.c b/applications/main/nfc/scenes/nfc_scene_mf_ultralight_menu.c index c511e9dcb..e7a494d27 100644 --- a/applications/main/nfc/scenes/nfc_scene_mf_ultralight_menu.c +++ b/applications/main/nfc/scenes/nfc_scene_mf_ultralight_menu.c @@ -19,7 +19,7 @@ void nfc_scene_mf_ultralight_menu_on_enter(void* context) { Submenu* submenu = nfc->submenu; MfUltralightData* data = &nfc->dev->dev_data.mf_ul_data; - if(!mf_ul_is_full_capture(data)) { + if(!mf_ul_is_full_capture(data) && data->type != MfUltralightTypeULC) { submenu_add_item( submenu, "Unlock", @@ -29,12 +29,14 @@ void nfc_scene_mf_ultralight_menu_on_enter(void* context) { } submenu_add_item( submenu, "Save", SubmenuIndexSave, nfc_scene_mf_ultralight_menu_submenu_callback, nfc); - submenu_add_item( - submenu, - "Emulate", - SubmenuIndexEmulate, - nfc_scene_mf_ultralight_menu_submenu_callback, - nfc); + if(mf_ul_emulation_supported(data)) { + submenu_add_item( + submenu, + "Emulate", + SubmenuIndexEmulate, + nfc_scene_mf_ultralight_menu_submenu_callback, + nfc); + } submenu_add_item( submenu, "Info", SubmenuIndexInfo, nfc_scene_mf_ultralight_menu_submenu_callback, nfc); diff --git a/applications/main/nfc/scenes/nfc_scene_saved_menu.c b/applications/main/nfc/scenes/nfc_scene_saved_menu.c index ba1f96539..e45dc4eb7 100644 --- a/applications/main/nfc/scenes/nfc_scene_saved_menu.c +++ b/applications/main/nfc/scenes/nfc_scene_saved_menu.c @@ -42,7 +42,8 @@ void nfc_scene_saved_menu_on_enter(void* context) { nfc); } } else if( - nfc->dev->format == NfcDeviceSaveFormatMifareUl || + (nfc->dev->format == NfcDeviceSaveFormatMifareUl && + mf_ul_emulation_supported(&nfc->dev->dev_data.mf_ul_data)) || nfc->dev->format == NfcDeviceSaveFormatMifareClassic) { submenu_add_item( submenu, "Emulate", SubmenuIndexEmulate, nfc_scene_saved_menu_submenu_callback, nfc); @@ -72,6 +73,7 @@ void nfc_scene_saved_menu_on_enter(void* context) { submenu_add_item( submenu, "Info", SubmenuIndexInfo, nfc_scene_saved_menu_submenu_callback, nfc); if(nfc->dev->format == NfcDeviceSaveFormatMifareUl && + nfc->dev->dev_data.mf_ul_data.type != MfUltralightTypeULC && !mf_ul_is_full_capture(&nfc->dev->dev_data.mf_ul_data)) { submenu_add_item( submenu, diff --git a/firmware/targets/f7/api_symbols.csv b/firmware/targets/f7/api_symbols.csv index aebfc9072..ccbaa5317 100644 --- a/firmware/targets/f7/api_symbols.csv +++ b/firmware/targets/f7/api_symbols.csv @@ -2013,6 +2013,7 @@ Function,-,mf_df_prepare_read_records,uint16_t,"uint8_t*, uint8_t, uint32_t, uin Function,-,mf_df_prepare_select_application,uint16_t,"uint8_t*, uint8_t[3]" Function,-,mf_df_read_card,_Bool,"FuriHalNfcTxRxContext*, MifareDesfireData*" Function,-,mf_ul_check_card_type,_Bool,"uint8_t, uint8_t, uint8_t" +Function,-,mf_ul_emulation_supported,_Bool,MfUltralightData* Function,-,mf_ul_is_full_capture,_Bool,MfUltralightData* Function,-,mf_ul_prepare_emulation,void,"MfUltralightEmulator*, MfUltralightData*" Function,-,mf_ul_prepare_emulation_response,_Bool,"uint8_t*, uint16_t, uint8_t*, uint16_t*, uint32_t*, void*" diff --git a/lib/nfc/nfc_types.c b/lib/nfc/nfc_types.c index 02ca85580..96b92640f 100644 --- a/lib/nfc/nfc_types.c +++ b/lib/nfc/nfc_types.c @@ -45,6 +45,8 @@ const char* nfc_mf_ul_type(MfUltralightType type, bool full_name) { return "NTAG I2C Plus 2K"; } else if(type == MfUltralightTypeNTAG203) { return "NTAG203"; + } else if(type == MfUltralightTypeULC) { + return "Mifare Ultralight C"; } else if(type == MfUltralightTypeUL11 && full_name) { return "Mifare Ultralight 11"; } else if(type == MfUltralightTypeUL21 && full_name) { diff --git a/lib/nfc/protocols/mifare_ultralight.c b/lib/nfc/protocols/mifare_ultralight.c index 6960bd2a1..266b6e2e2 100644 --- a/lib/nfc/protocols/mifare_ultralight.c +++ b/lib/nfc/protocols/mifare_ultralight.c @@ -79,6 +79,8 @@ static MfUltralightFeatures mf_ul_get_features(MfUltralightType type) { MfUltralightSupportSectorSelect; case MfUltralightTypeNTAG203: return MfUltralightSupportCompatWrite | MfUltralightSupportCounterInMemory; + case MfUltralightTypeULC: + return MfUltralightSupportCompatWrite | MfUltralightSupport3DesAuth; default: // Assumed original MFUL 512-bit return MfUltralightSupportCompatWrite; @@ -95,6 +97,11 @@ static void mf_ul_set_version_ntag203(MfUltralightReader* reader, MfUltralightDa reader->pages_to_read = 42; } +static void mf_ul_set_version_ulc(MfUltralightReader* reader, MfUltralightData* data) { + data->type = MfUltralightTypeULC; + reader->pages_to_read = 48; +} + bool mf_ultralight_read_version( FuriHalNfcTxRxContext* tx_rx, MfUltralightReader* reader, @@ -175,7 +182,7 @@ bool mf_ultralight_authenticate(FuriHalNfcTxRxContext* tx_rx, uint32_t key, uint do { FURI_LOG_D(TAG, "Authenticating"); - tx_rx->tx_data[0] = MF_UL_AUTH; + tx_rx->tx_data[0] = MF_UL_PWD_AUTH; nfc_util_num2bytes(key, 4, &tx_rx->tx_data[1]); tx_rx->tx_bits = 40; tx_rx->tx_rx_type = FuriHalNfcTxRxTypeDefault; @@ -716,6 +723,21 @@ bool mf_ultralight_read_tearing_flags(FuriHalNfcTxRxContext* tx_rx, MfUltralight return flag_read == 2; } +static bool mf_ul_probe_3des_auth(FuriHalNfcTxRxContext* tx_rx) { + tx_rx->tx_data[0] = MF_UL_AUTHENTICATE_1; + tx_rx->tx_data[1] = 0; + tx_rx->tx_bits = 16; + tx_rx->tx_rx_type = FuriHalNfcTxRxTypeDefault; + bool rc = furi_hal_nfc_tx_rx(tx_rx, 50) && tx_rx->rx_bits == 9 * 8 && + tx_rx->rx_data[0] == 0xAF; + + // Reset just in case, we're not going to finish authenticating and need to if tag doesn't support auth + furi_hal_nfc_sleep(); + furi_hal_nfc_activate_nfca(300, NULL); + + return rc; +} + bool mf_ul_read_card( FuriHalNfcTxRxContext* tx_rx, MfUltralightReader* reader, @@ -733,16 +755,20 @@ bool mf_ul_read_card( mf_ultralight_read_signature(tx_rx, data); } } else { - // No GET_VERSION command, check for NTAG203 by reading last page (41) uint8_t dummy[16]; - if(mf_ultralight_read_pages_direct(tx_rx, 41, dummy)) { + // No GET_VERSION command, check if AUTHENTICATE command available (detect UL C). + if(mf_ul_probe_3des_auth(tx_rx)) { + mf_ul_set_version_ulc(reader, data); + } else if(mf_ultralight_read_pages_direct(tx_rx, 41, dummy)) { + // No AUTHENTICATE, check for NTAG203 by reading last page (41) mf_ul_set_version_ntag203(reader, data); - reader->supported_features = mf_ul_get_features(data->type); } else { // We're really an original Mifare Ultralight, reset tag for safety furi_hal_nfc_sleep(); furi_hal_nfc_activate_nfca(300, NULL); } + + reader->supported_features = mf_ul_get_features(data->type); } card_read = mf_ultralight_read_pages(tx_rx, reader, data); @@ -1228,6 +1254,10 @@ static void mf_ul_emulate_write( emulator->data_changed = true; } +bool mf_ul_emulation_supported(MfUltralightData* data) { + return data->type != MfUltralightTypeULC; +} + void mf_ul_reset_emulation(MfUltralightEmulator* emulator, bool is_power_cycle) { emulator->comp_write_cmd_started = false; emulator->sector_select_cmd_started = false; @@ -1732,7 +1762,7 @@ bool mf_ul_prepare_emulation_response( } } } - } else if(cmd == MF_UL_AUTH) { + } else if(cmd == MF_UL_PWD_AUTH) { if(emulator->supported_features & MfUltralightSupportAuth) { if(buff_rx_len == (1 + 4) * 8) { // Record password sent by PCD diff --git a/lib/nfc/protocols/mifare_ultralight.h b/lib/nfc/protocols/mifare_ultralight.h index 4ab22e89c..d444fa798 100644 --- a/lib/nfc/protocols/mifare_ultralight.h +++ b/lib/nfc/protocols/mifare_ultralight.h @@ -16,7 +16,8 @@ #define MF_UL_COMP_WRITE (0xA0) #define MF_UL_READ_CNT (0x39) #define MF_UL_INC_CNT (0xA5) -#define MF_UL_AUTH (0x1B) +#define MF_UL_AUTHENTICATE_1 (0x1A) +#define MF_UL_PWD_AUTH (0x1B) #define MF_UL_READ_SIG (0x3C) #define MF_UL_CHECK_TEARING (0x3E) #define MF_UL_READ_VCSL (0x4B) @@ -41,6 +42,7 @@ typedef enum { typedef enum { MfUltralightTypeUnknown, MfUltralightTypeNTAG203, + MfUltralightTypeULC, // Below have config pages and GET_VERSION support MfUltralightTypeUL11, MfUltralightTypeUL21, @@ -77,6 +79,7 @@ typedef enum { MfUltralightSupportAsciiMirror = 1 << 11, // NTAG203 counter that's in memory rather than through a command MfUltralightSupportCounterInMemory = 1 << 12, + MfUltralightSupport3DesAuth = 1 << 13, } MfUltralightFeatures; typedef enum { @@ -237,6 +240,8 @@ bool mf_ul_read_card( MfUltralightReader* reader, MfUltralightData* data); +bool mf_ul_emulation_supported(MfUltralightData* data); + void mf_ul_reset_emulation(MfUltralightEmulator* emulator, bool is_power_cycle); void mf_ul_prepare_emulation(MfUltralightEmulator* emulator, MfUltralightData* data);