increased maximum memory size to match standard

added security status handling/load/save
added SELECT/QUIET handling
more fine grained allocation routines and checks
fix memset sizes
This commit is contained in:
g3gg0.de
2023-01-20 23:29:34 +01:00
committed by Tiernan Messmer
parent aa7ead724a
commit f03d31b647
5 changed files with 177 additions and 52 deletions
@@ -103,11 +103,12 @@ void nfc_scene_nfc_data_info_on_enter(void* context) {
}
for(int block = 0; block < maxBlocks; block++) {
const char* status = (nfcv_data->security_status[block] & 0x01) ? "(lck)" : "";
for(int pos = 0; pos < nfcv_data->block_size; pos++) {
furi_string_cat_printf(
temp_str, " %02X", nfcv_data->data[block * nfcv_data->block_size + pos]);
}
furi_string_cat_printf(temp_str, "\n");
furi_string_cat_printf(temp_str, " %s\n", status);
}
furi_string_cat_printf(temp_str, "\n");
@@ -75,6 +75,7 @@ void nfc_scene_nfcv_emulate_on_enter(void* context) {
TextBox* text_box = nfc->text_box;
text_box_set_font(text_box, TextBoxFontHex);
text_box_set_focus(text_box, TextBoxFocusEnd);
text_box_set_text(text_box, "");
furi_string_reset(nfc->text_box_store);
// Set Widget state and view
@@ -102,10 +103,10 @@ bool nfc_scene_nfcv_emulate_on_event(void* context, SceneManagerEvent event) {
if(event.type == SceneManagerEventTypeCustom) {
if(event.event == NfcCustomEventUpdateLog) {
// Add data button to widget if data is received for the first time
if(!furi_string_size(nfc->text_box_store)) {
nfc_scene_nfcv_emulate_widget_config(nfc, true);
}
if(strlen(nfcv_data->last_command) > 0) {
if(!furi_string_size(nfc->text_box_store)) {
nfc_scene_nfcv_emulate_widget_config(nfc, true);
}
/* use the last n bytes from the log so there's enough space for the new log entry */
size_t maxSize =
NFC_SCENE_EMULATE_NFCV_LOG_SIZE_MAX - (strlen(nfcv_data->last_command) + 1);
+15 -5
View File
@@ -674,7 +674,7 @@ static bool nfc_device_save_slix_data(FlipperFormat* file, NfcDevice* dev) {
bool nfc_device_load_slix_data(FlipperFormat* file, NfcDevice* dev) {
bool parsed = false;
NfcVSlixData* data = &dev->dev_data.nfcv_data.sub_data.slix;
memset(data, 0, sizeof(NfcVData));
memset(data, 0, sizeof(NfcVSlixData));
do {
if(!flipper_format_read_hex(file, "Password EAS", data->key_eas, sizeof(data->key_eas)))
@@ -715,7 +715,7 @@ static bool nfc_device_save_slix_s_data(FlipperFormat* file, NfcDevice* dev) {
bool nfc_device_load_slix_s_data(FlipperFormat* file, NfcDevice* dev) {
bool parsed = false;
NfcVSlixData* data = &dev->dev_data.nfcv_data.sub_data.slix;
memset(data, 0, sizeof(NfcVData));
memset(data, 0, sizeof(NfcVSlixData));
do {
if(!flipper_format_read_hex(file, "Password Read", data->key_read, sizeof(data->key_read)))
@@ -763,7 +763,7 @@ static bool nfc_device_save_slix_l_data(FlipperFormat* file, NfcDevice* dev) {
bool nfc_device_load_slix_l_data(FlipperFormat* file, NfcDevice* dev) {
bool parsed = false;
NfcVSlixData* data = &dev->dev_data.nfcv_data.sub_data.slix;
memset(data, 0, sizeof(NfcVData));
memset(data, 0, sizeof(NfcVSlixData));
do {
if(!flipper_format_read_hex(
@@ -811,7 +811,7 @@ static bool nfc_device_save_slix2_data(FlipperFormat* file, NfcDevice* dev) {
bool nfc_device_load_slix2_data(FlipperFormat* file, NfcDevice* dev) {
bool parsed = false;
NfcVSlixData* data = &dev->dev_data.nfcv_data.sub_data.slix;
memset(data, 0, sizeof(NfcVData));
memset(data, 0, sizeof(NfcVSlixData));
do {
if(!flipper_format_read_hex(file, "Password Read", data->key_read, sizeof(data->key_read)))
@@ -858,6 +858,9 @@ static bool nfc_device_save_nfcv_data(FlipperFormat* file, NfcDevice* dev) {
if(!flipper_format_write_hex(
file, "Data Content", data->data, data->block_num * data->block_size))
break;
if(!flipper_format_write_hex(
file, "Security Status", data->security_status, data->block_num))
break;
if(!flipper_format_write_comment_cstr(
file,
"Subtype of this card (0 = ISO15693, 1 = SLIX, 2 = SLIX-S, 3 = SLIX-L, 4 = SLIX2)"))
@@ -892,7 +895,7 @@ bool nfc_device_load_nfcv_data(FlipperFormat* file, NfcDevice* dev) {
bool parsed = false;
NfcVData* data = &dev->dev_data.nfcv_data;
memset(data, 0, sizeof(NfcVData));
memset(data, 0x00, sizeof(NfcVData));
do {
uint32_t temp_uint32 = 0;
@@ -907,6 +910,13 @@ bool nfc_device_load_nfcv_data(FlipperFormat* file, NfcDevice* dev) {
if(!flipper_format_read_hex(
file, "Data Content", data->data, data->block_num * data->block_size))
break;
/* optional, as added later */
if(flipper_format_key_exist(file, "Security Status")) {
if(!flipper_format_read_hex(
file, "Security Status", data->security_status, data->block_num))
break;
}
if(!flipper_format_read_hex(file, "Subtype", &temp_value, 1)) break;
data->sub_type = temp_value;
+139 -36
View File
@@ -183,10 +183,18 @@ void nfcv_crc(uint8_t* data, uint32_t length) {
void nfcv_emu_free_signals(NfcVEmuAirSignals* signals) {
furi_assert(signals);
digital_signal_free(signals->nfcv_resp_one);
digital_signal_free(signals->nfcv_resp_zero);
digital_signal_free(signals->nfcv_resp_sof);
digital_signal_free(signals->nfcv_resp_eof);
if(signals->nfcv_resp_one) {
digital_signal_free(signals->nfcv_resp_one);
}
if(signals->nfcv_resp_zero) {
digital_signal_free(signals->nfcv_resp_zero);
}
if(signals->nfcv_resp_sof) {
digital_signal_free(signals->nfcv_resp_sof);
}
if(signals->nfcv_resp_eof) {
digital_signal_free(signals->nfcv_resp_eof);
}
signals->nfcv_resp_one = NULL;
signals->nfcv_resp_zero = NULL;
signals->nfcv_resp_sof = NULL;
@@ -197,28 +205,40 @@ bool nfcv_emu_alloc_signals(NfcVEmuAir* air, NfcVEmuAirSignals* signals, uint32_
furi_assert(air);
furi_assert(signals);
bool ret = true;
bool success = true;
if(!signals->nfcv_resp_one) {
/* logical one: unmodulated then 8 pulses */
signals->nfcv_resp_one = digital_signal_alloc(
slowdown * (air->nfcv_resp_unmod->edge_cnt + 8 * air->nfcv_resp_pulse->edge_cnt));
if(!signals->nfcv_resp_one) {
return false;
}
for(size_t i = 0; i < slowdown; i++) {
ret &= digital_signal_append(signals->nfcv_resp_one, air->nfcv_resp_unmod);
success &= digital_signal_append(signals->nfcv_resp_one, air->nfcv_resp_unmod);
}
for(size_t i = 0; i < slowdown * 8; i++) {
ret &= digital_signal_append(signals->nfcv_resp_one, air->nfcv_resp_pulse);
success &= digital_signal_append(signals->nfcv_resp_one, air->nfcv_resp_pulse);
}
if(!success) {
return false;
}
}
if(!signals->nfcv_resp_zero) {
/* logical zero: 8 pulses then unmodulated */
signals->nfcv_resp_zero = digital_signal_alloc(
slowdown * (8 * air->nfcv_resp_pulse->edge_cnt + air->nfcv_resp_unmod->edge_cnt));
if(!signals->nfcv_resp_zero) {
return false;
}
for(size_t i = 0; i < slowdown * 8; i++) {
ret &= digital_signal_append(signals->nfcv_resp_zero, air->nfcv_resp_pulse);
success &= digital_signal_append(signals->nfcv_resp_zero, air->nfcv_resp_pulse);
}
for(size_t i = 0; i < slowdown; i++) {
ret &= digital_signal_append(signals->nfcv_resp_zero, air->nfcv_resp_unmod);
success &= digital_signal_append(signals->nfcv_resp_zero, air->nfcv_resp_unmod);
}
if(!success) {
return false;
}
}
if(!signals->nfcv_resp_sof) {
@@ -226,13 +246,19 @@ bool nfcv_emu_alloc_signals(NfcVEmuAir* air, NfcVEmuAirSignals* signals, uint32_
signals->nfcv_resp_sof = digital_signal_alloc(
slowdown * (3 * air->nfcv_resp_unmod->edge_cnt + 24 * air->nfcv_resp_pulse->edge_cnt) +
signals->nfcv_resp_one->edge_cnt);
if(!signals->nfcv_resp_sof) {
return false;
}
for(size_t i = 0; i < slowdown * 3; i++) {
ret &= digital_signal_append(signals->nfcv_resp_sof, air->nfcv_resp_unmod);
success &= digital_signal_append(signals->nfcv_resp_sof, air->nfcv_resp_unmod);
}
for(size_t i = 0; i < slowdown * 24; i++) {
ret &= digital_signal_append(signals->nfcv_resp_sof, air->nfcv_resp_pulse);
success &= digital_signal_append(signals->nfcv_resp_sof, air->nfcv_resp_pulse);
}
success &= digital_signal_append(signals->nfcv_resp_sof, signals->nfcv_resp_one);
if(!success) {
return false;
}
ret &= digital_signal_append(signals->nfcv_resp_sof, signals->nfcv_resp_one);
}
if(!signals->nfcv_resp_eof) {
/* EOF: logic 0, 24 pulses, unmodulated */
@@ -240,29 +266,48 @@ bool nfcv_emu_alloc_signals(NfcVEmuAir* air, NfcVEmuAirSignals* signals, uint32_
signals->nfcv_resp_zero->edge_cnt +
slowdown * (24 * air->nfcv_resp_pulse->edge_cnt + 3 * air->nfcv_resp_unmod->edge_cnt) +
air->nfcv_resp_unmod->edge_cnt);
ret &= digital_signal_append(signals->nfcv_resp_eof, signals->nfcv_resp_zero);
if(!signals->nfcv_resp_eof) {
return false;
}
success &= digital_signal_append(signals->nfcv_resp_eof, signals->nfcv_resp_zero);
for(size_t i = 0; i < slowdown * 24; i++) {
ret &= digital_signal_append(signals->nfcv_resp_eof, air->nfcv_resp_pulse);
success &= digital_signal_append(signals->nfcv_resp_eof, air->nfcv_resp_pulse);
}
for(size_t i = 0; i < slowdown * 3; i++) {
ret &= digital_signal_append(signals->nfcv_resp_eof, air->nfcv_resp_unmod);
success &= digital_signal_append(signals->nfcv_resp_eof, air->nfcv_resp_unmod);
}
/* add extra silence */
ret &= digital_signal_append(signals->nfcv_resp_eof, air->nfcv_resp_unmod);
success &= digital_signal_append(signals->nfcv_resp_eof, air->nfcv_resp_unmod);
if(!success) {
return false;
}
}
return ret;
return success;
}
void nfcv_emu_alloc(NfcVData* nfcv_data) {
bool nfcv_emu_alloc(NfcVData* nfcv_data) {
furi_assert(nfcv_data);
if(!nfcv_data->frame) {
nfcv_data->frame = malloc(NFCV_FRAMESIZE_MAX);
if(!nfcv_data->frame) {
return false;
}
}
if(!nfcv_data->emu_air.nfcv_signal) {
/* assuming max frame length is 255 bytes */
nfcv_data->emu_air.nfcv_signal = digital_sequence_alloc(8 * 255 + 2, &gpio_spi_r_mosi);
if(!nfcv_data->emu_air.nfcv_signal) {
return false;
}
}
if(!nfcv_data->emu_air.nfcv_resp_unmod) {
/* unmodulated 256/fc or 1024/fc signal as building block */
nfcv_data->emu_air.nfcv_resp_unmod = digital_signal_alloc(4);
if(!nfcv_data->emu_air.nfcv_resp_unmod) {
return false;
}
nfcv_data->emu_air.nfcv_resp_unmod->start_level = false;
nfcv_data->emu_air.nfcv_resp_unmod->edge_timings[0] =
(uint32_t)(NFCV_RESP_SUBC1_UNMOD_256 * DIGITAL_SIGNAL_UNIT_S);
@@ -271,6 +316,9 @@ void nfcv_emu_alloc(NfcVData* nfcv_data) {
if(!nfcv_data->emu_air.nfcv_resp_pulse) {
/* modulated fc/32 or fc/8 pulse as building block */
nfcv_data->emu_air.nfcv_resp_pulse = digital_signal_alloc(4);
if(!nfcv_data->emu_air.nfcv_resp_pulse) {
return false;
}
nfcv_data->emu_air.nfcv_resp_pulse->start_level = true;
nfcv_data->emu_air.nfcv_resp_pulse->edge_timings[0] =
(uint32_t)(NFCV_RESP_SUBC1_PULSE_32 * DIGITAL_SIGNAL_UNIT_S);
@@ -280,12 +328,12 @@ void nfcv_emu_alloc(NfcVData* nfcv_data) {
}
bool success = true;
success &= nfcv_emu_alloc_signals(&nfcv_data->emu_air, &nfcv_data->emu_air.signals_high, 1);
success &= nfcv_emu_alloc_signals(&nfcv_data->emu_air, &nfcv_data->emu_air.signals_low, 4);
if(!success) {
FURI_LOG_E(TAG, "Failed to allocate signals");
return false;
}
digital_sequence_set_signal(
@@ -320,16 +368,33 @@ void nfcv_emu_alloc(NfcVData* nfcv_data) {
nfcv_data->emu_air.nfcv_signal,
NFCV_SIG_LOW_EOF,
nfcv_data->emu_air.signals_low.nfcv_resp_eof);
return true;
}
void nfcv_emu_free(NfcVData* nfcv_data) {
furi_assert(nfcv_data);
digital_signal_free(nfcv_data->emu_air.nfcv_resp_unmod);
digital_signal_free(nfcv_data->emu_air.nfcv_resp_pulse);
digital_sequence_free(nfcv_data->emu_air.nfcv_signal);
pulse_reader_free(nfcv_data->emu_air.reader_signal);
if(nfcv_data->frame) {
free(nfcv_data->frame);
}
if(nfcv_data->emu_protocol_ctx) {
free(nfcv_data->emu_protocol_ctx);
}
if(nfcv_data->emu_air.nfcv_resp_unmod) {
digital_signal_free(nfcv_data->emu_air.nfcv_resp_unmod);
}
if(nfcv_data->emu_air.nfcv_resp_pulse) {
digital_signal_free(nfcv_data->emu_air.nfcv_resp_pulse);
}
if(nfcv_data->emu_air.nfcv_signal) {
digital_sequence_free(nfcv_data->emu_air.nfcv_signal);
}
if(nfcv_data->emu_air.reader_signal) {
pulse_reader_free(nfcv_data->emu_air.reader_signal);
}
nfcv_data->frame = NULL;
nfcv_data->emu_air.nfcv_resp_unmod = NULL;
nfcv_data->emu_air.nfcv_resp_pulse = NULL;
nfcv_data->emu_air.nfcv_signal = NULL;
@@ -428,6 +493,7 @@ void nfcv_emu_handle_packet(
/* parse the frame data for the upcoming part 3 handling */
ctx->flags = nfcv_data->frame[0];
ctx->command = nfcv_data->frame[1];
ctx->selected = (ctx->flags & RFAL_NFCV_REQ_FLAG_SELECT);
ctx->addressed = !(ctx->flags & RFAL_NFCV_REQ_FLAG_INVENTORY) &&
(ctx->flags & RFAL_NFCV_REQ_FLAG_ADDRESS);
ctx->advanced = (ctx->command >= 0xA0);
@@ -474,6 +540,14 @@ void nfcv_emu_handle_packet(
}
}
if(ctx->selected && !nfcv_data->selected) {
FURI_LOG_D(
TAG,
"selected card shall execute command 0x%02X, but we were not selected",
ctx->command);
return;
}
/* then give control to the card subtype specific protocol filter */
if(ctx->emu_protocol_filter != NULL) {
if(ctx->emu_protocol_filter(tx_rx, nfc_data, nfcv_data)) {
@@ -487,28 +561,39 @@ void nfcv_emu_handle_packet(
switch(ctx->command) {
case ISO15693_INVENTORY: {
ctx->response_buffer[0] = ISO15693_NOERROR;
ctx->response_buffer[1] = nfcv_data->dsfid;
nfcv_revuidcpy(&ctx->response_buffer[2], nfc_data->uid);
if(!nfcv_data->quiet) {
ctx->response_buffer[0] = ISO15693_NOERROR;
ctx->response_buffer[1] = nfcv_data->dsfid;
nfcv_revuidcpy(&ctx->response_buffer[2], nfc_data->uid);
nfcv_emu_send(
tx_rx, nfcv_data, ctx->response_buffer, 10, ctx->response_flags, ctx->send_time);
snprintf(nfcv_data->last_command, sizeof(nfcv_data->last_command), "INVENTORY");
nfcv_emu_send(
tx_rx, nfcv_data, ctx->response_buffer, 10, ctx->response_flags, ctx->send_time);
snprintf(nfcv_data->last_command, sizeof(nfcv_data->last_command), "INVENTORY");
} else {
snprintf(
nfcv_data->last_command, sizeof(nfcv_data->last_command), "INVENTORY (quiet)");
}
break;
}
case ISO15693_STAYQUIET: {
snprintf(nfcv_data->last_command, sizeof(nfcv_data->last_command), "STAYQUIET");
nfcv_data->quiet = true;
break;
}
case ISO15693_LOCKBLOCK: {
snprintf(nfcv_data->last_command, sizeof(nfcv_data->last_command), "LOCKBLOCK");
uint8_t block = nfcv_data->frame[ctx->payload_offset];
nfcv_data->security_status[block] |= 0x01;
nfcv_data->modified = true;
snprintf(nfcv_data->last_command, sizeof(nfcv_data->last_command), "LOCK BLOCK %d", block);
break;
}
case ISO15693_SELECT: {
ctx->response_buffer[0] = ISO15693_NOERROR;
nfcv_data->selected = true;
nfcv_data->quiet = false;
nfcv_emu_send(
tx_rx, nfcv_data, ctx->response_buffer, 1, ctx->response_flags, ctx->send_time);
snprintf(nfcv_data->last_command, sizeof(nfcv_data->last_command), "SELECT");
@@ -517,6 +602,7 @@ void nfcv_emu_handle_packet(
case ISO15693_RESET_TO_READY: {
ctx->response_buffer[0] = ISO15693_NOERROR;
nfcv_data->quiet = false;
nfcv_emu_send(
tx_rx, nfcv_data, ctx->response_buffer, 1, ctx->response_flags, ctx->send_time);
snprintf(nfcv_data->last_command, sizeof(nfcv_data->last_command), "RESET_TO_READY");
@@ -541,15 +627,16 @@ void nfcv_emu_handle_packet(
ctx->response_buffer[buffer_pos++] = ISO15693_NOERROR;
for(int current_block = 0; current_block < blocks; current_block++) {
for(int block_index = 0; block_index < blocks; block_index++) {
int block_current = block + block_index;
/* prepend security status */
if(ctx->flags & RFAL_NFCV_REQ_FLAG_OPTION) {
ctx->response_buffer[buffer_pos++] = 0;
ctx->response_buffer[buffer_pos++] = nfcv_data->security_status[block_current];
}
/* then the data block */
memcpy(
&ctx->response_buffer[buffer_pos],
&nfcv_data->data[nfcv_data->block_size * (block + current_block)],
&nfcv_data->data[nfcv_data->block_size * block_current],
nfcv_data->block_size);
buffer_pos += nfcv_data->block_size;
}
@@ -649,7 +736,19 @@ void nfcv_emu_init(FuriHalNfcDevData* nfc_data, NfcVData* nfcv_data) {
furi_assert(nfc_data);
furi_assert(nfcv_data);
nfcv_emu_alloc(nfcv_data);
if(!nfcv_emu_alloc(nfcv_data)) {
FURI_LOG_E(TAG, "Failed to allocate structures");
nfcv_data->ready = false;
return;
}
strcpy(nfcv_data->last_command, "");
nfcv_data->quiet = false;
nfcv_data->selected = false;
nfcv_data->modified = false;
/* everything is initialized */
nfcv_data->ready = true;
rfal_platform_spi_acquire();
/* configure for transparent and passive mode */
@@ -752,6 +851,10 @@ bool nfcv_emu_loop(
uint32_t timeout = timeout_ms * 1000;
bool wait_for_pulse = false;
if(!nfcv_data->ready) {
return false;
}
#ifdef NFCV_DIAGNOSTIC_DUMPS
uint8_t period_buffer[NFCV_DIAGNOSTIC_DUMP_SIZE];
uint32_t period_buffer_pos = 0;
@@ -825,7 +928,7 @@ bool nfcv_emu_loop(
periods_previous = 512 - (periods + 1);
byte_value = (periods - 1) / 2;
if(frame_pos < NFCV_MAX_FRAME_SIZE) {
if(frame_pos < NFCV_FRAMESIZE_MAX) {
nfcv_data->frame[frame_pos++] = (uint8_t)byte_value;
}
@@ -867,7 +970,7 @@ bool nfcv_emu_loop(
}
if(bits_received >= 8) {
if(frame_pos < NFCV_MAX_FRAME_SIZE) {
if(frame_pos < NFCV_FRAMESIZE_MAX) {
nfcv_data->frame[frame_pos++] = (uint8_t)byte_value;
}
bits_received = 0;
+17 -7
View File
@@ -21,10 +21,15 @@ extern "C" {
#define DIGITAL_SIGNAL_UNIT_S (100000000000.0f)
#define DIGITAL_SIGNAL_UNIT_US (100000.0f)
#define NFCV_TOTAL_BLOCKS_MAX 256
#define NFCV_BLOCK_SIZE 4
#define NFCV_MAX_DUMP_SIZE (NFCV_BLOCK_SIZE * NFCV_TOTAL_BLOCKS_MAX)
#define NFCV_MAX_FRAME_SIZE 64
/* ISO/IEC 15693-3:2019(E) 10.4.12: maximum number of blocks is defined as 256 */
#define NFCV_BLOCKS_MAX 256
/* ISO/IEC 15693-3:2019(E) 10.4.12: maximum size of blocks is defined as 32 */
#define NFCV_BLOCKSIZE_MAX 32
/* the resulting memory size a card can have */
#define NFCV_MEMSIZE_MAX (NFCV_BLOCKS_MAX * NFCV_BLOCKSIZE_MAX)
/* ISO/IEC 15693-3:2019(E) 7.1b: standard allows up to 8192, the maxium frame length that we are expected to receive/send is less */
#define NFCV_FRAMESIZE_MAX (1 + NFCV_MEMSIZE_MAX + NFCV_BLOCKS_MAX)
#define NFCV_LOG_STR_LEN 128
// #define NFCV_DIAGNOSTIC_DUMPS
@@ -147,12 +152,13 @@ typedef bool (*NfcVEmuProtocolFilter)(
typedef struct {
uint8_t flags; /* ISO15693-3 flags of the header as specified */
uint8_t command; /* ISO15693-3 command at offset 1 as specified */
bool selected; /* ISO15693-3 flags: selected frame */
bool addressed; /* ISO15693-3 flags: addressed frame */
bool advanced; /* ISO15693-3 command: advanced command */
uint8_t address_offset; /* ISO15693-3 offset of the address in frame, if addressed is set */
uint8_t payload_offset; /* ISO15693-3 offset of the payload in frame */
uint8_t response_buffer[NFCV_MAX_FRAME_SIZE]; /* pre-allocated response buffer */
uint8_t response_buffer[NFCV_FRAMESIZE_MAX]; /* pre-allocated response buffer */
NfcVSendFlags response_flags; /* flags to use when sending response */
uint32_t send_time; /* timestamp when to send the response */
@@ -166,9 +172,13 @@ typedef struct {
uint8_t ic_ref;
uint16_t block_num;
uint8_t block_size;
uint8_t data[NFCV_MAX_DUMP_SIZE];
uint8_t data[NFCV_MEMSIZE_MAX];
uint8_t security_status[NFCV_BLOCKS_MAX];
bool selected;
bool quiet;
bool modified;
bool ready;
/* specfic variant infos */
NfcVSubtype sub_type;
@@ -178,7 +188,7 @@ typedef struct {
/* precalced air level data */
NfcVEmuAir emu_air;
uint8_t frame[NFCV_MAX_FRAME_SIZE]; /* ISO15693-2 incoming raw data from air layer */
uint8_t* frame; /* [NFCV_FRAMESIZE_MAX] ISO15693-2 incoming raw data from air layer */
uint8_t frame_length; /* ISO15693-2 length of incoming data */
uint32_t eof_timestamp; /* ISO15693-2 EOF timestamp, read from DWT->CYCCNT */