mirror of
https://github.com/Next-Flip/Momentum-Firmware.git
synced 2026-05-12 17:58:36 -07:00
undo NfcA changes which might have looked better, but brought no reliability improvement
This commit is contained in:
@@ -368,7 +368,6 @@ void furi_hal_nfc_listen_start(FuriHalNfcDevData* nfc_data) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void furi_hal_nfcv_listen_start() {
|
void furi_hal_nfcv_listen_start() {
|
||||||
|
|
||||||
furi_hal_gpio_init(&gpio_nfc_irq_rfid_pull, GpioModeInput, GpioPullDown, GpioSpeedVeryHigh);
|
furi_hal_gpio_init(&gpio_nfc_irq_rfid_pull, GpioModeInput, GpioPullDown, GpioSpeedVeryHigh);
|
||||||
// Clear interrupts
|
// Clear interrupts
|
||||||
st25r3916ClearInterrupts();
|
st25r3916ClearInterrupts();
|
||||||
@@ -536,8 +535,9 @@ static bool furi_hal_nfc_transparent_tx_rx(FuriHalNfcTxRxContext* tx_rx, uint16_
|
|||||||
// Send signal
|
// Send signal
|
||||||
FURI_CRITICAL_ENTER();
|
FURI_CRITICAL_ENTER();
|
||||||
nfca_signal_encode(tx_rx->nfca_signal, tx_rx->tx_data, tx_rx->tx_bits, tx_rx->tx_parity);
|
nfca_signal_encode(tx_rx->nfca_signal, tx_rx->tx_data, tx_rx->tx_bits, tx_rx->tx_parity);
|
||||||
digital_sequence_send(tx_rx->nfca_signal->tx_signal);
|
digital_signal_send(tx_rx->nfca_signal->tx_signal, &gpio_spi_r_mosi);
|
||||||
FURI_CRITICAL_EXIT();
|
FURI_CRITICAL_EXIT();
|
||||||
|
furi_hal_gpio_write(&gpio_spi_r_mosi, false);
|
||||||
|
|
||||||
// Configure gpio back to SPI and exit transparent
|
// Configure gpio back to SPI and exit transparent
|
||||||
furi_hal_spi_bus_handle_init(&furi_hal_spi_bus_handle_nfc);
|
furi_hal_spi_bus_handle_init(&furi_hal_spi_bus_handle_nfc);
|
||||||
@@ -601,51 +601,6 @@ static bool furi_hal_nfc_transparent_tx_rx(FuriHalNfcTxRxContext* tx_rx, uint16_
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool furi_hal_nfc_fully_transparent_tx_rx(FuriHalNfcTxRxContext* tx_rx, uint16_t timeout_ms) {
|
|
||||||
furi_assert(tx_rx);
|
|
||||||
|
|
||||||
bool received = false;
|
|
||||||
|
|
||||||
tx_rx->rx_bits = 0;
|
|
||||||
|
|
||||||
if(tx_rx->tx_bits) {
|
|
||||||
nfca_trans_rx_pause(&tx_rx->nfca_trans_state);
|
|
||||||
FURI_CRITICAL_ENTER();
|
|
||||||
furi_hal_gpio_write(&gpio_spi_r_mosi, false);
|
|
||||||
nfca_signal_encode(tx_rx->nfca_signal, tx_rx->tx_data, tx_rx->tx_bits, tx_rx->tx_parity);
|
|
||||||
digital_sequence_send(tx_rx->nfca_signal->tx_signal);
|
|
||||||
furi_hal_gpio_write(&gpio_spi_r_mosi, false);
|
|
||||||
FURI_CRITICAL_EXIT();
|
|
||||||
nfca_trans_rx_continue(&tx_rx->nfca_trans_state);
|
|
||||||
|
|
||||||
if(tx_rx->sniff_tx) {
|
|
||||||
tx_rx->sniff_tx(tx_rx->tx_data, tx_rx->tx_bits, false, tx_rx->sniff_context);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(timeout_ms) {
|
|
||||||
tx_rx->nfca_trans_state.bits_received = 0;
|
|
||||||
received = nfca_trans_rx_loop(&tx_rx->nfca_trans_state, timeout_ms);
|
|
||||||
|
|
||||||
if(received) {
|
|
||||||
if(tx_rx->nfca_trans_state.bits_received > 7) {
|
|
||||||
tx_rx->rx_bits = tx_rx->nfca_trans_state.bits_received/9 * 8;
|
|
||||||
memcpy(tx_rx->rx_data, tx_rx->nfca_trans_state.frame_data, tx_rx->nfca_trans_state.bits_received/9);
|
|
||||||
} else {
|
|
||||||
tx_rx->rx_bits = tx_rx->nfca_trans_state.bits_received;
|
|
||||||
tx_rx->rx_data[0] = tx_rx->nfca_trans_state.frame_data[0] & ~(0xFF << tx_rx->rx_bits);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(tx_rx->sniff_rx) {
|
|
||||||
tx_rx->sniff_rx(tx_rx->rx_data, tx_rx->rx_bits, false, tx_rx->sniff_context);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return received;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static uint32_t furi_hal_nfc_tx_rx_get_flag(FuriHalNfcTxRxType type) {
|
static uint32_t furi_hal_nfc_tx_rx_get_flag(FuriHalNfcTxRxType type) {
|
||||||
uint32_t flags = 0;
|
uint32_t flags = 0;
|
||||||
|
|
||||||
@@ -719,26 +674,6 @@ uint16_t furi_hal_nfc_bitstream_to_data_and_parity(
|
|||||||
return curr_byte * 8;
|
return curr_byte * 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint8_t furi_hal_nfc_gen_parity(uint8_t value) {
|
|
||||||
value ^= (value >> 4);
|
|
||||||
value ^= (value >> 2);
|
|
||||||
value ^= (value >> 1);
|
|
||||||
|
|
||||||
return (value ^ 1) & 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void furi_hal_nfc_gen_bitstream(FuriHalNfcTxRxContext* tx_rx, uint8_t *buffer, size_t len) {
|
|
||||||
for(size_t pos = 0; pos < len; pos++) {
|
|
||||||
uint32_t parity_bit_num = pos % 8;
|
|
||||||
uint8_t bit = furi_hal_nfc_gen_parity(buffer[pos]);
|
|
||||||
|
|
||||||
tx_rx->tx_data[pos] = buffer[pos];
|
|
||||||
tx_rx->tx_parity[pos / 8] &= ~(1 << (7 - parity_bit_num));
|
|
||||||
tx_rx->tx_parity[pos / 8] |= bit << (7 - parity_bit_num);
|
|
||||||
}
|
|
||||||
tx_rx->tx_bits = len * 8;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool furi_hal_nfc_tx_rx(FuriHalNfcTxRxContext* tx_rx, uint16_t timeout_ms) {
|
bool furi_hal_nfc_tx_rx(FuriHalNfcTxRxContext* tx_rx, uint16_t timeout_ms) {
|
||||||
furi_assert(tx_rx);
|
furi_assert(tx_rx);
|
||||||
|
|
||||||
@@ -749,11 +684,6 @@ bool furi_hal_nfc_tx_rx(FuriHalNfcTxRxContext* tx_rx, uint16_t timeout_ms) {
|
|||||||
uint8_t* temp_rx_buff = NULL;
|
uint8_t* temp_rx_buff = NULL;
|
||||||
uint16_t* temp_rx_bits = NULL;
|
uint16_t* temp_rx_bits = NULL;
|
||||||
|
|
||||||
/* send and receive data using transparent mode */
|
|
||||||
if(tx_rx->tx_rx_type == FuriHalNfcTxRxFullyTransparent) {
|
|
||||||
return furi_hal_nfc_fully_transparent_tx_rx(tx_rx, timeout_ms);
|
|
||||||
}
|
|
||||||
/* send data using transparent mode and receive data in standard mode */
|
|
||||||
if(tx_rx->tx_rx_type == FuriHalNfcTxRxTransparent) {
|
if(tx_rx->tx_rx_type == FuriHalNfcTxRxTransparent) {
|
||||||
return furi_hal_nfc_transparent_tx_rx(tx_rx, timeout_ms);
|
return furi_hal_nfc_transparent_tx_rx(tx_rx, timeout_ms);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ extern "C" {
|
|||||||
#endif
|
#endif
|
||||||
#include <rfal_nfc.h>
|
#include <rfal_nfc.h>
|
||||||
#include <lib/nfc/protocols/nfca.h>
|
#include <lib/nfc/protocols/nfca.h>
|
||||||
#include <lib/nfc/protocols/nfca_trans_rx.h>
|
|
||||||
|
|
||||||
#define FURI_HAL_NFC_UID_MAX_LEN 10
|
#define FURI_HAL_NFC_UID_MAX_LEN 10
|
||||||
#define FURI_HAL_NFC_DATA_BUFF_SIZE (512)
|
#define FURI_HAL_NFC_DATA_BUFF_SIZE (512)
|
||||||
@@ -47,7 +46,6 @@ typedef enum {
|
|||||||
FuriHalNfcTxRxTypeRaw,
|
FuriHalNfcTxRxTypeRaw,
|
||||||
FuriHalNfcTxRxTypeRxRaw,
|
FuriHalNfcTxRxTypeRxRaw,
|
||||||
FuriHalNfcTxRxTransparent,
|
FuriHalNfcTxRxTransparent,
|
||||||
FuriHalNfcTxRxFullyTransparent
|
|
||||||
} FuriHalNfcTxRxType;
|
} FuriHalNfcTxRxType;
|
||||||
|
|
||||||
typedef bool (*FuriHalNfcEmulateCallback)(
|
typedef bool (*FuriHalNfcEmulateCallback)(
|
||||||
@@ -93,8 +91,6 @@ typedef struct {
|
|||||||
uint16_t rx_bits;
|
uint16_t rx_bits;
|
||||||
FuriHalNfcTxRxType tx_rx_type;
|
FuriHalNfcTxRxType tx_rx_type;
|
||||||
NfcaSignal* nfca_signal;
|
NfcaSignal* nfca_signal;
|
||||||
NfcaTransRxState nfca_trans_state;
|
|
||||||
bool nfca_trans_initialized;
|
|
||||||
|
|
||||||
FuriHalNfcTxRxSniffCallback sniff_tx;
|
FuriHalNfcTxRxSniffCallback sniff_tx;
|
||||||
FuriHalNfcTxRxSniffCallback sniff_rx;
|
FuriHalNfcTxRxSniffCallback sniff_rx;
|
||||||
@@ -429,9 +425,6 @@ FuriHalNfcReturn furi_hal_nfc_ll_txrx_bits(
|
|||||||
|
|
||||||
void furi_hal_nfc_ll_poll();
|
void furi_hal_nfc_ll_poll();
|
||||||
|
|
||||||
|
|
||||||
void furi_hal_nfc_gen_bitstream(FuriHalNfcTxRxContext* tx_rx, uint8_t *buffer, size_t len);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -6,7 +6,6 @@
|
|||||||
|
|
||||||
#define TAG "NfcWorker"
|
#define TAG "NfcWorker"
|
||||||
|
|
||||||
|
|
||||||
/***************************** NFC Worker API *******************************/
|
/***************************** NFC Worker API *******************************/
|
||||||
|
|
||||||
NfcWorker* nfc_worker_alloc() {
|
NfcWorker* nfc_worker_alloc() {
|
||||||
@@ -94,8 +93,6 @@ int32_t nfc_worker_task(void* context) {
|
|||||||
nfc_worker_read(nfc_worker);
|
nfc_worker_read(nfc_worker);
|
||||||
} else if(nfc_worker->state == NfcWorkerStateUidEmulate) {
|
} else if(nfc_worker->state == NfcWorkerStateUidEmulate) {
|
||||||
nfc_worker_emulate_uid(nfc_worker);
|
nfc_worker_emulate_uid(nfc_worker);
|
||||||
} else if(nfc_worker->state == NfcWorkerStateNfcVEmulate) {
|
|
||||||
nfc_worker_emulate_nfcv(nfc_worker);
|
|
||||||
} else if(nfc_worker->state == NfcWorkerStateEmulateApdu) {
|
} else if(nfc_worker->state == NfcWorkerStateEmulateApdu) {
|
||||||
nfc_worker_emulate_apdu(nfc_worker);
|
nfc_worker_emulate_apdu(nfc_worker);
|
||||||
} else if(nfc_worker->state == NfcWorkerStateMfUltralightEmulate) {
|
} else if(nfc_worker->state == NfcWorkerStateMfUltralightEmulate) {
|
||||||
@@ -112,6 +109,8 @@ int32_t nfc_worker_task(void* context) {
|
|||||||
nfc_worker_mf_classic_dict_attack(nfc_worker);
|
nfc_worker_mf_classic_dict_attack(nfc_worker);
|
||||||
} else if(nfc_worker->state == NfcWorkerStateAnalyzeReader) {
|
} else if(nfc_worker->state == NfcWorkerStateAnalyzeReader) {
|
||||||
nfc_worker_analyze_reader(nfc_worker);
|
nfc_worker_analyze_reader(nfc_worker);
|
||||||
|
} else if(nfc_worker->state == NfcWorkerStateNfcVEmulate) {
|
||||||
|
nfc_worker_emulate_nfcv(nfc_worker);
|
||||||
} else if(nfc_worker->state == NfcWorkerStateNfcVUnlock) {
|
} else if(nfc_worker->state == NfcWorkerStateNfcVUnlock) {
|
||||||
nfc_worker_nfcv_unlock(nfc_worker);
|
nfc_worker_nfcv_unlock(nfc_worker);
|
||||||
} else if(nfc_worker->state == NfcWorkerStateNfcVUnlockAndSave) {
|
} else if(nfc_worker->state == NfcWorkerStateNfcVUnlockAndSave) {
|
||||||
@@ -894,98 +893,8 @@ void nfc_worker_emulate_mf_classic(NfcWorker* nfc_worker) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
nfca_signal_free(nfca_signal);
|
nfca_signal_free(nfca_signal);
|
||||||
}
|
|
||||||
|
|
||||||
/* software-defined variant of MFC emulation, seems to also struggle with frame errors etc */
|
|
||||||
void nfc_worker_emulate_mf_classic_trans(NfcWorker* nfc_worker) {
|
|
||||||
FuriHalNfcTxRxContext tx_rx = {};
|
|
||||||
FuriHalNfcDevData* nfc_data = &nfc_worker->dev_data->nfc_data;
|
|
||||||
MfClassicEmulator emulator = {
|
|
||||||
.cuid = nfc_util_bytes2num(&nfc_data->uid[nfc_data->uid_len - 4], 4),
|
|
||||||
.data = nfc_worker->dev_data->mf_classic_data,
|
|
||||||
.data_changed = false,
|
|
||||||
};
|
|
||||||
NfcaSignal* nfca_signal = nfca_signal_alloc();
|
|
||||||
tx_rx.nfca_signal = nfca_signal;
|
|
||||||
|
|
||||||
rfal_platform_spi_acquire();
|
|
||||||
|
|
||||||
furi_hal_nfc_listen_start(nfc_data);
|
|
||||||
nfca_trans_rx_init(&tx_rx.nfca_trans_state);
|
|
||||||
|
|
||||||
/* we are usingthe fully transparent ISO14443-A mode */
|
|
||||||
tx_rx.tx_rx_type = FuriHalNfcTxRxFullyTransparent;
|
|
||||||
|
|
||||||
/* prepare some answers to save time */
|
|
||||||
uint8_t tx_buffer_aticoll[32];
|
|
||||||
memcpy(tx_buffer_aticoll, &nfc_data->uid, 4);
|
|
||||||
nfca_append_crc16(tx_buffer_aticoll, 4);
|
|
||||||
|
|
||||||
uint8_t tx_buffer_ack[8];
|
|
||||||
tx_buffer_ack[0] = nfc_data->sak;
|
|
||||||
nfca_append_crc16(tx_buffer_ack, 1);
|
|
||||||
|
|
||||||
while(nfc_worker->state == NfcWorkerStateMfClassicEmulate) {
|
|
||||||
tx_rx.tx_bits = 0;
|
|
||||||
tx_rx.rx_bits = 0;
|
|
||||||
if(furi_hal_nfc_tx_rx(&tx_rx, 300)) {
|
|
||||||
if(tx_rx.rx_bits == 7) {
|
|
||||||
switch(tx_rx.rx_data[0]) {
|
|
||||||
/* MAGIC WUPC1 */
|
|
||||||
case 0x40:
|
|
||||||
continue;
|
|
||||||
|
|
||||||
/* WUPA */
|
|
||||||
case 0x52:
|
|
||||||
furi_hal_nfc_gen_bitstream(&tx_rx, nfc_data->atqa, 2);
|
|
||||||
furi_hal_nfc_tx_rx(&tx_rx, 0);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(tx_rx.rx_bits >= 16) {
|
|
||||||
switch(tx_rx.rx_data[0]) {
|
|
||||||
/* SELECT */
|
|
||||||
case 0x93:
|
|
||||||
switch(tx_rx.rx_data[1]) {
|
|
||||||
/* ANTICOLL */
|
|
||||||
case 0x20:
|
|
||||||
furi_hal_nfc_gen_bitstream(&tx_rx, tx_buffer_aticoll, 6);
|
|
||||||
furi_hal_nfc_tx_rx(&tx_rx, 0);
|
|
||||||
continue;
|
|
||||||
|
|
||||||
/* SELECT UID */
|
|
||||||
case 0x70:
|
|
||||||
furi_hal_nfc_gen_bitstream(&tx_rx, tx_buffer_ack, 3);
|
|
||||||
furi_hal_nfc_tx_rx(&tx_rx, 0);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
/* HALS */
|
|
||||||
case 0x50:
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
mf_classic_emulator(&emulator, &tx_rx);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(emulator.data_changed) {
|
|
||||||
nfc_worker->dev_data->mf_classic_data = emulator.data;
|
|
||||||
if(nfc_worker->callback) {
|
|
||||||
nfc_worker->callback(NfcWorkerEventSuccess, nfc_worker->context);
|
|
||||||
}
|
|
||||||
emulator.data_changed = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
nfca_trans_rx_deinit(&tx_rx.nfca_trans_state);
|
|
||||||
|
|
||||||
rfal_platform_spi_release();
|
rfal_platform_spi_release();
|
||||||
|
|
||||||
|
|
||||||
nfca_signal_free(nfca_signal);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void nfc_worker_write_mf_classic(NfcWorker* nfc_worker) {
|
void nfc_worker_write_mf_classic(NfcWorker* nfc_worker) {
|
||||||
|
|||||||
@@ -93,3 +93,4 @@ void nfc_worker_start(
|
|||||||
void nfc_worker_stop(NfcWorker* nfc_worker);
|
void nfc_worker_stop(NfcWorker* nfc_worker);
|
||||||
void nfc_worker_nfcv_unlock(NfcWorker* nfc_worker);
|
void nfc_worker_nfcv_unlock(NfcWorker* nfc_worker);
|
||||||
void nfc_worker_emulate_nfcv(NfcWorker* nfc_worker);
|
void nfc_worker_emulate_nfcv(NfcWorker* nfc_worker);
|
||||||
|
|
||||||
|
|||||||
@@ -12,7 +12,6 @@
|
|||||||
#include <lib/nfc/protocols/mifare_classic.h>
|
#include <lib/nfc/protocols/mifare_classic.h>
|
||||||
#include <lib/nfc/protocols/mifare_desfire.h>
|
#include <lib/nfc/protocols/mifare_desfire.h>
|
||||||
#include <lib/nfc/protocols/nfca.h>
|
#include <lib/nfc/protocols/nfca.h>
|
||||||
#include <lib/nfc/protocols/nfca_trans_rx.h>
|
|
||||||
#include <lib/nfc/protocols/nfcv.h>
|
#include <lib/nfc/protocols/nfcv.h>
|
||||||
#include <lib/nfc/protocols/slix.h>
|
#include <lib/nfc/protocols/slix.h>
|
||||||
#include <lib/nfc/helpers/reader_analyzer.h>
|
#include <lib/nfc/helpers/reader_analyzer.h>
|
||||||
|
|||||||
@@ -2,27 +2,19 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <furi.h>
|
#include <furi.h>
|
||||||
#include <furi_hal_gpio.h>
|
|
||||||
#include <furi_hal_resources.h>
|
|
||||||
|
|
||||||
#define NFCA_CMD_RATS (0xE0U)
|
#define NFCA_CMD_RATS (0xE0U)
|
||||||
|
|
||||||
#define NFCA_CRC_INIT (0x6363)
|
#define NFCA_CRC_INIT (0x6363)
|
||||||
|
|
||||||
#define NFCA_F_SIG (13560000.0) /* [Hz] NFC frequency */
|
#define NFCA_F_SIG (13560000.0)
|
||||||
#define NFCA_F_SUB (NFCA_F_SIG/16) /* [Hz] NFC subcarrier frequency fs/16 (847500 Hz) */
|
#define T_SIG 7374 //73.746ns*100
|
||||||
#define T_SUB (1000000000000.0f / NFCA_F_SUB) /* [ps] subcarrier period = 1/NFCA_F_SUB (1.18 µs) */
|
#define T_SIG_x8 58992 //T_SIG*8
|
||||||
#define T_SUB_PHASE (T_SUB/2) /* [ps] a single subcarrier phase (590 µs) */
|
#define T_SIG_x8_x8 471936 //T_SIG*8*8
|
||||||
|
#define T_SIG_x8_x9 530928 //T_SIG*8*9
|
||||||
|
|
||||||
#define NFCA_SIGNAL_MAX_EDGES (1350)
|
#define NFCA_SIGNAL_MAX_EDGES (1350)
|
||||||
|
|
||||||
#define SEQ_SOF 0
|
|
||||||
#define SEQ_BIT0 1
|
|
||||||
#define SEQ_BIT1 2
|
|
||||||
#define SEQ_EOF 3
|
|
||||||
#define SEQ_IDLE 4
|
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint8_t cmd;
|
uint8_t cmd;
|
||||||
uint8_t param;
|
uint8_t param;
|
||||||
@@ -71,69 +63,46 @@ bool nfca_emulation_handler(
|
|||||||
return sleep;
|
return sleep;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void nfca_add_bit(DigitalSignal* signal, bool bit) {
|
||||||
|
if(bit) {
|
||||||
|
signal->start_level = true;
|
||||||
|
for(size_t i = 0; i < 7; i++) {
|
||||||
|
signal->edge_timings[i] = T_SIG_x8;
|
||||||
|
}
|
||||||
|
signal->edge_timings[7] = T_SIG_x8_x9;
|
||||||
|
signal->edge_cnt = 8;
|
||||||
|
} else {
|
||||||
|
signal->start_level = false;
|
||||||
|
signal->edge_timings[0] = T_SIG_x8_x8;
|
||||||
|
for(size_t i = 1; i < 9; i++) {
|
||||||
|
signal->edge_timings[i] = T_SIG_x8;
|
||||||
|
}
|
||||||
|
signal->edge_cnt = 9;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void nfca_add_byte(NfcaSignal* nfca_signal, uint8_t byte, bool parity) {
|
static void nfca_add_byte(NfcaSignal* nfca_signal, uint8_t byte, bool parity) {
|
||||||
for(uint8_t i = 0; i < 8; i++) {
|
for(uint8_t i = 0; i < 8; i++) {
|
||||||
if(byte & (1 << i)) {
|
if(byte & (1 << i)) {
|
||||||
digital_sequence_add(nfca_signal->tx_signal, SEQ_BIT1);
|
digital_signal_append(nfca_signal->tx_signal, nfca_signal->one);
|
||||||
} else {
|
} else {
|
||||||
digital_sequence_add(nfca_signal->tx_signal, SEQ_BIT0);
|
digital_signal_append(nfca_signal->tx_signal, nfca_signal->zero);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(parity) {
|
if(parity) {
|
||||||
digital_sequence_add(nfca_signal->tx_signal, SEQ_BIT1);
|
digital_signal_append(nfca_signal->tx_signal, nfca_signal->one);
|
||||||
} else {
|
} else {
|
||||||
digital_sequence_add(nfca_signal->tx_signal, SEQ_BIT0);
|
digital_signal_append(nfca_signal->tx_signal, nfca_signal->zero);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void nfca_add_modulation(DigitalSignal* signal, size_t phases) {
|
|
||||||
for(size_t i = 0; i < phases; i++) {
|
|
||||||
signal->edge_timings[signal->edge_cnt++] = DIGITAL_SIGNAL_PS(T_SUB_PHASE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void nfca_add_silence(DigitalSignal* signal, size_t phases) {
|
|
||||||
bool end_level = signal->start_level ^ ((signal->edge_cnt % 2) == 0);
|
|
||||||
|
|
||||||
if((signal->edge_cnt == 0) || end_level) {
|
|
||||||
signal->edge_timings[signal->edge_cnt++] = DIGITAL_SIGNAL_PS(phases * T_SUB_PHASE);
|
|
||||||
} else {
|
|
||||||
signal->edge_timings[signal->edge_cnt - 1] += DIGITAL_SIGNAL_PS(phases * T_SUB_PHASE);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
NfcaSignal* nfca_signal_alloc() {
|
NfcaSignal* nfca_signal_alloc() {
|
||||||
NfcaSignal* nfca_signal = malloc(sizeof(NfcaSignal));
|
NfcaSignal* nfca_signal = malloc(sizeof(NfcaSignal));
|
||||||
|
nfca_signal->one = digital_signal_alloc(10);
|
||||||
/* ISO14443-2 defines 3 sequences for type A communication */
|
nfca_signal->zero = digital_signal_alloc(10);
|
||||||
nfca_signal->seq_d = digital_signal_alloc(10);
|
nfca_add_bit(nfca_signal->one, true);
|
||||||
nfca_signal->seq_e = digital_signal_alloc(10);
|
nfca_add_bit(nfca_signal->zero, false);
|
||||||
nfca_signal->seq_f = digital_signal_alloc(10);
|
nfca_signal->tx_signal = digital_signal_alloc(NFCA_SIGNAL_MAX_EDGES);
|
||||||
|
|
||||||
/* SEQ D has the first half modulated, used as SOF */
|
|
||||||
nfca_signal->seq_d->start_level = true;
|
|
||||||
nfca_add_modulation(nfca_signal->seq_d, 8);
|
|
||||||
nfca_add_silence(nfca_signal->seq_d, 8);
|
|
||||||
|
|
||||||
/* SEQ E has the second half modulated */
|
|
||||||
nfca_signal->seq_e->start_level = false;
|
|
||||||
nfca_add_silence(nfca_signal->seq_e, 8);
|
|
||||||
nfca_add_modulation(nfca_signal->seq_e, 8);
|
|
||||||
|
|
||||||
/* SEQ F is just no modulation, used as EOF */
|
|
||||||
nfca_signal->seq_f->start_level = false;
|
|
||||||
nfca_add_silence(nfca_signal->seq_f, 16);
|
|
||||||
|
|
||||||
nfca_signal->tx_signal = digital_sequence_alloc(NFCA_SIGNAL_MAX_EDGES, &gpio_spi_r_mosi);
|
|
||||||
|
|
||||||
/* we are dealing with shorter sequences, enable bake-before-sending */
|
|
||||||
//nfca_signal->tx_signal->bake = true;
|
|
||||||
|
|
||||||
digital_sequence_set_signal(nfca_signal->tx_signal, SEQ_SOF, nfca_signal->seq_d);
|
|
||||||
digital_sequence_set_signal(nfca_signal->tx_signal, SEQ_BIT0, nfca_signal->seq_e);
|
|
||||||
digital_sequence_set_signal(nfca_signal->tx_signal, SEQ_BIT1, nfca_signal->seq_d);
|
|
||||||
digital_sequence_set_signal(nfca_signal->tx_signal, SEQ_EOF, nfca_signal->seq_f);
|
|
||||||
digital_sequence_set_signal(nfca_signal->tx_signal, SEQ_IDLE, nfca_signal->seq_f);
|
|
||||||
|
|
||||||
return nfca_signal;
|
return nfca_signal;
|
||||||
}
|
}
|
||||||
@@ -141,10 +110,9 @@ NfcaSignal* nfca_signal_alloc() {
|
|||||||
void nfca_signal_free(NfcaSignal* nfca_signal) {
|
void nfca_signal_free(NfcaSignal* nfca_signal) {
|
||||||
furi_assert(nfca_signal);
|
furi_assert(nfca_signal);
|
||||||
|
|
||||||
digital_signal_free(nfca_signal->seq_d);
|
digital_signal_free(nfca_signal->one);
|
||||||
digital_signal_free(nfca_signal->seq_e);
|
digital_signal_free(nfca_signal->zero);
|
||||||
digital_signal_free(nfca_signal->seq_f);
|
digital_signal_free(nfca_signal->tx_signal);
|
||||||
digital_sequence_free(nfca_signal->tx_signal);
|
|
||||||
free(nfca_signal);
|
free(nfca_signal);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -153,18 +121,17 @@ void nfca_signal_encode(NfcaSignal* nfca_signal, uint8_t* data, uint16_t bits, u
|
|||||||
furi_assert(data);
|
furi_assert(data);
|
||||||
furi_assert(parity);
|
furi_assert(parity);
|
||||||
|
|
||||||
digital_sequence_clear(nfca_signal->tx_signal);
|
nfca_signal->tx_signal->edge_cnt = 0;
|
||||||
|
nfca_signal->tx_signal->start_level = true;
|
||||||
/* add some idle bit times before SOF in case the GPIO was active */
|
// Start of frame
|
||||||
digital_sequence_add(nfca_signal->tx_signal, SEQ_IDLE);
|
digital_signal_append(nfca_signal->tx_signal, nfca_signal->one);
|
||||||
digital_sequence_add(nfca_signal->tx_signal, SEQ_SOF);
|
|
||||||
|
|
||||||
if(bits < 8) {
|
if(bits < 8) {
|
||||||
for(size_t i = 0; i < bits; i++) {
|
for(size_t i = 0; i < bits; i++) {
|
||||||
if(FURI_BIT(data[0], i)) {
|
if(FURI_BIT(data[0], i)) {
|
||||||
digital_sequence_add(nfca_signal->tx_signal, SEQ_BIT1);
|
digital_signal_append(nfca_signal->tx_signal, nfca_signal->one);
|
||||||
} else {
|
} else {
|
||||||
digital_sequence_add(nfca_signal->tx_signal, SEQ_BIT0);
|
digital_signal_append(nfca_signal->tx_signal, nfca_signal->zero);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -172,6 +139,4 @@ void nfca_signal_encode(NfcaSignal* nfca_signal, uint8_t* data, uint16_t bits, u
|
|||||||
nfca_add_byte(nfca_signal, data[i], parity[i / 8] & (1 << (7 - (i & 0x07))));
|
nfca_add_byte(nfca_signal, data[i], parity[i / 8] & (1 << (7 - (i & 0x07))));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
digital_sequence_add(nfca_signal->tx_signal, SEQ_EOF);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,10 +6,9 @@
|
|||||||
#include <lib/digital_signal/digital_signal.h>
|
#include <lib/digital_signal/digital_signal.h>
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
DigitalSignal* seq_d; /* sequence D, modulation with subcarrier during first half */
|
DigitalSignal* one;
|
||||||
DigitalSignal* seq_e; /* sequence E, modulation with subcarrier during second half */
|
DigitalSignal* zero;
|
||||||
DigitalSignal* seq_f; /* sequence F, no modulation at all */
|
DigitalSignal* tx_signal;
|
||||||
DigitalSequence* tx_signal;
|
|
||||||
} NfcaSignal;
|
} NfcaSignal;
|
||||||
|
|
||||||
uint16_t nfca_get_crc16(uint8_t* buff, uint16_t len);
|
uint16_t nfca_get_crc16(uint8_t* buff, uint16_t len);
|
||||||
|
|||||||
Reference in New Issue
Block a user