mirror of
https://github.com/Next-Flip/Momentum-Firmware.git
synced 2026-05-23 05:24:46 -07:00
merge all nfc app changes
by WillyJL
This commit is contained in:
@@ -13,6 +13,7 @@ typedef enum {
|
||||
NfcCustomEventCardLost,
|
||||
|
||||
NfcCustomEventViewExit,
|
||||
NfcCustomEventRetry,
|
||||
NfcCustomEventWorkerExit,
|
||||
NfcCustomEventWorkerUpdate,
|
||||
NfcCustomEventWrongCard,
|
||||
@@ -30,4 +31,6 @@ typedef enum {
|
||||
NfcCustomEventPollerFailure,
|
||||
|
||||
NfcCustomEventListenerUpdate,
|
||||
|
||||
NfcCustomEventEmulationTimeExpired,
|
||||
} NfcCustomEvent;
|
||||
|
||||
@@ -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 <flipper_application/flipper_application.h>
|
||||
#include <flipper_application/plugins/plugin_manager.h>
|
||||
#include <flipper_application/plugins/composite_resolver.h>
|
||||
#include <loader/firmware_api/firmware_api.h>
|
||||
|
||||
#include <furi.h>
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <core/string.h>
|
||||
#include <flipper_application/plugins/composite_resolver.h>
|
||||
|
||||
#include <nfc/nfc.h>
|
||||
#include <nfc/nfc_device.h>
|
||||
@@ -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
|
||||
|
||||
@@ -128,4 +128,11 @@ const NfcProtocolSupportBase nfc_protocol_support_emv = {
|
||||
.on_enter = nfc_protocol_support_common_on_enter_empty,
|
||||
.on_event = nfc_protocol_support_common_on_event_empty,
|
||||
},
|
||||
.scene_write =
|
||||
{
|
||||
.on_enter = nfc_protocol_support_common_on_enter_empty,
|
||||
.on_event = nfc_protocol_support_common_on_event_empty,
|
||||
},
|
||||
};
|
||||
|
||||
NFC_PROTOCOL_SUPPORT_PLUGIN(emv, NfcProtocolEmv);
|
||||
|
||||
@@ -133,15 +133,6 @@ static void nfc_scene_read_success_on_enter_felica(NfcApp* instance) {
|
||||
furi_string_free(temp_str);
|
||||
}
|
||||
|
||||
static bool nfc_scene_saved_menu_on_event_felica(NfcApp* instance, SceneManagerEvent event) {
|
||||
if(event.type == SceneManagerEventTypeCustom && event.event == SubmenuIndexCommonEdit) {
|
||||
scene_manager_next_scene(instance->scene_manager, NfcSceneSetUid);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void nfc_scene_emulate_on_enter_felica(NfcApp* instance) {
|
||||
const FelicaData* data = nfc_device_get_data(instance->nfc_device, NfcProtocolFelica);
|
||||
instance->listener = nfc_listener_alloc(instance->nfc, NfcProtocolFelica, data);
|
||||
@@ -201,7 +192,7 @@ const NfcProtocolSupportBase nfc_protocol_support_felica = {
|
||||
.scene_saved_menu =
|
||||
{
|
||||
.on_enter = nfc_protocol_support_common_on_enter_empty,
|
||||
.on_event = nfc_scene_saved_menu_on_event_felica,
|
||||
.on_event = nfc_protocol_support_common_on_event_empty,
|
||||
},
|
||||
.scene_save_name =
|
||||
{
|
||||
@@ -213,4 +204,11 @@ const NfcProtocolSupportBase nfc_protocol_support_felica = {
|
||||
.on_enter = nfc_scene_emulate_on_enter_felica,
|
||||
.on_event = nfc_protocol_support_common_on_event_empty,
|
||||
},
|
||||
.scene_write =
|
||||
{
|
||||
.on_enter = nfc_protocol_support_common_on_enter_empty,
|
||||
.on_event = nfc_protocol_support_common_on_event_empty,
|
||||
},
|
||||
};
|
||||
|
||||
NFC_PROTOCOL_SUPPORT_PLUGIN(felica, NfcProtocolFelica);
|
||||
|
||||
@@ -67,21 +67,22 @@ static NfcCommand
|
||||
furi_assert(event.protocol == NfcProtocolIso14443_3a);
|
||||
furi_assert(event.event_data);
|
||||
|
||||
NfcApp* nfc = context;
|
||||
NfcApp* instance = context;
|
||||
Iso14443_3aListenerEvent* iso14443_3a_event = event.event_data;
|
||||
|
||||
if(iso14443_3a_event->type == Iso14443_3aListenerEventTypeReceivedStandardFrame) {
|
||||
if(furi_string_size(nfc->text_box_store) < NFC_LOG_SIZE_MAX) {
|
||||
furi_string_cat_printf(nfc->text_box_store, "R:");
|
||||
if(furi_string_size(instance->text_box_store) < NFC_LOG_SIZE_MAX) {
|
||||
furi_string_cat_printf(instance->text_box_store, "R:");
|
||||
for(size_t i = 0; i < bit_buffer_get_size_bytes(iso14443_3a_event->data->buffer);
|
||||
i++) {
|
||||
furi_string_cat_printf(
|
||||
nfc->text_box_store,
|
||||
instance->text_box_store,
|
||||
" %02X",
|
||||
bit_buffer_get_byte(iso14443_3a_event->data->buffer, i));
|
||||
}
|
||||
furi_string_push_back(nfc->text_box_store, '\n');
|
||||
view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventListenerUpdate);
|
||||
furi_string_push_back(instance->text_box_store, '\n');
|
||||
view_dispatcher_send_custom_event(
|
||||
instance->view_dispatcher, NfcCustomEventListenerUpdate);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -97,15 +98,6 @@ static void nfc_scene_emulate_on_enter_iso14443_3a(NfcApp* instance) {
|
||||
instance->listener, nfc_scene_emulate_listener_callback_iso14443_3a, instance);
|
||||
}
|
||||
|
||||
static bool nfc_scene_read_menu_on_event_iso14443_3a(NfcApp* instance, SceneManagerEvent event) {
|
||||
if(event.type == SceneManagerEventTypeCustom && event.event == SubmenuIndexCommonEmulate) {
|
||||
scene_manager_next_scene(instance->scene_manager, NfcSceneEmulate);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
const NfcProtocolSupportBase nfc_protocol_support_iso14443_3a = {
|
||||
.features = NfcProtocolFeatureEmulateUid | NfcProtocolFeatureEditUid,
|
||||
|
||||
@@ -122,7 +114,7 @@ const NfcProtocolSupportBase nfc_protocol_support_iso14443_3a = {
|
||||
.scene_read_menu =
|
||||
{
|
||||
.on_enter = nfc_protocol_support_common_on_enter_empty,
|
||||
.on_event = nfc_scene_read_menu_on_event_iso14443_3a,
|
||||
.on_event = nfc_protocol_support_common_on_event_empty,
|
||||
},
|
||||
.scene_read_success =
|
||||
{
|
||||
@@ -144,4 +136,11 @@ const NfcProtocolSupportBase nfc_protocol_support_iso14443_3a = {
|
||||
.on_enter = nfc_scene_emulate_on_enter_iso14443_3a,
|
||||
.on_event = nfc_protocol_support_common_on_event_empty,
|
||||
},
|
||||
.scene_write =
|
||||
{
|
||||
.on_enter = nfc_protocol_support_common_on_enter_empty,
|
||||
.on_event = nfc_protocol_support_common_on_event_empty,
|
||||
},
|
||||
};
|
||||
|
||||
NFC_PROTOCOL_SUPPORT_PLUGIN(iso14443_3a, NfcProtocolIso14443_3a);
|
||||
|
||||
@@ -60,19 +60,6 @@ static void nfc_scene_read_success_on_enter_iso14443_3b(NfcApp* instance) {
|
||||
furi_string_free(temp_str);
|
||||
}
|
||||
|
||||
bool nfc_scene_saved_menu_on_event_iso14443_3b_common(NfcApp* instance, SceneManagerEvent event) {
|
||||
if(event.type == SceneManagerEventTypeCustom && event.event == SubmenuIndexCommonEdit) {
|
||||
scene_manager_next_scene(instance->scene_manager, NfcSceneSetUid);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool nfc_scene_saved_menu_on_event_iso14443_3b(NfcApp* instance, SceneManagerEvent event) {
|
||||
return nfc_scene_saved_menu_on_event_iso14443_3b_common(instance, event);
|
||||
}
|
||||
|
||||
const NfcProtocolSupportBase nfc_protocol_support_iso14443_3b = {
|
||||
.features = NfcProtocolFeatureNone,
|
||||
|
||||
@@ -99,7 +86,7 @@ const NfcProtocolSupportBase nfc_protocol_support_iso14443_3b = {
|
||||
.scene_saved_menu =
|
||||
{
|
||||
.on_enter = nfc_protocol_support_common_on_enter_empty,
|
||||
.on_event = nfc_scene_saved_menu_on_event_iso14443_3b,
|
||||
.on_event = nfc_protocol_support_common_on_event_empty,
|
||||
},
|
||||
.scene_save_name =
|
||||
{
|
||||
@@ -111,4 +98,11 @@ const NfcProtocolSupportBase nfc_protocol_support_iso14443_3b = {
|
||||
.on_enter = nfc_protocol_support_common_on_enter_empty,
|
||||
.on_event = nfc_protocol_support_common_on_event_empty,
|
||||
},
|
||||
.scene_write =
|
||||
{
|
||||
.on_enter = nfc_protocol_support_common_on_enter_empty,
|
||||
.on_event = nfc_protocol_support_common_on_event_empty,
|
||||
},
|
||||
};
|
||||
|
||||
NFC_PROTOCOL_SUPPORT_PLUGIN(iso14443_3b, NfcProtocolIso14443_3b);
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <nfc/protocols/iso14443_3b/iso14443_3b.h>
|
||||
|
||||
#include "iso14443_3b.h"
|
||||
|
||||
bool nfc_scene_saved_menu_on_event_iso14443_3b_common(NfcApp* instance, SceneManagerEvent event);
|
||||
@@ -70,21 +70,22 @@ NfcCommand nfc_scene_emulate_listener_callback_iso14443_4a(NfcGenericEvent event
|
||||
furi_assert(event.protocol == NfcProtocolIso14443_4a);
|
||||
furi_assert(event.event_data);
|
||||
|
||||
NfcApp* nfc = context;
|
||||
NfcApp* instance = context;
|
||||
Iso14443_4aListenerEvent* iso14443_4a_event = event.event_data;
|
||||
|
||||
if(iso14443_4a_event->type == Iso14443_4aListenerEventTypeReceivedData) {
|
||||
if(furi_string_size(nfc->text_box_store) < NFC_LOG_SIZE_MAX) {
|
||||
furi_string_cat_printf(nfc->text_box_store, "R:");
|
||||
if(furi_string_size(instance->text_box_store) < NFC_LOG_SIZE_MAX) {
|
||||
furi_string_cat_printf(instance->text_box_store, "R:");
|
||||
for(size_t i = 0; i < bit_buffer_get_size_bytes(iso14443_4a_event->data->buffer);
|
||||
i++) {
|
||||
furi_string_cat_printf(
|
||||
nfc->text_box_store,
|
||||
instance->text_box_store,
|
||||
" %02X",
|
||||
bit_buffer_get_byte(iso14443_4a_event->data->buffer, i));
|
||||
}
|
||||
furi_string_push_back(nfc->text_box_store, '\n');
|
||||
view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventListenerUpdate);
|
||||
furi_string_push_back(instance->text_box_store, '\n');
|
||||
view_dispatcher_send_custom_event(
|
||||
instance->view_dispatcher, NfcCustomEventListenerUpdate);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -100,15 +101,6 @@ static void nfc_scene_emulate_on_enter_iso14443_4a(NfcApp* instance) {
|
||||
instance->listener, nfc_scene_emulate_listener_callback_iso14443_4a, instance);
|
||||
}
|
||||
|
||||
static bool nfc_scene_read_menu_on_event_iso14443_4a(NfcApp* instance, SceneManagerEvent event) {
|
||||
if(event.type == SceneManagerEventTypeCustom && event.event == SubmenuIndexCommonEmulate) {
|
||||
scene_manager_next_scene(instance->scene_manager, NfcSceneEmulate);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
const NfcProtocolSupportBase nfc_protocol_support_iso14443_4a = {
|
||||
.features = NfcProtocolFeatureEmulateUid | NfcProtocolFeatureEditUid,
|
||||
|
||||
@@ -125,7 +117,7 @@ const NfcProtocolSupportBase nfc_protocol_support_iso14443_4a = {
|
||||
.scene_read_menu =
|
||||
{
|
||||
.on_enter = nfc_protocol_support_common_on_enter_empty,
|
||||
.on_event = nfc_scene_read_menu_on_event_iso14443_4a,
|
||||
.on_event = nfc_protocol_support_common_on_event_empty,
|
||||
},
|
||||
.scene_read_success =
|
||||
{
|
||||
@@ -147,4 +139,11 @@ const NfcProtocolSupportBase nfc_protocol_support_iso14443_4a = {
|
||||
.on_enter = nfc_scene_emulate_on_enter_iso14443_4a,
|
||||
.on_event = nfc_protocol_support_common_on_event_empty,
|
||||
},
|
||||
.scene_write =
|
||||
{
|
||||
.on_enter = nfc_protocol_support_common_on_enter_empty,
|
||||
.on_event = nfc_protocol_support_common_on_event_empty,
|
||||
},
|
||||
};
|
||||
|
||||
NFC_PROTOCOL_SUPPORT_PLUGIN(iso14443_4a, NfcProtocolIso14443_4a);
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
|
||||
#include "../nfc_protocol_support_common.h"
|
||||
#include "../nfc_protocol_support_gui_common.h"
|
||||
#include "../iso14443_3b/iso14443_3b_i.h"
|
||||
|
||||
static void nfc_scene_info_on_enter_iso14443_4b(NfcApp* instance) {
|
||||
const NfcDevice* device = instance->nfc_device;
|
||||
@@ -61,23 +60,6 @@ static void nfc_scene_read_success_on_enter_iso14443_4b(NfcApp* instance) {
|
||||
furi_string_free(temp_str);
|
||||
}
|
||||
|
||||
static void nfc_scene_saved_menu_on_enter_iso14443_4b(NfcApp* instance) {
|
||||
UNUSED(instance);
|
||||
}
|
||||
|
||||
static bool nfc_scene_read_menu_on_event_iso14443_4b(NfcApp* instance, SceneManagerEvent event) {
|
||||
if(event.type == SceneManagerEventTypeCustom && event.event == SubmenuIndexCommonEmulate) {
|
||||
scene_manager_next_scene(instance->scene_manager, NfcSceneEmulate);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool nfc_scene_saved_menu_on_event_iso14443_4b(NfcApp* instance, SceneManagerEvent event) {
|
||||
return nfc_scene_saved_menu_on_event_iso14443_3b_common(instance, event);
|
||||
}
|
||||
|
||||
const NfcProtocolSupportBase nfc_protocol_support_iso14443_4b = {
|
||||
.features = NfcProtocolFeatureNone,
|
||||
|
||||
@@ -94,7 +76,7 @@ const NfcProtocolSupportBase nfc_protocol_support_iso14443_4b = {
|
||||
.scene_read_menu =
|
||||
{
|
||||
.on_enter = nfc_protocol_support_common_on_enter_empty,
|
||||
.on_event = nfc_scene_read_menu_on_event_iso14443_4b,
|
||||
.on_event = nfc_protocol_support_common_on_event_empty,
|
||||
},
|
||||
.scene_read_success =
|
||||
{
|
||||
@@ -103,8 +85,8 @@ const NfcProtocolSupportBase nfc_protocol_support_iso14443_4b = {
|
||||
},
|
||||
.scene_saved_menu =
|
||||
{
|
||||
.on_enter = nfc_scene_saved_menu_on_enter_iso14443_4b,
|
||||
.on_event = nfc_scene_saved_menu_on_event_iso14443_4b,
|
||||
.on_enter = nfc_protocol_support_common_on_enter_empty,
|
||||
.on_event = nfc_protocol_support_common_on_event_empty,
|
||||
},
|
||||
.scene_save_name =
|
||||
{
|
||||
@@ -116,4 +98,11 @@ const NfcProtocolSupportBase nfc_protocol_support_iso14443_4b = {
|
||||
.on_enter = nfc_protocol_support_common_on_enter_empty,
|
||||
.on_event = nfc_protocol_support_common_on_event_empty,
|
||||
},
|
||||
.scene_write =
|
||||
{
|
||||
.on_enter = nfc_protocol_support_common_on_enter_empty,
|
||||
.on_event = nfc_protocol_support_common_on_event_empty,
|
||||
},
|
||||
};
|
||||
|
||||
NFC_PROTOCOL_SUPPORT_PLUGIN(iso14443_4b, NfcProtocolIso14443_4b);
|
||||
|
||||
@@ -80,20 +80,21 @@ static NfcCommand
|
||||
furi_assert(event.protocol == NfcProtocolIso15693_3);
|
||||
furi_assert(event.event_data);
|
||||
|
||||
NfcApp* nfc = context;
|
||||
NfcApp* instance = context;
|
||||
Iso15693_3ListenerEvent* iso15693_3_event = event.event_data;
|
||||
|
||||
if(iso15693_3_event->type == Iso15693_3ListenerEventTypeCustomCommand) {
|
||||
if(furi_string_size(nfc->text_box_store) < NFC_LOG_SIZE_MAX) {
|
||||
furi_string_cat_printf(nfc->text_box_store, "R:");
|
||||
if(furi_string_size(instance->text_box_store) < NFC_LOG_SIZE_MAX) {
|
||||
furi_string_cat_printf(instance->text_box_store, "R:");
|
||||
for(size_t i = 0; i < bit_buffer_get_size_bytes(iso15693_3_event->data->buffer); i++) {
|
||||
furi_string_cat_printf(
|
||||
nfc->text_box_store,
|
||||
instance->text_box_store,
|
||||
" %02X",
|
||||
bit_buffer_get_byte(iso15693_3_event->data->buffer, i));
|
||||
}
|
||||
furi_string_push_back(nfc->text_box_store, '\n');
|
||||
view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventListenerUpdate);
|
||||
furi_string_push_back(instance->text_box_store, '\n');
|
||||
view_dispatcher_send_custom_event(
|
||||
instance->view_dispatcher, NfcCustomEventListenerUpdate);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -108,15 +109,6 @@ static void nfc_scene_emulate_on_enter_iso15693_3(NfcApp* instance) {
|
||||
instance->listener, nfc_scene_emulate_listener_callback_iso15693_3, instance);
|
||||
}
|
||||
|
||||
static bool nfc_scene_saved_menu_on_event_iso15693_3(NfcApp* instance, SceneManagerEvent event) {
|
||||
if(event.type == SceneManagerEventTypeCustom && event.event == SubmenuIndexCommonEdit) {
|
||||
scene_manager_next_scene(instance->scene_manager, NfcSceneSetUid);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
const NfcProtocolSupportBase nfc_protocol_support_iso15693_3 = {
|
||||
.features = NfcProtocolFeatureEmulateFull | NfcProtocolFeatureEditUid |
|
||||
NfcProtocolFeatureMoreInfo,
|
||||
@@ -149,7 +141,7 @@ const NfcProtocolSupportBase nfc_protocol_support_iso15693_3 = {
|
||||
.scene_saved_menu =
|
||||
{
|
||||
.on_enter = nfc_protocol_support_common_on_enter_empty,
|
||||
.on_event = nfc_scene_saved_menu_on_event_iso15693_3,
|
||||
.on_event = nfc_protocol_support_common_on_event_empty,
|
||||
},
|
||||
.scene_save_name =
|
||||
{
|
||||
@@ -161,4 +153,11 @@ const NfcProtocolSupportBase nfc_protocol_support_iso15693_3 = {
|
||||
.on_enter = nfc_scene_emulate_on_enter_iso15693_3,
|
||||
.on_event = nfc_protocol_support_common_on_event_empty,
|
||||
},
|
||||
.scene_write =
|
||||
{
|
||||
.on_enter = nfc_protocol_support_common_on_enter_empty,
|
||||
.on_event = nfc_protocol_support_common_on_event_empty,
|
||||
},
|
||||
};
|
||||
|
||||
NFC_PROTOCOL_SUPPORT_PLUGIN(iso15693_3, NfcProtocolIso15693_3);
|
||||
|
||||
@@ -12,10 +12,9 @@
|
||||
|
||||
enum {
|
||||
SubmenuIndexDetectReader = SubmenuIndexCommonMax,
|
||||
SubmenuIndexWrite,
|
||||
SubmenuIndexUpdate,
|
||||
SubmenuIndexDictAttack,
|
||||
SubmenuIndexCrackNonces,
|
||||
SubmenuIndexUpdate,
|
||||
};
|
||||
|
||||
static void nfc_scene_info_on_enter_mf_classic(NfcApp* instance) {
|
||||
@@ -115,6 +114,9 @@ static void nfc_scene_read_menu_on_enter_mf_classic(NfcApp* instance) {
|
||||
Submenu* submenu = instance->submenu;
|
||||
const MfClassicData* data = nfc_device_get_data(instance->nfc_device, NfcProtocolMfClassic);
|
||||
|
||||
// Doesn't make sense to show "Write to Initial Card" right after reading
|
||||
submenu_remove_item(submenu, SubmenuIndexCommonWrite);
|
||||
|
||||
if(!mf_classic_is_card_read(data)) {
|
||||
submenu_add_item(
|
||||
submenu,
|
||||
@@ -160,6 +162,8 @@ static void nfc_scene_saved_menu_on_enter_mf_classic(NfcApp* instance) {
|
||||
Submenu* submenu = instance->submenu;
|
||||
const MfClassicData* data = nfc_device_get_data(instance->nfc_device, NfcProtocolMfClassic);
|
||||
|
||||
submenu_change_item_label(submenu, SubmenuIndexCommonWrite, "Write to Initial Card");
|
||||
|
||||
if(!mf_classic_is_card_read(data)) {
|
||||
submenu_add_item(
|
||||
submenu,
|
||||
@@ -175,12 +179,6 @@ static void nfc_scene_saved_menu_on_enter_mf_classic(NfcApp* instance) {
|
||||
nfc_protocol_support_common_submenu_callback,
|
||||
instance);
|
||||
}
|
||||
submenu_add_item(
|
||||
submenu,
|
||||
"Write to Initial Card",
|
||||
SubmenuIndexWrite,
|
||||
nfc_protocol_support_common_submenu_callback,
|
||||
instance);
|
||||
|
||||
submenu_add_item(
|
||||
submenu,
|
||||
@@ -215,9 +213,6 @@ static bool nfc_scene_read_menu_on_event_mf_classic(NfcApp* instance, SceneManag
|
||||
scene_manager_next_scene(instance->scene_manager, NfcSceneMfClassicDictAttack);
|
||||
}
|
||||
consumed = true;
|
||||
} else if(event.event == SubmenuIndexCommonEdit) {
|
||||
scene_manager_next_scene(instance->scene_manager, NfcSceneSetUid);
|
||||
consumed = true;
|
||||
} else if(event.event == SubmenuIndexCrackNonces) {
|
||||
scene_manager_set_scene_state(
|
||||
instance->scene_manager, NfcSceneSaveConfirm, NfcSceneSaveConfirmStateCrackNonces);
|
||||
@@ -236,18 +231,15 @@ static bool nfc_scene_saved_menu_on_event_mf_classic(NfcApp* instance, SceneMana
|
||||
if(event.event == SubmenuIndexDetectReader) {
|
||||
scene_manager_next_scene(instance->scene_manager, NfcSceneMfClassicDetectReader);
|
||||
consumed = true;
|
||||
} else if(event.event == SubmenuIndexWrite) {
|
||||
scene_manager_next_scene(instance->scene_manager, NfcSceneMfClassicWriteInitial);
|
||||
consumed = true;
|
||||
} else if(event.event == SubmenuIndexUpdate) {
|
||||
scene_manager_next_scene(instance->scene_manager, NfcSceneMfClassicUpdateInitial);
|
||||
consumed = true;
|
||||
} else if(event.event == SubmenuIndexDictAttack) {
|
||||
if(!scene_manager_search_and_switch_to_previous_scene(
|
||||
instance->scene_manager, NfcSceneMfClassicDictAttack)) {
|
||||
scene_manager_next_scene(instance->scene_manager, NfcSceneMfClassicDictAttack);
|
||||
}
|
||||
consumed = true;
|
||||
} else if(event.event == SubmenuIndexUpdate) {
|
||||
scene_manager_next_scene(instance->scene_manager, NfcSceneMfClassicUpdateInitial);
|
||||
consumed = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -267,8 +259,71 @@ static bool nfc_scene_save_name_on_event_mf_classic(NfcApp* instance, SceneManag
|
||||
return consumed;
|
||||
}
|
||||
|
||||
static NfcCommand
|
||||
nfc_scene_write_poller_callback_mf_classic(NfcGenericEvent event, void* context) {
|
||||
furi_assert(event.protocol == NfcProtocolMfClassic);
|
||||
|
||||
NfcApp* instance = context;
|
||||
MfClassicPollerEvent* mfc_event = event.event_data;
|
||||
NfcCommand command = NfcCommandContinue;
|
||||
const MfClassicData* write_data =
|
||||
nfc_device_get_data(instance->nfc_device, NfcProtocolMfClassic);
|
||||
|
||||
if(mfc_event->type == MfClassicPollerEventTypeCardDetected) {
|
||||
furi_string_reset(instance->text_box_store);
|
||||
view_dispatcher_send_custom_event(instance->view_dispatcher, NfcCustomEventCardDetected);
|
||||
} else if(mfc_event->type == MfClassicPollerEventTypeCardLost) {
|
||||
furi_string_set(instance->text_box_store, "Use the source\ncard only");
|
||||
view_dispatcher_send_custom_event(instance->view_dispatcher, NfcCustomEventCardLost);
|
||||
} else if(mfc_event->type == MfClassicPollerEventTypeRequestMode) {
|
||||
const MfClassicData* tag_data = nfc_poller_get_data(instance->poller);
|
||||
if(iso14443_3a_is_equal(tag_data->iso14443_3a_data, write_data->iso14443_3a_data)) {
|
||||
mfc_event->data->poller_mode.mode = MfClassicPollerModeWrite;
|
||||
} else {
|
||||
furi_string_set(
|
||||
instance->text_box_store, "Use source card!\nTo write blanks\nuse NFC Magic app");
|
||||
view_dispatcher_send_custom_event(instance->view_dispatcher, NfcCustomEventWrongCard);
|
||||
command = NfcCommandStop;
|
||||
}
|
||||
} else if(mfc_event->type == MfClassicPollerEventTypeRequestSectorTrailer) {
|
||||
uint8_t sector = mfc_event->data->sec_tr_data.sector_num;
|
||||
uint8_t sec_tr = mf_classic_get_sector_trailer_num_by_sector(sector);
|
||||
if(mf_classic_is_block_read(write_data, sec_tr)) {
|
||||
mfc_event->data->sec_tr_data.sector_trailer = write_data->block[sec_tr];
|
||||
mfc_event->data->sec_tr_data.sector_trailer_provided = true;
|
||||
} else {
|
||||
mfc_event->data->sec_tr_data.sector_trailer_provided = false;
|
||||
}
|
||||
} else if(mfc_event->type == MfClassicPollerEventTypeRequestWriteBlock) {
|
||||
uint8_t block_num = mfc_event->data->write_block_data.block_num;
|
||||
if(mf_classic_is_block_read(write_data, block_num)) {
|
||||
mfc_event->data->write_block_data.write_block = write_data->block[block_num];
|
||||
mfc_event->data->write_block_data.write_block_provided = true;
|
||||
} else {
|
||||
mfc_event->data->write_block_data.write_block_provided = false;
|
||||
}
|
||||
} else if(mfc_event->type == MfClassicPollerEventTypeSuccess) {
|
||||
furi_string_reset(instance->text_box_store);
|
||||
view_dispatcher_send_custom_event(instance->view_dispatcher, NfcCustomEventPollerSuccess);
|
||||
command = NfcCommandStop;
|
||||
} else if(mfc_event->type == MfClassicPollerEventTypeFail) {
|
||||
furi_string_set(instance->text_box_store, "Not all sectors\nwere written\ncorrectly");
|
||||
view_dispatcher_send_custom_event(instance->view_dispatcher, NfcCustomEventPollerFailure);
|
||||
command = NfcCommandStop;
|
||||
}
|
||||
|
||||
return command;
|
||||
}
|
||||
|
||||
static void nfc_scene_write_on_enter_mf_classic(NfcApp* instance) {
|
||||
instance->poller = nfc_poller_alloc(instance->nfc, NfcProtocolMfClassic);
|
||||
nfc_poller_start(instance->poller, nfc_scene_write_poller_callback_mf_classic, instance);
|
||||
furi_string_set(instance->text_box_store, "Use the source\ncard only");
|
||||
}
|
||||
|
||||
const NfcProtocolSupportBase nfc_protocol_support_mf_classic = {
|
||||
.features = NfcProtocolFeatureEmulateFull | NfcProtocolFeatureMoreInfo,
|
||||
.features = NfcProtocolFeatureEmulateFull | NfcProtocolFeatureMoreInfo |
|
||||
NfcProtocolFeatureWrite,
|
||||
|
||||
.scene_info =
|
||||
{
|
||||
@@ -310,4 +365,11 @@ const NfcProtocolSupportBase nfc_protocol_support_mf_classic = {
|
||||
.on_enter = nfc_scene_emulate_on_enter_mf_classic,
|
||||
.on_event = nfc_protocol_support_common_on_event_empty,
|
||||
},
|
||||
.scene_write =
|
||||
{
|
||||
.on_enter = nfc_scene_write_on_enter_mf_classic,
|
||||
.on_event = nfc_protocol_support_common_on_event_empty,
|
||||
},
|
||||
};
|
||||
|
||||
NFC_PROTOCOL_SUPPORT_PLUGIN(mf_classic, NfcProtocolMfClassic);
|
||||
|
||||
@@ -124,4 +124,11 @@ const NfcProtocolSupportBase nfc_protocol_support_mf_desfire = {
|
||||
.on_enter = nfc_scene_emulate_on_enter_mf_desfire,
|
||||
.on_event = nfc_protocol_support_common_on_event_empty,
|
||||
},
|
||||
.scene_write =
|
||||
{
|
||||
.on_enter = nfc_protocol_support_common_on_enter_empty,
|
||||
.on_event = nfc_protocol_support_common_on_event_empty,
|
||||
},
|
||||
};
|
||||
|
||||
NFC_PROTOCOL_SUPPORT_PLUGIN(mf_desfire, NfcProtocolMfDesfire);
|
||||
|
||||
@@ -25,6 +25,20 @@ static void nfc_scene_info_on_enter_mf_plus(NfcApp* instance) {
|
||||
|
||||
furi_string_free(temp_str);
|
||||
}
|
||||
|
||||
static void nfc_scene_more_info_on_enter_mf_plus(NfcApp* instance) {
|
||||
const NfcDevice* device = instance->nfc_device;
|
||||
const MfPlusData* data = nfc_device_get_data(device, NfcProtocolMfPlus);
|
||||
|
||||
furi_string_reset(instance->text_box_store);
|
||||
nfc_render_mf_plus_data(data, instance->text_box_store);
|
||||
|
||||
text_box_set_font(instance->text_box, TextBoxFontHex);
|
||||
text_box_set_text(instance->text_box, furi_string_get_cstr(instance->text_box_store));
|
||||
|
||||
view_dispatcher_switch_to_view(instance->view_dispatcher, NfcViewTextBox);
|
||||
}
|
||||
|
||||
static NfcCommand nfc_scene_read_poller_callback_mf_plus(NfcGenericEvent event, void* context) {
|
||||
furi_assert(context);
|
||||
furi_assert(event.protocol == NfcProtocolMfPlus);
|
||||
@@ -78,7 +92,7 @@ static void nfc_scene_emulate_on_enter_mf_plus(NfcApp* instance) {
|
||||
}
|
||||
|
||||
const NfcProtocolSupportBase nfc_protocol_support_mf_plus = {
|
||||
.features = NfcProtocolFeatureEmulateUid,
|
||||
.features = NfcProtocolFeatureEmulateUid | NfcProtocolFeatureMoreInfo,
|
||||
|
||||
.scene_info =
|
||||
{
|
||||
@@ -87,7 +101,7 @@ const NfcProtocolSupportBase nfc_protocol_support_mf_plus = {
|
||||
},
|
||||
.scene_more_info =
|
||||
{
|
||||
.on_enter = nfc_protocol_support_common_on_enter_empty,
|
||||
.on_enter = nfc_scene_more_info_on_enter_mf_plus,
|
||||
.on_event = nfc_protocol_support_common_on_event_empty,
|
||||
},
|
||||
.scene_read =
|
||||
@@ -120,4 +134,11 @@ const NfcProtocolSupportBase nfc_protocol_support_mf_plus = {
|
||||
.on_enter = nfc_scene_emulate_on_enter_mf_plus,
|
||||
.on_event = nfc_protocol_support_common_on_event_empty,
|
||||
},
|
||||
.scene_write =
|
||||
{
|
||||
.on_enter = nfc_protocol_support_common_on_enter_empty,
|
||||
.on_event = nfc_protocol_support_common_on_event_empty,
|
||||
},
|
||||
};
|
||||
|
||||
NFC_PROTOCOL_SUPPORT_PLUGIN(mf_plus, NfcProtocolMfPlus);
|
||||
|
||||
@@ -15,7 +15,21 @@ void nfc_render_mf_plus_info(
|
||||
}
|
||||
|
||||
void nfc_render_mf_plus_data(const MfPlusData* data, FuriString* str) {
|
||||
nfc_render_mf_plus_version(&data->version, str);
|
||||
MfPlusVersion empty_version = {0};
|
||||
if(memcmp(&data->version, &empty_version, sizeof(MfPlusVersion)) == 0) {
|
||||
const char* device_name = mf_plus_get_device_name(data, NfcDeviceNameTypeFull);
|
||||
if(data->type == MfPlusTypeUnknown || data->size == MfPlusSizeUnknown ||
|
||||
data->security_level == MfPlusSecurityLevelUnknown) {
|
||||
furi_string_cat_printf(str, "This %s", device_name);
|
||||
furi_string_replace(str, " Unknown", "");
|
||||
} else {
|
||||
furi_string_cat(str, device_name);
|
||||
}
|
||||
furi_string_replace(str, "Mifare", "MIFARE");
|
||||
furi_string_cat(str, " does not support the GetVersion command, extra info unavailable\n");
|
||||
} else {
|
||||
nfc_render_mf_plus_version(&data->version, str);
|
||||
}
|
||||
}
|
||||
|
||||
void nfc_render_mf_plus_version(const MfPlusVersion* data, FuriString* str) {
|
||||
|
||||
@@ -14,7 +14,6 @@ enum {
|
||||
SubmenuIndexUnlock = SubmenuIndexCommonMax,
|
||||
SubmenuIndexUnlockByReader,
|
||||
SubmenuIndexUnlockByPassword,
|
||||
SubmenuIndexWrite,
|
||||
};
|
||||
|
||||
enum {
|
||||
@@ -182,24 +181,22 @@ static void nfc_scene_read_and_saved_menu_on_enter_mf_ultralight(NfcApp* instanc
|
||||
|
||||
const MfUltralightData* data =
|
||||
nfc_device_get_data(instance->nfc_device, NfcProtocolMfUltralight);
|
||||
bool is_locked = !mf_ultralight_is_all_data_read(data);
|
||||
|
||||
if(!mf_ultralight_is_all_data_read(data)) {
|
||||
if(is_locked ||
|
||||
(data->type != MfUltralightTypeNTAG213 && data->type != MfUltralightTypeNTAG215 &&
|
||||
data->type != MfUltralightTypeNTAG216 && data->type != MfUltralightTypeUL11 &&
|
||||
data->type != MfUltralightTypeUL21 && data->type != MfUltralightTypeOrigin)) {
|
||||
submenu_remove_item(submenu, SubmenuIndexCommonWrite);
|
||||
}
|
||||
|
||||
if(is_locked) {
|
||||
submenu_add_item(
|
||||
submenu,
|
||||
"Unlock",
|
||||
SubmenuIndexUnlock,
|
||||
nfc_protocol_support_common_submenu_callback,
|
||||
instance);
|
||||
} else if(
|
||||
data->type == MfUltralightTypeNTAG213 || data->type == MfUltralightTypeNTAG215 ||
|
||||
data->type == MfUltralightTypeNTAG216 || data->type == MfUltralightTypeUL11 ||
|
||||
data->type == MfUltralightTypeUL21 || data->type == MfUltralightTypeOrigin) {
|
||||
submenu_add_item(
|
||||
submenu,
|
||||
"Write",
|
||||
SubmenuIndexWrite,
|
||||
nfc_protocol_support_common_submenu_callback,
|
||||
instance);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -252,19 +249,57 @@ static bool nfc_scene_read_and_saved_menu_on_event_mf_ultralight(
|
||||
NfcSceneMfUltralightUnlockMenu;
|
||||
scene_manager_next_scene(instance->scene_manager, next_scene);
|
||||
consumed = true;
|
||||
} else if(event.event == SubmenuIndexWrite) {
|
||||
scene_manager_next_scene(instance->scene_manager, NfcSceneMfUltralightWrite);
|
||||
consumed = true;
|
||||
} else if(event.event == SubmenuIndexCommonEdit) {
|
||||
scene_manager_next_scene(instance->scene_manager, NfcSceneSetUid);
|
||||
consumed = true;
|
||||
}
|
||||
}
|
||||
return consumed;
|
||||
}
|
||||
|
||||
static NfcCommand
|
||||
nfc_scene_write_poller_callback_mf_ultralight(NfcGenericEvent event, void* context) {
|
||||
furi_assert(event.protocol == NfcProtocolMfUltralight);
|
||||
|
||||
NfcApp* instance = context;
|
||||
MfUltralightPollerEvent* mf_ultralight_event = event.event_data;
|
||||
NfcCommand command = NfcCommandContinue;
|
||||
|
||||
if(mf_ultralight_event->type == MfUltralightPollerEventTypeRequestMode) {
|
||||
mf_ultralight_event->data->poller_mode = MfUltralightPollerModeWrite;
|
||||
furi_string_reset(instance->text_box_store);
|
||||
view_dispatcher_send_custom_event(instance->view_dispatcher, NfcCustomEventCardDetected);
|
||||
} else if(mf_ultralight_event->type == MfUltralightPollerEventTypeAuthRequest) {
|
||||
mf_ultralight_event->data->auth_context.skip_auth = true;
|
||||
} else if(mf_ultralight_event->type == MfUltralightPollerEventTypeRequestWriteData) {
|
||||
mf_ultralight_event->data->write_data =
|
||||
nfc_device_get_data(instance->nfc_device, NfcProtocolMfUltralight);
|
||||
} else if(mf_ultralight_event->type == MfUltralightPollerEventTypeCardMismatch) {
|
||||
furi_string_set(instance->text_box_store, "Card of the same\ntype should be\n presented");
|
||||
view_dispatcher_send_custom_event(instance->view_dispatcher, NfcCustomEventWrongCard);
|
||||
command = NfcCommandStop;
|
||||
} else if(mf_ultralight_event->type == MfUltralightPollerEventTypeCardLocked) {
|
||||
furi_string_set(
|
||||
instance->text_box_store, "Card protected by\npassword, AUTH0\nor lock bits");
|
||||
view_dispatcher_send_custom_event(instance->view_dispatcher, NfcCustomEventPollerFailure);
|
||||
command = NfcCommandStop;
|
||||
} else if(mf_ultralight_event->type == MfUltralightPollerEventTypeWriteFail) {
|
||||
command = NfcCommandStop;
|
||||
} else if(mf_ultralight_event->type == MfUltralightPollerEventTypeWriteSuccess) {
|
||||
furi_string_reset(instance->text_box_store);
|
||||
view_dispatcher_send_custom_event(instance->view_dispatcher, NfcCustomEventPollerSuccess);
|
||||
command = NfcCommandStop;
|
||||
}
|
||||
|
||||
return command;
|
||||
}
|
||||
|
||||
static void nfc_scene_write_on_enter_mf_ultralight(NfcApp* instance) {
|
||||
instance->poller = nfc_poller_alloc(instance->nfc, NfcProtocolMfUltralight);
|
||||
nfc_poller_start(instance->poller, nfc_scene_write_poller_callback_mf_ultralight, instance);
|
||||
furi_string_set(instance->text_box_store, "Apply the initial\ncard only");
|
||||
}
|
||||
|
||||
const NfcProtocolSupportBase nfc_protocol_support_mf_ultralight = {
|
||||
.features = NfcProtocolFeatureEmulateFull | NfcProtocolFeatureMoreInfo,
|
||||
.features = NfcProtocolFeatureEmulateFull | NfcProtocolFeatureMoreInfo |
|
||||
NfcProtocolFeatureWrite,
|
||||
|
||||
.scene_info =
|
||||
{
|
||||
@@ -306,4 +341,11 @@ const NfcProtocolSupportBase nfc_protocol_support_mf_ultralight = {
|
||||
.on_enter = nfc_scene_emulate_on_enter_mf_ultralight,
|
||||
.on_event = nfc_protocol_support_common_on_event_empty,
|
||||
},
|
||||
.scene_write =
|
||||
{
|
||||
.on_enter = nfc_scene_write_on_enter_mf_ultralight,
|
||||
.on_event = nfc_protocol_support_common_on_event_empty,
|
||||
},
|
||||
};
|
||||
|
||||
NFC_PROTOCOL_SUPPORT_PLUGIN(mf_ultralight, NfcProtocolMfUltralight);
|
||||
|
||||
@@ -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,147 @@ 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",
|
||||
[NfcProtocolNtag4xx] = "ntag4xx",
|
||||
[NfcProtocolType4Tag] = "type_4_tag",
|
||||
[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 +219,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 +275,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 +283,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 +309,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 +338,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 +352,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 +395,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 +403,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 +412,16 @@ static void nfc_protocol_support_scene_read_menu_on_enter(NfcApp* instance) {
|
||||
instance);
|
||||
}
|
||||
|
||||
nfc_protocol_support[protocol]->scene_read_menu.on_enter(instance);
|
||||
if(nfc_protocol_support_has_feature(protocol, instance, NfcProtocolFeatureWrite)) {
|
||||
submenu_add_item(
|
||||
submenu,
|
||||
"Write",
|
||||
SubmenuIndexCommonWrite,
|
||||
nfc_protocol_support_common_submenu_callback,
|
||||
instance);
|
||||
}
|
||||
|
||||
nfc_protocol_support_get(protocol, instance)->scene_read_menu.on_enter(instance);
|
||||
|
||||
submenu_add_item(
|
||||
submenu,
|
||||
@@ -291,9 +454,17 @@ static bool
|
||||
dolphin_deed(DolphinDeedNfcEmulate);
|
||||
scene_manager_next_scene(instance->scene_manager, NfcSceneEmulate);
|
||||
consumed = true;
|
||||
} else if(event.event == SubmenuIndexCommonWrite) {
|
||||
dolphin_deed(DolphinDeedNfcEmulate);
|
||||
scene_manager_next_scene(instance->scene_manager, NfcSceneWrite);
|
||||
consumed = true;
|
||||
} else if(event.event == SubmenuIndexCommonEdit) {
|
||||
scene_manager_next_scene(instance->scene_manager, NfcSceneSetUid);
|
||||
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) {
|
||||
@@ -312,13 +483,17 @@ static void nfc_protocol_support_scene_read_saved_menu_on_exit(NfcApp* instance)
|
||||
static void nfc_protocol_support_scene_read_success_on_enter(NfcApp* instance) {
|
||||
Widget* widget = instance->widget;
|
||||
|
||||
popup_set_header(instance->popup, "Parsing", 85, 27, AlignCenter, AlignTop);
|
||||
popup_set_icon(instance->popup, 12, 23, &A_Loading_24);
|
||||
view_dispatcher_switch_to_view(instance->view_dispatcher, NfcViewPopup);
|
||||
|
||||
FuriString* temp_str = furi_string_alloc();
|
||||
if(nfc_supported_cards_parse(instance->nfc_supported_cards, instance->nfc_device, temp_str)) {
|
||||
widget_add_text_scroll_element(
|
||||
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 +541,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 +549,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 +558,16 @@ 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, NfcProtocolFeatureWrite)) {
|
||||
submenu_add_item(
|
||||
submenu,
|
||||
"Write",
|
||||
SubmenuIndexCommonWrite,
|
||||
nfc_protocol_support_common_submenu_callback,
|
||||
instance);
|
||||
}
|
||||
|
||||
if(nfc_protocol_support_has_feature(protocol, instance, NfcProtocolFeatureEditUid)) {
|
||||
submenu_add_item(
|
||||
submenu,
|
||||
"Edit UID",
|
||||
@@ -393,7 +577,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)) {
|
||||
@@ -456,12 +640,19 @@ static bool
|
||||
dolphin_deed(is_added ? DolphinDeedNfcAddEmulate : DolphinDeedNfcEmulate);
|
||||
scene_manager_next_scene(instance->scene_manager, NfcSceneEmulate);
|
||||
consumed = true;
|
||||
} else if(event.event == SubmenuIndexCommonWrite) {
|
||||
const bool is_added =
|
||||
scene_manager_has_previous_scene(instance->scene_manager, NfcSceneSetType);
|
||||
dolphin_deed(is_added ? DolphinDeedNfcAddEmulate : DolphinDeedNfcEmulate);
|
||||
scene_manager_next_scene(instance->scene_manager, NfcSceneWrite);
|
||||
consumed = true;
|
||||
} else if(event.event == SubmenuIndexCommonEdit) {
|
||||
scene_manager_next_scene(instance->scene_manager, NfcSceneSetUid);
|
||||
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) {
|
||||
@@ -480,8 +671,18 @@ static void nfc_protocol_support_scene_save_name_on_enter(NfcApp* instance) {
|
||||
bool name_is_empty = furi_string_empty(instance->file_name);
|
||||
if(name_is_empty) {
|
||||
furi_string_set(instance->file_path, NFC_APP_FOLDER);
|
||||
name_generator_make_auto_basic(
|
||||
instance->text_store, NFC_TEXT_STORE_SIZE, NFC_APP_FILENAME_PREFIX);
|
||||
FuriString* prefix = furi_string_alloc();
|
||||
furi_string_set(prefix, nfc_device_get_name(instance->nfc_device, NfcDeviceNameTypeFull));
|
||||
furi_string_replace(prefix, "Mifare", "MF");
|
||||
furi_string_replace(prefix, " Classic", "C"); // MFC
|
||||
furi_string_replace(prefix, "Desfire", "Des"); // MF Des
|
||||
furi_string_replace(prefix, "Ultralight", "UL"); // MF UL
|
||||
furi_string_replace(prefix, " Plus", "+"); // NTAG I2C+
|
||||
furi_string_replace(prefix, " (Unknown)", "");
|
||||
furi_string_replace_all(prefix, " ", "_");
|
||||
name_generator_make_auto(
|
||||
instance->text_store, NFC_TEXT_STORE_SIZE, furi_string_get_cstr(prefix));
|
||||
furi_string_free(prefix);
|
||||
furi_string_set(folder_path, NFC_APP_FOLDER);
|
||||
} else {
|
||||
nfc_text_store_set(instance, "%s", furi_string_get_cstr(instance->file_name));
|
||||
@@ -527,8 +728,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);
|
||||
@@ -570,9 +771,9 @@ static void nfc_protocol_support_scene_emulate_on_enter(NfcApp* instance) {
|
||||
FuriString* temp_str = furi_string_alloc();
|
||||
const NfcProtocol protocol = nfc_device_get_protocol(instance->nfc_device);
|
||||
|
||||
widget_add_icon_element(widget, 0, 3, &I_NFC_dolphin_emulation_51x64);
|
||||
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");
|
||||
|
||||
@@ -613,7 +814,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);
|
||||
@@ -692,6 +893,191 @@ static void nfc_protocol_support_scene_emulate_on_exit(NfcApp* instance) {
|
||||
nfc_blink_stop(instance);
|
||||
}
|
||||
|
||||
// SceneWrite
|
||||
/**
|
||||
* @brief Current view displayed on the write scene.
|
||||
*
|
||||
* The emulation scene has five states, some protocols may not use all states.
|
||||
* Protocol handles poller events, when scene state needs to change it should
|
||||
* fill text_box_store with a short caption (when applicable) before sending
|
||||
* the relevant view dispatcher event.
|
||||
*/
|
||||
enum {
|
||||
NfcSceneWriteStateSearching, /**< Ask user to touch the card. Event: on_enter, CardLost. Needs caption. */
|
||||
NfcSceneWriteStateWriting, /**< Ask not to move while writing. Event: CardDetected. No caption. */
|
||||
NfcSceneWriteStateSuccess, /**< Card written successfully. Event: PollerSuccess. No caption. */
|
||||
NfcSceneWriteStateFailure, /**< An error is displayed. Event: PollerFailure. Needs caption. */
|
||||
NfcSceneWriteStateWrongCard, /**< Wrong card was presented. Event: WrongCard. Needs caption. */
|
||||
};
|
||||
|
||||
static void nfc_protocol_support_scene_write_popup_callback(void* context) {
|
||||
NfcApp* instance = context;
|
||||
view_dispatcher_send_custom_event(instance->view_dispatcher, NfcCustomEventViewExit);
|
||||
}
|
||||
|
||||
void nfc_protocol_support_scene_write_widget_callback(
|
||||
GuiButtonType result,
|
||||
InputType type,
|
||||
void* context) {
|
||||
NfcApp* instance = context;
|
||||
if(type == InputTypeShort && result == GuiButtonTypeLeft) {
|
||||
view_dispatcher_send_custom_event(instance->view_dispatcher, NfcCustomEventRetry);
|
||||
}
|
||||
}
|
||||
|
||||
static void nfc_protocol_support_scene_write_setup_view(NfcApp* instance) {
|
||||
Popup* popup = instance->popup;
|
||||
Widget* widget = instance->widget;
|
||||
popup_reset(popup);
|
||||
widget_reset(widget);
|
||||
uint32_t state = scene_manager_get_scene_state(instance->scene_manager, NfcSceneWrite);
|
||||
NfcView view = NfcViewPopup;
|
||||
|
||||
if(state == NfcSceneWriteStateSearching) {
|
||||
popup_set_header(popup, "Writing", 95, 20, AlignCenter, AlignCenter);
|
||||
popup_set_text(
|
||||
popup,
|
||||
furi_string_get_cstr(instance->text_box_store),
|
||||
95,
|
||||
38,
|
||||
AlignCenter,
|
||||
AlignCenter);
|
||||
popup_set_icon(popup, 0, 8, &I_NFC_manual_60x50);
|
||||
} else if(state == NfcSceneWriteStateWriting) {
|
||||
popup_set_header(popup, "Writing\nDon't move...", 52, 32, AlignLeft, AlignCenter);
|
||||
popup_set_icon(popup, 12, 23, &A_Loading_24);
|
||||
} else if(state == NfcSceneWriteStateSuccess) {
|
||||
popup_set_header(popup, "Successfully\nwritten!", 126, 2, AlignRight, AlignTop);
|
||||
popup_set_icon(popup, 0, 9, &I_DolphinSuccess_91x55);
|
||||
popup_set_timeout(popup, 1500);
|
||||
popup_set_context(popup, instance);
|
||||
popup_set_callback(popup, nfc_protocol_support_scene_write_popup_callback);
|
||||
popup_enable_timeout(popup);
|
||||
} else if(state == NfcSceneWriteStateFailure) {
|
||||
view = NfcViewWidget;
|
||||
widget_add_string_element(
|
||||
widget, 7, 4, AlignLeft, AlignTop, FontPrimary, "Writing gone wrong!");
|
||||
widget_add_string_multiline_element(
|
||||
widget,
|
||||
7,
|
||||
17,
|
||||
AlignLeft,
|
||||
AlignTop,
|
||||
FontSecondary,
|
||||
furi_string_get_cstr(instance->text_box_store));
|
||||
widget_add_icon_element(widget, 83, 22, &I_WarningDolphinFlip_45x42);
|
||||
widget_add_button_element(
|
||||
widget,
|
||||
GuiButtonTypeLeft,
|
||||
"Retry",
|
||||
nfc_protocol_support_scene_write_widget_callback,
|
||||
instance);
|
||||
} else if(state == NfcSceneWriteStateWrongCard) {
|
||||
view = NfcViewWidget;
|
||||
widget_add_string_element(widget, 3, 4, AlignLeft, AlignTop, FontPrimary, "Wrong card!");
|
||||
widget_add_string_multiline_element(
|
||||
widget,
|
||||
4,
|
||||
17,
|
||||
AlignLeft,
|
||||
AlignTop,
|
||||
FontSecondary,
|
||||
furi_string_get_cstr(instance->text_box_store));
|
||||
widget_add_icon_element(widget, 83, 22, &I_WarningDolphinFlip_45x42);
|
||||
widget_add_button_element(
|
||||
widget,
|
||||
GuiButtonTypeLeft,
|
||||
"Retry",
|
||||
nfc_protocol_support_scene_write_widget_callback,
|
||||
instance);
|
||||
}
|
||||
|
||||
view_dispatcher_switch_to_view(instance->view_dispatcher, view);
|
||||
}
|
||||
|
||||
static void nfc_protocol_support_scene_write_on_enter(NfcApp* instance) {
|
||||
scene_manager_set_scene_state(
|
||||
instance->scene_manager, NfcSceneWrite, NfcSceneWriteStateSearching);
|
||||
furi_string_reset(instance->text_box_store);
|
||||
|
||||
const NfcProtocol protocol = nfc_device_get_protocol(instance->nfc_device);
|
||||
|
||||
// instance->poller is allocated in the respective on_enter() handler
|
||||
nfc_protocol_support_get(protocol, instance)->scene_write.on_enter(instance);
|
||||
|
||||
nfc_protocol_support_scene_write_setup_view(instance);
|
||||
nfc_blink_emulate_start(instance);
|
||||
}
|
||||
|
||||
static bool nfc_protocol_support_scene_write_on_event(NfcApp* instance, SceneManagerEvent event) {
|
||||
bool consumed = false;
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
uint32_t new_state = -1;
|
||||
bool stop_poller = false;
|
||||
|
||||
if(event.event == NfcCustomEventCardDetected) {
|
||||
new_state = NfcSceneWriteStateWriting;
|
||||
consumed = true;
|
||||
} else if(event.event == NfcCustomEventCardLost) {
|
||||
new_state = NfcSceneWriteStateSearching;
|
||||
consumed = true;
|
||||
} else if(event.event == NfcCustomEventPollerSuccess) {
|
||||
dolphin_deed(DolphinDeedNfcSave);
|
||||
notification_message(instance->notifications, &sequence_success);
|
||||
new_state = NfcSceneWriteStateSuccess;
|
||||
stop_poller = true;
|
||||
consumed = true;
|
||||
} else if(event.event == NfcCustomEventPollerFailure) {
|
||||
notification_message(instance->notifications, &sequence_error);
|
||||
new_state = NfcSceneWriteStateFailure;
|
||||
stop_poller = true;
|
||||
consumed = true;
|
||||
} else if(event.event == NfcCustomEventWrongCard) {
|
||||
notification_message(instance->notifications, &sequence_error);
|
||||
new_state = NfcSceneWriteStateWrongCard;
|
||||
stop_poller = true;
|
||||
consumed = true;
|
||||
} else if(event.event == NfcCustomEventViewExit) {
|
||||
scene_manager_previous_scene(instance->scene_manager);
|
||||
consumed = true;
|
||||
} else if(event.event == NfcCustomEventRetry) {
|
||||
nfc_protocol_support_scenes[NfcProtocolSupportSceneWrite].on_exit(instance);
|
||||
nfc_protocol_support_scenes[NfcProtocolSupportSceneWrite].on_enter(instance);
|
||||
consumed = true;
|
||||
}
|
||||
|
||||
if(stop_poller) {
|
||||
if(instance->poller) {
|
||||
nfc_poller_stop(instance->poller);
|
||||
nfc_poller_free(instance->poller);
|
||||
instance->poller = NULL;
|
||||
}
|
||||
nfc_blink_stop(instance);
|
||||
}
|
||||
if(new_state != (uint32_t)-1) {
|
||||
scene_manager_set_scene_state(instance->scene_manager, NfcSceneWrite, new_state);
|
||||
nfc_protocol_support_scene_write_setup_view(instance);
|
||||
}
|
||||
}
|
||||
|
||||
return consumed;
|
||||
}
|
||||
|
||||
static void nfc_protocol_support_scene_write_on_exit(NfcApp* instance) {
|
||||
if(instance->poller) {
|
||||
nfc_poller_stop(instance->poller);
|
||||
nfc_poller_free(instance->poller);
|
||||
}
|
||||
|
||||
// Clear view
|
||||
popup_reset(instance->popup);
|
||||
widget_reset(instance->widget);
|
||||
furi_string_reset(instance->text_box_store);
|
||||
|
||||
nfc_blink_stop(instance);
|
||||
}
|
||||
|
||||
static void nfc_protocol_support_scene_rpc_on_enter(NfcApp* instance) {
|
||||
UNUSED(instance);
|
||||
}
|
||||
@@ -709,7 +1095,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;
|
||||
}
|
||||
@@ -807,6 +1193,12 @@ static const NfcProtocolSupportCommonSceneBase
|
||||
.on_event = nfc_protocol_support_scene_emulate_on_event,
|
||||
.on_exit = nfc_protocol_support_scene_emulate_on_exit,
|
||||
},
|
||||
[NfcProtocolSupportSceneWrite] =
|
||||
{
|
||||
.on_enter = nfc_protocol_support_scene_write_on_enter,
|
||||
.on_event = nfc_protocol_support_scene_write_on_event,
|
||||
.on_exit = nfc_protocol_support_scene_write_on_exit,
|
||||
},
|
||||
[NfcProtocolSupportSceneRpc] =
|
||||
{
|
||||
.on_enter = nfc_protocol_support_scene_rpc_on_enter,
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -9,6 +9,8 @@
|
||||
#include "../../nfc_app.h"
|
||||
#include "../../nfc_app_i.h"
|
||||
|
||||
#include <lib/flipper_application/flipper_application.h>
|
||||
|
||||
/**
|
||||
* @brief Scene entry handler.
|
||||
*
|
||||
@@ -114,4 +116,47 @@ typedef struct {
|
||||
* It is responsible for creating a listener and for handling its events.
|
||||
*/
|
||||
NfcProtocolSupportSceneBase scene_emulate;
|
||||
|
||||
/**
|
||||
* @brief Handlers for protocol-specific write scene.
|
||||
*
|
||||
* This scene is activated when a write operation is in progress.
|
||||
* It is responsible for creating a poller, handling its events and
|
||||
* displaying short captions for what is happening.
|
||||
*/
|
||||
NfcProtocolSupportSceneBase scene_write;
|
||||
} 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; \
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ typedef enum {
|
||||
NfcProtocolFeatureEmulateFull = 1UL << 1, /**< Complete emulation is supported. */
|
||||
NfcProtocolFeatureEditUid = 1UL << 2, /**< UID editing is supported. */
|
||||
NfcProtocolFeatureMoreInfo = 1UL << 3, /**< More information is provided. */
|
||||
NfcProtocolFeatureWrite = 1UL << 4, /**< Writing to real card is supported. */
|
||||
} NfcProtocolFeature;
|
||||
|
||||
/**
|
||||
@@ -30,6 +31,7 @@ typedef enum {
|
||||
NfcProtocolSupportSceneSavedMenu, /**< Menu for the card that was loaded from file. */
|
||||
NfcProtocolSupportSceneSaveName, /**< Shown when saving or renaming a file. */
|
||||
NfcProtocolSupportSceneEmulate, /**< Shown when emulating a card. */
|
||||
NfcProtocolSupportSceneWrite, /**< Shown when writing to a card. */
|
||||
NfcProtocolSupportSceneRpc, /**< Shown in remote-controlled (RPC) mode. */
|
||||
|
||||
NfcProtocolSupportSceneCount, /**< Special value equal to total scene count. Internal use. */
|
||||
|
||||
@@ -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 */
|
||||
};
|
||||
@@ -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[];
|
||||
@@ -26,9 +26,9 @@ void nfc_protocol_support_common_byte_input_done_callback(void* context) {
|
||||
}
|
||||
|
||||
void nfc_protocol_support_common_text_input_done_callback(void* context) {
|
||||
NfcApp* nfc = context;
|
||||
NfcApp* instance = context;
|
||||
|
||||
view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventTextInputDone);
|
||||
view_dispatcher_send_custom_event(instance->view_dispatcher, NfcCustomEventTextInputDone);
|
||||
}
|
||||
|
||||
void nfc_protocol_support_common_on_enter_empty(NfcApp* instance) {
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
enum {
|
||||
SubmenuIndexCommonSave, /**< Save menu option. */
|
||||
SubmenuIndexCommonEmulate, /**< Emulate menu option. */
|
||||
SubmenuIndexCommonWrite, /**< Write menu option. */
|
||||
SubmenuIndexCommonEdit, /**< Edit menu option. */
|
||||
SubmenuIndexCommonInfo, /**< Info menu option. */
|
||||
SubmenuIndexCommonRename, /**< Rename menu option. */
|
||||
@@ -23,6 +24,10 @@ enum {
|
||||
SubmenuIndexCommonMax, /**< Special value, internal use. */
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Common submenu callback.
|
||||
*
|
||||
@@ -84,3 +89,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
|
||||
|
||||
@@ -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
|
||||
|
||||
140
applications/main/nfc/helpers/protocol_support/ntag4xx/ntag4xx.c
Normal file
140
applications/main/nfc/helpers/protocol_support/ntag4xx/ntag4xx.c
Normal file
@@ -0,0 +1,140 @@
|
||||
#include "ntag4xx.h"
|
||||
#include "ntag4xx_render.h"
|
||||
|
||||
#include <nfc/protocols/ntag4xx/ntag4xx_poller.h>
|
||||
|
||||
#include "nfc/nfc_app_i.h"
|
||||
|
||||
#include "../nfc_protocol_support_common.h"
|
||||
#include "../nfc_protocol_support_gui_common.h"
|
||||
#include "../iso14443_4a/iso14443_4a_i.h"
|
||||
|
||||
static void nfc_scene_info_on_enter_ntag4xx(NfcApp* instance) {
|
||||
const NfcDevice* device = instance->nfc_device;
|
||||
const Ntag4xxData* data = nfc_device_get_data(device, NfcProtocolNtag4xx);
|
||||
|
||||
FuriString* temp_str = furi_string_alloc();
|
||||
nfc_append_filename_string_when_present(instance, temp_str);
|
||||
furi_string_cat_printf(
|
||||
temp_str, "\e#%s\n", nfc_device_get_name(device, NfcDeviceNameTypeFull));
|
||||
nfc_render_ntag4xx_info(data, NfcProtocolFormatTypeFull, temp_str);
|
||||
|
||||
widget_add_text_scroll_element(
|
||||
instance->widget, 0, 0, 128, 64, furi_string_get_cstr(temp_str));
|
||||
|
||||
furi_string_free(temp_str);
|
||||
}
|
||||
|
||||
static void nfc_scene_more_info_on_enter_ntag4xx(NfcApp* instance) {
|
||||
const NfcDevice* device = instance->nfc_device;
|
||||
const Ntag4xxData* data = nfc_device_get_data(device, NfcProtocolNtag4xx);
|
||||
|
||||
furi_string_reset(instance->text_box_store);
|
||||
nfc_render_ntag4xx_data(data, instance->text_box_store);
|
||||
|
||||
text_box_set_font(instance->text_box, TextBoxFontHex);
|
||||
text_box_set_text(instance->text_box, furi_string_get_cstr(instance->text_box_store));
|
||||
|
||||
view_dispatcher_switch_to_view(instance->view_dispatcher, NfcViewTextBox);
|
||||
}
|
||||
|
||||
static NfcCommand nfc_scene_read_poller_callback_ntag4xx(NfcGenericEvent event, void* context) {
|
||||
furi_assert(event.protocol == NfcProtocolNtag4xx);
|
||||
|
||||
NfcCommand command = NfcCommandContinue;
|
||||
|
||||
NfcApp* instance = context;
|
||||
const Ntag4xxPollerEvent* ntag4xx_event = event.event_data;
|
||||
|
||||
if(ntag4xx_event->type == Ntag4xxPollerEventTypeReadSuccess) {
|
||||
nfc_device_set_data(
|
||||
instance->nfc_device, NfcProtocolNtag4xx, nfc_poller_get_data(instance->poller));
|
||||
view_dispatcher_send_custom_event(instance->view_dispatcher, NfcCustomEventPollerSuccess);
|
||||
command = NfcCommandStop;
|
||||
} else if(ntag4xx_event->type == Ntag4xxPollerEventTypeReadFailed) {
|
||||
command = NfcCommandReset;
|
||||
}
|
||||
|
||||
return command;
|
||||
}
|
||||
|
||||
static void nfc_scene_read_on_enter_ntag4xx(NfcApp* instance) {
|
||||
nfc_poller_start(instance->poller, nfc_scene_read_poller_callback_ntag4xx, instance);
|
||||
}
|
||||
|
||||
static void nfc_scene_read_success_on_enter_ntag4xx(NfcApp* instance) {
|
||||
const NfcDevice* device = instance->nfc_device;
|
||||
const Ntag4xxData* data = nfc_device_get_data(device, NfcProtocolNtag4xx);
|
||||
|
||||
FuriString* temp_str = furi_string_alloc();
|
||||
furi_string_cat_printf(
|
||||
temp_str, "\e#%s\n", nfc_device_get_name(device, NfcDeviceNameTypeFull));
|
||||
nfc_render_ntag4xx_info(data, NfcProtocolFormatTypeShort, temp_str);
|
||||
|
||||
widget_add_text_scroll_element(
|
||||
instance->widget, 0, 0, 128, 52, furi_string_get_cstr(temp_str));
|
||||
|
||||
furi_string_free(temp_str);
|
||||
}
|
||||
|
||||
static void nfc_scene_emulate_on_enter_ntag4xx(NfcApp* instance) {
|
||||
const Iso14443_4aData* iso14443_4a_data =
|
||||
nfc_device_get_data(instance->nfc_device, NfcProtocolIso14443_4a);
|
||||
|
||||
instance->listener =
|
||||
nfc_listener_alloc(instance->nfc, NfcProtocolIso14443_4a, iso14443_4a_data);
|
||||
nfc_listener_start(
|
||||
instance->listener, nfc_scene_emulate_listener_callback_iso14443_4a, instance);
|
||||
}
|
||||
|
||||
const NfcProtocolSupportBase nfc_protocol_support_ntag4xx = {
|
||||
.features = NfcProtocolFeatureEmulateUid | NfcProtocolFeatureMoreInfo,
|
||||
|
||||
.scene_info =
|
||||
{
|
||||
.on_enter = nfc_scene_info_on_enter_ntag4xx,
|
||||
.on_event = nfc_protocol_support_common_on_event_empty,
|
||||
},
|
||||
.scene_more_info =
|
||||
{
|
||||
.on_enter = nfc_scene_more_info_on_enter_ntag4xx,
|
||||
.on_event = nfc_protocol_support_common_on_event_empty,
|
||||
},
|
||||
.scene_read =
|
||||
{
|
||||
.on_enter = nfc_scene_read_on_enter_ntag4xx,
|
||||
.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_scene_read_success_on_enter_ntag4xx,
|
||||
.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_scene_emulate_on_enter_ntag4xx,
|
||||
.on_event = nfc_protocol_support_common_on_event_empty,
|
||||
},
|
||||
.scene_write =
|
||||
{
|
||||
.on_enter = nfc_protocol_support_common_on_enter_empty,
|
||||
.on_event = nfc_protocol_support_common_on_event_empty,
|
||||
},
|
||||
};
|
||||
|
||||
NFC_PROTOCOL_SUPPORT_PLUGIN(ntag4xx, NfcProtocolNtag4xx);
|
||||
@@ -0,0 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include "../nfc_protocol_support_base.h"
|
||||
|
||||
extern const NfcProtocolSupportBase nfc_protocol_support_ntag4xx;
|
||||
@@ -0,0 +1,110 @@
|
||||
#include "ntag4xx_render.h"
|
||||
|
||||
#include "../iso14443_4a/iso14443_4a_render.h"
|
||||
|
||||
void nfc_render_ntag4xx_info(
|
||||
const Ntag4xxData* data,
|
||||
NfcProtocolFormatType format_type,
|
||||
FuriString* str) {
|
||||
nfc_render_iso14443_4a_brief(ntag4xx_get_base_data(data), str);
|
||||
|
||||
const Ntag4xxType type = ntag4xx_get_type_from_version(&data->version);
|
||||
if(type >= Ntag4xxTypeUnknown) {
|
||||
furi_string_cat(str, "Memory Size: unknown");
|
||||
} else {
|
||||
size_t size_cc = 32;
|
||||
size_t size_ndef = 0;
|
||||
size_t size_proprietary = 0;
|
||||
bool has_tagtamper = false;
|
||||
switch(type) {
|
||||
case Ntag4xxType413DNA:
|
||||
size_ndef = 128;
|
||||
size_proprietary = 0;
|
||||
break;
|
||||
case Ntag4xxType424DNATT:
|
||||
has_tagtamper = true;
|
||||
/* fall-through */
|
||||
case Ntag4xxType424DNA:
|
||||
size_ndef = 256;
|
||||
size_proprietary = 128;
|
||||
break;
|
||||
case Ntag4xxType426QDNATT:
|
||||
has_tagtamper = true;
|
||||
/* fall-through */
|
||||
case Ntag4xxType426QDNA:
|
||||
size_ndef = 768;
|
||||
size_proprietary = 128;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
furi_string_cat_printf(
|
||||
str, "\nMemory Size: %zu bytes\n", size_cc + size_ndef + size_proprietary);
|
||||
furi_string_cat_printf(str, "Usable NDEF Size: %zu bytes\n", size_ndef - sizeof(uint16_t));
|
||||
furi_string_cat_printf(str, "Capability Cont.: %zu bytes\n", size_cc);
|
||||
if(size_proprietary) {
|
||||
furi_string_cat_printf(str, "Proprietary File: %zu bytes\n", size_proprietary);
|
||||
}
|
||||
furi_string_cat_printf(str, "TagTamper: %ssupported", has_tagtamper ? "" : "not ");
|
||||
}
|
||||
|
||||
if(format_type != NfcProtocolFormatTypeFull) return;
|
||||
|
||||
furi_string_cat(str, "\n\e#ISO14443-4 data");
|
||||
nfc_render_iso14443_4a_extra(ntag4xx_get_base_data(data), str);
|
||||
}
|
||||
|
||||
void nfc_render_ntag4xx_data(const Ntag4xxData* data, FuriString* str) {
|
||||
nfc_render_ntag4xx_version(&data->version, str);
|
||||
}
|
||||
|
||||
void nfc_render_ntag4xx_version(const Ntag4xxVersion* data, FuriString* str) {
|
||||
furi_string_cat_printf(
|
||||
str,
|
||||
"%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
|
||||
data->uid[0],
|
||||
data->uid[1],
|
||||
data->uid[2],
|
||||
data->uid[3],
|
||||
data->uid[4],
|
||||
data->uid[5],
|
||||
data->uid[6]);
|
||||
furi_string_cat_printf(
|
||||
str,
|
||||
"hw %02x type %02x sub %02x\n"
|
||||
" maj %02x min %02x\n"
|
||||
" size %02x proto %02x\n",
|
||||
data->hw_vendor,
|
||||
data->hw_type,
|
||||
data->hw_subtype,
|
||||
data->hw_major,
|
||||
data->hw_minor,
|
||||
data->hw_storage,
|
||||
data->hw_proto);
|
||||
furi_string_cat_printf(
|
||||
str,
|
||||
"sw %02x type %02x sub %02x\n"
|
||||
" maj %02x min %02x\n"
|
||||
" size %02x proto %02x\n",
|
||||
data->sw_vendor,
|
||||
data->sw_type,
|
||||
data->sw_subtype,
|
||||
data->sw_major,
|
||||
data->sw_minor,
|
||||
data->sw_storage,
|
||||
data->sw_proto);
|
||||
furi_string_cat_printf(
|
||||
str,
|
||||
"batch %02x:%02x:%02x:%02x:%01x\n"
|
||||
"week %d year %d\n"
|
||||
"fab key %02x id %02x\n",
|
||||
data->batch[0],
|
||||
data->batch[1],
|
||||
data->batch[2],
|
||||
data->batch[3],
|
||||
data->batch_extra,
|
||||
data->prod_week,
|
||||
data->prod_year,
|
||||
(data->fab_key_4b << 1) | (data->fab_key_1b),
|
||||
data->optional.fab_key_id);
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
#include <nfc/protocols/ntag4xx/ntag4xx.h>
|
||||
|
||||
#include "../nfc_protocol_support_render_common.h"
|
||||
|
||||
void nfc_render_ntag4xx_info(
|
||||
const Ntag4xxData* data,
|
||||
NfcProtocolFormatType format_type,
|
||||
FuriString* str);
|
||||
|
||||
void nfc_render_ntag4xx_data(const Ntag4xxData* data, FuriString* str);
|
||||
|
||||
void nfc_render_ntag4xx_version(const Ntag4xxVersion* data, FuriString* str);
|
||||
@@ -78,20 +78,21 @@ static NfcCommand nfc_scene_emulate_listener_callback_slix(NfcGenericEvent event
|
||||
furi_assert(event.protocol == NfcProtocolSlix);
|
||||
furi_assert(event.event_data);
|
||||
|
||||
NfcApp* nfc = context;
|
||||
NfcApp* instance = context;
|
||||
SlixListenerEvent* slix_event = event.event_data;
|
||||
|
||||
if(slix_event->type == SlixListenerEventTypeCustomCommand) {
|
||||
if(furi_string_size(nfc->text_box_store) < NFC_LOG_SIZE_MAX) {
|
||||
furi_string_cat_printf(nfc->text_box_store, "R:");
|
||||
if(furi_string_size(instance->text_box_store) < NFC_LOG_SIZE_MAX) {
|
||||
furi_string_cat_printf(instance->text_box_store, "R:");
|
||||
for(size_t i = 0; i < bit_buffer_get_size_bytes(slix_event->data->buffer); i++) {
|
||||
furi_string_cat_printf(
|
||||
nfc->text_box_store,
|
||||
instance->text_box_store,
|
||||
" %02X",
|
||||
bit_buffer_get_byte(slix_event->data->buffer, i));
|
||||
}
|
||||
furi_string_push_back(nfc->text_box_store, '\n');
|
||||
view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventListenerUpdate);
|
||||
furi_string_push_back(instance->text_box_store, '\n');
|
||||
view_dispatcher_send_custom_event(
|
||||
instance->view_dispatcher, NfcCustomEventListenerUpdate);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -105,15 +106,6 @@ static void nfc_scene_emulate_on_enter_slix(NfcApp* instance) {
|
||||
nfc_listener_start(instance->listener, nfc_scene_emulate_listener_callback_slix, instance);
|
||||
}
|
||||
|
||||
static bool nfc_scene_saved_menu_on_event_slix(NfcApp* instance, SceneManagerEvent event) {
|
||||
if(event.type == SceneManagerEventTypeCustom && event.event == SubmenuIndexCommonEdit) {
|
||||
scene_manager_next_scene(instance->scene_manager, NfcSceneSetUid);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
const NfcProtocolSupportBase nfc_protocol_support_slix = {
|
||||
.features = NfcProtocolFeatureEmulateFull | NfcProtocolFeatureMoreInfo,
|
||||
|
||||
@@ -145,7 +137,7 @@ const NfcProtocolSupportBase nfc_protocol_support_slix = {
|
||||
.scene_saved_menu =
|
||||
{
|
||||
.on_enter = nfc_protocol_support_common_on_enter_empty,
|
||||
.on_event = nfc_scene_saved_menu_on_event_slix,
|
||||
.on_event = nfc_protocol_support_common_on_event_empty,
|
||||
},
|
||||
.scene_save_name =
|
||||
{
|
||||
@@ -157,4 +149,11 @@ const NfcProtocolSupportBase nfc_protocol_support_slix = {
|
||||
.on_enter = nfc_scene_emulate_on_enter_slix,
|
||||
.on_event = nfc_protocol_support_common_on_event_empty,
|
||||
},
|
||||
.scene_write =
|
||||
{
|
||||
.on_enter = nfc_protocol_support_common_on_enter_empty,
|
||||
.on_event = nfc_protocol_support_common_on_event_empty,
|
||||
},
|
||||
};
|
||||
|
||||
NFC_PROTOCOL_SUPPORT_PLUGIN(slix, NfcProtocolSlix);
|
||||
|
||||
@@ -61,15 +61,6 @@ static void nfc_scene_read_success_on_enter_st25tb(NfcApp* instance) {
|
||||
furi_string_free(temp_str);
|
||||
}
|
||||
|
||||
static bool nfc_scene_saved_menu_on_event_st25tb(NfcApp* instance, SceneManagerEvent event) {
|
||||
if(event.type == SceneManagerEventTypeCustom && event.event == SubmenuIndexCommonEdit) {
|
||||
scene_manager_next_scene(instance->scene_manager, NfcSceneSetUid);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
const NfcProtocolSupportBase nfc_protocol_support_st25tb = {
|
||||
.features = NfcProtocolFeatureNone,
|
||||
|
||||
@@ -96,7 +87,7 @@ const NfcProtocolSupportBase nfc_protocol_support_st25tb = {
|
||||
.scene_saved_menu =
|
||||
{
|
||||
.on_enter = nfc_protocol_support_common_on_enter_empty,
|
||||
.on_event = nfc_scene_saved_menu_on_event_st25tb,
|
||||
.on_event = nfc_protocol_support_common_on_event_empty,
|
||||
},
|
||||
.scene_save_name =
|
||||
{
|
||||
@@ -108,4 +99,11 @@ const NfcProtocolSupportBase nfc_protocol_support_st25tb = {
|
||||
.on_enter = nfc_protocol_support_common_on_enter_empty,
|
||||
.on_event = nfc_protocol_support_common_on_event_empty,
|
||||
},
|
||||
.scene_write =
|
||||
{
|
||||
.on_enter = nfc_protocol_support_common_on_enter_empty,
|
||||
.on_event = nfc_protocol_support_common_on_event_empty,
|
||||
},
|
||||
};
|
||||
|
||||
NFC_PROTOCOL_SUPPORT_PLUGIN(st25tb, NfcProtocolSt25tb);
|
||||
|
||||
@@ -0,0 +1,260 @@
|
||||
#include "type_4_tag.h"
|
||||
#include "type_4_tag_render.h"
|
||||
|
||||
#include <nfc/protocols/type_4_tag/type_4_tag_poller.h>
|
||||
#include <nfc/protocols/type_4_tag/type_4_tag_listener.h>
|
||||
#include <toolbox/pretty_format.h>
|
||||
|
||||
#include "nfc/nfc_app_i.h"
|
||||
|
||||
#include "../nfc_protocol_support_common.h"
|
||||
#include "../nfc_protocol_support_gui_common.h"
|
||||
|
||||
enum {
|
||||
NfcSceneMoreInfoStateASCII,
|
||||
NfcSceneMoreInfoStateRawData,
|
||||
};
|
||||
|
||||
static void nfc_scene_info_on_enter_type_4_tag(NfcApp* instance) {
|
||||
const NfcDevice* device = instance->nfc_device;
|
||||
const Type4TagData* data = nfc_device_get_data(device, NfcProtocolType4Tag);
|
||||
|
||||
FuriString* temp_str = furi_string_alloc();
|
||||
nfc_append_filename_string_when_present(instance, temp_str);
|
||||
furi_string_cat_printf(
|
||||
temp_str, "\e#%s\n", nfc_device_get_name(device, NfcDeviceNameTypeFull));
|
||||
nfc_render_type_4_tag_info(data, NfcProtocolFormatTypeFull, temp_str);
|
||||
|
||||
widget_add_text_scroll_element(
|
||||
instance->widget, 0, 0, 128, 52, furi_string_get_cstr(temp_str));
|
||||
|
||||
furi_string_free(temp_str);
|
||||
}
|
||||
|
||||
static void nfc_scene_more_info_on_enter_type_4_tag(NfcApp* instance) {
|
||||
const NfcDevice* device = instance->nfc_device;
|
||||
const Type4TagData* data = nfc_device_get_data(device, NfcProtocolType4Tag);
|
||||
|
||||
furi_string_reset(instance->text_box_store);
|
||||
uint32_t scene_state =
|
||||
scene_manager_get_scene_state(instance->scene_manager, NfcSceneMoreInfo);
|
||||
|
||||
if(scene_state == NfcSceneMoreInfoStateASCII) {
|
||||
if(simple_array_get_count(data->ndef_data) == 0) {
|
||||
furi_string_cat_str(instance->text_box_store, "No NDEF data to show");
|
||||
} else {
|
||||
pretty_format_bytes_hex_canonical(
|
||||
instance->text_box_store,
|
||||
TYPE_4_TAG_RENDER_BYTES_PER_LINE,
|
||||
PRETTY_FORMAT_FONT_MONOSPACE,
|
||||
simple_array_cget_data(data->ndef_data),
|
||||
simple_array_get_count(data->ndef_data));
|
||||
}
|
||||
|
||||
widget_add_text_scroll_element(
|
||||
instance->widget, 0, 0, 128, 48, furi_string_get_cstr(instance->text_box_store));
|
||||
widget_add_button_element(
|
||||
instance->widget,
|
||||
GuiButtonTypeRight,
|
||||
"Raw Data",
|
||||
nfc_protocol_support_common_widget_callback,
|
||||
instance);
|
||||
|
||||
widget_add_button_element(
|
||||
instance->widget,
|
||||
GuiButtonTypeLeft,
|
||||
"Info",
|
||||
nfc_protocol_support_common_widget_callback,
|
||||
instance);
|
||||
} else if(scene_state == NfcSceneMoreInfoStateRawData) {
|
||||
nfc_render_type_4_tag_dump(data, instance->text_box_store);
|
||||
widget_add_text_scroll_element(
|
||||
instance->widget, 0, 0, 128, 48, furi_string_get_cstr(instance->text_box_store));
|
||||
|
||||
widget_add_button_element(
|
||||
instance->widget,
|
||||
GuiButtonTypeLeft,
|
||||
"ASCII",
|
||||
nfc_protocol_support_common_widget_callback,
|
||||
instance);
|
||||
}
|
||||
}
|
||||
|
||||
static bool nfc_scene_more_info_on_event_type_4_tag(NfcApp* instance, SceneManagerEvent event) {
|
||||
bool consumed = false;
|
||||
|
||||
if((event.type == SceneManagerEventTypeCustom && event.event == GuiButtonTypeLeft) ||
|
||||
(event.type == SceneManagerEventTypeBack)) {
|
||||
scene_manager_set_scene_state(
|
||||
instance->scene_manager, NfcSceneMoreInfo, NfcSceneMoreInfoStateASCII);
|
||||
scene_manager_previous_scene(instance->scene_manager);
|
||||
consumed = true;
|
||||
} else if(event.type == SceneManagerEventTypeCustom && event.event == GuiButtonTypeRight) {
|
||||
scene_manager_set_scene_state(
|
||||
instance->scene_manager, NfcSceneMoreInfo, NfcSceneMoreInfoStateRawData);
|
||||
scene_manager_next_scene(instance->scene_manager, NfcSceneMoreInfo);
|
||||
consumed = true;
|
||||
}
|
||||
return consumed;
|
||||
}
|
||||
|
||||
static NfcCommand nfc_scene_read_poller_callback_type_4_tag(NfcGenericEvent event, void* context) {
|
||||
furi_assert(event.protocol == NfcProtocolType4Tag);
|
||||
|
||||
NfcCommand command = NfcCommandContinue;
|
||||
|
||||
NfcApp* instance = context;
|
||||
const Type4TagPollerEvent* type_4_tag_event = event.event_data;
|
||||
|
||||
if(type_4_tag_event->type == Type4TagPollerEventTypeReadSuccess) {
|
||||
nfc_device_set_data(
|
||||
instance->nfc_device, NfcProtocolType4Tag, nfc_poller_get_data(instance->poller));
|
||||
view_dispatcher_send_custom_event(instance->view_dispatcher, NfcCustomEventPollerSuccess);
|
||||
command = NfcCommandStop;
|
||||
} else if(type_4_tag_event->type == Type4TagPollerEventTypeReadFailed) {
|
||||
command = NfcCommandReset;
|
||||
}
|
||||
|
||||
return command;
|
||||
}
|
||||
|
||||
static void nfc_scene_read_on_enter_type_4_tag(NfcApp* instance) {
|
||||
nfc_poller_start(instance->poller, nfc_scene_read_poller_callback_type_4_tag, instance);
|
||||
}
|
||||
|
||||
static void nfc_scene_read_success_on_enter_type_4_tag(NfcApp* instance) {
|
||||
const NfcDevice* device = instance->nfc_device;
|
||||
const Type4TagData* data = nfc_device_get_data(device, NfcProtocolType4Tag);
|
||||
|
||||
FuriString* temp_str = furi_string_alloc();
|
||||
furi_string_cat_printf(
|
||||
temp_str, "\e#%s\n", nfc_device_get_name(device, NfcDeviceNameTypeFull));
|
||||
nfc_render_type_4_tag_info(data, NfcProtocolFormatTypeShort, temp_str);
|
||||
|
||||
widget_add_text_scroll_element(
|
||||
instance->widget, 0, 0, 128, 52, furi_string_get_cstr(temp_str));
|
||||
|
||||
furi_string_free(temp_str);
|
||||
}
|
||||
|
||||
static NfcCommand
|
||||
nfc_scene_emulate_listener_callback_type_4_tag(NfcGenericEvent event, void* context) {
|
||||
furi_assert(event.protocol == NfcProtocolType4Tag);
|
||||
|
||||
NfcApp* instance = context;
|
||||
Type4TagListenerEvent* type_4_tag_event = event.event_data;
|
||||
|
||||
if(type_4_tag_event->type == Type4TagListenerEventTypeCustomCommand) {
|
||||
if(furi_string_size(instance->text_box_store) < NFC_LOG_SIZE_MAX) {
|
||||
furi_string_cat_printf(instance->text_box_store, "R:");
|
||||
for(size_t i = 0; i < bit_buffer_get_size_bytes(type_4_tag_event->data->buffer); i++) {
|
||||
furi_string_cat_printf(
|
||||
instance->text_box_store,
|
||||
" %02X",
|
||||
bit_buffer_get_byte(type_4_tag_event->data->buffer, i));
|
||||
}
|
||||
furi_string_push_back(instance->text_box_store, '\n');
|
||||
view_dispatcher_send_custom_event(
|
||||
instance->view_dispatcher, NfcCustomEventListenerUpdate);
|
||||
}
|
||||
}
|
||||
|
||||
return NfcCommandContinue;
|
||||
}
|
||||
|
||||
static void nfc_scene_emulate_on_enter_type_4_tag(NfcApp* instance) {
|
||||
const Type4TagData* data = nfc_device_get_data(instance->nfc_device, NfcProtocolType4Tag);
|
||||
|
||||
instance->listener = nfc_listener_alloc(instance->nfc, NfcProtocolType4Tag, data);
|
||||
nfc_listener_start(
|
||||
instance->listener, nfc_scene_emulate_listener_callback_type_4_tag, instance);
|
||||
}
|
||||
|
||||
static NfcCommand
|
||||
nfc_scene_write_poller_callback_type_4_tag(NfcGenericEvent event, void* context) {
|
||||
furi_assert(event.protocol == NfcProtocolType4Tag);
|
||||
|
||||
NfcApp* instance = context;
|
||||
Type4TagPollerEvent* type_4_tag_event = event.event_data;
|
||||
NfcCommand command = NfcCommandContinue;
|
||||
|
||||
if(type_4_tag_event->type == Type4TagPollerEventTypeRequestMode) {
|
||||
type_4_tag_event->data->poller_mode.mode = Type4TagPollerModeWrite;
|
||||
type_4_tag_event->data->poller_mode.data =
|
||||
nfc_device_get_data(instance->nfc_device, NfcProtocolType4Tag);
|
||||
furi_string_reset(instance->text_box_store);
|
||||
view_dispatcher_send_custom_event(instance->view_dispatcher, NfcCustomEventCardDetected);
|
||||
} else if(type_4_tag_event->type == Type4TagPollerEventTypeWriteFail) {
|
||||
const char* error_str = type_4_tag_event->data->error == Type4TagErrorCardLocked ?
|
||||
"Card does not\nallow writing\nnew data" :
|
||||
"Failed to\nwrite new data";
|
||||
furi_string_set(instance->text_box_store, error_str);
|
||||
view_dispatcher_send_custom_event(instance->view_dispatcher, NfcCustomEventPollerFailure);
|
||||
command = NfcCommandStop;
|
||||
} else if(type_4_tag_event->type == Type4TagPollerEventTypeWriteSuccess) {
|
||||
furi_string_reset(instance->text_box_store);
|
||||
view_dispatcher_send_custom_event(instance->view_dispatcher, NfcCustomEventPollerSuccess);
|
||||
command = NfcCommandStop;
|
||||
}
|
||||
|
||||
return command;
|
||||
}
|
||||
|
||||
static void nfc_scene_write_on_enter_type_4_tag(NfcApp* instance) {
|
||||
instance->poller = nfc_poller_alloc(instance->nfc, NfcProtocolType4Tag);
|
||||
nfc_poller_start(instance->poller, nfc_scene_write_poller_callback_type_4_tag, instance);
|
||||
furi_string_set(instance->text_box_store, "Apply card\nto the back");
|
||||
}
|
||||
|
||||
const NfcProtocolSupportBase nfc_protocol_support_type_4_tag = {
|
||||
.features = NfcProtocolFeatureEmulateFull | NfcProtocolFeatureMoreInfo |
|
||||
NfcProtocolFeatureWrite,
|
||||
|
||||
.scene_info =
|
||||
{
|
||||
.on_enter = nfc_scene_info_on_enter_type_4_tag,
|
||||
.on_event = nfc_protocol_support_common_on_event_empty,
|
||||
},
|
||||
.scene_more_info =
|
||||
{
|
||||
.on_enter = nfc_scene_more_info_on_enter_type_4_tag,
|
||||
.on_event = nfc_scene_more_info_on_event_type_4_tag,
|
||||
},
|
||||
.scene_read =
|
||||
{
|
||||
.on_enter = nfc_scene_read_on_enter_type_4_tag,
|
||||
.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_scene_read_success_on_enter_type_4_tag,
|
||||
.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_scene_emulate_on_enter_type_4_tag,
|
||||
.on_event = nfc_protocol_support_common_on_event_empty,
|
||||
},
|
||||
.scene_write =
|
||||
{
|
||||
.on_enter = nfc_scene_write_on_enter_type_4_tag,
|
||||
.on_event = nfc_protocol_support_common_on_event_empty,
|
||||
},
|
||||
};
|
||||
|
||||
NFC_PROTOCOL_SUPPORT_PLUGIN(type_4_tag, NfcProtocolType4Tag);
|
||||
@@ -0,0 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include "../nfc_protocol_support_base.h"
|
||||
|
||||
extern const NfcProtocolSupportBase nfc_protocol_support_type_4_tag;
|
||||
@@ -0,0 +1,59 @@
|
||||
#include "type_4_tag_render.h"
|
||||
|
||||
#include "../iso14443_4a/iso14443_4a_render.h"
|
||||
|
||||
void nfc_render_type_4_tag_info(
|
||||
const Type4TagData* data,
|
||||
NfcProtocolFormatType format_type,
|
||||
FuriString* str) {
|
||||
nfc_render_iso14443_4a_brief(type_4_tag_get_base_data(data), str);
|
||||
|
||||
furi_string_cat(str, "\n:::::::::::::::[Stored NDEF]:::::::::::::::\n");
|
||||
furi_string_cat_printf(str, "Current NDEF Size: %lu", simple_array_get_count(data->ndef_data));
|
||||
|
||||
if(data->is_tag_specific) {
|
||||
furi_string_cat(str, "\n::::::::::::::::::[Tag Specs]::::::::::::::::::\n");
|
||||
furi_string_cat_printf(
|
||||
str,
|
||||
"Card: %s\n",
|
||||
furi_string_empty(data->platform_name) ? "unknown" :
|
||||
furi_string_get_cstr(data->platform_name));
|
||||
furi_string_cat_printf(
|
||||
str, "T4T Mapping Version: %u.%u\n", data->t4t_version.major, data->t4t_version.minor);
|
||||
furi_string_cat_printf(str, "NDEF File ID: %04X\n", data->ndef_file_id);
|
||||
furi_string_cat_printf(str, "Max NDEF Size: %u\n", data->ndef_max_len);
|
||||
furi_string_cat_printf(
|
||||
str, "APDU Sizes: R:%u W:%u\n", data->chunk_max_read, data->chunk_max_write);
|
||||
furi_string_cat_printf(
|
||||
str,
|
||||
"Read Lock: %02X%s\n",
|
||||
data->ndef_read_lock,
|
||||
data->ndef_read_lock == 0 ? " (unlocked)" : "");
|
||||
furi_string_cat_printf(
|
||||
str,
|
||||
"Write Lock: %02X%s",
|
||||
data->ndef_write_lock,
|
||||
data->ndef_write_lock == 0 ? " (unlocked)" : "");
|
||||
}
|
||||
|
||||
if(format_type != NfcProtocolFormatTypeFull) return;
|
||||
|
||||
furi_string_cat(str, "\n\e#ISO14443-4 data");
|
||||
nfc_render_iso14443_4a_extra(type_4_tag_get_base_data(data), str);
|
||||
}
|
||||
|
||||
void nfc_render_type_4_tag_dump(const Type4TagData* data, FuriString* str) {
|
||||
size_t ndef_len = simple_array_get_count(data->ndef_data);
|
||||
if(ndef_len == 0) {
|
||||
furi_string_cat_str(str, "No NDEF data to show");
|
||||
return;
|
||||
}
|
||||
const uint8_t* ndef_data = simple_array_cget_data(data->ndef_data);
|
||||
furi_string_cat_printf(str, "\e*");
|
||||
for(size_t i = 0; i < ndef_len; i += TYPE_4_TAG_RENDER_BYTES_PER_LINE) {
|
||||
const uint8_t* line_data = &ndef_data[i];
|
||||
for(size_t j = 0; j < TYPE_4_TAG_RENDER_BYTES_PER_LINE; j += 2) {
|
||||
furi_string_cat_printf(str, " %02X%02X", line_data[j], line_data[j + 1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
#include <nfc/protocols/type_4_tag/type_4_tag.h>
|
||||
|
||||
#include "../nfc_protocol_support_render_common.h"
|
||||
|
||||
#define TYPE_4_TAG_RENDER_BYTES_PER_LINE (4U)
|
||||
|
||||
void nfc_render_type_4_tag_info(
|
||||
const Type4TagData* data,
|
||||
NfcProtocolFormatType format_type,
|
||||
FuriString* str);
|
||||
|
||||
void nfc_render_type_4_tag_dump(const Type4TagData* data, FuriString* str);
|
||||
Reference in New Issue
Block a user