Ver Fonte

[FL-2701], [FL-2702], [FL-2699] NFC fixes (#1478)

* nfc: change read scene views
* nfc: rework return after save success
* nfc: add fallback to read UID of unrecognized iso14443-3
* nfc: show mifare desfire on read success
* nfc: add restore original confirm scene
* nfc: fix icon name
* nfc: clear 6 bit in SAK to emulate 14443-4 uids
* nfc: don't change original sak
gornekich há 3 anos atrás
pai
commit
c40e8811d6

+ 1 - 0
applications/nfc/scenes/nfc_scene_config.h

@@ -30,6 +30,7 @@ ADD_SCENE(nfc, emulate_apdu_sequence, EmulateApduSequence)
 ADD_SCENE(nfc, device_info, DeviceInfo)
 ADD_SCENE(nfc, device_info, DeviceInfo)
 ADD_SCENE(nfc, delete, Delete)
 ADD_SCENE(nfc, delete, Delete)
 ADD_SCENE(nfc, delete_success, DeleteSuccess)
 ADD_SCENE(nfc, delete_success, DeleteSuccess)
+ADD_SCENE(nfc, restore_original_confirm, RestoreOriginalConfirm)
 ADD_SCENE(nfc, restore_original, RestoreOriginal)
 ADD_SCENE(nfc, restore_original, RestoreOriginal)
 ADD_SCENE(nfc, debug, Debug)
 ADD_SCENE(nfc, debug, Debug)
 ADD_SCENE(nfc, field, Field)
 ADD_SCENE(nfc, field, Field)

+ 4 - 10
applications/nfc/scenes/nfc_scene_mf_desfire_read_success.c

@@ -34,18 +34,12 @@ void nfc_scene_mf_desfire_read_success_on_enter(void* context) {
         }
         }
     }
     }
 
 
