Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
83 commits
Select commit Hold shift + click to select a range
358631e
NFC: Implement Type 4 Tag reading
WillyJL Mar 5, 2025
d5161f0
Fix reading empty NDEF message
WillyJL Mar 6, 2025
aa38025
NFC: Implement Type 4 Tag saving
WillyJL Mar 6, 2025
0beee0c
Fix reading NLEN header in NDEF message
WillyJL Mar 6, 2025
e3f7e1c
NFC: Implement Type 4 Tag NDEF parsing
WillyJL Mar 6, 2025
f760d97
Sort and add missing protocol mentions
WillyJL Mar 9, 2025
730f1b6
Fix event struct passed to callbacks
WillyJL Mar 10, 2025
385e8b3
Add more specific error types
WillyJL Mar 10, 2025
4dce879
Cleanup includes
WillyJL Mar 10, 2025
b0690de
NFC: Expose iso14443_3a_listener functions (OFW issue 4059)
WillyJL Mar 10, 2025
cfeddbf
BitBuffer: Allow copy right/left on same instance
WillyJL Mar 10, 2025
fbc176e
NFC: Rudimentary iso14443_4a_listener_send_block() (no PCB handling) …
WillyJL Mar 10, 2025
d174fa9
NFC: Implement Type 4 Tag rudimentary emulation
WillyJL Mar 10, 2025
2e77e87
Support larger NDEF messages
WillyJL Mar 10, 2025
99b2762
Fix sending error responses
WillyJL Mar 10, 2025
e64292d
NFC: Initial ISO14443-4 PCB listener handling
WillyJL Mar 11, 2025
01b113f
Fix chunk sizes
WillyJL Mar 14, 2025
084774d
Fix ISO READ BINARY params definitions
WillyJL Mar 15, 2025
799ed9f
Fix emulate after save
WillyJL Mar 15, 2025
b05a735
Allow selecting PICC level too
WillyJL Mar 15, 2025
384f365
Refactor CC parsing and dumping
WillyJL Mar 15, 2025
7689efa
Use flags for ISO14443-4 layer decode result
WillyJL Mar 15, 2025
e0b5aa8
For now send NACK to all R blocks
WillyJL Mar 15, 2025
967eb06
NFC: Handle writes to Type 4 Tag while emulating
WillyJL Mar 15, 2025
22a6c37
Refactor ISO APDUs in T4T poller
WillyJL Mar 17, 2025
0df5a66
Keep prev selection when new selection fails
WillyJL Mar 17, 2025
b503020
NFC: Implement Type 4 Tag writing biolerplate and structure
WillyJL Mar 17, 2025
ca30673
Improve ISO SELECT naming and handling
WillyJL Mar 18, 2025
b1346bc
Make APDU arrays static
WillyJL Mar 18, 2025
106d72a
Better handling of read/write failure
WillyJL Mar 18, 2025
0af703d
NFC: Implement Type 4 Tag writing to initialized tags
WillyJL Mar 18, 2025
121ce31
NFC: Detect Type 4 Tag platform (eg DESFire)
WillyJL Mar 18, 2025
27c977b
Fix writing with platform detect
WillyJL Mar 19, 2025
f7198c6
NFC: Support creating NDEF AID on DESFire
WillyJL Mar 19, 2025
19ee0f4
Rename mf_desfire_send_chunks() to mf_desfire_poller_send_chunks()
WillyJL Mar 20, 2025
cc78911
NFC: Implement DESFire ISO 7816 command wrapping
WillyJL Mar 20, 2025
da36d40
NFC: T4T interact with DESFire without state reset
WillyJL Mar 20, 2025
3cffc69
Fix some message strings
WillyJL Mar 20, 2025
3c977b7
Static define T4T DESFire app ids
WillyJL Mar 20, 2025
e2b7cd2
Simplify return here
WillyJL Mar 20, 2025
c4f2206
Fix some edge cases with max NDEF size
WillyJL Mar 20, 2025
f01972e
NFC: Support creating CC and NDEF files on DESFire
WillyJL Mar 20, 2025
5ed0dc2
GUI: Add submenu_remove_item()
WillyJL Mar 21, 2025
1943661
NFC: Refactor Write actions into ProtocolSupport
WillyJL Mar 21, 2025
2a31127
NFC: Pressing back on MFC Update doesn't retry
WillyJL Mar 21, 2025
3bd92f8
NFC: Fix duplicated ProtocolSupport handling, fix some inconsistent n…
WillyJL Mar 21, 2025
4c12733
Fix writing retrying after success
WillyJL Mar 21, 2025
ff340ea
NFC: Implement basic NTAG4xx detection
WillyJL Mar 22, 2025
11af323
Small cleanup
WillyJL Mar 22, 2025
49127b1
Check HWMajorVersion like NXP commands \o/
WillyJL Mar 22, 2025
1f8cfcc
NFC: Detect NTAG4xx in Type 4 Tag poller
WillyJL Mar 22, 2025
118e745
NFC: Refactor common NXP Native command handling
WillyJL Mar 22, 2025
d2f4d0c
NFC: Show version info for MIFARE Plus (was implemented but not shown)
WillyJL Mar 22, 2025
2f521d5
NFC: Only show MFP GetVersion info when available
WillyJL Mar 23, 2025
5194cf7
NFC: Fix detecting MIFARE Plus SE 1K SL1/3
WillyJL Mar 25, 2025
f037f73
Merge remote-tracking branch 'ofw/dev' into feat/nfc-type-4
WillyJL Mar 25, 2025
0b04d7d
Expose dESFire NDEF size
WillyJL Mar 25, 2025
6fb122e
Stop poller and blinking on write success/fail
WillyJL Mar 26, 2025
768508a
GUI: Add submenu_remove_item()
WillyJL Mar 27, 2025
e9830fa
NFC: Refactor write scenes into protocol support
WillyJL Mar 27, 2025
2db0d9b
NFC: Cleanup duplicate event handling
WillyJL Mar 27, 2025
0b42027
NFC: Refactor DESFire poller to NxpNativeCommand helper
WillyJL Mar 27, 2025
7525662
NFC: Sort protocol defs and add missing ones
WillyJL Mar 27, 2025
6ebc4c7
NFC: Support NTAG4xx detection and basic info
WillyJL Mar 27, 2025
d362cb5
NFC: Allow choosing DESFire poller cmd mode, fix send_chunks() naming
WillyJL Mar 27, 2025
bd6e5f8
NFC: Check MIFARE types with HWType lower nibble
WillyJL Mar 27, 2025
9b3d970
NFC: Refactor MIFARE Plus with NxpNativeCommand helper
WillyJL Mar 27, 2025
4717966
NFC: Fix detecting MIFARE Plus SE 1K SL1/3
WillyJL Mar 27, 2025
ec97852
NFC: Show MIFARE Plus EV1/2 GetVersion info like DESFire
WillyJL Mar 27, 2025
ff10a2f
Merge remote-tracking branch 'ofw/dev' into feat/nfc-type-4
WillyJL Mar 27, 2025
628c706
Merge branch 'feat/nfc-write-refactor' into feat/nfc-type-4
WillyJL Mar 27, 2025
a575d95
Merge branch 'feat/ntag4xx-detect' into feat/nfc-type-4
WillyJL Mar 27, 2025
f85b5c2
Revert "BitBuffer: Allow copy right/left on same instance"
WillyJL Mar 27, 2025
9e8c8ad
Use dedicated buffer
WillyJL Mar 27, 2025
c706262
Simpler naming scheme
WillyJL Mar 27, 2025
04415bf
Merge remote-tracking branch 'ofw/dev' into feat/nfc-type-4
WillyJL Apr 10, 2025
af17d70
Merge remote-tracking branch 'ofw/dev' into feat/nfc-type-4
WillyJL Apr 22, 2025
77debdc
Update TODOs that are out of scope for the project
WillyJL Apr 22, 2025
aa64333
Fix typos
WillyJL Jun 29, 2025
8b25c87
Merge remote-tracking branch 'ofw/dev' into feat/nfc-type-4-final
WillyJL Jun 29, 2025
649e173
Merge branch 'dev' into feat/nfc-type-4-final
hedger Sep 25, 2025
43f08bd
Merge remote-tracking branch 'ofw/dev' into feat/nfc-type-4-final
WillyJL Oct 5, 2025
c4fcda7
Fix merge
WillyJL Oct 5, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions applications/main/nfc/application.fam
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,16 @@ App(
sources=["plugins/supported_cards/ndef.c"],
)

