diff options
author | gornekich <n.gorbadey@gmail.com> | 2022-05-24 17:00:15 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-05-24 17:00:15 +0300 |
commit | d31578508a95144cf5964878349a21aac642850d (patch) | |
tree | 6b206a5d43de87ef661933c6ce977dac7d800ccf /firmware | |
parent | 2017baac48939fc58344a2d60294a9d9e6513b64 (diff) |
[FL-2245] Introduce Mifare Classic Emulation (#1242)
* digital signal: introduce digital signal
* nfca: add nfca signal encoder
* nfc: add mifare classic emulation scene
* nfca: add classic emulation support to lib and hal
* mifare classic: support basic read commands
* nfc: add mifare classic menu scene
* mifare classic: start parsing commands in emulation
* mifare classic: add nested auth
* nfc: fix errors
* mifare classic: add encrypt function
* nfc: fix mifare classic save
* lib hex: add hex uint64_t ASCII parser
* flipper format: add uint64 hex format support
* nfc: add mifare classic key map
* nfc: hide mifare classic keys on emulation
* mifare classic: add NACK responce
* nfc: add partial bytes support in transparent mode
* nfc: mifare classic add shadow file support
* digital signal: move arr buffer from BSS to heap
* mifare classic: process access bits more careful
* nfca: fix memory leack
* nfc: format sources
* mifare classic: cleun up
Co-authored-by: あく <alleteam@gmail.com>
Diffstat (limited to 'firmware')
-rwxr-xr-x | firmware/targets/f7/furi_hal/furi_hal_nfc.c | 89 | ||||
-rwxr-xr-x | firmware/targets/furi_hal_include/furi_hal_nfc.h | 5 |
2 files changed, 92 insertions, 2 deletions
diff --git a/firmware/targets/f7/furi_hal/furi_hal_nfc.c b/firmware/targets/f7/furi_hal/furi_hal_nfc.c index 768a4bac..4391685e 100755 --- a/firmware/targets/f7/furi_hal/furi_hal_nfc.c +++ b/firmware/targets/f7/furi_hal/furi_hal_nfc.c @@ -1,9 +1,12 @@ #include "furi_hal_nfc.h" #include <st25r3916.h> +#include <st25r3916_irq.h> #include <rfal_rf.h> #include <furi.h> #include <m-string.h> -#include <lib/nfc_protocols/nfca.h> + +#include <lib/digital_signal/digital_signal.h> +#include <furi_hal_delay.h> #define TAG "FuriHalNfc" @@ -394,6 +397,80 @@ ReturnCode furi_hal_nfc_data_exchange( return ret; } +static bool furi_hal_nfc_transparent_tx_rx(FuriHalNfcTxRxContext* tx_rx, uint16_t timeout_ms) { + furi_assert(tx_rx->nfca_signal); + + platformDisableIrqCallback(); + + bool ret = false; + + // Start transparent mode + st25r3916ExecuteCommand(ST25R3916_CMD_TRANSPARENT_MODE); + // Reconfigure gpio + furi_hal_spi_bus_handle_deinit(&furi_hal_spi_bus_handle_nfc); + furi_hal_gpio_init(&gpio_spi_r_sck, GpioModeInput, GpioPullUp, GpioSpeedLow); + furi_hal_gpio_init(&gpio_spi_r_miso, GpioModeInput, GpioPullUp, GpioSpeedLow); + furi_hal_gpio_init(&gpio_nfc_cs, GpioModeInput, GpioPullUp, GpioSpeedLow); + furi_hal_gpio_init(&gpio_spi_r_mosi, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh); + furi_hal_gpio_write(&gpio_spi_r_mosi, false); + + // Send signal + nfca_signal_encode(tx_rx->nfca_signal, tx_rx->tx_data, tx_rx->tx_bits, tx_rx->tx_parity); + digital_signal_send(tx_rx->nfca_signal->tx_signal, &gpio_spi_r_mosi); + furi_hal_gpio_write(&gpio_spi_r_mosi, false); + + // Configure gpio back to SPI and exit transparent + furi_hal_spi_bus_handle_init(&furi_hal_spi_bus_handle_nfc); + st25r3916ExecuteCommand(ST25R3916_CMD_UNMASK_RECEIVE_DATA); + + // Manually wait for interrupt + furi_hal_gpio_init(&gpio_rfid_pull, GpioModeInput, GpioPullDown, GpioSpeedVeryHigh); + st25r3916ClearAndEnableInterrupts(ST25R3916_IRQ_MASK_RXE); + + uint32_t irq = 0; + uint8_t rxe = 0; + uint32_t start = DWT->CYCCNT; + while(true) { + if(furi_hal_gpio_read(&gpio_rfid_pull) == true) { + st25r3916ReadRegister(ST25R3916_REG_IRQ_MAIN, &rxe); + if(rxe & (1 << 4)) { + irq = 1; + break; + } + } + uint32_t timeout = DWT->CYCCNT - start; + if(timeout / furi_hal_delay_instructions_per_microsecond() > timeout_ms * 1000) { + FURI_LOG_D(TAG, "Interrupt waiting timeout"); + break; + } + } + if(irq) { + uint8_t fifo_stat[2]; + st25r3916ReadMultipleRegisters( + ST25R3916_REG_FIFO_STATUS1, fifo_stat, ST25R3916_FIFO_STATUS_LEN); + uint16_t len = + ((((uint16_t)fifo_stat[1] & ST25R3916_REG_FIFO_STATUS2_fifo_b_mask) >> + ST25R3916_REG_FIFO_STATUS2_fifo_b_shift) + << RFAL_BITS_IN_BYTE); + len |= (((uint16_t)fifo_stat[0]) & 0x00FFU); + uint8_t rx[100]; + st25r3916ReadFifo(rx, len); + + tx_rx->rx_bits = len * 8; + memcpy(tx_rx->rx_data, rx, len); + + ret = true; + } else { + FURI_LOG_E(TAG, "Timeout error"); + ret = false; + } + + st25r3916ClearInterrupts(); + platformEnableIrqCallback(); + + return ret; +} + static uint32_t furi_hal_nfc_tx_rx_get_flag(FuriHalNfcTxRxType type) { uint32_t flags = 0; @@ -405,6 +482,9 @@ static uint32_t furi_hal_nfc_tx_rx_get_flag(FuriHalNfcTxRxType type) { } else if(type == FuriHalNfcTxRxTypeRaw) { flags = RFAL_TXRX_FLAGS_CRC_TX_MANUAL | RFAL_TXRX_FLAGS_CRC_RX_KEEP | RFAL_TXRX_FLAGS_PAR_RX_KEEP | RFAL_TXRX_FLAGS_PAR_TX_NONE; + } else if(type == FuriHalNfcTxRxTypeRxRaw) { + flags = RFAL_TXRX_FLAGS_CRC_TX_MANUAL | RFAL_TXRX_FLAGS_CRC_RX_KEEP | + RFAL_TXRX_FLAGS_PAR_RX_KEEP | RFAL_TXRX_FLAGS_PAR_TX_NONE; } return flags; @@ -470,6 +550,10 @@ bool furi_hal_nfc_tx_rx(FuriHalNfcTxRxContext* tx_rx, uint16_t timeout_ms) { uint8_t* temp_rx_buff = NULL; uint16_t* temp_rx_bits = NULL; + if(tx_rx->tx_rx_type == FuriHalNfcTxRxTransparent) { + return furi_hal_nfc_transparent_tx_rx(tx_rx, timeout_ms); + } + // Prepare data for FIFO if necessary uint32_t flags = furi_hal_nfc_tx_rx_get_flag(tx_rx->tx_rx_type); if(tx_rx->tx_rx_type == FuriHalNfcTxRxTypeRaw) { @@ -502,7 +586,8 @@ bool furi_hal_nfc_tx_rx(FuriHalNfcTxRxContext* tx_rx, uint16_t timeout_ms) { osDelay(1); } - if(tx_rx->tx_rx_type == FuriHalNfcTxRxTypeRaw) { + if(tx_rx->tx_rx_type == FuriHalNfcTxRxTypeRaw || + tx_rx->tx_rx_type == FuriHalNfcTxRxTypeRxRaw) { tx_rx->rx_bits = 8 * furi_hal_nfc_bitstream_to_data_and_parity( temp_rx_buff, *temp_rx_bits, tx_rx->rx_data, tx_rx->rx_parity); } else { diff --git a/firmware/targets/furi_hal_include/furi_hal_nfc.h b/firmware/targets/furi_hal_include/furi_hal_nfc.h index 20a46900..860db80d 100755 --- a/firmware/targets/furi_hal_include/furi_hal_nfc.h +++ b/firmware/targets/furi_hal_include/furi_hal_nfc.h @@ -10,6 +10,8 @@ #include <stdbool.h> #include <stdint.h> +#include <lib/nfc_protocols/nfca.h> + #ifdef __cplusplus extern "C" { #endif @@ -39,6 +41,8 @@ typedef enum { FuriHalNfcTxRxTypeRxNoCrc, FuriHalNfcTxRxTypeRxKeepPar, FuriHalNfcTxRxTypeRaw, + FuriHalNfcTxRxTypeRxRaw, + FuriHalNfcTxRxTransparent, } FuriHalNfcTxRxType; typedef bool (*FuriHalNfcEmulateCallback)( @@ -80,6 +84,7 @@ typedef struct { uint8_t rx_parity[FURI_HAL_NFC_PARITY_BUFF_SIZE]; uint16_t rx_bits; FuriHalNfcTxRxType tx_rx_type; + NfcaSignal* nfca_signal; } FuriHalNfcTxRxContext; /** Init nfc |