From 602c125ef5255ccd8563fe521401dc571e7a1327 Mon Sep 17 00:00:00 2001 From: gornekich Date: Fri, 2 Jul 2021 16:44:10 +0300 Subject: [PATCH] [FL-1499] NFC App: save and load from SD card (#560) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * nfc: add save name and save success scenes * applications: increase nfc app stack size to 4k * nfc: move nfc device data to separate file * nfc: add nfc device save to SD card * nfc: add file select scene * nfc: add saved key menu scene * nfc: add manual SAK, ATQA, UID enter * nfc: add manual enter * nfc scenes: remove typedef in SubmenuIndex enu * nfc_device: close file_worker after load data Co-authored-by: あく --- applications/applications.c | 2 +- applications/nfc/nfc.c | 16 +++ applications/nfc/nfc_device.c | 123 ++++++++++++++++++ applications/nfc/nfc_device.h | 55 ++++++++ applications/nfc/nfc_i.h | 26 ++++ applications/nfc/nfc_worker.h | 34 +---- applications/nfc/scenes/nfc_scene_card_menu.c | 6 +- .../nfc/scenes/nfc_scene_debug_menu.c | 4 +- .../nfc/scenes/nfc_scene_emulate_uid.c | 11 +- .../nfc/scenes/nfc_scene_file_select.c | 39 ++++++ .../nfc/scenes/nfc_scene_file_select.h | 7 + applications/nfc/scenes/nfc_scene_read_card.c | 1 + .../nfc/scenes/nfc_scene_read_card_success.c | 3 + applications/nfc/scenes/nfc_scene_save_name.c | 72 ++++++++++ applications/nfc/scenes/nfc_scene_save_name.h | 7 + .../nfc/scenes/nfc_scene_save_success.c | 66 ++++++++++ .../nfc/scenes/nfc_scene_save_success.h | 7 + .../nfc/scenes/nfc_scene_saved_menu.c | 83 ++++++++++++ .../nfc/scenes/nfc_scene_saved_menu.h | 7 + applications/nfc/scenes/nfc_scene_set_atqa.c | 61 +++++++++ applications/nfc/scenes/nfc_scene_set_atqa.h | 7 + applications/nfc/scenes/nfc_scene_set_sak.c | 60 +++++++++ applications/nfc/scenes/nfc_scene_set_sak.h | 7 + applications/nfc/scenes/nfc_scene_set_type.c | 67 ++++++++++ applications/nfc/scenes/nfc_scene_set_type.h | 7 + applications/nfc/scenes/nfc_scene_set_uid.c | 65 +++++++++ applications/nfc/scenes/nfc_scene_set_uid.h | 7 + applications/nfc/scenes/nfc_scene_start.c | 10 +- 28 files changed, 812 insertions(+), 48 deletions(-) create mode 100755 applications/nfc/nfc_device.c create mode 100644 applications/nfc/nfc_device.h mode change 100755 => 100644 applications/nfc/scenes/nfc_scene_emulate_uid.c create mode 100755 applications/nfc/scenes/nfc_scene_file_select.c create mode 100644 applications/nfc/scenes/nfc_scene_file_select.h create mode 100755 applications/nfc/scenes/nfc_scene_save_name.c create mode 100644 applications/nfc/scenes/nfc_scene_save_name.h create mode 100755 applications/nfc/scenes/nfc_scene_save_success.c create mode 100644 applications/nfc/scenes/nfc_scene_save_success.h create mode 100755 applications/nfc/scenes/nfc_scene_saved_menu.c create mode 100644 applications/nfc/scenes/nfc_scene_saved_menu.h create mode 100755 applications/nfc/scenes/nfc_scene_set_atqa.c create mode 100644 applications/nfc/scenes/nfc_scene_set_atqa.h create mode 100755 applications/nfc/scenes/nfc_scene_set_sak.c create mode 100644 applications/nfc/scenes/nfc_scene_set_sak.h create mode 100755 applications/nfc/scenes/nfc_scene_set_type.c create mode 100644 applications/nfc/scenes/nfc_scene_set_type.h create mode 100755 applications/nfc/scenes/nfc_scene_set_uid.c create mode 100644 applications/nfc/scenes/nfc_scene_set_uid.h diff --git a/applications/applications.c b/applications/applications.c index 62b934b9..0ecf2c24 100644 --- a/applications/applications.c +++ b/applications/applications.c @@ -175,7 +175,7 @@ const FlipperApplication FLIPPER_APPS[] = { #endif #ifdef APP_NFC - {.app = nfc_task, .name = "NFC", .stack_size = 1024, .icon = A_NFC_14}, + {.app = nfc_task, .name = "NFC", .stack_size = 4096, .icon = A_NFC_14}, #endif #ifdef APP_SUBGHZ diff --git a/applications/nfc/nfc.c b/applications/nfc/nfc.c index 3575e323..f41d6386 100755 --- a/applications/nfc/nfc.c +++ b/applications/nfc/nfc.c @@ -77,6 +77,14 @@ Nfc* nfc_alloc() { nfc->scene_debug_read_emv = nfc_scene_debug_read_emv_alloc(); nfc->scene_debug_read_mifare_ul = nfc_scene_debug_read_mifare_ul_alloc(); nfc->scene_emulate_uid = nfc_scene_emulate_uid_alloc(); + nfc->scene_save_name = nfc_scene_save_name_alloc(); + nfc->scene_save_success = nfc_scene_save_success_alloc(); + nfc->scene_file_select = nfc_scene_file_select_alloc(); + nfc->scene_saved_menu = nfc_scene_saved_menu_alloc(); + nfc->scene_set_type = nfc_scene_set_type_alloc(); + nfc->scene_set_sak = nfc_scene_set_sak_alloc(); + nfc->scene_set_atqa = nfc_scene_set_atqa_alloc(); + nfc->scene_set_uid = nfc_scene_set_uid_alloc(); view_dispatcher_add_scene(nfc->nfc_common.view_dispatcher, nfc->scene_start); @@ -138,6 +146,14 @@ void nfc_free(Nfc* nfc) { nfc_scene_debug_read_emv_free(nfc->scene_debug_read_emv); nfc_scene_debug_read_mifare_ul_free(nfc->scene_debug_read_mifare_ul); nfc_scene_emulate_uid_free(nfc->scene_emulate_uid); + nfc_scene_save_name_free(nfc->scene_save_name); + nfc_scene_save_success_free(nfc->scene_save_success); + nfc_scene_file_select_free(nfc->scene_file_select); + nfc_scene_saved_menu_free(nfc->scene_saved_menu); + nfc_scene_set_type_free(nfc->scene_set_type); + nfc_scene_set_sak_free(nfc->scene_set_sak); + nfc_scene_set_atqa_free(nfc->scene_set_atqa); + nfc_scene_set_uid_free(nfc->scene_set_uid); // View Dispatcher view_dispatcher_free(nfc->nfc_common.view_dispatcher); diff --git a/applications/nfc/nfc_device.c b/applications/nfc/nfc_device.c new file mode 100755 index 00000000..ec1882d0 --- /dev/null +++ b/applications/nfc/nfc_device.c @@ -0,0 +1,123 @@ +#include "nfc_device.h" + +#include + +#define NFC_DEVICE_MAX_DATA_LEN 14 + +static const char* nfc_app_folder = "nfc"; +static const char* nfc_app_extension = ".nfc"; + +void nfc_device_set_name(NfcDevice* dev, const char* name) { + furi_assert(dev); + + strlcpy(dev->dev_name, name, NFC_DEV_NAME_MAX_LEN); +} + +bool nfc_device_save(NfcDevice* dev, const char* dev_name) { + furi_assert(dev); + + FileWorker* file_worker = file_worker_alloc(false); + string_t dev_file_name; + + // Create nfc directory if necessary + if(!file_worker_mkdir(file_worker, nfc_app_folder)) { + return false; + }; + + // First remove nfc device file if it was saved + string_init_printf(dev_file_name, "%s/%s%s", nfc_app_folder, dev->dev_name, nfc_app_extension); + if(!file_worker_remove(file_worker, string_get_cstr(dev_file_name))) { + string_clear(dev_file_name); + return false; + }; + + // Prepare buffer to write + uint8_t buff[NFC_DEVICE_MAX_DATA_LEN]; + buff[0] = dev->data.uid_len; + memcpy(&buff[1], dev->data.uid, dev->data.uid_len); + memcpy(&buff[dev->data.uid_len + 1], dev->data.atqa, 2); + buff[dev->data.uid_len + 3] = dev->data.sak; + + // Save nfc device + bool res = file_worker_open( + file_worker, string_get_cstr(dev_file_name), FSAM_WRITE, FSOM_CREATE_ALWAYS); + string_clear(dev_file_name); + if(res) { + // Write UID length + if(!file_worker_write_hex(file_worker, buff, dev->data.uid_len + 4)) { + file_worker_close(file_worker); + return false; + } + } + file_worker_close(file_worker); + file_worker_free(file_worker); + + return true; +} + +static bool nfc_device_load_data(FileWorker* file_worker, string_t path, NfcDevice* dev) { + // Open key file + if(!file_worker_open(file_worker, string_get_cstr(path), FSAM_READ, FSOM_OPEN_EXISTING)) { + return false; + } + + uint8_t buff[NFC_DEVICE_MAX_DATA_LEN] = {}; + + // Load first byte - UID length + if(!file_worker_read_hex(file_worker, buff, 1)) { + return false; + } + // Read space + uint8_t space = 0; + if(!file_worker_read(file_worker, &space, 1)) { + return false; + } + + // // Load other data + if(!file_worker_read_hex(file_worker, &buff[1], buff[0] + 3)) { + return false; + } + + // Set loaded data + dev->data.uid_len = buff[0]; + memcpy(dev->data.uid, &buff[1], dev->data.uid_len); + memcpy(dev->data.atqa, &buff[dev->data.uid_len + 1], 2); + dev->data.sak = buff[dev->data.uid_len + 3]; + return true; +} + +bool nfc_device_load(NfcDevice* dev, const char* dev_name) { + furi_assert(dev); + + return true; +} + +bool nfc_file_select(NfcDevice* dev) { + furi_assert(dev); + + FileWorker* file_worker = file_worker_alloc(false); + // Input events and views are managed by file_select + bool res = file_worker_file_select( + file_worker, + nfc_app_folder, + nfc_app_extension, + dev->file_name, + sizeof(dev->file_name), + NULL); + if(res) { + string_t dev_str; + + // Get key file path + string_init_printf(dev_str, "%s/%s%s", nfc_app_folder, dev->file_name, nfc_app_extension); + + res = nfc_device_load_data(file_worker, dev_str, dev); + if(res) { + nfc_device_set_name(dev, dev->file_name); + } + string_clear(dev_str); + } + file_worker_close(file_worker); + file_worker_free(file_worker); + + return res; +} diff --git a/applications/nfc/nfc_device.h b/applications/nfc/nfc_device.h new file mode 100644 index 00000000..31147259 --- /dev/null +++ b/applications/nfc/nfc_device.h @@ -0,0 +1,55 @@ +#pragma once + +#include +#include + +#define NFC_DEV_NAME_MAX_LEN 22 +#define NFC_FILE_NAME_MAX_LEN 120 + +typedef enum { + NfcDeviceNfca, + NfcDeviceNfcb, + NfcDeviceNfcf, + NfcDeviceNfcv, +} NfcDeviceType; + +typedef enum { + NfcDeviceProtocolUnknown, + NfcDeviceProtocolEMV, + NfcDeviceProtocolMfUltralight, +} NfcProtocol; + +typedef struct { + uint8_t uid_len; + uint8_t uid[10]; + uint8_t atqa[2]; + uint8_t sak; + NfcDeviceType device; + NfcProtocol protocol; +} NfcDeviceData; + +typedef struct { + NfcDeviceData nfc_data; + char name[32]; + uint8_t number[8]; +} NfcEmvData; + +typedef struct { + NfcDeviceData nfc_data; + uint8_t man_block[12]; + uint8_t otp[4]; +} NfcMifareUlData; + +typedef struct { + NfcDeviceData data; + char dev_name[NFC_DEV_NAME_MAX_LEN]; + char file_name[NFC_FILE_NAME_MAX_LEN]; +} NfcDevice; + +void nfc_device_set_name(NfcDevice* dev, const char* name); + +bool nfc_device_save(NfcDevice* dev, const char* dev_name); + +bool nfc_device_load(NfcDevice* dev, const char* dev_name); + +bool nfc_file_select(NfcDevice* dev); diff --git a/applications/nfc/nfc_i.h b/applications/nfc/nfc_i.h index 8953792b..8d3d3e2b 100644 --- a/applications/nfc/nfc_i.h +++ b/applications/nfc/nfc_i.h @@ -3,6 +3,7 @@ #include "nfc.h" #include "nfc_types.h" #include "nfc_worker.h" +#include "nfc_device.h" #include @@ -29,6 +30,14 @@ #include "scenes/nfc_scene_card_menu.h" #include "scenes/nfc_scene_emulate_uid.h" #include "scenes/nfc_scene_not_implemented.h" +#include "scenes/nfc_scene_save_name.h" +#include "scenes/nfc_scene_save_success.h" +#include "scenes/nfc_scene_file_select.h" +#include "scenes/nfc_scene_saved_menu.h" +#include "scenes/nfc_scene_set_type.h" +#include "scenes/nfc_scene_set_sak.h" +#include "scenes/nfc_scene_set_atqa.h" +#include "scenes/nfc_scene_set_uid.h" // TODO delete debug scenes #include "scenes/nfc_scene_debug_menu.h" @@ -43,6 +52,7 @@ struct Nfc { NfcCommon nfc_common; Gui* gui; NotificationApp* notifications; + NfcDevice device; char text_store[NFC_TEXT_STORE_SIZE + 1]; @@ -66,6 +76,14 @@ struct Nfc { AppScene* scene_card_menu; AppScene* scene_not_implemented; AppScene* scene_emulate_uid; + AppScene* scene_save_name; + AppScene* scene_save_success; + AppScene* scene_file_select; + AppScene* scene_saved_menu; + AppScene* scene_set_type; + AppScene* scene_set_sak; + AppScene* scene_set_atqa; + AppScene* scene_set_uid; // TODO delete debug scenes AppScene* scene_debug_menu; @@ -99,6 +117,14 @@ typedef enum { NfcSceneDebugEmulate, NfcSceneDebugReadEmv, NfcSceneDebugReadMifareUl, + NfcSceneSaveName, + NfcSceneSaveSuccess, + NfcSceneFileSelect, + NfcSceneSavedMenu, + NfcSceneSetType, + NfcSceneSetSak, + NfcSceneSetAtqa, + NfcSceneSetUid, } NfcScene; Nfc* nfc_alloc(); diff --git a/applications/nfc/nfc_worker.h b/applications/nfc/nfc_worker.h index 87928977..d77bfd8d 100755 --- a/applications/nfc/nfc_worker.h +++ b/applications/nfc/nfc_worker.h @@ -1,38 +1,6 @@ #pragma once -typedef enum { - NfcDeviceNfca, - NfcDeviceNfcb, - NfcDeviceNfcf, - NfcDeviceNfcv, -} NfcDeviceType; - -typedef enum { - NfcDeviceProtocolUnknown, - NfcDeviceProtocolEMV, - NfcDeviceProtocolMfUltralight, -} NfcProtocol; - -typedef struct { - uint8_t uid_len; - uint8_t uid[10]; - uint8_t atqa[2]; - uint8_t sak; - NfcDeviceType device; - NfcProtocol protocol; -} NfcDeviceData; - -typedef struct { - NfcDeviceData nfc_data; - char name[32]; - uint8_t number[8]; -} NfcEmvData; - -typedef struct { - NfcDeviceData nfc_data; - uint8_t man_block[12]; - uint8_t otp[4]; -} NfcMifareUlData; +#include "nfc_device.h" typedef struct { union { diff --git a/applications/nfc/scenes/nfc_scene_card_menu.c b/applications/nfc/scenes/nfc_scene_card_menu.c index f95cc6a7..3b3e917f 100755 --- a/applications/nfc/scenes/nfc_scene_card_menu.c +++ b/applications/nfc/scenes/nfc_scene_card_menu.c @@ -5,12 +5,12 @@ #include #include -typedef enum { +enum SubmenuIndex { SubmenuIndexRunApp, SubmenuIndexChooseScript, SubmenuIndexEmulate, SubmenuIndexSave, -} SubmenuIndex; +}; void nfc_scene_card_menu_submenu_callback(void* context, uint32_t index) { Nfc* nfc = (Nfc*)context; @@ -61,7 +61,7 @@ const bool nfc_scene_card_menu_on_event(void* context, uint32_t event) { nfc->nfc_common.view_dispatcher, ViewNavigatorEventNext); return true; } else if(event == SubmenuIndexSave) { - view_dispatcher_add_scene(nfc->nfc_common.view_dispatcher, nfc->scene_not_implemented); + view_dispatcher_add_scene(nfc->nfc_common.view_dispatcher, nfc->scene_save_name); view_dispatcher_send_navigation_event( nfc->nfc_common.view_dispatcher, ViewNavigatorEventNext); return true; diff --git a/applications/nfc/scenes/nfc_scene_debug_menu.c b/applications/nfc/scenes/nfc_scene_debug_menu.c index 305953e7..73d2d187 100755 --- a/applications/nfc/scenes/nfc_scene_debug_menu.c +++ b/applications/nfc/scenes/nfc_scene_debug_menu.c @@ -5,12 +5,12 @@ #include #include -typedef enum { +enum SubmenuIndex { SubmenuIndexDetect, SubmenuIndexEmulate, SubmenuIndexReadEmv, SubmenuIndexReadMifareUl, -} SubmenuIndex; +}; void nfc_scene_debug_menu_submenu_callback(void* context, uint32_t index) { Nfc* nfc = (Nfc*)context; diff --git a/applications/nfc/scenes/nfc_scene_emulate_uid.c b/applications/nfc/scenes/nfc_scene_emulate_uid.c old mode 100755 new mode 100644 index bb0c2e9c..582d71ee --- a/applications/nfc/scenes/nfc_scene_emulate_uid.c +++ b/applications/nfc/scenes/nfc_scene_emulate_uid.c @@ -9,8 +9,11 @@ const void nfc_scene_emulate_uid_on_enter(void* context) { // Setup view Popup* popup = nfc->popup; - NfcDeviceData* data = &nfc->nfc_common.worker_result.nfc_detect_data; - if(data->uid_len == 4) { + NfcDeviceData* data = &nfc->device.data; + + if(strcmp(nfc->device.dev_name, "")) { + nfc_set_text_store(nfc, "%s", nfc->device.dev_name); + } else if(data->uid_len == 4) { nfc_set_text_store( nfc, "%02X %02X %02X %02X", data->uid[0], data->uid[1], data->uid[2], data->uid[3]); } else if(data->uid_len == 7) { @@ -31,8 +34,8 @@ const void nfc_scene_emulate_uid_on_enter(void* context) { popup_set_text(popup, nfc->text_store, 56, 43, AlignLeft, AlignTop); // Setup and start worker - nfc_worker_set_emulation_params( - nfc->nfc_common.worker, &nfc->nfc_common.worker_result.nfc_detect_data); + + nfc_worker_set_emulation_params(nfc->nfc_common.worker, data); nfc_worker_start( nfc->nfc_common.worker, NfcWorkerStateEmulate, &nfc->nfc_common.worker_result, NULL, nfc); view_dispatcher_switch_to_view(nfc->nfc_common.view_dispatcher, NfcViewPopup); diff --git a/applications/nfc/scenes/nfc_scene_file_select.c b/applications/nfc/scenes/nfc_scene_file_select.c new file mode 100755 index 00000000..d1ecad2c --- /dev/null +++ b/applications/nfc/scenes/nfc_scene_file_select.c @@ -0,0 +1,39 @@ +#include + +#include + +#include "../nfc_i.h" + +const void nfc_scene_file_select_on_enter(void* context) { + Nfc* nfc = (Nfc*)context; + // Process file_select return + if(nfc_file_select(&nfc->device)) { + view_dispatcher_add_scene(nfc->nfc_common.view_dispatcher, nfc->scene_saved_menu); + view_dispatcher_send_navigation_event( + nfc->nfc_common.view_dispatcher, ViewNavigatorEventNext); + } else { + view_dispatcher_send_back_search_scene_event( + nfc->nfc_common.view_dispatcher, NfcSceneStart); + } +} + +const bool nfc_scene_file_select_on_event(void* context, uint32_t event) { + return false; +} + +const void nfc_scene_file_select_on_exit(void* context) { +} + +AppScene* nfc_scene_file_select_alloc() { + AppScene* scene = furi_alloc(sizeof(AppScene)); + scene->id = NfcSceneFileSelect; + scene->on_enter = nfc_scene_file_select_on_enter; + scene->on_event = nfc_scene_file_select_on_event; + scene->on_exit = nfc_scene_file_select_on_exit; + + return scene; +} + +void nfc_scene_file_select_free(AppScene* scene) { + free(scene); +} diff --git a/applications/nfc/scenes/nfc_scene_file_select.h b/applications/nfc/scenes/nfc_scene_file_select.h new file mode 100644 index 00000000..58dfd0a8 --- /dev/null +++ b/applications/nfc/scenes/nfc_scene_file_select.h @@ -0,0 +1,7 @@ +#pragma once + +#include "app_scene.h" + +AppScene* nfc_scene_file_select_alloc(); + +void nfc_scene_file_select_free(AppScene* scene); diff --git a/applications/nfc/scenes/nfc_scene_read_card.c b/applications/nfc/scenes/nfc_scene_read_card.c index b7ccafaa..fab9de3d 100755 --- a/applications/nfc/scenes/nfc_scene_read_card.c +++ b/applications/nfc/scenes/nfc_scene_read_card.c @@ -34,6 +34,7 @@ const bool nfc_scene_read_card_on_event(void* context, uint32_t event) { Nfc* nfc = (Nfc*)context; if(event == NfcEventDetect) { + nfc->device.data = nfc->nfc_common.worker_result.nfc_detect_data; view_dispatcher_add_scene(nfc->nfc_common.view_dispatcher, nfc->scene_read_card_success); view_dispatcher_send_navigation_event( nfc->nfc_common.view_dispatcher, ViewNavigatorEventNext); diff --git a/applications/nfc/scenes/nfc_scene_read_card_success.c b/applications/nfc/scenes/nfc_scene_read_card_success.c index ea472cb9..816ccc42 100755 --- a/applications/nfc/scenes/nfc_scene_read_card_success.c +++ b/applications/nfc/scenes/nfc_scene_read_card_success.c @@ -16,6 +16,9 @@ void nfc_scene_read_card_success_dialog_callback(DialogExResult result, void* co const void nfc_scene_read_card_success_on_enter(void* context) { Nfc* nfc = (Nfc*)context; + // Clear device name + nfc_device_set_name(&nfc->device, ""); + // Send notification notification_message(nfc->notifications, &sequence_success); diff --git a/applications/nfc/scenes/nfc_scene_save_name.c b/applications/nfc/scenes/nfc_scene_save_name.c new file mode 100755 index 00000000..ba2ad1ec --- /dev/null +++ b/applications/nfc/scenes/nfc_scene_save_name.c @@ -0,0 +1,72 @@ +#include + +#include + +#include "../nfc_i.h" +#include "../views/nfc_detect.h" + +#include + +#define SCENE_SAVE_NAME_CUSTOM_EVENT (0UL) + +void nfc_scene_save_name_text_input_callback(void* context) { + Nfc* nfc = (Nfc*)context; + + view_dispatcher_send_custom_event( + nfc->nfc_common.view_dispatcher, SCENE_SAVE_NAME_CUSTOM_EVENT); +} + +const void nfc_scene_save_name_on_enter(void* context) { + Nfc* nfc = (Nfc*)context; + + // Setup view + TextInput* text_input = nfc->text_input; + nfc_set_text_store(nfc, ""); + text_input_set_header_text(text_input, "Name the card"); + text_input_set_result_callback( + text_input, + nfc_scene_save_name_text_input_callback, + nfc, + nfc->text_store, + sizeof(nfc->text_store)); + view_dispatcher_switch_to_view(nfc->nfc_common.view_dispatcher, NfcViewTextInput); +} + +const bool nfc_scene_save_name_on_event(void* context, uint32_t event) { + Nfc* nfc = (Nfc*)context; + + if(event == SCENE_SAVE_NAME_CUSTOM_EVENT) { + memcpy(&nfc->device.dev_name, nfc->text_store, strlen(nfc->text_store)); + if(nfc_device_save(&nfc->device, "test")) { + view_dispatcher_add_scene(nfc->nfc_common.view_dispatcher, nfc->scene_save_success); + view_dispatcher_send_navigation_event( + nfc->nfc_common.view_dispatcher, ViewNavigatorEventNext); + } else { + view_dispatcher_send_back_search_scene_event( + nfc->nfc_common.view_dispatcher, NfcSceneStart); + } + return true; + } + return false; +} + +const void nfc_scene_save_name_on_exit(void* context) { + Nfc* nfc = (Nfc*)context; + + // Clear view + text_input_set_header_text(nfc->text_input, NULL); +} + +AppScene* nfc_scene_save_name_alloc() { + AppScene* scene = furi_alloc(sizeof(AppScene)); + scene->id = NfcSceneSaveName; + scene->on_enter = nfc_scene_save_name_on_enter; + scene->on_event = nfc_scene_save_name_on_event; + scene->on_exit = nfc_scene_save_name_on_exit; + + return scene; +} + +void nfc_scene_save_name_free(AppScene* scene) { + free(scene); +} diff --git a/applications/nfc/scenes/nfc_scene_save_name.h b/applications/nfc/scenes/nfc_scene_save_name.h new file mode 100644 index 00000000..880dc0ad --- /dev/null +++ b/applications/nfc/scenes/nfc_scene_save_name.h @@ -0,0 +1,7 @@ +#pragma once + +#include "app_scene.h" + +AppScene* nfc_scene_save_name_alloc(); + +void nfc_scene_save_name_free(AppScene* scene); diff --git a/applications/nfc/scenes/nfc_scene_save_success.c b/applications/nfc/scenes/nfc_scene_save_success.c new file mode 100755 index 00000000..fe9a7962 --- /dev/null +++ b/applications/nfc/scenes/nfc_scene_save_success.c @@ -0,0 +1,66 @@ +#include + +#include + +#include "../nfc_i.h" + +#define SCENE_SAVE_SUCCESS_CUSTOM_EVENT (0UL) + +void nfc_scene_save_success_popup_callback(void* context) { + Nfc* nfc = (Nfc*)context; + view_dispatcher_send_custom_event( + nfc->nfc_common.view_dispatcher, SCENE_SAVE_SUCCESS_CUSTOM_EVENT); +} + +const void nfc_scene_save_success_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, "Saved!", 13, 22, AlignLeft, AlignBottom); + popup_set_timeout(popup, 1500); + popup_set_context(popup, nfc); + popup_set_callback(popup, nfc_scene_save_success_popup_callback); + popup_enable_timeout(popup); + view_dispatcher_switch_to_view(nfc->nfc_common.view_dispatcher, NfcViewPopup); +} + +const bool nfc_scene_save_success_on_event(void* context, uint32_t event) { + Nfc* nfc = (Nfc*)context; + + if(event == SCENE_SAVE_SUCCESS_CUSTOM_EVENT) { + view_dispatcher_send_back_search_scene_event( + nfc->nfc_common.view_dispatcher, NfcSceneStart); + return true; + } + return false; +} + +const void nfc_scene_save_success_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, I_Empty_1x1); + popup_set_callback(popup, NULL); + popup_set_context(popup, NULL); + popup_set_timeout(popup, 0); + popup_disable_timeout(popup); +} + +AppScene* nfc_scene_save_success_alloc() { + AppScene* scene = furi_alloc(sizeof(AppScene)); + scene->id = NfcSceneSaveSuccess; + scene->on_enter = nfc_scene_save_success_on_enter; + scene->on_event = nfc_scene_save_success_on_event; + scene->on_exit = nfc_scene_save_success_on_exit; + + return scene; +} + +void nfc_scene_save_success_free(AppScene* scene) { + free(scene); +} diff --git a/applications/nfc/scenes/nfc_scene_save_success.h b/applications/nfc/scenes/nfc_scene_save_success.h new file mode 100644 index 00000000..46f7d13d --- /dev/null +++ b/applications/nfc/scenes/nfc_scene_save_success.h @@ -0,0 +1,7 @@ +#pragma once + +#include "app_scene.h" + +AppScene* nfc_scene_save_success_alloc(); + +void nfc_scene_save_success_free(AppScene* scene); diff --git a/applications/nfc/scenes/nfc_scene_saved_menu.c b/applications/nfc/scenes/nfc_scene_saved_menu.c new file mode 100755 index 00000000..44ba55f7 --- /dev/null +++ b/applications/nfc/scenes/nfc_scene_saved_menu.c @@ -0,0 +1,83 @@ +#include "nfc_scene_saved_menu.h" +#include "../nfc_i.h" + +#include +#include +#include + +enum SubmenuIndex { + SubmenuIndexEmulate, + SubmenuIndexEdit, + SubmenuIndexDelete, + SubmenuIndexInfo, +}; + +void nfc_scene_saved_menu_submenu_callback(void* context, uint32_t index) { + Nfc* nfc = (Nfc*)context; + + view_dispatcher_send_custom_event(nfc->nfc_common.view_dispatcher, index); +} + +const void nfc_scene_saved_menu_on_enter(void* context) { + Nfc* nfc = (Nfc*)context; + Submenu* submenu = nfc->submenu; + + submenu_add_item( + submenu, "Emulate", SubmenuIndexEmulate, nfc_scene_saved_menu_submenu_callback, nfc); + submenu_add_item( + submenu, "Edit UID and name", SubmenuIndexEdit, nfc_scene_saved_menu_submenu_callback, nfc); + submenu_add_item( + submenu, "Delete", SubmenuIndexDelete, nfc_scene_saved_menu_submenu_callback, nfc); + submenu_add_item( + submenu, "Info", SubmenuIndexInfo, nfc_scene_saved_menu_submenu_callback, nfc); + + view_dispatcher_switch_to_view(nfc->nfc_common.view_dispatcher, NfcViewMenu); +} + +const bool nfc_scene_saved_menu_on_event(void* context, uint32_t event) { + Nfc* nfc = (Nfc*)context; + + if(event == SubmenuIndexEmulate) { + view_dispatcher_add_scene(nfc->nfc_common.view_dispatcher, nfc->scene_emulate_uid); + view_dispatcher_send_navigation_event( + nfc->nfc_common.view_dispatcher, ViewNavigatorEventNext); + return true; + } else if(event == SubmenuIndexEdit) { + view_dispatcher_add_scene(nfc->nfc_common.view_dispatcher, nfc->scene_not_implemented); + view_dispatcher_send_navigation_event( + nfc->nfc_common.view_dispatcher, ViewNavigatorEventNext); + return true; + } else if(event == SubmenuIndexDelete) { + view_dispatcher_add_scene(nfc->nfc_common.view_dispatcher, nfc->scene_not_implemented); + view_dispatcher_send_navigation_event( + nfc->nfc_common.view_dispatcher, ViewNavigatorEventNext); + return true; + } else if(event == SubmenuIndexInfo) { + view_dispatcher_add_scene(nfc->nfc_common.view_dispatcher, nfc->scene_not_implemented); + view_dispatcher_send_navigation_event( + nfc->nfc_common.view_dispatcher, ViewNavigatorEventNext); + return true; + } + + return false; +} + +const void nfc_scene_saved_menu_on_exit(void* context) { + Nfc* nfc = (Nfc*)context; + + submenu_clean(nfc->submenu); +} + +AppScene* nfc_scene_saved_menu_alloc() { + AppScene* scene = furi_alloc(sizeof(AppScene)); + scene->id = NfcSceneSavedMenu; + scene->on_enter = nfc_scene_saved_menu_on_enter; + scene->on_event = nfc_scene_saved_menu_on_event; + scene->on_exit = nfc_scene_saved_menu_on_exit; + + return scene; +} + +void nfc_scene_saved_menu_free(AppScene* scene) { + free(scene); +} diff --git a/applications/nfc/scenes/nfc_scene_saved_menu.h b/applications/nfc/scenes/nfc_scene_saved_menu.h new file mode 100644 index 00000000..111fa372 --- /dev/null +++ b/applications/nfc/scenes/nfc_scene_saved_menu.h @@ -0,0 +1,7 @@ +#pragma once + +#include "app_scene.h" + +AppScene* nfc_scene_saved_menu_alloc(); + +void nfc_scene_saved_menu_free(AppScene* scene); diff --git a/applications/nfc/scenes/nfc_scene_set_atqa.c b/applications/nfc/scenes/nfc_scene_set_atqa.c new file mode 100755 index 00000000..ee199eff --- /dev/null +++ b/applications/nfc/scenes/nfc_scene_set_atqa.c @@ -0,0 +1,61 @@ +#include + +#include + +#include "../nfc_i.h" + +#include + +#define SCENE_SET_ATQA_CUSTOM_EVENT (0UL) + +void nfc_scene_set_atqa_byte_input_callback(void* context, uint8_t* bytes, uint8_t bytes_count) { + Nfc* nfc = (Nfc*)context; + + view_dispatcher_send_custom_event( + nfc->nfc_common.view_dispatcher, SCENE_SET_ATQA_CUSTOM_EVENT); +} + +const void nfc_scene_set_atqa_on_enter(void* context) { + Nfc* nfc = (Nfc*)context; + + // Setup view + ByteInput* byte_input = nfc->byte_input; + byte_input_set_header_text(byte_input, "Enter atqa in hex"); + byte_input_set_result_callback( + byte_input, nfc_scene_set_atqa_byte_input_callback, NULL, nfc, nfc->device.data.atqa, 2); + view_dispatcher_switch_to_view(nfc->nfc_common.view_dispatcher, NfcViewByteInput); +} + +const bool nfc_scene_set_atqa_on_event(void* context, uint32_t event) { + Nfc* nfc = (Nfc*)context; + + if(event == SCENE_SET_ATQA_CUSTOM_EVENT) { + view_dispatcher_add_scene(nfc->nfc_common.view_dispatcher, nfc->scene_set_uid); + view_dispatcher_send_navigation_event( + nfc->nfc_common.view_dispatcher, ViewNavigatorEventNext); + return true; + } + return false; +} + +const void nfc_scene_set_atqa_on_exit(void* context) { + Nfc* nfc = (Nfc*)context; + + // Clear view + byte_input_set_result_callback(nfc->byte_input, NULL, NULL, NULL, NULL, 0); + byte_input_set_header_text(nfc->byte_input, ""); +} + +AppScene* nfc_scene_set_atqa_alloc() { + AppScene* scene = furi_alloc(sizeof(AppScene)); + scene->id = NfcSceneSetAtqa; + scene->on_enter = nfc_scene_set_atqa_on_enter; + scene->on_event = nfc_scene_set_atqa_on_event; + scene->on_exit = nfc_scene_set_atqa_on_exit; + + return scene; +} + +void nfc_scene_set_atqa_free(AppScene* scene) { + free(scene); +} diff --git a/applications/nfc/scenes/nfc_scene_set_atqa.h b/applications/nfc/scenes/nfc_scene_set_atqa.h new file mode 100644 index 00000000..a732e270 --- /dev/null +++ b/applications/nfc/scenes/nfc_scene_set_atqa.h @@ -0,0 +1,7 @@ +#pragma once + +#include "app_scene.h" + +AppScene* nfc_scene_set_atqa_alloc(); + +void nfc_scene_set_atqa_free(AppScene* scene); diff --git a/applications/nfc/scenes/nfc_scene_set_sak.c b/applications/nfc/scenes/nfc_scene_set_sak.c new file mode 100755 index 00000000..16db6517 --- /dev/null +++ b/applications/nfc/scenes/nfc_scene_set_sak.c @@ -0,0 +1,60 @@ +#include + +#include + +#include "../nfc_i.h" + +#include + +#define SCENE_SET_SAK_CUSTOM_EVENT (0UL) + +void nfc_scene_set_sak_byte_input_callback(void* context, uint8_t* bytes, uint8_t bytes_count) { + Nfc* nfc = (Nfc*)context; + + view_dispatcher_send_custom_event(nfc->nfc_common.view_dispatcher, SCENE_SET_SAK_CUSTOM_EVENT); +} + +const void nfc_scene_set_sak_on_enter(void* context) { + Nfc* nfc = (Nfc*)context; + + // Setup view + ByteInput* byte_input = nfc->byte_input; + byte_input_set_header_text(byte_input, "Enter SAK in hex"); + byte_input_set_result_callback( + byte_input, nfc_scene_set_sak_byte_input_callback, NULL, nfc, &nfc->device.data.sak, 1); + view_dispatcher_switch_to_view(nfc->nfc_common.view_dispatcher, NfcViewByteInput); +} + +const bool nfc_scene_set_sak_on_event(void* context, uint32_t event) { + Nfc* nfc = (Nfc*)context; + + if(event == SCENE_SET_SAK_CUSTOM_EVENT) { + view_dispatcher_add_scene(nfc->nfc_common.view_dispatcher, nfc->scene_set_atqa); + view_dispatcher_send_navigation_event( + nfc->nfc_common.view_dispatcher, ViewNavigatorEventNext); + return true; + } + return false; +} + +const void nfc_scene_set_sak_on_exit(void* context) { + Nfc* nfc = (Nfc*)context; + + // Clear view + byte_input_set_result_callback(nfc->byte_input, NULL, NULL, NULL, NULL, 0); + byte_input_set_header_text(nfc->byte_input, ""); +} + +AppScene* nfc_scene_set_sak_alloc() { + AppScene* scene = furi_alloc(sizeof(AppScene)); + scene->id = NfcSceneSetSak; + scene->on_enter = nfc_scene_set_sak_on_enter; + scene->on_event = nfc_scene_set_sak_on_event; + scene->on_exit = nfc_scene_set_sak_on_exit; + + return scene; +} + +void nfc_scene_set_sak_free(AppScene* scene) { + free(scene); +} diff --git a/applications/nfc/scenes/nfc_scene_set_sak.h b/applications/nfc/scenes/nfc_scene_set_sak.h new file mode 100644 index 00000000..706ecb56 --- /dev/null +++ b/applications/nfc/scenes/nfc_scene_set_sak.h @@ -0,0 +1,7 @@ +#pragma once + +#include "app_scene.h" + +AppScene* nfc_scene_set_sak_alloc(); + +void nfc_scene_set_sak_free(AppScene* scene); diff --git a/applications/nfc/scenes/nfc_scene_set_type.c b/applications/nfc/scenes/nfc_scene_set_type.c new file mode 100755 index 00000000..de767b7f --- /dev/null +++ b/applications/nfc/scenes/nfc_scene_set_type.c @@ -0,0 +1,67 @@ +#include "nfc_scene_set_type.h" +#include "../nfc_i.h" + +#include +#include +#include + +enum SubmenuIndex { + SubmenuIndexNFCA4, + SubmenuIndexNFCA7, +}; + +void nfc_scene_set_type_submenu_callback(void* context, uint32_t index) { + Nfc* nfc = (Nfc*)context; + + view_dispatcher_send_custom_event(nfc->nfc_common.view_dispatcher, index); +} + +const void nfc_scene_set_type_on_enter(void* context) { + Nfc* nfc = (Nfc*)context; + Submenu* submenu = nfc->submenu; + + submenu_add_item( + submenu, "NFC-A 7-bytes UID", SubmenuIndexNFCA7, nfc_scene_set_type_submenu_callback, nfc); + submenu_add_item( + submenu, "NFC-A 4-bytes UID", SubmenuIndexNFCA4, nfc_scene_set_type_submenu_callback, nfc); + view_dispatcher_switch_to_view(nfc->nfc_common.view_dispatcher, NfcViewMenu); +} + +const bool nfc_scene_set_type_on_event(void* context, uint32_t event) { + Nfc* nfc = (Nfc*)context; + + if(event == SubmenuIndexNFCA7) { + nfc->device.data.uid_len = 7; + view_dispatcher_add_scene(nfc->nfc_common.view_dispatcher, nfc->scene_set_sak); + view_dispatcher_send_navigation_event( + nfc->nfc_common.view_dispatcher, ViewNavigatorEventNext); + return true; + } else if(event == SubmenuIndexNFCA4) { + nfc->device.data.uid_len = 4; + view_dispatcher_add_scene(nfc->nfc_common.view_dispatcher, nfc->scene_set_sak); + view_dispatcher_send_navigation_event( + nfc->nfc_common.view_dispatcher, ViewNavigatorEventNext); + return true; + } + return false; +} + +const void nfc_scene_set_type_on_exit(void* context) { + Nfc* nfc = (Nfc*)context; + + submenu_clean(nfc->submenu); +} + +AppScene* nfc_scene_set_type_alloc() { + AppScene* scene = furi_alloc(sizeof(AppScene)); + scene->id = NfcSceneSetType; + scene->on_enter = nfc_scene_set_type_on_enter; + scene->on_event = nfc_scene_set_type_on_event; + scene->on_exit = nfc_scene_set_type_on_exit; + + return scene; +} + +void nfc_scene_set_type_free(AppScene* scene) { + free(scene); +} \ No newline at end of file diff --git a/applications/nfc/scenes/nfc_scene_set_type.h b/applications/nfc/scenes/nfc_scene_set_type.h new file mode 100644 index 00000000..a6f586ef --- /dev/null +++ b/applications/nfc/scenes/nfc_scene_set_type.h @@ -0,0 +1,7 @@ +#pragma once + +#include "app_scene.h" + +AppScene* nfc_scene_set_type_alloc(); + +void nfc_scene_set_type_free(AppScene* scene); diff --git a/applications/nfc/scenes/nfc_scene_set_uid.c b/applications/nfc/scenes/nfc_scene_set_uid.c new file mode 100755 index 00000000..74d013ea --- /dev/null +++ b/applications/nfc/scenes/nfc_scene_set_uid.c @@ -0,0 +1,65 @@ +#include + +#include + +#include "../nfc_i.h" + +#include + +#define SCENE_SET_UID_CUSTOM_EVENT (0UL) + +void nfc_scene_set_uid_byte_input_callback(void* context, uint8_t* bytes, uint8_t bytes_count) { + Nfc* nfc = (Nfc*)context; + + view_dispatcher_send_custom_event(nfc->nfc_common.view_dispatcher, SCENE_SET_UID_CUSTOM_EVENT); +} + +const void nfc_scene_set_uid_on_enter(void* context) { + Nfc* nfc = (Nfc*)context; + + // Setup view + ByteInput* byte_input = nfc->byte_input; + byte_input_set_header_text(byte_input, "Enter uid in hex"); + byte_input_set_result_callback( + byte_input, + nfc_scene_set_uid_byte_input_callback, + NULL, + nfc, + nfc->device.data.uid, + nfc->device.data.uid_len); + view_dispatcher_switch_to_view(nfc->nfc_common.view_dispatcher, NfcViewByteInput); +} + +const bool nfc_scene_set_uid_on_event(void* context, uint32_t event) { + Nfc* nfc = (Nfc*)context; + + if(event == SCENE_SET_UID_CUSTOM_EVENT) { + view_dispatcher_add_scene(nfc->nfc_common.view_dispatcher, nfc->scene_save_name); + view_dispatcher_send_navigation_event( + nfc->nfc_common.view_dispatcher, ViewNavigatorEventNext); + return true; + } + return false; +} + +const void nfc_scene_set_uid_on_exit(void* context) { + Nfc* nfc = (Nfc*)context; + + // Clear view + byte_input_set_result_callback(nfc->byte_input, NULL, NULL, NULL, NULL, 0); + byte_input_set_header_text(nfc->byte_input, ""); +} + +AppScene* nfc_scene_set_uid_alloc() { + AppScene* scene = furi_alloc(sizeof(AppScene)); + scene->id = NfcSceneSetUid; + scene->on_enter = nfc_scene_set_uid_on_enter; + scene->on_event = nfc_scene_set_uid_on_event; + scene->on_exit = nfc_scene_set_uid_on_exit; + + return scene; +} + +void nfc_scene_set_uid_free(AppScene* scene) { + free(scene); +} diff --git a/applications/nfc/scenes/nfc_scene_set_uid.h b/applications/nfc/scenes/nfc_scene_set_uid.h new file mode 100644 index 00000000..1afe2272 --- /dev/null +++ b/applications/nfc/scenes/nfc_scene_set_uid.h @@ -0,0 +1,7 @@ +#pragma once + +#include "app_scene.h" + +AppScene* nfc_scene_set_uid_alloc(); + +void nfc_scene_set_uid_free(AppScene* scene); diff --git a/applications/nfc/scenes/nfc_scene_start.c b/applications/nfc/scenes/nfc_scene_start.c index db85e677..15c59266 100644 --- a/applications/nfc/scenes/nfc_scene_start.c +++ b/applications/nfc/scenes/nfc_scene_start.c @@ -5,13 +5,13 @@ #include #include -typedef enum { +enum SubmenuIndex { SubmenuIndexRead, SubmenuIndexRunScript, SubmenuIndexSaved, SubmenuIndexAddManualy, SubmenuIndexDebug, -} SubmenuIndex; +}; void nfc_scene_start_submenu_callback(void* context, uint32_t index) { Nfc* nfc = (Nfc*)context; @@ -34,7 +34,7 @@ const void nfc_scene_start_on_enter(void* context) { submenu_add_item( submenu, "Saved cards", SubmenuIndexSaved, nfc_scene_start_submenu_callback, nfc); submenu_add_item( - submenu, "Add manualy", SubmenuIndexAddManualy, nfc_scene_start_submenu_callback, nfc); + submenu, "Add manually", SubmenuIndexAddManualy, nfc_scene_start_submenu_callback, nfc); submenu_add_item(submenu, "Debug", SubmenuIndexDebug, nfc_scene_start_submenu_callback, nfc); view_dispatcher_switch_to_view(nfc->nfc_common.view_dispatcher, NfcViewMenu); @@ -54,12 +54,12 @@ const bool nfc_scene_start_on_event(void* context, uint32_t event) { nfc->nfc_common.view_dispatcher, ViewNavigatorEventNext); return true; } else if(event == SubmenuIndexSaved) { - view_dispatcher_add_scene(nfc->nfc_common.view_dispatcher, nfc->scene_not_implemented); + view_dispatcher_add_scene(nfc->nfc_common.view_dispatcher, nfc->scene_file_select); view_dispatcher_send_navigation_event( nfc->nfc_common.view_dispatcher, ViewNavigatorEventNext); return true; } else if(event == SubmenuIndexAddManualy) { - view_dispatcher_add_scene(nfc->nfc_common.view_dispatcher, nfc->scene_not_implemented); + view_dispatcher_add_scene(nfc->nfc_common.view_dispatcher, nfc->scene_set_type); view_dispatcher_send_navigation_event( nfc->nfc_common.view_dispatcher, ViewNavigatorEventNext); return true;