Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/ClusterM/flipperzero-firmware.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorgornekich <n.gorbadey@gmail.com>2022-02-02 22:59:28 +0300
committerGitHub <noreply@github.com>2022-02-02 22:59:28 +0300
commit8cfd0eab9e5f99a41c2c79ab5c3c0c4afe253555 (patch)
treee6a664fb003996923009d11e148b35e0da15f9b6
parent838df4c9ea67d390e609d7919cbdc1ca0bb26412 (diff)
[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 <alleteam@gmail.com>
-rw-r--r--applications/bad_usb/scenes/bad_usb_scene_error.c2
-rw-r--r--applications/gui/elements.c3
-rwxr-xr-xapplications/gui/modules/text_box.c46
-rwxr-xr-x[-rw-r--r--]applications/gui/modules/text_box.h20
-rwxr-xr-xapplications/gui/modules/widget.c4
-rwxr-xr-xapplications/gui/modules/widget.h4
-rwxr-xr-xapplications/ibutton/scene/ibutton_scene_delete_confirm.cpp4
-rwxr-xr-xapplications/ibutton/scene/ibutton_scene_info.cpp2
-rw-r--r--applications/nfc/helpers/nfc_custom_event.h11
-rw-r--r--applications/nfc/nfc_device.h7
-rwxr-xr-xapplications/nfc/nfc_i.h1
-rwxr-xr-xapplications/nfc/nfc_worker.c95
-rwxr-xr-xapplications/nfc/scenes/nfc_scene_delete.c2
-rwxr-xr-xapplications/nfc/scenes/nfc_scene_delete_success.c6
-rwxr-xr-xapplications/nfc/scenes/nfc_scene_device_info.c26
-rwxr-xr-xapplications/nfc/scenes/nfc_scene_emulate_uid.c146
-rwxr-xr-xapplications/nfc/scenes/nfc_scene_read_card.c6
-rwxr-xr-xapplications/nfc/scenes/nfc_scene_read_card_success.c2
-rwxr-xr-xapplications/nfc/scenes/nfc_scene_read_emv_app.c6
-rwxr-xr-xapplications/nfc/scenes/nfc_scene_read_emv_data.c6
-rwxr-xr-xapplications/nfc/scenes/nfc_scene_read_emv_data_success.c2
-rwxr-xr-xapplications/nfc/scenes/nfc_scene_read_mifare_ul.c6
-rwxr-xr-xapplications/nfc/scenes/nfc_scene_read_mifare_ul_success.c46
-rw-r--r--applications/nfc/scenes/nfc_scene_restore_original.c6
-rwxr-xr-xapplications/nfc/scenes/nfc_scene_save_name.c6
-rwxr-xr-xapplications/nfc/scenes/nfc_scene_save_success.c6
-rwxr-xr-xapplications/nfc/scenes/nfc_scene_set_atqa.c6
-rwxr-xr-xapplications/nfc/scenes/nfc_scene_set_sak.c6
-rwxr-xr-xapplications/nfc/scenes/nfc_scene_set_uid.c6
-rwxr-xr-xapplications/nfc/views/bank_card.c2
-rw-r--r--applications/subghz/scenes/subghz_scene_delete.c2
-rw-r--r--applications/subghz/scenes/subghz_scene_delete_raw.c2
-rw-r--r--applications/subghz/scenes/subghz_scene_need_saving.c2
-rw-r--r--applications/subghz/scenes/subghz_scene_receiver_info.c2
-rw-r--r--applications/subghz/scenes/subghz_scene_show_error.c2
-rw-r--r--applications/u2f/scenes/u2f_scene_error.c2
-rwxr-xr-xdebug/PyCortexMDebug/cmdebug/svd.py11
-rwxr-xr-x[-rw-r--r--]firmware/targets/f6/furi_hal/furi_hal_nfc.c131
-rwxr-xr-x[-rw-r--r--]firmware/targets/f7/furi_hal/furi_hal_nfc.c131
-rw-r--r--firmware/targets/furi_hal_include/furi_hal_nfc.h31
-rw-r--r--lib/ST25RFAL002/include/rfal_rf.h29
-rw-r--r--lib/ST25RFAL002/source/st25r3916/rfal_rfst25r3916.c45
-rw-r--r--lib/nfc_protocols/mifare_ultralight.c31
-rw-r--r--lib/nfc_protocols/mifare_ultralight.h8
-rwxr-xr-xlib/nfc_protocols/nfca.c32
-rw-r--r--lib/nfc_protocols/nfca.h10
46 files changed, 715 insertions, 247 deletions
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
index 6928adcb..2a0548f2 100644..100755
--- 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 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"
@@ -55,10 +56,16 @@ typedef struct {
} 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 <nfc/scenes/nfc_scene.h>
+#include <nfc/helpers/nfc_custom_event.h>
#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 <dolphin/dolphin.h>
-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 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 <dolphin/dolphin.h>
-#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 <dolphin/dolphin.h>
-#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 <dolphin/dolphin.h>
-#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 <dolphin/dolphin.h>
-#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 <dolphin/dolphin.h>
#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 <lib/toolbox/random_name.h>
#include <gui/modules/validators.h>
-#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 <dolphin/dolphin.h>
-#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 <dolphin/dolphin.h>
-#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 <http://www.gnu.org/licenses/>.
"""
-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
index be79aca1..c2560b75 100644..100755
--- 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 <st25r3916.h>
+#include <rfal_rf.h>
+#include <furi.h>
+#include <m-string.h>
+#include <lib/nfc_protocols/nfca.h>
#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
index be79aca1..c2560b75 100644..100755
--- 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 <st25r3916.h>
+#include <rfal_rf.h>
+#include <furi.h>
+#include <m-string.h>
+#include <lib/nfc_protocols/nfca.h>
#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 <furi.h>
+#include <furi_hal_nfc.h>
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 <string.h>
+#include <stdio.h>
+
+#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 <stdint.h>
+#include <stdbool.h>
+
+bool nfca_emulation_handler(
+ uint8_t* buff_rx,
+ uint16_t buff_rx_len,
+ uint8_t* buff_tx,
+ uint16_t* buff_tx_len);