From d2c4f15af5f79756343df95640fad404ee1af6f8 Mon Sep 17 00:00:00 2001 From: Nikolay Minaylov Date: Wed, 2 Feb 2022 17:27:33 +0300 Subject: [PATCH 1/3] [FL-2226] BadUSB, U2F: missing assets error (#979) * badusb, u2f: showing error screen if assets are missing * BadUsb: remove dead code * U2F: remove dead code Co-authored-by: Aleksandr Kutuzov --- applications/bad_usb/bad_usb_app.c | 34 +++++++++++- applications/bad_usb/bad_usb_app_i.h | 3 ++ applications/bad_usb/bad_usb_script.c | 2 - .../bad_usb/scenes/bad_usb_scene_config.h | 1 + .../bad_usb/scenes/bad_usb_scene_error.c | 53 +++++++++++++++++++ applications/u2f/scenes/u2f_scene_config.h | 1 + applications/u2f/scenes/u2f_scene_error.c | 49 +++++++++++++++++ applications/u2f/u2f_app.c | 15 +++++- applications/u2f/u2f_app_i.h | 5 ++ applications/u2f/u2f_data.c | 20 +++++++ applications/u2f/u2f_data.h | 2 + applications/u2f/views/u2f_view.c | 2 +- 12 files changed, 182 insertions(+), 5 deletions(-) create mode 100644 applications/bad_usb/scenes/bad_usb_scene_error.c create mode 100644 applications/u2f/scenes/u2f_scene_error.c diff --git a/applications/bad_usb/bad_usb_app.c b/applications/bad_usb/bad_usb_app.c index 4f94598e876..c4a3c9301d8 100644 --- a/applications/bad_usb/bad_usb_app.c +++ b/applications/bad_usb/bad_usb_app.c @@ -1,6 +1,7 @@ #include "bad_usb_app_i.h" #include #include +#include static bool bad_usb_app_custom_event_callback(void* context, uint32_t event) { furi_assert(context); @@ -20,6 +21,24 @@ static void bad_usb_app_tick_event_callback(void* context) { scene_manager_handle_tick_event(app->scene_manager); } +static bool bad_usb_check_assets() { + Storage* fs_api = furi_record_open("storage"); + + File* dir = storage_file_alloc(fs_api); + bool ret = false; + + if(storage_dir_open(dir, BAD_USB_APP_PATH_FOLDER)) { + ret = true; + } + + storage_dir_close(dir); + storage_file_free(dir); + + furi_record_close("storage"); + + return ret; +} + BadUsbApp* bad_usb_app_alloc() { BadUsbApp* app = furi_alloc(sizeof(BadUsbApp)); @@ -41,11 +60,20 @@ BadUsbApp* bad_usb_app_alloc() { view_dispatcher_attach_to_gui(app->view_dispatcher, app->gui, ViewDispatcherTypeFullscreen); + // Custom Widget + app->widget = widget_alloc(); + view_dispatcher_add_view( + app->view_dispatcher, BadUsbAppViewError, widget_get_view(app->widget)); + app->bad_usb_view = bad_usb_alloc(); view_dispatcher_add_view( app->view_dispatcher, BadUsbAppViewWork, bad_usb_get_view(app->bad_usb_view)); - scene_manager_next_scene(app->scene_manager, BadUsbAppViewFileSelect); + if(bad_usb_check_assets()) { + scene_manager_next_scene(app->scene_manager, BadUsbSceneFileSelect); + } else { + scene_manager_next_scene(app->scene_manager, BadUsbSceneError); + } return app; } @@ -58,6 +86,10 @@ void bad_usb_app_free(BadUsbApp* app) { view_dispatcher_remove_view(app->view_dispatcher, BadUsbAppViewWork); bad_usb_free(app->bad_usb_view); + // Custom Widget + view_dispatcher_remove_view(app->view_dispatcher, BadUsbAppViewError); + widget_free(app->widget); + // View dispatcher view_dispatcher_free(app->view_dispatcher); scene_manager_free(app->scene_manager); diff --git a/applications/bad_usb/bad_usb_app_i.h b/applications/bad_usb/bad_usb_app_i.h index 2806cd70e95..5772725da1d 100644 --- a/applications/bad_usb/bad_usb_app_i.h +++ b/applications/bad_usb/bad_usb_app_i.h @@ -11,6 +11,7 @@ #include #include #include +#include #include "views/bad_usb_view.h" #define BAD_USB_APP_PATH_FOLDER "/any/badusb" @@ -23,6 +24,7 @@ struct BadUsbApp { SceneManager* scene_manager; NotificationApp* notifications; DialogsApp* dialogs; + Widget* widget; char file_name[BAD_USB_FILE_NAME_LEN + 1]; BadUsb* bad_usb_view; @@ -30,6 +32,7 @@ struct BadUsbApp { }; typedef enum { + BadUsbAppViewError, BadUsbAppViewFileSelect, BadUsbAppViewWork, } BadUsbAppView; diff --git a/applications/bad_usb/bad_usb_script.c b/applications/bad_usb/bad_usb_script.c index 6cf460df4f9..53710372050 100644 --- a/applications/bad_usb/bad_usb_script.c +++ b/applications/bad_usb/bad_usb_script.c @@ -159,8 +159,6 @@ static bool ducky_altchar(const char* charcode) { uint8_t i = 0; bool state = false; - //TODO: numlock - FURI_LOG_I(WORKER_TAG, "char %s", charcode); furi_hal_hid_kb_press(KEY_MOD_LEFT_ALT); diff --git a/applications/bad_usb/scenes/bad_usb_scene_config.h b/applications/bad_usb/scenes/bad_usb_scene_config.h index b32ecb9111f..0ab8f54f874 100644 --- a/applications/bad_usb/scenes/bad_usb_scene_config.h +++ b/applications/bad_usb/scenes/bad_usb_scene_config.h @@ -1,2 +1,3 @@ ADD_SCENE(bad_usb, file_select, FileSelect) ADD_SCENE(bad_usb, work, Work) +ADD_SCENE(bad_usb, error, Error) diff --git a/applications/bad_usb/scenes/bad_usb_scene_error.c b/applications/bad_usb/scenes/bad_usb_scene_error.c new file mode 100644 index 00000000000..6419ee375f0 --- /dev/null +++ b/applications/bad_usb/scenes/bad_usb_scene_error.c @@ -0,0 +1,53 @@ +#include "../bad_usb_app_i.h" + +typedef enum { + SubghzCustomEventErrorBack, +} BadUsbCustomEvent; + +static void + bad_usb_scene_error_event_callback(GuiButtonType result, InputType type, void* context) { + furi_assert(context); + BadUsbApp* app = context; + + if((result == GuiButtonTypeLeft) && (type == InputTypeShort)) { + view_dispatcher_send_custom_event(app->view_dispatcher, SubghzCustomEventErrorBack); + } +} + +void bad_usb_scene_error_on_enter(void* context) { + BadUsbApp* app = context; + + widget_add_icon_element(app->widget, 0, 0, &I_SDQuestion_35x43); + + widget_add_string_multiline_element( + app->widget, + 81, + 4, + AlignCenter, + AlignTop, + FontSecondary, + "No SD card or\napp data found.\nThis app will not\nwork without\nrequired files."); + + widget_add_button_element( + app->widget, GuiButtonTypeLeft, "Back", bad_usb_scene_error_event_callback, app); + + view_dispatcher_switch_to_view(app->view_dispatcher, BadUsbAppViewError); +} + +bool bad_usb_scene_error_on_event(void* context, SceneManagerEvent event) { + BadUsbApp* app = context; + bool consumed = false; + + if(event.type == SceneManagerEventTypeCustom) { + if(event.event == SubghzCustomEventErrorBack) { + view_dispatcher_stop(app->view_dispatcher); + consumed = true; + } + } + return consumed; +} + +void bad_usb_scene_error_on_exit(void* context) { + BadUsbApp* app = context; + widget_clear(app->widget); +} diff --git a/applications/u2f/scenes/u2f_scene_config.h b/applications/u2f/scenes/u2f_scene_config.h index 636589f262d..7bacd67b7b0 100644 --- a/applications/u2f/scenes/u2f_scene_config.h +++ b/applications/u2f/scenes/u2f_scene_config.h @@ -1 +1,2 @@ ADD_SCENE(u2f, main, Main) +ADD_SCENE(u2f, error, Error) diff --git a/applications/u2f/scenes/u2f_scene_error.c b/applications/u2f/scenes/u2f_scene_error.c new file mode 100644 index 00000000000..d0338568202 --- /dev/null +++ b/applications/u2f/scenes/u2f_scene_error.c @@ -0,0 +1,49 @@ +#include "../u2f_app_i.h" + +static void u2f_scene_error_event_callback(GuiButtonType result, InputType type, void* context) { + furi_assert(context); + U2fApp* app = context; + + if((result == GuiButtonTypeLeft) && (type == InputTypeShort)) { + view_dispatcher_send_custom_event(app->view_dispatcher, U2fCustomEventErrorBack); + } +} + +void u2f_scene_error_on_enter(void* context) { + U2fApp* app = context; + + widget_add_icon_element(app->widget, 0, 0, &I_SDQuestion_35x43); + + widget_add_string_multiline_element( + app->widget, + 81, + 4, + AlignCenter, + AlignTop, + FontSecondary, + "No SD card or\napp data found.\nThis app will not\nwork without\nrequired files."); + + widget_add_button_element( + app->widget, GuiButtonTypeLeft, "Back", u2f_scene_error_event_callback, app); + + view_dispatcher_switch_to_view(app->view_dispatcher, U2fAppViewError); +} + +bool u2f_scene_error_on_event(void* context, SceneManagerEvent event) { + U2fApp* app = context; + bool consumed = false; + + if(event.type == SceneManagerEventTypeCustom) { + if(event.event == U2fCustomEventErrorBack) { + view_dispatcher_stop(app->view_dispatcher); + consumed = true; + } + } + + return consumed; +} + +void u2f_scene_error_on_exit(void* context) { + U2fApp* app = context; + widget_clear(app->widget); +} diff --git a/applications/u2f/u2f_app.c b/applications/u2f/u2f_app.c index c512e5316bc..f2e5573044b 100644 --- a/applications/u2f/u2f_app.c +++ b/applications/u2f/u2f_app.c @@ -1,4 +1,5 @@ #include "u2f_app_i.h" +#include "u2f_data.h" #include #include @@ -39,11 +40,19 @@ U2fApp* u2f_app_alloc() { view_dispatcher_attach_to_gui(app->view_dispatcher, app->gui, ViewDispatcherTypeFullscreen); + // Custom Widget + app->widget = widget_alloc(); + view_dispatcher_add_view(app->view_dispatcher, U2fAppViewError, widget_get_view(app->widget)); + app->u2f_view = u2f_view_alloc(); view_dispatcher_add_view( app->view_dispatcher, U2fAppViewMain, u2f_view_get_view(app->u2f_view)); - scene_manager_next_scene(app->scene_manager, U2fAppViewMain); + if(u2f_data_check()) { + scene_manager_next_scene(app->scene_manager, U2fSceneMain); + } else { + scene_manager_next_scene(app->scene_manager, U2fSceneError); + } return app; } @@ -55,6 +64,10 @@ void u2f_app_free(U2fApp* app) { view_dispatcher_remove_view(app->view_dispatcher, U2fAppViewMain); u2f_view_free(app->u2f_view); + // Custom Widget + view_dispatcher_remove_view(app->view_dispatcher, U2fAppViewError); + widget_free(app->widget); + // View dispatcher view_dispatcher_free(app->view_dispatcher); scene_manager_free(app->scene_manager); diff --git a/applications/u2f/u2f_app_i.h b/applications/u2f/u2f_app_i.h index 6bb95a03890..33092ba3c92 100644 --- a/applications/u2f/u2f_app_i.h +++ b/applications/u2f/u2f_app_i.h @@ -10,6 +10,7 @@ #include #include #include +#include #include "views/u2f_view.h" #include "u2f_hid.h" #include "u2f.h" @@ -29,9 +30,12 @@ typedef enum { U2fCustomEventConfirm, + U2fCustomEventErrorBack, + } GpioCustomEvent; typedef enum { + U2fAppViewError, U2fAppViewMain, } U2fAppView; @@ -40,6 +44,7 @@ struct U2fApp { ViewDispatcher* view_dispatcher; SceneManager* scene_manager; NotificationApp* notifications; + Widget* widget; osTimerId_t timer; U2fHid* u2f_hid; U2fView* u2f_view; diff --git a/applications/u2f/u2f_data.c b/applications/u2f/u2f_data.c index 6f4cbbdfb76..1de86164124 100644 --- a/applications/u2f/u2f_data.c +++ b/applications/u2f/u2f_data.c @@ -38,6 +38,26 @@ typedef struct { uint32_t control; } __attribute__((packed)) U2fCounterData; +bool u2f_data_check() { + bool state = false; + Storage* fs_api = furi_record_open("storage"); + File* file = storage_file_alloc(fs_api); + + if(storage_file_open(file, U2F_CERT_FILE, FSAM_READ, FSOM_OPEN_EXISTING)) { + storage_file_close(file); + if(storage_file_open(file, U2F_CERT_KEY_FILE, FSAM_READ, FSOM_OPEN_EXISTING)) { + state = true; + } + } + + storage_file_close(file); + storage_file_free(file); + + furi_record_close("storage"); + + return state; +} + bool u2f_data_cert_check() { bool state = false; Storage* fs_api = furi_record_open("storage"); diff --git a/applications/u2f/u2f_data.h b/applications/u2f/u2f_data.h index e47e26a1f7c..a96704eb220 100644 --- a/applications/u2f/u2f_data.h +++ b/applications/u2f/u2f_data.h @@ -6,6 +6,8 @@ extern "C" { #include +bool u2f_data_check(); + bool u2f_data_cert_check(); uint32_t u2f_data_cert_load(uint8_t* cert); diff --git a/applications/u2f/views/u2f_view.c b/applications/u2f/views/u2f_view.c index 20c34e9c807..c810d141087 100644 --- a/applications/u2f/views/u2f_view.c +++ b/applications/u2f/views/u2f_view.c @@ -39,7 +39,7 @@ static void u2f_view_draw_callback(Canvas* canvas, void* _model) { canvas, 128 / 2, 3, AlignCenter, AlignTop, "Authentication successfull!"); } else if(model->display_msg == U2fMsgError) { canvas_draw_icon(canvas, 22, 15, &I_Error_62x31); - canvas_draw_str_aligned(canvas, 128 / 2, 3, AlignCenter, AlignTop, "Ceritficate missing"); + canvas_draw_str_aligned(canvas, 128 / 2, 3, AlignCenter, AlignTop, "Ceritficate error"); } } From 838df4c9ea67d390e609d7919cbdc1ca0bb26412 Mon Sep 17 00:00:00 2001 From: gornekich Date: Wed, 2 Feb 2022 18:58:52 +0300 Subject: [PATCH 2/3] [FL-2229] New assets paths (#978) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * assets: change resources paths * apps: rework nfc, irda and subghz with new assets path * subghz: remove unused paths * subghz: fix incorrect path * badusb and u2f fix Co-authored-by: あく Co-authored-by: nminaylov --- .../archive/helpers/archive_browser.h | 2 +- .../scenes/bad_usb_scene_file_select.c | 2 +- applications/irda/scene/irda_app_scene.h | 4 ++-- applications/nfc/helpers/nfc_emv_parser.c | 7 +++--- .../subghz/scenes/subghz_scene_read_raw.c | 2 +- .../subghz/scenes/subghz_scene_save_name.c | 2 +- applications/subghz/subghz.c | 8 +++---- applications/subghz/subghz_cli.c | 8 +++---- applications/subghz/subghz_i.c | 20 ++++++------------ applications/u2f/u2f_data.c | 4 ++-- .../irda/{universal => assets}/tv.ir | 0 assets/resources/nfc/{emv => assets}/aid.nfc | 0 .../nfc/{emv => assets}/country_code.nfc | 0 .../nfc/{emv => assets}/currency_code.nfc | 0 .../resources/subghz/{ => assets}/came_atomo | 0 .../subghz/{ => assets}/keeloq_mfcodes | 0 .../subghz/{ => assets}/keeloq_mfcodes_user | 0 .../subghz/{ => assets}/nice_flor_s_rx | 0 .../subghz/{ => assets}/nice_flor_s_tx | 0 assets/resources/u2f/{ => assets}/cert.der | Bin .../resources/u2f/{ => assets}/cert_key.u2f | 0 lib/subghz/protocols/subghz_protocol_common.h | 2 -- lib/subghz/protocols/subghz_protocol_raw.c | 7 +----- 23 files changed, 28 insertions(+), 40 deletions(-) mode change 100644 => 100755 applications/subghz/subghz_i.c rename assets/resources/irda/{universal => assets}/tv.ir (100%) rename assets/resources/nfc/{emv => assets}/aid.nfc (100%) rename assets/resources/nfc/{emv => assets}/country_code.nfc (100%) rename assets/resources/nfc/{emv => assets}/currency_code.nfc (100%) rename assets/resources/subghz/{ => assets}/came_atomo (100%) rename assets/resources/subghz/{ => assets}/keeloq_mfcodes (100%) rename assets/resources/subghz/{ => assets}/keeloq_mfcodes_user (100%) rename assets/resources/subghz/{ => assets}/nice_flor_s_rx (100%) rename assets/resources/subghz/{ => assets}/nice_flor_s_tx (100%) rename assets/resources/u2f/{ => assets}/cert.der (100%) rename assets/resources/u2f/{ => assets}/cert_key.u2f (100%) mode change 100644 => 100755 lib/subghz/protocols/subghz_protocol_raw.c diff --git a/applications/archive/helpers/archive_browser.h b/applications/archive/helpers/archive_browser.h index 519fab75a01..44bce9140c6 100644 --- a/applications/archive/helpers/archive_browser.h +++ b/applications/archive/helpers/archive_browser.h @@ -8,7 +8,7 @@ static const char* tab_default_paths[] = { [ArchiveTabFavorites] = "/any/favorites", [ArchiveTabIButton] = "/any/ibutton", [ArchiveTabNFC] = "/any/nfc", - [ArchiveTabSubGhz] = "/any/subghz/saved", + [ArchiveTabSubGhz] = "/any/subghz", [ArchiveTabLFRFID] = "/any/lfrfid", [ArchiveTabIrda] = "/any/irda", [ArchiveTabBrowser] = "/any", diff --git a/applications/bad_usb/scenes/bad_usb_scene_file_select.c b/applications/bad_usb/scenes/bad_usb_scene_file_select.c index 2ba673bcd17..678a003c2fc 100644 --- a/applications/bad_usb/scenes/bad_usb_scene_file_select.c +++ b/applications/bad_usb/scenes/bad_usb_scene_file_select.c @@ -19,7 +19,7 @@ void bad_usb_scene_file_select_on_enter(void* context) { BadUsbApp* bad_usb = context; if(bad_usb_file_select(bad_usb)) { - scene_manager_next_scene(bad_usb->scene_manager, BadUsbAppViewWork); + scene_manager_next_scene(bad_usb->scene_manager, BadUsbSceneWork); } else { //scene_manager_previous_scene(bad_usb->scene_manager); view_dispatcher_stop(bad_usb->view_dispatcher); diff --git a/applications/irda/scene/irda_app_scene.h b/applications/irda/scene/irda_app_scene.h index 81915924678..9de48e18e89 100644 --- a/applications/irda/scene/irda_app_scene.h +++ b/applications/irda/scene/irda_app_scene.h @@ -159,7 +159,7 @@ class IrdaAppSceneUniversalTV : public IrdaAppSceneUniversalCommon { public: void on_enter(IrdaApp* app) final; IrdaAppSceneUniversalTV() - : IrdaAppSceneUniversalCommon("/ext/irda/universal/tv.ir") { + : IrdaAppSceneUniversalCommon("/ext/irda/assets/tv.ir") { } ~IrdaAppSceneUniversalTV() { } @@ -169,7 +169,7 @@ class IrdaAppSceneUniversalAudio : public IrdaAppSceneUniversalCommon { public: void on_enter(IrdaApp* app) final; IrdaAppSceneUniversalAudio() - : IrdaAppSceneUniversalCommon("/ext/irda/universal/audio.ir") { + : IrdaAppSceneUniversalCommon("/ext/irda/assets/audio.ir") { } ~IrdaAppSceneUniversalAudio() { } diff --git a/applications/nfc/helpers/nfc_emv_parser.c b/applications/nfc/helpers/nfc_emv_parser.c index 54c6c2035fc..4012ff45b84 100755 --- a/applications/nfc/helpers/nfc_emv_parser.c +++ b/applications/nfc/helpers/nfc_emv_parser.c @@ -44,7 +44,7 @@ bool nfc_emv_parser_get_aid_name( for(uint8_t i = 0; i < aid_len; i++) { string_cat_printf(key, "%02X", aid[i]); } - if(nfc_emv_parser_search_data(storage, "/ext/nfc/emv/aid.nfc", key, aid_name)) { + if(nfc_emv_parser_search_data(storage, "/ext/nfc/assets/aid.nfc", key, aid_name)) { parsed = true; } string_clear(key); @@ -58,7 +58,7 @@ bool nfc_emv_parser_get_country_name( bool parsed = false; string_t key; string_init_printf(key, "%04X", country_code); - if(nfc_emv_parser_search_data(storage, "/ext/nfc/emv/country_code.nfc", key, country_name)) { + if(nfc_emv_parser_search_data(storage, "/ext/nfc/assets/country_code.nfc", key, country_name)) { parsed = true; } string_clear(key); @@ -72,7 +72,8 @@ bool nfc_emv_parser_get_currency_name( bool parsed = false; string_t key; string_init_printf(key, "%04X", currency_code); - if(nfc_emv_parser_search_data(storage, "/ext/nfc/emv/currency_code.nfc", key, currency_name)) { + if(nfc_emv_parser_search_data( + storage, "/ext/nfc/assets/currency_code.nfc", key, currency_name)) { parsed = true; } string_clear(key); diff --git a/applications/subghz/scenes/subghz_scene_read_raw.c b/applications/subghz/scenes/subghz_scene_read_raw.c index 481138dc4b9..170d3c7d06b 100644 --- a/applications/subghz/scenes/subghz_scene_read_raw.c +++ b/applications/subghz/scenes/subghz_scene_read_raw.c @@ -23,7 +23,7 @@ bool subghz_scene_read_raw_update_filename(SubGhz* subghz) { path_extract_filename_no_ext(string_get_cstr(temp_str), temp_str); strcpy(subghz->file_name, string_get_cstr(temp_str)); string_printf( - temp_str, "%s/%s%s", SUBGHZ_APP_PATH_FOLDER, subghz->file_name, SUBGHZ_APP_EXTENSION); + temp_str, "%s/%s%s", SUBGHZ_APP_FOLDER, subghz->file_name, SUBGHZ_APP_EXTENSION); subghz_protocol_raw_set_last_file_name( (SubGhzProtocolRAW*)subghz->txrx->protocol_result, string_get_cstr(temp_str)); diff --git a/applications/subghz/scenes/subghz_scene_save_name.c b/applications/subghz/scenes/subghz_scene_save_name.c index 142ba7c9c38..ee1df00f598 100644 --- a/applications/subghz/scenes/subghz_scene_save_name.c +++ b/applications/subghz/scenes/subghz_scene_save_name.c @@ -39,7 +39,7 @@ void subghz_scene_save_name_on_enter(void* context) { dev_name_empty); ValidatorIsFile* validator_is_file = - validator_is_file_alloc_init(SUBGHZ_APP_PATH_FOLDER, SUBGHZ_APP_EXTENSION); + validator_is_file_alloc_init(SUBGHZ_APP_FOLDER, SUBGHZ_APP_EXTENSION); text_input_set_validator(text_input, validator_is_file_callback, validator_is_file); view_dispatcher_switch_to_view(subghz->view_dispatcher, SubGhzViewTextInput); diff --git a/applications/subghz/subghz.c b/applications/subghz/subghz.c index f13c86d6e0f..4f442562e07 100644 --- a/applications/subghz/subghz.c +++ b/applications/subghz/subghz.c @@ -284,10 +284,10 @@ int32_t subghz_app(void* p) { //Load database bool load_database = - subghz_parser_load_keeloq_file(subghz->txrx->parser, "/ext/subghz/keeloq_mfcodes"); - subghz_parser_load_keeloq_file(subghz->txrx->parser, "/ext/subghz/keeloq_mfcodes_user"); - subghz_parser_load_nice_flor_s_file(subghz->txrx->parser, "/ext/subghz/nice_flor_s_rx"); - subghz_parser_load_came_atomo_file(subghz->txrx->parser, "/ext/subghz/came_atomo"); + subghz_parser_load_keeloq_file(subghz->txrx->parser, "/ext/subghz/assets/keeloq_mfcodes"); + subghz_parser_load_keeloq_file(subghz->txrx->parser, "/ext/subghz/assets/keeloq_mfcodes_user"); + subghz_parser_load_nice_flor_s_file(subghz->txrx->parser, "/ext/subghz/assets/nice_flor_s_rx"); + subghz_parser_load_came_atomo_file(subghz->txrx->parser, "/ext/subghz/assets/came_atomo"); // Check argument and run corresponding scene if(p && subghz_key_load(subghz, p)) { diff --git a/applications/subghz/subghz_cli.c b/applications/subghz/subghz_cli.c index b91b9a4b705..c54533d9f19 100644 --- a/applications/subghz/subghz_cli.c +++ b/applications/subghz/subghz_cli.c @@ -215,10 +215,10 @@ void subghz_cli_command_rx(Cli* cli, string_t args, void* context) { furi_check(instance->stream); SubGhzParser* parser = subghz_parser_alloc(); - subghz_parser_load_keeloq_file(parser, "/ext/subghz/keeloq_mfcodes"); - subghz_parser_load_keeloq_file(parser, "/ext/subghz/keeloq_mfcodes_user"); - subghz_parser_load_nice_flor_s_file(parser, "/ext/subghz/nice_flor_s_rx"); - subghz_parser_load_came_atomo_file(parser, "/ext/subghz/came_atomo"); + subghz_parser_load_keeloq_file(parser, "/ext/subghz/assets/keeloq_mfcodes"); + subghz_parser_load_keeloq_file(parser, "/ext/subghz/assets/keeloq_mfcodes_user"); + subghz_parser_load_nice_flor_s_file(parser, "/ext/subghz/assets/nice_flor_s_rx"); + subghz_parser_load_came_atomo_file(parser, "/ext/subghz/assets/came_atomo"); subghz_parser_enable_dump_text(parser, subghz_cli_command_rx_text_callback, instance); // Configure radio diff --git a/applications/subghz/subghz_i.c b/applications/subghz/subghz_i.c old mode 100644 new mode 100755 index 5a1f67feb93..87537ca2967 --- a/applications/subghz/subghz_i.c +++ b/applications/subghz/subghz_i.c @@ -284,7 +284,7 @@ bool subghz_get_next_name_file(SubGhz* subghz) { if(strcmp(subghz->file_name, "")) { //get the name of the next free file storage_get_next_filename( - storage, SUBGHZ_RAW_PATH_FOLDER, subghz->file_name, SUBGHZ_APP_EXTENSION, temp_str); + storage, SUBGHZ_RAW_FOLDER, subghz->file_name, SUBGHZ_APP_EXTENSION, temp_str); strcpy(subghz->file_name, string_get_cstr(temp_str)); res = true; @@ -319,15 +319,9 @@ bool subghz_save_protocol_to_file(SubGhz* subghz, const char* dev_name) { dialog_message_show_storage_error(subghz->dialogs, "Cannot create\nfolder"); break; } - // Create saved directory if necessary - if(!storage_simply_mkdir(storage, SUBGHZ_APP_PATH_FOLDER)) { - dialog_message_show_storage_error(subghz->dialogs, "Cannot create\nfolder"); - break; - } // First remove subghz device file if it was saved - string_printf( - dev_file_name, "%s/%s%s", SUBGHZ_APP_PATH_FOLDER, dev_name, SUBGHZ_APP_EXTENSION); + string_printf(dev_file_name, "%s/%s%s", SUBGHZ_APP_FOLDER, dev_name, SUBGHZ_APP_EXTENSION); if(!storage_simply_remove(storage, string_get_cstr(dev_file_name))) { break; @@ -386,7 +380,7 @@ bool subghz_load_protocol_from_file(SubGhz* subghz) { // Input events and views are managed by file_select bool res = dialog_file_select_show( subghz->dialogs, - SUBGHZ_APP_PATH_FOLDER, + SUBGHZ_APP_FOLDER, SUBGHZ_APP_EXTENSION, subghz->file_name, sizeof(subghz->file_name), @@ -394,7 +388,7 @@ bool subghz_load_protocol_from_file(SubGhz* subghz) { if(res) { string_printf( - file_name, "%s/%s%s", SUBGHZ_APP_PATH_FOLDER, subghz->file_name, SUBGHZ_APP_EXTENSION); + file_name, "%s/%s%s", SUBGHZ_APP_FOLDER, subghz->file_name, SUBGHZ_APP_EXTENSION); res = subghz_key_load(subghz, string_get_cstr(file_name)); } @@ -413,10 +407,10 @@ bool subghz_rename_file(SubGhz* subghz) { Storage* storage = furi_record_open("storage"); string_init_printf( - old_path, "%s/%s%s", SUBGHZ_APP_PATH_FOLDER, subghz->file_name_tmp, SUBGHZ_APP_EXTENSION); + old_path, "%s/%s%s", SUBGHZ_APP_FOLDER, subghz->file_name_tmp, SUBGHZ_APP_EXTENSION); string_init_printf( - new_path, "%s/%s%s", SUBGHZ_APP_PATH_FOLDER, subghz->file_name, SUBGHZ_APP_EXTENSION); + new_path, "%s/%s%s", SUBGHZ_APP_FOLDER, subghz->file_name, SUBGHZ_APP_EXTENSION); FS_Error fs_result = storage_common_rename(storage, string_get_cstr(old_path), string_get_cstr(new_path)); @@ -439,7 +433,7 @@ bool subghz_delete_file(SubGhz* subghz) { Storage* storage = furi_record_open("storage"); string_t file_path; string_init_printf( - file_path, "%s/%s%s", SUBGHZ_APP_PATH_FOLDER, subghz->file_name_tmp, SUBGHZ_APP_EXTENSION); + file_path, "%s/%s%s", SUBGHZ_APP_FOLDER, subghz->file_name_tmp, SUBGHZ_APP_EXTENSION); bool result = storage_simply_remove(storage, string_get_cstr(file_path)); furi_record_close("storage"); diff --git a/applications/u2f/u2f_data.c b/applications/u2f/u2f_data.c index 1de86164124..f517d22264e 100644 --- a/applications/u2f/u2f_data.c +++ b/applications/u2f/u2f_data.c @@ -8,8 +8,8 @@ #define TAG "U2F" #define U2F_DATA_FOLDER "/any/u2f/" -#define U2F_CERT_FILE U2F_DATA_FOLDER "cert.der" -#define U2F_CERT_KEY_FILE U2F_DATA_FOLDER "cert_key.u2f" +#define U2F_CERT_FILE U2F_DATA_FOLDER "assets/cert.der" +#define U2F_CERT_KEY_FILE U2F_DATA_FOLDER "assets/cert_key.u2f" #define U2F_KEY_FILE U2F_DATA_FOLDER "key.u2f" #define U2F_CNT_FILE U2F_DATA_FOLDER "cnt.u2f" diff --git a/assets/resources/irda/universal/tv.ir b/assets/resources/irda/assets/tv.ir similarity index 100% rename from assets/resources/irda/universal/tv.ir rename to assets/resources/irda/assets/tv.ir diff --git a/assets/resources/nfc/emv/aid.nfc b/assets/resources/nfc/assets/aid.nfc similarity index 100% rename from assets/resources/nfc/emv/aid.nfc rename to assets/resources/nfc/assets/aid.nfc diff --git a/assets/resources/nfc/emv/country_code.nfc b/assets/resources/nfc/assets/country_code.nfc similarity index 100% rename from assets/resources/nfc/emv/country_code.nfc rename to assets/resources/nfc/assets/country_code.nfc diff --git a/assets/resources/nfc/emv/currency_code.nfc b/assets/resources/nfc/assets/currency_code.nfc similarity index 100% rename from assets/resources/nfc/emv/currency_code.nfc rename to assets/resources/nfc/assets/currency_code.nfc diff --git a/assets/resources/subghz/came_atomo b/assets/resources/subghz/assets/came_atomo similarity index 100% rename from assets/resources/subghz/came_atomo rename to assets/resources/subghz/assets/came_atomo diff --git a/assets/resources/subghz/keeloq_mfcodes b/assets/resources/subghz/assets/keeloq_mfcodes similarity index 100% rename from assets/resources/subghz/keeloq_mfcodes rename to assets/resources/subghz/assets/keeloq_mfcodes diff --git a/assets/resources/subghz/keeloq_mfcodes_user b/assets/resources/subghz/assets/keeloq_mfcodes_user similarity index 100% rename from assets/resources/subghz/keeloq_mfcodes_user rename to assets/resources/subghz/assets/keeloq_mfcodes_user diff --git a/assets/resources/subghz/nice_flor_s_rx b/assets/resources/subghz/assets/nice_flor_s_rx similarity index 100% rename from assets/resources/subghz/nice_flor_s_rx rename to assets/resources/subghz/assets/nice_flor_s_rx diff --git a/assets/resources/subghz/nice_flor_s_tx b/assets/resources/subghz/assets/nice_flor_s_tx similarity index 100% rename from assets/resources/subghz/nice_flor_s_tx rename to assets/resources/subghz/assets/nice_flor_s_tx diff --git a/assets/resources/u2f/cert.der b/assets/resources/u2f/assets/cert.der similarity index 100% rename from assets/resources/u2f/cert.der rename to assets/resources/u2f/assets/cert.der diff --git a/assets/resources/u2f/cert_key.u2f b/assets/resources/u2f/assets/cert_key.u2f similarity index 100% rename from assets/resources/u2f/cert_key.u2f rename to assets/resources/u2f/assets/cert_key.u2f diff --git a/lib/subghz/protocols/subghz_protocol_common.h b/lib/subghz/protocols/subghz_protocol_common.h index 155b6a89c5b..1441e4d52cf 100644 --- a/lib/subghz/protocols/subghz_protocol_common.h +++ b/lib/subghz/protocols/subghz_protocol_common.h @@ -15,9 +15,7 @@ #define DURATION_DIFF(x, y) ((x < y) ? (y - x) : (x - y)) #define SUBGHZ_APP_FOLDER "/any/subghz" -#define SUBGHZ_APP_PATH_FOLDER "/any/subghz/saved" #define SUBGHZ_RAW_FOLDER "/ext/subghz" -#define SUBGHZ_RAW_PATH_FOLDER "/ext/subghz/saved" #define SUBGHZ_APP_EXTENSION ".sub" #define SUBGHZ_ENCODER_UPLOAD_MAX_SIZE 2048 diff --git a/lib/subghz/protocols/subghz_protocol_raw.c b/lib/subghz/protocols/subghz_protocol_raw.c old mode 100644 new mode 100755 index 9f36cdced7a..8b2bcf19765 --- a/lib/subghz/protocols/subghz_protocol_raw.c +++ b/lib/subghz/protocols/subghz_protocol_raw.c @@ -176,15 +176,10 @@ bool subghz_protocol_raw_save_to_file_init( if(!storage_simply_mkdir(instance->storage, SUBGHZ_RAW_FOLDER)) { break; } - // Create saved directory if necessary - if(!storage_simply_mkdir(instance->storage, SUBGHZ_RAW_PATH_FOLDER)) { - break; - } string_set(instance->file_name, dev_name); // First remove subghz device file if it was saved - string_printf( - dev_file_name, "%s/%s%s", SUBGHZ_APP_PATH_FOLDER, dev_name, SUBGHZ_APP_EXTENSION); + string_printf(dev_file_name, "%s/%s%s", SUBGHZ_RAW_FOLDER, dev_name, SUBGHZ_APP_EXTENSION); if(!storage_simply_remove(instance->storage, string_get_cstr(dev_file_name))) { break; From 8cfd0eab9e5f99a41c2c79ab5c3c0c4afe253555 Mon Sep 17 00:00:00 2001 From: gornekich Date: Wed, 2 Feb 2022 22:59:28 +0300 Subject: [PATCH 3/3] [FL-2198], [FL-2161] NFC emulation refactoring (#968) * rfal: add state changed callback * furi_hal_nfc: add NFC-A emulation API * nfc: add emulation logger, refactor scenes * elements: fix text_box element * gui: fix text box module * nfc: remove unnecessary buffers * nfc: introduce emulation callback concept * nfc: format sources * bt settings: fix incorrect scene switch * bt settings: format sources * Debug: fix x2d import for python 3 * Gui: rename method name widget_clear to widget_reset * nfc: add nfca emulation handler * nfc: add global custom events enum * nfc: UID emulation Data -> Log * furi_hal_nfc: fix incorrect timings * u2f, badusb: widget_clear() -> widget_reset() Co-authored-by: Aleksandr Kutuzov --- .../bad_usb/scenes/bad_usb_scene_error.c | 2 +- applications/gui/elements.c | 3 +- applications/gui/modules/text_box.c | 46 +++--- applications/gui/modules/text_box.h | 20 ++- applications/gui/modules/widget.c | 4 +- applications/gui/modules/widget.h | 4 +- .../scene/ibutton_scene_delete_confirm.cpp | 4 +- .../ibutton/scene/ibutton_scene_info.cpp | 2 +- applications/nfc/helpers/nfc_custom_event.h | 11 ++ applications/nfc/nfc_device.h | 7 + applications/nfc/nfc_i.h | 1 + applications/nfc/nfc_worker.c | 95 +++++------- applications/nfc/scenes/nfc_scene_delete.c | 2 +- .../nfc/scenes/nfc_scene_delete_success.c | 6 +- .../nfc/scenes/nfc_scene_device_info.c | 26 ++-- .../nfc/scenes/nfc_scene_emulate_uid.c | 146 ++++++++++++++---- applications/nfc/scenes/nfc_scene_read_card.c | 6 +- .../nfc/scenes/nfc_scene_read_card_success.c | 2 +- .../nfc/scenes/nfc_scene_read_emv_app.c | 6 +- .../nfc/scenes/nfc_scene_read_emv_data.c | 6 +- .../scenes/nfc_scene_read_emv_data_success.c | 2 +- .../nfc/scenes/nfc_scene_read_mifare_ul.c | 6 +- .../scenes/nfc_scene_read_mifare_ul_success.c | 46 ++---- .../nfc/scenes/nfc_scene_restore_original.c | 6 +- applications/nfc/scenes/nfc_scene_save_name.c | 6 +- .../nfc/scenes/nfc_scene_save_success.c | 6 +- applications/nfc/scenes/nfc_scene_set_atqa.c | 6 +- applications/nfc/scenes/nfc_scene_set_sak.c | 6 +- applications/nfc/scenes/nfc_scene_set_uid.c | 6 +- applications/nfc/views/bank_card.c | 2 +- .../subghz/scenes/subghz_scene_delete.c | 2 +- .../subghz/scenes/subghz_scene_delete_raw.c | 2 +- .../subghz/scenes/subghz_scene_need_saving.c | 2 +- .../scenes/subghz_scene_receiver_info.c | 2 +- .../subghz/scenes/subghz_scene_show_error.c | 2 +- applications/u2f/scenes/u2f_scene_error.c | 2 +- debug/PyCortexMDebug/cmdebug/svd.py | 11 +- firmware/targets/f6/furi_hal/furi_hal_nfc.c | 131 ++++++++++++++++ firmware/targets/f7/furi_hal/furi_hal_nfc.c | 131 ++++++++++++++++ .../targets/furi_hal_include/furi_hal_nfc.h | 31 ++++ lib/ST25RFAL002/include/rfal_rf.h | 29 +++- .../source/st25r3916/rfal_rfst25r3916.c | 45 +++++- lib/nfc_protocols/mifare_ultralight.c | 31 +++- lib/nfc_protocols/mifare_ultralight.h | 8 +- lib/nfc_protocols/nfca.c | 32 ++++ lib/nfc_protocols/nfca.h | 10 ++ 46 files changed, 715 insertions(+), 247 deletions(-) mode change 100644 => 100755 applications/gui/modules/text_box.h create mode 100644 applications/nfc/helpers/nfc_custom_event.h mode change 100644 => 100755 firmware/targets/f6/furi_hal/furi_hal_nfc.c mode change 100644 => 100755 firmware/targets/f7/furi_hal/furi_hal_nfc.c create mode 100755 lib/nfc_protocols/nfca.c create mode 100644 lib/nfc_protocols/nfca.h diff --git a/applications/bad_usb/scenes/bad_usb_scene_error.c b/applications/bad_usb/scenes/bad_usb_scene_error.c index 6419ee375f0..52650022009 100644 --- a/applications/bad_usb/scenes/bad_usb_scene_error.c +++ b/applications/bad_usb/scenes/bad_usb_scene_error.c @@ -49,5 +49,5 @@ bool bad_usb_scene_error_on_event(void* context, SceneManagerEvent event) { void bad_usb_scene_error_on_exit(void* context) { BadUsbApp* app = context; - widget_clear(app->widget); + widget_reset(app->widget); } diff --git a/applications/gui/elements.c b/applications/gui/elements.c index 5f39aa84e4f..0cd341b36e4 100644 --- a/applications/gui/elements.c +++ b/applications/gui/elements.c @@ -594,7 +594,6 @@ void elements_text_box( line[line_num].height = line_height; line[line_num].descender = line_descender; if(total_height_min + line_leading_min > height) { - line_num--; break; } total_height_min += line_leading_min; @@ -640,7 +639,7 @@ void elements_text_box( uint8_t free_pixel_num = height - total_height_min; uint8_t fill_pixel = 0; uint8_t j = 1; - line[0].y = line[0].height; + 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++; diff --git a/applications/gui/modules/text_box.c b/applications/gui/modules/text_box.c index 40a8c382f35..7e7eacd6255 100755 --- a/applications/gui/modules/text_box.c +++ b/applications/gui/modules/text_box.c @@ -7,17 +7,16 @@ struct TextBox { View* view; - void* context; - TextBoxExitCallback callback; }; typedef struct { const char* text; char* text_pos; string_t text_formatted; - size_t scroll_pos; - size_t scroll_num; + int32_t scroll_pos; + int32_t scroll_num; TextBoxFont font; + TextBoxFocus focus; bool formatted; } TextBoxModel; @@ -52,12 +51,6 @@ static void text_box_process_up(TextBox* text_box) { }); } -static void text_box_process_back(TextBox* text_box) { - if(text_box->callback) { - text_box->callback(text_box->context); - } -} - static void text_box_insert_endline(Canvas* canvas, TextBoxModel* model) { size_t i = 0; size_t line_width = 0; @@ -84,8 +77,18 @@ static void text_box_insert_endline(Canvas* canvas, TextBoxModel* model) { line_num++; model->text = string_get_cstr(model->text_formatted); model->text_pos = (char*)model->text; - model->scroll_num = MAX(line_num - 4, 0); - model->scroll_pos = 0; + if(model->focus == TextBoxFocusEnd && line_num > 5) { + // Set text position to 5th line from the end + for(uint8_t i = 0; i < line_num - 5; i++) { + while(*model->text_pos++ != '\n') { + }; + } + model->scroll_num = line_num - 4; + model->scroll_pos = line_num - 5; + } else { + model->scroll_num = MAX(line_num - 4, 0); + model->scroll_pos = 0; + } } static void text_box_view_draw_callback(Canvas* canvas, void* _model) { @@ -119,9 +122,6 @@ static bool text_box_view_input_callback(InputEvent* event, void* context) { } else if(event->key == InputKeyUp) { text_box_process_up(text_box); consumed = true; - } else if(event->key == InputKeyBack) { - text_box_process_back(text_box); - consumed = true; } } return consumed; @@ -172,10 +172,9 @@ void text_box_reset(TextBox* text_box) { model->text = NULL; string_set_str(model->text_formatted, ""); model->font = TextBoxFontText; + model->focus = TextBoxFocusStart; return true; }); - text_box->context = NULL; - text_box->callback = NULL; } void text_box_set_text(TextBox* text_box, const char* text) { @@ -185,6 +184,7 @@ void text_box_set_text(TextBox* text_box, const char* text) { with_view_model( text_box->view, (TextBoxModel * model) { model->text = text; + string_reset(model->text_formatted); string_reserve(model->text_formatted, strlen(text)); model->formatted = false; return true; @@ -201,12 +201,12 @@ void text_box_set_font(TextBox* text_box, TextBoxFont font) { }); } -void text_box_set_context(TextBox* text_box, void* context) { +void text_box_set_focus(TextBox* text_box, TextBoxFocus focus) { furi_assert(text_box); - text_box->context = context; -} -void text_box_set_exit_callback(TextBox* text_box, TextBoxExitCallback callback) { - furi_assert(text_box); - text_box->callback = callback; + with_view_model( + text_box->view, (TextBoxModel * model) { + model->focus = focus; + return true; + }); } diff --git a/applications/gui/modules/text_box.h b/applications/gui/modules/text_box.h old mode 100644 new mode 100755 index 6928adcb701..2a0548f2ea4 --- a/applications/gui/modules/text_box.h +++ b/applications/gui/modules/text_box.h @@ -13,13 +13,17 @@ extern "C" { /** TextBox anonymous structure */ typedef struct TextBox TextBox; -typedef void (*TextBoxExitCallback)(void* context); typedef enum { TextBoxFontText, TextBoxFontHex, } TextBoxFont; +typedef enum { + TextBoxFocusStart, + TextBoxFocusEnd, +} TextBoxFocus; + /** Allocate and initialize text_box * * @return TextBox instance @@ -60,19 +64,13 @@ void text_box_set_text(TextBox* text_box, const char* text); */ void text_box_set_font(TextBox* text_box, TextBoxFont font); -/** Set text_box context - * - * @param text_box TextBox instance - * @param context context pointer - */ -void text_box_set_context(TextBox* text_box, void* context); - -/** Set exit callback +/** Set TextBox focus + * @note Use to display from start or from end * * @param text_box TextBox instance - * @param callback TextBoxExitCallback callback pointer + * @param focus TextBoxFocus instance */ -void text_box_set_exit_callback(TextBox* text_box, TextBoxExitCallback callback); +void text_box_set_focus(TextBox* text_box, TextBoxFocus focus); #ifdef __cplusplus } diff --git a/applications/gui/modules/widget.c b/applications/gui/modules/widget.c index 58ca7db2aba..d6c50aaa8fe 100755 --- a/applications/gui/modules/widget.c +++ b/applications/gui/modules/widget.c @@ -68,7 +68,7 @@ Widget* widget_alloc() { return widget; } -void widget_clear(Widget* widget) { +void widget_reset(Widget* widget) { furi_assert(widget); with_view_model( @@ -89,7 +89,7 @@ void widget_clear(Widget* widget) { void widget_free(Widget* widget) { furi_assert(widget); // Free all elements - widget_clear(widget); + widget_reset(widget); // Free elements container with_view_model( widget->view, (GuiWidgetModel * model) { diff --git a/applications/gui/modules/widget.h b/applications/gui/modules/widget.h index 4b4b0dd92fc..98a89435127 100755 --- a/applications/gui/modules/widget.h +++ b/applications/gui/modules/widget.h @@ -27,11 +27,11 @@ Widget* widget_alloc(); */ void widget_free(Widget* widget); -/** Clear Widget +/** Reset Widget * * @param widget Widget instance */ -void widget_clear(Widget* widget); +void widget_reset(Widget* widget); /** Get Widget view * diff --git a/applications/ibutton/scene/ibutton_scene_delete_confirm.cpp b/applications/ibutton/scene/ibutton_scene_delete_confirm.cpp index 4dc83b9036f..e5303d04bb3 100755 --- a/applications/ibutton/scene/ibutton_scene_delete_confirm.cpp +++ b/applications/ibutton/scene/ibutton_scene_delete_confirm.cpp @@ -75,7 +75,7 @@ void iButtonSceneDeleteConfirm::on_exit(iButtonApp* app) { app->set_text_store(""); - widget_clear(widget); + widget_reset(widget); } void iButtonSceneDeleteConfirm::widget_callback( @@ -91,4 +91,4 @@ void iButtonSceneDeleteConfirm::widget_callback( } app->get_view_manager()->send_event(&event); -} \ No newline at end of file +} diff --git a/applications/ibutton/scene/ibutton_scene_info.cpp b/applications/ibutton/scene/ibutton_scene_info.cpp index 81c43c5de0d..a05d013f466 100755 --- a/applications/ibutton/scene/ibutton_scene_info.cpp +++ b/applications/ibutton/scene/ibutton_scene_info.cpp @@ -69,7 +69,7 @@ void iButtonSceneInfo::on_exit(iButtonApp* app) { app->set_text_store(""); - widget_clear(widget); + widget_reset(widget); } void iButtonSceneInfo::widget_callback(GuiButtonType result, InputType type, void* context) { diff --git a/applications/nfc/helpers/nfc_custom_event.h b/applications/nfc/helpers/nfc_custom_event.h new file mode 100644 index 00000000000..5ef111b6ba6 --- /dev/null +++ b/applications/nfc/helpers/nfc_custom_event.h @@ -0,0 +1,11 @@ +#pragma once + +enum NfcCustomEvent { + // Reserve first 100 events for button types and indexes, starting from 0 + NfcCustomEventReserved = 100, + + NfcCustomEventViewExit, + NfcCustomEventWorkerExit, + NfcCustomEventByteInputDone, + NfcCustomEventTextInputDone, +}; \ No newline at end of file diff --git a/applications/nfc/nfc_device.h b/applications/nfc/nfc_device.h index cf0c389cb50..b26e6bf9d19 100644 --- a/applications/nfc/nfc_device.h +++ b/applications/nfc/nfc_device.h @@ -9,6 +9,7 @@ #define NFC_DEV_NAME_MAX_LEN 22 #define NFC_FILE_NAME_MAX_LEN 120 +#define NFC_READER_DATA_MAX_SIZE 64 #define NFC_APP_FOLDER "/any/nfc" #define NFC_APP_EXTENSION ".nfc" @@ -54,11 +55,17 @@ typedef struct { uint16_t currency_code; } NfcEmvData; +typedef struct { + uint8_t data[NFC_READER_DATA_MAX_SIZE]; + uint16_t size; +} NfcReaderRequestData; + typedef struct { NfcDeviceCommonData nfc_data; union { NfcEmvData emv_data; MifareUlData mf_ul_data; + NfcReaderRequestData reader_data; }; } NfcDeviceData; diff --git a/applications/nfc/nfc_i.h b/applications/nfc/nfc_i.h index 2c17df75f97..86164315349 100755 --- a/applications/nfc/nfc_i.h +++ b/applications/nfc/nfc_i.h @@ -26,6 +26,7 @@ #include "views/bank_card.h" #include +#include #define NFC_SEND_NOTIFICATION_FALSE (0UL) #define NFC_SEND_NOTIFICATION_TRUE (1UL) diff --git a/applications/nfc/nfc_worker.c b/applications/nfc/nfc_worker.c index 98d064ca61f..4f9691882f5 100755 --- a/applications/nfc/nfc_worker.c +++ b/applications/nfc/nfc_worker.c @@ -57,7 +57,7 @@ void nfc_worker_stop(NfcWorker* nfc_worker) { if(nfc_worker->state == NfcWorkerStateBroken || nfc_worker->state == NfcWorkerStateReady) { return; } - + furi_hal_nfc_stop(); nfc_worker_change_state(nfc_worker, NfcWorkerStateStop); } @@ -140,13 +140,37 @@ void nfc_worker_detect(NfcWorker* nfc_worker) { } } +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(nfc_worker->context); + } + } + return true; +} + void nfc_worker_emulate(NfcWorker* nfc_worker) { NfcDeviceCommonData* data = &nfc_worker->dev_data->nfc_data; while(nfc_worker->state == NfcWorkerStateEmulate) { - if(furi_hal_nfc_listen(data->uid, data->uid_len, data->atqa, data->sak, false, 100)) { - FURI_LOG_D(TAG, "Reader detected"); - } - osDelay(10); + furi_hal_nfc_emulate_nfca( + data->uid, + data->uid_len, + data->atqa, + data->sak, + nfc_worker_emulate_uid_callback, + nfc_worker, + 1000); } } @@ -603,65 +627,26 @@ void nfc_worker_read_mifare_ul(NfcWorker* nfc_worker) { } void nfc_worker_emulate_mifare_ul(NfcWorker* nfc_worker) { - ReturnCode err; - uint8_t tx_buff[255] = {}; - uint16_t tx_len = 0; - uint8_t* rx_buff; - uint16_t* rx_len; - NfcDeviceData* data = nfc_worker->dev_data; + NfcDeviceCommonData* nfc_common = &nfc_worker->dev_data->nfc_data; MifareUlDevice mf_ul_emulate; - // Setup emulation parameters from mifare ultralight data structure - mf_ul_prepare_emulation(&mf_ul_emulate, &data->mf_ul_data); + mf_ul_prepare_emulation(&mf_ul_emulate, &nfc_worker->dev_data->mf_ul_data); while(nfc_worker->state == NfcWorkerStateEmulateMifareUl) { - // WARNING - // DO NOT call any blocking functions (e.g. FURI_LOG_*) in this loop, - // as any delay will negatively affect the stability of the emulation. - if(furi_hal_nfc_listen( - data->nfc_data.uid, - data->nfc_data.uid_len, - data->nfc_data.atqa, - data->nfc_data.sak, - true, - 200)) { - if(furi_hal_nfc_get_first_frame(&rx_buff, &rx_len)) { - // Data exchange loop - while(nfc_worker->state == NfcWorkerStateEmulateMifareUl) { - tx_len = mf_ul_prepare_emulation_response( - rx_buff, *rx_len, tx_buff, &mf_ul_emulate); - if(tx_len > 0) { - if(tx_len < 8) { - err = furi_hal_nfc_raw_bitstream_exchange( - tx_buff, tx_len, &rx_buff, &rx_len, false); - *rx_len /= 8; - } else { - err = furi_hal_nfc_data_exchange( - tx_buff, tx_len / 8, &rx_buff, &rx_len, false); - } - if(err == ERR_NONE) { - continue; - } else { - FURI_LOG_D(TAG, "Communication error: %d", err); - break; - } - } else { - furi_hal_nfc_deactivate(); - break; - } - } - } else { - FURI_LOG_D(TAG, "Error in 1st data exchange"); - furi_hal_nfc_deactivate(); - } - } + furi_hal_nfc_emulate_nfca( + nfc_common->uid, + nfc_common->uid_len, + nfc_common->atqa, + nfc_common->sak, + mf_ul_prepare_emulation_response, + &mf_ul_emulate, + 5000); // Check if data was modified if(mf_ul_emulate.data_changed) { nfc_worker->dev_data->mf_ul_data = mf_ul_emulate.data; if(nfc_worker->callback) { nfc_worker->callback(nfc_worker->context); } + mf_ul_emulate.data_changed = false; } - FURI_LOG_D(TAG, "Can't find reader"); - osThreadYield(); } } diff --git a/applications/nfc/scenes/nfc_scene_delete.c b/applications/nfc/scenes/nfc_scene_delete.c index 57d777dfc70..2661d1667dc 100755 --- a/applications/nfc/scenes/nfc_scene_delete.c +++ b/applications/nfc/scenes/nfc_scene_delete.c @@ -88,5 +88,5 @@ bool nfc_scene_delete_on_event(void* context, SceneManagerEvent event) { void nfc_scene_delete_on_exit(void* context) { Nfc* nfc = (Nfc*)context; - widget_clear(nfc->widget); + 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 96e70693cb0..1392fa9e09d 100755 --- a/applications/nfc/scenes/nfc_scene_delete_success.c +++ b/applications/nfc/scenes/nfc_scene_delete_success.c @@ -1,10 +1,8 @@ #include "../nfc_i.h" -#define SCENE_SAVE_SUCCESS_CUSTOM_EVENT (0UL) - void nfc_scene_delete_success_popup_callback(void* context) { Nfc* nfc = (Nfc*)context; - view_dispatcher_send_custom_event(nfc->view_dispatcher, SCENE_SAVE_SUCCESS_CUSTOM_EVENT); + view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventViewExit); } void nfc_scene_delete_success_on_enter(void* context) { @@ -25,7 +23,7 @@ bool nfc_scene_delete_success_on_event(void* context, SceneManagerEvent event) { Nfc* nfc = (Nfc*)context; if(event.type == SceneManagerEventTypeCustom) { - if(event.event == SCENE_SAVE_SUCCESS_CUSTOM_EVENT) { + if(event.event == NfcCustomEventViewExit) { return scene_manager_search_and_switch_to_previous_scene( nfc->scene_manager, NfcSceneStart); } diff --git a/applications/nfc/scenes/nfc_scene_device_info.c b/applications/nfc/scenes/nfc_scene_device_info.c index 4aea026be8d..e9d5bfda609 100755 --- a/applications/nfc/scenes/nfc_scene_device_info.c +++ b/applications/nfc/scenes/nfc_scene_device_info.c @@ -1,8 +1,6 @@ #include "../nfc_i.h" #include "../helpers/nfc_emv_parser.h" -#define NFC_SCENE_DEVICE_INFO_BACK_EVENT (0UL) - enum { NfcSceneDeviceInfoUid, NfcSceneDeviceInfoData, @@ -17,18 +15,15 @@ void nfc_scene_device_info_widget_callback(GuiButtonType result, InputType type, void nfc_scene_device_info_dialog_callback(DialogExResult result, void* context) { Nfc* nfc = context; - view_dispatcher_send_custom_event(nfc->view_dispatcher, result); -} - -void nfc_scene_device_info_text_box_callback(void* context) { - Nfc* nfc = context; - view_dispatcher_send_custom_event(nfc->view_dispatcher, NFC_SCENE_DEVICE_INFO_BACK_EVENT); + if(result == DialogExResultLeft) { + view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventViewExit); + } } void nfc_scene_device_info_bank_card_callback(GuiButtonType result, InputType type, void* context) { Nfc* nfc = context; if(type == InputTypeShort) { - view_dispatcher_send_custom_event(nfc->view_dispatcher, NFC_SCENE_DEVICE_INFO_BACK_EVENT); + view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventViewExit); } } @@ -97,8 +92,6 @@ void nfc_scene_device_info_on_enter(void* context) { } else if(nfc->dev->format == NfcDeviceSaveFormatMifareUl) { MifareUlData* mf_ul_data = &nfc->dev->dev_data.mf_ul_data; TextBox* text_box = nfc->text_box; - text_box_set_context(text_box, nfc); - text_box_set_exit_callback(text_box, nfc_scene_device_info_text_box_callback); text_box_set_font(text_box, TextBoxFontHex); for(uint16_t i = 0; i < mf_ul_data->data_size; i += 2) { if(!(i % 8) && i) { @@ -170,7 +163,14 @@ bool nfc_scene_device_info_on_event(void* context, SceneManagerEvent event) { view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewBankCard); consumed = true; } - } else if(state == NfcSceneDeviceInfoData) { + } else if(state == NfcSceneDeviceInfoData && event.event == NfcCustomEventViewExit) { + scene_manager_set_scene_state( + nfc->scene_manager, NfcSceneDeviceInfo, NfcSceneDeviceInfoUid); + view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewWidget); + consumed = true; + } + } else if(event.type == SceneManagerEventTypeBack) { + if(state == NfcSceneDeviceInfoData) { scene_manager_set_scene_state( nfc->scene_manager, NfcSceneDeviceInfo, NfcSceneDeviceInfoUid); view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewWidget); @@ -184,7 +184,7 @@ void nfc_scene_device_info_on_exit(void* context) { Nfc* nfc = (Nfc*)context; // Clear Custom Widget - widget_clear(nfc->widget); + widget_reset(nfc->widget); if(nfc->dev->format == NfcDeviceSaveFormatUid) { // Clear Dialog diff --git a/applications/nfc/scenes/nfc_scene_emulate_uid.c b/applications/nfc/scenes/nfc_scene_emulate_uid.c index a7af371cb6f..79974f3fede 100755 --- a/applications/nfc/scenes/nfc_scene_emulate_uid.c +++ b/applications/nfc/scenes/nfc_scene_emulate_uid.c @@ -1,61 +1,139 @@ #include "../nfc_i.h" #include -void nfc_scene_emulate_uid_on_enter(void* context) { - Nfc* nfc = (Nfc*)context; - DOLPHIN_DEED(DolphinDeedNfcEmulate); +enum { + NfcSceneEmulateUidStateWidget, + NfcSceneEmulateUidStateTextBox, +}; + +void nfc_emulate_uid_worker_callback(void* context) { + furi_assert(context); + Nfc* nfc = context; + view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventWorkerExit); +} + +void nfc_scene_emulate_uid_widget_callback(GuiButtonType result, InputType type, void* context) { + furi_assert(context); + Nfc* nfc = context; + if(type == InputTypeShort) { + view_dispatcher_send_custom_event(nfc->view_dispatcher, result); + } +} - // Setup view - Popup* popup = nfc->popup; +void nfc_emulate_uid_textbox_callback(void* context) { + furi_assert(context); + Nfc* nfc = context; + view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventViewExit); +} + +// 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; + Widget* widget = nfc->widget; + widget_reset(widget); + string_t info_str; + string_init(info_str); + widget_add_icon_element(widget, 0, 3, &I_RFIDDolphinSend_97x61); + widget_add_string_element(widget, 56, 32, AlignLeft, AlignTop, FontPrimary, "Emulating UID"); if(strcmp(nfc->dev->dev_name, "")) { - nfc_text_store_set(nfc, "%s", nfc->dev->dev_name); - } else if(data->uid_len == 4) { - nfc_text_store_set( - nfc, "%02X %02X %02X %02X", data->uid[0], data->uid[1], data->uid[2], data->uid[3]); - } else if(data->uid_len == 7) { - nfc_text_store_set( - nfc, - "%02X %02X %02X %02X\n%02X %02X %02X", - data->uid[0], - data->uid[1], - data->uid[2], - data->uid[3], - data->uid[4], - data->uid[5], - data->uid[6]); + string_printf(info_str, "%s", nfc->dev->dev_name); + } else { + for(uint8_t i = 0; i < data->uid_len; i++) { + string_cat_printf(info_str, "%02X ", data->uid[i]); + } } + string_strim(info_str); + widget_add_text_box_element( + widget, 56, 43, 70, 21, AlignLeft, AlignTop, string_get_cstr(info_str)); + string_clear(info_str); + if(data_received) { + widget_add_button_element( + widget, GuiButtonTypeCenter, "Log", nfc_scene_emulate_uid_widget_callback, nfc); + } +} - popup_set_icon(popup, 0, 3, &I_RFIDDolphinSend_97x61); - popup_set_header(popup, "Emulating UID", 56, 31, AlignLeft, AlignTop); - popup_set_text(popup, nfc->text_store, 56, 43, AlignLeft, AlignTop); +void nfc_scene_emulate_uid_on_enter(void* context) { + Nfc* nfc = context; + DOLPHIN_DEED(DolphinDeedNfcEmulate); - // Setup and start worker + // Setup Widget + nfc_scene_emulate_uid_widget_config(nfc, false); + // Setup TextBox + TextBox* text_box = nfc->text_box; + text_box_set_font(text_box, TextBoxFontHex); + text_box_set_focus(text_box, TextBoxFocusEnd); + string_reset(nfc->text_box_store); - view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewPopup); - nfc_worker_start(nfc->worker, NfcWorkerStateEmulate, &nfc->dev->dev_data, NULL, nfc); + // Set Widget state and view + scene_manager_set_scene_state( + nfc->scene_manager, NfcSceneEmulateUid, NfcSceneEmulateUidStateWidget); + view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewWidget); + // Start worker + memset(&nfc->dev->dev_data.reader_data, 0, sizeof(NfcReaderRequestData)); + nfc_worker_start( + nfc->worker, + NfcWorkerStateEmulate, + &nfc->dev->dev_data, + nfc_emulate_uid_worker_callback, + nfc); } bool nfc_scene_emulate_uid_on_event(void* context, SceneManagerEvent event) { - Nfc* nfc = (Nfc*)context; + Nfc* nfc = context; + NfcReaderRequestData* reader_data = &nfc->dev->dev_data.reader_data; + uint32_t state = scene_manager_get_scene_state(nfc->scene_manager, NfcSceneEmulateUid); + bool consumed = false; if(event.type == SceneManagerEventTypeTick) { notification_message(nfc->notifications, &sequence_blink_blue_10); - return true; + consumed = true; + } else if(event.type == SceneManagerEventTypeCustom) { + if(event.event == NfcCustomEventWorkerExit) { + // Add data button to widget if data is received for the first time + if(!string_size(nfc->text_box_store)) { + 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]); + } + 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); + scene_manager_set_scene_state( + nfc->scene_manager, NfcSceneEmulateUid, NfcSceneEmulateUidStateTextBox); + consumed = true; + } else if(event.event == NfcCustomEventViewExit && state == NfcSceneEmulateUidStateTextBox) { + view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewWidget); + scene_manager_set_scene_state( + nfc->scene_manager, NfcSceneEmulateUid, NfcSceneEmulateUidStateWidget); + consumed = true; + } + } else if(event.type == SceneManagerEventTypeBack) { + if(state == NfcSceneEmulateUidStateTextBox) { + view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewWidget); + scene_manager_set_scene_state( + nfc->scene_manager, NfcSceneEmulateUid, NfcSceneEmulateUidStateWidget); + consumed = true; + } } - return false; + + return consumed; } void nfc_scene_emulate_uid_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); + widget_reset(nfc->widget); + text_box_reset(nfc->text_box); + string_reset(nfc->text_box_store); } diff --git a/applications/nfc/scenes/nfc_scene_read_card.c b/applications/nfc/scenes/nfc_scene_read_card.c index 10cf74f2e59..35b3b7bf654 100755 --- a/applications/nfc/scenes/nfc_scene_read_card.c +++ b/applications/nfc/scenes/nfc_scene_read_card.c @@ -1,11 +1,9 @@ #include "../nfc_i.h" #include -#define NFC_READ_CARD_CUSTOM_EVENT (10UL) - void nfc_read_card_worker_callback(void* context) { Nfc* nfc = (Nfc*)context; - view_dispatcher_send_custom_event(nfc->view_dispatcher, NFC_READ_CARD_CUSTOM_EVENT); + view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventWorkerExit); } void nfc_scene_read_card_on_enter(void* context) { @@ -27,7 +25,7 @@ bool nfc_scene_read_card_on_event(void* context, SceneManagerEvent event) { Nfc* nfc = (Nfc*)context; if(event.type == SceneManagerEventTypeCustom) { - if(event.event == NFC_READ_CARD_CUSTOM_EVENT) { + if(event.event == NfcCustomEventWorkerExit) { scene_manager_next_scene(nfc->scene_manager, NfcSceneReadCardSuccess); return true; } diff --git a/applications/nfc/scenes/nfc_scene_read_card_success.c b/applications/nfc/scenes/nfc_scene_read_card_success.c index 097cdd8d3cf..260dccefa38 100755 --- a/applications/nfc/scenes/nfc_scene_read_card_success.c +++ b/applications/nfc/scenes/nfc_scene_read_card_success.c @@ -85,5 +85,5 @@ 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; - widget_clear(nfc->widget); + 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 c6eff352b15..5e28c642232 100755 --- a/applications/nfc/scenes/nfc_scene_read_emv_app.c +++ b/applications/nfc/scenes/nfc_scene_read_emv_app.c @@ -1,11 +1,9 @@ #include "../nfc_i.h" #include -#define NFC_READ_EMV_APP_CUSTOM_EVENT (10UL) - void nfc_read_emv_app_worker_callback(void* context) { Nfc* nfc = (Nfc*)context; - view_dispatcher_send_custom_event(nfc->view_dispatcher, NFC_READ_EMV_APP_CUSTOM_EVENT); + view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventWorkerExit); } void nfc_scene_read_emv_app_on_enter(void* context) { @@ -31,7 +29,7 @@ bool nfc_scene_read_emv_app_on_event(void* context, SceneManagerEvent event) { Nfc* nfc = (Nfc*)context; if(event.type == SceneManagerEventTypeCustom) { - if(event.event == NFC_READ_EMV_APP_CUSTOM_EVENT) { + 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); diff --git a/applications/nfc/scenes/nfc_scene_read_emv_data.c b/applications/nfc/scenes/nfc_scene_read_emv_data.c index 36f525f14b8..7fb2f09bcbe 100755 --- a/applications/nfc/scenes/nfc_scene_read_emv_data.c +++ b/applications/nfc/scenes/nfc_scene_read_emv_data.c @@ -1,11 +1,9 @@ #include "../nfc_i.h" #include -#define NFC_READ_EMV_DATA_CUSTOM_EVENT (10UL) - void nfc_read_emv_data_worker_callback(void* context) { Nfc* nfc = (Nfc*)context; - view_dispatcher_send_custom_event(nfc->view_dispatcher, NFC_READ_EMV_DATA_CUSTOM_EVENT); + view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventWorkerExit); } void nfc_scene_read_emv_data_on_enter(void* context) { @@ -33,7 +31,7 @@ bool nfc_scene_read_emv_data_on_event(void* context, SceneManagerEvent event) { Nfc* nfc = (Nfc*)context; if(event.type == SceneManagerEventTypeCustom) { - if(event.event == NFC_READ_EMV_DATA_CUSTOM_EVENT) { + 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); 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 9991245037a..78078d05b90 100755 --- a/applications/nfc/scenes/nfc_scene_read_emv_data_success.c +++ b/applications/nfc/scenes/nfc_scene_read_emv_data_success.c @@ -140,5 +140,5 @@ bool nfc_scene_read_emv_data_success_on_event(void* context, SceneManagerEvent e void nfc_scene_read_emv_data_success_on_exit(void* context) { Nfc* nfc = (Nfc*)context; - widget_clear(nfc->widget); + widget_reset(nfc->widget); } diff --git a/applications/nfc/scenes/nfc_scene_read_mifare_ul.c b/applications/nfc/scenes/nfc_scene_read_mifare_ul.c index c5b7c497954..7bc7ea33f5f 100755 --- a/applications/nfc/scenes/nfc_scene_read_mifare_ul.c +++ b/applications/nfc/scenes/nfc_scene_read_mifare_ul.c @@ -1,11 +1,9 @@ #include "../nfc_i.h" #include -#define NFC_READ_MIFARE_UL_CUSTOM_EVENT (10UL) - void nfc_read_mifare_ul_worker_callback(void* context) { Nfc* nfc = (Nfc*)context; - view_dispatcher_send_custom_event(nfc->view_dispatcher, NFC_READ_MIFARE_UL_CUSTOM_EVENT); + view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventWorkerExit); } void nfc_scene_read_mifare_ul_on_enter(void* context) { @@ -31,7 +29,7 @@ bool nfc_scene_read_mifare_ul_on_event(void* context, SceneManagerEvent event) { Nfc* nfc = (Nfc*)context; if(event.type == SceneManagerEventTypeCustom) { - if(event.event == NFC_READ_MIFARE_UL_CUSTOM_EVENT) { + if(event.event == NfcCustomEventWorkerExit) { scene_manager_next_scene(nfc->scene_manager, NfcSceneReadMifareUlSuccess); return true; } 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 a7fcc2fc721..b396fae1cbc 100755 --- a/applications/nfc/scenes/nfc_scene_read_mifare_ul_success.c +++ b/applications/nfc/scenes/nfc_scene_read_mifare_ul_success.c @@ -2,7 +2,6 @@ #include #define NFC_SCENE_READ_SUCCESS_SHIFT " " -#define NFC_SCENE_READ_MF_UL_CUSTOM_EVENT (0UL) enum { ReadMifareUlStateShowUID, @@ -15,12 +14,6 @@ void nfc_scene_read_mifare_ul_success_dialog_callback(DialogExResult result, voi view_dispatcher_send_custom_event(nfc->view_dispatcher, result); } -void nfc_scene_read_mifare_ul_success_text_box_callback(void* context) { - Nfc* nfc = (Nfc*)context; - - view_dispatcher_send_custom_event(nfc->view_dispatcher, NFC_SCENE_READ_MF_UL_CUSTOM_EVENT); -} - void nfc_scene_read_mifare_ul_success_on_enter(void* context) { Nfc* nfc = (Nfc*)context; DOLPHIN_DEED(DolphinDeedNfcReadSuccess); @@ -59,8 +52,6 @@ void nfc_scene_read_mifare_ul_success_on_enter(void* context) { // Setup TextBox view TextBox* text_box = nfc->text_box; - text_box_set_context(text_box, nfc); - text_box_set_exit_callback(text_box, nfc_scene_read_mifare_ul_success_text_box_callback); text_box_set_font(text_box, TextBoxFontHex); for(uint16_t i = 0; i < mf_ul_data->data_size; i += 2) { if(!(i % 8) && i) { @@ -77,39 +68,34 @@ 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 = (Nfc*)context; + Nfc* nfc = context; + uint32_t state = + scene_manager_get_scene_state(nfc->scene_manager, NfcSceneReadMifareUlSuccess); + bool consumed = false; if(event.type == SceneManagerEventTypeCustom) { - if((scene_manager_get_scene_state(nfc->scene_manager, NfcSceneReadMifareUlSuccess) == - ReadMifareUlStateShowUID) && - (event.event == DialogExResultLeft)) { + if(state == ReadMifareUlStateShowUID && event.event == DialogExResultLeft) { scene_manager_previous_scene(nfc->scene_manager); - return true; - } else if( - (scene_manager_get_scene_state(nfc->scene_manager, NfcSceneReadMifareUlSuccess) == - ReadMifareUlStateShowUID) && - (event.event == DialogExResultRight)) { + consumed = true; + } else if(state == ReadMifareUlStateShowUID && event.event == DialogExResultRight) { scene_manager_next_scene(nfc->scene_manager, NfcSceneMifareUlMenu); - return true; - } else if( - (scene_manager_get_scene_state(nfc->scene_manager, NfcSceneReadMifareUlSuccess) == - ReadMifareUlStateShowUID) && - (event.event == DialogExResultCenter)) { + consumed = true; + } else if(state == ReadMifareUlStateShowUID && event.event == DialogExResultCenter) { view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewTextBox); scene_manager_set_scene_state( nfc->scene_manager, NfcSceneReadMifareUlSuccess, ReadMifareUlStateShowData); - return true; - } else if( - (scene_manager_get_scene_state(nfc->scene_manager, NfcSceneReadMifareUlSuccess) == - ReadMifareUlStateShowData) && - (event.event == NFC_SCENE_READ_MF_UL_CUSTOM_EVENT)) { + consumed = true; + } + } else if(event.type == SceneManagerEventTypeBack) { + if(state == ReadMifareUlStateShowData) { view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewDialogEx); scene_manager_set_scene_state( nfc->scene_manager, NfcSceneReadMifareUlSuccess, ReadMifareUlStateShowUID); - return true; + consumed = true; } } - return false; + + return consumed; } void nfc_scene_read_mifare_ul_success_on_exit(void* context) { diff --git a/applications/nfc/scenes/nfc_scene_restore_original.c b/applications/nfc/scenes/nfc_scene_restore_original.c index 124815927d7..8ddac366169 100644 --- a/applications/nfc/scenes/nfc_scene_restore_original.c +++ b/applications/nfc/scenes/nfc_scene_restore_original.c @@ -1,10 +1,8 @@ #include "../nfc_i.h" -#define SCENE_RESTORE_ORIGINAL_CUSTOM_EVENT (0UL) - void nfc_scene_restore_original_popup_callback(void* context) { Nfc* nfc = (Nfc*)context; - view_dispatcher_send_custom_event(nfc->view_dispatcher, SCENE_RESTORE_ORIGINAL_CUSTOM_EVENT); + view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventViewExit); } void nfc_scene_restore_original_on_enter(void* context) { @@ -26,7 +24,7 @@ bool nfc_scene_restore_original_on_event(void* context, SceneManagerEvent event) bool consumed = false; if(event.type == SceneManagerEventTypeCustom) { - if(event.event == SCENE_RESTORE_ORIGINAL_CUSTOM_EVENT) { + if(event.event == NfcCustomEventViewExit) { consumed = scene_manager_previous_scene(nfc->scene_manager); } } diff --git a/applications/nfc/scenes/nfc_scene_save_name.c b/applications/nfc/scenes/nfc_scene_save_name.c index c66484ffb50..f239baa8fba 100755 --- a/applications/nfc/scenes/nfc_scene_save_name.c +++ b/applications/nfc/scenes/nfc_scene_save_name.c @@ -2,12 +2,10 @@ #include #include -#define SCENE_SAVE_NAME_CUSTOM_EVENT (0UL) - void nfc_scene_save_name_text_input_callback(void* context) { Nfc* nfc = (Nfc*)context; - view_dispatcher_send_custom_event(nfc->view_dispatcher, SCENE_SAVE_NAME_CUSTOM_EVENT); + view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventTextInputDone); } void nfc_scene_save_name_on_enter(void* context) { @@ -42,7 +40,7 @@ bool nfc_scene_save_name_on_event(void* context, SceneManagerEvent event) { Nfc* nfc = (Nfc*)context; if(event.type == SceneManagerEventTypeCustom) { - if(event.event == SCENE_SAVE_NAME_CUSTOM_EVENT) { + if(event.event == NfcCustomEventTextInputDone) { if(strcmp(nfc->dev->dev_name, "")) { nfc_device_delete(nfc->dev); } diff --git a/applications/nfc/scenes/nfc_scene_save_success.c b/applications/nfc/scenes/nfc_scene_save_success.c index 67599c24a4a..f8195d8c19f 100755 --- a/applications/nfc/scenes/nfc_scene_save_success.c +++ b/applications/nfc/scenes/nfc_scene_save_success.c @@ -1,11 +1,9 @@ #include "../nfc_i.h" #include -#define SCENE_SAVE_SUCCESS_CUSTOM_EVENT (0UL) - void nfc_scene_save_success_popup_callback(void* context) { Nfc* nfc = (Nfc*)context; - view_dispatcher_send_custom_event(nfc->view_dispatcher, SCENE_SAVE_SUCCESS_CUSTOM_EVENT); + view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventViewExit); } void nfc_scene_save_success_on_enter(void* context) { @@ -28,7 +26,7 @@ bool nfc_scene_save_success_on_event(void* context, SceneManagerEvent event) { bool consumed = false; if(event.type == SceneManagerEventTypeCustom) { - if(event.event == SCENE_SAVE_SUCCESS_CUSTOM_EVENT) { + if(event.event == NfcCustomEventViewExit) { if(scene_manager_has_previous_scene(nfc->scene_manager, NfcSceneCardMenu)) { consumed = scene_manager_search_and_switch_to_previous_scene( nfc->scene_manager, NfcSceneCardMenu); diff --git a/applications/nfc/scenes/nfc_scene_set_atqa.c b/applications/nfc/scenes/nfc_scene_set_atqa.c index 1c682f18179..85a70fe8d03 100755 --- a/applications/nfc/scenes/nfc_scene_set_atqa.c +++ b/applications/nfc/scenes/nfc_scene_set_atqa.c @@ -1,11 +1,9 @@ #include "../nfc_i.h" -#define SCENE_SET_ATQA_CUSTOM_EVENT (0UL) - void nfc_scene_set_atqa_byte_input_callback(void* context) { Nfc* nfc = (Nfc*)context; - view_dispatcher_send_custom_event(nfc->view_dispatcher, SCENE_SET_ATQA_CUSTOM_EVENT); + view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventByteInputDone); } void nfc_scene_set_atqa_on_enter(void* context) { @@ -28,7 +26,7 @@ bool nfc_scene_set_atqa_on_event(void* context, SceneManagerEvent event) { Nfc* nfc = (Nfc*)context; if(event.type == SceneManagerEventTypeCustom) { - if(event.event == SCENE_SET_ATQA_CUSTOM_EVENT) { + if(event.event == NfcCustomEventByteInputDone) { scene_manager_next_scene(nfc->scene_manager, NfcSceneSetUid); return true; } diff --git a/applications/nfc/scenes/nfc_scene_set_sak.c b/applications/nfc/scenes/nfc_scene_set_sak.c index edeb27a96b5..11cfcf4670c 100755 --- a/applications/nfc/scenes/nfc_scene_set_sak.c +++ b/applications/nfc/scenes/nfc_scene_set_sak.c @@ -1,11 +1,9 @@ #include "../nfc_i.h" -#define SCENE_SET_SAK_CUSTOM_EVENT (0UL) - void nfc_scene_set_sak_byte_input_callback(void* context) { Nfc* nfc = (Nfc*)context; - view_dispatcher_send_custom_event(nfc->view_dispatcher, SCENE_SET_SAK_CUSTOM_EVENT); + view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventByteInputDone); } void nfc_scene_set_sak_on_enter(void* context) { @@ -28,7 +26,7 @@ bool nfc_scene_set_sak_on_event(void* context, SceneManagerEvent event) { Nfc* nfc = (Nfc*)context; if(event.type == SceneManagerEventTypeCustom) { - if(event.event == SCENE_SET_SAK_CUSTOM_EVENT) { + if(event.event == NfcCustomEventByteInputDone) { scene_manager_next_scene(nfc->scene_manager, NfcSceneSetAtqua); return true; } diff --git a/applications/nfc/scenes/nfc_scene_set_uid.c b/applications/nfc/scenes/nfc_scene_set_uid.c index e23efe793bf..c59501294bb 100755 --- a/applications/nfc/scenes/nfc_scene_set_uid.c +++ b/applications/nfc/scenes/nfc_scene_set_uid.c @@ -1,12 +1,10 @@ #include "../nfc_i.h" #include -#define SCENE_SET_UID_CUSTOM_EVENT (0UL) - void nfc_scene_set_uid_byte_input_callback(void* context) { Nfc* nfc = (Nfc*)context; - view_dispatcher_send_custom_event(nfc->view_dispatcher, SCENE_SET_UID_CUSTOM_EVENT); + view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventByteInputDone); } void nfc_scene_set_uid_on_enter(void* context) { @@ -30,7 +28,7 @@ bool nfc_scene_set_uid_on_event(void* context, SceneManagerEvent event) { Nfc* nfc = (Nfc*)context; if(event.type == SceneManagerEventTypeCustom) { - if(event.event == SCENE_SET_UID_CUSTOM_EVENT) { + if(event.event == NfcCustomEventByteInputDone) { DOLPHIN_DEED(DolphinDeedNfcAdd); scene_manager_next_scene(nfc->scene_manager, NfcSceneSaveName); return true; diff --git a/applications/nfc/views/bank_card.c b/applications/nfc/views/bank_card.c index 07b4db581d0..ee54c4b0972 100755 --- a/applications/nfc/views/bank_card.c +++ b/applications/nfc/views/bank_card.c @@ -25,7 +25,7 @@ View* bank_card_get_view(BankCard* bank_card) { void bank_card_clear(BankCard* bank_card) { furi_assert(bank_card); - widget_clear(bank_card->widget); + widget_reset(bank_card->widget); } void bank_card_set_name(BankCard* bank_card, char* name) { diff --git a/applications/subghz/scenes/subghz_scene_delete.c b/applications/subghz/scenes/subghz_scene_delete.c index 9452946e360..46c33c723c8 100644 --- a/applications/subghz/scenes/subghz_scene_delete.c +++ b/applications/subghz/scenes/subghz_scene_delete.c @@ -65,5 +65,5 @@ bool subghz_scene_delete_on_event(void* context, SceneManagerEvent event) { void subghz_scene_delete_on_exit(void* context) { SubGhz* subghz = context; - widget_clear(subghz->widget); + widget_reset(subghz->widget); } diff --git a/applications/subghz/scenes/subghz_scene_delete_raw.c b/applications/subghz/scenes/subghz_scene_delete_raw.c index 8f3292c29f2..5dc293b34d7 100644 --- a/applications/subghz/scenes/subghz_scene_delete_raw.c +++ b/applications/subghz/scenes/subghz_scene_delete_raw.c @@ -73,5 +73,5 @@ bool subghz_scene_delete_raw_on_event(void* context, SceneManagerEvent event) { void subghz_scene_delete_raw_on_exit(void* context) { SubGhz* subghz = context; - widget_clear(subghz->widget); + widget_reset(subghz->widget); } diff --git a/applications/subghz/scenes/subghz_scene_need_saving.c b/applications/subghz/scenes/subghz_scene_need_saving.c index cab36dc4868..3d794bf4980 100644 --- a/applications/subghz/scenes/subghz_scene_need_saving.c +++ b/applications/subghz/scenes/subghz_scene_need_saving.c @@ -63,5 +63,5 @@ bool subghz_scene_need_saving_on_event(void* context, SceneManagerEvent event) { void subghz_scene_need_saving_on_exit(void* context) { SubGhz* subghz = context; - widget_clear(subghz->widget); + widget_reset(subghz->widget); } diff --git a/applications/subghz/scenes/subghz_scene_receiver_info.c b/applications/subghz/scenes/subghz_scene_receiver_info.c index 64d3633cf19..179316d1144 100644 --- a/applications/subghz/scenes/subghz_scene_receiver_info.c +++ b/applications/subghz/scenes/subghz_scene_receiver_info.c @@ -180,5 +180,5 @@ bool subghz_scene_receiver_info_on_event(void* context, SceneManagerEvent event) void subghz_scene_receiver_info_on_exit(void* context) { SubGhz* subghz = context; - widget_clear(subghz->widget); + widget_reset(subghz->widget); } diff --git a/applications/subghz/scenes/subghz_scene_show_error.c b/applications/subghz/scenes/subghz_scene_show_error.c index 1e450f1e4d0..697f6b9f476 100644 --- a/applications/subghz/scenes/subghz_scene_show_error.c +++ b/applications/subghz/scenes/subghz_scene_show_error.c @@ -79,6 +79,6 @@ void subghz_scene_show_error_on_exit(void* context) { SubGhz* subghz = context; scene_manager_set_scene_state( subghz->scene_manager, SubGhzSceneShowError, SubghzCustomEventManagerNoSet); - widget_clear(subghz->widget); + widget_reset(subghz->widget); string_reset(subghz->error_str); } diff --git a/applications/u2f/scenes/u2f_scene_error.c b/applications/u2f/scenes/u2f_scene_error.c index d0338568202..76406fbf179 100644 --- a/applications/u2f/scenes/u2f_scene_error.c +++ b/applications/u2f/scenes/u2f_scene_error.c @@ -45,5 +45,5 @@ bool u2f_scene_error_on_event(void* context, SceneManagerEvent event) { void u2f_scene_error_on_exit(void* context) { U2fApp* app = context; - widget_clear(app->widget); + widget_reset(app->widget); } diff --git a/debug/PyCortexMDebug/cmdebug/svd.py b/debug/PyCortexMDebug/cmdebug/svd.py index 10c9e0af631..f4a884bb4a5 100755 --- a/debug/PyCortexMDebug/cmdebug/svd.py +++ b/debug/PyCortexMDebug/cmdebug/svd.py @@ -16,14 +16,15 @@ along with PyCortexMDebug. If not, see . """ -import sys from collections import OrderedDict -import os -import pickle +from . import x2d + import traceback -import re import warnings -import x2d +import pickle +import sys +import os +import re class SmartDict: diff --git a/firmware/targets/f6/furi_hal/furi_hal_nfc.c b/firmware/targets/f6/furi_hal/furi_hal_nfc.c old mode 100644 new mode 100755 index be79aca1a36..c2560b75de1 --- a/firmware/targets/f6/furi_hal/furi_hal_nfc.c +++ b/firmware/targets/f6/furi_hal/furi_hal_nfc.c @@ -1,14 +1,25 @@ #include "furi_hal_nfc.h" #include +#include +#include +#include +#include #define TAG "FuriHalNfc" static const uint32_t clocks_in_ms = 64 * 1000; +osEventFlagsId_t event = NULL; +#define EVENT_FLAG_INTERRUPT (1UL << 0) +#define EVENT_FLAG_STATE_CHANGED (1UL << 1) +#define EVENT_FLAG_STOP (1UL << 2) +#define EVENT_FLAG_ALL (EVENT_FLAG_INTERRUPT | EVENT_FLAG_STATE_CHANGED | EVENT_FLAG_STOP) + void furi_hal_nfc_init() { ReturnCode ret = rfalNfcInitialize(); if(ret == ERR_NONE) { furi_hal_nfc_start_sleep(); + event = osEventFlagsNew(NULL); FURI_LOG_I(TAG, "Init OK"); } else { FURI_LOG_W(TAG, "Initialization failed, RFAL returned: %d", ret); @@ -140,6 +151,126 @@ bool furi_hal_nfc_listen( return true; } +void rfal_interrupt_callback_handler() { + osEventFlagsSet(event, EVENT_FLAG_INTERRUPT); +} + +void rfal_state_changed_callback(void* context) { + osEventFlagsSet(event, EVENT_FLAG_STATE_CHANGED); +} + +void furi_hal_nfc_stop() { + if(event) { + osEventFlagsSet(event, EVENT_FLAG_STOP); + } +} + +bool furi_hal_nfc_emulate_nfca( + uint8_t* uid, + uint8_t uid_len, + uint8_t* atqa, + uint8_t sak, + FuriHalNfcEmulateCallback callback, + void* context, + uint32_t timeout) { + rfalSetUpperLayerCallback(rfal_interrupt_callback_handler); + rfal_set_state_changed_callback(rfal_state_changed_callback); + + rfalLmConfPA config; + config.nfcidLen = uid_len; + memcpy(config.nfcid, uid, uid_len); + memcpy(config.SENS_RES, atqa, RFAL_LM_SENS_RES_LEN); + config.SEL_RES = sak; + uint8_t buff_rx[256]; + uint16_t buff_rx_size = 256; + uint16_t buff_rx_len = 0; + uint8_t buff_tx[256]; + uint16_t buff_tx_len = 0; + uint32_t data_type = FURI_HAL_NFC_TXRX_DEFAULT; + + rfalLowPowerModeStop(); + if(rfalListenStart( + RFAL_LM_MASK_NFCA, + &config, + NULL, + NULL, + buff_rx, + rfalConvBytesToBits(buff_rx_size), + &buff_rx_len)) { + rfalListenStop(); + FURI_LOG_E(TAG, "Failed to start listen mode"); + return false; + } + while(true) { + buff_rx_len = 0; + buff_tx_len = 0; + uint32_t flag = osEventFlagsWait(event, EVENT_FLAG_ALL, osFlagsWaitAny, timeout); + if(flag == osErrorTimeout || flag == EVENT_FLAG_STOP) { + break; + } + bool data_received = false; + buff_rx_len = 0; + rfalWorker(); + rfalLmState state = rfalListenGetState(&data_received, NULL); + if(data_received) { + rfalTransceiveBlockingRx(); + if(nfca_emulation_handler(buff_rx, buff_rx_len, buff_tx, &buff_tx_len)) { + if(rfalListenSleepStart( + RFAL_LM_STATE_SLEEP_A, + buff_rx, + rfalConvBytesToBits(buff_rx_size), + &buff_rx_len)) { + FURI_LOG_E(TAG, "Failed to enter sleep mode"); + break; + } else { + continue; + } + } + if(buff_tx_len) { + ReturnCode ret = rfalTransceiveBitsBlockingTx( + buff_tx, + buff_tx_len, + buff_rx, + sizeof(buff_rx), + &buff_rx_len, + data_type, + RFAL_FWT_NONE); + if(ret) { + FURI_LOG_E(TAG, "Tranceive failed with status %d", ret); + break; + } + continue; + } + if((state == RFAL_LM_STATE_ACTIVE_A || state == RFAL_LM_STATE_ACTIVE_Ax)) { + if(callback) { + callback(buff_rx, buff_rx_len, buff_tx, &buff_tx_len, &data_type, context); + } + if(!rfalIsExtFieldOn()) { + break; + } + if(buff_tx_len) { + ReturnCode ret = rfalTransceiveBitsBlockingTx( + buff_tx, + buff_tx_len, + buff_rx, + sizeof(buff_rx), + &buff_rx_len, + data_type, + RFAL_FWT_NONE); + if(ret) { + FURI_LOG_E(TAG, "Tranceive failed with status %d", ret); + continue; + } + } else { + break; + } + } + } + } + rfalListenStop(); + 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); diff --git a/firmware/targets/f7/furi_hal/furi_hal_nfc.c b/firmware/targets/f7/furi_hal/furi_hal_nfc.c old mode 100644 new mode 100755 index be79aca1a36..c2560b75de1 --- a/firmware/targets/f7/furi_hal/furi_hal_nfc.c +++ b/firmware/targets/f7/furi_hal/furi_hal_nfc.c @@ -1,14 +1,25 @@ #include "furi_hal_nfc.h" #include +#include +#include +#include +#include #define TAG "FuriHalNfc" static const uint32_t clocks_in_ms = 64 * 1000; +osEventFlagsId_t event = NULL; +#define EVENT_FLAG_INTERRUPT (1UL << 0) +#define EVENT_FLAG_STATE_CHANGED (1UL << 1) +#define EVENT_FLAG_STOP (1UL << 2) +#define EVENT_FLAG_ALL (EVENT_FLAG_INTERRUPT | EVENT_FLAG_STATE_CHANGED | EVENT_FLAG_STOP) + void furi_hal_nfc_init() { ReturnCode ret = rfalNfcInitialize(); if(ret == ERR_NONE) { furi_hal_nfc_start_sleep(); + event = osEventFlagsNew(NULL); FURI_LOG_I(TAG, "Init OK"); } else { FURI_LOG_W(TAG, "Initialization failed, RFAL returned: %d", ret); @@ -140,6 +151,126 @@ bool furi_hal_nfc_listen( return true; } +void rfal_interrupt_callback_handler() { + osEventFlagsSet(event, EVENT_FLAG_INTERRUPT); +} + +void rfal_state_changed_callback(void* context) { + osEventFlagsSet(event, EVENT_FLAG_STATE_CHANGED); +} + +void furi_hal_nfc_stop() { + if(event) { + osEventFlagsSet(event, EVENT_FLAG_STOP); + } +} + +bool furi_hal_nfc_emulate_nfca( + uint8_t* uid, + uint8_t uid_len, + uint8_t* atqa, + uint8_t sak, + FuriHalNfcEmulateCallback callback, + void* context, + uint32_t timeout) { + rfalSetUpperLayerCallback(rfal_interrupt_callback_handler); + rfal_set_state_changed_callback(rfal_state_changed_callback); + + rfalLmConfPA config; + config.nfcidLen = uid_len; + memcpy(config.nfcid, uid, uid_len); + memcpy(config.SENS_RES, atqa, RFAL_LM_SENS_RES_LEN); + config.SEL_RES = sak; + uint8_t buff_rx[256]; + uint16_t buff_rx_size = 256; + uint16_t buff_rx_len = 0; + uint8_t buff_tx[256]; + uint16_t buff_tx_len = 0; + uint32_t data_type = FURI_HAL_NFC_TXRX_DEFAULT; + + rfalLowPowerModeStop(); + if(rfalListenStart( + RFAL_LM_MASK_NFCA, + &config, + NULL, + NULL, + buff_rx, + rfalConvBytesToBits(buff_rx_size), + &buff_rx_len)) { + rfalListenStop(); + FURI_LOG_E(TAG, "Failed to start listen mode"); + return false; + } + while(true) { + buff_rx_len = 0; + buff_tx_len = 0; + uint32_t flag = osEventFlagsWait(event, EVENT_FLAG_ALL, osFlagsWaitAny, timeout); + if(flag == osErrorTimeout || flag == EVENT_FLAG_STOP) { + break; + } + bool data_received = false; + buff_rx_len = 0; + rfalWorker(); + rfalLmState state = rfalListenGetState(&data_received, NULL); + if(data_received) { + rfalTransceiveBlockingRx(); + if(nfca_emulation_handler(buff_rx, buff_rx_len, buff_tx, &buff_tx_len)) { + if(rfalListenSleepStart( + RFAL_LM_STATE_SLEEP_A, + buff_rx, + rfalConvBytesToBits(buff_rx_size), + &buff_rx_len)) { + FURI_LOG_E(TAG, "Failed to enter sleep mode"); + break; + } else { + continue; + } + } + if(buff_tx_len) { + ReturnCode ret = rfalTransceiveBitsBlockingTx( + buff_tx, + buff_tx_len, + buff_rx, + sizeof(buff_rx), + &buff_rx_len, + data_type, + RFAL_FWT_NONE); + if(ret) { + FURI_LOG_E(TAG, "Tranceive failed with status %d", ret); + break; + } + continue; + } + if((state == RFAL_LM_STATE_ACTIVE_A || state == RFAL_LM_STATE_ACTIVE_Ax)) { + if(callback) { + callback(buff_rx, buff_rx_len, buff_tx, &buff_tx_len, &data_type, context); + } + if(!rfalIsExtFieldOn()) { + break; + } + if(buff_tx_len) { + ReturnCode ret = rfalTransceiveBitsBlockingTx( + buff_tx, + buff_tx_len, + buff_rx, + sizeof(buff_rx), + &buff_rx_len, + data_type, + RFAL_FWT_NONE); + if(ret) { + FURI_LOG_E(TAG, "Tranceive failed with status %d", ret); + continue; + } + } else { + break; + } + } + } + } + rfalListenStop(); + 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); diff --git a/firmware/targets/furi_hal_include/furi_hal_nfc.h b/firmware/targets/furi_hal_include/furi_hal_nfc.h index 61d95e9037c..3d0c2024934 100644 --- a/firmware/targets/furi_hal_include/furi_hal_nfc.h +++ b/firmware/targets/furi_hal_include/furi_hal_nfc.h @@ -16,6 +16,26 @@ extern "C" { #define FURI_HAL_NFC_UID_MAX_LEN 10 +#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) + +#define FURI_HAL_NFC_TXRX_RAW \ + ((uint32_t)RFAL_TXRX_FLAGS_CRC_TX_MANUAL | (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_NONE | \ + (uint32_t)RFAL_TXRX_FLAGS_NFCV_FLAG_AUTO) + +typedef bool (*FuriHalNfcEmulateCallback)( + uint8_t* buff_rx, + uint16_t buff_rx_len, + uint8_t* buff_tx, + uint16_t* buff_tx_len, + uint32_t* flags, + void* context); + /** Init nfc */ void furi_hal_nfc_init(); @@ -76,6 +96,15 @@ bool furi_hal_nfc_listen( bool activate_after_sak, uint32_t timeout); +bool furi_hal_nfc_emulate_nfca( + uint8_t* uid, + uint8_t uid_len, + uint8_t* atqa, + uint8_t sak, + FuriHalNfcEmulateCallback callback, + void* context, + uint32_t timeout); + /** Get first command from reader after activation in emulation mode * * @param rx_buff pointer to receive buffer @@ -113,6 +142,8 @@ ReturnCode furi_hal_nfc_raw_bitstream_exchange( */ void furi_hal_nfc_deactivate(); +void furi_hal_nfc_stop(); + #ifdef __cplusplus } #endif diff --git a/lib/ST25RFAL002/include/rfal_rf.h b/lib/ST25RFAL002/include/rfal_rf.h index 014d184e68d..23c060a9a01 100644 --- a/lib/ST25RFAL002/include/rfal_rf.h +++ b/lib/ST25RFAL002/include/rfal_rf.h @@ -545,10 +545,13 @@ typedef struct { typedef void (*rfalUpperLayerCallback)(void); /*! Callback to be executed before a Transceive */ -typedef void (*rfalPreTxRxCallback)(void); +typedef void (*rfalPreTxRxCallback)(void* context); /*! Callback to be executed after a Transceive */ -typedef void (*rfalPostTxRxCallback)(void); +typedef void (*rfalPostTxRxCallback)(void* context); + +/** Callback to be executed on each RFAL state change */ +typedef void (*RfalStateChangedCallback)(void* context); /*******************************************************************************/ /* ISO14443A */ @@ -819,6 +822,19 @@ void rfalSetPreTxRxCallback(rfalPreTxRxCallback pFunc); */ void rfalSetPostTxRxCallback(rfalPostTxRxCallback pFunc); +/** Set RFAL state changed callback + * + * @param cb RfalStateChangedCallback instance + * @param ctx pointer to context + */ +void rfal_set_state_changed_callback(RfalStateChangedCallback callback); + +/** Set callback context + * + * @param ctx pointer to context + */ +void rfal_set_callback_context(void* context); + /*! ***************************************************************************** * \brief RFAL Deinitialize @@ -1480,6 +1496,15 @@ ReturnCode rfalTransceiveBlockingTxRx( uint32_t flags, uint32_t fwt); +ReturnCode rfalTransceiveBitsBlockingTx( + uint8_t* txBuf, + uint16_t txBufLen, + uint8_t* rxBuf, + uint16_t rxBufLen, + uint16_t* actLen, + uint32_t flags, + uint32_t fwt); + /***************************************************************************** * Listen Mode * *****************************************************************************/ diff --git a/lib/ST25RFAL002/source/st25r3916/rfal_rfst25r3916.c b/lib/ST25RFAL002/source/st25r3916/rfal_rfst25r3916.c index e7658fe9e51..9ad35bcb6bb 100644 --- a/lib/ST25RFAL002/source/st25r3916/rfal_rfst25r3916.c +++ b/lib/ST25RFAL002/source/st25r3916/rfal_rfst25r3916.c @@ -130,6 +130,8 @@ typedef struct { typedef struct { rfalPreTxRxCallback preTxRx; /*!< RFAL's Pre TxRx callback */ rfalPostTxRxCallback postTxRx; /*!< RFAL's Post TxRx callback */ + RfalStateChangedCallback state_changed_cb; + void* ctx; } rfalCallbacks; /*! Struct that holds counters to control the FIFO on Tx and Rx */ @@ -595,6 +597,8 @@ ReturnCode rfalInitialize(void) { gRFAL.callbacks.preTxRx = NULL; gRFAL.callbacks.postTxRx = NULL; + gRFAL.callbacks.state_changed_cb = NULL; + gRFAL.callbacks.ctx = NULL; #if RFAL_FEATURE_NFCV /* Initialize NFC-V Data */ @@ -669,6 +673,14 @@ void rfalSetPostTxRxCallback(rfalPostTxRxCallback pFunc) { gRFAL.callbacks.postTxRx = pFunc; } +void rfal_set_state_changed_callback(RfalStateChangedCallback callback) { + gRFAL.callbacks.state_changed_cb = callback; +} + +void rfal_set_callback_context(void* context) { + gRFAL.callbacks.ctx = context; +} + /*******************************************************************************/ ReturnCode rfalDeinitialize(void) { /* Deinitialize chip */ @@ -1520,6 +1532,30 @@ ReturnCode rfalTransceiveBlockingTx( return rfalTransceiveRunBlockingTx(); } +ReturnCode rfalTransceiveBitsBlockingTx( + uint8_t* txBuf, + uint16_t txBufLen, + uint8_t* rxBuf, + uint16_t rxBufLen, + uint16_t* actLen, + uint32_t flags, + uint32_t fwt) { + ReturnCode ret; + rfalTransceiveContext ctx = { + .rxBuf = rxBuf, + .rxBufLen = rxBufLen, + .rxRcvdLen = actLen, + .txBuf = txBuf, + .txBufLen = txBufLen, + .flags = flags, + .fwt = fwt, + }; + + EXIT_ON_ERR(ret, rfalStartTransceive(&ctx)); + + return rfalTransceiveRunBlockingTx(); +} + /*******************************************************************************/ static ReturnCode rfalTransceiveRunBlockingTx(void) { ReturnCode ret; @@ -1797,7 +1833,7 @@ static void rfalCleanupTransceive(void) { /* Execute Post Transceive Callback */ /*******************************************************************************/ if(gRFAL.callbacks.postTxRx != NULL) { - gRFAL.callbacks.postTxRx(); + gRFAL.callbacks.postTxRx(gRFAL.callbacks.ctx); } /*******************************************************************************/ } @@ -1838,7 +1874,7 @@ static void rfalPrepareTransceive(void) { /* Execute Pre Transceive Callback */ /*******************************************************************************/ if(gRFAL.callbacks.preTxRx != NULL) { - gRFAL.callbacks.preTxRx(); + gRFAL.callbacks.preTxRx(gRFAL.callbacks.ctx); } /*******************************************************************************/ @@ -4164,6 +4200,11 @@ ReturnCode rfalListenSetState(rfalLmState newSt) { gRFAL.Lm.state = newState; + // Call callback on state change + if(gRFAL.callbacks.state_changed_cb) { + gRFAL.callbacks.state_changed_cb(gRFAL.callbacks.ctx); + } + return ret; } diff --git a/lib/nfc_protocols/mifare_ultralight.c b/lib/nfc_protocols/mifare_ultralight.c index 96e18bd674e..a2e64017c88 100644 --- a/lib/nfc_protocols/mifare_ultralight.c +++ b/lib/nfc_protocols/mifare_ultralight.c @@ -1,4 +1,6 @@ #include "mifare_ultralight.h" +#include +#include bool mf_ul_check_card_type(uint8_t ATQA0, uint8_t ATQA1, uint8_t SAK) { if((ATQA0 == 0x44) && (ATQA1 == 0x00) && (SAK == 0x00)) { @@ -154,6 +156,7 @@ 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; @@ -197,11 +200,15 @@ void mf_ul_protect_auth_data_on_read_command( } } -uint16_t mf_ul_prepare_emulation_response( +bool mf_ul_prepare_emulation_response( uint8_t* buff_rx, - uint16_t len_rx, + uint16_t buff_rx_len, uint8_t* buff_tx, - MifareUlDevice* mf_ul_emulate) { + uint16_t* buff_tx_len, + uint32_t* data_type, + void* context) { + furi_assert(context); + MifareUlDevice* mf_ul_emulate = context; uint8_t cmd = buff_rx[0]; uint16_t page_num = mf_ul_emulate->data.data_size / 4; uint16_t tx_bytes = 0; @@ -211,12 +218,13 @@ uint16_t mf_ul_prepare_emulation_response( // Check composite commands if(mf_ul_emulate->comp_write_cmd_started) { // Compatibility write is the only one composit command - if(len_rx == 16) { + 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; // 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; @@ -224,6 +232,7 @@ uint16_t mf_ul_prepare_emulation_response( 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); + *data_type = FURI_HAL_NFC_TXRX_DEFAULT; command_parsed = true; } } else if(cmd == MF_UL_READ_CMD) { @@ -243,6 +252,7 @@ uint16_t mf_ul_prepare_emulation_response( } mf_ul_protect_auth_data_on_read_command( buff_tx, start_page, (start_page + 4), mf_ul_emulate); + *data_type = FURI_HAL_NFC_TXRX_DEFAULT; command_parsed = true; } } else if(cmd == MF_UL_FAST_READ_CMD) { @@ -254,6 +264,7 @@ uint16_t mf_ul_prepare_emulation_response( 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); + *data_type = FURI_HAL_NFC_TXRX_DEFAULT; command_parsed = true; } } @@ -265,6 +276,7 @@ uint16_t mf_ul_prepare_emulation_response( // ACK buff_tx[0] = 0x0A; tx_bits = 4; + *data_type = FURI_HAL_NFC_TXRX_RAW; command_parsed = true; } } else if(cmd == MF_UL_COMP_WRITE) { @@ -275,6 +287,7 @@ uint16_t mf_ul_prepare_emulation_response( // ACK buff_tx[0] = 0x0A; tx_bits = 4; + *data_type = FURI_HAL_NFC_TXRX_RAW; command_parsed = true; } } else if(cmd == MF_UL_READ_CNT) { @@ -284,6 +297,7 @@ uint16_t mf_ul_prepare_emulation_response( buff_tx[1] = mf_ul_emulate->data.counter[cnt_num] >> 8; buff_tx[2] = mf_ul_emulate->data.counter[cnt_num]; tx_bytes = 3; + *data_type = FURI_HAL_NFC_TXRX_DEFAULT; command_parsed = true; } } else if(cmd == MF_UL_INC_CNT) { @@ -295,6 +309,7 @@ uint16_t mf_ul_prepare_emulation_response( // ACK buff_tx[0] = 0x0A; tx_bits = 4; + *data_type = FURI_HAL_NFC_TXRX_RAW; command_parsed = true; } } else if(cmd == MF_UL_AUTH) { @@ -303,11 +318,13 @@ uint16_t mf_ul_prepare_emulation_response( buff_tx[0] = mf_ul_emulate->auth_data->pack.raw[0]; buff_tx[1] = mf_ul_emulate->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) { buff_tx[0] = 0x80; buff_tx[1] = 0x80; tx_bytes = 2; + *data_type = FURI_HAL_NFC_TXRX_DEFAULT; command_parsed = true; } } @@ -316,6 +333,7 @@ uint16_t mf_ul_prepare_emulation_response( if(buff_rx[1] == 0x00) { tx_bytes = sizeof(mf_ul_emulate->data.signature); memcpy(buff_tx, mf_ul_emulate->data.signature, tx_bytes); + *data_type = FURI_HAL_NFC_TXRX_DEFAULT; command_parsed = true; } } else if(cmd == MF_UL_CHECK_TEARING) { @@ -323,6 +341,7 @@ uint16_t mf_ul_prepare_emulation_response( if(cnt_num < 3) { buff_tx[0] = mf_ul_emulate->data.tearing[cnt_num]; tx_bytes = 1; + *data_type = FURI_HAL_NFC_TXRX_DEFAULT; command_parsed = true; } } else if(cmd == MF_UL_HALT_START) { @@ -334,10 +353,12 @@ uint16_t mf_ul_prepare_emulation_response( // Send NACK buff_tx[0] = 0x00; tx_bits = 4; + *data_type = FURI_HAL_NFC_TXRX_RAW; } // Return tx buffer size in bits if(tx_bytes) { tx_bits = tx_bytes * 8; } - return tx_bits; + *buff_tx_len = tx_bits; + return tx_bits > 0; } diff --git a/lib/nfc_protocols/mifare_ultralight.h b/lib/nfc_protocols/mifare_ultralight.h index bc7705efb55..06bab2223d1 100644 --- a/lib/nfc_protocols/mifare_ultralight.h +++ b/lib/nfc_protocols/mifare_ultralight.h @@ -116,8 +116,10 @@ void mf_ul_parse_fast_read_response( uint16_t mf_ul_prepare_write(uint8_t* dest, uint16_t page_addr, uint32_t data); void mf_ul_prepare_emulation(MifareUlDevice* mf_ul_emulate, MifareUlData* data); -uint16_t mf_ul_prepare_emulation_response( +bool mf_ul_prepare_emulation_response( uint8_t* buff_rx, - uint16_t len_rx, + uint16_t buff_rx_len, uint8_t* buff_tx, - MifareUlDevice* mf_ul_emulate); + uint16_t* buff_tx_len, + uint32_t* data_type, + void* context); \ No newline at end of file diff --git a/lib/nfc_protocols/nfca.c b/lib/nfc_protocols/nfca.c new file mode 100755 index 00000000000..1c165de5f5e --- /dev/null +++ b/lib/nfc_protocols/nfca.c @@ -0,0 +1,32 @@ +#include "nfca.h" +#include +#include + +#define NFCA_CMD_RATS (0xE0U) + +typedef struct { + uint8_t cmd; + uint8_t param; +} nfca_cmd_rats; + +static uint8_t nfca_default_ats[] = {0x05, 0x78, 0x80, 0x80, 0x00}; + +static uint8_t nfca_sleep_req[] = {0x50, 0x00}; + +bool nfca_emulation_handler( + uint8_t* buff_rx, + uint16_t buff_rx_len, + uint8_t* buff_tx, + uint16_t* buff_tx_len) { + bool sleep = false; + uint8_t rx_bytes = buff_rx_len / 8; + + if(rx_bytes == sizeof(nfca_sleep_req) && !memcmp(buff_rx, nfca_sleep_req, rx_bytes)) { + sleep = true; + } else if(rx_bytes == sizeof(nfca_cmd_rats) && buff_rx[0] == NFCA_CMD_RATS) { + memcpy(buff_tx, nfca_default_ats, sizeof(nfca_default_ats)); + *buff_tx_len = sizeof(nfca_default_ats) * 8; + } + + return sleep; +} \ No newline at end of file diff --git a/lib/nfc_protocols/nfca.h b/lib/nfc_protocols/nfca.h new file mode 100644 index 00000000000..0764a6c05c7 --- /dev/null +++ b/lib/nfc_protocols/nfca.h @@ -0,0 +1,10 @@ +#pragma once + +#include +#include + +bool nfca_emulation_handler( + uint8_t* buff_rx, + uint16_t buff_rx_len, + uint8_t* buff_tx, + uint16_t* buff_tx_len);