diff --git a/lib/nfc/protocols/nfcv.c b/lib/nfc/protocols/nfcv.c index 9557c28fa..f8e739beb 100644 --- a/lib/nfc/protocols/nfcv.c +++ b/lib/nfc/protocols/nfcv.c @@ -256,10 +256,22 @@ void nfcv_emu_alloc(NfcVData* data) { digital_sequence_set_signal(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); - digital_sequence_add(nfcv->emulation.nfcv_signal, NFCV_SIG_SOF); + + if(flags & NfcVSendFlagsSof) { + 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; @@ -269,20 +281,18 @@ static void nfcv_emu_send_raw(NfcVData* nfcv, uint8_t* data, uint8_t length) { digital_sequence_add(nfcv->emulation.nfcv_signal, (data[byte_pos] & bit_val) ? NFCV_SIG_BIT1 : NFCV_SIG_BIT0); } - digital_sequence_add(nfcv->emulation.nfcv_signal, NFCV_SIG_EOF); + if(flags & NfcVSendFlagsEof) { + 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 + 2) * 8, false, tx_rx->sniff_context); + tx_rx->sniff_tx(data, length * 8, false, tx_rx->sniff_context); } } @@ -326,6 +336,7 @@ void nfcv_emu_handle_packet(FuriHalNfcTxRxContext* tx_rx, FuriHalNfcDevData* nfc 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); @@ -360,7 +371,7 @@ void nfcv_emu_handle_packet(FuriHalNfcTxRxContext* tx_rx, FuriHalNfcDevData* nfc response_buffer[1] = nfcv_data->dsfid; nfcv_uidcpy(&response_buffer[2], nfc_data->uid); - nfcv_emu_send(tx_rx, nfcv_data, response_buffer, 10); + nfcv_emu_send(tx_rx, nfcv_data, response_buffer, 10, response_flags); snprintf(nfcv_data->last_command, sizeof(nfcv_data->last_command), "INVENTORY"); break; } @@ -392,7 +403,7 @@ void nfcv_emu_handle_packet(FuriHalNfcTxRxContext* tx_rx, FuriHalNfcDevData* nfc case ISO15693_SELECT: { response_buffer[0] = ISO15693_NOERROR; - nfcv_emu_send(tx_rx, nfcv_data, response_buffer, 1); + nfcv_emu_send(tx_rx, nfcv_data, response_buffer, 1, response_flags); snprintf(nfcv_data->last_command, sizeof(nfcv_data->last_command), "SELECT"); break; } @@ -403,11 +414,11 @@ void nfcv_emu_handle_packet(FuriHalNfcTxRxContext* tx_rx, FuriHalNfcDevData* nfc if(block >= nfcv_data->block_num) { response_buffer[0] = ISO15693_ERROR_BLOCK_WRITE; - nfcv_emu_send(tx_rx, nfcv_data, response_buffer, 1); + 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); + 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; @@ -424,7 +435,7 @@ void nfcv_emu_handle_packet(FuriHalNfcTxRxContext* tx_rx, FuriHalNfcDevData* nfc 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); + 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; } @@ -440,7 +451,7 @@ void nfcv_emu_handle_packet(FuriHalNfcTxRxContext* tx_rx, FuriHalNfcDevData* nfc 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); + nfcv_emu_send(tx_rx, nfcv_data, response_buffer, 15, response_flags); snprintf(nfcv_data->last_command, sizeof(nfcv_data->last_command), "SYSTEMINFO"); break; @@ -455,7 +466,7 @@ void nfcv_emu_handle_packet(FuriHalNfcTxRxContext* tx_rx, FuriHalNfcDevData* nfc 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); + 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], @@ -495,7 +506,7 @@ void nfcv_emu_handle_packet(FuriHalNfcTxRxContext* tx_rx, FuriHalNfcDevData* nfc 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); + 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); @@ -507,7 +518,7 @@ void nfcv_emu_handle_packet(FuriHalNfcTxRxContext* tx_rx, FuriHalNfcDevData* nfc { response_buffer[0] = ISO15693_NOERROR; - nfcv_emu_send(tx_rx, nfcv_data, response_buffer, 1); + 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; diff --git a/lib/nfc/protocols/nfcv.h b/lib/nfc/protocols/nfcv.h index 3e1c651dd..2f72f872e 100644 --- a/lib/nfc/protocols/nfcv.h +++ b/lib/nfc/protocols/nfcv.h @@ -104,6 +104,17 @@ 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];