Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/ClusterM/flipperzero-firmware.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorgornekich <n.gorbadey@gmail.com>2021-07-08 23:41:34 +0300
committerGitHub <noreply@github.com>2021-07-08 23:41:34 +0300
commit20fe544b4f53e637667a17d25c3e4190405aefc9 (patch)
treed4d5fb6b97fe058263cd71d7f8d1b40039ac25b9 /applications/nfc
parent9f6e14d0054671135ce4319d001e9397ffeb3c3a (diff)
[FL-1501] NFC: read Mifare Ultralight (#571)
* nfc: add scripts menu scene * canvas: add glyph width api * app_scene: add state to Scene template * gui: introduce TextBox view * nfc: add mifare ultralight read scenes * nfc: add mifare ultralight menu scene * nfc: fix scene functions declaration * Gui: use size_t for sizes. Co-authored-by: あく <alleteam@gmail.com>
Diffstat (limited to 'applications/nfc')
-rwxr-xr-xapplications/nfc/nfc.c19
-rw-r--r--applications/nfc/nfc_device.h5
-rwxr-xr-x[-rw-r--r--]applications/nfc/nfc_i.h16
-rwxr-xr-xapplications/nfc/nfc_worker.c5
-rwxr-xr-xapplications/nfc/scenes/nfc_scene_mifare_ul_menu.c69
-rw-r--r--applications/nfc/scenes/nfc_scene_mifare_ul_menu.h7
-rwxr-xr-xapplications/nfc/scenes/nfc_scene_read_mifare_ul.c67
-rw-r--r--applications/nfc/scenes/nfc_scene_read_mifare_ul.h7
-rwxr-xr-xapplications/nfc/scenes/nfc_scene_read_mifare_ul_success.c152
-rw-r--r--applications/nfc/scenes/nfc_scene_read_mifare_ul_success.h7
-rwxr-xr-xapplications/nfc/scenes/nfc_scene_scripts_menu.c75
-rw-r--r--applications/nfc/scenes/nfc_scene_scripts_menu.h7
-rw-r--r--applications/nfc/scenes/nfc_scene_start.c2
13 files changed, 436 insertions, 2 deletions
diff --git a/applications/nfc/nfc.c b/applications/nfc/nfc.c
index f41d6386..6bee68c2 100755
--- a/applications/nfc/nfc.c
+++ b/applications/nfc/nfc.c
@@ -43,6 +43,12 @@ Nfc* nfc_alloc() {
view_dispatcher_add_view(
nfc->nfc_common.view_dispatcher, NfcViewByteInput, byte_input_get_view(nfc->byte_input));
+ // TextBox
+ nfc->text_box = text_box_alloc();
+ view_dispatcher_add_view(
+ nfc->nfc_common.view_dispatcher, NfcViewTextBox, text_box_get_view(nfc->text_box));
+ string_init(nfc->text_box_store);
+
// Detect
nfc->nfc_detect = nfc_detect_alloc(&nfc->nfc_common);
view_dispatcher_add_view(
@@ -85,6 +91,10 @@ Nfc* nfc_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();
+ nfc->scene_scripts_menu = nfc_scene_scripts_menu_alloc();
+ nfc->scene_read_mifare_ul = nfc_scene_read_mifare_ul_alloc();
+ nfc->scene_read_mifare_ul_success = nfc_scene_read_mifare_ul_success_alloc();
+ nfc->scene_mifare_ul_menu = nfc_scene_mifare_ul_menu_alloc();
view_dispatcher_add_scene(nfc->nfc_common.view_dispatcher, nfc->scene_start);
@@ -114,6 +124,11 @@ void nfc_free(Nfc* nfc) {
view_dispatcher_remove_view(nfc->nfc_common.view_dispatcher, NfcViewByteInput);
byte_input_free(nfc->byte_input);
+ // TextBox
+ view_dispatcher_remove_view(nfc->nfc_common.view_dispatcher, NfcViewTextBox);
+ text_box_free(nfc->text_box);
+ string_clear(nfc->text_box_store);
+
// Detect
view_dispatcher_remove_view(nfc->nfc_common.view_dispatcher, NfcViewDetect);
nfc_detect_free(nfc->nfc_detect);
@@ -154,6 +169,10 @@ void nfc_free(Nfc* nfc) {
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);
+ nfc_scene_scripts_menu_free(nfc->scene_scripts_menu);
+ nfc_scene_read_mifare_ul_free(nfc->scene_read_mifare_ul);
+ nfc_scene_read_mifare_ul_success_free(nfc->scene_read_mifare_ul_success);
+ nfc_scene_mifare_ul_menu_free(nfc->scene_mifare_ul_menu);
// View Dispatcher
view_dispatcher_free(nfc->nfc_common.view_dispatcher);
diff --git a/applications/nfc/nfc_device.h b/applications/nfc/nfc_device.h
index 31147259..ac922320 100644
--- a/applications/nfc/nfc_device.h
+++ b/applications/nfc/nfc_device.h
@@ -6,6 +6,8 @@
#define NFC_DEV_NAME_MAX_LEN 22
#define NFC_FILE_NAME_MAX_LEN 120
+#define NFC_MIFARE_UL_MAX_SIZE 256
+
typedef enum {
NfcDeviceNfca,
NfcDeviceNfcb,
@@ -36,6 +38,9 @@ typedef struct {
typedef struct {
NfcDeviceData nfc_data;
+ uint8_t full_dump[NFC_MIFARE_UL_MAX_SIZE];
+ uint16_t dump_size;
+ // TODO delete with debug view
uint8_t man_block[12];
uint8_t otp[4];
} NfcMifareUlData;
diff --git a/applications/nfc/nfc_i.h b/applications/nfc/nfc_i.h
index 8d3d3e2b..861dde63 100644..100755
--- a/applications/nfc/nfc_i.h
+++ b/applications/nfc/nfc_i.h
@@ -18,6 +18,7 @@
#include <gui/modules/popup.h>
#include <gui/modules/text_input.h>
#include <gui/modules/byte_input.h>
+#include <gui/modules/text_box.h>
#include "views/nfc_detect.h"
#include "views/nfc_emulate.h"
@@ -38,6 +39,10 @@
#include "scenes/nfc_scene_set_sak.h"
#include "scenes/nfc_scene_set_atqa.h"
#include "scenes/nfc_scene_set_uid.h"
+#include "scenes/nfc_scene_scripts_menu.h"
+#include "scenes/nfc_scene_read_mifare_ul.h"
+#include "scenes/nfc_scene_read_mifare_ul_success.h"
+#include "scenes/nfc_scene_mifare_ul_menu.h"
// TODO delete debug scenes
#include "scenes/nfc_scene_debug_menu.h"
@@ -55,6 +60,7 @@ struct Nfc {
NfcDevice device;
char text_store[NFC_TEXT_STORE_SIZE + 1];
+ string_t text_box_store;
// Nfc Views
NfcDetect* nfc_detect;
@@ -68,6 +74,7 @@ struct Nfc {
Popup* popup;
TextInput* text_input;
ByteInput* byte_input;
+ TextBox* text_box;
// Scenes
AppScene* scene_start;
@@ -84,6 +91,10 @@ struct Nfc {
AppScene* scene_set_sak;
AppScene* scene_set_atqa;
AppScene* scene_set_uid;
+ AppScene* scene_scripts_menu;
+ AppScene* scene_read_mifare_ul;
+ AppScene* scene_read_mifare_ul_success;
+ AppScene* scene_mifare_ul_menu;
// TODO delete debug scenes
AppScene* scene_debug_menu;
@@ -99,6 +110,7 @@ typedef enum {
NfcViewPopup,
NfcViewTextInput,
NfcViewByteInput,
+ NfcViewTextBox,
NfcViewDetect,
NfcViewEmulate,
NfcViewEmv,
@@ -125,6 +137,10 @@ typedef enum {
NfcSceneSetSak,
NfcSceneSetAtqa,
NfcSceneSetUid,
+ NfcSceneScriptsMenu,
+ NfcSceneReadMifareUl,
+ NfcSceneReadMifareUlSuccess,
+ NfcSceneReadMifareUlMenu,
} NfcScene;
Nfc* nfc_alloc();
diff --git a/applications/nfc/nfc_worker.c b/applications/nfc/nfc_worker.c
index 18e0337a..b23caccc 100755
--- a/applications/nfc/nfc_worker.c
+++ b/applications/nfc/nfc_worker.c
@@ -383,7 +383,7 @@ void nfc_worker_read_mf_ultralight(NfcWorker* nfc_worker) {
mf_ul_set_default_version(&mf_ul_read);
// Reinit device
api_hal_nfc_deactivate();
- if(!api_hal_nfc_detect(&dev_list, &dev_cnt, 1000, false)) {
+ if(!api_hal_nfc_detect(&dev_list, &dev_cnt, 300, false)) {
FURI_LOG_E(NFC_WORKER_TAG, "Lost connection. Restarting search");
continue;
}
@@ -439,6 +439,9 @@ void nfc_worker_read_mf_ultralight(NfcWorker* nfc_worker) {
result->nfc_data.uid, dev_list[0].dev.nfca.nfcId1, result->nfc_data.uid_len);
memcpy(result->man_block, mf_ul_read.dump, 4 * 3);
memcpy(result->otp, &mf_ul_read.dump[4 * 3], 4);
+ result->dump_size = mf_ul_read.pages_readed * 4;
+ memcpy(result->full_dump, mf_ul_read.dump, result->dump_size);
+
for(uint8_t i = 0; i < mf_ul_read.pages_readed * 4; i += 4) {
printf("Page %2d: ", i / 4);
for(uint8_t j = 0; j < 4; j++) {
diff --git a/applications/nfc/scenes/nfc_scene_mifare_ul_menu.c b/applications/nfc/scenes/nfc_scene_mifare_ul_menu.c
new file mode 100755
index 00000000..298833ec
--- /dev/null
+++ b/applications/nfc/scenes/nfc_scene_mifare_ul_menu.c
@@ -0,0 +1,69 @@
+#include "nfc_scene_mifare_ul_menu.h"
+#include "../nfc_i.h"
+
+#include <furi.h>
+
+enum SubmenuIndex {
+ SubmenuIndexSave,
+ SubmenuIndexEmulate,
+};
+
+void nfc_scene_mifare_ul_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_mifare_ul_menu_on_enter(void* context) {
+ Nfc* nfc = (Nfc*)context;
+ Submenu* submenu = nfc->submenu;
+
+ submenu_add_item(
+ submenu, "Name and save", SubmenuIndexSave, nfc_scene_mifare_ul_menu_submenu_callback, nfc);
+ submenu_add_item(
+ submenu, "Emulate", SubmenuIndexEmulate, nfc_scene_mifare_ul_menu_submenu_callback, nfc);
+
+ view_dispatcher_switch_to_view(nfc->nfc_common.view_dispatcher, NfcViewMenu);
+}
+
+const bool nfc_scene_mifare_ul_menu_on_event(void* context, uint32_t event) {
+ Nfc* nfc = (Nfc*)context;
+
+ if(event == SubmenuIndexSave) {
+ 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 == SubmenuIndexEmulate) {
+ 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 == ViewNavigatorEventBack) {
+ view_dispatcher_send_back_search_scene_event(
+ nfc->nfc_common.view_dispatcher, NfcSceneStart);
+ return true;
+ }
+
+ return false;
+}
+
+const void nfc_scene_mifare_ul_menu_on_exit(void* context) {
+ Nfc* nfc = (Nfc*)context;
+
+ submenu_clean(nfc->submenu);
+}
+
+AppScene* nfc_scene_mifare_ul_menu_alloc() {
+ AppScene* scene = furi_alloc(sizeof(AppScene));
+ scene->id = NfcSceneReadMifareUlMenu;
+ scene->on_enter = nfc_scene_mifare_ul_menu_on_enter;
+ scene->on_event = nfc_scene_mifare_ul_menu_on_event;
+ scene->on_exit = nfc_scene_mifare_ul_menu_on_exit;
+
+ return scene;
+}
+
+void nfc_scene_mifare_ul_menu_free(AppScene* scene) {
+ free(scene);
+} \ No newline at end of file
diff --git a/applications/nfc/scenes/nfc_scene_mifare_ul_menu.h b/applications/nfc/scenes/nfc_scene_mifare_ul_menu.h
new file mode 100644
index 00000000..d757eeb8
--- /dev/null
+++ b/applications/nfc/scenes/nfc_scene_mifare_ul_menu.h
@@ -0,0 +1,7 @@
+#pragma once
+
+#include "app_scene.h"
+
+AppScene* nfc_scene_mifare_ul_menu_alloc();
+
+void nfc_scene_mifare_ul_menu_free(AppScene* scene);
diff --git a/applications/nfc/scenes/nfc_scene_read_mifare_ul.c b/applications/nfc/scenes/nfc_scene_read_mifare_ul.c
new file mode 100755
index 00000000..58763114
--- /dev/null
+++ b/applications/nfc/scenes/nfc_scene_read_mifare_ul.c
@@ -0,0 +1,67 @@
+#include <nfc/scenes/nfc_scene_read_mifare_ul.h>
+#include <furi.h>
+#include "../nfc_i.h"
+
+void nfc_read_mifare_ul_worker_callback(void* context) {
+ Nfc* nfc = (Nfc*)context;
+ view_dispatcher_send_custom_event(nfc->nfc_common.view_dispatcher, NfcEventMifareUl);
+}
+
+const void nfc_scene_read_mifare_ul_on_enter(void* context) {
+ Nfc* nfc = (Nfc*)context;
+
+ // Setup view
+ Popup* popup = nfc->popup;
+ popup_set_header(popup, "Detecting\nultralight", 70, 34, AlignLeft, AlignTop);
+ popup_set_icon(popup, 0, 3, &I_RFIDDolphinReceive_97x61);
+
+ // Start worker
+ nfc_worker_start(
+ nfc->nfc_common.worker,
+ NfcWorkerStateReadMfUltralight,
+ &nfc->nfc_common.worker_result,
+ nfc_read_mifare_ul_worker_callback,
+ nfc);
+ view_dispatcher_switch_to_view(nfc->nfc_common.view_dispatcher, NfcViewPopup);
+}
+
+const bool nfc_scene_read_mifare_ul_on_event(void* context, uint32_t event) {
+ Nfc* nfc = (Nfc*)context;
+
+ if(event == NfcEventMifareUl) {
+ nfc->device.data = nfc->nfc_common.worker_result.nfc_detect_data;
+ view_dispatcher_add_scene(
+ nfc->nfc_common.view_dispatcher, nfc->scene_read_mifare_ul_success);
+ view_dispatcher_send_navigation_event(
+ nfc->nfc_common.view_dispatcher, ViewNavigatorEventNext);
+ return true;
+ }
+ return false;
+}
+
+const void nfc_scene_read_mifare_ul_on_exit(void* context) {
+ Nfc* nfc = (Nfc*)context;
+
+ // Stop worker
+ nfc_worker_stop(nfc->nfc_common.worker);
+
+ // 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);
+}
+
+AppScene* nfc_scene_read_mifare_ul_alloc() {
+ AppScene* scene = furi_alloc(sizeof(AppScene));
+ scene->id = NfcSceneReadMifareUl;
+ scene->on_enter = nfc_scene_read_mifare_ul_on_enter;
+ scene->on_event = nfc_scene_read_mifare_ul_on_event;
+ scene->on_exit = nfc_scene_read_mifare_ul_on_exit;
+
+ return scene;
+}
+
+void nfc_scene_read_mifare_ul_free(AppScene* scene) {
+ free(scene);
+}
diff --git a/applications/nfc/scenes/nfc_scene_read_mifare_ul.h b/applications/nfc/scenes/nfc_scene_read_mifare_ul.h
new file mode 100644
index 00000000..19b8e6cb
--- /dev/null
+++ b/applications/nfc/scenes/nfc_scene_read_mifare_ul.h
@@ -0,0 +1,7 @@
+#pragma once
+
+#include "app_scene.h"
+
+AppScene* nfc_scene_read_mifare_ul_alloc();
+
+void nfc_scene_read_mifare_ul_free(AppScene* scene);
diff --git a/applications/nfc/scenes/nfc_scene_read_mifare_ul_success.c b/applications/nfc/scenes/nfc_scene_read_mifare_ul_success.c
new file mode 100755
index 00000000..621a45a4
--- /dev/null
+++ b/applications/nfc/scenes/nfc_scene_read_mifare_ul_success.c
@@ -0,0 +1,152 @@
+#include "nfc_scene_read_mifare_ul_success.h"
+#include "../nfc_i.h"
+
+#include <furi.h>
+#include <gui/modules/dialog_ex.h>
+#include <gui/view_dispatcher.h>
+
+#define NFC_SCENE_READ_SUCCESS_SHIFT " "
+#define NFC_SCENE_READ_MF_UL_CUSTOM_EVENT (0UL)
+
+enum {
+ ReadMifareUlStateShowUID,
+ ReadMifareUlStateShowData,
+};
+
+void nfc_scene_read_mifare_ul_success_dialog_callback(DialogExResult result, void* context) {
+ Nfc* nfc = (Nfc*)context;
+
+ view_dispatcher_send_custom_event(nfc->nfc_common.view_dispatcher, result);
+}
+
+void nfc_scene_read_mifare_ul_success_text_box_callback(void* context) {
+ Nfc* nfc = (Nfc*)context;
+
+ view_dispatcher_send_custom_event(
+ nfc->nfc_common.view_dispatcher, NFC_SCENE_READ_MF_UL_CUSTOM_EVENT);
+}
+
+const void nfc_scene_read_mifare_ul_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);
+
+ // Setup dialog view
+ NfcDeviceData* data =
+ (NfcDeviceData*)&nfc->nfc_common.worker_result.nfc_mifare_ul_data.nfc_data;
+ DialogEx* dialog_ex = nfc->dialog_ex;
+ dialog_ex_set_left_button_text(dialog_ex, "Retry");
+ dialog_ex_set_right_button_text(dialog_ex, "More");
+ dialog_ex_set_center_button_text(dialog_ex, "Data");
+ dialog_ex_set_header(dialog_ex, "Mifare Ultralight", 22, 8, AlignLeft, AlignCenter);
+ dialog_ex_set_icon(dialog_ex, 8, 13, &I_Medium_chip_22x21);
+ // Display UID
+ nfc_set_text_store(
+ nfc,
+ NFC_SCENE_READ_SUCCESS_SHIFT "ATQA: %02X%02X\n" NFC_SCENE_READ_SUCCESS_SHIFT
+ "SAK: %02X\nUID: %02X %02X %02X %02X %02X %02X %02X",
+ data->atqa[0],
+ data->atqa[1],
+ data->sak,
+ data->uid[0],
+ data->uid[1],
+ data->uid[2],
+ data->uid[3],
+ data->uid[4],
+ data->uid[5],
+ data->uid[6]);
+ dialog_ex_set_text(dialog_ex, nfc->text_store, 8, 16, AlignLeft, AlignTop);
+ dialog_ex_set_context(dialog_ex, nfc);
+ dialog_ex_set_result_callback(dialog_ex, nfc_scene_read_mifare_ul_success_dialog_callback);
+
+ // Setup TextBox view
+ NfcMifareUlData* mf_ul_data =
+ (NfcMifareUlData*)&nfc->nfc_common.worker_result.nfc_mifare_ul_data;
+ TextBox* text_box = nfc->text_box;
+ text_box_set_context(text_box, nfc);
+ text_box_set_exit_callback(text_box, nfc_scene_read_mifare_ul_success_text_box_callback);
+ text_box_set_font(text_box, TextBoxFontHex);
+ for(uint16_t i = 0; i < mf_ul_data->dump_size; i += 2) {
+ if(!(i % 8) && i) {
+ string_push_back(nfc->text_box_store, '\n');
+ }
+ string_cat_printf(
+ nfc->text_box_store,
+ "%02X%02X ",
+ mf_ul_data->full_dump[i],
+ mf_ul_data->full_dump[i + 1]);
+ }
+ text_box_set_text(text_box, string_get_cstr(nfc->text_box_store));
+
+ nfc->scene_read_mifare_ul_success->state = ReadMifareUlStateShowUID;
+ view_dispatcher_switch_to_view(nfc->nfc_common.view_dispatcher, NfcViewDialogEx);
+}
+
+const bool nfc_scene_read_mifare_ul_success_on_event(void* context, uint32_t event) {
+ Nfc* nfc = (Nfc*)context;
+
+ if((nfc->scene_read_mifare_ul_success->state == ReadMifareUlStateShowUID) &&
+ (event == DialogExResultLeft)) {
+ view_dispatcher_send_navigation_event(
+ nfc->nfc_common.view_dispatcher, ViewNavigatorEventBack);
+ return true;
+ } else if(
+ (nfc->scene_read_mifare_ul_success->state == ReadMifareUlStateShowUID) &&
+ (event == DialogExResultRight)) {
+ view_dispatcher_add_scene(nfc->nfc_common.view_dispatcher, nfc->scene_mifare_ul_menu);
+ view_dispatcher_send_navigation_event(
+ nfc->nfc_common.view_dispatcher, ViewNavigatorEventNext);
+ return true;
+ } else if(
+ (nfc->scene_read_mifare_ul_success->state == ReadMifareUlStateShowUID) &&
+ (event == DialogExResultCenter)) {
+ view_dispatcher_switch_to_view(nfc->nfc_common.view_dispatcher, NfcViewTextBox);
+ nfc->scene_read_mifare_ul_success->state = ReadMifareUlStateShowData;
+ return true;
+ } else if(
+ (nfc->scene_read_mifare_ul_success->state == ReadMifareUlStateShowData) &&
+ (event == NFC_SCENE_READ_MF_UL_CUSTOM_EVENT)) {
+ view_dispatcher_switch_to_view(nfc->nfc_common.view_dispatcher, NfcViewDialogEx);
+ nfc->scene_read_mifare_ul_success->state = ReadMifareUlStateShowUID;
+ return true;
+ }
+ return false;
+}
+
+const void nfc_scene_read_mifare_ul_success_on_exit(void* context) {
+ Nfc* nfc = (Nfc*)context;
+
+ // Clean dialog
+ DialogEx* dialog_ex = nfc->dialog_ex;
+ dialog_ex_set_header(dialog_ex, NULL, 0, 0, AlignCenter, AlignCenter);
+ dialog_ex_set_text(dialog_ex, NULL, 0, 0, AlignCenter, AlignTop);
+ dialog_ex_set_icon(dialog_ex, 0, 0, NULL);
+ dialog_ex_set_left_button_text(dialog_ex, NULL);
+ dialog_ex_set_right_button_text(dialog_ex, NULL);
+ dialog_ex_set_center_button_text(dialog_ex, NULL);
+ dialog_ex_set_result_callback(dialog_ex, NULL);
+ dialog_ex_set_context(dialog_ex, NULL);
+
+ // Clean TextBox
+ TextBox* text_box = nfc->text_box;
+ text_box_clean(text_box);
+ string_clean(nfc->text_box_store);
+}
+
+AppScene* nfc_scene_read_mifare_ul_success_alloc() {
+ AppScene* scene = furi_alloc(sizeof(AppScene));
+ scene->id = NfcSceneReadMifareUlSuccess;
+ scene->on_enter = nfc_scene_read_mifare_ul_success_on_enter;
+ scene->on_event = nfc_scene_read_mifare_ul_success_on_event;
+ scene->on_exit = nfc_scene_read_mifare_ul_success_on_exit;
+
+ return scene;
+}
+
+void nfc_scene_read_mifare_ul_success_free(AppScene* scene) {
+ free(scene);
+}
diff --git a/applications/nfc/scenes/nfc_scene_read_mifare_ul_success.h b/applications/nfc/scenes/nfc_scene_read_mifare_ul_success.h
new file mode 100644
index 00000000..a8f9e44b
--- /dev/null
+++ b/applications/nfc/scenes/nfc_scene_read_mifare_ul_success.h
@@ -0,0 +1,7 @@
+#pragma once
+
+#include "app_scene.h"
+
+AppScene* nfc_scene_read_mifare_ul_success_alloc();
+
+void nfc_scene_read_mifare_ul_success_free(AppScene* scene);
diff --git a/applications/nfc/scenes/nfc_scene_scripts_menu.c b/applications/nfc/scenes/nfc_scene_scripts_menu.c
new file mode 100755
index 00000000..29086f12
--- /dev/null
+++ b/applications/nfc/scenes/nfc_scene_scripts_menu.c
@@ -0,0 +1,75 @@
+#include "nfc_scene_scripts_menu.h"
+#include "../nfc_i.h"
+
+#include <furi.h>
+#include <gui/modules/submenu.h>
+#include <gui/view_dispatcher.h>
+
+enum SubmenuIndex {
+ SubmenuIndexBankCard,
+ SubmenuIndexMifareUltralight,
+};
+
+void nfc_scene_scripts_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_scripts_menu_on_enter(void* context) {
+ Nfc* nfc = (Nfc*)context;
+ Submenu* submenu = nfc->submenu;
+
+ submenu_add_item(
+ submenu,
+ "Read bank card",
+ SubmenuIndexBankCard,
+ nfc_scene_scripts_menu_submenu_callback,
+ nfc);
+ submenu_add_item(
+ submenu,
+ "Read Mifare Ultralight",
+ SubmenuIndexMifareUltralight,
+ nfc_scene_scripts_menu_submenu_callback,
+ nfc);
+
+ view_dispatcher_switch_to_view(nfc->nfc_common.view_dispatcher, NfcViewMenu);
+}
+
+const bool nfc_scene_scripts_menu_on_event(void* context, uint32_t event) {
+ Nfc* nfc = (Nfc*)context;
+
+ if(event == SubmenuIndexBankCard) {
+ 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 == SubmenuIndexMifareUltralight) {
+ view_dispatcher_add_scene(nfc->nfc_common.view_dispatcher, nfc->scene_read_mifare_ul);
+ view_dispatcher_send_navigation_event(
+ nfc->nfc_common.view_dispatcher, ViewNavigatorEventNext);
+ return true;
+ }
+
+ return false;
+}
+
+const void nfc_scene_scripts_menu_on_exit(void* context) {
+ Nfc* nfc = (Nfc*)context;
+
+ submenu_clean(nfc->submenu);
+}
+
+AppScene* nfc_scene_scripts_menu_alloc() {
+ AppScene* scene = furi_alloc(sizeof(AppScene));
+ scene->id = NfcSceneScriptsMenu;
+ scene->on_enter = nfc_scene_scripts_menu_on_enter;
+ scene->on_event = nfc_scene_scripts_menu_on_event;
+ scene->on_exit = nfc_scene_scripts_menu_on_exit;
+
+ return scene;
+}
+
+void nfc_scene_scripts_menu_free(AppScene* scene) {
+ free(scene);
+} \ No newline at end of file
diff --git a/applications/nfc/scenes/nfc_scene_scripts_menu.h b/applications/nfc/scenes/nfc_scene_scripts_menu.h
new file mode 100644
index 00000000..8002e568
--- /dev/null
+++ b/applications/nfc/scenes/nfc_scene_scripts_menu.h
@@ -0,0 +1,7 @@
+#pragma once
+
+#include "app_scene.h"
+
+AppScene* nfc_scene_scripts_menu_alloc();
+
+void nfc_scene_scripts_menu_free(AppScene* scene);
diff --git a/applications/nfc/scenes/nfc_scene_start.c b/applications/nfc/scenes/nfc_scene_start.c
index 15c59266..80f497b8 100644
--- a/applications/nfc/scenes/nfc_scene_start.c
+++ b/applications/nfc/scenes/nfc_scene_start.c
@@ -49,7 +49,7 @@ const bool nfc_scene_start_on_event(void* context, uint32_t event) {
nfc->nfc_common.view_dispatcher, ViewNavigatorEventNext);
return true;
} else if(event == SubmenuIndexRunScript) {
- view_dispatcher_add_scene(nfc->nfc_common.view_dispatcher, nfc->scene_not_implemented);
+ view_dispatcher_add_scene(nfc->nfc_common.view_dispatcher, nfc->scene_scripts_menu);
view_dispatcher_send_navigation_event(
nfc->nfc_common.view_dispatcher, ViewNavigatorEventNext);
return true;