diff --git a/.github/assets/social-preview.png b/.github/assets/social-preview.png new file mode 100644 index 000000000..a26053cd6 Binary files /dev/null and b/.github/assets/social-preview.png differ diff --git a/applications/debug/file_browser_test/scenes/file_browser_scene_start.c b/applications/debug/file_browser_test/scenes/file_browser_scene_start.c index 9211ff3bb..9eb26944f 100644 --- a/applications/debug/file_browser_test/scenes/file_browser_scene_start.c +++ b/applications/debug/file_browser_test/scenes/file_browser_scene_start.c @@ -19,7 +19,7 @@ bool file_browser_scene_start_on_event(void* context, SceneManagerEvent event) { bool consumed = false; if(event.type == SceneManagerEventTypeCustom) { - furi_string_set(app->file_path, ANY_PATH("badkb/demo_windows.txt")); + furi_string_set(app->file_path, ANY_PATH("badusb/demo_windows.txt")); scene_manager_next_scene(app->scene_manager, FileBrowserSceneBrowser); consumed = true; } else if(event.type == SceneManagerEventTypeTick) { diff --git a/applications/debug/unit_tests/datetimelib/datetimelib_test.c b/applications/debug/unit_tests/datetimelib/datetimelib_test.c index 42bc7dbed..bf8e6fabd 100644 --- a/applications/debug/unit_tests/datetimelib/datetimelib_test.c +++ b/applications/debug/unit_tests/datetimelib/datetimelib_test.c @@ -112,7 +112,7 @@ MU_TEST_SUITE(test_datetime_validate_datetime) { MU_TEST(test_datetime_timestamp_to_datetime_min) { uint32_t test_value = 0; - DateTime min_datetime_expected = {0, 0, 0, 1, 1, 1970, 0}; + DateTime min_datetime_expected = {0, 0, 0, 1, 1, 1970, 4}; DateTime result = {0}; datetime_timestamp_to_datetime(test_value, &result); @@ -122,7 +122,7 @@ MU_TEST(test_datetime_timestamp_to_datetime_min) { MU_TEST(test_datetime_timestamp_to_datetime_max) { uint32_t test_value = UINT32_MAX; - DateTime max_datetime_expected = {6, 28, 15, 7, 2, 2106, 0}; + DateTime max_datetime_expected = {6, 28, 15, 7, 2, 2106, 7}; DateTime result = {0}; datetime_timestamp_to_datetime(test_value, &result); @@ -141,10 +141,26 @@ MU_TEST(test_datetime_timestamp_to_datetime_to_timestamp) { mu_assert_int_eq(test_value, result); } +MU_TEST(test_datetime_timestamp_to_datetime_weekday) { + uint32_t test_value = 1709748421; // Wed Mar 06 18:07:01 2024 UTC + + DateTime datetime = {0}; + datetime_timestamp_to_datetime(test_value, &datetime); + + mu_assert_int_eq(datetime.hour, 18); + mu_assert_int_eq(datetime.minute, 7); + mu_assert_int_eq(datetime.second, 1); + mu_assert_int_eq(datetime.day, 6); + mu_assert_int_eq(datetime.month, 3); + mu_assert_int_eq(datetime.weekday, 3); + mu_assert_int_eq(datetime.year, 2024); +} + MU_TEST_SUITE(test_datetime_timestamp_to_datetime_suite) { MU_RUN_TEST(test_datetime_timestamp_to_datetime_min); MU_RUN_TEST(test_datetime_timestamp_to_datetime_max); MU_RUN_TEST(test_datetime_timestamp_to_datetime_to_timestamp); + MU_RUN_TEST(test_datetime_timestamp_to_datetime_weekday); } MU_TEST(test_datetime_datetime_to_timestamp_min) { diff --git a/applications/external b/applications/external index a3b7d5046..ae1131894 160000 --- a/applications/external +++ b/applications/external @@ -1 +1 @@ -Subproject commit a3b7d504694797cbe18c3b70f5cad848e97ec732 +Subproject commit ae1131894f6830d782d1240bd73669a72cc9f650 diff --git a/applications/main/archive/helpers/archive_browser.h b/applications/main/archive/helpers/archive_browser.h index 232ca5c60..6966dc8de 100644 --- a/applications/main/archive/helpers/archive_browser.h +++ b/applications/main/archive/helpers/archive_browser.h @@ -14,7 +14,7 @@ static const char* tab_default_paths[] = { [ArchiveTabSubGhz] = EXT_PATH("subghz"), [ArchiveTabLFRFID] = EXT_PATH("lfrfid"), [ArchiveTabInfrared] = EXT_PATH("infrared"), - [ArchiveTabBadKb] = EXT_PATH("badkb"), + [ArchiveTabBadKb] = EXT_PATH("badusb"), [ArchiveTabU2f] = "/app:u2f", [ArchiveTabApplications] = EXT_PATH("apps"), [ArchiveTabSearch] = "/app:search", diff --git a/applications/main/bad_kb/bad_kb_app.c b/applications/main/bad_kb/bad_kb_app.c index 081a5dfe8..883371c47 100644 --- a/applications/main/bad_kb/bad_kb_app.c +++ b/applications/main/bad_kb/bad_kb_app.c @@ -3,7 +3,6 @@ #include #include #include -#include #include #include #include "helpers/ducky_script_i.h" @@ -29,7 +28,7 @@ static void bad_kb_app_tick_event_callback(void* context) { scene_manager_handle_tick_event(app->scene_manager); } -static void bad_kb_load_settings(BadKbApp* app) { +void bad_kb_load_settings(BadKbApp* app) { furi_string_reset(app->keyboard_layout); BadKbConfig* cfg = &app->config; @@ -37,35 +36,59 @@ static void bad_kb_load_settings(BadKbApp* app) { FlipperFormat* file = flipper_format_file_alloc(storage); if(flipper_format_file_open_existing(file, BAD_KB_SETTINGS_PATH)) { FuriString* tmp_str = furi_string_alloc(); + if(!flipper_format_read_string(file, "Keyboard_Layout", app->keyboard_layout)) { furi_string_reset(app->keyboard_layout); + flipper_format_rewind(file); } - if(flipper_format_read_string(file, "Bt_Name", tmp_str) && !furi_string_empty(tmp_str)) { + + if(!flipper_format_read_bool(file, "Is_Bt", &app->is_bt, 1)) { + app->is_bt = false; + flipper_format_rewind(file); + } + + if(!flipper_format_read_bool(file, "Bt_Remember", &app->bt_remember, 1)) { + app->bt_remember = false; + flipper_format_rewind(file); + } + + if(flipper_format_read_string(file, "Bt_Name", tmp_str)) { strlcpy(cfg->ble.name, furi_string_get_cstr(tmp_str), sizeof(cfg->ble.name)); } else { - strcpy(cfg->ble.name, ""); + cfg->ble.name[0] = '\0'; + flipper_format_rewind(file); } + if(!flipper_format_read_hex( file, "Bt_Mac", (uint8_t*)&cfg->ble.mac, sizeof(cfg->ble.mac))) { memset(cfg->ble.mac, 0, sizeof(cfg->ble.mac)); + flipper_format_rewind(file); } - if(flipper_format_read_string(file, "Usb_Manuf", tmp_str) && !furi_string_empty(tmp_str)) { + + if(flipper_format_read_string(file, "Usb_Manuf", tmp_str)) { strlcpy(cfg->usb.manuf, furi_string_get_cstr(tmp_str), sizeof(cfg->usb.manuf)); } else { - strcpy(cfg->usb.manuf, ""); + cfg->usb.manuf[0] = '\0'; + flipper_format_rewind(file); } - if(flipper_format_read_string(file, "Usb_Product", tmp_str) && - !furi_string_empty(tmp_str)) { + + if(flipper_format_read_string(file, "Usb_Product", tmp_str)) { strlcpy(cfg->usb.product, furi_string_get_cstr(tmp_str), sizeof(cfg->usb.product)); } else { - strcpy(cfg->usb.product, ""); + cfg->usb.product[0] = '\0'; + flipper_format_rewind(file); } + if(!flipper_format_read_uint32(file, "Usb_Vid", &cfg->usb.vid, 1)) { cfg->usb.vid = 0; + flipper_format_rewind(file); } + if(!flipper_format_read_uint32(file, "Usb_Pid", &cfg->usb.pid, 1)) { cfg->usb.pid = 0; + flipper_format_rewind(file); } + furi_string_free(tmp_str); flipper_format_file_close(file); } @@ -93,6 +116,8 @@ static void bad_kb_save_settings(BadKbApp* app) { FlipperFormat* file = flipper_format_file_alloc(storage); if(flipper_format_file_open_always(file, BAD_KB_SETTINGS_PATH)) { flipper_format_write_string(file, "Keyboard_Layout", app->keyboard_layout); + flipper_format_write_bool(file, "Is_Bt", &app->is_bt, 1); + flipper_format_write_bool(file, "Bt_Remember", &app->bt_remember, 1); flipper_format_write_string_cstr(file, "Bt_Name", cfg->ble.name); flipper_format_write_hex(file, "Bt_Mac", (uint8_t*)&cfg->ble.mac, sizeof(cfg->ble.mac)); flipper_format_write_string_cstr(file, "Usb_Manuf", cfg->usb.manuf); @@ -265,14 +290,6 @@ void bad_kb_config_refresh(BadKbApp* app) { // Reload config page scene_manager_next_scene(app->scene_manager, BadKbSceneConfig); scene_manager_previous_scene(app->scene_manager); - - // Update settings - if(momentum_settings.bad_bt != app->is_bt || - momentum_settings.bad_bt_remember != app->bt_remember) { - momentum_settings.bad_bt = app->is_bt; - momentum_settings.bad_bt_remember = app->bt_remember; - momentum_settings_save(); - } } BadKbApp* bad_kb_app_alloc(char* arg) { @@ -308,8 +325,6 @@ BadKbApp* bad_kb_app_alloc(char* arg) { Bt* bt = furi_record_open(RECORD_BT); app->bt = bt; app->bt->suppress_pin_screen = true; - app->is_bt = momentum_settings.bad_bt; - app->bt_remember = momentum_settings.bad_bt_remember; bad_kb_config_adjust(&app->config); // Save prev config diff --git a/applications/main/bad_kb/bad_kb_app_i.h b/applications/main/bad_kb/bad_kb_app_i.h index 8618ea999..e009f0e60 100644 --- a/applications/main/bad_kb/bad_kb_app_i.h +++ b/applications/main/bad_kb/bad_kb_app_i.h @@ -102,6 +102,8 @@ typedef enum { void bad_kb_app_show_loading_popup(BadKbApp* app, bool show); +void bad_kb_load_settings(BadKbApp* app); + int32_t bad_kb_conn_apply(BadKbApp* app); void bad_kb_conn_reset(BadKbApp* app); diff --git a/applications/main/bad_kb/bad_kb_paths.h b/applications/main/bad_kb/bad_kb_paths.h index 72685b905..4ba1bbbab 100644 --- a/applications/main/bad_kb/bad_kb_paths.h +++ b/applications/main/bad_kb/bad_kb_paths.h @@ -2,7 +2,7 @@ #include -#define BAD_KB_APP_BASE_FOLDER EXT_PATH("badkb") +#define BAD_KB_APP_BASE_FOLDER EXT_PATH("badusb") #define BAD_KB_KEYS_PATH BAD_KB_APP_BASE_FOLDER "/.badkb.keys" #define BAD_KB_SETTINGS_PATH BAD_KB_APP_BASE_FOLDER "/.badkb.settings" #define BAD_KB_APP_PATH_LAYOUT_FOLDER BAD_KB_APP_BASE_FOLDER "/assets/layouts" diff --git a/applications/main/bad_kb/resources/badkb/assets/layouts/ba-BA.kl b/applications/main/bad_kb/resources/badusb/assets/layouts/ba-BA.kl similarity index 100% rename from applications/main/bad_kb/resources/badkb/assets/layouts/ba-BA.kl rename to applications/main/bad_kb/resources/badusb/assets/layouts/ba-BA.kl diff --git a/applications/main/bad_kb/resources/badkb/assets/layouts/cz_CS.kl b/applications/main/bad_kb/resources/badusb/assets/layouts/cz_CS.kl similarity index 100% rename from applications/main/bad_kb/resources/badkb/assets/layouts/cz_CS.kl rename to applications/main/bad_kb/resources/badusb/assets/layouts/cz_CS.kl diff --git a/applications/main/bad_kb/resources/badkb/assets/layouts/da-DA.kl b/applications/main/bad_kb/resources/badusb/assets/layouts/da-DA.kl similarity index 100% rename from applications/main/bad_kb/resources/badkb/assets/layouts/da-DA.kl rename to applications/main/bad_kb/resources/badusb/assets/layouts/da-DA.kl diff --git a/applications/main/bad_kb/resources/badkb/assets/layouts/de-CH.kl b/applications/main/bad_kb/resources/badusb/assets/layouts/de-CH.kl similarity index 100% rename from applications/main/bad_kb/resources/badkb/assets/layouts/de-CH.kl rename to applications/main/bad_kb/resources/badusb/assets/layouts/de-CH.kl diff --git a/applications/main/bad_kb/resources/badkb/assets/layouts/de-DE.kl b/applications/main/bad_kb/resources/badusb/assets/layouts/de-DE.kl similarity index 100% rename from applications/main/bad_kb/resources/badkb/assets/layouts/de-DE.kl rename to applications/main/bad_kb/resources/badusb/assets/layouts/de-DE.kl diff --git a/applications/main/bad_kb/resources/badkb/assets/layouts/dvorak.kl b/applications/main/bad_kb/resources/badusb/assets/layouts/dvorak.kl similarity index 100% rename from applications/main/bad_kb/resources/badkb/assets/layouts/dvorak.kl rename to applications/main/bad_kb/resources/badusb/assets/layouts/dvorak.kl diff --git a/applications/main/bad_kb/resources/badkb/assets/layouts/en-UK.kl b/applications/main/bad_kb/resources/badusb/assets/layouts/en-UK.kl similarity index 100% rename from applications/main/bad_kb/resources/badkb/assets/layouts/en-UK.kl rename to applications/main/bad_kb/resources/badusb/assets/layouts/en-UK.kl diff --git a/applications/main/bad_kb/resources/badkb/assets/layouts/en-US.kl b/applications/main/bad_kb/resources/badusb/assets/layouts/en-US.kl similarity index 100% rename from applications/main/bad_kb/resources/badkb/assets/layouts/en-US.kl rename to applications/main/bad_kb/resources/badusb/assets/layouts/en-US.kl diff --git a/applications/main/bad_kb/resources/badkb/assets/layouts/es-ES.kl b/applications/main/bad_kb/resources/badusb/assets/layouts/es-ES.kl similarity index 100% rename from applications/main/bad_kb/resources/badkb/assets/layouts/es-ES.kl rename to applications/main/bad_kb/resources/badusb/assets/layouts/es-ES.kl diff --git a/applications/main/bad_kb/resources/badkb/assets/layouts/fr-BE.kl b/applications/main/bad_kb/resources/badusb/assets/layouts/fr-BE.kl similarity index 100% rename from applications/main/bad_kb/resources/badkb/assets/layouts/fr-BE.kl rename to applications/main/bad_kb/resources/badusb/assets/layouts/fr-BE.kl diff --git a/applications/main/bad_kb/resources/badkb/assets/layouts/fr-CA.kl b/applications/main/bad_kb/resources/badusb/assets/layouts/fr-CA.kl similarity index 100% rename from applications/main/bad_kb/resources/badkb/assets/layouts/fr-CA.kl rename to applications/main/bad_kb/resources/badusb/assets/layouts/fr-CA.kl diff --git a/applications/main/bad_kb/resources/badkb/assets/layouts/fr-CH.kl b/applications/main/bad_kb/resources/badusb/assets/layouts/fr-CH.kl similarity index 100% rename from applications/main/bad_kb/resources/badkb/assets/layouts/fr-CH.kl rename to applications/main/bad_kb/resources/badusb/assets/layouts/fr-CH.kl diff --git a/applications/main/bad_kb/resources/badkb/assets/layouts/fr-FR-mac.kl b/applications/main/bad_kb/resources/badusb/assets/layouts/fr-FR-mac.kl similarity index 100% rename from applications/main/bad_kb/resources/badkb/assets/layouts/fr-FR-mac.kl rename to applications/main/bad_kb/resources/badusb/assets/layouts/fr-FR-mac.kl diff --git a/applications/main/bad_kb/resources/badkb/assets/layouts/fr-FR.kl b/applications/main/bad_kb/resources/badusb/assets/layouts/fr-FR.kl similarity index 100% rename from applications/main/bad_kb/resources/badkb/assets/layouts/fr-FR.kl rename to applications/main/bad_kb/resources/badusb/assets/layouts/fr-FR.kl diff --git a/applications/main/bad_kb/resources/badkb/assets/layouts/hr-HR.kl b/applications/main/bad_kb/resources/badusb/assets/layouts/hr-HR.kl similarity index 100% rename from applications/main/bad_kb/resources/badkb/assets/layouts/hr-HR.kl rename to applications/main/bad_kb/resources/badusb/assets/layouts/hr-HR.kl diff --git a/applications/main/bad_kb/resources/badkb/assets/layouts/hu-HU.kl b/applications/main/bad_kb/resources/badusb/assets/layouts/hu-HU.kl similarity index 100% rename from applications/main/bad_kb/resources/badkb/assets/layouts/hu-HU.kl rename to applications/main/bad_kb/resources/badusb/assets/layouts/hu-HU.kl diff --git a/applications/main/bad_kb/resources/badkb/assets/layouts/it-IT-mac.kl b/applications/main/bad_kb/resources/badusb/assets/layouts/it-IT-mac.kl similarity index 100% rename from applications/main/bad_kb/resources/badkb/assets/layouts/it-IT-mac.kl rename to applications/main/bad_kb/resources/badusb/assets/layouts/it-IT-mac.kl diff --git a/applications/main/bad_kb/resources/badkb/assets/layouts/it-IT.kl b/applications/main/bad_kb/resources/badusb/assets/layouts/it-IT.kl similarity index 100% rename from applications/main/bad_kb/resources/badkb/assets/layouts/it-IT.kl rename to applications/main/bad_kb/resources/badusb/assets/layouts/it-IT.kl diff --git a/applications/main/bad_kb/resources/badkb/assets/layouts/nb-NO.kl b/applications/main/bad_kb/resources/badusb/assets/layouts/nb-NO.kl similarity index 100% rename from applications/main/bad_kb/resources/badkb/assets/layouts/nb-NO.kl rename to applications/main/bad_kb/resources/badusb/assets/layouts/nb-NO.kl diff --git a/applications/main/bad_kb/resources/badkb/assets/layouts/nl-NL.kl b/applications/main/bad_kb/resources/badusb/assets/layouts/nl-NL.kl similarity index 100% rename from applications/main/bad_kb/resources/badkb/assets/layouts/nl-NL.kl rename to applications/main/bad_kb/resources/badusb/assets/layouts/nl-NL.kl diff --git a/applications/main/bad_kb/resources/badkb/assets/layouts/pt-BR.kl b/applications/main/bad_kb/resources/badusb/assets/layouts/pt-BR.kl similarity index 100% rename from applications/main/bad_kb/resources/badkb/assets/layouts/pt-BR.kl rename to applications/main/bad_kb/resources/badusb/assets/layouts/pt-BR.kl diff --git a/applications/main/bad_kb/resources/badkb/assets/layouts/pt-PT.kl b/applications/main/bad_kb/resources/badusb/assets/layouts/pt-PT.kl similarity index 100% rename from applications/main/bad_kb/resources/badkb/assets/layouts/pt-PT.kl rename to applications/main/bad_kb/resources/badusb/assets/layouts/pt-PT.kl diff --git a/applications/main/bad_kb/resources/badkb/assets/layouts/si-SI.kl b/applications/main/bad_kb/resources/badusb/assets/layouts/si-SI.kl similarity index 100% rename from applications/main/bad_kb/resources/badkb/assets/layouts/si-SI.kl rename to applications/main/bad_kb/resources/badusb/assets/layouts/si-SI.kl diff --git a/applications/main/bad_kb/resources/badkb/assets/layouts/sk-SK.kl b/applications/main/bad_kb/resources/badusb/assets/layouts/sk-SK.kl similarity index 100% rename from applications/main/bad_kb/resources/badkb/assets/layouts/sk-SK.kl rename to applications/main/bad_kb/resources/badusb/assets/layouts/sk-SK.kl diff --git a/applications/main/bad_kb/resources/badkb/assets/layouts/sv-SE.kl b/applications/main/bad_kb/resources/badusb/assets/layouts/sv-SE.kl similarity index 100% rename from applications/main/bad_kb/resources/badkb/assets/layouts/sv-SE.kl rename to applications/main/bad_kb/resources/badusb/assets/layouts/sv-SE.kl diff --git a/applications/main/bad_kb/resources/badkb/assets/layouts/tr-TR.kl b/applications/main/bad_kb/resources/badusb/assets/layouts/tr-TR.kl similarity index 100% rename from applications/main/bad_kb/resources/badkb/assets/layouts/tr-TR.kl rename to applications/main/bad_kb/resources/badusb/assets/layouts/tr-TR.kl diff --git a/applications/main/bad_kb/resources/badkb/demo_android.txt b/applications/main/bad_kb/resources/badusb/demo_android.txt similarity index 100% rename from applications/main/bad_kb/resources/badkb/demo_android.txt rename to applications/main/bad_kb/resources/badusb/demo_android.txt diff --git a/applications/main/bad_kb/resources/badkb/demo_ios.txt b/applications/main/bad_kb/resources/badusb/demo_ios.txt similarity index 100% rename from applications/main/bad_kb/resources/badkb/demo_ios.txt rename to applications/main/bad_kb/resources/badusb/demo_ios.txt diff --git a/applications/main/bad_kb/resources/badkb/demo_macos.txt b/applications/main/bad_kb/resources/badusb/demo_macos.txt similarity index 100% rename from applications/main/bad_kb/resources/badkb/demo_macos.txt rename to applications/main/bad_kb/resources/badusb/demo_macos.txt diff --git a/applications/main/bad_kb/resources/badkb/demo_windows.txt b/applications/main/bad_kb/resources/badusb/demo_windows.txt similarity index 100% rename from applications/main/bad_kb/resources/badkb/demo_windows.txt rename to applications/main/bad_kb/resources/badusb/demo_windows.txt diff --git a/applications/main/bad_kb/scenes/bad_kb_scene_config.c b/applications/main/bad_kb/scenes/bad_kb_scene_config.c index 3083e8696..8845bd5d5 100644 --- a/applications/main/bad_kb/scenes/bad_kb_scene_config.c +++ b/applications/main/bad_kb/scenes/bad_kb_scene_config.c @@ -1,7 +1,6 @@ #include "../bad_kb_app_i.h" #include "furi_hal_power.h" #include "furi_hal_usb.h" -#include enum VarItemListIndex { VarItemListIndexKeyboardLayout, diff --git a/applications/main/bad_kb/scenes/bad_kb_scene_file_select.c b/applications/main/bad_kb/scenes/bad_kb_scene_file_select.c index 884682685..790b02a85 100644 --- a/applications/main/bad_kb/scenes/bad_kb_scene_file_select.c +++ b/applications/main/bad_kb/scenes/bad_kb_scene_file_select.c @@ -8,15 +8,16 @@ static bool bad_kb_file_select(BadKbApp* bad_kb) { bad_kb_app_show_loading_popup(bad_kb, true); Storage* storage = furi_record_open(RECORD_STORAGE); - if(storage_dir_exists(storage, EXT_PATH("badusb"))) { + if(storage_dir_exists(storage, EXT_PATH("badkb"))) { DialogMessage* message = dialog_message_alloc(); - dialog_message_set_header(message, "Migrate BadUSB?", 64, 0, AlignCenter, AlignTop); + dialog_message_set_header(message, "Migrate Scripts?", 64, 0, AlignCenter, AlignTop); dialog_message_set_buttons(message, "No", NULL, "Yes"); dialog_message_set_text( message, - "A badusb folder was found!\n" - "Momentum uses the badkb folder.\n" - "Want to transfer the files?", + "Momentum uses the 'badusb'\n" + "folder for compatibility.\n" + "Want to migrate from\n" + "'badkb' folder?", 64, 32, AlignCenter, @@ -25,7 +26,12 @@ static bool bad_kb_file_select(BadKbApp* bad_kb) { dialog_message_free(message); furi_record_close(RECORD_DIALOGS); if(res == DialogMessageButtonRight) { - storage_common_migrate(storage, EXT_PATH("badusb"), BAD_KB_APP_BASE_FOLDER); + storage_common_migrate(storage, EXT_PATH("badkb"), BAD_KB_APP_BASE_FOLDER); + if(bad_kb->conn_init_thread) { + furi_thread_join(bad_kb->conn_init_thread); + } + bad_kb_load_settings(bad_kb); + bad_kb_config_adjust(&bad_kb->config); } } storage_simply_mkdir(storage, BAD_KB_APP_BASE_FOLDER); diff --git a/applications/main/bad_kb/views/bad_kb_view.c b/applications/main/bad_kb/views/bad_kb_view.c index 5f1a8bdda..a5dea1a19 100644 --- a/applications/main/bad_kb/views/bad_kb_view.c +++ b/applications/main/bad_kb/views/bad_kb_view.c @@ -4,7 +4,6 @@ #include #include #include -#include #include #define MAX_NAME_LEN 64 diff --git a/applications/main/ibutton/application.fam b/applications/main/ibutton/application.fam index 4f57148f8..d33519580 100644 --- a/applications/main/ibutton/application.fam +++ b/applications/main/ibutton/application.fam @@ -11,11 +11,20 @@ App( fap_category="iButton", ) +App( + appid="ibutton_cli", + targets=["f7"], + apptype=FlipperAppType.PLUGIN, + entry_point="ibutton_cli_plugin_ep", + requires=["cli"], + sources=["ibutton_cli.c"], +) + App( appid="ibutton_start", apptype=FlipperAppType.STARTUP, targets=["f7"], entry_point="ibutton_on_system_start", - sources=["ibutton_cli.c"], + sources=["ibutton_start.c"], order=60, ) diff --git a/applications/main/ibutton/ibutton_cli.c b/applications/main/ibutton/ibutton_cli.c index 12da64fcc..ca179efb8 100644 --- a/applications/main/ibutton/ibutton_cli.c +++ b/applications/main/ibutton/ibutton_cli.c @@ -8,19 +8,6 @@ #include #include -static void ibutton_cli(Cli* cli, FuriString* args, void* context); - -// app cli function -void ibutton_on_system_start() { -#ifdef SRV_CLI - Cli* cli = furi_record_open(RECORD_CLI); - cli_add_command(cli, "ikey", CliCommandFlagDefault, ibutton_cli, cli); - furi_record_close(RECORD_CLI); -#else - UNUSED(ibutton_cli); -#endif -} - static void ibutton_cli_print_usage() { printf("Usage:\r\n"); printf("ikey read\r\n"); @@ -252,3 +239,15 @@ void ibutton_cli(Cli* cli, FuriString* args, void* context) { furi_string_free(cmd); } + +#include + +static const FlipperAppPluginDescriptor plugin_descriptor = { + .appid = "ibutton_cli", + .ep_api_version = 1, + .entry_point = &ibutton_cli, +}; + +const FlipperAppPluginDescriptor* ibutton_cli_plugin_ep() { + return &plugin_descriptor; +} diff --git a/applications/main/ibutton/ibutton_start.c b/applications/main/ibutton/ibutton_start.c new file mode 100644 index 000000000..ca07becf5 --- /dev/null +++ b/applications/main/ibutton/ibutton_start.c @@ -0,0 +1,11 @@ +#include + +static void ibutton_cli_wrapper(Cli* cli, FuriString* args, void* context) { + cli_plugin_wrapper("ibutton_cli", 1, cli, args, context); +} + +void ibutton_on_system_start() { + Cli* cli = furi_record_open(RECORD_CLI); + cli_add_command(cli, "ikey", CliCommandFlagDefault, ibutton_cli_wrapper, cli); + furi_record_close(RECORD_CLI); +} diff --git a/applications/main/infrared/application.fam b/applications/main/infrared/application.fam index 57e3f9ce6..8ffaafa34 100644 --- a/applications/main/infrared/application.fam +++ b/applications/main/infrared/application.fam @@ -14,14 +14,23 @@ App( ) App( - appid="infrared_start", - apptype=FlipperAppType.STARTUP, + appid="infrared_cli", targets=["f7"], - entry_point="infrared_on_system_start", + apptype=FlipperAppType.PLUGIN, + entry_point="infrared_cli_plugin_ep", + requires=["cli"], sources=[ "infrared_cli.c", "infrared_brute_force.c", "infrared_signal.c", ], +) + +App( + appid="infrared_start", + apptype=FlipperAppType.STARTUP, + targets=["f7"], + entry_point="infrared_on_system_start", + sources=["infrared_start.c"], order=20, ) diff --git a/applications/main/infrared/infrared_app.c b/applications/main/infrared/infrared_app.c index e674cd13d..726caf85f 100644 --- a/applications/main/infrared/infrared_app.c +++ b/applications/main/infrared/infrared_app.c @@ -6,7 +6,8 @@ #define TAG "InfraredApp" -#define INFRARED_TX_MIN_INTERVAL_MS 50U +#define INFRARED_TX_MIN_INTERVAL_MS (50U) +#define INFRARED_TASK_STACK_SIZE (2048UL) static const NotificationSequence* infrared_notification_sequences[InfraredNotificationMessageCount] = { @@ -128,6 +129,8 @@ static void infrared_find_vacant_remote_name(FuriString* name, const char* path) static InfraredApp* infrared_alloc() { InfraredApp* infrared = malloc(sizeof(InfraredApp)); + infrared->task_thread = + furi_thread_alloc_ex("InfraredTask", INFRARED_TASK_STACK_SIZE, NULL, infrared); infrared->file_path = furi_string_alloc(); infrared->button_name = furi_string_alloc(); @@ -192,6 +195,10 @@ static InfraredApp* infrared_alloc() { view_dispatcher_add_view( view_dispatcher, InfraredViewMove, infrared_move_view_get_view(infrared->move_view)); + infrared->loading = loading_alloc(); + view_dispatcher_add_view( + view_dispatcher, InfraredViewLoading, loading_get_view(infrared->loading)); + if(app_state->is_debug_enabled) { infrared->debug_view = infrared_debug_view_alloc(); view_dispatcher_add_view( @@ -201,7 +208,6 @@ static InfraredApp* infrared_alloc() { } infrared->button_panel = button_panel_alloc(); - infrared->loading = loading_alloc(); infrared->progress = infrared_progress_view_alloc(); infrared->last_settings = infrared_last_settings_alloc(); @@ -213,6 +219,10 @@ static InfraredApp* infrared_alloc() { static void infrared_free(InfraredApp* infrared) { furi_assert(infrared); + + furi_thread_join(infrared->task_thread); + furi_thread_free(infrared->task_thread); + ViewDispatcher* view_dispatcher = infrared->view_dispatcher; InfraredAppState* app_state = &infrared->app_state; @@ -246,13 +256,15 @@ static void infrared_free(InfraredApp* infrared) { view_dispatcher_remove_view(view_dispatcher, InfraredViewMove); infrared_move_view_free(infrared->move_view); + view_dispatcher_remove_view(view_dispatcher, InfraredViewLoading); + loading_free(infrared->loading); + if(app_state->is_debug_enabled) { view_dispatcher_remove_view(view_dispatcher, InfraredViewDebugView); infrared_debug_view_free(infrared->debug_view); } button_panel_free(infrared->button_panel); - loading_free(infrared->loading); infrared_progress_view_free(infrared->progress); view_dispatcher_free(view_dispatcher); @@ -393,6 +405,17 @@ void infrared_tx_stop(InfraredApp* infrared) { infrared->app_state.last_transmit_time = furi_get_tick(); } +void infrared_blocking_task_start(InfraredApp* infrared, FuriThreadCallback callback) { + view_dispatcher_switch_to_view(infrared->view_dispatcher, InfraredViewLoading); + furi_thread_set_callback(infrared->task_thread, callback); + furi_thread_start(infrared->task_thread); +} + +bool infrared_blocking_task_finalize(InfraredApp* infrared) { + furi_thread_join(infrared->task_thread); + return furi_thread_get_return_code(infrared->task_thread); +} + void infrared_text_store_set(InfraredApp* infrared, uint32_t bank, const char* fmt, ...) { va_list args; va_start(args, fmt); @@ -413,21 +436,6 @@ void infrared_play_notification_message( notification_message(infrared->notifications, infrared_notification_sequences[message]); } -void infrared_show_loading_popup(const InfraredApp* infrared, bool show) { - ViewStack* view_stack = infrared->view_stack; - Loading* loading = infrared->loading; - - if(show) { - // Raise timer priority so that animations can play - furi_timer_set_thread_priority(FuriTimerThreadPriorityElevated); - view_stack_add_view(view_stack, loading_get_view(loading)); - } else { - view_stack_remove_view(view_stack, loading_get_view(loading)); - // Restore default timer priority - furi_timer_set_thread_priority(FuriTimerThreadPriorityNormal); - } -} - void infrared_show_error_message(const InfraredApp* infrared, const char* fmt, ...) { va_list args; va_start(args, fmt); diff --git a/applications/main/infrared/infrared_app_i.h b/applications/main/infrared/infrared_app_i.h index a840f24cc..f45e0be8e 100644 --- a/applications/main/infrared/infrared_app_i.h +++ b/applications/main/infrared/infrared_app_i.h @@ -20,12 +20,13 @@ #include #include +#include #include #include #include -#include +#include #include "infrared_app.h" #include "infrared_remote.h" @@ -38,9 +39,6 @@ #include "views/infrared_debug_view.h" #include "views/infrared_move_view.h" -#include "rpc/rpc_app.h" -#include - #define INFRARED_FILE_NAME_SIZE 100 #define INFRARED_TEXT_STORE_NUM 2 #define INFRARED_TEXT_STORE_SIZE 128 @@ -124,6 +122,7 @@ struct InfraredApp { Loading* loading; /**< Standard view for informing about long operations. */ InfraredProgressView* progress; /**< Custom view for showing brute force progress. */ + FuriThread* task_thread; /**< Pointer to a FuriThread instance for concurrent tasks. */ FuriString* file_path; /**< Full path to the currently loaded file. */ FuriString* button_name; /**< Name of the button requested in RPC mode. */ /** Arbitrary text storage for various inputs. */ @@ -147,6 +146,7 @@ typedef enum { InfraredViewDebugView, InfraredViewMove, InfraredViewVariableItemList, + InfraredViewLoading, } InfraredView; /** @@ -216,6 +216,29 @@ void infrared_tx_start_button_index(InfraredApp* infrared, size_t button_index); */ void infrared_tx_stop(InfraredApp* infrared); +/** + * @brief Start a blocking task in a separate thread. + * + * Before starting a blocking task, the current view will be replaced + * with a busy animation. All subsequent user input will be ignored. + * + * @param[in,out] infrared pointer to the application instance. + * @param[in] callback pointer to the function to be run in the thread. + */ +void infrared_blocking_task_start(InfraredApp* infrared, FuriThreadCallback callback); + +/** + * @brief Wait for a blocking task to finish and get the result. + * + * The busy animation shown during the infrared_blocking_task_start() call + * will NOT be hidden and WILL remain on screen. If another view is needed + * (e.g. to display the results), the caller code MUST set it explicitly. + * + * @param[in,out] infrared pointer to the application instance. + * @return true if the blocking task finished successfully, false otherwise. + */ +bool infrared_blocking_task_finalize(InfraredApp* infrared); + /** * @brief Set the internal text store with formatted text. * @@ -245,17 +268,6 @@ void infrared_play_notification_message( const InfraredApp* infrared, InfraredNotificationMessage message); -/** - * @brief Show a loading pop-up screen. - * - * In order for this to work, a Stack view must be currently active and - * the main view must be added to it. - * - * @param[in] infrared pointer to the application instance. - * @param[in] show whether to show or hide the pop-up. - */ -void infrared_show_loading_popup(const InfraredApp* infrared, bool show); - /** * @brief Show a formatted error messsage. * diff --git a/applications/main/infrared/infrared_cli.c b/applications/main/infrared/infrared_cli.c index c960ffa28..acc18ef08 100644 --- a/applications/main/infrared/infrared_cli.c +++ b/applications/main/infrared/infrared_cli.c @@ -10,8 +10,10 @@ #include "infrared_signal.h" #include "infrared_brute_force.h" -#define INFRARED_CLI_BUF_SIZE 10 -#define INFRARED_ASSETS_FOLDER "infrared/assets" +#define INFRARED_CLI_BUF_SIZE (10U) +#define INFRARED_CLI_FILE_NAME_SIZE (256U) +#define INFRARED_FILE_EXTENSION ".ir" +#define INFRARED_ASSETS_FOLDER EXT_PATH("infrared/assets") #define INFRARED_BRUTE_FORCE_DUMMY_INDEX 0 DICT_DEF2(dict_signals, FuriString*, FURI_STRING_OPLIST, int, M_DEFAULT_OPLIST) @@ -66,6 +68,37 @@ static void signal_received_callback(void* context, InfraredWorkerSignal* receiv } } +static void infrared_cli_print_universal_remotes(void) { + Storage* storage = furi_record_open(RECORD_STORAGE); + File* dir = storage_file_alloc(storage); + + do { + if(!storage_dir_open(dir, INFRARED_ASSETS_FOLDER)) break; + + FileInfo file_info; + char file_name[INFRARED_CLI_FILE_NAME_SIZE]; + + while(storage_dir_read(dir, &file_info, file_name, sizeof(file_name))) { + if(file_info.flags & FSF_DIRECTORY) { + continue; + } + + char* file_ext = strstr(file_name, INFRARED_FILE_EXTENSION); + if((file_ext == NULL) || (strcmp(file_ext, INFRARED_FILE_EXTENSION) != 0)) { + continue; + } + + *file_ext = '\0'; + printf("%s ", file_name); + } + + printf("\r\n"); + } while(false); + + storage_file_free(dir); + furi_record_close(RECORD_STORAGE); +} + static void infrared_cli_print_usage(void) { printf("Usage:\r\n"); printf("\tir rx [raw]\r\n"); @@ -85,8 +118,9 @@ static void infrared_cli_print_usage(void) { printf("\tir decode []\r\n"); printf("\tir universal \r\n"); printf("\tir universal list \r\n"); - // TODO FL-3496: Do not hardcode universal remote names - printf("\tAvailable universal remotes: tv audio ac projector\r\n"); + printf("\tAvailable universal remotes: "); + + infrared_cli_print_universal_remotes(); } static void infrared_cli_start_ir_rx(Cli* cli, FuriString* args) { @@ -211,7 +245,6 @@ static bool infrared_cli_decode_raw_signal( size_t i; for(i = 0; i < raw_signal->timings_size; ++i) { - // TODO FL-3523: Any infrared_check_decoder_ready() magic? const InfraredMessage* message = infrared_decode(decoder, level, raw_signal->timings[i]); if(message) { @@ -365,7 +398,10 @@ static void infrared_cli_list_remote_signals(FuriString* remote_name) { Storage* storage = furi_record_open(RECORD_STORAGE); FlipperFormat* ff = flipper_format_buffered_file_alloc(storage); FuriString* remote_path = furi_string_alloc_printf( - "%s/%s.ir", EXT_PATH(INFRARED_ASSETS_FOLDER), furi_string_get_cstr(remote_name)); + "%s/%s%s", + INFRARED_ASSETS_FOLDER, + furi_string_get_cstr(remote_name), + INFRARED_FILE_EXTENSION); do { if(!flipper_format_buffered_file_open_existing(ff, furi_string_get_cstr(remote_path))) { @@ -413,7 +449,7 @@ static void infrared_cli_brute_force_signals(Cli* cli, FuriString* remote_name, FuriString* signal_name) { InfraredBruteForce* brute_force = infrared_brute_force_alloc(); FuriString* remote_path = furi_string_alloc_printf( - "%s/%s.ir", EXT_PATH(INFRARED_ASSETS_FOLDER), furi_string_get_cstr(remote_name)); + "%s/%s.ir", INFRARED_ASSETS_FOLDER, furi_string_get_cstr(remote_name)); infrared_brute_force_set_db_filename(brute_force, furi_string_get_cstr(remote_path)); infrared_brute_force_add_record( @@ -508,12 +544,15 @@ static void infrared_cli_start_ir(Cli* cli, FuriString* args, void* context) { furi_string_free(command); } -void infrared_on_system_start() { -#ifdef SRV_CLI - Cli* cli = (Cli*)furi_record_open(RECORD_CLI); - cli_add_command(cli, "ir", CliCommandFlagDefault, infrared_cli_start_ir, NULL); - furi_record_close(RECORD_CLI); -#else - UNUSED(infrared_cli_start_ir); -#endif + +#include + +static const FlipperAppPluginDescriptor plugin_descriptor = { + .appid = "infrared_cli", + .ep_api_version = 1, + .entry_point = &infrared_cli_start_ir, +}; + +const FlipperAppPluginDescriptor* infrared_cli_plugin_ep() { + return &plugin_descriptor; } diff --git a/applications/main/infrared/infrared_custom_event.h b/applications/main/infrared/infrared_custom_event.h index 30bb0f729..b53e52a2f 100644 --- a/applications/main/infrared/infrared_custom_event.h +++ b/applications/main/infrared/infrared_custom_event.h @@ -14,6 +14,7 @@ enum InfraredCustomEventType { InfraredCustomEventTypePopupClosed, InfraredCustomEventTypeButtonSelected, InfraredCustomEventTypeBackPressed, + InfraredCustomEventTypeTaskFinished, InfraredCustomEventTypeRpcLoadFile, InfraredCustomEventTypeRpcExit, diff --git a/applications/main/infrared/infrared_start.c b/applications/main/infrared/infrared_start.c new file mode 100644 index 000000000..9e4a82026 --- /dev/null +++ b/applications/main/infrared/infrared_start.c @@ -0,0 +1,11 @@ +#include + +static void infrared_cli_start_ir_wrapper(Cli* cli, FuriString* args, void* context) { + cli_plugin_wrapper("infrared_cli", 1, cli, args, context); +} + +void infrared_on_system_start() { + Cli* cli = (Cli*)furi_record_open(RECORD_CLI); + cli_add_command(cli, "ir", CliCommandFlagDefault, infrared_cli_start_ir_wrapper, NULL); + furi_record_close(RECORD_CLI); +} diff --git a/applications/main/infrared/resources/infrared/assets/ac.ir b/applications/main/infrared/resources/infrared/assets/ac.ir index c26d282c4..38db599b2 100644 --- a/applications/main/infrared/resources/infrared/assets/ac.ir +++ b/applications/main/infrared/resources/infrared/assets/ac.ir @@ -1,43 +1,43 @@ Filetype: IR library file Version: 1 -# Last Updated 16th Aug, 2023 -# Last Checked 16th Aug, 2023 +# Last Updated 21st Feb, 2024 +# Last Checked 21st Feb, 2024 # # Model: Electrolux EACM-16 HP/N3 name: Off type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 502 3436 510 475 509 476 508 477 507 477 507 479 505 480 504 480 504 490 504 481 502 482 501 483 563 420 511 474 510 475 509 476 508 485 561 423 508 476 508 477 507 478 506 479 505 480 504 481 503 517 508 476 508 478 506 479 505 479 505 481 503 483 521 1456 501 498 507 479 505 480 504 481 503 482 501 483 563 421 562 422 509 499 506 479 505 480 504 481 503 482 502 484 510 1451 506 479 505 1542 562 1396 509 471 502 476 508 469 504 3425 511 # name: Dh type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 507 3430 506 479 505 480 504 481 503 481 503 483 501 485 509 1453 504 1465 503 482 502 483 511 473 500 485 509 476 508 477 507 478 506 487 507 477 507 478 506 479 505 480 504 482 502 483 501 484 500 523 503 482 502 484 500 485 509 476 508 476 508 478 506 1456 501 501 504 482 502 483 501 484 500 485 509 476 508 477 507 1455 502 509 506 479 505 1457 500 485 509 476 508 1454 503 482 502 483 501 568 499 1459 509 1450 507 471 502 474 510 3421 505 # name: Cool_hi type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 504 3433 503 482 502 484 510 474 510 475 509 476 508 478 506 1456 564 1405 510 475 509 476 508 502 482 477 507 478 506 479 505 480 504 489 505 480 504 481 503 482 502 483 511 473 511 474 510 475 509 509 506 479 505 480 504 481 503 482 512 473 511 474 510 476 508 1469 509 475 509 476 508 477 507 478 506 479 505 480 504 481 503 505 510 475 509 502 482 503 481 504 480 505 478 507 477 1459 509 560 507 1451 506 473 511 493 480 1450 507 3422 503 # name: Cool_lo type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 525 3615 530 506 561 474 562 474 562 473 563 473 531 505 562 1502 528 1542 562 474 562 474 530 505 531 504 532 504 532 504 616 419 533 510 589 447 526 509 527 509 527 509 527 508 528 508 528 507 529 542 525 510 526 509 527 509 527 509 527 508 528 508 528 1535 527 524 533 503 533 503 533 502 534 502 534 502 534 501 535 501 525 534 533 502 534 502 534 501 535 502 534 1529 533 503 533 503 533 587 533 497 528 501 524 1536 526 501 524 3609 526 # name: Heat_hi type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 531 3406 530 455 529 456 528 457 537 447 537 448 535 450 534 1429 528 1442 536 448 536 449 534 451 532 452 532 453 530 454 530 455 529 464 530 454 529 456 528 457 537 448 536 449 535 450 533 451 533 490 535 449 534 450 534 451 533 452 532 453 531 455 529 1433 534 1443 535 449 535 450 534 452 531 453 530 454 530 455 529 456 538 472 532 452 532 454 530 1433 535 1427 530 1432 536 1427 530 1431 537 1511 530 448 536 1422 535 1423 534 1422 535 3395 530 # name: Heat_lo type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 506 3430 506 478 506 479 505 480 504 481 503 482 502 484 500 1463 505 1465 503 482 502 483 501 484 500 485 509 476 508 477 507 478 506 486 508 477 507 478 506 479 505 480 504 481 503 482 502 483 500 523 502 482 502 483 501 484 500 485 509 476 508 478 506 1455 502 498 507 478 506 479 505 481 503 482 501 483 500 484 500 485 509 500 505 481 502 482 502 1461 507 1455 502 1459 509 476 508 477 507 563 504 1453 504 1454 503 1454 503 1453 504 3426 499 # # Model: Hisense Generic @@ -959,3 +959,65 @@ type: raw frequency: 38000 duty_cycle: 0.330000 data: 664 17757 3057 8901 528 469 550 1434 556 465 553 440 529 465 554 439 555 439 555 438 555 440 553 1435 552 443 550 470 524 1466 522 472 522 472 521 1467 523 1466 549 1440 549 1440 548 1440 548 445 549 445 549 445 549 446 548 470 524 471 523 471 523 471 523 472 522 472 522 473 522 472 523 472 548 446 549 445 550 445 548 446 548 446 548 446 548 446 548 447 547 470 524 471 523 471 523 471 523 471 523 474 519 474 521 474 521 473 522 473 546 447 547 1441 548 1442 546 1442 547 1442 546 2947 3023 8935 522 1466 522 472 522 498 496 498 495 499 496 498 496 498 521 473 522 471 523 1466 522 471 523 471 522 1466 523 471 523 1467 522 1467 522 1467 521 1493 495 1494 496 1493 521 473 522 472 522 471 523 472 522 471 523 472 522 472 522 472 522 472 522 472 522 472 522 472 522 473 521 499 495 499 495 499 495 499 496 498 522 473 522 472 523 471 522 472 522 472 522 472 522 472 522 472 522 472 522 473 521 473 521 473 521 473 521 499 495 500 494 500 495 499 496 498 522 2947 3023 8937 521 1468 520 473 521 473 521 473 521 473 521 473 521 473 521 474 520 474 520 1470 518 500 494 500 494 500 494 500 494 1494 521 1468 521 473 521 1468 520 1468 520 1469 520 1469 520 1470 518 1495 493 1496 493 1495 494 500 519 475 520 474 520 1469 519 1469 520 1469 519 474 520 474 520 475 519 477 517 500 494 1496 493 1496 493 1496 493 500 495 1495 519 475 518 475 519 475 518 476 518 475 519 1470 519 500 494 500 494 501 493 501 493 501 493 1499 490 1497 493 1497 492 1496 518 +# +name: Heat_hi +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 148 110377 9082 4422 707 499 706 500 704 1603 703 1606 701 505 700 507 699 506 700 507 699 506 700 1607 700 1608 700 1609 699 506 699 507 699 506 699 507 699 507 699 506 700 507 699 507 699 507 699 1608 699 1607 699 507 699 507 699 507 699 507 699 507 699 1609 699 507 699 1608 699 507 699 507 699 1609 699 507 699 19940 700 506 700 506 699 507 699 507 699 506 700 506 700 507 699 507 699 507 700 507 699 506 699 507 699 507 699 507 699 507 699 507 699 507 699 507 699 507 698 507 700 507 699 507 699 507 699 507 699 507 699 508 698 508 698 507 699 507 699 508 698 1610 699 508 698 +# +name: Cool_hi +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 315 101050 3094 3056 3093 4437 580 1648 572 534 576 1649 582 525 574 530 580 1646 574 1653 578 529 570 534 576 529 571 534 576 529 570 1655 576 1651 580 527 572 532 578 1647 573 1654 577 1651 580 526 573 531 579 526 573 531 579 526 573 531 579 526 573 531 579 526 573 531 579 525 574 531 579 525 574 531 579 1646 574 532 578 526 573 531 579 526 573 531 579 526 573 1652 579 527 572 1653 578 528 571 534 576 528 571 533 577 528 571 533 577 528 572 533 577 528 572 532 578 527 572 532 578 527 572 532 578 526 573 1652 579 527 572 532 578 527 572 532 578 527 572 532 578 526 573 531 579 526 573 531 579 526 573 531 579 525 574 530 580 525 574 530 580 525 574 530 580 524 575 529 581 524 575 529 571 534 576 528 571 533 577 528 571 533 577 528 571 533 577 527 572 532 578 527 572 532 578 526 573 531 579 526 573 531 579 525 574 531 579 525 574 530 580 525 574 1650 581 525 574 1651 580 1647 573 533 577 527 572 1653 578 528 572 1654 577 1650 581 1646 574 71637 254 +# +name: Cool_lo +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 284 19161 3098 3053 3096 4435 572 1656 575 532 578 1648 572 534 576 530 570 1682 549 1652 579 527 572 534 576 1649 571 1656 575 1652 579 1649 571 1656 575 531 579 527 572 1653 578 1649 571 1656 575 531 579 527 572 532 578 527 572 533 577 527 572 533 577 527 573 532 578 527 572 532 578 527 573 532 578 527 572 1652 579 527 572 533 577 528 571 533 577 528 571 533 577 1648 572 533 577 1649 571 535 575 530 569 536 574 531 569 536 574 530 569 536 574 530 570 535 575 530 570 535 575 530 569 535 575 530 569 535 575 1649 571 535 575 531 568 536 574 531 568 536 574 531 568 536 574 531 569 536 574 530 569 536 574 530 569 535 575 530 569 535 575 530 569 535 575 530 570 535 575 529 570 534 576 529 570 534 576 529 570 534 576 528 571 534 576 528 571 534 576 528 571 534 576 528 571 534 576 528 571 533 577 528 571 533 577 528 572 533 577 528 571 533 577 528 572 1652 579 527 572 1653 578 529 570 534 576 529 570 535 575 529 570 1654 577 1677 554 1673 547 +# +name: Cool_lo +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 301 132136 5036 2167 337 1766 361 689 358 692 366 684 363 1770 357 692 366 684 363 718 329 690 357 1776 361 687 360 1773 364 1767 360 689 358 1775 362 1769 357 1774 363 1768 359 1773 364 684 363 718 329 1773 364 684 363 718 329 691 356 694 364 716 331 719 328 1775 362 1769 358 1774 363 1768 359 1772 365 714 333 1770 357 1774 363 716 331 719 328 722 336 715 332 718 329 721 326 724 334 716 331 719 328 722 336 715 332 718 329 1773 364 1767 360 1772 354 1777 360 719 328 721 326 725 333 717 330 29455 5036 2139 354 1777 360 688 359 691 367 714 333 1770 356 692 366 684 363 687 360 690 357 1776 361 688 359 1773 364 1768 359 689 358 1775 362 1769 357 1774 363 1768 359 1773 364 684 363 687 360 1773 364 685 362 688 359 691 356 694 364 686 361 689 358 692 366 685 362 688 359 691 356 1777 360 1771 355 693 365 685 362 1771 355 693 365 1768 359 1773 364 1767 360 689 358 692 366 685 362 1771 355 1775 362 687 360 690 357 1775 362 687 360 690 357 693 365 716 331 689 358 1774 363 686 361 689 358 692 366 685 362 688 359 691 356 694 364 686 361 689 358 692 366 685 362 688 359 691 356 694 364 686 361 689 358 692 366 685 362 1771 355 693 365 1768 358 1773 364 684 363 687 360 690 357 693 365 1768 359 690 357 1776 361 688 359 691 356 694 364 686 361 689 358 692 366 685 362 1770 356 693 365 685 362 688 359 691 356 1777 360 1771 355 693 365 686 361 689 358 692 366 685 362 1770 356 +# +# Model: Fujitsu ASYG24KMTB +# +name: Dh +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 3302 1639 405 423 407 420 410 1234 405 421 409 1210 440 387 432 420 410 417 413 1231 408 1238 412 388 431 422 408 392 438 1233 406 1238 412 389 430 396 434 419 411 390 440 413 406 394 436 391 439 388 431 421 409 417 413 414 405 421 409 392 438 1233 406 421 409 417 413 414 405 395 435 418 412 388 432 421 409 1236 414 387 432 420 410 390 440 388 431 1213 437 1208 431 1239 411 1234 405 1213 437 1208 431 1214 436 1235 415 386 433 420 410 1234 405 422 408 418 412 389 431 396 434 1211 439 388 432 422 408 418 412 1233 406 1238 412 415 404 422 408 1237 413 388 432 422 408 1236 414 1205 434 1210 440 1205 434 392 438 390 440 1231 408 392 438 415 404 396 434 392 438 415 404 422 408 419 411 416 414 412 407 394 436 417 413 414 405 421 409 417 413 1232 407 419 411 390 440 1204 435 418 412 415 415 412 407 419 411 1208 431 421 409 418 412 388 432 421 409 392 438 415 404 395 435 1211 439 388 432 1213 437 416 414 386 433 1212 438 415 404 396 434 392 438 416 414 413 406 420 410 417 413 1231 409 418 412 389 430 1240 410 391 439 1205 434 420 410 390 440 387 432 420 410 417 413 +# +name: Cool_hi +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 3293 1649 405 396 434 419 411 1207 432 395 435 1236 414 413 406 394 436 417 413 1232 407 1212 438 415 404 396 434 419 411 1234 405 1239 411 417 413 414 405 421 409 419 411 389 430 423 407 393 437 416 414 387 432 394 436 417 413 388 431 421 409 1236 414 387 432 421 409 418 412 414 405 422 408 418 412 415 404 1240 410 391 439 414 405 421 409 419 411 1234 405 1239 411 1208 431 1239 411 1235 404 1214 436 1210 440 1205 434 419 411 416 414 1204 435 418 412 415 404 396 434 393 437 1235 404 396 434 420 410 416 414 1231 408 1210 440 387 432 421 409 1235 415 414 405 395 435 418 412 1232 407 420 410 1208 431 422 408 1237 413 415 404 396 434 419 411 416 414 413 406 420 410 417 413 414 405 421 409 418 412 415 404 422 408 419 411 416 414 413 406 1238 412 415 404 422 408 1237 413 414 405 421 409 418 412 416 414 1231 408 418 412 415 404 422 408 419 411 416 414 413 406 420 410 1235 404 423 407 420 410 1234 405 422 408 1210 440 414 405 421 409 392 438 415 404 422 408 420 410 417 413 1231 408 419 411 416 414 413 406 1237 413 415 404 1239 411 417 413 1232 407 420 410 417 413 +# +name: Cool_lo +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 3302 1614 440 414 405 421 409 1235 414 413 406 1238 411 415 404 422 408 419 411 1234 405 1240 409 418 412 415 404 422 408 1237 412 1232 407 420 410 417 413 414 405 422 408 419 411 416 414 413 406 420 410 417 413 414 405 421 409 418 412 415 404 1239 410 418 412 415 404 422 408 419 411 416 414 413 406 420 410 1234 405 422 408 419 411 416 414 414 405 1239 411 1207 432 1239 410 1235 414 1230 409 1236 413 1232 407 1237 412 415 415 412 407 1237 412 414 405 422 408 419 411 416 414 1231 408 419 411 416 414 413 406 1238 411 1206 433 421 409 418 412 1206 433 421 409 418 412 1206 433 1238 412 1207 432 1213 436 390 440 1232 407 420 410 417 413 414 405 421 409 418 412 415 404 422 408 419 411 416 414 413 406 421 409 418 412 415 404 422 408 419 411 1233 406 421 409 418 412 1232 407 420 410 418 412 389 430 422 408 1210 440 414 405 395 435 418 412 415 404 423 407 420 410 416 414 414 405 422 408 418 412 415 404 1240 409 1235 414 413 406 420 410 417 413 414 405 422 408 419 411 416 414 1231 408 418 412 415 404 1240 409 1209 440 387 432 1212 437 1234 405 1214 435 1209 440 1204 435 +# +name: Heat_hi +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 3301 1615 439 415 404 422 408 1210 439 414 405 1239 410 416 414 414 405 395 435 1209 440 1205 434 419 411 417 413 414 405 1212 437 1207 432 422 408 419 411 416 414 414 405 421 409 418 412 415 404 422 408 393 437 416 414 413 406 420 410 417 413 1205 434 420 410 417 413 414 405 421 409 418 412 415 404 422 408 1210 439 414 405 422 408 419 411 417 413 1205 434 1236 413 1206 433 1211 438 1207 432 1212 437 1209 440 1204 435 418 412 415 415 1204 435 418 412 415 404 422 408 419 411 1208 441 412 407 420 410 417 413 1205 434 1237 412 414 405 422 408 1210 439 415 404 396 434 419 411 1207 432 1213 436 417 413 1205 434 420 410 417 413 1231 408 419 411 416 414 413 406 421 409 418 412 414 405 422 408 419 411 415 404 424 406 421 409 418 412 415 404 1239 410 417 413 414 405 1239 410 416 414 413 406 422 408 419 411 1233 406 421 409 418 412 415 404 423 407 419 411 416 414 413 406 1238 411 416 414 413 406 421 409 1235 414 1230 409 418 412 415 415 412 407 420 410 417 413 414 405 422 408 1236 413 413 406 421 409 1235 414 1204 435 1210 439 1206 433 1212 437 1207 432 395 435 1236 413 +# +name: Heat_lo +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 3295 1646 408 420 410 390 440 1205 434 393 437 1234 405 421 409 419 411 415 415 1230 409 1210 440 414 405 421 409 418 412 1233 406 1212 437 416 414 413 406 394 436 418 412 415 404 422 408 393 437 416 414 413 406 420 410 417 413 414 405 421 409 1236 413 414 405 421 409 418 412 415 404 423 407 419 411 416 414 1231 408 418 412 415 415 412 407 421 409 1235 414 1204 435 1209 441 1205 434 1210 440 1205 434 1212 437 1207 432 395 435 419 411 1233 406 421 409 418 412 415 404 422 408 1238 411 415 404 396 434 419 411 1234 405 1239 410 417 413 414 405 1213 436 417 413 414 405 1213 436 1235 404 1214 435 1209 441 413 406 421 409 418 412 1206 433 394 436 418 412 388 431 422 408 419 411 415 415 386 433 420 410 418 412 414 405 422 408 419 411 389 430 1241 408 418 412 415 404 1240 409 417 413 414 405 395 435 419 411 1233 406 395 435 418 412 415 404 422 408 419 411 416 414 413 406 421 409 1236 413 413 406 394 436 1235 414 1230 409 418 412 415 404 422 408 420 410 417 413 414 405 421 409 1236 413 413 406 420 410 417 413 1232 407 1237 412 416 414 1230 409 1236 413 1205 434 1210 439 +# +name: Off +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 3302 1640 404 423 407 420 410 1212 437 390 440 1234 405 395 435 392 438 415 415 1207 432 1242 407 420 410 391 439 414 405 1243 406 1241 408 392 438 415 415 386 433 393 437 390 440 414 405 396 434 419 411 389 441 412 407 420 410 390 440 387 432 1242 407 393 437 390 440 414 405 395 435 392 438 389 430 396 434 1240 409 417 413 414 405 395 435 419 411 1237 412 389 430 396 434 393 437 416 414 387 432 394 436 1212 437 389 441 1234 405 1217 432 1241 408 1213 436 1212 437 1210 439 diff --git a/applications/main/infrared/scenes/common/infrared_scene_universal_common.c b/applications/main/infrared/scenes/common/infrared_scene_universal_common.c index 4967d1956..9bdcdc4a8 100644 --- a/applications/main/infrared/scenes/common/infrared_scene_universal_common.c +++ b/applications/main/infrared/scenes/common/infrared_scene_universal_common.c @@ -32,9 +32,23 @@ static void infrared_scene_universal_common_hide_popup(InfraredApp* infrared) { infrared_play_notification_message(infrared, InfraredNotificationMessageBlinkStop); } +static int32_t infrared_scene_universal_common_task_callback(void* context) { + InfraredApp* infrared = context; + const bool success = infrared_brute_force_calculate_messages(infrared->brute_force); + view_dispatcher_send_custom_event( + infrared->view_dispatcher, + infrared_custom_event_pack(InfraredCustomEventTypeTaskFinished, 0)); + + return success; +} + void infrared_scene_universal_common_on_enter(void* context) { InfraredApp* infrared = context; + view_set_orientation(view_stack_get_view(infrared->view_stack), ViewOrientationVertical); view_stack_add_view(infrared->view_stack, button_panel_get_view(infrared->button_panel)); + + // Load universal remote data in background + infrared_blocking_task_start(infrared, infrared_scene_universal_common_task_callback); } bool infrared_scene_universal_common_on_event(void* context, SceneManagerEvent event) { @@ -58,26 +72,36 @@ bool infrared_scene_universal_common_on_event(void* context, SceneManagerEvent e if(infrared_custom_event_get_type(event.event) == InfraredCustomEventTypeBackPressed) { infrared_brute_force_stop(brute_force); infrared_scene_universal_common_hide_popup(infrared); - consumed = true; } + consumed = true; } } else { if(event.type == SceneManagerEventTypeBack) { scene_manager_previous_scene(scene_manager); consumed = true; } else if(event.type == SceneManagerEventTypeCustom) { - if(infrared_custom_event_get_type(event.event) == - InfraredCustomEventTypeButtonSelected) { + uint16_t event_type; + int16_t event_value; + infrared_custom_event_unpack(event.event, &event_type, &event_value); + + if(event_type == InfraredCustomEventTypeButtonSelected) { uint32_t record_count; - if(infrared_brute_force_start( - brute_force, infrared_custom_event_get_value(event.event), &record_count)) { + if(infrared_brute_force_start(brute_force, event_value, &record_count)) { dolphin_deed(DolphinDeedIrSend); infrared_scene_universal_common_show_popup(infrared, record_count); } else { scene_manager_next_scene(scene_manager, InfraredSceneErrorDatabases); } - consumed = true; + } else if(event_type == InfraredCustomEventTypeTaskFinished) { + const bool task_success = infrared_blocking_task_finalize(infrared); + + if(!task_success) { + scene_manager_next_scene(infrared->scene_manager, InfraredSceneErrorDatabases); + } else { + view_dispatcher_switch_to_view(infrared->view_dispatcher, InfraredViewStack); + } } + consumed = true; } } diff --git a/applications/main/infrared/scenes/infrared_scene_debug_settings.c b/applications/main/infrared/scenes/infrared_scene_debug_settings.c index e07dc1d6f..8a64d3641 100644 --- a/applications/main/infrared/scenes/infrared_scene_debug_settings.c +++ b/applications/main/infrared/scenes/infrared_scene_debug_settings.c @@ -1,5 +1,7 @@ #include "../infrared_app_i.h" +#include + uint8_t value_index_ir; #define DEB_PINS_COUNT (sizeof(infrared_debug_cfg_variables_text) / sizeof(char* const)) diff --git a/applications/main/infrared/scenes/infrared_scene_edit_delete.c b/applications/main/infrared/scenes/infrared_scene_edit_delete.c index 0cb88efdb..90a2633d3 100644 --- a/applications/main/infrared/scenes/infrared_scene_edit_delete.c +++ b/applications/main/infrared/scenes/infrared_scene_edit_delete.c @@ -6,12 +6,33 @@ static void view_dispatcher_send_custom_event(infrared->view_dispatcher, result); } +static int32_t infrared_scene_edit_delete_task_callback(void* context) { + InfraredApp* infrared = context; + InfraredAppState* app_state = &infrared->app_state; + const InfraredEditTarget edit_target = app_state->edit_target; + + bool success; + if(edit_target == InfraredEditTargetButton) { + furi_assert(app_state->current_button_index != InfraredButtonIndexNone); + success = infrared_remote_delete_signal(infrared->remote, app_state->current_button_index); + } else if(edit_target == InfraredEditTargetRemote) { + success = infrared_remote_remove(infrared->remote); + } else { + furi_crash(); + } + + view_dispatcher_send_custom_event( + infrared->view_dispatcher, InfraredCustomEventTypeTaskFinished); + + return success; +} + void infrared_scene_edit_delete_on_enter(void* context) { InfraredApp* infrared = context; DialogEx* dialog_ex = infrared->dialog_ex; InfraredRemote* remote = infrared->remote; - const InfraredEditTarget edit_target = infrared->app_state.edit_target; + if(edit_target == InfraredEditTargetButton) { dialog_ex_set_header(dialog_ex, "Delete Button?", 64, 0, AlignCenter, AlignTop); @@ -70,10 +91,7 @@ void infrared_scene_edit_delete_on_enter(void* context) { dialog_ex_set_result_callback(dialog_ex, infrared_scene_edit_delete_dialog_result_callback); dialog_ex_set_context(dialog_ex, context); - view_set_orientation(view_stack_get_view(infrared->view_stack), ViewOrientationHorizontal); - view_stack_add_view(infrared->view_stack, dialog_ex_get_view(infrared->dialog_ex)); - - view_dispatcher_switch_to_view(infrared->view_dispatcher, InfraredViewStack); + view_dispatcher_switch_to_view(infrared->view_dispatcher, InfraredViewDialogEx); } bool infrared_scene_edit_delete_on_event(void* context, SceneManagerEvent event) { @@ -84,39 +102,30 @@ bool infrared_scene_edit_delete_on_event(void* context, SceneManagerEvent event) if(event.type == SceneManagerEventTypeCustom) { if(event.event == DialogExResultLeft) { scene_manager_previous_scene(scene_manager); - consumed = true; } else if(event.event == DialogExResultRight) { - bool success = false; - InfraredRemote* remote = infrared->remote; + // Delete a button or a remote in a separate thread + infrared_blocking_task_start(infrared, infrared_scene_edit_delete_task_callback); + + } else if(event.event == InfraredCustomEventTypeTaskFinished) { + const bool task_success = infrared_blocking_task_finalize(infrared); + InfraredAppState* app_state = &infrared->app_state; - const InfraredEditTarget edit_target = app_state->edit_target; - if(edit_target == InfraredEditTargetButton) { - furi_assert(app_state->current_button_index != InfraredButtonIndexNone); - infrared_show_loading_popup(infrared, true); - success = infrared_remote_delete_signal(remote, app_state->current_button_index); - infrared_show_loading_popup(infrared, false); - app_state->current_button_index = InfraredButtonIndexNone; - } else if(edit_target == InfraredEditTargetRemote) { - success = infrared_remote_remove(remote); - app_state->current_button_index = InfraredButtonIndexNone; - } else { - furi_crash(); - } - - if(success) { + if(task_success) { scene_manager_next_scene(scene_manager, InfraredSceneEditDeleteDone); } else { - infrared_show_error_message( - infrared, - "Failed to\ndelete %s", - edit_target == InfraredEditTargetButton ? "button" : "file"); + const char* edit_target_text = + app_state->edit_target == InfraredEditTargetButton ? "button" : "file"; + infrared_show_error_message(infrared, "Failed to\ndelete %s", edit_target_text); + const uint32_t possible_scenes[] = {InfraredSceneRemoteList, InfraredSceneStart}; scene_manager_search_and_switch_to_previous_scene_one_of( scene_manager, possible_scenes, COUNT_OF(possible_scenes)); } - consumed = true; + + app_state->current_button_index = InfraredButtonIndexNone; } + consumed = true; } return consumed; @@ -124,5 +133,5 @@ bool infrared_scene_edit_delete_on_event(void* context, SceneManagerEvent event) void infrared_scene_edit_delete_on_exit(void* context) { InfraredApp* infrared = context; - view_stack_remove_view(infrared->view_stack, dialog_ex_get_view(infrared->dialog_ex)); + dialog_ex_reset(infrared->dialog_ex); } diff --git a/applications/main/infrared/scenes/infrared_scene_edit_move.c b/applications/main/infrared/scenes/infrared_scene_edit_move.c index 4959a8310..fcac1fc15 100644 --- a/applications/main/infrared/scenes/infrared_scene_edit_move.c +++ b/applications/main/infrared/scenes/infrared_scene_edit_move.c @@ -1,5 +1,17 @@ #include "../infrared_app_i.h" +static int32_t infrared_scene_edit_move_task_callback(void* context) { + InfraredApp* infrared = context; + const bool success = infrared_remote_move_signal( + infrared->remote, + infrared->app_state.prev_button_index, + infrared->app_state.current_button_index); + view_dispatcher_send_custom_event( + infrared->view_dispatcher, InfraredCustomEventTypeTaskFinished); + + return success; +} + static void infrared_scene_edit_move_button_callback( uint32_t index_old, uint32_t index_new, @@ -26,10 +38,7 @@ void infrared_scene_edit_move_on_enter(void* context) { infrared_move_view_set_callback( infrared->move_view, infrared_scene_edit_move_button_callback, infrared); - view_set_orientation(view_stack_get_view(infrared->view_stack), ViewOrientationHorizontal); - view_stack_add_view(infrared->view_stack, infrared_move_view_get_view(infrared->move_view)); - - view_dispatcher_switch_to_view(infrared->view_dispatcher, InfraredViewStack); + view_dispatcher_switch_to_view(infrared->view_dispatcher, InfraredViewMove); } bool infrared_scene_edit_move_on_event(void* context, SceneManagerEvent event) { @@ -38,25 +47,23 @@ bool infrared_scene_edit_move_on_event(void* context, SceneManagerEvent event) { if(event.type == SceneManagerEventTypeCustom) { if(event.event == InfraredCustomEventTypeButtonSelected) { - infrared_show_loading_popup(infrared, true); - const bool button_moved = infrared_remote_move_signal( - infrared->remote, - infrared->app_state.prev_button_index, - infrared->app_state.current_button_index); - infrared_show_loading_popup(infrared, false); + // Move the button in a separate thread + infrared_blocking_task_start(infrared, infrared_scene_edit_move_task_callback); - if(!button_moved) { - infrared_show_error_message( - infrared, - "Failed to move\n\"%s\"", - infrared_remote_get_signal_name( - infrared->remote, infrared->app_state.current_button_index)); + } else if(event.event == InfraredCustomEventTypeTaskFinished) { + const bool task_success = infrared_blocking_task_finalize(infrared); + + if(!task_success) { + const char* signal_name = infrared_remote_get_signal_name( + infrared->remote, infrared->app_state.current_button_index); + infrared_show_error_message(infrared, "Failed to move\n\"%s\"", signal_name); scene_manager_search_and_switch_to_previous_scene( infrared->scene_manager, InfraredSceneRemoteList); + } else { + view_dispatcher_switch_to_view(infrared->view_dispatcher, InfraredViewMove); } - - consumed = true; } + consumed = true; } return consumed; @@ -64,6 +71,5 @@ bool infrared_scene_edit_move_on_event(void* context, SceneManagerEvent event) { void infrared_scene_edit_move_on_exit(void* context) { InfraredApp* infrared = context; - view_stack_remove_view(infrared->view_stack, infrared_move_view_get_view(infrared->move_view)); infrared_move_view_reset(infrared->move_view); } diff --git a/applications/main/infrared/scenes/infrared_scene_edit_rename.c b/applications/main/infrared/scenes/infrared_scene_edit_rename.c index 178690926..a546ad6e5 100644 --- a/applications/main/infrared/scenes/infrared_scene_edit_rename.c +++ b/applications/main/infrared/scenes/infrared_scene_edit_rename.c @@ -3,6 +3,28 @@ #include #include +static int32_t infrared_scene_edit_rename_task_callback(void* context) { + InfraredApp* infrared = context; + InfraredAppState* app_state = &infrared->app_state; + const InfraredEditTarget edit_target = app_state->edit_target; + + bool success; + if(edit_target == InfraredEditTargetButton) { + furi_assert(app_state->current_button_index != InfraredButtonIndexNone); + success = infrared_remote_rename_signal( + infrared->remote, app_state->current_button_index, infrared->text_store[0]); + } else if(edit_target == InfraredEditTargetRemote) { + success = infrared_rename_current_remote(infrared, infrared->text_store[0]); + } else { + furi_crash(); + } + + view_dispatcher_send_custom_event( + infrared->view_dispatcher, InfraredCustomEventTypeTaskFinished); + + return success; +} + void infrared_scene_edit_rename_on_enter(void* context) { InfraredApp* infrared = context; InfraredRemote* remote = infrared->remote; @@ -53,49 +75,36 @@ void infrared_scene_edit_rename_on_enter(void* context) { enter_name_length, false); - view_set_orientation(view_stack_get_view(infrared->view_stack), ViewOrientationHorizontal); - view_stack_add_view(infrared->view_stack, text_input_get_view(infrared->text_input)); - - view_dispatcher_switch_to_view(infrared->view_dispatcher, InfraredViewStack); + view_dispatcher_switch_to_view(infrared->view_dispatcher, InfraredViewTextInput); } bool infrared_scene_edit_rename_on_event(void* context, SceneManagerEvent event) { InfraredApp* infrared = context; - InfraredRemote* remote = infrared->remote; SceneManager* scene_manager = infrared->scene_manager; - InfraredAppState* app_state = &infrared->app_state; bool consumed = false; if(event.type == SceneManagerEventTypeCustom) { if(event.event == InfraredCustomEventTypeTextEditDone) { - bool success = false; - const InfraredEditTarget edit_target = app_state->edit_target; - if(edit_target == InfraredEditTargetButton) { - const int32_t current_button_index = app_state->current_button_index; - furi_assert(current_button_index != InfraredButtonIndexNone); - infrared_show_loading_popup(infrared, true); - success = infrared_remote_rename_signal( - remote, current_button_index, infrared->text_store[0]); - infrared_show_loading_popup(infrared, false); - app_state->current_button_index = InfraredButtonIndexNone; - } else if(edit_target == InfraredEditTargetRemote) { - success = infrared_rename_current_remote(infrared, infrared->text_store[0]); - } else { - furi_crash(); - } + // Rename a button or a remote in a separate thread + infrared_blocking_task_start(infrared, infrared_scene_edit_rename_task_callback); - if(success) { + } else if(event.event == InfraredCustomEventTypeTaskFinished) { + const bool task_success = infrared_blocking_task_finalize(infrared); + InfraredAppState* app_state = &infrared->app_state; + + if(task_success) { scene_manager_next_scene(scene_manager, InfraredSceneEditRenameDone); } else { - infrared_show_error_message( - infrared, - "Failed to\nrename %s", - edit_target == InfraredEditTargetButton ? "button" : "file"); + const char* edit_target_text = + app_state->edit_target == InfraredEditTargetButton ? "button" : "file"; + infrared_show_error_message(infrared, "Failed to\nrename %s", edit_target_text); scene_manager_search_and_switch_to_previous_scene( scene_manager, InfraredSceneRemoteList); } - consumed = true; + + app_state->current_button_index = InfraredButtonIndexNone; } + consumed = true; } return consumed; @@ -105,12 +114,10 @@ void infrared_scene_edit_rename_on_exit(void* context) { InfraredApp* infrared = context; TextInput* text_input = infrared->text_input; - view_stack_remove_view(infrared->view_stack, text_input_get_view(text_input)); - - void* validator_context = text_input_get_validator_callback_context(text_input); - text_input_set_validator(text_input, NULL, NULL); - + ValidatorIsFile* validator_context = text_input_get_validator_callback_context(text_input); if(validator_context) { - validator_is_file_free((ValidatorIsFile*)validator_context); + validator_is_file_free(validator_context); } + + text_input_reset(text_input); } diff --git a/applications/main/infrared/scenes/infrared_scene_remote_list.c b/applications/main/infrared/scenes/infrared_scene_remote_list.c index 2276e270a..9c880ac2f 100644 --- a/applications/main/infrared/scenes/infrared_scene_remote_list.c +++ b/applications/main/infrared/scenes/infrared_scene_remote_list.c @@ -1,41 +1,56 @@ #include "../infrared_app_i.h" -void infrared_scene_remote_list_on_enter(void* context) { +static int32_t infrared_scene_remote_list_task_callback(void* context) { InfraredApp* infrared = context; - SceneManager* scene_manager = infrared->scene_manager; - ViewDispatcher* view_dispatcher = infrared->view_dispatcher; - - view_set_orientation(view_stack_get_view(infrared->view_stack), ViewOrientationVertical); - view_dispatcher_switch_to_view(view_dispatcher, InfraredViewStack); + const bool success = + infrared_remote_load(infrared->remote, furi_string_get_cstr(infrared->file_path)); + view_dispatcher_send_custom_event( + infrared->view_dispatcher, InfraredCustomEventTypeTaskFinished); + return success; +} +static void infrared_scene_remote_list_select_and_load(InfraredApp* infrared) { DialogsFileBrowserOptions browser_options; dialog_file_browser_set_basic_options(&browser_options, INFRARED_APP_EXTENSION, &I_ir_10px); browser_options.base_path = INFRARED_APP_FOLDER; - while(dialog_file_browser_show( - infrared->dialogs, infrared->file_path, infrared->file_path, &browser_options)) { - const char* file_path = furi_string_get_cstr(infrared->file_path); + const bool file_selected = dialog_file_browser_show( + infrared->dialogs, infrared->file_path, infrared->file_path, &browser_options); - infrared_show_loading_popup(infrared, true); - const bool remote_loaded = infrared_remote_load(infrared->remote, file_path); - infrared_show_loading_popup(infrared, false); + if(file_selected) { + // Load the remote in a separate thread + infrared_blocking_task_start(infrared, infrared_scene_remote_list_task_callback); - if(remote_loaded) { - scene_manager_next_scene(scene_manager, InfraredSceneRemote); - return; - } else { - infrared_show_error_message(infrared, "Failed to load\n\"%s\"", file_path); - } + } else { + scene_manager_previous_scene(infrared->scene_manager); } +} - scene_manager_previous_scene(scene_manager); +void infrared_scene_remote_list_on_enter(void* context) { + InfraredApp* infrared = context; + infrared_scene_remote_list_select_and_load(infrared); } bool infrared_scene_remote_list_on_event(void* context, SceneManagerEvent event) { - UNUSED(context); - UNUSED(event); + InfraredApp* infrared = context; + bool consumed = false; + if(event.type == SceneManagerEventTypeCustom) { + if(event.event == InfraredCustomEventTypeTaskFinished) { + const bool task_success = infrared_blocking_task_finalize(infrared); + + if(task_success) { + scene_manager_next_scene(infrared->scene_manager, InfraredSceneRemote); + } else { + infrared_show_error_message( + infrared, "Failed to load\n\"%s\"", furi_string_get_cstr(infrared->file_path)); + infrared_scene_remote_list_select_and_load(infrared); + } + } + consumed = true; + } + return consumed; } diff --git a/applications/main/infrared/scenes/infrared_scene_rpc.c b/applications/main/infrared/scenes/infrared_scene_rpc.c index f3408fba4..4c263a117 100644 --- a/applications/main/infrared/scenes/infrared_scene_rpc.c +++ b/applications/main/infrared/scenes/infrared_scene_rpc.c @@ -9,6 +9,15 @@ typedef enum { InfraredRpcStateSending, } InfraredRpcState; +static int32_t infrared_scene_rpc_task_callback(void* context) { + InfraredApp* infrared = context; + const bool success = + infrared_remote_load(infrared->remote, furi_string_get_cstr(infrared->file_path)); + view_dispatcher_send_custom_event( + infrared->view_dispatcher, InfraredCustomEventTypeTaskFinished); + return success; +} + void infrared_scene_rpc_on_enter(void* context) { InfraredApp* infrared = context; Popup* popup = infrared->popup; @@ -22,9 +31,7 @@ void infrared_scene_rpc_on_enter(void* context) { popup_set_callback(popup, infrared_popup_closed_callback); view_dispatcher_switch_to_view(infrared->view_dispatcher, InfraredViewPopup); - scene_manager_set_scene_state(infrared->scene_manager, InfraredSceneRpc, InfraredRpcStateIdle); - notification_message(infrared->notifications, &sequence_display_backlight_on); } @@ -33,76 +40,89 @@ bool infrared_scene_rpc_on_event(void* context, SceneManagerEvent event) { bool consumed = false; if(event.type == SceneManagerEventTypeCustom) { - consumed = true; - InfraredRpcState state = + InfraredAppState* app_state = &infrared->app_state; + InfraredRpcState rpc_state = scene_manager_get_scene_state(infrared->scene_manager, InfraredSceneRpc); - if(event.event == InfraredCustomEventTypeBackPressed) { - view_dispatcher_stop(infrared->view_dispatcher); - } else if(event.event == InfraredCustomEventTypePopupClosed) { - view_dispatcher_stop(infrared->view_dispatcher); - } else if(event.event == InfraredCustomEventTypeRpcLoadFile) { - bool result = false; - if(state == InfraredRpcStateIdle) { - result = infrared_remote_load( - infrared->remote, furi_string_get_cstr(infrared->file_path)); - if(result) { - scene_manager_set_scene_state( - infrared->scene_manager, InfraredSceneRpc, InfraredRpcStateLoaded); - } - } - const char* remote_name = infrared_remote_get_name(infrared->remote); - infrared_text_store_set(infrared, 0, "loaded\n%s", remote_name); + if(event.event == InfraredCustomEventTypeRpcLoadFile) { + if(rpc_state == InfraredRpcStateIdle) { + // Load the remote in a separate thread + infrared_blocking_task_start(infrared, infrared_scene_rpc_task_callback); + } + + } else if(event.event == InfraredCustomEventTypeTaskFinished) { + const bool task_success = infrared_blocking_task_finalize(infrared); + + if(task_success) { + const char* remote_name = infrared_remote_get_name(infrared->remote); + infrared_text_store_set(infrared, 0, "loaded\n%s", remote_name); + scene_manager_set_scene_state( + infrared->scene_manager, InfraredSceneRpc, InfraredRpcStateLoaded); + + } else { + infrared_text_store_set( + infrared, 0, "failed to load\n%s", furi_string_get_cstr(infrared->file_path)); + } + popup_set_text( infrared->popup, infrared->text_store[0], 89, 44, AlignCenter, AlignTop); + view_dispatcher_switch_to_view(infrared->view_dispatcher, InfraredViewPopup); + + rpc_system_app_confirm(infrared->rpc_ctx, task_success); - rpc_system_app_confirm(infrared->rpc_ctx, result); } else if( event.event == InfraredCustomEventTypeRpcButtonPressName || event.event == InfraredCustomEventTypeRpcButtonPressIndex) { bool result = false; - if(state == InfraredRpcStateLoaded) { + if(rpc_state == InfraredRpcStateLoaded) { if(event.event == InfraredCustomEventTypeRpcButtonPressName) { const char* button_name = furi_string_get_cstr(infrared->button_name); size_t index; const bool index_found = infrared_remote_get_signal_index(infrared->remote, button_name, &index); - infrared->app_state.current_button_index = - index_found ? (signed)index : InfraredButtonIndexNone; + app_state->current_button_index = index_found ? (signed)index : + InfraredButtonIndexNone; FURI_LOG_D(TAG, "Sending signal with name \"%s\"", button_name); } else { FURI_LOG_D( - TAG, - "Sending signal with index \"%ld\"", - infrared->app_state.current_button_index); + TAG, "Sending signal with index \"%ld\"", app_state->current_button_index); } if(infrared->app_state.current_button_index != InfraredButtonIndexNone) { - infrared_tx_start_button_index( - infrared, infrared->app_state.current_button_index); + infrared_tx_start_button_index(infrared, app_state->current_button_index); scene_manager_set_scene_state( infrared->scene_manager, InfraredSceneRpc, InfraredRpcStateSending); result = true; } } rpc_system_app_confirm(infrared->rpc_ctx, result); + } else if(event.event == InfraredCustomEventTypeRpcButtonRelease) { bool result = false; - if(state == InfraredRpcStateSending) { + + if(rpc_state == InfraredRpcStateSending) { infrared_tx_stop(infrared); result = true; scene_manager_set_scene_state( infrared->scene_manager, InfraredSceneRpc, InfraredRpcStateLoaded); } + rpc_system_app_confirm(infrared->rpc_ctx, result); - } else if(event.event == InfraredCustomEventTypeRpcExit) { - scene_manager_stop(infrared->scene_manager); - view_dispatcher_stop(infrared->view_dispatcher); - rpc_system_app_confirm(infrared->rpc_ctx, true); - } else if(event.event == InfraredCustomEventTypeRpcSessionClose) { + + } else if( + event.event == InfraredCustomEventTypeRpcExit || + event.event == InfraredCustomEventTypeRpcSessionClose || + event.event == InfraredCustomEventTypePopupClosed) { scene_manager_stop(infrared->scene_manager); view_dispatcher_stop(infrared->view_dispatcher); + + if(event.event == InfraredCustomEventTypeRpcExit) { + rpc_system_app_confirm(infrared->rpc_ctx, true); + } } + + consumed = true; } + return consumed; } @@ -112,5 +132,6 @@ void infrared_scene_rpc_on_exit(void* context) { InfraredRpcStateSending) { infrared_tx_stop(infrared); } + popup_reset(infrared->popup); } diff --git a/applications/main/infrared/scenes/infrared_scene_universal_ac.c b/applications/main/infrared/scenes/infrared_scene_universal_ac.c index c691aef43..45f6b4ab6 100644 --- a/applications/main/infrared/scenes/infrared_scene_universal_ac.c +++ b/applications/main/infrared/scenes/infrared_scene_universal_ac.c @@ -3,8 +3,6 @@ #include "common/infrared_scene_universal_common.h" void infrared_scene_universal_ac_on_enter(void* context) { - infrared_scene_universal_common_on_enter(context); - InfraredApp* infrared = context; ButtonPanel* button_panel = infrared->button_panel; InfraredBruteForce* brute_force = infrared->brute_force; @@ -122,16 +120,7 @@ void infrared_scene_universal_ac_on_enter(void* context) { button_panel_add_label(button_panel, 22, 10, FontPrimary, "ACs"); - view_set_orientation(view_stack_get_view(infrared->view_stack), ViewOrientationVertical); - view_dispatcher_switch_to_view(infrared->view_dispatcher, InfraredViewStack); - - infrared_show_loading_popup(infrared, true); - bool success = infrared_brute_force_calculate_messages(brute_force); - infrared_show_loading_popup(infrared, false); - - if(!success) { - scene_manager_next_scene(infrared->scene_manager, InfraredSceneErrorDatabases); - } + infrared_scene_universal_common_on_enter(context); } bool infrared_scene_universal_ac_on_event(void* context, SceneManagerEvent event) { diff --git a/applications/main/infrared/scenes/infrared_scene_universal_audio.c b/applications/main/infrared/scenes/infrared_scene_universal_audio.c index 11f84acc4..9e90d859e 100644 --- a/applications/main/infrared/scenes/infrared_scene_universal_audio.c +++ b/applications/main/infrared/scenes/infrared_scene_universal_audio.c @@ -3,8 +3,6 @@ #include "common/infrared_scene_universal_common.h" void infrared_scene_universal_audio_on_enter(void* context) { - infrared_scene_universal_common_on_enter(context); - InfraredApp* infrared = context; ButtonPanel* button_panel = infrared->button_panel; InfraredBruteForce* brute_force = infrared->brute_force; @@ -119,16 +117,7 @@ void infrared_scene_universal_audio_on_enter(void* context) { button_panel_add_label(button_panel, 18, 10, FontPrimary, "Audio"); button_panel_add_icon(button_panel, 34, 56, &I_vol_ac_text_30x30); - view_set_orientation(view_stack_get_view(infrared->view_stack), ViewOrientationVertical); - view_dispatcher_switch_to_view(infrared->view_dispatcher, InfraredViewStack); - - infrared_show_loading_popup(infrared, true); - bool success = infrared_brute_force_calculate_messages(brute_force); - infrared_show_loading_popup(infrared, false); - - if(!success) { - scene_manager_next_scene(infrared->scene_manager, InfraredSceneErrorDatabases); - } + infrared_scene_universal_common_on_enter(context); } bool infrared_scene_universal_audio_on_event(void* context, SceneManagerEvent event) { diff --git a/applications/main/infrared/scenes/infrared_scene_universal_digital_sign.c b/applications/main/infrared/scenes/infrared_scene_universal_digital_sign.c index 37f86e71b..4b0d5cc5d 100644 --- a/applications/main/infrared/scenes/infrared_scene_universal_digital_sign.c +++ b/applications/main/infrared/scenes/infrared_scene_universal_digital_sign.c @@ -3,8 +3,6 @@ #include "common/infrared_scene_universal_common.h" void infrared_scene_universal_digital_sign_on_enter(void* context) { - infrared_scene_universal_common_on_enter(context); - InfraredApp* infrared = context; ButtonPanel* button_panel = infrared->button_panel; InfraredBruteForce* brute_force = infrared->brute_force; @@ -71,16 +69,7 @@ void infrared_scene_universal_digital_sign_on_enter(void* context) { button_panel_add_label(button_panel, 1, 11, FontPrimary, "Digital Signs"); - view_set_orientation(view_stack_get_view(infrared->view_stack), ViewOrientationVertical); - view_dispatcher_switch_to_view(infrared->view_dispatcher, InfraredViewStack); - - infrared_show_loading_popup(infrared, true); - bool success = infrared_brute_force_calculate_messages(brute_force); - infrared_show_loading_popup(infrared, false); - - if(!success) { - scene_manager_next_scene(infrared->scene_manager, InfraredSceneErrorDatabases); - } + infrared_scene_universal_common_on_enter(context); } bool infrared_scene_universal_digital_sign_on_event(void* context, SceneManagerEvent event) { diff --git a/applications/main/infrared/scenes/infrared_scene_universal_fan.c b/applications/main/infrared/scenes/infrared_scene_universal_fan.c index ef3e819fd..6f3a7d4b7 100644 --- a/applications/main/infrared/scenes/infrared_scene_universal_fan.c +++ b/applications/main/infrared/scenes/infrared_scene_universal_fan.c @@ -3,8 +3,6 @@ #include "common/infrared_scene_universal_common.h" void infrared_scene_universal_fan_on_enter(void* context) { - infrared_scene_universal_common_on_enter(context); - InfraredApp* infrared = context; ButtonPanel* button_panel = infrared->button_panel; InfraredBruteForce* brute_force = infrared->brute_force; @@ -97,16 +95,7 @@ void infrared_scene_universal_fan_on_enter(void* context) { button_panel_add_label(button_panel, 20, 11, FontPrimary, "Fans"); button_panel_add_icon(button_panel, 34, 68, &I_speed_text_30x30); - view_set_orientation(view_stack_get_view(infrared->view_stack), ViewOrientationVertical); - view_dispatcher_switch_to_view(infrared->view_dispatcher, InfraredViewStack); - - infrared_show_loading_popup(infrared, true); - bool success = infrared_brute_force_calculate_messages(brute_force); - infrared_show_loading_popup(infrared, false); - - if(!success) { - scene_manager_next_scene(infrared->scene_manager, InfraredSceneErrorDatabases); - } + infrared_scene_universal_common_on_enter(context); } bool infrared_scene_universal_fan_on_event(void* context, SceneManagerEvent event) { diff --git a/applications/main/infrared/scenes/infrared_scene_universal_led.c b/applications/main/infrared/scenes/infrared_scene_universal_led.c index ca50a4a38..1055f71e9 100644 --- a/applications/main/infrared/scenes/infrared_scene_universal_led.c +++ b/applications/main/infrared/scenes/infrared_scene_universal_led.c @@ -3,8 +3,6 @@ #include "common/infrared_scene_universal_common.h" void infrared_scene_universal_led_on_enter(void* context) { - infrared_scene_universal_common_on_enter(context); - InfraredApp* infrared = context; ButtonPanel* button_panel = infrared->button_panel; InfraredBruteForce* brute_force = infrared->brute_force; @@ -71,16 +69,7 @@ void infrared_scene_universal_led_on_enter(void* context) { button_panel_add_label(button_panel, 21, 11, FontPrimary, "LEDs"); - view_set_orientation(view_stack_get_view(infrared->view_stack), ViewOrientationVertical); - view_dispatcher_switch_to_view(infrared->view_dispatcher, InfraredViewStack); - - infrared_show_loading_popup(infrared, true); - bool success = infrared_brute_force_calculate_messages(brute_force); - infrared_show_loading_popup(infrared, false); - - if(!success) { - scene_manager_next_scene(infrared->scene_manager, InfraredSceneErrorDatabases); - } + infrared_scene_universal_common_on_enter(context); } bool infrared_scene_universal_led_on_event(void* context, SceneManagerEvent event) { diff --git a/applications/main/infrared/scenes/infrared_scene_universal_monitor.c b/applications/main/infrared/scenes/infrared_scene_universal_monitor.c index 65e2f790c..da3d53999 100644 --- a/applications/main/infrared/scenes/infrared_scene_universal_monitor.c +++ b/applications/main/infrared/scenes/infrared_scene_universal_monitor.c @@ -3,8 +3,6 @@ #include "common/infrared_scene_universal_common.h" void infrared_scene_universal_monitor_on_enter(void* context) { - infrared_scene_universal_common_on_enter(context); - InfraredApp* infrared = context; ButtonPanel* button_panel = infrared->button_panel; InfraredBruteForce* brute_force = infrared->brute_force; @@ -72,16 +70,7 @@ void infrared_scene_universal_monitor_on_enter(void* context) { button_panel_add_label(button_panel, 10, 11, FontPrimary, "Monitors"); - view_set_orientation(view_stack_get_view(infrared->view_stack), ViewOrientationVertical); - view_dispatcher_switch_to_view(infrared->view_dispatcher, InfraredViewStack); - - infrared_show_loading_popup(infrared, true); - bool success = infrared_brute_force_calculate_messages(brute_force); - infrared_show_loading_popup(infrared, false); - - if(!success) { - scene_manager_next_scene(infrared->scene_manager, InfraredSceneErrorDatabases); - } + infrared_scene_universal_common_on_enter(context); } bool infrared_scene_universal_monitor_on_event(void* context, SceneManagerEvent event) { diff --git a/applications/main/infrared/scenes/infrared_scene_universal_projector.c b/applications/main/infrared/scenes/infrared_scene_universal_projector.c index 0e6b462fd..a90765c5f 100644 --- a/applications/main/infrared/scenes/infrared_scene_universal_projector.c +++ b/applications/main/infrared/scenes/infrared_scene_universal_projector.c @@ -3,8 +3,6 @@ #include "common/infrared_scene_universal_common.h" void infrared_scene_universal_projector_on_enter(void* context) { - infrared_scene_universal_common_on_enter(context); - InfraredApp* infrared = context; ButtonPanel* button_panel = infrared->button_panel; InfraredBruteForce* brute_force = infrared->brute_force; @@ -94,16 +92,7 @@ void infrared_scene_universal_projector_on_enter(void* context) { button_panel_add_label(button_panel, 7, 11, FontPrimary, "Projectors"); button_panel_add_icon(button_panel, 34, 68, &I_vol_ac_text_30x30); - view_set_orientation(view_stack_get_view(infrared->view_stack), ViewOrientationVertical); - view_dispatcher_switch_to_view(infrared->view_dispatcher, InfraredViewStack); - - infrared_show_loading_popup(infrared, true); - bool success = infrared_brute_force_calculate_messages(brute_force); - infrared_show_loading_popup(infrared, false); - - if(!success) { - scene_manager_next_scene(infrared->scene_manager, InfraredSceneErrorDatabases); - } + infrared_scene_universal_common_on_enter(context); } bool infrared_scene_universal_projector_on_event(void* context, SceneManagerEvent event) { diff --git a/applications/main/infrared/scenes/infrared_scene_universal_tv.c b/applications/main/infrared/scenes/infrared_scene_universal_tv.c index c7e755848..a1fa4b26f 100644 --- a/applications/main/infrared/scenes/infrared_scene_universal_tv.c +++ b/applications/main/infrared/scenes/infrared_scene_universal_tv.c @@ -3,8 +3,6 @@ #include "common/infrared_scene_universal_common.h" void infrared_scene_universal_tv_on_enter(void* context) { - infrared_scene_universal_common_on_enter(context); - InfraredApp* infrared = context; ButtonPanel* button_panel = infrared->button_panel; InfraredBruteForce* brute_force = infrared->brute_force; @@ -95,16 +93,7 @@ void infrared_scene_universal_tv_on_enter(void* context) { button_panel_add_label(button_panel, 22, 10, FontPrimary, "TVs"); - view_set_orientation(view_stack_get_view(infrared->view_stack), ViewOrientationVertical); - view_dispatcher_switch_to_view(infrared->view_dispatcher, InfraredViewStack); - - infrared_show_loading_popup(infrared, true); - bool success = infrared_brute_force_calculate_messages(brute_force); - infrared_show_loading_popup(infrared, false); - - if(!success) { - scene_manager_next_scene(infrared->scene_manager, InfraredSceneErrorDatabases); - } + infrared_scene_universal_common_on_enter(context); } bool infrared_scene_universal_tv_on_event(void* context, SceneManagerEvent event) { diff --git a/applications/main/lfrfid/application.fam b/applications/main/lfrfid/application.fam index f8d062f36..5e97e925d 100644 --- a/applications/main/lfrfid/application.fam +++ b/applications/main/lfrfid/application.fam @@ -11,11 +11,20 @@ App( fap_category="RFID", ) +App( + appid="lfrfid_cli", + targets=["f7"], + apptype=FlipperAppType.PLUGIN, + entry_point="lfrfid_cli_plugin_ep", + requires=["cli"], + sources=["lfrfid_cli.c"], +) + App( appid="lfrfid_start", targets=["f7"], apptype=FlipperAppType.STARTUP, entry_point="lfrfid_on_system_start", - sources=["lfrfid_cli.c"], + sources=["lfrfid_start.c"], order=50, ) diff --git a/applications/main/lfrfid/lfrfid_cli.c b/applications/main/lfrfid/lfrfid_cli.c index af340008a..5af1f6abe 100644 --- a/applications/main/lfrfid/lfrfid_cli.c +++ b/applications/main/lfrfid/lfrfid_cli.c @@ -14,15 +14,6 @@ #include #include -static void lfrfid_cli(Cli* cli, FuriString* args, void* context); - -// app cli function -void lfrfid_on_system_start() { - Cli* cli = furi_record_open(RECORD_CLI); - cli_add_command(cli, "rfid", CliCommandFlagDefault, lfrfid_cli, NULL); - furi_record_close(RECORD_CLI); -} - static void lfrfid_cli_print_usage() { printf("Usage:\r\n"); printf("rfid read - read in ASK/PSK mode\r\n"); @@ -577,3 +568,15 @@ static void lfrfid_cli(Cli* cli, FuriString* args, void* context) { furi_string_free(cmd); } + +#include + +static const FlipperAppPluginDescriptor plugin_descriptor = { + .appid = "lfrfid_cli", + .ep_api_version = 1, + .entry_point = &lfrfid_cli, +}; + +const FlipperAppPluginDescriptor* lfrfid_cli_plugin_ep() { + return &plugin_descriptor; +} diff --git a/applications/main/lfrfid/lfrfid_start.c b/applications/main/lfrfid/lfrfid_start.c new file mode 100644 index 000000000..1ed88d2f0 --- /dev/null +++ b/applications/main/lfrfid/lfrfid_start.c @@ -0,0 +1,11 @@ +#include + +static void lfrfid_cli_wrapper(Cli* cli, FuriString* args, void* context) { + cli_plugin_wrapper("lfrfid_cli", 1, cli, args, context); +} + +void lfrfid_on_system_start() { + Cli* cli = furi_record_open(RECORD_CLI); + cli_add_command(cli, "rfid", CliCommandFlagDefault, lfrfid_cli_wrapper, NULL); + furi_record_close(RECORD_CLI); +} diff --git a/applications/main/momentum_app/momentum_app.c b/applications/main/momentum_app/momentum_app.c index 94ee34ee7..d1ff7d620 100644 --- a/applications/main/momentum_app/momentum_app.c +++ b/applications/main/momentum_app/momentum_app.c @@ -242,11 +242,21 @@ MomentumApp* momentum_app_alloc() { CharList_init(app->mainmenu_app_exes); Stream* stream = file_stream_alloc(storage); FuriString* line = furi_string_alloc(); - if(file_stream_open(stream, MAINMENU_APPS_PATH, FSAM_READ, FSOM_OPEN_EXISTING)) { - stream_read_line(stream, line); + uint32_t version; + if(file_stream_open(stream, MAINMENU_APPS_PATH, FSAM_READ, FSOM_OPEN_EXISTING) && + stream_read_line(stream, line) && + sscanf(furi_string_get_cstr(line), "MenuAppList Version %lu", &version) == 1 && + version <= 1) { while(stream_read_line(stream, line)) { furi_string_replace_all(line, "\r", ""); furi_string_replace_all(line, "\n", ""); + if(version == 0) { + if(!furi_string_cmp(line, "RFID")) { + furi_string_set(line, "125 kHz RFID"); + } else if(!furi_string_cmp(line, "SubGHz")) { + furi_string_set(line, "Sub-GHz"); + } + } CharList_push_back(app->mainmenu_app_exes, strdup(furi_string_get_cstr(line))); flipper_application_load_name_and_icon(line, storage, NULL, line); if(!furi_string_cmp(line, "Momentum")) { diff --git a/applications/main/momentum_app/scenes/momentum_app_scene_protocols.c b/applications/main/momentum_app/scenes/momentum_app_scene_protocols.c index cbe69e46c..7258a9d9a 100644 --- a/applications/main/momentum_app/scenes/momentum_app_scene_protocols.c +++ b/applications/main/momentum_app/scenes/momentum_app_scene_protocols.c @@ -1,8 +1,6 @@ #include "../momentum_app.h" enum VarItemListIndex { - VarItemListIndexBadkbMode, - VarItemListIndexBadbtRemember, VarItemListIndexSubghzFreqs, VarItemListIndexSubghzExtend, VarItemListIndexGpioPins, @@ -13,22 +11,6 @@ void momentum_app_scene_protocols_var_item_list_callback(void* context, uint32_t view_dispatcher_send_custom_event(app->view_dispatcher, index); } -static void momentum_app_scene_protocols_bad_bt_changed(VariableItem* item) { - MomentumApp* app = variable_item_get_context(item); - bool value = variable_item_get_current_value_index(item); - variable_item_set_current_value_text(item, value ? "BT" : "USB"); - momentum_settings.bad_bt = value; - app->save_settings = true; -} - -static void momentum_app_scene_protocols_bad_bt_remember_changed(VariableItem* item) { - MomentumApp* app = variable_item_get_context(item); - bool value = variable_item_get_current_value_index(item); - variable_item_set_current_value_text(item, value ? "ON" : "OFF"); - momentum_settings.bad_bt_remember = value; - app->save_settings = true; -} - static void momentum_app_scene_protocols_subghz_extend_changed(VariableItem* item) { MomentumApp* app = variable_item_get_context(item); app->subghz_extend = variable_item_get_current_value_index(item); @@ -49,20 +31,6 @@ void momentum_app_scene_protocols_on_enter(void* context) { VariableItemList* var_item_list = app->var_item_list; VariableItem* item; - item = variable_item_list_add( - var_item_list, "BadKB Mode", 2, momentum_app_scene_protocols_bad_bt_changed, app); - variable_item_set_current_value_index(item, momentum_settings.bad_bt); - variable_item_set_current_value_text(item, momentum_settings.bad_bt ? "BT" : "USB"); - - item = variable_item_list_add( - var_item_list, - "BadBT Remember", - 2, - momentum_app_scene_protocols_bad_bt_remember_changed, - app); - variable_item_set_current_value_index(item, momentum_settings.bad_bt_remember); - variable_item_set_current_value_text(item, momentum_settings.bad_bt_remember ? "ON" : "OFF"); - item = variable_item_list_add(var_item_list, "SubGHz Freqs", 0, NULL, app); variable_item_set_current_value_text(item, ">"); diff --git a/applications/main/nfc/application.fam b/applications/main/nfc/application.fam index 0468e4bfb..10c288f24 100644 --- a/applications/main/nfc/application.fam +++ b/applications/main/nfc/application.fam @@ -263,11 +263,20 @@ App( sources=["plugins/supported_cards/sonicare.c"], ) +App( + appid="nfc_cli", + targets=["f7"], + apptype=FlipperAppType.PLUGIN, + entry_point="nfc_cli_plugin_ep", + requires=["cli"], + sources=["nfc_cli.c"], +) + App( appid="nfc_start", targets=["f7"], apptype=FlipperAppType.STARTUP, entry_point="nfc_on_system_start", - sources=["nfc_cli.c"], + sources=["nfc_start.c"], order=30, ) diff --git a/applications/main/nfc/nfc_cli.c b/applications/main/nfc/nfc_cli.c index b5a40b122..85cc2ae84 100644 --- a/applications/main/nfc/nfc_cli.c +++ b/applications/main/nfc/nfc_cli.c @@ -63,12 +63,14 @@ static void nfc_cli(Cli* cli, FuriString* args, void* context) { furi_string_free(cmd); } -void nfc_on_system_start() { -#ifdef SRV_CLI - Cli* cli = furi_record_open(RECORD_CLI); - cli_add_command(cli, "nfc", CliCommandFlagDefault, nfc_cli, NULL); - furi_record_close(RECORD_CLI); -#else - UNUSED(nfc_cli); -#endif +#include + +static const FlipperAppPluginDescriptor plugin_descriptor = { + .appid = "nfc_cli", + .ep_api_version = 1, + .entry_point = &nfc_cli, +}; + +const FlipperAppPluginDescriptor* nfc_cli_plugin_ep() { + return &plugin_descriptor; } diff --git a/applications/main/nfc/nfc_start.c b/applications/main/nfc/nfc_start.c new file mode 100644 index 000000000..6e5b5a8b2 --- /dev/null +++ b/applications/main/nfc/nfc_start.c @@ -0,0 +1,11 @@ +#include + +static void nfc_cli_wrapper(Cli* cli, FuriString* args, void* context) { + cli_plugin_wrapper("nfc_cli", 1, cli, args, context); +} + +void nfc_on_system_start() { + Cli* cli = furi_record_open(RECORD_CLI); + cli_add_command(cli, "nfc", CliCommandFlagDefault, nfc_cli_wrapper, NULL); + furi_record_close(RECORD_CLI); +} diff --git a/applications/main/nfc/plugins/supported_cards/bip.c b/applications/main/nfc/plugins/supported_cards/bip.c index f6fed6774..c3587fbd3 100644 --- a/applications/main/nfc/plugins/supported_cards/bip.c +++ b/applications/main/nfc/plugins/supported_cards/bip.c @@ -1,70 +1,139 @@ #include "nfc_supported_card_plugin.h" +#include -#include -#include -#include +#include "protocols/mf_classic/mf_classic.h" #include +#include +#include + #define TAG "Bip" -#define SECTOR_BLOCK_OFFSET(sector, block) (((sector) * 4) + (block)) +#define BIP_CARD_ID_SECTOR_NUMBER (0) +#define BIP_BALANCE_SECTOR_NUMBER (8) +#define BIP_TRIP_TIME_WINDOW_SECTOR_NUMBER (5) +#define BIP_LAST_TOP_UPS_SECTOR_NUMBER (10) +#define BIP_TRIPS_INFO_SECTOR_NUMBER (11) -static const uint64_t bip_keys_a[] = { - 0x3a42f33af429, - 0x6338a371c0ed, - 0xf124c2578ad0, - 0x32ac3b90ac13, - 0x4ad1e273eaf1, - 0xe2c42591368a, - 0x2a3c347a1200, - 0x16f3d5ab1139, - 0x937a4fff3011, - 0x35c3d2caee88, - 0x693143f10368, - 0xa3f97428dd01, - 0x63f17a449af0, - 0xc4652c54261c, - 0xd49e2826664f, - 0x3df14c8000a1, +typedef struct { + DateTime datetime; + uint16_t amount; +} BipTransaction; + +typedef struct { + uint64_t a; + uint64_t b; +} MfClassicKeyPair; + +static const MfClassicKeyPair bip_1k_keys[] = { + {.a = 0x3a42f33af429, .b = 0x1fc235ac1309}, + {.a = 0x6338a371c0ed, .b = 0x243f160918d1}, + {.a = 0xf124c2578ad0, .b = 0x9afc42372af1}, + {.a = 0x32ac3b90ac13, .b = 0x682d401abb09}, + {.a = 0x4ad1e273eaf1, .b = 0x067db45454a9}, + {.a = 0xe2c42591368a, .b = 0x15fc4c7613fe}, + {.a = 0x2a3c347a1200, .b = 0x68d30288910a}, + {.a = 0x16f3d5ab1139, .b = 0xf59a36a2546d}, + {.a = 0x937a4fff3011, .b = 0x64e3c10394c2}, + {.a = 0x35c3d2caee88, .b = 0xb736412614af}, + {.a = 0x693143f10368, .b = 0x324f5df65310}, + {.a = 0xa3f97428dd01, .b = 0x643fb6de2217}, + {.a = 0x63f17a449af0, .b = 0x82f435dedf01}, + {.a = 0xc4652c54261c, .b = 0x0263de1278f3}, + {.a = 0xd49e2826664f, .b = 0x51284c3686a6}, + {.a = 0x3df14c8000a1, .b = 0x6a470d54127c}, }; -static const uint64_t bip_keys_b[] = { - 0x1fc235ac1309, - 0x243f160918d1, - 0x9afc42372af1, - 0x682d401abb09, - 0x067db45454a9, - 0x15fc4c7613fe, - 0x68d30288910a, - 0xf59a36a2546d, - 0x64e3c10394c2, - 0xb736412614af, - 0x324f5df65310, - 0x643fb6de2217, - 0x82f435dedf01, - 0x0263de1278f3, - 0x51284c3686a6, - 0x6a470d54127c, -}; +static void bip_parse_datetime(const MfClassicBlock* block, DateTime* parsed_data) { + furi_assert(block); + furi_assert(parsed_data); + + parsed_data->day = (((block->data[1] << 8) + block->data[0]) >> 6) & 0x1f; + parsed_data->month = (((block->data[1] << 8) + block->data[0]) >> 11) & 0xf; + parsed_data->year = 2000 + ((((block->data[2] << 8) + block->data[1]) >> 7) & 0x1f); + parsed_data->hour = (((block->data[3] << 8) + block->data[2]) >> 4) & 0x1f; + parsed_data->minute = (((block->data[3] << 8) + block->data[2]) >> 9) & 0x3f; + parsed_data->second = (((block->data[4] << 8) + block->data[3]) >> 7) & 0x3f; +} + +static void bip_print_datetime(const DateTime* datetime, FuriString* str) { + furi_assert(datetime); + furi_assert(str); + + LocaleDateFormat date_format = locale_get_date_format(); + const char* separator = (date_format == LocaleDateFormatDMY) ? "." : "/"; + + FuriString* date_str = furi_string_alloc(); + locale_format_date(date_str, datetime, date_format, separator); + + FuriString* time_str = furi_string_alloc(); + locale_format_time(time_str, datetime, locale_get_time_format(), true); + + furi_string_cat_printf( + str, "%s %s", furi_string_get_cstr(date_str), furi_string_get_cstr(time_str)); + + furi_string_free(date_str); + furi_string_free(time_str); +} + +static int datetime_cmp(const DateTime* dt_1, const DateTime* dt_2) { + furi_assert(dt_1); + furi_assert(dt_2); + + if(dt_1->year != dt_2->year) { + return dt_1->year - dt_2->year; + } + if(dt_1->month != dt_2->month) { + return dt_1->month - dt_2->month; + } + if(dt_1->day != dt_2->day) { + return dt_1->day - dt_2->day; + } + if(dt_1->hour != dt_2->hour) { + return dt_1->hour - dt_2->hour; + } + if(dt_1->minute != dt_2->minute) { + return dt_1->minute - dt_2->minute; + } + if(dt_1->second != dt_2->second) { + return dt_1->second - dt_2->second; + } + return 0; +} + +static bool is_bip_block_empty(const MfClassicBlock* block) { + furi_assert(block); + // check if all but last byte are zero (last is checksum) + for(size_t i = 0; i < sizeof(block->data) - 1; i++) { + if(block->data[i] != 0) { + return false; + } + } + return true; +} bool bip_verify(Nfc* nfc) { - bool verified = true; + bool verified = false; - const uint8_t verify_sector = 0; - uint8_t block_num = mf_classic_get_first_block_num_of_sector(verify_sector); - FURI_LOG_D(TAG, "Verifying sector %u", verify_sector); + do { + const uint8_t verify_sector = 0; + uint8_t block_num = mf_classic_get_first_block_num_of_sector(verify_sector); + FURI_LOG_D(TAG, "Verifying sector %u", verify_sector); - MfClassicKey key_a_0 = {}; - bit_lib_num_to_bytes_be(bip_keys_a[0], COUNT_OF(key_a_0.data), key_a_0.data); + MfClassicKey key = {}; + bit_lib_num_to_bytes_be(bip_1k_keys[0].a, COUNT_OF(key.data), key.data); - MfClassicAuthContext auth_ctx = {}; - MfClassicError error = - mf_classic_poller_sync_auth(nfc, block_num, &key_a_0, MfClassicKeyTypeA, &auth_ctx); + MfClassicAuthContext auth_ctx = {}; + MfClassicError error = + mf_classic_poller_sync_auth(nfc, block_num, &key, MfClassicKeyTypeA, &auth_ctx); - if(error == MfClassicErrorNotPresent) { - FURI_LOG_D(TAG, "Failed to read block %u: %d", block_num, error); - verified = false; - } + if(error == MfClassicErrorNone) { + FURI_LOG_D(TAG, "Failed to read block %u: %d", block_num, error); + break; + } + + verified = true; + } while(false); return verified; } @@ -79,31 +148,33 @@ static bool bip_read(Nfc* nfc, NfcDevice* device) { nfc_device_copy_data(device, NfcProtocolMfClassic, data); do { - MfClassicType type = MfClassicType1k; + MfClassicType type = MfClassicTypeMini; MfClassicError error = mf_classic_poller_sync_detect_type(nfc, &type); - if(error == MfClassicErrorNotPresent) { - FURI_LOG_W(TAG, "Card not MIFARE Classic 1k"); - break; - } + if(error != MfClassicErrorNone) break; data->type = type; - MfClassicDeviceKeys keys = {}; + if(type != MfClassicType1k) break; + + MfClassicDeviceKeys keys = { + .key_a_mask = 0, + .key_b_mask = 0, + }; for(size_t i = 0; i < mf_classic_get_total_sectors_num(data->type); i++) { - bit_lib_num_to_bytes_be(bip_keys_a[i], sizeof(MfClassicKey), keys.key_a[i].data); + bit_lib_num_to_bytes_be(bip_1k_keys[i].a, sizeof(MfClassicKey), keys.key_a[i].data); FURI_BIT_SET(keys.key_a_mask, i); - bit_lib_num_to_bytes_be(bip_keys_b[i], sizeof(MfClassicKey), keys.key_b[i].data); + bit_lib_num_to_bytes_be(bip_1k_keys[i].b, sizeof(MfClassicKey), keys.key_b[i].data); FURI_BIT_SET(keys.key_b_mask, i); } error = mf_classic_poller_sync_read(nfc, &keys, data); if(error == MfClassicErrorNotPresent) { - FURI_LOG_W(TAG, "Failed to read data. Bad keys?"); + FURI_LOG_W(TAG, "Failed to read data"); break; } nfc_device_set_data(device, NfcProtocolMfClassic, data); - is_read = true; + is_read = (error == MfClassicErrorNone); } while(false); mf_classic_free(data); @@ -111,183 +182,91 @@ static bool bip_read(Nfc* nfc, NfcDevice* device) { return is_read; } -typedef struct { - uint16_t year; - uint8_t month; - uint8_t day; - uint8_t hour; - uint8_t minute; - uint8_t second; -} BipTimestamp; - -static void parse_bip_timestamp(const MfClassicBlock* block, BipTimestamp* timestamp) { - furi_assert(block); - furi_assert(timestamp); - - timestamp->day = (((block->data[1] << 8) + block->data[0]) >> 6) & 0x1f; - timestamp->month = (((block->data[1] << 8) + block->data[0]) >> 11) & 0xf; - timestamp->year = 2000 + ((((block->data[2] << 8) + block->data[1]) >> 7) & 0x1f); - timestamp->hour = (((block->data[3] << 8) + block->data[2]) >> 4) & 0x1f; - timestamp->minute = (((block->data[3] << 8) + block->data[2]) >> 9) & 0x3f; - timestamp->second = (((block->data[4] << 8) + block->data[3]) >> 7) & 0x3f; -} - -static int compare_bip_timestamp(const BipTimestamp* t1, const BipTimestamp* t2) { - furi_assert(t1); - furi_assert(t2); - if(t1->year != t2->year) { - return t1->year - t2->year; - } - if(t1->month != t2->month) { - return t1->month - t2->month; - } - if(t1->day != t2->day) { - return t1->day - t2->day; - } - if(t1->hour != t2->hour) { - return t1->hour - t2->hour; - } - if(t1->minute != t2->minute) { - return t1->minute - t2->minute; - } - if(t1->second != t2->second) { - return t1->second - t2->second; - } - return 0; -} - -static void print_bip_timestamp(const BipTimestamp* timestamp, FuriString* str) { - furi_assert(timestamp); - furi_assert(str); - furi_string_cat_printf( - str, - "%04u-%02u-%02u %02u:%02u:%02u", - timestamp->year, - timestamp->month, - timestamp->day, - timestamp->hour, - timestamp->minute, - timestamp->second); -} - -static bool is_bip_block_empty(const MfClassicBlock* block) { - furi_assert(block); - // check if all but last byte are zero (last is checksum) - for(size_t i = 0; i < sizeof(block->data) - 1; i++) { - if(block->data[i] != 0) { - return false; - } - } - return true; -} - -static void parse_uint16_le(const uint8_t* data, uint16_t* value) { - furi_assert(data); - furi_assert(value); - - *value = (data[0]) | (data[1] << 8); -} - -static void parse_uint32_le(const uint8_t* data, uint32_t* value) { - furi_assert(data); - furi_assert(value); - - *value = (data[0]) | (data[1] << 8) | (data[2] << 16) | (data[3] << 24); -} - -static void parse_uint16_txn_amount(const uint8_t* data, uint16_t* value) { - furi_assert(data); - furi_assert(value); - - parse_uint16_le(data, value); - *value = *value >> 2; -} - -typedef struct { - BipTimestamp timestamp; - uint16_t amount; -} BipTransaction; - static bool bip_parse(const NfcDevice* device, FuriString* parsed_data) { furi_assert(device); furi_assert(parsed_data); - bool parsed = true; - struct { uint32_t card_id; uint16_t balance; uint16_t flags; - BipTimestamp trip_time_window; + DateTime trip_time_window; BipTransaction top_ups[3]; BipTransaction charges[3]; - } bip_data = { - .card_id = 0, - .balance = 0, - .flags = 0, - .trip_time_window = {0, 0, 0, 0, 0, 0}, - .top_ups = - { - {{0, 0, 0, 0, 0, 0}, 0}, - {{0, 0, 0, 0, 0, 0}, 0}, - {{0, 0, 0, 0, 0, 0}, 0}, - }, - .charges = - { - {{0, 0, 0, 0, 0, 0}, 0}, - {{0, 0, 0, 0, 0, 0}, 0}, - {{0, 0, 0, 0, 0, 0}, 0}, - }, - }; + } bip_data = {0}; const MfClassicData* data = nfc_device_get_data(device, NfcProtocolMfClassic); + bool parsed = false; + do { - // verify first sector keys + // verify sector 0 key A MfClassicSectorTrailer* sec_tr = mf_classic_get_sector_trailer_by_sector(data, 0); + + if(data->type != MfClassicType1k) break; + uint64_t key = bit_lib_bytes_to_num_be(sec_tr->key_a.data, 6); - if(key != bip_keys_a[0]) { - parsed = false; + if(key != bip_1k_keys[0].a) { break; } + + // verify sector 0 key B key = bit_lib_bytes_to_num_be(sec_tr->key_b.data, 6); - if(key != bip_keys_b[0]) { - parsed = false; + if(key != bip_1k_keys[0].b) { break; } // Get Card ID, little-endian 4 bytes at sector 0 block 1, bytes 4-7 - parse_uint32_le(&data->block[SECTOR_BLOCK_OFFSET(0, 1)].data[4], &bip_data.card_id); + const uint8_t card_id_start_block_num = + mf_classic_get_first_block_num_of_sector(BIP_CARD_ID_SECTOR_NUMBER); + const uint8_t* block_start_ptr = &data->block[card_id_start_block_num + 1].data[0]; + + bip_data.card_id = bit_lib_bytes_to_num_le(block_start_ptr + 4, 4); // Get balance, little-endian 2 bytes at sector 8 block 1, bytes 0-1 - parse_uint16_le(&data->block[SECTOR_BLOCK_OFFSET(8, 1)].data[0], &bip_data.balance); + const uint8_t balance_start_block_num = + mf_classic_get_first_block_num_of_sector(BIP_BALANCE_SECTOR_NUMBER); + block_start_ptr = &data->block[balance_start_block_num + 1].data[0]; + + bip_data.balance = bit_lib_bytes_to_num_le(block_start_ptr, 2); // Get balance flags (negative balance, etc.), little-endian 2 bytes at sector 8 block 1, bytes 2-3 - parse_uint16_le(&data->block[SECTOR_BLOCK_OFFSET(8, 1)].data[2], &bip_data.flags); + bip_data.flags = bit_lib_bytes_to_num_le(block_start_ptr + 2, 2); // Get trip time window, proprietary format, at sector 5 block 1, bytes 0-7 - parse_bip_timestamp(&data->block[SECTOR_BLOCK_OFFSET(5, 1)], &bip_data.trip_time_window); + const uint8_t trip_time_window_start_block_num = + mf_classic_get_first_block_num_of_sector(BIP_TRIP_TIME_WINDOW_SECTOR_NUMBER); + const MfClassicBlock* trip_window_block_ptr = + &data->block[trip_time_window_start_block_num + 1]; + + bip_parse_datetime(trip_window_block_ptr, &bip_data.trip_time_window); // Last 3 top-ups: sector 10, ring-buffer of 3 blocks, timestamp in bytes 0-7, amount in bytes 9-10 + const uint8_t top_ups_start_block_num = + mf_classic_get_first_block_num_of_sector(BIP_LAST_TOP_UPS_SECTOR_NUMBER); for(size_t i = 0; i < 3; i++) { - if(is_bip_block_empty(&data->block[SECTOR_BLOCK_OFFSET(10, i)])) { - continue; - } + const MfClassicBlock* block = &data->block[top_ups_start_block_num + i]; + + if(is_bip_block_empty(block)) continue; + BipTransaction* top_up = &bip_data.top_ups[i]; - parse_bip_timestamp(&data->block[SECTOR_BLOCK_OFFSET(10, i)], &top_up->timestamp); - parse_uint16_txn_amount( - &data->block[SECTOR_BLOCK_OFFSET(10, i)].data[9], &top_up->amount); + bip_parse_datetime(block, &top_up->datetime); + + top_up->amount = bit_lib_bytes_to_num_le(&block->data[9], 2) >> 2; } // Last 3 charges (i.e. trips), sector 11, ring-buffer of 3 blocks, timestamp in bytes 0-7, amount in bytes 10-11 + const uint8_t trips_start_block_num = + mf_classic_get_first_block_num_of_sector(BIP_TRIPS_INFO_SECTOR_NUMBER); for(size_t i = 0; i < 3; i++) { - if(is_bip_block_empty(&data->block[SECTOR_BLOCK_OFFSET(11, i)])) { - continue; - } + const MfClassicBlock* block = &data->block[trips_start_block_num + i]; + + if(is_bip_block_empty(block)) continue; + BipTransaction* charge = &bip_data.charges[i]; - parse_bip_timestamp(&data->block[SECTOR_BLOCK_OFFSET(11, i)], &charge->timestamp); - parse_uint16_txn_amount( - &data->block[SECTOR_BLOCK_OFFSET(11, i)].data[10], &charge->amount); + bip_parse_datetime(block, &charge->datetime); + + charge->amount = bit_lib_bytes_to_num_le(&block->data[10], 2) >> 2; } // All data is now parsed and stored in bip_data, now print it @@ -303,14 +282,14 @@ static bool bip_parse(const NfcDevice* device, FuriString* parsed_data) { bip_data.balance, bip_data.flags); - print_bip_timestamp(&bip_data.trip_time_window, parsed_data); + bip_print_datetime(&bip_data.trip_time_window, parsed_data); // Find newest top-up size_t newest_top_up = 0; for(size_t i = 1; i < 3; i++) { - const BipTimestamp* newest = &bip_data.top_ups[newest_top_up].timestamp; - const BipTimestamp* current = &bip_data.top_ups[i].timestamp; - if(compare_bip_timestamp(current, newest) > 0) { + const DateTime* newest = &bip_data.top_ups[newest_top_up].datetime; + const DateTime* current = &bip_data.top_ups[i].datetime; + if(datetime_cmp(current, newest) > 0) { newest_top_up = i; } } @@ -320,15 +299,15 @@ static bool bip_parse(const NfcDevice* device, FuriString* parsed_data) { for(size_t i = 0; i < 3; i++) { const BipTransaction* top_up = &bip_data.top_ups[(3u + newest_top_up - i) % 3]; furi_string_cat_printf(parsed_data, "\n+$%d\n @", top_up->amount); - print_bip_timestamp(&top_up->timestamp, parsed_data); + bip_print_datetime(&top_up->datetime, parsed_data); } // Find newest charge size_t newest_charge = 0; for(size_t i = 1; i < 3; i++) { - const BipTimestamp* newest = &bip_data.charges[newest_charge].timestamp; - const BipTimestamp* current = &bip_data.charges[i].timestamp; - if(compare_bip_timestamp(current, newest) > 0) { + const DateTime* newest = &bip_data.charges[newest_charge].datetime; + const DateTime* current = &bip_data.charges[i].datetime; + if(datetime_cmp(current, newest) > 0) { newest_charge = i; } } @@ -338,7 +317,7 @@ static bool bip_parse(const NfcDevice* device, FuriString* parsed_data) { for(size_t i = 0; i < 3; i++) { const BipTransaction* charge = &bip_data.charges[(3u + newest_charge - i) % 3]; furi_string_cat_printf(parsed_data, "\n-$%d\n @", charge->amount); - print_bip_timestamp(&charge->timestamp, parsed_data); + bip_print_datetime(&charge->datetime, parsed_data); } parsed = true; diff --git a/applications/main/onewire/application.fam b/applications/main/onewire/application.fam index 3d35abce9..9fac2ff21 100644 --- a/applications/main/onewire/application.fam +++ b/applications/main/onewire/application.fam @@ -1,6 +1,16 @@ +App( + appid="onewire_cli", + targets=["f7"], + apptype=FlipperAppType.PLUGIN, + entry_point="onewire_cli_plugin_ep", + requires=["cli"], + sources=["onewire_cli.c"], +) + App( appid="onewire_start", apptype=FlipperAppType.STARTUP, entry_point="onewire_on_system_start", + sources=["onewire_start.c"], order=60, ) diff --git a/applications/main/onewire/onewire_cli.c b/applications/main/onewire/onewire_cli.c index 9a7ffe55c..7fb01bef0 100644 --- a/applications/main/onewire/onewire_cli.c +++ b/applications/main/onewire/onewire_cli.c @@ -6,18 +6,6 @@ #include -static void onewire_cli(Cli* cli, FuriString* args, void* context); - -void onewire_on_system_start() { -#ifdef SRV_CLI - Cli* cli = furi_record_open(RECORD_CLI); - cli_add_command(cli, "onewire", CliCommandFlagDefault, onewire_cli, cli); - furi_record_close(RECORD_CLI); -#else - UNUSED(onewire_cli); -#endif -} - static void onewire_cli_print_usage() { printf("Usage:\r\n"); printf("onewire search\r\n"); @@ -70,3 +58,15 @@ void onewire_cli(Cli* cli, FuriString* args, void* context) { furi_string_free(cmd); } + +#include + +static const FlipperAppPluginDescriptor plugin_descriptor = { + .appid = "onewire_cli", + .ep_api_version = 1, + .entry_point = &onewire_cli, +}; + +const FlipperAppPluginDescriptor* onewire_cli_plugin_ep() { + return &plugin_descriptor; +} diff --git a/applications/main/onewire/onewire_start.c b/applications/main/onewire/onewire_start.c new file mode 100644 index 000000000..6249204ab --- /dev/null +++ b/applications/main/onewire/onewire_start.c @@ -0,0 +1,11 @@ +#include + +static void onewire_cli_wrapper(Cli* cli, FuriString* args, void* context) { + cli_plugin_wrapper("onewire_cli", 1, cli, args, context); +} + +void onewire_on_system_start() { + Cli* cli = furi_record_open(RECORD_CLI); + cli_add_command(cli, "onewire", CliCommandFlagDefault, onewire_cli_wrapper, cli); + furi_record_close(RECORD_CLI); +} diff --git a/applications/main/subghz/application.fam b/applications/main/subghz/application.fam index b7c768bd2..8fb501c72 100644 --- a/applications/main/subghz/application.fam +++ b/applications/main/subghz/application.fam @@ -32,13 +32,22 @@ App( fap_category="Sub-GHz", ) +App( + appid="subghz_cli", + targets=["f7"], + apptype=FlipperAppType.PLUGIN, + entry_point="subghz_cli_plugin_ep", + requires=["cli"], + sources=["subghz_cli.c", "helpers/subghz_chat.c"], +) + App( appid="subghz_start", targets=["f7"], apptype=FlipperAppType.STARTUP, entry_point="subghz_on_system_start", - # sources=["subghz_cli.c", "helpers/subghz_chat.c"], + # sources=["subghz_start.c"], order=40, ) diff --git a/applications/main/subghz/subghz_cli.c b/applications/main/subghz/subghz_cli.c index f84d59983..15a890080 100644 --- a/applications/main/subghz/subghz_cli.c +++ b/applications/main/subghz/subghz_cli.c @@ -1197,17 +1197,14 @@ static void subghz_cli_command(Cli* cli, FuriString* args, void* context) { furi_string_free(cmd); } -void subghz_on_system_start() { -#ifdef SRV_CLI - Cli* cli = furi_record_open(RECORD_CLI); +#include - cli_add_command(cli, "subghz", CliCommandFlagDefault, subghz_cli_command, NULL); +static const FlipperAppPluginDescriptor plugin_descriptor = { + .appid = "subghz_cli", + .ep_api_version = 1, + .entry_point = &subghz_cli_command, +}; - // psst RM... i know you dont care much about errors, but if you ever see this... incompatible pointer type :3 - cli_add_command(cli, "chat", CliCommandFlagDefault, subghz_cli_command_chat, NULL); - - furi_record_close(RECORD_CLI); -#else - UNUSED(subghz_cli_command); -#endif +const FlipperAppPluginDescriptor* subghz_cli_plugin_ep() { + return &plugin_descriptor; } diff --git a/applications/main/subghz/subghz_start.c b/applications/main/subghz/subghz_start.c new file mode 100644 index 000000000..1cabcb5e6 --- /dev/null +++ b/applications/main/subghz/subghz_start.c @@ -0,0 +1,17 @@ +#include + +static void subghz_cli_command_wrapper(Cli* cli, FuriString* args, void* context) { + cli_plugin_wrapper("subghz_cli", 1, cli, args, context); +} + +static void subghz_cli_command_chat_wrapper(Cli* cli, FuriString* args, void* context) { + furi_string_replace_at(args, 0, 0, "chat "); + subghz_cli_command_wrapper(cli, args, context); +} + +void subghz_on_system_start() { + Cli* cli = furi_record_open(RECORD_CLI); + cli_add_command(cli, "subghz", CliCommandFlagDefault, subghz_cli_command_wrapper, NULL); + cli_add_command(cli, "chat", CliCommandFlagDefault, subghz_cli_command_chat_wrapper, NULL); + furi_record_close(RECORD_CLI); +} diff --git a/applications/services/bt/application.fam b/applications/services/bt/application.fam index d871029de..1ef59bd49 100644 --- a/applications/services/bt/application.fam +++ b/applications/services/bt/application.fam @@ -17,6 +17,15 @@ App( sdk_headers=["bt_service/bt.h", "bt_settings.h"], ) +App( + appid="bt_cli", + targets=["f7"], + apptype=FlipperAppType.PLUGIN, + entry_point="bt_cli_plugin_ep", + requires=["cli"], + sources=["bt_cli.c"], +) + App( appid="bt_start", apptype=FlipperAppType.STARTUP, diff --git a/applications/services/bt/bt_cli.c b/applications/services/bt/bt_cli.c index e8ba215bf..610e033bf 100644 --- a/applications/services/bt/bt_cli.c +++ b/applications/services/bt/bt_cli.c @@ -5,7 +5,7 @@ #include #include "bt_settings.h" -#include "bt_service/bt.h" +#include "bt_service/bt_i.h" #include static void bt_cli_command_hci_info(Cli* cli, FuriString* args, void* context) { @@ -181,12 +181,10 @@ static void bt_cli_print_usage() { static void bt_cli(Cli* cli, FuriString* args, void* context) { UNUSED(context); - furi_record_open(RECORD_BT); + Bt* bt = furi_record_open(RECORD_BT); FuriString* cmd; cmd = furi_string_alloc(); - BtSettings bt_settings; - bt_settings_load(&bt_settings); do { if(!args_read_string_and_trim(args, cmd)) { @@ -219,7 +217,7 @@ static void bt_cli(Cli* cli, FuriString* args, void* context) { bt_cli_print_usage(); } while(false); - if(bt_settings.enabled) { + if(bt->bt_settings.enabled) { furi_hal_bt_start_advertising(); } @@ -227,12 +225,14 @@ static void bt_cli(Cli* cli, FuriString* args, void* context) { furi_record_close(RECORD_BT); } -void bt_on_system_start() { -#ifdef SRV_CLI - Cli* cli = furi_record_open(RECORD_CLI); - cli_add_command(cli, RECORD_BT, CliCommandFlagDefault, bt_cli, NULL); - furi_record_close(RECORD_CLI); -#else - UNUSED(bt_cli); -#endif +#include + +static const FlipperAppPluginDescriptor plugin_descriptor = { + .appid = "bt_cli", + .ep_api_version = 1, + .entry_point = &bt_cli, +}; + +const FlipperAppPluginDescriptor* bt_cli_plugin_ep() { + return &plugin_descriptor; } diff --git a/applications/services/bt/bt_start.c b/applications/services/bt/bt_start.c new file mode 100644 index 000000000..52b98825d --- /dev/null +++ b/applications/services/bt/bt_start.c @@ -0,0 +1,12 @@ +#include +#include "bt_service/bt.h" + +static void bt_cli_wrapper(Cli* cli, FuriString* args, void* context) { + cli_plugin_wrapper("bt_cli", 1, cli, args, context); +} + +void bt_on_system_start() { + Cli* cli = furi_record_open(RECORD_CLI); + cli_add_command(cli, RECORD_BT, CliCommandFlagDefault, bt_cli_wrapper, NULL); + furi_record_close(RECORD_CLI); +} diff --git a/applications/services/cli/cli.c b/applications/services/cli/cli.c index e1e32222a..26e204a4c 100644 --- a/applications/services/cli/cli.c +++ b/applications/services/cli/cli.c @@ -4,6 +4,10 @@ #include #include +#include +#include +#include + #define TAG "CliSrv" #define CLI_INPUT_LEN_LIMIT 256 @@ -481,3 +485,58 @@ int32_t cli_srv(void* p) { return 0; } + +void cli_plugin_wrapper( + const char* handler_name, + uint32_t handler_version, + Cli* cli, + FuriString* args, + void* context) { + Storage* storage = furi_record_open(RECORD_STORAGE); + FlipperApplication* plugin_app = flipper_application_alloc(storage, firmware_api_interface); + do { + FuriString* full_handler_path = + furi_string_alloc_printf(EXT_PATH("apps_data/cli/plugins/%s.fal"), handler_name); + FlipperApplicationPreloadStatus preload_res = + flipper_application_preload(plugin_app, furi_string_get_cstr(full_handler_path)); + furi_string_free(full_handler_path); + + if(preload_res != FlipperApplicationPreloadStatusSuccess) { + printf("Failed to preload CLI plugin. Code: %d\r\n", preload_res); + break; + } + + if(!flipper_application_is_plugin(plugin_app)) { + printf("CLI plugin file is not a library\r\n"); + break; + } + + FlipperApplicationLoadStatus load_status = flipper_application_map_to_memory(plugin_app); + if(load_status != FlipperApplicationLoadStatusSuccess) { + printf("Failed to load CLI plugin file. Code %d\r\n", load_status); + break; + } + + const FlipperAppPluginDescriptor* app_descriptor = + flipper_application_plugin_get_descriptor(plugin_app); + + if(strcmp(app_descriptor->appid, handler_name) != 0) { + printf("CLI plugin type doesn't match\r\n"); + break; + } + + if(app_descriptor->ep_api_version != handler_version) { + printf( + "CLI plugin version %" PRIu32 " doesn't match\r\n", + app_descriptor->ep_api_version); + break; + } + + const CliCallback handler = app_descriptor->entry_point; + + handler(cli, args, context); + + } while(false); + flipper_application_free(plugin_app); + furi_record_close(RECORD_STORAGE); +} diff --git a/applications/services/cli/cli_i.h b/applications/services/cli/cli_i.h index 858cd0c8f..cd0e50740 100644 --- a/applications/services/cli/cli_i.h +++ b/applications/services/cli/cli_i.h @@ -62,6 +62,16 @@ void cli_putc(Cli* cli, char c); void cli_stdout_callback(void* _cookie, const char* data, size_t size); +// Wraps CLI commands to load from plugin file +// Must call from CLI context, like dummy CLI command callback +// You need to setup the plugin to compile correctly separately +void cli_plugin_wrapper( + const char* handler_name, + uint32_t handler_version, + Cli* cli, + FuriString* args, + void* context); + #ifdef __cplusplus } #endif \ No newline at end of file diff --git a/applications/services/crypto/application.fam b/applications/services/crypto/application.fam index 7771c5ed2..9a45c27db 100644 --- a/applications/services/crypto/application.fam +++ b/applications/services/crypto/application.fam @@ -1,6 +1,16 @@ +App( + appid="crypto_cli", + targets=["f7"], + apptype=FlipperAppType.PLUGIN, + entry_point="crypto_cli_plugin_ep", + requires=["cli"], + sources=["crypto_cli.c"], +) + App( appid="crypto_start", apptype=FlipperAppType.STARTUP, entry_point="crypto_on_system_start", + sources=["crypto_start.c"], order=10, ) diff --git a/applications/services/crypto/crypto_cli.c b/applications/services/crypto/crypto_cli.c index 128ee636b..1d55aca12 100644 --- a/applications/services/crypto/crypto_cli.c +++ b/applications/services/crypto/crypto_cli.c @@ -316,12 +316,14 @@ static void crypto_cli(Cli* cli, FuriString* args, void* context) { furi_string_free(cmd); } -void crypto_on_system_start() { -#ifdef SRV_CLI - Cli* cli = furi_record_open(RECORD_CLI); - cli_add_command(cli, "crypto", CliCommandFlagDefault, crypto_cli, NULL); - furi_record_close(RECORD_CLI); -#else - UNUSED(crypto_cli); -#endif +#include + +static const FlipperAppPluginDescriptor plugin_descriptor = { + .appid = "crypto_cli", + .ep_api_version = 1, + .entry_point = &crypto_cli, +}; + +const FlipperAppPluginDescriptor* crypto_cli_plugin_ep() { + return &plugin_descriptor; } diff --git a/applications/services/crypto/crypto_start.c b/applications/services/crypto/crypto_start.c new file mode 100644 index 000000000..f78bc9df0 --- /dev/null +++ b/applications/services/crypto/crypto_start.c @@ -0,0 +1,11 @@ +#include + +static void crypto_cli_wrapper(Cli* cli, FuriString* args, void* context) { + cli_plugin_wrapper("crypto_cli", 1, cli, args, context); +} + +void crypto_on_system_start() { + Cli* cli = furi_record_open(RECORD_CLI); + cli_add_command(cli, "crypto", CliCommandFlagDefault, crypto_cli_wrapper, NULL); + furi_record_close(RECORD_CLI); +} diff --git a/applications/services/gui/view_dispatcher.h b/applications/services/gui/view_dispatcher.h index 67a3fc40b..bec15f6e3 100644 --- a/applications/services/gui/view_dispatcher.h +++ b/applications/services/gui/view_dispatcher.h @@ -1,6 +1,8 @@ /** * @file view_dispatcher.h - * GUI: ViewDispatcher API + * @brief GUI: ViewDispatcher API + * + * @warning Views added to a ViewDispatcher MUST NOT be in a ViewStack at the same time. */ #pragma once diff --git a/applications/services/gui/view_holder.h b/applications/services/gui/view_holder.h index 8e7db3b85..0bd29652c 100644 --- a/applications/services/gui/view_holder.h +++ b/applications/services/gui/view_holder.h @@ -1,3 +1,9 @@ +/** + * @file view_holder.h + * @brief GUI: ViewHolder API + * + * @warning View added to a ViewHolder MUST NOT be in a ViewStack at the same time. + */ #pragma once #include diff --git a/applications/services/gui/view_stack.h b/applications/services/gui/view_stack.h index ebe65ab88..5cfcbc5ab 100644 --- a/applications/services/gui/view_stack.h +++ b/applications/services/gui/view_stack.h @@ -1,11 +1,13 @@ /** * @file view_stack.h - * GUI: ViewStack API + * @brief GUI: ViewStack API * * ViewStack accumulates several Views in one stack. * Draw callbacks are called sequentially starting from * first added. Input callbacks are called in reverse order. * Consumed input is not passed on underlying layers. + * + * @warning Views added to a ViewStack MUST NOT be in a ViewDispatcher or a ViewHolder at the same time. */ #pragma once diff --git a/applications/services/input/application.fam b/applications/services/input/application.fam index d344fc350..f4df7c109 100644 --- a/applications/services/input/application.fam +++ b/applications/services/input/application.fam @@ -8,3 +8,12 @@ App( order=80, sdk_headers=["input.h"], ) + +App( + appid="input_cli", + targets=["f7"], + apptype=FlipperAppType.PLUGIN, + entry_point="input_cli_plugin_ep", + requires=["cli"], + sources=["input_cli.c"], +) diff --git a/applications/services/input/input.c b/applications/services/input/input.c index 5f5872504..105fac008 100644 --- a/applications/services/input/input.c +++ b/applications/services/input/input.c @@ -54,6 +54,12 @@ const char* input_get_type_name(InputType type) { } } +#include + +static void input_cli_wrapper(Cli* cli, FuriString* args, void* context) { + cli_plugin_wrapper("input_cli", 1, cli, args, context); +} + int32_t input_srv(void* p) { UNUSED(p); input = malloc(sizeof(Input)); @@ -69,7 +75,9 @@ int32_t input_srv(void* p) { #ifdef SRV_CLI input->cli = furi_record_open(RECORD_CLI); - cli_add_command(input->cli, "input", CliCommandFlagParallelSafe, input_cli, input); + cli_add_command(input->cli, "input", CliCommandFlagParallelSafe, input_cli_wrapper, input); +#else + UNUSED(input_cli_wrapper); #endif input->pin_states = malloc(input_pins_count * sizeof(InputPinState)); diff --git a/applications/services/input/input_cli.c b/applications/services/input/input_cli.c index c625532e3..007b104b3 100644 --- a/applications/services/input/input_cli.c +++ b/applications/services/input/input_cli.c @@ -222,3 +222,15 @@ void input_cli(Cli* cli, FuriString* args, void* context) { furi_string_free(cmd); } + +#include + +static const FlipperAppPluginDescriptor plugin_descriptor = { + .appid = "input_cli", + .ep_api_version = 1, + .entry_point = &input_cli, +}; + +const FlipperAppPluginDescriptor* input_cli_plugin_ep() { + return &plugin_descriptor; +} diff --git a/applications/services/loader/application.fam b/applications/services/loader/application.fam index f4d006e07..b3035dee4 100644 --- a/applications/services/loader/application.fam +++ b/applications/services/loader/application.fam @@ -14,6 +14,15 @@ App( ], ) +App( + appid="loader_cli", + targets=["f7"], + apptype=FlipperAppType.PLUGIN, + entry_point="loader_cli_plugin_ep", + requires=["cli"], + sources=["loader_cli.c"], +) + App( appid="loader_start", apptype=FlipperAppType.STARTUP, diff --git a/applications/services/loader/loader_cli.c b/applications/services/loader/loader_cli.c index 17f0319e2..775e36536 100644 --- a/applications/services/loader/loader_cli.c +++ b/applications/services/loader/loader_cli.c @@ -104,12 +104,14 @@ static void loader_cli(Cli* cli, FuriString* args, void* context) { furi_record_close(RECORD_LOADER); } -void loader_on_system_start() { -#ifdef SRV_CLI - Cli* cli = furi_record_open(RECORD_CLI); - cli_add_command(cli, RECORD_LOADER, CliCommandFlagParallelSafe, loader_cli, NULL); - furi_record_close(RECORD_CLI); -#else - UNUSED(loader_cli); -#endif +#include + +static const FlipperAppPluginDescriptor plugin_descriptor = { + .appid = "loader_cli", + .ep_api_version = 1, + .entry_point = &loader_cli, +}; + +const FlipperAppPluginDescriptor* loader_cli_plugin_ep() { + return &plugin_descriptor; } diff --git a/applications/services/loader/loader_start.c b/applications/services/loader/loader_start.c new file mode 100644 index 000000000..7e47099d9 --- /dev/null +++ b/applications/services/loader/loader_start.c @@ -0,0 +1,12 @@ +#include +#include "loader.h" + +static void loader_cli_wrapper(Cli* cli, FuriString* args, void* context) { + cli_plugin_wrapper("loader_cli", 1, cli, args, context); +} + +void loader_on_system_start() { + Cli* cli = furi_record_open(RECORD_CLI); + cli_add_command(cli, RECORD_LOADER, CliCommandFlagParallelSafe, loader_cli_wrapper, NULL); + furi_record_close(RECORD_CLI); +} diff --git a/applications/services/power/application.fam b/applications/services/power/application.fam index d390ab965..6514e41b3 100644 --- a/applications/services/power/application.fam +++ b/applications/services/power/application.fam @@ -17,6 +17,15 @@ App( sdk_headers=["power_service/power.h", "power_settings.h"], ) +App( + appid="power_cli", + targets=["f7"], + apptype=FlipperAppType.PLUGIN, + entry_point="power_cli_plugin_ep", + requires=["cli"], + sources=["power_cli.c"], +) + App( appid="power_start", apptype=FlipperAppType.STARTUP, diff --git a/applications/services/power/power_cli.c b/applications/services/power/power_cli.c index 021ce3553..2e7dabc79 100644 --- a/applications/services/power/power_cli.c +++ b/applications/services/power/power_cli.c @@ -106,14 +106,14 @@ void power_cli(Cli* cli, FuriString* args, void* context) { furi_string_free(cmd); } -void power_on_system_start() { -#ifdef SRV_CLI - Cli* cli = furi_record_open(RECORD_CLI); +#include - cli_add_command(cli, "power", CliCommandFlagParallelSafe, power_cli, NULL); +static const FlipperAppPluginDescriptor plugin_descriptor = { + .appid = "power_cli", + .ep_api_version = 1, + .entry_point = &power_cli, +}; - furi_record_close(RECORD_CLI); -#else - UNUSED(power_cli); -#endif +const FlipperAppPluginDescriptor* power_cli_plugin_ep() { + return &plugin_descriptor; } diff --git a/applications/services/power/power_start.c b/applications/services/power/power_start.c new file mode 100644 index 000000000..3ddb5ba78 --- /dev/null +++ b/applications/services/power/power_start.c @@ -0,0 +1,11 @@ +#include + +static void power_cli_wrapper(Cli* cli, FuriString* args, void* context) { + cli_plugin_wrapper("power_cli", 1, cli, args, context); +} + +void power_on_system_start() { + Cli* cli = furi_record_open(RECORD_CLI); + cli_add_command(cli, "power", CliCommandFlagParallelSafe, power_cli_wrapper, NULL); + furi_record_close(RECORD_CLI); +} diff --git a/applications/services/rpc/rpc.c b/applications/services/rpc/rpc.c index 9f9a2a8dd..15a133818 100644 --- a/applications/services/rpc/rpc.c +++ b/applications/services/rpc/rpc.c @@ -193,8 +193,6 @@ bool rpc_pb_stream_read(pb_istream_t* istream, pb_byte_t* buf, size_t count) { furi_assert(session); furi_assert(istream->bytes_left); - /* TODO FL-3768 this function may be called after - marking the worker for termination */ if(session->terminate) { return false; } diff --git a/applications/system/findmy/findmy.c b/applications/system/findmy/findmy.c index b51343ce1..7bb10f6b7 100644 --- a/applications/system/findmy/findmy.c +++ b/applications/system/findmy/findmy.c @@ -53,7 +53,7 @@ static FindMy* findmy_app_alloc() { findmy_main_update_active(app->findmy_main, furi_hal_bt_extra_beacon_is_active()); findmy_main_update_interval(app->findmy_main, app->state.broadcast_interval); - findmy_main_update_type(app->findmy_main, findmy_data_get_type(app->state.data)); + findmy_main_update_type(app->findmy_main, app->state.tag_type); return app; } @@ -141,16 +141,19 @@ void findmy_toggle_beacon(FindMy* app) { findmy_main_update_active(app->findmy_main, furi_hal_bt_extra_beacon_is_active()); } -FindMyType findmy_data_get_type(uint8_t data[EXTRA_BEACON_MAX_DATA_SIZE]) { - if(data[0] == 0x1E && // Length - data[1] == 0xFF && // Manufacturer Specific Data - data[2] == 0x4C && // Company ID (Apple, Inc.) - data[3] == 0x00 && // ... - data[4] == 0x12 && // Type (FindMy) - data[5] == 0x19 // Length - ) { - return FindMyTypeApple; - } else { - return FindMyTypeSamsung; +void findmy_set_tag_type(FindMy* app, FindMyType type) { + app->state.tag_type = type; + findmy_state_sync_config(&app->state); + findmy_state_save(&app->state); + findmy_main_update_type(app->findmy_main, type); + FURI_LOG_I("TagType2", "Tag Type: %d", type); +} + +void furi_hal_bt_reverse_mac_addr(uint8_t mac_addr[GAP_MAC_ADDR_SIZE]) { + uint8_t tmp; + for(size_t i = 0; i < GAP_MAC_ADDR_SIZE / 2; i++) { + tmp = mac_addr[i]; + mac_addr[i] = mac_addr[GAP_MAC_ADDR_SIZE - 1 - i]; + mac_addr[GAP_MAC_ADDR_SIZE - 1 - i] = tmp; } } \ No newline at end of file diff --git a/applications/system/findmy/findmy.h b/applications/system/findmy/findmy.h index a5135f2d7..344882ef1 100644 --- a/applications/system/findmy/findmy.h +++ b/applications/system/findmy/findmy.h @@ -1,5 +1,3 @@ #pragma once typedef struct FindMy FindMy; - -typedef enum FindMyType FindMyType; \ No newline at end of file diff --git a/applications/system/findmy/findmy_i.h b/applications/system/findmy/findmy_i.h index e008d30b3..8f0920157 100644 --- a/applications/system/findmy/findmy_i.h +++ b/applications/system/findmy/findmy_i.h @@ -20,6 +20,9 @@ #include #include "scenes/findmy_scene.h" #include "helpers/base64.h" +#if FW_ORIGIN_Official +void furi_hal_bt_reverse_mac_addr(uint8_t mac_addr[GAP_MAC_ADDR_SIZE]); +#endif struct FindMy { Gui* gui; @@ -46,12 +49,7 @@ typedef enum { FindMyViewPopup, } FindMyView; -enum FindMyType { - FindMyTypeApple, - FindMyTypeSamsung, -}; - void findmy_change_broadcast_interval(FindMy* app, uint8_t value); void findmy_change_transmit_power(FindMy* app, uint8_t value); +void findmy_set_tag_type(FindMy* app, FindMyType type); void findmy_toggle_beacon(FindMy* app); -FindMyType findmy_data_get_type(uint8_t data[EXTRA_BEACON_MAX_DATA_SIZE]); diff --git a/applications/system/findmy/findmy_state.c b/applications/system/findmy/findmy_state.c index 12e8cbed2..5528080b0 100644 --- a/applications/system/findmy/findmy_state.c +++ b/applications/system/findmy/findmy_state.c @@ -29,9 +29,18 @@ bool findmy_state_load(FindMyState* out_state) { if(!flipper_format_read_uint32(file, "transmit_power", &tmp, 1)) break; state.transmit_power = tmp; + if(!flipper_format_read_uint32(file, "tag_type", &tmp, 1)) { + // Support migrating from old config + tmp = FindMyTypeApple; + flipper_format_rewind(file); + } + state.tag_type = tmp; + if(!flipper_format_read_hex(file, "mac", state.mac, sizeof(state.mac))) break; - if(!flipper_format_read_hex(file, "data", state.data, sizeof(state.data))) break; + if(!flipper_format_read_hex( + file, "data", state.data, findmy_state_data_size(state.tag_type))) + break; loaded_from_file = true; } while(0); @@ -45,6 +54,8 @@ bool findmy_state_load(FindMyState* out_state) { state.broadcast_interval = 5; state.transmit_power = 6; + state.tag_type = FindMyTypeApple; + // Set default mac uint8_t default_mac[EXTRA_BEACON_MAC_ADDR_SIZE] = {0x66, 0x55, 0x44, 0x33, 0x22, 0x11}; memcpy(state.mac, default_mac, sizeof(state.mac)); @@ -88,7 +99,8 @@ void findmy_state_apply(FindMyState* state) { furi_check(furi_hal_bt_extra_beacon_set_config(&state->config)); - furi_check(furi_hal_bt_extra_beacon_set_data(state->data, sizeof(state->data))); + furi_check( + furi_hal_bt_extra_beacon_set_data(state->data, findmy_state_data_size(state->tag_type))); if(state->beacon_active) { furi_check(furi_hal_bt_extra_beacon_start()); @@ -120,11 +132,28 @@ void findmy_state_save(FindMyState* state) { tmp = state->transmit_power; if(!flipper_format_write_uint32(file, "transmit_power", &tmp, 1)) break; + tmp = state->tag_type; + if(!flipper_format_write_uint32(file, "tag_type", &tmp, 1)) break; + if(!flipper_format_write_hex(file, "mac", state->mac, sizeof(state->mac))) break; - if(!flipper_format_write_hex(file, "data", state->data, sizeof(state->data))) break; + if(!flipper_format_write_hex( + file, "data", state->data, findmy_state_data_size(state->tag_type))) + break; } while(0); flipper_format_free(file); furi_record_close(RECORD_STORAGE); } + +uint8_t findmy_state_data_size(FindMyType type) { + switch(type) { + case FindMyTypeApple: + case FindMyTypeSamsung: + return 31; + case FindMyTypeTile: + return 21; + default: + return 0; + } +} diff --git a/applications/system/findmy/findmy_state.h b/applications/system/findmy/findmy_state.h index d11313e58..4b25ffabb 100644 --- a/applications/system/findmy/findmy_state.h +++ b/applications/system/findmy/findmy_state.h @@ -7,6 +7,12 @@ #define FINDMY_STATE_DIR EXT_PATH("apps_data/findmy") #define FINDMY_STATE_PATH FINDMY_STATE_DIR "/findmy_state.txt" +typedef enum { + FindMyTypeApple, + FindMyTypeSamsung, + FindMyTypeTile, +} FindMyType; + typedef struct { bool beacon_active; uint8_t broadcast_interval; @@ -14,6 +20,7 @@ typedef struct { uint8_t mac[EXTRA_BEACON_MAC_ADDR_SIZE]; uint8_t data[EXTRA_BEACON_MAX_DATA_SIZE]; + FindMyType tag_type; // Generated from the other state values GapExtraBeaconConfig config; @@ -26,3 +33,5 @@ void findmy_state_apply(FindMyState* state); void findmy_state_sync_config(FindMyState* state); void findmy_state_save(FindMyState* state); + +uint8_t findmy_state_data_size(FindMyType type); diff --git a/applications/system/findmy/generate_keys.py b/applications/system/findmy/generate_keys.py index 83ca274fd..e0e0282d9 100644 --- a/applications/system/findmy/generate_keys.py +++ b/applications/system/findmy/generate_keys.py @@ -73,11 +73,7 @@ def main(): s256_b64 = base64.b64encode(public_key_hash.finalize()).decode("ascii") if "/" not in s256_b64[:7]: - fname = ( - f"{prefix}_{s256_b64[:7]}.keys" - if prefix - else f"{s256_b64[:7]}.keys" - ) + fname = f"{prefix}_{mac}.keys" if prefix else f"{mac}.keys" print(f"{i + 1})") print("Private key (Base64):", private_key_b64) @@ -95,8 +91,9 @@ def main(): print("Payload:", payload) print() print( - "Place the .keys file onto your Flipper or input the MAC and Payload manually." + "Place the .keys file onto your Flipper in the Apps_Data->FindMyFlipper folder or input the MAC and Payload manually." ) + print() with open(f"keys/{fname}", "w") as f: f.write(f"Private key: {private_key_b64}\n") @@ -106,6 +103,8 @@ def main(): f.write(f"Public key (Hex): {public_key_hex}\n") f.write(f"MAC: {mac}\n") f.write(f"Payload: {payload}\n") + print("Keys file saved to:", os.path.abspath(f"keys/{fname}")) + print() break diff --git a/applications/system/findmy/scenes/findmy_scene_config.c b/applications/system/findmy/scenes/findmy_scene_config.c index eba1a85a2..13c671c8d 100644 --- a/applications/system/findmy/scenes/findmy_scene_config.c +++ b/applications/system/findmy/scenes/findmy_scene_config.c @@ -3,8 +3,7 @@ enum VarItemListIndex { VarItemListIndexBroadcastInterval, VarItemListIndexTransmitPower, - VarItemListIndexImportTagFromFile, - VarItemListIndexRegisterTagManually, + VarItemListIndexRegisterTag, VarItemListIndexAbout, }; @@ -58,9 +57,7 @@ void findmy_scene_config_on_enter(void* context) { snprintf(power_str, sizeof(power_str), "%ddBm", app->state.transmit_power); variable_item_set_current_value_text(item, power_str); - item = variable_item_list_add(var_item_list, "Import Tag From File", 0, NULL, NULL); - - item = variable_item_list_add(var_item_list, "Register Tag Manually", 0, NULL, NULL); + item = variable_item_list_add(var_item_list, "Register Tag", 0, NULL, NULL); item = variable_item_list_add( var_item_list, @@ -86,11 +83,8 @@ bool findmy_scene_config_on_event(void* context, SceneManagerEvent event) { scene_manager_set_scene_state(app->scene_manager, FindMySceneConfig, event.event); consumed = true; switch(event.event) { - case VarItemListIndexImportTagFromFile: - scene_manager_next_scene(app->scene_manager, FindMySceneConfigImport); - break; - case VarItemListIndexRegisterTagManually: - scene_manager_next_scene(app->scene_manager, FindMySceneConfigMac); + case VarItemListIndexRegisterTag: + scene_manager_next_scene(app->scene_manager, FindMySceneConfigTagtype); break; case VarItemListIndexAbout: break; diff --git a/applications/system/findmy/scenes/findmy_scene_config_import.c b/applications/system/findmy/scenes/findmy_scene_config_import.c index 798c1af44..d7cc3d7e3 100644 --- a/applications/system/findmy/scenes/findmy_scene_config_import.c +++ b/applications/system/findmy/scenes/findmy_scene_config_import.c @@ -3,6 +3,7 @@ enum VarItemListIndex { VarItemListIndexNrfConnect, VarItemListIndexOpenHaystack, + VarItemListIndexRegisterTagManually, }; static const char* parse_nrf_connect(FindMy* app, const char* path) { @@ -42,10 +43,15 @@ static const char* parse_nrf_connect(FindMy* app, const char* path) { furi_string_trim(line); error = "Wrong payload size"; - uint8_t data[EXTRA_BEACON_MAX_DATA_SIZE]; - if(furi_string_size(line) != sizeof(data) * 2) break; + size_t line_size = furi_string_size(line); + uint8_t data_size = findmy_state_data_size(app->state.tag_type); + FURI_LOG_I("ImportPayload", "Line Size: %d", line_size); + FURI_LOG_I("ImportPayload", "Data Size: %d", data_size * 2); + if(line_size != data_size * 2) break; + // Initialize full data to 0's, then fill only first data_size bytes + uint8_t data[EXTRA_BEACON_MAX_DATA_SIZE] = {0}; error = NULL; - for(size_t i = 0; i < sizeof(data); i++) { + for(size_t i = 0; i < data_size; i++) { char a = furi_string_get_char(line, i * 2); char b = furi_string_get_char(line, i * 2 + 1); if((a < 'A' && a > 'F') || (a < '0' && a > '9') || (b < 'A' && b > 'F') || @@ -151,6 +157,8 @@ void findmy_scene_config_import_on_enter(void* context) { item = variable_item_list_add(var_item_list, "OpenHaystack (.keys)", 0, NULL, NULL); + item = variable_item_list_add(var_item_list, "Register Tag Manually", 0, NULL, NULL); + // This scene acts more like a submenu than a var item list tbh UNUSED(item); @@ -178,6 +186,9 @@ bool findmy_scene_config_import_on_event(void* context, SceneManagerEvent event) case VarItemListIndexOpenHaystack: extension = ".keys"; break; + case VarItemListIndexRegisterTagManually: + scene_manager_next_scene(app->scene_manager, FindMySceneConfigMac); + break; default: break; } diff --git a/applications/system/findmy/scenes/findmy_scene_config_packet.c b/applications/system/findmy/scenes/findmy_scene_config_packet.c index 9d77fb1d7..80f23af98 100644 --- a/applications/system/findmy/scenes/findmy_scene_config_packet.c +++ b/applications/system/findmy/scenes/findmy_scene_config_packet.c @@ -16,7 +16,7 @@ void findmy_scene_config_packet_on_enter(void* context) { byte_input_set_header_text(byte_input, "Enter Bluetooth Payload:"); - memcpy(app->packet_buf, app->state.data, sizeof(app->packet_buf)); + memcpy(app->packet_buf, app->state.data, findmy_state_data_size(app->state.tag_type)); byte_input_set_result_callback( byte_input, @@ -24,7 +24,7 @@ void findmy_scene_config_packet_on_enter(void* context) { NULL, app, app->packet_buf, - sizeof(app->packet_buf)); + findmy_state_data_size(app->state.tag_type)); view_dispatcher_switch_to_view(app->view_dispatcher, FindMyViewByteInput); } @@ -39,11 +39,10 @@ bool findmy_scene_config_packet_on_event(void* context, SceneManagerEvent event) case ByteInputResultOk: scene_manager_search_and_switch_to_previous_scene( app->scene_manager, FindMySceneConfig); - memcpy(app->state.data, app->packet_buf, sizeof(app->state.data)); + memcpy(app->state.data, app->packet_buf, findmy_state_data_size(app->state.tag_type)); findmy_state_save(&app->state); - furi_check( - furi_hal_bt_extra_beacon_set_data(app->state.data, sizeof(app->state.data))); - findmy_main_update_type(app->findmy_main, findmy_data_get_type(app->state.data)); + furi_check(furi_hal_bt_extra_beacon_set_data( + app->state.data, findmy_state_data_size(app->state.tag_type))); break; default: break; diff --git a/applications/system/findmy/scenes/findmy_scene_config_tagtype.c b/applications/system/findmy/scenes/findmy_scene_config_tagtype.c new file mode 100644 index 000000000..e43eea7f8 --- /dev/null +++ b/applications/system/findmy/scenes/findmy_scene_config_tagtype.c @@ -0,0 +1,70 @@ +#include "../findmy_i.h" + +enum VarItemListIndex { + VarItemListIndexApple, + VarItemListIndexSamsung, + VarItemListIndexTile, +}; + +void findmy_scene_config_tagtype_callback(void* context, uint32_t index) { + furi_assert(context); + FindMy* app = context; + view_dispatcher_send_custom_event(app->view_dispatcher, index); +} + +void findmy_scene_config_tagtype_on_enter(void* context) { + FindMy* app = context; + VariableItemList* var_item_list = app->var_item_list; + VariableItem* item; + + variable_item_list_set_header(var_item_list, "Choose tag type"); + + item = variable_item_list_add(var_item_list, "Apple AirTag", 0, NULL, NULL); + + item = variable_item_list_add(var_item_list, "Samsung SmartTag", 0, NULL, NULL); + + item = variable_item_list_add(var_item_list, "Tile SmartTag", 0, NULL, NULL); + + UNUSED(item); + + variable_item_list_set_enter_callback( + var_item_list, findmy_scene_config_tagtype_callback, app); + + variable_item_list_set_selected_item( + var_item_list, scene_manager_get_scene_state(app->scene_manager, FindMySceneConfigImport)); + view_dispatcher_switch_to_view(app->view_dispatcher, FindMyViewVarItemList); +} + +bool findmy_scene_config_tagtype_on_event(void* context, SceneManagerEvent event) { + FindMy* app = context; + bool consumed = false; + + if(event.type == SceneManagerEventTypeCustom) { + scene_manager_set_scene_state(app->scene_manager, FindMySceneConfigTagtype, event.event); + consumed = true; + + switch(event.event) { + case VarItemListIndexApple: + findmy_set_tag_type(app, FindMyTypeApple); + break; + case VarItemListIndexSamsung: + findmy_set_tag_type(app, FindMyTypeSamsung); + break; + case VarItemListIndexTile: + findmy_set_tag_type(app, FindMyTypeTile); + break; + default: + break; + } + scene_manager_next_scene(app->scene_manager, FindMySceneConfigImport); + } + + return consumed; +} + +void findmy_scene_config_tagtype_on_exit(void* context) { + FindMy* app = context; + VariableItemList* var_item_list = app->var_item_list; + + variable_item_list_reset(var_item_list); +} \ No newline at end of file diff --git a/applications/system/findmy/scenes/findmy_scenes.h b/applications/system/findmy/scenes/findmy_scenes.h index 9a35c519d..0680e2c5f 100644 --- a/applications/system/findmy/scenes/findmy_scenes.h +++ b/applications/system/findmy/scenes/findmy_scenes.h @@ -1,6 +1,7 @@ ADD_SCENE(findmy, main, Main) ADD_SCENE(findmy, config, Config) ADD_SCENE(findmy, config_import, ConfigImport) +ADD_SCENE(findmy, config_tagtype, ConfigTagtype) ADD_SCENE(findmy, config_import_result, ConfigImportResult) ADD_SCENE(findmy, config_mac, ConfigMac) ADD_SCENE(findmy, config_packet, ConfigPacket) diff --git a/applications/system/findmy/views/findmy_main.c b/applications/system/findmy/views/findmy_main.c index b39adc2bf..829088be7 100644 --- a/applications/system/findmy/views/findmy_main.c +++ b/applications/system/findmy/views/findmy_main.c @@ -34,18 +34,22 @@ static void findmy_main_draw_callback(Canvas* canvas, void* _model) { snprintf(interval_str, sizeof(interval_str), "Ping Interval: %ds", model->interval); canvas_draw_str(canvas, 4, 62, interval_str); canvas_set_font(canvas, FontPrimary); + const char* network_text = ""; switch(model->type) { case FindMyTypeApple: - canvas_draw_str(canvas, 4, 32, "Apple Network"); - canvas_draw_icon(canvas, 80, 24, &I_Lock_7x8); + network_text = "Apple Network"; break; case FindMyTypeSamsung: - canvas_draw_str(canvas, 4, 32, "Samsung Network"); - canvas_draw_icon(canvas, 97, 24, &I_Lock_7x8); + network_text = "Samsung Network"; + break; + case FindMyTypeTile: + network_text = "Tile Network"; break; default: break; } + canvas_draw_str(canvas, 4, 32, network_text); + canvas_draw_icon(canvas, 6 + canvas_string_width(canvas, network_text), 24, &I_Lock_7x8); canvas_set_font(canvas, FontSecondary); canvas_draw_str(canvas, 100, 61, "Config"); canvas_draw_line(canvas, 100, 51, 127, 51); @@ -103,7 +107,7 @@ FindMyMain* findmy_main_alloc(FindMy* app) { { model->active = app->state.beacon_active; model->interval = app->state.broadcast_interval; - model->type = findmy_data_get_type(app->state.data); + model->type = app->state.tag_type; }, false); view_set_context(findmy_main->view, findmy_main); diff --git a/applications/system/findmy/views/findmy_main.h b/applications/system/findmy/views/findmy_main.h index 92a9170ec..d73040ee2 100644 --- a/applications/system/findmy/views/findmy_main.h +++ b/applications/system/findmy/views/findmy_main.h @@ -1,6 +1,7 @@ #pragma once #include "../findmy.h" +#include "../findmy_state.h" #include typedef enum { diff --git a/applications/system/js_app/application.fam b/applications/system/js_app/application.fam index 1da65ee1d..67931216f 100644 --- a/applications/system/js_app/application.fam +++ b/applications/system/js_app/application.fam @@ -94,6 +94,7 @@ App( requires=["js_app"], sources=["modules/js_keyboard.c"], ) + App( appid="js_subghz", apptype=FlipperAppType.PLUGIN, @@ -101,3 +102,11 @@ App( requires=["js_app"], sources=["modules/js_subghz/*.c"], ) + +App( + appid="js_gpio", + apptype=FlipperAppType.PLUGIN, + entry_point="js_gpio_ep", + requires=["js_app"], + sources=["modules/js_gpio.c"], +) diff --git a/applications/system/js_app/examples/apps/Scripts/dialog.js b/applications/system/js_app/examples/apps/Scripts/dialog.js index 9fc44f8b9..4c5b0af20 100644 --- a/applications/system/js_app/examples/apps/Scripts/dialog.js +++ b/applications/system/js_app/examples/apps/Scripts/dialog.js @@ -7,13 +7,16 @@ let dialog_params = ({ header: "Test_header", text: "Test_text", button_left: "Left", - button_right: "Right", + button_right: "Files", button_center: "OK" }); let result2 = dialog.custom(dialog_params); if (result2 === "") { print("Back is pressed"); +} else if (result2 === "Files") { + let result3 = dialog.pickFile("/ext", "*"); + print("Selected", result3); } else { print(result2, "is pressed"); } diff --git a/applications/system/js_app/examples/apps/Scripts/gpio.js b/applications/system/js_app/examples/apps/Scripts/gpio.js new file mode 100644 index 000000000..02b55a3ad --- /dev/null +++ b/applications/system/js_app/examples/apps/Scripts/gpio.js @@ -0,0 +1,62 @@ +let gpio = require("gpio"); + +// initialize pins +gpio.init("PC3", "outputPushPull", "up"); // pin, mode, pull +print("PC3 is initialized as outputPushPull with pull-up"); + +gpio.init("PC1", "input", "down"); // pin, mode, pull +print("PC1 is initialized as input with pull-down"); + +// let led on PC3 blink +gpio.write("PC3", true); // high +delay(1000); +gpio.write("PC3", false); // low +delay(1000); +gpio.write("PC3", true); // high +delay(1000); +gpio.write("PC3", false); // low + +// read value from PC1 and write it to PC3 +while (true) { + let value = gpio.read("PC1"); + gpio.write("PC3", value); + + value ? print("PC1 is high") : print("PC1 is low"); + + delay(100); +} + + +// possible pins https://docs.flipper.net/gpio-and-modules#miFsS +// "PA7" aka 2 +// "PA6" aka 3 +// "PA4" aka 4 +// "PB3" aka 5 +// "PB2" aka 6 +// "PC3" aka 7 +// "PA14" aka 10 +// "PA13" aka 12 +// "PB6" aka 13 +// "PB7" aka 14 +// "PC1" aka 15 +// "PC0" aka 16 +// "PB14" aka 17 + +// possible modes +// "input" +// "outputPushPull" +// "outputOpenDrain" +// "altFunctionPushPull" +// "altFunctionOpenDrain" +// "analog" +// "interruptRise" +// "interruptFall" +// "interruptRiseFall" +// "eventRise" +// "eventFall" +// "eventRiseFall" + +// possible pull +// "no" +// "up" +// "down" \ No newline at end of file diff --git a/applications/system/js_app/examples/apps/Scripts/storage.js b/applications/system/js_app/examples/apps/Scripts/storage.js index c469688e0..c19f0f003 100644 --- a/applications/system/js_app/examples/apps/Scripts/storage.js +++ b/applications/system/js_app/examples/apps/Scripts/storage.js @@ -4,10 +4,13 @@ let path = "/ext/storage.test"; print("File exists:", storage.exists(path)); print("Writing..."); -storage.write(path, "Hello World!"); +storage.write(path, "Hello "); print("File exists:", storage.exists(path)); +// Append will create the file even if it doesnt exist! +storage.append(path, "World!"); + print("Reading..."); let data = storage.read(path); print(data); diff --git a/applications/system/js_app/modules/js_dialog.c b/applications/system/js_app/modules/js_dialog.c index 34de6d641..1de1d9069 100644 --- a/applications/system/js_app/modules/js_dialog.c +++ b/applications/system/js_app/modules/js_dialog.c @@ -1,6 +1,7 @@ #include #include "../js_modules.h" #include +#include static bool js_dialog_msg_parse_params(struct mjs* mjs, const char** hdr, const char** msg) { size_t num_args = mjs_nargs(mjs); @@ -128,10 +129,62 @@ static void js_dialog_custom(struct mjs* mjs) { } } +static void js_dialog_pick_file(struct mjs* mjs) { + if(mjs_nargs(mjs) != 2) { + mjs_prepend_errorf(mjs, MJS_BAD_ARGS_ERROR, "Wrong arguments"); + mjs_return(mjs, MJS_UNDEFINED); + return; + } + + mjs_val_t base_path_obj = mjs_arg(mjs, 0); + if(!mjs_is_string(base_path_obj)) { + mjs_prepend_errorf(mjs, MJS_BAD_ARGS_ERROR, "Base path must be a string"); + mjs_return(mjs, MJS_UNDEFINED); + return; + } + size_t base_path_len = 0; + const char* base_path = mjs_get_string(mjs, &base_path_obj, &base_path_len); + if((base_path_len == 0) || (base_path == NULL)) { + mjs_prepend_errorf(mjs, MJS_BAD_ARGS_ERROR, "Bad base path argument"); + mjs_return(mjs, MJS_UNDEFINED); + return; + } + + mjs_val_t extension_obj = mjs_arg(mjs, 1); + if(!mjs_is_string(extension_obj)) { + mjs_prepend_errorf(mjs, MJS_BAD_ARGS_ERROR, "Extension must be a string"); + mjs_return(mjs, MJS_UNDEFINED); + return; + } + size_t extension_len = 0; + const char* extension = mjs_get_string(mjs, &extension_obj, &extension_len); + if((extension_len == 0) || (extension == NULL)) { + mjs_prepend_errorf(mjs, MJS_BAD_ARGS_ERROR, "Bad extension argument"); + mjs_return(mjs, MJS_UNDEFINED); + return; + } + + DialogsApp* dialogs = furi_record_open(RECORD_DIALOGS); + const DialogsFileBrowserOptions browser_options = { + .extension = extension, + .icon = &I_file_10px, + .base_path = base_path, + }; + FuriString* path = furi_string_alloc_set(base_path); + if(dialog_file_browser_show(dialogs, path, path, &browser_options)) { + mjs_return(mjs, mjs_mk_string(mjs, furi_string_get_cstr(path), ~0, true)); + } else { + mjs_return(mjs, MJS_UNDEFINED); + } + furi_string_free(path); + furi_record_close(RECORD_DIALOGS); +} + static void* js_dialog_create(struct mjs* mjs, mjs_val_t* object) { mjs_val_t dialog_obj = mjs_mk_object(mjs); mjs_set(mjs, dialog_obj, "message", ~0, MJS_MK_FN(js_dialog_message)); mjs_set(mjs, dialog_obj, "custom", ~0, MJS_MK_FN(js_dialog_custom)); + mjs_set(mjs, dialog_obj, "pickFile", ~0, MJS_MK_FN(js_dialog_pick_file)); *object = dialog_obj; return (void*)1; diff --git a/applications/system/js_app/modules/js_gpio.c b/applications/system/js_app/modules/js_gpio.c new file mode 100644 index 000000000..8f6158418 --- /dev/null +++ b/applications/system/js_app/modules/js_gpio.c @@ -0,0 +1,272 @@ +#include "../js_modules.h" +#include +#include +#include + +typedef struct { + const GpioPin* pin; + const char* name; +} GpioPinCtx; + +static const GpioPinCtx js_gpio_pins[] = { + {.pin = &gpio_ext_pa7, .name = "PA7"}, // 2 + {.pin = &gpio_ext_pa6, .name = "PA6"}, // 3 + {.pin = &gpio_ext_pa4, .name = "PA4"}, // 4 + {.pin = &gpio_ext_pb3, .name = "PB3"}, // 5 + {.pin = &gpio_ext_pb2, .name = "PB2"}, // 6 + {.pin = &gpio_ext_pc3, .name = "PC3"}, // 7 + {.pin = &gpio_swclk, .name = "PA14"}, // 10 + {.pin = &gpio_swdio, .name = "PA13"}, // 12 + {.pin = &gpio_usart_tx, .name = "PB6"}, // 13 + {.pin = &gpio_usart_rx, .name = "PB7"}, // 14 + {.pin = &gpio_ext_pc1, .name = "PC1"}, // 15 + {.pin = &gpio_ext_pc0, .name = "PC0"}, // 16 + {.pin = &gpio_ibutton, .name = "PB14"}, // 17 +}; + +bool js_gpio_get_gpio_pull(const char* pull, GpioPull* value) { + if(strcmp(pull, "no") == 0) { + *value = GpioPullNo; + return true; + } else if(strcmp(pull, "up") == 0) { + *value = GpioPullUp; + return true; + } else if(strcmp(pull, "down") == 0) { + *value = GpioPullDown; + return true; + } else { + *value = GpioPullNo; + return true; + } + return false; +} + +bool js_gpio_get_gpio_mode(const char* mode, GpioMode* value) { + if(strcmp(mode, "input") == 0) { + *value = GpioModeInput; + return true; + } else if(strcmp(mode, "outputPushPull") == 0) { + *value = GpioModeOutputPushPull; + return true; + } else if(strcmp(mode, "outputOpenDrain") == 0) { + *value = GpioModeOutputOpenDrain; + return true; + } else if(strcmp(mode, "altFunctionPushPull") == 0) { + *value = GpioModeAltFunctionPushPull; + return true; + } else if(strcmp(mode, "altFunctionOpenDrain") == 0) { + *value = GpioModeAltFunctionOpenDrain; + return true; + } else if(strcmp(mode, "analog") == 0) { + *value = GpioModeAnalog; + return true; + } else if(strcmp(mode, "interruptRise") == 0) { + *value = GpioModeInterruptRise; + return true; + } else if(strcmp(mode, "interruptFall") == 0) { + *value = GpioModeInterruptFall; + return true; + } else if(strcmp(mode, "interruptRiseFall") == 0) { + *value = GpioModeInterruptRiseFall; + return true; + } else if(strcmp(mode, "eventRise") == 0) { + *value = GpioModeEventRise; + return true; + } else if(strcmp(mode, "eventFall") == 0) { + *value = GpioModeEventFall; + return true; + } else if(strcmp(mode, "eventRiseFall") == 0) { + *value = GpioModeEventRiseFall; + return true; + } else { + return false; + } +} + +const GpioPin* js_gpio_get_gpio_pin(const char* name) { + for(size_t i = 0; i < COUNT_OF(js_gpio_pins); i++) { + if(strcmp(js_gpio_pins[i].name, name) == 0) { + return js_gpio_pins[i].pin; + } + } + return NULL; +} + +static void js_gpio_init(struct mjs* mjs) { + mjs_val_t pin_arg = mjs_arg(mjs, 0); + mjs_val_t mode_arg = mjs_arg(mjs, 1); + mjs_val_t pull_arg = mjs_arg(mjs, 2); + + if(!mjs_is_string(pin_arg)) { + mjs_prepend_errorf(mjs, MJS_BAD_ARGS_ERROR, "Argument must be a string"); + mjs_return(mjs, MJS_UNDEFINED); + return; + } + + const char* pin_name = mjs_get_string(mjs, &pin_arg, NULL); + if(!pin_name) { + mjs_prepend_errorf(mjs, MJS_BAD_ARGS_ERROR, "Failed to get pin name"); + mjs_return(mjs, MJS_UNDEFINED); + return; + } + + if(!mjs_is_string(mode_arg)) { + mjs_prepend_errorf(mjs, MJS_BAD_ARGS_ERROR, "Argument must be a string"); + mjs_return(mjs, MJS_UNDEFINED); + return; + } + + const char* mode_name = mjs_get_string(mjs, &mode_arg, NULL); + if(!mode_name) { + mjs_prepend_errorf(mjs, MJS_BAD_ARGS_ERROR, "Failed to get mode name"); + mjs_return(mjs, MJS_UNDEFINED); + return; + } + + if(!mjs_is_string(pull_arg)) { + mjs_prepend_errorf(mjs, MJS_BAD_ARGS_ERROR, "Argument must be a string"); + mjs_return(mjs, MJS_UNDEFINED); + return; + } + + const char* pull_name = mjs_get_string(mjs, &pull_arg, NULL); + if(!pull_name) { + mjs_prepend_errorf(mjs, MJS_BAD_ARGS_ERROR, "Failed to get pull name"); + mjs_return(mjs, MJS_UNDEFINED); + return; + } + + const GpioPin* gpio_pin = js_gpio_get_gpio_pin(pin_name); + if(gpio_pin == NULL) { + mjs_prepend_errorf(mjs, MJS_BAD_ARGS_ERROR, "Invalid pin name"); + mjs_return(mjs, MJS_UNDEFINED); + return; + } + + GpioMode gpio_mode; + if(!js_gpio_get_gpio_mode(mode_name, &gpio_mode)) { + mjs_prepend_errorf(mjs, MJS_BAD_ARGS_ERROR, "Invalid mode name"); + mjs_return(mjs, MJS_UNDEFINED); + return; + } + + GpioPull gpio_pull; + if(!js_gpio_get_gpio_pull(pull_name, &gpio_pull)) { + mjs_prepend_errorf(mjs, MJS_BAD_ARGS_ERROR, "Invalid pull name"); + mjs_return(mjs, MJS_UNDEFINED); + return; + } + + expansion_disable(furi_record_open(RECORD_EXPANSION)); + furi_record_close(RECORD_EXPANSION); + + furi_hal_gpio_init(gpio_pin, gpio_mode, gpio_pull, GpioSpeedVeryHigh); + + mjs_return(mjs, MJS_UNDEFINED); +} + +static void js_gpio_write(struct mjs* mjs) { + mjs_val_t pin_arg = mjs_arg(mjs, 0); + mjs_val_t value_arg = mjs_arg(mjs, 1); + + if(!mjs_is_string(pin_arg)) { + mjs_prepend_errorf(mjs, MJS_BAD_ARGS_ERROR, "Argument must be a string"); + mjs_return(mjs, MJS_UNDEFINED); + return; + } + + const char* pin_name = mjs_get_string(mjs, &pin_arg, NULL); + if(!pin_name) { + mjs_prepend_errorf(mjs, MJS_BAD_ARGS_ERROR, "Failed to get pin name"); + mjs_return(mjs, MJS_UNDEFINED); + return; + } + + if(!mjs_is_boolean(value_arg)) { + mjs_prepend_errorf(mjs, MJS_BAD_ARGS_ERROR, "Argument must be a boolean"); + mjs_return(mjs, MJS_UNDEFINED); + return; + } + + bool value = mjs_get_bool(mjs, value_arg); + + const GpioPin* gpio_pin = js_gpio_get_gpio_pin(pin_name); + + if(gpio_pin == NULL) { + mjs_prepend_errorf(mjs, MJS_BAD_ARGS_ERROR, "Invalid pin name"); + mjs_return(mjs, MJS_UNDEFINED); + return; + } + + furi_hal_gpio_write(gpio_pin, value); + + mjs_return(mjs, MJS_UNDEFINED); +} + +static void js_gpio_read(struct mjs* mjs) { + mjs_val_t pin_arg = mjs_arg(mjs, 0); + + if(!mjs_is_string(pin_arg)) { + mjs_prepend_errorf(mjs, MJS_BAD_ARGS_ERROR, "Argument must be a string"); + mjs_return(mjs, MJS_UNDEFINED); + return; + } + + const char* pin_name = mjs_get_string(mjs, &pin_arg, NULL); + if(!pin_name) { + mjs_prepend_errorf(mjs, MJS_BAD_ARGS_ERROR, "Failed to get pin name"); + mjs_return(mjs, MJS_UNDEFINED); + return; + } + + const GpioPin* gpio_pin = js_gpio_get_gpio_pin(pin_name); + + if(gpio_pin == NULL) { + mjs_prepend_errorf(mjs, MJS_BAD_ARGS_ERROR, "Invalid pin name"); + mjs_return(mjs, MJS_UNDEFINED); + return; + } + + bool value = furi_hal_gpio_read(gpio_pin); + + mjs_return(mjs, mjs_mk_boolean(mjs, value)); +} + +static void* js_gpio_create(struct mjs* mjs, mjs_val_t* object) { + mjs_val_t gpio_obj = mjs_mk_object(mjs); + mjs_set(mjs, gpio_obj, "init", ~0, MJS_MK_FN(js_gpio_init)); + mjs_set(mjs, gpio_obj, "write", ~0, MJS_MK_FN(js_gpio_write)); + mjs_set(mjs, gpio_obj, "read", ~0, MJS_MK_FN(js_gpio_read)); + *object = gpio_obj; + + return (void*)1; +} + +static void js_gpio_destroy(void* inst) { + UNUSED(inst); + + // loop through all pins and reset them to analog mode + for(size_t i = 0; i < COUNT_OF(js_gpio_pins); i++) { + furi_hal_gpio_write(js_gpio_pins[i].pin, false); + furi_hal_gpio_init(js_gpio_pins[i].pin, GpioModeAnalog, GpioPullNo, GpioSpeedVeryHigh); + } + + expansion_enable(furi_record_open(RECORD_EXPANSION)); + furi_record_close(RECORD_EXPANSION); +} + +static const JsModuleDescriptor js_gpio_desc = { + "gpio", + js_gpio_create, + js_gpio_destroy, +}; + +static const FlipperAppPluginDescriptor plugin_descriptor = { + .appid = PLUGIN_APP_ID, + .ep_api_version = PLUGIN_API_VERSION, + .entry_point = &js_gpio_desc, +}; + +const FlipperAppPluginDescriptor* js_gpio_ep(void) { + return &plugin_descriptor; +} \ No newline at end of file diff --git a/applications/system/js_app/modules/js_storage.c b/applications/system/js_app/modules/js_storage.c index 7c84887e3..717bab882 100644 --- a/applications/system/js_app/modules/js_storage.c +++ b/applications/system/js_app/modules/js_storage.c @@ -108,6 +108,35 @@ static void js_storage_write(struct mjs* mjs) { storage_file_free(file); } +static void js_storage_append(struct mjs* mjs) { + JsStorageInst* storage = get_this_ctx(mjs); + if(!check_arg_count(mjs, 2)) return; + + const char* path; + if(!get_path_arg(mjs, &path)) return; + + mjs_val_t data_obj = mjs_arg(mjs, 1); + if(!mjs_is_string(data_obj)) { + ret_bad_args(mjs, "Data must be a string"); + return; + } + size_t data_len = 0; + const char* data = mjs_get_string(mjs, &data_obj, &data_len); + if((data_len == 0) || (data == NULL)) { + ret_bad_args(mjs, "Bad data argument"); + return; + } + + File* file = storage_file_alloc(storage->api); + if(!storage_file_open(file, path, FSAM_WRITE, FSOM_OPEN_APPEND)) { + ret_int_err(mjs, storage_file_get_error_desc(file)); + } else { + size_t write = storage_file_write(file, data, data_len); + mjs_return(mjs, mjs_mk_boolean(mjs, write == data_len)); + } + storage_file_free(file); +} + static void js_storage_exists(struct mjs* mjs) { JsStorageInst* storage = get_this_ctx(mjs); if(!check_arg_count(mjs, 1)) return; @@ -194,6 +223,7 @@ static void* js_storage_create(struct mjs* mjs, mjs_val_t* object) { mjs_set(mjs, storage_obj, INST_PROP_NAME, ~0, mjs_mk_foreign(mjs, storage)); mjs_set(mjs, storage_obj, "read", ~0, MJS_MK_FN(js_storage_read)); mjs_set(mjs, storage_obj, "write", ~0, MJS_MK_FN(js_storage_write)); + mjs_set(mjs, storage_obj, "append", ~0, MJS_MK_FN(js_storage_append)); mjs_set(mjs, storage_obj, "exists", ~0, MJS_MK_FN(js_storage_exists)); mjs_set(mjs, storage_obj, "remove", ~0, MJS_MK_FN(js_storage_remove)); mjs_set(mjs, storage_obj, "virtualInit", ~0, MJS_MK_FN(js_storage_virtual_init)); diff --git a/assets/icons/Archive/file_10px.png b/assets/icons/Archive/file_10px.png new file mode 100644 index 000000000..8e8a6183d Binary files /dev/null and b/assets/icons/Archive/file_10px.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_0.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_0.png new file mode 100644 index 000000000..055618575 Binary files /dev/null and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_0.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_1.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_1.png new file mode 100644 index 000000000..8a9791cae Binary files /dev/null and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_1.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_10.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_10.png new file mode 100644 index 000000000..b266dc763 Binary files /dev/null and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_10.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_11.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_11.png new file mode 100644 index 000000000..00f572b44 Binary files /dev/null and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_11.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_12.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_12.png new file mode 100644 index 000000000..6f14b771e Binary files /dev/null and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_12.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_13.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_13.png new file mode 100644 index 000000000..11773d46e Binary files /dev/null and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_13.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_14.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_14.png new file mode 100644 index 000000000..667347940 Binary files /dev/null and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_14.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_15.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_15.png new file mode 100644 index 000000000..27e85a5f2 Binary files /dev/null and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_15.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_16.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_16.png new file mode 100644 index 000000000..2fe9d4d82 Binary files /dev/null and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_16.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_17.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_17.png new file mode 100644 index 000000000..407edc01a Binary files /dev/null and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_17.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_18.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_18.png new file mode 100644 index 000000000..1be417331 Binary files /dev/null and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_18.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_19.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_19.png new file mode 100644 index 000000000..ceb4a1f81 Binary files /dev/null and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_19.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_2.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_2.png new file mode 100644 index 000000000..befa38a39 Binary files /dev/null and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_2.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_20.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_20.png new file mode 100644 index 000000000..3d11e2682 Binary files /dev/null and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_20.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_21.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_21.png new file mode 100644 index 000000000..f9b0e6f30 Binary files /dev/null and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_21.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_22.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_22.png new file mode 100644 index 000000000..6116575d2 Binary files /dev/null and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_22.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_23.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_23.png new file mode 100644 index 000000000..65731227e Binary files /dev/null and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_23.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_24.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_24.png new file mode 100644 index 000000000..b04b01022 Binary files /dev/null and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_24.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_25.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_25.png new file mode 100644 index 000000000..11700cc86 Binary files /dev/null and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_25.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_26.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_26.png new file mode 100644 index 000000000..09f682ef0 Binary files /dev/null and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_26.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_27.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_27.png new file mode 100644 index 000000000..d94772677 Binary files /dev/null and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_27.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_28.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_28.png new file mode 100644 index 000000000..7ede5be12 Binary files /dev/null and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_28.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_29.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_29.png new file mode 100644 index 000000000..4cb438641 Binary files /dev/null and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_29.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_3.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_3.png new file mode 100644 index 000000000..cf3162f5f Binary files /dev/null and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_3.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_30.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_30.png new file mode 100644 index 000000000..b98badc41 Binary files /dev/null and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_30.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_31.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_31.png new file mode 100644 index 000000000..59a88d76b Binary files /dev/null and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_31.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_32.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_32.png new file mode 100644 index 000000000..0422eed15 Binary files /dev/null and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_32.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_33.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_33.png new file mode 100644 index 000000000..d78c42def Binary files /dev/null and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_33.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_34.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_34.png new file mode 100644 index 000000000..334c3d231 Binary files /dev/null and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_34.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_35.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_35.png new file mode 100644 index 000000000..a41323dd1 Binary files /dev/null and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_35.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_36.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_36.png new file mode 100644 index 000000000..acac70e6c Binary files /dev/null and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_36.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_37.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_37.png new file mode 100644 index 000000000..350929192 Binary files /dev/null and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_37.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_38.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_38.png new file mode 100644 index 000000000..1ee2294f8 Binary files /dev/null and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_38.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_39.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_39.png new file mode 100644 index 000000000..1b3d3773d Binary files /dev/null and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_39.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_4.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_4.png new file mode 100644 index 000000000..27804f250 Binary files /dev/null and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_4.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_5.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_5.png new file mode 100644 index 000000000..7799b20aa Binary files /dev/null and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_5.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_6.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_6.png new file mode 100644 index 000000000..7cc929236 Binary files /dev/null and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_6.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_7.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_7.png new file mode 100644 index 000000000..29f8df8f9 Binary files /dev/null and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_7.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_8.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_8.png new file mode 100644 index 000000000..926ff0911 Binary files /dev/null and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_8.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_9.png b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_9.png new file mode 100644 index 000000000..4f992440f Binary files /dev/null and b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/frame_9.png differ diff --git a/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/meta.txt b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/meta.txt new file mode 100644 index 000000000..b3fef5559 --- /dev/null +++ b/assets/packs/Momentum/Anims/Kuronons_CFW_Momentum3_128x64/meta.txt @@ -0,0 +1,15 @@ +Filetype: Flipper Animation +Version: 1 + +Width: 128 +Height: 64 +Passive frames: 16 +Active frames: 74 +Frames order: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 0 1 2 3 4 5 6 7 8 8 8 8 8 8 16 17 18 19 19 19 20 21 22 23 23 23 23 23 24 25 26 27 28 29 29 29 29 29 29 30 31 32 33 34 35 36 37 32 33 34 35 36 37 38 39 29 29 29 29 29 29 28 27 26 25 24 23 23 23 23 8 8 8 8 +Active cycles: 1 +Frame rate: 6 +Duration: 3600 +Active cooldown: 3 + +Bubble slots: 0 + diff --git a/assets/packs/Momentum/Anims/manifest.txt b/assets/packs/Momentum/Anims/manifest.txt index 70b59e015..ec928793e 100644 --- a/assets/packs/Momentum/Anims/manifest.txt +++ b/assets/packs/Momentum/Anims/manifest.txt @@ -13,4 +13,11 @@ Min butthurt: 0 Max butthurt: 18 Min level: 1 Max level: 30 +Weight: 3 + +Name: Kuronons_CFW_Momentum3_128x64 +Min butthurt: 0 +Max butthurt: 18 +Min level: 1 +Max level: 30 Weight: 3 \ No newline at end of file diff --git a/assets/packs/Momentum/Icons/Interface/Lockscreen.png b/assets/packs/Momentum/Icons/Interface/Lockscreen.png new file mode 100644 index 000000000..3c25d73e8 Binary files /dev/null and b/assets/packs/Momentum/Icons/Interface/Lockscreen.png differ diff --git a/assets/packs/Momentum/Icons/Passport/passport_bad_46x49.png b/assets/packs/Momentum/Icons/Passport/passport_bad_46x49.png new file mode 100644 index 000000000..5e27db68c Binary files /dev/null and b/assets/packs/Momentum/Icons/Passport/passport_bad_46x49.png differ diff --git a/assets/packs/Momentum/Icons/Passport/passport_happy_46x49.png b/assets/packs/Momentum/Icons/Passport/passport_happy_46x49.png new file mode 100644 index 000000000..94e70ccbc Binary files /dev/null and b/assets/packs/Momentum/Icons/Passport/passport_happy_46x49.png differ diff --git a/assets/packs/Momentum/Icons/Passport/passport_okay_46x49.png b/assets/packs/Momentum/Icons/Passport/passport_okay_46x49.png new file mode 100644 index 000000000..6d96bcc0a Binary files /dev/null and b/assets/packs/Momentum/Icons/Passport/passport_okay_46x49.png differ diff --git a/assets/packs/ReadMe.md b/assets/packs/ReadMe.md index cb4ca1ec4..bd0b03b4b 100644 --- a/assets/packs/ReadMe.md +++ b/assets/packs/ReadMe.md @@ -2,11 +2,13 @@ - **`Momentum`** - Credits: - [Kuronons](https://github.com/Kuronons) for the [desktop animations](https://github.com/Kuronons/FZ_graphics/tree/main/Animations/Custom_Firmwares) + - [Kuronons](https://github.com/Kuronons) for the [passport portraits](https://github.com/Kuronons/FZ_graphics/tree/main/Passport%20profile%20pictures) - [Kuronons](https://github.com/Kuronons) for the [passport background](https://github.com/Kuronons/FZ_graphics/tree/main/Passport%20background) (not in asset pack, it's in base firmware) - **`WatchDogs`** - Credits: - [WrenchAtHome](https://github.com/wrenchathome) for some [desktop animations](https://github.com/wrenchathome/flip0anims) - - [u/Cheroon](https://www.reddit.com/user/Cheroon/) for the [passport portait](https://www.reddit.com/r/watch_dogs/comments/50n046/pixel_art_wrench_mask_gif/) + - [Kuronons](https://github.com/Kuronons) for the [passport portaits](https://github.com/Kuronons/FZ_graphics/tree/main/Passport%20profile%20pictures) + - [Kuronons](https://github.com/Kuronons) for the [passport background](https://github.com/Kuronons/FZ_graphics/tree/main/Passport%20background) - [David Libeau](https://davidlibeau.fr/) for the [primary font (hacked)](http://bit.ly/WatchDogsFont) - [Gissio](https://github.com/Gissio) for the [secondary font (tiny5)](https://github.com/Gissio/font_tiny5) - Ife Mena for the [keyboard font (3x5im)](https://www.pentacom.jp/pentacom/bitfontmaker2/gallery/?id=7785) diff --git a/assets/packs/WatchDogs/Icons/Passport/passport_128x64.png b/assets/packs/WatchDogs/Icons/Passport/passport_128x64.png new file mode 100644 index 000000000..331c09eec Binary files /dev/null and b/assets/packs/WatchDogs/Icons/Passport/passport_128x64.png differ diff --git a/assets/packs/WatchDogs/Icons/Passport/passport_bad_46x49.png b/assets/packs/WatchDogs/Icons/Passport/passport_bad_46x49.png index 5d4348d3c..7c9e758cb 100644 Binary files a/assets/packs/WatchDogs/Icons/Passport/passport_bad_46x49.png and b/assets/packs/WatchDogs/Icons/Passport/passport_bad_46x49.png differ diff --git a/assets/packs/WatchDogs/Icons/Passport/passport_happy_46x49.png b/assets/packs/WatchDogs/Icons/Passport/passport_happy_46x49.png index 657c8c352..9001675d0 100644 Binary files a/assets/packs/WatchDogs/Icons/Passport/passport_happy_46x49.png and b/assets/packs/WatchDogs/Icons/Passport/passport_happy_46x49.png differ diff --git a/assets/packs/WatchDogs/Icons/Passport/passport_okay_46x49.png b/assets/packs/WatchDogs/Icons/Passport/passport_okay_46x49.png index 10383b31b..efcba2b64 100644 Binary files a/assets/packs/WatchDogs/Icons/Passport/passport_okay_46x49.png and b/assets/packs/WatchDogs/Icons/Passport/passport_okay_46x49.png differ diff --git a/documentation/JavaScript.md b/documentation/JavaScript.md new file mode 100644 index 000000000..ad7a6d002 --- /dev/null +++ b/documentation/JavaScript.md @@ -0,0 +1,148 @@ + +# JavaScript scripting API (WIP) +## Note: This documentation is still work in progress! +Todo: +- Add missing parameters +- Add missing returns +- Add examples + +## Description +Momentum supports JavaScript scripting using [mjs](https://github.com/cesanta/mjs). +**Note: Read about mjs's limitations in the link above! You will experience alot of missing js features (e.g. createTimeout).** + +## API +### SubGHZ +`const subghz = require("subghz");` +#### Methods +- setup(): void +- setRx(): void +- setIdle(): void +- getRssi(): number +- getState(): string +- getFrequency(): number +- setFrequency(freq: number): number | undefined +- isExternal(): bool +- transmitFile(file: string): bool | undefined + +### Usbdisk +`const usbdisk = require("usbdisk");` +#### Methods +- createImage(file: string, size: number): undefined +- start(file: string): undefined +- stop(): undefined +- wasEjected(): bool | undefined + +### BadUsb +`const badusb = require("badusb");` +#### Methods +- setup +- quit +- isConnected +- press +- hold +- release +- print +- println +- +### BleBeacon +`const blebeacon = require("blebeacon");` +#### Methods +- isActive +- setConfig +- setData +- start +- stop +- keepAlive + +### Dialog +`const dialog = require("dialog");` +#### Methods +- message +- custom +- pickFile + +### Flipper +`const flipper= require("flipper");` +#### Methods +- getModel +- getName +- getBatteryCharge + +### Gpio +`const gpio = require("gpio");` +#### Methods +- init +- write +- read + +### Keyboard +`const keyboard = require("keyboard");` +#### Methods +- setHeader +- text +- byte + +### Math +`const math = require("math");` +#### Methods +- abs +- acos +- acosh +- asin +- asinh +- atan +- atan2 +- atanh +- cbrt +- ceil +- clz32 +- cos +- exp +- floor +- log +- max +- min +- pow +- random +- sign +- sin +- sqrt +- trunc +- PI +- E + +### Notification +`const notify = require("notification");` +#### Methods +- success +- error +- blink + +### Serial +`const serial = require("serial");` +#### Methods +- setup +- write +- read +- readln +- readBytes +- expect + +### Storage +`const storage = require("storage");` +#### Methods +- read +- write +- append +- exists +- remove +- virtualInit +- virtualMount +- virtualQuit + +### Submenu +`const submenu = require("submenu");` +#### Methods +- addItem +- setHeader +- show diff --git a/furi/flipper.c b/furi/flipper.c index 50c6659e0..8b59c5ead 100644 --- a/furi/flipper.c +++ b/furi/flipper.c @@ -98,14 +98,6 @@ void flipper_migrate_files() { furi_record_close(RECORD_STORAGE); } - -static void flipper_boot_status(Canvas* canvas, const char* text) { - FURI_LOG_I(TAG, text); - canvas_reset(canvas); - canvas_draw_icon(canvas, 33, 16, &I_Updating_Logo_62x15); - canvas_draw_str_aligned(canvas, 64, 44, AlignCenter, AlignCenter, text); - canvas_commit(canvas); -} #endif void flipper_start_service(const FlipperInternalApplication* service) { @@ -123,12 +115,17 @@ void flipper_init() { furi_hal_light_sequence("rgb WB"); flipper_print_version("Firmware", furi_hal_version_get_firmware_version()); FURI_LOG_I(TAG, "Boot mode %d", furi_hal_rtc_get_boot_mode()); + #ifndef FURI_RAM_EXEC Canvas* canvas = canvas_init(); + canvas_draw_icon(canvas, 33, 16, &I_Updating_Logo_62x15); + if(furi_hal_is_normal_boot()) { + canvas_draw_icon(canvas, 19, 44, &I_SDcardMounted_11x8); + } + canvas_commit(canvas); +#endif // Start storage service first, thanks OFW :/ - flipper_boot_status(canvas, "Initializing Storage"); -#endif flipper_start_service(&FLIPPER_SERVICES[0]); #ifndef FURI_RAM_EXEC @@ -137,28 +134,32 @@ void flipper_init() { furi_record_open(RECORD_STORAGE); furi_record_close(RECORD_STORAGE); - flipper_boot_status(canvas, "Migrating Files"); + canvas_draw_icon(canvas, 39, 43, &I_dir_10px); + canvas_commit(canvas); flipper_migrate_files(); - flipper_boot_status(canvas, "Starting Namespoof"); + canvas_draw_icon(canvas, 59, 42, &I_Apps_10px); + canvas_commit(canvas); namespoof_init(); - flipper_boot_status(canvas, "Loading Settings"); + canvas_draw_icon(canvas, 79, 44, &I_Rpc_active_7x8); + canvas_commit(canvas); momentum_settings_load(); - furi_hal_light_sequence("rgb RB"); - flipper_boot_status(canvas, "Loading Asset Packs"); + furi_hal_light_sequence("rgb RB"); + canvas_draw_icon(canvas, 99, 44, &I_Hidden_window_9x8); + canvas_commit(canvas); asset_packs_init(); } else { FURI_LOG_I(TAG, "Special boot, skipping optional components"); } - flipper_boot_status(canvas, "Initializing Services"); #endif // Everything else for(size_t i = 1; i < FLIPPER_SERVICES_COUNT; i++) { flipper_start_service(&FLIPPER_SERVICES[i]); } + #ifndef FURI_RAM_EXEC canvas_free(canvas); #endif diff --git a/lib/datetime/datetime.c b/lib/datetime/datetime.c index 7b1f73dd0..73044fae6 100644 --- a/lib/datetime/datetime.c +++ b/lib/datetime/datetime.c @@ -71,6 +71,7 @@ void datetime_timestamp_to_datetime(uint32_t timestamp, DateTime* datetime) { uint32_t seconds_in_day = timestamp % SECONDS_PER_DAY; datetime->year = EPOCH_START_YEAR; + datetime->weekday = ((days + 3) % 7) + 1; while(days >= datetime_get_days_per_year(datetime->year)) { days -= datetime_get_days_per_year(datetime->year); diff --git a/lib/fatfs/ff.c b/lib/fatfs/ff.c index 949ea7247..fa9da1b6d 100644 --- a/lib/fatfs/ff.c +++ b/lib/fatfs/ff.c @@ -5297,7 +5297,6 @@ FRESULT f_forward ( /*-----------------------------------------------------------------------*/ /* Create an FAT/exFAT volume */ /*-----------------------------------------------------------------------*/ -#define _MKFS_ONLY_EXFAT FRESULT f_mkfs ( const TCHAR* path, /* Logical drive number */ @@ -5370,16 +5369,6 @@ FRESULT f_mkfs ( if (sz_vol < 128) return FR_MKFS_ABORTED; /* Check if volume size is >=128s */ /* Pre-determine the FAT type */ -#ifdef _MKFS_ONLY_EXFAT - (void)sz_dir; - (void)sz_rsv; - (void)pau; - (void)cst32; - (void)cst; - (void)n_rootdir; - (void)n_fats; - fmt = FS_EXFAT; -#else do { if (_FS_EXFAT && (opt & FM_EXFAT)) { /* exFAT possible? */ if ((opt & FM_ANY) == FM_EXFAT || sz_vol >= 0x2000000 || au > 128) { /* exFAT only, vol >= 32Ms or au > 128s ? */ @@ -5395,7 +5384,6 @@ FRESULT f_mkfs ( if (!(opt & FM_FAT)) return FR_INVALID_PARAMETER; /* no-FAT? */ fmt = FS_FAT16; } while (0); -#endif #if _FS_EXFAT if (fmt == FS_EXFAT) { /* Create an exFAT volume */ @@ -5560,11 +5548,6 @@ FRESULT f_mkfs ( } else #endif /* _FS_EXFAT */ -#ifdef _MKFS_ONLY_EXFAT - { - return FR_INVALID_PARAMETER; - } -#else { /* Create an FAT12/16/32 volume */ do { pau = au; @@ -5718,12 +5701,8 @@ FRESULT f_mkfs ( sect += n; nsect -= n; } while (nsect); } -#endif /* Determine system ID in the partition table */ -#ifdef _MKFS_ONLY_EXFAT - sys = 0x07; /* HPFS/NTFS/exFAT */ -#else if (_FS_EXFAT && fmt == FS_EXFAT) { sys = 0x07; /* HPFS/NTFS/exFAT */ } else { @@ -5737,7 +5716,6 @@ FRESULT f_mkfs ( } } } -#endif /* Update partition information */ if (_MULTI_PARTITION && part != 0) { /* Created in the existing partition */ diff --git a/lib/lfrfid/protocols/protocol_em4100.c b/lib/lfrfid/protocols/protocol_em4100.c index 05952110d..2a9e60b00 100644 --- a/lib/lfrfid/protocols/protocol_em4100.c +++ b/lib/lfrfid/protocols/protocol_em4100.c @@ -318,8 +318,8 @@ bool protocol_em4100_write_data(ProtocolEM4100* protocol, void* data) { request->t5577.block[0] = (LFRFID_T5577_MODULATION_MANCHESTER | protocol_em4100_get_t5577_bitrate(protocol) | (2 << LFRFID_T5577_MAXBLOCK_SHIFT)); - request->t5577.block[1] = protocol->encoded_data; - request->t5577.block[2] = protocol->encoded_data >> 32; + request->t5577.block[1] = protocol->encoded_data >> 32; + request->t5577.block[2] = protocol->encoded_data; request->t5577.blocks_to_write = 3; result = true; } diff --git a/lib/momentum/momentum.h b/lib/momentum/momentum.h index e2555c99c..c3d43f43b 100644 --- a/lib/momentum/momentum.h +++ b/lib/momentum/momentum.h @@ -77,8 +77,6 @@ typedef struct { bool show_hidden_files; bool show_internal_tab; uint32_t favorite_timeout; - bool bad_bt; - bool bad_bt_remember; bool dark_mode; bool rgb_backlight; uint32_t butthurt_timer; diff --git a/lib/momentum/settings.c b/lib/momentum/settings.c index a4086ebbb..209f6bc4a 100644 --- a/lib/momentum/settings.c +++ b/lib/momentum/settings.c @@ -30,8 +30,6 @@ MomentumSettings momentum_settings = { .show_hidden_files = false, // OFF .show_internal_tab = false, // OFF .favorite_timeout = 0, // OFF - .bad_bt = false, // USB - .bad_bt_remember = false, // OFF .dark_mode = false, // OFF .rgb_backlight = false, // OFF .butthurt_timer = 21600, // 6 H @@ -102,8 +100,6 @@ static const struct { {setting_bool(show_hidden_files)}, {setting_bool(show_internal_tab)}, {setting_uint(favorite_timeout, 0, 60)}, - {setting_bool(bad_bt)}, - {setting_bool(bad_bt_remember)}, {setting_bool(dark_mode)}, {setting_bool(rgb_backlight)}, {setting_uint(butthurt_timer, 0, 172800)}, diff --git a/lib/nfc/protocols/mf_desfire/mf_desfire_poller.c b/lib/nfc/protocols/mf_desfire/mf_desfire_poller.c index 5af033d4c..f6e638d7c 100644 --- a/lib/nfc/protocols/mf_desfire/mf_desfire_poller.c +++ b/lib/nfc/protocols/mf_desfire/mf_desfire_poller.c @@ -225,8 +225,8 @@ static bool mf_desfire_poller_detect(NfcGenericEvent event, void* context) { bool protocol_detected = false; if(iso14443_4a_event->type == Iso14443_4aPollerEventTypeReady) { - MfDesfireVersion version = {}; - const MfDesfireError error = mf_desfire_poller_read_version(instance, &version); + MfDesfireKeyVersion key_version = 0; + MfDesfireError error = mf_desfire_poller_read_key_version(instance, 0, &key_version); protocol_detected = (error == MfDesfireErrorNone); } diff --git a/lib/nfc/protocols/mf_desfire/mf_desfire_poller.h b/lib/nfc/protocols/mf_desfire/mf_desfire_poller.h index 6ef2f3f68..707df42cd 100644 --- a/lib/nfc/protocols/mf_desfire/mf_desfire_poller.h +++ b/lib/nfc/protocols/mf_desfire/mf_desfire_poller.h @@ -91,6 +91,21 @@ MfDesfireError MfDesfireError mf_desfire_poller_read_key_settings(MfDesfirePoller* instance, MfDesfireKeySettings* data); +/** + * @brief Read key version on MfDesfire card. + * + * Must ONLY be used inside the callback function. + * + * @param[in, out] instance pointer to the instance to be used in the transaction. + * @param[out] key_num key number. + * @param[in] data pointer to the MfDesfireKeyVersion structure to be filled with key version data. + * @return MfDesfireErrorNone on success, an error code on failure. + */ +MfDesfireError mf_desfire_poller_read_key_version( + MfDesfirePoller* instance, + uint8_t key_num, + MfDesfireKeyVersion* data); + /** * @brief Read key versions on MfDesfire card. * diff --git a/lib/nfc/protocols/mf_desfire/mf_desfire_poller_i.c b/lib/nfc/protocols/mf_desfire/mf_desfire_poller_i.c index 0b2d84138..1a91c5261 100644 --- a/lib/nfc/protocols/mf_desfire/mf_desfire_poller_i.c +++ b/lib/nfc/protocols/mf_desfire/mf_desfire_poller_i.c @@ -139,6 +139,28 @@ MfDesfireError return error; } +MfDesfireError mf_desfire_poller_read_key_version( + MfDesfirePoller* instance, + uint8_t key_num, + MfDesfireKeyVersion* data) { + furi_assert(instance); + furi_assert(data); + + bit_buffer_set_size_bytes(instance->input_buffer, sizeof(uint8_t) * 2); + bit_buffer_set_byte(instance->input_buffer, 0, MF_DESFIRE_CMD_GET_KEY_VERSION); + bit_buffer_set_byte(instance->input_buffer, 1, key_num); + + MfDesfireError error = + mf_desfire_send_chunks(instance, instance->input_buffer, instance->result_buffer); + if(error == MfDesfireErrorNone) { + if(!mf_desfire_key_version_parse(data, instance->result_buffer)) { + error = MfDesfireErrorProtocol; + } + } + + return error; +} + MfDesfireError mf_desfire_poller_read_key_versions( MfDesfirePoller* instance, SimpleArray* data, @@ -148,22 +170,11 @@ MfDesfireError mf_desfire_poller_read_key_versions( simple_array_init(data, count); - bit_buffer_set_size_bytes(instance->input_buffer, sizeof(uint8_t) * 2); - bit_buffer_set_byte(instance->input_buffer, 0, MF_DESFIRE_CMD_GET_KEY_VERSION); - MfDesfireError error = MfDesfireErrorNone; for(uint32_t i = 0; i < count; ++i) { - bit_buffer_set_byte(instance->input_buffer, 1, i); - - error = mf_desfire_send_chunks(instance, instance->input_buffer, instance->result_buffer); - + error = mf_desfire_poller_read_key_version(instance, i, simple_array_get(data, i)); if(error != MfDesfireErrorNone) break; - - if(!mf_desfire_key_version_parse(simple_array_get(data, i), instance->result_buffer)) { - error = MfDesfireErrorProtocol; - break; - } } return error; diff --git a/lib/nfc/protocols/slix/slix.c b/lib/nfc/protocols/slix/slix.c index b575baa72..6361787d3 100644 --- a/lib/nfc/protocols/slix/slix.c +++ b/lib/nfc/protocols/slix/slix.c @@ -78,8 +78,8 @@ typedef struct { static const SlixPasswordConfig slix_password_configs[] = { [SlixPasswordTypeRead] = {SLIX_PASSWORD_READ_KEY, SLIX_TYPE_FEATURE_READ, 0x00000000U}, [SlixPasswordTypeWrite] = {SLIX_PASSWORD_WRITE_KEY, SLIX_TYPE_FEATURE_WRITE, 0x00000000U}, - [SlixPasswordTypePrivacy] = {SLIX_PASSWORD_PRIVACY_KEY, SLIX_TYPE_FEATURE_PRIVACY, 0xFFFFFFFFU}, - [SlixPasswordTypeDestroy] = {SLIX_PASSWORD_DESTROY_KEY, SLIX_TYPE_FEATURE_DESTROY, 0xFFFFFFFFU}, + [SlixPasswordTypePrivacy] = {SLIX_PASSWORD_PRIVACY_KEY, SLIX_TYPE_FEATURE_PRIVACY, 0x0F0F0F0FU}, + [SlixPasswordTypeDestroy] = {SLIX_PASSWORD_DESTROY_KEY, SLIX_TYPE_FEATURE_DESTROY, 0x0F0F0F0FU}, [SlixPasswordTypeEasAfi] = {SLIX_PASSWORD_EAS_KEY, SLIX_TYPE_FEATURE_EAS, 0x00000000U}, }; diff --git a/lib/nfc/protocols/slix/slix_poller.c b/lib/nfc/protocols/slix/slix_poller.c index d9d38d102..3c9a7cce4 100644 --- a/lib/nfc/protocols/slix/slix_poller.c +++ b/lib/nfc/protocols/slix/slix_poller.c @@ -73,17 +73,62 @@ static NfcCommand slix_poller_handler_read_signature(SlixPoller* instance) { if(slix_type_has_features(instance->type, SLIX_TYPE_FEATURE_SIGNATURE)) { instance->error = slix_poller_read_signature(instance, &instance->data->signature); if(instance->error == SlixErrorNone) { - instance->poller_state = SlixPollerStateReady; + instance->poller_state = SlixPollerStateCheckPrivacyPassword; } else { instance->poller_state = SlixPollerStateError; } } else { - instance->poller_state = SlixPollerStateReady; + instance->poller_state = SlixPollerStateCheckPrivacyPassword; } return NfcCommandContinue; } +static NfcCommand slix_poller_handler_check_privacy_password(SlixPoller* instance) { + NfcCommand command = NfcCommandContinue; + + do { + if(!slix_type_has_features(instance->type, SLIX_TYPE_FEATURE_PRIVACY)) { + instance->poller_state = SlixPollerStateReady; + break; + } + if(instance->privacy_password_checked) { + instance->poller_state = SlixPollerStateReady; + break; + } + + instance->slix_event.type = SlixPollerEventTypePrivacyUnlockRequest; + command = instance->callback(instance->general_event, instance->context); + + if(!instance->slix_event_data.privacy_password.password_set) { + instance->poller_state = SlixPollerStateReady; + break; + } + + SlixPassword pwd = instance->slix_event_data.privacy_password.password; + FURI_LOG_I(TAG, "Trying to check privacy password: %08lX", pwd); + + instance->error = slix_poller_get_random_number(instance, &instance->random_number); + if(instance->error != SlixErrorNone) { + instance->poller_state = SlixPollerStateReady; + break; + } + + instance->error = slix_poller_set_password(instance, SlixPasswordTypePrivacy, pwd); + if(instance->error != SlixErrorNone) { + command = NfcCommandReset; + break; + } + + FURI_LOG_I(TAG, "Found privacy password"); + instance->data->passwords[SlixPasswordTypePrivacy] = pwd; + instance->privacy_password_checked = true; + instance->poller_state = SlixPollerStateReady; + } while(false); + + return command; +} + static NfcCommand slix_poller_handler_privacy_unlock(SlixPoller* instance) { NfcCommand command = NfcCommandContinue; instance->poller_state = SlixPollerStateError; @@ -108,6 +153,7 @@ static NfcCommand slix_poller_handler_privacy_unlock(SlixPoller* instance) { FURI_LOG_I(TAG, "Privacy mode disabled"); instance->data->passwords[SlixPasswordTypePrivacy] = pwd; + instance->privacy_password_checked = true; instance->poller_state = SlixPollerStateIdle; slix_unlocked = true; } while(false); @@ -140,6 +186,7 @@ static const SlixPollerStateHandler slix_poller_state_handler[SlixPollerStateNum [SlixPollerStateError] = slix_poller_handler_error, [SlixPollerStateGetNxpSysInfo] = slix_poller_handler_get_nfc_system_info, [SlixPollerStateReadSignature] = slix_poller_handler_read_signature, + [SlixPollerStateCheckPrivacyPassword] = slix_poller_handler_check_privacy_password, [SlixPollerStatePrivacyUnlock] = slix_poller_handler_privacy_unlock, [SlixPollerStateReady] = slix_poller_handler_ready, }; diff --git a/lib/nfc/protocols/slix/slix_poller_i.h b/lib/nfc/protocols/slix/slix_poller_i.h index 7a3b543b7..38c23c297 100644 --- a/lib/nfc/protocols/slix/slix_poller_i.h +++ b/lib/nfc/protocols/slix/slix_poller_i.h @@ -14,6 +14,7 @@ typedef enum { SlixPollerStateIdle, SlixPollerStateGetNxpSysInfo, SlixPollerStateReadSignature, + SlixPollerStateCheckPrivacyPassword, SlixPollerStatePrivacyUnlock, SlixPollerStateReady, SlixPollerStateError, @@ -27,6 +28,7 @@ struct SlixPoller { SlixPollerState poller_state; SlixError error; SlixRandomNumber random_number; + bool privacy_password_checked; BitBuffer* tx_buffer; BitBuffer* rx_buffer; diff --git a/lib/subghz/protocols/acurite_592txr.c b/lib/subghz/protocols/acurite_592txr.c index 44c8761c7..f8a2b0bf0 100644 --- a/lib/subghz/protocols/acurite_592txr.c +++ b/lib/subghz/protocols/acurite_592txr.c @@ -67,7 +67,8 @@ const SubGhzProtocolDecoder ws_protocol_acurite_592txr_decoder = { .feed = ws_protocol_decoder_acurite_592txr_feed, .reset = ws_protocol_decoder_acurite_592txr_reset, - .get_hash_data = ws_protocol_decoder_acurite_592txr_get_hash_data, + .get_hash_data = NULL, + .get_hash_data_long = ws_protocol_decoder_acurite_592txr_get_hash_data, .serialize = ws_protocol_decoder_acurite_592txr_serialize, .deserialize = ws_protocol_decoder_acurite_592txr_deserialize, .get_string = ws_protocol_decoder_acurite_592txr_get_string, diff --git a/lib/subghz/protocols/acurite_606tx.c b/lib/subghz/protocols/acurite_606tx.c index 0f14c7db4..209b77ace 100644 --- a/lib/subghz/protocols/acurite_606tx.c +++ b/lib/subghz/protocols/acurite_606tx.c @@ -50,7 +50,8 @@ const SubGhzProtocolDecoder ws_protocol_acurite_606tx_decoder = { .feed = ws_protocol_decoder_acurite_606tx_feed, .reset = ws_protocol_decoder_acurite_606tx_reset, - .get_hash_data = ws_protocol_decoder_acurite_606tx_get_hash_data, + .get_hash_data = NULL, + .get_hash_data_long = ws_protocol_decoder_acurite_606tx_get_hash_data, .serialize = ws_protocol_decoder_acurite_606tx_serialize, .deserialize = ws_protocol_decoder_acurite_606tx_deserialize, .get_string = ws_protocol_decoder_acurite_606tx_get_string, diff --git a/lib/subghz/protocols/acurite_609txc.c b/lib/subghz/protocols/acurite_609txc.c index 8c082aace..e885cb421 100644 --- a/lib/subghz/protocols/acurite_609txc.c +++ b/lib/subghz/protocols/acurite_609txc.c @@ -51,7 +51,8 @@ const SubGhzProtocolDecoder ws_protocol_acurite_609txc_decoder = { .feed = ws_protocol_decoder_acurite_609txc_feed, .reset = ws_protocol_decoder_acurite_609txc_reset, - .get_hash_data = ws_protocol_decoder_acurite_609txc_get_hash_data, + .get_hash_data = NULL, + .get_hash_data_long = ws_protocol_decoder_acurite_609txc_get_hash_data, .serialize = ws_protocol_decoder_acurite_609txc_serialize, .deserialize = ws_protocol_decoder_acurite_609txc_deserialize, .get_string = ws_protocol_decoder_acurite_609txc_get_string, diff --git a/lib/subghz/protocols/acurite_986.c b/lib/subghz/protocols/acurite_986.c index ba64dc22e..5ddab0cd7 100644 --- a/lib/subghz/protocols/acurite_986.c +++ b/lib/subghz/protocols/acurite_986.c @@ -57,7 +57,8 @@ const SubGhzProtocolDecoder ws_protocol_acurite_986_decoder = { .feed = ws_protocol_decoder_acurite_986_feed, .reset = ws_protocol_decoder_acurite_986_reset, - .get_hash_data = ws_protocol_decoder_acurite_986_get_hash_data, + .get_hash_data = NULL, + .get_hash_data_long = ws_protocol_decoder_acurite_986_get_hash_data, .serialize = ws_protocol_decoder_acurite_986_serialize, .deserialize = ws_protocol_decoder_acurite_986_deserialize, .get_string = ws_protocol_decoder_acurite_986_get_string, diff --git a/lib/subghz/protocols/alutech_at_4n.c b/lib/subghz/protocols/alutech_at_4n.c index 0f29293f9..5b7976ad9 100644 --- a/lib/subghz/protocols/alutech_at_4n.c +++ b/lib/subghz/protocols/alutech_at_4n.c @@ -54,7 +54,8 @@ const SubGhzProtocolDecoder subghz_protocol_alutech_at_4n_decoder = { .feed = subghz_protocol_decoder_alutech_at_4n_feed, .reset = subghz_protocol_decoder_alutech_at_4n_reset, - .get_hash_data = subghz_protocol_decoder_alutech_at_4n_get_hash_data, + .get_hash_data = NULL, + .get_hash_data_long = subghz_protocol_decoder_alutech_at_4n_get_hash_data, .serialize = subghz_protocol_decoder_alutech_at_4n_serialize, .deserialize = subghz_protocol_decoder_alutech_at_4n_deserialize, .get_string = subghz_protocol_decoder_alutech_at_4n_get_string, diff --git a/lib/subghz/protocols/ambient_weather.c b/lib/subghz/protocols/ambient_weather.c index 33844c405..a18627404 100644 --- a/lib/subghz/protocols/ambient_weather.c +++ b/lib/subghz/protocols/ambient_weather.c @@ -65,7 +65,8 @@ const SubGhzProtocolDecoder ws_protocol_ambient_weather_decoder = { .feed = ws_protocol_decoder_ambient_weather_feed, .reset = ws_protocol_decoder_ambient_weather_reset, - .get_hash_data = ws_protocol_decoder_ambient_weather_get_hash_data, + .get_hash_data = NULL, + .get_hash_data_long = ws_protocol_decoder_ambient_weather_get_hash_data, .serialize = ws_protocol_decoder_ambient_weather_serialize, .deserialize = ws_protocol_decoder_ambient_weather_deserialize, .get_string = ws_protocol_decoder_ambient_weather_get_string, diff --git a/lib/subghz/protocols/ansonic.c b/lib/subghz/protocols/ansonic.c index 571b0ad99..1c91815c6 100644 --- a/lib/subghz/protocols/ansonic.c +++ b/lib/subghz/protocols/ansonic.c @@ -49,7 +49,8 @@ const SubGhzProtocolDecoder subghz_protocol_ansonic_decoder = { .feed = subghz_protocol_decoder_ansonic_feed, .reset = subghz_protocol_decoder_ansonic_reset, - .get_hash_data = subghz_protocol_decoder_ansonic_get_hash_data, + .get_hash_data = NULL, + .get_hash_data_long = subghz_protocol_decoder_ansonic_get_hash_data, .serialize = subghz_protocol_decoder_ansonic_serialize, .deserialize = subghz_protocol_decoder_ansonic_deserialize, .get_string = subghz_protocol_decoder_ansonic_get_string, diff --git a/lib/subghz/protocols/auriol_ahfl.c b/lib/subghz/protocols/auriol_ahfl.c index 4be9f8b00..209068d8d 100644 --- a/lib/subghz/protocols/auriol_ahfl.c +++ b/lib/subghz/protocols/auriol_ahfl.c @@ -62,7 +62,8 @@ const SubGhzProtocolDecoder ws_protocol_auriol_ahfl_decoder = { .feed = ws_protocol_decoder_auriol_ahfl_feed, .reset = ws_protocol_decoder_auriol_ahfl_reset, - .get_hash_data = ws_protocol_decoder_auriol_ahfl_get_hash_data, + .get_hash_data = NULL, + .get_hash_data_long = ws_protocol_decoder_auriol_ahfl_get_hash_data, .serialize = ws_protocol_decoder_auriol_ahfl_serialize, .deserialize = ws_protocol_decoder_auriol_ahfl_deserialize, .get_string = ws_protocol_decoder_auriol_ahfl_get_string, diff --git a/lib/subghz/protocols/auriol_hg0601a.c b/lib/subghz/protocols/auriol_hg0601a.c index 543b7a2a7..26a51ad26 100644 --- a/lib/subghz/protocols/auriol_hg0601a.c +++ b/lib/subghz/protocols/auriol_hg0601a.c @@ -61,7 +61,8 @@ const SubGhzProtocolDecoder ws_protocol_auriol_th_decoder = { .feed = ws_protocol_decoder_auriol_th_feed, .reset = ws_protocol_decoder_auriol_th_reset, - .get_hash_data = ws_protocol_decoder_auriol_th_get_hash_data, + .get_hash_data = NULL, + .get_hash_data_long = ws_protocol_decoder_auriol_th_get_hash_data, .serialize = ws_protocol_decoder_auriol_th_serialize, .deserialize = ws_protocol_decoder_auriol_th_deserialize, .get_string = ws_protocol_decoder_auriol_th_get_string, diff --git a/lib/subghz/protocols/base.c b/lib/subghz/protocols/base.c index 716ee9299..463b95c89 100644 --- a/lib/subghz/protocols/base.c +++ b/lib/subghz/protocols/base.c @@ -52,12 +52,14 @@ SubGhzProtocolStatus subghz_protocol_decoder_base_deserialize( uint8_t subghz_protocol_decoder_base_get_hash_data(SubGhzProtocolDecoderBase* decoder_base) { uint8_t hash = 0; + if(!decoder_base->protocol || !decoder_base->protocol->decoder) return hash; - if(decoder_base->protocol && decoder_base->protocol->decoder && - decoder_base->protocol->decoder->get_hash_data) { - uint32_t full = decoder_base->protocol->decoder->get_hash_data(decoder_base); - uint8_t* p = (uint8_t*)&full; - for(size_t i = 0; i < sizeof(full); i++) { + if(decoder_base->protocol->decoder->get_hash_data) { + hash = decoder_base->protocol->decoder->get_hash_data(decoder_base); + } else if(decoder_base->protocol->decoder->get_hash_data_long) { + uint32_t long_hash = decoder_base->protocol->decoder->get_hash_data_long(decoder_base); + uint8_t* p = (uint8_t*)&long_hash; + for(size_t i = 0; i < sizeof(long_hash); i++) { hash ^= p[i]; } } @@ -67,10 +69,12 @@ uint8_t subghz_protocol_decoder_base_get_hash_data(SubGhzProtocolDecoderBase* de uint32_t subghz_protocol_decoder_base_get_hash_data_long(SubGhzProtocolDecoderBase* decoder_base) { uint32_t hash = 0; + if(!decoder_base->protocol || !decoder_base->protocol->decoder) return hash; - if(decoder_base->protocol && decoder_base->protocol->decoder && - decoder_base->protocol->decoder->get_hash_data) { + if(decoder_base->protocol->decoder->get_hash_data) { hash = decoder_base->protocol->decoder->get_hash_data(decoder_base); + } else if(decoder_base->protocol->decoder->get_hash_data_long) { + hash = decoder_base->protocol->decoder->get_hash_data_long(decoder_base); } return hash; diff --git a/lib/subghz/protocols/bett.c b/lib/subghz/protocols/bett.c index 054f41ceb..c310e78e9 100644 --- a/lib/subghz/protocols/bett.c +++ b/lib/subghz/protocols/bett.c @@ -59,7 +59,8 @@ const SubGhzProtocolDecoder subghz_protocol_bett_decoder = { .feed = subghz_protocol_decoder_bett_feed, .reset = subghz_protocol_decoder_bett_reset, - .get_hash_data = subghz_protocol_decoder_bett_get_hash_data, + .get_hash_data = NULL, + .get_hash_data_long = subghz_protocol_decoder_bett_get_hash_data, .serialize = subghz_protocol_decoder_bett_serialize, .deserialize = subghz_protocol_decoder_bett_deserialize, .get_string = subghz_protocol_decoder_bett_get_string, diff --git a/lib/subghz/protocols/bin_raw.c b/lib/subghz/protocols/bin_raw.c index 58ec69cb7..d78c079ff 100644 --- a/lib/subghz/protocols/bin_raw.c +++ b/lib/subghz/protocols/bin_raw.c @@ -96,7 +96,8 @@ const SubGhzProtocolDecoder subghz_protocol_bin_raw_decoder = { .feed = subghz_protocol_decoder_bin_raw_feed, .reset = subghz_protocol_decoder_bin_raw_reset, - .get_hash_data = subghz_protocol_decoder_bin_raw_get_hash_data, + .get_hash_data = NULL, + .get_hash_data_long = subghz_protocol_decoder_bin_raw_get_hash_data, .serialize = subghz_protocol_decoder_bin_raw_serialize, .deserialize = subghz_protocol_decoder_bin_raw_deserialize, .get_string = subghz_protocol_decoder_bin_raw_get_string, diff --git a/lib/subghz/protocols/came.c b/lib/subghz/protocols/came.c index 74ff42f4d..b40e2fefc 100644 --- a/lib/subghz/protocols/came.c +++ b/lib/subghz/protocols/came.c @@ -55,7 +55,8 @@ const SubGhzProtocolDecoder subghz_protocol_came_decoder = { .feed = subghz_protocol_decoder_came_feed, .reset = subghz_protocol_decoder_came_reset, - .get_hash_data = subghz_protocol_decoder_came_get_hash_data, + .get_hash_data = NULL, + .get_hash_data_long = subghz_protocol_decoder_came_get_hash_data, .serialize = subghz_protocol_decoder_came_serialize, .deserialize = subghz_protocol_decoder_came_deserialize, .get_string = subghz_protocol_decoder_came_get_string, diff --git a/lib/subghz/protocols/came_atomo.c b/lib/subghz/protocols/came_atomo.c index 4ad5ac060..c1d332131 100644 --- a/lib/subghz/protocols/came_atomo.c +++ b/lib/subghz/protocols/came_atomo.c @@ -46,7 +46,8 @@ const SubGhzProtocolDecoder subghz_protocol_came_atomo_decoder = { .feed = subghz_protocol_decoder_came_atomo_feed, .reset = subghz_protocol_decoder_came_atomo_reset, - .get_hash_data = subghz_protocol_decoder_came_atomo_get_hash_data, + .get_hash_data = NULL, + .get_hash_data_long = subghz_protocol_decoder_came_atomo_get_hash_data, .serialize = subghz_protocol_decoder_came_atomo_serialize, .deserialize = subghz_protocol_decoder_came_atomo_deserialize, .get_string = subghz_protocol_decoder_came_atomo_get_string, diff --git a/lib/subghz/protocols/came_twee.c b/lib/subghz/protocols/came_twee.c index 113343fec..1993e021b 100644 --- a/lib/subghz/protocols/came_twee.c +++ b/lib/subghz/protocols/came_twee.c @@ -77,7 +77,8 @@ const SubGhzProtocolDecoder subghz_protocol_came_twee_decoder = { .feed = subghz_protocol_decoder_came_twee_feed, .reset = subghz_protocol_decoder_came_twee_reset, - .get_hash_data = subghz_protocol_decoder_came_twee_get_hash_data, + .get_hash_data = NULL, + .get_hash_data_long = subghz_protocol_decoder_came_twee_get_hash_data, .serialize = subghz_protocol_decoder_came_twee_serialize, .deserialize = subghz_protocol_decoder_came_twee_deserialize, .get_string = subghz_protocol_decoder_came_twee_get_string, diff --git a/lib/subghz/protocols/chamberlain_code.c b/lib/subghz/protocols/chamberlain_code.c index 53ec20088..7c200e92b 100644 --- a/lib/subghz/protocols/chamberlain_code.c +++ b/lib/subghz/protocols/chamberlain_code.c @@ -73,7 +73,8 @@ const SubGhzProtocolDecoder subghz_protocol_chamb_code_decoder = { .feed = subghz_protocol_decoder_chamb_code_feed, .reset = subghz_protocol_decoder_chamb_code_reset, - .get_hash_data = subghz_protocol_decoder_chamb_code_get_hash_data, + .get_hash_data = NULL, + .get_hash_data_long = subghz_protocol_decoder_chamb_code_get_hash_data, .serialize = subghz_protocol_decoder_chamb_code_serialize, .deserialize = subghz_protocol_decoder_chamb_code_deserialize, .get_string = subghz_protocol_decoder_chamb_code_get_string, diff --git a/lib/subghz/protocols/clemsa.c b/lib/subghz/protocols/clemsa.c index b558f6a9e..f3dd32b92 100644 --- a/lib/subghz/protocols/clemsa.c +++ b/lib/subghz/protocols/clemsa.c @@ -58,7 +58,8 @@ const SubGhzProtocolDecoder subghz_protocol_clemsa_decoder = { .feed = subghz_protocol_decoder_clemsa_feed, .reset = subghz_protocol_decoder_clemsa_reset, - .get_hash_data = subghz_protocol_decoder_clemsa_get_hash_data, + .get_hash_data = NULL, + .get_hash_data_long = subghz_protocol_decoder_clemsa_get_hash_data, .serialize = subghz_protocol_decoder_clemsa_serialize, .deserialize = subghz_protocol_decoder_clemsa_deserialize, .get_string = subghz_protocol_decoder_clemsa_get_string, diff --git a/lib/subghz/protocols/doitrand.c b/lib/subghz/protocols/doitrand.c index d9572c0f1..8e8d73e8c 100644 --- a/lib/subghz/protocols/doitrand.c +++ b/lib/subghz/protocols/doitrand.c @@ -50,7 +50,8 @@ const SubGhzProtocolDecoder subghz_protocol_doitrand_decoder = { .feed = subghz_protocol_decoder_doitrand_feed, .reset = subghz_protocol_decoder_doitrand_reset, - .get_hash_data = subghz_protocol_decoder_doitrand_get_hash_data, + .get_hash_data = NULL, + .get_hash_data_long = subghz_protocol_decoder_doitrand_get_hash_data, .serialize = subghz_protocol_decoder_doitrand_serialize, .deserialize = subghz_protocol_decoder_doitrand_deserialize, .get_string = subghz_protocol_decoder_doitrand_get_string, diff --git a/lib/subghz/protocols/dooya.c b/lib/subghz/protocols/dooya.c index f847be9b8..1c2c1d6cd 100644 --- a/lib/subghz/protocols/dooya.c +++ b/lib/subghz/protocols/dooya.c @@ -44,7 +44,8 @@ const SubGhzProtocolDecoder subghz_protocol_dooya_decoder = { .feed = subghz_protocol_decoder_dooya_feed, .reset = subghz_protocol_decoder_dooya_reset, - .get_hash_data = subghz_protocol_decoder_dooya_get_hash_data, + .get_hash_data = NULL, + .get_hash_data_long = subghz_protocol_decoder_dooya_get_hash_data, .serialize = subghz_protocol_decoder_dooya_serialize, .deserialize = subghz_protocol_decoder_dooya_deserialize, .get_string = subghz_protocol_decoder_dooya_get_string, diff --git a/lib/subghz/protocols/faac_slh.c b/lib/subghz/protocols/faac_slh.c index d90f304fe..51f82fe8d 100644 --- a/lib/subghz/protocols/faac_slh.c +++ b/lib/subghz/protocols/faac_slh.c @@ -65,7 +65,8 @@ const SubGhzProtocolDecoder subghz_protocol_faac_slh_decoder = { .feed = subghz_protocol_decoder_faac_slh_feed, .reset = subghz_protocol_decoder_faac_slh_reset, - .get_hash_data = subghz_protocol_decoder_faac_slh_get_hash_data, + .get_hash_data = NULL, + .get_hash_data_long = subghz_protocol_decoder_faac_slh_get_hash_data, .serialize = subghz_protocol_decoder_faac_slh_serialize, .deserialize = subghz_protocol_decoder_faac_slh_deserialize, .get_string = subghz_protocol_decoder_faac_slh_get_string, diff --git a/lib/subghz/protocols/faac_slh.h b/lib/subghz/protocols/faac_slh.h index 1f0dadf69..b6ea07c63 100644 --- a/lib/subghz/protocols/faac_slh.h +++ b/lib/subghz/protocols/faac_slh.h @@ -107,7 +107,3 @@ SubGhzProtocolStatus * @param output Resulting text */ void subghz_protocol_decoder_faac_slh_get_string(void* context, FuriString* output); - -// Reset prog mode vars -// TODO: Remake in proper way -void faac_slh_reset_prog_mode(); \ No newline at end of file diff --git a/lib/subghz/protocols/gate_tx.c b/lib/subghz/protocols/gate_tx.c index bfff90e11..b85e1e1b5 100644 --- a/lib/subghz/protocols/gate_tx.c +++ b/lib/subghz/protocols/gate_tx.c @@ -43,7 +43,8 @@ const SubGhzProtocolDecoder subghz_protocol_gate_tx_decoder = { .feed = subghz_protocol_decoder_gate_tx_feed, .reset = subghz_protocol_decoder_gate_tx_reset, - .get_hash_data = subghz_protocol_decoder_gate_tx_get_hash_data, + .get_hash_data = NULL, + .get_hash_data_long = subghz_protocol_decoder_gate_tx_get_hash_data, .serialize = subghz_protocol_decoder_gate_tx_serialize, .deserialize = subghz_protocol_decoder_gate_tx_deserialize, .get_string = subghz_protocol_decoder_gate_tx_get_string, diff --git a/lib/subghz/protocols/gt_wt_02.c b/lib/subghz/protocols/gt_wt_02.c index a00003417..d5bfe0fc6 100644 --- a/lib/subghz/protocols/gt_wt_02.c +++ b/lib/subghz/protocols/gt_wt_02.c @@ -64,7 +64,8 @@ const SubGhzProtocolDecoder ws_protocol_gt_wt_02_decoder = { .feed = ws_protocol_decoder_gt_wt_02_feed, .reset = ws_protocol_decoder_gt_wt_02_reset, - .get_hash_data = ws_protocol_decoder_gt_wt_02_get_hash_data, + .get_hash_data = NULL, + .get_hash_data_long = ws_protocol_decoder_gt_wt_02_get_hash_data, .serialize = ws_protocol_decoder_gt_wt_02_serialize, .deserialize = ws_protocol_decoder_gt_wt_02_deserialize, .get_string = ws_protocol_decoder_gt_wt_02_get_string, diff --git a/lib/subghz/protocols/gt_wt_03.c b/lib/subghz/protocols/gt_wt_03.c index 253022a1f..18f2e9a20 100644 --- a/lib/subghz/protocols/gt_wt_03.c +++ b/lib/subghz/protocols/gt_wt_03.c @@ -90,7 +90,8 @@ const SubGhzProtocolDecoder ws_protocol_gt_wt_03_decoder = { .feed = ws_protocol_decoder_gt_wt_03_feed, .reset = ws_protocol_decoder_gt_wt_03_reset, - .get_hash_data = ws_protocol_decoder_gt_wt_03_get_hash_data, + .get_hash_data = NULL, + .get_hash_data_long = ws_protocol_decoder_gt_wt_03_get_hash_data, .serialize = ws_protocol_decoder_gt_wt_03_serialize, .deserialize = ws_protocol_decoder_gt_wt_03_deserialize, .get_string = ws_protocol_decoder_gt_wt_03_get_string, diff --git a/lib/subghz/protocols/holtek.c b/lib/subghz/protocols/holtek.c index 56ee15559..382b607e5 100644 --- a/lib/subghz/protocols/holtek.c +++ b/lib/subghz/protocols/holtek.c @@ -53,7 +53,8 @@ const SubGhzProtocolDecoder subghz_protocol_holtek_decoder = { .feed = subghz_protocol_decoder_holtek_feed, .reset = subghz_protocol_decoder_holtek_reset, - .get_hash_data = subghz_protocol_decoder_holtek_get_hash_data, + .get_hash_data = NULL, + .get_hash_data_long = subghz_protocol_decoder_holtek_get_hash_data, .serialize = subghz_protocol_decoder_holtek_serialize, .deserialize = subghz_protocol_decoder_holtek_deserialize, .get_string = subghz_protocol_decoder_holtek_get_string, diff --git a/lib/subghz/protocols/holtek_ht12x.c b/lib/subghz/protocols/holtek_ht12x.c index 9d3796fc9..2cc8fbe43 100644 --- a/lib/subghz/protocols/holtek_ht12x.c +++ b/lib/subghz/protocols/holtek_ht12x.c @@ -60,7 +60,8 @@ const SubGhzProtocolDecoder subghz_protocol_holtek_th12x_decoder = { .feed = subghz_protocol_decoder_holtek_th12x_feed, .reset = subghz_protocol_decoder_holtek_th12x_reset, - .get_hash_data = subghz_protocol_decoder_holtek_th12x_get_hash_data, + .get_hash_data = NULL, + .get_hash_data_long = subghz_protocol_decoder_holtek_th12x_get_hash_data, .serialize = subghz_protocol_decoder_holtek_th12x_serialize, .deserialize = subghz_protocol_decoder_holtek_th12x_deserialize, .get_string = subghz_protocol_decoder_holtek_th12x_get_string, diff --git a/lib/subghz/protocols/honeywell.c b/lib/subghz/protocols/honeywell.c index 593a9c64e..3d0629b6f 100644 --- a/lib/subghz/protocols/honeywell.c +++ b/lib/subghz/protocols/honeywell.c @@ -345,7 +345,8 @@ const SubGhzProtocolDecoder subghz_protocol_honeywell_decoder = { .free = subghz_protocol_decoder_honeywell_free, .feed = subghz_protocol_decoder_honeywell_feed, .reset = subghz_protocol_decoder_honeywell_reset, - .get_hash_data = subghz_protocol_decoder_honeywell_get_hash_data, + .get_hash_data = NULL, + .get_hash_data_long = subghz_protocol_decoder_honeywell_get_hash_data, .serialize = subghz_protocol_decoder_honeywell_serialize, .deserialize = subghz_protocol_decoder_honeywell_deserialize, .get_string = subghz_protocol_decoder_honeywell_get_string, diff --git a/lib/subghz/protocols/honeywell_wdb.c b/lib/subghz/protocols/honeywell_wdb.c index f22eec53d..f8345f6e1 100644 --- a/lib/subghz/protocols/honeywell_wdb.c +++ b/lib/subghz/protocols/honeywell_wdb.c @@ -54,7 +54,8 @@ const SubGhzProtocolDecoder subghz_protocol_honeywell_wdb_decoder = { .feed = subghz_protocol_decoder_honeywell_wdb_feed, .reset = subghz_protocol_decoder_honeywell_wdb_reset, - .get_hash_data = subghz_protocol_decoder_honeywell_wdb_get_hash_data, + .get_hash_data = NULL, + .get_hash_data_long = subghz_protocol_decoder_honeywell_wdb_get_hash_data, .serialize = subghz_protocol_decoder_honeywell_wdb_serialize, .deserialize = subghz_protocol_decoder_honeywell_wdb_deserialize, .get_string = subghz_protocol_decoder_honeywell_wdb_get_string, diff --git a/lib/subghz/protocols/hormann.c b/lib/subghz/protocols/hormann.c index 280e04d1d..e0d0d0092 100644 --- a/lib/subghz/protocols/hormann.c +++ b/lib/subghz/protocols/hormann.c @@ -47,7 +47,8 @@ const SubGhzProtocolDecoder subghz_protocol_hormann_decoder = { .feed = subghz_protocol_decoder_hormann_feed, .reset = subghz_protocol_decoder_hormann_reset, - .get_hash_data = subghz_protocol_decoder_hormann_get_hash_data, + .get_hash_data = NULL, + .get_hash_data_long = subghz_protocol_decoder_hormann_get_hash_data, .serialize = subghz_protocol_decoder_hormann_serialize, .deserialize = subghz_protocol_decoder_hormann_deserialize, .get_string = subghz_protocol_decoder_hormann_get_string, diff --git a/lib/subghz/protocols/ido.c b/lib/subghz/protocols/ido.c index ff9744825..61dc165d1 100644 --- a/lib/subghz/protocols/ido.c +++ b/lib/subghz/protocols/ido.c @@ -43,7 +43,8 @@ const SubGhzProtocolDecoder subghz_protocol_ido_decoder = { .feed = subghz_protocol_decoder_ido_feed, .reset = subghz_protocol_decoder_ido_reset, - .get_hash_data = subghz_protocol_decoder_ido_get_hash_data, + .get_hash_data = NULL, + .get_hash_data_long = subghz_protocol_decoder_ido_get_hash_data, .deserialize = subghz_protocol_decoder_ido_deserialize, .serialize = subghz_protocol_decoder_ido_serialize, .get_string = subghz_protocol_decoder_ido_get_string, diff --git a/lib/subghz/protocols/infactory.c b/lib/subghz/protocols/infactory.c index 311974ae9..b540bca3e 100644 --- a/lib/subghz/protocols/infactory.c +++ b/lib/subghz/protocols/infactory.c @@ -75,7 +75,8 @@ const SubGhzProtocolDecoder ws_protocol_infactory_decoder = { .feed = ws_protocol_decoder_infactory_feed, .reset = ws_protocol_decoder_infactory_reset, - .get_hash_data = ws_protocol_decoder_infactory_get_hash_data, + .get_hash_data = NULL, + .get_hash_data_long = ws_protocol_decoder_infactory_get_hash_data, .serialize = ws_protocol_decoder_infactory_serialize, .deserialize = ws_protocol_decoder_infactory_deserialize, .get_string = ws_protocol_decoder_infactory_get_string, diff --git a/lib/subghz/protocols/intertechno_v3.c b/lib/subghz/protocols/intertechno_v3.c index dae04cd94..e1a9630fa 100644 --- a/lib/subghz/protocols/intertechno_v3.c +++ b/lib/subghz/protocols/intertechno_v3.c @@ -52,7 +52,8 @@ const SubGhzProtocolDecoder subghz_protocol_intertechno_v3_decoder = { .feed = subghz_protocol_decoder_intertechno_v3_feed, .reset = subghz_protocol_decoder_intertechno_v3_reset, - .get_hash_data = subghz_protocol_decoder_intertechno_v3_get_hash_data, + .get_hash_data = NULL, + .get_hash_data_long = subghz_protocol_decoder_intertechno_v3_get_hash_data, .serialize = subghz_protocol_decoder_intertechno_v3_serialize, .deserialize = subghz_protocol_decoder_intertechno_v3_deserialize, .get_string = subghz_protocol_decoder_intertechno_v3_get_string, diff --git a/lib/subghz/protocols/kedsum_th.c b/lib/subghz/protocols/kedsum_th.c index d7ce1f1f5..8ee1f06d3 100644 --- a/lib/subghz/protocols/kedsum_th.c +++ b/lib/subghz/protocols/kedsum_th.c @@ -61,7 +61,8 @@ const SubGhzProtocolDecoder ws_protocol_kedsum_th_decoder = { .feed = ws_protocol_decoder_kedsum_th_feed, .reset = ws_protocol_decoder_kedsum_th_reset, - .get_hash_data = ws_protocol_decoder_kedsum_th_get_hash_data, + .get_hash_data = NULL, + .get_hash_data_long = ws_protocol_decoder_kedsum_th_get_hash_data, .serialize = ws_protocol_decoder_kedsum_th_serialize, .deserialize = ws_protocol_decoder_kedsum_th_deserialize, .get_string = ws_protocol_decoder_kedsum_th_get_string, diff --git a/lib/subghz/protocols/keeloq.c b/lib/subghz/protocols/keeloq.c index 21427b3a4..733accd8c 100644 --- a/lib/subghz/protocols/keeloq.c +++ b/lib/subghz/protocols/keeloq.c @@ -61,7 +61,8 @@ const SubGhzProtocolDecoder subghz_protocol_keeloq_decoder = { .feed = subghz_protocol_decoder_keeloq_feed, .reset = subghz_protocol_decoder_keeloq_reset, - .get_hash_data = subghz_protocol_decoder_keeloq_get_hash_data, + .get_hash_data = NULL, + .get_hash_data_long = subghz_protocol_decoder_keeloq_get_hash_data, .serialize = subghz_protocol_decoder_keeloq_serialize, .deserialize = subghz_protocol_decoder_keeloq_deserialize, .get_string = subghz_protocol_decoder_keeloq_get_string, diff --git a/lib/subghz/protocols/kia.c b/lib/subghz/protocols/kia.c index 66e79d338..18e5fc50a 100644 --- a/lib/subghz/protocols/kia.c +++ b/lib/subghz/protocols/kia.c @@ -45,7 +45,8 @@ const SubGhzProtocolDecoder subghz_protocol_kia_decoder = { .feed = subghz_protocol_decoder_kia_feed, .reset = subghz_protocol_decoder_kia_reset, - .get_hash_data = subghz_protocol_decoder_kia_get_hash_data, + .get_hash_data = NULL, + .get_hash_data_long = subghz_protocol_decoder_kia_get_hash_data, .serialize = subghz_protocol_decoder_kia_serialize, .deserialize = subghz_protocol_decoder_kia_deserialize, .get_string = subghz_protocol_decoder_kia_get_string, diff --git a/lib/subghz/protocols/kinggates_stylo_4k.c b/lib/subghz/protocols/kinggates_stylo_4k.c index 7665f0ea3..a32be0692 100644 --- a/lib/subghz/protocols/kinggates_stylo_4k.c +++ b/lib/subghz/protocols/kinggates_stylo_4k.c @@ -50,7 +50,8 @@ const SubGhzProtocolDecoder subghz_protocol_kinggates_stylo_4k_decoder = { .feed = subghz_protocol_decoder_kinggates_stylo_4k_feed, .reset = subghz_protocol_decoder_kinggates_stylo_4k_reset, - .get_hash_data = subghz_protocol_decoder_kinggates_stylo_4k_get_hash_data, + .get_hash_data = NULL, + .get_hash_data_long = subghz_protocol_decoder_kinggates_stylo_4k_get_hash_data, .serialize = subghz_protocol_decoder_kinggates_stylo_4k_serialize, .deserialize = subghz_protocol_decoder_kinggates_stylo_4k_deserialize, .get_string = subghz_protocol_decoder_kinggates_stylo_4k_get_string, diff --git a/lib/subghz/protocols/lacrosse_tx.c b/lib/subghz/protocols/lacrosse_tx.c index 1ac3e8a0e..5f9328729 100644 --- a/lib/subghz/protocols/lacrosse_tx.c +++ b/lib/subghz/protocols/lacrosse_tx.c @@ -79,7 +79,8 @@ const SubGhzProtocolDecoder ws_protocol_lacrosse_tx_decoder = { .feed = ws_protocol_decoder_lacrosse_tx_feed, .reset = ws_protocol_decoder_lacrosse_tx_reset, - .get_hash_data = ws_protocol_decoder_lacrosse_tx_get_hash_data, + .get_hash_data = NULL, + .get_hash_data_long = ws_protocol_decoder_lacrosse_tx_get_hash_data, .serialize = ws_protocol_decoder_lacrosse_tx_serialize, .deserialize = ws_protocol_decoder_lacrosse_tx_deserialize, .get_string = ws_protocol_decoder_lacrosse_tx_get_string, diff --git a/lib/subghz/protocols/lacrosse_tx141thbv2.c b/lib/subghz/protocols/lacrosse_tx141thbv2.c index 1e30b299a..8bbf0b63a 100644 --- a/lib/subghz/protocols/lacrosse_tx141thbv2.c +++ b/lib/subghz/protocols/lacrosse_tx141thbv2.c @@ -57,7 +57,8 @@ const SubGhzProtocolDecoder ws_protocol_lacrosse_tx141thbv2_decoder = { .feed = ws_protocol_decoder_lacrosse_tx141thbv2_feed, .reset = ws_protocol_decoder_lacrosse_tx141thbv2_reset, - .get_hash_data = ws_protocol_decoder_lacrosse_tx141thbv2_get_hash_data, + .get_hash_data = NULL, + .get_hash_data_long = ws_protocol_decoder_lacrosse_tx141thbv2_get_hash_data, .serialize = ws_protocol_decoder_lacrosse_tx141thbv2_serialize, .deserialize = ws_protocol_decoder_lacrosse_tx141thbv2_deserialize, .get_string = ws_protocol_decoder_lacrosse_tx141thbv2_get_string, diff --git a/lib/subghz/protocols/linear.c b/lib/subghz/protocols/linear.c index b4c162c35..365b7af52 100644 --- a/lib/subghz/protocols/linear.c +++ b/lib/subghz/protocols/linear.c @@ -49,7 +49,8 @@ const SubGhzProtocolDecoder subghz_protocol_linear_decoder = { .feed = subghz_protocol_decoder_linear_feed, .reset = subghz_protocol_decoder_linear_reset, - .get_hash_data = subghz_protocol_decoder_linear_get_hash_data, + .get_hash_data = NULL, + .get_hash_data_long = subghz_protocol_decoder_linear_get_hash_data, .serialize = subghz_protocol_decoder_linear_serialize, .deserialize = subghz_protocol_decoder_linear_deserialize, .get_string = subghz_protocol_decoder_linear_get_string, diff --git a/lib/subghz/protocols/linear_delta3.c b/lib/subghz/protocols/linear_delta3.c index f8171cf16..1326bf96b 100644 --- a/lib/subghz/protocols/linear_delta3.c +++ b/lib/subghz/protocols/linear_delta3.c @@ -50,7 +50,8 @@ const SubGhzProtocolDecoder subghz_protocol_linear_delta3_decoder = { .feed = subghz_protocol_decoder_linear_delta3_feed, .reset = subghz_protocol_decoder_linear_delta3_reset, - .get_hash_data = subghz_protocol_decoder_linear_delta3_get_hash_data, + .get_hash_data = NULL, + .get_hash_data_long = subghz_protocol_decoder_linear_delta3_get_hash_data, .serialize = subghz_protocol_decoder_linear_delta3_serialize, .deserialize = subghz_protocol_decoder_linear_delta3_deserialize, .get_string = subghz_protocol_decoder_linear_delta3_get_string, diff --git a/lib/subghz/protocols/magellan.c b/lib/subghz/protocols/magellan.c index e154baf27..9e3646b77 100644 --- a/lib/subghz/protocols/magellan.c +++ b/lib/subghz/protocols/magellan.c @@ -45,7 +45,8 @@ const SubGhzProtocolDecoder subghz_protocol_magellan_decoder = { .feed = subghz_protocol_decoder_magellan_feed, .reset = subghz_protocol_decoder_magellan_reset, - .get_hash_data = subghz_protocol_decoder_magellan_get_hash_data, + .get_hash_data = NULL, + .get_hash_data_long = subghz_protocol_decoder_magellan_get_hash_data, .serialize = subghz_protocol_decoder_magellan_serialize, .deserialize = subghz_protocol_decoder_magellan_deserialize, .get_string = subghz_protocol_decoder_magellan_get_string, diff --git a/lib/subghz/protocols/marantec.c b/lib/subghz/protocols/marantec.c index 82981ceb5..06709712e 100644 --- a/lib/subghz/protocols/marantec.c +++ b/lib/subghz/protocols/marantec.c @@ -45,7 +45,8 @@ const SubGhzProtocolDecoder subghz_protocol_marantec_decoder = { .feed = subghz_protocol_decoder_marantec_feed, .reset = subghz_protocol_decoder_marantec_reset, - .get_hash_data = subghz_protocol_decoder_marantec_get_hash_data, + .get_hash_data = NULL, + .get_hash_data_long = subghz_protocol_decoder_marantec_get_hash_data, .serialize = subghz_protocol_decoder_marantec_serialize, .deserialize = subghz_protocol_decoder_marantec_deserialize, .get_string = subghz_protocol_decoder_marantec_get_string, diff --git a/lib/subghz/protocols/mastercode.c b/lib/subghz/protocols/mastercode.c index c8f7eb333..425441f66 100644 --- a/lib/subghz/protocols/mastercode.c +++ b/lib/subghz/protocols/mastercode.c @@ -57,7 +57,8 @@ const SubGhzProtocolDecoder subghz_protocol_mastercode_decoder = { .feed = subghz_protocol_decoder_mastercode_feed, .reset = subghz_protocol_decoder_mastercode_reset, - .get_hash_data = subghz_protocol_decoder_mastercode_get_hash_data, + .get_hash_data = NULL, + .get_hash_data_long = subghz_protocol_decoder_mastercode_get_hash_data, .serialize = subghz_protocol_decoder_mastercode_serialize, .deserialize = subghz_protocol_decoder_mastercode_deserialize, .get_string = subghz_protocol_decoder_mastercode_get_string, diff --git a/lib/subghz/protocols/megacode.c b/lib/subghz/protocols/megacode.c index aae6c7db0..d2d37aacf 100644 --- a/lib/subghz/protocols/megacode.c +++ b/lib/subghz/protocols/megacode.c @@ -55,7 +55,8 @@ const SubGhzProtocolDecoder subghz_protocol_megacode_decoder = { .feed = subghz_protocol_decoder_megacode_feed, .reset = subghz_protocol_decoder_megacode_reset, - .get_hash_data = subghz_protocol_decoder_megacode_get_hash_data, + .get_hash_data = NULL, + .get_hash_data_long = subghz_protocol_decoder_megacode_get_hash_data, .serialize = subghz_protocol_decoder_megacode_serialize, .deserialize = subghz_protocol_decoder_megacode_deserialize, .get_string = subghz_protocol_decoder_megacode_get_string, diff --git a/lib/subghz/protocols/nero_radio.c b/lib/subghz/protocols/nero_radio.c index 9f356a239..c64d20877 100644 --- a/lib/subghz/protocols/nero_radio.c +++ b/lib/subghz/protocols/nero_radio.c @@ -45,7 +45,8 @@ const SubGhzProtocolDecoder subghz_protocol_nero_radio_decoder = { .feed = subghz_protocol_decoder_nero_radio_feed, .reset = subghz_protocol_decoder_nero_radio_reset, - .get_hash_data = subghz_protocol_decoder_nero_radio_get_hash_data, + .get_hash_data = NULL, + .get_hash_data_long = subghz_protocol_decoder_nero_radio_get_hash_data, .serialize = subghz_protocol_decoder_nero_radio_serialize, .deserialize = subghz_protocol_decoder_nero_radio_deserialize, .get_string = subghz_protocol_decoder_nero_radio_get_string, diff --git a/lib/subghz/protocols/nero_sketch.c b/lib/subghz/protocols/nero_sketch.c index 484d142b3..9155f5f24 100644 --- a/lib/subghz/protocols/nero_sketch.c +++ b/lib/subghz/protocols/nero_sketch.c @@ -44,7 +44,8 @@ const SubGhzProtocolDecoder subghz_protocol_nero_sketch_decoder = { .feed = subghz_protocol_decoder_nero_sketch_feed, .reset = subghz_protocol_decoder_nero_sketch_reset, - .get_hash_data = subghz_protocol_decoder_nero_sketch_get_hash_data, + .get_hash_data = NULL, + .get_hash_data_long = subghz_protocol_decoder_nero_sketch_get_hash_data, .serialize = subghz_protocol_decoder_nero_sketch_serialize, .deserialize = subghz_protocol_decoder_nero_sketch_deserialize, .get_string = subghz_protocol_decoder_nero_sketch_get_string, diff --git a/lib/subghz/protocols/nexus_th.c b/lib/subghz/protocols/nexus_th.c index 085018ba2..08187789a 100644 --- a/lib/subghz/protocols/nexus_th.c +++ b/lib/subghz/protocols/nexus_th.c @@ -340,7 +340,8 @@ const SubGhzProtocolDecoder ws_protocol_nexus_th_decoder = { .feed = ws_protocol_decoder_nexus_th_feed, .reset = ws_protocol_decoder_nexus_th_reset, - .get_hash_data = ws_protocol_decoder_nexus_th_get_hash_data, + .get_hash_data = NULL, + .get_hash_data_long = ws_protocol_decoder_nexus_th_get_hash_data, .serialize = ws_protocol_decoder_nexus_th_serialize, .deserialize = ws_protocol_decoder_nexus_th_deserialize, .get_string = ws_protocol_decoder_nexus_th_get_string, diff --git a/lib/subghz/protocols/nice_flo.c b/lib/subghz/protocols/nice_flo.c index 31f234dd1..ac2f1e41e 100644 --- a/lib/subghz/protocols/nice_flo.c +++ b/lib/subghz/protocols/nice_flo.c @@ -42,7 +42,8 @@ const SubGhzProtocolDecoder subghz_protocol_nice_flo_decoder = { .feed = subghz_protocol_decoder_nice_flo_feed, .reset = subghz_protocol_decoder_nice_flo_reset, - .get_hash_data = subghz_protocol_decoder_nice_flo_get_hash_data, + .get_hash_data = NULL, + .get_hash_data_long = subghz_protocol_decoder_nice_flo_get_hash_data, .serialize = subghz_protocol_decoder_nice_flo_serialize, .deserialize = subghz_protocol_decoder_nice_flo_deserialize, .get_string = subghz_protocol_decoder_nice_flo_get_string, diff --git a/lib/subghz/protocols/nice_flor_s.c b/lib/subghz/protocols/nice_flor_s.c index cc447d685..8ce944dff 100644 --- a/lib/subghz/protocols/nice_flor_s.c +++ b/lib/subghz/protocols/nice_flor_s.c @@ -60,7 +60,8 @@ const SubGhzProtocolDecoder subghz_protocol_nice_flor_s_decoder = { .feed = subghz_protocol_decoder_nice_flor_s_feed, .reset = subghz_protocol_decoder_nice_flor_s_reset, - .get_hash_data = subghz_protocol_decoder_nice_flor_s_get_hash_data, + .get_hash_data = NULL, + .get_hash_data_long = subghz_protocol_decoder_nice_flor_s_get_hash_data, .serialize = subghz_protocol_decoder_nice_flor_s_serialize, .deserialize = subghz_protocol_decoder_nice_flor_s_deserialize, .get_string = subghz_protocol_decoder_nice_flor_s_get_string, diff --git a/lib/subghz/protocols/oregon2.c b/lib/subghz/protocols/oregon2.c index 01b462af1..af92ab63d 100644 --- a/lib/subghz/protocols/oregon2.c +++ b/lib/subghz/protocols/oregon2.c @@ -414,7 +414,8 @@ const SubGhzProtocolDecoder ws_protocol_oregon2_decoder = { .feed = ws_protocol_decoder_oregon2_feed, .reset = ws_protocol_decoder_oregon2_reset, - .get_hash_data = ws_protocol_decoder_oregon2_get_hash_data, + .get_hash_data = NULL, + .get_hash_data_long = ws_protocol_decoder_oregon2_get_hash_data, .serialize = ws_protocol_decoder_oregon2_serialize, .deserialize = ws_protocol_decoder_oregon2_deserialize, .get_string = ws_protocol_decoder_oregon2_get_string, diff --git a/lib/subghz/protocols/oregon3.c b/lib/subghz/protocols/oregon3.c index 75c2d60d6..8d5a4a35d 100644 --- a/lib/subghz/protocols/oregon3.c +++ b/lib/subghz/protocols/oregon3.c @@ -350,7 +350,8 @@ const SubGhzProtocolDecoder ws_protocol_oregon3_decoder = { .feed = ws_protocol_decoder_oregon3_feed, .reset = ws_protocol_decoder_oregon3_reset, - .get_hash_data = ws_protocol_decoder_oregon3_get_hash_data, + .get_hash_data = NULL, + .get_hash_data_long = ws_protocol_decoder_oregon3_get_hash_data, .serialize = ws_protocol_decoder_oregon3_serialize, .deserialize = ws_protocol_decoder_oregon3_deserialize, .get_string = ws_protocol_decoder_oregon3_get_string, diff --git a/lib/subghz/protocols/oregon_v1.c b/lib/subghz/protocols/oregon_v1.c index b7593f005..65d6d7bb3 100644 --- a/lib/subghz/protocols/oregon_v1.c +++ b/lib/subghz/protocols/oregon_v1.c @@ -76,7 +76,8 @@ const SubGhzProtocolDecoder ws_protocol_oregon_v1_decoder = { .feed = ws_protocol_decoder_oregon_v1_feed, .reset = ws_protocol_decoder_oregon_v1_reset, - .get_hash_data = ws_protocol_decoder_oregon_v1_get_hash_data, + .get_hash_data = NULL, + .get_hash_data_long = ws_protocol_decoder_oregon_v1_get_hash_data, .serialize = ws_protocol_decoder_oregon_v1_serialize, .deserialize = ws_protocol_decoder_oregon_v1_deserialize, .get_string = ws_protocol_decoder_oregon_v1_get_string, diff --git a/lib/subghz/protocols/phoenix_v2.c b/lib/subghz/protocols/phoenix_v2.c index e1e2b9acc..33019dd16 100644 --- a/lib/subghz/protocols/phoenix_v2.c +++ b/lib/subghz/protocols/phoenix_v2.c @@ -45,7 +45,8 @@ const SubGhzProtocolDecoder subghz_protocol_phoenix_v2_decoder = { .feed = subghz_protocol_decoder_phoenix_v2_feed, .reset = subghz_protocol_decoder_phoenix_v2_reset, - .get_hash_data = subghz_protocol_decoder_phoenix_v2_get_hash_data, + .get_hash_data = NULL, + .get_hash_data_long = subghz_protocol_decoder_phoenix_v2_get_hash_data, .serialize = subghz_protocol_decoder_phoenix_v2_serialize, .deserialize = subghz_protocol_decoder_phoenix_v2_deserialize, .get_string = subghz_protocol_decoder_phoenix_v2_get_string, diff --git a/lib/subghz/protocols/pocsag.c b/lib/subghz/protocols/pocsag.c index 6cd7e67a2..0fa2c89d8 100644 --- a/lib/subghz/protocols/pocsag.c +++ b/lib/subghz/protocols/pocsag.c @@ -420,7 +420,8 @@ const SubGhzProtocolDecoder subghz_protocol_pocsag_decoder = { .free = subghz_protocol_decoder_pocsag_free, .reset = subghz_protocol_decoder_pocsag_reset, .feed = subghz_protocol_decoder_pocsag_feed, - .get_hash_data = subghz_protocol_decoder_pocsag_get_hash_data, + .get_hash_data = NULL, + .get_hash_data_long = subghz_protocol_decoder_pocsag_get_hash_data, .serialize = subghz_protocol_decoder_pocsag_serialize, .deserialize = subghz_protocol_decoder_pocsag_deserialize, .get_string = subhz_protocol_decoder_pocsag_get_string, diff --git a/lib/subghz/protocols/power_smart.c b/lib/subghz/protocols/power_smart.c index b75d3d8e7..256118b05 100644 --- a/lib/subghz/protocols/power_smart.c +++ b/lib/subghz/protocols/power_smart.c @@ -52,7 +52,8 @@ const SubGhzProtocolDecoder subghz_protocol_power_smart_decoder = { .feed = subghz_protocol_decoder_power_smart_feed, .reset = subghz_protocol_decoder_power_smart_reset, - .get_hash_data = subghz_protocol_decoder_power_smart_get_hash_data, + .get_hash_data = NULL, + .get_hash_data_long = subghz_protocol_decoder_power_smart_get_hash_data, .serialize = subghz_protocol_decoder_power_smart_serialize, .deserialize = subghz_protocol_decoder_power_smart_deserialize, .get_string = subghz_protocol_decoder_power_smart_get_string, diff --git a/lib/subghz/protocols/princeton.c b/lib/subghz/protocols/princeton.c index f8eee62e3..01c69b1f2 100644 --- a/lib/subghz/protocols/princeton.c +++ b/lib/subghz/protocols/princeton.c @@ -53,7 +53,8 @@ const SubGhzProtocolDecoder subghz_protocol_princeton_decoder = { .feed = subghz_protocol_decoder_princeton_feed, .reset = subghz_protocol_decoder_princeton_reset, - .get_hash_data = subghz_protocol_decoder_princeton_get_hash_data, + .get_hash_data = NULL, + .get_hash_data_long = subghz_protocol_decoder_princeton_get_hash_data, .serialize = subghz_protocol_decoder_princeton_serialize, .deserialize = subghz_protocol_decoder_princeton_deserialize, .get_string = subghz_protocol_decoder_princeton_get_string, diff --git a/lib/subghz/protocols/public_api.h b/lib/subghz/protocols/public_api.h index d7ae21c2a..37f3521f4 100644 --- a/lib/subghz/protocols/public_api.h +++ b/lib/subghz/protocols/public_api.h @@ -212,6 +212,10 @@ void subghz_protocol_decoder_bin_raw_data_input_rssi( */ bool subghz_protocol_secplus_v1_check_fixed(uint32_t fixed); +// Reset prog mode vars +// TODO: Remake in proper way +void faac_slh_reset_prog_mode(); + #ifdef __cplusplus } #endif diff --git a/lib/subghz/protocols/raw.c b/lib/subghz/protocols/raw.c index 35ac7fdd2..4b10b81c9 100644 --- a/lib/subghz/protocols/raw.c +++ b/lib/subghz/protocols/raw.c @@ -58,6 +58,7 @@ const SubGhzProtocolDecoder subghz_protocol_raw_decoder = { .reset = subghz_protocol_decoder_raw_reset, .get_hash_data = NULL, + .get_hash_data_long = NULL, .serialize = NULL, .deserialize = subghz_protocol_decoder_raw_deserialize, .get_string = subghz_protocol_decoder_raw_get_string, diff --git a/lib/subghz/protocols/scher_khan.c b/lib/subghz/protocols/scher_khan.c index dfe6c4a8f..1c91502ab 100644 --- a/lib/subghz/protocols/scher_khan.c +++ b/lib/subghz/protocols/scher_khan.c @@ -51,7 +51,8 @@ const SubGhzProtocolDecoder subghz_protocol_scher_khan_decoder = { .feed = subghz_protocol_decoder_scher_khan_feed, .reset = subghz_protocol_decoder_scher_khan_reset, - .get_hash_data = subghz_protocol_decoder_scher_khan_get_hash_data, + .get_hash_data = NULL, + .get_hash_data_long = subghz_protocol_decoder_scher_khan_get_hash_data, .serialize = subghz_protocol_decoder_scher_khan_serialize, .deserialize = subghz_protocol_decoder_scher_khan_deserialize, .get_string = subghz_protocol_decoder_scher_khan_get_string, diff --git a/lib/subghz/protocols/schrader_gg4.c b/lib/subghz/protocols/schrader_gg4.c index 562404975..963193589 100644 --- a/lib/subghz/protocols/schrader_gg4.c +++ b/lib/subghz/protocols/schrader_gg4.c @@ -82,7 +82,8 @@ const SubGhzProtocolDecoder tpms_protocol_schrader_gg4_decoder = { .feed = tpms_protocol_decoder_schrader_gg4_feed, .reset = tpms_protocol_decoder_schrader_gg4_reset, - .get_hash_data = tpms_protocol_decoder_schrader_gg4_get_hash_data, + .get_hash_data = NULL, + .get_hash_data_long = tpms_protocol_decoder_schrader_gg4_get_hash_data, .serialize = tpms_protocol_decoder_schrader_gg4_serialize, .deserialize = tpms_protocol_decoder_schrader_gg4_deserialize, .get_string = tpms_protocol_decoder_schrader_gg4_get_string, diff --git a/lib/subghz/protocols/secplus_v1.c b/lib/subghz/protocols/secplus_v1.c index d754d4328..a1f049caa 100644 --- a/lib/subghz/protocols/secplus_v1.c +++ b/lib/subghz/protocols/secplus_v1.c @@ -66,7 +66,8 @@ const SubGhzProtocolDecoder subghz_protocol_secplus_v1_decoder = { .feed = subghz_protocol_decoder_secplus_v1_feed, .reset = subghz_protocol_decoder_secplus_v1_reset, - .get_hash_data = subghz_protocol_decoder_secplus_v1_get_hash_data, + .get_hash_data = NULL, + .get_hash_data_long = subghz_protocol_decoder_secplus_v1_get_hash_data, .serialize = subghz_protocol_decoder_secplus_v1_serialize, .deserialize = subghz_protocol_decoder_secplus_v1_deserialize, .get_string = subghz_protocol_decoder_secplus_v1_get_string, diff --git a/lib/subghz/protocols/secplus_v2.c b/lib/subghz/protocols/secplus_v2.c index 0aa5e2508..3964e9262 100644 --- a/lib/subghz/protocols/secplus_v2.c +++ b/lib/subghz/protocols/secplus_v2.c @@ -60,7 +60,8 @@ const SubGhzProtocolDecoder subghz_protocol_secplus_v2_decoder = { .feed = subghz_protocol_decoder_secplus_v2_feed, .reset = subghz_protocol_decoder_secplus_v2_reset, - .get_hash_data = subghz_protocol_decoder_secplus_v2_get_hash_data, + .get_hash_data = NULL, + .get_hash_data_long = subghz_protocol_decoder_secplus_v2_get_hash_data, .serialize = subghz_protocol_decoder_secplus_v2_serialize, .deserialize = subghz_protocol_decoder_secplus_v2_deserialize, .get_string = subghz_protocol_decoder_secplus_v2_get_string, diff --git a/lib/subghz/protocols/smc5326.c b/lib/subghz/protocols/smc5326.c index dd990b74b..984f791fa 100644 --- a/lib/subghz/protocols/smc5326.c +++ b/lib/subghz/protocols/smc5326.c @@ -68,7 +68,8 @@ const SubGhzProtocolDecoder subghz_protocol_smc5326_decoder = { .feed = subghz_protocol_decoder_smc5326_feed, .reset = subghz_protocol_decoder_smc5326_reset, - .get_hash_data = subghz_protocol_decoder_smc5326_get_hash_data, + .get_hash_data = NULL, + .get_hash_data_long = subghz_protocol_decoder_smc5326_get_hash_data, .serialize = subghz_protocol_decoder_smc5326_serialize, .deserialize = subghz_protocol_decoder_smc5326_deserialize, .get_string = subghz_protocol_decoder_smc5326_get_string, diff --git a/lib/subghz/protocols/somfy_keytis.c b/lib/subghz/protocols/somfy_keytis.c index 110b3d2d7..6eeef77c6 100644 --- a/lib/subghz/protocols/somfy_keytis.c +++ b/lib/subghz/protocols/somfy_keytis.c @@ -49,7 +49,8 @@ const SubGhzProtocolDecoder subghz_protocol_somfy_keytis_decoder = { .feed = subghz_protocol_decoder_somfy_keytis_feed, .reset = subghz_protocol_decoder_somfy_keytis_reset, - .get_hash_data = subghz_protocol_decoder_somfy_keytis_get_hash_data, + .get_hash_data = NULL, + .get_hash_data_long = subghz_protocol_decoder_somfy_keytis_get_hash_data, .serialize = subghz_protocol_decoder_somfy_keytis_serialize, .deserialize = subghz_protocol_decoder_somfy_keytis_deserialize, .get_string = subghz_protocol_decoder_somfy_keytis_get_string, diff --git a/lib/subghz/protocols/somfy_telis.c b/lib/subghz/protocols/somfy_telis.c index 4f6c43a7a..421a3ac87 100644 --- a/lib/subghz/protocols/somfy_telis.c +++ b/lib/subghz/protocols/somfy_telis.c @@ -50,7 +50,8 @@ const SubGhzProtocolDecoder subghz_protocol_somfy_telis_decoder = { .feed = subghz_protocol_decoder_somfy_telis_feed, .reset = subghz_protocol_decoder_somfy_telis_reset, - .get_hash_data = subghz_protocol_decoder_somfy_telis_get_hash_data, + .get_hash_data = NULL, + .get_hash_data_long = subghz_protocol_decoder_somfy_telis_get_hash_data, .serialize = subghz_protocol_decoder_somfy_telis_serialize, .deserialize = subghz_protocol_decoder_somfy_telis_deserialize, .get_string = subghz_protocol_decoder_somfy_telis_get_string, diff --git a/lib/subghz/protocols/star_line.c b/lib/subghz/protocols/star_line.c index 87483e748..f48359c9e 100644 --- a/lib/subghz/protocols/star_line.c +++ b/lib/subghz/protocols/star_line.c @@ -60,7 +60,8 @@ const SubGhzProtocolDecoder subghz_protocol_star_line_decoder = { .feed = subghz_protocol_decoder_star_line_feed, .reset = subghz_protocol_decoder_star_line_reset, - .get_hash_data = subghz_protocol_decoder_star_line_get_hash_data, + .get_hash_data = NULL, + .get_hash_data_long = subghz_protocol_decoder_star_line_get_hash_data, .serialize = subghz_protocol_decoder_star_line_serialize, .deserialize = subghz_protocol_decoder_star_line_deserialize, .get_string = subghz_protocol_decoder_star_line_get_string, diff --git a/lib/subghz/protocols/thermopro_tx4.c b/lib/subghz/protocols/thermopro_tx4.c index f809bee93..7e34dda91 100644 --- a/lib/subghz/protocols/thermopro_tx4.c +++ b/lib/subghz/protocols/thermopro_tx4.c @@ -60,7 +60,8 @@ const SubGhzProtocolDecoder ws_protocol_thermopro_tx4_decoder = { .feed = ws_protocol_decoder_thermopro_tx4_feed, .reset = ws_protocol_decoder_thermopro_tx4_reset, - .get_hash_data = ws_protocol_decoder_thermopro_tx4_get_hash_data, + .get_hash_data = NULL, + .get_hash_data_long = ws_protocol_decoder_thermopro_tx4_get_hash_data, .serialize = ws_protocol_decoder_thermopro_tx4_serialize, .deserialize = ws_protocol_decoder_thermopro_tx4_deserialize, .get_string = ws_protocol_decoder_thermopro_tx4_get_string, diff --git a/lib/subghz/protocols/tx_8300.c b/lib/subghz/protocols/tx_8300.c index 247304b57..012153c33 100644 --- a/lib/subghz/protocols/tx_8300.c +++ b/lib/subghz/protocols/tx_8300.c @@ -71,7 +71,8 @@ const SubGhzProtocolDecoder ws_protocol_tx_8300_decoder = { .feed = ws_protocol_decoder_tx_8300_feed, .reset = ws_protocol_decoder_tx_8300_reset, - .get_hash_data = ws_protocol_decoder_tx_8300_get_hash_data, + .get_hash_data = NULL, + .get_hash_data_long = ws_protocol_decoder_tx_8300_get_hash_data, .serialize = ws_protocol_decoder_tx_8300_serialize, .deserialize = ws_protocol_decoder_tx_8300_deserialize, .get_string = ws_protocol_decoder_tx_8300_get_string, diff --git a/lib/subghz/protocols/wendox_w6726.c b/lib/subghz/protocols/wendox_w6726.c index a19568b8e..54160853b 100644 --- a/lib/subghz/protocols/wendox_w6726.c +++ b/lib/subghz/protocols/wendox_w6726.c @@ -65,7 +65,8 @@ const SubGhzProtocolDecoder ws_protocol_wendox_w6726_decoder = { .feed = ws_protocol_decoder_wendox_w6726_feed, .reset = ws_protocol_decoder_wendox_w6726_reset, - .get_hash_data = ws_protocol_decoder_wendox_w6726_get_hash_data, + .get_hash_data = NULL, + .get_hash_data_long = ws_protocol_decoder_wendox_w6726_get_hash_data, .serialize = ws_protocol_decoder_wendox_w6726_serialize, .deserialize = ws_protocol_decoder_wendox_w6726_deserialize, .get_string = ws_protocol_decoder_wendox_w6726_get_string, diff --git a/lib/subghz/protocols/x10.c b/lib/subghz/protocols/x10.c index 546fce550..a4a385be7 100644 --- a/lib/subghz/protocols/x10.c +++ b/lib/subghz/protocols/x10.c @@ -71,7 +71,8 @@ const SubGhzProtocolDecoder subghz_protocol_x10_decoder = { .free = subghz_protocol_decoder_x10_free, .feed = subghz_protocol_decoder_x10_feed, .reset = subghz_protocol_decoder_x10_reset, - .get_hash_data = subghz_protocol_decoder_x10_get_hash_data, + .get_hash_data = NULL, + .get_hash_data_long = subghz_protocol_decoder_x10_get_hash_data, .serialize = subghz_protocol_decoder_x10_serialize, .deserialize = subghz_protocol_decoder_x10_deserialize, .get_string = subghz_protocol_decoder_x10_get_string, diff --git a/lib/subghz/subghz_setting.c b/lib/subghz/subghz_setting.c index 43f270978..480cda532 100644 --- a/lib/subghz/subghz_setting.c +++ b/lib/subghz/subghz_setting.c @@ -43,6 +43,7 @@ static const uint32_t subghz_frequency_list[] = { 390000000, 418000000, 430000000, + 430500000, 431000000, 431500000, 433075000, /* LPD433 first */ diff --git a/lib/subghz/types.h b/lib/subghz/types.h index ca059e551..0a50ab5b3 100644 --- a/lib/subghz/types.h +++ b/lib/subghz/types.h @@ -78,7 +78,8 @@ typedef SubGhzProtocolStatus (*SubGhzDeserialize)(void* context, FlipperFormat* // Decoder specific typedef void (*SubGhzDecoderFeed)(void* decoder, bool level, uint32_t duration); typedef void (*SubGhzDecoderReset)(void* decoder); -typedef uint32_t (*SubGhzGetHashData)(void* decoder); +typedef uint8_t (*SubGhzGetHashData)(void* decoder); +typedef uint32_t (*SubGhzGetHashDataLong)(void* decoder); typedef void (*SubGhzGetString)(void* decoder, FuriString* output); // Encoder specific @@ -96,6 +97,8 @@ typedef struct { SubGhzGetString get_string; SubGhzSerialize serialize; SubGhzDeserialize deserialize; + + SubGhzGetHashDataLong get_hash_data_long; } SubGhzProtocolDecoder; typedef struct { diff --git a/lib/toolbox/name_generator.c b/lib/toolbox/name_generator.c index b676fe372..6cbc17d49 100644 --- a/lib/toolbox/name_generator.c +++ b/lib/toolbox/name_generator.c @@ -13,36 +13,41 @@ const char* const name_generator_left[] = { "big", "little", "liquid", - "unknown", - "thin", + "qq", + "cheeky", "thick", - "great", - "my", - "mini", + "sneaky", + "quick", + "quantum", + "kurwa", + "feral", + "smart", + "yappy", "ultra", - "haupt", - "small", + "whois", "random", - "strange", + "looshite", }; const char* const name_generator_right[] = { - "maslina", + "bidet", "sus", - "anomalija", - "artefact", - "monolit", - "burer", + "fed", + "moroder", + "bobr", + "chomik", "sidorovich", - "habar", - "radar", - "borov", - "pda", - "konserva", - "aptechka", - "door", - "thing", - "stuff", + "stalker", + "yapper", + "bnuuy", + "jezyk", + "juzyk", + "cult", + "pp", + "zalaz", + "breeky", + "pingwin", + "kot", }; void name_generator_make_auto_datetime( @@ -63,6 +68,15 @@ void name_generator_make_auto(char* name, size_t max_name_size, const char* pref name_generator_make_auto_datetime(name, max_name_size, prefix, NULL); } +void name_generator_make_auto_basic(char* name, size_t max_name_size, const char* prefix) { + if(!furi_hal_rtc_is_flag_set(FuriHalRtcFlagRandomFilename)) { + name_generator_make_detailed_datetime( + name, max_name_size, prefix, NULL, momentum_settings.file_naming_prefix_after); + } else { + name_generator_make_random(name, max_name_size); + } +} + void name_generator_make_random_prefixed( char* name, size_t max_name_size, diff --git a/lib/toolbox/name_generator.h b/lib/toolbox/name_generator.h index c6139fb92..f8d4ecc8e 100644 --- a/lib/toolbox/name_generator.h +++ b/lib/toolbox/name_generator.h @@ -21,6 +21,9 @@ void name_generator_make_auto_datetime( const char* prefix, DateTime* custom_time); +// Generate name without prefix in random names +void name_generator_make_auto_basic(char* name, size_t max_name_size, const char* prefix); + /** Generates random name * * @param name buffer to write random name diff --git a/scripts/assets.py b/scripts/assets.py index 9c33dac76..3dcbda4b5 100755 --- a/scripts/assets.py +++ b/scripts/assets.py @@ -139,9 +139,10 @@ class Main(App): icons = [] paths = [] is_main_assets = self.args.filename == "assets_icons" - symbols = ( - pathlib.Path(__file__).parent / "../targets/f7/api_symbols.csv" - ).read_text() + symbols = pathlib.Path(__file__).parent.parent + if "UFBT_HOME" in os.environ: + symbols /= "sdk_headers/f7_sdk" + symbols = (symbols / "targets/f7/api_symbols.csv").read_text() api_has_icon = lambda name: f"Variable,+,{name},Icon," in symbols # Traverse icons tree, append image data to source file for dirpath, dirnames, filenames in os.walk(self.args.input_directory): diff --git a/targets/f18/api_symbols.csv b/targets/f18/api_symbols.csv index bdfa8c7a4..8f6b8530e 100644 --- a/targets/f18/api_symbols.csv +++ b/targets/f18/api_symbols.csv @@ -1,5 +1,5 @@ entry,status,name,type,params -Version,+,58.0,, +Version,+,58.1,, Header,+,applications/services/bt/bt_service/bt.h,, Header,+,applications/services/cli/cli.h,, Header,+,applications/services/cli/cli_vcp.h,, diff --git a/targets/f7/api_symbols.csv b/targets/f7/api_symbols.csv index 6a738babe..5e9783b1f 100644 --- a/targets/f7/api_symbols.csv +++ b/targets/f7/api_symbols.csv @@ -1,5 +1,5 @@ entry,status,name,type,params -Version,+,58.0,, +Version,+,58.1,, Header,+,applications/drivers/subghz/cc1101_ext/cc1101_ext_interconnect.h,, Header,+,applications/main/archive/helpers/archive_helpers_ext.h,, Header,+,applications/main/subghz/subghz_fap.h,, @@ -1043,6 +1043,7 @@ Function,-,explicit_bzero,void,"void*, size_t" Function,-,expm1,double,double Function,-,expm1f,float,float Function,-,expm1l,long double,long double +Function,+,faac_slh_reset_prog_mode,void, Function,-,fabs,double,double Function,-,fabsf,float,float Function,-,fabsl,long double,long double @@ -2553,6 +2554,7 @@ Function,+,mf_desfire_poller_read_file_settings_multi,MfDesfireError,"MfDesfireP Function,+,mf_desfire_poller_read_file_value,MfDesfireError,"MfDesfirePoller*, MfDesfireFileId, MfDesfireFileData*" Function,+,mf_desfire_poller_read_free_memory,MfDesfireError,"MfDesfirePoller*, MfDesfireFreeMemory*" Function,+,mf_desfire_poller_read_key_settings,MfDesfireError,"MfDesfirePoller*, MfDesfireKeySettings*" +Function,+,mf_desfire_poller_read_key_version,MfDesfireError,"MfDesfirePoller*, uint8_t, MfDesfireKeyVersion*" Function,+,mf_desfire_poller_read_key_versions,MfDesfireError,"MfDesfirePoller*, SimpleArray*, uint32_t" Function,+,mf_desfire_poller_read_version,MfDesfireError,"MfDesfirePoller*, MfDesfireVersion*" Function,+,mf_desfire_poller_select_application,MfDesfireError,"MfDesfirePoller*, const MfDesfireApplicationId*" @@ -2707,6 +2709,7 @@ Function,-,music_worker_set_volume,void,"MusicWorker*, float" Function,-,music_worker_start,void,MusicWorker* Function,-,music_worker_stop,void,MusicWorker* Function,+,name_generator_make_auto,void,"char*, size_t, const char*" +Function,+,name_generator_make_auto_basic,void,"char*, size_t, const char*" Function,+,name_generator_make_auto_datetime,void,"char*, size_t, const char*, DateTime*" Function,+,name_generator_make_detailed,void,"char*, size_t, const char*" Function,+,name_generator_make_detailed_datetime,void,"char*, size_t, const char*, DateTime*, _Bool" @@ -3353,14 +3356,14 @@ Function,+,subghz_file_encoder_worker_get_text_progress,void,"SubGhzFileEncoderW Function,+,subghz_file_encoder_worker_is_running,_Bool,SubGhzFileEncoderWorker* Function,+,subghz_file_encoder_worker_start,_Bool,"SubGhzFileEncoderWorker*, const char*, const char*" Function,+,subghz_file_encoder_worker_stop,void,SubGhzFileEncoderWorker* -Function,-,subghz_keystore_alloc,SubGhzKeystore*, -Function,-,subghz_keystore_free,void,SubGhzKeystore* +Function,+,subghz_keystore_alloc,SubGhzKeystore*, +Function,+,subghz_keystore_free,void,SubGhzKeystore* Function,-,subghz_keystore_get_data,SubGhzKeyArray_t*,SubGhzKeystore* -Function,-,subghz_keystore_load,_Bool,"SubGhzKeystore*, const char*" -Function,-,subghz_keystore_raw_encrypted_save,_Bool,"const char*, const char*, uint8_t*" +Function,+,subghz_keystore_load,_Bool,"SubGhzKeystore*, const char*" +Function,+,subghz_keystore_raw_encrypted_save,_Bool,"const char*, const char*, uint8_t*" Function,-,subghz_keystore_raw_get_data,_Bool,"const char*, size_t, uint8_t*, size_t" Function,-,subghz_keystore_reset_kl,void,SubGhzKeystore* -Function,-,subghz_keystore_save,_Bool,"SubGhzKeystore*, const char*, uint8_t*" +Function,+,subghz_keystore_save,_Bool,"SubGhzKeystore*, const char*, uint8_t*" Function,+,subghz_protocol_alutech_at_4n_create_data,_Bool,"void*, FlipperFormat*, uint32_t, uint8_t, uint16_t, SubGhzRadioPreset*" Function,+,subghz_protocol_blocks_add_bit,void,"SubGhzBlockDecoder*, uint8_t" Function,+,subghz_protocol_blocks_add_bytes,uint8_t,"const uint8_t[], size_t" @@ -3870,6 +3873,7 @@ Variable,+,I_exit_hover_19x20,Icon, Variable,+,I_exit_text_18x5,Icon, Variable,+,I_fahren_24x23,Icon, Variable,+,I_fahren_hover_24x23,Icon, +Variable,+,I_file_10px,Icon, Variable,+,I_flash_19x20,Icon, Variable,+,I_flash_hover_19x20,Icon, Variable,+,I_flash_text_21x5,Icon,