From 85e39b53a1ed8795940b4c2f9a879a974463d3bc Mon Sep 17 00:00:00 2001 From: RogueMaster Date: Sat, 24 Dec 2022 01:34:48 -0500 Subject: [PATCH 1/8] upd wifi marauder --- ReadMe.md | 16 +--- .../wifi_marauder_scene_console_output.c | 2 +- .../scenes/wifi_marauder_scene_start.c | 38 ++++++-- .../scenes/wifi_marauder_scene_text_input.c | 88 ++++++++++++++++++- .../wifi_marauder_app.c | 2 + .../wifi_marauder_app_i.h | 7 +- .../wifi_marauder_custom_event.h | 2 + 7 files changed, 127 insertions(+), 28 deletions(-) diff --git a/ReadMe.md b/ReadMe.md index 0dab31b89..b1d48951f 100644 --- a/ReadMe.md +++ b/ReadMe.md @@ -22,19 +22,7 @@ Thank you to all the supporters! - Last Synced/Checked [Unleashed/xMasterX](https://github.com/DarkFlippers/unleashed-firmware), changes in [changelog](https://github.com/RogueMaster/flipperzero-firmware-wPlugins/blob/420/CHANGELOG.md) and in [commits](https://github.com/DarkFlippers/unleashed-firmware/commits/dev): `2022-12-23 10:44 EST` - Last Synced/Checked [OFW](https://github.com/flipperdevices/flipperzero-firmware), changes in [commits](https://github.com/flipperdevices/flipperzero-firmware/commits/dev): `2022-12-23 10:44 EST` -- Updated: [NRF24 Scanner v2.0 (By vad7)](https://github.com/vad7/nrf24scan) -- New Animation: [Hentai (By qqMajikpp)](https://github.com/qqmajikpp/) for [PATREON members](https://www.patreon.com/RogueMaster/membership) now included on 18Plus releases -- [PATREON ONLY UPDATES: For STOCK Animations Release: Not Stoned, Passport display closer to OFW, Passport avatar from OFW, Top desktop bar from OFW & Internal Apps have OFW animation scenes](https://www.patreon.com/RogueMaster/) -- Swapped favorite buttons to fix Favorite location bug. -- Updated: [Authenticator/TOTP (By akopachov)](https://github.com/akopachov/flipper-zero_authenticator) -- Updated: [NRF24 Scanner v2.1 (By vad7)](https://github.com/vad7/nrf24scan) -- Fixed passport to show more data for EXP -- Added: [Mifare dictionary attack performance improvements. #2173 (By nezza)](https://github.com/flipperdevices/flipperzero-firmware/pull/2173) -- [New PAXGOD Build: Unlocked, 1 New Custom PaxGod animation and non-anime/RM animations from Minimal, and Mountains Passport Theme (from Kuranons) on PATREON](https://www.patreon.com/posts/76225261) - Custom FW Builds available for [PATREON subscribers](https://www.patreon.com/RogueMaster/membership) -- Updated: [NRF24 Scanner v2.1 (By vad7)](https://github.com/vad7/nrf24scan) -- Added: [2048 (By eugene-kirzhanov)](https://github.com/eugene-kirzhanov/flipper-zero-2048-game) (Titled 2048 (Improved)) -- Fixed game mode 2048 to new version -- [18 Plus Build Update: 5 New Animations included on 18 Plus releases](https://www.patreon.com/posts/76253078) +- Updated: [WiFi (Marauder) v3.0 (By 0xchocolate)](https://github.com/0xchocolate/flipperzero-firmware-with-wifi-marauder-companion) `Req: ESP32 WITH MARAUDER FLASHED` ## Install from Release FLASH STOCK FIRST BEFORE UPDATING TO CUSTOM FIRMWARE! @@ -258,7 +246,7 @@ $ ./fbt resources icons dolphin_ext - [USB Midi (By DrZlo13)](https://github.com/DrZlo13/flipper-zero-usb-midi) with thanks to [xMasterX](https://github.com/xMasterX/unleashed-extra-pack) - [WAV Player (By DrZlo13)](https://github.com/flipperdevices/flipperzero-firmware/tree/zlo/wav-player) Updated by Atmanos & RogueMaster To Work - [WiFi (Deauther) V2 (By Timmotools)](https://github.com/Timmotools/flipperzero_esp8266_deautherv2) `Req: ESP8266` -- [WiFi (Marauder) (By 0xchocolate)](https://github.com/0xchocolate/flipperzero-firmware-with-wifi-marauder-companion) `Req: ESP32 WITH MARAUDER FLASHED` +- [WiFi (Marauder) v3.0 (By 0xchocolate)](https://github.com/0xchocolate/flipperzero-firmware-with-wifi-marauder-companion) `Req: ESP32 WITH MARAUDER FLASHED` - [WiFi Scanner v.0.4 (By SequoiaSan)](https://github.com/SequoiaSan/FlipperZero-WiFi-Scanner_Module-ESP8266) `Req: ESP8266 or ESP32` - [Wii EC Analyser (By csBlueChip)](https://github.com/csBlueChip/FlipperZero_WiiEC) - [Zero Tracker (By DrZZlo13)](https://github.com/DrZlo13/flipper-zero-music-tracker) diff --git a/applications/plugins/wifi_marauder_companion/scenes/wifi_marauder_scene_console_output.c b/applications/plugins/wifi_marauder_companion/scenes/wifi_marauder_scene_console_output.c index 25ea0abb0..8b9984dbf 100644 --- a/applications/plugins/wifi_marauder_companion/scenes/wifi_marauder_scene_console_output.c +++ b/applications/plugins/wifi_marauder_companion/scenes/wifi_marauder_scene_console_output.c @@ -34,7 +34,7 @@ void wifi_marauder_scene_console_output_on_enter(void* context) { app->text_box_store_strlen = 0; if(0 == strncmp("help", app->selected_tx_string, strlen("help"))) { const char* help_msg = - "Marauder companion v0.2.2\nFor app support/feedback,\nreach out to me:\n@cococode#6011 (discord)\n0xchocolate (github)\n"; + "Marauder companion v0.3.0\nFor app support/feedback,\nreach out to me:\n@cococode#6011 (discord)\n0xchocolate (github)\n"; furi_string_cat_str(app->text_box_store, help_msg); app->text_box_store_strlen += strlen(help_msg); } diff --git a/applications/plugins/wifi_marauder_companion/scenes/wifi_marauder_scene_start.c b/applications/plugins/wifi_marauder_companion/scenes/wifi_marauder_scene_start.c index 029614c5d..1ba810efe 100644 --- a/applications/plugins/wifi_marauder_companion/scenes/wifi_marauder_scene_start.c +++ b/applications/plugins/wifi_marauder_companion/scenes/wifi_marauder_scene_start.c @@ -26,7 +26,7 @@ typedef struct { // NUM_MENU_ITEMS defined in wifi_marauder_app_i.h - if you add an entry here, increment it! const WifiMarauderItem items[NUM_MENU_ITEMS] = { {"View Log from", {"start", "end"}, 2, {"", ""}, NO_ARGS, FOCUS_CONSOLE_TOGGLE, NO_TIP}, - {"Scan AP", {""}, 1, {"scanap"}, NO_ARGS, FOCUS_CONSOLE_END, SHOW_STOPSCAN_TIP}, + {"Scan", {"ap", "station"}, 2, {"scanap", "scansta"}, NO_ARGS, FOCUS_CONSOLE_END, SHOW_STOPSCAN_TIP}, {"SSID", {"add rand", "add name", "remove"}, 3, @@ -34,12 +34,24 @@ const WifiMarauderItem items[NUM_MENU_ITEMS] = { INPUT_ARGS, FOCUS_CONSOLE_START, NO_TIP}, - {"List", {"ap", "ssid"}, 2, {"list -a", "list -s"}, NO_ARGS, FOCUS_CONSOLE_START, NO_TIP}, - {"Select", {"ap", "ssid"}, 2, {"select -a", "select -s"}, INPUT_ARGS, FOCUS_CONSOLE_END, NO_TIP}, + {"List", + {"ap", "ssid", "station"}, + 3, + {"list -a", "list -s", "list -c"}, + NO_ARGS, + FOCUS_CONSOLE_START, + NO_TIP}, + {"Select", + {"ap", "ssid", "station"}, + 3, + {"select -a", "select -s", "select -c"}, + INPUT_ARGS, + FOCUS_CONSOLE_END, + NO_TIP}, {"Clear List", - {"ap", "ssid"}, - 2, - {"clearlist -a", "clearlist -s"}, + {"ap", "ssid", "station"}, + 3, + {"clearlist -a", "clearlist -s", "clearlist -c"}, NO_ARGS, FOCUS_CONSOLE_END, NO_TIP}, @@ -50,6 +62,13 @@ const WifiMarauderItem items[NUM_MENU_ITEMS] = { NO_ARGS, FOCUS_CONSOLE_END, SHOW_STOPSCAN_TIP}, + {"Targeted Deauth", + {"station", "manual"}, + 2, + {"attack -t deauth -c", "attack -t deauth -s"}, + TOGGLE_ARGS, + FOCUS_CONSOLE_END, + SHOW_STOPSCAN_TIP}, {"Beacon Spam", {"ap list", "ssid list", "random"}, 3, @@ -87,18 +106,19 @@ const WifiMarauderItem items[NUM_MENU_ITEMS] = { FOCUS_CONSOLE_END, NO_TIP}, {"Settings", - {"display", "restore", "ForcePMKID", "ForceProbe", "SavePCAP", "other"}, - 6, + {"display", "restore", "ForcePMKID", "ForceProbe", "SavePCAP", "EnableLED", "other"}, + 7, {"settings", "settings -r", "settings -s ForcePMKID enable", "settings -s ForceProbe enable", "settings -s SavePCAP enable", + "settings -s EnableLED enable", "settings -s"}, TOGGLE_ARGS, FOCUS_CONSOLE_START, NO_TIP}, - {"Update", {""}, 1, {"update -w"}, NO_ARGS, FOCUS_CONSOLE_END, NO_TIP}, + {"Update", {"ota", "sd"}, 2, {"update -w", "update -s"}, NO_ARGS, FOCUS_CONSOLE_END, NO_TIP}, {"Reboot", {""}, 1, {"reboot"}, NO_ARGS, FOCUS_CONSOLE_END, NO_TIP}, {"Help", {""}, 1, {"help"}, NO_ARGS, FOCUS_CONSOLE_START, SHOW_STOPSCAN_TIP}, }; diff --git a/applications/plugins/wifi_marauder_companion/scenes/wifi_marauder_scene_text_input.c b/applications/plugins/wifi_marauder_companion/scenes/wifi_marauder_scene_text_input.c index 061e9c5fe..ac8b15a2d 100644 --- a/applications/plugins/wifi_marauder_companion/scenes/wifi_marauder_scene_text_input.c +++ b/applications/plugins/wifi_marauder_companion/scenes/wifi_marauder_scene_text_input.c @@ -3,13 +3,34 @@ void wifi_marauder_scene_text_input_callback(void* context) { WifiMarauderApp* app = context; - view_dispatcher_send_custom_event(app->view_dispatcher, WifiMarauderEventStartConsole); + switch(app->special_case_input_step) { + case 0: // most commands + view_dispatcher_send_custom_event(app->view_dispatcher, WifiMarauderEventStartConsole); + break; + case 1: // special case for deauth: save source MAC + view_dispatcher_send_custom_event(app->view_dispatcher, WifiMarauderEventSaveSourceMac); + break; + case 2: // special case for deauth: save destination MAC + view_dispatcher_send_custom_event( + app->view_dispatcher, WifiMarauderEventSaveDestinationMac); + break; + default: + break; + } } void wifi_marauder_scene_text_input_on_enter(void* context) { WifiMarauderApp* app = context; - if(false == app->is_custom_tx_string) { + if(0 == + strncmp("attack -t deauth -s", app->selected_tx_string, strlen("attack -t deauth -s"))) { + // Special case for manual deauth input + app->special_case_input_step = 1; + bzero(app->text_input_store, WIFI_MARAUDER_TEXT_INPUT_STORE_SIZE); + } else if(false == app->is_custom_tx_string) { + // Most commands + app->special_case_input_step = 0; + // Fill text input with selected string so that user can add to it size_t length = strlen(app->selected_tx_string); furi_assert(length < WIFI_MARAUDER_TEXT_INPUT_STORE_SIZE); @@ -25,7 +46,9 @@ void wifi_marauder_scene_text_input_on_enter(void* context) { // Setup view TextInput* text_input = app->text_input; // Add help message to header - if(0 == strncmp("ssid -a -g", app->selected_tx_string, strlen("ssid -a -g"))) { + if(app->special_case_input_step == 1) { + text_input_set_header_text(text_input, "Enter source MAC"); + } else if(0 == strncmp("ssid -a -g", app->selected_tx_string, strlen("ssid -a -g"))) { text_input_set_header_text(text_input, "Enter # SSIDs to generate"); } else if(0 == strncmp("ssid -a -n", app->selected_tx_string, strlen("ssid -a -n"))) { text_input_set_header_text(text_input, "Enter SSID name to add"); @@ -59,6 +82,65 @@ bool wifi_marauder_scene_text_input_on_event(void* context, SceneManagerEvent ev app->selected_tx_string = app->text_input_store; scene_manager_next_scene(app->scene_manager, WifiMarauderAppViewConsoleOutput); consumed = true; + } else if(event.event == WifiMarauderEventSaveSourceMac) { + if(12 != strlen(app->text_input_store)) { + text_input_set_header_text(app->text_input, "MAC must be 12 hex chars!"); + } else { + snprintf( + app->special_case_input_src_addr, + sizeof(app->special_case_input_src_addr), + "%c%c:%c%c:%c%c:%c%c:%c%c:%c%c", + app->text_input_store[0], + app->text_input_store[1], + app->text_input_store[2], + app->text_input_store[3], + app->text_input_store[4], + app->text_input_store[5], + app->text_input_store[6], + app->text_input_store[7], + app->text_input_store[8], + app->text_input_store[9], + app->text_input_store[10], + app->text_input_store[11]); + + // Advance scene to input destination MAC, clear text input + app->special_case_input_step = 2; + bzero(app->text_input_store, WIFI_MARAUDER_TEXT_INPUT_STORE_SIZE); + text_input_set_header_text(app->text_input, "Enter destination MAC"); + } + consumed = true; + } else if(event.event == WifiMarauderEventSaveDestinationMac) { + if(12 != strlen(app->text_input_store)) { + text_input_set_header_text(app->text_input, "MAC must be 12 hex chars!"); + } else { + snprintf( + app->special_case_input_dst_addr, + sizeof(app->special_case_input_dst_addr), + "%c%c:%c%c:%c%c:%c%c:%c%c:%c%c", + app->text_input_store[0], + app->text_input_store[1], + app->text_input_store[2], + app->text_input_store[3], + app->text_input_store[4], + app->text_input_store[5], + app->text_input_store[6], + app->text_input_store[7], + app->text_input_store[8], + app->text_input_store[9], + app->text_input_store[10], + app->text_input_store[11]); + + // Construct command with source and destination MACs + snprintf( + app->text_input_store, + WIFI_MARAUDER_TEXT_INPUT_STORE_SIZE, + "attack -t deauth -s %18s -d %18s", + app->special_case_input_src_addr, + app->special_case_input_dst_addr); + app->selected_tx_string = app->text_input_store; + scene_manager_next_scene(app->scene_manager, WifiMarauderAppViewConsoleOutput); + } + consumed = true; } } diff --git a/applications/plugins/wifi_marauder_companion/wifi_marauder_app.c b/applications/plugins/wifi_marauder_companion/wifi_marauder_app.c index 2a4b23e8b..79d35a808 100644 --- a/applications/plugins/wifi_marauder_companion/wifi_marauder_app.c +++ b/applications/plugins/wifi_marauder_companion/wifi_marauder_app.c @@ -50,6 +50,8 @@ WifiMarauderApp* wifi_marauder_app_alloc() { app->selected_option_index[i] = 0; } + app->special_case_input_step = 0; + app->text_box = text_box_alloc(); view_dispatcher_add_view( app->view_dispatcher, WifiMarauderAppViewConsoleOutput, text_box_get_view(app->text_box)); diff --git a/applications/plugins/wifi_marauder_companion/wifi_marauder_app_i.h b/applications/plugins/wifi_marauder_companion/wifi_marauder_app_i.h index f571a11a2..4df9e326b 100644 --- a/applications/plugins/wifi_marauder_companion/wifi_marauder_app_i.h +++ b/applications/plugins/wifi_marauder_companion/wifi_marauder_app_i.h @@ -14,7 +14,7 @@ #include #include -#define NUM_MENU_ITEMS (15) +#define NUM_MENU_ITEMS (16) #define WIFI_MARAUDER_TEXT_BOX_STORE_SIZE (4096) #define WIFI_MARAUDER_TEXT_INPUT_STORE_SIZE (512) @@ -41,6 +41,11 @@ struct WifiMarauderApp { bool is_custom_tx_string; bool focus_console_start; bool show_stopscan_tip; + + // For input source and destination MAC in targeted deauth attack + int special_case_input_step; + char special_case_input_src_addr[20]; + char special_case_input_dst_addr[20]; }; // Supported commands: diff --git a/applications/plugins/wifi_marauder_companion/wifi_marauder_custom_event.h b/applications/plugins/wifi_marauder_companion/wifi_marauder_custom_event.h index fe1bff6af..990b457f5 100644 --- a/applications/plugins/wifi_marauder_companion/wifi_marauder_custom_event.h +++ b/applications/plugins/wifi_marauder_companion/wifi_marauder_custom_event.h @@ -4,4 +4,6 @@ typedef enum { WifiMarauderEventRefreshConsoleOutput = 0, WifiMarauderEventStartConsole, WifiMarauderEventStartKeyboard, + WifiMarauderEventSaveSourceMac, + WifiMarauderEventSaveDestinationMac } WifiMarauderCustomEvent; From 9ee1322f8d111373e9990ddc576cccdf7e296112 Mon Sep 17 00:00:00 2001 From: RogueMaster Date: Sat, 24 Dec 2022 01:35:47 -0500 Subject: [PATCH 2/8] FMT --- .../scenes/wifi_marauder_scene_start.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/applications/plugins/wifi_marauder_companion/scenes/wifi_marauder_scene_start.c b/applications/plugins/wifi_marauder_companion/scenes/wifi_marauder_scene_start.c index 1ba810efe..df759bd15 100644 --- a/applications/plugins/wifi_marauder_companion/scenes/wifi_marauder_scene_start.c +++ b/applications/plugins/wifi_marauder_companion/scenes/wifi_marauder_scene_start.c @@ -26,7 +26,13 @@ typedef struct { // NUM_MENU_ITEMS defined in wifi_marauder_app_i.h - if you add an entry here, increment it! const WifiMarauderItem items[NUM_MENU_ITEMS] = { {"View Log from", {"start", "end"}, 2, {"", ""}, NO_ARGS, FOCUS_CONSOLE_TOGGLE, NO_TIP}, - {"Scan", {"ap", "station"}, 2, {"scanap", "scansta"}, NO_ARGS, FOCUS_CONSOLE_END, SHOW_STOPSCAN_TIP}, + {"Scan", + {"ap", "station"}, + 2, + {"scanap", "scansta"}, + NO_ARGS, + FOCUS_CONSOLE_END, + SHOW_STOPSCAN_TIP}, {"SSID", {"add rand", "add name", "remove"}, 3, From 05f8cf2492f6dc57f3281aea2c879393cedaa42c Mon Sep 17 00:00:00 2001 From: RogueMaster Date: Sat, 24 Dec 2022 01:52:18 -0500 Subject: [PATCH 3/8] 4 minor updates --- ReadMe.md | 8 +++- applications/plugins/bpmtapper/README.md | 2 +- .../plugins/bpmtapper/application.fam | 4 +- applications/plugins/bpmtapper/bpm.c | 39 +++++++++--------- applications/plugins/metronome/README.md | 4 +- .../plugins/metronome/application.fam | 2 +- .../plugins/metronome/gui_extensions.c | 2 +- .../plugins/metronome/images/ButtonUp_7x4.png | Bin 102 -> 0 bytes applications/plugins/metronome/metronome.c | 35 +++++++--------- applications/plugins/minesweeper/README.md | 2 - .../plugins/minesweeper/minesweeper.c | 8 +--- applications/plugins/nrf24scan/nrf24scan.c | 24 +++++++---- .../apps_data/nrf24scan/addresses.txt | 1 + 13 files changed, 63 insertions(+), 68 deletions(-) delete mode 100644 applications/plugins/metronome/images/ButtonUp_7x4.png diff --git a/ReadMe.md b/ReadMe.md index b1d48951f..6a9177677 100644 --- a/ReadMe.md +++ b/ReadMe.md @@ -20,9 +20,13 @@ Thank you to all the supporters! ## [BUILDS NOW AVAILABLE WITH STOCK, RM SELECT, RM SELECT + 18PLUS, RM MINIMAL (default) and RM 18PLUS ANIMATION SETS](https://www.patreon.com/RogueMaster/membership) -- Last Synced/Checked [Unleashed/xMasterX](https://github.com/DarkFlippers/unleashed-firmware), changes in [changelog](https://github.com/RogueMaster/flipperzero-firmware-wPlugins/blob/420/CHANGELOG.md) and in [commits](https://github.com/DarkFlippers/unleashed-firmware/commits/dev): `2022-12-23 10:44 EST` -- Last Synced/Checked [OFW](https://github.com/flipperdevices/flipperzero-firmware), changes in [commits](https://github.com/flipperdevices/flipperzero-firmware/commits/dev): `2022-12-23 10:44 EST` +- Last Synced/Checked [Unleashed/xMasterX](https://github.com/DarkFlippers/unleashed-firmware), changes in [changelog](https://github.com/RogueMaster/flipperzero-firmware-wPlugins/blob/420/CHANGELOG.md) and in [commits](https://github.com/DarkFlippers/unleashed-firmware/commits/dev): `2022-12-24 01:42 EST` +- Last Synced/Checked [OFW](https://github.com/flipperdevices/flipperzero-firmware), changes in [commits](https://github.com/flipperdevices/flipperzero-firmware/commits/dev): `2022-12-24 01:42 EST` - Updated: [WiFi (Marauder) v3.0 (By 0xchocolate)](https://github.com/0xchocolate/flipperzero-firmware-with-wifi-marauder-companion) `Req: ESP32 WITH MARAUDER FLASHED` +- Updated: [BPM Tapper (By panki27)](https://github.com/panki27/bpm-tapper) +- Updated: [Metronome (By panki27)](https://github.com/panki27/Metronome) +- Updated: [Minesweeper (By panki27)](https://github.com/panki27/minesweeper) +- Updated: [NRF24 Scanner v2.1 (By vad7)](https://github.com/vad7/nrf24scan) ## Install from Release FLASH STOCK FIRST BEFORE UPDATING TO CUSTOM FIRMWARE! diff --git a/applications/plugins/bpmtapper/README.md b/applications/plugins/bpmtapper/README.md index 8e88863ee..224d2cb5b 100644 --- a/applications/plugins/bpmtapper/README.md +++ b/applications/plugins/bpmtapper/README.md @@ -9,6 +9,6 @@ Hit any button other than back repeatedly. Calculates based on the average of th ## Compiling ``` -./fbt firmware_bpm_tapper +./fbt fap_bpm_tapper ``` diff --git a/applications/plugins/bpmtapper/application.fam b/applications/plugins/bpmtapper/application.fam index 93c4179c5..b6ad315b6 100644 --- a/applications/plugins/bpmtapper/application.fam +++ b/applications/plugins/bpmtapper/application.fam @@ -7,7 +7,7 @@ App( requires=["gui"], stack_size=2 * 1024, fap_icon="bpm_10px.png", - fap_category="Music", fap_icon_assets="icons", - order=15, + fap_category="Music", + order=35, ) diff --git a/applications/plugins/bpmtapper/bpm.c b/applications/plugins/bpmtapper/bpm.c index cee83a6a4..323a898a4 100644 --- a/applications/plugins/bpmtapper/bpm.c +++ b/applications/plugins/bpmtapper/bpm.c @@ -3,6 +3,7 @@ #include #include #include +#include #include #include "BPM_Tapper_icons.h" @@ -126,7 +127,7 @@ static void input_callback(InputEvent* input_event, FuriMessageQueue* event_queu } static void render_callback(Canvas* const canvas, void* ctx) { - FuriString* tempStr; + string_t tempStr; const BPMTapper* bpm_state = acquire_mutex((ValueMutex*)ctx, 25); if(bpm_state == NULL) { @@ -136,32 +137,30 @@ static void render_callback(Canvas* const canvas, void* ctx) { //canvas_draw_frame(canvas, 0, 0, 128, 64); canvas_set_font(canvas, FontPrimary); - tempStr = furi_string_alloc(); + string_init(tempStr); - furi_string_printf(tempStr, "Taps: %d", bpm_state->taps); - canvas_draw_str_aligned(canvas, 5, 10, AlignLeft, AlignBottom, furi_string_get_cstr(tempStr)); - furi_string_reset(tempStr); + string_printf(tempStr, "Taps: %d", bpm_state->taps); + canvas_draw_str_aligned(canvas, 5, 10, AlignLeft, AlignBottom, string_get_cstr(tempStr)); + string_reset(tempStr); - furi_string_printf(tempStr, "Queue: %d", bpm_state->tap_queue->size); - canvas_draw_str_aligned(canvas, 70, 10, AlignLeft, AlignBottom, furi_string_get_cstr(tempStr)); - furi_string_reset(tempStr); + string_printf(tempStr, "Queue: %d", bpm_state->tap_queue->size); + canvas_draw_str_aligned(canvas, 70, 10, AlignLeft, AlignBottom, string_get_cstr(tempStr)); + string_reset(tempStr); - furi_string_printf(tempStr, "Interval: %ldms", bpm_state->interval); - canvas_draw_str_aligned(canvas, 5, 20, AlignLeft, AlignBottom, furi_string_get_cstr(tempStr)); - furi_string_reset(tempStr); + string_printf(tempStr, "Interval: %dms", bpm_state->interval); + canvas_draw_str_aligned(canvas, 5, 20, AlignLeft, AlignBottom, string_get_cstr(tempStr)); + string_reset(tempStr); - furi_string_printf(tempStr, "x2 %.2f /2 %.2f", bpm_state->bpm * 2, bpm_state->bpm / 2); - canvas_draw_str_aligned( - canvas, 64, 60, AlignCenter, AlignCenter, furi_string_get_cstr(tempStr)); - furi_string_reset(tempStr); + string_printf(tempStr, "x2 %.2f /2 %.2f", bpm_state->bpm * 2, bpm_state->bpm / 2); + canvas_draw_str_aligned(canvas, 64, 60, AlignCenter, AlignCenter, string_get_cstr(tempStr)); + string_reset(tempStr); - furi_string_printf(tempStr, "%.2f", bpm_state->bpm); + string_printf(tempStr, "%.2f", bpm_state->bpm); canvas_set_font(canvas, FontBigNumbers); - canvas_draw_str_aligned( - canvas, 64, 40, AlignCenter, AlignCenter, furi_string_get_cstr(tempStr)); - furi_string_reset(tempStr); + canvas_draw_str_aligned(canvas, 64, 40, AlignCenter, AlignCenter, string_get_cstr(tempStr)); + string_reset(tempStr); - furi_string_free(tempStr); + string_clear(tempStr); release_mutex((ValueMutex*)ctx, bpm_state); } diff --git a/applications/plugins/metronome/README.md b/applications/plugins/metronome/README.md index 4b6cd3122..79134c350 100644 --- a/applications/plugins/metronome/README.md +++ b/applications/plugins/metronome/README.md @@ -1,7 +1,5 @@ # Metronome -[Original link](https://github.com/panki27/Metronome) - A metronome for the [Flipper Zero](https://flipperzero.one/) device. Goes along perfectly with my [BPM tapper](https://github.com/panki27/bpm-tapper). ![screenshot](img/screenshot.png) @@ -19,5 +17,5 @@ A metronome for the [Flipper Zero](https://flipperzero.one/) device. Goes along ## Compiling ``` -./fbt firmware_metronome +./fbt fap_metronome ``` diff --git a/applications/plugins/metronome/application.fam b/applications/plugins/metronome/application.fam index 32588d06e..b40809638 100644 --- a/applications/plugins/metronome/application.fam +++ b/applications/plugins/metronome/application.fam @@ -8,8 +8,8 @@ App( "gui", ], fap_icon="metronome_icon.png", + fap_icon_assets="icons", fap_category="Music", - fap_icon_assets="images", stack_size=2 * 1024, order=20, ) diff --git a/applications/plugins/metronome/gui_extensions.c b/applications/plugins/metronome/gui_extensions.c index 458eb137b..a7661ec28 100644 --- a/applications/plugins/metronome/gui_extensions.c +++ b/applications/plugins/metronome/gui_extensions.c @@ -1,6 +1,6 @@ #include #include -#include +#include "Metronome_icons.h" //lib can only do bottom left/right void elements_button_top_left(Canvas* canvas, const char* str) { diff --git a/applications/plugins/metronome/images/ButtonUp_7x4.png b/applications/plugins/metronome/images/ButtonUp_7x4.png deleted file mode 100644 index 1be79328b40a93297a5609756328406565c437c0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 102 zcmeAS@N?(olHy`uVBq!ia0vp^>_E)I!3HFqj;YoHDIHH2#}J8d-yTOk1_O>mFaFD) zeWb+ZHz{mGZZ1QpXe09^4tcYT#4oe=UbmGC^A-KE*|F&zP#=S*tDnm{r-UX30HgpM AM*si- diff --git a/applications/plugins/metronome/metronome.c b/applications/plugins/metronome/metronome.c index 5c1105574..4c374aa75 100644 --- a/applications/plugins/metronome/metronome.c +++ b/applications/plugins/metronome/metronome.c @@ -1,6 +1,7 @@ #include #include #include +#include #include #include @@ -57,26 +58,23 @@ static void render_callback(Canvas* const canvas, void* ctx) { return; } - FuriString* tempStr; - tempStr = furi_string_alloc(); + string_t tempStr; + string_init(tempStr); canvas_draw_frame(canvas, 0, 0, 128, 64); canvas_set_font(canvas, FontPrimary); // draw bars/beat - furi_string_printf( - tempStr, "%d/%d", metronome_state->beats_per_bar, metronome_state->note_length); - canvas_draw_str_aligned( - canvas, 64, 8, AlignCenter, AlignCenter, furi_string_get_cstr(tempStr)); - furi_string_reset(tempStr); + string_printf(tempStr, "%d/%d", metronome_state->beats_per_bar, metronome_state->note_length); + canvas_draw_str_aligned(canvas, 64, 8, AlignCenter, AlignCenter, string_get_cstr(tempStr)); + string_reset(tempStr); // draw BPM value - furi_string_printf(tempStr, "%.2f", metronome_state->bpm); + string_printf(tempStr, "%.2f", metronome_state->bpm); canvas_set_font(canvas, FontBigNumbers); - canvas_draw_str_aligned( - canvas, 64, 24, AlignCenter, AlignCenter, furi_string_get_cstr(tempStr)); - furi_string_reset(tempStr); + canvas_draw_str_aligned(canvas, 64, 24, AlignCenter, AlignCenter, string_get_cstr(tempStr)); + string_reset(tempStr); // draw volume indicator // always draw first waves @@ -128,7 +126,7 @@ static void render_callback(Canvas* const canvas, void* ctx) { canvas, 8, 36, 112, (float)metronome_state->current_beat / metronome_state->beats_per_bar); // cleanup - furi_string_free(tempStr); + string_clear(tempStr); release_mutex((ValueMutex*)ctx, metronome_state); } @@ -160,8 +158,6 @@ static void timer_callback(void* ctx) { break; case Silent: break; - default: - break; } } else { // unpronounced beat @@ -177,8 +173,6 @@ static void timer_callback(void* ctx) { break; case Silent: break; - default: - break; } }; @@ -203,8 +197,6 @@ static void timer_callback(void* ctx) { break; case Silent: break; - default: - break; } notification_message(metronome_state->notifications, &sequence_reset_rgb); @@ -295,6 +287,7 @@ int32_t metronome_app() { metronome_state->timer = furi_timer_alloc(timer_callback, FuriTimerTypePeriodic, &state_mutex); // Open GUI and register view_port + // Gui* gui = furi_record_open("gui"); gui_add_view_port(gui, view_port, GuiLayerFullscreen); @@ -333,7 +326,7 @@ int32_t metronome_app() { case InputKeyBack: processing = false; break; - default: + case InputKeyMAX: break; } } else if(event.input.type == InputTypeLong) { @@ -355,7 +348,7 @@ int32_t metronome_app() { case InputKeyBack: processing = false; break; - default: + case InputKeyMAX: break; } } else if(event.input.type == InputTypeRepeat) { @@ -376,7 +369,7 @@ int32_t metronome_app() { case InputKeyBack: processing = false; break; - default: + case InputKeyMAX: break; } } diff --git a/applications/plugins/minesweeper/README.md b/applications/plugins/minesweeper/README.md index 28176bd5e..eb1ebcad2 100644 --- a/applications/plugins/minesweeper/README.md +++ b/applications/plugins/minesweeper/README.md @@ -1,7 +1,5 @@ # Minesweeper -[Original Link](https://github.com/panki27/minesweeper) - This is a Minesweeper implementation for the Flipper Zero device. ![screenshot](img/screenshot.png) diff --git a/applications/plugins/minesweeper/minesweeper.c b/applications/plugins/minesweeper/minesweeper.c index fa9fdcc78..75fb32e56 100644 --- a/applications/plugins/minesweeper/minesweeper.c +++ b/applications/plugins/minesweeper/minesweeper.c @@ -217,10 +217,6 @@ static bool game_lost(Minesweeper* minesweeper_state) { dialog_message_set_icon(message, NULL, 0, 10); - // Set cursor to initial position - minesweeper_state->cursor_x = 0; - minesweeper_state->cursor_y = 0; - NotificationApp* notifications = furi_record_open(RECORD_NOTIFICATION); notification_message(notifications, &sequence_set_vibro_on); furi_record_close(RECORD_NOTIFICATION); @@ -476,7 +472,7 @@ int32_t minesweeper_app(void* p) { // Exit the plugin processing = false; break; - default: + case InputKeyMAX: break; } } else if(event.input.type == InputTypeLong) { @@ -495,7 +491,7 @@ int32_t minesweeper_app(void* p) { case InputKeyBack: processing = false; break; - default: + case InputKeyMAX: break; } } diff --git a/applications/plugins/nrf24scan/nrf24scan.c b/applications/plugins/nrf24scan/nrf24scan.c index da0093e8d..d142d1479 100644 --- a/applications/plugins/nrf24scan/nrf24scan.c +++ b/applications/plugins/nrf24scan/nrf24scan.c @@ -212,8 +212,11 @@ void write_to_log_file(Storage* storage, bool f_settings) { if(fl) { FURI_LOG_D(TAG, "Save to %s", furi_string_get_cstr(str)); if(save_to_new_log || f_settings) { - //if(what_to_do == 1) furi_string_printf(str, "%s\n", SettingsFld_Sniff); else furi_string_reset(str); - furi_string_printf( + if(what_to_do == 1) + furi_string_printf(str, "%s\n", SettingsFld_Sniff); + else + furi_string_reset(str); + furi_string_cat_printf( str, "%s %d\n%s %d\n%s %d\n", SettingsFld_Rate, @@ -231,9 +234,11 @@ void write_to_log_file(Storage* storage, bool f_settings) { NRF_CRC, SettingsFld_Payload, what_to_do == 1 ? NRF_Payload_sniff_min : NRF_Payload); - furi_string_cat_printf(str, "P0: "); - add_to_furi_str_hex_bytes(str, (char*)addrs.addr_P0, addrs.addr_len); - furi_string_cat(str, "\n"); + if(addrs.addr_count > 0) { + furi_string_cat_printf(str, "P0: "); + add_to_furi_str_hex_bytes(str, (char*)addrs.addr_P0, addrs.addr_len); + furi_string_cat(str, "\n"); + } if(addrs.addr_count > 1) { furi_string_cat_printf(str, "P1: "); add_to_furi_str_hex_bytes(str, (char*)addrs.addr_P1, addrs.addr_len); @@ -428,13 +433,14 @@ static uint8_t load_settings_file(Stream* file_stream) { if(err == 0 && a) adr->addr_count = a - '0' + 1; } else if(line_len >= 3 * 2) { // data if(!log_loaded) { + log_loaded = true; clear_log(); what_to_do = 0; - log_loaded = true; } if(log_arr_idx < MAX_LOG_RECORDS - 1) { - ConvertHexToArray( - line_ptr, APP->log_arr + log_arr_idx * LOG_REC_SIZE, LOG_REC_SIZE); + if(ConvertHexToArray( + line_ptr, APP->log_arr + log_arr_idx * LOG_REC_SIZE, LOG_REC_SIZE) > 0) + err = 0; log_arr_idx++; } } @@ -1013,7 +1019,7 @@ static void render_callback(Canvas* const canvas, void* ctx) { if(log_arr_idx && (*p & 0x80)) { // +RAW snprintf(screen_buf, sizeof(screen_buf), "Start read: "); add_to_str_hex_bytes(screen_buf, (char*)p + 2, (*(p + 1) & 0b11) + 2); - if(what_to_do == 3) strcpy(screen_buf + strlen(screen_buf) - 2, "* "); + if(what_to_do == 2) strcpy(screen_buf + strlen(screen_buf) - 2, "* "); } else snprintf( screen_buf, diff --git a/assets/resources/apps_data/nrf24scan/addresses.txt b/assets/resources/apps_data/nrf24scan/addresses.txt index 1934efbf4..e5bd3ed32 100644 --- a/assets/resources/apps_data/nrf24scan/addresses.txt +++ b/assets/resources/apps_data/nrf24scan/addresses.txt @@ -3,6 +3,7 @@ Ch: 2 ESB: 1 DPL: 0 CRC: 2 +Payload: 4 P0: C8C8C0 P1: C8C8C1 P2: C2 From 40700c1ffbeb927aaa3c3de018e668d3661bc6e2 Mon Sep 17 00:00:00 2001 From: RogueMaster Date: Sat, 24 Dec 2022 01:56:07 -0500 Subject: [PATCH 4/8] Latest Release RM1224-0152-0.74.2-05f8cf2 on PATREON --- ReadMe.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ReadMe.md b/ReadMe.md index 6a9177677..1fe39ed62 100644 --- a/ReadMe.md +++ b/ReadMe.md @@ -16,7 +16,7 @@ Thank you to all the supporters! - Donations: ETH: `0xC32Ea488DBeCF95992A5C81BD411e56Bd418BC5f` - [Join THE Flipper Uncensored Discord](https://discord.gg/gF2bBUzAFe) -## Latest Updates - [PATREON: Latest Release RM1223-1104-0.74.2-0652595](https://www.patreon.com/posts/76286379) +## Latest Updates - [PATREON: Latest Release RM1224-0152-0.74.2-05f8cf2](https://www.patreon.com/posts/76312727) ## [BUILDS NOW AVAILABLE WITH STOCK, RM SELECT, RM SELECT + 18PLUS, RM MINIMAL (default) and RM 18PLUS ANIMATION SETS](https://www.patreon.com/RogueMaster/membership) From 5d9926be0a6c650011d8bf1858abd0893c93c33f Mon Sep 17 00:00:00 2001 From: RogueMaster Date: Sat, 24 Dec 2022 06:59:56 -0500 Subject: [PATCH 5/8] nrf24 fix --- applications/plugins/nrf24scan/nrf24scan.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/applications/plugins/nrf24scan/nrf24scan.c b/applications/plugins/nrf24scan/nrf24scan.c index d142d1479..6d8e5b984 100644 --- a/applications/plugins/nrf24scan/nrf24scan.c +++ b/applications/plugins/nrf24scan/nrf24scan.c @@ -517,13 +517,14 @@ static void prepare_nrf24(bool fsend_packet) { } if(what_to_do == 1) { // SNIFF payload = 32; - nrf24_write_reg(nrf24_HANDLE, REG_CONFIG, 0x70); // Mask all interrupts + nrf24_write_reg(nrf24_HANDLE, REG_CONFIG, 0x70); // Mask all interrupts, NO CRC nrf24_write_reg(nrf24_HANDLE, REG_SETUP_RETR, 0); // Automatic Retransmission nrf24_write_reg(nrf24_HANDLE, REG_EN_AA, 0); // Auto acknowledgement nrf24_write_reg( nrf24_HANDLE, REG_FEATURE, 0); // Enables the W_TX_PAYLOAD_NOACK command, Disable Payload with ACK, set Dynamic Payload + nrf24_write_reg(nrf24_HANDLE, REG_RF_CH, NRF_channel); } else if(setup_from_log) { // Scan nrf24_write_reg( nrf24_HANDLE, From 92e8ab89483f952f72bae0dd6c9455c0fa649c79 Mon Sep 17 00:00:00 2001 From: RogueMaster Date: Sat, 24 Dec 2022 07:04:11 -0500 Subject: [PATCH 6/8] Latest Release RM1224-0701-0.74.2-5d9926b on PATREON --- ReadMe.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ReadMe.md b/ReadMe.md index 1fe39ed62..db6987ea1 100644 --- a/ReadMe.md +++ b/ReadMe.md @@ -16,7 +16,7 @@ Thank you to all the supporters! - Donations: ETH: `0xC32Ea488DBeCF95992A5C81BD411e56Bd418BC5f` - [Join THE Flipper Uncensored Discord](https://discord.gg/gF2bBUzAFe) -## Latest Updates - [PATREON: Latest Release RM1224-0152-0.74.2-05f8cf2](https://www.patreon.com/posts/76312727) +## Latest Updates - [PATREON: Latest Release RM1224-0701-0.74.2-5d9926b](https://www.patreon.com/posts/76318937) ## [BUILDS NOW AVAILABLE WITH STOCK, RM SELECT, RM SELECT + 18PLUS, RM MINIMAL (default) and RM 18PLUS ANIMATION SETS](https://www.patreon.com/RogueMaster/membership) From c2cb14834d5ef65c36ffcc00ae6bc6ffaf69ca02 Mon Sep 17 00:00:00 2001 From: Sergey Gavrilov Date: Sun, 25 Dec 2022 00:13:21 +1000 Subject: [PATCH 7/8] [FL-3062] Fix unit tests (#2180) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * SubGHZ unit test: fail if async_tx is not started * Memgr unit test: fix for multithreaded enviroment * Unit tests: fix failed_tests count * Unit tests: remove debug code * Double update test: increase flipper detection time Co-authored-by: あく --- .../debug/unit_tests/furi/furi_memmgr_test.c | 99 ++++--------------- .../debug/unit_tests/subghz/subghz_test.c | 5 +- applications/debug/unit_tests/test_index.c | 38 +++---- scripts/testing/await_flipper.py | 2 +- 4 files changed, 44 insertions(+), 100 deletions(-) diff --git a/applications/debug/unit_tests/furi/furi_memmgr_test.c b/applications/debug/unit_tests/furi/furi_memmgr_test.c index cf3848747..f7bc234a0 100644 --- a/applications/debug/unit_tests/furi/furi_memmgr_test.c +++ b/applications/debug/unit_tests/furi/furi_memmgr_test.c @@ -3,98 +3,37 @@ #include #include -// this test is not accurate, but gives a basic understanding -// that memory management is working fine - -// do not include memmgr.h here -// we also test that we are linking against stdlib -extern size_t memmgr_get_free_heap(void); -extern size_t memmgr_get_minimum_free_heap(void); - -// current heap management realization consume: -// X bytes after allocate and 0 bytes after allocate and free, -// where X = sizeof(void*) + sizeof(size_t), look to BlockLink_t -const size_t heap_overhead_max_size = sizeof(void*) + sizeof(size_t); - -bool heap_equal(size_t heap_size, size_t heap_size_old) { - // heap borders with overhead - const size_t heap_low = heap_size_old - heap_overhead_max_size; - const size_t heap_high = heap_size_old + heap_overhead_max_size; - - // not exact, so we must test it against bigger numbers than "overhead size" - const bool result = ((heap_size >= heap_low) && (heap_size <= heap_high)); - - // debug allocation info - if(!result) { - printf("\n(hl: %zu) <= (p: %zu) <= (hh: %zu)\n", heap_low, heap_size, heap_high); - } - - return result; -} - void test_furi_memmgr() { - size_t heap_size = 0; - size_t heap_size_old = 0; - const int alloc_size = 128; - - void* ptr = NULL; - void* original_ptr = NULL; - - // do not include furi memmgr.h case -#ifdef FURI_MEMMGR_GUARD - mu_fail("do not link against furi memmgr.h"); -#endif + void* ptr; // allocate memory case - heap_size_old = memmgr_get_free_heap(); - ptr = malloc(alloc_size); - heap_size = memmgr_get_free_heap(); - mu_assert_pointers_not_eq(ptr, NULL); - mu_assert(heap_equal(heap_size, heap_size_old - alloc_size), "allocate failed"); - - // free memory case - heap_size_old = memmgr_get_free_heap(); + ptr = malloc(100); + mu_check(ptr != NULL); + // test that memory is zero-initialized after allocation + for(int i = 0; i < 100; i++) { + mu_assert_int_eq(0, ((uint8_t*)ptr)[i]); + } free(ptr); - ptr = NULL; - heap_size = memmgr_get_free_heap(); - mu_assert(heap_equal(heap_size, heap_size_old + alloc_size), "free failed"); // reallocate memory case + ptr = malloc(100); + memset(ptr, 66, 100); + ptr = realloc(ptr, 200); + mu_check(ptr != NULL); - // get filled array with some data - original_ptr = malloc(alloc_size); - mu_assert_pointers_not_eq(original_ptr, NULL); - for(int i = 0; i < alloc_size; i++) { - *(unsigned char*)(original_ptr + i) = i; + // test that memory is really reallocated + for(int i = 0; i < 100; i++) { + mu_assert_int_eq(66, ((uint8_t*)ptr)[i]); } - // malloc array and copy data - ptr = malloc(alloc_size); - mu_assert_pointers_not_eq(ptr, NULL); - memcpy(ptr, original_ptr, alloc_size); - - // reallocate array - heap_size_old = memmgr_get_free_heap(); - ptr = realloc(ptr, alloc_size * 2); - heap_size = memmgr_get_free_heap(); - mu_assert(heap_equal(heap_size, heap_size_old - alloc_size), "reallocate failed"); - mu_assert_int_eq(memcmp(original_ptr, ptr, alloc_size), 0); - free(original_ptr); + // TODO: fix realloc to copy only old size, and write testcase that leftover of reallocated memory is zero-initialized free(ptr); // allocate and zero-initialize array (calloc) - original_ptr = malloc(alloc_size); - mu_assert_pointers_not_eq(original_ptr, NULL); - - for(int i = 0; i < alloc_size; i++) { - *(unsigned char*)(original_ptr + i) = 0; + ptr = calloc(100, 2); + mu_check(ptr != NULL); + for(int i = 0; i < 100 * 2; i++) { + mu_assert_int_eq(0, ((uint8_t*)ptr)[i]); } - heap_size_old = memmgr_get_free_heap(); - ptr = calloc(1, alloc_size); - heap_size = memmgr_get_free_heap(); - mu_assert(heap_equal(heap_size, heap_size_old - alloc_size), "callocate failed"); - mu_assert_int_eq(memcmp(original_ptr, ptr, alloc_size), 0); - - free(original_ptr); free(ptr); } diff --git a/applications/debug/unit_tests/subghz/subghz_test.c b/applications/debug/unit_tests/subghz/subghz_test.c index d954ddd94..cb89e1f02 100644 --- a/applications/debug/unit_tests/subghz/subghz_test.c +++ b/applications/debug/unit_tests/subghz/subghz_test.c @@ -318,7 +318,10 @@ bool subghz_hal_async_tx_test_run(SubGhzHalAsyncTxTestType type) { furi_hal_subghz_load_preset(FuriHalSubGhzPresetOok650Async); furi_hal_subghz_set_frequency_and_path(433920000); - furi_hal_subghz_start_async_tx(subghz_hal_async_tx_test_yield, &test); + if(!furi_hal_subghz_start_async_tx(subghz_hal_async_tx_test_yield, &test)) { + return false; + } + while(!furi_hal_subghz_is_async_tx_complete()) { furi_delay_ms(10); } diff --git a/applications/debug/unit_tests/test_index.c b/applications/debug/unit_tests/test_index.c index 36c2b4aef..5bc53c82e 100644 --- a/applications/debug/unit_tests/test_index.c +++ b/applications/debug/unit_tests/test_index.c @@ -73,7 +73,6 @@ void unit_tests_cli(Cli* cli, FuriString* args, void* context) { UNUSED(cli); UNUSED(args); UNUSED(context); - uint32_t failed_tests = 0; minunit_run = 0; minunit_assert = 0; minunit_fail = 0; @@ -99,32 +98,35 @@ void unit_tests_cli(Cli* cli, FuriString* args, void* context) { if(furi_string_size(args)) { if(furi_string_cmp_str(args, unit_tests[i].name) == 0) { - failed_tests += unit_tests[i].entry(); + unit_tests[i].entry(); } else { printf("Skipping %s\r\n", unit_tests[i].name); } } else { - failed_tests += unit_tests[i].entry(); + unit_tests[i].entry(); } } - printf("\r\nFailed tests: %lu\r\n", failed_tests); - // Time report - cycle_counter = (furi_get_tick() - cycle_counter); - printf("Consumed: %lu ms\r\n", cycle_counter); + if(minunit_run != 0) { + printf("\r\nFailed tests: %u\r\n", minunit_fail); - // Wait for tested services and apps to deallocate memory - furi_delay_ms(200); - uint32_t heap_after = memmgr_get_free_heap(); - printf("Leaked: %ld\r\n", heap_before - heap_after); + // Time report + cycle_counter = (furi_get_tick() - cycle_counter); + printf("Consumed: %lu ms\r\n", cycle_counter); - // Final Report - if(failed_tests == 0) { - notification_message(notification, &sequence_success); - printf("Status: PASSED\r\n"); - } else { - notification_message(notification, &sequence_error); - printf("Status: FAILED\r\n"); + // Wait for tested services and apps to deallocate memory + furi_delay_ms(200); + uint32_t heap_after = memmgr_get_free_heap(); + printf("Leaked: %ld\r\n", heap_before - heap_after); + + // Final Report + if(minunit_fail == 0) { + notification_message(notification, &sequence_success); + printf("Status: PASSED\r\n"); + } else { + notification_message(notification, &sequence_error); + printf("Status: FAILED\r\n"); + } } } diff --git a/scripts/testing/await_flipper.py b/scripts/testing/await_flipper.py index efae6765d..704d75a75 100755 --- a/scripts/testing/await_flipper.py +++ b/scripts/testing/await_flipper.py @@ -24,7 +24,7 @@ def flp_serial_by_name(flp_name): return "" -UPDATE_TIMEOUT = 60 +UPDATE_TIMEOUT = 60 * 4 # 4 minutes def main(): From 8dd0cf0cdf7c37095174f1746f4fe61f6eaed187 Mon Sep 17 00:00:00 2001 From: VerstreuteSeele Date: Sat, 24 Dec 2022 21:36:42 +0100 Subject: [PATCH 8/8] Asset fixes --- .../main/ibutton/images/DolphinNice_96x59.png | Bin 4599 -> 5422 bytes .../main/ibutton/images/DolphinWait_61x59.png | Bin 3896 -> 5122 bytes .../iButtonDolphinVerySuccess_108x52.png | Bin 2157 -> 4719 bytes applications/main/u2f/images/Auth_62x31.png | Bin 3761 -> 1864 bytes .../main/u2f/images/Connect_me_62x31.png | Bin 3767 -> 1895 bytes .../main/u2f/images/Connected_62x31.png | Bin 3765 -> 1874 bytes applications/main/u2f/images/Error_62x31.png | Bin 3751 -> 1863 bytes 7 files changed, 0 insertions(+), 0 deletions(-) diff --git a/applications/main/ibutton/images/DolphinNice_96x59.png b/applications/main/ibutton/images/DolphinNice_96x59.png index b111196c700fbb936a5e7636560b565334b979d3..43cc58bd9b263ddf1ae1676f997ebd3aa5c2d74d 100644 GIT binary patch literal 5422 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 Y0|Y+`m_^9JS^xk507*qoM6N<$f{I?90ssI2 literal 4599 zcmd5=2~-o;8pgi9mKMQMtqX`w15^+u$xM<-W)L-iK*X>_7NKr4lSvpLnJ`J%q;^4( zY5`Gb-4GPCRZv_|OQG^at+ogip;n|-ac$id++JJT2}{cB(aL#!@0{kGWai%a@4tTk z{qE%b@X#Rpmz`d=v9YmN1P7?N>wNC(WBVNUYqxv!o809kLvXB-8x6O7huExHH`>N# zXcQee%QQbEnI8S>+&>5_1^~Sz5aS0Qo;RXT37g|E<5mb{_IfI!^>M^b+1ymBH zqx2>tCkt6+4e^YLF~&1bQEh$v9|pM8DwS3nPxM8nvzjoPrloLU^d;np(#FVi10_&V zM#jvN)U*`NP1pWtj3yQJdp-xToD=U^Y{2|k3O6xqB*P^2S2?^tUI2#pFyIkG>(xxE z(bHnBZvhp6n-qg4Wf2OdS#54@6!?|qHI$TQ$408aS`;_YY?o z4V}b2Fsg$50L3(a1VRx6g!xd9yGkXd&>Ky-o}?53zC12gK257JkxV2*DH+LmE+Ij& z1d)KK7$-qQrjf|RB2*+HI72<<#sV19Y{8FZeQztN8IsfSyL)Oig`z@=03j&?fsjm0 zfCNP0AVfeiH6bHpVlm#YEsUkPZpM=aYPEQ!<}^}>NGcXeHK0VwIV6*CdQd_{T9m;A zq@iTE6t?tCuV2Bmk*jffUl-1#lKbwGXrKpq7*1L`%9lr4&_Jnqebe+4@-ZmOed|-> zDNgC1prqHjkB$rdWCa5C+1^>H;tTV1L!#Ghs)HWfX#nIii)~6eva{6i9Ha4r&mYRE82L zN{5E@!`{UiT`h<1ePOVFTDx=$b5Ya-P_867B=WPHDOQUxWS^4J4Rs~ z!&^DOpPdKWpO*E^UuAgvv;&<4Tb$CSHK-Q@=OAJL@{k5MKDr!MlwWWQeWP`(2I`lLguvpSJ!Q z{@r4Gw?_+{!lEX8_=f!}MUNeSac^IyoOax{BrNHTguEZ;e^Kn3d~-a2w4OV-Ao z4jq+fTI#j0Yst0iP4QnZ??y6J(UOvr5#6O>q%+Zh4~5(&)70mhd&~cF8@T z2yI!Qo$b>3p$}pjN6hm+8do^9A>z`*XziB3#GuM;1t;>$ybCtXa&_^kki=aEuH+PI zDnPF$vWSfcK-N8{xADie6R0{&0U|E_rVQLO=EAlNhplslAGo*W>JM;3&9*!}x~Fk= z%%YD{oQrfVo6JoeBVpp&ZF#{|C+5~q*S%B^180D#mH*!AEkC*O&eaJogg(AU!@jCh zb0%@Yny_RlQNpBtqpX+Q3qt>3WegU{-|&;E4m;T;jh>dwRu=t=+T5O46GiJ(65^f~<|!PQS7uaQ56P{qj{V5lHl- z=7z$fo=t9ZT1O9GmViV}|Izccnh;ZkFe}7cncGQSTKP?FX4w1nMF1f`>~*ABb?sbv zYiPRpoMBIA?V`m_1zt;4j>E2bFr5lHR76zd72f6-ZH=CIW<`A@y^Acb{POW=|HQf` z`zEjC3Co)j#_abxwWutkWPy82_2LlwP4=+4!|8Q&e0;|)*Trzh_Op-AjFT=;-FWh( z$Kz1c_|`?cg)0}nnC#G1tcYn2xUuK7yiu`eqz7`^EoVDs>+^B&_#4-nGv9uDg2P>x zkm8&+k2y0PUiONa2dz&KX$ravu4gKEoqKDg_YYhp%Cvi+HvjUVySoirrcV0K6x3eQ z5?p=q>hRE=4nK`--rOJ$TPVs+UXWRrS{ii}*p*e6a|fuuU-R4sH^*0gesF4U<=V#6 z8Lz+NeQ(j_DaR&emFCn`C+B-3asD4}^9jms4{G9l(WYmyeUoxmeK7jnmu&qqTi9^> zRoA-S5sW{k`qtF?kfTLn@9f16mXE=RP{NOA2{EI`NS)IqP=)?Bbuz@>|L+ss~j^zs)-T!ml<|-A20c TKCsjB*NkFXXux*A`S1M(Ru-fV diff --git a/applications/main/ibutton/images/DolphinWait_61x59.png b/applications/main/ibutton/images/DolphinWait_61x59.png index bb0c3840038a0470ea1830779c1f1ebf78b839e3..4beec55efbc4a6907e37e5d7422b9f7c33d3dbf1 100644 GIT binary patch literal 5122 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 literal 3896 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 literal 2157 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 diff --git a/applications/main/u2f/images/Connect_me_62x31.png b/applications/main/u2f/images/Connect_me_62x31.png index 68c48c0e68142548919d6a4b02e40b48a243b04e..495e8ab55c1e2dabb547151c2319f321f4af13bb 100644 GIT binary patch delta 1891 zcmV-p2b}n~9p?^^8Gix*001yk>3{$L010qNS#tmY4#NNd4#NS*Z>VGd00$XKL_t(| z+O?QlOjSn|hG8oRh>GGZ;swMCiVCP$2m(U5h>bOddI{B*1Oy&HNv)*;Bx*FKeZkhI zB-%dM1e>&xrj7K$)`!xj)v9R=_C!b_pdvRBLEK z*T2@F<>ch7UAs0lHPyw%W%1(0vu4fWapugKPEJnFFPgqDO&e_bx7Dv2om?gSDrp=gE^NdIBg8sLrZYs~}Qxax$H$sHm{8u)Msypr9a30==5a zBGSKg>sDb`!T3UNZ*QM6WyTNU-=G)7 zYFilOUQ<&uzR)2$tR2p2fv%WSS69dWba!{Vy1F(sHO-wnH}-0rkB?7qa4qP>Z+C&CQU9LAEP4HkJ-sfu~_V z#xQ|tn194ZjmD`;NvwJutRN6S306k%AA?JmE}b)Hj-En*yuA3Bc%7INGuVyUvu8hk{8$kQU-Am( z?A*E2_gg=;M0|WaQV3$W#INShpO3-F6#Y?pU4PvzLq~%F#K&+OlmP3qXU}jjzI^!b zA$^&LNz6p`=|o0Gp7kkvzjc3J)4r_#GQ-2enNI-Rym|B5wQC_EAp|r(ApnMEhL_if z=x!A{+yE273SaRP(sAn4DUvI=MK`erNnvN0jbX=+A4ea3eSO!hTNfG{x^?T;O`A3y zK7V`|BZc~%ot>gEBxXHs!d_jr(F4~kaauG$x8h zK>$3BB_uB%OG`^3dQnl)>C>m*ZA;r&o$Oz}hCH|~m=%8D%x3@Q9 zpPQQt{n)^a&OM4J` z;6QeEHXMujbHnhp3SEo72>3GouLSlGo6QwtC}J}Ty$W=pIQU=-noS;AxpHMfLIO6d z|0623>1_xD6DU`hom90k;qSx~KA+fL6xN~fX1L9`J_cS#1c6SZQuHAa7cN{VDJcPc zMMZ_ofH~|5l2?`VkAsU6B)gh-TYnW0=P}|s&?V!b*^*Pr%F2!%I|jLB1}uWRk-x8( znRZ*{>%ZWIQQ~%}hJg%x34G)~qysTQ4ats3d#UH=KL%AGc38#KfFA-K`Re)e=T#yz zqqu{(Rq3Mc7IUgb{Pp(s!U{M8ttp}KG4_}W?!rRu;MPNN1iG9;%oJvP5=&i3>3!?xNjc8YH;|2Z^PqxcysetUaZ|03GL9}00m)2BnQ5|^li z6l6#^jwh8`gsZNBk4%#(X<}kxEO5X$;u=O6-_c_oI#~I0_wHSMOqimNkej+dk>p%> zIRQXX@R|Eb!yEtVe+*o8@qZZhjj4!Vwrp8jTbnIF4l~|P@K<-eW^aB&TOHKn)K_}uPy*Tkbhhb?3!P=Xj2!XFf!3Ut%seSt+u^c>?GJv9N2wf(2uK d6tdy_{{j6OA(WAZ17rXI002ovPDHLkV1l_ti)jD= literal 3767 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 IM6N<$g6Xe=bpQYW literal 3765 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 literal 3751 zcmaJ@c|25Y8$PzOWJz{mj7Wu9B$SJOBT_hxTW}}?zE_4c_a$<+_)XRO1uf`sab3S=^Myapp zSwt9ndV1~CTIG25_YA#exFt~oydbeL)@xtB zdH|T^q0=I%j||tj9+CiVfZVCIN4#P1S9FEFnkxWG0tUe1<3e1CXrNKcsZj!GlmQ+& zKJ^v^QUD;39&Q2#?h6A`3swevKsO_~Pa5dX-_76$u5$qy>Xv)Bja~w$ozJ5+xNBbn zc}yd)7H@3{SCsp6xFvT~6(0~1@0KWPbQ*}tFwtlRK!>>jQ^j2^JRobHJZMMF0K=0U zQ;y;SYFVi*>Bl;>CCXFZ%Z2`!9T-v`dL8)K1S7pq%tv4ZoSmMfvI{lNW8Jy~0OVHM zUu_;XOdKB@865K&4`eUY=WhnglE4PabN!o@*SL8BG21qFkLT!U7Z16C>rrq`0OJJE z;{y2guXt$p3gjIZd>^(FM?bu7q?mi#zENLcx1f;Fw5r$bD(G;W!7uGW(m-6~66fn? zZ`dqwCetXRxV9jA;|zuvQi6^jXYrcAh|A+Dn+-ANHsbfS4;_4bQbY3UoZFRhd$3Id z{RKM7Ot~p_NPOZPd`>BCLm)X+7+_wqtF?W;{TVB;HgblGJ5I!{BLpytoY%Z2CzJ$; z`5uJRmjNKTW+lPs02k1bUN{T@mEUAe-b<0Te#;L4W_joLKQi9F20TF za$n0-UJ~FnZsgyEQAWh>^os8WxAIG8#PfnNsDn463PBUG5)R<{MoJ+!!^A(y1Eumq zlOmya{iM-qVs9e|es%q7r6nxo{1XSBkKDmVFYYPHU45Gu)J{Dp>JgQeAJ8sWs)&qw zo?p~{>{~Duh`1V$jcSL9_+0ypIeG1}`ROZea%v4y*iknfmjoTGf}3uLq4Uoako3 zRGU#&RL)gBwO3@9XEJJ!NYjlGTR~;jM7WiZRRF3NrCI1$XwV^s&$d>ZOe8dY9pQfx z#RR1%l_iQM+TB=ddNWccfvArivKGkSgDy-FKdOT>9Ob=p3vQB;ci*9fk^7PVek|hF zaVtVzh&{ydGGo`l;7rw)EGbh~p=Lqn`%Jtqe%TK)L9Gz@60K;S{yx1U;M?|z@rme# z&>g~;grgf!Uh1*|vS($BWXfbA8P<3CKBQ+fIzd0dXI6nI)2~DImp?tlYU>w>4CH8gHtXMcP*Ts+7B}XK1x04WGFblWE?7KMTepj?AshX z3#vUgF05jOpInNu$h(9paKe_omA$Sk^%jnsb2I6pxbRGB1l+XoI`L#>$~uH^O+Ey2 z*4oiD=)MorC&?#g>`V)n$lJ#QvwEMikG3ke3b&rs{A?BtlJaTQ{Ce= zO_`ROp6p=~lam^ggf7=WdwJKa z9a)Gh*7JMCS;ciBS%iLxA&G>29s3p?i9N8X^(n!r%&BeDdP|rk)g{7Gn?mz$afPlU z)Fa^(YH)K%Ah~j~aPZ(8MjhkLgsZQ-@9m(Rc^&Dy#}ZlM=^^RTj)bDCMZ{ZStkhAt znTn2Q9~KL;US{cGoKuul^m;yV9C9k; zl>4c*Dn+}e*=o66P(ovG-HCxJ*4fht10-&>b%Mv>tpWF~uv?d_?^c8Rk<}`ZU6C1) z+t+i~j;yja5`NYU(tk+J+47y{dc`%$RdrtO{8OF)9wpuk-aFfM_^$K4+y>cUAZfBg zK-gW0l1!?V{vp4D)$a4v$ZVH<$Dbp4Tz(bWtY)p)wKM)w8-Kr8Brq*o_tuZ4`F>xR@1VXI`CuJ>TJRS@}`@8)G>xsY{2y z9EmVp^}A$e5&TwLzz%(Yo+NwYh045*i&@uKX4~g8pEdPTvQx4P(8Bn%(gUBMW$I;i zJ_imY3y;vp2=C;RFTYzJQCSI^@0ARUv2HIYMVHu%NLfSf9iW|%IYBE&RiTc5)b97$ z{Jx?hbU`Y-D)Eth`J<=ZuJ#fMGU@9Y}iA5|~IQ{}FiAnW#X8Wgio^Uz0Upm#3NoL+F`T5AA zd~C?o*0VEwkxuC8`FgbM-Si}CvT%~fTz0Q{c(lsjxbyv`S>a;&x$C3yo`j=cskg)Y z7voz>Ti&(s=wNiFPc%Pg_Wrnis9-59=bQ)2Wuy2(S@mbNp01iNp=aksq7@{Md}XIh zRX#gFa}B66k60vj%v|`AAm=4tQ8O0#rQ9;qu0A*6?47gQm(1Cd{!~(6-@}@kCjtcY zq3en$1bH+oiqw-eof-O!e0;yiYva*Zd;9N(pB=XUcDwaW-rg*)WZ{` zN!&7P+Eu@Vx?nSTq@DfY+^Tb~(GEzoAMgLw((7(|*2v728ns-fr1oJbZH&N5z0>gg{~tf`$bDrHkOqx6BYQ=r0I0015tgP;NH%AX5?r2h!Do zX=0&JC`eaN3+Ii2dujV%uo@sZ6b^&HIJd4QOcw#yM!@tye_vpZLyET#0&QmTw>!=X z3HGB>$p{D}G&EEzR9lNg@rA(j^z9U%aaLwXFh@iSkM~AE&5cbh^bSD}LA7Bpn7OI3u8xkLIsA~0 zxrG@Ns;&2%YevEb6L3W8Z?5-$xUfHRw;F;#=6E*4QSc!+Zwm^E0QxIy1pbe)=$QXe z?{BX6A7jz6_#+p>2?nyYxBs=*zfGJ5+M52;yqv{9?T;gJdY-~*Zg0;L80TPYv$u9K z|8;fij8rUEKsiIHm6@>86>a#`zsK)U zcJjEKZ