diff --git a/applications/bad_usb/scenes/bad_usb_scene_error.c b/applications/bad_usb/scenes/bad_usb_scene_error.c index 6419ee37..52650022 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 5f39aa84..0cd341b3 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 40a8c382..7e7eacd6 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 6928adcb..2a0548f2 --- 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 +/** Set TextBox focus + * @note Use to display from start or from end * * @param text_box TextBox instance - * @param context context pointer + * @param focus TextBoxFocus instance */ -void text_box_set_context(TextBox* text_box, void* context); - -/** Set exit callback - * - * @param text_box TextBox instance - * @param callback TextBoxExitCallback callback pointer - */ -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 58ca7db2..d6c50aaa 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 4b4b0dd9..98a89435 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 4dc83b90..e5303d04 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 81c43c5d..a05d013f 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 00000000..5ef111b6 --- /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 cf0c389c..b26e6bf9 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 2c17df75..86164315 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 98d064ca..4f969188 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 57d777df..2661d166 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 96e70693..1392fa9e 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 4aea026b..e9d5bfda 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 a7af371c..79974f3f 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 +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); + } +} + +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, "")) { + 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); + } +} + void nfc_scene_emulate_uid_on_enter(void* context) { - Nfc* nfc = (Nfc*)context; + Nfc* nfc = context; DOLPHIN_DEED(DolphinDeedNfcEmulate); - // Setup view - Popup* popup = nfc->popup; - NfcDeviceCommonData* data = &nfc->dev->dev_data.nfc_data; + // 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); - 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]); - } - - 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); - - // Setup and start worker - - 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 10cf74f2..35b3b7bf 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 097cdd8d..260dccef 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 c6eff352..5e28c642 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 36f525f1..7fb2f09b 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 99912450..78078d05 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 c5b7c497..7bc7ea33 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 a7fcc2fc..b396fae1 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 12481592..8ddac366 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 c66484ff..f239baa8 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 67599c24..f8195d8c 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 1c682f18..85a70fe8 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 edeb27a9..11cfcf46 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 e23efe79..c5950129 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 07b4db58..ee54c4b0 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 9452946e..46c33c72 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 8f3292c2..5dc293b3 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 cab36dc4..3d794bf4 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 64d3633c..179316d1 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 1e450f1e..697f6b9f 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 d0338568..76406fbf 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 10c9e0af..f4a884bb 100755 --- a/debug/PyCortexMDebug/cmdebug/svd.py +++ b/debug/PyCortexMDebug/cmdebug/svd.py @@ -16,14 +16,15 @@ You should have received a copy of the GNU General Public License 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 be79aca1..c2560b75 --- 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 be79aca1..c2560b75 --- 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 61d95e90..3d0c2024 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 014d184e..23c060a9 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 e7658fe9..9ad35bcb 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 96e18bd6..a2e64017 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 bc7705ef..06bab222 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 00000000..1c165de5 --- /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 00000000..0764a6c0 --- /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);