diff --git a/applications/debug/unit_tests/subghz/subghz_test.c b/applications/debug/unit_tests/subghz/subghz_test.c index 1900f2045..80a1c1040 100644 --- a/applications/debug/unit_tests/subghz/subghz_test.c +++ b/applications/debug/unit_tests/subghz/subghz_test.c @@ -42,8 +42,6 @@ static void subghz_test_rx_callback( static void subghz_test_init(void) { environment_handler = subghz_environment_alloc(); - subghz_environment_set_came_atomo_rainbow_table_file_name( - environment_handler, CAME_ATOMO_DIR_NAME); subghz_environment_set_nice_flor_s_rainbow_table_file_name( environment_handler, NICE_FLOR_S_DIR_NAME); subghz_environment_set_alutech_at_4n_rainbow_table_file_name( diff --git a/applications/main/ibutton/ibutton.c b/applications/main/ibutton/ibutton.c index 3c2cd28a7..f3ac2c739 100644 --- a/applications/main/ibutton/ibutton.c +++ b/applications/main/ibutton/ibutton.c @@ -196,6 +196,7 @@ bool ibutton_load_key(iButton* ibutton) { bool ibutton_select_and_load_key(iButton* ibutton) { DialogsFileBrowserOptions browser_options; + bool success = false; dialog_file_browser_set_basic_options( &browser_options, IBUTTON_APP_FILENAME_EXTENSION, &I_ibutt_10px); browser_options.base_path = IBUTTON_APP_FOLDER; @@ -204,9 +205,14 @@ bool ibutton_select_and_load_key(iButton* ibutton) { furi_string_set(ibutton->file_path, browser_options.base_path); } - return dialog_file_browser_show( - ibutton->dialogs, ibutton->file_path, ibutton->file_path, &browser_options) && - ibutton_load_key(ibutton); + do { + if(!dialog_file_browser_show( + ibutton->dialogs, ibutton->file_path, ibutton->file_path, &browser_options)) + break; + success = ibutton_load_key(ibutton); + } while(!success); + + return success; } bool ibutton_save_key(iButton* ibutton) { diff --git a/applications/main/subghz/helpers/subghz_custom_event.h b/applications/main/subghz/helpers/subghz_custom_event.h index e5321264e..d59d0ea3c 100644 --- a/applications/main/subghz/helpers/subghz_custom_event.h +++ b/applications/main/subghz/helpers/subghz_custom_event.h @@ -6,6 +6,8 @@ typedef enum { SubGhzCustomEventManagerSetRAW, //SubmenuIndex + SubmenuIndexFaacSLH_Manual_433, + SubmenuIndexFaacSLH_Manual_868, SubmenuIndexFaacSLH_433, SubmenuIndexFaacSLH_868, SubmenuIndexBFTClone, diff --git a/applications/main/subghz/helpers/subghz_txrx.c b/applications/main/subghz/helpers/subghz_txrx.c index 5c36a781a..c3f8ad445 100644 --- a/applications/main/subghz/helpers/subghz_txrx.c +++ b/applications/main/subghz/helpers/subghz_txrx.c @@ -46,8 +46,6 @@ SubGhzTxRx* subghz_txrx_alloc() { instance->is_database_loaded = subghz_environment_load_keystore(instance->environment, SUBGHZ_KEYSTORE_DIR_NAME); subghz_environment_load_keystore(instance->environment, SUBGHZ_KEYSTORE_DIR_USER_NAME); - subghz_environment_set_came_atomo_rainbow_table_file_name( - instance->environment, SUBGHZ_CAME_ATOMO_DIR_NAME); subghz_environment_set_alutech_at_4n_rainbow_table_file_name( instance->environment, SUBGHZ_ALUTECH_AT_4N_DIR_NAME); subghz_environment_set_nice_flor_s_rainbow_table_file_name( @@ -665,6 +663,8 @@ void subghz_txrx_reset_dynamic_and_custom_btns(SubGhzTxRx* instance) { furi_assert(instance); subghz_environment_reset_keeloq(instance->environment); + faac_slh_reset_prog_mode(); + subghz_custom_btns_reset(); } diff --git a/applications/main/subghz/helpers/subghz_txrx_create_protocol_key.c b/applications/main/subghz/helpers/subghz_txrx_create_protocol_key.c index a83e17da6..040aff46c 100644 --- a/applications/main/subghz/helpers/subghz_txrx_create_protocol_key.c +++ b/applications/main/subghz/helpers/subghz_txrx_create_protocol_key.c @@ -228,7 +228,9 @@ bool subghz_txrx_gen_faac_slh_protocol( seed_data[sizeof(uint32_t) - i - 1] = (seed >> i * 8) & 0xFF; } + bool tmp_allow_zero_seed = true; flipper_format_write_hex(txrx->fff_data, "Seed", seed_data, sizeof(uint32_t)); + flipper_format_write_bool(txrx->fff_data, "AllowZeroSeed", &tmp_allow_zero_seed, 1); } subghz_transmitter_free(txrx->transmitter); diff --git a/applications/main/subghz/scenes/subghz_scene_config.h b/applications/main/subghz/scenes/subghz_scene_config.h index ddff47208..b12a66f98 100644 --- a/applications/main/subghz/scenes/subghz_scene_config.h +++ b/applications/main/subghz/scenes/subghz_scene_config.h @@ -23,4 +23,4 @@ ADD_SCENE(subghz, more_raw, MoreRAW) ADD_SCENE(subghz, decode_raw, DecodeRAW) ADD_SCENE(subghz, delete_raw, DeleteRAW) ADD_SCENE(subghz, need_saving, NeedSaving) -ADD_SCENE(subghz, rpc, Rpc) +ADD_SCENE(subghz, rpc, Rpc) \ No newline at end of file diff --git a/applications/main/subghz/scenes/subghz_scene_radio_settings.c b/applications/main/subghz/scenes/subghz_scene_radio_settings.c index 6f2b99b26..969c7c1a9 100644 --- a/applications/main/subghz/scenes/subghz_scene_radio_settings.c +++ b/applications/main/subghz/scenes/subghz_scene_radio_settings.c @@ -32,7 +32,7 @@ const char* const debug_pin_text[DEBUG_P_COUNT] = { "17(1W)", }; -#define DEBUG_COUNTER_COUNT 6 +#define DEBUG_COUNTER_COUNT 13 const char* const debug_counter_text[DEBUG_COUNTER_COUNT] = { "+1", "+2", @@ -40,6 +40,13 @@ const char* const debug_counter_text[DEBUG_COUNTER_COUNT] = { "+4", "+5", "+10", + "0", + "-1", + "-2", + "-3", + "-4", + "-5", + "-10", }; const uint32_t debug_counter_val[DEBUG_COUNTER_COUNT] = { 1, @@ -48,6 +55,13 @@ const uint32_t debug_counter_val[DEBUG_COUNTER_COUNT] = { 4, 5, 10, + 0, + -1, + -2, + -3, + -4, + -5, + -10, }; static void subghz_scene_radio_settings_set_device(VariableItem* item) { diff --git a/applications/main/subghz/scenes/subghz_scene_save_name.c b/applications/main/subghz/scenes/subghz_scene_save_name.c index 3dd03cba1..80aedcb0d 100644 --- a/applications/main/subghz/scenes/subghz_scene_save_name.c +++ b/applications/main/subghz/scenes/subghz_scene_save_name.c @@ -130,7 +130,15 @@ bool subghz_scene_save_name_on_event(void* context, SceneManagerEvent event) { furi_string_set(subghz->file_path, subghz->file_path_tmp); } } - scene_manager_previous_scene(subghz->scene_manager); + if(scene_manager_has_previous_scene(subghz->scene_manager, SubGhzSceneSetSeed)) { + scene_manager_search_and_switch_to_previous_scene( + subghz->scene_manager, SubGhzSceneSetType); + } else { + scene_manager_previous_scene(subghz->scene_manager); + } + // Set file path to default + furi_string_set(subghz->file_path, SUBGHZ_APP_FOLDER); + return true; } else if(event.type == SceneManagerEventTypeCustom) { if(event.event == SubGhzCustomEventSceneSaveName) { diff --git a/applications/main/subghz/scenes/subghz_scene_saved_menu.c b/applications/main/subghz/scenes/subghz_scene_saved_menu.c index a65830f4b..6897a2d8a 100644 --- a/applications/main/subghz/scenes/subghz_scene_saved_menu.c +++ b/applications/main/subghz/scenes/subghz_scene_saved_menu.c @@ -19,7 +19,7 @@ void subghz_scene_saved_menu_on_enter(void* context) { SubmenuIndexEmulate, subghz_scene_saved_menu_submenu_callback, subghz); - + submenu_add_item( subghz->submenu, "Rename", diff --git a/applications/main/subghz/scenes/subghz_scene_set_cnt.c b/applications/main/subghz/scenes/subghz_scene_set_cnt.c index 4faff7bbb..0a07557fb 100644 --- a/applications/main/subghz/scenes/subghz_scene_set_cnt.c +++ b/applications/main/subghz/scenes/subghz_scene_set_cnt.c @@ -18,7 +18,7 @@ void subghz_scene_set_cnt_on_enter(void* context) { switch(state) { case SubmenuIndexBFTClone: - byte_input_set_header_text(byte_input, "Enter COUNTER in hex"); + byte_input_set_header_text(byte_input, "Enter COUNTER in Hex"); byte_input_set_result_callback( byte_input, subghz_scene_set_cnt_byte_input_callback, @@ -27,9 +27,9 @@ void subghz_scene_set_cnt_on_enter(void* context) { subghz->secure_data->cnt, 2); break; - case SubmenuIndexFaacSLH_433: - case SubmenuIndexFaacSLH_868: - byte_input_set_header_text(byte_input, "Enter COUNTER in hex, 20bits"); + case SubmenuIndexFaacSLH_Manual_433: + case SubmenuIndexFaacSLH_Manual_868: + byte_input_set_header_text(byte_input, "Enter COUNTER in Hex 20 bits"); byte_input_set_result_callback( byte_input, subghz_scene_set_cnt_byte_input_callback, diff --git a/applications/main/subghz/scenes/subghz_scene_set_fix.c b/applications/main/subghz/scenes/subghz_scene_set_fix.c index 7564fb24d..b58f39ddd 100644 --- a/applications/main/subghz/scenes/subghz_scene_set_fix.c +++ b/applications/main/subghz/scenes/subghz_scene_set_fix.c @@ -13,7 +13,7 @@ void subghz_scene_set_fix_on_enter(void* context) { // Setup view ByteInput* byte_input = subghz->byte_input; - byte_input_set_header_text(byte_input, "Enter FIX in hex"); + byte_input_set_header_text(byte_input, "Enter FIX in Hex"); byte_input_set_result_callback( byte_input, subghz_scene_set_fix_byte_input_callback, diff --git a/applications/main/subghz/scenes/subghz_scene_set_seed.c b/applications/main/subghz/scenes/subghz_scene_set_seed.c index e5778b84f..c1f3662cb 100644 --- a/applications/main/subghz/scenes/subghz_scene_set_seed.c +++ b/applications/main/subghz/scenes/subghz_scene_set_seed.c @@ -14,7 +14,7 @@ void subghz_scene_set_seed_on_enter(void* context) { // Setup view ByteInput* byte_input = subghz->byte_input; - byte_input_set_header_text(byte_input, "Enter SEED in hex"); + byte_input_set_header_text(byte_input, "Enter SEED in Hex"); byte_input_set_result_callback( byte_input, subghz_scene_set_seed_byte_input_callback, @@ -45,13 +45,6 @@ bool subghz_scene_set_seed_on_event(void* context, SceneManagerEvent event) { seed = subghz->secure_data->seed[0] << 24 | subghz->secure_data->seed[1] << 16 | subghz->secure_data->seed[2] << 8 | subghz->secure_data->seed[3]; - if(seed == 0) { - furi_string_set(subghz->error_str, "Seed value\ncan not be 0."); - scene_manager_next_scene(subghz->scene_manager, SubGhzSceneShowError); - consumed = true; - break; - } - generated_protocol = subghz_txrx_gen_keeloq_bft_protocol( subghz->txrx, "AM650", @@ -69,8 +62,8 @@ bool subghz_scene_set_seed_on_event(void* context, SceneManagerEvent event) { } consumed = true; break; - case SubmenuIndexFaacSLH_433: - case SubmenuIndexFaacSLH_868: + case SubmenuIndexFaacSLH_Manual_433: + case SubmenuIndexFaacSLH_Manual_868: fix_part = subghz->secure_data->fix[0] << 24 | subghz->secure_data->fix[1] << 16 | subghz->secure_data->fix[2] << 8 | subghz->secure_data->fix[3]; @@ -80,13 +73,7 @@ bool subghz_scene_set_seed_on_event(void* context, SceneManagerEvent event) { seed = subghz->secure_data->seed[0] << 24 | subghz->secure_data->seed[1] << 16 | subghz->secure_data->seed[2] << 8 | subghz->secure_data->seed[3]; - if(seed == 0) { - furi_string_set(subghz->error_str, "Seed value\ncan not be 0."); - scene_manager_next_scene(subghz->scene_manager, SubGhzSceneShowError); - consumed = true; - break; - } - if(state == SubmenuIndexFaacSLH_433) { + if(state == SubmenuIndexFaacSLH_Manual_433) { generated_protocol = subghz_txrx_gen_faac_slh_protocol( subghz->txrx, "AM650", @@ -96,7 +83,7 @@ bool subghz_scene_set_seed_on_event(void* context, SceneManagerEvent event) { (cnt & 0xFFFFF), seed, "FAAC_SLH"); - } else if(state == SubmenuIndexFaacSLH_868) { + } else if(state == SubmenuIndexFaacSLH_Manual_868) { generated_protocol = subghz_txrx_gen_faac_slh_protocol( subghz->txrx, "AM650", diff --git a/applications/main/subghz/scenes/subghz_scene_set_type.c b/applications/main/subghz/scenes/subghz_scene_set_type.c index e5a92608e..062bc813a 100644 --- a/applications/main/subghz/scenes/subghz_scene_set_type.c +++ b/applications/main/subghz/scenes/subghz_scene_set_type.c @@ -15,14 +15,14 @@ void subghz_scene_set_type_on_enter(void* context) { submenu_add_item( subghz->submenu, - "Faac SLH 868MHz", - SubmenuIndexFaacSLH_868, + "FAAC SLH [Man.] 868MHz", + SubmenuIndexFaacSLH_Manual_868, subghz_scene_set_type_submenu_callback, subghz); submenu_add_item( subghz->submenu, - "Faac SLH 433MHz", - SubmenuIndexFaacSLH_433, + "FAAC SLH [Man.] 433MHz", + SubmenuIndexFaacSLH_Manual_433, subghz_scene_set_type_submenu_callback, subghz); submenu_add_item( @@ -31,6 +31,18 @@ void subghz_scene_set_type_on_enter(void* context) { SubmenuIndexBFTClone, subghz_scene_set_type_submenu_callback, subghz); + submenu_add_item( + subghz->submenu, + "FAAC SLH 868MHz", + SubmenuIndexFaacSLH_868, + subghz_scene_set_type_submenu_callback, + subghz); + submenu_add_item( + subghz->submenu, + "FAAC SLH 433MHz", + SubmenuIndexFaacSLH_433, + subghz_scene_set_type_submenu_callback, + subghz); submenu_add_item( subghz->submenu, "BFT Mitto 433MHz", @@ -319,10 +331,10 @@ bool subghz_scene_set_type_on_event(void* context, SceneManagerEvent event) { if(event.type == SceneManagerEventTypeCustom) { uint32_t key = (uint32_t)rand(); switch(event.event) { - case SubmenuIndexFaacSLH_868: + case SubmenuIndexFaacSLH_Manual_868: scene_manager_next_scene(subghz->scene_manager, SubGhzSceneSetFix); break; - case SubmenuIndexFaacSLH_433: + case SubmenuIndexFaacSLH_Manual_433: scene_manager_next_scene(subghz->scene_manager, SubGhzSceneSetFix); break; case SubmenuIndexBFTClone: @@ -390,6 +402,38 @@ bool subghz_scene_set_type_on_event(void* context, SceneManagerEvent event) { generated_protocol = subghz_txrx_gen_data_protocol( subghz->txrx, "AM650", 433920000, SUBGHZ_PROTOCOL_GATE_TX_NAME, rev_key, 24); break; + case SubmenuIndexFaacSLH_433: + generated_protocol = subghz_txrx_gen_faac_slh_protocol( + subghz->txrx, + "AM650", + 433920000, + ((key & 0x00FFFFF0) | 0xA0000006) >> 4, + 0x6, + 0x00002, + key, + "FAAC_SLH"); + if(!generated_protocol) { + furi_string_set( + subghz->error_str, "Function requires\nan SD card with\nfresh databases."); + scene_manager_next_scene(subghz->scene_manager, SubGhzSceneShowError); + } + break; + case SubmenuIndexFaacSLH_868: + generated_protocol = subghz_txrx_gen_faac_slh_protocol( + subghz->txrx, + "AM650", + 868350000, + ((key & 0x00FFFFF0) | 0xA0000006) >> 4, + 0x6, + 0x00002, + key, + "FAAC_SLH"); + if(!generated_protocol) { + furi_string_set( + subghz->error_str, "Function requires\nan SD card with\nfresh databases."); + scene_manager_next_scene(subghz->scene_manager, SubGhzSceneShowError); + } + break; case SubmenuIndexBeninca433: generated_protocol = subghz_txrx_gen_keeloq_protocol( subghz->txrx, diff --git a/applications/main/subghz/scenes/subghz_scene_transmitter.c b/applications/main/subghz/scenes/subghz_scene_transmitter.c index 48dc69ea0..36c694d2b 100644 --- a/applications/main/subghz/scenes/subghz_scene_transmitter.c +++ b/applications/main/subghz/scenes/subghz_scene_transmitter.c @@ -101,11 +101,15 @@ bool subghz_scene_transmitter_on_event(void* context, SceneManagerEvent event) { subghz_txrx_stop(subghz->txrx); if(subghz_custom_btn_get() != SUBGHZ_CUSTOM_BTN_OK) { subghz_custom_btn_set(SUBGHZ_CUSTOM_BTN_OK); - uint8_t tmp_counter = furi_hal_subghz_get_rolling_counter_mult(); + int8_t tmp_counter = furi_hal_subghz_get_rolling_counter_mult(); furi_hal_subghz_set_rolling_counter_mult(0); // Calling restore! subghz_tx_start(subghz, subghz_txrx_get_fff_data(subghz->txrx)); subghz_txrx_stop(subghz->txrx); + // Calling restore 2nd time special for FAAC SLH! + // TODO: Find better way to restore after custom button is used!!! + subghz_tx_start(subghz, subghz_txrx_get_fff_data(subghz->txrx)); + subghz_txrx_stop(subghz->txrx); furi_hal_subghz_set_rolling_counter_mult(tmp_counter); } if(subghz->fav_timeout) { diff --git a/applications/main/subghz/subghz_cli.c b/applications/main/subghz/subghz_cli.c index 273251de0..b9494d213 100644 --- a/applications/main/subghz/subghz_cli.c +++ b/applications/main/subghz/subghz_cli.c @@ -326,8 +326,6 @@ void subghz_cli_command_rx(Cli* cli, FuriString* args, void* context) { SubGhzEnvironment* environment = subghz_environment_alloc(); subghz_environment_load_keystore(environment, SUBGHZ_KEYSTORE_DIR_NAME); subghz_environment_load_keystore(environment, SUBGHZ_KEYSTORE_DIR_USER_NAME); - subghz_environment_set_came_atomo_rainbow_table_file_name( - environment, SUBGHZ_CAME_ATOMO_DIR_NAME); subghz_environment_set_alutech_at_4n_rainbow_table_file_name( environment, SUBGHZ_ALUTECH_AT_4N_DIR_NAME); subghz_environment_set_nice_flor_s_rainbow_table_file_name( @@ -526,8 +524,6 @@ void subghz_cli_command_decode_raw(Cli* cli, FuriString* args, void* context) { printf( "SubGhz decode_raw: Load_keystore keeloq_mfcodes_user \033[0;31mERROR\033[0m\r\n"); } - subghz_environment_set_came_atomo_rainbow_table_file_name( - environment, SUBGHZ_CAME_ATOMO_DIR_NAME); subghz_environment_set_alutech_at_4n_rainbow_table_file_name( environment, SUBGHZ_ALUTECH_AT_4N_DIR_NAME); subghz_environment_set_nice_flor_s_rainbow_table_file_name( diff --git a/applications/main/subghz/subghz_i.h b/applications/main/subghz/subghz_i.h index 340cdb137..41b085b03 100644 --- a/applications/main/subghz/subghz_i.h +++ b/applications/main/subghz/subghz_i.h @@ -45,7 +45,7 @@ typedef struct { uint8_t fix[4]; - uint8_t cnt[3]; + uint8_t cnt[4]; uint8_t seed[4]; } SecureData; diff --git a/applications/services/gui/elements.c b/applications/services/gui/elements.c index 4944b3ac9..3578411f7 100644 --- a/applications/services/gui/elements.c +++ b/applications/services/gui/elements.c @@ -313,7 +313,8 @@ void elements_multiline_text_aligned( } else if((y + font_height) > canvas_height(canvas)) { line = furi_string_alloc_printf("%.*s...\n", chars_fit, start); } else { - line = furi_string_alloc_printf("%.*s-\n", chars_fit, start); + // Account for the added "-" in length + line = furi_string_alloc_printf("%.*s-\n", chars_fit - 1, start); } canvas_draw_str_aligned(canvas, x, y, horizontal, vertical, furi_string_get_cstr(line)); furi_string_free(line); diff --git a/assets/resources/subghz/assets/came_atomo b/assets/resources/subghz/assets/came_atomo deleted file mode 100644 index 0952f3f20..000000000 --- a/assets/resources/subghz/assets/came_atomo +++ /dev/null @@ -1,6 +0,0 @@ -Filetype: Flipper SubGhz Keystore RAW File -Version: 0 -Encryption: 1 -IV: 47 69 6D 6D 65 20 74 68 65 63 6F 6F 6B 69 65 73 -Encrypt_data: RAW -E0BDF15D68F29AE787E7FCEE6C3611C90A92305D677B8FFFBE225196F5DC04CAEAE1102B4AB830E76C9C14DBA7FA5BD1F30864ABAF51387222FDCC0BA87E4FF709812D5C59DD953859AFD698A0EA2ECEFA0DC49652861EF4CF1864843F135DB8680E0C5C9EEC3BC548E2EB696DC8CA1B0F627347D2C476B410CF03A0F4D1EFB36DFB0574FE8F48FB61910CA539EC04583CA170A51822225A1D3E86C07219FE92E5DE9F557A45E611D74028BAF56E7F2C53DBA8DC53DA89B642FAC0A9A0BAC1756BDA0833ACB09F56E0FA3080CBE9E6A04B235F3AC82BB955FBFD779C59725E6D1875E04E0E84ABD0C3C1C8FAB247EC2755ACEC9961244E0D79AE710E4C7D33E9 \ No newline at end of file diff --git a/firmware.scons b/firmware.scons index a91b7cdfc..2a82db371 100644 --- a/firmware.scons +++ b/firmware.scons @@ -8,6 +8,9 @@ from fbt_extra.util import ( link_elf_dir_as_latest, ) +from fbt.sdk.cache import LazySdkVersionLoader + + Import("ENV", "fw_build_meta") # Building initial C environment for libs @@ -71,6 +74,8 @@ env = ENV.Clone( }, FW_API_TABLE=None, _APP_ICONS=None, + APPS=_.split(",") if (_ := GetOption("extra_int_apps")) else [], + EXTRA_EXT_APPS=_.split(",") if (_ := GetOption("extra_ext_apps")) else [], ) env.PreConfigureFwEnvionment() @@ -125,9 +130,6 @@ if env["IS_BASE_FIRMWARE"]: else: fwenv.Append(APPS=["updater"]) -if extra_int_apps := GetOption("extra_int_apps"): - fwenv.Append(APPS=extra_int_apps.split(",")) - for app_dir, _ in fwenv["APPDIRS"]: app_dir_node = env.Dir("#").Dir(app_dir) @@ -136,7 +138,6 @@ for app_dir, _ in fwenv["APPDIRS"]: if isinstance(entry, FS.Dir) and not str(entry).startswith("."): fwenv.LoadAppManifest(entry) - fwenv.PrepareApplicationsBuild() # Build external apps + configure SDK @@ -148,6 +149,11 @@ if env["IS_BASE_FIRMWARE"]: ) fw_artifacts.append(fwenv["FW_EXTAPPS"].sdk_tree) + fwenv.Append(FBT_API_VERSION=LazySdkVersionLoader(fwenv.subst("$SDK_DEFINITION"))) + fwenv.PhonyTarget( + "get_apiversion", + "@echo $( ${FBT_API_VERSION} $)", + ) # Add preprocessor definitions for current set of apps fwenv.Append( diff --git a/firmware/targets/f7/api_symbols.csv b/firmware/targets/f7/api_symbols.csv index 4f29e357e..71bfd96f8 100644 --- a/firmware/targets/f7/api_symbols.csv +++ b/firmware/targets/f7/api_symbols.csv @@ -1461,7 +1461,7 @@ Function,+,furi_hal_subghz_flush_tx,void, Function,+,furi_hal_subghz_get_data_gpio,const GpioPin*, Function,+,furi_hal_subghz_get_ext_power_amp,_Bool, Function,+,furi_hal_subghz_get_lqi,uint8_t, -Function,+,furi_hal_subghz_get_rolling_counter_mult,uint8_t, +Function,+,furi_hal_subghz_get_rolling_counter_mult,int8_t, Function,+,furi_hal_subghz_get_rssi,float, Function,+,furi_hal_subghz_idle,void, Function,-,furi_hal_subghz_init,void, @@ -1481,7 +1481,7 @@ Function,+,furi_hal_subghz_set_ext_power_amp,void,_Bool Function,+,furi_hal_subghz_set_frequency,uint32_t,uint32_t Function,+,furi_hal_subghz_set_frequency_and_path,uint32_t,uint32_t Function,+,furi_hal_subghz_set_path,void,FuriHalSubGhzPath -Function,+,furi_hal_subghz_set_rolling_counter_mult,void,uint8_t +Function,+,furi_hal_subghz_set_rolling_counter_mult,void,int8_t Function,+,furi_hal_subghz_shutdown,void, Function,+,furi_hal_subghz_sleep,void, Function,+,furi_hal_subghz_start_async_rx,void,"FuriHalSubGhzCaptureCallback, void*" diff --git a/firmware/targets/f7/furi_hal/furi_hal_bt.c b/firmware/targets/f7/furi_hal/furi_hal_bt.c index 6a27b86e3..4f78f77de 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_bt.c +++ b/firmware/targets/f7/furi_hal/furi_hal_bt.c @@ -489,7 +489,7 @@ bool furi_hal_bt_custom_adv_set(const uint8_t* adv_data, size_t adv_len) { FURI_LOG_E(TAG, "custom_adv_set failed %d", status); return false; } else { - FURI_LOG_I(TAG, "custom_adv_set success"); + FURI_LOG_D(TAG, "custom_adv_set success"); return true; } } @@ -511,7 +511,7 @@ bool furi_hal_bt_custom_adv_start( FURI_LOG_E(TAG, "custom_adv_start failed %d", status); return false; } else { - FURI_LOG_I(TAG, "custom_adv_start success"); + FURI_LOG_D(TAG, "custom_adv_start success"); return true; } } @@ -522,7 +522,7 @@ bool furi_hal_bt_custom_adv_stop() { FURI_LOG_E(TAG, "custom_adv_stop failed %d", status); return false; } else { - FURI_LOG_I(TAG, "custom_adv_stop success"); + FURI_LOG_D(TAG, "custom_adv_stop success"); return true; } } diff --git a/firmware/targets/f7/furi_hal/furi_hal_subghz.c b/firmware/targets/f7/furi_hal/furi_hal_subghz.c index 007e29bd6..c5326e3fd 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_subghz.c +++ b/firmware/targets/f7/furi_hal/furi_hal_subghz.c @@ -52,7 +52,7 @@ typedef struct { volatile SubGhzRegulation regulation; const GpioPin* async_mirror_pin; - uint8_t rolling_counter_mult; + int8_t rolling_counter_mult; bool ext_power_amp : 1; bool extended_frequency_i : 1; } FuriHalSubGhz; @@ -66,11 +66,11 @@ volatile FuriHalSubGhz furi_hal_subghz = { .extended_frequency_i = false, }; -uint8_t furi_hal_subghz_get_rolling_counter_mult(void) { +int8_t furi_hal_subghz_get_rolling_counter_mult(void) { return furi_hal_subghz.rolling_counter_mult; } -void furi_hal_subghz_set_rolling_counter_mult(uint8_t mult) { +void furi_hal_subghz_set_rolling_counter_mult(int8_t mult) { furi_hal_subghz.rolling_counter_mult = mult; } diff --git a/firmware/targets/f7/furi_hal/furi_hal_subghz.h b/firmware/targets/f7/furi_hal/furi_hal_subghz.h index b390ac6cc..136a2af41 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_subghz.h +++ b/firmware/targets/f7/furi_hal/furi_hal_subghz.h @@ -173,15 +173,15 @@ uint32_t furi_hal_subghz_set_frequency_and_path(uint32_t value); */ bool furi_hal_subghz_is_tx_allowed(uint32_t value); -/** Get the current rolling protocols counter ++ value - * @return uint8_t current value +/** Get the current rolling protocols counter ++/-- value + * @return int8_t current value */ -uint8_t furi_hal_subghz_get_rolling_counter_mult(void); +int8_t furi_hal_subghz_get_rolling_counter_mult(void); -/** Set the current rolling protocols counter ++ value - * @param mult uint8_t = 1, 2, 4, 8 +/** Set the current rolling protocols counter ++/-- value + * @param mult int8_t = -1, -10, -100, 0, 1, 10, 100 */ -void furi_hal_subghz_set_rolling_counter_mult(uint8_t mult); +void furi_hal_subghz_set_rolling_counter_mult(int8_t mult); /** Set frequency * diff --git a/lib/subghz/blocks/custom_btn.c b/lib/subghz/blocks/custom_btn.c index 1919fc5e4..e33f79887 100644 --- a/lib/subghz/blocks/custom_btn.c +++ b/lib/subghz/blocks/custom_btn.c @@ -48,4 +48,4 @@ void subghz_custom_btn_set_prog_mode(ProgMode prog_mode) { ProgMode subghz_custom_btn_get_prog_mode() { return controller_programming_mode; -} \ No newline at end of file +} diff --git a/lib/subghz/blocks/custom_btn_i.h b/lib/subghz/blocks/custom_btn_i.h index f75ba4068..33ea6be9f 100644 --- a/lib/subghz/blocks/custom_btn_i.h +++ b/lib/subghz/blocks/custom_btn_i.h @@ -14,4 +14,4 @@ void subghz_custom_btn_set_max(uint8_t b); void subghz_custom_btn_set_prog_mode(ProgMode prog_mode); -ProgMode subghz_custom_btn_get_prog_mode(); \ No newline at end of file +ProgMode subghz_custom_btn_get_prog_mode(); diff --git a/lib/subghz/environment.c b/lib/subghz/environment.c index b69494e66..7b1e87b41 100644 --- a/lib/subghz/environment.c +++ b/lib/subghz/environment.c @@ -4,7 +4,6 @@ struct SubGhzEnvironment { SubGhzKeystore* keystore; const SubGhzProtocolRegistry* protocol_registry; - const char* came_atomo_rainbow_table_file_name; const char* nice_flor_s_rainbow_table_file_name; const char* alutech_at_4n_rainbow_table_file_name; const char* mfname; @@ -16,7 +15,6 @@ SubGhzEnvironment* subghz_environment_alloc() { instance->keystore = subghz_keystore_alloc(); instance->protocol_registry = NULL; - instance->came_atomo_rainbow_table_file_name = NULL; instance->nice_flor_s_rainbow_table_file_name = NULL; instance->alutech_at_4n_rainbow_table_file_name = NULL; instance->mfname = ""; @@ -29,7 +27,6 @@ void subghz_environment_free(SubGhzEnvironment* instance) { furi_assert(instance); instance->protocol_registry = NULL; - instance->came_atomo_rainbow_table_file_name = NULL; instance->nice_flor_s_rainbow_table_file_name = NULL; instance->alutech_at_4n_rainbow_table_file_name = NULL; subghz_keystore_free(instance->keystore); @@ -52,16 +49,17 @@ SubGhzKeystore* subghz_environment_get_keystore(SubGhzEnvironment* instance) { void subghz_environment_set_came_atomo_rainbow_table_file_name( SubGhzEnvironment* instance, const char* filename) { - furi_assert(instance); - - instance->came_atomo_rainbow_table_file_name = filename; + UNUSED(instance); + UNUSED(filename); + // Do nothing :) + return; } const char* subghz_environment_get_came_atomo_rainbow_table_file_name(SubGhzEnvironment* instance) { - furi_assert(instance); - - return instance->came_atomo_rainbow_table_file_name; + UNUSED(instance); + // No table, sorry + return ""; } void subghz_environment_set_alutech_at_4n_rainbow_table_file_name( diff --git a/lib/subghz/protocols/faac_slh.c b/lib/subghz/protocols/faac_slh.c index 3ae6c8e23..2044d9d20 100644 --- a/lib/subghz/protocols/faac_slh.c +++ b/lib/subghz/protocols/faac_slh.c @@ -8,6 +8,8 @@ #include "../blocks/generic.h" #include "../blocks/math.h" +#include "../blocks/custom_btn_i.h" + #define TAG "SubGhzProtocolFaacSLH" static const SubGhzBlockConst subghz_protocol_faac_slh_const = { @@ -17,6 +19,18 @@ static const SubGhzBlockConst subghz_protocol_faac_slh_const = { .min_count_bit_for_found = 64, }; +static uint32_t temp_fix_backup = 0; +static uint32_t temp_counter_backup = 0; +static bool faac_prog_mode = false; +static bool allow_zero_seed = false; + +void faac_slh_reset_prog_mode() { + temp_fix_backup = 0; + temp_counter_backup = 0; + faac_prog_mode = false; + allow_zero_seed = false; +} + struct SubGhzProtocolDecoderFaacSLH { SubGhzProtocolDecoderBase base; @@ -110,11 +124,76 @@ void subghz_protocol_encoder_faac_slh_free(void* context) { } static bool subghz_protocol_faac_slh_gen_data(SubGhzProtocolEncoderFaacSLH* instance) { - if(instance->generic.seed != 0x0) { - instance->generic.cnt += furi_hal_subghz_get_rolling_counter_mult(); - } else { - // Do not generate new data, send data from buffer + // TODO: Stupid bypass for custom button, remake later + if(subghz_custom_btn_get_original() == 0) { + subghz_custom_btn_set_original(0xF); + } + + uint8_t custom_btn_id = subghz_custom_btn_get(); + + // If we are using UP button - generate programming mode key and send it, otherwise - send regular key if possible + if((custom_btn_id == SUBGHZ_CUSTOM_BTN_UP) && + !(!allow_zero_seed && (instance->generic.seed == 0x0))) { + uint8_t data_tmp = 0; + uint8_t data_prg[8]; + + data_prg[0] = 0x00; + + if(allow_zero_seed || (instance->generic.seed != 0x0)) { + instance->generic.cnt += furi_hal_subghz_get_rolling_counter_mult(); + if(temp_counter_backup != 0x0) { + temp_counter_backup += furi_hal_subghz_get_rolling_counter_mult(); + } + } + + data_prg[1] = instance->generic.cnt & 0xFF; + + data_prg[2] = (uint8_t)(instance->generic.seed & 0xFF); + data_prg[3] = (uint8_t)(instance->generic.seed >> 8 & 0xFF); + data_prg[4] = (uint8_t)(instance->generic.seed >> 16 & 0xFF); + data_prg[5] = (uint8_t)(instance->generic.seed >> 24); + + data_prg[2] ^= data_prg[1]; + data_prg[3] ^= data_prg[1]; + data_prg[4] ^= data_prg[1]; + data_prg[5] ^= data_prg[1]; + + for(uint8_t i = data_prg[1] & 0x0F; i != 0; i--) { + data_tmp = data_prg[5]; + + data_prg[5] = ((data_prg[5] << 1) & 0xFF) | (data_prg[4] & 0x80) >> 7; + data_prg[4] = ((data_prg[4] << 1) & 0xFF) | (data_prg[3] & 0x80) >> 7; + data_prg[3] = ((data_prg[3] << 1) & 0xFF) | (data_prg[2] & 0x80) >> 7; + data_prg[2] = ((data_prg[2] << 1) & 0xFF) | (data_tmp & 0x80) >> 7; + } + data_prg[6] = 0x0F; + data_prg[7] = 0x52; + + uint32_t enc_prg_1 = data_prg[7] << 24 | data_prg[6] << 16 | data_prg[5] << 8 | + data_prg[4]; + uint32_t enc_prg_2 = data_prg[3] << 24 | data_prg[2] << 16 | data_prg[1] << 8 | + data_prg[0]; + instance->generic.data = (uint64_t)enc_prg_1 << 32 | enc_prg_2; + //FURI_LOG_D(TAG, "New Prog Mode Key Generated: %016llX\r", instance->generic.data); + return true; + } else { + if(!allow_zero_seed && (instance->generic.seed == 0x0)) { + // Do not generate new data, send data from buffer + return true; + } + // If we are in prog mode and regular Send button is used - Do not generate new data, send data from buffer + if((faac_prog_mode == true) && (instance->generic.serial == 0x0) && + (instance->generic.btn == 0x0) && (temp_fix_backup == 0x0)) { + return true; + } + } + // Restore main remote data when we exit programming mode + if((instance->generic.serial == 0x0) && (instance->generic.btn == 0x0) && + (temp_fix_backup != 0x0) && !faac_prog_mode) { + instance->generic.serial = temp_fix_backup >> 4; + instance->generic.btn = temp_fix_backup & 0xF; + instance->generic.cnt = temp_counter_backup; } uint32_t fix = instance->generic.serial << 4 | instance->generic.btn; uint32_t hop = 0; @@ -126,6 +205,11 @@ static bool subghz_protocol_faac_slh_gen_data(SubGhzProtocolEncoderFaacSLH* inst for(int i = 0; i < 8; i++) { fixx[i] = (fix >> (shiftby -= 4)) & 0xF; } + + if(allow_zero_seed || (instance->generic.seed != 0x0)) { + instance->generic.cnt += furi_hal_subghz_get_rolling_counter_mult(); + } + if((instance->generic.cnt % 2) == 0) { decrypt = fixx[6] << 28 | fixx[7] << 24 | fixx[5] << 20 | (instance->generic.cnt & 0xFFFFF); @@ -172,6 +256,7 @@ bool subghz_protocol_faac_slh_create_data( instance->generic.seed = seed; instance->manufacture_name = manufacture_name; instance->generic.data_count_bit = 64; + allow_zero_seed = true; bool res = subghz_protocol_faac_slh_gen_data(instance); if(res) { return SubGhzProtocolStatusOk == @@ -242,6 +327,13 @@ SubGhzProtocolStatus FURI_LOG_E(TAG, "Missing Seed"); break; } + bool tmp_allow_zero_seed; + if(flipper_format_read_bool(flipper_format, "AllowZeroSeed", &tmp_allow_zero_seed, 1)) { + allow_zero_seed = true; + } else { + allow_zero_seed = false; + } + instance->generic.seed = seed_data[0] << 24 | seed_data[1] << 16 | seed_data[2] << 8 | seed_data[3]; @@ -403,11 +495,62 @@ static void subghz_protocol_faac_slh_check_remote_controller( const char** manufacture_name) { uint32_t code_fix = instance->data >> 32; uint32_t code_hop = instance->data & 0xFFFFFFFF; - instance->serial = code_fix >> 4; - instance->btn = code_fix & 0xF; uint32_t decrypt = 0; uint64_t man; + // TODO: Stupid bypass for custom button, remake later + if(subghz_custom_btn_get_original() == 0) { + subghz_custom_btn_set_original(0xF); + } + + subghz_custom_btn_set_max(1); + + uint8_t data_tmp = 0; + uint8_t data_prg[8]; + data_prg[0] = (code_hop & 0xFF); + data_prg[1] = ((code_hop >> 8) & 0xFF); + data_prg[2] = ((code_hop >> 16) & 0xFF); + data_prg[3] = (code_hop >> 24); + data_prg[4] = (code_fix & 0xFF); + data_prg[5] = ((code_fix >> 8) & 0xFF); + data_prg[6] = ((code_fix >> 16) & 0xFF); + data_prg[7] = (code_fix >> 24); + + if(((data_prg[7] == 0x52) && (data_prg[6] == 0x0F) && (data_prg[0] == 0x00))) { + faac_prog_mode = true; + // ProgMode ON + for(uint8_t i = data_prg[1] & 0xF; i != 0; i--) { + data_tmp = data_prg[2]; + + data_prg[2] = data_prg[2] >> 1 | (data_prg[3] & 1) << 7; + data_prg[3] = data_prg[3] >> 1 | (data_prg[4] & 1) << 7; + data_prg[4] = data_prg[4] >> 1 | (data_prg[5] & 1) << 7; + data_prg[5] = data_prg[5] >> 1 | (data_tmp & 1) << 7; + } + data_prg[2] ^= data_prg[1]; + data_prg[3] ^= data_prg[1]; + data_prg[4] ^= data_prg[1]; + data_prg[5] ^= data_prg[1]; + instance->seed = data_prg[5] << 24 | data_prg[4] << 16 | data_prg[3] << 8 | data_prg[2]; + uint32_t dec_prg_1 = data_prg[7] << 24 | data_prg[6] << 16 | data_prg[5] << 8 | + data_prg[4]; + uint32_t dec_prg_2 = data_prg[3] << 24 | data_prg[2] << 16 | data_prg[1] << 8 | + data_prg[0]; + instance->data_2 = (uint64_t)dec_prg_1 << 32 | dec_prg_2; + instance->cnt = data_prg[1]; + + *manufacture_name = "FAAC_SLH"; + return; + } else { + if(code_fix != 0x0) { + temp_fix_backup = code_fix; + instance->serial = code_fix >> 4; + instance->btn = code_fix & 0xF; + } + + faac_prog_mode = false; + } + for M_EACH(manufacture_code, *subghz_keystore_get_data(keystore), SubGhzKeyArray_t) { switch(manufacture_code->type) { @@ -421,6 +564,10 @@ static void subghz_protocol_faac_slh_check_remote_controller( } } instance->cnt = decrypt & 0xFFFFF; + // Backup counter in case when we need to use programming mode + if(code_fix != 0x0) { + temp_counter_backup = instance->cnt; + } } uint8_t subghz_protocol_decoder_faac_slh_get_hash_data(void* context) { @@ -439,6 +586,7 @@ SubGhzProtocolStatus subghz_protocol_decoder_faac_slh_serialize( // Reset seed leftover from previous decoded signal instance->generic.seed = 0x0; + temp_fix_backup = 0x0; SubGhzProtocolStatus res = subghz_block_generic_serialize(&instance->generic, flipper_format, preset); @@ -486,6 +634,12 @@ SubGhzProtocolStatus FURI_LOG_E(TAG, "Missing Seed"); break; } + bool tmp_allow_zero_seed; + if(flipper_format_read_bool(flipper_format, "AllowZeroSeed", &tmp_allow_zero_seed, 1)) { + allow_zero_seed = true; + } else { + allow_zero_seed = false; + } instance->generic.seed = seed_data[0] << 24 | seed_data[1] << 16 | seed_data[2] << 8 | seed_data[3]; @@ -507,7 +661,23 @@ void subghz_protocol_decoder_faac_slh_get_string(void* context, FuriString* outp uint32_t code_fix = instance->generic.data >> 32; uint32_t code_hop = instance->generic.data & 0xFFFFFFFF; - if(instance->generic.seed == 0x0) { + if(faac_prog_mode == true) { + furi_string_cat_printf( + output, + "%s %dbit\r\n" + "Master Remote Prog Mode\r\n" + "Ke:%lX%08lX\r\n" + "Kd:%lX%08lX\r\n" + "Seed:%08lX mCnt:%02X", + instance->generic.protocol_name, + instance->generic.data_count_bit, + (uint32_t)(instance->generic.data >> 32), + (uint32_t)instance->generic.data, + (uint32_t)(instance->generic.data_2 >> 32), + (uint32_t)instance->generic.data_2, + instance->generic.seed, + (uint8_t)(instance->generic.cnt & 0xFF)); + } else if((allow_zero_seed == false) && (instance->generic.seed == 0x0)) { furi_string_cat_printf( output, "%s %dbit\r\n" diff --git a/lib/subghz/protocols/faac_slh.h b/lib/subghz/protocols/faac_slh.h index bab042ca6..8d03d7907 100644 --- a/lib/subghz/protocols/faac_slh.h +++ b/lib/subghz/protocols/faac_slh.h @@ -129,3 +129,7 @@ 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/keeloq.c b/lib/subghz/protocols/keeloq.c index a274602f3..0bda954ba 100644 --- a/lib/subghz/protocols/keeloq.c +++ b/lib/subghz/protocols/keeloq.c @@ -990,7 +990,7 @@ static void subghz_protocol_keeloq_check_remote_controller( instance->cnt = temp_counter; } else { // Counter protection - furi_crash("Unsuported Prog Mode"); + furi_crash("Unsupported Prog Mode"); } instance->serial = key_fix & 0x0FFFFFFF; @@ -1249,6 +1249,23 @@ void subghz_protocol_decoder_keeloq_get_string(void* context, FuriString* output instance->generic.btn, instance->manufacture_name, instance->generic.seed); + } else if(strcmp(instance->manufacture_name, "Unknown") == 0) { + instance->generic.cnt = 0x0; + furi_string_cat_printf( + output, + "%s %dbit\r\n" + "Key:%08lX%08lX\r\n" + "Fix:0x%08lX Cnt:????\r\n" + "Hop:0x%08lX Btn:%01X\r\n" + "MF:%s", + instance->generic.protocol_name, + instance->generic.data_count_bit, + code_found_hi, + code_found_lo, + code_found_reverse_hi, + code_found_reverse_lo, + instance->generic.btn, + instance->manufacture_name); } else { furi_string_cat_printf( output, diff --git a/lib/subghz/protocols/somfy_keytis.c b/lib/subghz/protocols/somfy_keytis.c index be8ebacf5..22d2b5e9f 100644 --- a/lib/subghz/protocols/somfy_keytis.c +++ b/lib/subghz/protocols/somfy_keytis.c @@ -200,7 +200,7 @@ bool subghz_protocol_somfy_keytis_create_data( /** * Generating an upload from data. - * @param instance Pointer to a SubGhzProtocolEncoderKeeloq instance + * @param instance Pointer to a SubGhzProtocolEncoderSomfyKeytis instance * @return true On success */ static bool subghz_protocol_encoder_somfy_keytis_get_upload( diff --git a/lib/subghz/protocols/somfy_telis.c b/lib/subghz/protocols/somfy_telis.c index 9a3882d87..b198ce491 100644 --- a/lib/subghz/protocols/somfy_telis.c +++ b/lib/subghz/protocols/somfy_telis.c @@ -189,7 +189,7 @@ bool subghz_protocol_somfy_telis_create_data( /** * Generating an upload from data. - * @param instance Pointer to a SubGhzProtocolEncoderKeeloq instance + * @param instance Pointer to a SubGhzProtocolEncoderSomfyTelis instance * @return true On success */ static bool subghz_protocol_encoder_somfy_telis_get_upload( diff --git a/scripts/fbt/appmanifest.py b/scripts/fbt/appmanifest.py index 87fea3123..c999dda29 100644 --- a/scripts/fbt/appmanifest.py +++ b/scripts/fbt/appmanifest.py @@ -188,8 +188,19 @@ class AppManager: raise FlipperManifestException(f"Duplicate app declaration: {app.appid}") self.known_apps[app.appid] = app - def filter_apps(self, applist: List[str], hw_target: str): - return AppBuildset(self, applist, hw_target) + def filter_apps( + self, + *, + applist: List[str], + ext_applist: List[str], + hw_target: str, + ): + return AppBuildset( + self, + hw_target=hw_target, + appnames=applist, + extra_ext_appnames=ext_applist, + ) class AppBuilderException(Exception): @@ -206,6 +217,12 @@ class AppBuildset: FlipperAppType.SETTINGS, FlipperAppType.STARTUP, ) + EXTERNAL_APP_TYPES = ( + FlipperAppType.EXTERNAL, + FlipperAppType.MENUEXTERNAL, + FlipperAppType.PLUGIN, + FlipperAppType.DEBUG, + ) @staticmethod def print_writer(message): @@ -214,16 +231,21 @@ class AppBuildset: def __init__( self, appmgr: AppManager, - appnames: List[str], hw_target: str, + appnames: List[str], + *, + extra_ext_appnames: List[str], message_writer: Callable | None = None, ): self.appmgr = appmgr self.appnames = set(appnames) + self.incompatible_extapps, self.extapps = [], [] + self._extra_ext_appnames = extra_ext_appnames self._orig_appnames = appnames self.hw_target = hw_target self._writer = message_writer if message_writer else self.print_writer self._process_deps() + self._process_ext_apps() self._check_conflicts() self._check_unsatisfied() # unneeded? self._check_target_match() @@ -267,6 +289,27 @@ class AppBuildset: break self.appnames.update(provided) + def _process_ext_apps(self): + extapps = [ + app + for apptype in self.EXTERNAL_APP_TYPES + for app in self.get_apps_of_type(apptype, True) + ] + extapps.extend(map(self.appmgr.get, self._extra_ext_appnames)) + + for app in extapps: + ( + self.extapps + if app.supports_hardware_target(self.hw_target) + else self.incompatible_extapps + ).append(app) + + def get_ext_apps(self): + return self.extapps + + def get_incompatible_ext_apps(self): + return self.incompatible_extapps + def _check_conflicts(self): conflicts = [] for app in self.appnames: diff --git a/scripts/fbt/sdk/cache.py b/scripts/fbt/sdk/cache.py index 074cac6b9..e3d93a319 100644 --- a/scripts/fbt/sdk/cache.py +++ b/scripts/fbt/sdk/cache.py @@ -255,3 +255,18 @@ class SdkCache: self.sync_sets(self.sdk.headers, api.headers, False) self.sync_sets(self.sdk.functions, api.functions) self.sync_sets(self.sdk.variables, api.variables) + + +class LazySdkVersionLoader: + def __init__(self, sdk_path: str): + self.sdk_path = sdk_path + self._version = None + + @property + def version(self) -> SdkVersion: + if self._version is None: + self._version = SdkCache(self.sdk_path, load_version_only=True).version + return self._version + + def __str__(self) -> str: + return str(self.version) diff --git a/scripts/fbt_tools/fbt_apps.py b/scripts/fbt_tools/fbt_apps.py index cbb3bf726..9a0718055 100644 --- a/scripts/fbt_tools/fbt_apps.py +++ b/scripts/fbt_tools/fbt_apps.py @@ -36,7 +36,9 @@ def LoadAppManifest(env, entry): def PrepareApplicationsBuild(env): try: appbuild = env["APPBUILD"] = env["APPMGR"].filter_apps( - env["APPS"], env.subst("f${TARGET_HW}") + applist=env["APPS"], + ext_applist=env["EXTRA_EXT_APPS"], + hw_target=env.subst("f${TARGET_HW}"), ) except Exception as e: raise StopError(e) @@ -56,6 +58,11 @@ def DumpApplicationConfig(target, source, env): fg.green(f"{apptype.value}:\n\t"), ", ".join(app.appid for app in app_sublist), ) + if incompatible_ext_apps := env["APPBUILD"].get_incompatible_ext_apps(): + print( + fg.blue("Incompatible apps (skipped):\n\t"), + ", ".join(app.appid for app in incompatible_ext_apps), + ) def build_apps_c(target, source, env): diff --git a/scripts/ufbt/SConstruct b/scripts/ufbt/SConstruct index 1630135c2..98e6b638f 100644 --- a/scripts/ufbt/SConstruct +++ b/scripts/ufbt/SConstruct @@ -107,6 +107,7 @@ env = core_env.Clone( SINGLEQUOTEFUNC=single_quote, ABSPATHGETTERFUNC=resolve_real_dir_node, APPS=[], + EXTRA_EXT_APPS=[], UFBT_API_VERSION=SdkCache( core_env.subst("$SDK_DEFINITION"), load_version_only=True ).version, diff --git a/site_scons/extapps.scons b/site_scons/extapps.scons index 97b7ac095..f9227ed37 100644 --- a/site_scons/extapps.scons +++ b/site_scons/extapps.scons @@ -60,40 +60,12 @@ class FlipperExtAppBuildArtifacts: sdk_tree: NodeList = field(default_factory=NodeList) -apps_to_build_as_faps = [ - FlipperAppType.PLUGIN, - FlipperAppType.EXTERNAL, - FlipperAppType.MENUEXTERNAL, - FlipperAppType.DEBUG, -] - -known_extapps = [ - app - for apptype in apps_to_build_as_faps - for app in appenv["APPBUILD"].get_apps_of_type(apptype, True) -] - -# Ugly access to global option -if extra_app_list := GetOption("extra_ext_apps"): - known_extapps.extend(map(appenv["APPMGR"].get, extra_app_list.split(","))) - -incompatible_apps = [] -for app in known_extapps: - if not app.supports_hardware_target(appenv.subst("f${TARGET_HW}")): - incompatible_apps.append(app) - continue - +for app in appenv["APPBUILD"].get_ext_apps(): appenv.BuildAppElf(app) extapps = FlipperExtAppBuildArtifacts() extapps.application_map = appenv["EXT_APPS"] -if incompatible_apps: - warn( - WarningOnByDefault, - f"Skipping build of {len(incompatible_apps)} incompatible app(s): " - + ", ".join(f"'{app.name}' (id '{app.appid}')" for app in incompatible_apps), - ) if appenv["FORCE"]: appenv.AlwaysBuild(