[FL-1526] Mifare Ultralight emulation (#645)
* rfal: add discovery parameter for passing listen activation * nfc: add discovery parameter to furi_hal_nfc_listen * mifare_ul: add emulation parsing commands * nfc: add mifare ul emulation * nfc: switch to mifare ultralight emulation form menu * furi-hal-nfc: add first frame reception in emulation mode * nfc: change argument check * nfc: rework nfc worker and mifare ul lib * mifare_ul: add write and cnt increment commands * nfc: add card modification check * mifare_ul: add data changed flag * nfc: add shodow files * nfc: add restore original file Co-authored-by: あく <alleteam@gmail.com>
This commit is contained in:
@@ -26,3 +26,4 @@ ADD_SCENE(nfc, run_emv_app_confirm, RunEmvAppConfirm)
|
||||
ADD_SCENE(nfc, read_emv_data, ReadEmvData)
|
||||
ADD_SCENE(nfc, read_emv_data_success, ReadEmvDataSuccess)
|
||||
ADD_SCENE(nfc, emulate_apdu_sequence, EmulateApduSequence)
|
||||
ADD_SCENE(nfc, restore_original, RestoreOriginal)
|
||||
|
@@ -1,38 +1,33 @@
|
||||
#include "../nfc_i.h"
|
||||
|
||||
#define NFC_MF_UL_DATA_NOT_CHANGED (0UL)
|
||||
#define NFC_MF_UL_DATA_CHANGED (1UL)
|
||||
|
||||
void nfc_emulate_mifare_ul_worker_callback(void* context) {
|
||||
Nfc* nfc = (Nfc*)context;
|
||||
scene_manager_set_scene_state(
|
||||
nfc->scene_manager, NfcSceneEmulateMifareUl, NFC_MF_UL_DATA_CHANGED);
|
||||
}
|
||||
|
||||
const void nfc_scene_emulate_mifare_ul_on_enter(void* context) {
|
||||
Nfc* nfc = (Nfc*)context;
|
||||
|
||||
// Setup view
|
||||
Popup* popup = nfc->popup;
|
||||
NfcDeviceCommomData* data = &nfc->dev.dev_data.nfc_data;
|
||||
|
||||
if(strcmp(nfc->dev.dev_name, "")) {
|
||||
nfc_text_store_set(nfc, "%s", nfc->dev.dev_name);
|
||||
} else if(data->uid_len == 4) {
|
||||
nfc_text_store_set(
|
||||
nfc, "%02X %02X %02X %02X", data->uid[0], data->uid[1], data->uid[2], data->uid[3]);
|
||||
} else if(data->uid_len == 7) {
|
||||
nfc_text_store_set(
|
||||
nfc,
|
||||
"%02X %02X %02X %02X\n%02X %02X %02X",
|
||||
data->uid[0],
|
||||
data->uid[1],
|
||||
data->uid[2],
|
||||
data->uid[3],
|
||||
data->uid[4],
|
||||
data->uid[5],
|
||||
data->uid[6]);
|
||||
}
|
||||
|
||||
popup_set_icon(popup, 0, 3, &I_RFIDDolphinSend_97x61);
|
||||
popup_set_header(popup, "Emulating Mf Ul", 56, 31, AlignLeft, AlignTop);
|
||||
popup_set_text(popup, nfc->text_store, 56, 43, AlignLeft, AlignTop);
|
||||
popup_set_header(popup, "Emulating\nMf Ultralight", 56, 31, AlignLeft, AlignTop);
|
||||
|
||||
// Setup and start worker
|
||||
|
||||
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewPopup);
|
||||
nfc_worker_start(nfc->worker, NfcWorkerStateEmulateMifareUl, &nfc->dev.dev_data, NULL, nfc);
|
||||
nfc_worker_start(
|
||||
nfc->worker,
|
||||
NfcWorkerStateEmulateMifareUl,
|
||||
&nfc->dev.dev_data,
|
||||
nfc_emulate_mifare_ul_worker_callback,
|
||||
nfc);
|
||||
}
|
||||
|
||||
const bool nfc_scene_emulate_mifare_ul_on_event(void* context, SceneManagerEvent event) {
|
||||
@@ -42,6 +37,17 @@ const bool nfc_scene_emulate_mifare_ul_on_event(void* context, SceneManagerEvent
|
||||
if(event.type == SceneManagerEventTypeTick) {
|
||||
notification_message(nfc->notifications, &sequence_blink_blue_10);
|
||||
consumed = true;
|
||||
} else if(event.type == SceneManagerEventTypeBack) {
|
||||
// Stop worker
|
||||
nfc_worker_stop(nfc->worker);
|
||||
// Check if data changed and save in shadow file
|
||||
if(scene_manager_get_scene_state(nfc->scene_manager, NfcSceneEmulateMifareUl) ==
|
||||
NFC_MF_UL_DATA_CHANGED) {
|
||||
scene_manager_set_scene_state(
|
||||
nfc->scene_manager, NfcSceneEmulateMifareUl, NFC_MF_UL_DATA_NOT_CHANGED);
|
||||
nfc_device_save_shadow(&nfc->dev, nfc->dev.dev_name);
|
||||
}
|
||||
consumed = false;
|
||||
}
|
||||
return consumed;
|
||||
}
|
||||
@@ -49,9 +55,6 @@ const bool nfc_scene_emulate_mifare_ul_on_event(void* context, SceneManagerEvent
|
||||
const void nfc_scene_emulate_mifare_ul_on_exit(void* context) {
|
||||
Nfc* nfc = (Nfc*)context;
|
||||
|
||||
// Stop worker
|
||||
nfc_worker_stop(nfc->worker);
|
||||
|
||||
// Clear view
|
||||
Popup* popup = nfc->popup;
|
||||
popup_set_header(popup, NULL, 0, 0, AlignCenter, AlignBottom);
|
||||
|
@@ -38,7 +38,7 @@ const bool nfc_scene_mifare_ul_menu_on_event(void* context, SceneManagerEvent ev
|
||||
} else if(event.event == SubmenuIndexEmulate) {
|
||||
scene_manager_set_scene_state(
|
||||
nfc->scene_manager, NfcSceneMifareUlMenu, SubmenuIndexEmulate);
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneNotImplemented);
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneEmulateMifareUl);
|
||||
return true;
|
||||
}
|
||||
} else if(event.type == SceneManagerEventTypeBack) {
|
||||
|
48
applications/nfc/scenes/nfc_scene_restore_original.c
Normal file
48
applications/nfc/scenes/nfc_scene_restore_original.c
Normal file
@@ -0,0 +1,48 @@
|
||||
#include "../nfc_i.h"
|
||||
|
||||
#define SCENE_RESTORE_ORIGINAL_CUSTOM_EVENT (0UL)
|
||||
|
||||
void nfc_scene_restore_original_popup_callback(void* context) {
|
||||
Nfc* nfc = (Nfc*)context;
|
||||
view_dispatcher_send_custom_event(nfc->view_dispatcher, SCENE_RESTORE_ORIGINAL_CUSTOM_EVENT);
|
||||
}
|
||||
|
||||
const void nfc_scene_restore_original_on_enter(void* context) {
|
||||
Nfc* nfc = (Nfc*)context;
|
||||
|
||||
// Setup view
|
||||
Popup* popup = nfc->popup;
|
||||
popup_set_icon(popup, 32, 5, &I_DolphinNice_96x59);
|
||||
popup_set_header(popup, "Original file\nrestored", 13, 22, AlignLeft, AlignBottom);
|
||||
popup_set_timeout(popup, 1500);
|
||||
popup_set_context(popup, nfc);
|
||||
popup_set_callback(popup, nfc_scene_restore_original_popup_callback);
|
||||
popup_enable_timeout(popup);
|
||||
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewPopup);
|
||||
}
|
||||
|
||||
const bool nfc_scene_restore_original_on_event(void* context, SceneManagerEvent event) {
|
||||
Nfc* nfc = (Nfc*)context;
|
||||
bool consumed = false;
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == SCENE_RESTORE_ORIGINAL_CUSTOM_EVENT) {
|
||||
consumed = scene_manager_previous_scene(nfc->scene_manager);
|
||||
}
|
||||
}
|
||||
return consumed;
|
||||
}
|
||||
|
||||
const void nfc_scene_restore_original_on_exit(void* context) {
|
||||
Nfc* nfc = (Nfc*)context;
|
||||
|
||||
// Clear view
|
||||
Popup* popup = nfc->popup;
|
||||
popup_set_header(popup, NULL, 0, 0, AlignCenter, AlignBottom);
|
||||
popup_set_text(popup, NULL, 0, 0, AlignCenter, AlignTop);
|
||||
popup_set_icon(popup, 0, 0, NULL);
|
||||
popup_set_callback(popup, NULL);
|
||||
popup_set_context(popup, NULL);
|
||||
popup_set_timeout(popup, 0);
|
||||
popup_disable_timeout(popup);
|
||||
}
|
@@ -5,6 +5,7 @@ enum SubmenuIndex {
|
||||
SubmenuIndexEdit,
|
||||
SubmenuIndexDelete,
|
||||
SubmenuIndexInfo,
|
||||
SubmenuIndexRestoreOriginal,
|
||||
};
|
||||
|
||||
void nfc_scene_saved_menu_submenu_callback(void* context, uint32_t index) {
|
||||
@@ -29,36 +30,52 @@ const void nfc_scene_saved_menu_on_enter(void* context) {
|
||||
submenu, "Info", SubmenuIndexInfo, nfc_scene_saved_menu_submenu_callback, nfc);
|
||||
submenu_set_selected_item(
|
||||
nfc->submenu, scene_manager_get_scene_state(nfc->scene_manager, NfcSceneSavedMenu));
|
||||
if(nfc->dev.shadow_file_exist) {
|
||||
submenu_add_item(
|
||||
submenu,
|
||||
"Restore original",
|
||||
SubmenuIndexRestoreOriginal,
|
||||
nfc_scene_saved_menu_submenu_callback,
|
||||
nfc);
|
||||
}
|
||||
|
||||
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewMenu);
|
||||
}
|
||||
|
||||
const bool nfc_scene_saved_menu_on_event(void* context, SceneManagerEvent event) {
|
||||
Nfc* nfc = (Nfc*)context;
|
||||
bool consumed = false;
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
scene_manager_set_scene_state(nfc->scene_manager, NfcSceneSavedMenu, event.event);
|
||||
if(event.event == SubmenuIndexEmulate) {
|
||||
scene_manager_set_scene_state(
|
||||
nfc->scene_manager, NfcSceneSavedMenu, SubmenuIndexEmulate);
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneEmulateUid);
|
||||
return true;
|
||||
if(nfc->dev.format == NfcDeviceSaveFormatMifareUl) {
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneEmulateMifareUl);
|
||||
} else {
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneEmulateUid);
|
||||
}
|
||||
consumed = true;
|
||||
} else if(event.event == SubmenuIndexEdit) {
|
||||
scene_manager_set_scene_state(nfc->scene_manager, NfcSceneSavedMenu, SubmenuIndexEdit);
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneSetUid);
|
||||
return true;
|
||||
consumed = true;
|
||||
} else if(event.event == SubmenuIndexDelete) {
|
||||
scene_manager_set_scene_state(
|
||||
nfc->scene_manager, NfcSceneSavedMenu, SubmenuIndexDelete);
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneDelete);
|
||||
return true;
|
||||
consumed = true;
|
||||
} else if(event.event == SubmenuIndexInfo) {
|
||||
scene_manager_set_scene_state(nfc->scene_manager, NfcSceneSavedMenu, SubmenuIndexInfo);
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneDeviceInfo);
|
||||
return true;
|
||||
consumed = true;
|
||||
} else if(event.event == SubmenuIndexRestoreOriginal) {
|
||||
if(!nfc_device_restore(&nfc->dev)) {
|
||||
scene_manager_search_and_switch_to_previous_scene(
|
||||
nfc->scene_manager, NfcSceneStart);
|
||||
} else {
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneRestoreOriginal);
|
||||
}
|
||||
consumed = true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
return consumed;
|
||||
}
|
||||
|
||||
const void nfc_scene_saved_menu_on_exit(void* context) {
|
||||
|
Reference in New Issue
Block a user