From 29e5e57a7011db12ac10d053180fdd7f0054313b Mon Sep 17 00:00:00 2001 From: Dmitry Pavlov Date: Tue, 19 Apr 2022 14:07:14 +0300 Subject: [PATCH 1/5] [FL-2461] IR: change word from key to button (#1119) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 2461 ir renamed menu items * Renamed the key to the button Co-authored-by: あく --- applications/infrared/scene/infrared_app_scene_edit.cpp | 6 +++--- .../infrared/scene/infrared_app_scene_edit_key_select.cpp | 5 +++-- .../infrared/scene/infrared_app_scene_edit_rename.cpp | 2 +- .../infrared/scene/infrared_app_scene_learn_enter_name.cpp | 2 +- 4 files changed, 8 insertions(+), 7 deletions(-) diff --git a/applications/infrared/scene/infrared_app_scene_edit.cpp b/applications/infrared/scene/infrared_app_scene_edit.cpp index 73e9153e9..5a2ae72ff 100644 --- a/applications/infrared/scene/infrared_app_scene_edit.cpp +++ b/applications/infrared/scene/infrared_app_scene_edit.cpp @@ -23,9 +23,9 @@ void InfraredAppSceneEdit::on_enter(InfraredApp* app) { InfraredAppViewManager* view_manager = app->get_view_manager(); Submenu* submenu = view_manager->get_submenu(); - submenu_add_item(submenu, "Add Key", SubmenuIndexAddKey, submenu_callback, app); - submenu_add_item(submenu, "Rename Key", SubmenuIndexRenameKey, submenu_callback, app); - submenu_add_item(submenu, "Delete Key", SubmenuIndexDeleteKey, submenu_callback, app); + submenu_add_item(submenu, "Add Button", SubmenuIndexAddKey, submenu_callback, app); + submenu_add_item(submenu, "Rename Button", SubmenuIndexRenameKey, submenu_callback, app); + submenu_add_item(submenu, "Delete Button", SubmenuIndexDeleteKey, submenu_callback, app); submenu_add_item(submenu, "Rename Remote", SubmenuIndexRenameRemote, submenu_callback, app); submenu_add_item(submenu, "Delete Remote", SubmenuIndexDeleteRemote, submenu_callback, app); submenu_set_selected_item(submenu, submenu_item_selected); diff --git a/applications/infrared/scene/infrared_app_scene_edit_key_select.cpp b/applications/infrared/scene/infrared_app_scene_edit_key_select.cpp index 7f94fb152..49142c212 100644 --- a/applications/infrared/scene/infrared_app_scene_edit_key_select.cpp +++ b/applications/infrared/scene/infrared_app_scene_edit_key_select.cpp @@ -16,8 +16,9 @@ void InfraredAppSceneEditKeySelect::on_enter(InfraredApp* app) { Submenu* submenu = view_manager->get_submenu(); int item_number = 0; - const char* header = - app->get_edit_action() == InfraredApp::EditAction::Rename ? "Rename key:" : "Delete key:"; + const char* header = app->get_edit_action() == InfraredApp::EditAction::Rename ? + "Rename Button:" : + "Delete Button:"; submenu_set_header(submenu, header); auto remote_manager = app->get_remote_manager(); diff --git a/applications/infrared/scene/infrared_app_scene_edit_rename.cpp b/applications/infrared/scene/infrared_app_scene_edit_rename.cpp index 0bdd90ac8..dc63c64b1 100644 --- a/applications/infrared/scene/infrared_app_scene_edit_rename.cpp +++ b/applications/infrared/scene/infrared_app_scene_edit_rename.cpp @@ -14,7 +14,7 @@ void InfraredAppSceneEditRename::on_enter(InfraredApp* app) { strncpy(buffer_str, button_name.c_str(), max_len); buffer_str[max_len + 1] = 0; enter_name_length = max_len; - text_input_set_header_text(text_input, "Name the key"); + text_input_set_header_text(text_input, "Name the button"); } else { auto remote_name = remote_manager->get_remote_name(); strncpy(app->get_text_store(0), remote_name.c_str(), app->get_text_store_size()); diff --git a/applications/infrared/scene/infrared_app_scene_learn_enter_name.cpp b/applications/infrared/scene/infrared_app_scene_learn_enter_name.cpp index e0f2ebd13..0f148e807 100644 --- a/applications/infrared/scene/infrared_app_scene_learn_enter_name.cpp +++ b/applications/infrared/scene/infrared_app_scene_learn_enter_name.cpp @@ -20,7 +20,7 @@ void InfraredAppSceneLearnEnterName::on_enter(InfraredApp* app) { app->set_text_store(0, "RAW_%d", raw_signal.timings_cnt); } - text_input_set_header_text(text_input, "Name the key"); + text_input_set_header_text(text_input, "Name the button"); text_input_set_result_callback( text_input, InfraredApp::text_input_callback, From e55d1572dac6279d83ab45b19bc9b98ed89ef093 Mon Sep 17 00:00:00 2001 From: Dmitry Pavlov Date: Tue, 19 Apr 2022 18:15:42 +0300 Subject: [PATCH 2/5] [FL-2343] IR: Rename the left button #1134 --- applications/infrared/scene/infrared_app_scene_edit_delete.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/applications/infrared/scene/infrared_app_scene_edit_delete.cpp b/applications/infrared/scene/infrared_app_scene_edit_delete.cpp index 0818b6fb8..d49acec52 100644 --- a/applications/infrared/scene/infrared_app_scene_edit_delete.cpp +++ b/applications/infrared/scene/infrared_app_scene_edit_delete.cpp @@ -51,7 +51,7 @@ void InfraredAppSceneEditDelete::on_enter(InfraredApp* app) { dialog_ex_set_text(dialog_ex, app->get_text_store(0), 64, 31, AlignCenter, AlignCenter); dialog_ex_set_icon(dialog_ex, 0, 0, NULL); - dialog_ex_set_left_button_text(dialog_ex, "Back"); + dialog_ex_set_left_button_text(dialog_ex, "Cancel"); dialog_ex_set_right_button_text(dialog_ex, "Delete"); dialog_ex_set_result_callback(dialog_ex, dialog_result_callback); dialog_ex_set_context(dialog_ex, app); From 956788c09b5551ad02ca296dffc5dbbc430d83b3 Mon Sep 17 00:00:00 2001 From: gornekich Date: Tue, 19 Apr 2022 18:23:58 +0300 Subject: [PATCH 3/5] [FL-2369] NFC refactoring (#1095) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * nfc: clean up scenes * nfc worker: remove field on from worker * nfc worker: move full data exchange to furi hal * nfc_device: check UID length * nfc protocol: introduce mifare common API * nfc: move common data to furi hal nfc * nfc: rename emv_decoder -> emv * nfc: move emv data structure to emv lib * nfc: remove deactivate after detection * nfc: rework furi hal nfc detect * nfc: clean up CLI commands and type * nfc: remove unused includes and function * nfc: add TxRxType enum * nfc: read mifare ultralight refactoring * nfc: refactore mifare ultralight start * rfal: fix custom data exchange * nfc: refactor read bank card * nfc: refactor read emv application * nfc: refactor emv test emulation * nfc: refactor uid emulation * nfc: add limit to uid emulation logger * fix source formatting * furi_hal_nfc: fix data exchange full * nfc: fix mifare ultralight type load Co-authored-by: あく --- applications/nfc/nfc.c | 6 +- applications/nfc/nfc_cli.c | 44 +- applications/nfc/nfc_device.c | 29 +- applications/nfc/nfc_device.h | 37 +- applications/nfc/nfc_i.h | 2 +- applications/nfc/nfc_types.c | 44 +- applications/nfc/nfc_types.h | 12 +- applications/nfc/nfc_worker.c | 747 ++++-------------- applications/nfc/nfc_worker.h | 6 +- applications/nfc/nfc_worker_i.h | 15 +- applications/nfc/scenes/nfc_scene_card_menu.c | 10 +- applications/nfc/scenes/nfc_scene_config.h | 1 - applications/nfc/scenes/nfc_scene_debug.c | 8 +- applications/nfc/scenes/nfc_scene_delete.c | 49 +- .../nfc/scenes/nfc_scene_delete_success.c | 24 +- .../nfc/scenes/nfc_scene_device_info.c | 49 +- .../scenes/nfc_scene_emulate_apdu_sequence.c | 18 +- .../nfc/scenes/nfc_scene_emulate_mifare_ul.c | 16 +- .../nfc/scenes/nfc_scene_emulate_uid.c | 16 +- applications/nfc/scenes/nfc_scene_field.c | 11 +- .../nfc/scenes/nfc_scene_file_select.c | 2 +- .../nfc/scenes/nfc_scene_mifare_desfire_app.c | 17 +- .../scenes/nfc_scene_mifare_desfire_data.c | 17 +- .../scenes/nfc_scene_mifare_desfire_menu.c | 14 +- .../nfc/scenes/nfc_scene_mifare_ul_menu.c | 20 +- .../nfc/scenes/nfc_scene_not_implemented.c | 42 - applications/nfc/scenes/nfc_scene_read_card.c | 21 +- .../nfc/scenes/nfc_scene_read_card_success.c | 22 +- .../nfc/scenes/nfc_scene_read_emv_app.c | 21 +- .../scenes/nfc_scene_read_emv_app_success.c | 84 +- .../nfc/scenes/nfc_scene_read_emv_data.c | 23 +- .../scenes/nfc_scene_read_emv_data_success.c | 40 +- .../scenes/nfc_scene_read_mifare_desfire.c | 21 +- .../nfc_scene_read_mifare_desfire_success.c | 11 +- .../nfc/scenes/nfc_scene_read_mifare_ul.c | 3 +- .../scenes/nfc_scene_read_mifare_ul_success.c | 22 +- .../nfc/scenes/nfc_scene_restore_original.c | 17 +- .../scenes/nfc_scene_run_emv_app_confirm.c | 27 +- applications/nfc/scenes/nfc_scene_save_name.c | 15 +- .../nfc/scenes/nfc_scene_save_success.c | 17 +- .../nfc/scenes/nfc_scene_saved_menu.c | 8 +- applications/nfc/scenes/nfc_scene_set_atqa.c | 13 +- applications/nfc/scenes/nfc_scene_set_sak.c | 13 +- applications/nfc/scenes/nfc_scene_set_type.c | 15 +- applications/nfc/scenes/nfc_scene_set_uid.c | 11 +- applications/nfc/scenes/nfc_scene_start.c | 8 +- firmware/targets/f7/furi_hal/furi_hal_nfc.c | 155 ++-- .../targets/furi_hal_include/furi_hal_nfc.h | 86 +- lib/ST25RFAL002/source/rfal_isoDep.c | 2 +- lib/ST25RFAL002/source/rfal_nfc.c | 20 +- lib/nfc_protocols/{emv_decoder.c => emv.c} | 298 +++++-- lib/nfc_protocols/emv.h | 87 ++ lib/nfc_protocols/emv_decoder.h | 67 -- lib/nfc_protocols/mifare_classic.c | 18 +- lib/nfc_protocols/mifare_common.c | 17 + lib/nfc_protocols/mifare_common.h | 12 + lib/nfc_protocols/mifare_ultralight.c | 459 ++++++----- lib/nfc_protocols/mifare_ultralight.h | 61 +- 58 files changed, 1349 insertions(+), 1601 deletions(-) delete mode 100644 applications/nfc/scenes/nfc_scene_not_implemented.c rename lib/nfc_protocols/{emv_decoder.c => emv.c} (55%) create mode 100755 lib/nfc_protocols/emv.h delete mode 100755 lib/nfc_protocols/emv_decoder.h create mode 100644 lib/nfc_protocols/mifare_common.c create mode 100644 lib/nfc_protocols/mifare_common.h diff --git a/applications/nfc/nfc.c b/applications/nfc/nfc.c index a249f85e7..e59896e3e 100755 --- a/applications/nfc/nfc.c +++ b/applications/nfc/nfc.c @@ -3,19 +3,19 @@ bool nfc_custom_event_callback(void* context, uint32_t event) { furi_assert(context); - Nfc* nfc = (Nfc*)context; + Nfc* nfc = context; return scene_manager_handle_custom_event(nfc->scene_manager, event); } bool nfc_back_event_callback(void* context) { furi_assert(context); - Nfc* nfc = (Nfc*)context; + Nfc* nfc = context; return scene_manager_handle_back_event(nfc->scene_manager); } void nfc_tick_event_callback(void* context) { furi_assert(context); - Nfc* nfc = (Nfc*)context; + Nfc* nfc = context; scene_manager_handle_tick_event(nfc->scene_manager); } diff --git a/applications/nfc/nfc_cli.c b/applications/nfc/nfc_cli.c index 98024e7da..52c971ef4 100755 --- a/applications/nfc/nfc_cli.c +++ b/applications/nfc/nfc_cli.c @@ -16,40 +16,35 @@ static void nfc_cli_print_usage() { } } -void nfc_cli_detect(Cli* cli, string_t args) { +static void nfc_cli_detect(Cli* cli, string_t args) { // Check if nfc worker is not busy if(furi_hal_nfc_is_busy()) { printf("Nfc is busy\r\n"); return; } - rfalNfcDevice* dev_list; - uint8_t dev_cnt = 0; + + FuriHalNfcDevData dev_data = {}; bool cmd_exit = false; furi_hal_nfc_exit_sleep(); printf("Detecting nfc...\r\nPress Ctrl+C to abort\r\n"); while(!cmd_exit) { cmd_exit |= cli_cmd_interrupt_received(cli); - cmd_exit |= furi_hal_nfc_detect(&dev_list, &dev_cnt, 400, true); - if(dev_cnt > 0) { - printf("Found %d devices\r\n", dev_cnt); - for(uint8_t i = 0; i < dev_cnt; i++) { - printf("%d found: %s ", i + 1, nfc_get_rfal_type(dev_list[i].type)); - if(dev_list[i].type == RFAL_NFC_LISTEN_TYPE_NFCA) { - printf("type: %s, ", nfc_get_nfca_type(dev_list[i].dev.nfca.type)); - } - printf("UID length: %d, UID:", dev_list[i].nfcidLen); - for(uint8_t j = 0; j < dev_list[i].nfcidLen; j++) { - printf("%02X", dev_list[i].nfcid[j]); - } - printf("\r\n"); + if(furi_hal_nfc_detect(&dev_data, 400)) { + printf("found: %s ", nfc_get_dev_type(dev_data.type)); + printf("UID length: %d, UID:", dev_data.uid_len); + for(size_t i = 0; i < dev_data.uid_len; i++) { + printf("%02X", dev_data.uid[i]); } + printf("\r\n"); + break; } + furi_hal_nfc_sleep(); osDelay(50); } - furi_hal_nfc_deactivate(); + furi_hal_nfc_sleep(); } -void nfc_cli_emulate(Cli* cli, string_t args) { +static void nfc_cli_emulate(Cli* cli, string_t args) { // Check if nfc worker is not busy if(furi_hal_nfc_is_busy()) { printf("Nfc is busy\r\n"); @@ -60,26 +55,25 @@ void nfc_cli_emulate(Cli* cli, string_t args) { printf("Emulating NFC-A Type: T2T UID: 36 9C E7 B1 0A C1 34 SAK: 00 ATQA: 00/44\r\n"); printf("Press Ctrl+C to abort\r\n"); - NfcDeviceCommonData params = { + FuriHalNfcDevData params = { .uid = {0x36, 0x9C, 0xe7, 0xb1, 0x0A, 0xC1, 0x34}, .uid_len = 7, .atqa = {0x44, 0x00}, .sak = 0x00, - .device = NfcDeviceNfca, - .protocol = NfcDeviceProtocolMifareUl, + .type = FuriHalNfcTypeA, }; while(!cli_cmd_interrupt_received(cli)) { if(furi_hal_nfc_listen(params.uid, params.uid_len, params.atqa, params.sak, false, 100)) { printf("Reader detected\r\n"); - furi_hal_nfc_deactivate(); + furi_hal_nfc_sleep(); } osDelay(50); } - furi_hal_nfc_deactivate(); + furi_hal_nfc_sleep(); } -void nfc_cli_field(Cli* cli, string_t args) { +static void nfc_cli_field(Cli* cli, string_t args) { // Check if nfc worker is not busy if(furi_hal_nfc_is_busy()) { printf("Nfc is busy\r\n"); @@ -97,7 +91,7 @@ void nfc_cli_field(Cli* cli, string_t args) { } furi_hal_nfc_field_off(); - furi_hal_nfc_deactivate(); + furi_hal_nfc_sleep(); } static void nfc_cli(Cli* cli, string_t args, void* context) { diff --git a/applications/nfc/nfc_device.c b/applications/nfc/nfc_device.c index 954a48cd1..c3e6bdd46 100644 --- a/applications/nfc/nfc_device.c +++ b/applications/nfc/nfc_device.c @@ -41,31 +41,31 @@ static void nfc_device_prepare_format_string(NfcDevice* dev, string_t format_str static bool nfc_device_parse_format_string(NfcDevice* dev, string_t format_string) { if(string_start_with_str_p(format_string, "UID")) { dev->format = NfcDeviceSaveFormatUid; - dev->dev_data.nfc_data.protocol = NfcDeviceProtocolUnknown; + dev->dev_data.protocol = NfcDeviceProtocolUnknown; return true; } if(string_start_with_str_p(format_string, "Bank card")) { dev->format = NfcDeviceSaveFormatBankCard; - dev->dev_data.nfc_data.protocol = NfcDeviceProtocolEMV; + dev->dev_data.protocol = NfcDeviceProtocolEMV; return true; } // Check Mifare Ultralight types for(MfUltralightType type = MfUltralightTypeUnknown; type < MfUltralightTypeNum; type++) { - if(string_start_with_str_p(format_string, nfc_mf_ul_type(type, true))) { + if(string_equal_str_p(format_string, nfc_mf_ul_type(type, true))) { dev->format = NfcDeviceSaveFormatMifareUl; - dev->dev_data.nfc_data.protocol = NfcDeviceProtocolMifareUl; + dev->dev_data.protocol = NfcDeviceProtocolMifareUl; dev->dev_data.mf_ul_data.type = type; return true; } } if(string_start_with_str_p(format_string, "Mifare Classic")) { dev->format = NfcDeviceSaveFormatMifareClassic; - dev->dev_data.nfc_data.protocol = NfcDeviceProtocolMifareClassic; + dev->dev_data.protocol = NfcDeviceProtocolMifareClassic; return true; } if(string_start_with_str_p(format_string, "Mifare DESFire")) { dev->format = NfcDeviceSaveFormatMifareDesfire; - dev->dev_data.nfc_data.protocol = NfcDeviceProtocolMifareDesfire; + dev->dev_data.protocol = NfcDeviceProtocolMifareDesfire; return true; } return false; @@ -73,7 +73,7 @@ static bool nfc_device_parse_format_string(NfcDevice* dev, string_t format_strin static bool nfc_device_save_mifare_ul_data(FlipperFormat* file, NfcDevice* dev) { bool saved = false; - MifareUlData* data = &dev->dev_data.mf_ul_data; + MfUltralightData* data = &dev->dev_data.mf_ul_data; string_t temp_str; string_init(temp_str); @@ -122,7 +122,7 @@ static bool nfc_device_save_mifare_ul_data(FlipperFormat* file, NfcDevice* dev) bool nfc_device_load_mifare_ul_data(FlipperFormat* file, NfcDevice* dev) { bool parsed = false; - MifareUlData* data = &dev->dev_data.mf_ul_data; + MfUltralightData* data = &dev->dev_data.mf_ul_data; string_t temp_str; string_init(temp_str); @@ -548,7 +548,7 @@ bool nfc_device_load_mifare_df_data(FlipperFormat* file, NfcDevice* dev) { static bool nfc_device_save_bank_card_data(FlipperFormat* file, NfcDevice* dev) { bool saved = false; - NfcEmvData* data = &dev->dev_data.emv_data; + EmvData* data = &dev->dev_data.emv_data; uint32_t data_temp = 0; do { @@ -577,8 +577,8 @@ static bool nfc_device_save_bank_card_data(FlipperFormat* file, NfcDevice* dev) bool nfc_device_load_bank_card_data(FlipperFormat* file, NfcDevice* dev) { bool parsed = false; - NfcEmvData* data = &dev->dev_data.emv_data; - memset(data, 0, sizeof(NfcEmvData)); + EmvData* data = &dev->dev_data.emv_data; + memset(data, 0, sizeof(EmvData)); uint32_t data_cnt = 0; string_t temp_str; string_init(temp_str); @@ -700,7 +700,7 @@ static bool nfc_device_save_file( bool saved = false; FlipperFormat* file = flipper_format_file_alloc(dev->storage); - NfcDeviceCommonData* data = &dev->dev_data.nfc_data; + FuriHalNfcDevData* data = &dev->dev_data.nfc_data; string_t temp_str; string_init(temp_str); @@ -758,7 +758,7 @@ bool nfc_device_save_shadow(NfcDevice* dev, const char* dev_name) { static bool nfc_device_load_data(NfcDevice* dev, string_t path) { bool parsed = false; FlipperFormat* file = flipper_format_file_alloc(dev->storage); - NfcDeviceCommonData* data = &dev->dev_data.nfc_data; + FuriHalNfcDevData* data = &dev->dev_data.nfc_data; uint32_t data_cnt = 0; string_t temp_str; string_init(temp_str); @@ -789,6 +789,7 @@ static bool nfc_device_load_data(NfcDevice* dev, string_t path) { if(!nfc_device_parse_format_string(dev, temp_str)) break; // Read and parse UID, ATQA and SAK if(!flipper_format_get_value_count(file, "UID", &data_cnt)) break; + if(!(data_cnt == 4 || data_cnt == 7)) break; data->uid_len = data_cnt; if(!flipper_format_read_hex(file, "UID", data->uid, data->uid_len)) break; if(!flipper_format_read_hex(file, "ATQA", data->atqa, 2)) break; @@ -863,7 +864,7 @@ bool nfc_file_select(NfcDevice* dev) { } void nfc_device_data_clear(NfcDeviceData* dev_data) { - if(dev_data->nfc_data.protocol == NfcDeviceProtocolMifareDesfire) { + if(dev_data->protocol == NfcDeviceProtocolMifareDesfire) { mf_df_clear(&dev_data->mf_df_data); } } diff --git a/applications/nfc/nfc_device.h b/applications/nfc/nfc_device.h index 78b2fe4ce..215f637fa 100644 --- a/applications/nfc/nfc_device.h +++ b/applications/nfc/nfc_device.h @@ -5,6 +5,8 @@ #include #include +#include +#include #include #include #include @@ -17,13 +19,6 @@ #define NFC_APP_EXTENSION ".nfc" #define NFC_APP_SHADOW_EXTENSION ".shd" -typedef enum { - NfcDeviceNfca, - NfcDeviceNfcb, - NfcDeviceNfcf, - NfcDeviceNfcv, -} NfcDeviceType; - typedef enum { NfcDeviceProtocolUnknown, NfcDeviceProtocolEMV, @@ -40,38 +35,18 @@ typedef enum { NfcDeviceSaveFormatMifareDesfire, } NfcDeviceSaveFormat; -typedef struct { - uint8_t uid_len; - uint8_t uid[10]; - uint8_t atqa[2]; - uint8_t sak; - NfcDeviceType device; - NfcProtocol protocol; -} NfcDeviceCommonData; - -typedef struct { - char name[32]; - uint8_t aid[16]; - uint16_t aid_len; - uint8_t number[10]; - uint8_t number_len; - uint8_t exp_mon; - uint8_t exp_year; - uint16_t country_code; - uint16_t currency_code; -} NfcEmvData; - typedef struct { uint8_t data[NFC_READER_DATA_MAX_SIZE]; uint16_t size; } NfcReaderRequestData; typedef struct { - NfcDeviceCommonData nfc_data; + FuriHalNfcDevData nfc_data; + NfcProtocol protocol; NfcReaderRequestData reader_data; union { - NfcEmvData emv_data; - MifareUlData mf_ul_data; + EmvData emv_data; + MfUltralightData mf_ul_data; MfClassicData mf_classic_data; MifareDesfireData mf_df_data; }; diff --git a/applications/nfc/nfc_i.h b/applications/nfc/nfc_i.h index 34b9b9069..51ea82e6c 100755 --- a/applications/nfc/nfc_i.h +++ b/applications/nfc/nfc_i.h @@ -40,7 +40,7 @@ struct Nfc { NotificationApp* notifications; SceneManager* scene_manager; NfcDevice* dev; - NfcDeviceCommonData dev_edit_data; + FuriHalNfcDevData dev_edit_data; char text_store[NFC_TEXT_STORE_SIZE + 1]; string_t text_box_store; diff --git a/applications/nfc/nfc_types.c b/applications/nfc/nfc_types.c index 6cd424457..1b67284c4 100644 --- a/applications/nfc/nfc_types.c +++ b/applications/nfc/nfc_types.c @@ -1,48 +1,14 @@ #include "nfc_types.h" -const char* nfc_get_rfal_type(rfalNfcDevType type) { - if(type == RFAL_NFC_LISTEN_TYPE_NFCA) { +const char* nfc_get_dev_type(FuriHalNfcType type) { + if(type == FuriHalNfcTypeA) { return "NFC-A"; - } else if(type == RFAL_NFC_LISTEN_TYPE_NFCB) { + } else if(type == FuriHalNfcTypeB) { return "NFC-B"; - } else if(type == RFAL_NFC_LISTEN_TYPE_NFCF) { + } else if(type == FuriHalNfcTypeF) { return "NFC-F"; - } else if(type == RFAL_NFC_LISTEN_TYPE_NFCV) { + } else if(type == FuriHalNfcTypeV) { return "NFC-V"; - } else if(type == RFAL_NFC_LISTEN_TYPE_ST25TB) { - return "NFC-ST25TB"; - } else if(type == RFAL_NFC_LISTEN_TYPE_AP2P) { - return "NFC-AP2P"; - } else { - return "Unknown"; - } -} - -const char* nfc_get_dev_type(NfcDeviceType type) { - if(type == NfcDeviceNfca) { - return "NFC-A"; - } else if(type == NfcDeviceNfcb) { - return "NFC-B"; - } else if(type == NfcDeviceNfcf) { - return "NFC-F"; - } else if(type == NfcDeviceNfcv) { - return "NFC-V"; - } else { - return "Unknown"; - } -} - -const char* nfc_get_nfca_type(rfalNfcaListenDeviceType type) { - if(type == RFAL_NFCA_T1T) { - return "T1T"; - } else if(type == RFAL_NFCA_T2T) { - return "T2T"; - } else if(type == RFAL_NFCA_T4T) { - return "T4T"; - } else if(type == RFAL_NFCA_NFCDEP) { - return "NFCDEP"; - } else if(type == RFAL_NFCA_T4T_NFCDEP) { - return "T4T_NFCDEP"; } else { return "Unknown"; } diff --git a/applications/nfc/nfc_types.h b/applications/nfc/nfc_types.h index 267934d63..fb53ce7c2 100644 --- a/applications/nfc/nfc_types.h +++ b/applications/nfc/nfc_types.h @@ -1,16 +1,8 @@ #pragma once -#include "st_errno.h" -#include "rfal_nfc.h" +#include "nfc_device.h" -#include -#include "nfc_worker.h" - -const char* nfc_get_rfal_type(rfalNfcDevType type); - -const char* nfc_get_dev_type(NfcDeviceType type); - -const char* nfc_get_nfca_type(rfalNfcaListenDeviceType type); +const char* nfc_get_dev_type(FuriHalNfcType type); const char* nfc_guess_protocol(NfcProtocol protocol); diff --git a/applications/nfc/nfc_worker.c b/applications/nfc/nfc_worker.c index a925a8d73..132483943 100644 --- a/applications/nfc/nfc_worker.c +++ b/applications/nfc/nfc_worker.c @@ -2,7 +2,8 @@ #include #include -#include +#include +#include #include #include #include @@ -94,22 +95,20 @@ int32_t nfc_worker_task(void* context) { nfc_worker_emulate(nfc_worker); } else if(nfc_worker->state == NfcWorkerStateReadEMVApp) { nfc_worker_read_emv_app(nfc_worker); - } else if(nfc_worker->state == NfcWorkerStateReadEMV) { + } else if(nfc_worker->state == NfcWorkerStateReadEMVData) { nfc_worker_read_emv(nfc_worker); } else if(nfc_worker->state == NfcWorkerStateEmulateApdu) { nfc_worker_emulate_apdu(nfc_worker); - } else if(nfc_worker->state == NfcWorkerStateReadMifareUl) { - nfc_worker_read_mifare_ul(nfc_worker); - } else if(nfc_worker->state == NfcWorkerStateEmulateMifareUl) { + } else if(nfc_worker->state == NfcWorkerStateReadMifareUltralight) { + nfc_worker_read_mifare_ultralight(nfc_worker); + } else if(nfc_worker->state == NfcWorkerStateEmulateMifareUltralight) { nfc_worker_emulate_mifare_ul(nfc_worker); } else if(nfc_worker->state == NfcWorkerStateReadMifareClassic) { nfc_worker_mifare_classic_dict_attack(nfc_worker); } else if(nfc_worker->state == NfcWorkerStateReadMifareDesfire) { nfc_worker_read_mifare_desfire(nfc_worker); - } else if(nfc_worker->state == NfcWorkerStateField) { - nfc_worker_field(nfc_worker); } - furi_hal_nfc_deactivate(); + furi_hal_nfc_sleep(); nfc_worker_change_state(nfc_worker, NfcWorkerStateReady); furi_hal_power_insomnia_exit(); @@ -117,579 +116,225 @@ int32_t nfc_worker_task(void* context) { } void nfc_worker_detect(NfcWorker* nfc_worker) { - rfalNfcDevice* dev_list; - rfalNfcDevice* dev; - uint8_t dev_cnt; nfc_device_data_clear(nfc_worker->dev_data); - NfcDeviceCommonData* result = &nfc_worker->dev_data->nfc_data; + NfcDeviceData* dev_data = nfc_worker->dev_data; + FuriHalNfcDevData* nfc_data = &nfc_worker->dev_data->nfc_data; while(nfc_worker->state == NfcWorkerStateDetect) { - if(furi_hal_nfc_detect(&dev_list, &dev_cnt, 1000, true)) { + if(furi_hal_nfc_detect(nfc_data, 1000)) { // Process first found device - dev = &dev_list[0]; - result->uid_len = dev->nfcidLen; - memcpy(result->uid, dev->nfcid, dev->nfcidLen); - if(dev->type == RFAL_NFC_LISTEN_TYPE_NFCA) { - result->device = NfcDeviceNfca; - result->atqa[0] = dev->dev.nfca.sensRes.anticollisionInfo; - result->atqa[1] = dev->dev.nfca.sensRes.platformInfo; - result->sak = dev->dev.nfca.selRes.sak; - if(mf_ul_check_card_type( - dev->dev.nfca.sensRes.anticollisionInfo, - dev->dev.nfca.sensRes.platformInfo, - dev->dev.nfca.selRes.sak)) { - result->protocol = NfcDeviceProtocolMifareUl; + if(nfc_data->type == FuriHalNfcTypeA) { + if(mf_ul_check_card_type(nfc_data->atqa[0], nfc_data->atqa[1], nfc_data->sak)) { + dev_data->protocol = NfcDeviceProtocolMifareUl; } else if(mf_classic_check_card_type( - dev->dev.nfca.sensRes.anticollisionInfo, - dev->dev.nfca.sensRes.platformInfo, - dev->dev.nfca.selRes.sak)) { - result->protocol = NfcDeviceProtocolMifareClassic; + nfc_data->atqa[0], nfc_data->atqa[1], nfc_data->sak)) { + dev_data->protocol = NfcDeviceProtocolMifareClassic; } else if(mf_df_check_card_type( - dev->dev.nfca.sensRes.anticollisionInfo, - dev->dev.nfca.sensRes.platformInfo, - dev->dev.nfca.selRes.sak)) { - result->protocol = NfcDeviceProtocolMifareDesfire; - } else if(dev->rfInterface == RFAL_NFC_INTERFACE_ISODEP) { - result->protocol = NfcDeviceProtocolEMV; + nfc_data->atqa[0], nfc_data->atqa[1], nfc_data->sak)) { + dev_data->protocol = NfcDeviceProtocolMifareDesfire; + } else if(nfc_data->interface == FuriHalNfcInterfaceIsoDep) { + dev_data->protocol = NfcDeviceProtocolEMV; } else { - result->protocol = NfcDeviceProtocolUnknown; + dev_data->protocol = NfcDeviceProtocolUnknown; } - } else if(dev->type == RFAL_NFC_LISTEN_TYPE_NFCB) { - result->device = NfcDeviceNfcb; - } else if(dev->type == RFAL_NFC_LISTEN_TYPE_NFCF) { - result->device = NfcDeviceNfcf; - } else if(dev->type == RFAL_NFC_LISTEN_TYPE_NFCV) { - result->device = NfcDeviceNfcv; } + // Notify caller and exit if(nfc_worker->callback) { nfc_worker->callback(NfcWorkerEventSuccess, nfc_worker->context); } break; } + furi_hal_nfc_sleep(); osDelay(100); } } -bool nfc_worker_emulate_uid_callback( - uint8_t* buff_rx, - uint16_t buff_rx_len, - uint8_t* buff_tx, - uint16_t* buff_tx_len, - uint32_t* data_type, - void* context) { - furi_assert(context); - NfcWorker* nfc_worker = context; - NfcReaderRequestData* reader_data = &nfc_worker->dev_data->reader_data; - reader_data->size = buff_rx_len / 8; - if(reader_data->size > 0) { - memcpy(reader_data->data, buff_rx, reader_data->size); - if(nfc_worker->callback) { - nfc_worker->callback(NfcWorkerEventSuccess, nfc_worker->context); - } - } - return true; -} - void nfc_worker_emulate(NfcWorker* nfc_worker) { - NfcDeviceCommonData* data = &nfc_worker->dev_data->nfc_data; + FuriHalNfcTxRxContext tx_rx = {}; + FuriHalNfcDevData* data = &nfc_worker->dev_data->nfc_data; + NfcReaderRequestData* reader_data = &nfc_worker->dev_data->reader_data; + while(nfc_worker->state == NfcWorkerStateEmulate) { - furi_hal_nfc_emulate_nfca( - data->uid, - data->uid_len, - data->atqa, - data->sak, - nfc_worker_emulate_uid_callback, - nfc_worker, - 1000); + if(furi_hal_nfc_listen(data->uid, data->uid_len, data->atqa, data->sak, true, 100)) { + if(furi_hal_nfc_tx_rx(&tx_rx, 100)) { + reader_data->size = tx_rx.rx_bits / 8; + if(reader_data->size > 0) { + memcpy(reader_data->data, tx_rx.rx_data, reader_data->size); + if(nfc_worker->callback) { + nfc_worker->callback(NfcWorkerEventSuccess, nfc_worker->context); + } + } + } else { + FURI_LOG_E(TAG, "Failed to get reader commands"); + } + } } } void nfc_worker_read_emv_app(NfcWorker* nfc_worker) { - ReturnCode err; - rfalNfcDevice* dev_list; + FuriHalNfcTxRxContext tx_rx = {}; EmvApplication emv_app = {}; - uint8_t dev_cnt = 0; - uint8_t tx_buff[255] = {}; - uint16_t tx_len = 0; - uint8_t* rx_buff; - uint16_t* rx_len; NfcDeviceData* result = nfc_worker->dev_data; + FuriHalNfcDevData* nfc_data = &nfc_worker->dev_data->nfc_data; nfc_device_data_clear(result); while(nfc_worker->state == NfcWorkerStateReadEMVApp) { - memset(&emv_app, 0, sizeof(emv_app)); - if(furi_hal_nfc_detect(&dev_list, &dev_cnt, 1000, false)) { + if(furi_hal_nfc_detect(nfc_data, 1000)) { // Card was found. Check that it supports EMV - if(dev_list[0].rfInterface == RFAL_NFC_INTERFACE_ISODEP) { - result->nfc_data.uid_len = dev_list[0].dev.nfca.nfcId1Len; - result->nfc_data.atqa[0] = dev_list[0].dev.nfca.sensRes.anticollisionInfo; - result->nfc_data.atqa[1] = dev_list[0].dev.nfca.sensRes.platformInfo; - result->nfc_data.sak = dev_list[0].dev.nfca.selRes.sak; - memcpy( - result->nfc_data.uid, dev_list[0].dev.nfca.nfcId1, result->nfc_data.uid_len); - result->nfc_data.protocol = NfcDeviceProtocolEMV; - - FURI_LOG_D(TAG, "Send select PPSE command"); - tx_len = emv_prepare_select_ppse(tx_buff); - err = furi_hal_nfc_data_exchange(tx_buff, tx_len, &rx_buff, &rx_len, false); - if(err != ERR_NONE) { - FURI_LOG_D(TAG, "Error during selection PPSE request: %d", err); - furi_hal_nfc_deactivate(); - continue; - } - FURI_LOG_D(TAG, "Select PPSE response received. Start parsing response"); - if(emv_decode_ppse_response(rx_buff, *rx_len, &emv_app)) { - FURI_LOG_D(TAG, "Select PPSE responce parced"); + if(nfc_data->interface == FuriHalNfcInterfaceIsoDep) { + result->protocol = NfcDeviceProtocolEMV; + if(emv_search_application(&tx_rx, &emv_app)) { // Notify caller and exit result->emv_data.aid_len = emv_app.aid_len; memcpy(result->emv_data.aid, emv_app.aid, emv_app.aid_len); if(nfc_worker->callback) { nfc_worker->callback(NfcWorkerEventSuccess, nfc_worker->context); } - break; - } else { - FURI_LOG_D(TAG, "Can't find pay application"); - furi_hal_nfc_deactivate(); - continue; } } else { - // Can't find EMV card FURI_LOG_W(TAG, "Card doesn't support EMV"); - furi_hal_nfc_deactivate(); } } else { - // Can't find EMV card FURI_LOG_D(TAG, "Can't find any cards"); - furi_hal_nfc_deactivate(); } + furi_hal_nfc_sleep(); osDelay(20); } } void nfc_worker_read_emv(NfcWorker* nfc_worker) { - ReturnCode err; - rfalNfcDevice* dev_list; + FuriHalNfcTxRxContext tx_rx = {}; EmvApplication emv_app = {}; - uint8_t dev_cnt = 0; - uint8_t tx_buff[255] = {}; - uint16_t tx_len = 0; - uint8_t* rx_buff; - uint16_t* rx_len; NfcDeviceData* result = nfc_worker->dev_data; + FuriHalNfcDevData* nfc_data = &nfc_worker->dev_data->nfc_data; nfc_device_data_clear(result); - while(nfc_worker->state == NfcWorkerStateReadEMV) { - memset(&emv_app, 0, sizeof(emv_app)); - if(furi_hal_nfc_detect(&dev_list, &dev_cnt, 1000, false)) { + while(nfc_worker->state == NfcWorkerStateReadEMVData) { + if(furi_hal_nfc_detect(nfc_data, 1000)) { // Card was found. Check that it supports EMV - if(dev_list[0].rfInterface == RFAL_NFC_INTERFACE_ISODEP) { - result->nfc_data.uid_len = dev_list[0].dev.nfca.nfcId1Len; - result->nfc_data.atqa[0] = dev_list[0].dev.nfca.sensRes.anticollisionInfo; - result->nfc_data.atqa[1] = dev_list[0].dev.nfca.sensRes.platformInfo; - result->nfc_data.sak = dev_list[0].dev.nfca.selRes.sak; - memcpy( - result->nfc_data.uid, dev_list[0].dev.nfca.nfcId1, result->nfc_data.uid_len); - result->nfc_data.protocol = NfcDeviceProtocolEMV; - - FURI_LOG_D(TAG, "Send select PPSE command"); - tx_len = emv_prepare_select_ppse(tx_buff); - err = furi_hal_nfc_data_exchange(tx_buff, tx_len, &rx_buff, &rx_len, false); - if(err != ERR_NONE) { - FURI_LOG_D(TAG, "Error during selection PPSE request: %d", err); - furi_hal_nfc_deactivate(); - continue; - } - FURI_LOG_D(TAG, "Select PPSE response received. Start parsing response"); - if(emv_decode_ppse_response(rx_buff, *rx_len, &emv_app)) { - FURI_LOG_D(TAG, "Select PPSE responce parced"); + if(nfc_data->interface == FuriHalNfcInterfaceIsoDep) { + result->protocol = NfcDeviceProtocolEMV; + if(emv_read_bank_card(&tx_rx, &emv_app)) { + result->emv_data.number_len = emv_app.card_number_len; + memcpy( + result->emv_data.number, emv_app.card_number, result->emv_data.number_len); result->emv_data.aid_len = emv_app.aid_len; memcpy(result->emv_data.aid, emv_app.aid, emv_app.aid_len); - } else { - FURI_LOG_D(TAG, "Can't find pay application"); - furi_hal_nfc_deactivate(); - continue; + if(emv_app.name_found) { + memcpy(result->emv_data.name, emv_app.name, sizeof(emv_app.name)); + } + if(emv_app.exp_month) { + result->emv_data.exp_mon = emv_app.exp_month; + result->emv_data.exp_year = emv_app.exp_year; + } + if(emv_app.country_code) { + result->emv_data.country_code = emv_app.country_code; + } + if(emv_app.currency_code) { + result->emv_data.currency_code = emv_app.currency_code; + } + // Notify caller and exit + if(nfc_worker->callback) { + nfc_worker->callback(NfcWorkerEventSuccess, nfc_worker->context); + } + break; } - FURI_LOG_D(TAG, "Starting application ..."); - tx_len = emv_prepare_select_app(tx_buff, &emv_app); - err = furi_hal_nfc_data_exchange(tx_buff, tx_len, &rx_buff, &rx_len, false); - if(err != ERR_NONE) { - FURI_LOG_D(TAG, "Error during application selection request: %d", err); - furi_hal_nfc_deactivate(); - continue; - } - FURI_LOG_D(TAG, "Select application response received. Start parsing response"); - if(emv_decode_select_app_response(rx_buff, *rx_len, &emv_app)) { - FURI_LOG_D(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_D(TAG, "Can't find card name, but PDOL is present."); - } else { - FURI_LOG_D(TAG, "Can't find card name or PDOL"); - furi_hal_nfc_deactivate(); - continue; - } - FURI_LOG_D(TAG, "Starting Get Processing Options command ..."); - tx_len = emv_prepare_get_proc_opt(tx_buff, &emv_app); - err = furi_hal_nfc_data_exchange(tx_buff, tx_len, &rx_buff, &rx_len, false); - if(err != ERR_NONE) { - FURI_LOG_D(TAG, "Error during Get Processing Options command: %d", err); - furi_hal_nfc_deactivate(); - continue; - } - if(emv_decode_get_proc_opt(rx_buff, *rx_len, &emv_app)) { - FURI_LOG_D(TAG, "Card number parsed"); - result->emv_data.number_len = emv_app.card_number_len; - memcpy(result->emv_data.number, emv_app.card_number, emv_app.card_number_len); + } else { + FURI_LOG_W(TAG, "Card doesn't support EMV"); + } + } else { + FURI_LOG_D(TAG, "Can't find any cards"); + } + furi_hal_nfc_sleep(); + osDelay(20); + } +} + +void nfc_worker_emulate_apdu(NfcWorker* nfc_worker) { + FuriHalNfcTxRxContext tx_rx = {}; + FuriHalNfcDevData params = { + .uid = {0xCF, 0x72, 0xd4, 0x40}, + .uid_len = 4, + .atqa = {0x00, 0x04}, + .sak = 0x20, + .type = FuriHalNfcTypeA, + }; + + while(nfc_worker->state == NfcWorkerStateEmulateApdu) { + if(furi_hal_nfc_listen(params.uid, params.uid_len, params.atqa, params.sak, false, 300)) { + FURI_LOG_D(TAG, "POS terminal detected"); + if(emv_card_emulation(&tx_rx)) { + FURI_LOG_D(TAG, "EMV card emulated"); + } + } else { + FURI_LOG_D(TAG, "Can't find reader"); + } + furi_hal_nfc_sleep(); + osDelay(20); + } +} + +void nfc_worker_read_mifare_ultralight(NfcWorker* nfc_worker) { + FuriHalNfcTxRxContext tx_rx = {}; + MfUltralightReader reader = {}; + MfUltralightData data = {}; + NfcDeviceData* result = nfc_worker->dev_data; + FuriHalNfcDevData* nfc_data = &nfc_worker->dev_data->nfc_data; + + while(nfc_worker->state == NfcWorkerStateReadMifareUltralight) { + if(furi_hal_nfc_detect(nfc_data, 300)) { + if(nfc_data->type == FuriHalNfcTypeA && + mf_ul_check_card_type(nfc_data->atqa[0], nfc_data->atqa[1], nfc_data->sak)) { + FURI_LOG_D(TAG, "Found Mifare Ultralight tag. Start reading"); + if(mf_ul_read_card(&tx_rx, &reader, &data)) { + result->protocol = NfcDeviceProtocolMifareUl; + result->mf_ul_data = data; // Notify caller and exit if(nfc_worker->callback) { nfc_worker->callback(NfcWorkerEventSuccess, nfc_worker->context); } break; } else { - // Mastercard doesn't give PAN / card number as GPO response - // Iterate over all files found in application - bool pan_found = false; - for(uint8_t i = 0; (i < emv_app.afl.size) && !pan_found; i += 4) { - uint8_t sfi = emv_app.afl.data[i] >> 3; - uint8_t record_start = emv_app.afl.data[i + 1]; - uint8_t record_end = emv_app.afl.data[i + 2]; - - // Iterate over all records in file - for(uint8_t record = record_start; record <= record_end; ++record) { - tx_len = emv_prepare_read_sfi_record(tx_buff, sfi, record); - err = furi_hal_nfc_data_exchange( - tx_buff, tx_len, &rx_buff, &rx_len, false); - if(err != ERR_NONE) { - FURI_LOG_D( - TAG, - "Error reading application sfi %d, record %d", - sfi, - record); - } - if(emv_decode_read_sfi_record(rx_buff, *rx_len, &emv_app)) { - pan_found = true; - break; - } - } - } - if(pan_found) { - FURI_LOG_D(TAG, "Card PAN found"); - result->emv_data.number_len = emv_app.card_number_len; - memcpy( - result->emv_data.number, - 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; - } - if(emv_app.country_code) { - result->emv_data.country_code = emv_app.country_code; - } - if(emv_app.currency_code) { - result->emv_data.currency_code = emv_app.currency_code; - } - // Notify caller and exit - if(nfc_worker->callback) { - nfc_worker->callback(NfcWorkerEventSuccess, nfc_worker->context); - } - break; - } else { - FURI_LOG_D(TAG, "Can't read card number"); - } - furi_hal_nfc_deactivate(); + FURI_LOG_D(TAG, "Failed reading Mifare Ultralight"); } } else { - // Can't find EMV card - FURI_LOG_W(TAG, "Card doesn't support EMV"); - furi_hal_nfc_deactivate(); - } - } else { - // Can't find EMV card - FURI_LOG_D(TAG, "Can't find any cards"); - furi_hal_nfc_deactivate(); - } - osDelay(20); - } -} - -void nfc_worker_emulate_apdu(NfcWorker* nfc_worker) { - ReturnCode err; - uint8_t tx_buff[255] = {}; - uint16_t tx_len = 0; - uint8_t* rx_buff; - uint16_t* rx_len; - NfcDeviceCommonData params = { - .uid = {0xCF, 0x72, 0xd4, 0x40}, - .uid_len = 4, - .atqa = {0x00, 0x04}, - .sak = 0x20, - .device = NfcDeviceNfca, - .protocol = NfcDeviceProtocolEMV, - }; - // Test RX data - const uint8_t debug_rx[] = { - 0xba, 0x0b, 0xba, 0xba, 0x20, 0x00, 0x02, 0x28, 0xde, 0xad, 0xbe, 0xef, 0x00, 0xca, 0xca, - 0xca, 0xfe, 0xfa, 0xce, 0x14, 0x88, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, - 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, 0xba, - 0x0b, 0xba, 0xba, 0x20, 0x00, 0x02, 0x28, 0xde, 0xad, 0xbe, 0xef, 0x00, 0xca, 0xca, 0xca, - 0xfe, 0xfa, 0xce, 0x14, 0x88, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, - 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, 0xba, 0x0b, - 0xba, 0xba, 0x20, 0x00, 0x02, 0x28, 0xde, 0xad, 0xbe, 0xef, 0x00, 0xca, 0xca, 0xca, 0xfe, - 0xfa, 0xce, 0x14, 0x88, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, - 0xbb, 0xcc, 0xdd, 0xee, 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, 0xba, 0x0b, 0xba, - 0xba, 0x20, 0x00, 0x02, 0x28, 0xde, 0xad, 0xbe, 0xef, 0x00, 0xca, 0xca, 0xca, 0xfe, 0xfa, - 0xce, 0x14, 0x88, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, - 0xcc, 0xdd, 0xee, 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, 0xba, 0x0b, 0xba, 0xba, - 0x20, 0x00, 0x02, 0x28, 0xde, 0xad, 0xbe, 0xef, 0x00, 0xca, 0xca, 0xca, 0xfe, 0xfa, 0xce, - 0x14, 0x88, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, - 0xdd, 0xee, 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, 0xba, 0x0b, 0xba, 0xba, 0x20, - 0x00, 0x02, 0x28, 0xde, 0xad, 0xbe, 0xef, 0x00, 0xca, 0xca, 0xca, 0xfe, 0xfa, 0xce, 0x14, - 0x88, 0x00}; - // Test TX data - const uint8_t debug_tx[] = { - 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xff, 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, - 0x10, 0x14, 0x88, 0x02, 0x28, 0x00, 0x00, 0xca, 0xca, 0x00, 0xc0, 0xc0, 0x00, 0xde, 0xad, - 0xbe, 0xef, 0xce, 0xee, 0xec, 0xca, 0xfe, 0xba, 0xba, 0xb0, 0xb0, 0xac, 0xdc, 0x11, 0x12, - 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xff, 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, - 0x14, 0x88, 0x02, 0x28, 0x00, 0x00, 0xca, 0xca, 0x00, 0xc0, 0xc0, 0x00, 0xde, 0xad, 0xbe, - 0xef, 0xce, 0xee, 0xec, 0xca, 0xfe, 0xba, 0xba, 0xb0, 0xb0, 0xac, 0xdc, 0x11, 0x12, 0x34, - 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xff, 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, 0x14, - 0x88, 0x02, 0x28, 0x00, 0x00, 0xca, 0xca, 0x00, 0xc0, 0xc0, 0x00, 0xde, 0xad, 0xbe, 0xef, - 0xce, 0xee, 0xec, 0xca, 0xfe, 0xba, 0xba, 0xb0, 0xb0, 0xac, 0xdc, 0x11, 0x12, 0x34, 0x56, - 0x78, 0x9a, 0xbc, 0xde, 0xff, 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, 0x14, 0x88, - 0x02, 0x28, 0x00, 0x00, 0xca, 0xca, 0x00, 0xc0, 0xc0, 0x00, 0xde, 0xad, 0xbe, 0xef, 0xce, - 0xee, 0xec, 0xca, 0xfe, 0xba, 0xba, 0xb0, 0xb0, 0xac, 0xdc, 0x11, 0x12, 0x34, 0x56, 0x78, - 0x9a, 0xbc, 0xde, 0xff, 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, 0x14, 0x88, 0x02, - 0x28, 0x00, 0x00, 0xca, 0xca, 0x00, 0xc0, 0xc0, 0x00, 0xde, 0xad, 0xbe, 0xef, 0xce, 0xee, - 0xec, 0xca, 0xfe, 0xba, 0xba, 0xb0, 0xb0, 0xac, 0xdc, 0x11, 0x12, 0x34, 0x56, 0x78, 0x9a, - 0xbc, 0xde, 0xff, 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, 0x14, 0x88, 0x02, 0x28, - 0x00, 0x00}; - - while(nfc_worker->state == NfcWorkerStateEmulateApdu) { - if(furi_hal_nfc_listen(params.uid, params.uid_len, params.atqa, params.sak, false, 300)) { - FURI_LOG_D(TAG, "POS terminal detected"); - // Read data from POS terminal - err = furi_hal_nfc_data_exchange(NULL, 0, &rx_buff, &rx_len, false); - if(err == ERR_NONE) { - FURI_LOG_D(TAG, "Received Select PPSE"); - } else { - FURI_LOG_D(TAG, "Error in 1st data exchange: select PPSE"); - furi_hal_nfc_deactivate(); - continue; - } - FURI_LOG_D(TAG, "Transive SELECT PPSE ANS"); - tx_len = emv_select_ppse_ans(tx_buff); - err = furi_hal_nfc_data_exchange(tx_buff, tx_len, &rx_buff, &rx_len, false); - if(err == ERR_NONE) { - FURI_LOG_D(TAG, "Received Select APP"); - } else { - FURI_LOG_D(TAG, "Error in 2nd data exchange: select APP"); - furi_hal_nfc_deactivate(); - continue; - } - - FURI_LOG_D(TAG, "Transive SELECT APP ANS"); - tx_len = emv_select_app_ans(tx_buff); - err = furi_hal_nfc_data_exchange(tx_buff, tx_len, &rx_buff, &rx_len, false); - if(err == ERR_NONE) { - FURI_LOG_D(TAG, "Received PDOL"); - } else { - FURI_LOG_D(TAG, "Error in 3rd data exchange: receive PDOL"); - furi_hal_nfc_deactivate(); - continue; - } - - FURI_LOG_D(TAG, "Transive PDOL ANS"); - tx_len = emv_get_proc_opt_ans(tx_buff); - err = furi_hal_nfc_data_exchange(tx_buff, tx_len, &rx_buff, &rx_len, false); - if(err == ERR_NONE) { - FURI_LOG_D(TAG, "Transive PDOL ANS"); - } else { - FURI_LOG_D(TAG, "Error in 4rd data exchange: Transive PDOL ANS"); - furi_hal_nfc_deactivate(); - continue; - } - - if(*rx_len != sizeof(debug_rx) || memcmp(rx_buff, debug_rx, sizeof(debug_rx))) { - FURI_LOG_D(TAG, "Failed long message test"); - } else { - FURI_LOG_D(TAG, "Correct debug message received"); - tx_len = sizeof(debug_tx); - err = furi_hal_nfc_data_exchange( - (uint8_t*)debug_tx, tx_len, &rx_buff, &rx_len, false); - if(err == ERR_NONE) { - FURI_LOG_D(TAG, "Transive Debug message"); - } - } - furi_hal_nfc_deactivate(); - } else { - FURI_LOG_D(TAG, "Can't find reader"); - } - osDelay(20); - } -} - -void nfc_worker_read_mifare_ul(NfcWorker* nfc_worker) { - ReturnCode err; - rfalNfcDevice* dev_list; - uint8_t dev_cnt = 0; - uint8_t tx_buff[255] = {}; - uint16_t tx_len = 0; - uint8_t* rx_buff; - uint16_t* rx_len; - MifareUlDevice mf_ul_read; - NfcDeviceData* result = nfc_worker->dev_data; - nfc_device_data_clear(result); - - while(nfc_worker->state == NfcWorkerStateReadMifareUl) { - furi_hal_nfc_deactivate(); - memset(&mf_ul_read, 0, sizeof(mf_ul_read)); - if(furi_hal_nfc_detect(&dev_list, &dev_cnt, 300, false)) { - if(dev_list[0].type == RFAL_NFC_LISTEN_TYPE_NFCA && - mf_ul_check_card_type( - dev_list[0].dev.nfca.sensRes.anticollisionInfo, - dev_list[0].dev.nfca.sensRes.platformInfo, - dev_list[0].dev.nfca.selRes.sak)) { - // Get Mifare Ultralight version - FURI_LOG_D(TAG, "Found Mifare Ultralight tag. Reading tag version"); - tx_len = mf_ul_prepare_get_version(tx_buff); - err = furi_hal_nfc_data_exchange(tx_buff, tx_len, &rx_buff, &rx_len, false); - if(err == ERR_NONE) { - mf_ul_parse_get_version_response(rx_buff, &mf_ul_read); - FURI_LOG_D( - TAG, - "Mifare Ultralight Type: %d, Pages: %d", - mf_ul_read.data.type, - mf_ul_read.pages_to_read); - FURI_LOG_D(TAG, "Reading signature ..."); - tx_len = mf_ul_prepare_read_signature(tx_buff); - if(furi_hal_nfc_data_exchange(tx_buff, tx_len, &rx_buff, &rx_len, false)) { - FURI_LOG_D(TAG, "Failed reading signature"); - memset(mf_ul_read.data.signature, 0, sizeof(mf_ul_read.data.signature)); - } else { - mf_ul_parse_read_signature_response(rx_buff, &mf_ul_read); - } - } else if(err == ERR_TIMEOUT) { - FURI_LOG_D( - TAG, - "Card doesn't respond to GET VERSION command. Setting default read parameters"); - err = ERR_NONE; - mf_ul_set_default_version(&mf_ul_read); - // Reinit device - furi_hal_nfc_deactivate(); - if(!furi_hal_nfc_detect(&dev_list, &dev_cnt, 300, false)) { - FURI_LOG_D(TAG, "Lost connection. Restarting search"); - continue; - } - } else { - FURI_LOG_D( - TAG, "Error getting Mifare Ultralight version. Error code: %d", err); - continue; - } - - if(mf_ul_read.support_fast_read) { - FURI_LOG_D(TAG, "Reading pages ..."); - tx_len = mf_ul_prepare_fast_read(tx_buff, 0x00, mf_ul_read.pages_to_read - 1); - if(furi_hal_nfc_data_exchange(tx_buff, tx_len, &rx_buff, &rx_len, false)) { - FURI_LOG_D(TAG, "Failed reading pages"); - continue; - } else { - mf_ul_parse_fast_read_response( - rx_buff, 0x00, mf_ul_read.pages_to_read - 1, &mf_ul_read); - } - - FURI_LOG_D(TAG, "Reading 3 counters ..."); - for(uint8_t i = 0; i < 3; i++) { - tx_len = mf_ul_prepare_read_cnt(tx_buff, i); - if(furi_hal_nfc_data_exchange(tx_buff, tx_len, &rx_buff, &rx_len, false)) { - FURI_LOG_W(TAG, "Failed reading Counter %d", i); - mf_ul_read.data.counter[i] = 0; - } else { - mf_ul_parse_read_cnt_response(rx_buff, i, &mf_ul_read); - } - } - - FURI_LOG_D(TAG, "Checking tearing flags ..."); - for(uint8_t i = 0; i < 3; i++) { - tx_len = mf_ul_prepare_check_tearing(tx_buff, i); - if(furi_hal_nfc_data_exchange(tx_buff, tx_len, &rx_buff, &rx_len, false)) { - FURI_LOG_D(TAG, "Error checking tearing flag %d", i); - mf_ul_read.data.tearing[i] = MF_UL_TEARING_FLAG_DEFAULT; - } else { - mf_ul_parse_check_tearing_response(rx_buff, i, &mf_ul_read); - } - } - } else { - // READ card with READ command (4 pages at a time) - for(uint8_t page = 0; page < mf_ul_read.pages_to_read; page += 4) { - FURI_LOG_D(TAG, "Reading pages %d - %d ...", page, page + 3); - tx_len = mf_ul_prepare_read(tx_buff, page); - if(furi_hal_nfc_data_exchange(tx_buff, tx_len, &rx_buff, &rx_len, false)) { - FURI_LOG_D(TAG, "Read pages %d - %d failed", page, page + 3); - continue; - } else { - mf_ul_parse_read_response(rx_buff, page, &mf_ul_read); - } - } - } - - // Fill result data - result->nfc_data.uid_len = dev_list[0].dev.nfca.nfcId1Len; - result->nfc_data.atqa[0] = dev_list[0].dev.nfca.sensRes.anticollisionInfo; - result->nfc_data.atqa[1] = dev_list[0].dev.nfca.sensRes.platformInfo; - result->nfc_data.sak = dev_list[0].dev.nfca.selRes.sak; - result->nfc_data.protocol = NfcDeviceProtocolMifareUl; - memcpy( - result->nfc_data.uid, dev_list[0].dev.nfca.nfcId1, result->nfc_data.uid_len); - result->mf_ul_data = mf_ul_read.data; - - // Notify caller and exit - if(nfc_worker->callback) { - nfc_worker->callback(NfcWorkerEventSuccess, nfc_worker->context); - } - break; - } else { - FURI_LOG_W(TAG, "Tag does not support Mifare Ultralight"); + FURI_LOG_W(TAG, "Tag is not Mifare Ultralight"); } } else { FURI_LOG_D(TAG, "Can't find any tags"); } + furi_hal_nfc_sleep(); osDelay(100); } } void nfc_worker_emulate_mifare_ul(NfcWorker* nfc_worker) { - NfcDeviceCommonData* nfc_common = &nfc_worker->dev_data->nfc_data; - MifareUlDevice mf_ul_emulate; - mf_ul_prepare_emulation(&mf_ul_emulate, &nfc_worker->dev_data->mf_ul_data); - while(nfc_worker->state == NfcWorkerStateEmulateMifareUl) { + FuriHalNfcDevData* nfc_data = &nfc_worker->dev_data->nfc_data; + MfUltralightEmulator emulator = {}; + mf_ul_prepare_emulation(&emulator, &nfc_worker->dev_data->mf_ul_data); + while(nfc_worker->state == NfcWorkerStateEmulateMifareUltralight) { furi_hal_nfc_emulate_nfca( - nfc_common->uid, - nfc_common->uid_len, - nfc_common->atqa, - nfc_common->sak, + nfc_data->uid, + nfc_data->uid_len, + nfc_data->atqa, + nfc_data->sak, mf_ul_prepare_emulation_response, - &mf_ul_emulate, + &emulator, 5000); // Check if data was modified - if(mf_ul_emulate.data_changed) { - nfc_worker->dev_data->mf_ul_data = mf_ul_emulate.data; + if(emulator.data_changed) { + nfc_worker->dev_data->mf_ul_data = emulator.data; if(nfc_worker->callback) { nfc_worker->callback(NfcWorkerEventSuccess, nfc_worker->context); } - mf_ul_emulate.data_changed = false; + emulator.data_changed = false; } } } void nfc_worker_mifare_classic_dict_attack(NfcWorker* nfc_worker) { furi_assert(nfc_worker->callback); - rfalNfcDevice* dev_list; - rfalNfcDevice* dev; - NfcDeviceCommonData* nfc_common; - uint8_t dev_cnt = 0; FuriHalNfcTxRxContext tx_rx_ctx = {}; MfClassicAuthContext auth_ctx = {}; MfClassicReader reader = {}; @@ -697,6 +342,7 @@ void nfc_worker_mifare_classic_dict_attack(NfcWorker* nfc_worker) { uint16_t curr_sector = 0; uint8_t total_sectors = 0; NfcWorkerEvent event; + FuriHalNfcDevData* nfc_data = &nfc_worker->dev_data->nfc_data; // Open dictionary nfc_worker->dict_stream = file_stream_alloc(nfc_worker->storage); @@ -710,14 +356,13 @@ void nfc_worker_mifare_classic_dict_attack(NfcWorker* nfc_worker) { // Detect Mifare Classic card while(nfc_worker->state == NfcWorkerStateReadMifareClassic) { - if(furi_hal_nfc_detect(&dev_list, &dev_cnt, 300, false)) { - dev = &dev_list[0]; + if(furi_hal_nfc_detect(nfc_data, 300)) { if(mf_classic_get_type( - dev->nfcid, - dev->nfcidLen, - dev->dev.nfca.sensRes.anticollisionInfo, - dev->dev.nfca.sensRes.platformInfo, - dev->dev.nfca.selRes.sak, + nfc_data->uid, + nfc_data->uid_len, + nfc_data->atqa[0], + nfc_data->atqa[1], + nfc_data->sak, &reader)) { total_sectors = mf_classic_get_total_sectors_num(&reader); if(reader.type == MfClassicType1k) { @@ -745,7 +390,7 @@ void nfc_worker_mifare_classic_dict_attack(NfcWorker* nfc_worker) { mf_classic_auth_init_context(&auth_ctx, reader.cuid, curr_sector); bool sector_key_found = false; while(nfc_mf_classic_dict_get_next_key(nfc_worker->dict_stream, &curr_key)) { - furi_hal_nfc_deactivate(); + furi_hal_nfc_sleep(); if(furi_hal_nfc_activate_nfca(300, &reader.cuid)) { if(!card_found_notified) { if(reader.type == MfClassicType1k) { @@ -817,15 +462,8 @@ void nfc_worker_mifare_classic_dict_attack(NfcWorker* nfc_worker) { uint8_t sectors_read = mf_classic_read_card(&tx_rx_ctx, &reader, &nfc_worker->dev_data->mf_classic_data); if(sectors_read) { - dev = &dev_list[0]; - nfc_common = &nfc_worker->dev_data->nfc_data; - nfc_common->uid_len = dev->dev.nfca.nfcId1Len; - nfc_common->atqa[0] = dev->dev.nfca.sensRes.anticollisionInfo; - nfc_common->atqa[1] = dev->dev.nfca.sensRes.platformInfo; - nfc_common->sak = dev->dev.nfca.selRes.sak; - nfc_common->protocol = NfcDeviceProtocolMifareClassic; - memcpy(nfc_common->uid, dev->dev.nfca.nfcId1, nfc_common->uid_len); event = NfcWorkerEventSuccess; + nfc_worker->dev_data->protocol = NfcDeviceProtocolMifareClassic; FURI_LOG_I(TAG, "Successfully read %d sectors", sectors_read); } else { event = NfcWorkerEventFail; @@ -838,42 +476,8 @@ void nfc_worker_mifare_classic_dict_attack(NfcWorker* nfc_worker) { stream_free(nfc_worker->dict_stream); } -ReturnCode nfc_exchange_full( - uint8_t* tx_buff, - uint16_t tx_len, - uint8_t* rx_buff, - uint16_t rx_cap, - uint16_t* rx_len) { - ReturnCode err; - uint8_t* part_buff; - uint16_t* part_len; - - err = furi_hal_nfc_data_exchange(tx_buff, tx_len, &part_buff, &part_len, false); - if(*part_len > rx_cap) { - return ERR_OVERRUN; - } - memcpy(rx_buff, part_buff, *part_len); - *rx_len = *part_len; - while(err == ERR_NONE && rx_buff[0] == 0xAF) { - err = furi_hal_nfc_data_exchange(rx_buff, 1, &part_buff, &part_len, false); - if(*part_len > rx_cap - *rx_len) { - return ERR_OVERRUN; - } - if(*part_len == 0) { - return ERR_PROTO; - } - memcpy(rx_buff + *rx_len, part_buff + 1, *part_len - 1); - *rx_buff = *part_buff; - *rx_len += *part_len - 1; - } - - return err; -} - void nfc_worker_read_mifare_desfire(NfcWorker* nfc_worker) { ReturnCode err; - rfalNfcDevice* dev_list; - uint8_t dev_cnt = 0; uint8_t tx_buff[64] = {}; uint16_t tx_len = 0; uint8_t rx_buff[512] = {}; @@ -881,19 +485,17 @@ void nfc_worker_read_mifare_desfire(NfcWorker* nfc_worker) { NfcDeviceData* result = nfc_worker->dev_data; nfc_device_data_clear(result); MifareDesfireData* data = &result->mf_df_data; + FuriHalNfcDevData* nfc_data = &nfc_worker->dev_data->nfc_data; while(nfc_worker->state == NfcWorkerStateReadMifareDesfire) { - furi_hal_nfc_deactivate(); - if(!furi_hal_nfc_detect(&dev_list, &dev_cnt, 300, false)) { + furi_hal_nfc_sleep(); + if(!furi_hal_nfc_detect(nfc_data, 300)) { osDelay(100); continue; } memset(data, 0, sizeof(MifareDesfireData)); - if(dev_list[0].type != RFAL_NFC_LISTEN_TYPE_NFCA || - !mf_df_check_card_type( - dev_list[0].dev.nfca.sensRes.anticollisionInfo, - dev_list[0].dev.nfca.sensRes.platformInfo, - dev_list[0].dev.nfca.selRes.sak)) { + if(nfc_data->type != FuriHalNfcTypeA || + !mf_df_check_card_type(nfc_data->atqa[0], nfc_data->atqa[1], nfc_data->sak)) { FURI_LOG_D(TAG, "Tag is not DESFire"); osDelay(100); continue; @@ -901,18 +503,11 @@ void nfc_worker_read_mifare_desfire(NfcWorker* nfc_worker) { FURI_LOG_D(TAG, "Found DESFire tag"); - // Fill non-DESFire result data - result->nfc_data.uid_len = dev_list[0].dev.nfca.nfcId1Len; - result->nfc_data.atqa[0] = dev_list[0].dev.nfca.sensRes.anticollisionInfo; - result->nfc_data.atqa[1] = dev_list[0].dev.nfca.sensRes.platformInfo; - result->nfc_data.sak = dev_list[0].dev.nfca.selRes.sak; - result->nfc_data.device = NfcDeviceNfca; - result->nfc_data.protocol = NfcDeviceProtocolMifareDesfire; - memcpy(result->nfc_data.uid, dev_list[0].dev.nfca.nfcId1, result->nfc_data.uid_len); + result->protocol = NfcDeviceProtocolMifareDesfire; // Get DESFire version tx_len = mf_df_prepare_get_version(tx_buff); - err = nfc_exchange_full(tx_buff, tx_len, rx_buff, sizeof(rx_buff), &rx_len); + err = furi_hal_nfc_exchange_full(tx_buff, tx_len, rx_buff, sizeof(rx_buff), &rx_len); if(err != ERR_NONE) { FURI_LOG_W(TAG, "Bad exchange getting version, err: %d", err); continue; @@ -923,7 +518,7 @@ void nfc_worker_read_mifare_desfire(NfcWorker* nfc_worker) { } tx_len = mf_df_prepare_get_free_memory(tx_buff); - err = nfc_exchange_full(tx_buff, tx_len, rx_buff, sizeof(rx_buff), &rx_len); + err = furi_hal_nfc_exchange_full(tx_buff, tx_len, rx_buff, sizeof(rx_buff), &rx_len); if(err == ERR_NONE) { data->free_memory = malloc(sizeof(MifareDesfireFreeMemory)); memset(data->free_memory, 0, sizeof(MifareDesfireFreeMemory)); @@ -935,7 +530,7 @@ void nfc_worker_read_mifare_desfire(NfcWorker* nfc_worker) { } tx_len = mf_df_prepare_get_key_settings(tx_buff); - err = nfc_exchange_full(tx_buff, tx_len, rx_buff, sizeof(rx_buff), &rx_len); + err = furi_hal_nfc_exchange_full(tx_buff, tx_len, rx_buff, sizeof(rx_buff), &rx_len); if(err != ERR_NONE) { FURI_LOG_D(TAG, "Bad exchange getting key settings, err: %d", err); } else { @@ -951,7 +546,8 @@ void nfc_worker_read_mifare_desfire(NfcWorker* nfc_worker) { &data->master_key_settings->key_version_head; for(uint8_t key_id = 0; key_id < data->master_key_settings->max_keys; key_id++) { tx_len = mf_df_prepare_get_key_version(tx_buff, key_id); - err = nfc_exchange_full(tx_buff, tx_len, rx_buff, sizeof(rx_buff), &rx_len); + err = + furi_hal_nfc_exchange_full(tx_buff, tx_len, rx_buff, sizeof(rx_buff), &rx_len); if(err != ERR_NONE) { FURI_LOG_W(TAG, "Bad exchange getting key version, err: %d", err); continue; @@ -970,7 +566,7 @@ void nfc_worker_read_mifare_desfire(NfcWorker* nfc_worker) { } tx_len = mf_df_prepare_get_application_ids(tx_buff); - err = nfc_exchange_full(tx_buff, tx_len, rx_buff, sizeof(rx_buff), &rx_len); + err = furi_hal_nfc_exchange_full(tx_buff, tx_len, rx_buff, sizeof(rx_buff), &rx_len); if(err != ERR_NONE) { FURI_LOG_W(TAG, "Bad exchange getting application IDs, err: %d", err); } else { @@ -981,13 +577,13 @@ void nfc_worker_read_mifare_desfire(NfcWorker* nfc_worker) { for(MifareDesfireApplication* app = data->app_head; app; app = app->next) { tx_len = mf_df_prepare_select_application(tx_buff, app->id); - err = nfc_exchange_full(tx_buff, tx_len, rx_buff, sizeof(rx_buff), &rx_len); + err = furi_hal_nfc_exchange_full(tx_buff, tx_len, rx_buff, sizeof(rx_buff), &rx_len); if(!mf_df_parse_select_application_response(rx_buff, rx_len)) { FURI_LOG_W(TAG, "Bad exchange selecting application, err: %d", err); continue; } tx_len = mf_df_prepare_get_key_settings(tx_buff); - err = nfc_exchange_full(tx_buff, tx_len, rx_buff, sizeof(rx_buff), &rx_len); + err = furi_hal_nfc_exchange_full(tx_buff, tx_len, rx_buff, sizeof(rx_buff), &rx_len); if(err != ERR_NONE) { FURI_LOG_W(TAG, "Bad exchange getting key settings, err: %d", err); } else { @@ -1002,7 +598,8 @@ void nfc_worker_read_mifare_desfire(NfcWorker* nfc_worker) { MifareDesfireKeyVersion** key_version_head = &app->key_settings->key_version_head; for(uint8_t key_id = 0; key_id < app->key_settings->max_keys; key_id++) { tx_len = mf_df_prepare_get_key_version(tx_buff, key_id); - err = nfc_exchange_full(tx_buff, tx_len, rx_buff, sizeof(rx_buff), &rx_len); + err = furi_hal_nfc_exchange_full( + tx_buff, tx_len, rx_buff, sizeof(rx_buff), &rx_len); if(err != ERR_NONE) { FURI_LOG_W(TAG, "Bad exchange getting key version, err: %d", err); continue; @@ -1021,7 +618,7 @@ void nfc_worker_read_mifare_desfire(NfcWorker* nfc_worker) { } tx_len = mf_df_prepare_get_file_ids(tx_buff); - err = nfc_exchange_full(tx_buff, tx_len, rx_buff, sizeof(rx_buff), &rx_len); + err = furi_hal_nfc_exchange_full(tx_buff, tx_len, rx_buff, sizeof(rx_buff), &rx_len); if(err != ERR_NONE) { FURI_LOG_W(TAG, "Bad exchange getting file IDs, err: %d", err); } else { @@ -1032,7 +629,8 @@ void nfc_worker_read_mifare_desfire(NfcWorker* nfc_worker) { for(MifareDesfireFile* file = app->file_head; file; file = file->next) { tx_len = mf_df_prepare_get_file_settings(tx_buff, file->id); - err = nfc_exchange_full(tx_buff, tx_len, rx_buff, sizeof(rx_buff), &rx_len); + err = + furi_hal_nfc_exchange_full(tx_buff, tx_len, rx_buff, sizeof(rx_buff), &rx_len); if(err != ERR_NONE) { FURI_LOG_W(TAG, "Bad exchange getting file settings, err: %d", err); continue; @@ -1054,7 +652,8 @@ void nfc_worker_read_mifare_desfire(NfcWorker* nfc_worker) { tx_len = mf_df_prepare_read_records(tx_buff, file->id, 0, 0); break; } - err = nfc_exchange_full(tx_buff, tx_len, rx_buff, sizeof(rx_buff), &rx_len); + err = + furi_hal_nfc_exchange_full(tx_buff, tx_len, rx_buff, sizeof(rx_buff), &rx_len); if(err != ERR_NONE) { FURI_LOG_W(TAG, "Bad exchange reading file %d, err: %d", file->id, err); continue; @@ -1073,11 +672,3 @@ void nfc_worker_read_mifare_desfire(NfcWorker* nfc_worker) { break; } } - -void nfc_worker_field(NfcWorker* nfc_worker) { - furi_hal_nfc_field_on(); - while(nfc_worker->state == NfcWorkerStateField) { - osDelay(50); - } - furi_hal_nfc_field_off(); -} diff --git a/applications/nfc/nfc_worker.h b/applications/nfc/nfc_worker.h index a0a5ae83d..1933a79b7 100755 --- a/applications/nfc/nfc_worker.h +++ b/applications/nfc/nfc_worker.h @@ -13,11 +13,11 @@ typedef enum { NfcWorkerStateDetect, NfcWorkerStateEmulate, NfcWorkerStateReadEMVApp, - NfcWorkerStateReadEMV, + NfcWorkerStateReadEMVData, NfcWorkerStateEmulateApdu, NfcWorkerStateField, - NfcWorkerStateReadMifareUl, - NfcWorkerStateEmulateMifareUl, + NfcWorkerStateReadMifareUltralight, + NfcWorkerStateEmulateMifareUltralight, NfcWorkerStateReadMifareClassic, NfcWorkerStateReadMifareDesfire, // Transition diff --git a/applications/nfc/nfc_worker_i.h b/applications/nfc/nfc_worker_i.h index bba983fc4..a6f937f7d 100755 --- a/applications/nfc/nfc_worker_i.h +++ b/applications/nfc/nfc_worker_i.h @@ -4,19 +4,8 @@ #include "nfc_worker.h" #include -#include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include - struct NfcWorker { FuriThread* thread; Storage* storage; @@ -44,9 +33,7 @@ void nfc_worker_detect(NfcWorker* nfc_worker); void nfc_worker_emulate(NfcWorker* nfc_worker); -void nfc_worker_field(NfcWorker* nfc_worker); - -void nfc_worker_read_mifare_ul(NfcWorker* nfc_worker); +void nfc_worker_read_mifare_ultralight(NfcWorker* nfc_worker); void nfc_worker_mifare_classic_dict_attack(NfcWorker* nfc_worker); diff --git a/applications/nfc/scenes/nfc_scene_card_menu.c b/applications/nfc/scenes/nfc_scene_card_menu.c index 03497958d..b78624097 100755 --- a/applications/nfc/scenes/nfc_scene_card_menu.c +++ b/applications/nfc/scenes/nfc_scene_card_menu.c @@ -17,7 +17,7 @@ void nfc_scene_card_menu_on_enter(void* context) { Nfc* nfc = context; Submenu* submenu = nfc->submenu; - if(nfc->dev->dev_data.nfc_data.protocol > NfcDeviceProtocolUnknown) { + if(nfc->dev->dev_data.protocol > NfcDeviceProtocolUnknown) { submenu_add_item( submenu, "Run Compatible App", @@ -49,13 +49,13 @@ bool nfc_scene_card_menu_on_event(void* context, SceneManagerEvent event) { if(event.event == SubmenuIndexRunApp) { scene_manager_set_scene_state( nfc->scene_manager, NfcSceneCardMenu, SubmenuIndexRunApp); - if(nfc->dev->dev_data.nfc_data.protocol == NfcDeviceProtocolMifareUl) { + if(nfc->dev->dev_data.protocol == NfcDeviceProtocolMifareUl) { scene_manager_next_scene(nfc->scene_manager, NfcSceneReadMifareUl); - } else if(nfc->dev->dev_data.nfc_data.protocol == NfcDeviceProtocolMifareDesfire) { + } else if(nfc->dev->dev_data.protocol == NfcDeviceProtocolMifareDesfire) { scene_manager_next_scene(nfc->scene_manager, NfcSceneReadMifareDesfire); - } else if(nfc->dev->dev_data.nfc_data.protocol == NfcDeviceProtocolEMV) { + } else if(nfc->dev->dev_data.protocol == NfcDeviceProtocolEMV) { scene_manager_next_scene(nfc->scene_manager, NfcSceneReadEmvApp); - } else if(nfc->dev->dev_data.nfc_data.protocol == NfcDeviceProtocolMifareClassic) { + } else if(nfc->dev->dev_data.protocol == NfcDeviceProtocolMifareClassic) { scene_manager_next_scene(nfc->scene_manager, NfcSceneReadMifareClassic); } consumed = true; diff --git a/applications/nfc/scenes/nfc_scene_config.h b/applications/nfc/scenes/nfc_scene_config.h index c66725b95..6b5d5d10c 100755 --- a/applications/nfc/scenes/nfc_scene_config.h +++ b/applications/nfc/scenes/nfc_scene_config.h @@ -2,7 +2,6 @@ ADD_SCENE(nfc, start, Start) ADD_SCENE(nfc, read_card, ReadCard) ADD_SCENE(nfc, read_card_success, ReadCardSuccess) ADD_SCENE(nfc, card_menu, CardMenu) -ADD_SCENE(nfc, not_implemented, NotImplemented) ADD_SCENE(nfc, emulate_uid, EmulateUid) ADD_SCENE(nfc, save_name, SaveName) ADD_SCENE(nfc, save_success, SaveSuccess) diff --git a/applications/nfc/scenes/nfc_scene_debug.c b/applications/nfc/scenes/nfc_scene_debug.c index a8f1e686f..ed079c2ed 100644 --- a/applications/nfc/scenes/nfc_scene_debug.c +++ b/applications/nfc/scenes/nfc_scene_debug.c @@ -6,13 +6,13 @@ enum SubmenuDebugIndex { }; void nfc_scene_debug_submenu_callback(void* context, uint32_t index) { - Nfc* nfc = (Nfc*)context; + Nfc* nfc = context; view_dispatcher_send_custom_event(nfc->view_dispatcher, index); } void nfc_scene_debug_on_enter(void* context) { - Nfc* nfc = (Nfc*)context; + Nfc* nfc = context; Submenu* submenu = nfc->submenu; submenu_add_item( @@ -28,7 +28,7 @@ void nfc_scene_debug_on_enter(void* context) { } bool nfc_scene_debug_on_event(void* context, SceneManagerEvent event) { - Nfc* nfc = (Nfc*)context; + Nfc* nfc = context; bool consumed = false; if(event.type == SceneManagerEventTypeCustom) { @@ -48,7 +48,7 @@ bool nfc_scene_debug_on_event(void* context, SceneManagerEvent event) { } void nfc_scene_debug_on_exit(void* context) { - Nfc* nfc = (Nfc*)context; + Nfc* nfc = context; submenu_reset(nfc->submenu); } diff --git a/applications/nfc/scenes/nfc_scene_delete.c b/applications/nfc/scenes/nfc_scene_delete.c index 2661d1667..29328743c 100755 --- a/applications/nfc/scenes/nfc_scene_delete.c +++ b/applications/nfc/scenes/nfc_scene_delete.c @@ -1,29 +1,28 @@ #include "../nfc_i.h" void nfc_scene_delete_widget_callback(GuiButtonType result, InputType type, void* context) { - Nfc* nfc = (Nfc*)context; + Nfc* nfc = context; if(type == InputTypeShort) { view_dispatcher_send_custom_event(nfc->view_dispatcher, result); } } void nfc_scene_delete_on_enter(void* context) { - Nfc* nfc = (Nfc*)context; + Nfc* nfc = context; // Setup Custom Widget view - char delete_str[64]; - snprintf(delete_str, sizeof(delete_str), "\e#Delete %s?\e#", nfc->dev->dev_name); - widget_add_text_box_element(nfc->widget, 0, 0, 128, 23, AlignCenter, AlignCenter, delete_str); + char temp_str[64]; + snprintf(temp_str, sizeof(temp_str), "\e#Delete %s?\e#", nfc->dev->dev_name); + widget_add_text_box_element(nfc->widget, 0, 0, 128, 23, AlignCenter, AlignCenter, temp_str); widget_add_button_element( nfc->widget, GuiButtonTypeLeft, "Back", nfc_scene_delete_widget_callback, nfc); widget_add_button_element( nfc->widget, GuiButtonTypeRight, "Delete", nfc_scene_delete_widget_callback, nfc); - char uid_str[32]; - NfcDeviceCommonData* data = &nfc->dev->dev_data.nfc_data; + FuriHalNfcDevData* data = &nfc->dev->dev_data.nfc_data; if(data->uid_len == 4) { snprintf( - uid_str, - sizeof(uid_str), + temp_str, + sizeof(temp_str), "UID: %02X %02X %02X %02X", data->uid[0], data->uid[1], @@ -31,8 +30,8 @@ void nfc_scene_delete_on_enter(void* context) { data->uid[3]); } else if(data->uid_len == 7) { snprintf( - uid_str, - sizeof(uid_str), + temp_str, + sizeof(temp_str), "UID: %02X %02X %02X %02X %02X %02X %02X", data->uid[0], data->uid[1], @@ -42,12 +41,13 @@ void nfc_scene_delete_on_enter(void* context) { data->uid[5], data->uid[6]); } - widget_add_string_element(nfc->widget, 64, 23, AlignCenter, AlignTop, FontSecondary, uid_str); + widget_add_string_element(nfc->widget, 64, 23, AlignCenter, AlignTop, FontSecondary, temp_str); const char* protocol_name = NULL; - if(data->protocol == NfcDeviceProtocolEMV) { - protocol_name = nfc_guess_protocol(data->protocol); - } else if(data->protocol == NfcDeviceProtocolMifareUl) { + NfcProtocol protocol = nfc->dev->dev_data.protocol; + if(protocol == NfcDeviceProtocolEMV) { + protocol_name = nfc_guess_protocol(protocol); + } else if(protocol == NfcDeviceProtocolMifareUl) { protocol_name = nfc_mf_ul_type(nfc->dev->dev_data.mf_ul_data.type, false); } if(protocol_name) { @@ -56,18 +56,17 @@ void nfc_scene_delete_on_enter(void* context) { } // TODO change dinamically widget_add_string_element(nfc->widget, 118, 33, AlignRight, AlignTop, FontSecondary, "NFC-A"); - char sak_str[16]; - snprintf(sak_str, sizeof(sak_str), "SAK: %02X", data->sak); - widget_add_string_element(nfc->widget, 10, 43, AlignLeft, AlignTop, FontSecondary, sak_str); - char atqa_str[16]; - snprintf(atqa_str, sizeof(atqa_str), "ATQA: %02X%02X", data->atqa[0], data->atqa[1]); - widget_add_string_element(nfc->widget, 118, 43, AlignRight, AlignTop, FontSecondary, atqa_str); + snprintf(temp_str, sizeof(temp_str), "SAK: %02X", data->sak); + widget_add_string_element(nfc->widget, 10, 43, AlignLeft, AlignTop, FontSecondary, temp_str); + snprintf(temp_str, sizeof(temp_str), "ATQA: %02X%02X", data->atqa[0], data->atqa[1]); + widget_add_string_element(nfc->widget, 118, 43, AlignRight, AlignTop, FontSecondary, temp_str); view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewWidget); } bool nfc_scene_delete_on_event(void* context, SceneManagerEvent event) { - Nfc* nfc = (Nfc*)context; + Nfc* nfc = context; + bool consumed = false; if(event.type == SceneManagerEventTypeCustom) { if(event.event == GuiButtonTypeLeft) { @@ -79,14 +78,14 @@ bool nfc_scene_delete_on_event(void* context, SceneManagerEvent event) { scene_manager_search_and_switch_to_previous_scene( nfc->scene_manager, NfcSceneStart); } - return true; + consumed = true; } } - return false; + return consumed; } void nfc_scene_delete_on_exit(void* context) { - Nfc* nfc = (Nfc*)context; + Nfc* nfc = context; widget_reset(nfc->widget); } diff --git a/applications/nfc/scenes/nfc_scene_delete_success.c b/applications/nfc/scenes/nfc_scene_delete_success.c index 1392fa9e0..a52c40d86 100755 --- a/applications/nfc/scenes/nfc_scene_delete_success.c +++ b/applications/nfc/scenes/nfc_scene_delete_success.c @@ -1,12 +1,12 @@ #include "../nfc_i.h" void nfc_scene_delete_success_popup_callback(void* context) { - Nfc* nfc = (Nfc*)context; + Nfc* nfc = context; view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventViewExit); } void nfc_scene_delete_success_on_enter(void* context) { - Nfc* nfc = (Nfc*)context; + Nfc* nfc = context; // Setup view Popup* popup = nfc->popup; @@ -20,27 +20,21 @@ void nfc_scene_delete_success_on_enter(void* context) { } bool nfc_scene_delete_success_on_event(void* context, SceneManagerEvent event) { - Nfc* nfc = (Nfc*)context; + Nfc* nfc = context; + bool consumed = false; if(event.type == SceneManagerEventTypeCustom) { if(event.event == NfcCustomEventViewExit) { - return scene_manager_search_and_switch_to_previous_scene( + consumed = scene_manager_search_and_switch_to_previous_scene( nfc->scene_manager, NfcSceneStart); } } - return false; + return consumed; } void nfc_scene_delete_success_on_exit(void* context) { - Nfc* nfc = (Nfc*)context; + Nfc* nfc = context; // 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); - popup_set_callback(popup, NULL); - popup_set_context(popup, NULL); - popup_set_timeout(popup, 0); - popup_disable_timeout(popup); -} + popup_reset(nfc->popup); +} \ No newline at end of file diff --git a/applications/nfc/scenes/nfc_scene_device_info.c b/applications/nfc/scenes/nfc_scene_device_info.c index d408e555d..78e56c097 100644 --- a/applications/nfc/scenes/nfc_scene_device_info.c +++ b/applications/nfc/scenes/nfc_scene_device_info.c @@ -43,12 +43,12 @@ void nfc_scene_device_info_on_enter(void* context) { widget_add_button_element( nfc->widget, GuiButtonTypeRight, "Data", nfc_scene_device_info_widget_callback, nfc); } - char uid_str[32]; - NfcDeviceCommonData* data = &nfc->dev->dev_data.nfc_data; + char temp_str[32]; + FuriHalNfcDevData* data = &nfc->dev->dev_data.nfc_data; if(data->uid_len == 4) { snprintf( - uid_str, - sizeof(uid_str), + temp_str, + sizeof(temp_str), "UID: %02X %02X %02X %02X", data->uid[0], data->uid[1], @@ -56,8 +56,8 @@ void nfc_scene_device_info_on_enter(void* context) { data->uid[3]); } else if(data->uid_len == 7) { snprintf( - uid_str, - sizeof(uid_str), + temp_str, + sizeof(temp_str), "UID: %02X %02X %02X %02X %02X %02X %02X", data->uid[0], data->uid[1], @@ -67,15 +67,15 @@ void nfc_scene_device_info_on_enter(void* context) { data->uid[5], data->uid[6]); } - widget_add_string_element(nfc->widget, 64, 21, AlignCenter, AlignTop, FontSecondary, uid_str); + widget_add_string_element(nfc->widget, 64, 21, AlignCenter, AlignTop, FontSecondary, temp_str); const char* protocol_name = NULL; - if(data->protocol == NfcDeviceProtocolEMV || - data->protocol == NfcDeviceProtocolMifareDesfire) { - protocol_name = nfc_guess_protocol(data->protocol); - } else if(data->protocol == NfcDeviceProtocolMifareUl) { + NfcProtocol protocol = nfc->dev->dev_data.protocol; + if(protocol == NfcDeviceProtocolEMV || protocol == NfcDeviceProtocolMifareDesfire) { + protocol_name = nfc_guess_protocol(protocol); + } else if(protocol == NfcDeviceProtocolMifareUl) { protocol_name = nfc_mf_ul_type(nfc->dev->dev_data.mf_ul_data.type, false); - } else if(data->protocol == NfcDeviceProtocolMifareClassic) { + } else if(protocol == NfcDeviceProtocolMifareClassic) { protocol_name = nfc_mf_classic_type(nfc->dev->dev_data.mf_classic_data.type); } if(protocol_name) { @@ -84,12 +84,10 @@ void nfc_scene_device_info_on_enter(void* context) { } // TODO change dinamically widget_add_string_element(nfc->widget, 118, 32, AlignRight, AlignTop, FontSecondary, "NFC-A"); - char sak_str[16]; - snprintf(sak_str, sizeof(sak_str), "SAK: %02X", data->sak); - widget_add_string_element(nfc->widget, 10, 42, AlignLeft, AlignTop, FontSecondary, sak_str); - char atqa_str[16]; - snprintf(atqa_str, sizeof(atqa_str), "ATQA: %02X%02X", data->atqa[0], data->atqa[1]); - widget_add_string_element(nfc->widget, 118, 42, AlignRight, AlignTop, FontSecondary, atqa_str); + snprintf(temp_str, sizeof(temp_str), "SAK: %02X", data->sak); + widget_add_string_element(nfc->widget, 10, 42, AlignLeft, AlignTop, FontSecondary, temp_str); + snprintf(temp_str, sizeof(temp_str), "ATQA: %02X%02X", data->atqa[0], data->atqa[1]); + widget_add_string_element(nfc->widget, 118, 42, AlignRight, AlignTop, FontSecondary, temp_str); // Setup Data View if(nfc->dev->format == NfcDeviceSaveFormatUid) { @@ -99,7 +97,7 @@ void nfc_scene_device_info_on_enter(void* context) { dialog_ex_set_context(dialog_ex, nfc); dialog_ex_set_result_callback(dialog_ex, nfc_scene_device_info_dialog_callback); } else if(nfc->dev->format == NfcDeviceSaveFormatMifareUl) { - MifareUlData* mf_ul_data = &nfc->dev->dev_data.mf_ul_data; + MfUltralightData* mf_ul_data = &nfc->dev->dev_data.mf_ul_data; TextBox* text_box = nfc->text_box; text_box_set_font(text_box, TextBoxFontHex); for(uint16_t i = 0; i < mf_ul_data->data_size; i += 2) { @@ -130,7 +128,7 @@ void nfc_scene_device_info_on_enter(void* context) { widget_add_string_element( nfc->widget, 64, 17, AlignCenter, AlignBottom, FontSecondary, nfc->text_store); } else if(nfc->dev->format == NfcDeviceSaveFormatBankCard) { - NfcEmvData* emv_data = &nfc->dev->dev_data.emv_data; + EmvData* 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, emv_data->number_len); @@ -212,21 +210,16 @@ bool nfc_scene_device_info_on_event(void* context, SceneManagerEvent event) { } void nfc_scene_device_info_on_exit(void* context) { - Nfc* nfc = (Nfc*)context; + Nfc* nfc = context; - // Clear Custom Widget + // Clear views widget_reset(nfc->widget); - if(nfc->dev->format == NfcDeviceSaveFormatUid) { - // Clear Dialog - DialogEx* dialog_ex = nfc->dialog_ex; - dialog_ex_reset(dialog_ex); + dialog_ex_reset(nfc->dialog_ex); } else if(nfc->dev->format == NfcDeviceSaveFormatMifareUl) { - // Clear TextBox text_box_reset(nfc->text_box); string_reset(nfc->text_box_store); } else if(nfc->dev->format == NfcDeviceSaveFormatBankCard) { - // Clear Bank Card bank_card_clear(nfc->bank_card); } } diff --git a/applications/nfc/scenes/nfc_scene_emulate_apdu_sequence.c b/applications/nfc/scenes/nfc_scene_emulate_apdu_sequence.c index 1a87ea583..4f9626e9b 100644 --- a/applications/nfc/scenes/nfc_scene_emulate_apdu_sequence.c +++ b/applications/nfc/scenes/nfc_scene_emulate_apdu_sequence.c @@ -1,36 +1,34 @@ #include "../nfc_i.h" void nfc_scene_emulate_apdu_sequence_on_enter(void* context) { - Nfc* nfc = (Nfc*)context; + Nfc* nfc = context; // Setup view Popup* popup = nfc->popup; - popup_set_header(popup, "Run APDU reader", 64, 31, AlignCenter, AlignTop); // Setup and start worker - view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewPopup); nfc_worker_start(nfc->worker, NfcWorkerStateEmulateApdu, &nfc->dev->dev_data, NULL, nfc); } bool nfc_scene_emulate_apdu_sequence_on_event(void* context, SceneManagerEvent event) { - Nfc* nfc = (Nfc*)context; + Nfc* nfc = context; + bool consumed = false; if(event.type == SceneManagerEventTypeTick) { notification_message(nfc->notifications, &sequence_blink_blue_10); - return true; + consumed = true; } - return false; + + return consumed; } void nfc_scene_emulate_apdu_sequence_on_exit(void* context) { - Nfc* nfc = (Nfc*)context; + Nfc* nfc = context; // Stop worker nfc_worker_stop(nfc->worker); - // Clear view - Popup* popup = nfc->popup; - popup_reset(popup); + popup_reset(nfc->popup); } diff --git a/applications/nfc/scenes/nfc_scene_emulate_mifare_ul.c b/applications/nfc/scenes/nfc_scene_emulate_mifare_ul.c index 68225f33f..871ca6364 100755 --- a/applications/nfc/scenes/nfc_scene_emulate_mifare_ul.c +++ b/applications/nfc/scenes/nfc_scene_emulate_mifare_ul.c @@ -5,13 +5,14 @@ #define NFC_MF_UL_DATA_CHANGED (1UL) void nfc_emulate_mifare_ul_worker_callback(NfcWorkerEvent event, void* context) { - Nfc* nfc = (Nfc*)context; + Nfc* nfc = context; + scene_manager_set_scene_state( nfc->scene_manager, NfcSceneEmulateMifareUl, NFC_MF_UL_DATA_CHANGED); } void nfc_scene_emulate_mifare_ul_on_enter(void* context) { - Nfc* nfc = (Nfc*)context; + Nfc* nfc = context; DOLPHIN_DEED(DolphinDeedNfcEmulate); // Setup view @@ -26,14 +27,14 @@ void nfc_scene_emulate_mifare_ul_on_enter(void* context) { view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewPopup); nfc_worker_start( nfc->worker, - NfcWorkerStateEmulateMifareUl, + NfcWorkerStateEmulateMifareUltralight, &nfc->dev->dev_data, nfc_emulate_mifare_ul_worker_callback, nfc); } bool nfc_scene_emulate_mifare_ul_on_event(void* context, SceneManagerEvent event) { - Nfc* nfc = (Nfc*)context; + Nfc* nfc = context; bool consumed = false; if(event.type == SceneManagerEventTypeTick) { @@ -55,11 +56,8 @@ bool nfc_scene_emulate_mifare_ul_on_event(void* context, SceneManagerEvent event } void nfc_scene_emulate_mifare_ul_on_exit(void* context) { - Nfc* nfc = (Nfc*)context; + Nfc* nfc = context; // 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); + popup_reset(nfc->popup); } diff --git a/applications/nfc/scenes/nfc_scene_emulate_uid.c b/applications/nfc/scenes/nfc_scene_emulate_uid.c index 027a325de..3eeb5706a 100755 --- a/applications/nfc/scenes/nfc_scene_emulate_uid.c +++ b/applications/nfc/scenes/nfc_scene_emulate_uid.c @@ -1,6 +1,8 @@ #include "../nfc_i.h" #include +#define NFC_SCENE_EMULATE_UID_LOG_SIZE_MAX (200) + enum { NfcSceneEmulateUidStateWidget, NfcSceneEmulateUidStateTextBox, @@ -28,7 +30,7 @@ void nfc_emulate_uid_textbox_callback(void* context) { // Add widget with device name or inform that data received static void nfc_scene_emulate_uid_widget_config(Nfc* nfc, bool data_received) { - NfcDeviceCommonData* data = &nfc->dev->dev_data.nfc_data; + FuriHalNfcDevData* data = &nfc->dev->dev_data.nfc_data; Widget* widget = nfc->widget; widget_reset(widget); string_t info_str; @@ -95,13 +97,15 @@ bool nfc_scene_emulate_uid_on_event(void* context, SceneManagerEvent event) { nfc_scene_emulate_uid_widget_config(nfc, true); } // Update TextBox data - string_cat_printf(nfc->text_box_store, "R:"); - for(uint16_t i = 0; i < reader_data->size; i++) { - string_cat_printf(nfc->text_box_store, " %02X", reader_data->data[i]); + if(string_size(nfc->text_box_store) < NFC_SCENE_EMULATE_UID_LOG_SIZE_MAX) { + string_cat_printf(nfc->text_box_store, "R:"); + for(uint16_t i = 0; i < reader_data->size; i++) { + string_cat_printf(nfc->text_box_store, " %02X", reader_data->data[i]); + } + string_push_back(nfc->text_box_store, '\n'); + text_box_set_text(nfc->text_box, string_get_cstr(nfc->text_box_store)); } - string_push_back(nfc->text_box_store, '\n'); memset(reader_data, 0, sizeof(NfcReaderRequestData)); - text_box_set_text(nfc->text_box, string_get_cstr(nfc->text_box_store)); consumed = true; } else if(event.event == GuiButtonTypeCenter && state == NfcSceneEmulateUidStateWidget) { view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewTextBox); diff --git a/applications/nfc/scenes/nfc_scene_field.c b/applications/nfc/scenes/nfc_scene_field.c index 366703876..31cf74b8e 100644 --- a/applications/nfc/scenes/nfc_scene_field.c +++ b/applications/nfc/scenes/nfc_scene_field.c @@ -1,7 +1,7 @@ #include "../nfc_i.h" void nfc_scene_field_on_enter(void* context) { - Nfc* nfc = (Nfc*)context; + Nfc* nfc = context; furi_hal_nfc_field_on(); @@ -23,12 +23,9 @@ bool nfc_scene_field_on_event(void* context, SceneManagerEvent event) { } void nfc_scene_field_on_exit(void* context) { - Nfc* nfc = (Nfc*)context; - - notification_internal_message(nfc->notifications, &sequence_reset_blue); - - Popup* popup = nfc->popup; - popup_reset(popup); + Nfc* nfc = context; furi_hal_nfc_field_off(); + notification_internal_message(nfc->notifications, &sequence_reset_blue); + popup_reset(nfc->popup); } diff --git a/applications/nfc/scenes/nfc_scene_file_select.c b/applications/nfc/scenes/nfc_scene_file_select.c index 010e807ef..a8126456f 100755 --- a/applications/nfc/scenes/nfc_scene_file_select.c +++ b/applications/nfc/scenes/nfc_scene_file_select.c @@ -1,7 +1,7 @@ #include "../nfc_i.h" void nfc_scene_file_select_on_enter(void* context) { - Nfc* nfc = (Nfc*)context; + Nfc* nfc = context; // Process file_select return if(nfc_file_select(nfc->dev)) { scene_manager_next_scene(nfc->scene_manager, NfcSceneSavedMenu); diff --git a/applications/nfc/scenes/nfc_scene_mifare_desfire_app.c b/applications/nfc/scenes/nfc_scene_mifare_desfire_app.c index e68d46d1f..0974c062c 100644 --- a/applications/nfc/scenes/nfc_scene_mifare_desfire_app.c +++ b/applications/nfc/scenes/nfc_scene_mifare_desfire_app.c @@ -18,13 +18,13 @@ MifareDesfireApplication* nfc_scene_mifare_desfire_app_get_app(Nfc* nfc) { } void nfc_scene_mifare_desfire_app_submenu_callback(void* context, uint32_t index) { - Nfc* nfc = (Nfc*)context; + Nfc* nfc = context; view_dispatcher_send_custom_event(nfc->view_dispatcher, index); } void nfc_scene_mifare_desfire_app_on_enter(void* context) { - Nfc* nfc = (Nfc*)context; + Nfc* nfc = context; Submenu* submenu = nfc->submenu; MifareDesfireApplication* app = nfc_scene_mifare_desfire_app_get_app(nfc); if(!app) { @@ -73,7 +73,8 @@ void nfc_scene_mifare_desfire_app_on_enter(void* context) { } bool nfc_scene_mifare_desfire_app_on_event(void* context, SceneManagerEvent event) { - Nfc* nfc = (Nfc*)context; + Nfc* nfc = context; + bool consumed = false; uint32_t state = scene_manager_get_scene_state(nfc->scene_manager, NfcSceneMifareDesfireApp); if(event.type == SceneManagerEventTypeCustom) { @@ -96,24 +97,24 @@ bool nfc_scene_mifare_desfire_app_on_event(void* context, SceneManagerEvent even text_box_set_text(text_box, string_get_cstr(nfc->text_box_store)); scene_manager_set_scene_state(nfc->scene_manager, NfcSceneMifareDesfireApp, state | 1); view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewTextBox); - return true; + consumed = true; } else if(event.type == SceneManagerEventTypeBack) { if(state & 1) { view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewMenu); scene_manager_set_scene_state( nfc->scene_manager, NfcSceneMifareDesfireApp, state & ~1); - return true; + consumed = true; } } - return false; + return consumed; } void nfc_scene_mifare_desfire_app_on_exit(void* context) { - Nfc* nfc = (Nfc*)context; + Nfc* nfc = context; + // Clear views text_box_reset(nfc->text_box); string_reset(nfc->text_box_store); - submenu_reset(nfc->submenu); } diff --git a/applications/nfc/scenes/nfc_scene_mifare_desfire_data.c b/applications/nfc/scenes/nfc_scene_mifare_desfire_data.c index c34d7af17..3eb23fc27 100644 --- a/applications/nfc/scenes/nfc_scene_mifare_desfire_data.c +++ b/applications/nfc/scenes/nfc_scene_mifare_desfire_data.c @@ -19,7 +19,7 @@ void nfc_scene_mifare_desfire_data_submenu_callback(void* context, uint32_t inde } void nfc_scene_mifare_desfire_data_on_enter(void* context) { - Nfc* nfc = (Nfc*)context; + Nfc* nfc = context; Submenu* submenu = nfc->submenu; uint32_t state = scene_manager_get_scene_state(nfc->scene_manager, NfcSceneMifareDesfireData); MifareDesfireData* data = &nfc->dev->dev_data.mf_df_data; @@ -61,7 +61,8 @@ void nfc_scene_mifare_desfire_data_on_enter(void* context) { } bool nfc_scene_mifare_desfire_data_on_event(void* context, SceneManagerEvent event) { - Nfc* nfc = (Nfc*)context; + Nfc* nfc = context; + bool consumed = false; uint32_t state = scene_manager_get_scene_state(nfc->scene_manager, NfcSceneMifareDesfireData); MifareDesfireData* data = &nfc->dev->dev_data.mf_df_data; @@ -76,7 +77,7 @@ bool nfc_scene_mifare_desfire_data_on_event(void* context, SceneManagerEvent eve nfc->scene_manager, NfcSceneMifareDesfireData, MifareDesfireDataStateItem + SubmenuIndexCardInfo); - return true; + consumed = true; } else { uint16_t index = event.event - SubmenuIndexDynamic; scene_manager_set_scene_state( @@ -84,25 +85,25 @@ bool nfc_scene_mifare_desfire_data_on_event(void* context, SceneManagerEvent eve scene_manager_set_scene_state( nfc->scene_manager, NfcSceneMifareDesfireApp, index << 1); scene_manager_next_scene(nfc->scene_manager, NfcSceneMifareDesfireApp); - return true; + consumed = true; } } else if(event.type == SceneManagerEventTypeBack) { if(state >= MifareDesfireDataStateItem) { view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewMenu); scene_manager_set_scene_state( nfc->scene_manager, NfcSceneMifareDesfireData, MifareDesfireDataStateMenu); - return true; + consumed = true; } } - return false; + return consumed; } void nfc_scene_mifare_desfire_data_on_exit(void* context) { - Nfc* nfc = (Nfc*)context; + Nfc* nfc = context; + // Clear views text_box_reset(nfc->text_box); string_reset(nfc->text_box_store); - submenu_reset(nfc->submenu); } diff --git a/applications/nfc/scenes/nfc_scene_mifare_desfire_menu.c b/applications/nfc/scenes/nfc_scene_mifare_desfire_menu.c index 9aa68a430..f6171c8b9 100644 --- a/applications/nfc/scenes/nfc_scene_mifare_desfire_menu.c +++ b/applications/nfc/scenes/nfc_scene_mifare_desfire_menu.c @@ -5,13 +5,13 @@ enum SubmenuIndex { }; void nfc_scene_mifare_desfire_menu_submenu_callback(void* context, uint32_t index) { - Nfc* nfc = (Nfc*)context; + Nfc* nfc = context; view_dispatcher_send_custom_event(nfc->view_dispatcher, index); } void nfc_scene_mifare_desfire_menu_on_enter(void* context) { - Nfc* nfc = (Nfc*)context; + Nfc* nfc = context; Submenu* submenu = nfc->submenu; submenu_add_item( @@ -24,7 +24,8 @@ void nfc_scene_mifare_desfire_menu_on_enter(void* context) { } bool nfc_scene_mifare_desfire_menu_on_event(void* context, SceneManagerEvent event) { - Nfc* nfc = (Nfc*)context; + Nfc* nfc = context; + bool consumed = false; if(event.type == SceneManagerEventTypeCustom) { if(event.event == SubmenuIndexSave) { @@ -34,15 +35,16 @@ bool nfc_scene_mifare_desfire_menu_on_event(void* context, SceneManagerEvent eve // Clear device name nfc_device_set_name(nfc->dev, ""); scene_manager_next_scene(nfc->scene_manager, NfcSceneSaveName); - return true; + consumed = true; } } - return false; + return consumed; } void nfc_scene_mifare_desfire_menu_on_exit(void* context) { - Nfc* nfc = (Nfc*)context; + Nfc* nfc = context; + // Clear view submenu_reset(nfc->submenu); } diff --git a/applications/nfc/scenes/nfc_scene_mifare_ul_menu.c b/applications/nfc/scenes/nfc_scene_mifare_ul_menu.c index 0e2aaf997..0099f1a0b 100755 --- a/applications/nfc/scenes/nfc_scene_mifare_ul_menu.c +++ b/applications/nfc/scenes/nfc_scene_mifare_ul_menu.c @@ -6,13 +6,13 @@ enum SubmenuIndex { }; void nfc_scene_mifare_ul_menu_submenu_callback(void* context, uint32_t index) { - Nfc* nfc = (Nfc*)context; + Nfc* nfc = context; view_dispatcher_send_custom_event(nfc->view_dispatcher, index); } void nfc_scene_mifare_ul_menu_on_enter(void* context) { - Nfc* nfc = (Nfc*)context; + Nfc* nfc = context; Submenu* submenu = nfc->submenu; submenu_add_item( @@ -26,7 +26,8 @@ void nfc_scene_mifare_ul_menu_on_enter(void* context) { } bool nfc_scene_mifare_ul_menu_on_event(void* context, SceneManagerEvent event) { - Nfc* nfc = (Nfc*)context; + Nfc* nfc = context; + bool consumed = false; if(event.type == SceneManagerEventTypeCustom) { if(event.event == SubmenuIndexSave) { @@ -36,23 +37,24 @@ bool nfc_scene_mifare_ul_menu_on_event(void* context, SceneManagerEvent event) { // Clear device name nfc_device_set_name(nfc->dev, ""); scene_manager_next_scene(nfc->scene_manager, NfcSceneSaveName); - return true; + consumed = true; } else if(event.event == SubmenuIndexEmulate) { scene_manager_set_scene_state( nfc->scene_manager, NfcSceneMifareUlMenu, SubmenuIndexEmulate); scene_manager_next_scene(nfc->scene_manager, NfcSceneEmulateMifareUl); - return true; + consumed = true; } } else if(event.type == SceneManagerEventTypeBack) { - return scene_manager_search_and_switch_to_previous_scene( - nfc->scene_manager, NfcSceneStart); + consumed = + scene_manager_search_and_switch_to_previous_scene(nfc->scene_manager, NfcSceneStart); } - return false; + return consumed; } void nfc_scene_mifare_ul_menu_on_exit(void* context) { - Nfc* nfc = (Nfc*)context; + Nfc* nfc = context; + // Clear view submenu_reset(nfc->submenu); } diff --git a/applications/nfc/scenes/nfc_scene_not_implemented.c b/applications/nfc/scenes/nfc_scene_not_implemented.c deleted file mode 100644 index 3167f9c0a..000000000 --- a/applications/nfc/scenes/nfc_scene_not_implemented.c +++ /dev/null @@ -1,42 +0,0 @@ -#include "../nfc_i.h" - -void nfc_scene_not_implemented_dialog_callback(DialogExResult result, void* context) { - Nfc* nfc = (Nfc*)context; - - view_dispatcher_send_custom_event(nfc->view_dispatcher, result); -} - -void nfc_scene_not_implemented_on_enter(void* context) { - Nfc* nfc = (Nfc*)context; - - // TODO Set data from worker - DialogEx* dialog_ex = nfc->dialog_ex; - dialog_ex_set_left_button_text(dialog_ex, "Back"); - dialog_ex_set_header(dialog_ex, "Not implemented", 60, 24, AlignCenter, AlignCenter); - dialog_ex_set_context(dialog_ex, nfc); - dialog_ex_set_result_callback(dialog_ex, nfc_scene_not_implemented_dialog_callback); - - view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewDialogEx); -} - -bool nfc_scene_not_implemented_on_event(void* context, SceneManagerEvent event) { - Nfc* nfc = (Nfc*)context; - - if(event.type == SceneManagerEventTypeCustom) { - if(event.event == DialogExResultLeft) { - return scene_manager_previous_scene(nfc->scene_manager); - } - } - return false; -} - -void nfc_scene_not_implemented_on_exit(void* context) { - Nfc* nfc = (Nfc*)context; - - 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_left_button_text(dialog_ex, NULL); - dialog_ex_set_result_callback(dialog_ex, NULL); - dialog_ex_set_context(dialog_ex, NULL); -} diff --git a/applications/nfc/scenes/nfc_scene_read_card.c b/applications/nfc/scenes/nfc_scene_read_card.c index 72a6e4f22..4d151c08e 100755 --- a/applications/nfc/scenes/nfc_scene_read_card.c +++ b/applications/nfc/scenes/nfc_scene_read_card.c @@ -2,12 +2,12 @@ #include void nfc_read_card_worker_callback(NfcWorkerEvent event, void* context) { - Nfc* nfc = (Nfc*)context; + Nfc* nfc = context; view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventWorkerExit); } void nfc_scene_read_card_on_enter(void* context) { - Nfc* nfc = (Nfc*)context; + Nfc* nfc = context; DOLPHIN_DEED(DolphinDeedNfcRead); // Setup view @@ -22,29 +22,26 @@ void nfc_scene_read_card_on_enter(void* context) { } bool nfc_scene_read_card_on_event(void* context, SceneManagerEvent event) { - Nfc* nfc = (Nfc*)context; + Nfc* nfc = context; + bool consumed = false; if(event.type == SceneManagerEventTypeCustom) { if(event.event == NfcCustomEventWorkerExit) { scene_manager_next_scene(nfc->scene_manager, NfcSceneReadCardSuccess); - return true; + consumed = true; } } else if(event.type == SceneManagerEventTypeTick) { notification_message(nfc->notifications, &sequence_blink_blue_10); - return true; + consumed = true; } - return false; + return consumed; } void nfc_scene_read_card_on_exit(void* context) { - Nfc* nfc = (Nfc*)context; + Nfc* nfc = context; // Stop worker nfc_worker_stop(nfc->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); + popup_reset(nfc->popup); } diff --git a/applications/nfc/scenes/nfc_scene_read_card_success.c b/applications/nfc/scenes/nfc_scene_read_card_success.c index 260dccefa..c0a865bca 100755 --- a/applications/nfc/scenes/nfc_scene_read_card_success.c +++ b/applications/nfc/scenes/nfc_scene_read_card_success.c @@ -7,13 +7,15 @@ void nfc_scene_read_card_success_widget_callback( void* context) { furi_assert(context); Nfc* nfc = context; + if(type == InputTypeShort) { view_dispatcher_send_custom_event(nfc->view_dispatcher, result); } } void nfc_scene_read_card_success_on_enter(void* context) { - Nfc* nfc = (Nfc*)context; + Nfc* nfc = context; + string_t data_str; string_t uid_str; string_init(data_str); @@ -24,9 +26,9 @@ void nfc_scene_read_card_success_on_enter(void* context) { notification_message(nfc->notifications, &sequence_success); // Setup view - NfcDeviceCommonData* data = &nfc->dev->dev_data.nfc_data; + FuriHalNfcDevData* data = &nfc->dev->dev_data.nfc_data; Widget* widget = nfc->widget; - string_set_str(data_str, nfc_get_dev_type(data->device)); + string_set_str(data_str, nfc_get_dev_type(data->type)); string_set_str(uid_str, "UID:"); for(uint8_t i = 0; i < data->uid_len; i++) { string_cat_printf(uid_str, " %02X", data->uid[i]); @@ -34,7 +36,7 @@ void nfc_scene_read_card_success_on_enter(void* context) { widget_add_button_element( widget, GuiButtonTypeLeft, "Retry", nfc_scene_read_card_success_widget_callback, nfc); - if(data->device == NfcDeviceNfca) { + if(data->type == FuriHalNfcTypeA) { widget_add_button_element( widget, GuiButtonTypeRight, "More", nfc_scene_read_card_success_widget_callback, nfc); widget_add_icon_element(widget, 8, 13, &I_Medium_chip_22x21); @@ -44,7 +46,7 @@ void nfc_scene_read_card_success_on_enter(void* context) { string_printf( data_str, "%s\nATQA: %02X%02X SAK: %02X", - nfc_guess_protocol(data->protocol), + nfc_guess_protocol(nfc->dev->dev_data.protocol), data->atqa[0], data->atqa[1], data->sak); @@ -66,14 +68,14 @@ void nfc_scene_read_card_success_on_enter(void* context) { } bool nfc_scene_read_card_success_on_event(void* context, SceneManagerEvent event) { - Nfc* nfc = (Nfc*)context; - NfcDeviceCommonData* data = &nfc->dev->dev_data.nfc_data; + Nfc* nfc = context; + FuriHalNfcDevData* data = &nfc->dev->dev_data.nfc_data; bool consumed = false; if(event.type == SceneManagerEventTypeCustom) { if(event.event == GuiButtonTypeLeft) { consumed = scene_manager_previous_scene(nfc->scene_manager); - } else if(data->device == NfcDeviceNfca && event.event == GuiButtonTypeRight) { + } else if(data->type == FuriHalNfcTypeA && event.event == GuiButtonTypeRight) { // Clear device name nfc_device_set_name(nfc->dev, ""); scene_manager_next_scene(nfc->scene_manager, NfcSceneCardMenu); @@ -84,6 +86,8 @@ bool nfc_scene_read_card_success_on_event(void* context, SceneManagerEvent event } void nfc_scene_read_card_success_on_exit(void* context) { - Nfc* nfc = (Nfc*)context; + Nfc* nfc = context; + + // Clear view widget_reset(nfc->widget); } diff --git a/applications/nfc/scenes/nfc_scene_read_emv_app.c b/applications/nfc/scenes/nfc_scene_read_emv_app.c index a2f0a3259..f0192cb9a 100755 --- a/applications/nfc/scenes/nfc_scene_read_emv_app.c +++ b/applications/nfc/scenes/nfc_scene_read_emv_app.c @@ -2,12 +2,12 @@ #include void nfc_read_emv_app_worker_callback(NfcWorkerEvent event, void* context) { - Nfc* nfc = (Nfc*)context; + Nfc* nfc = context; view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventWorkerExit); } void nfc_scene_read_emv_app_on_enter(void* context) { - Nfc* nfc = (Nfc*)context; + Nfc* nfc = context; DOLPHIN_DEED(DolphinDeedNfcRead); // Setup view @@ -26,31 +26,30 @@ void nfc_scene_read_emv_app_on_enter(void* context) { } bool nfc_scene_read_emv_app_on_event(void* context, SceneManagerEvent event) { - Nfc* nfc = (Nfc*)context; + Nfc* nfc = context; + bool consumed = false; if(event.type == SceneManagerEventTypeCustom) { if(event.event == NfcCustomEventWorkerExit) { scene_manager_set_scene_state( nfc->scene_manager, NfcSceneReadEmvAppSuccess, NFC_SEND_NOTIFICATION_TRUE); scene_manager_next_scene(nfc->scene_manager, NfcSceneReadEmvAppSuccess); - return true; + consumed = true; } } else if(event.type == SceneManagerEventTypeTick) { notification_message(nfc->notifications, &sequence_blink_blue_10); - return true; + consumed = true; } - return false; + + return consumed; } void nfc_scene_read_emv_app_on_exit(void* context) { - Nfc* nfc = (Nfc*)context; + Nfc* nfc = context; // Stop worker nfc_worker_stop(nfc->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); + popup_reset(nfc->popup); } diff --git a/applications/nfc/scenes/nfc_scene_read_emv_app_success.c b/applications/nfc/scenes/nfc_scene_read_emv_app_success.c index 057dd59e3..b9bc5ba40 100755 --- a/applications/nfc/scenes/nfc_scene_read_emv_app_success.c +++ b/applications/nfc/scenes/nfc_scene_read_emv_app_success.c @@ -2,27 +2,38 @@ #include "../helpers/nfc_emv_parser.h" #include -#define NFC_SCENE_READ_SUCCESS_SHIFT " " - -void nfc_scene_read_emv_app_success_dialog_callback(DialogExResult result, void* context) { - Nfc* nfc = (Nfc*)context; - - view_dispatcher_send_custom_event(nfc->view_dispatcher, result); +void nfc_scene_read_emv_app_widget_callback(GuiButtonType result, InputType type, void* context) { + Nfc* nfc = context; + if(type == InputTypeShort) { + view_dispatcher_send_custom_event(nfc->view_dispatcher, result); + } } void nfc_scene_read_emv_app_success_on_enter(void* context) { - Nfc* nfc = (Nfc*)context; + Nfc* nfc = context; DOLPHIN_DEED(DolphinDeedNfcReadSuccess); // Setup view - NfcDeviceCommonData* nfc_data = &nfc->dev->dev_data.nfc_data; - NfcEmvData* emv_data = &nfc->dev->dev_data.emv_data; - DialogEx* dialog_ex = nfc->dialog_ex; - dialog_ex_set_left_button_text(dialog_ex, "Retry"); - dialog_ex_set_right_button_text(dialog_ex, "Run app"); - dialog_ex_set_header(dialog_ex, "Found EMV App", 36, 8, AlignLeft, AlignCenter); - dialog_ex_set_icon(dialog_ex, 8, 13, &I_Medium_chip_22x21); - // Display UID and AID + FuriHalNfcDevData* nfc_data = &nfc->dev->dev_data.nfc_data; + EmvData* emv_data = &nfc->dev->dev_data.emv_data; + Widget* widget = nfc->widget; + widget_add_button_element( + widget, GuiButtonTypeLeft, "Retry", nfc_scene_read_emv_app_widget_callback, nfc); + widget_add_button_element( + widget, GuiButtonTypeRight, "Run app", nfc_scene_read_emv_app_widget_callback, nfc); + widget_add_string_element(widget, 36, 5, AlignLeft, AlignTop, FontPrimary, "Found EMV App"); + widget_add_icon_element(widget, 8, 5, &I_Medium_chip_22x21); + // Display UID + string_t temp_str; + string_init_printf(temp_str, "UID:"); + for(size_t i = 0; i < nfc_data->uid_len; i++) { + string_cat_printf(temp_str, " %02X", nfc_data->uid[i]); + } + widget_add_string_element( + widget, 36, 18, AlignLeft, AlignTop, FontSecondary, string_get_cstr(temp_str)); + string_reset(temp_str); + // Display application + string_printf(temp_str, "App: "); string_t aid; string_init(aid); bool aid_found = @@ -32,19 +43,11 @@ void nfc_scene_read_emv_app_success_on_enter(void* context) { 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" NFC_SCENE_READ_SUCCESS_SHIFT - "Application:\n%s", - nfc_data->uid[0], - nfc_data->uid[1], - nfc_data->uid[2], - nfc_data->uid[3], - string_get_cstr(aid)); + string_cat(temp_str, aid); + widget_add_string_element( + widget, 7, 29, AlignLeft, AlignTop, FontSecondary, string_get_cstr(temp_str)); + string_clear(temp_str); string_clear(aid); - 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_emv_app_success_dialog_callback); // Send notification if(scene_manager_get_scene_state(nfc->scene_manager, NfcSceneReadEmvAppSuccess) == @@ -54,32 +57,27 @@ void nfc_scene_read_emv_app_success_on_enter(void* context) { nfc->scene_manager, NfcSceneReadEmvAppSuccess, NFC_SEND_NOTIFICATION_FALSE); } - view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewDialogEx); + view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewWidget); } bool nfc_scene_read_emv_app_success_on_event(void* context, SceneManagerEvent event) { - Nfc* nfc = (Nfc*)context; + Nfc* nfc = context; + bool consumed = false; if(event.type == SceneManagerEventTypeCustom) { - if(event.event == DialogExResultLeft) { - return scene_manager_previous_scene(nfc->scene_manager); - } else if(event.event == DialogExResultRight) { + if(event.event == GuiButtonTypeLeft) { + consumed = scene_manager_previous_scene(nfc->scene_manager); + } else if(event.event == GuiButtonTypeRight) { scene_manager_next_scene(nfc->scene_manager, NfcSceneRunEmvAppConfirm); - return true; + consumed = true; } } - return false; + return consumed; } void nfc_scene_read_emv_app_success_on_exit(void* context) { - Nfc* nfc = (Nfc*)context; + Nfc* nfc = context; - 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_result_callback(dialog_ex, NULL); - dialog_ex_set_context(dialog_ex, NULL); + // Clear views + widget_reset(nfc->widget); } diff --git a/applications/nfc/scenes/nfc_scene_read_emv_data.c b/applications/nfc/scenes/nfc_scene_read_emv_data.c index 37442c333..b72c873e4 100755 --- a/applications/nfc/scenes/nfc_scene_read_emv_data.c +++ b/applications/nfc/scenes/nfc_scene_read_emv_data.c @@ -2,12 +2,12 @@ #include void nfc_read_emv_data_worker_callback(NfcWorkerEvent event, void* context) { - Nfc* nfc = (Nfc*)context; + Nfc* nfc = context; view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventWorkerExit); } void nfc_scene_read_emv_data_on_enter(void* context) { - Nfc* nfc = (Nfc*)context; + Nfc* nfc = context; DOLPHIN_DEED(DolphinDeedNfcRead); // Setup view @@ -21,38 +21,35 @@ void nfc_scene_read_emv_data_on_enter(void* context) { // Start worker nfc_worker_start( nfc->worker, - NfcWorkerStateReadEMV, + NfcWorkerStateReadEMVData, &nfc->dev->dev_data, nfc_read_emv_data_worker_callback, nfc); } bool nfc_scene_read_emv_data_on_event(void* context, SceneManagerEvent event) { - Nfc* nfc = (Nfc*)context; + Nfc* nfc = context; + bool consumed = false; if(event.type == SceneManagerEventTypeCustom) { if(event.event == NfcCustomEventWorkerExit) { scene_manager_set_scene_state( nfc->scene_manager, NfcSceneReadEmvDataSuccess, NFC_SEND_NOTIFICATION_TRUE); scene_manager_next_scene(nfc->scene_manager, NfcSceneReadEmvDataSuccess); - return true; + consumed = true; } } else if(event.type == SceneManagerEventTypeTick) { notification_message(nfc->notifications, &sequence_blink_blue_10); - return true; + consumed = true; } - return false; + return consumed; } void nfc_scene_read_emv_data_on_exit(void* context) { - Nfc* nfc = (Nfc*)context; + Nfc* nfc = context; // Stop worker nfc_worker_stop(nfc->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); + popup_reset(nfc->popup); } diff --git a/applications/nfc/scenes/nfc_scene_read_emv_data_success.c b/applications/nfc/scenes/nfc_scene_read_emv_data_success.c index 78078d05b..275e9b86e 100755 --- a/applications/nfc/scenes/nfc_scene_read_emv_data_success.c +++ b/applications/nfc/scenes/nfc_scene_read_emv_data_success.c @@ -6,16 +6,16 @@ void nfc_scene_read_emv_data_success_widget_callback( GuiButtonType result, InputType type, void* context) { - Nfc* nfc = (Nfc*)context; + Nfc* nfc = context; if(type == InputTypeShort) { view_dispatcher_send_custom_event(nfc->view_dispatcher, result); } } void nfc_scene_read_emv_data_success_on_enter(void* context) { - Nfc* nfc = (Nfc*)context; - NfcEmvData* emv_data = &nfc->dev->dev_data.emv_data; - NfcDeviceCommonData* nfc_data = &nfc->dev->dev_data.nfc_data; + Nfc* nfc = context; + EmvData* emv_data = &nfc->dev->dev_data.emv_data; + FuriHalNfcDevData* nfc_data = &nfc->dev->dev_data.nfc_data; DOLPHIN_DEED(DolphinDeedNfcReadSuccess); // Setup Custom Widget view @@ -78,25 +78,23 @@ void nfc_scene_read_emv_data_success_on_enter(void* context) { string_clear(disp_currency); } string_clear(currency_name); + char temp_str[32]; // Add ATQA - char atqa_str[16]; - snprintf(atqa_str, sizeof(atqa_str), "ATQA: %02X%02X", nfc_data->atqa[0], nfc_data->atqa[1]); - widget_add_string_element(nfc->widget, 121, 32, AlignRight, AlignTop, FontSecondary, atqa_str); + snprintf(temp_str, sizeof(temp_str), "ATQA: %02X%02X", nfc_data->atqa[0], nfc_data->atqa[1]); + widget_add_string_element(nfc->widget, 121, 32, AlignRight, AlignTop, FontSecondary, temp_str); // Add UID - char uid_str[32]; snprintf( - uid_str, - sizeof(uid_str), + temp_str, + sizeof(temp_str), "UID: %02X %02X %02X %02X", nfc_data->uid[0], nfc_data->uid[1], nfc_data->uid[2], nfc_data->uid[3]); - widget_add_string_element(nfc->widget, 7, 42, AlignLeft, AlignTop, FontSecondary, uid_str); + widget_add_string_element(nfc->widget, 7, 42, AlignLeft, AlignTop, FontSecondary, temp_str); // Add SAK - char sak_str[16]; - snprintf(sak_str, sizeof(sak_str), "SAK: %02X", nfc_data->sak); - widget_add_string_element(nfc->widget, 121, 42, AlignRight, AlignTop, FontSecondary, sak_str); + snprintf(temp_str, sizeof(temp_str), "SAK: %02X", nfc_data->sak); + widget_add_string_element(nfc->widget, 121, 42, AlignRight, AlignTop, FontSecondary, temp_str); // Add expiration date if(emv_data->exp_mon) { char exp_str[16]; @@ -117,28 +115,30 @@ void nfc_scene_read_emv_data_success_on_enter(void* context) { } bool nfc_scene_read_emv_data_success_on_event(void* context, SceneManagerEvent event) { - Nfc* nfc = (Nfc*)context; + Nfc* nfc = context; + bool consumed = false; if(event.type == SceneManagerEventTypeCustom) { if(event.event == GuiButtonTypeLeft) { - return scene_manager_search_and_switch_to_previous_scene( + consumed = 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; + consumed = true; } } else if(event.type == SceneManagerEventTypeBack) { - return scene_manager_search_and_switch_to_previous_scene( + consumed = scene_manager_search_and_switch_to_previous_scene( nfc->scene_manager, NfcSceneReadEmvAppSuccess); } - return false; + return consumed; } void nfc_scene_read_emv_data_success_on_exit(void* context) { - Nfc* nfc = (Nfc*)context; + Nfc* nfc = context; + // Clear view widget_reset(nfc->widget); } diff --git a/applications/nfc/scenes/nfc_scene_read_mifare_desfire.c b/applications/nfc/scenes/nfc_scene_read_mifare_desfire.c index 1a0b35246..ebd7289b9 100644 --- a/applications/nfc/scenes/nfc_scene_read_mifare_desfire.c +++ b/applications/nfc/scenes/nfc_scene_read_mifare_desfire.c @@ -2,12 +2,12 @@ #include void nfc_read_mifare_desfire_worker_callback(NfcWorkerEvent event, void* context) { - Nfc* nfc = (Nfc*)context; + Nfc* nfc = context; view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventWorkerExit); } void nfc_scene_read_mifare_desfire_on_enter(void* context) { - Nfc* nfc = (Nfc*)context; + Nfc* nfc = context; DOLPHIN_DEED(DolphinDeedNfcRead); // Setup view @@ -26,31 +26,28 @@ void nfc_scene_read_mifare_desfire_on_enter(void* context) { } bool nfc_scene_read_mifare_desfire_on_event(void* context, SceneManagerEvent event) { - Nfc* nfc = (Nfc*)context; + Nfc* nfc = context; + bool consumed = false; if(event.type == SceneManagerEventTypeCustom) { if(event.event == NfcCustomEventWorkerExit) { notification_message(nfc->notifications, &sequence_success); scene_manager_next_scene(nfc->scene_manager, NfcSceneReadMifareDesfireSuccess); - return true; + consumed = true; } } else if(event.type == SceneManagerEventTypeTick) { notification_message(nfc->notifications, &sequence_blink_blue_10); DOLPHIN_DEED(DolphinDeedNfcReadSuccess); - return true; + consumed = true; } - return false; + return consumed; } void nfc_scene_read_mifare_desfire_on_exit(void* context) { - Nfc* nfc = (Nfc*)context; + Nfc* nfc = context; // Stop worker nfc_worker_stop(nfc->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); + popup_reset(nfc->popup); } diff --git a/applications/nfc/scenes/nfc_scene_read_mifare_desfire_success.c b/applications/nfc/scenes/nfc_scene_read_mifare_desfire_success.c index 995869bf7..17f62e411 100644 --- a/applications/nfc/scenes/nfc_scene_read_mifare_desfire_success.c +++ b/applications/nfc/scenes/nfc_scene_read_mifare_desfire_success.c @@ -9,13 +9,13 @@ enum { }; void nfc_scene_read_mifare_desfire_success_dialog_callback(DialogExResult result, void* context) { - Nfc* nfc = (Nfc*)context; + Nfc* nfc = context; view_dispatcher_send_custom_event(nfc->view_dispatcher, result); } void nfc_scene_read_mifare_desfire_success_on_enter(void* context) { - Nfc* nfc = (Nfc*)context; + Nfc* nfc = context; MifareDesfireData* data = &nfc->dev->dev_data.mf_df_data; DialogEx* dialog_ex = nfc->dialog_ex; @@ -67,9 +67,9 @@ void nfc_scene_read_mifare_desfire_success_on_enter(void* context) { bool nfc_scene_read_mifare_desfire_success_on_event(void* context, SceneManagerEvent event) { Nfc* nfc = context; + bool consumed = false; uint32_t state = scene_manager_get_scene_state(nfc->scene_manager, NfcSceneReadMifareDesfireSuccess); - bool consumed = false; if(event.type == SceneManagerEventTypeCustom) { if(state == ReadMifareDesfireSuccessStateShowUID && event.event == DialogExResultLeft) { @@ -98,9 +98,8 @@ bool nfc_scene_read_mifare_desfire_success_on_event(void* context, SceneManagerE } void nfc_scene_read_mifare_desfire_success_on_exit(void* context) { - Nfc* nfc = (Nfc*)context; + Nfc* nfc = context; // Clean dialog - DialogEx* dialog_ex = nfc->dialog_ex; - dialog_ex_reset(dialog_ex); + dialog_ex_reset(nfc->dialog_ex); } diff --git a/applications/nfc/scenes/nfc_scene_read_mifare_ul.c b/applications/nfc/scenes/nfc_scene_read_mifare_ul.c index ce6d160e5..8903e2c43 100755 --- a/applications/nfc/scenes/nfc_scene_read_mifare_ul.c +++ b/applications/nfc/scenes/nfc_scene_read_mifare_ul.c @@ -19,7 +19,7 @@ void nfc_scene_read_mifare_ul_on_enter(void* context) { // Start worker nfc_worker_start( nfc->worker, - NfcWorkerStateReadMifareUl, + NfcWorkerStateReadMifareUltralight, &nfc->dev->dev_data, nfc_read_mifare_ul_worker_callback, nfc); @@ -43,6 +43,7 @@ bool nfc_scene_read_mifare_ul_on_event(void* context, SceneManagerEvent event) { void nfc_scene_read_mifare_ul_on_exit(void* context) { Nfc* nfc = context; + // Stop worker nfc_worker_stop(nfc->worker); // Clear view diff --git a/applications/nfc/scenes/nfc_scene_read_mifare_ul_success.c b/applications/nfc/scenes/nfc_scene_read_mifare_ul_success.c index 603ad54ae..5bcf15894 100755 --- a/applications/nfc/scenes/nfc_scene_read_mifare_ul_success.c +++ b/applications/nfc/scenes/nfc_scene_read_mifare_ul_success.c @@ -9,21 +9,21 @@ enum { }; void nfc_scene_read_mifare_ul_success_dialog_callback(DialogExResult result, void* context) { - Nfc* nfc = (Nfc*)context; + Nfc* nfc = context; view_dispatcher_send_custom_event(nfc->view_dispatcher, result); } void nfc_scene_read_mifare_ul_success_on_enter(void* context) { - Nfc* nfc = (Nfc*)context; + Nfc* nfc = context; DOLPHIN_DEED(DolphinDeedNfcReadSuccess); // Send notification notification_message(nfc->notifications, &sequence_success); // Setup dialog view - NfcDeviceCommonData* data = &nfc->dev->dev_data.nfc_data; - MifareUlData* mf_ul_data = &nfc->dev->dev_data.mf_ul_data; + FuriHalNfcDevData* data = &nfc->dev->dev_data.nfc_data; + MfUltralightData* mf_ul_data = &nfc->dev->dev_data.mf_ul_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"); @@ -69,9 +69,9 @@ void nfc_scene_read_mifare_ul_success_on_enter(void* context) { bool nfc_scene_read_mifare_ul_success_on_event(void* context, SceneManagerEvent event) { Nfc* nfc = context; + bool consumed = false; uint32_t state = scene_manager_get_scene_state(nfc->scene_manager, NfcSceneReadMifareUlSuccess); - bool consumed = false; if(event.type == SceneManagerEventTypeCustom) { if(state == ReadMifareUlStateShowUID && event.event == DialogExResultLeft) { @@ -99,14 +99,10 @@ bool nfc_scene_read_mifare_ul_success_on_event(void* context, SceneManagerEvent } void nfc_scene_read_mifare_ul_success_on_exit(void* context) { - Nfc* nfc = (Nfc*)context; + Nfc* nfc = context; - // Clean dialog - DialogEx* dialog_ex = nfc->dialog_ex; - dialog_ex_reset(dialog_ex); - - // Clean TextBox - TextBox* text_box = nfc->text_box; - text_box_reset(text_box); + // Clean views + dialog_ex_reset(nfc->dialog_ex); + text_box_reset(nfc->text_box); string_reset(nfc->text_box_store); } diff --git a/applications/nfc/scenes/nfc_scene_restore_original.c b/applications/nfc/scenes/nfc_scene_restore_original.c index 8ddac3661..40b59b9eb 100644 --- a/applications/nfc/scenes/nfc_scene_restore_original.c +++ b/applications/nfc/scenes/nfc_scene_restore_original.c @@ -1,12 +1,12 @@ #include "../nfc_i.h" void nfc_scene_restore_original_popup_callback(void* context) { - Nfc* nfc = (Nfc*)context; + Nfc* nfc = context; view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventViewExit); } void nfc_scene_restore_original_on_enter(void* context) { - Nfc* nfc = (Nfc*)context; + Nfc* nfc = context; // Setup view Popup* popup = nfc->popup; @@ -20,7 +20,7 @@ void nfc_scene_restore_original_on_enter(void* context) { } bool nfc_scene_restore_original_on_event(void* context, SceneManagerEvent event) { - Nfc* nfc = (Nfc*)context; + Nfc* nfc = context; bool consumed = false; if(event.type == SceneManagerEventTypeCustom) { @@ -32,15 +32,8 @@ bool nfc_scene_restore_original_on_event(void* context, SceneManagerEvent event) } void nfc_scene_restore_original_on_exit(void* context) { - Nfc* nfc = (Nfc*)context; + Nfc* nfc = context; // 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); - popup_set_callback(popup, NULL); - popup_set_context(popup, NULL); - popup_set_timeout(popup, 0); - popup_disable_timeout(popup); + popup_reset(nfc->popup); } diff --git a/applications/nfc/scenes/nfc_scene_run_emv_app_confirm.c b/applications/nfc/scenes/nfc_scene_run_emv_app_confirm.c index d9948d4e5..5ee9f442c 100755 --- a/applications/nfc/scenes/nfc_scene_run_emv_app_confirm.c +++ b/applications/nfc/scenes/nfc_scene_run_emv_app_confirm.c @@ -1,15 +1,13 @@ #include "../nfc_i.h" -#define NFC_SCENE_READ_SUCCESS_SHIFT " " - void nfc_scene_run_emv_app_confirm_dialog_callback(DialogExResult result, void* context) { - Nfc* nfc = (Nfc*)context; + Nfc* nfc = context; view_dispatcher_send_custom_event(nfc->view_dispatcher, result); } void nfc_scene_run_emv_app_confirm_on_enter(void* context) { - Nfc* nfc = (Nfc*)context; + Nfc* nfc = context; DialogEx* dialog_ex = nfc->dialog_ex; dialog_ex_set_left_button_text(dialog_ex, "Back"); @@ -29,28 +27,23 @@ void nfc_scene_run_emv_app_confirm_on_enter(void* context) { } bool nfc_scene_run_emv_app_confirm_on_event(void* context, SceneManagerEvent event) { - Nfc* nfc = (Nfc*)context; + Nfc* nfc = context; + bool consumed = false; if(event.type == SceneManagerEventTypeCustom) { if(event.event == DialogExResultLeft) { - return scene_manager_previous_scene(nfc->scene_manager); + consumed = scene_manager_previous_scene(nfc->scene_manager); } else if(event.event == DialogExResultRight) { scene_manager_next_scene(nfc->scene_manager, NfcSceneReadEmvData); - return true; + consumed = true; } } - return false; + return consumed; } void nfc_scene_run_emv_app_confirm_on_exit(void* context) { - Nfc* nfc = (Nfc*)context; + Nfc* nfc = context; - 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_result_callback(dialog_ex, NULL); - dialog_ex_set_context(dialog_ex, NULL); + // Clean view + dialog_ex_reset(nfc->dialog_ex); } diff --git a/applications/nfc/scenes/nfc_scene_save_name.c b/applications/nfc/scenes/nfc_scene_save_name.c index aa05c8a6b..e95c97eb4 100755 --- a/applications/nfc/scenes/nfc_scene_save_name.c +++ b/applications/nfc/scenes/nfc_scene_save_name.c @@ -3,13 +3,13 @@ #include void nfc_scene_save_name_text_input_callback(void* context) { - Nfc* nfc = (Nfc*)context; + Nfc* nfc = context; view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventTextInputDone); } void nfc_scene_save_name_on_enter(void* context) { - Nfc* nfc = (Nfc*)context; + Nfc* nfc = context; // Setup view TextInput* text_input = nfc->text_input; @@ -37,7 +37,8 @@ void nfc_scene_save_name_on_enter(void* context) { } bool nfc_scene_save_name_on_event(void* context, SceneManagerEvent event) { - Nfc* nfc = (Nfc*)context; + Nfc* nfc = context; + bool consumed = false; if(event.type == SceneManagerEventTypeCustom) { if(event.event == NfcCustomEventTextInputDone) { @@ -50,18 +51,18 @@ bool nfc_scene_save_name_on_event(void* context, SceneManagerEvent event) { 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; + consumed = true; } else { - return scene_manager_search_and_switch_to_previous_scene( + consumed = scene_manager_search_and_switch_to_previous_scene( nfc->scene_manager, NfcSceneStart); } } } - return false; + return consumed; } void nfc_scene_save_name_on_exit(void* context) { - Nfc* nfc = (Nfc*)context; + Nfc* nfc = context; // Clear view void* validator_context = text_input_get_validator_callback_context(nfc->text_input); diff --git a/applications/nfc/scenes/nfc_scene_save_success.c b/applications/nfc/scenes/nfc_scene_save_success.c index b1a84003c..985897a6d 100644 --- a/applications/nfc/scenes/nfc_scene_save_success.c +++ b/applications/nfc/scenes/nfc_scene_save_success.c @@ -2,12 +2,12 @@ #include void nfc_scene_save_success_popup_callback(void* context) { - Nfc* nfc = (Nfc*)context; + Nfc* nfc = context; view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventViewExit); } void nfc_scene_save_success_on_enter(void* context) { - Nfc* nfc = (Nfc*)context; + Nfc* nfc = context; DOLPHIN_DEED(DolphinDeedNfcSave); // Setup view @@ -22,7 +22,7 @@ void nfc_scene_save_success_on_enter(void* context) { } bool nfc_scene_save_success_on_event(void* context, SceneManagerEvent event) { - Nfc* nfc = (Nfc*)context; + Nfc* nfc = context; bool consumed = false; if(event.type == SceneManagerEventTypeCustom) { @@ -47,15 +47,8 @@ bool nfc_scene_save_success_on_event(void* context, SceneManagerEvent event) { } void nfc_scene_save_success_on_exit(void* context) { - Nfc* nfc = (Nfc*)context; + Nfc* nfc = context; // 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); - popup_set_callback(popup, NULL); - popup_set_context(popup, NULL); - popup_set_timeout(popup, 0); - popup_disable_timeout(popup); + popup_reset(nfc->popup); } diff --git a/applications/nfc/scenes/nfc_scene_saved_menu.c b/applications/nfc/scenes/nfc_scene_saved_menu.c index 14eb4ca26..e0489c157 100644 --- a/applications/nfc/scenes/nfc_scene_saved_menu.c +++ b/applications/nfc/scenes/nfc_scene_saved_menu.c @@ -9,13 +9,13 @@ enum SubmenuIndex { }; void nfc_scene_saved_menu_submenu_callback(void* context, uint32_t index) { - Nfc* nfc = (Nfc*)context; + Nfc* nfc = context; view_dispatcher_send_custom_event(nfc->view_dispatcher, index); } void nfc_scene_saved_menu_on_enter(void* context) { - Nfc* nfc = (Nfc*)context; + Nfc* nfc = context; Submenu* submenu = nfc->submenu; if(nfc->dev->format == NfcDeviceSaveFormatUid || @@ -56,7 +56,7 @@ void nfc_scene_saved_menu_on_enter(void* context) { } bool nfc_scene_saved_menu_on_event(void* context, SceneManagerEvent event) { - Nfc* nfc = (Nfc*)context; + Nfc* nfc = context; bool consumed = false; if(event.type == SceneManagerEventTypeCustom) { @@ -92,7 +92,7 @@ bool nfc_scene_saved_menu_on_event(void* context, SceneManagerEvent event) { } void nfc_scene_saved_menu_on_exit(void* context) { - Nfc* nfc = (Nfc*)context; + Nfc* nfc = context; submenu_reset(nfc->submenu); } diff --git a/applications/nfc/scenes/nfc_scene_set_atqa.c b/applications/nfc/scenes/nfc_scene_set_atqa.c index 85a70fe8d..f2100aa19 100755 --- a/applications/nfc/scenes/nfc_scene_set_atqa.c +++ b/applications/nfc/scenes/nfc_scene_set_atqa.c @@ -1,13 +1,13 @@ #include "../nfc_i.h" void nfc_scene_set_atqa_byte_input_callback(void* context) { - Nfc* nfc = (Nfc*)context; + Nfc* nfc = context; view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventByteInputDone); } void nfc_scene_set_atqa_on_enter(void* context) { - Nfc* nfc = (Nfc*)context; + Nfc* nfc = context; // Setup view ByteInput* byte_input = nfc->byte_input; @@ -23,19 +23,20 @@ void nfc_scene_set_atqa_on_enter(void* context) { } bool nfc_scene_set_atqa_on_event(void* context, SceneManagerEvent event) { - Nfc* nfc = (Nfc*)context; + Nfc* nfc = context; + bool consumed = false; if(event.type == SceneManagerEventTypeCustom) { if(event.event == NfcCustomEventByteInputDone) { scene_manager_next_scene(nfc->scene_manager, NfcSceneSetUid); - return true; + consumed = true; } } - return false; + return consumed; } void nfc_scene_set_atqa_on_exit(void* context) { - Nfc* nfc = (Nfc*)context; + Nfc* nfc = context; // Clear view byte_input_set_result_callback(nfc->byte_input, NULL, NULL, NULL, NULL, 0); diff --git a/applications/nfc/scenes/nfc_scene_set_sak.c b/applications/nfc/scenes/nfc_scene_set_sak.c index 11cfcf467..3c88f3504 100755 --- a/applications/nfc/scenes/nfc_scene_set_sak.c +++ b/applications/nfc/scenes/nfc_scene_set_sak.c @@ -1,13 +1,13 @@ #include "../nfc_i.h" void nfc_scene_set_sak_byte_input_callback(void* context) { - Nfc* nfc = (Nfc*)context; + Nfc* nfc = context; view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventByteInputDone); } void nfc_scene_set_sak_on_enter(void* context) { - Nfc* nfc = (Nfc*)context; + Nfc* nfc = context; // Setup view ByteInput* byte_input = nfc->byte_input; @@ -23,19 +23,20 @@ void nfc_scene_set_sak_on_enter(void* context) { } bool nfc_scene_set_sak_on_event(void* context, SceneManagerEvent event) { - Nfc* nfc = (Nfc*)context; + Nfc* nfc = context; + bool consumed = false; if(event.type == SceneManagerEventTypeCustom) { if(event.event == NfcCustomEventByteInputDone) { scene_manager_next_scene(nfc->scene_manager, NfcSceneSetAtqua); - return true; + consumed = true; } } - return false; + return consumed; } void nfc_scene_set_sak_on_exit(void* context) { - Nfc* nfc = (Nfc*)context; + Nfc* nfc = context; // Clear view byte_input_set_result_callback(nfc->byte_input, NULL, NULL, NULL, NULL, 0); diff --git a/applications/nfc/scenes/nfc_scene_set_type.c b/applications/nfc/scenes/nfc_scene_set_type.c index 0e6624bda..0dbb4f7ea 100755 --- a/applications/nfc/scenes/nfc_scene_set_type.c +++ b/applications/nfc/scenes/nfc_scene_set_type.c @@ -6,13 +6,13 @@ enum SubmenuIndex { }; void nfc_scene_set_type_submenu_callback(void* context, uint32_t index) { - Nfc* nfc = (Nfc*)context; + Nfc* nfc = context; view_dispatcher_send_custom_event(nfc->view_dispatcher, index); } void nfc_scene_set_type_on_enter(void* context) { - Nfc* nfc = (Nfc*)context; + Nfc* nfc = context; Submenu* submenu = nfc->submenu; // Clear device name nfc_device_set_name(nfc->dev, ""); @@ -24,26 +24,27 @@ void nfc_scene_set_type_on_enter(void* context) { } bool nfc_scene_set_type_on_event(void* context, SceneManagerEvent event) { - Nfc* nfc = (Nfc*)context; + Nfc* nfc = context; + bool consumed = false; if(event.type == SceneManagerEventTypeCustom) { if(event.event == SubmenuIndexNFCA7) { nfc->dev->dev_data.nfc_data.uid_len = 7; nfc->dev->format = NfcDeviceSaveFormatUid; scene_manager_next_scene(nfc->scene_manager, NfcSceneSetSak); - return true; + consumed = true; } else if(event.event == SubmenuIndexNFCA4) { nfc->dev->dev_data.nfc_data.uid_len = 4; nfc->dev->format = NfcDeviceSaveFormatUid; scene_manager_next_scene(nfc->scene_manager, NfcSceneSetSak); - return true; + consumed = true; } } - return false; + return consumed; } void nfc_scene_set_type_on_exit(void* context) { - Nfc* nfc = (Nfc*)context; + Nfc* nfc = context; submenu_reset(nfc->submenu); } diff --git a/applications/nfc/scenes/nfc_scene_set_uid.c b/applications/nfc/scenes/nfc_scene_set_uid.c index c59501294..6fe807ced 100755 --- a/applications/nfc/scenes/nfc_scene_set_uid.c +++ b/applications/nfc/scenes/nfc_scene_set_uid.c @@ -2,13 +2,13 @@ #include void nfc_scene_set_uid_byte_input_callback(void* context) { - Nfc* nfc = (Nfc*)context; + Nfc* nfc = context; view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventByteInputDone); } void nfc_scene_set_uid_on_enter(void* context) { - Nfc* nfc = (Nfc*)context; + Nfc* nfc = context; // Setup view ByteInput* byte_input = nfc->byte_input; @@ -26,19 +26,20 @@ void nfc_scene_set_uid_on_enter(void* context) { bool nfc_scene_set_uid_on_event(void* context, SceneManagerEvent event) { Nfc* nfc = (Nfc*)context; + bool consumed = false; if(event.type == SceneManagerEventTypeCustom) { if(event.event == NfcCustomEventByteInputDone) { DOLPHIN_DEED(DolphinDeedNfcAdd); scene_manager_next_scene(nfc->scene_manager, NfcSceneSaveName); - return true; + consumed = true; } } - return false; + return consumed; } void nfc_scene_set_uid_on_exit(void* context) { - Nfc* nfc = (Nfc*)context; + Nfc* nfc = context; // Clear view byte_input_set_result_callback(nfc->byte_input, NULL, NULL, NULL, NULL, 0); diff --git a/applications/nfc/scenes/nfc_scene_start.c b/applications/nfc/scenes/nfc_scene_start.c index 2be7775b3..d64aa76e3 100644 --- a/applications/nfc/scenes/nfc_scene_start.c +++ b/applications/nfc/scenes/nfc_scene_start.c @@ -9,13 +9,13 @@ enum SubmenuIndex { }; void nfc_scene_start_submenu_callback(void* context, uint32_t index) { - Nfc* nfc = (Nfc*)context; + Nfc* nfc = context; view_dispatcher_send_custom_event(nfc->view_dispatcher, index); } void nfc_scene_start_on_enter(void* context) { - Nfc* nfc = (Nfc*)context; + Nfc* nfc = context; Submenu* submenu = nfc->submenu; submenu_add_item( @@ -43,7 +43,7 @@ void nfc_scene_start_on_enter(void* context) { } bool nfc_scene_start_on_event(void* context, SceneManagerEvent event) { - Nfc* nfc = (Nfc*)context; + Nfc* nfc = context; bool consumed = false; if(event.type == SceneManagerEventTypeCustom) { @@ -70,7 +70,7 @@ bool nfc_scene_start_on_event(void* context, SceneManagerEvent event) { } void nfc_scene_start_on_exit(void* context) { - Nfc* nfc = (Nfc*)context; + Nfc* nfc = context; submenu_reset(nfc->submenu); } diff --git a/firmware/targets/f7/furi_hal/furi_hal_nfc.c b/firmware/targets/f7/furi_hal/furi_hal_nfc.c index b29c5026c..1d2c02d9a 100755 --- a/firmware/targets/f7/furi_hal/furi_hal_nfc.c +++ b/firmware/targets/f7/furi_hal/furi_hal_nfc.c @@ -48,13 +48,12 @@ void furi_hal_nfc_exit_sleep() { rfalLowPowerModeStop(); } -bool furi_hal_nfc_detect( - rfalNfcDevice** dev_list, - uint8_t* dev_cnt, - uint32_t timeout, - bool deactivate) { - furi_assert(dev_list); - furi_assert(dev_cnt); +bool furi_hal_nfc_detect(FuriHalNfcDevData* nfc_data, uint32_t timeout) { + furi_assert(nfc_data); + + rfalNfcDevice* dev_list = NULL; + uint8_t dev_cnt = 0; + bool detected = false; rfalLowPowerModeStop(); rfalNfcState state = rfalNfcGetState(); @@ -77,9 +76,13 @@ bool furi_hal_nfc_detect( uint32_t start = DWT->CYCCNT; rfalNfcDiscover(¶ms); - while(state != RFAL_NFC_STATE_ACTIVATED) { + while(true) { rfalNfcWorker(); state = rfalNfcGetState(); + if(state == RFAL_NFC_STATE_ACTIVATED) { + detected = true; + break; + } FURI_LOG_T(TAG, "Current state %d", state); if(state == RFAL_NFC_STATE_POLL_ACTIVATION) { start = DWT->CYCCNT; @@ -91,16 +94,42 @@ bool furi_hal_nfc_detect( if(DWT->CYCCNT - start > timeout * clocks_in_ms) { rfalNfcDeactivate(true); FURI_LOG_T(TAG, "Timeout"); - return false; + break; } osThreadYield(); } - rfalNfcGetDevicesFound(dev_list, dev_cnt); - if(deactivate) { - rfalNfcDeactivate(false); - rfalLowPowerModeStart(); + rfalNfcGetDevicesFound(&dev_list, &dev_cnt); + if(detected) { + if(dev_list[0].type == RFAL_NFC_LISTEN_TYPE_NFCA) { + nfc_data->type = FuriHalNfcTypeA; + nfc_data->atqa[0] = dev_list[0].dev.nfca.sensRes.anticollisionInfo; + nfc_data->atqa[1] = dev_list[0].dev.nfca.sensRes.platformInfo; + nfc_data->sak = dev_list[0].dev.nfca.selRes.sak; + uint8_t* cuid_start = dev_list[0].nfcid; + if(dev_list[0].nfcidLen == 7) { + cuid_start = &dev_list[0].nfcid[3]; + } + nfc_data->cuid = (cuid_start[0] << 24) | (cuid_start[1] << 16) | (cuid_start[2] << 8) | + (cuid_start[3]); + } else if(dev_list[0].type == RFAL_NFC_LISTEN_TYPE_NFCB) { + nfc_data->type = FuriHalNfcTypeB; + } else if(dev_list[0].type == RFAL_NFC_LISTEN_TYPE_NFCF) { + nfc_data->type = FuriHalNfcTypeF; + } else if(dev_list[0].type == RFAL_NFC_LISTEN_TYPE_NFCV) { + nfc_data->type = FuriHalNfcTypeV; + } + if(dev_list[0].rfInterface == RFAL_NFC_INTERFACE_RF) { + nfc_data->interface = FuriHalNfcInterfaceRf; + } else if(dev_list[0].rfInterface == RFAL_NFC_INTERFACE_ISODEP) { + nfc_data->interface = FuriHalNfcInterfaceIsoDep; + } else if(dev_list[0].rfInterface == RFAL_NFC_INTERFACE_NFCDEP) { + nfc_data->interface = FuriHalNfcInterfaceNfcDep; + } + nfc_data->uid_len = dev_list[0].nfcidLen; + memcpy(nfc_data->uid, dev_list[0].nfcid, nfc_data->uid_len); } - return true; + + return detected; } bool furi_hal_nfc_activate_nfca(uint32_t timeout, uint32_t* cuid) { @@ -326,12 +355,6 @@ bool furi_hal_nfc_emulate_nfca( return true; } -bool furi_hal_nfc_get_first_frame(uint8_t** rx_buff, uint16_t** rx_len) { - ReturnCode ret = - rfalNfcDataExchangeStart(NULL, 0, rx_buff, rx_len, 0, RFAL_TXRX_FLAGS_DEFAULT); - return ret == ERR_NONE; -} - ReturnCode furi_hal_nfc_data_exchange( uint8_t* tx_buff, uint16_t tx_len, @@ -370,6 +393,22 @@ ReturnCode furi_hal_nfc_data_exchange( return ret; } +static uint32_t furi_hal_nfc_tx_rx_get_flag(FuriHalNfcTxRxType type) { + uint32_t flags = 0; + + if(type == FuriHalNfcTxRxTypeRxNoCrc) { + flags = RFAL_TXRX_FLAGS_CRC_RX_KEEP; + } else if(type == FuriHalNfcTxRxTypeRxKeepPar) { + flags = RFAL_TXRX_FLAGS_CRC_TX_MANUAL | RFAL_TXRX_FLAGS_CRC_RX_KEEP | + RFAL_TXRX_FLAGS_PAR_RX_KEEP; + } else if(type == FuriHalNfcTxRxTypeRaw) { + flags = RFAL_TXRX_FLAGS_CRC_TX_MANUAL | RFAL_TXRX_FLAGS_CRC_RX_KEEP | + RFAL_TXRX_FLAGS_PAR_RX_KEEP | RFAL_TXRX_FLAGS_PAR_TX_NONE; + } + + return flags; +} + static uint16_t furi_hal_nfc_data_and_parity_to_bitstream( uint8_t* data, uint16_t len, @@ -420,8 +459,8 @@ uint16_t furi_hal_nfc_bitstream_to_data_and_parity( return curr_byte; } -bool furi_hal_nfc_tx_rx(FuriHalNfcTxRxContext* tx_rx_ctx) { - furi_assert(tx_rx_ctx); +bool furi_hal_nfc_tx_rx(FuriHalNfcTxRxContext* tx_rx, uint16_t timeout_ms) { + furi_assert(tx_rx); ReturnCode ret; rfalNfcState state = RFAL_NFC_STATE_ACTIVATED; @@ -431,26 +470,18 @@ bool furi_hal_nfc_tx_rx(FuriHalNfcTxRxContext* tx_rx_ctx) { uint16_t* temp_rx_bits = NULL; // Prepare data for FIFO if necessary - if(tx_rx_ctx->tx_rx_type == FURI_HAL_NFC_TXRX_RAW) { + uint32_t flags = furi_hal_nfc_tx_rx_get_flag(tx_rx->tx_rx_type); + if(tx_rx->tx_rx_type == FuriHalNfcTxRxTypeRaw) { temp_tx_bits = furi_hal_nfc_data_and_parity_to_bitstream( - tx_rx_ctx->tx_data, tx_rx_ctx->tx_bits / 8, tx_rx_ctx->tx_parity, temp_tx_buff); + tx_rx->tx_data, tx_rx->tx_bits / 8, tx_rx->tx_parity, temp_tx_buff); ret = rfalNfcDataExchangeCustomStart( - temp_tx_buff, - temp_tx_bits, - &temp_rx_buff, - &temp_rx_bits, - RFAL_FWT_NONE, - tx_rx_ctx->tx_rx_type); + temp_tx_buff, temp_tx_bits, &temp_rx_buff, &temp_rx_bits, RFAL_FWT_NONE, flags); } else { ret = rfalNfcDataExchangeCustomStart( - tx_rx_ctx->tx_data, - tx_rx_ctx->tx_bits, - &temp_rx_buff, - &temp_rx_bits, - RFAL_FWT_NONE, - tx_rx_ctx->tx_rx_type); + tx_rx->tx_data, tx_rx->tx_bits, &temp_rx_buff, &temp_rx_bits, RFAL_FWT_NONE, flags); } if(ret != ERR_NONE) { + FURI_LOG_E(TAG, "Failed to start data exchange"); return false; } uint32_t start = DWT->CYCCNT; @@ -459,28 +490,64 @@ bool furi_hal_nfc_tx_rx(FuriHalNfcTxRxContext* tx_rx_ctx) { state = rfalNfcGetState(); ret = rfalNfcDataExchangeGetStatus(); if(ret == ERR_BUSY) { - if(DWT->CYCCNT - start > 4 * clocks_in_ms) { + if(DWT->CYCCNT - start > timeout_ms * clocks_in_ms) { + FURI_LOG_D(TAG, "Timeout during data exchange"); return false; } continue; } else { start = DWT->CYCCNT; } - taskYIELD(); + osThreadYield(); } - if(tx_rx_ctx->tx_rx_type == FURI_HAL_NFC_TXRX_RAW) { - tx_rx_ctx->rx_bits = - 8 * furi_hal_nfc_bitstream_to_data_and_parity( - temp_rx_buff, *temp_rx_bits, tx_rx_ctx->rx_data, tx_rx_ctx->rx_parity); + if(tx_rx->tx_rx_type == FuriHalNfcTxRxTypeRaw) { + tx_rx->rx_bits = 8 * furi_hal_nfc_bitstream_to_data_and_parity( + temp_rx_buff, *temp_rx_bits, tx_rx->rx_data, tx_rx->rx_parity); } else { - memcpy(tx_rx_ctx->rx_data, temp_rx_buff, *temp_rx_bits / 8); + memcpy(tx_rx->rx_data, temp_rx_buff, MIN(*temp_rx_bits / 8, FURI_HAL_NFC_DATA_BUFF_SIZE)); + tx_rx->rx_bits = *temp_rx_bits; } return true; } -void furi_hal_nfc_deactivate() { +ReturnCode furi_hal_nfc_exchange_full( + uint8_t* tx_buff, + uint16_t tx_len, + uint8_t* rx_buff, + uint16_t rx_cap, + uint16_t* rx_len) { + ReturnCode err; + uint8_t* part_buff; + uint16_t* part_len_bits; + uint16_t part_len_bytes; + + err = furi_hal_nfc_data_exchange(tx_buff, tx_len, &part_buff, &part_len_bits, false); + part_len_bytes = *part_len_bits / 8; + if(part_len_bytes > rx_cap) { + return ERR_OVERRUN; + } + memcpy(rx_buff, part_buff, part_len_bytes); + *rx_len = part_len_bytes; + while(err == ERR_NONE && rx_buff[0] == 0xAF) { + err = furi_hal_nfc_data_exchange(rx_buff, 1, &part_buff, &part_len_bits, false); + part_len_bytes = *part_len_bits / 8; + if(part_len_bytes > rx_cap - *rx_len) { + return ERR_OVERRUN; + } + if(part_len_bytes == 0) { + return ERR_PROTO; + } + memcpy(rx_buff + *rx_len, part_buff + 1, part_len_bytes - 1); + *rx_buff = *part_buff; + *rx_len += part_len_bytes - 1; + } + + return err; +} + +void furi_hal_nfc_sleep() { rfalNfcDeactivate(false); rfalLowPowerModeStart(); } diff --git a/firmware/targets/furi_hal_include/furi_hal_nfc.h b/firmware/targets/furi_hal_include/furi_hal_nfc.h index edccab76b..20a469002 100755 --- a/firmware/targets/furi_hal_include/furi_hal_nfc.h +++ b/firmware/targets/furi_hal_include/furi_hal_nfc.h @@ -15,32 +15,31 @@ extern "C" { #endif #define FURI_HAL_NFC_UID_MAX_LEN 10 -#define FURI_HAL_NFC_DATA_BUFF_SIZE (64) +#define FURI_HAL_NFC_DATA_BUFF_SIZE (256) #define FURI_HAL_NFC_PARITY_BUFF_SIZE (FURI_HAL_NFC_DATA_BUFF_SIZE / 8) #define FURI_HAL_NFC_TXRX_DEFAULT \ ((uint32_t)RFAL_TXRX_FLAGS_CRC_TX_AUTO | (uint32_t)RFAL_TXRX_FLAGS_CRC_RX_REMV | \ - (uint32_t)RFAL_TXRX_FLAGS_NFCIP1_OFF | (uint32_t)RFAL_TXRX_FLAGS_AGC_ON | \ - (uint32_t)RFAL_TXRX_FLAGS_PAR_RX_REMV | (uint32_t)RFAL_TXRX_FLAGS_PAR_TX_AUTO | \ - (uint32_t)RFAL_TXRX_FLAGS_NFCV_FLAG_AUTO) + (uint32_t)RFAL_TXRX_FLAGS_PAR_RX_REMV | (uint32_t)RFAL_TXRX_FLAGS_PAR_TX_AUTO) #define FURI_HAL_NFC_TX_DEFAULT_RX_NO_CRC \ ((uint32_t)RFAL_TXRX_FLAGS_CRC_TX_AUTO | (uint32_t)RFAL_TXRX_FLAGS_CRC_RX_KEEP | \ - (uint32_t)RFAL_TXRX_FLAGS_NFCIP1_OFF | (uint32_t)RFAL_TXRX_FLAGS_AGC_ON | \ - (uint32_t)RFAL_TXRX_FLAGS_PAR_RX_REMV | (uint32_t)RFAL_TXRX_FLAGS_PAR_TX_AUTO | \ - (uint32_t)RFAL_TXRX_FLAGS_NFCV_FLAG_AUTO) + (uint32_t)RFAL_TXRX_FLAGS_PAR_RX_REMV | (uint32_t)RFAL_TXRX_FLAGS_PAR_TX_AUTO) #define FURI_HAL_NFC_TXRX_WITH_PAR \ ((uint32_t)RFAL_TXRX_FLAGS_CRC_TX_MANUAL | (uint32_t)RFAL_TXRX_FLAGS_CRC_RX_KEEP | \ - (uint32_t)RFAL_TXRX_FLAGS_NFCIP1_OFF | (uint32_t)RFAL_TXRX_FLAGS_AGC_ON | \ - (uint32_t)RFAL_TXRX_FLAGS_PAR_RX_KEEP | (uint32_t)RFAL_TXRX_FLAGS_PAR_TX_AUTO | \ - (uint32_t)RFAL_TXRX_FLAGS_NFCV_FLAG_AUTO) + (uint32_t)RFAL_TXRX_FLAGS_PAR_RX_KEEP | (uint32_t)RFAL_TXRX_FLAGS_PAR_TX_AUTO) #define FURI_HAL_NFC_TXRX_RAW \ ((uint32_t)RFAL_TXRX_FLAGS_CRC_TX_MANUAL | (uint32_t)RFAL_TXRX_FLAGS_CRC_RX_KEEP | \ - (uint32_t)RFAL_TXRX_FLAGS_NFCIP1_OFF | (uint32_t)RFAL_TXRX_FLAGS_AGC_ON | \ - (uint32_t)RFAL_TXRX_FLAGS_PAR_RX_KEEP | (uint32_t)RFAL_TXRX_FLAGS_PAR_TX_NONE | \ - (uint32_t)RFAL_TXRX_FLAGS_NFCV_FLAG_AUTO) + (uint32_t)RFAL_TXRX_FLAGS_PAR_RX_KEEP | (uint32_t)RFAL_TXRX_FLAGS_PAR_TX_NONE) + +typedef enum { + FuriHalNfcTxRxTypeDefault, + FuriHalNfcTxRxTypeRxNoCrc, + FuriHalNfcTxRxTypeRxKeepPar, + FuriHalNfcTxRxTypeRaw, +} FuriHalNfcTxRxType; typedef bool (*FuriHalNfcEmulateCallback)( uint8_t* buff_rx, @@ -50,6 +49,29 @@ typedef bool (*FuriHalNfcEmulateCallback)( uint32_t* flags, void* context); +typedef enum { + FuriHalNfcTypeA, + FuriHalNfcTypeB, + FuriHalNfcTypeF, + FuriHalNfcTypeV, +} FuriHalNfcType; + +typedef enum { + FuriHalNfcInterfaceRf, + FuriHalNfcInterfaceIsoDep, + FuriHalNfcInterfaceNfcDep, +} FuriHalNfcInterface; + +typedef struct { + FuriHalNfcType type; + FuriHalNfcInterface interface; + uint8_t uid_len; + uint8_t uid[10]; + uint32_t cuid; + uint8_t atqa[2]; + uint8_t sak; +} FuriHalNfcDevData; + typedef struct { uint8_t tx_data[FURI_HAL_NFC_DATA_BUFF_SIZE]; uint8_t tx_parity[FURI_HAL_NFC_PARITY_BUFF_SIZE]; @@ -57,7 +79,7 @@ typedef struct { uint8_t rx_data[FURI_HAL_NFC_DATA_BUFF_SIZE]; uint8_t rx_parity[FURI_HAL_NFC_PARITY_BUFF_SIZE]; uint16_t rx_bits; - uint32_t tx_rx_type; + FuriHalNfcTxRxType tx_rx_type; } FuriHalNfcTxRxContext; /** Init nfc @@ -95,11 +117,7 @@ void furi_hal_nfc_exit_sleep(); * * @return true on success */ -bool furi_hal_nfc_detect( - rfalNfcDevice** dev_list, - uint8_t* dev_cnt, - uint32_t timeout, - bool deactivate); +bool furi_hal_nfc_detect(FuriHalNfcDevData* nfc_data, uint32_t timeout); /** Activate NFC-A tag * @@ -138,15 +156,6 @@ bool furi_hal_nfc_emulate_nfca( void* context, uint32_t timeout); -/** Get first command from reader after activation in emulation mode - * - * @param rx_buff pointer to receive buffer - * @param rx_len receive buffer length - * - * @return true on success - */ -bool furi_hal_nfc_get_first_frame(uint8_t** rx_buff, uint16_t** rx_len); - /** NFC data exchange * * @param tx_buff transmit buffer @@ -170,11 +179,28 @@ ReturnCode furi_hal_nfc_data_exchange( * * @return true on success */ -bool furi_hal_nfc_tx_rx(FuriHalNfcTxRxContext* tx_rx_ctx); +bool furi_hal_nfc_tx_rx(FuriHalNfcTxRxContext* tx_rx, uint16_t timeout_ms); + +/** NFC data full exhange + * + * @param tx_buff transmit buffer + * @param tx_len transmit buffer length + * @param rx_buff receive buffer + * @param rx_cap receive buffer capacity + * @param rx_len receive buffer length + * + * @return ST ReturnCode + */ +ReturnCode furi_hal_nfc_exchange_full( + uint8_t* tx_buff, + uint16_t tx_len, + uint8_t* rx_buff, + uint16_t rx_cap, + uint16_t* rx_len); /** NFC deactivate and start sleep */ -void furi_hal_nfc_deactivate(); +void furi_hal_nfc_sleep(); void furi_hal_nfc_stop(); diff --git a/lib/ST25RFAL002/source/rfal_isoDep.c b/lib/ST25RFAL002/source/rfal_isoDep.c index 4f0cff58a..77e67521d 100644 --- a/lib/ST25RFAL002/source/rfal_isoDep.c +++ b/lib/ST25RFAL002/source/rfal_isoDep.c @@ -3015,7 +3015,7 @@ ReturnCode rfalIsoDepGetApduTransceiveStatus(void) { } /* Update output param rxLen */ - *gIsoDep.APDUParam.rxLen = gIsoDep.APDURxPos; + *gIsoDep.APDUParam.rxLen = gIsoDep.APDURxPos * 8; /* Wait for following I-Block or APDU TxRx has finished */ return ((ret == ERR_AGAIN) ? ERR_BUSY : ERR_NONE); diff --git a/lib/ST25RFAL002/source/rfal_nfc.c b/lib/ST25RFAL002/source/rfal_nfc.c index a4a6094d5..9040b7f9d 100755 --- a/lib/ST25RFAL002/source/rfal_nfc.c +++ b/lib/ST25RFAL002/source/rfal_nfc.c @@ -725,9 +725,14 @@ ReturnCode rfalNfcDataExchangeCustomStart( { /*******************************************************************************/ case RFAL_NFC_INTERFACE_RF: - ctx.rxBuf = gNfcDev.rxBuf.rfBuf, ctx.rxBufLen = sizeof(gNfcDev.rxBuf.rfBuf), - ctx.rxRcvdLen = &gNfcDev.rxLen, ctx.txBuf = txData, ctx.txBufLen = txDataLen, - ctx.flags = flags, ctx.fwt = fwt, *rxData = (uint8_t*)gNfcDev.rxBuf.rfBuf; + ctx.rxBuf = gNfcDev.rxBuf.rfBuf; + ctx.rxBufLen = 8 * sizeof(gNfcDev.rxBuf.rfBuf); + ctx.rxRcvdLen = &gNfcDev.rxLen; + ctx.txBuf = txData; + ctx.txBufLen = txDataLen; + ctx.flags = flags; + ctx.fwt = fwt; + *rxData = (uint8_t*)gNfcDev.rxBuf.rfBuf; *rvdLen = (uint16_t*)&gNfcDev.rxLen; err = rfalStartTransceive(&ctx); break; @@ -736,13 +741,14 @@ ReturnCode rfalNfcDataExchangeCustomStart( /*******************************************************************************/ case RFAL_NFC_INTERFACE_ISODEP: { rfalIsoDepApduTxRxParam isoDepTxRx; + uint16_t tx_bytes = txDataLen / 8; - if(txDataLen > sizeof(gNfcDev.txBuf.isoDepBuf.apdu)) { + if(tx_bytes > sizeof(gNfcDev.txBuf.isoDepBuf.apdu)) { return ERR_NOMEM; } - if(txDataLen > 0U) { - ST_MEMCPY((uint8_t*)gNfcDev.txBuf.isoDepBuf.apdu, txData, txDataLen); + if(tx_bytes > 0U) { + ST_MEMCPY((uint8_t*)gNfcDev.txBuf.isoDepBuf.apdu, txData, tx_bytes); } isoDepTxRx.DID = RFAL_ISODEP_NO_DID; @@ -751,7 +757,7 @@ ReturnCode rfalNfcDataExchangeCustomStart( isoDepTxRx.dFWT = gNfcDev.activeDev->proto.isoDep.info.dFWT; isoDepTxRx.FWT = gNfcDev.activeDev->proto.isoDep.info.FWT; isoDepTxRx.txBuf = &gNfcDev.txBuf.isoDepBuf; - isoDepTxRx.txBufLen = txDataLen; + isoDepTxRx.txBufLen = tx_bytes; isoDepTxRx.rxBuf = &gNfcDev.rxBuf.isoDepBuf; isoDepTxRx.rxLen = &gNfcDev.rxLen; isoDepTxRx.tmpBuf = &gNfcDev.tmpBuf.isoDepBuf; diff --git a/lib/nfc_protocols/emv_decoder.c b/lib/nfc_protocols/emv.c similarity index 55% rename from lib/nfc_protocols/emv_decoder.c rename to lib/nfc_protocols/emv.c index e63a6e968..6756981b6 100644 --- a/lib/nfc_protocols/emv_decoder.c +++ b/lib/nfc_protocols/emv.c @@ -1,4 +1,8 @@ -#include "emv_decoder.h" +#include "emv.h" + +#include + +#define TAG "Emv" const PDOLValue pdol_term_info = {0x9F59, {0xC8, 0x80, 0x00}}; // Terminal transaction information const PDOLValue pdol_term_type = {0x9F5A, {0x00}}; // Terminal transaction type @@ -69,19 +73,6 @@ static bool emv_decode_search_tag_u16_r(uint16_t tag, uint8_t* buff, uint16_t* i return false; } -uint16_t emv_prepare_select_ppse(uint8_t* dest) { - const uint8_t emv_select_ppse[] = { - 0x00, 0xA4, // SELECT ppse - 0x04, 0x00, // P1:By name, P2: empty - 0x0e, // Lc: Data length - 0x32, 0x50, 0x41, 0x59, 0x2e, 0x53, 0x59, // Data string: - 0x53, 0x2e, 0x44, 0x44, 0x46, 0x30, 0x31, // 2PAY.SYS.DDF01 (PPSE) - 0x00 // Le - }; - memcpy(dest, emv_select_ppse, sizeof(emv_select_ppse)); - return sizeof(emv_select_ppse); -} - bool emv_decode_ppse_response(uint8_t* buff, uint16_t len, EmvApplication* app) { uint16_t i = 0; bool app_aid_found = false; @@ -89,7 +80,7 @@ bool emv_decode_ppse_response(uint8_t* buff, uint16_t len, EmvApplication* app) while(i < len) { if(buff[i] == EMV_TAG_APP_TEMPLATE) { uint8_t app_len = buff[++i]; - for(uint16_t j = i; j < i + app_len; j++) { + for(uint16_t j = i; j < MIN(i + app_len, len - 1); j++) { if(buff[j] == EMV_TAG_AID) { app_aid_found = true; app->aid_len = buff[j + 1]; @@ -105,7 +96,59 @@ bool emv_decode_ppse_response(uint8_t* buff, uint16_t len, EmvApplication* app) return app_aid_found; } -uint16_t emv_prepare_select_app(uint8_t* dest, EmvApplication* app) { +bool emv_select_ppse(FuriHalNfcTxRxContext* tx_rx, EmvApplication* app) { + bool app_aid_found = false; + const uint8_t emv_select_ppse_cmd[] = { + 0x00, 0xA4, // SELECT ppse + 0x04, 0x00, // P1:By name, P2: empty + 0x0e, // Lc: Data length + 0x32, 0x50, 0x41, 0x59, 0x2e, 0x53, 0x59, // Data string: + 0x53, 0x2e, 0x44, 0x44, 0x46, 0x30, 0x31, // 2PAY.SYS.DDF01 (PPSE) + 0x00 // Le + }; + + memcpy(tx_rx->tx_data, emv_select_ppse_cmd, sizeof(emv_select_ppse_cmd)); + tx_rx->tx_bits = sizeof(emv_select_ppse_cmd) * 8; + tx_rx->tx_rx_type = FuriHalNfcTxRxTypeDefault; + + FURI_LOG_D(TAG, "Send select PPSE"); + if(furi_hal_nfc_tx_rx(tx_rx, 300)) { + if(emv_decode_ppse_response(tx_rx->rx_data, tx_rx->rx_bits / 8, app)) { + app_aid_found = true; + } else { + FURI_LOG_E(TAG, "Failed to parse application"); + } + } else { + FURI_LOG_E(TAG, "Failed select PPSE"); + } + + return app_aid_found; +} + +static bool emv_decode_select_app_response(uint8_t* buff, uint16_t len, EmvApplication* app) { + uint16_t i = 0; + bool decode_success = false; + + while(i < len) { + if(buff[i] == EMV_TAG_CARD_NAME) { + uint8_t name_len = buff[i + 1]; + emv_parse_TLV((uint8_t*)app->name, buff, &i); + app->name[name_len] = '\0'; + app->name_found = true; + decode_success = true; + } else if(((buff[i] << 8) | buff[i + 1]) == EMV_TAG_PDOL) { + i++; + app->pdol.size = emv_parse_TLV(app->pdol.data, buff, &i); + decode_success = true; + } + i++; + } + + return decode_success; +} + +bool emv_select_app(FuriHalNfcTxRxContext* tx_rx, EmvApplication* app) { + bool select_app_success = false; const uint8_t emv_select_header[] = { 0x00, 0xA4, // SELECT application @@ -113,33 +156,29 @@ uint16_t emv_prepare_select_app(uint8_t* dest, EmvApplication* app) { 0x00 // P1:By name, P2:First or only occurence }; uint16_t size = sizeof(emv_select_header); + // Copy header - memcpy(dest, emv_select_header, size); + memcpy(tx_rx->tx_data, emv_select_header, size); // Copy AID - dest[size++] = app->aid_len; - memcpy(&dest[size], app->aid, app->aid_len); + tx_rx->tx_data[size++] = app->aid_len; + memcpy(&tx_rx->tx_data[size], app->aid, app->aid_len); size += app->aid_len; - dest[size++] = 0; - return size; -} + tx_rx->tx_data[size++] = 0x00; + tx_rx->tx_bits = size * 8; + tx_rx->tx_rx_type = FuriHalNfcTxRxTypeDefault; -bool emv_decode_select_app_response(uint8_t* buff, uint16_t len, EmvApplication* app) { - uint16_t i = 0; - bool found_name = false; - - while(i < len) { - if(buff[i] == EMV_TAG_CARD_NAME) { - uint8_t name_len = buff[i + 1]; - emv_parse_TLV((uint8_t*)app->name, buff, &i); - app->name[name_len] = '\0'; - found_name = true; - } else if(((buff[i] << 8) | buff[i + 1]) == EMV_TAG_PDOL) { - i++; - app->pdol.size = emv_parse_TLV(app->pdol.data, buff, &i); + FURI_LOG_D(TAG, "Start application"); + if(furi_hal_nfc_tx_rx(tx_rx, 300)) { + if(emv_decode_select_app_response(tx_rx->rx_data, tx_rx->rx_bits / 8, app)) { + select_app_success = true; + } else { + FURI_LOG_E(TAG, "Failed to read PAN or PDOL"); } - i++; + } else { + FURI_LOG_E(TAG, "Failed to start application"); } - return found_name; + + return select_app_success; } static uint16_t emv_prepare_pdol(APDU* dest, APDU* src) { @@ -175,53 +214,56 @@ static uint16_t emv_prepare_pdol(APDU* dest, APDU* src) { return dest->size; } -uint16_t emv_prepare_get_proc_opt(uint8_t* dest, EmvApplication* app) { - // Get processing option header - const uint8_t emv_gpo_header[] = {0x80, 0xA8, 0x00, 0x00}; - uint16_t size = sizeof(emv_gpo_header); - // Copy header - memcpy(dest, emv_gpo_header, size); - APDU pdol_data = {0, {0}}; - // Prepare and copy pdol parameters - emv_prepare_pdol(&pdol_data, &app->pdol); - dest[size++] = 0x02 + pdol_data.size; - dest[size++] = 0x83; - dest[size++] = pdol_data.size; - memcpy(dest + size, pdol_data.data, pdol_data.size); - size += pdol_data.size; - dest[size++] = 0; - return size; -} +static bool emv_decode_get_proc_opt(uint8_t* buff, uint16_t len, EmvApplication* app) { + bool card_num_read = false; -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) { app->card_number_len = 8; memcpy(app->card_number, &buff[i + 2], app->card_number_len); - return true; + card_num_read = true; } else if(buff[i] == EMV_TAG_AFL) { app->afl.size = emv_parse_TLV(app->afl.data, buff, &i); } } - return false; + + return card_num_read; } -uint16_t emv_prepare_read_sfi_record(uint8_t* dest, uint8_t sfi, uint8_t record_num) { - const uint8_t sfi_param = (sfi << 3) | (1 << 2); - const uint8_t emv_sfi_header[] = { - 0x00, - 0xB2, // READ RECORD - record_num, - sfi_param, // P1:record_number and P2:SFI - 0x00 // Le - }; - uint16_t size = sizeof(emv_sfi_header); - memcpy(dest, emv_sfi_header, size); - return size; +static bool emv_get_processing_options(FuriHalNfcTxRxContext* tx_rx, EmvApplication* app) { + bool card_num_read = false; + const uint8_t emv_gpo_header[] = {0x80, 0xA8, 0x00, 0x00}; + uint16_t size = sizeof(emv_gpo_header); + + // Copy header + memcpy(tx_rx->tx_data, emv_gpo_header, size); + APDU pdol_data = {0, {0}}; + // Prepare and copy pdol parameters + emv_prepare_pdol(&pdol_data, &app->pdol); + tx_rx->tx_data[size++] = 0x02 + pdol_data.size; + tx_rx->tx_data[size++] = 0x83; + tx_rx->tx_data[size++] = pdol_data.size; + memcpy(tx_rx->tx_data + size, pdol_data.data, pdol_data.size); + size += pdol_data.size; + tx_rx->tx_data[size++] = 0; + tx_rx->tx_bits = size * 8; + tx_rx->tx_rx_type = FuriHalNfcTxRxTypeDefault; + + FURI_LOG_D(TAG, "Get proccessing options"); + if(furi_hal_nfc_tx_rx(tx_rx, 300)) { + if(emv_decode_get_proc_opt(tx_rx->rx_data, tx_rx->rx_bits / 8, app)) { + card_num_read = true; + } + } else { + FURI_LOG_E(TAG, "Failed to get processing options"); + } + + return card_num_read; } -bool emv_decode_read_sfi_record(uint8_t* buff, uint16_t len, EmvApplication* app) { +static 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) { if(buff[i + 1] == 8 || buff[i + 1] == 10) { @@ -240,20 +282,118 @@ bool emv_decode_read_sfi_record(uint8_t* buff, uint16_t len, EmvApplication* app i += 2; } } + return pan_parsed; } -uint16_t emv_select_ppse_ans(uint8_t* buff) { - memcpy(buff, select_ppse_ans, sizeof(select_ppse_ans)); - return sizeof(select_ppse_ans); +static bool emv_read_sfi_record( + FuriHalNfcTxRxContext* tx_rx, + EmvApplication* app, + uint8_t sfi, + uint8_t record_num) { + bool card_num_read = false; + uint8_t sfi_param = (sfi << 3) | (1 << 2); + uint8_t emv_sfi_header[] = { + 0x00, + 0xB2, // READ RECORD + record_num, // P1:record_number + sfi_param, // P2:SFI + 0x00 // Le + }; + + memcpy(tx_rx->tx_data, emv_sfi_header, sizeof(emv_sfi_header)); + tx_rx->tx_bits = sizeof(emv_sfi_header) * 8; + tx_rx->tx_rx_type = FuriHalNfcTxRxTypeDefault; + + if(furi_hal_nfc_tx_rx(tx_rx, 300)) { + if(emv_decode_read_sfi_record(tx_rx->rx_data, tx_rx->rx_bits / 8, app)) { + card_num_read = true; + } + } else { + FURI_LOG_E(TAG, "Failed to read SFI record %d", record_num); + } + + return card_num_read; } -uint16_t emv_select_app_ans(uint8_t* buff) { - memcpy(buff, select_app_ans, sizeof(select_app_ans)); - return sizeof(select_app_ans); +static bool emv_read_files(FuriHalNfcTxRxContext* tx_rx, EmvApplication* app) { + bool card_num_read = false; + + if(app->afl.size == 0) { + return false; + } + + FURI_LOG_D(TAG, "Search PAN in SFI"); + // Iterate through all files + for(size_t i = 0; i < app->afl.size; i += 4) { + uint8_t sfi = app->afl.data[i] >> 3; + uint8_t record_start = app->afl.data[i + 1]; + uint8_t record_end = app->afl.data[i + 2]; + // Iterate through all records in file + for(uint8_t record = record_start; record <= record_end; ++record) { + card_num_read |= emv_read_sfi_record(tx_rx, app, sfi, record); + } + } + + return card_num_read; } -uint16_t emv_get_proc_opt_ans(uint8_t* buff) { - memcpy(buff, pdol_ans, sizeof(pdol_ans)); - return sizeof(pdol_ans); +bool emv_search_application(FuriHalNfcTxRxContext* tx_rx, EmvApplication* emv_app) { + furi_assert(tx_rx); + furi_assert(emv_app); + memset(emv_app, 0, sizeof(EmvApplication)); + + return emv_select_ppse(tx_rx, emv_app); +} + +bool emv_read_bank_card(FuriHalNfcTxRxContext* tx_rx, EmvApplication* emv_app) { + furi_assert(tx_rx); + furi_assert(emv_app); + bool card_num_read = false; + memset(emv_app, 0, sizeof(EmvApplication)); + + do { + if(!emv_select_ppse(tx_rx, emv_app)) break; + if(!emv_select_app(tx_rx, emv_app)) break; + if(emv_get_processing_options(tx_rx, emv_app)) { + card_num_read = true; + } else { + card_num_read = emv_read_files(tx_rx, emv_app); + } + } while(false); + + return card_num_read; +} + +bool emv_card_emulation(FuriHalNfcTxRxContext* tx_rx) { + furi_assert(tx_rx); + bool emulation_complete = false; + memset(tx_rx, 0, sizeof(FuriHalNfcTxRxContext)); + + do { + FURI_LOG_D(TAG, "Read select PPSE command"); + if(!furi_hal_nfc_tx_rx(tx_rx, 300)) break; + + memcpy(tx_rx->tx_data, select_ppse_ans, sizeof(select_ppse_ans)); + tx_rx->tx_bits = sizeof(select_ppse_ans) * 8; + tx_rx->tx_rx_type = FuriHalNfcTxRxTypeDefault; + FURI_LOG_D(TAG, "Send select PPSE answer and read select App command"); + if(!furi_hal_nfc_tx_rx(tx_rx, 300)) break; + + memcpy(tx_rx->tx_data, select_app_ans, sizeof(select_app_ans)); + tx_rx->tx_bits = sizeof(select_app_ans) * 8; + tx_rx->tx_rx_type = FuriHalNfcTxRxTypeDefault; + FURI_LOG_D(TAG, "Send select App answer and read get PDOL command"); + if(!furi_hal_nfc_tx_rx(tx_rx, 300)) break; + + memcpy(tx_rx->tx_data, pdol_ans, sizeof(pdol_ans)); + tx_rx->tx_bits = sizeof(pdol_ans) * 8; + tx_rx->tx_rx_type = FuriHalNfcTxRxTypeDefault; + FURI_LOG_D(TAG, "Send get PDOL answer"); + if(!furi_hal_nfc_tx_rx(tx_rx, 300)) break; + + emulation_complete = true; + } while(false); + + return emulation_complete; } diff --git a/lib/nfc_protocols/emv.h b/lib/nfc_protocols/emv.h new file mode 100755 index 000000000..b5a0c574f --- /dev/null +++ b/lib/nfc_protocols/emv.h @@ -0,0 +1,87 @@ +#pragma once + +#include + +#define MAX_APDU_LEN 255 + +#define EMV_TAG_APP_TEMPLATE 0x61 +#define EMV_TAG_AID 0x4F +#define EMV_TAG_PRIORITY 0x87 +#define EMV_TAG_PDOL 0x9F38 +#define EMV_TAG_CARD_NAME 0x50 +#define EMV_TAG_FCI 0xBF0C +#define EMV_TAG_LOG_CTRL 0x9F4D +#define EMV_TAG_CARD_NUM 0x57 +#define EMV_TAG_PAN 0x5A +#define EMV_TAG_AFL 0x94 +#define EMV_TAG_EXP_DATE 0x5F24 +#define EMV_TAG_COUNTRY_CODE 0x5F28 +#define EMV_TAG_CURRENCY_CODE 0x9F42 +#define EMV_TAG_CARDHOLDER_NAME 0x5F20 + +typedef struct { + char name[32]; + uint8_t aid[16]; + uint16_t aid_len; + uint8_t number[10]; + uint8_t number_len; + uint8_t exp_mon; + uint8_t exp_year; + uint16_t country_code; + uint16_t currency_code; +} EmvData; + +typedef struct { + uint16_t tag; + uint8_t data[]; +} PDOLValue; + +typedef struct { + uint8_t size; + uint8_t data[MAX_APDU_LEN]; +} APDU; + +typedef struct { + uint8_t priority; + uint8_t aid[16]; + uint8_t aid_len; + char name[32]; + bool name_found; + uint8_t card_number[10]; + uint8_t card_number_len; + uint8_t exp_month; + uint8_t exp_year; + uint16_t country_code; + uint16_t currency_code; + APDU pdol; + APDU afl; +} EmvApplication; + +/** Read bank card data + * @note Search EMV Application, start it, try to read AID, PAN, card name, + * expiration date, currency and country codes + * + * @param tx_rx FuriHalNfcTxRxContext instance + * @param emv_app EmvApplication instance + * + * @return true on success + */ +bool emv_read_bank_card(FuriHalNfcTxRxContext* tx_rx, EmvApplication* emv_app); + +/** Search for EMV Application + * + * @param tx_rx FuriHalNfcTxRxContext instance + * @param emv_app EmvApplication instance + * + * @return true on success + */ +bool emv_search_application(FuriHalNfcTxRxContext* tx_rx, EmvApplication* emv_app); + +/** Emulate bank card + * @note Answer to application selection and PDOL + * + * @param tx_rx FuriHalNfcTxRxContext instance + * + * @return true on success + */ +bool emv_card_emulation(FuriHalNfcTxRxContext* tx_rx); diff --git a/lib/nfc_protocols/emv_decoder.h b/lib/nfc_protocols/emv_decoder.h deleted file mode 100755 index 7328ee79d..000000000 --- a/lib/nfc_protocols/emv_decoder.h +++ /dev/null @@ -1,67 +0,0 @@ -#pragma once - -#include -#include -#include - -#define MAX_APDU_LEN 255 - -#define EMV_TAG_APP_TEMPLATE 0x61 -#define EMV_TAG_AID 0x4F -#define EMV_TAG_PRIORITY 0x87 -#define EMV_TAG_PDOL 0x9F38 -#define EMV_TAG_CARD_NAME 0x50 -#define EMV_TAG_FCI 0xBF0C -#define EMV_TAG_LOG_CTRL 0x9F4D -#define EMV_TAG_CARD_NUM 0x57 -#define EMV_TAG_PAN 0x5A -#define EMV_TAG_AFL 0x94 -#define EMV_TAG_EXP_DATE 0x5F24 -#define EMV_TAG_COUNTRY_CODE 0x5F28 -#define EMV_TAG_CURRENCY_CODE 0x9F42 -#define EMV_TAG_CARDHOLDER_NAME 0x5F20 - -typedef struct { - uint16_t tag; - uint8_t data[]; -} PDOLValue; - -extern const PDOLValue* const pdol_values[]; - -typedef struct { - uint8_t size; - uint8_t data[MAX_APDU_LEN]; -} APDU; - -typedef struct { - uint8_t priority; - uint8_t aid[16]; - uint8_t aid_len; - char name[32]; - uint8_t card_number[10]; - uint8_t card_number_len; - uint8_t exp_month; - uint8_t exp_year; - uint16_t country_code; - uint16_t currency_code; - APDU pdol; - APDU afl; -} EmvApplication; - -/* Terminal emulation */ -uint16_t emv_prepare_select_ppse(uint8_t* dest); -bool emv_decode_ppse_response(uint8_t* buff, uint16_t len, EmvApplication* app); - -uint16_t emv_prepare_select_app(uint8_t* dest, EmvApplication* app); -bool emv_decode_select_app_response(uint8_t* buff, uint16_t len, EmvApplication* app); - -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); - -uint16_t emv_prepare_read_sfi_record(uint8_t* dest, uint8_t sfi, uint8_t record_num); -bool emv_decode_read_sfi_record(uint8_t* buff, uint16_t len, EmvApplication* app); - -/* Card emulation */ -uint16_t emv_select_ppse_ans(uint8_t* buff); -uint16_t emv_select_app_ans(uint8_t* buff); -uint16_t emv_get_proc_opt_ans(uint8_t* buff); diff --git a/lib/nfc_protocols/mifare_classic.c b/lib/nfc_protocols/mifare_classic.c index 65408e78e..eb5d3dda0 100644 --- a/lib/nfc_protocols/mifare_classic.c +++ b/lib/nfc_protocols/mifare_classic.c @@ -116,17 +116,15 @@ static bool mf_classic_auth( tx_rx->tx_data[0] = MF_CLASSIC_AUTH_KEY_B_CMD; } tx_rx->tx_data[1] = block; - tx_rx->tx_rx_type = FURI_HAL_NFC_TX_DEFAULT_RX_NO_CRC; + tx_rx->tx_rx_type = FuriHalNfcTxRxTypeRxNoCrc; tx_rx->tx_bits = 2 * 8; - if(!furi_hal_nfc_tx_rx(tx_rx)) break; + if(!furi_hal_nfc_tx_rx(tx_rx, 4)) break; uint32_t nt = (uint32_t)nfc_util_bytes2num(tx_rx->rx_data, 4); crypto1_init(crypto, key); crypto1_word(crypto, nt ^ cuid, 0); uint8_t nr[4] = {}; - // uint8_t parity = 0; nfc_util_num2bytes(prng_successor(DWT->CYCCNT, 32), 4, nr); - // uint8_t nr_ar[8] = {}; for(uint8_t i = 0; i < 4; i++) { tx_rx->tx_data[i] = crypto1_byte(crypto, nr[i], 0) ^ nr[i]; tx_rx->tx_parity[0] |= @@ -140,9 +138,9 @@ static bool mf_classic_auth( (((crypto1_filter(crypto->odd) ^ nfc_util_odd_parity8(nt & 0xff)) & 0x01) << (7 - i)); } - tx_rx->tx_rx_type = FURI_HAL_NFC_TXRX_RAW; + tx_rx->tx_rx_type = FuriHalNfcTxRxTypeRaw; tx_rx->tx_bits = 8 * 8; - if(!furi_hal_nfc_tx_rx(tx_rx)) break; + if(!furi_hal_nfc_tx_rx(tx_rx, 4)) break; if(tx_rx->rx_bits == 32) { crypto1_word(crypto, 0, 0); auth_success = true; @@ -178,7 +176,7 @@ bool mf_classic_auth_attempt( } if(need_halt) { - furi_hal_nfc_deactivate(); + furi_hal_nfc_sleep(); furi_hal_nfc_activate_nfca(300, &auth_ctx->cuid); } @@ -220,9 +218,9 @@ bool mf_classic_read_block( ((crypto1_filter(crypto->odd) ^ nfc_util_odd_parity8(plain_cmd[i])) & 0x01) << (7 - i); } tx_rx->tx_bits = 4 * 9; - tx_rx->tx_rx_type = FURI_HAL_NFC_TXRX_RAW; + tx_rx->tx_rx_type = FuriHalNfcTxRxTypeRaw; - if(furi_hal_nfc_tx_rx(tx_rx)) { + if(furi_hal_nfc_tx_rx(tx_rx, 4)) { if(tx_rx->rx_bits == 8 * 18) { for(uint8_t i = 0; i < 18; i++) { block->value[i] = crypto1_byte(crypto, 0, 0) ^ tx_rx->rx_data[i]; @@ -248,7 +246,7 @@ bool mf_classic_read_sector( uint8_t first_block; bool sector_read = false; - furi_hal_nfc_deactivate(); + furi_hal_nfc_sleep(); do { // Activate card if(!furi_hal_nfc_activate_nfca(200, &cuid)) break; diff --git a/lib/nfc_protocols/mifare_common.c b/lib/nfc_protocols/mifare_common.c new file mode 100644 index 000000000..0be24b512 --- /dev/null +++ b/lib/nfc_protocols/mifare_common.c @@ -0,0 +1,17 @@ +#include "mifare_common.h" + +MifareType mifare_common_get_type(uint8_t ATQA0, uint8_t ATQA1, uint8_t SAK) { + MifareType type = MifareTypeUnknown; + + if((ATQA0 == 0x44) && (ATQA1 == 0x00) && (SAK == 0x00)) { + type = MifareTypeUltralight; + } else if( + ((ATQA0 == 0x44 || ATQA0 == 0x04) && (SAK == 0x08)) || + ((ATQA0 == 0x42 || ATQA0 == 0x02) && (SAK == 0x18))) { + type = MifareTypeClassic; + } else if(ATQA0 == 0x44 && ATQA1 == 0x03 && SAK == 0x20) { + type = MifareTypeDesfire; + } + + return type; +} diff --git a/lib/nfc_protocols/mifare_common.h b/lib/nfc_protocols/mifare_common.h new file mode 100644 index 000000000..2b694d906 --- /dev/null +++ b/lib/nfc_protocols/mifare_common.h @@ -0,0 +1,12 @@ +#pragma once + +#include + +typedef enum { + MifareTypeUnknown, + MifareTypeUltralight, + MifareTypeClassic, + MifareTypeDesfire, +} MifareType; + +MifareType mifare_common_get_type(uint8_t ATQA0, uint8_t ATQA1, uint8_t SAK); diff --git a/lib/nfc_protocols/mifare_ultralight.c b/lib/nfc_protocols/mifare_ultralight.c index c9311124e..c824c6461 100644 --- a/lib/nfc_protocols/mifare_ultralight.c +++ b/lib/nfc_protocols/mifare_ultralight.c @@ -1,6 +1,7 @@ #include "mifare_ultralight.h" #include -#include + +#define TAG "MfUltralight" bool mf_ul_check_card_type(uint8_t ATQA0, uint8_t ATQA1, uint8_t SAK) { if((ATQA0 == 0x44) && (ATQA1 == 0x00) && (SAK == 0x00)) { @@ -9,187 +10,204 @@ bool mf_ul_check_card_type(uint8_t ATQA0, uint8_t ATQA1, uint8_t SAK) { return false; } -uint16_t mf_ul_prepare_get_version(uint8_t* dest) { - dest[0] = MF_UL_GET_VERSION_CMD; - return 1; +static void mf_ul_set_default_version(MfUltralightReader* reader, MfUltralightData* data) { + data->type = MfUltralightTypeUnknown; + reader->pages_to_read = 16; + reader->support_fast_read = false; } -void mf_ul_parse_get_version_response(uint8_t* buff, MifareUlDevice* mf_ul_read) { - MfUltralightVersion* version = (MfUltralightVersion*)buff; - memcpy(&mf_ul_read->data.version, version, sizeof(MfUltralightVersion)); - if(version->storage_size == 0x0B || version->storage_size == 0x00) { - mf_ul_read->data.type = MfUltralightTypeUL11; - mf_ul_read->pages_to_read = 20; - mf_ul_read->support_fast_read = true; - } else if(version->storage_size == 0x0E) { - mf_ul_read->data.type = MfUltralightTypeUL21; - mf_ul_read->pages_to_read = 41; - mf_ul_read->support_fast_read = true; - } else if(version->storage_size == 0x0F) { - mf_ul_read->data.type = MfUltralightTypeNTAG213; - mf_ul_read->pages_to_read = 45; - mf_ul_read->support_fast_read = false; - } else if(version->storage_size == 0x11) { - mf_ul_read->data.type = MfUltralightTypeNTAG215; - mf_ul_read->pages_to_read = 135; - mf_ul_read->support_fast_read = false; - } else if(version->storage_size == 0x13) { - mf_ul_read->data.type = MfUltralightTypeNTAG216; - mf_ul_read->pages_to_read = 231; - mf_ul_read->support_fast_read = false; +bool mf_ultralight_read_version( + FuriHalNfcTxRxContext* tx_rx, + MfUltralightReader* reader, + MfUltralightData* data) { + bool version_read = false; + + do { + FURI_LOG_D(TAG, "Reading version"); + tx_rx->tx_data[0] = MF_UL_GET_VERSION_CMD; + tx_rx->tx_bits = 8; + tx_rx->tx_rx_type = FuriHalNfcTxRxTypeDefault; + if(!furi_hal_nfc_tx_rx(tx_rx, 4)) { + FURI_LOG_D(TAG, "Failed reading version"); + mf_ul_set_default_version(reader, data); + furi_hal_nfc_sleep(); + furi_hal_nfc_activate_nfca(300, NULL); + break; + } + MfUltralightVersion* version = (MfUltralightVersion*)tx_rx->rx_data; + data->version = *version; + if(version->storage_size == 0x0B || version->storage_size == 0x00) { + data->type = MfUltralightTypeUL11; + reader->pages_to_read = 20; + reader->support_fast_read = true; + } else if(version->storage_size == 0x0E) { + data->type = MfUltralightTypeUL21; + reader->pages_to_read = 41; + reader->support_fast_read = true; + } else if(version->storage_size == 0x0F) { + data->type = MfUltralightTypeNTAG213; + reader->pages_to_read = 45; + reader->support_fast_read = false; + } else if(version->storage_size == 0x11) { + data->type = MfUltralightTypeNTAG215; + reader->pages_to_read = 135; + reader->support_fast_read = false; + } else if(version->storage_size == 0x13) { + data->type = MfUltralightTypeNTAG216; + reader->pages_to_read = 231; + reader->support_fast_read = false; + } else { + mf_ul_set_default_version(reader, data); + break; + } + version_read = true; + } while(false); + + return version_read; +} + +bool mf_ultralight_read_pages( + FuriHalNfcTxRxContext* tx_rx, + MfUltralightReader* reader, + MfUltralightData* data) { + uint8_t pages_read_cnt = 0; + + for(size_t i = 0; i < reader->pages_to_read; i += 4) { + FURI_LOG_D(TAG, "Reading pages %d - %d", i, i + 3); + tx_rx->tx_data[0] = MF_UL_READ_CMD; + tx_rx->tx_data[1] = i; + tx_rx->tx_bits = 16; + tx_rx->tx_rx_type = FuriHalNfcTxRxTypeDefault; + if(!furi_hal_nfc_tx_rx(tx_rx, 4)) { + FURI_LOG_D(TAG, "Failed to read pages %d - %d", i, i + 3); + break; + } + if(i + 4 <= reader->pages_to_read) { + pages_read_cnt = 4; + } else { + pages_read_cnt = reader->pages_to_read - reader->pages_read; + } + reader->pages_read += pages_read_cnt; + data->data_size = reader->pages_read * 4; + memcpy(&data->data[i * 4], tx_rx->rx_data, pages_read_cnt * 4); + } + + return reader->pages_read == reader->pages_to_read; +} + +bool mf_ultralight_fast_read_pages( + FuriHalNfcTxRxContext* tx_rx, + MfUltralightReader* reader, + MfUltralightData* data) { + FURI_LOG_D(TAG, "Reading pages 0 - %d", reader->pages_to_read); + tx_rx->tx_data[0] = MF_UL_FAST_READ_CMD; + tx_rx->tx_data[1] = 0; + tx_rx->tx_data[2] = reader->pages_to_read - 1; + tx_rx->tx_bits = 24; + tx_rx->tx_rx_type = FuriHalNfcTxRxTypeDefault; + if(furi_hal_nfc_tx_rx(tx_rx, 20)) { + reader->pages_read = reader->pages_to_read; + data->data_size = reader->pages_read * 4; + memcpy(data->data, tx_rx->rx_data, data->data_size); } else { - mf_ul_set_default_version(mf_ul_read); - } -} - -void mf_ul_set_default_version(MifareUlDevice* mf_ul_read) { - mf_ul_read->data.type = MfUltralightTypeUnknown; - mf_ul_read->pages_to_read = 16; - mf_ul_read->support_fast_read = false; -} - -uint16_t mf_ul_prepare_read(uint8_t* dest, uint8_t start_page) { - dest[0] = MF_UL_READ_CMD; - dest[1] = start_page; - return 2; -} - -void mf_ul_parse_read_response(uint8_t* buff, uint16_t page_addr, MifareUlDevice* mf_ul_read) { - uint8_t pages_read = 4; - uint8_t page_read_count = mf_ul_read->pages_read + pages_read; - if(page_read_count > mf_ul_read->pages_to_read) { - pages_read -= page_read_count - mf_ul_read->pages_to_read; - } - mf_ul_read->pages_read += pages_read; - mf_ul_read->data.data_size = mf_ul_read->pages_read * 4; - memcpy(&mf_ul_read->data.data[page_addr * 4], buff, pages_read * 4); -} - -uint16_t mf_ul_prepare_fast_read(uint8_t* dest, uint8_t start_page, uint8_t end_page) { - dest[0] = MF_UL_FAST_READ_CMD; - dest[1] = start_page; - dest[2] = end_page; - return 3; -} - -void mf_ul_parse_fast_read_response( - uint8_t* buff, - uint8_t start_page, - uint8_t end_page, - MifareUlDevice* mf_ul_read) { - mf_ul_read->pages_read = end_page - start_page + 1; - mf_ul_read->data.data_size = mf_ul_read->pages_read * 4; - memcpy(mf_ul_read->data.data, buff, mf_ul_read->data.data_size); -} - -uint16_t mf_ul_prepare_read_signature(uint8_t* dest) { - dest[0] = MF_UL_READ_SIG; - dest[1] = 0; - return 2; -} - -void mf_ul_parse_read_signature_response(uint8_t* buff, MifareUlDevice* mf_ul_read) { - memcpy(mf_ul_read->data.signature, buff, sizeof(mf_ul_read->data.signature)); -} - -uint16_t mf_ul_prepare_read_cnt(uint8_t* dest, uint8_t cnt_index) { - if(cnt_index > 2) { - return 0; - } - dest[0] = MF_UL_READ_CNT; - dest[1] = cnt_index; - return 2; -} - -void mf_ul_parse_read_cnt_response(uint8_t* buff, uint8_t cnt_index, MifareUlDevice* mf_ul_read) { - // Reverse LSB sequence - if(cnt_index < 3) { - mf_ul_read->data.counter[cnt_index] = (buff[2] << 16) | (buff[1] << 8) | (buff[0]); - } -} - -uint16_t mf_ul_prepare_inc_cnt(uint8_t* dest, uint8_t cnt_index, uint32_t value) { - if(cnt_index > 2) { - return 0; - } - dest[0] = MF_UL_INC_CNT; - dest[1] = cnt_index; - dest[2] = (uint8_t)value; - dest[3] = (uint8_t)(value >> 8); - dest[4] = (uint8_t)(value >> 16); - dest[5] = 0; - return 6; -} - -uint16_t mf_ul_prepare_check_tearing(uint8_t* dest, uint8_t cnt_index) { - if(cnt_index > 2) { - return 0; - } - dest[0] = MF_UL_CHECK_TEARING; - dest[1] = cnt_index; - return 2; -} - -void mf_ul_parse_check_tearing_response( - uint8_t* buff, - uint8_t cnt_index, - MifareUlDevice* mf_ul_read) { - if(cnt_index < 2) { - mf_ul_read->data.tearing[cnt_index] = buff[0]; - } -} - -uint16_t mf_ul_prepare_write(uint8_t* dest, uint16_t page_addr, uint32_t data) { - if(page_addr < 2) { - return 0; - } - dest[0] = MF_UL_WRITE; - dest[1] = page_addr; - dest[2] = (uint8_t)(data >> 24); - dest[3] = (uint8_t)(data >> 16); - dest[4] = (uint8_t)(data >> 8); - dest[5] = (uint8_t)data; - return 6; -} - -void mf_ul_prepare_emulation(MifareUlDevice* mf_ul_emulate, MifareUlData* data) { - mf_ul_emulate->data = *data; - mf_ul_emulate->auth_data = NULL; - mf_ul_emulate->data_changed = false; - mf_ul_emulate->comp_write_cmd_started = false; - if(data->version.storage_size == 0) { - mf_ul_emulate->data.type = MfUltralightTypeUnknown; - mf_ul_emulate->support_fast_read = false; - } else if(data->version.storage_size == 0x0B) { - mf_ul_emulate->data.type = MfUltralightTypeUL11; - mf_ul_emulate->support_fast_read = true; - } else if(data->version.storage_size == 0x0E) { - mf_ul_emulate->data.type = MfUltralightTypeUL21; - mf_ul_emulate->support_fast_read = true; - } else if(data->version.storage_size == 0x0F) { - mf_ul_emulate->data.type = MfUltralightTypeNTAG213; - mf_ul_emulate->support_fast_read = true; - } else if(data->version.storage_size == 0x11) { - mf_ul_emulate->data.type = MfUltralightTypeNTAG215; - mf_ul_emulate->support_fast_read = true; - } else if(data->version.storage_size == 0x13) { - mf_ul_emulate->data.type = MfUltralightTypeNTAG216; - mf_ul_emulate->support_fast_read = true; + FURI_LOG_D(TAG, "Failed to read pages 0 - %d", reader->pages_to_read); } - if(mf_ul_emulate->data.type >= MfUltralightTypeNTAG213) { - uint16_t pwd_page = (data->data_size / 4) - 2; - mf_ul_emulate->auth_data = (MifareUlAuthData*)&data->data[pwd_page * 4]; - } + return reader->pages_read == reader->pages_to_read; } -void mf_ul_protect_auth_data_on_read_command( +bool mf_ultralight_read_signature(FuriHalNfcTxRxContext* tx_rx, MfUltralightData* data) { + bool signature_read = false; + + FURI_LOG_D(TAG, "Reading signature"); + tx_rx->tx_data[0] = MF_UL_READ_SIG; + tx_rx->tx_data[1] = 0; + tx_rx->tx_bits = 16; + tx_rx->tx_rx_type = FuriHalNfcTxRxTypeDefault; + if(furi_hal_nfc_tx_rx(tx_rx, 7)) { + memcpy(data->signature, tx_rx->rx_data, sizeof(data->signature)); + signature_read = true; + } else { + FURI_LOG_D(TAG, "Failed redaing signature"); + } + + return signature_read; +} + +bool mf_ultralight_read_counters(FuriHalNfcTxRxContext* tx_rx, MfUltralightData* data) { + uint8_t counter_read = 0; + + FURI_LOG_D(TAG, "Reading counters"); + for(size_t i = 0; i < 3; i++) { + tx_rx->tx_data[0] = MF_UL_READ_CNT; + tx_rx->rx_data[1] = i; + tx_rx->tx_bits = 16; + tx_rx->tx_rx_type = FuriHalNfcTxRxTypeDefault; + if(!furi_hal_nfc_tx_rx(tx_rx, 4)) { + FURI_LOG_D(TAG, "Failed to read %d counter", i); + break; + } + data->counter[i] = (tx_rx->rx_data[2] << 16) | (tx_rx->rx_data[1] << 8) | + tx_rx->rx_data[0]; + counter_read++; + } + + return counter_read == 2; +} + +bool mf_ultralight_read_tearing_flags(FuriHalNfcTxRxContext* tx_rx, MfUltralightData* data) { + uint8_t flag_read = 0; + + FURI_LOG_D(TAG, "Reading tearing flags"); + for(size_t i = 0; i < 3; i++) { + tx_rx->tx_data[0] = MF_UL_CHECK_TEARING; + tx_rx->rx_data[1] = i; + tx_rx->tx_bits = 16; + tx_rx->tx_rx_type = FuriHalNfcTxRxTypeDefault; + if(!furi_hal_nfc_tx_rx(tx_rx, 4)) { + FURI_LOG_D(TAG, "Failed to read %d tearing flag", i); + break; + } + data->tearing[i] = tx_rx->rx_data[0]; + flag_read++; + } + + return flag_read == 2; +} + +bool mf_ul_read_card( + FuriHalNfcTxRxContext* tx_rx, + MfUltralightReader* reader, + MfUltralightData* data) { + furi_assert(tx_rx); + furi_assert(reader); + furi_assert(data); + + bool card_read = false; + + // Read Mifare Ultralight version + if(mf_ultralight_read_version(tx_rx, reader, data)) { + // Read Signature + mf_ultralight_read_signature(tx_rx, data); + } + // Read data blocks + if(reader->support_fast_read) { + mf_ultralight_read_counters(tx_rx, data); + mf_ultralight_read_tearing_flags(tx_rx, data); + } + card_read = mf_ultralight_read_pages(tx_rx, reader, data); + + return card_read; +} + +// TODO rework +static void mf_ul_protect_auth_data_on_read_command( uint8_t* tx_buff, uint8_t start_page, uint8_t end_page, - MifareUlDevice* mf_ul_emulate) { - if(mf_ul_emulate->data.type >= MfUltralightTypeNTAG213) { - uint8_t pwd_page = (mf_ul_emulate->data.data_size / 4) - 2; + MfUltralightEmulator* emulator) { + if(emulator->data.type >= MfUltralightTypeNTAG213) { + uint8_t pwd_page = (emulator->data.data_size / 4) - 2; uint8_t pack_page = pwd_page + 1; if((start_page <= pwd_page) && (end_page >= pwd_page)) { memset(&tx_buff[(pwd_page - start_page) * 4], 0, 4); @@ -200,6 +218,31 @@ void mf_ul_protect_auth_data_on_read_command( } } +void mf_ul_prepare_emulation(MfUltralightEmulator* emulator, MfUltralightData* data) { + emulator->data = *data; + emulator->auth_data = NULL; + emulator->data_changed = false; + emulator->comp_write_cmd_started = false; + if(data->type == MfUltralightTypeUnknown) { + emulator->support_fast_read = false; + } else if(data->type == MfUltralightTypeUL11) { + emulator->support_fast_read = true; + } else if(data->type == MfUltralightTypeUL21) { + emulator->support_fast_read = true; + } else if(data->type == MfUltralightTypeNTAG213) { + emulator->support_fast_read = false; + } else if(data->type == MfUltralightTypeNTAG215) { + emulator->support_fast_read = false; + } else if(data->type == MfUltralightTypeNTAG216) { + emulator->support_fast_read = false; + } + + if(data->type >= MfUltralightTypeNTAG213) { + uint16_t pwd_page = (data->data_size / 4) - 2; + emulator->auth_data = (MfUltralightAuth*)&data->data[pwd_page * 4]; + } +} + bool mf_ul_prepare_emulation_response( uint8_t* buff_rx, uint16_t buff_rx_len, @@ -208,30 +251,30 @@ bool mf_ul_prepare_emulation_response( uint32_t* data_type, void* context) { furi_assert(context); - MifareUlDevice* mf_ul_emulate = context; + MfUltralightEmulator* emulator = context; uint8_t cmd = buff_rx[0]; - uint16_t page_num = mf_ul_emulate->data.data_size / 4; + uint16_t page_num = emulator->data.data_size / 4; uint16_t tx_bytes = 0; uint16_t tx_bits = 0; bool command_parsed = false; // Check composite commands - if(mf_ul_emulate->comp_write_cmd_started) { + if(emulator->comp_write_cmd_started) { // Compatibility write is the only one composit command if(buff_rx_len == 16) { - memcpy(&mf_ul_emulate->data.data[mf_ul_emulate->comp_write_page_addr * 4], buff_rx, 4); - mf_ul_emulate->data_changed = true; + memcpy(&emulator->data.data[emulator->comp_write_page_addr * 4], buff_rx, 4); + emulator->data_changed = true; // Send ACK message buff_tx[0] = 0x0A; tx_bits = 4; *data_type = FURI_HAL_NFC_TXRX_RAW; command_parsed = true; } - mf_ul_emulate->comp_write_cmd_started = false; + emulator->comp_write_cmd_started = false; } else if(cmd == MF_UL_GET_VERSION_CMD) { - if(mf_ul_emulate->data.type != MfUltralightTypeUnknown) { - tx_bytes = sizeof(mf_ul_emulate->data.version); - memcpy(buff_tx, &mf_ul_emulate->data.version, tx_bytes); + if(emulator->data.type != MfUltralightTypeUnknown) { + tx_bytes = sizeof(emulator->data.version); + memcpy(buff_tx, &emulator->data.version, tx_bytes); *data_type = FURI_HAL_NFC_TXRX_DEFAULT; command_parsed = true; } @@ -242,28 +285,24 @@ bool mf_ul_prepare_emulation_response( if(start_page + 4 > page_num) { // Handle roll-over mechanism uint8_t end_pages_num = page_num - start_page; - memcpy(buff_tx, &mf_ul_emulate->data.data[start_page * 4], end_pages_num * 4); - memcpy( - &buff_tx[end_pages_num * 4], - mf_ul_emulate->data.data, - (4 - end_pages_num) * 4); + memcpy(buff_tx, &emulator->data.data[start_page * 4], end_pages_num * 4); + memcpy(&buff_tx[end_pages_num * 4], emulator->data.data, (4 - end_pages_num) * 4); } else { - memcpy(buff_tx, &mf_ul_emulate->data.data[start_page * 4], tx_bytes); + memcpy(buff_tx, &emulator->data.data[start_page * 4], tx_bytes); } mf_ul_protect_auth_data_on_read_command( - buff_tx, start_page, (start_page + 4), mf_ul_emulate); + buff_tx, start_page, (start_page + 4), emulator); *data_type = FURI_HAL_NFC_TXRX_DEFAULT; command_parsed = true; } } else if(cmd == MF_UL_FAST_READ_CMD) { - if(mf_ul_emulate->support_fast_read) { + if(emulator->support_fast_read) { uint8_t start_page = buff_rx[1]; uint8_t end_page = buff_rx[2]; if((start_page < page_num) && (end_page < page_num) && (start_page < (end_page + 1))) { tx_bytes = ((end_page + 1) - start_page) * 4; - memcpy(buff_tx, &mf_ul_emulate->data.data[start_page * 4], tx_bytes); - mf_ul_protect_auth_data_on_read_command( - buff_tx, start_page, end_page, mf_ul_emulate); + memcpy(buff_tx, &emulator->data.data[start_page * 4], tx_bytes); + mf_ul_protect_auth_data_on_read_command(buff_tx, start_page, end_page, emulator); *data_type = FURI_HAL_NFC_TXRX_DEFAULT; command_parsed = true; } @@ -271,8 +310,8 @@ bool mf_ul_prepare_emulation_response( } else if(cmd == MF_UL_WRITE) { uint8_t write_page = buff_rx[1]; if((write_page > 1) && (write_page < page_num - 2)) { - memcpy(&mf_ul_emulate->data.data[write_page * 4], &buff_rx[2], 4); - mf_ul_emulate->data_changed = true; + memcpy(&emulator->data.data[write_page * 4], &buff_rx[2], 4); + emulator->data_changed = true; // ACK buff_tx[0] = 0x0A; tx_bits = 4; @@ -282,8 +321,8 @@ bool mf_ul_prepare_emulation_response( } else if(cmd == MF_UL_COMP_WRITE) { uint8_t write_page = buff_rx[1]; if((write_page > 1) && (write_page < page_num - 2)) { - mf_ul_emulate->comp_write_cmd_started = true; - mf_ul_emulate->comp_write_page_addr = write_page; + emulator->comp_write_cmd_started = true; + emulator->comp_write_page_addr = write_page; // ACK buff_tx[0] = 0x0A; tx_bits = 4; @@ -293,9 +332,9 @@ bool mf_ul_prepare_emulation_response( } else if(cmd == MF_UL_READ_CNT) { uint8_t cnt_num = buff_rx[1]; if(cnt_num < 3) { - buff_tx[0] = mf_ul_emulate->data.counter[cnt_num] >> 16; - buff_tx[1] = mf_ul_emulate->data.counter[cnt_num] >> 8; - buff_tx[2] = mf_ul_emulate->data.counter[cnt_num]; + buff_tx[0] = emulator->data.counter[cnt_num] >> 16; + buff_tx[1] = emulator->data.counter[cnt_num] >> 8; + buff_tx[2] = emulator->data.counter[cnt_num]; tx_bytes = 3; *data_type = FURI_HAL_NFC_TXRX_DEFAULT; command_parsed = true; @@ -303,9 +342,9 @@ bool mf_ul_prepare_emulation_response( } else if(cmd == MF_UL_INC_CNT) { uint8_t cnt_num = buff_rx[1]; uint32_t inc = (buff_rx[2] | (buff_rx[3] << 8) | (buff_rx[4] << 16)); - if((cnt_num < 3) && (mf_ul_emulate->data.counter[cnt_num] + inc < 0x00FFFFFF)) { - mf_ul_emulate->data.counter[cnt_num] += inc; - mf_ul_emulate->data_changed = true; + if((cnt_num < 3) && (emulator->data.counter[cnt_num] + inc < 0x00FFFFFF)) { + emulator->data.counter[cnt_num] += inc; + emulator->data_changed = true; // ACK buff_tx[0] = 0x0A; tx_bits = 4; @@ -313,14 +352,14 @@ bool mf_ul_prepare_emulation_response( command_parsed = true; } } else if(cmd == MF_UL_AUTH) { - if(mf_ul_emulate->data.type >= MfUltralightTypeNTAG213) { - if(memcmp(&buff_rx[1], mf_ul_emulate->auth_data->pwd, 4) == 0) { - buff_tx[0] = mf_ul_emulate->auth_data->pack.raw[0]; - buff_tx[1] = mf_ul_emulate->auth_data->pack.raw[1]; + if(emulator->data.type >= MfUltralightTypeNTAG213) { + if(memcmp(&buff_rx[1], emulator->auth_data->pwd, 4) == 0) { + buff_tx[0] = emulator->auth_data->pack.raw[0]; + buff_tx[1] = emulator->auth_data->pack.raw[1]; tx_bytes = 2; *data_type = FURI_HAL_NFC_TXRX_DEFAULT; command_parsed = true; - } else if(!mf_ul_emulate->auth_data->pack.value) { + } else if(!emulator->auth_data->pack.value) { buff_tx[0] = 0x80; buff_tx[1] = 0x80; tx_bytes = 2; @@ -331,15 +370,15 @@ bool mf_ul_prepare_emulation_response( } else if(cmd == MF_UL_READ_SIG) { // Check 2nd byte = 0x00 - RFU if(buff_rx[1] == 0x00) { - tx_bytes = sizeof(mf_ul_emulate->data.signature); - memcpy(buff_tx, mf_ul_emulate->data.signature, tx_bytes); + tx_bytes = sizeof(emulator->data.signature); + memcpy(buff_tx, emulator->data.signature, tx_bytes); *data_type = FURI_HAL_NFC_TXRX_DEFAULT; command_parsed = true; } } else if(cmd == MF_UL_CHECK_TEARING) { uint8_t cnt_num = buff_rx[1]; if(cnt_num < 3) { - buff_tx[0] = mf_ul_emulate->data.tearing[cnt_num]; + buff_tx[0] = emulator->data.tearing[cnt_num]; tx_bytes = 1; *data_type = FURI_HAL_NFC_TXRX_DEFAULT; command_parsed = true; diff --git a/lib/nfc_protocols/mifare_ultralight.h b/lib/nfc_protocols/mifare_ultralight.h index 84447c5de..b554b75b5 100644 --- a/lib/nfc_protocols/mifare_ultralight.h +++ b/lib/nfc_protocols/mifare_ultralight.h @@ -1,8 +1,6 @@ #pragma once -#include -#include -#include +#include #define MF_UL_MAX_DUMP_SIZE 1024 @@ -62,7 +60,7 @@ typedef struct { uint8_t tearing[3]; uint16_t data_size; uint8_t data[MF_UL_MAX_DUMP_SIZE]; -} MifareUlData; +} MfUltralightData; typedef struct { uint8_t pwd[4]; @@ -70,52 +68,53 @@ typedef struct { uint8_t raw[2]; uint16_t value; } pack; -} MifareUlAuthData; +} MfUltralightAuth; typedef struct { uint8_t pages_to_read; uint8_t pages_read; bool support_fast_read; +} MfUltralightReader; + +typedef struct { + MfUltralightData data; + bool support_fast_read; bool data_changed; - MifareUlData data; - MifareUlAuthData* auth_data; bool comp_write_cmd_started; uint8_t comp_write_page_addr; -} MifareUlDevice; + MfUltralightAuth* auth_data; +} MfUltralightEmulator; bool mf_ul_check_card_type(uint8_t ATQA0, uint8_t ATQA1, uint8_t SAK); -uint16_t mf_ul_prepare_get_version(uint8_t* dest); -void mf_ul_parse_get_version_response(uint8_t* buff, MifareUlDevice* mf_ul_read); -void mf_ul_set_default_version(MifareUlDevice* mf_ul_read); +bool mf_ultralight_read_version( + FuriHalNfcTxRxContext* tx_rx, + MfUltralightReader* reader, + MfUltralightData* data); -uint16_t mf_ul_prepare_read_signature(uint8_t* dest); -void mf_ul_parse_read_signature_response(uint8_t* buff, MifareUlDevice* mf_ul_read); +bool mf_ultralight_read_pages( + FuriHalNfcTxRxContext* tx_rx, + MfUltralightReader* reader, + MfUltralightData* data); -uint16_t mf_ul_prepare_read_cnt(uint8_t* dest, uint8_t cnt_index); -void mf_ul_parse_read_cnt_response(uint8_t* buff, uint8_t cnt_index, MifareUlDevice* mf_ul_read); +bool mf_ultralight_fast_read_pages( + FuriHalNfcTxRxContext* tx_rx, + MfUltralightReader* reader, + MfUltralightData* data); -uint16_t mf_ul_prepare_inc_cnt(uint8_t* dest, uint8_t cnt_index, uint32_t value); +bool mf_ultralight_read_signature(FuriHalNfcTxRxContext* tx_rx, MfUltralightData* data); -uint16_t mf_ul_prepare_check_tearing(uint8_t* dest, uint8_t cnt_index); -void mf_ul_parse_check_tearing_response( - uint8_t* buff, - uint8_t cnt_index, - MifareUlDevice* mf_ul_read); +bool mf_ultralight_read_counters(FuriHalNfcTxRxContext* tx_rx, MfUltralightData* data); -uint16_t mf_ul_prepare_read(uint8_t* dest, uint8_t start_page); -void mf_ul_parse_read_response(uint8_t* buff, uint16_t page_addr, MifareUlDevice* mf_ul_read); +bool mf_ultralight_read_tearing_flags(FuriHalNfcTxRxContext* tx_rx, MfUltralightData* data); -uint16_t mf_ul_prepare_fast_read(uint8_t* dest, uint8_t start_page, uint8_t end_page); -void mf_ul_parse_fast_read_response( - uint8_t* buff, - uint8_t start_page, - uint8_t end_page, - MifareUlDevice* mf_ul_read); +bool mf_ul_read_card( + FuriHalNfcTxRxContext* tx_rx, + MfUltralightReader* reader, + MfUltralightData* data); -uint16_t mf_ul_prepare_write(uint8_t* dest, uint16_t page_addr, uint32_t data); +void mf_ul_prepare_emulation(MfUltralightEmulator* emulator, MfUltralightData* data); -void mf_ul_prepare_emulation(MifareUlDevice* mf_ul_emulate, MifareUlData* data); bool mf_ul_prepare_emulation_response( uint8_t* buff_rx, uint16_t buff_rx_len, From 57312961e8ced1ac51f99bdd9ce481a0350b985a Mon Sep 17 00:00:00 2001 From: hedger Date: Tue, 19 Apr 2022 22:02:37 +0300 Subject: [PATCH 4/5] [FL-2481] Renamed assets->resources; enforcing Manifest build if it does not exist (#1135) * Renamed assets->resources; enforcing Manifest build if it does not exist * Rebuild resources from CI * Added Manifest to repo - be sure to rebuild it with `make -C assets` before committing changes! * Actually added Manifest. * Keeping Manifest on assets clean * Spelling fix in Makefile --- .github/workflows/build.yml | 2 +- Makefile | 17 +- applications/updater/util/update_task.c | 2 +- applications/updater/util/update_task.h | 2 +- .../updater/util/update_task_workers.c | 3 +- assets/.gitignore | 2 +- assets/Makefile | 16 +- assets/assets.mk | 6 +- assets/resources/Manifest | 240 ++++++++++++++++++ lib/update_util/update_manifest.c | 2 +- make/rules.mk | 1 - scripts/assets.py | 13 +- scripts/dist.py | 12 +- scripts/flash.py | 2 +- scripts/flipper/assets/manifest.py | 17 +- scripts/flipper/utils/fstree.py | 38 ++- scripts/update.py | 36 +-- 17 files changed, 343 insertions(+), 68 deletions(-) create mode 100644 assets/resources/Manifest diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index b1063e0bc..db09f7541 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -76,7 +76,7 @@ jobs: with: run: | set -e - make assets_manifest + make assets_rebuild assets_manifest git diff --quiet || ( echo "Assets recompilation required."; exit 255 ) - name: 'Build the firmware in docker' diff --git a/Makefile b/Makefile index d90c4e739..ca3caa22d 100644 --- a/Makefile +++ b/Makefile @@ -79,7 +79,6 @@ ifeq ($(FORCE), 1) endif @$(MAKE) -C $(PROJECT_ROOT)/firmware -j$(NPROCS) flash - .PHONY: updater updater: @$(MAKE) -C $(PROJECT_ROOT)/firmware -j$(NPROCS) RAM_EXEC=1 all @@ -97,14 +96,16 @@ updater_package_bin: firmware_all updater @$(PROJECT_ROOT)/scripts/dist.py copy -t $(TARGET) -p firmware updater -s $(DIST_SUFFIX) --bundlever "$(VERSION_STRING)" .PHONY: updater_package -updater_package: firmware_all updater - @$(PROJECT_ROOT)/scripts/dist.py copy -t $(TARGET) -p firmware updater -s $(DIST_SUFFIX) -a assets/resources --bundlever "$(VERSION_STRING)" +updater_package: firmware_all updater assets_manifest + @$(PROJECT_ROOT)/scripts/dist.py copy -t $(TARGET) -p firmware updater -s $(DIST_SUFFIX) -r $(PROJECT_ROOT)/assets/resources --bundlever "$(VERSION_STRING)" .PHONY: assets_manifest assets_manifest: - @$(MAKE) -C $(PROJECT_ROOT)/assets clean - @$(MAKE) -C $(PROJECT_ROOT)/assets - @$(PROJECT_ROOT)/scripts/assets.py manifest assets/resources + @$(MAKE) -C $(PROJECT_ROOT)/assets manifest + +.PHONY: assets_rebuild +assets_rebuild: + @$(MAKE) -C $(PROJECT_ROOT)/assets clean all .PHONY: flash_radio flash_radio: @@ -124,8 +125,8 @@ flash_radio_fus: .PHONY: flash_radio_fus_please_i_m_not_going_to_complain flash_radio_fus_please_i_m_not_going_to_complain: - @$(PROJECT_ROOT)/scripts/flash.py core2fus 0x080EC000 --statement=AGREE_TO_LOOSE_FLIPPER_FEATURES_THAT_USES_CRYPTO_ENCLAVE $(COPRO_DIR)/stm32wb5x_FUS_fw_for_fus_0_5_3.bin - @$(PROJECT_ROOT)/scripts/flash.py core2fus 0x080EC000 --statement=AGREE_TO_LOOSE_FLIPPER_FEATURES_THAT_USES_CRYPTO_ENCLAVE $(COPRO_DIR)/stm32wb5x_FUS_fw.bin + @$(PROJECT_ROOT)/scripts/flash.py core2fus 0x080EC000 --statement=AGREE_TO_LOSE_FLIPPER_FEATURES_THAT_USE_CRYPTO_ENCLAVE $(COPRO_DIR)/stm32wb5x_FUS_fw_for_fus_0_5_3.bin + @$(PROJECT_ROOT)/scripts/flash.py core2fus 0x080EC000 --statement=AGREE_TO_LOSE_FLIPPER_FEATURES_THAT_USE_CRYPTO_ENCLAVE $(COPRO_DIR)/stm32wb5x_FUS_fw.bin @$(PROJECT_ROOT)/scripts/ob.py set .PHONY: lint diff --git a/applications/updater/util/update_task.c b/applications/updater/util/update_task.c index 04405bcfd..197d42f5d 100644 --- a/applications/updater/util/update_task.c +++ b/applications/updater/util/update_task.c @@ -19,7 +19,7 @@ static const char* update_task_stage_descr[] = { [UpdateTaskStageRadioCommit] = "Applying radio stack", [UpdateTaskStageLfsBackup] = "Backing up LFS", [UpdateTaskStageLfsRestore] = "Restoring LFS", - [UpdateTaskStageAssetsUpdate] = "Updating assets", + [UpdateTaskStageResourcesUpdate] = "Updating resources", [UpdateTaskStageCompleted] = "Completed!", [UpdateTaskStageError] = "Error", }; diff --git a/applications/updater/util/update_task.h b/applications/updater/util/update_task.h index 25650de87..2325824cb 100644 --- a/applications/updater/util/update_task.h +++ b/applications/updater/util/update_task.h @@ -23,7 +23,7 @@ typedef enum { UpdateTaskStageRadioCommit, UpdateTaskStageLfsBackup, UpdateTaskStageLfsRestore, - UpdateTaskStageAssetsUpdate, + UpdateTaskStageResourcesUpdate, UpdateTaskStageCompleted, UpdateTaskStageError, } UpdateTaskStage; diff --git a/applications/updater/util/update_task_workers.c b/applications/updater/util/update_task_workers.c index 2a22692bc..d0abbc18e 100644 --- a/applications/updater/util/update_task_workers.c +++ b/applications/updater/util/update_task_workers.c @@ -166,14 +166,13 @@ static bool update_task_post_update(UpdateTask* update_task) { .total_files = 0, .processed_files = 0, }; - update_task_set_progress(update_task, UpdateTaskStageAssetsUpdate, 0); + update_task_set_progress(update_task, UpdateTaskStageResourcesUpdate, 0); path_concat( string_get_cstr(update_task->update_path), string_get_cstr(update_task->manifest->resource_bundle), file_path); - update_task_set_progress(update_task, UpdateTaskStageProgress, 0); TarArchive* archive = tar_archive_alloc(update_task->storage); tar_archive_set_file_callback(archive, update_task_resource_unpack_cb, &progress); success = tar_archive_open(archive, string_get_cstr(file_path), TAR_OPEN_MODE_READ); diff --git a/assets/.gitignore b/assets/.gitignore index 3f30e2276..0a0acede9 100644 --- a/assets/.gitignore +++ b/assets/.gitignore @@ -1 +1 @@ -/headers \ No newline at end of file +/headers diff --git a/assets/Makefile b/assets/Makefile index 91cc06713..19d148fdb 100644 --- a/assets/Makefile +++ b/assets/Makefile @@ -3,11 +3,11 @@ PROJECT_ROOT = $(abspath $(dir $(abspath $(firstword $(MAKEFILE_LIST))))..) include $(PROJECT_ROOT)/assets/assets.mk .PHONY: all -all: icons protobuf dolphin +all: icons protobuf dolphin manifest -$(ASSETS): $(ASSETS_SOURCES) $(ASSETS_COMPILLER) +$(ASSETS): $(ASSETS_SOURCES) $(ASSETS_COMPILER) @echo "\tASSETS\t\t" $@ - @$(ASSETS_COMPILLER) icons "$(ASSETS_SOURCE_DIR)" "$(ASSETS_COMPILED_DIR)" + @$(ASSETS_COMPILER) icons "$(ASSETS_SOURCE_DIR)" "$(ASSETS_COMPILED_DIR)" .PHONY: icons icons: $(ASSETS) @@ -22,11 +22,15 @@ protobuf: $(PROTOBUF) $(DOLPHIN_EXTERNAL_OUTPUT_DIR): $(DOLPHIN_SOURCE_DIR) @echo "\tDOLPHIN blocking" - @$(ASSETS_COMPILLER) dolphin -s dolphin_blocking "$(DOLPHIN_SOURCE_DIR)/blocking" "$(DOLPHIN_INTERNAL_OUTPUT_DIR)" + @$(ASSETS_COMPILER) dolphin -s dolphin_blocking "$(DOLPHIN_SOURCE_DIR)/blocking" "$(DOLPHIN_INTERNAL_OUTPUT_DIR)" @echo "\tDOLPHIN internal" - @$(ASSETS_COMPILLER) dolphin -s dolphin_internal "$(DOLPHIN_SOURCE_DIR)/internal" "$(DOLPHIN_INTERNAL_OUTPUT_DIR)" + @$(ASSETS_COMPILER) dolphin -s dolphin_internal "$(DOLPHIN_SOURCE_DIR)/internal" "$(DOLPHIN_INTERNAL_OUTPUT_DIR)" @echo "\tDOLPHIN external" - @$(ASSETS_COMPILLER) dolphin "$(DOLPHIN_SOURCE_DIR)/external" "$(DOLPHIN_EXTERNAL_OUTPUT_DIR)" + @$(ASSETS_COMPILER) dolphin "$(DOLPHIN_SOURCE_DIR)/external" "$(DOLPHIN_EXTERNAL_OUTPUT_DIR)" + +.PHONY: manifest +manifest: + $(ASSETS_COMPILER) manifest $(RESOURCES_DIR) .PHONY: dolphin dolphin: $(DOLPHIN_EXTERNAL_OUTPUT_DIR) diff --git a/assets/assets.mk b/assets/assets.mk index 55783ec8b..18e0a244c 100644 --- a/assets/assets.mk +++ b/assets/assets.mk @@ -1,11 +1,15 @@ ASSETS_DIR := $(PROJECT_ROOT)/assets -ASSETS_COMPILLER := $(PROJECT_ROOT)/scripts/assets.py +ASSETS_COMPILER := $(PROJECT_ROOT)/scripts/assets.py ASSETS_COMPILED_DIR := $(ASSETS_DIR)/compiled ASSETS_SOURCE_DIR := $(ASSETS_DIR)/icons ASSETS_SOURCES += $(shell find $(ASSETS_SOURCE_DIR) -type f -iname '*.png' -or -iname 'frame_rate') ASSETS += $(ASSETS_COMPILED_DIR)/assets_icons.c +RESOURCES_DIR := $(ASSETS_DIR)/resources +RESOURCES_MANIFEST := $(RESOURCES_DIR)/Manifest +RESOURCES_FILES := $(shell find $(RESOURCES_DIR) ! -name Manifest -type f) + DOLPHIN_SOURCE_DIR := $(ASSETS_DIR)/dolphin DOLPHIN_INTERNAL_OUTPUT_DIR := $(ASSETS_COMPILED_DIR) DOLPHIN_EXTERNAL_OUTPUT_DIR := $(ASSETS_DIR)/resources/dolphin diff --git a/assets/resources/Manifest b/assets/resources/Manifest new file mode 100644 index 000000000..12773c00a --- /dev/null +++ b/assets/resources/Manifest @@ -0,0 +1,240 @@ +V:0 +T:1650389893 +D:badusb +D:dolphin +D:infrared +D:nfc +D:subghz +D:u2f +F:bb8ffef2d052f171760ce3dc5220cbad:1591:badusb/demo_macos.txt +F:e538ad2ce5a06ec45e1b5b24824901b1:1552:badusb/demo_windows.txt +D:dolphin/L1_Boxing_128x64 +D:dolphin/L1_Cry_128x64 +D:dolphin/L1_Furippa1_128x64 +D:dolphin/L1_Laptop_128x51 +D:dolphin/L1_Leaving_sad_128x64 +D:dolphin/L1_Mad_fist_128x64 +D:dolphin/L1_Read_books_128x64 +D:dolphin/L1_Recording_128x51 +D:dolphin/L1_Sleep_128x64 +D:dolphin/L1_Waves_128x50 +D:dolphin/L2_Furippa2_128x64 +D:dolphin/L2_Hacking_pc_128x64 +D:dolphin/L2_Soldering_128x64 +D:dolphin/L3_Furippa3_128x64 +D:dolphin/L3_Hijack_radio_128x64 +D:dolphin/L3_Lab_research_128x54 +F:d1148ab5354eaf4fa7f959589d840932:1563:dolphin/manifest.txt +F:d37be8444102ec5cde5fe3a85d55b57d:481:dolphin/L1_Boxing_128x64/frame_0.bm +F:54fb07443bc153ded9589b74d23b4263:461:dolphin/L1_Boxing_128x64/frame_1.bm +F:e007afe130d699c715b99ce8e5b407bd:531:dolphin/L1_Boxing_128x64/frame_2.bm +F:a999a9a6c76c66158f1aa5ccb56de7c9:437:dolphin/L1_Boxing_128x64/frame_3.bm +F:ec6af9cb451ab16c0fa62e95e8134b49:459:dolphin/L1_Boxing_128x64/frame_4.bm +F:2aa0c1e7bf1131b9dc172aa595ec01f2:450:dolphin/L1_Boxing_128x64/frame_5.bm +F:bbc8f750d17d156438c5cfe1122ec7f4:442:dolphin/L1_Boxing_128x64/frame_6.bm +F:f6e51ada3e3285e330714dab5b4277dd:418:dolphin/L1_Boxing_128x64/meta.txt +F:ab33a6f37209541f3db938d1cfe1706f:889:dolphin/L1_Cry_128x64/frame_0.bm +F:1b3fdeb404af0f7402caa5a5e091a8f8:911:dolphin/L1_Cry_128x64/frame_1.bm +F:4db644b173af72f3d371d2bd81f76b05:910:dolphin/L1_Cry_128x64/frame_2.bm +F:cd4c0ef67a8e514edecd9600242db068:923:dolphin/L1_Cry_128x64/frame_3.bm +F:ee02e9589e0714d3e2bc0d93aa294ccb:894:dolphin/L1_Cry_128x64/frame_4.bm +F:7703a7d9745d13b45d73ce4b86b4cdc8:940:dolphin/L1_Cry_128x64/frame_5.bm +F:ee6de6a0ed903317c4948cb445e0a9a8:915:dolphin/L1_Cry_128x64/frame_6.bm +F:a3892e45826c66f48d3d64fb81521446:934:dolphin/L1_Cry_128x64/frame_7.bm +F:680b12cc4dad722d6583b7e710bfc297:516:dolphin/L1_Cry_128x64/meta.txt +F:4911eaa7cb84ced19e5dea2af51b91a5:294:dolphin/L1_Furippa1_128x64/frame_0.bm +F:5669bee57c7b3d93a1665dd87fd5372a:325:dolphin/L1_Furippa1_128x64/frame_1.bm +F:80b48a77682b853e6236cd1c89083e6f:465:dolphin/L1_Furippa1_128x64/frame_10.bm +F:9d8ea10bf3d3831cb4a94957dc0b41c6:698:dolphin/L1_Furippa1_128x64/frame_11.bm +F:2dbb3125ea63550906fba8f7ec7b1da3:541:dolphin/L1_Furippa1_128x64/frame_12.bm +F:6a06b718957dca9caa63a4f3baa73abb:584:dolphin/L1_Furippa1_128x64/frame_13.bm +F:5450bf16c3d2fceaf5e6ea585b7ef7c1:610:dolphin/L1_Furippa1_128x64/frame_14.bm +F:535c0eca62703eb7df36f17334a6191b:719:dolphin/L1_Furippa1_128x64/frame_15.bm +F:7c03af85ade9b791755f3a4d106c2b7c:458:dolphin/L1_Furippa1_128x64/frame_16.bm +F:41b8fea16ad8705f4594e6119eade395:400:dolphin/L1_Furippa1_128x64/frame_17.bm +F:2db7fd3da5208a8e41902ae27cf41702:333:dolphin/L1_Furippa1_128x64/frame_18.bm +F:7e47428442e0f04959fc6afde979936e:351:dolphin/L1_Furippa1_128x64/frame_2.bm +F:0eb187078f169d7a852e97ecf430aea0:324:dolphin/L1_Furippa1_128x64/frame_3.bm +F:967c402971a442a5bf28eba804bb3ff4:387:dolphin/L1_Furippa1_128x64/frame_4.bm +F:175cb930fba0fc86f54a3a109b741708:390:dolphin/L1_Furippa1_128x64/frame_5.bm +F:f8c3ee1ab657549d1d00c1c72d8d2ff5:407:dolphin/L1_Furippa1_128x64/frame_6.bm +F:4911eaa7cb84ced19e5dea2af51b91a5:294:dolphin/L1_Furippa1_128x64/frame_7.bm +F:8f649ff34b224f4e564644a4494c54ed:283:dolphin/L1_Furippa1_128x64/frame_8.bm +F:3ec3c40d26bf8d3e691b1335d20d4ec0:312:dolphin/L1_Furippa1_128x64/frame_9.bm +F:ebe088426d184cf6651288accd21add6:241:dolphin/L1_Furippa1_128x64/meta.txt +F:d02fdfd1a3b89da00d2acf32bd09da80:555:dolphin/L1_Laptop_128x51/frame_0.bm +F:7e29ea503d41023fa3895d15458f106d:557:dolphin/L1_Laptop_128x51/frame_1.bm +F:eb55e0629de873f537d8412ced528eb4:560:dolphin/L1_Laptop_128x51/frame_2.bm +F:1516472ab3c140dd5bd4d089caa44747:556:dolphin/L1_Laptop_128x51/frame_3.bm +F:61172f89cf0a17bd7f978edccdeed166:560:dolphin/L1_Laptop_128x51/frame_4.bm +F:9d54913928c7e9477b6b8a43f3767621:554:dolphin/L1_Laptop_128x51/frame_5.bm +F:5243d6272bbb213e9c17af07ee011402:553:dolphin/L1_Laptop_128x51/frame_6.bm +F:aa68e0f28f117891ba0f4d7613224fc6:560:dolphin/L1_Laptop_128x51/frame_7.bm +F:9ef1935ab29fe70bbc517f4b602547d7:403:dolphin/L1_Laptop_128x51/meta.txt +F:6ce34e62c5bf4764a4163101afe63e60:514:dolphin/L1_Leaving_sad_128x64/frame_0.bm +F:19a0e0c518d222d91d24b8712ab6bb80:526:dolphin/L1_Leaving_sad_128x64/frame_1.bm +F:837bfb424c8d8a3bfbda7d6a28ba5a5c:316:dolphin/L1_Leaving_sad_128x64/frame_10.bm +F:1a69b6f63a96e0958837ea8b21db3966:294:dolphin/L1_Leaving_sad_128x64/frame_11.bm +F:c3ea827593a4563d544dfb7e99d73885:322:dolphin/L1_Leaving_sad_128x64/frame_12.bm +F:1e3842669191fe9599f830ac133e0751:542:dolphin/L1_Leaving_sad_128x64/frame_2.bm +F:9161660e6827bd776a15eefa2a8add19:557:dolphin/L1_Leaving_sad_128x64/frame_3.bm +F:d01a79fdb4f84397d82bf9927aeb71e0:488:dolphin/L1_Leaving_sad_128x64/frame_4.bm +F:316e30ef319c080fab2a79c21e526319:469:dolphin/L1_Leaving_sad_128x64/frame_5.bm +F:09a812d59b60b5fe7724057daa14ad60:499:dolphin/L1_Leaving_sad_128x64/frame_6.bm +F:9eb07b76cc864a0ce2918d68e41d4500:486:dolphin/L1_Leaving_sad_128x64/frame_7.bm +F:cf8c4cc4abbd700b096037b7ebfd0e31:403:dolphin/L1_Leaving_sad_128x64/frame_8.bm +F:889728ded689203aa82193e573912d18:317:dolphin/L1_Leaving_sad_128x64/frame_9.bm +F:2bff1f09ad1e9059a60e08990ca1d414:477:dolphin/L1_Leaving_sad_128x64/meta.txt +F:c31a882e95ed5c69fd63226db2188710:520:dolphin/L1_Mad_fist_128x64/frame_0.bm +F:740326828f6ba6e29373943ba835e77f:540:dolphin/L1_Mad_fist_128x64/frame_1.bm +F:0c9693dda040fd73ca6d773a10924bd8:542:dolphin/L1_Mad_fist_128x64/frame_10.bm +F:425c1d101debd1e9502db2628640b704:505:dolphin/L1_Mad_fist_128x64/frame_11.bm +F:aa576f7dbd14ec682f6c50314165fb14:501:dolphin/L1_Mad_fist_128x64/frame_12.bm +F:712335eabefb8c7bb7fb2f4301419c10:500:dolphin/L1_Mad_fist_128x64/frame_13.bm +F:b6e11711ea4dcc2e64f267d888f91baf:515:dolphin/L1_Mad_fist_128x64/frame_2.bm +F:61bdd22a2b1e67efe093b6acf7dfadce:538:dolphin/L1_Mad_fist_128x64/frame_3.bm +F:20ae06a3ce7a07656e578edb024e2b3f:512:dolphin/L1_Mad_fist_128x64/frame_4.bm +F:45cf2bd55365a7328df39fe98a496cc9:519:dolphin/L1_Mad_fist_128x64/frame_5.bm +F:4b8840eebb3a4a1ead69a7130816047e:524:dolphin/L1_Mad_fist_128x64/frame_6.bm +F:0de4497a5fbf80cc93e523465c5e3122:515:dolphin/L1_Mad_fist_128x64/frame_7.bm +F:32d8ddeb19bfa415fe283666b1e323a2:517:dolphin/L1_Mad_fist_128x64/frame_8.bm +F:a42a0578c2d0411500fb3485a3beb536:526:dolphin/L1_Mad_fist_128x64/frame_9.bm +F:10a521c78168a5928c859494e2a61cd2:349:dolphin/L1_Mad_fist_128x64/meta.txt +F:61565b7be9a69a60ce2dbae0273df347:653:dolphin/L1_Read_books_128x64/frame_0.bm +F:cf5a2d423540e3af37e789d70c9c1fbf:653:dolphin/L1_Read_books_128x64/frame_1.bm +F:c91935861979d024e6637b8810889878:650:dolphin/L1_Read_books_128x64/frame_2.bm +F:0c007a30f396f3e7a0ded2b24080357d:646:dolphin/L1_Read_books_128x64/frame_3.bm +F:323a52816dd79d6d3186f451e26e06ad:650:dolphin/L1_Read_books_128x64/frame_4.bm +F:494f27958f4cea9b94d09cf27725c5cd:652:dolphin/L1_Read_books_128x64/frame_5.bm +F:a6a7491fe80255e1745c9f293da52805:646:dolphin/L1_Read_books_128x64/frame_6.bm +F:238497e6643fd491cd6002e98c615c05:647:dolphin/L1_Read_books_128x64/frame_7.bm +F:300651e8f53d9a29ae38d4b9292c73cf:643:dolphin/L1_Read_books_128x64/frame_8.bm +F:3d9568deeff646b677092902a98f9ceb:325:dolphin/L1_Read_books_128x64/meta.txt +F:2aba555567ab70cff003ded4138c6721:663:dolphin/L1_Recording_128x51/frame_0.bm +F:8456c6e86825957e5662e2f08eb6c116:657:dolphin/L1_Recording_128x51/frame_1.bm +F:2e4a1aca5afa5a6ab254884210875eb4:629:dolphin/L1_Recording_128x51/frame_10.bm +F:9f1cf96598e3d935879b1d0c97705778:659:dolphin/L1_Recording_128x51/frame_11.bm +F:409abfeca974e5649affcd1faafea988:628:dolphin/L1_Recording_128x51/frame_2.bm +F:66b2a5abf05acbf79f9943e01b8b8cec:654:dolphin/L1_Recording_128x51/frame_3.bm +F:d55c5ed28c2ff48f42ab30b420d64fa3:662:dolphin/L1_Recording_128x51/frame_4.bm +F:2ce12d8cfdd953c9dadb9459c580a320:622:dolphin/L1_Recording_128x51/frame_5.bm +F:da631e3837fcdf3ee9e6abdf17fb764b:664:dolphin/L1_Recording_128x51/frame_6.bm +F:604a7cdac2491c9bc2e88b9e91c99dcc:626:dolphin/L1_Recording_128x51/frame_7.bm +F:fc94649dc98244dd9a0ab7fe62721d3c:663:dolphin/L1_Recording_128x51/frame_8.bm +F:b2475ab8ee26cbd9a403ee603520bd35:661:dolphin/L1_Recording_128x51/frame_9.bm +F:a7c2b3b420706712149cc2426c68df4f:219:dolphin/L1_Recording_128x51/meta.txt +F:9858fd34b55cebcb9be50c5710212a13:580:dolphin/L1_Sleep_128x64/frame_0.bm +F:e47ef8c846083b8fde028b1724861444:589:dolphin/L1_Sleep_128x64/frame_1.bm +F:9749bd05b47fd07cc3a41ab201f86bf4:582:dolphin/L1_Sleep_128x64/frame_2.bm +F:edf11266b20b846ace622e41cd36906b:597:dolphin/L1_Sleep_128x64/frame_3.bm +F:8fbb96a9d809d85fa6bad931fe4e6fe2:510:dolphin/L1_Sleep_128x64/meta.txt +F:283b41f1b2c581c510ff176293b7288a:443:dolphin/L1_Waves_128x50/frame_0.bm +F:c9fc5127e1d8a4217b6b177716725ba0:448:dolphin/L1_Waves_128x50/frame_1.bm +F:8e0797bf26d5d8d3cbeb99798c222b80:463:dolphin/L1_Waves_128x50/frame_2.bm +F:da02b1deb3119b31f2b8f182d5bf3242:472:dolphin/L1_Waves_128x50/frame_3.bm +F:8e6fb4133acbda7e5bb9adad0aed306c:620:dolphin/L1_Waves_128x50/meta.txt +F:be80d2fa903e3250b69c063a1eef0621:350:dolphin/L2_Furippa2_128x64/frame_0.bm +F:9e628f5e154f12d6c57b13befed1f5f6:385:dolphin/L2_Furippa2_128x64/frame_1.bm +F:80b48a77682b853e6236cd1c89083e6f:465:dolphin/L2_Furippa2_128x64/frame_10.bm +F:9d8ea10bf3d3831cb4a94957dc0b41c6:698:dolphin/L2_Furippa2_128x64/frame_11.bm +F:2dbb3125ea63550906fba8f7ec7b1da3:541:dolphin/L2_Furippa2_128x64/frame_12.bm +F:6a06b718957dca9caa63a4f3baa73abb:584:dolphin/L2_Furippa2_128x64/frame_13.bm +F:5450bf16c3d2fceaf5e6ea585b7ef7c1:610:dolphin/L2_Furippa2_128x64/frame_14.bm +F:e3c92103f403857b502081d3b058e53a:740:dolphin/L2_Furippa2_128x64/frame_15.bm +F:432669d796bbf7be1d14f5b7db036a92:533:dolphin/L2_Furippa2_128x64/frame_16.bm +F:53485c6b465c80a1ce8ddf03c4976039:451:dolphin/L2_Furippa2_128x64/frame_17.bm +F:333b75b16c088428a28259c931630fb9:397:dolphin/L2_Furippa2_128x64/frame_18.bm +F:ed02d68380382361f3f01cbf01d13b0c:402:dolphin/L2_Furippa2_128x64/frame_2.bm +F:b0ba042d7b60dc5681182b1d4005f0a2:374:dolphin/L2_Furippa2_128x64/frame_3.bm +F:518a84fa5a4e9e7f84246d5d82e87f15:440:dolphin/L2_Furippa2_128x64/frame_4.bm +F:9b7b0ae6f4f55d30cb43b0465216aa25:449:dolphin/L2_Furippa2_128x64/frame_5.bm +F:03b153949b0dae2efe1fc5f0dc57a0ef:466:dolphin/L2_Furippa2_128x64/frame_6.bm +F:be80d2fa903e3250b69c063a1eef0621:350:dolphin/L2_Furippa2_128x64/frame_7.bm +F:a8433f451cf3efc4ce2fb04a38c1f84f:319:dolphin/L2_Furippa2_128x64/frame_8.bm +F:d32a11bf9779d57191c1e59fe69cf83d:317:dolphin/L2_Furippa2_128x64/frame_9.bm +F:ebe088426d184cf6651288accd21add6:241:dolphin/L2_Furippa2_128x64/meta.txt +F:af4ec0085c29732085c51b18dc97bc27:543:dolphin/L2_Hacking_pc_128x64/frame_0.bm +F:eb141965fb6fb9f8b28766bac92abe1a:545:dolphin/L2_Hacking_pc_128x64/frame_1.bm +F:f7b33d3541dab08aaf4e8375e262b982:548:dolphin/L2_Hacking_pc_128x64/frame_2.bm +F:03634d90c54fd235aa76c0f9f794c80b:608:dolphin/L2_Hacking_pc_128x64/frame_3.bm +F:4c77406302f3fb74f8bdba568097082a:609:dolphin/L2_Hacking_pc_128x64/frame_4.bm +F:b0d1783358094534ac95b3455124d5fe:409:dolphin/L2_Hacking_pc_128x64/meta.txt +F:584c92e6fb15e99389b84d567e6d4d02:699:dolphin/L2_Soldering_128x64/frame_0.bm +F:3fa01b93460379204b6d14f43573b4f3:688:dolphin/L2_Soldering_128x64/frame_1.bm +F:6fad29757d4b7231b1d0ec53d0529b45:699:dolphin/L2_Soldering_128x64/frame_10.bm +F:e82c83e5a03abf4f6a1efd0a0f1ca33a:689:dolphin/L2_Soldering_128x64/frame_2.bm +F:7f9f310e22ef85af225dd1aefa2c47ba:689:dolphin/L2_Soldering_128x64/frame_3.bm +F:1ff31af6f90f07c0cdfa3283f52a5adc:693:dolphin/L2_Soldering_128x64/frame_4.bm +F:1a8f25aff949860cc6ffc79b4f48d5dd:696:dolphin/L2_Soldering_128x64/frame_5.bm +F:dbaa75feb8aebaf9b1cc5201c29952b8:712:dolphin/L2_Soldering_128x64/frame_6.bm +F:ee356bd981fba90c402d8e08d3015792:732:dolphin/L2_Soldering_128x64/frame_7.bm +F:09d5c5a685df606562d407bb9dac798e:705:dolphin/L2_Soldering_128x64/frame_8.bm +F:5451816e73bad029b3b9f3f55d294582:698:dolphin/L2_Soldering_128x64/frame_9.bm +F:c38ffad11987faf5ba6e363ead705e78:319:dolphin/L2_Soldering_128x64/meta.txt +F:2e083023ab65d1f99bba71f9aae6db9a:398:dolphin/L3_Furippa3_128x64/frame_0.bm +F:8cf20e07d84fd6a1157ba932beca70ea:438:dolphin/L3_Furippa3_128x64/frame_1.bm +F:018344c951691b7b1d77c1c6729d3e42:559:dolphin/L3_Furippa3_128x64/frame_10.bm +F:07008e2508064ab7a8467802472a9803:728:dolphin/L3_Furippa3_128x64/frame_11.bm +F:2dbb3125ea63550906fba8f7ec7b1da3:541:dolphin/L3_Furippa3_128x64/frame_12.bm +F:6a06b718957dca9caa63a4f3baa73abb:584:dolphin/L3_Furippa3_128x64/frame_13.bm +F:5450bf16c3d2fceaf5e6ea585b7ef7c1:610:dolphin/L3_Furippa3_128x64/frame_14.bm +F:e333224a4bed87b606df57a252ed4887:741:dolphin/L3_Furippa3_128x64/frame_15.bm +F:a20a6abfbd66fc3f92c66adacc4444a3:559:dolphin/L3_Furippa3_128x64/frame_16.bm +F:c1e051dce6b90e4f69b4792d0356a6b3:492:dolphin/L3_Furippa3_128x64/frame_17.bm +F:377f3621507c6590120cbc1c8ca92999:445:dolphin/L3_Furippa3_128x64/frame_18.bm +F:81f09c0fcd2bddb8a107a199e7149230:463:dolphin/L3_Furippa3_128x64/frame_2.bm +F:ed7fd1ada1070493462c1899f7372baf:424:dolphin/L3_Furippa3_128x64/frame_3.bm +F:e5fb2cdc4e08d6abff3191d37a1007ed:499:dolphin/L3_Furippa3_128x64/frame_4.bm +F:923a05250e5a93c7db7bbbf48448d164:504:dolphin/L3_Furippa3_128x64/frame_5.bm +F:1e9628db28a9a908c4a4b24cb16c5d20:521:dolphin/L3_Furippa3_128x64/frame_6.bm +F:2e083023ab65d1f99bba71f9aae6db9a:398:dolphin/L3_Furippa3_128x64/frame_7.bm +F:f1ec6e12daba9490f9e2e0e308ae3f83:419:dolphin/L3_Furippa3_128x64/frame_8.bm +F:106997120ad4cd23bd51e6f26bd7d74d:435:dolphin/L3_Furippa3_128x64/frame_9.bm +F:ebe088426d184cf6651288accd21add6:241:dolphin/L3_Furippa3_128x64/meta.txt +F:42970030123b2468984785fea7c60318:524:dolphin/L3_Hijack_radio_128x64/frame_0.bm +F:491c6d8ef21e48ca0f6b5fbd269c820b:527:dolphin/L3_Hijack_radio_128x64/frame_1.bm +F:ff499c8716c5f7fc1110a5ee82bda20c:550:dolphin/L3_Hijack_radio_128x64/frame_10.bm +F:ee39d82d6efc6a6992d19b6d75a6c509:572:dolphin/L3_Hijack_radio_128x64/frame_11.bm +F:5d14e8cb9d67bf8f597d6c749d07a135:539:dolphin/L3_Hijack_radio_128x64/frame_12.bm +F:9461004b75a34a36097668159c4cabe6:579:dolphin/L3_Hijack_radio_128x64/frame_13.bm +F:c925d4b1dff9c81463944cf930d7da8d:526:dolphin/L3_Hijack_radio_128x64/frame_2.bm +F:f98ed80cfab3a94b580be81654401c89:529:dolphin/L3_Hijack_radio_128x64/frame_3.bm +F:97ba548c27732be9e05fb8f7be8204ce:571:dolphin/L3_Hijack_radio_128x64/frame_4.bm +F:524932eb2391057fc1dea7237c7086e3:574:dolphin/L3_Hijack_radio_128x64/frame_5.bm +F:8eb9672f719926ac9c4c158575f388cd:524:dolphin/L3_Hijack_radio_128x64/frame_6.bm +F:7ca93fbab93bc278d4a11089d624a07b:655:dolphin/L3_Hijack_radio_128x64/frame_7.bm +F:37b4368f0b7235f3a7347bf499541666:645:dolphin/L3_Hijack_radio_128x64/frame_8.bm +F:ea9c3d7bab4756c2916369d5e130fa71:611:dolphin/L3_Hijack_radio_128x64/frame_9.bm +F:8583743f18a12ff647d3478e7aebdad6:230:dolphin/L3_Hijack_radio_128x64/meta.txt +F:f5f02a9df03bba734bdb7ed3297795f0:611:dolphin/L3_Lab_research_128x54/frame_0.bm +F:8f9655ad286464159443922d00e45620:614:dolphin/L3_Lab_research_128x54/frame_1.bm +F:7793b1bc107d4ea2e311e92dc16bf946:576:dolphin/L3_Lab_research_128x54/frame_10.bm +F:f24b8409f9dc770f3845424fe0ab489e:585:dolphin/L3_Lab_research_128x54/frame_11.bm +F:4ea93c4482dac43f40b67cc308f21e6d:571:dolphin/L3_Lab_research_128x54/frame_12.bm +F:cf3bb68dc78c568db22f37057a9fdd66:615:dolphin/L3_Lab_research_128x54/frame_13.bm +F:79719219aaebc95ea525def9173cabf5:618:dolphin/L3_Lab_research_128x54/frame_2.bm +F:05572cfd756704acd6ce9d6c15d03fc0:608:dolphin/L3_Lab_research_128x54/frame_3.bm +F:a26604a0d5427d5cf62a7a911a68b16c:615:dolphin/L3_Lab_research_128x54/frame_4.bm +F:9edc345fe53017970f93dc680818e63e:618:dolphin/L3_Lab_research_128x54/frame_5.bm +F:cf3bb68dc78c568db22f37057a9fdd66:615:dolphin/L3_Lab_research_128x54/frame_6.bm +F:5442895c85f769349288aa3df0990f9d:585:dolphin/L3_Lab_research_128x54/frame_7.bm +F:33b8fde22f34ef556b64b77164bc19b0:578:dolphin/L3_Lab_research_128x54/frame_8.bm +F:f267f0654781049ca323b11bb4375519:581:dolphin/L3_Lab_research_128x54/frame_9.bm +F:41106c0cbc5144f151b2b2d3daaa0527:727:dolphin/L3_Lab_research_128x54/meta.txt +D:infrared/assets +F:5b16e1a59daf3ef1d0fc95b3b5596d67:74300:infrared/assets/tv.ir +D:nfc/assets +F:c6826a621d081d68309e4be424d3d974:4715:nfc/assets/aid.nfc +F:86efbebdf41bb6bf15cc51ef88f069d5:2565:nfc/assets/country_code.nfc +F:41b4f08774249014cb8d3dffa5f5c07d:1757:nfc/assets/currency_code.nfc +F:c60e862919731b0bd538a1001bbc1098:17453:nfc/assets/mf_classic_dict.nfc +D:subghz/assets +F:dda1ef895b8a25fde57c874feaaef997:650:subghz/assets/came_atomo +F:610a0ffa2479a874f2060eb2348104c5:2712:subghz/assets/keeloq_mfcodes +F:9214f9c10463b746a27e82ce0b96e040:465:subghz/assets/keeloq_mfcodes_user +F:653bd8d349055a41e1152e557d4a52d3:202:subghz/assets/nice_flor_s +F:00e967e5c558e44a0651bb821d5cf1d0:414:subghz/assets/setting_frequency_analyzer_user +F:16e8c7cb4a13f26ea55b2b0a59f9cc7a:554:subghz/assets/setting_user +D:u2f/assets +F:7e11e688e39034bbb9d88410044795e1:365:u2f/assets/cert.der +F:f60b88c20ed479ed9684e249f7134618:264:u2f/assets/cert_key.u2f diff --git a/lib/update_util/update_manifest.c b/lib/update_util/update_manifest.c index 5ec942c89..3d9ec9c39 100644 --- a/lib/update_util/update_manifest.c +++ b/lib/update_util/update_manifest.c @@ -13,7 +13,7 @@ #define MANIFEST_KEY_RADIO_ADDRESS "Radio address" #define MANIFEST_KEY_RADIO_VERSION "Radio version" #define MANIFEST_KEY_RADIO_CRC "Radio CRC" -#define MANIFEST_KEY_ASSETS_FILE "Assets" +#define MANIFEST_KEY_ASSETS_FILE "Resources" UpdateManifest* update_manifest_alloc() { UpdateManifest* update_manifest = malloc(sizeof(UpdateManifest)); diff --git a/make/rules.mk b/make/rules.mk index e907b0eb8..32e525b64 100644 --- a/make/rules.mk +++ b/make/rules.mk @@ -86,7 +86,6 @@ $(OBJ_DIR)/upload: $(OBJ_DIR)/$(PROJECT).bin dfu-util -d 0483:df11 -D $(OBJ_DIR)/$(PROJECT).bin -a 0 -s $(FLASH_ADDRESS) $(DFU_OPTIONS) touch $@ - .PHONY: flash flash: $(OBJ_DIR)/flash diff --git a/scripts/assets.py b/scripts/assets.py index 3d4556460..bb7b493d6 100755 --- a/scripts/assets.py +++ b/scripts/assets.py @@ -203,15 +203,12 @@ class Main(App): manifest_file = os.path.join(directory_path, "Manifest") old_manifest = Manifest() if os.path.exists(manifest_file): - self.logger.info( - f"old manifest is present, loading for compare and removing file" - ) + self.logger.info("old manifest is present, loading for compare") old_manifest.load(manifest_file) - os.unlink(manifest_file) self.logger.info(f'Creating new Manifest for directory "{directory_path}"') new_manifest = Manifest() new_manifest.create(directory_path) - new_manifest.save(manifest_file) + self.logger.info(f"Comparing new manifest with old") only_in_old, changed, only_in_new = Manifest.compare(old_manifest, new_manifest) for record in only_in_old: @@ -220,6 +217,12 @@ class Main(App): self.logger.info(f"Changed: {record}") for record in only_in_new: self.logger.info(f"Only in new: {record}") + if any((only_in_old, changed, only_in_new)): + self.logger.warning("Manifests are different, updating") + new_manifest.save(manifest_file) + else: + self.logger.info("Manifest is up-to-date!") + self.logger.info(f"Complete") return 0 diff --git a/scripts/dist.py b/scripts/dist.py index 541c386ee..de1a02c8a 100755 --- a/scripts/dist.py +++ b/scripts/dist.py @@ -18,7 +18,7 @@ class Main(App): self.parser_copy.add_argument("-t", dest="target", required=True) self.parser_copy.add_argument("-p", dest="projects", nargs="+", required=True) self.parser_copy.add_argument("-s", dest="suffix", required=True) - self.parser_copy.add_argument("-a", dest="assets", required=False) + self.parser_copy.add_argument("-r", dest="resources", required=False) self.parser_copy.add_argument( "--bundlever", dest="version", @@ -79,16 +79,16 @@ class Main(App): self.args.version, "-t", self.args.target, - "-dfu", + "--dfu", self.get_dist_filepath(self.get_project_filename("firmware", "dfu")), - "-stage", + "--stage", self.get_dist_filepath(self.get_project_filename("updater", "bin")), ] - if self.args.assets: + if self.args.resources: bundle_args.extend( ( - "-a", - self.args.assets, + "-r", + self.args.resources, ) ) self.logger.info( diff --git a/scripts/flash.py b/scripts/flash.py index 170d43118..cc5c5e179 100755 --- a/scripts/flash.py +++ b/scripts/flash.py @@ -8,7 +8,7 @@ import os from flipper.app import App from flipper.cube import CubeProgrammer -STATEMENT = "AGREE_TO_LOOSE_FLIPPER_FEATURES_THAT_USES_CRYPTO_ENCLAVE" +STATEMENT = "AGREE_TO_LOSE_FLIPPER_FEATURES_THAT_USE_CRYPTO_ENCLAVE" class Main(App): diff --git a/scripts/flipper/assets/manifest.py b/scripts/flipper/assets/manifest.py index c2962e7c3..103f07b6b 100644 --- a/scripts/flipper/assets/manifest.py +++ b/scripts/flipper/assets/manifest.py @@ -18,10 +18,10 @@ class ManifestRecord: def toLine(self): raise NotImplementedError - def _unpack(self, manifest, key, type): + def _unpack(self, manifest, key, nodetype): key, value = manifest.readline().split(":", 1) assert key == key - return type(value) + return nodetype(value) MANIFEST_TAGS_RECORDS = {} @@ -94,7 +94,7 @@ class ManifestRecordFile(ManifestRecord): @staticmethod def fromLine(line): data = line.split(":", 3) - return ManifestRecordFile(data[2], data[0], data[1]) + return ManifestRecordFile(data[2], data[0], int(data[1])) def toLine(self): return f"{self.tag}:{self.md5}:{self.size}:{self.path}\n" @@ -133,7 +133,7 @@ class Manifest: def addFile(self, path, md5, size): self.records.append(ManifestRecordFile(path, md5, size)) - def create(self, directory_path): + def create(self, directory_path, ignore_files=["Manifest"]): for root, dirs, files in os.walk(directory_path): relative_root = root.replace(directory_path, "", 1) if relative_root.startswith("/"): @@ -141,13 +141,16 @@ class Manifest: # process directories for dir in dirs: relative_dir_path = os.path.join(relative_root, dir) - self.logger.info(f'Adding directory: "{relative_dir_path}"') + self.logger.debug(f'Adding directory: "{relative_dir_path}"') self.addDirectory(relative_dir_path) # Process files for file in files: relative_file_path = os.path.join(relative_root, file) + if file in ignore_files: + self.logger.info(f'Skipping file "{relative_file_path}"') + continue full_file_path = os.path.join(root, file) - self.logger.info(f'Adding file: "{relative_file_path}"') + self.logger.debug(f'Adding file: "{relative_file_path}"') self.addFile( relative_file_path, file_md5(full_file_path), @@ -155,7 +158,7 @@ class Manifest: ) def toFsTree(self): - root = FsNode("", FsNode.Type.Directory) + root = FsNode("", FsNode.NodeType.Directory) for record in self.records: if isinstance(record, ManifestRecordDirectory): root.addDirectory(record.path) diff --git a/scripts/flipper/utils/fstree.py b/scripts/flipper/utils/fstree.py index c42b4aa63..206a1d997 100644 --- a/scripts/flipper/utils/fstree.py +++ b/scripts/flipper/utils/fstree.py @@ -3,13 +3,13 @@ from collections import OrderedDict class FsNode: - class Type(Enum): + class NodeType(Enum): File = 0 Directory = 1 - def __init__(self, name: str, type: "FsNode.Type", **kwargs): + def __init__(self, name: str, nodetype: "FsNode.Type", **kwargs): self.name = name - self.type = type + self.nodetype = nodetype self.data = kwargs self.parent = None self.children = OrderedDict() @@ -25,7 +25,7 @@ class FsNode: parent_node = self.traverse(fragments) if not parent_node: raise Exception(f"No parent node found for: {path}") - parent_node.addChild(FsNode(name, FsNode.Type.Directory)) + parent_node.addChild(FsNode(name, FsNode.NodeType.Directory)) def addFile(self, path, md5, size): fragments = path.split("/") @@ -34,7 +34,7 @@ class FsNode: parent_node = self.traverse(fragments) if not parent_node: raise Exception(f"No parent node found for: {path}") - parent_node.addChild(FsNode(name, FsNode.Type.File, md5=md5, size=size)) + parent_node.addChild(FsNode(name, FsNode.NodeType.File, md5=md5, size=size)) def getChild(self, name): return self.children[name] @@ -58,19 +58,37 @@ class FsNode: def dump(self): ret = {} ret["name"] = (self.name,) - ret["type"] = (self.type,) + ret["type"] = (self.nodetype,) ret["path"] = (self.getPath(),) if len(self.children): ret["children"] = [node.dump() for node in self.children.values()] return ret +def walk_nodes(node: FsNode): + yield node + for child in node.children.values(): + yield from walk_nodes(child) + + +# Returns filenames: [only_in_left], [changed], [only_in_right] def compare_fs_trees(left: FsNode, right: FsNode): # import pprint # pprint.pprint(left.dump()) # pprint.pprint(right.dump()) + left_dict = dict((node.getPath(), node) for node in walk_nodes(left)) + right_dict = dict((node.getPath(), node) for node in walk_nodes(right)) - only_in_left = [] - changed = [] - only_in_right = [] - return [], [], [] + left_names = set(left_dict.keys()) + right_names = set(right_dict.keys()) + common_names = left_names.intersection(right_names) + + return ( + list(left_names - right_names), + list( + name + for name in common_names + if left_dict[name].data != right_dict[name].data + ), + list(right_names - left_names), + ) diff --git a/scripts/update.py b/scripts/update.py index 187c9288b..25ae2733a 100755 --- a/scripts/update.py +++ b/scripts/update.py @@ -10,8 +10,12 @@ import tarfile class Main(App): + UPDATE_MANIFEST_NAME = "update.fuf" + # No compression, plain tar - ASSET_TAR_MODE = "w:" + RESOURCE_TAR_MODE = "w:" + RESOURCE_TAR_FORMAT = tarfile.USTAR_FORMAT + RESOURCE_FILE_NAME = "resources.tar" def init(self): self.subparsers = self.parser.add_subparsers(help="sub-command help") @@ -24,17 +28,17 @@ class Main(App): self.parser_generate.add_argument("-d", dest="directory", required=True) self.parser_generate.add_argument("-v", dest="version", required=True) self.parser_generate.add_argument("-t", dest="target", required=True) - self.parser_generate.add_argument("-dfu", dest="dfu", required=False) - self.parser_generate.add_argument("-a", dest="assets", required=False) - self.parser_generate.add_argument("-stage", dest="stage", required=True) + self.parser_generate.add_argument("--dfu", dest="dfu", required=False) + self.parser_generate.add_argument("-r", dest="resources", required=False) + self.parser_generate.add_argument("--stage", dest="stage", required=True) self.parser_generate.add_argument( - "-radio", dest="radiobin", default="", required=False + "--radio", dest="radiobin", default="", required=False ) self.parser_generate.add_argument( - "-radioaddr", dest="radioaddr", required=False + "--radioaddr", dest="radioaddr", required=False ) self.parser_generate.add_argument( - "-radiover", dest="radioversion", required=False + "--radiover", dest="radioversion", required=False ) self.parser_generate.set_defaults(func=self.generate) @@ -43,7 +47,7 @@ class Main(App): stage_basename = basename(self.args.stage) dfu_basename = basename(self.args.dfu) radiobin_basename = basename(self.args.radiobin) - assets_basename = "" + resources_basename = "" if not exists(self.args.directory): os.makedirs(self.args.directory) @@ -54,10 +58,10 @@ class Main(App): shutil.copyfile( self.args.radiobin, join(self.args.directory, radiobin_basename) ) - if self.args.assets: - assets_basename = "assets.tar" - self.package_assets( - self.args.assets, join(self.args.directory, assets_basename) + if self.args.resources: + resources_basename = self.RESOURCE_FILE_NAME + self.package_resources( + self.args.resources, join(self.args.directory, resources_basename) ) file = FlipperFormatFile() @@ -75,14 +79,14 @@ class Main(App): file.writeKey("Radio CRC", self.int2ffhex(self.crc(self.args.radiobin))) else: file.writeKey("Radio CRC", self.int2ffhex(0)) - file.writeKey("Assets", assets_basename) - file.save(join(self.args.directory, "update.fuf")) + file.writeKey("Resources", resources_basename) + file.save(join(self.args.directory, self.UPDATE_MANIFEST_NAME)) return 0 - def package_assets(self, srcdir: str, dst_name: str): + def package_resources(self, srcdir: str, dst_name: str): with tarfile.open( - dst_name, self.ASSET_TAR_MODE, format=tarfile.USTAR_FORMAT + dst_name, self.RESOURCE_TAR_MODE, format=self.RESOURCE_TAR_FORMAT ) as tarball: tarball.add(srcdir, arcname="") From 9351076c89cad62e8a33fd2e809e7e81eaa37fca Mon Sep 17 00:00:00 2001 From: gornekich Date: Tue, 19 Apr 2022 22:23:50 +0300 Subject: [PATCH 5/5] [FL-2475] Text Box add three dots trim option (#1136) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * introduce text box debug application * text box: add strip to dots option * applications: update text box usage Co-authored-by: あく --- applications/applications.c | 5 + applications/applications.mk | 6 + .../archive/scenes/archive_scene_delete.c | 3 +- applications/debug_tools/text_box_test.c | 126 ++++++++++++++++++ applications/gui/elements.c | 55 ++++---- applications/gui/elements.h | 26 ++-- applications/gui/modules/widget.c | 7 +- applications/gui/modules/widget.h | 26 ++-- .../widget_elements/widget_element_i.h | 3 +- .../widget_elements/widget_element_text_box.c | 8 +- .../scene/ibutton_scene_delete_confirm.cpp | 2 +- .../ibutton/scene/ibutton_scene_info.cpp | 2 +- applications/nfc/scenes/nfc_scene_delete.c | 3 +- .../nfc/scenes/nfc_scene_device_info.c | 2 +- .../nfc/scenes/nfc_scene_emulate_uid.c | 2 +- .../subghz/scenes/subghz_scene_delete_raw.c | 2 +- applications/subghz/views/subghz_read_raw.c | 10 +- 17 files changed, 226 insertions(+), 62 deletions(-) create mode 100644 applications/debug_tools/text_box_test.c mode change 100755 => 100644 applications/gui/modules/widget.c diff --git a/applications/applications.c b/applications/applications.c index aba50fee7..6b4c63211 100644 --- a/applications/applications.c +++ b/applications/applications.c @@ -43,6 +43,7 @@ extern int32_t usb_test_app(void* p); extern int32_t vibro_test_app(void* p); extern int32_t bt_hid_app(void* p); extern int32_t battery_test_app(void* p); +extern int32_t text_box_test_app(void* p); // Plugins extern int32_t music_player_app(void* p); @@ -304,6 +305,10 @@ const FlipperApplication FLIPPER_DEBUG_APPS[] = { #ifdef APP_BATTERY_TEST {.app = battery_test_app, .name = "Battery Test", .stack_size = 1024, .icon = NULL}, #endif + +#ifdef APP_TEXT_BOX_TEST + {.app = text_box_test_app, .name = "Text Box Test", .stack_size = 1024, .icon = NULL}, +#endif }; const size_t FLIPPER_DEBUG_APPS_COUNT = COUNT_OF(FLIPPER_DEBUG_APPS); diff --git a/applications/applications.mk b/applications/applications.mk index c6295fd80..efe6aa425 100644 --- a/applications/applications.mk +++ b/applications/applications.mk @@ -165,6 +165,12 @@ CFLAGS += -DAPP_DISPLAY_TEST SRV_GUI = 1 endif +APP_TEXT_BOX_TEST ?= 0 +ifeq ($(APP_TEXT_BOX_TEST), 1) +CFLAGS += -DAPP_TEXT_BOX_TEST +SRV_GUI = 1 +endif + APP_BATTERY_TEST ?= 0 ifeq ($(APP_BATTERY_TEST), 1) CFLAGS += -DAPP_BATTERY_TEST diff --git a/applications/archive/scenes/archive_scene_delete.c b/applications/archive/scenes/archive_scene_delete.c index e5bc5df3d..fbcba7773 100644 --- a/applications/archive/scenes/archive_scene_delete.c +++ b/applications/archive/scenes/archive_scene_delete.c @@ -33,7 +33,8 @@ void archive_scene_delete_on_enter(void* context) { char delete_str[64]; snprintf(delete_str, sizeof(delete_str), "\e#Delete %s?\e#", name); - widget_add_text_box_element(app->widget, 0, 0, 128, 23, AlignCenter, AlignCenter, delete_str); + widget_add_text_box_element( + app->widget, 0, 0, 128, 23, AlignCenter, AlignCenter, delete_str, false); view_dispatcher_switch_to_view(app->view_dispatcher, ArchiveViewWidget); } diff --git a/applications/debug_tools/text_box_test.c b/applications/debug_tools/text_box_test.c new file mode 100644 index 000000000..1c7ce18b1 --- /dev/null +++ b/applications/debug_tools/text_box_test.c @@ -0,0 +1,126 @@ +#include +#include +#include +#include + +#define TAG "TextBoxTest" + +static void text_box_center_top_secondary_128x22(Canvas* canvas) { + canvas_draw_frame(canvas, 0, 0, 128, 22); + elements_text_box(canvas, 0, 0, 128, 22, AlignCenter, AlignTop, "secondary font test", false); +} + +static void text_box_right_bottom_bold_128x22(Canvas* canvas) { + canvas_draw_frame(canvas, 0, 0, 128, 22); + elements_text_box( + canvas, 0, 0, 128, 22, AlignRight, AlignBottom, "\e#Bold font test\e#", false); +} + +static void text_box_left_center_mixed_80x50(Canvas* canvas) { + canvas_draw_frame(canvas, 0, 0, 80, 50); + elements_text_box( + canvas, + 0, + 0, + 80, + 50, + AlignLeft, + AlignCenter, + "\e#Never\e# gonna give you up\n\e!Never\e! gonna let you down", + false); +} + +static void text_box_center_center_secondary_110x44(Canvas* canvas) { + canvas_draw_frame(canvas, 4, 20, 110, 30); + elements_text_box( + canvas, + 4, + 20, + 110, + 30, + AlignCenter, + AlignCenter, + "Loooooooooooooo0000000ooong file name from happy 100500 Flipper 0wners", + true); +} + +static void (*text_box_test_render[])(Canvas* canvas) = { + text_box_center_top_secondary_128x22, + text_box_right_bottom_bold_128x22, + text_box_left_center_mixed_80x50, + text_box_center_center_secondary_110x44, +}; + +typedef struct { + uint32_t idx; +} TextBoxTestState; + +static void text_box_test_render_callback(Canvas* canvas, void* ctx) { + TextBoxTestState* state = acquire_mutex((ValueMutex*)ctx, 25); + canvas_clear(canvas); + + text_box_test_render[state->idx](canvas); + + release_mutex((ValueMutex*)ctx, state); +} + +static void text_box_test_input_callback(InputEvent* input_event, void* ctx) { + osMessageQueueId_t event_queue = ctx; + osMessageQueuePut(event_queue, input_event, 0, osWaitForever); +} + +int32_t text_box_test_app(void* p) { + osMessageQueueId_t event_queue = osMessageQueueNew(32, sizeof(InputEvent), NULL); + furi_check(event_queue); + + TextBoxTestState _state = {.idx = 0}; + + ValueMutex state_mutex; + if(!init_mutex(&state_mutex, &_state, sizeof(TextBoxTestState))) { + FURI_LOG_E(TAG, "Cannot create mutex"); + return 0; + } + + ViewPort* view_port = view_port_alloc(); + + view_port_draw_callback_set(view_port, text_box_test_render_callback, &state_mutex); + view_port_input_callback_set(view_port, text_box_test_input_callback, event_queue); + + // Open GUI and register view_port + Gui* gui = furi_record_open("gui"); + gui_add_view_port(gui, view_port, GuiLayerFullscreen); + + uint32_t test_renders_num = SIZEOF_ARRAY(text_box_test_render); + InputEvent event; + while(osMessageQueueGet(event_queue, &event, NULL, osWaitForever) == osOK) { + TextBoxTestState* state = acquire_mutex_block(&state_mutex); + + if(event.type == InputTypeShort) { + if(event.key == InputKeyRight) { + if(state->idx < test_renders_num - 1) { + state->idx++; + } + } else if(event.key == InputKeyLeft) { + if(state->idx > 0) { + state->idx--; + } + } else if(event.key == InputKeyBack) { + release_mutex(&state_mutex, state); + break; + } + } + + release_mutex(&state_mutex, state); + view_port_update(view_port); + } + + // remove & free all stuff created by app + gui_remove_view_port(gui, view_port); + view_port_free(view_port); + osMessageQueueDelete(event_queue); + delete_mutex(&state_mutex); + + furi_record_close("gui"); + + return 0; +} diff --git a/applications/gui/elements.c b/applications/gui/elements.c index 289e4d8e0..48d70b3a7 100644 --- a/applications/gui/elements.c +++ b/applications/gui/elements.c @@ -547,7 +547,8 @@ void elements_text_box( uint8_t height, Align horizontal, Align vertical, - const char* text) { + const char* text, + bool strip_to_dots) { furi_assert(canvas); ElementTextBoxLine line[ELEMENTS_MAX_LINES_NUM]; @@ -571,6 +572,7 @@ void elements_text_box( uint8_t total_height_default = 0; uint16_t i = 0; bool full_text_processed = false; + uint16_t dots_width = canvas_string_width(canvas, "..."); canvas_set_font(canvas, FontSecondary); @@ -663,31 +665,29 @@ void elements_text_box( } // Set vertical alignment for all lines - if(full_text_processed) { - if(total_height_default < height) { - if(vertical == AlignTop) { - line[0].y = y + line[0].height; - } else if(vertical == AlignCenter) { - line[0].y = y + line[0].height + (height - total_height_default) / 2; - } else if(vertical == AlignBottom) { - line[0].y = y + line[0].height + (height - total_height_default); - } - if(line_num > 1) { - for(uint8_t i = 1; i < line_num; i++) { - line[i].y = line[i - 1].y + line[i - 1].leading_default; - } - } - } else if(line_num > 1) { - uint8_t free_pixel_num = height - total_height_min; - uint8_t fill_pixel = 0; - uint8_t j = 1; + if(total_height_default < height) { + if(vertical == AlignTop) { line[0].y = y + line[0].height; - while(fill_pixel < free_pixel_num) { - line[j].y = line[j - 1].y + line[j - 1].leading_min + 1; - fill_pixel++; - j = j % (line_num - 1) + 1; + } else if(vertical == AlignCenter) { + line[0].y = y + line[0].height + (height - total_height_default) / 2; + } else if(vertical == AlignBottom) { + line[0].y = y + line[0].height + (height - total_height_default); + } + if(line_num > 1) { + for(uint8_t i = 1; i < line_num; i++) { + line[i].y = line[i - 1].y + line[i - 1].leading_default; } } + } else if(line_num > 1) { + uint8_t free_pixel_num = height - total_height_min; + uint8_t fill_pixel = 0; + uint8_t j = 1; + line[0].y = y + line[0].height; + while(fill_pixel < free_pixel_num) { + line[j].y = line[j - 1].y + line[j - 1].leading_min + 1; + fill_pixel++; + j = j % (line_num - 1) + 1; + } } // Draw line by line @@ -733,10 +733,17 @@ void elements_text_box( canvas_draw_glyph(canvas, line[i].x, line[i].y, line[i].text[j]); canvas_invert_color(canvas); } else { + if((i == line_num - 1) && strip_to_dots) { + uint8_t next_symbol_width = canvas_glyph_width(canvas, line[i].text[j]); + if(line[i].x + next_symbol_width + dots_width > x + width) { + canvas_draw_str(canvas, line[i].x, line[i].y, "..."); + break; + } + } canvas_draw_glyph(canvas, line[i].x, line[i].y, line[i].text[j]); } line[i].x += canvas_glyph_width(canvas, line[i].text[j]); } } canvas_set_font(canvas, FontSecondary); -} \ No newline at end of file +} diff --git a/applications/gui/elements.h b/applications/gui/elements.h index 33b5fc666..2b8b8d3f2 100644 --- a/applications/gui/elements.h +++ b/applications/gui/elements.h @@ -194,17 +194,18 @@ void elements_string_fit_width(Canvas* canvas, string_t string, uint8_t width); /** Draw text box element * - * @param canvas Canvas instance - * @param x x coordinate - * @param y y coordinate - * @param width width to fit text - * @param height height to fit text - * @param horizontal Align instance - * @param vertical Align instance - * @param[in] text Formatted text. The following formats are available: - * "\e#Bold text\e#" - bold font is used - * "\e*Monospaced text\e*" - monospaced font is used - * "\e#Inversed text\e#" - white text on black background + * @param canvas Canvas instance + * @param x x coordinate + * @param y y coordinate + * @param width width to fit text + * @param height height to fit text + * @param horizontal Align instance + * @param vertical Align instance + * @param[in] text Formatted text. The following formats are available: + * "\e#Bold text\e#" - bold font is used + * "\e*Monospaced text\e*" - monospaced font is used + * "\e#Inversed text\e#" - white text on black background + * @param strip_to_dots Strip text to ... if does not fit to width */ void elements_text_box( Canvas* canvas, @@ -214,7 +215,8 @@ void elements_text_box( uint8_t height, Align horizontal, Align vertical, - const char* text); + const char* text, + bool strip_to_dots); #ifdef __cplusplus } diff --git a/applications/gui/modules/widget.c b/applications/gui/modules/widget.c old mode 100755 new mode 100644 index 09729ee65..8d7acb013 --- a/applications/gui/modules/widget.c +++ b/applications/gui/modules/widget.c @@ -154,10 +154,11 @@ void widget_add_text_box_element( uint8_t height, Align horizontal, Align vertical, - const char* text) { + const char* text, + bool strip_to_dots) { furi_assert(widget); - WidgetElement* text_box_element = - widget_element_text_box_create(x, y, width, height, horizontal, vertical, text); + WidgetElement* text_box_element = widget_element_text_box_create( + x, y, width, height, horizontal, vertical, text, strip_to_dots); widget_add_element(widget, text_box_element); } diff --git a/applications/gui/modules/widget.h b/applications/gui/modules/widget.h index 98a894351..55af59d7c 100755 --- a/applications/gui/modules/widget.h +++ b/applications/gui/modules/widget.h @@ -81,17 +81,18 @@ void widget_add_string_element( /** Add Text Box Element * - * @param widget Widget instance - * @param x x coordinate - * @param y y coordinate - * @param width width to fit text - * @param height height to fit text - * @param horizontal Align instance - * @param vertical Align instance - * @param[in] text Formatted text. The following formats are available: - * "\e#Bold text\e#" - bold font is used - * "\e*Monospaced text\e*" - monospaced font is used - * "\e#Inversed text\e#" - white text on black background + * @param widget Widget instance + * @param x x coordinate + * @param y y coordinate + * @param width width to fit text + * @param height height to fit text + * @param horizontal Align instance + * @param vertical Align instance + * @param[in] text Formatted text. The following formats are available: + * "\e#Bold text\e#" - bold font is used + * "\e*Monospaced text\e*" - monospaced font is used + * "\e#Inversed text\e#" - white text on black background + * @param strip_to_dots Strip text to ... if does not fit to width */ void widget_add_text_box_element( Widget* widget, @@ -101,7 +102,8 @@ void widget_add_text_box_element( uint8_t height, Align horizontal, Align vertical, - const char* text); + const char* text, + bool strip_to_dots); /** Add Button Element * diff --git a/applications/gui/modules/widget_elements/widget_element_i.h b/applications/gui/modules/widget_elements/widget_element_i.h index d7b4e4634..bcbd4afdb 100755 --- a/applications/gui/modules/widget_elements/widget_element_i.h +++ b/applications/gui/modules/widget_elements/widget_element_i.h @@ -60,7 +60,8 @@ WidgetElement* widget_element_text_box_create( uint8_t height, Align horizontal, Align vertical, - const char* text); + const char* text, + bool strip_to_dots); /** Create button element */ WidgetElement* widget_element_button_create( diff --git a/applications/gui/modules/widget_elements/widget_element_text_box.c b/applications/gui/modules/widget_elements/widget_element_text_box.c index a4dee5f6c..4750f8f8f 100644 --- a/applications/gui/modules/widget_elements/widget_element_text_box.c +++ b/applications/gui/modules/widget_elements/widget_element_text_box.c @@ -10,6 +10,7 @@ typedef struct { Align horizontal; Align vertical; string_t text; + bool strip_to_dots; } GuiTextBoxModel; static void gui_text_box_draw(Canvas* canvas, WidgetElement* element) { @@ -26,7 +27,8 @@ static void gui_text_box_draw(Canvas* canvas, WidgetElement* element) { model->height, model->horizontal, model->vertical, - string_get_cstr(model->text)); + string_get_cstr(model->text), + model->strip_to_dots); } } @@ -46,7 +48,8 @@ WidgetElement* widget_element_text_box_create( uint8_t height, Align horizontal, Align vertical, - const char* text) { + const char* text, + bool strip_to_dots) { furi_assert(text); // Allocate and init model @@ -58,6 +61,7 @@ WidgetElement* widget_element_text_box_create( model->horizontal = horizontal; model->vertical = vertical; string_init_set_str(model->text, text); + model->strip_to_dots = strip_to_dots; // Allocate and init Element WidgetElement* gui_string = malloc(sizeof(WidgetElement)); diff --git a/applications/ibutton/scene/ibutton_scene_delete_confirm.cpp b/applications/ibutton/scene/ibutton_scene_delete_confirm.cpp index 1c96b4dfe..8e782e330 100755 --- a/applications/ibutton/scene/ibutton_scene_delete_confirm.cpp +++ b/applications/ibutton/scene/ibutton_scene_delete_confirm.cpp @@ -21,7 +21,7 @@ void iButtonSceneDeleteConfirm::on_enter(iButtonApp* app) { app->set_text_store("\e#Delete %s?\e#", ibutton_key_get_name_p(key)); widget_add_text_box_element( - widget, 0, 0, 128, 27, AlignCenter, AlignCenter, app->get_text_store()); + widget, 0, 0, 128, 27, AlignCenter, AlignCenter, app->get_text_store(), false); widget_add_button_element(widget, GuiButtonTypeLeft, "Cancel", widget_callback, app); widget_add_button_element(widget, GuiButtonTypeRight, "Delete", widget_callback, app); diff --git a/applications/ibutton/scene/ibutton_scene_info.cpp b/applications/ibutton/scene/ibutton_scene_info.cpp index ae39774f8..e51b2095f 100755 --- a/applications/ibutton/scene/ibutton_scene_info.cpp +++ b/applications/ibutton/scene/ibutton_scene_info.cpp @@ -9,7 +9,7 @@ void iButtonSceneInfo::on_enter(iButtonApp* app) { app->set_text_store("%s", ibutton_key_get_name_p(key)); widget_add_text_box_element( - widget, 0, 0, 128, 28, AlignCenter, AlignCenter, app->get_text_store()); + widget, 0, 0, 128, 28, AlignCenter, AlignCenter, app->get_text_store(), false); switch(ibutton_key_get_type(key)) { case iButtonKeyDS1990: diff --git a/applications/nfc/scenes/nfc_scene_delete.c b/applications/nfc/scenes/nfc_scene_delete.c index 29328743c..e8ba3e440 100755 --- a/applications/nfc/scenes/nfc_scene_delete.c +++ b/applications/nfc/scenes/nfc_scene_delete.c @@ -13,7 +13,8 @@ void nfc_scene_delete_on_enter(void* context) { // Setup Custom Widget view char temp_str[64]; snprintf(temp_str, sizeof(temp_str), "\e#Delete %s?\e#", nfc->dev->dev_name); - widget_add_text_box_element(nfc->widget, 0, 0, 128, 23, AlignCenter, AlignCenter, temp_str); + widget_add_text_box_element( + nfc->widget, 0, 0, 128, 23, AlignCenter, AlignCenter, temp_str, false); widget_add_button_element( nfc->widget, GuiButtonTypeLeft, "Back", nfc_scene_delete_widget_callback, nfc); widget_add_button_element( diff --git a/applications/nfc/scenes/nfc_scene_device_info.c b/applications/nfc/scenes/nfc_scene_device_info.c index 78e56c097..10851e860 100644 --- a/applications/nfc/scenes/nfc_scene_device_info.c +++ b/applications/nfc/scenes/nfc_scene_device_info.c @@ -36,7 +36,7 @@ void nfc_scene_device_info_on_enter(void* context) { (nfc->dev->format == NfcDeviceSaveFormatBankCard); // Setup Custom Widget view widget_add_text_box_element( - nfc->widget, 0, 0, 128, 22, AlignCenter, AlignTop, nfc->dev->dev_name); + nfc->widget, 0, 0, 128, 22, AlignCenter, AlignTop, nfc->dev->dev_name, false); widget_add_button_element( nfc->widget, GuiButtonTypeLeft, "Back", nfc_scene_device_info_widget_callback, nfc); if(data_display_supported) { diff --git a/applications/nfc/scenes/nfc_scene_emulate_uid.c b/applications/nfc/scenes/nfc_scene_emulate_uid.c index 3eeb5706a..362cb128a 100755 --- a/applications/nfc/scenes/nfc_scene_emulate_uid.c +++ b/applications/nfc/scenes/nfc_scene_emulate_uid.c @@ -47,7 +47,7 @@ static void nfc_scene_emulate_uid_widget_config(Nfc* nfc, bool data_received) { } string_strim(info_str); widget_add_text_box_element( - widget, 56, 43, 70, 21, AlignLeft, AlignTop, string_get_cstr(info_str)); + widget, 56, 43, 70, 21, AlignLeft, AlignTop, string_get_cstr(info_str), true); string_clear(info_str); if(data_received) { widget_add_button_element( diff --git a/applications/subghz/scenes/subghz_scene_delete_raw.c b/applications/subghz/scenes/subghz_scene_delete_raw.c index df57926c9..d24ab8d86 100644 --- a/applications/subghz/scenes/subghz_scene_delete_raw.c +++ b/applications/subghz/scenes/subghz_scene_delete_raw.c @@ -24,7 +24,7 @@ void subghz_scene_delete_raw_on_enter(void* context) { char delete_str[64]; snprintf(delete_str, sizeof(delete_str), "\e#Delete %s?\e#", subghz->file_name); widget_add_text_box_element( - subghz->widget, 0, 0, 128, 23, AlignCenter, AlignCenter, delete_str); + subghz->widget, 0, 0, 128, 23, AlignCenter, AlignCenter, delete_str, false); widget_add_string_element( subghz->widget, 38, 25, AlignLeft, AlignTop, FontSecondary, "RAW signal"); diff --git a/applications/subghz/views/subghz_read_raw.c b/applications/subghz/views/subghz_read_raw.c index c5b1f09b4..3a2612683 100644 --- a/applications/subghz/views/subghz_read_raw.c +++ b/applications/subghz/views/subghz_read_raw.c @@ -236,7 +236,15 @@ void subghz_read_raw_draw(Canvas* canvas, SubGhzReadRAWModel* model) { elements_button_center(canvas, "Send"); elements_button_right(canvas, "More"); elements_text_box( - canvas, 4, 12, 110, 44, AlignCenter, AlignCenter, string_get_cstr(model->file_name)); + canvas, + 4, + 12, + 110, + 44, + AlignCenter, + AlignCenter, + string_get_cstr(model->file_name), + true); break; case SubGhzReadRAWStatusTX: