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:
Diffstat (limited to 'firmware/targets/f6/furi_hal/furi_hal_nfc.c')
-rw-r--r--firmware/targets/f6/furi_hal/furi_hal_nfc.c233
1 files changed, 233 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
new file mode 100644
index 00000000..be79aca1
--- /dev/null
+++ b/firmware/targets/f6/furi_hal/furi_hal_nfc.c
@@ -0,0 +1,233 @@
+#include "furi_hal_nfc.h"
+#include <st25r3916.h>
+
+#define TAG "FuriHalNfc"
+
+static const uint32_t clocks_in_ms = 64 * 1000;
+
+void furi_hal_nfc_init() {
+ ReturnCode ret = rfalNfcInitialize();
+ if(ret == ERR_NONE) {
+ furi_hal_nfc_start_sleep();
+ FURI_LOG_I(TAG, "Init OK");
+ } else {
+ FURI_LOG_W(TAG, "Initialization failed, RFAL returned: %d", ret);
+ }
+}
+
+bool furi_hal_nfc_is_busy() {
+ return rfalNfcGetState() != RFAL_NFC_STATE_IDLE;
+}
+
+void furi_hal_nfc_field_on() {
+ furi_hal_nfc_exit_sleep();
+ st25r3916TxRxOn();
+}
+
+void furi_hal_nfc_field_off() {
+ st25r3916TxRxOff();
+ furi_hal_nfc_start_sleep();
+}
+
+void furi_hal_nfc_start_sleep() {
+ rfalLowPowerModeStart();
+}
+
+void furi_hal_nfc_exit_sleep() {
+ rfalLowPowerModeStop();
+}
+
+bool furi_hal_nfc_detect(
+ rfalNfcDevice** dev_list,
+ uint8_t* dev_cnt,
+ uint32_t timeout,
+ bool deactivate) {
+ furi_assert(dev_list);
+ furi_assert(dev_cnt);
+
+ rfalLowPowerModeStop();
+ rfalNfcState state = rfalNfcGetState();
+ if(state == RFAL_NFC_STATE_NOTINIT) {
+ rfalNfcInitialize();
+ }
+ rfalNfcDiscoverParam params;
+ params.compMode = RFAL_COMPLIANCE_MODE_EMV;
+ params.techs2Find = RFAL_NFC_POLL_TECH_A | RFAL_NFC_POLL_TECH_B | RFAL_NFC_POLL_TECH_F |
+ RFAL_NFC_POLL_TECH_V | RFAL_NFC_POLL_TECH_AP2P | RFAL_NFC_POLL_TECH_ST25TB;
+ params.totalDuration = 1000;
+ params.devLimit = 3;
+ params.wakeupEnabled = false;
+ params.wakeupConfigDefault = true;
+ params.nfcfBR = RFAL_BR_212;
+ params.ap2pBR = RFAL_BR_424;
+ params.maxBR = RFAL_BR_KEEP;
+ params.GBLen = RFAL_NFCDEP_GB_MAX_LEN;
+ params.notifyCb = NULL;
+
+ uint32_t start = DWT->CYCCNT;
+ rfalNfcDiscover(&params);
+ while(state != RFAL_NFC_STATE_ACTIVATED) {
+ rfalNfcWorker();
+ state = rfalNfcGetState();
+ FURI_LOG_T(TAG, "Current state %d", state);
+ if(state == RFAL_NFC_STATE_POLL_ACTIVATION) {
+ start = DWT->CYCCNT;
+ continue;
+ }
+ if(state == RFAL_NFC_STATE_POLL_SELECT) {
+ rfalNfcSelect(0);
+ }
+ if(DWT->CYCCNT - start > timeout * clocks_in_ms) {
+ rfalNfcDeactivate(true);
+ FURI_LOG_T(TAG, "Timeout");
+ return false;
+ }
+ osThreadYield();
+ }
+ rfalNfcGetDevicesFound(dev_list, dev_cnt);
+ if(deactivate) {
+ rfalNfcDeactivate(false);
+ rfalLowPowerModeStart();
+ }
+ return true;
+}
+
+bool furi_hal_nfc_listen(
+ uint8_t* uid,
+ uint8_t uid_len,
+ uint8_t* atqa,
+ uint8_t sak,
+ bool activate_after_sak,
+ uint32_t timeout) {
+ rfalNfcState state = rfalNfcGetState();
+ if(state == RFAL_NFC_STATE_NOTINIT) {
+ rfalNfcInitialize();
+ } else if(state >= RFAL_NFC_STATE_ACTIVATED) {
+ rfalNfcDeactivate(false);
+ }
+ rfalLowPowerModeStop();
+ rfalNfcDiscoverParam params = {
+ .compMode = RFAL_COMPLIANCE_MODE_NFC,
+ .techs2Find = RFAL_NFC_LISTEN_TECH_A,
+ .totalDuration = 1000,
+ .devLimit = 1,
+ .wakeupEnabled = false,
+ .wakeupConfigDefault = true,
+ .nfcfBR = RFAL_BR_212,
+ .ap2pBR = RFAL_BR_424,
+ .maxBR = RFAL_BR_KEEP,
+ .GBLen = RFAL_NFCDEP_GB_MAX_LEN,
+ .notifyCb = NULL,
+ .activate_after_sak = activate_after_sak,
+ };
+ params.lmConfigPA.nfcidLen = uid_len;
+ memcpy(params.lmConfigPA.nfcid, uid, uid_len);
+ params.lmConfigPA.SENS_RES[0] = atqa[0];
+ params.lmConfigPA.SENS_RES[1] = atqa[1];
+ params.lmConfigPA.SEL_RES = sak;
+ rfalNfcDiscover(&params);
+
+ uint32_t start = DWT->CYCCNT;
+ while(state != RFAL_NFC_STATE_ACTIVATED) {
+ rfalNfcWorker();
+ state = rfalNfcGetState();
+ if(DWT->CYCCNT - start > timeout * clocks_in_ms) {
+ rfalNfcDeactivate(true);
+ return false;
+ }
+ osThreadYield();
+ }
+ return true;
+}
+
+bool furi_hal_nfc_get_first_frame(uint8_t** rx_buff, uint16_t** rx_len) {
+ ReturnCode ret =
+ rfalNfcDataExchangeStart(NULL, 0, rx_buff, rx_len, 0, RFAL_TXRX_FLAGS_DEFAULT);
+ return ret == ERR_NONE;
+}
+
+ReturnCode furi_hal_nfc_data_exchange(
+ uint8_t* tx_buff,
+ uint16_t tx_len,
+ uint8_t** rx_buff,
+ uint16_t** rx_len,
+ bool deactivate) {
+ furi_assert(rx_buff);
+ furi_assert(rx_len);
+
+ ReturnCode ret;
+ rfalNfcState state = RFAL_NFC_STATE_ACTIVATED;
+ ret = rfalNfcDataExchangeStart(tx_buff, tx_len, rx_buff, rx_len, 0, RFAL_TXRX_FLAGS_DEFAULT);
+ if(ret != ERR_NONE) {
+ return ret;
+ }
+ uint32_t start = DWT->CYCCNT;
+ while(state != RFAL_NFC_STATE_DATAEXCHANGE_DONE) {
+ rfalNfcWorker();
+ state = rfalNfcGetState();
+ ret = rfalNfcDataExchangeGetStatus();
+ if(ret > ERR_SLEEP_REQ) {
+ return ret;
+ }
+ if(ret == ERR_BUSY) {
+ if(DWT->CYCCNT - start > 1000 * clocks_in_ms) {
+ return ERR_TIMEOUT;
+ }
+ continue;
+ } else {
+ start = DWT->CYCCNT;
+ }
+ taskYIELD();
+ }
+ if(deactivate) {
+ rfalNfcDeactivate(false);
+ rfalLowPowerModeStart();
+ }
+ return ERR_NONE;
+}
+
+ReturnCode furi_hal_nfc_raw_bitstream_exchange(
+ uint8_t* tx_buff,
+ uint16_t tx_bit_len,
+ uint8_t** rx_buff,
+ uint16_t** rx_bit_len,
+ bool deactivate) {
+ furi_assert(rx_buff);
+ furi_assert(rx_bit_len);
+
+ ReturnCode ret;
+ rfalNfcState state = RFAL_NFC_STATE_ACTIVATED;
+ ret =
+ rfalNfcDataExchangeStart(tx_buff, tx_bit_len, rx_buff, rx_bit_len, 0, RFAL_TXRX_FLAGS_RAW);
+ if(ret != ERR_NONE) {
+ return ret;
+ }
+ uint32_t start = DWT->CYCCNT;
+ while(state != RFAL_NFC_STATE_DATAEXCHANGE_DONE) {
+ rfalNfcWorker();
+ state = rfalNfcGetState();
+ ret = rfalNfcDataExchangeGetStatus();
+ if(ret > ERR_SLEEP_REQ) {
+ return ret;
+ }
+ if(ret == ERR_BUSY) {
+ if(DWT->CYCCNT - start > 1000 * clocks_in_ms) {
+ return ERR_TIMEOUT;
+ }
+ continue;
+ } else {
+ start = DWT->CYCCNT;
+ }
+ taskYIELD();
+ }
+ if(deactivate) {
+ rfalNfcDeactivate(false);
+ rfalLowPowerModeStart();
+ }
+ return ERR_NONE;
+}
+
+void furi_hal_nfc_deactivate() {
+ rfalNfcDeactivate(false);
+ rfalLowPowerModeStart();
+}