Przeglądaj źródła

[FL-2843] NFC fixes (#1764)

* nfc: fix empty desfire card message
* nfc: limit total user keys to list
* nfc: increase popup timeout

Co-authored-by: あく <alleteam@gmail.com>
gornekich 3 lat temu
rodzic
commit
e70121e20f

+ 64 - 24
applications/main/nfc/scenes/nfc_scene_mf_classic_keys_list.c

@@ -1,48 +1,87 @@
 #include "../nfc_i.h"
 
+#define NFC_SCENE_MF_CLASSIC_KEYS_LIST_MAX (100)
+
 void nfc_scene_mf_classic_keys_list_submenu_callback(void* context, uint32_t index) {
-    Nfc* nfc = context;
+    furi_assert(context);
 
+    Nfc* nfc = context;
     view_dispatcher_send_custom_event(nfc->view_dispatcher, index);
 }
 
-void nfc_scene_mf_classic_keys_list_on_enter(void* context) {
+void nfc_scene_mf_classic_keys_list_popup_callback(void* context) {
+    furi_assert(context);
+
     Nfc* nfc = context;
+    view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventViewExit);
+}
+
+void nfc_scene_mf_classic_keys_list_prepare(Nfc* nfc, MfClassicDict* dict) {
     Submenu* submenu = nfc->submenu;
-    MfClassicDict* dict = mf_classic_dict_alloc(MfClassicDictTypeUser);
     uint32_t index = 0;
     string_t temp_key;
-    MfClassicUserKeys_init(nfc->mfc_key_strs);
     string_init(temp_key);
+
+    submenu_set_header(submenu, "Select key to delete:");
+    while(mf_classic_dict_get_next_key_str(dict, temp_key)) {
+        char* current_key = (char*)malloc(sizeof(char) * 13);
+        strncpy(current_key, string_get_cstr(temp_key), 12);
+        MfClassicUserKeys_push_back(nfc->mfc_key_strs, current_key);
+        FURI_LOG_D("ListKeys", "Key %d: %s", index, current_key);
+        submenu_add_item(
+            submenu, current_key, index++, nfc_scene_mf_classic_keys_list_submenu_callback, nfc);
+    }
+    string_clear(temp_key);
+}
+
+void nfc_scene_mf_classic_keys_list_on_enter(void* context) {
+    Nfc* nfc = context;
+    MfClassicDict* dict = mf_classic_dict_alloc(MfClassicDictTypeUser);
+    MfClassicUserKeys_init(nfc->mfc_key_strs);
     if(dict) {
-        mf_classic_dict_rewind(dict);
-        while(mf_classic_dict_get_next_key_str(dict, temp_key)) {
-            char* current_key = (char*)malloc(sizeof(char) * 13);
-            strncpy(current_key, string_get_cstr(temp_key), 12);
-            MfClassicUserKeys_push_back(nfc->mfc_key_strs, current_key);
-            FURI_LOG_D("ListKeys", "Key %d: %s", index, current_key);
-            submenu_add_item(
-                submenu,
-                current_key,
-                index++,
-                nfc_scene_mf_classic_keys_list_submenu_callback,
-                nfc);
+        uint32_t total_user_keys = mf_classic_dict_get_total_keys(dict);
+        if(total_user_keys < NFC_SCENE_MF_CLASSIC_KEYS_LIST_MAX) {
+            nfc_scene_mf_classic_keys_list_prepare(nfc, dict);
+            view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewMenu);
+        } else {
+            popup_set_header(nfc->popup, "Too many keys!", 64, 0, AlignCenter, AlignTop);
+            popup_set_text(
+                nfc->popup,
+                "Edit user dictionary\nwith file browser",
+                64,
+                12,
+                AlignCenter,
+                AlignTop);
+            popup_set_callback(nfc->popup, nfc_scene_mf_classic_keys_list_popup_callback);
+            popup_set_context(nfc->popup, nfc);
+            popup_set_timeout(nfc->popup, 3000);
+            popup_enable_timeout(nfc->popup);
+            view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewPopup);
         }
+        mf_classic_dict_free(dict);
+    } else {
+        popup_set_header(
+            nfc->popup, "Failed to load dictionary", 64, 32, AlignCenter, AlignCenter);
+        popup_set_callback(nfc->popup, nfc_scene_mf_classic_keys_list_popup_callback);
+        popup_set_context(nfc->popup, nfc);
+        popup_set_timeout(nfc->popup, 3000);
+        popup_enable_timeout(nfc->popup);
+        view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewPopup);
     }
