Преглед изворни кода

[FL-1723, FL-1662, FL-1870] NFC bug fixes (#745)

* nfc: fix notifications in read EMV sequence
* nfc: set focus on previously saved card
* nfc: add incorrect file format message
* mifare ultralight: increase size of max dump
* elements: draw multiline text only until it fits screen
* nfc: support variable PAN number length
* nfc: change AID display
* nfc: change worker custom event to prevent scene reenter
* nfc: double check for PAN tag
* nfc: fix edit card name appearance
* Nfc: read EMV card without name if PDOL is present.
* Desktop: increase unlock key press interval, switch to OS ticks instead of HAL.
* Desktop: remove debug logging

Co-authored-by: Aleksandr Kutuzov <alleteam@gmail.com>
gornekich пре 4 година
родитељ
комит
42e553bad5

+ 1 - 1
applications/desktop/views/desktop_locked.c

@@ -124,7 +124,7 @@ bool desktop_locked_input(InputEvent* event, void* context) {
         desktop_locked_update_hint_timeout(locked_view);
 
         if(event->key == InputKeyBack) {
-            uint32_t press_time = HAL_GetTick();
+            uint32_t press_time = osKernelGetTickCount();
 
             // check if pressed sequentially
             if(press_time - locked_view->lock_lastpress > UNLOCK_RST_TIMEOUT) {

+ 1 - 1
applications/desktop/views/desktop_locked.h

@@ -6,7 +6,7 @@
 #include <gui/elements.h>
 #include <furi.h>
 
-#define UNLOCK_RST_TIMEOUT 200
+#define UNLOCK_RST_TIMEOUT 300
 #define UNLOCK_CNT 2 // 3 actually
 
 typedef enum {

+ 1 - 1
applications/gui/elements.c

@@ -278,7 +278,7 @@ void elements_multiline_text(Canvas* canvas, uint8_t x, uint8_t y, const char* t
         canvas_draw_str(canvas, x, y, string_get_cstr(str));
         start = end + 1;
         y += font_height;
-    } while(end);
+    } while(end && y < 64);
     string_clear(str);
 }
 

+ 15 - 5
applications/nfc/nfc_device.c

@@ -200,8 +200,9 @@ uint16_t nfc_device_prepare_bank_card_string(NfcDevice* dev, string_t bank_card_
     for(uint8_t i = 0; i < data->aid_len; i++) {
         string_cat_printf(bank_card_string, " %02X", data->aid[i]);
     }
-    string_cat_printf(bank_card_string, "\nName: %s\nNumber:", data->name);
-    for(uint8_t i = 0; i < sizeof(data->number); i++) {
+    string_cat_printf(
+        bank_card_string, "\nName: %s\nNumber len: %d\nNumber:", data->name, data->number_len);
+    for(uint8_t i = 0; i < data->number_len; i++) {
         string_cat_printf(bank_card_string, " %02X", data->number[i]);
     }
     if(data->exp_mon) {
@@ -242,9 +243,15 @@ bool nfc_device_parse_bank_card_string(NfcDevice* dev, string_t bank_card_string
         }
         ws = string_search_char(bank_card_string, '\n');
         string_right(bank_card_string, ws + 1);
+        res = sscanf(string_get_cstr(bank_card_string), "Number len: %hhu", &data->number_len);
+        if(res != 1) {
+            break;
+        }
+        ws = string_search_char(bank_card_string, '\n');
+        string_right(bank_card_string, ws + 1);
         // strlen("Number: ") = 8
         string_right(bank_card_string, 8);
-        if(!nfc_device_read_hex(bank_card_string, data->number, sizeof(data->number), 1)) {
+        if(!nfc_device_read_hex(bank_card_string, data->number, data->number_len, 1)) {
             break;
         }
         parsed = true;
@@ -415,6 +422,10 @@ static bool nfc_device_load_data(FileWorker* file_worker, string_t path, NfcDevi
         parsed = true;
     } while(0);
 
+    if(!parsed) {
+        file_worker_show_error(file_worker, "Can not parse\nfile");
+    }
+
     string_clear(temp_string);
     return parsed;
 }
@@ -451,7 +462,7 @@ bool nfc_file_select(NfcDevice* dev) {
         nfc_app_extension,
         dev->file_name,
         sizeof(dev->file_name),
-        NULL);
+        dev->dev_name);
     if(res) {
         string_t dev_str;
 
@@ -474,7 +485,6 @@ void nfc_device_clear(NfcDevice* dev) {
     furi_assert(dev);
 
     memset(&dev->dev_data, 0, sizeof(dev->dev_data));
-    nfc_device_set_name(dev, "");
     dev->format = NfcDeviceSaveFormatUid;
 }
 

+ 3 - 2
applications/nfc/nfc_device.h

@@ -40,7 +40,8 @@ typedef struct {
     char name[32];
     uint8_t aid[16];
     uint16_t aid_len;
-    uint8_t number[8];
+    uint8_t number[10];
+    uint8_t number_len;
     uint8_t exp_mon;
     uint8_t exp_year;
     uint16_t country_code;
@@ -57,7 +58,7 @@ typedef struct {
 
 typedef struct {
     NfcDeviceData dev_data;
-    char dev_name[NFC_DEV_NAME_MAX_LEN];
+    char dev_name[NFC_DEV_NAME_MAX_LEN + 1];
     char file_name[NFC_FILE_NAME_MAX_LEN];
     NfcDeviceSaveFormat format;
     bool shadow_file_exist;

+ 2 - 0
applications/nfc/nfc_i.h

@@ -26,6 +26,8 @@
 
 #include <nfc/scenes/nfc_scene.h>
 
+#define NFC_SEND_NOTIFICATION_FALSE (0UL)
+#define NFC_SEND_NOTIFICATION_TRUE (1UL)
 #define NFC_TEXT_STORE_SIZE 128
 
 struct Nfc {

+ 7 - 4
applications/nfc/nfc_worker.c

@@ -268,8 +268,10 @@ void nfc_worker_read_emv(NfcWorker* nfc_worker) {
                 if(emv_decode_select_app_response(rx_buff, *rx_len, &emv_app)) {
                     FURI_LOG_I(NFC_WORKER_TAG, "Card name: %s", emv_app.name);
                     memcpy(result->emv_data.name, emv_app.name, sizeof(emv_app.name));
+                } else if(emv_app.pdol.size > 0) {
+                    FURI_LOG_W(NFC_WORKER_TAG, "Can't find card name, but PDOL is present.");
                 } else {
-                    FURI_LOG_E(NFC_WORKER_TAG, "Can't read card name");
+                    FURI_LOG_E(NFC_WORKER_TAG, "Can't find card name or PDOL");
                     furi_hal_nfc_deactivate();
                     continue;
                 }
@@ -284,8 +286,8 @@ void nfc_worker_read_emv(NfcWorker* nfc_worker) {
                 }
                 if(emv_decode_get_proc_opt(rx_buff, *rx_len, &emv_app)) {
                     FURI_LOG_I(NFC_WORKER_TAG, "Card number parsed");
-                    memcpy(
-                        result->emv_data.number, emv_app.card_number, sizeof(emv_app.card_number));
+                    result->emv_data.number_len = emv_app.card_number_len;
+                    memcpy(result->emv_data.number, emv_app.card_number, emv_app.card_number_len);
                     // Notify caller and exit
                     if(nfc_worker->callback) {
                         nfc_worker->callback(nfc_worker->context);
@@ -320,10 +322,11 @@ void nfc_worker_read_emv(NfcWorker* nfc_worker) {
                     }
                     if(pan_found) {
                         FURI_LOG_I(NFC_WORKER_TAG, "Card PAN found");
+                        result->emv_data.number_len = emv_app.card_number_len;
                         memcpy(
                             result->emv_data.number,
                             emv_app.card_number,
-                            sizeof(emv_app.card_number));
+                            result->emv_data.number_len);
                         if(emv_app.exp_month) {
                             result->emv_data.exp_mon = emv_app.exp_month;
                             result->emv_data.exp_year = emv_app.exp_year;

+ 1 - 1
applications/nfc/scenes/nfc_scene_device_info.c

@@ -111,7 +111,7 @@ void nfc_scene_device_info_on_enter(void* context) {
         NfcEmvData* emv_data = &nfc->dev.dev_data.emv_data;
         BankCard* bank_card = nfc->bank_card;
         bank_card_set_name(bank_card, emv_data->name);
-        bank_card_set_number(bank_card, emv_data->number);
+        bank_card_set_number(bank_card, emv_data->number, emv_data->number_len);
         bank_card_set_back_callback(bank_card, nfc_scene_device_info_bank_card_callback, nfc);
         if(emv_data->exp_mon) {
             bank_card_set_exp_date(bank_card, emv_data->exp_mon, emv_data->exp_year);

+ 2 - 0
applications/nfc/scenes/nfc_scene_mifare_ul_menu.c

@@ -33,6 +33,8 @@ bool nfc_scene_mifare_ul_menu_on_event(void* context, SceneManagerEvent event) {
             scene_manager_set_scene_state(
                 nfc->scene_manager, NfcSceneMifareUlMenu, SubmenuIndexSave);
             nfc->dev.format = NfcDeviceSaveFormatMifareUl;
+            // Clear device name
+            nfc_device_set_name(&nfc->dev, "");
             scene_manager_next_scene(nfc->scene_manager, NfcSceneSaveName);
             return true;
         } else if(event.event == SubmenuIndexEmulate) {

+ 1 - 1
applications/nfc/scenes/nfc_scene_read_card.c

@@ -1,6 +1,6 @@
 #include "../nfc_i.h"
 
-#define NFC_READ_CARD_CUSTOM_EVENT (0UL)
+#define NFC_READ_CARD_CUSTOM_EVENT (10UL)
 
 void nfc_read_card_worker_callback(void* context) {
     Nfc* nfc = (Nfc*)context;

+ 2 - 3
applications/nfc/scenes/nfc_scene_read_card_success.c

@@ -11,9 +11,6 @@ void nfc_scene_read_card_success_dialog_callback(DialogExResult result, void* co
 void nfc_scene_read_card_success_on_enter(void* context) {
     Nfc* nfc = (Nfc*)context;
 
-    // Clear device name
-    nfc_device_set_name(&nfc->dev, "");
-
     // Send notification
     notification_message(nfc->notifications, &sequence_success);
 
@@ -70,6 +67,8 @@ bool nfc_scene_read_card_success_on_event(void* context, SceneManagerEvent event
         if(event.event == DialogExResultLeft) {
             return scene_manager_previous_scene(nfc->scene_manager);
         } else if(event.event == DialogExResultRight) {
+            // Clear device name
+            nfc_device_set_name(&nfc->dev, "");
             scene_manager_next_scene(nfc->scene_manager, NfcSceneCardMenu);
             return true;
         }

+ 3 - 1
applications/nfc/scenes/nfc_scene_read_emv_app.c

@@ -1,6 +1,6 @@
 #include "../nfc_i.h"
 
-#define NFC_READ_EMV_APP_CUSTOM_EVENT (0UL)
+#define NFC_READ_EMV_APP_CUSTOM_EVENT (10UL)
 
 void nfc_read_emv_app_worker_callback(void* context) {
     Nfc* nfc = (Nfc*)context;
@@ -30,6 +30,8 @@ bool nfc_scene_read_emv_app_on_event(void* context, SceneManagerEvent event) {
 
     if(event.type == SceneManagerEventTypeCustom) {
         if(event.event == NFC_READ_EMV_APP_CUSTOM_EVENT) {
+            scene_manager_set_scene_state(
+                nfc->scene_manager, NfcSceneReadEmvAppSuccess, NFC_SEND_NOTIFICATION_TRUE);
             scene_manager_next_scene(nfc->scene_manager, NfcSceneReadEmvAppSuccess);
             return true;
         }

+ 11 - 2
applications/nfc/scenes/nfc_scene_read_emv_app_success.c

@@ -26,12 +26,13 @@ void nfc_scene_read_emv_app_success_on_enter(void* context) {
     bool aid_found = nfc_emv_parser_get_aid_name(emv_data->aid, emv_data->aid_len, aid);
     if(!aid_found) {
         for(uint8_t i = 0; i < emv_data->aid_len; i++) {
-            string_cat_printf(aid, " %02X", emv_data->aid[i]);
+            string_cat_printf(aid, "%02X", emv_data->aid[i]);
         }
     }
     nfc_text_store_set(
         nfc,
-        NFC_SCENE_READ_SUCCESS_SHIFT "UID: %02X %02X %02X %02X \n\n%s",
+        NFC_SCENE_READ_SUCCESS_SHIFT "UID: %02X %02X %02X %02X \n" NFC_SCENE_READ_SUCCESS_SHIFT
+                                     "Application:\n%s",
         nfc_data->uid[0],
         nfc_data->uid[1],
         nfc_data->uid[2],
@@ -42,6 +43,14 @@ void nfc_scene_read_emv_app_success_on_enter(void* context) {
     dialog_ex_set_context(dialog_ex, nfc);
     dialog_ex_set_result_callback(dialog_ex, nfc_scene_read_emv_app_success_dialog_callback);
 
+    // Send notification
+    if(scene_manager_get_scene_state(nfc->scene_manager, NfcSceneReadEmvAppSuccess) ==
+       NFC_SEND_NOTIFICATION_TRUE) {
+        notification_message(nfc->notifications, &sequence_success);
+        scene_manager_set_scene_state(
+            nfc->scene_manager, NfcSceneReadEmvAppSuccess, NFC_SEND_NOTIFICATION_FALSE);
+    }
+
     view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewDialogEx);
 }
 

+ 3 - 4
applications/nfc/scenes/nfc_scene_read_emv_data.c

@@ -1,6 +1,6 @@
 #include "../nfc_i.h"
 
-#define NFC_READ_EMV_DATA_CUSTOM_EVENT (0UL)
+#define NFC_READ_EMV_DATA_CUSTOM_EVENT (10UL)
 
 void nfc_read_emv_data_worker_callback(void* context) {
     Nfc* nfc = (Nfc*)context;
@@ -32,6 +32,8 @@ bool nfc_scene_read_emv_data_on_event(void* context, SceneManagerEvent event) {
 
     if(event.type == SceneManagerEventTypeCustom) {
         if(event.event == NFC_READ_EMV_DATA_CUSTOM_EVENT) {
+            scene_manager_set_scene_state(
+                nfc->scene_manager, NfcSceneReadEmvDataSuccess, NFC_SEND_NOTIFICATION_TRUE);
             scene_manager_next_scene(nfc->scene_manager, NfcSceneReadEmvDataSuccess);
             return true;
         }
@@ -48,9 +50,6 @@ void nfc_scene_read_emv_data_on_exit(void* context) {
     // Stop worker
     nfc_worker_stop(nfc->worker);
 
-    // Send notification
-    notification_message(nfc->notifications, &sequence_success);
-
     // Clear view
     Popup* popup = nfc->popup;
     popup_set_header(popup, NULL, 0, 0, AlignCenter, AlignBottom);

+ 19 - 17
applications/nfc/scenes/nfc_scene_read_emv_data_success.c

@@ -16,9 +16,6 @@ void nfc_scene_read_emv_data_success_on_enter(void* context) {
     NfcEmvData* emv_data = &nfc->dev.dev_data.emv_data;
     NfcDeviceCommonData* nfc_data = &nfc->dev.dev_data.nfc_data;
 
-    // Clear device name
-    nfc_device_set_name(&nfc->dev, "");
-
     // Setup Custom Widget view
     // Add frame
     widget_add_frame_element(nfc->widget, 0, 0, 128, 64, 6);
@@ -39,20 +36,15 @@ void nfc_scene_read_emv_data_success_on_enter(void* context) {
     widget_add_string_element(
         nfc->widget, 64, 3, AlignCenter, AlignTop, FontSecondary, nfc->dev.dev_data.emv_data.name);
     // Add cad number
-    char pan_str[32];
-    snprintf(
-        pan_str,
-        sizeof(pan_str),
-        "%02X%02X %02X%02X %02X%02X %02X%02X",
-        emv_data->number[0],
-        emv_data->number[1],
-        emv_data->number[2],
-        emv_data->number[3],
-        emv_data->number[4],
-        emv_data->number[5],
-        emv_data->number[6],
-        emv_data->number[7]);
-    widget_add_string_element(nfc->widget, 64, 13, AlignCenter, AlignTop, FontSecondary, pan_str);
+    string_t pan_str;
+    string_init(pan_str);
+    for(uint8_t i = 0; i < emv_data->number_len; i += 2) {
+        string_cat_printf(pan_str, "%02X%02X ", emv_data->number[i], emv_data->number[i + 1]);
+    }
+    string_strim(pan_str);
+    widget_add_string_element(
+        nfc->widget, 64, 13, AlignCenter, AlignTop, FontSecondary, string_get_cstr(pan_str));
+    string_clear(pan_str);
     // Parse country code
     string_t country_name;
     string_init(country_name);
@@ -110,6 +102,14 @@ void nfc_scene_read_emv_data_success_on_enter(void* context) {
         widget_add_string_element(nfc->widget, 7, 32, AlignLeft, AlignTop, FontSecondary, exp_str);
     }
 
+    // Send notification
+    if(scene_manager_get_scene_state(nfc->scene_manager, NfcSceneReadEmvDataSuccess) ==
+       NFC_SEND_NOTIFICATION_TRUE) {
+        notification_message(nfc->notifications, &sequence_success);
+        scene_manager_set_scene_state(
+            nfc->scene_manager, NfcSceneReadEmvDataSuccess, NFC_SEND_NOTIFICATION_FALSE);
+    }
+
     view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewWidget);
 }
 
@@ -121,6 +121,8 @@ bool nfc_scene_read_emv_data_success_on_event(void* context, SceneManagerEvent e
             return scene_manager_search_and_switch_to_previous_scene(
                 nfc->scene_manager, NfcSceneReadEmvAppSuccess);
         } else if(event.event == GuiButtonTypeRight) {
+            // Clear device name
+            nfc_device_set_name(&nfc->dev, "");
             nfc->dev.format = NfcDeviceSaveFormatBankCard;
             scene_manager_next_scene(nfc->scene_manager, NfcSceneSaveName);
             return true;

+ 1 - 1
applications/nfc/scenes/nfc_scene_read_mifare_ul.c

@@ -1,6 +1,6 @@
 #include "../nfc_i.h"
 
-#define NFC_READ_MIFARE_UL_CUSTOM_EVENT (0UL)
+#define NFC_READ_MIFARE_UL_CUSTOM_EVENT (10UL)
 
 void nfc_read_mifare_ul_worker_callback(void* context) {
     Nfc* nfc = (Nfc*)context;

+ 0 - 3
applications/nfc/scenes/nfc_scene_read_mifare_ul_success.c

@@ -23,9 +23,6 @@ void nfc_scene_read_mifare_ul_success_text_box_callback(void* context) {
 void nfc_scene_read_mifare_ul_success_on_enter(void* context) {
     Nfc* nfc = (Nfc*)context;
 
-    // Clear device name
-    nfc_device_set_name(&nfc->dev, "");
-
     // Send notification
     notification_message(nfc->notifications, &sequence_success);
 

+ 1 - 1
applications/nfc/scenes/nfc_scene_save_name.c

@@ -43,7 +43,7 @@ bool nfc_scene_save_name_on_event(void* context, SceneManagerEvent event) {
             if(scene_manager_has_previous_scene(nfc->scene_manager, NfcSceneSetUid)) {
                 nfc->dev.dev_data.nfc_data = nfc->dev_edit_data;
             }
-            memcpy(&nfc->dev.dev_name, nfc->text_store, strlen(nfc->text_store));
+            strlcpy(nfc->dev.dev_name, nfc->text_store, strlen(nfc->text_store) + 1);
             if(nfc_device_save(&nfc->dev, nfc->text_store)) {
                 scene_manager_next_scene(nfc->scene_manager, NfcSceneSaveSuccess);
                 return true;

+ 2 - 1
applications/nfc/scenes/nfc_scene_set_type.c

@@ -14,7 +14,8 @@ void nfc_scene_set_type_submenu_callback(void* context, uint32_t index) {
 void nfc_scene_set_type_on_enter(void* context) {
     Nfc* nfc = (Nfc*)context;
     Submenu* submenu = nfc->submenu;
-
+    // Clear device name
+    nfc_device_set_name(&nfc->dev, "");
     submenu_add_item(
         submenu, "NFC-A 7-bytes UID", SubmenuIndexNFCA7, nfc_scene_set_type_submenu_callback, nfc);
     submenu_add_item(

+ 2 - 2
applications/nfc/views/bank_card.c

@@ -35,12 +35,12 @@ void bank_card_set_name(BankCard* bank_card, char* name) {
         bank_card->widget, 64, 6, AlignCenter, AlignTop, FontSecondary, name);
 }
 
-void bank_card_set_number(BankCard* bank_card, uint8_t* number) {
+void bank_card_set_number(BankCard* bank_card, uint8_t* number, uint8_t len) {
     furi_assert(bank_card);
     furi_assert(number);
     string_t num_str;
     string_init(num_str);
-    for(uint8_t i = 0; i < 8; i += 2) {
+    for(uint8_t i = 0; i < len; i += 2) {
         string_cat_printf(num_str, "%02X%02X ", number[i], number[i + 1]);
     }
     // Add number

+ 1 - 1
applications/nfc/views/bank_card.h

@@ -17,7 +17,7 @@ void bank_card_set_back_callback(BankCard* bank_card, ButtonCallback callback, v
 
 void bank_card_set_name(BankCard* bank_card, char* name);
 
-void bank_card_set_number(BankCard* bank_card, uint8_t* number);
+void bank_card_set_number(BankCard* bank_card, uint8_t* number, uint8_t len);
 
 void bank_card_set_exp_date(BankCard* bank_card, uint8_t mon, uint8_t year);
 

+ 7 - 3
lib/nfc_protocols/emv_decoder.c

@@ -198,7 +198,8 @@ uint16_t emv_prepare_get_proc_opt(uint8_t* dest, EmvApplication* app) {
 bool emv_decode_get_proc_opt(uint8_t* buff, uint16_t len, EmvApplication* app) {
     for(uint16_t i = 0; i < len; i++) {
         if(buff[i] == EMV_TAG_CARD_NUM) {
-            memcpy(app->card_number, &buff[i + 2], 8);
+            app->card_number_len = 8;
+            memcpy(app->card_number, &buff[i + 2], app->card_number_len);
             return true;
         } else if(buff[i] == EMV_TAG_AFL) {
             app->afl.size = emv_parse_TLV(app->afl.data, buff, &i);
@@ -225,8 +226,11 @@ bool emv_decode_read_sfi_record(uint8_t* buff, uint16_t len, EmvApplication* app
     bool pan_parsed = false;
     for(uint16_t i = 0; i < len; i++) {
         if(buff[i] == EMV_TAG_PAN) {
-            memcpy(app->card_number, &buff[i + 2], 8);
-            pan_parsed = true;
+            if(buff[i + 1] == 8 || buff[i + 1] == 10) {
+                app->card_number_len = buff[i + 1];
+                memcpy(app->card_number, &buff[i + 2], app->card_number_len);
+                pan_parsed = true;
+            }
         } else if(emv_decode_search_tag_u16_r(EMV_TAG_EXP_DATE, buff, &i)) {
             app->exp_year = buff[i++];
             app->exp_month = buff[i++];

+ 2 - 1
lib/nfc_protocols/emv_decoder.h

@@ -38,7 +38,8 @@ typedef struct {
     uint8_t aid[16];
     uint8_t aid_len;
     char name[32];
-    uint8_t card_number[8];
+    uint8_t card_number[10];
+    uint8_t card_number_len;
     uint8_t exp_month;
     uint8_t exp_year;
     uint16_t country_code;

+ 1 - 1
lib/nfc_protocols/mifare_ultralight.h

@@ -4,7 +4,7 @@
 #include <stdbool.h>
 #include <string.h>
 
-#define MF_UL_MAX_DUMP_SIZE 255
+#define MF_UL_MAX_DUMP_SIZE 1024
 
 #define MF_UL_TEARING_FLAG_DEFAULT (0xBD)