+    // TODO rework info view
     nfc_text_store_set(
     nfc_text_store_set(
         nfc,
         nfc,
-        "UID: %02X %02X %02X %02X %02X %02X %02X\n" NFC_SCENE_READ_SUCCESS_SHIFT
-        "%d%s bytes\n" NFC_SCENE_READ_SUCCESS_SHIFT "%d bytes free\n"
-        "%d application%s, %d file%s",
-        data->version.uid[0],
-        data->version.uid[1],
-        data->version.uid[2],
-        data->version.uid[3],
-        data->version.uid[4],
-        data->version.uid[5],
-        data->version.uid[6],
+        NFC_SCENE_READ_SUCCESS_SHIFT "Mifare DESFire\n" NFC_SCENE_READ_SUCCESS_SHIFT
+                                     "%d%s bytes\n" NFC_SCENE_READ_SUCCESS_SHIFT "%d bytes free\n"
+                                     "%d application%s, %d file%s",
         1 << (data->version.sw_storage >> 1),
         1 << (data->version.sw_storage >> 1),
         (data->version.sw_storage & 1) ? "+" : "",
         (data->version.sw_storage & 1) ? "+" : "",
         data->free_memory ? data->free_memory->bytes : 0,
         data->free_memory ? data->free_memory->bytes : 0,

+ 6 - 3
applications/nfc/scenes/nfc_scene_read.c

@@ -23,12 +23,15 @@ void nfc_scene_read_set_state(Nfc* nfc, NfcSceneReadState state) {
     uint32_t curr_state = scene_manager_get_scene_state(nfc->scene_manager, NfcSceneRead);
     uint32_t curr_state = scene_manager_get_scene_state(nfc->scene_manager, NfcSceneRead);
     if(curr_state != state) {
     if(curr_state != state) {
         if(state == NfcSceneReadStateDetecting) {
         if(state == NfcSceneReadStateDetecting) {
-            popup_set_header(nfc->popup, "Detecting\nNFC card", 90, 24, AlignCenter, AlignTop);
-            popup_set_icon(nfc->popup, 5, 7, &I_NFC_manual);
+            popup_reset(nfc->popup);
+            popup_set_text(
+                nfc->popup, "Apply card to\nFlipper's back", 97, 24, AlignCenter, AlignTop);
+            popup_set_icon(nfc->popup, 0, 8, &I_NFC_manual);
         } else if(state == NfcSceneReadStateReading) {
         } else if(state == NfcSceneReadStateReading) {
+            popup_reset(nfc->popup);
             popup_set_header(
             popup_set_header(
                 nfc->popup, "Reading card\nDon't move...", 85, 24, AlignCenter, AlignTop);
                 nfc->popup, "Reading card\nDon't move...", 85, 24, AlignCenter, AlignTop);
-            popup_set_icon(nfc->popup, 19, 23, &A_Loading_24);
+            popup_set_icon(nfc->popup, 12, 23, &A_Loading_24);
         }
         }
         scene_manager_set_scene_state(nfc->scene_manager, NfcSceneRead, state);
         scene_manager_set_scene_state(nfc->scene_manager, NfcSceneRead, state);
     }
     }

+ 7 - 1
applications/nfc/scenes/nfc_scene_restore_original.c

@@ -25,7 +25,13 @@ bool nfc_scene_restore_original_on_event(void* context, SceneManagerEvent event)
 
 
     if(event.type == SceneManagerEventTypeCustom) {
     if(event.type == SceneManagerEventTypeCustom) {
         if(event.event == NfcCustomEventViewExit) {
         if(event.event == NfcCustomEventViewExit) {
-            consumed = scene_manager_previous_scene(nfc->scene_manager);
+            if(scene_manager_has_previous_scene(nfc->scene_manager, NfcSceneSavedMenu)) {
+                consumed = scene_manager_search_and_switch_to_previous_scene(
+                    nfc->scene_manager, NfcSceneSavedMenu);
+            } else {
+                consumed = scene_manager_search_and_switch_to_previous_scene(
+                    nfc->scene_manager, NfcSceneStart);
+            }
         }
         }
     }
     }
     return consumed;
     return consumed;

+ 53 - 0
applications/nfc/scenes/nfc_scene_restore_original_confirm.c

@@ -0,0 +1,53 @@
+#include "../nfc_i.h"
+
+void nfc_scene_restore_original_confirm_dialog_callback(DialogExResult result, void* context) {
+    Nfc* nfc = context;
+
+    view_dispatcher_send_custom_event(nfc->view_dispatcher, result);
+}
+
+void nfc_scene_restore_original_confirm_on_enter(void* context) {
+    Nfc* nfc = context;
+    DialogEx* dialog_ex = nfc->dialog_ex;
+
+    dialog_ex_set_header(dialog_ex, "Restore card data?", 64, 0, AlignCenter, AlignTop);
+    dialog_ex_set_icon(dialog_ex, 5, 15, &I_Restoring);
+    dialog_ex_set_text(
+        dialog_ex, "It will be returned\nto its original state.", 47, 21, AlignLeft, AlignTop);
+    dialog_ex_set_left_button_text(dialog_ex, "Cancel");
+    dialog_ex_set_right_button_text(dialog_ex, "Restore");
+    dialog_ex_set_context(dialog_ex, nfc);
+    dialog_ex_set_result_callback(dialog_ex, nfc_scene_restore_original_confirm_dialog_callback);
+
+    view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewDialogEx);
+}
+
+bool nfc_scene_restore_original_confirm_on_event(void* context, SceneManagerEvent event) {
+    Nfc* nfc = context;
+    bool consumed = false;
+
+    if(event.type == SceneManagerEventTypeCustom) {
+        if(event.event == DialogExResultRight) {
+            if(!nfc_device_restore(nfc->dev, true)) {
+                scene_manager_search_and_switch_to_previous_scene(
+                    nfc->scene_manager, NfcSceneStart);
+            } else {
+                scene_manager_next_scene(nfc->scene_manager, NfcSceneRestoreOriginal);
+            }
+            consumed = true;
+        } else if(event.event == DialogExResultLeft) {
+            consumed = scene_manager_previous_scene(nfc->scene_manager);
+        }
+    } else if(event.type == SceneManagerEventTypeBack) {
+        consumed = true;
+    }
+
+    return consumed;
+}
+
+void nfc_scene_restore_original_confirm_on_exit(void* context) {
+    Nfc* nfc = context;
+
+    // Clean view
+    dialog_ex_reset(nfc->dialog_ex);
+}

+ 4 - 4
applications/nfc/scenes/nfc_scene_save_success.c

@@ -27,12 +27,12 @@ bool nfc_scene_save_success_on_event(void* context, SceneManagerEvent event) {
 
 
     if(event.type == SceneManagerEventTypeCustom) {
     if(event.type == SceneManagerEventTypeCustom) {
         if(event.event == NfcCustomEventViewExit) {
         if(event.event == NfcCustomEventViewExit) {
-            if(scene_manager_has_previous_scene(nfc->scene_manager, NfcSceneMfDesfireMenu)) {
+            if(scene_manager_has_previous_scene(nfc->scene_manager, NfcSceneSavedMenu)) {
                 consumed = scene_manager_search_and_switch_to_previous_scene(
                 consumed = scene_manager_search_and_switch_to_previous_scene(
-                    nfc->scene_manager, NfcSceneMfDesfireMenu);
+                    nfc->scene_manager, NfcSceneSavedMenu);
             } else {
             } else {
-                consumed = scene_manager_search_and_switch_to_previous_scene(
-                    nfc->scene_manager, NfcSceneStart);
+                consumed = scene_manager_search_and_switch_to_another_scene(
+                    nfc->scene_manager, NfcSceneFileSelect);
             }
             }
         }
         }
     }
     }

+ 9 - 14
applications/nfc/scenes/nfc_scene_saved_menu.c

@@ -2,7 +2,7 @@
 
 
 enum SubmenuIndex {
 enum SubmenuIndex {
     SubmenuIndexEmulate,
     SubmenuIndexEmulate,
-    SubmenuIndexEdit,
+    SubmenuIndexRename,
     SubmenuIndexDelete,
     SubmenuIndexDelete,
     SubmenuIndexInfo,
     SubmenuIndexInfo,
     SubmenuIndexRestoreOriginal,
     SubmenuIndexRestoreOriginal,
@@ -33,10 +33,6 @@ void nfc_scene_saved_menu_on_enter(void* context) {
         submenu_add_item(
         submenu_add_item(
             submenu, "Emulate", SubmenuIndexEmulate, nfc_scene_saved_menu_submenu_callback, nfc);
             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_add_item(
         submenu, "Info", SubmenuIndexInfo, nfc_scene_saved_menu_submenu_callback, nfc);
         submenu, "Info", SubmenuIndexInfo, nfc_scene_saved_menu_submenu_callback, nfc);
     submenu_set_selected_item(
     submenu_set_selected_item(
@@ -44,11 +40,15 @@ void nfc_scene_saved_menu_on_enter(void* context) {
     if(nfc->dev->shadow_file_exist) {
     if(nfc->dev->shadow_file_exist) {
         submenu_add_item(
         submenu_add_item(
             submenu,
             submenu,
-            "Restore original",
+            "Restore to original",
             SubmenuIndexRestoreOriginal,
             SubmenuIndexRestoreOriginal,
             nfc_scene_saved_menu_submenu_callback,
             nfc_scene_saved_menu_submenu_callback,
             nfc);
             nfc);
     }
     }
+    submenu_add_item(
+        submenu, "Rename", SubmenuIndexRename, nfc_scene_saved_menu_submenu_callback, nfc);
+    submenu_add_item(
+        submenu, "Delete", SubmenuIndexDelete, nfc_scene_saved_menu_submenu_callback, nfc);
 
 
     view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewMenu);
     view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewMenu);
 }
 }
@@ -68,8 +68,8 @@ bool nfc_scene_saved_menu_on_event(void* context, SceneManagerEvent event) {
                 scene_manager_next_scene(nfc->scene_manager, NfcSceneEmulateUid);
                 scene_manager_next_scene(nfc->scene_manager, NfcSceneEmulateUid);
             }
             }
             consumed = true;
             consumed = true;
-        } else if(event.event == SubmenuIndexEdit) {
-            scene_manager_next_scene(nfc->scene_manager, NfcSceneSetUid);
+        } else if(event.event == SubmenuIndexRename) {
+            scene_manager_next_scene(nfc->scene_manager, NfcSceneSaveName);
             consumed = true;
             consumed = true;
         } else if(event.event == SubmenuIndexDelete) {
         } else if(event.event == SubmenuIndexDelete) {
             scene_manager_next_scene(nfc->scene_manager, NfcSceneDelete);
             scene_manager_next_scene(nfc->scene_manager, NfcSceneDelete);
@@ -78,12 +78,7 @@ bool nfc_scene_saved_menu_on_event(void* context, SceneManagerEvent event) {
             scene_manager_next_scene(nfc->scene_manager, NfcSceneDeviceInfo);
             scene_manager_next_scene(nfc->scene_manager, NfcSceneDeviceInfo);
             consumed = true;
             consumed = true;
         } else if(event.event == SubmenuIndexRestoreOriginal) {
         } else if(event.event == SubmenuIndexRestoreOriginal) {
-            if(!nfc_device_restore(nfc->dev, true)) {
-                scene_manager_search_and_switch_to_previous_scene(
-                    nfc->scene_manager, NfcSceneStart);
-            } else {
-                scene_manager_next_scene(nfc->scene_manager, NfcSceneRestoreOriginal);
-            }
+            scene_manager_next_scene(nfc->scene_manager, NfcSceneRestoreOriginalConfirm);
             consumed = true;
             consumed = true;
         }
         }
     }
     }

BIN
assets/icons/NFC/NFC_manual.png


BIN
assets/icons/NFC/Restoring.png


+ 4 - 0
furi/core/common_defines.h

@@ -92,6 +92,10 @@ extern "C" {
 #define FURI_BIT_SET(x, n) ((x) |= (1 << (n)))
 #define FURI_BIT_SET(x, n) ((x) |= (1 << (n)))
 #endif
 #endif
 
 
+#ifndef FURI_BIT_CLEAR
+#define FURI_BIT_CLEAR(x, n) ((x) &= ~(1 << (n)))
+#endif
+
 #ifndef FURI_IS_IRQ_MASKED
 #ifndef FURI_IS_IRQ_MASKED
 #define FURI_IS_IRQ_MASKED() (__get_PRIMASK() != 0U)
 #define FURI_IS_IRQ_MASKED() (__get_PRIMASK() != 0U)
 #endif
 #endif

+ 10 - 1
lib/nfc/nfc_worker.c

@@ -245,6 +245,9 @@ static bool nfc_worker_read_nfca(NfcWorker* nfc_worker, FuriHalNfcTxRxContext* t
             nfc_worker->dev_data->protocol = NfcDeviceProtocolUnknown;
             nfc_worker->dev_data->protocol = NfcDeviceProtocolUnknown;
         }
         }
         card_read = true;
         card_read = true;
+    } else {
+        nfc_worker->dev_data->protocol = NfcDeviceProtocolUnknown;
+        card_read = true;
     }
     }
 
 
     return card_read;
     return card_read;