App(
appid="ndef_t4t_parser",
apptype=FlipperAppType.PLUGIN,
cdefines=[("NDEF_PROTO", "NDEF_PROTO_T4T")],
entry_point="ndef_plugin_ep",
targets=["f7"],
requires=["nfc"],
sources=["plugins/supported_cards/ndef.c"],
)

App(
appid="disney_infinity_parser",
apptype=FlipperAppType.PLUGIN,
Expand Down
1 change: 1 addition & 0 deletions applications/main/nfc/helpers/nfc_custom_event.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ typedef enum {
NfcCustomEventCardLost,

NfcCustomEventViewExit,
NfcCustomEventRetry,
NfcCustomEventWorkerExit,
NfcCustomEventWorkerUpdate,
NfcCustomEventWrongCard,
Expand Down
16 changes: 6 additions & 10 deletions applications/main/nfc/helpers/protocol_support/felica/felica.c
Original file line number Diff line number Diff line change
Expand Up @@ -124,15 +124,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);
Expand Down Expand Up @@ -192,7 +183,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 =
{
Expand All @@ -204,4 +195,9 @@ 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,
},
};
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}

Expand All @@ -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,

Expand All @@ -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 =
{
Expand All @@ -144,4 +136,9 @@ 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,
},
};
Original file line number Diff line number Diff line change
Expand Up @@ -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,

Expand All @@ -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 =
{
Expand All @@ -111,4 +98,9 @@ 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,
},
};

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}

Expand All @@ -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,

Expand All @@ -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 =
{
Expand All @@ -147,4 +139,9 @@ 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,
},
};
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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,

Expand All @@ -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 =
{
Expand All @@ -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 =
{
Expand All @@ -116,4 +98,9 @@ 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,
},
};
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}

Expand All @@ -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,
Expand Down Expand Up @@ -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 =
{
Expand All @@ -161,4 +153,9 @@ 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,
},
};
Loading