-    submenu_set_header(submenu, "Select key to delete:");
-    mf_classic_dict_free(dict);
-    string_clear(temp_key);
-    view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewMenu);
 }
 
 bool nfc_scene_mf_classic_keys_list_on_event(void* context, SceneManagerEvent event) {
     Nfc* nfc = context;
     bool consumed = false;
     if(event.type == SceneManagerEventTypeCustom) {
-        scene_manager_set_scene_state(
-            nfc->scene_manager, NfcSceneMfClassicKeysDelete, event.event);
-        scene_manager_next_scene(nfc->scene_manager, NfcSceneMfClassicKeysDelete);
-        consumed = true;
+        if(event.event == NfcCustomEventViewExit) {
+            consumed = scene_manager_previous_scene(nfc->scene_manager);
+        } else {
+            scene_manager_set_scene_state(
+                nfc->scene_manager, NfcSceneMfClassicKeysDelete, event.event);
+            scene_manager_next_scene(nfc->scene_manager, NfcSceneMfClassicKeysDelete);
+            consumed = true;
+        }
     }
     return consumed;
 }
@@ -57,4 +96,5 @@ void nfc_scene_mf_classic_keys_list_on_exit(void* context) {
     }
     MfClassicUserKeys_clear(nfc->mfc_key_strs);
     submenu_reset(nfc->submenu);
+    popup_reset(nfc->popup);
 }

+ 61 - 50
applications/main/nfc/scenes/nfc_scene_mf_desfire_app.c

@@ -7,6 +7,13 @@ enum SubmenuIndex {
     SubmenuIndexDynamic, // dynamic indexes start here
 };
 