@@ -321,8 +324,14 @@ void nfc_worker_emulate_uid(NfcWorker* nfc_worker) {
     FuriHalNfcDevData* data = &nfc_worker->dev_data->nfc_data;
     FuriHalNfcDevData* data = &nfc_worker->dev_data->nfc_data;
     NfcReaderRequestData* reader_data = &nfc_worker->dev_data->reader_data;
     NfcReaderRequestData* reader_data = &nfc_worker->dev_data->reader_data;
 
 
+    // TODO add support for RATS
+    // Now remove bit 6 in SAK to support ISO-14443A-3 emulation
+    // Need to save ATS to support ISO-14443A-4 emulation
+    uint8_t sak = data->sak;
+    FURI_BIT_CLEAR(sak, 5);
+
     while(nfc_worker->state == NfcWorkerStateUidEmulate) {
     while(nfc_worker->state == NfcWorkerStateUidEmulate) {
-        if(furi_hal_nfc_listen(data->uid, data->uid_len, data->atqa, data->sak, true, 100)) {
+        if(furi_hal_nfc_listen(data->uid, data->uid_len, data->atqa, sak, true, 100)) {
             if(furi_hal_nfc_tx_rx(&tx_rx, 100)) {
             if(furi_hal_nfc_tx_rx(&tx_rx, 100)) {
                 reader_data->size = tx_rx.rx_bits / 8;
                 reader_data->size = tx_rx.rx_bits / 8;
                 if(reader_data->size > 0) {
                 if(reader_data->size > 0) {