diff --git a/CHANGELOG.md b/CHANGELOG.md index d0526484d..647e1f376 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -97,6 +97,8 @@ - NFC: - Support MIFARE DESFire Transaction MAC file type, fixes reading some EV2+ cards (by @Willy-JL) - Improve NDEF parser handling and display of raw non-text data (by @Willy-JL) + - Split NfcProtocolSupport handlers into plugins for ~23kb less RAM usage (#396 by @Willy-JL) + - Enable Asset Packs in NFC app again due to reduced RAM usage (#396 by @Willy-JL) - Improve loading of parser plugins (by @Willy-JL) - OFW: Added naming for DESFire cards + fix MF3ICD40 cards unable to be read (by @Demae) - OFW: FeliCa Protocol Expose Read Block API and Allow Specifying Service (by @zinongli) diff --git a/applications/main/nfc/api/nfc_app_api_table_i.h b/applications/main/nfc/api/nfc_app_api_table_i.h index 790fa5766..d31857b09 100644 --- a/applications/main/nfc/api/nfc_app_api_table_i.h +++ b/applications/main/nfc/api/nfc_app_api_table_i.h @@ -1,5 +1,8 @@ #include "gallagher/gallagher_util.h" #include "mosgortrans/mosgortrans_util.h" +#include "../nfc_app_i.h" +#include "../helpers/protocol_support/nfc_protocol_support_gui_common.h" +#include "../helpers/protocol_support/nfc_protocol_support_unlock_helper.h" /* * A list of app's private functions and objects to expose for plugins. @@ -22,4 +25,20 @@ static constexpr auto nfc_app_api_table = sort(create_array_t( (FuriString * str, const char* name, uint8_t prefix_separator_cnt, - uint8_t suffix_separator_cnt)))); + uint8_t suffix_separator_cnt)), + API_METHOD( + nfc_append_filename_string_when_present, + void, + (NfcApp * instance, FuriString* string)), + API_METHOD(nfc_protocol_support_common_submenu_callback, void, (void* context, uint32_t index)), + API_METHOD( + nfc_protocol_support_common_widget_callback, + void, + (GuiButtonType result, InputType type, void* context)), + API_METHOD(nfc_protocol_support_common_on_enter_empty, void, (NfcApp * instance)), + API_METHOD( + nfc_protocol_support_common_on_event_empty, + bool, + (NfcApp * instance, SceneManagerEvent event)), + API_METHOD(nfc_unlock_helper_setup_from_state, void, (NfcApp * instance)), + API_METHOD(nfc_unlock_helper_card_detected_handler, void, (NfcApp * instance)))); diff --git a/applications/main/nfc/application.fam b/applications/main/nfc/application.fam index 576c66008..2edf748ce 100644 --- a/applications/main/nfc/application.fam +++ b/applications/main/nfc/application.fam @@ -16,7 +16,178 @@ App( fap_libs=["assets", "mbedtls"], fap_icon="icon.png", fap_category="NFC", - flags=["UnloadAssetPacks"], + # flags=["UnloadAssetPacks"], +) + +# Protocol support plugins + +App( + appid="nfc_emv", + targets=["f7"], + apptype=FlipperAppType.PLUGIN, + entry_point="nfc_emv_ep", + requires=["nfc"], + sources=[ + "helpers/protocol_support/emv/*.c", + ], + fal_embedded=True, +) + +App( + appid="nfc_felica", + targets=["f7"], + apptype=FlipperAppType.PLUGIN, + entry_point="nfc_felica_ep", + requires=["nfc"], + sources=[ + "helpers/protocol_support/felica/*.c", + "helpers/felica_*.c", + ], + fal_embedded=True, +) + +App( + appid="nfc_iso14443_3a", + targets=["f7"], + apptype=FlipperAppType.PLUGIN, + entry_point="nfc_iso14443_3a_ep", + requires=["nfc"], + sources=[ + "helpers/protocol_support/iso14443_3a/*.c", + ], + fal_embedded=True, +) + +App( + appid="nfc_iso14443_3b", + targets=["f7"], + apptype=FlipperAppType.PLUGIN, + entry_point="nfc_iso14443_3b_ep", + requires=["nfc"], + sources=[ + "helpers/protocol_support/iso14443_3b/*.c", + ], + fal_embedded=True, +) + +App( + appid="nfc_iso14443_4a", + targets=["f7"], + apptype=FlipperAppType.PLUGIN, + entry_point="nfc_iso14443_4a_ep", + requires=["nfc"], + sources=[ + "helpers/protocol_support/iso14443_4a/*.c", + "helpers/protocol_support/iso14443_3a/*.c", + ], + fal_embedded=True, +) + +App( + appid="nfc_iso14443_4b", + targets=["f7"], + apptype=FlipperAppType.PLUGIN, + entry_point="nfc_iso14443_4b_ep", + requires=["nfc"], + sources=[ + "helpers/protocol_support/iso14443_4b/*.c", + "helpers/protocol_support/iso14443_3b/*.c", + ], + fal_embedded=True, +) + +App( + appid="nfc_iso15693_3", + targets=["f7"], + apptype=FlipperAppType.PLUGIN, + entry_point="nfc_iso15693_3_ep", + requires=["nfc"], + sources=[ + "helpers/protocol_support/iso15693_3/*.c", + ], + fal_embedded=True, +) + +App( + appid="nfc_mf_classic", + targets=["f7"], + apptype=FlipperAppType.PLUGIN, + entry_point="nfc_mf_classic_ep", + requires=["nfc"], + sources=[ + "helpers/protocol_support/mf_classic/*.c", + "helpers/protocol_support/iso14443_3a/*.c", + "helpers/mf_classic_*.c", + ], + fal_embedded=True, +) + +App( + appid="nfc_mf_desfire", + targets=["f7"], + apptype=FlipperAppType.PLUGIN, + entry_point="nfc_mf_desfire_ep", + requires=["nfc"], + sources=[ + "helpers/protocol_support/mf_desfire/*.c", + "helpers/protocol_support/iso14443_4a/*.c", + "helpers/protocol_support/iso14443_3a/*.c", + ], + fal_embedded=True, +) + +App( + appid="nfc_mf_plus", + targets=["f7"], + apptype=FlipperAppType.PLUGIN, + entry_point="nfc_mf_plus_ep", + requires=["nfc"], + sources=[ + "helpers/protocol_support/mf_plus/*.c", + "helpers/protocol_support/iso14443_4a/*.c", + "helpers/protocol_support/iso14443_3a/*.c", + ], + fal_embedded=True, +) + +App( + appid="nfc_mf_ultralight", + targets=["f7"], + apptype=FlipperAppType.PLUGIN, + entry_point="nfc_mf_ultralight_ep", + requires=["nfc"], + sources=[ + "helpers/protocol_support/mf_ultralight/*.c", + "helpers/protocol_support/iso14443_3a/*.c", + "helpers/mf_ultralight_*.c", + ], + fap_libs=["mbedtls"], + fal_embedded=True, +) + +App( + appid="nfc_slix", + targets=["f7"], + apptype=FlipperAppType.PLUGIN, + entry_point="nfc_slix_ep", + requires=["nfc"], + sources=[ + "helpers/protocol_support/slix/*.c", + "helpers/protocol_support/iso15693_3/*.c", + ], + fal_embedded=True, +) + +App( + appid="nfc_st25tb", + targets=["f7"], + apptype=FlipperAppType.PLUGIN, + entry_point="nfc_st25tb_ep", + requires=["nfc"], + sources=[ + "helpers/protocol_support/st25tb/*.c", + ], + fal_embedded=True, ) # Parser plugins diff --git a/applications/main/nfc/helpers/nfc_supported_cards.c b/applications/main/nfc/helpers/nfc_supported_cards.c index 6513eef5f..5c974f463 100644 --- a/applications/main/nfc/helpers/nfc_supported_cards.c +++ b/applications/main/nfc/helpers/nfc_supported_cards.c @@ -1,11 +1,9 @@ #include "nfc_supported_cards.h" -#include "../api/nfc_app_api_interface.h" #include "../plugins/supported_cards/nfc_supported_card_plugin.h" #include #include -#include #include #include @@ -52,12 +50,9 @@ struct NfcSupportedCards { NfcSupportedCardsLoadContext* load_context; }; -NfcSupportedCards* nfc_supported_cards_alloc(void) { +NfcSupportedCards* nfc_supported_cards_alloc(CompositeApiResolver* api_resolver) { NfcSupportedCards* instance = malloc(sizeof(NfcSupportedCards)); - - instance->api_resolver = composite_api_resolver_alloc(); - composite_api_resolver_add(instance->api_resolver, firmware_api_interface); - composite_api_resolver_add(instance->api_resolver, nfc_application_api_interface); + instance->api_resolver = api_resolver; NfcSupportedCardsPluginCache_init(instance->plugins_cache_arr); @@ -76,7 +71,6 @@ void nfc_supported_cards_free(NfcSupportedCards* instance) { } NfcSupportedCardsPluginCache_clear(instance->plugins_cache_arr); - composite_api_resolver_free(instance->api_resolver); free(instance); } diff --git a/applications/main/nfc/helpers/nfc_supported_cards.h b/applications/main/nfc/helpers/nfc_supported_cards.h index 5eaee360a..363abe30b 100644 --- a/applications/main/nfc/helpers/nfc_supported_cards.h +++ b/applications/main/nfc/helpers/nfc_supported_cards.h @@ -7,6 +7,7 @@ #pragma once #include +#include #include #include @@ -25,7 +26,7 @@ typedef struct NfcSupportedCards NfcSupportedCards; * * @return pointer to allocated NfcSupportedCards instance. */ -NfcSupportedCards* nfc_supported_cards_alloc(void); +NfcSupportedCards* nfc_supported_cards_alloc(CompositeApiResolver* api_resolver); /** * @brief Delete an NfcSupportedCards instance diff --git a/applications/main/nfc/helpers/protocol_support/emv/emv.c b/applications/main/nfc/helpers/protocol_support/emv/emv.c index 06e2ca624..5fc6d383c 100644 --- a/applications/main/nfc/helpers/protocol_support/emv/emv.c +++ b/applications/main/nfc/helpers/protocol_support/emv/emv.c @@ -129,3 +129,5 @@ const NfcProtocolSupportBase nfc_protocol_support_emv = { .on_event = nfc_protocol_support_common_on_event_empty, }, }; + +NFC_PROTOCOL_SUPPORT_PLUGIN(emv, NfcProtocolEmv); diff --git a/applications/main/nfc/helpers/protocol_support/felica/felica.c b/applications/main/nfc/helpers/protocol_support/felica/felica.c index 561cd4d2e..8067b16e2 100644 --- a/applications/main/nfc/helpers/protocol_support/felica/felica.c +++ b/applications/main/nfc/helpers/protocol_support/felica/felica.c @@ -214,3 +214,5 @@ const NfcProtocolSupportBase nfc_protocol_support_felica = { .on_event = nfc_protocol_support_common_on_event_empty, }, }; + +NFC_PROTOCOL_SUPPORT_PLUGIN(felica, NfcProtocolFelica); diff --git a/applications/main/nfc/helpers/protocol_support/iso14443_3a/iso14443_3a.c b/applications/main/nfc/helpers/protocol_support/iso14443_3a/iso14443_3a.c index 99e211301..0e49efe6e 100644 --- a/applications/main/nfc/helpers/protocol_support/iso14443_3a/iso14443_3a.c +++ b/applications/main/nfc/helpers/protocol_support/iso14443_3a/iso14443_3a.c @@ -145,3 +145,5 @@ const NfcProtocolSupportBase nfc_protocol_support_iso14443_3a = { .on_event = nfc_protocol_support_common_on_event_empty, }, }; + +NFC_PROTOCOL_SUPPORT_PLUGIN(iso14443_3a, NfcProtocolIso14443_3a); diff --git a/applications/main/nfc/helpers/protocol_support/iso14443_3b/iso14443_3b.c b/applications/main/nfc/helpers/protocol_support/iso14443_3b/iso14443_3b.c index 43b541111..eb4021658 100644 --- a/applications/main/nfc/helpers/protocol_support/iso14443_3b/iso14443_3b.c +++ b/applications/main/nfc/helpers/protocol_support/iso14443_3b/iso14443_3b.c @@ -112,3 +112,5 @@ const NfcProtocolSupportBase nfc_protocol_support_iso14443_3b = { .on_event = nfc_protocol_support_common_on_event_empty, }, }; + +NFC_PROTOCOL_SUPPORT_PLUGIN(iso14443_3b, NfcProtocolIso14443_3b); diff --git a/applications/main/nfc/helpers/protocol_support/iso14443_4a/iso14443_4a.c b/applications/main/nfc/helpers/protocol_support/iso14443_4a/iso14443_4a.c index 17435ccd4..b0185f55f 100644 --- a/applications/main/nfc/helpers/protocol_support/iso14443_4a/iso14443_4a.c +++ b/applications/main/nfc/helpers/protocol_support/iso14443_4a/iso14443_4a.c @@ -148,3 +148,5 @@ const NfcProtocolSupportBase nfc_protocol_support_iso14443_4a = { .on_event = nfc_protocol_support_common_on_event_empty, }, }; + +NFC_PROTOCOL_SUPPORT_PLUGIN(iso14443_4a, NfcProtocolIso14443_4a); diff --git a/applications/main/nfc/helpers/protocol_support/iso14443_4b/iso14443_4b.c b/applications/main/nfc/helpers/protocol_support/iso14443_4b/iso14443_4b.c index 8038e0491..0d3d9b4c4 100644 --- a/applications/main/nfc/helpers/protocol_support/iso14443_4b/iso14443_4b.c +++ b/applications/main/nfc/helpers/protocol_support/iso14443_4b/iso14443_4b.c @@ -117,3 +117,5 @@ const NfcProtocolSupportBase nfc_protocol_support_iso14443_4b = { .on_event = nfc_protocol_support_common_on_event_empty, }, }; + +NFC_PROTOCOL_SUPPORT_PLUGIN(iso14443_4b, NfcProtocolIso14443_4b); diff --git a/applications/main/nfc/helpers/protocol_support/iso15693_3/iso15693_3.c b/applications/main/nfc/helpers/protocol_support/iso15693_3/iso15693_3.c index 7efd102f1..a40e95e8b 100644 --- a/applications/main/nfc/helpers/protocol_support/iso15693_3/iso15693_3.c +++ b/applications/main/nfc/helpers/protocol_support/iso15693_3/iso15693_3.c @@ -162,3 +162,5 @@ const NfcProtocolSupportBase nfc_protocol_support_iso15693_3 = { .on_event = nfc_protocol_support_common_on_event_empty, }, }; + +NFC_PROTOCOL_SUPPORT_PLUGIN(iso15693_3, NfcProtocolIso15693_3); diff --git a/applications/main/nfc/helpers/protocol_support/mf_classic/mf_classic.c b/applications/main/nfc/helpers/protocol_support/mf_classic/mf_classic.c index 4f8540d6e..3a2aa6c75 100644 --- a/applications/main/nfc/helpers/protocol_support/mf_classic/mf_classic.c +++ b/applications/main/nfc/helpers/protocol_support/mf_classic/mf_classic.c @@ -311,3 +311,5 @@ const NfcProtocolSupportBase nfc_protocol_support_mf_classic = { .on_event = nfc_protocol_support_common_on_event_empty, }, }; + +NFC_PROTOCOL_SUPPORT_PLUGIN(mf_classic, NfcProtocolMfClassic); diff --git a/applications/main/nfc/helpers/protocol_support/mf_desfire/mf_desfire.c b/applications/main/nfc/helpers/protocol_support/mf_desfire/mf_desfire.c index deba1bca2..3b80bc952 100644 --- a/applications/main/nfc/helpers/protocol_support/mf_desfire/mf_desfire.c +++ b/applications/main/nfc/helpers/protocol_support/mf_desfire/mf_desfire.c @@ -125,3 +125,5 @@ const NfcProtocolSupportBase nfc_protocol_support_mf_desfire = { .on_event = nfc_protocol_support_common_on_event_empty, }, }; + +NFC_PROTOCOL_SUPPORT_PLUGIN(mf_desfire, NfcProtocolMfDesfire); diff --git a/applications/main/nfc/helpers/protocol_support/mf_plus/mf_plus.c b/applications/main/nfc/helpers/protocol_support/mf_plus/mf_plus.c index c7b36e21e..9bacbab59 100644 --- a/applications/main/nfc/helpers/protocol_support/mf_plus/mf_plus.c +++ b/applications/main/nfc/helpers/protocol_support/mf_plus/mf_plus.c @@ -121,3 +121,5 @@ const NfcProtocolSupportBase nfc_protocol_support_mf_plus = { .on_event = nfc_protocol_support_common_on_event_empty, }, }; + +NFC_PROTOCOL_SUPPORT_PLUGIN(mf_plus, NfcProtocolMfPlus); diff --git a/applications/main/nfc/helpers/protocol_support/mf_ultralight/mf_ultralight.c b/applications/main/nfc/helpers/protocol_support/mf_ultralight/mf_ultralight.c index 3adf2a1f5..7fc97b43d 100644 --- a/applications/main/nfc/helpers/protocol_support/mf_ultralight/mf_ultralight.c +++ b/applications/main/nfc/helpers/protocol_support/mf_ultralight/mf_ultralight.c @@ -307,3 +307,5 @@ const NfcProtocolSupportBase nfc_protocol_support_mf_ultralight = { .on_event = nfc_protocol_support_common_on_event_empty, }, }; + +NFC_PROTOCOL_SUPPORT_PLUGIN(mf_ultralight, NfcProtocolMfUltralight); diff --git a/applications/main/nfc/helpers/protocol_support/nfc_protocol_support.c b/applications/main/nfc/helpers/protocol_support/nfc_protocol_support.c index b559667be..3c4e1f26d 100644 --- a/applications/main/nfc/helpers/protocol_support/nfc_protocol_support.c +++ b/applications/main/nfc/helpers/protocol_support/nfc_protocol_support.c @@ -9,9 +9,13 @@ #include "nfc/nfc_app_i.h" -#include "nfc_protocol_support_defs.h" +#include "nfc_protocol_support_base.h" #include "nfc_protocol_support_gui_common.h" +#include + +#define TAG "NfcProtocolSupport" + /** * @brief Common scene entry handler. * @@ -46,6 +50,145 @@ typedef struct { static const NfcProtocolSupportCommonSceneBase nfc_protocol_support_scenes[]; +const NfcProtocolSupportBase nfc_protocol_support_empty = { + .features = NfcProtocolFeatureNone, + + .scene_info = + { + .on_enter = nfc_protocol_support_common_on_enter_empty, + .on_event = nfc_protocol_support_common_on_event_empty, + }, + .scene_more_info = + { + .on_enter = nfc_protocol_support_common_on_enter_empty, + .on_event = nfc_protocol_support_common_on_event_empty, + }, + .scene_read = + { + .on_enter = nfc_protocol_support_common_on_enter_empty, + .on_event = nfc_protocol_support_common_on_event_empty, + }, + .scene_read_menu = + { + .on_enter = nfc_protocol_support_common_on_enter_empty, + .on_event = nfc_protocol_support_common_on_event_empty, + }, + .scene_read_success = + { + .on_enter = nfc_protocol_support_common_on_enter_empty, + .on_event = nfc_protocol_support_common_on_event_empty, + }, + .scene_saved_menu = + { + .on_enter = nfc_protocol_support_common_on_enter_empty, + .on_event = nfc_protocol_support_common_on_event_empty, + }, + .scene_save_name = + { + .on_enter = nfc_protocol_support_common_on_enter_empty, + .on_event = nfc_protocol_support_common_on_event_empty, + }, + .scene_emulate = + { + .on_enter = nfc_protocol_support_common_on_enter_empty, + .on_event = nfc_protocol_support_common_on_event_empty, + }, +}; + +struct NfcProtocolSupport { + NfcProtocol protocol; + PluginManager* plugin_manager; + const NfcProtocolSupportBase* base; +}; + +const char* nfc_protocol_support_plugin_names[NfcProtocolNum] = { + [NfcProtocolIso14443_3a] = "iso14443_3a", + [NfcProtocolIso14443_3b] = "iso14443_3b", + [NfcProtocolIso14443_4a] = "iso14443_4a", + [NfcProtocolIso14443_4b] = "iso14443_4b", + [NfcProtocolIso15693_3] = "iso15693_3", + [NfcProtocolFelica] = "felica", + [NfcProtocolMfUltralight] = "mf_ultralight", + [NfcProtocolMfClassic] = "mf_classic", + [NfcProtocolMfPlus] = "mf_plus", + [NfcProtocolMfDesfire] = "mf_desfire", + [NfcProtocolSlix] = "slix", + [NfcProtocolSt25tb] = "st25tb", + [NfcProtocolEmv] = "emv", + /* Add new protocol support plugin names here */ +}; + +void nfc_protocol_support_alloc(NfcProtocol protocol, void* context) { + furi_assert(context); + + NfcApp* instance = context; + + NfcProtocolSupport* protocol_support = malloc(sizeof(NfcProtocolSupport)); + protocol_support->protocol = protocol; + + const char* protocol_name = nfc_protocol_support_plugin_names[protocol]; + FuriString* plugin_path = + furi_string_alloc_printf(APP_ASSETS_PATH("plugins/nfc_%s.fal"), protocol_name); + FURI_LOG_D(TAG, "Loading %s", furi_string_get_cstr(plugin_path)); + + protocol_support->plugin_manager = plugin_manager_alloc( + NFC_PROTOCOL_SUPPORT_PLUGIN_APP_ID, + NFC_PROTOCOL_SUPPORT_PLUGIN_API_VERSION, + composite_api_resolver_get(instance->api_resolver)); + do { + if(plugin_manager_load_single( + protocol_support->plugin_manager, furi_string_get_cstr(plugin_path)) != + PluginManagerErrorNone) { + break; + } + const NfcProtocolSupportPlugin* plugin = + plugin_manager_get_ep(protocol_support->plugin_manager, 0); + + if(plugin->protocol != protocol) { + break; + } + + protocol_support->base = plugin->base; + } while(false); + if(!protocol_support->base) { + protocol_support->base = &nfc_protocol_support_empty; + plugin_manager_free(protocol_support->plugin_manager); + protocol_support->plugin_manager = NULL; + } + + furi_string_free(plugin_path); + + instance->protocol_support = protocol_support; +} + +void nfc_protocol_support_free(void* context) { + furi_assert(context); + + NfcApp* instance = context; + + if(instance->protocol_support->plugin_manager) { + plugin_manager_free(instance->protocol_support->plugin_manager); + } + free(instance->protocol_support); + instance->protocol_support = NULL; +} + +static const NfcProtocolSupportBase* + nfc_protocol_support_get(NfcProtocol protocol, void* context) { + furi_assert(context); + + NfcApp* instance = context; + + if(instance->protocol_support && instance->protocol_support->protocol != protocol) { + nfc_protocol_support_free(instance); + } + if(!instance->protocol_support) { + nfc_protocol_support_alloc(protocol, instance); + } + + return instance->protocol_support->base; +} + // Interface functions void nfc_protocol_support_on_enter(NfcProtocolSupportScene scene, void* context) { furi_assert(scene < NfcProtocolSupportSceneCount); @@ -74,17 +217,23 @@ void nfc_protocol_support_on_exit(NfcProtocolSupportScene scene, void* context) nfc_protocol_support_scenes[scene].on_exit(instance); } -bool nfc_protocol_support_has_feature(NfcProtocol protocol, NfcProtocolFeature feature) { - return nfc_protocol_support[protocol]->features & feature; +bool nfc_protocol_support_has_feature( + NfcProtocol protocol, + void* context, + NfcProtocolFeature feature) { + furi_assert(context); + + NfcApp* instance = context; + return nfc_protocol_support_get(protocol, instance)->features & feature; } // Common scene handlers // SceneInfo static void nfc_protocol_support_scene_info_on_enter(NfcApp* instance) { const NfcProtocol protocol = nfc_device_get_protocol(instance->nfc_device); - nfc_protocol_support[protocol]->scene_info.on_enter(instance); + nfc_protocol_support_get(protocol, instance)->scene_info.on_enter(instance); - if(nfc_protocol_support_has_feature(protocol, NfcProtocolFeatureMoreInfo)) { + if(nfc_protocol_support_has_feature(protocol, instance, NfcProtocolFeatureMoreInfo)) { widget_add_button_element( instance->widget, GuiButtonTypeRight, @@ -124,7 +273,7 @@ static void nfc_protocol_support_scene_info_on_exit(NfcApp* instance) { // SceneMoreInfo static void nfc_protocol_support_scene_more_info_on_enter(NfcApp* instance) { const NfcProtocol protocol = nfc_device_get_protocol(instance->nfc_device); - nfc_protocol_support[protocol]->scene_more_info.on_enter(instance); + nfc_protocol_support_get(protocol, instance)->scene_more_info.on_enter(instance); } static bool @@ -132,7 +281,8 @@ static bool bool consumed = false; const NfcProtocol protocol = nfc_device_get_protocol(instance->nfc_device); - consumed = nfc_protocol_support[protocol]->scene_more_info.on_event(instance, event); + consumed = + nfc_protocol_support_get(protocol, instance)->scene_more_info.on_event(instance, event); return consumed; } @@ -157,7 +307,7 @@ static void nfc_protocol_support_scene_read_on_enter(NfcApp* instance) { //nfc_supported_cards_load_cache(instance->nfc_supported_cards); // Start poller with the appropriate callback - nfc_protocol_support[protocol]->scene_read.on_enter(instance); + nfc_protocol_support_get(protocol, instance)->scene_read.on_enter(instance); nfc_blink_read_start(instance); } @@ -186,7 +336,8 @@ static bool nfc_protocol_support_scene_read_on_event(NfcApp* instance, SceneMana } else { const NfcProtocol protocol = nfc_detected_protocols_get_selected(instance->detected_protocols); - consumed = nfc_protocol_support[protocol]->scene_read.on_event(instance, event); + consumed = nfc_protocol_support_get(protocol, instance) + ->scene_read.on_event(instance, event); } } else if(event.event == NfcCustomEventPollerFailure) { nfc_poller_stop(instance->poller); @@ -199,7 +350,8 @@ static bool nfc_protocol_support_scene_read_on_event(NfcApp* instance, SceneMana } else if(event.event == NfcCustomEventCardDetected) { const NfcProtocol protocol = nfc_detected_protocols_get_selected(instance->detected_protocols); - consumed = nfc_protocol_support[protocol]->scene_read.on_event(instance, event); + consumed = + nfc_protocol_support_get(protocol, instance)->scene_read.on_event(instance, event); } } else if(event.type == SceneManagerEventTypeBack) { nfc_poller_stop(instance->poller); @@ -241,7 +393,7 @@ static void nfc_protocol_support_scene_read_menu_on_enter(NfcApp* instance) { instance); } - if(nfc_protocol_support_has_feature(protocol, NfcProtocolFeatureEmulateUid)) { + if(nfc_protocol_support_has_feature(protocol, instance, NfcProtocolFeatureEmulateUid)) { submenu_add_item( submenu, "Emulate UID", @@ -249,7 +401,7 @@ static void nfc_protocol_support_scene_read_menu_on_enter(NfcApp* instance) { nfc_protocol_support_common_submenu_callback, instance); - } else if(nfc_protocol_support_has_feature(protocol, NfcProtocolFeatureEmulateFull)) { + } else if(nfc_protocol_support_has_feature(protocol, instance, NfcProtocolFeatureEmulateFull)) { submenu_add_item( submenu, "Emulate", @@ -258,7 +410,7 @@ static void nfc_protocol_support_scene_read_menu_on_enter(NfcApp* instance) { instance); } - nfc_protocol_support[protocol]->scene_read_menu.on_enter(instance); + nfc_protocol_support_get(protocol, instance)->scene_read_menu.on_enter(instance); submenu_add_item( submenu, @@ -293,7 +445,8 @@ static bool consumed = true; } else { const NfcProtocol protocol = nfc_device_get_protocol(instance->nfc_device); - consumed = nfc_protocol_support[protocol]->scene_read_menu.on_event(instance, event); + consumed = nfc_protocol_support_get(protocol, instance) + ->scene_read_menu.on_event(instance, event); } } else if(event.type == SceneManagerEventTypeBack) { @@ -322,7 +475,7 @@ static void nfc_protocol_support_scene_read_success_on_enter(NfcApp* instance) { instance->widget, 0, 0, 128, 52, furi_string_get_cstr(temp_str)); } else { const NfcProtocol protocol = nfc_device_get_protocol(instance->nfc_device); - nfc_protocol_support[protocol]->scene_read_success.on_enter(instance); + nfc_protocol_support_get(protocol, instance)->scene_read_success.on_enter(instance); } furi_string_free(temp_str); @@ -370,7 +523,7 @@ static void nfc_protocol_support_scene_saved_menu_on_enter(NfcApp* instance) { Submenu* submenu = instance->submenu; // Header submenu items - if(nfc_protocol_support_has_feature(protocol, NfcProtocolFeatureEmulateUid)) { + if(nfc_protocol_support_has_feature(protocol, instance, NfcProtocolFeatureEmulateUid)) { submenu_add_item( submenu, "Emulate UID", @@ -378,7 +531,7 @@ static void nfc_protocol_support_scene_saved_menu_on_enter(NfcApp* instance) { nfc_protocol_support_common_submenu_callback, instance); - } else if(nfc_protocol_support_has_feature(protocol, NfcProtocolFeatureEmulateFull)) { + } else if(nfc_protocol_support_has_feature(protocol, instance, NfcProtocolFeatureEmulateFull)) { submenu_add_item( submenu, "Emulate", @@ -387,7 +540,7 @@ static void nfc_protocol_support_scene_saved_menu_on_enter(NfcApp* instance) { instance); } - if(nfc_protocol_support_has_feature(protocol, NfcProtocolFeatureEditUid)) { + if(nfc_protocol_support_has_feature(protocol, instance, NfcProtocolFeatureEditUid)) { submenu_add_item( submenu, "Edit UID", @@ -397,7 +550,7 @@ static void nfc_protocol_support_scene_saved_menu_on_enter(NfcApp* instance) { } // Protocol-dependent menu items - nfc_protocol_support[protocol]->scene_saved_menu.on_enter(instance); + nfc_protocol_support_get(protocol, instance)->scene_saved_menu.on_enter(instance); // Trailer submenu items if(nfc_has_shadow_file(instance)) { @@ -465,7 +618,8 @@ static bool consumed = true; } else { const NfcProtocol protocol = nfc_device_get_protocol(instance->nfc_device); - consumed = nfc_protocol_support[protocol]->scene_saved_menu.on_event(instance, event); + consumed = nfc_protocol_support_get(protocol, instance) + ->scene_saved_menu.on_event(instance, event); } } else if(event.type == SceneManagerEventTypeBack) { @@ -541,8 +695,8 @@ static bool DolphinDeedNfcSave); const NfcProtocol protocol = nfc_device_get_protocol(instance->nfc_device); - consumed = - nfc_protocol_support[protocol]->scene_save_name.on_event(instance, event); + consumed = nfc_protocol_support_get(protocol, instance) + ->scene_save_name.on_event(instance, event); } else { consumed = scene_manager_search_and_switch_to_previous_scene( instance->scene_manager, NfcSceneStart); @@ -586,7 +740,7 @@ static void nfc_protocol_support_scene_emulate_on_enter(NfcApp* instance) { widget_add_icon_element(widget, 0, 0, &I_NFC_dolphin_emulation_51x64); - if(nfc_protocol_support_has_feature(protocol, NfcProtocolFeatureEmulateUid)) { + if(nfc_protocol_support_has_feature(protocol, instance, NfcProtocolFeatureEmulateUid)) { widget_add_string_element( widget, 90, 26, AlignCenter, AlignCenter, FontPrimary, "Emulating UID"); @@ -627,7 +781,7 @@ static void nfc_protocol_support_scene_emulate_on_enter(NfcApp* instance) { furi_string_reset(instance->text_box_store); // instance->listener is allocated in the respective on_enter() handler - nfc_protocol_support[protocol]->scene_emulate.on_enter(instance); + nfc_protocol_support_get(protocol, instance)->scene_emulate.on_enter(instance); scene_manager_set_scene_state( instance->scene_manager, NfcSceneEmulate, NfcSceneEmulateStateWidget); @@ -723,7 +877,7 @@ static void nfc_protocol_support_scene_rpc_setup_ui_and_emulate(NfcApp* instance nfc_blink_emulate_start(instance); const NfcProtocol protocol = nfc_device_get_protocol(instance->nfc_device); - nfc_protocol_support[protocol]->scene_emulate.on_enter(instance); + nfc_protocol_support_get(protocol, instance)->scene_emulate.on_enter(instance); instance->rpc_state = NfcRpcStateEmulating; } diff --git a/applications/main/nfc/helpers/protocol_support/nfc_protocol_support.h b/applications/main/nfc/helpers/protocol_support/nfc_protocol_support.h index d3efc3a41..157d00b83 100644 --- a/applications/main/nfc/helpers/protocol_support/nfc_protocol_support.h +++ b/applications/main/nfc/helpers/protocol_support/nfc_protocol_support.h @@ -40,7 +40,7 @@ * * | Filename | Explanation | * |:-----------------------|:------------| - * | protocol_name.h | Interface structure declaration used in `nfc_protocol_support_defs.c`. | + * | protocol_name.h | Interface structure declaration. | * | protocol_name.c | Protocol-specific scene implemenatations and definitions. | * | protocol_name_render.h | Protocol-specific rendering (formatting) functions. Used for converting protocol data into textual descriptions. | * | protocol_name_render.c | Implementations for functions declared in `protocol_name_render.h`.| @@ -65,8 +65,13 @@ * * After completing the protocol support, it must be registered within the application in order for it to be usable. * - * In nfc_protocol_support_defs.c, include the `protocol_name.h` file and add a new entry in the `nfc_protocol_support[]` - * array under the appropriate index. + * In `protocol_name.c`, add `NFC_PROTOCOL_SUPPORT_PLUGIN(protocol_name, NfcProtocolName)` at the bottom, + * below the `NfcProtocolSupportBase` structure definition. + * + * In `application.fam`, add a new entry for the plugin, following the other examples. + * + * In nfc_protocol_support.c, add a new entry in the `nfc_protocol_support_plugin_names[]` + * array under the appropriate index with the name of the plugin (without the `nfc_` prefix). * * ## Done! * @@ -80,6 +85,10 @@ #include "nfc_protocol_support_common.h" +typedef struct NfcProtocolSupport NfcProtocolSupport; + +void nfc_protocol_support_free(void* context); + /** * @brief Abstract interface for on_enter() scene handler. * @@ -113,4 +122,7 @@ bool nfc_protocol_support_on_event( */ void nfc_protocol_support_on_exit(NfcProtocolSupportScene scene, void* context); -bool nfc_protocol_support_has_feature(NfcProtocol protocol, NfcProtocolFeature feature); +bool nfc_protocol_support_has_feature( + NfcProtocol protocol, + void* context, + NfcProtocolFeature feature); diff --git a/applications/main/nfc/helpers/protocol_support/nfc_protocol_support_base.h b/applications/main/nfc/helpers/protocol_support/nfc_protocol_support_base.h index eec736ca2..7220c4d3d 100644 --- a/applications/main/nfc/helpers/protocol_support/nfc_protocol_support_base.h +++ b/applications/main/nfc/helpers/protocol_support/nfc_protocol_support_base.h @@ -9,6 +9,8 @@ #include "../../nfc_app.h" #include "../../nfc_app_i.h" +#include + /** * @brief Scene entry handler. * @@ -115,3 +117,37 @@ typedef struct { */ NfcProtocolSupportSceneBase scene_emulate; } NfcProtocolSupportBase; + +/** + * @brief Unique string identifier for protocol support plugins. + */ +#define NFC_PROTOCOL_SUPPORT_PLUGIN_APP_ID "NfcProtocolSupportPlugin" + +/** + * @brief Currently supported plugin API version. + */ +#define NFC_PROTOCOL_SUPPORT_PLUGIN_API_VERSION 1 + +/** + * @brief Protocol support plugin interface. + */ +typedef struct { + NfcProtocol protocol; /**< Identifier of the protocol this plugin implements. */ + const NfcProtocolSupportBase* base; /**< Pointer to the protocol support interface. */ +} NfcProtocolSupportPlugin; + +#define NFC_PROTOCOL_SUPPORT_PLUGIN(name, protocol) \ + static const NfcProtocolSupportPlugin nfc_protocol_support_##name##_desc = { \ + protocol, \ + &nfc_protocol_support_##name, \ + }; \ + \ + static const FlipperAppPluginDescriptor plugin_descriptor_##name = { \ + .appid = NFC_PROTOCOL_SUPPORT_PLUGIN_APP_ID, \ + .ep_api_version = NFC_PROTOCOL_SUPPORT_PLUGIN_API_VERSION, \ + .entry_point = &nfc_protocol_support_##name##_desc, \ + }; \ + \ + const FlipperAppPluginDescriptor* nfc_##name##_ep(void) { \ + return &plugin_descriptor_##name; \ + } diff --git a/applications/main/nfc/helpers/protocol_support/nfc_protocol_support_defs.c b/applications/main/nfc/helpers/protocol_support/nfc_protocol_support_defs.c deleted file mode 100644 index a80cd6cc0..000000000 --- a/applications/main/nfc/helpers/protocol_support/nfc_protocol_support_defs.c +++ /dev/null @@ -1,49 +0,0 @@ -/** - * @file nfc_protocol_support_defs.c - * @brief Application-level protocol support definitions. - * - * This file is to be modified whenever support for - * a new protocol is to be added. - */ -#include "nfc_protocol_support_base.h" - -#include - -#include "iso14443_3a/iso14443_3a.h" -#include "iso14443_3b/iso14443_3b.h" -#include "iso14443_4a/iso14443_4a.h" -#include "iso14443_4b/iso14443_4b.h" -#include "iso15693_3/iso15693_3.h" -#include "felica/felica.h" -#include "mf_ultralight/mf_ultralight.h" -#include "mf_classic/mf_classic.h" -#include "mf_plus/mf_plus.h" -#include "mf_desfire/mf_desfire.h" -#include "emv/emv.h" -#include "slix/slix.h" -#include "st25tb/st25tb.h" - -/** - * @brief Array of pointers to concrete protocol support implementations. - * - * When adding support for a new protocol, add it to the end of this array - * under its respective index. - * - * @see nfc_protocol.h - */ -const NfcProtocolSupportBase* nfc_protocol_support[NfcProtocolNum] = { - [NfcProtocolIso14443_3a] = &nfc_protocol_support_iso14443_3a, - [NfcProtocolIso14443_3b] = &nfc_protocol_support_iso14443_3b, - [NfcProtocolIso14443_4a] = &nfc_protocol_support_iso14443_4a, - [NfcProtocolIso14443_4b] = &nfc_protocol_support_iso14443_4b, - [NfcProtocolIso15693_3] = &nfc_protocol_support_iso15693_3, - [NfcProtocolFelica] = &nfc_protocol_support_felica, - [NfcProtocolMfUltralight] = &nfc_protocol_support_mf_ultralight, - [NfcProtocolMfClassic] = &nfc_protocol_support_mf_classic, - [NfcProtocolMfPlus] = &nfc_protocol_support_mf_plus, - [NfcProtocolMfDesfire] = &nfc_protocol_support_mf_desfire, - [NfcProtocolSlix] = &nfc_protocol_support_slix, - [NfcProtocolSt25tb] = &nfc_protocol_support_st25tb, - [NfcProtocolEmv] = &nfc_protocol_support_emv, - /* Add new protocol support implementations here */ -}; diff --git a/applications/main/nfc/helpers/protocol_support/nfc_protocol_support_defs.h b/applications/main/nfc/helpers/protocol_support/nfc_protocol_support_defs.h deleted file mode 100644 index 7a9d5b637..000000000 --- a/applications/main/nfc/helpers/protocol_support/nfc_protocol_support_defs.h +++ /dev/null @@ -1,12 +0,0 @@ -/** - * @file nfc_protocol_support_defs.h - * @brief Application-level protocol support declarations. - */ -#pragma once - -#include "nfc_protocol_support_base.h" - -/** - * @brief Declaraion of array of pointers to protocol support implementations. - */ -extern const NfcProtocolSupportBase* nfc_protocol_support[]; diff --git a/applications/main/nfc/helpers/protocol_support/nfc_protocol_support_gui_common.h b/applications/main/nfc/helpers/protocol_support/nfc_protocol_support_gui_common.h index 3230f1a7e..ddee280be 100644 --- a/applications/main/nfc/helpers/protocol_support/nfc_protocol_support_gui_common.h +++ b/applications/main/nfc/helpers/protocol_support/nfc_protocol_support_gui_common.h @@ -23,6 +23,10 @@ enum { SubmenuIndexCommonMax, /**< Special value, internal use. */ }; +#ifdef __cplusplus +extern "C" { +#endif + /** * @brief Common submenu callback. * @@ -84,3 +88,7 @@ void nfc_protocol_support_common_on_enter_empty(NfcApp* instance); * @returns always true. */ bool nfc_protocol_support_common_on_event_empty(NfcApp* instance, SceneManagerEvent event); + +#ifdef __cplusplus +} +#endif diff --git a/applications/main/nfc/helpers/protocol_support/nfc_protocol_support_unlock_helper.h b/applications/main/nfc/helpers/protocol_support/nfc_protocol_support_unlock_helper.h index 34f52496b..9cb35971e 100644 --- a/applications/main/nfc/helpers/protocol_support/nfc_protocol_support_unlock_helper.h +++ b/applications/main/nfc/helpers/protocol_support/nfc_protocol_support_unlock_helper.h @@ -5,5 +5,13 @@ typedef enum { NfcSceneReadMenuStateCardFound, } NfcSceneUnlockReadState; +#ifdef __cplusplus +extern "C" { +#endif + void nfc_unlock_helper_setup_from_state(NfcApp* instance); void nfc_unlock_helper_card_detected_handler(NfcApp* instance); + +#ifdef __cplusplus +} +#endif diff --git a/applications/main/nfc/helpers/protocol_support/slix/slix.c b/applications/main/nfc/helpers/protocol_support/slix/slix.c index 35592eaa1..52345e3a2 100644 --- a/applications/main/nfc/helpers/protocol_support/slix/slix.c +++ b/applications/main/nfc/helpers/protocol_support/slix/slix.c @@ -158,3 +158,5 @@ const NfcProtocolSupportBase nfc_protocol_support_slix = { .on_event = nfc_protocol_support_common_on_event_empty, }, }; + +NFC_PROTOCOL_SUPPORT_PLUGIN(slix, NfcProtocolSlix); diff --git a/applications/main/nfc/helpers/protocol_support/st25tb/st25tb.c b/applications/main/nfc/helpers/protocol_support/st25tb/st25tb.c index 0305d614c..761b47f4b 100644 --- a/applications/main/nfc/helpers/protocol_support/st25tb/st25tb.c +++ b/applications/main/nfc/helpers/protocol_support/st25tb/st25tb.c @@ -109,3 +109,5 @@ const NfcProtocolSupportBase nfc_protocol_support_st25tb = { .on_event = nfc_protocol_support_common_on_event_empty, }, }; + +NFC_PROTOCOL_SUPPORT_PLUGIN(st25tb, NfcProtocolSt25tb); diff --git a/applications/main/nfc/nfc_app.c b/applications/main/nfc/nfc_app.c index db09dde05..1cff11abf 100644 --- a/applications/main/nfc/nfc_app.c +++ b/applications/main/nfc/nfc_app.c @@ -1,7 +1,9 @@ #include "nfc_app_i.h" +#include "api/nfc_app_api_interface.h" #include "helpers/protocol_support/nfc_protocol_support.h" #include +#include #include bool nfc_custom_event_callback(void* context, uint32_t event) { @@ -50,12 +52,16 @@ NfcApp* nfc_app_alloc(void) { instance->nfc = nfc_alloc(); + instance->api_resolver = composite_api_resolver_alloc(); + composite_api_resolver_add(instance->api_resolver, firmware_api_interface); + composite_api_resolver_add(instance->api_resolver, nfc_application_api_interface); + instance->detected_protocols = nfc_detected_protocols_alloc(); instance->felica_auth = felica_auth_alloc(); instance->mf_ul_auth = mf_ultralight_auth_alloc(); instance->slix_unlock = slix_unlock_alloc(); instance->mfc_key_cache = mf_classic_key_cache_alloc(); - instance->nfc_supported_cards = nfc_supported_cards_alloc(); + instance->nfc_supported_cards = nfc_supported_cards_alloc(instance->api_resolver); // Nfc device instance->nfc_device = nfc_device_alloc(); @@ -149,6 +155,9 @@ void nfc_app_free(NfcApp* instance) { slix_unlock_free(instance->slix_unlock); mf_classic_key_cache_free(instance->mfc_key_cache); nfc_supported_cards_free(instance->nfc_supported_cards); + if(instance->protocol_support) { + nfc_protocol_support_free(instance); + } // Nfc device nfc_device_free(instance->nfc_device); @@ -470,7 +479,7 @@ static bool nfc_is_hal_ready(void) { static void nfc_show_initial_scene_for_device(NfcApp* nfc) { NfcProtocol prot = nfc_device_get_protocol(nfc->nfc_device); uint32_t scene = nfc_protocol_support_has_feature( - prot, NfcProtocolFeatureEmulateFull | NfcProtocolFeatureEmulateUid) ? + prot, nfc, NfcProtocolFeatureEmulateFull | NfcProtocolFeatureEmulateUid) ? NfcSceneEmulate : NfcSceneSavedMenu; // Load plugins (parsers) in case if we are in the saved menu diff --git a/applications/main/nfc/nfc_app_i.h b/applications/main/nfc/nfc_app_i.h index 3be8ba571..6ff7b5717 100644 --- a/applications/main/nfc/nfc_app_i.h +++ b/applications/main/nfc/nfc_app_i.h @@ -32,10 +32,12 @@ #include "helpers/mfkey32_logger.h" #include "helpers/nfc_emv_parser.h" #include "helpers/mf_classic_key_cache.h" +#include "helpers/protocol_support/nfc_protocol_support.h" #include "helpers/nfc_supported_cards.h" #include "helpers/felica_auth.h" #include "helpers/slix_unlock.h" +#include #include #include #include @@ -149,6 +151,8 @@ struct NfcApp { Mfkey32Logger* mfkey32_logger; MfUserDict* mf_user_dict; MfClassicKeyCache* mfc_key_cache; + CompositeApiResolver* api_resolver; + NfcProtocolSupport* protocol_support; NfcSupportedCards* nfc_supported_cards; NfcDevice* nfc_device; @@ -178,6 +182,10 @@ typedef enum { NfcSceneSaveConfirmStateCrackNonces, } NfcSceneSaveConfirmState; +#ifdef __cplusplus +extern "C" { +#endif + int32_t nfc_task(void* p); void nfc_text_store_set(NfcApp* nfc, const char* text, ...); @@ -215,3 +223,7 @@ void nfc_make_app_folder(NfcApp* instance); void nfc_append_filename_string_when_present(NfcApp* instance, FuriString* string); void nfc_app_run_external(NfcApp* nfc, const char* app_path); + +#ifdef __cplusplus +} +#endif diff --git a/applications/main/nfc/scenes/nfc_scene_start.c b/applications/main/nfc/scenes/nfc_scene_start.c index 01cf35e41..c0d8d7443 100644 --- a/applications/main/nfc/scenes/nfc_scene_start.c +++ b/applications/main/nfc/scenes/nfc_scene_start.c @@ -63,37 +63,25 @@ bool nfc_scene_start_on_event(void* context, SceneManagerEvent event) { bool consumed = false; if(event.type == SceneManagerEventTypeCustom) { + consumed = true; if(event.event == SubmenuIndexRead) { - scene_manager_set_scene_state(nfc->scene_manager, NfcSceneStart, SubmenuIndexRead); scene_manager_next_scene(nfc->scene_manager, NfcSceneDetect); dolphin_deed(DolphinDeedNfcRead); - consumed = true; } else if(event.event == SubmenuIndexDetectReader) { - scene_manager_set_scene_state( - nfc->scene_manager, NfcSceneStart, SubmenuIndexDetectReader); scene_manager_next_scene(nfc->scene_manager, NfcSceneMfClassicDetectReader); - consumed = true; } else if(event.event == SubmenuIndexSaved) { - // Save the scene state explicitly in each branch, so that - // if the user cancels loading a file, the Saved menu item - // is properly reselected. - scene_manager_set_scene_state(nfc->scene_manager, NfcSceneStart, SubmenuIndexSaved); scene_manager_next_scene(nfc->scene_manager, NfcSceneFileSelect); - consumed = true; } else if(event.event == SubmenuIndexExtraAction) { - scene_manager_set_scene_state( - nfc->scene_manager, NfcSceneStart, SubmenuIndexExtraAction); scene_manager_next_scene(nfc->scene_manager, NfcSceneExtraActions); - consumed = true; } else if(event.event == SubmenuIndexAddManually) { - scene_manager_set_scene_state( - nfc->scene_manager, NfcSceneStart, SubmenuIndexAddManually); scene_manager_next_scene(nfc->scene_manager, NfcSceneSetType); - consumed = true; } else if(event.event == SubmenuIndexDebug) { - scene_manager_set_scene_state(nfc->scene_manager, NfcSceneStart, SubmenuIndexDebug); scene_manager_next_scene(nfc->scene_manager, NfcSceneDebug); - consumed = true; + } else { + consumed = false; + } + if(consumed) { + scene_manager_set_scene_state(nfc->scene_manager, NfcSceneStart, event.event); } } return consumed; diff --git a/applications/system/js_app/application.fam b/applications/system/js_app/application.fam index e5d6dbb9c..90e35abe4 100644 --- a/applications/system/js_app/application.fam +++ b/applications/system/js_app/application.fam @@ -32,6 +32,7 @@ App( "js_app.c", "js_modules.c", "js_thread.c", + "js_value.c", "plugin_api/app_api_table.cpp", "modules/js_flipper.c", "modules/js_tests.c", diff --git a/scripts/fbt_tools/fbt_extapps.py b/scripts/fbt_tools/fbt_extapps.py index 61e5f58c8..e284f0dc9 100644 --- a/scripts/fbt_tools/fbt_extapps.py +++ b/scripts/fbt_tools/fbt_extapps.py @@ -291,96 +291,108 @@ def _validate_app_imports(target, source, env): for line in f: app_syms.add(line.split()[0]) unresolved_syms = app_syms - sdk_cache.get_valid_names() - ignore_syms = [ - sym - for sym in unresolved_syms - if sym.startswith( - ( - # example_advanced_plugins app_api_table - "app_api_accumulator_", - # js_app app_api_table - "js_delay_with_flags", - "js_flags_set", - "js_flags_wait", - "js_module_get", - "js_value_buffer_size", - "js_value_parse", - # js_event_loop_api_table - "js_event_loop_get_loop", - # js_gui_api_table - "js_gui_make_view_factory", - # metroflip_api_table - "metroflip_", - "bit_slice_to_dec", - "byte_to_binary", - "read_file", - "apdu_success", - "select_app", - "mf_classic_key_cache_", - "manage_keyfiles", - "uid_to_string", - "handle_keyfile_case", - "get_calypso_", - "get_network_", - "is_calypso_", - "free_calypso_", - "guess_card_type", - "get_intercode_", - "show_navigo_", - "get_opus_", - "show_opus_", - "get_ravkav_", - "show_ravkav_", - "mosgortrans_parse_transport_block", - "render_section_header", - # nfc_app_api_table - "gallagher_deobfuscate_and_parse_credential", - "GALLAGHER_CARDAX_ASCII", - "mosgortrans_parse_transport_block", - "render_section_header", - # totp app_api_table - "totp_", - "memset_s", - "token_info_", - # unit_tests_api_table - "js_thread_run", - "js_thread_stop", - "js_value_buffer_size", - "js_value_parse", - ) - ) - and any( - prefix in source[0].path - for prefix in [ - # example_advanced_plugins app_api_table - "advanced_plugin", - # js_app app_api_table, js_event_loop_api_table, js_gui_api_table - "js_", # js_app and all js_ modules - # metroflip_api_table - "bip_plugin", - "calypso_plugin", - "charliecard_plugin", - "clipper_plugin", - "gocard_plugin", - "itso_plugin", - "metromoney_plugin", - "myki_plugin", - "opal_plugin", - "smartrider_plugin", - "troika_plugin", - # nfc_app_api_table - "gallagher", - "social_moscow", - "troika", - # totp app_api_table - "totp_", - # unit_tests_api_table - "test_js", + known_syms = { + # example_advanced_plugins app_api_table + ("advanced_plugin",): ( + "app_api_accumulator_set", + "app_api_accumulator_get", + "app_api_accumulator_add", + "app_api_accumulator_sub", + "app_api_accumulator_mul", + ), + # js_app app_api_table, js_event_loop_api_table, js_gui_api_table + ("js_",): ( + "js_delay_with_flags", + "js_flags_set", + "js_flags_wait", + "js_module_get", + "js_value_buffer_size", + "js_value_parse", + "js_event_loop_get_loop", + "js_gui_make_view_factory", + ), + # metroflip_api_table + ( + "bip_plugin", + "calypso_plugin", + "charliecard_plugin", + "clipper_plugin", + "gocard_plugin", + "itso_plugin", + "metromoney_plugin", + "myki_plugin", + "opal_plugin", + "smartrider_plugin", + "troika_plugin", + ): ( + "metroflip_", + "bit_slice_to_dec", + "byte_to_binary", + "read_file", + "apdu_success", + "select_app", + "mf_classic_key_cache_", + "manage_keyfiles", + "uid_to_string", + "handle_keyfile_case", + "get_calypso_", + "get_network_", + "is_calypso_", + "free_calypso_", + "guess_card_type", + "get_intercode_", + "show_navigo_", + "get_opus_", + "show_opus_", + "get_ravkav_", + "show_ravkav_", + "mosgortrans_parse_transport_block", + "render_section_header", + ), + # nfc_app_api_table + ( + "nfc_", + "gallagher", + "social_moscow", + "troika", + ): ( + "gallagher_deobfuscate_and_parse_credential", + "GALLAGHER_CARDAX_ASCII", + "mosgortrans_parse_transport_block", + "render_section_header", + "nfc_append_filename_string_when_present", + "nfc_protocol_support_common_submenu_callback", + "nfc_protocol_support_common_widget_callback", + "nfc_protocol_support_common_on_enter_empty", + "nfc_protocol_support_common_on_event_empty", + "nfc_unlock_helper_setup_from_state", + "nfc_unlock_helper_card_detected_handler", + ), + # totp app_api_table + ("totp_",): ( + "totp_", + "memset_s", + "token_info_", + ), + # unit_tests_api_table + ("test_js",): ( + "js_thread_run", + "js_thread_stop", + "js_value_buffer_size", + "js_value_parse", + ), + } + ignore_syms = [] + for source_names, sym_prefixes in known_syms.items(): + if any(source_name in source[0].path for source_name in source_names): + ignore_syms = [ + unresolved_sym + for unresolved_sym in unresolved_syms + if unresolved_sym.startswith(sym_prefixes) ] - ) - ] - for sym in ignore_syms: - unresolved_syms.remove(sym) + break + for ignore_sym in ignore_syms: + unresolved_syms.remove(ignore_sym) if unresolved_syms: warning_msg = fg.brightyellow( f"{source[0].path}: app may not be runnable. Symbols not resolved using firmware's API: "