Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NFC: initial support for NFC-F (FeliCa) #2093

Closed
wants to merge 51 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
eaa2dea
NFC: initial support for NFC-F (FeliCa)
nullableVoidPtr Dec 5, 2022
68b3cc2
NFC: add specific FeliCa type read option
nullableVoidPtr Dec 5, 2022
c7d60e5
mf_classic_check_card_type: ATQA1 is used
Dec 7, 2022
72d9ad8
mf_classic_get_classic_type: ATQA1 is used
Dec 7, 2022
2871759
use FuriHalNfcADevData instead of using each of its fields in functio…
Dec 7, 2022
6c7cd09
NFC: Add Felica info scenes and properly clear felica_data
nullableVoidPtr Dec 10, 2022
eaf7234
Merge branch 'dev' into nfcf
nullableVoidPtr Dec 10, 2022
5c26ddb
Bump API version
nullableVoidPtr Dec 10, 2022
c41ce0b
Merge branch 'nfcf' of github.com:erakem/flipperzero-firmware into er…
nullableVoidPtr Dec 10, 2022
b53690a
Add headers to submenu
nullableVoidPtr Dec 11, 2022
82387bf
Merge remote-tracking branch 'origin/dev' into nfcf
nullableVoidPtr Dec 11, 2022
95f91b5
Merge branch 'dev' into nfcf
nullableVoidPtr Dec 25, 2022
94558df
Merge branch 'dev' into nfcf
nullableVoidPtr Dec 28, 2022
8fecca3
NFC: bump API version and format FeliCa scene code
nullableVoidPtr Dec 28, 2022
653d0d7
NFC: slight FeliCa refactor
nullableVoidPtr Dec 28, 2022
d0e3bfd
Merge branch 'dev' into nfcf
nullableVoidPtr Dec 29, 2022
3a098dc
Merge branch 'dev' into nfcf
nullableVoidPtr Dec 30, 2022
7d79379
NFC: FeliCa menu select uses new submenu ownership model
nullableVoidPtr Dec 30, 2022
556c76e
Merge branch 'dev' into nfcf
nullableVoidPtr Jan 24, 2023
8ef89d9
Merge branch 'dev' into nfcf
nullableVoidPtr Jan 24, 2023
b521761
Merge branch 'dev' into nfcf
nullableVoidPtr Feb 4, 2023
a2cd122
Move FeliCa IDm/PMm display to the new NFC-F info screen
dogtopus Mar 10, 2023
4334198
Array use refactor
dogtopus Mar 18, 2023
c1cb656
Merge branch 'dev' into nfcf
nullableVoidPtr Mar 24, 2023
b30ecb6
Merge remote-tracking branch 'dogtopus/nfcf' into nfcf
nullableVoidPtr Mar 28, 2023
eed9231
wip: NFC: FeliCa lite authentication
nullableVoidPtr Mar 29, 2023
e265935
FeliCa Standard system traversal
dogtopus Apr 9, 2023
6265a67
FeliCa Standard dumping WIP
dogtopus Apr 10, 2023
c29accc
Finish FeliCa Standard dumping
dogtopus Apr 12, 2023
94979a8
Rename felica_info_select to felica_data and invoke from nfc_data_info
dogtopus Apr 12, 2023
9bdf643
Move to an inode-based structure
dogtopus Apr 15, 2023
9070405
Fix node tree not populating
dogtopus Apr 17, 2023
7e21f39
New FeliCa Standard viewer WIP
dogtopus Apr 17, 2023
fb1ef88
Mostly working Standard area and service viewer
dogtopus Apr 18, 2023
b9c8819
Implement area info, better card stat printing, and various other things
dogtopus Apr 19, 2023
229a3df
Bring back Lite data viewer and add monolithic NDEF support
dogtopus Apr 20, 2023
0cbafe5
New card detection routine
dogtopus Apr 21, 2023
3235c21
Merge remote-tracking branch 'upstream/dev' into nfcf
nullableVoidPtr Apr 22, 2023
1e64209
Various adjustments
dogtopus Apr 22, 2023
bd3f6e0
Respect PMm
dogtopus Apr 22, 2023
926f0f3
Implement system info viewer
dogtopus Apr 22, 2023
3f1a698
Add spec version dumping and card info view
dogtopus Apr 23, 2023
f610e81
Cleanups and some renames
dogtopus Apr 23, 2023
3672095
Remove NDEF autodetect shortcut
dogtopus Apr 23, 2023
8062b3e
Merge branch 'dev' into nfcf
dogtopus Apr 25, 2023
13d85dd
Clean up text box on exit
dogtopus Apr 25, 2023
f36beec
WIP
nullableVoidPtr Apr 29, 2023
ddc2631
Merge remote-tracking branch 'upstream/dev' into nfcf
nullableVoidPtr May 7, 2023
8299365
Merge remote-tracking branch 'dogtopus/nfcf' into nfcf
nullableVoidPtr May 15, 2023
75ed1d2
nfc (felica): save functionality (CRASHING)
nullableVoidPtr Jul 18, 2023
e171015
Merge remote-tracking branch 'upstream/dev' into nfcf
nullableVoidPtr Jul 18, 2023
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: 5 additions & 5 deletions applications/external/nfc_magic/nfc_magic_worker.c
Original file line number Diff line number Diff line change
Expand Up @@ -183,9 +183,9 @@ void nfc_magic_worker_write(NfcMagicWorker* nfc_magic_worker) {
}
gen4_config[7] = 0x00;
memset(gen4_config + 8, 0, 16);
gen4_config[24] = dev_data->nfc_data.atqa[0];
gen4_config[25] = dev_data->nfc_data.atqa[1];
gen4_config[26] = dev_data->nfc_data.sak;
gen4_config[24] = dev_data->nfc_data.a_data.atqa[0];
gen4_config[25] = dev_data->nfc_data.a_data.atqa[1];
gen4_config[26] = dev_data->nfc_data.a_data.sak;