+void nfc_scene_mf_desfire_popup_callback(void* context) {
+    furi_assert(context);
+
+    Nfc* nfc = context;
+    view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventViewExit);
+}
+
 MifareDesfireApplication* nfc_scene_mf_desfire_app_get_app(Nfc* nfc) {
     uint32_t app_idx = scene_manager_get_scene_state(nfc->scene_manager, NfcSceneMfDesfireApp) >>
                        1;
@@ -25,46 +32,45 @@ void nfc_scene_mf_desfire_app_submenu_callback(void* context, uint32_t index) {
 
 void nfc_scene_mf_desfire_app_on_enter(void* context) {
     Nfc* nfc = context;
-    Submenu* submenu = nfc->submenu;
     MifareDesfireApplication* app = nfc_scene_mf_desfire_app_get_app(nfc);
     if(!app) {
         popup_set_icon(nfc->popup, 5, 5, &I_WarningDolphin_45x42);
-        popup_set_header(nfc->popup, "Internal Error!", 55, 12, AlignLeft, AlignBottom);
-        popup_set_text(
-            nfc->popup,
-            "No app selected.\nThis should\nnever happen,\nplease file a bug.",
-            55,
-            15,
-            AlignLeft,
-            AlignTop);
+        popup_set_header(nfc->popup, "Empty card!", 55, 12, AlignLeft, AlignBottom);
+        popup_set_callback(nfc->popup, nfc_scene_mf_desfire_popup_callback);
+        popup_set_context(nfc->popup, nfc);
+        popup_set_timeout(nfc->popup, 3000);
+        popup_enable_timeout(nfc->popup);
+        popup_set_text(nfc->popup, "No application\nfound.", 55, 15, AlignLeft, AlignTop);
         view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewPopup);
-        FURI_LOG_E(TAG, "Bad state. No app selected?");
-        return;
-    }
-
-    text_box_set_font(nfc->text_box, TextBoxFontHex);
+    } else {
+        text_box_set_font(nfc->text_box, TextBoxFontHex);
+        submenu_add_item(
+            nfc->submenu,
+            "App info",
+            SubmenuIndexAppInfo,
+            nfc_scene_mf_desfire_app_submenu_callback,
+            nfc);
 
-    submenu_add_item(
-        submenu, "App info", SubmenuIndexAppInfo, nfc_scene_mf_desfire_app_submenu_callback, nfc);
-
-    uint16_t cap = NFC_TEXT_STORE_SIZE;
-    char* buf = nfc->text_store;
-    int idx = SubmenuIndexDynamic;
-    for(MifareDesfireFile* file = app->file_head; file; file = file->next) {
-        int size = snprintf(buf, cap, "File %d", file->id);
-        if(size < 0 || size >= cap) {
-            FURI_LOG_W(
-                TAG,
-                "Exceeded NFC_TEXT_STORE_SIZE when preparing file id strings; menu truncated");
-            break;
+        uint16_t cap = NFC_TEXT_STORE_SIZE;
+        char* buf = nfc->text_store;
+        int idx = SubmenuIndexDynamic;
+        for(MifareDesfireFile* file = app->file_head; file; file = file->next) {
+            int size = snprintf(buf, cap, "File %d", file->id);
+            if(size < 0 || size >= cap) {
+                FURI_LOG_W(
+                    TAG,
+                    "Exceeded NFC_TEXT_STORE_SIZE when preparing file id strings; menu truncated");
+                break;
+            }
+            char* label = buf;
+            cap -= size + 1;
+            buf += size + 1;
+            submenu_add_item(
+                nfc->submenu, label, idx++, nfc_scene_mf_desfire_app_submenu_callback, nfc);
         }
-        char* label = buf;
-        cap -= size + 1;
-        buf += size + 1;
-        submenu_add_item(submenu, label, idx++, nfc_scene_mf_desfire_app_submenu_callback, nfc);
-    }
 
-    view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewMenu);
+        view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewMenu);
+    }
 }
 
 bool nfc_scene_mf_desfire_app_on_event(void* context, SceneManagerEvent event) {
@@ -73,26 +79,30 @@ bool nfc_scene_mf_desfire_app_on_event(void* context, SceneManagerEvent event) {
     uint32_t state = scene_manager_get_scene_state(nfc->scene_manager, NfcSceneMfDesfireApp);
 
     if(event.type == SceneManagerEventTypeCustom) {
-        MifareDesfireApplication* app = nfc_scene_mf_desfire_app_get_app(nfc);
-        TextBox* text_box = nfc->text_box;
-        string_reset(nfc->text_box_store);
-        if(event.event == SubmenuIndexAppInfo) {
-            mf_df_cat_application_info(app, nfc->text_box_store);
+        if(event.event == NfcCustomEventViewExit) {
+            consumed = scene_manager_previous_scene(nfc->scene_manager);
         } else {
-            uint16_t index = event.event - SubmenuIndexDynamic;
-            MifareDesfireFile* file = app->file_head;
-            for(int i = 0; file && i < index; i++) {
-                file = file->next;
-            }
-            if(!file) {
-                return false;
+            MifareDesfireApplication* app = nfc_scene_mf_desfire_app_get_app(nfc);
+            TextBox* text_box = nfc->text_box;
+            string_reset(nfc->text_box_store);
+            if(event.event == SubmenuIndexAppInfo) {
+                mf_df_cat_application_info(app, nfc->text_box_store);
+            } else {
+                uint16_t index = event.event - SubmenuIndexDynamic;
+                MifareDesfireFile* file = app->file_head;
+                for(int i = 0; file && i < index; i++) {
+                    file = file->next;
+                }
+                if(!file) {
+                    return false;
+                }
+                mf_df_cat_file(file, nfc->text_box_store);
             }
-            mf_df_cat_file(file, nfc->text_box_store);
+            text_box_set_text(text_box, string_get_cstr(nfc->text_box_store));
+            scene_manager_set_scene_state(nfc->scene_manager, NfcSceneMfDesfireApp, state | 1);
+            view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewTextBox);
+            consumed = true;
         }
-        text_box_set_text(text_box, string_get_cstr(nfc->text_box_store));
-        scene_manager_set_scene_state(nfc->scene_manager, NfcSceneMfDesfireApp, state | 1);
-        view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewTextBox);
-        consumed = true;
     } else if(event.type == SceneManagerEventTypeBack) {
         if(state & 1) {
             view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewMenu);
@@ -108,6 +118,7 @@ void nfc_scene_mf_desfire_app_on_exit(void* context) {
     Nfc* nfc = context;
 
     // Clear views
+    popup_reset(nfc->popup);
     text_box_reset(nfc->text_box);
     string_reset(nfc->text_box_store);
     submenu_reset(nfc->submenu);