diff --git a/firmware/targets/f7/api_symbols.csv b/firmware/targets/f7/api_symbols.csv index db62c8c7e..598eae2fc 100644 --- a/firmware/targets/f7/api_symbols.csv +++ b/firmware/targets/f7/api_symbols.csv @@ -1186,6 +1186,7 @@ Function,+,furi_hal_nfc_emulate_nfca,_Bool,"uint8_t*, uint8_t, uint8_t*, uint8_t Function,+,furi_hal_nfc_exit_sleep,void, Function,+,furi_hal_nfc_field_off,void, Function,+,furi_hal_nfc_field_on,void, +Function,-,furi_hal_nfc_gen_bitstream,void,"FuriHalNfcTxRxContext*, uint8_t*, size_t" Function,-,furi_hal_nfc_init,void, Function,+,furi_hal_nfc_is_busy,_Bool, Function,+,furi_hal_nfc_is_init,_Bool, @@ -1209,6 +1210,7 @@ Function,+,furi_hal_nfc_stop,void, Function,+,furi_hal_nfc_stop_cmd,void, Function,+,furi_hal_nfc_tx_rx,_Bool,"FuriHalNfcTxRxContext*, uint16_t" Function,+,furi_hal_nfc_tx_rx_full,_Bool,FuriHalNfcTxRxContext* +Function,-,furi_hal_nfcv_listen_start,void, Function,-,furi_hal_os_init,void, Function,+,furi_hal_os_tick,void, Function,+,furi_hal_power_check_otg_status,void, @@ -2025,6 +2027,10 @@ Function,-,nfca_get_crc16,uint16_t,"uint8_t*, uint16_t" Function,-,nfca_signal_alloc,NfcaSignal*, Function,-,nfca_signal_encode,void,"NfcaSignal*, uint8_t*, uint16_t, uint8_t*" Function,-,nfca_signal_free,void,NfcaSignal* +Function,-,nfca_trans_rx_continue,void,NfcaTransRxState* +Function,-,nfca_trans_rx_deinit,void,NfcaTransRxState* +Function,-,nfca_trans_rx_init,void,NfcaTransRxState* +Function,-,nfca_trans_rx_loop,_Bool,"NfcaTransRxState*, uint32_t" Function,-,nfcv_emu_deinit,void,NfcVData* Function,-,nfcv_emu_init,void,"FuriHalNfcDevData*, NfcVData*" Function,-,nfcv_emu_loop,_Bool,"FuriHalNfcTxRxContext*, FuriHalNfcDevData*, NfcVData*, uint32_t" diff --git a/firmware/targets/f7/furi_hal/furi_hal_nfc.c b/firmware/targets/f7/furi_hal/furi_hal_nfc.c index 2d27313ae..44505c7cd 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_nfc.c +++ b/firmware/targets/f7/furi_hal/furi_hal_nfc.c @@ -367,6 +367,38 @@ void furi_hal_nfc_listen_start(FuriHalNfcDevData* nfc_data) { st25r3916ExecuteCommand(ST25R3916_CMD_GOTO_SENSE); } +void furi_hal_nfcv_listen_start() { + furi_hal_gpio_init(&gpio_nfc_irq_rfid_pull, GpioModeInput, GpioPullDown, GpioSpeedVeryHigh); + // Clear interrupts + st25r3916ClearInterrupts(); + // Mask all interrupts + st25r3916DisableInterrupts(ST25R3916_IRQ_MASK_ALL); + // RESET + st25r3916ExecuteCommand(ST25R3916_CMD_STOP); + // Setup registers + st25r3916WriteRegister( + ST25R3916_REG_OP_CONTROL, + ST25R3916_REG_OP_CONTROL_en | ST25R3916_REG_OP_CONTROL_rx_en | + ST25R3916_REG_OP_CONTROL_en_fd_auto_efd); + st25r3916WriteRegister( + ST25R3916_REG_MODE, + ST25R3916_REG_MODE_targ_targ | ST25R3916_REG_MODE_om3 | ST25R3916_REG_MODE_om0); + st25r3916WriteRegister( + ST25R3916_REG_PASSIVE_TARGET, + ST25R3916_REG_PASSIVE_TARGET_fdel_2 | ST25R3916_REG_PASSIVE_TARGET_fdel_0 | + ST25R3916_REG_PASSIVE_TARGET_d_ac_ap2p | ST25R3916_REG_PASSIVE_TARGET_d_212_424_1r); + st25r3916WriteRegister(ST25R3916_REG_MASK_RX_TIMER, 0x02); + + // Mask interrupts + uint32_t clear_irq_mask = + (ST25R3916_IRQ_MASK_RXE | ST25R3916_IRQ_MASK_RXE_PTA | ST25R3916_IRQ_MASK_WU_A_X | + ST25R3916_IRQ_MASK_WU_A); + st25r3916EnableInterrupts(clear_irq_mask); + + // Go to sense + st25r3916ExecuteCommand(ST25R3916_CMD_GOTO_SENSE); +} + void rfal_interrupt_callback_handler() { furi_event_flag_set(event, EVENT_FLAG_INTERRUPT); } diff --git a/firmware/targets/furi_hal_include/furi_hal_nfc.h b/firmware/targets/furi_hal_include/furi_hal_nfc.h index d3f6de602..1363a1572 100644 --- a/firmware/targets/furi_hal_include/furi_hal_nfc.h +++ b/firmware/targets/furi_hal_include/furi_hal_nfc.h @@ -177,6 +177,12 @@ bool furi_hal_nfc_listen( */ void furi_hal_nfc_listen_start(FuriHalNfcDevData* nfc_data); +/** Start Target Listen mode + * @note RFAL free implementation + * + */ +void furi_hal_nfcv_listen_start(); + /** Read data in Target Listen mode * @note Must be called only after furi_hal_nfc_listen_start() * diff --git a/lib/nfc/protocols/nfcv.c b/lib/nfc/protocols/nfcv.c index 78a4f126b..91fe92003 100644 --- a/lib/nfc/protocols/nfcv.c +++ b/lib/nfc/protocols/nfcv.c @@ -276,22 +276,9 @@ void nfcv_emu_alloc(NfcVData* data) { data->emulation.nfcv_signal, NFCV_SIG_EOF, data->emulation.nfcv_resp_eof); } -static void nfcv_emu_send(FuriHalNfcTxRxContext* tx_rx, NfcVData* nfcv, uint8_t* data, uint8_t length, NfcVSendFlags flags) { - /* picked default value (0) to match the most common format */ - if(!flags) { - flags = NfcVSendFlagsSof | NfcVSendFlagsCrc | NfcVSendFlagsEof | NfcVSendFlagsOneSubcarrier | NfcVSendFlagsHighRate; - } - - if(flags & NfcVSendFlagsCrc) { - nfcv_crc(data, length); - length += 2; - } - +static void nfcv_emu_send_raw(NfcVData* nfcv, uint8_t* data, uint8_t length) { digital_sequence_clear(nfcv->emulation.nfcv_signal); - - if(flags & NfcVSendFlagsSof) { - digital_sequence_add(nfcv->emulation.nfcv_signal, NFCV_SIG_SOF); - } + digital_sequence_add(nfcv->emulation.nfcv_signal, NFCV_SIG_SOF); for(int bit_total = 0; bit_total < length * 8; bit_total++) { uint32_t byte_pos = bit_total / 8; @@ -303,17 +290,20 @@ static void nfcv_emu_send(FuriHalNfcTxRxContext* tx_rx, NfcVData* nfcv, uint8_t* (data[byte_pos] & bit_val) ? NFCV_SIG_BIT1 : NFCV_SIG_BIT0); } - if(flags & NfcVSendFlagsEof) { - digital_sequence_add(nfcv->emulation.nfcv_signal, NFCV_SIG_EOF); - } + digital_sequence_add(nfcv->emulation.nfcv_signal, NFCV_SIG_EOF); FURI_CRITICAL_ENTER(); digital_sequence_send(nfcv->emulation.nfcv_signal); FURI_CRITICAL_EXIT(); furi_hal_gpio_write(&gpio_spi_r_mosi, false); +} +static void + nfcv_emu_send(FuriHalNfcTxRxContext* tx_rx, NfcVData* nfcv, uint8_t* data, uint8_t length) { + nfcv_crc(data, length); + nfcv_emu_send_raw(nfcv, data, length + 2); if(tx_rx->sniff_tx) { - tx_rx->sniff_tx(data, length * 8, false, tx_rx->sniff_context); + tx_rx->sniff_tx(data, (length + 2) * 8, false, tx_rx->sniff_context); } } @@ -362,7 +352,6 @@ void nfcv_emu_handle_packet( uint8_t payload_offset = address_offset + (addressed ? 8 : 0); uint8_t* address = &payload[address_offset]; uint8_t response_buffer[32]; - NfcVSendFlags response_flags = NfcVSendFlagsNormal; if(addressed && nfcv_uidcmp(address, nfc_data->uid)) { FURI_LOG_D(TAG, "addressed command 0x%02X, but not for us:", command); @@ -418,10 +407,10 @@ void nfcv_emu_handle_packet( response_buffer[1] = nfcv_data->dsfid; nfcv_uidcpy(&response_buffer[2], nfc_data->uid); - nfcv_emu_send(tx_rx, nfcv_data, response_buffer, 10, response_flags); - snprintf(nfcv_data->last_command, sizeof(nfcv_data->last_command), "INVENTORY"); - break; - } + nfcv_emu_send(tx_rx, nfcv_data, response_buffer, 10); + snprintf(nfcv_data->last_command, sizeof(nfcv_data->last_command), "INVENTORY"); + break; + } case ISO15693_STAYQUIET: { snprintf(nfcv_data->last_command, sizeof(nfcv_data->last_command), "STAYQUIET"); @@ -443,78 +432,26 @@ void nfcv_emu_handle_packet( break; } - case ISO15693_SELECT: - { + case ISO15693_SELECT: { + response_buffer[0] = ISO15693_NOERROR; + nfcv_emu_send(tx_rx, nfcv_data, response_buffer, 1); + snprintf(nfcv_data->last_command, sizeof(nfcv_data->last_command), "SELECT"); + break; + } + + case ISO15693_READBLOCK: { + uint8_t block = payload[payload_offset]; + + if(block >= nfcv_data->block_num) { + response_buffer[0] = ISO15693_ERROR_BLOCK_WRITE; + nfcv_emu_send(tx_rx, nfcv_data, response_buffer, 1); + } else { response_buffer[0] = ISO15693_NOERROR; - nfcv_emu_send(tx_rx, nfcv_data, response_buffer, 1, response_flags); - snprintf(nfcv_data->last_command, sizeof(nfcv_data->last_command), "SELECT"); - break; - } - - case ISO15693_READBLOCK: - { - uint8_t block = payload[payload_offset]; - - if(block >= nfcv_data->block_num) { - response_buffer[0] = ISO15693_ERROR_BLOCK_WRITE; - nfcv_emu_send(tx_rx, nfcv_data, response_buffer, 1, response_flags); - } else { - response_buffer[0] = ISO15693_NOERROR; - memcpy(&response_buffer[1], &nfcv_data->data[nfcv_data->block_size * block], nfcv_data->block_size); - nfcv_emu_send(tx_rx, nfcv_data, response_buffer, 1 + nfcv_data->block_size, response_flags); - } - snprintf(nfcv_data->last_command, sizeof(nfcv_data->last_command), "READ BLOCK %d", block); - break; - } - - case ISO15693_WRITEBLOCK: - { - uint8_t block = payload[payload_offset]; - uint8_t *data = &payload[payload_offset + 1]; - - if(block >= nfcv_data->block_num) { - response_buffer[0] = ISO15693_ERROR_BLOCK_WRITE; - } else { - response_buffer[0] = ISO15693_NOERROR; - memcpy(&nfcv_data->data[nfcv_data->block_size * block], &response_buffer[1], nfcv_data->block_size); - } - nfcv_emu_send(tx_rx, nfcv_data, response_buffer, 1, response_flags); - snprintf(nfcv_data->last_command, sizeof(nfcv_data->last_command), "WRITE BLOCK %d <- %02X %02X %02X %02X", block, data[0], data[1], data[2], data[3]); - break; - } - - case ISO15693_GET_SYSTEM_INFO: - { - response_buffer[0] = ISO15693_NOERROR; - response_buffer[1] = 0x0F; - nfcv_uidcpy(&response_buffer[2], nfc_data->uid); - response_buffer[10] = nfcv_data->dsfid; /* DSFID */ - response_buffer[11] = nfcv_data->afi; /* AFI */ - response_buffer[12] = nfcv_data->block_num - 1; /* number of blocks */ - response_buffer[13] = nfcv_data->block_size - 1; /* block size */ - response_buffer[14] = nfcv_data->ic_ref; /* IC reference */ - - nfcv_emu_send(tx_rx, nfcv_data, response_buffer, 15, response_flags); - snprintf(nfcv_data->last_command, sizeof(nfcv_data->last_command), "SYSTEMINFO"); - - break; - } - - case ISO15693_CMD_NXP_GET_RANDOM_NUMBER: - { - nfcv_data->sub_data.slix_l.rand[0] = furi_hal_random_get(); - nfcv_data->sub_data.slix_l.rand[1] = furi_hal_random_get(); - - response_buffer[0] = ISO15693_NOERROR; - response_buffer[1] = nfcv_data->sub_data.slix_l.rand[1]; - response_buffer[2] = nfcv_data->sub_data.slix_l.rand[0]; - - nfcv_emu_send(tx_rx, nfcv_data, response_buffer, 3, response_flags); - snprintf(nfcv_data->last_command, sizeof(nfcv_data->last_command), - "GET_RANDOM_NUMBER -> 0x%02X%02X", - nfcv_data->sub_data.slix_l.rand[0], - nfcv_data->sub_data.slix_l.rand[1]); - break; + memcpy( + &response_buffer[1], + &nfcv_data->data[nfcv_data->block_size * block], + nfcv_data->block_size); + nfcv_emu_send(tx_rx, nfcv_data, response_buffer, 1 + nfcv_data->block_size); } snprintf(nfcv_data->last_command, sizeof(nfcv_data->last_command), "READ BLOCK %d", block); break; @@ -524,47 +461,14 @@ void nfcv_emu_handle_packet( uint8_t block = payload[payload_offset]; uint8_t* data = &payload[payload_offset + 1]; - switch(password_id) { - case 4: - password = nfcv_data->sub_data.slix_l.key_privacy; - break; - case 8: - password = nfcv_data->sub_data.slix_l.key_destroy; - break; - case 10: - password = nfcv_data->sub_data.slix_l.key_eas; - break; - default: - break; - } - - for(int pos = 0; pos < 4; pos++) { - password_rcv[pos] = password_xored[3 - pos] ^ rand[pos % 2]; - } - uint32_t pass_expect = nfcv_read_be(password, 4); - uint32_t pass_received = nfcv_read_be(password_rcv, 4); - - /* if the password is all-zeroes, just accept any password*/ - if(!pass_expect || pass_expect == pass_received) { - nfcv_data->sub_data.slix_l.privacy = false; - response_buffer[0] = ISO15693_NOERROR; - nfcv_emu_send(tx_rx, nfcv_data, response_buffer, 1, response_flags); - snprintf(nfcv_data->last_command, sizeof(nfcv_data->last_command), "SET_PASSWORD #%02X 0x%08lX OK", password_id, pass_received); - } else { - snprintf(nfcv_data->last_command, sizeof(nfcv_data->last_command), "SET_PASSWORD #%02X 0x%08lX/%08lX FAIL", password_id, pass_received, pass_expect); - } - break; - } - - case ISO15693_CMD_NXP_ENABLE_PRIVACY: - { + if(block >= nfcv_data->block_num) { + response_buffer[0] = ISO15693_ERROR_BLOCK_WRITE; + } else { response_buffer[0] = ISO15693_NOERROR; - - nfcv_emu_send(tx_rx, nfcv_data, response_buffer, 1, response_flags); - snprintf(nfcv_data->last_command, sizeof(nfcv_data->last_command), "ISO15693_CMD_NXP_ENABLE_PRIVACY"); - - nfcv_data->sub_data.slix_l.privacy = true; - break; + memcpy( + &nfcv_data->data[nfcv_data->block_size * block], + &response_buffer[1], + nfcv_data->block_size); } nfcv_emu_send(tx_rx, nfcv_data, response_buffer, 1); snprintf( diff --git a/lib/nfc/protocols/nfcv.h b/lib/nfc/protocols/nfcv.h index c7691c1af..e6e63f7d4 100644 --- a/lib/nfc/protocols/nfcv.h +++ b/lib/nfc/protocols/nfcv.h @@ -98,17 +98,6 @@ typedef struct { uint8_t rand[2]; } NfcVSlixData; -typedef enum { - NfcVSendFlagsNormal = 0, - NfcVSendFlagsSof = 1<<0, - NfcVSendFlagsCrc = 1<<1, - NfcVSendFlagsEof = 1<<2, - NfcVSendFlagsOneSubcarrier = 0, - NfcVSendFlagsTwoSubcarrier = 1<<3, - NfcVSendFlagsLowRate = 0, - NfcVSendFlagsHighRate = 1<<4 -} NfcVSendFlags; - typedef struct { uint8_t key_read[4]; uint8_t key_write[4]; diff --git a/lib/nfc/protocols/slix.c b/lib/nfc/protocols/slix.c index ea799b149..659be07ca 100644 --- a/lib/nfc/protocols/slix.c +++ b/lib/nfc/protocols/slix.c @@ -6,26 +6,17 @@ #include #include "furi_hal_nfc.h" -uint8_t slix_get_ti(FuriHalNfcDevData* nfc_data) { - return (nfc_data->uid[3] >> 3) & 3; -} - - bool slix_check_card_type(FuriHalNfcDevData* nfc_data) { - if((nfc_data->uid[0] == 0xE0) - && (nfc_data->uid[1] == 0x04) - && (nfc_data->uid[2] == 0x01) - && slix_get_ti(nfc_data) == 2) { + if((nfc_data->uid[0] == 0xE0) && (nfc_data->uid[1] == 0x04) && (nfc_data->uid[2] == 0x01) && + (((nfc_data->uid[3] >> 4) & 3) == 2)) { return true; } return false; } bool slix2_check_card_type(FuriHalNfcDevData* nfc_data) { - if((nfc_data->uid[0] == 0xE0) - && (nfc_data->uid[1] == 0x04) - && (nfc_data->uid[2] == 0x01) - && slix_get_ti(nfc_data) == 1) { + if((nfc_data->uid[0] == 0xE0) && (nfc_data->uid[1] == 0x04) && (nfc_data->uid[2] == 0x01) && + (((nfc_data->uid[3] >> 4) & 3) == 1)) { return true; } return false;