furi_hal_nfc_sleep();
furi_hal_nfc_activate_nfca(200, &cuid);
Expand Down Expand Up @@ -305,7 +305,7 @@ void nfc_magic_worker_check(NfcMagicWorker* nfc_magic_worker) {
}

if(furi_hal_nfc_detect(&nfc_data, 200)) {
magic_dev->cuid = nfc_data.cuid;
magic_dev->cuid = nfc_data.a_data.cuid;
magic_dev->uid_len = nfc_data.uid_len;
} else {
// wrong BCC
Expand All @@ -317,7 +317,7 @@ void nfc_magic_worker_check(NfcMagicWorker* nfc_magic_worker) {
magic_deactivate();
magic_activate();
if(furi_hal_nfc_detect(&nfc_data, 200)) {
magic_dev->cuid = nfc_data.cuid;
magic_dev->cuid = nfc_data.a_data.cuid;
magic_dev->uid_len = nfc_data.uid_len;
if(magic_gen4_get_cfg(magic_dev->password, gen4_config)) {
magic_dev->type = MagicTypeGen4;
Expand Down
29 changes: 22 additions & 7 deletions applications/main/nfc/nfc_cli.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,21 @@ static void nfc_cli_detect(Cli* cli, FuriString* args) {
while(!cmd_exit) {
cmd_exit |= cli_cmd_interrupt_received(cli);
if(furi_hal_nfc_detect(&dev_data, 400)) {
printf("Found: %s ", nfc_get_dev_type(dev_data.type));
printf("UID length: %d, UID:", dev_data.uid_len);
for(size_t i = 0; i < dev_data.uid_len; i++) {
printf("%02X", dev_data.uid[i]);
printf("found: %s ", nfc_get_dev_type(dev_data.type));
if(dev_data.type == FuriHalNfcTypeA) {
printf("UID length: %d, UID:", dev_data.uid_len);
for(size_t i = 0; i < dev_data.uid_len; i++) {
printf("%02X", dev_data.uid[i]);
}
} else if(dev_data.type == FuriHalNfcTypeF) {
printf("IDm:");
for(size_t i = 0; i < 8; i++) {
printf("%02X", dev_data.uid[i]);
}
printf(", PMm:");
for(size_t i = 0; i < 8; i++) {
printf("%02X", dev_data.f_data.pmm[i]);
}
}
printf("\r\n");
break;
Expand All @@ -63,13 +74,17 @@ static void nfc_cli_emulate(Cli* cli, FuriString* args) {
FuriHalNfcDevData params = {
.uid = {0x36, 0x9C, 0xe7, 0xb1, 0x0A, 0xC1, 0x34},
.uid_len = 7,
.atqa = {0x44, 0x00},
.sak = 0x00,
.a_data =
{
.atqa = {0x44, 0x00},
.sak = 0x00,
},
.type = FuriHalNfcTypeA,
};

while(!cli_cmd_interrupt_received(cli)) {
if(furi_hal_nfc_listen(params.uid, params.uid_len, params.atqa, params.sak, false, 100)) {
if(furi_hal_nfc_listen(
params.uid, params.uid_len, params.a_data.atqa, params.a_data.sak, false, 100)) {
printf("Reader detected\r\n");
furi_hal_nfc_sleep();
}
Expand Down
13 changes: 12 additions & 1 deletion applications/main/nfc/nfc_i.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,23 @@

#include "rpc/rpc_app.h"

#include <m-list.h>
#include <m-array.h>

ARRAY_DEF(MfClassicUserKeys, char*, M_PTR_OPLIST);
ARRAY_DEF(FelicaAreaPath, FelicaArea*, M_PTR_OPLIST)
ARRAY_DEF(MfClassicUserKeys, char*, M_PTR_OPLIST)

#define NFC_TEXT_STORE_SIZE 128
#define NFC_APP_FOLDER ANY_PATH("nfc")

typedef struct {
FelicaSystem* selected_system;

FelicaAreaPath_t selected_areas;

FelicaService* selected_service;
} FelicaSelectState;

typedef enum {
NfcRpcStateIdle,
NfcRpcStateEmulating,
Expand All @@ -65,6 +75,7 @@ struct Nfc {
FuriString* text_box_store;
uint8_t byte_input_store[6];
MfClassicUserKeys_t mfc_key_strs; // Used in MFC key listing
FelicaSelectState felica_select;

void* rpc_ctx;
NfcRpcState rpc_state;
Expand Down
6 changes: 6 additions & 0 deletions applications/main/nfc/scenes/nfc_scene_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ ADD_SCENE(nfc, file_select, FileSelect)
ADD_SCENE(nfc, emulate_uid, EmulateUid)
ADD_SCENE(nfc, nfca_read_success, NfcaReadSuccess)
ADD_SCENE(nfc, nfca_menu, NfcaMenu)
ADD_SCENE(nfc, nfcf_read_success, NfcfReadSuccess)
ADD_SCENE(nfc, nfcf_menu, NfcfMenu)
ADD_SCENE(nfc, nfcv_menu, NfcVMenu)
ADD_SCENE(nfc, nfcv_unlock_menu, NfcVUnlockMenu)
ADD_SCENE(nfc, nfcv_key_input, NfcVKeyInput)
Expand Down Expand Up @@ -53,6 +55,10 @@ ADD_SCENE(nfc, mf_classic_update_success, MfClassicUpdateSuccess)
ADD_SCENE(nfc, mf_classic_wrong_card, MfClassicWrongCard)
ADD_SCENE(nfc, emv_read_success, EmvReadSuccess)
ADD_SCENE(nfc, emv_menu, EmvMenu)
ADD_SCENE(nfc, felica_read_success, FelicaReadSuccess)
ADD_SCENE(nfc, felica_menu, FelicaMenu)
ADD_SCENE(nfc, felica_data, FelicaData)
ADD_SCENE(nfc, felica_sys_data, FelicaSysData)
ADD_SCENE(nfc, emulate_apdu_sequence, EmulateApduSequence)
ADD_SCENE(nfc, device_info, DeviceInfo)
ADD_SCENE(nfc, delete, Delete)
Expand Down
2 changes: 2 additions & 0 deletions applications/main/nfc/scenes/nfc_scene_delete.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ void nfc_scene_delete_on_enter(void* context) {
furi_string_set(temp_str, nfc_mf_classic_type(nfc->dev->dev_data.mf_classic_data.type));
} else if(protocol == NfcDeviceProtocolMifareDesfire) {
furi_string_set(temp_str, "MIFARE DESFire");
} else if(protocol == NfcDeviceProtocolFelica) {
furi_string_set(temp_str, "FeliCa");
} else if(protocol == NfcDeviceProtocolNfcV) {
furi_string_set(temp_str, "ISO15693 tag");
nfc_type = "NFC-V";
Expand Down
95 changes: 95 additions & 0 deletions applications/main/nfc/scenes/nfc_scene_felica_data.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
#include "../nfc_i.h"
#include <dolphin/dolphin.h>

enum SubmenuIndex {
SubmenuIndexCardInfo = 0,
SubmenuIndexDynamic,
};

void nfc_scene_felica_data_submenu_callback(void* context, uint32_t index) {
Nfc* nfc = context;

view_dispatcher_send_custom_event(nfc->view_dispatcher, index);
}

void nfc_scene_felica_data_on_enter(void* context) {
Nfc* nfc = context;
Submenu* submenu = nfc->submenu;
FelicaData* data = &nfc->dev->dev_data.felica_data;
FuriString* system_name = furi_string_alloc();

submenu_add_item(
submenu, "Card Info", SubmenuIndexCardInfo, nfc_scene_felica_data_submenu_callback, nfc);
uint8_t i = SubmenuIndexDynamic;
for
M_EACH(current_system, data->systems, FelicaSystemArray_t) {
felica_describe_system(current_system, system_name);
submenu_add_item(
submenu,
furi_string_get_cstr(system_name),
i++,
nfc_scene_felica_data_submenu_callback,
nfc);
furi_string_reset(system_name);
}

furi_string_free(system_name);

submenu_set_selected_item(
nfc->submenu, scene_manager_get_scene_state(nfc->scene_manager, NfcSceneFelicaData) >> 1);

view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewMenu);
}

bool nfc_scene_felica_data_on_event(void* context, SceneManagerEvent event) {
Nfc* nfc = context;
SceneManager* scene_manager = nfc->scene_manager;
ViewDispatcher* view_dispatcher = nfc->view_dispatcher;
FelicaData* data = &nfc->dev->dev_data.felica_data;
TextBox* text_box = nfc->text_box;
FuriString* text_box_store = nfc->text_box_store;
bool consumed = false;

if(event.type == SceneManagerEventTypeCustom) {
uint8_t index = event.event;
scene_manager_set_scene_state(scene_manager, NfcSceneFelicaData, index << 1);

if(index == SubmenuIndexCardInfo) {
furi_string_reset(text_box_store);

felica_print_card_spec(&data->spec, text_box_store);
text_box_set_text(text_box, furi_string_get_cstr(text_box_store));

scene_manager_set_scene_state(scene_manager, NfcSceneFelicaData, 1);

text_box_set_font(text_box, TextBoxFontHex);
view_dispatcher_switch_to_view(view_dispatcher, NfcViewTextBox);
consumed = true;
} else {
uint8_t system_index = (index - SubmenuIndexDynamic) & 0xf;
scene_manager_set_scene_state(
scene_manager, NfcSceneFelicaSysData, system_index << 16);
scene_manager_next_scene(scene_manager, NfcSceneFelicaSysData);
consumed = true;
}
} else if(event.type == SceneManagerEventTypeBack) {
uint8_t state = scene_manager_get_scene_state(scene_manager, NfcSceneFelicaData);
if(state & 1) {
scene_manager_set_scene_state(scene_manager, NfcSceneFelicaData, 0);
view_dispatcher_switch_to_view(view_dispatcher, NfcViewMenu);
consumed = true;
} else {
consumed = scene_manager_previous_scene(scene_manager);
}
}

return consumed;
}

void nfc_scene_felica_data_on_exit(void* context) {
Nfc* nfc = context;

submenu_reset(nfc->submenu);
text_box_reset(nfc->text_box);
furi_string_reset(nfc->text_box_store);
}
87 changes: 87 additions & 0 deletions applications/main/nfc/scenes/nfc_scene_felica_menu.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
#include "../nfc_i.h"
#include <dolphin/dolphin.h>

enum SubmenuIndex {
/*
SubmenuIndexUnlock,
*/
SubmenuIndexSave,
/*
SubmenuIndexEmulate,
*/
SubmenuIndexInfo,
};

void nfc_scene_felica_menu_submenu_callback(void* context, uint32_t index) {
Nfc* nfc = context;

view_dispatcher_send_custom_event(nfc->view_dispatcher, index);
}

void nfc_scene_felica_menu_on_enter(void* context) {
Nfc* nfc = context;
Submenu* submenu = nfc->submenu;
// FelicaData* data = &nfc->dev->dev_data.felica_data;

/*
submenu_add_item(
submenu, "Unlock", SubmenuIndexUnlock, nfc_scene_felica_menu_submenu_callback, nfc);
*/
submenu_add_item(
submenu, "Save", SubmenuIndexSave, nfc_scene_felica_menu_submenu_callback, nfc);
/*
submenu_add_item(
submenu, "Emulate", SubmenuIndexEmulate, nfc_scene_felica_menu_submenu_callback, nfc);
*/
submenu_add_item(
submenu, "Info", SubmenuIndexInfo, nfc_scene_felica_menu_submenu_callback, nfc);

submenu_set_selected_item(
nfc->submenu, scene_manager_get_scene_state(nfc->scene_manager, NfcSceneFelicaMenu));

view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewMenu);
}

bool nfc_scene_felica_menu_on_event(void* context, SceneManagerEvent event) {
Nfc* nfc = context;
bool consumed = false;

if(event.type == SceneManagerEventTypeCustom) {
if(event.event == SubmenuIndexSave) {
nfc->dev->format = NfcDeviceSaveFormatFelica;
// Clear device name
nfc_device_set_name(nfc->dev, "");
scene_manager_next_scene(nfc->scene_manager, NfcSceneSaveName);
consumed = true;
/*
} else if(event.event == SubmenuIndexEmulate) {
scene_manager_next_scene(nfc->scene_manager, NfcSceneFelicaEmulate);
if(scene_manager_has_previous_scene(nfc->scene_manager, NfcSceneSetType)) {
dolphin_deed(DolphinDeedNfcAddEmulate);
} else {
dolphin_deed(DolphinDeedNfcEmulate);
}
consumed = true;
} else if(event.event == SubmenuIndexUnlock) {
scene_manager_next_scene(nfc->scene_manager, NfcSceneFelicaUnlockMenu);
consumed = true;
*/
} else if(event.event == SubmenuIndexInfo) {
scene_manager_next_scene(nfc->scene_manager, NfcSceneNfcDataInfo);
consumed = true;
}
scene_manager_set_scene_state(nfc->scene_manager, NfcSceneFelicaMenu, event.event);

} else if(event.type == SceneManagerEventTypeBack) {
consumed = scene_manager_previous_scene(nfc->scene_manager);
}

return consumed;
}

void nfc_scene_felica_menu_on_exit(void* context) {
Nfc* nfc = context;

// Clear view
submenu_reset(nfc->submenu);
}
75 changes: 75 additions & 0 deletions applications/main/nfc/scenes/nfc_scene_felica_read_success.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
#include "../nfc_i.h"

void nfc_scene_felica_read_success_widget_callback(
GuiButtonType result,
InputType type,
void* context) {
furi_assert(context);
Nfc* nfc = context;

if(type == InputTypeShort) {
view_dispatcher_send_custom_event(nfc->view_dispatcher, result);
}
}

void nfc_scene_felica_read_success_on_enter(void* context) {
Nfc* nfc = context;
FelicaData* felica_data = &nfc->dev->dev_data.felica_data;

// Setup view
Widget* widget = nfc->widget;
widget_add_button_element(
widget, GuiButtonTypeLeft, "Retry", nfc_scene_felica_read_success_widget_callback, nfc);
widget_add_button_element(
widget, GuiButtonTypeRight, "More", nfc_scene_felica_read_success_widget_callback, nfc);

FuriString* temp_str = NULL;
if(furi_string_size(nfc->dev->dev_data.parsed_data)) {
temp_str = furi_string_alloc_set(nfc->dev->dev_data.parsed_data);
} else {
temp_str = furi_string_alloc_printf("\e#%s", nfc_felica_type(felica_data->type));

furi_string_cat_printf(temp_str, "\nID:");
for(size_t i = 0; i < nfc->dev->dev_data.nfc_data.uid_len; i++) {
furi_string_cat_printf(temp_str, " %02X", nfc->dev->dev_data.nfc_data.uid[i]);
}

furi_string_push_back(temp_str, '\n');
felica_print_card_stat(felica_data, temp_str);
}

widget_add_text_scroll_element(widget, 0, 0, 128, 52, furi_string_get_cstr(temp_str));
furi_string_free(temp_str);

notification_message_block(nfc->notifications, &sequence_set_green_255);

view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewWidget);
}

bool nfc_scene_felica_read_success_on_event(void* context, SceneManagerEvent event) {
Nfc* nfc = context;
bool consumed = false;

if(event.type == SceneManagerEventTypeCustom) {
if(event.event == GuiButtonTypeLeft) {
scene_manager_next_scene(nfc->scene_manager, NfcSceneRetryConfirm);
consumed = true;
} else if(event.event == GuiButtonTypeRight) {
scene_manager_next_scene(nfc->scene_manager, NfcSceneFelicaMenu);
consumed = true;
}
} else if(event.type == SceneManagerEventTypeBack) {
scene_manager_next_scene(nfc->scene_manager, NfcSceneExitConfirm);
consumed = true;
}
return consumed;
}

void nfc_scene_felica_read_success_on_exit(void* context) {
Nfc* nfc = context;

notification_message_block(nfc->notifications, &sequence_reset_green);

// Clear view
widget_reset(nfc->widget);
}
Loading