Explorar o código

Start on data view scene

TollyH %!s(int64=2) %!d(string=hai) anos
pai
achega
d15fa8fd79

+ 15 - 0
mfc_editor_app.c

@@ -43,6 +43,9 @@ MfcEditorApp* mfc_editor_app_alloc() {
     instance->nfc_device = nfc_device_alloc();
     instance->file_path = furi_string_alloc_set(NFC_APP_FOLDER);
 
+    instance->data_view_header = furi_string_alloc();
+    instance->data_view_text = furi_string_alloc();
+
     instance->submenu = submenu_alloc();
     view_dispatcher_add_view(
         instance->view_dispatcher, MfcEditorAppViewSubmenu, submenu_get_view(instance->submenu));
@@ -51,6 +54,12 @@ MfcEditorApp* mfc_editor_app_alloc() {
     view_dispatcher_add_view(
         instance->view_dispatcher, MfcEditorAppViewPopup, popup_get_view(instance->popup));
 
+    instance->dialog_ex = dialog_ex_alloc();
+    view_dispatcher_add_view(
+        instance->view_dispatcher,
+        MfcEditorAppViewDialogEx,
+        dialog_ex_get_view(instance->dialog_ex));
+
     return instance;
 }
 
@@ -63,6 +72,9 @@ void mfc_editor_app_free(MfcEditorApp* instance) {
     view_dispatcher_remove_view(instance->view_dispatcher, MfcEditorAppViewPopup);
     popup_free(instance->popup);
 
+    view_dispatcher_remove_view(instance->view_dispatcher, MfcEditorAppViewDialogEx);
+    dialog_ex_free(instance->dialog_ex);
+
     view_dispatcher_free(instance->view_dispatcher);
     scene_manager_free(instance->scene_manager);
 
@@ -78,6 +90,9 @@ void mfc_editor_app_free(MfcEditorApp* instance) {
     nfc_device_free(instance->nfc_device);
     furi_string_free(instance->file_path);
 
+    furi_string_free(instance->data_view_header);
+    furi_string_free(instance->data_view_text);
+
     free(instance);
 }
 

+ 21 - 0
mfc_editor_app_i.h

@@ -8,6 +8,7 @@
 #include <gui/scene_manager.h>
 #include <gui/view_dispatcher.h>
 
+#include <gui/modules/dialog_ex.h>
 #include <gui/modules/popup.h>
 #include <gui/modules/submenu.h>
 
@@ -44,6 +45,7 @@ struct MfcEditorApp {
 
     Submenu* submenu;
     Popup* popup;
+    DialogEx* dialog_ex;
 
     NfcDevice* nfc_device;
     const MfClassicData* mf_classic_data;
@@ -52,11 +54,16 @@ struct MfcEditorApp {
 
     uint8_t current_sector;
     uint8_t current_block;
+
+    // DialogEx doesn't copy the strings given to it, so we need these
+    FuriString* data_view_header;
+    FuriString* data_view_text;
 };
 
 typedef enum {
     MfcEditorAppViewSubmenu,
     MfcEditorAppViewPopup,
+    MfcEditorAppViewDialogEx,
 } MfcEditorAppView;
 
 typedef enum {
@@ -71,6 +78,20 @@ typedef enum {
     MfcEditorPromptResponseExitedShadow,
 } MfcEditorPromptResponse;
 
+typedef enum {
+    MfcEditorBlockViewNormal,
+
+    // Special options - Sector 0 only
+    MfcEditorBlockViewUID,
+    MfcEditorBlockViewManufacturerBytes,
+
+    // Special options - All sectors
+    MfcEditorBlockViewKeyA,
+    MfcEditorBlockViewKeyB,
+    MfcEditorBlockViewAccessBits,
+    MfcEditorBlockViewUserByte,
+} MfcEditorBlockView;
+
 MfcEditorPromptResponse mfc_editor_prompt_load_file(MfcEditorApp* instance);
 
 MfcEditorPromptResponse mfc_editor_load_file(MfcEditorApp* instance, FuriString* file_path);

+ 21 - 3
scenes/mfc_editor_scene_block_select.c

@@ -91,12 +91,30 @@ bool mfc_editor_scene_block_select_on_event(void* context, SceneManagerEvent eve
     MfcEditorApp* instance = context;
     bool consumed = false;
 
-    UNUSED(instance);
-
     if(event.type == SceneManagerEventTypeCustom) {
         scene_manager_set_scene_state(
             instance->scene_manager, MfcEditorSceneBlockSelect, event.event);
-        FURI_LOG_I(TAG, "Block select event %lu", event.event);
+
+        MfcEditorBlockView block_view;
+        if(event.event == SubmenuIndexUID) {
+            block_view = MfcEditorBlockViewUID;
+        } else if(event.event == SubmenuIndexManufacturerBytes) {
+            block_view = MfcEditorBlockViewManufacturerBytes;
+        } else if(event.event == SubmenuIndexKeyA) {
+            block_view = MfcEditorBlockViewKeyA;
+        } else if(event.event == SubmenuIndexKeyB) {
+            block_view = MfcEditorBlockViewKeyB;
+        } else if(event.event == SubmenuIndexAccessBits) {
+            block_view = MfcEditorBlockViewAccessBits;
+        } else if(event.event == SubmenuIndexUserByte) {
+            block_view = MfcEditorBlockViewUserByte;
+        } else {
+            block_view = MfcEditorBlockViewNormal;
+            instance->current_block = event.event;
+        }
+
+        scene_manager_set_scene_state(instance->scene_manager, MfcEditorSceneDataView, block_view);
+        scene_manager_next_scene(instance->scene_manager, MfcEditorSceneDataView);
         consumed = true;
     }
 

+ 1 - 0
scenes/mfc_editor_scene_config.h

@@ -3,3 +3,4 @@ ADD_SCENE(mfc_editor, file_select, FileSelect)
 ADD_SCENE(mfc_editor, invalid_file, InvalidFile)
 ADD_SCENE(mfc_editor, sector_select, SectorSelect)
 ADD_SCENE(mfc_editor, block_select, BlockSelect)
+ADD_SCENE(mfc_editor, data_view, DataView)

+ 92 - 0
scenes/mfc_editor_scene_data_view.c

@@ -0,0 +1,92 @@
+#include "../mfc_editor_app_i.h"
+
+void mfc_editor_scene_data_view_on_enter(void* context) {
+    MfcEditorApp* instance = context;
+
+    DialogEx* dialog_ex = instance->dialog_ex;
+    dialog_ex_set_context(instance->dialog_ex, instance);
+
+    MfcEditorBlockView block_view =
+        scene_manager_get_scene_state(instance->scene_manager, MfcEditorSceneDataView);
+
+    const MfClassicData* mf_classic_data = instance->mf_classic_data;
+    Iso14443_3aData* iso14443_3a_data = mf_classic_data->iso14443_3a_data;
+
+    if(block_view == MfcEditorBlockViewUID) {
+        dialog_ex_set_header(dialog_ex, "UID", 63, 3, AlignCenter, AlignTop);
+
+        furi_string_set(instance->data_view_text, "");
+        for(int i = 0; i < iso14443_3a_data->uid_len; i++) {
+            furi_string_cat_printf(instance->data_view_text, "%02hhX ", iso14443_3a_data->uid[i]);
+        }
+        // Remove trailing space
+        furi_string_trim(instance->data_view_text);
+    } else if(block_view == MfcEditorBlockViewManufacturerBytes) {
+        dialog_ex_set_header(dialog_ex, "Manufacturer Bytes", 63, 3, AlignCenter, AlignTop);
+
+        if(mf_classic_is_block_read(mf_classic_data, 0)) {
+            furi_string_set(instance->data_view_text, "");
+            uint8_t byte_num = MF_CLASSIC_BLOCK_SIZE - iso14443_3a_data->uid_len - 1;
+            // +1 to ignore BCC byte
+            // TODO: should we do this for 4K?
+            for(int i = iso14443_3a_data->uid_len + 1; i < MF_CLASSIC_BLOCK_SIZE; i++) {
+                furi_string_cat_printf(
+                    instance->data_view_text, "%02hhX", mf_classic_data->block[0].data[i]);
+                // Go onto next line when halfway through
+                if(MF_CLASSIC_BLOCK_SIZE - i - 1 == byte_num / 2) {
+                    furi_string_cat(instance->data_view_text, "\n");
+                } else {
+                    furi_string_cat(instance->data_view_text, " ");
+                }
+            }
+            // Remove trailing space
+            furi_string_trim(instance->data_view_text);
+        } else {
+            furi_string_set(
+                instance->data_view_text, "Data unavailable.\nBlock 0 has not been read.");
+        }
+    } else if(block_view == MfcEditorBlockViewKeyA) {
+        dialog_ex_set_header(dialog_ex, "Key A", 63, 3, AlignCenter, AlignTop);
+    } else if(block_view == MfcEditorBlockViewKeyB) {
+        dialog_ex_set_header(dialog_ex, "Key B", 63, 3, AlignCenter, AlignTop);
+    } else if(block_view == MfcEditorBlockViewAccessBits) {
+        dialog_ex_set_header(dialog_ex, "Access Bits", 63, 3, AlignCenter, AlignTop);
+    } else if(block_view == MfcEditorBlockViewUserByte) {
+        dialog_ex_set_header(dialog_ex, "User Byte", 63, 3, AlignCenter, AlignTop);
+    } else {
+        furi_string_printf(instance->data_view_header, "Block %hhu Data", instance->current_block);
+        dialog_ex_set_header(
+            dialog_ex,
+            furi_string_get_cstr(instance->data_view_header),
+            63,
+            3,
+            AlignCenter,
+            AlignTop);
+    }
+
+    dialog_ex_set_text(
+        dialog_ex,
+        furi_string_get_cstr(instance->data_view_text),
+        63,
+        31,
+        AlignCenter,
+        AlignCenter);
+
+    view_dispatcher_switch_to_view(instance->view_dispatcher, MfcEditorAppViewDialogEx);
+}
+
+bool mfc_editor_scene_data_view_on_event(void* context, SceneManagerEvent event) {
+    MfcEditorApp* instance = context;
+    bool consumed = false;
+
+    UNUSED(instance);
+    UNUSED(event);
+
+    return consumed;
+}
+
+void mfc_editor_scene_data_view_on_exit(void* context) {
+    MfcEditorApp* instance = context;
+
+    dialog_ex_reset(instance->dialog_ex);
+}