From b503020f6dafaa2ef170ba177ae8c2f1229040d2 Mon Sep 17 00:00:00 2001 From: Willy-JL <49810075+Willy-JL@users.noreply.github.com> Date: Mon, 17 Mar 2025 06:46:13 +0000 Subject: [PATCH] NFC: Implement Type 4 Tag writing biolerplate and structure --- .../protocol_support/type_4_tag/type_4_tag.c | 6 +- .../main/nfc/scenes/nfc_scene_config.h | 4 + .../nfc/scenes/nfc_scene_type_4_tag_write.c | 105 ++++++++++++++ .../scenes/nfc_scene_type_4_tag_write_fail.c | 72 ++++++++++ .../nfc_scene_type_4_tag_write_success.c | 46 ++++++ lib/nfc/protocols/type_4_tag/type_4_tag.h | 1 + .../protocols/type_4_tag/type_4_tag_poller.c | 135 +++++++++++++++--- .../protocols/type_4_tag/type_4_tag_poller.h | 22 +++ .../type_4_tag/type_4_tag_poller_i.c | 25 +++- .../type_4_tag/type_4_tag_poller_i.h | 18 ++- 10 files changed, 408 insertions(+), 26 deletions(-) create mode 100644 applications/main/nfc/scenes/nfc_scene_type_4_tag_write.c create mode 100644 applications/main/nfc/scenes/nfc_scene_type_4_tag_write_fail.c create mode 100644 applications/main/nfc/scenes/nfc_scene_type_4_tag_write_success.c diff --git a/applications/main/nfc/helpers/protocol_support/type_4_tag/type_4_tag.c b/applications/main/nfc/helpers/protocol_support/type_4_tag/type_4_tag.c index 043fd5f73..f0ee7baf3 100644 --- a/applications/main/nfc/helpers/protocol_support/type_4_tag/type_4_tag.c +++ b/applications/main/nfc/helpers/protocol_support/type_4_tag/type_4_tag.c @@ -129,9 +129,10 @@ static void nfc_scene_read_on_enter_type_4_tag(NfcApp* instance) { static void nfc_scene_read_and_saved_menu_on_enter_type_4_tag(NfcApp* instance) { Submenu* submenu = instance->submenu; + // FIXME: standardize this and the write scenes into protocol support helper submenu_add_item( submenu, - "Write (Not Implemented)", + "Write", SubmenuIndexWrite, nfc_protocol_support_common_submenu_callback, instance); @@ -144,8 +145,7 @@ static bool if(event.type == SceneManagerEventTypeCustom) { if(event.event == SubmenuIndexWrite) { - // TODO: Implement write - // scene_manager_next_scene(instance->scene_manager, NfcSceneType4TagWrite); + scene_manager_next_scene(instance->scene_manager, NfcSceneType4TagWrite); consumed = true; } } diff --git a/applications/main/nfc/scenes/nfc_scene_config.h b/applications/main/nfc/scenes/nfc_scene_config.h index 83c8ffeed..080294126 100644 --- a/applications/main/nfc/scenes/nfc_scene_config.h +++ b/applications/main/nfc/scenes/nfc_scene_config.h @@ -67,4 +67,8 @@ ADD_SCENE(nfc, slix_key_input, SlixKeyInput) ADD_SCENE(nfc, slix_unlock, SlixUnlock) ADD_SCENE(nfc, slix_unlock_success, SlixUnlockSuccess) +ADD_SCENE(nfc, type_4_tag_write, Type4TagWrite) +ADD_SCENE(nfc, type_4_tag_write_success, Type4TagWriteSuccess) +ADD_SCENE(nfc, type_4_tag_write_fail, Type4TagWriteFail) + ADD_SCENE(nfc, generate_info, GenerateInfo) diff --git a/applications/main/nfc/scenes/nfc_scene_type_4_tag_write.c b/applications/main/nfc/scenes/nfc_scene_type_4_tag_write.c new file mode 100644 index 000000000..cf1c93c34 --- /dev/null +++ b/applications/main/nfc/scenes/nfc_scene_type_4_tag_write.c @@ -0,0 +1,105 @@ +#include "../nfc_app_i.h" + +#include + +enum { + NfcSceneType4TagWriteStateCardSearch, + NfcSceneType4TagWriteStateCardFound, +}; + +NfcCommand nfc_scene_type_4_tag_write_worker_callback(NfcGenericEvent event, void* context) { + furi_assert(context); + furi_assert(event.event_data); + furi_assert(event.protocol == NfcProtocolType4Tag); + + NfcCommand command = NfcCommandContinue; + NfcApp* instance = context; + Type4TagPollerEvent* t4t_event = event.event_data; + + if(t4t_event->type == Type4TagPollerEventTypeRequestMode) { + t4t_event->data->poller_mode.mode = Type4TagPollerModeWrite; + t4t_event->data->poller_mode.data = + nfc_device_get_data(instance->nfc_device, NfcProtocolType4Tag); + view_dispatcher_send_custom_event(instance->view_dispatcher, NfcCustomEventCardDetected); + } else if(t4t_event->type == Type4TagPollerEventTypeWriteFail) { + scene_manager_set_scene_state( + instance->scene_manager, NfcSceneType4TagWriteFail, t4t_event->data->error); + view_dispatcher_send_custom_event(instance->view_dispatcher, NfcCustomEventPollerFailure); + command = NfcCommandStop; + } else if(t4t_event->type == Type4TagPollerEventTypeWriteSuccess) { + view_dispatcher_send_custom_event(instance->view_dispatcher, NfcCustomEventPollerSuccess); + command = NfcCommandStop; + } + return command; +} + +static void nfc_scene_type_4_tag_write_setup_view(NfcApp* instance) { + Popup* popup = instance->popup; + popup_reset(popup); + uint32_t state = scene_manager_get_scene_state(instance->scene_manager, NfcSceneType4TagWrite); + + if(state == NfcSceneType4TagWriteStateCardSearch) { + popup_set_header(instance->popup, "Writing", 95, 20, AlignCenter, AlignCenter); + popup_set_text( + instance->popup, "Apply card\nto the back", 95, 38, AlignCenter, AlignCenter); + popup_set_icon(instance->popup, 0, 8, &I_NFC_manual_60x50); + } else { + popup_set_header(popup, "Writing\nDon't move...", 52, 32, AlignLeft, AlignCenter); + popup_set_icon(popup, 12, 23, &A_Loading_24); + } + + view_dispatcher_switch_to_view(instance->view_dispatcher, NfcViewPopup); +} + +void nfc_scene_type_4_tag_write_on_enter(void* context) { + NfcApp* instance = context; + dolphin_deed(DolphinDeedNfcEmulate); + + scene_manager_set_scene_state( + instance->scene_manager, NfcSceneType4TagWrite, NfcSceneType4TagWriteStateCardSearch); + nfc_scene_type_4_tag_write_setup_view(instance); + + // Setup and start worker + instance->poller = nfc_poller_alloc(instance->nfc, NfcProtocolType4Tag); + nfc_poller_start(instance->poller, nfc_scene_type_4_tag_write_worker_callback, instance); + + nfc_blink_emulate_start(instance); +} + +bool nfc_scene_type_4_tag_write_on_event(void* context, SceneManagerEvent event) { + NfcApp* instance = context; + bool consumed = false; + + if(event.type == SceneManagerEventTypeCustom) { + if(event.event == NfcCustomEventCardDetected) { + scene_manager_set_scene_state( + instance->scene_manager, + NfcSceneType4TagWrite, + NfcSceneType4TagWriteStateCardFound); + nfc_scene_type_4_tag_write_setup_view(instance); + consumed = true; + } else if(event.event == NfcCustomEventPollerSuccess) { + scene_manager_next_scene(instance->scene_manager, NfcSceneType4TagWriteSuccess); + consumed = true; + } else if(event.event == NfcCustomEventPollerFailure) { + scene_manager_next_scene(instance->scene_manager, NfcSceneType4TagWriteFail); + consumed = true; + } + } + + return consumed; +} + +void nfc_scene_type_4_tag_write_on_exit(void* context) { + NfcApp* instance = context; + + nfc_poller_stop(instance->poller); + nfc_poller_free(instance->poller); + + scene_manager_set_scene_state( + instance->scene_manager, NfcSceneType4TagWrite, NfcSceneType4TagWriteStateCardSearch); + // Clear view + popup_reset(instance->popup); + + nfc_blink_stop(instance); +} diff --git a/applications/main/nfc/scenes/nfc_scene_type_4_tag_write_fail.c b/applications/main/nfc/scenes/nfc_scene_type_4_tag_write_fail.c new file mode 100644 index 000000000..7b4b0a9ae --- /dev/null +++ b/applications/main/nfc/scenes/nfc_scene_type_4_tag_write_fail.c @@ -0,0 +1,72 @@ +#include "../nfc_app_i.h" + +#include + +void nfc_scene_type_4_tag_write_fail_widget_callback( + GuiButtonType result, + InputType type, + void* context) { + NfcApp* instance = context; + if(type == InputTypeShort) { + view_dispatcher_send_custom_event(instance->view_dispatcher, result); + } +} + +void nfc_scene_type_4_tag_write_fail_on_enter(void* context) { + NfcApp* instance = context; + Widget* widget = instance->widget; + + notification_message(instance->notifications, &sequence_error); + + widget_add_icon_element(widget, 83, 22, &I_WarningDolphinFlip_45x42); + widget_add_string_element( + widget, 7, 4, AlignLeft, AlignTop, FontPrimary, "Writing gone wrong!"); + Type4TagError error = + scene_manager_get_scene_state(instance->scene_manager, NfcSceneType4TagWriteFail); + widget_add_string_multiline_element( + widget, + 7, + 17, + AlignLeft, + AlignTop, + FontSecondary, + error == Type4TagErrorCardLocked ? "Card does not\nallow writing\nnew data" : + "Failed to\nwrite new data"); + + widget_add_button_element( + widget, + GuiButtonTypeLeft, + "Finish", + nfc_scene_type_4_tag_write_fail_widget_callback, + instance); + + // Setup and start worker + view_dispatcher_switch_to_view(instance->view_dispatcher, NfcViewWidget); +} + +static bool nfc_scene_type_4_tag_write_fail_move_to_back_scene(const NfcApp* const instance) { + bool was_saved = scene_manager_has_previous_scene(instance->scene_manager, NfcSceneSavedMenu); + uint32_t scene_id = was_saved ? NfcSceneSavedMenu : NfcSceneReadMenu; + + return scene_manager_search_and_switch_to_previous_scene(instance->scene_manager, scene_id); +} + +bool nfc_scene_type_4_tag_write_fail_on_event(void* context, SceneManagerEvent event) { + NfcApp* instance = context; + bool consumed = false; + + if(event.type == SceneManagerEventTypeCustom) { + if(event.event == GuiButtonTypeLeft) { + consumed = nfc_scene_type_4_tag_write_fail_move_to_back_scene(instance); + } + } else if(event.type == SceneManagerEventTypeBack) { + consumed = nfc_scene_type_4_tag_write_fail_move_to_back_scene(instance); + } + return consumed; +} + +void nfc_scene_type_4_tag_write_fail_on_exit(void* context) { + NfcApp* instance = context; + + widget_reset(instance->widget); +} diff --git a/applications/main/nfc/scenes/nfc_scene_type_4_tag_write_success.c b/applications/main/nfc/scenes/nfc_scene_type_4_tag_write_success.c new file mode 100644 index 000000000..125c29e71 --- /dev/null +++ b/applications/main/nfc/scenes/nfc_scene_type_4_tag_write_success.c @@ -0,0 +1,46 @@ +#include "../nfc_app_i.h" + +void nfc_scene_type_4_tag_write_success_popup_callback(void* context) { + NfcApp* instance = context; + view_dispatcher_send_custom_event(instance->view_dispatcher, NfcCustomEventViewExit); +} + +void nfc_scene_type_4_tag_write_success_on_enter(void* context) { + NfcApp* instance = context; + dolphin_deed(DolphinDeedNfcSave); + + notification_message(instance->notifications, &sequence_success); + + Popup* popup = instance->popup; + popup_set_icon(popup, 48, 6, &I_DolphinDone_80x58); + popup_set_header(popup, "Successfully\nwritten", 5, 22, AlignLeft, AlignBottom); + popup_set_timeout(popup, 1500); + popup_set_context(popup, instance); + popup_set_callback(popup, nfc_scene_type_4_tag_write_success_popup_callback); + popup_enable_timeout(popup); + + view_dispatcher_switch_to_view(instance->view_dispatcher, NfcViewPopup); +} + +bool nfc_scene_type_4_tag_write_success_on_event(void* context, SceneManagerEvent event) { + NfcApp* instance = context; + bool consumed = false; + + if(event.type == SceneManagerEventTypeCustom) { + if(event.event == NfcCustomEventViewExit) { + bool was_saved = + scene_manager_has_previous_scene(instance->scene_manager, NfcSceneSavedMenu); + + consumed = scene_manager_search_and_switch_to_previous_scene( + instance->scene_manager, was_saved ? NfcSceneSavedMenu : NfcSceneReadSuccess); + } + } + return consumed; +} + +void nfc_scene_type_4_tag_write_success_on_exit(void* context) { + NfcApp* instance = context; + + // Clear view + popup_reset(instance->popup); +} diff --git a/lib/nfc/protocols/type_4_tag/type_4_tag.h b/lib/nfc/protocols/type_4_tag/type_4_tag.h index 220458e86..e68895a2f 100644 --- a/lib/nfc/protocols/type_4_tag/type_4_tag.h +++ b/lib/nfc/protocols/type_4_tag/type_4_tag.h @@ -14,6 +14,7 @@ typedef enum { Type4TagErrorWrongFormat, Type4TagErrorNotSupported, Type4TagErrorApduFailed, + Type4TagErrorCardLocked, Type4TagErrorCustomCommand, } Type4TagError; diff --git a/lib/nfc/protocols/type_4_tag/type_4_tag_poller.c b/lib/nfc/protocols/type_4_tag/type_4_tag_poller.c index 8e321312b..8eef2b70d 100644 --- a/lib/nfc/protocols/type_4_tag/type_4_tag_poller.c +++ b/lib/nfc/protocols/type_4_tag/type_4_tag_poller.c @@ -45,10 +45,27 @@ static NfcCommand type_4_tag_poller_handler_idle(Type4TagPoller* instance) { instance->data->iso14443_4a_data, iso14443_4a_poller_get_data(instance->iso14443_4a_poller)); - instance->state = Type4TagPollerStateSelectApplication; + instance->state = Type4TagPollerStateRequestMode; return NfcCommandContinue; } +static NfcCommand type_4_tag_poller_handler_request_mode(Type4TagPoller* instance) { + NfcCommand command = NfcCommandContinue; + + instance->type_4_tag_event.type = Type4TagPollerEventTypeRequestMode; + instance->type_4_tag_event.data->poller_mode.mode = Type4TagPollerModeRead; + instance->type_4_tag_event.data->poller_mode.data = NULL; + + command = instance->callback(instance->general_event, instance->context); + instance->mode = instance->type_4_tag_event.data->poller_mode.mode; + if(instance->mode == Type4TagPollerModeWrite) { + type_4_tag_copy(instance->data, instance->type_4_tag_event.data->poller_mode.data); + } + + instance->state = Type4TagPollerStateSelectApplication; + return command; +} + static NfcCommand type_4_tag_poller_handler_select_app(Type4TagPoller* instance) { instance->error = type_4_tag_poller_select_app(instance); if(instance->error == Type4TagErrorNone) { @@ -56,8 +73,12 @@ static NfcCommand type_4_tag_poller_handler_select_app(Type4TagPoller* instance) instance->state = Type4TagPollerStateReadCapabilityContainer; } else { FURI_LOG_E(TAG, "Failed to select application"); - iso14443_4a_poller_halt(instance->iso14443_4a_poller); - instance->state = Type4TagPollerStateReadFailed; + if(instance->mode == Type4TagPollerModeWrite && + instance->error == Type4TagErrorApduFailed) { + instance->state = Type4TagPollerStateCreateApplication; + } else { + instance->state = Type4TagPollerStateFailed; + } } return NfcCommandContinue; @@ -67,11 +88,17 @@ static NfcCommand type_4_tag_poller_handler_read_cc(Type4TagPoller* instance) { instance->error = type_4_tag_poller_read_cc(instance); if(instance->error == Type4TagErrorNone) { FURI_LOG_D(TAG, "Read CC success"); - instance->state = Type4TagPollerStateReadNdefMessage; + instance->state = instance->mode == Type4TagPollerModeRead ? + Type4TagPollerStateReadNdefMessage : + Type4TagPollerStateWriteNdefMessage; } else { FURI_LOG_E(TAG, "Failed to read CC"); - iso14443_4a_poller_halt(instance->iso14443_4a_poller); - instance->state = Type4TagPollerStateReadFailed; + if(instance->mode == Type4TagPollerModeWrite && + instance->error == Type4TagErrorApduFailed) { + instance->state = Type4TagPollerStateCreateCapabilityContainer; + } else { + instance->state = Type4TagPollerStateFailed; + } } return NfcCommandContinue; @@ -81,41 +108,115 @@ static NfcCommand type_4_tag_poller_handler_read_ndef(Type4TagPoller* instance) instance->error = type_4_tag_poller_read_ndef(instance); if(instance->error == Type4TagErrorNone) { FURI_LOG_D(TAG, "Read NDEF success"); - instance->state = Type4TagPollerStateReadSuccess; + instance->state = Type4TagPollerStateSuccess; } else { FURI_LOG_E(TAG, "Failed to read NDEF"); - iso14443_4a_poller_halt(instance->iso14443_4a_poller); - instance->state = Type4TagPollerStateReadFailed; + instance->state = Type4TagPollerStateFailed; } return NfcCommandContinue; } -static NfcCommand type_4_tag_poller_handler_read_fail(Type4TagPoller* instance) { - FURI_LOG_D(TAG, "Read Failed"); +static NfcCommand type_4_tag_poller_handler_create_app(Type4TagPoller* instance) { + instance->error = type_4_tag_poller_create_app(instance); + if(instance->error == Type4TagErrorNone) { + FURI_LOG_D(TAG, "Create application success"); + instance->state = Type4TagPollerStateSelectApplication; + } else { + FURI_LOG_E(TAG, "Failed to create application"); + if(instance->error == Type4TagErrorApduFailed) { + instance->error = Type4TagErrorCardLocked; + } + instance->state = Type4TagPollerStateFailed; + } + + return NfcCommandContinue; +} + +static NfcCommand type_4_tag_poller_handler_create_cc(Type4TagPoller* instance) { + instance->error = type_4_tag_poller_create_cc(instance); + if(instance->error == Type4TagErrorNone) { + FURI_LOG_D(TAG, "Create CC success"); + instance->state = Type4TagPollerStateReadCapabilityContainer; + } else { + FURI_LOG_E(TAG, "Failed to create CC"); + if(instance->error == Type4TagErrorApduFailed) { + instance->error = Type4TagErrorCardLocked; + } + instance->state = Type4TagPollerStateFailed; + } + + return NfcCommandContinue; +} + +static NfcCommand type_4_tag_poller_handler_create_ndef(Type4TagPoller* instance) { + instance->error = type_4_tag_poller_create_ndef(instance); + if(instance->error == Type4TagErrorNone) { + FURI_LOG_D(TAG, "Create NDEF success"); + instance->state = Type4TagPollerStateWriteNdefMessage; + } else { + FURI_LOG_E(TAG, "Failed to create NDEF"); + if(instance->error == Type4TagErrorApduFailed) { + instance->error = Type4TagErrorCardLocked; + } + instance->state = Type4TagPollerStateFailed; + } + + return NfcCommandContinue; +} + +static NfcCommand type_4_tag_poller_handler_write_ndef(Type4TagPoller* instance) { + instance->error = type_4_tag_poller_write_ndef(instance); + if(instance->error == Type4TagErrorNone) { + FURI_LOG_D(TAG, "Write NDEF success"); + instance->state = Type4TagPollerStateSuccess; + } else { + FURI_LOG_E(TAG, "Failed to write NDEF"); + if(instance->mode == Type4TagPollerModeWrite && + instance->error == Type4TagErrorApduFailed) { + instance->state = Type4TagPollerStateCreateNdefMessage; + } else { + instance->state = Type4TagPollerStateFailed; + } + } + + return NfcCommandContinue; +} + +static NfcCommand type_4_tag_poller_handler_fail(Type4TagPoller* instance) { + FURI_LOG_D(TAG, "Operation Failed"); iso14443_4a_poller_halt(instance->iso14443_4a_poller); - instance->type_4_tag_event.type = Type4TagPollerEventTypeReadFailed; + instance->type_4_tag_event.type = instance->mode == Type4TagPollerModeRead ? + Type4TagPollerEventTypeReadFailed : + Type4TagPollerEventTypeWriteFail; instance->type_4_tag_event.data->error = instance->error; NfcCommand command = instance->callback(instance->general_event, instance->context); instance->state = Type4TagPollerStateIdle; return command; } -static NfcCommand type_4_tag_poller_handler_read_success(Type4TagPoller* instance) { - FURI_LOG_D(TAG, "Read success."); +static NfcCommand type_4_tag_poller_handler_success(Type4TagPoller* instance) { + FURI_LOG_D(TAG, "Operation succeeded"); iso14443_4a_poller_halt(instance->iso14443_4a_poller); - instance->type_4_tag_event.type = Type4TagPollerEventTypeReadSuccess; + instance->type_4_tag_event.type = instance->mode == Type4TagPollerModeRead ? + Type4TagPollerEventTypeReadSuccess : + Type4TagPollerEventTypeWriteSuccess; NfcCommand command = instance->callback(instance->general_event, instance->context); return command; } static const Type4TagPollerReadHandler type_4_tag_poller_read_handler[Type4TagPollerStateNum] = { [Type4TagPollerStateIdle] = type_4_tag_poller_handler_idle, + [Type4TagPollerStateRequestMode] = type_4_tag_poller_handler_request_mode, [Type4TagPollerStateSelectApplication] = type_4_tag_poller_handler_select_app, [Type4TagPollerStateReadCapabilityContainer] = type_4_tag_poller_handler_read_cc, [Type4TagPollerStateReadNdefMessage] = type_4_tag_poller_handler_read_ndef, - [Type4TagPollerStateReadFailed] = type_4_tag_poller_handler_read_fail, - [Type4TagPollerStateReadSuccess] = type_4_tag_poller_handler_read_success, + [Type4TagPollerStateCreateApplication] = type_4_tag_poller_handler_create_app, + [Type4TagPollerStateCreateCapabilityContainer] = type_4_tag_poller_handler_create_cc, + [Type4TagPollerStateCreateNdefMessage] = type_4_tag_poller_handler_create_ndef, + [Type4TagPollerStateWriteNdefMessage] = type_4_tag_poller_handler_write_ndef, + [Type4TagPollerStateFailed] = type_4_tag_poller_handler_fail, + [Type4TagPollerStateSuccess] = type_4_tag_poller_handler_success, }; static void type_4_tag_poller_set_callback( diff --git a/lib/nfc/protocols/type_4_tag/type_4_tag_poller.h b/lib/nfc/protocols/type_4_tag/type_4_tag_poller.h index eb5e03a14..5ac4fd0f2 100644 --- a/lib/nfc/protocols/type_4_tag/type_4_tag_poller.h +++ b/lib/nfc/protocols/type_4_tag/type_4_tag_poller.h @@ -15,15 +15,37 @@ typedef struct Type4TagPoller Type4TagPoller; * @brief Enumeration of possible Type4Tag poller event types. */ typedef enum { + Type4TagPollerEventTypeRequestMode, /**< Poller requests for operating mode. */ Type4TagPollerEventTypeReadSuccess, /**< Card was read successfully. */ Type4TagPollerEventTypeReadFailed, /**< Poller failed to read card. */ + Type4TagPollerEventTypeWriteSuccess, /**< Poller wrote card successfully. */ + Type4TagPollerEventTypeWriteFail, /**< Poller failed to write card. */ } Type4TagPollerEventType; +/** + * @brief Enumeration of possible Type4Tag poller operating modes. + */ +typedef enum { + Type4TagPollerModeRead, /**< Poller will only read card. It's a default mode. */ + Type4TagPollerModeWrite, /**< Poller will write already saved card to another presented card. */ +} Type4TagPollerMode; + +/** + * @brief Type4Tag poller request mode event data. + * + * This instance of this structure must be filled on Type4TagPollerEventTypeRequestMode event. + */ +typedef struct { + Type4TagPollerMode mode; /**< Mode to be used by poller. */ + const Type4TagData* data; /**< Data to be used by poller. */ +} Type4TagPollerEventDataRequestMode; + /** * @brief Type4Tag poller event data. */ typedef union { Type4TagError error; /**< Error code indicating card reading fail reason. */ + Type4TagPollerEventDataRequestMode poller_mode; /**< Poller mode context. */ } Type4TagPollerEventData; /** diff --git a/lib/nfc/protocols/type_4_tag/type_4_tag_poller_i.c b/lib/nfc/protocols/type_4_tag/type_4_tag_poller_i.c index 55ba1b059..eab1d474b 100644 --- a/lib/nfc/protocols/type_4_tag/type_4_tag_poller_i.c +++ b/lib/nfc/protocols/type_4_tag/type_4_tag_poller_i.c @@ -198,11 +198,28 @@ Type4TagError type_4_tag_poller_read_ndef(Type4TagPoller* instance) { if(error != Type4TagErrorNone) break; FURI_LOG_D( - TAG, - "Read NDEF file 0x%04X of %lu bytes", - instance->data->ndef_file_id, - simple_array_get_count(instance->data->ndef_data)); + TAG, "Read %hu bytes from NDEF file 0x%04X", ndef_len, instance->data->ndef_file_id); } while(false); return error; } + +Type4TagError type_4_tag_poller_create_app(Type4TagPoller* instance) { + UNUSED(instance); + return Type4TagErrorNotSupported; +} + +Type4TagError type_4_tag_poller_create_cc(Type4TagPoller* instance) { + UNUSED(instance); + return Type4TagErrorNotSupported; +} + +Type4TagError type_4_tag_poller_create_ndef(Type4TagPoller* instance) { + UNUSED(instance); + return Type4TagErrorNotSupported; +} + +Type4TagError type_4_tag_poller_write_ndef(Type4TagPoller* instance) { + UNUSED(instance); + return Type4TagErrorNotSupported; +} diff --git a/lib/nfc/protocols/type_4_tag/type_4_tag_poller_i.h b/lib/nfc/protocols/type_4_tag/type_4_tag_poller_i.h index 0301e21a3..3fbead2f8 100644 --- a/lib/nfc/protocols/type_4_tag/type_4_tag_poller_i.h +++ b/lib/nfc/protocols/type_4_tag/type_4_tag_poller_i.h @@ -10,11 +10,16 @@ extern "C" { typedef enum { Type4TagPollerStateIdle, + Type4TagPollerStateRequestMode, Type4TagPollerStateSelectApplication, Type4TagPollerStateReadCapabilityContainer, Type4TagPollerStateReadNdefMessage, - Type4TagPollerStateReadFailed, - Type4TagPollerStateReadSuccess, + Type4TagPollerStateCreateApplication, + Type4TagPollerStateCreateCapabilityContainer, + Type4TagPollerStateCreateNdefMessage, + Type4TagPollerStateWriteNdefMessage, + Type4TagPollerStateFailed, + Type4TagPollerStateSuccess, Type4TagPollerStateNum, } Type4TagPollerState; @@ -22,6 +27,7 @@ typedef enum { struct Type4TagPoller { Iso14443_4aPoller* iso14443_4a_poller; Type4TagPollerState state; + Type4TagPollerMode mode; Type4TagError error; Type4TagData* data; BitBuffer* tx_buffer; @@ -41,6 +47,14 @@ Type4TagError type_4_tag_poller_read_cc(Type4TagPoller* instance); Type4TagError type_4_tag_poller_read_ndef(Type4TagPoller* instance); +Type4TagError type_4_tag_poller_create_app(Type4TagPoller* instance); + +Type4TagError type_4_tag_poller_create_cc(Type4TagPoller* instance); + +Type4TagError type_4_tag_poller_create_ndef(Type4TagPoller* instance); + +Type4TagError type_4_tag_poller_write_ndef(Type4TagPoller* instance); + #ifdef __cplusplus } #endif