NFC: Split NfcProtocolSupport into plugins

This commit is contained in:
Willy-JL
2025-04-13 03:01:10 +01:00
parent 7b95117e32
commit 399c72dd35
23 changed files with 423 additions and 92 deletions

View File

@@ -1,5 +1,7 @@
#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"
/*
* A list of app's private functions and objects to expose for plugins.
@@ -22,4 +24,13 @@ static constexpr auto nfc_app_api_table = sort(create_array_t<sym_entry>(
(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_on_enter_empty, void, (NfcApp * instance)),
API_METHOD(
nfc_protocol_support_common_on_event_empty,
bool,
(NfcApp * instance, SceneManagerEvent event))));

View File

@@ -19,6 +19,138 @@ App(
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/**/*.c"],
fal_embedded=True,
)
App(
appid="nfc_felica",
targets=["f7"],
apptype=FlipperAppType.PLUGIN,
entry_point="nfc_felica_ep",
requires=["nfc"],
sources=["helpers/protocol_support/**/*.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/**/*.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/**/*.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/**/*.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/**/*.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/**/*.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/**/*.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/**/*.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/**/*.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/**/*.c"],
fal_embedded=True,
)
App(
appid="nfc_slix",
targets=["f7"],
apptype=FlipperAppType.PLUGIN,
entry_point="nfc_slix_ep",
requires=["nfc"],
sources=["helpers/protocol_support/**/*.c"],
fal_embedded=True,
)
App(
appid="nfc_st25tb",
targets=["f7"],
apptype=FlipperAppType.PLUGIN,
entry_point="nfc_st25tb_ep",
requires=["nfc"],
sources=["helpers/protocol_support/**/*.c"],
fal_embedded=True,
)
# Parser plugins
App(

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);

View File

@@ -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 <flipper_application/plugins/plugin_manager.h>
#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) {
@@ -318,7 +471,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);
@@ -366,7 +519,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",
@@ -374,7 +527,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",
@@ -383,7 +536,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",
@@ -393,7 +546,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)) {
@@ -461,7 +614,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) {
@@ -537,8 +691,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);
@@ -582,7 +736,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");
@@ -623,7 +777,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);
@@ -719,7 +873,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;
}

View File

@@ -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);

View File

@@ -9,6 +9,8 @@
#include "../../nfc_app.h"
#include "../../nfc_app_i.h"
#include <lib/flipper_application/flipper_application.h>
/**
* @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; \
}

View File

@@ -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 <nfc/protocols/nfc_protocol.h>
#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 */
};

View File

@@ -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[];

View File

@@ -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

View File

@@ -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);

View File

@@ -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);

View File

@@ -155,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);
@@ -471,7 +474,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

View File

@@ -32,6 +32,7 @@
#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"
@@ -151,6 +152,7 @@ struct NfcApp {
MfUserDict* mf_user_dict;
MfClassicKeyCache* mfc_key_cache;
CompositeApiResolver* api_resolver;
NfcProtocolSupport* protocol_support;
NfcSupportedCards* nfc_supported_cards;
NfcDevice* nfc_device;
@@ -180,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, ...);
@@ -217,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