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 /firmware
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>
Diffstat (limited to 'firmware')
-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
3 files changed, 293 insertions, 0 deletions
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