mirror of
https://github.com/Next-Flip/Momentum-Firmware.git
synced 2026-07-23 01:18:12 -07:00
Refactor ISO APDUs in T4T poller
This commit is contained in:
@@ -13,7 +13,7 @@ typedef enum {
|
||||
Type4TagErrorTimeout,
|
||||
Type4TagErrorWrongFormat,
|
||||
Type4TagErrorNotSupported,
|
||||
Type4TagErrorUnknown,
|
||||
Type4TagErrorApduFailed,
|
||||
Type4TagErrorCustomCommand,
|
||||
} Type4TagError;
|
||||
|
||||
|
||||
@@ -9,6 +9,9 @@
|
||||
|
||||
#define TYPE_4_TAG_FFF_NDEF_DATA_PER_LINE (16U)
|
||||
|
||||
const uint8_t type_4_tag_iso_picc_name[TYPE_4_TAG_ISO_NAME_LEN] = {TYPE_4_TAG_ISO_PICC_NAME};
|
||||
const uint8_t type_4_tag_iso_app_name[TYPE_4_TAG_ISO_NAME_LEN] = {TYPE_4_TAG_ISO_APP_NAME};
|
||||
|
||||
Type4TagError type_4_tag_process_error(Iso14443_4aError error) {
|
||||
switch(error) {
|
||||
case Iso14443_4aErrorNone:
|
||||
@@ -56,14 +59,13 @@ void type_4_tag_cc_dump(const Type4TagData* data, uint8_t* buf, size_t len) {
|
||||
data->is_tag_specific ? data->ndef_write_lock : TYPE_4_TAG_T4T_CC_RW_LOCK_NONE;
|
||||
}
|
||||
|
||||
Type4TagError type_4_tag_cc_parse(Type4TagData* data, const BitBuffer* buf) {
|
||||
const size_t cc_len = bit_buffer_get_size_bytes(buf);
|
||||
if(cc_len < TYPE_4_TAG_T4T_CC_MIN_SIZE) {
|
||||
Type4TagError type_4_tag_cc_parse(Type4TagData* data, const uint8_t* buf, size_t len) {
|
||||
if(len < TYPE_4_TAG_T4T_CC_MIN_SIZE) {
|
||||
FURI_LOG_E(TAG, "Unsupported T4T version");
|
||||
return Type4TagErrorWrongFormat;
|
||||
}
|
||||
|
||||
const Type4TagCc* cc = (const Type4TagCc*)bit_buffer_get_data(buf);
|
||||
const Type4TagCc* cc = (const Type4TagCc*)buf;
|
||||
if(cc->t4t_vno != TYPE_4_TAG_T4T_CC_VNO) {
|
||||
FURI_LOG_E(TAG, "Unsupported T4T version");
|
||||
return Type4TagErrorNotSupported;
|
||||
@@ -71,7 +73,7 @@ Type4TagError type_4_tag_cc_parse(Type4TagData* data, const BitBuffer* buf) {
|
||||
|
||||
const Type4TagCcTlv* tlv = cc->tlv;
|
||||
const Type4TagCcTlvNdefFileCtrl* ndef_file_ctrl = NULL;
|
||||
const void* end = MIN((void*)cc + cc->len, (void*)cc + cc_len);
|
||||
const void* end = MIN((void*)cc + cc->len, (void*)cc + len);
|
||||
while((void*)tlv < end) {
|
||||
if(tlv->type == Type4TagCcTlvTypeNdefFileCtrl) {
|
||||
ndef_file_ctrl = &tlv->value.ndef_file_ctrl;
|
||||
|
||||
@@ -33,10 +33,9 @@
|
||||
#define TYPE_4_TAG_ISO_STATUS_NO_CMD 0x68, 0x00
|
||||
#define TYPE_4_TAG_ISO_RW_CHUNK_LEN (255U)
|
||||
#define TYPE_4_TAG_ISO_NAME_LEN (7U)
|
||||
#define TYPE_4_TAG_ISO_APP_NAME 0xD2, 0x76, 0x00, 0x00, 0x85, 0x01, 0x01
|
||||
#define TYPE_4_TAG_ISO_PICC_NAME 0xD2, 0x76, 0x00, 0x00, 0x85, 0x01, 0x00
|
||||
#define TYPE_4_TAG_T4T_CC_FILE_ID_LEN (2U)
|
||||
#define TYPE_4_TAG_T4T_CC_FILE_ID 0xE1, 0x03
|
||||
#define TYPE_4_TAG_ISO_APP_NAME 0xD2, 0x76, 0x00, 0x00, 0x85, 0x01, 0x01
|
||||
#define TYPE_4_TAG_T4T_CC_FILE_ID 0xE103
|
||||
#define TYPE_4_TAG_T4T_CC_VNO (0x20)
|
||||
#define TYPE_4_TAG_T4T_DEFAULT_FILE_ID 0xE104
|
||||
#define TYPE_4_TAG_T4T_CC_RW_LOCK_NONE 0x00
|
||||
@@ -48,6 +47,9 @@
|
||||
#define TYPE_4_TAG_CHUNK_LEN MIN(TYPE_4_TAG_BUF_SIZE - 5U, TYPE_4_TAG_ISO_RW_CHUNK_LEN)
|
||||
#define TYPE_4_TAG_DEFAULT_SIZE (2048U)
|
||||
|
||||
extern const uint8_t type_4_tag_iso_picc_name[TYPE_4_TAG_ISO_NAME_LEN];
|
||||
extern const uint8_t type_4_tag_iso_app_name[TYPE_4_TAG_ISO_NAME_LEN];
|
||||
|
||||
// Capability Container parsing structures
|
||||
|
||||
typedef enum FURI_PACKED {
|
||||
@@ -86,7 +88,7 @@ Type4TagError type_4_tag_process_error(Iso14443_4aError error);
|
||||
|
||||
void type_4_tag_cc_dump(const Type4TagData* data, uint8_t* buf, size_t len);
|
||||
|
||||
Type4TagError type_4_tag_cc_parse(Type4TagData* data, const BitBuffer* buf);
|
||||
Type4TagError type_4_tag_cc_parse(Type4TagData* data, const uint8_t* buf, size_t len);
|
||||
|
||||
// Load internal Type4Tag structures
|
||||
|
||||
|
||||
@@ -36,16 +36,16 @@ static Type4TagError type_4_tag_listener_iso_select(
|
||||
UNUSED(le);
|
||||
|
||||
if(p1 == TYPE_4_TAG_ISO_SELECT_P1_BY_DF_NAME) {
|
||||
static const uint8_t t4t_picc[TYPE_4_TAG_ISO_NAME_LEN] = {TYPE_4_TAG_ISO_PICC_NAME};
|
||||
if(lc == sizeof(t4t_picc) && memcmp(t4t_picc, data, sizeof(t4t_picc)) == 0) {
|
||||
if(lc == sizeof(type_4_tag_iso_picc_name) &&
|
||||
memcmp(type_4_tag_iso_picc_name, data, sizeof(type_4_tag_iso_picc_name)) == 0) {
|
||||
instance->state = Type4TagListenerStateSelectedPicc;
|
||||
bit_buffer_append_bytes(
|
||||
instance->tx_buffer, type_4_tag_success_apdu, sizeof(type_4_tag_success_apdu));
|
||||
return Type4TagErrorNone;
|
||||
}
|
||||
|
||||
static const uint8_t t4t_app[TYPE_4_TAG_ISO_NAME_LEN] = {TYPE_4_TAG_ISO_APP_NAME};
|
||||
if(lc == sizeof(t4t_app) && memcmp(t4t_app, data, sizeof(t4t_app)) == 0) {
|
||||
if(lc == sizeof(type_4_tag_iso_app_name) &&
|
||||
memcmp(type_4_tag_iso_app_name, data, sizeof(type_4_tag_iso_app_name)) == 0) {
|
||||
instance->state = Type4TagListenerStateSelectedApplication;
|
||||
bit_buffer_append_bytes(
|
||||
instance->tx_buffer, type_4_tag_success_apdu, sizeof(type_4_tag_success_apdu));
|
||||
@@ -54,23 +54,18 @@ static Type4TagError type_4_tag_listener_iso_select(
|
||||
|
||||
} else if(
|
||||
instance->state >= Type4TagListenerStateSelectedApplication &&
|
||||
(p1 == TYPE_4_TAG_ISO_SELECT_P1_BY_ID || p1 == TYPE_4_TAG_ISO_SELECT_P1_BY_EF_ID)) {
|
||||
static const uint8_t cc_id[TYPE_4_TAG_T4T_CC_FILE_ID_LEN] = {TYPE_4_TAG_T4T_CC_FILE_ID};
|
||||
if(lc == sizeof(cc_id) && memcmp(cc_id, data, sizeof(cc_id)) == 0) {
|
||||
(p1 == TYPE_4_TAG_ISO_SELECT_P1_BY_ID || p1 == TYPE_4_TAG_ISO_SELECT_P1_BY_EF_ID) &&
|
||||
lc == sizeof(uint16_t)) {
|
||||
uint16_t file_id = bit_lib_bytes_to_num_be(data, sizeof(uint16_t));
|
||||
if(file_id == TYPE_4_TAG_T4T_CC_FILE_ID) {
|
||||
instance->state = Type4TagListenerStateSelectedCapabilityContainer;
|
||||
bit_buffer_append_bytes(
|
||||
instance->tx_buffer, type_4_tag_success_apdu, sizeof(type_4_tag_success_apdu));
|
||||
return Type4TagErrorNone;
|
||||
}
|
||||
|
||||
uint8_t ndef_file_id_be[sizeof(instance->data->ndef_file_id)];
|
||||
bit_lib_num_to_bytes_be(
|
||||
instance->data->is_tag_specific ? instance->data->ndef_file_id :
|
||||
TYPE_4_TAG_T4T_DEFAULT_FILE_ID,
|
||||
sizeof(ndef_file_id_be),
|
||||
ndef_file_id_be);
|
||||
if(lc == sizeof(ndef_file_id_be) &&
|
||||
memcmp(ndef_file_id_be, data, sizeof(ndef_file_id_be)) == 0) {
|
||||
if(file_id == (instance->data->is_tag_specific ? instance->data->ndef_file_id :
|
||||
TYPE_4_TAG_T4T_DEFAULT_FILE_ID)) {
|
||||
instance->state = Type4TagListenerStateSelectedNdefMessage;
|
||||
bit_buffer_append_bytes(
|
||||
instance->tx_buffer, type_4_tag_success_apdu, sizeof(type_4_tag_success_apdu));
|
||||
|
||||
@@ -35,27 +35,106 @@ Type4TagError type_4_tag_apdu_trx(Type4TagPoller* instance, BitBuffer* tx_buf, B
|
||||
return Type4TagErrorNone;
|
||||
} else {
|
||||
FURI_LOG_E(TAG, "APDU failed: 0x%02X%02X", status[0], status[1]);
|
||||
return Type4TagErrorUnknown;
|
||||
return Type4TagErrorApduFailed;
|
||||
}
|
||||
}
|
||||
|
||||
static Type4TagError type_5_tag_poller_iso_select_name(
|
||||
Type4TagPoller* instance,
|
||||
const uint8_t* df_name,
|
||||
uint8_t df_name_len) {
|
||||
const uint8_t type_4_tag_iso_select_name_apdu[] = {
|
||||
TYPE_4_TAG_ISO_SELECT_CMD,
|
||||
TYPE_4_TAG_ISO_SELECT_P1_BY_DF_NAME,
|
||||
TYPE_4_TAG_ISO_SELECT_P2_EMPTY,
|
||||
};
|
||||
|
||||
bit_buffer_append_bytes(
|
||||
instance->tx_buffer,
|
||||
type_4_tag_iso_select_name_apdu,
|
||||
sizeof(type_4_tag_iso_select_name_apdu));
|
||||
bit_buffer_append_byte(instance->tx_buffer, df_name_len);
|
||||
bit_buffer_append_bytes(instance->tx_buffer, df_name, df_name_len);
|
||||
|
||||
return type_4_tag_apdu_trx(instance, instance->tx_buffer, instance->rx_buffer);
|
||||
}
|
||||
|
||||
static Type4TagError
|
||||
type_5_tag_poller_iso_select_file(Type4TagPoller* instance, uint16_t file_id) {
|
||||
const uint8_t type_4_tag_iso_select_file_apdu[] = {
|
||||
TYPE_4_TAG_ISO_SELECT_CMD,
|
||||
TYPE_4_TAG_ISO_SELECT_P1_BY_ID,
|
||||
TYPE_4_TAG_ISO_SELECT_P2_EMPTY,
|
||||
sizeof(file_id),
|
||||
};
|
||||
uint8_t file_id_be[sizeof(file_id)];
|
||||
bit_lib_num_to_bytes_be(file_id, sizeof(file_id), file_id_be);
|
||||
|
||||
bit_buffer_append_bytes(
|
||||
instance->tx_buffer,
|
||||
type_4_tag_iso_select_file_apdu,
|
||||
sizeof(type_4_tag_iso_select_file_apdu));
|
||||
bit_buffer_append_bytes(instance->tx_buffer, file_id_be, sizeof(file_id_be));
|
||||
|
||||
return type_4_tag_apdu_trx(instance, instance->tx_buffer, instance->rx_buffer);
|
||||
}
|
||||
|
||||
static Type4TagError type_5_tag_poller_iso_read(
|
||||
Type4TagPoller* instance,
|
||||
uint16_t offset,
|
||||
uint16_t length,
|
||||
uint8_t* buffer) {
|
||||
const uint8_t chunk_max = instance->data->is_tag_specific ?
|
||||
MIN(instance->data->chunk_max_read, TYPE_4_TAG_CHUNK_LEN) :
|
||||
TYPE_4_TAG_CHUNK_LEN;
|
||||
if(offset + length > TYPE_4_TAG_ISO_READ_P_OFFSET_MAX + chunk_max - sizeof(length)) {
|
||||
FURI_LOG_E(TAG, "File too large: %zu bytes", length);
|
||||
return Type4TagErrorNotSupported;
|
||||
}
|
||||
|
||||
const uint8_t type_4_tag_iso_read_apdu[] = {
|
||||
TYPE_4_TAG_ISO_READ_CMD,
|
||||
};
|
||||
|
||||
while(length > 0) {
|
||||
uint8_t chunk_len = MIN(length, chunk_max);
|
||||
uint8_t offset_be[sizeof(offset)];
|
||||
bit_lib_num_to_bytes_be(offset, sizeof(offset_be), offset_be);
|
||||
|
||||
bit_buffer_append_bytes(
|
||||
instance->tx_buffer, type_4_tag_iso_read_apdu, sizeof(type_4_tag_iso_read_apdu));
|
||||
bit_buffer_append_bytes(instance->tx_buffer, offset_be, sizeof(offset_be));
|
||||
bit_buffer_append_byte(instance->tx_buffer, chunk_len);
|
||||
|
||||
Type4TagError error =
|
||||
type_4_tag_apdu_trx(instance, instance->tx_buffer, instance->rx_buffer);
|
||||
if(error != Type4TagErrorNone) {
|
||||
return error;
|
||||
}
|
||||
if(bit_buffer_get_size_bytes(instance->rx_buffer) != chunk_len) {
|
||||
FURI_LOG_E(
|
||||
TAG,
|
||||
"Wrong chunk len: %zu != %zu",
|
||||
bit_buffer_get_size_bytes(instance->rx_buffer),
|
||||
chunk_len);
|
||||
return Type4TagErrorWrongFormat;
|
||||
}
|
||||
|
||||
memcpy(buffer, bit_buffer_get_data(instance->rx_buffer), chunk_len);
|
||||
buffer += chunk_len;
|
||||
offset += chunk_len;
|
||||
length -= chunk_len;
|
||||
}
|
||||
|
||||
return Type4TagErrorNone;
|
||||
}
|
||||
|
||||
Type4TagError type_4_tag_poller_select_app(Type4TagPoller* instance) {
|
||||
furi_check(instance);
|
||||
|
||||
FURI_LOG_D(TAG, "Select application");
|
||||
const uint8_t type_4_tag_select_app_apdu[] = {
|
||||
TYPE_4_TAG_ISO_SELECT_CMD,
|
||||
TYPE_4_TAG_ISO_SELECT_P1_BY_DF_NAME,
|
||||
TYPE_4_TAG_ISO_SELECT_P2_EMPTY,
|
||||
TYPE_4_TAG_ISO_NAME_LEN,
|
||||
TYPE_4_TAG_ISO_APP_NAME,
|
||||
TYPE_4_TAG_ISO_SELECT_LE_EMPTY,
|
||||
};
|
||||
|
||||
bit_buffer_append_bytes(
|
||||
instance->tx_buffer, type_4_tag_select_app_apdu, sizeof(type_4_tag_select_app_apdu));
|
||||
|
||||
return type_4_tag_apdu_trx(instance, instance->tx_buffer, instance->rx_buffer);
|
||||
return type_5_tag_poller_iso_select_name(
|
||||
instance, type_4_tag_iso_app_name, sizeof(type_4_tag_iso_app_name));
|
||||
}
|
||||
|
||||
Type4TagError type_4_tag_poller_read_cc(Type4TagPoller* instance) {
|
||||
@@ -65,35 +144,22 @@ Type4TagError type_4_tag_poller_read_cc(Type4TagPoller* instance) {
|
||||
|
||||
do {
|
||||
FURI_LOG_D(TAG, "Select CC");
|
||||
const uint8_t type_4_tag_select_cc_apdu[] = {
|
||||
TYPE_4_TAG_ISO_SELECT_CMD,
|
||||
TYPE_4_TAG_ISO_SELECT_P1_BY_ID,
|
||||
TYPE_4_TAG_ISO_SELECT_P2_EMPTY,
|
||||
TYPE_4_TAG_T4T_CC_FILE_ID_LEN,
|
||||
TYPE_4_TAG_T4T_CC_FILE_ID,
|
||||
TYPE_4_TAG_ISO_SELECT_LE_EMPTY,
|
||||
};
|
||||
|
||||
bit_buffer_append_bytes(
|
||||
instance->tx_buffer, type_4_tag_select_cc_apdu, sizeof(type_4_tag_select_cc_apdu));
|
||||
|
||||
error = type_4_tag_apdu_trx(instance, instance->tx_buffer, instance->rx_buffer);
|
||||
error = type_5_tag_poller_iso_select_file(instance, TYPE_4_TAG_T4T_CC_FILE_ID);
|
||||
if(error != Type4TagErrorNone) break;
|
||||
|
||||
FURI_LOG_D(TAG, "Read CC len");
|
||||
uint16_t cc_len;
|
||||
uint8_t cc_len_be[sizeof(cc_len)];
|
||||
error = type_5_tag_poller_iso_read(instance, 0, sizeof(cc_len_be), cc_len_be);
|
||||
if(error != Type4TagErrorNone) break;
|
||||
cc_len = bit_lib_bytes_to_num_be(cc_len_be, sizeof(cc_len_be));
|
||||
|
||||
FURI_LOG_D(TAG, "Read CC");
|
||||
const uint8_t type_4_tag_read_cc_apdu[] = {
|
||||
TYPE_4_TAG_ISO_READ_CMD,
|
||||
TYPE_4_TAG_ISO_READ_P_BEGINNING,
|
||||
TYPE_4_TAG_ISO_READ_LE_FULL,
|
||||
};
|
||||
|
||||
bit_buffer_append_bytes(
|
||||
instance->tx_buffer, type_4_tag_read_cc_apdu, sizeof(type_4_tag_read_cc_apdu));
|
||||
|
||||
error = type_4_tag_apdu_trx(instance, instance->tx_buffer, instance->rx_buffer);
|
||||
uint8_t cc_buf[cc_len];
|
||||
error = type_5_tag_poller_iso_read(instance, 0, sizeof(cc_buf), cc_buf);
|
||||
if(error != Type4TagErrorNone) break;
|
||||
|
||||
error = type_4_tag_cc_parse(instance->data, instance->rx_buffer);
|
||||
error = type_4_tag_cc_parse(instance->data, cc_buf, sizeof(cc_buf));
|
||||
if(error != Type4TagErrorNone) break;
|
||||
instance->data->is_tag_specific = true;
|
||||
|
||||
@@ -110,97 +176,25 @@ Type4TagError type_4_tag_poller_read_ndef(Type4TagPoller* instance) {
|
||||
|
||||
do {
|
||||
FURI_LOG_D(TAG, "Select NDEF");
|
||||
const uint8_t type_4_tag_select_ndef_apdu_1[] = {
|
||||
TYPE_4_TAG_ISO_SELECT_CMD,
|
||||
TYPE_4_TAG_ISO_SELECT_P1_BY_ID,
|
||||
TYPE_4_TAG_ISO_SELECT_P2_EMPTY,
|
||||
sizeof(instance->data->ndef_file_id),
|
||||
};
|
||||
uint8_t ndef_file_id_be[sizeof(instance->data->ndef_file_id)];
|
||||
bit_lib_num_to_bytes_be(
|
||||
instance->data->ndef_file_id, sizeof(instance->data->ndef_file_id), ndef_file_id_be);
|
||||
const uint8_t type_4_tag_select_ndef_apdu_2[] = {
|
||||
TYPE_4_TAG_ISO_SELECT_LE_EMPTY,
|
||||
};
|
||||
|
||||
bit_buffer_append_bytes(
|
||||
instance->tx_buffer,
|
||||
type_4_tag_select_ndef_apdu_1,
|
||||
sizeof(type_4_tag_select_ndef_apdu_1));
|
||||
bit_buffer_append_bytes(instance->tx_buffer, ndef_file_id_be, sizeof(ndef_file_id_be));
|
||||
bit_buffer_append_bytes(
|
||||
instance->tx_buffer,
|
||||
type_4_tag_select_ndef_apdu_2,
|
||||
sizeof(type_4_tag_select_ndef_apdu_2));
|
||||
|
||||
error = type_4_tag_apdu_trx(instance, instance->tx_buffer, instance->rx_buffer);
|
||||
error = type_5_tag_poller_iso_select_file(instance, instance->data->ndef_file_id);
|
||||
if(error != Type4TagErrorNone) break;
|
||||
|
||||
FURI_LOG_D(TAG, "Read NDEF len");
|
||||
uint16_t ndef_len;
|
||||
const uint8_t type_4_tag_read_ndef_len_apdu[] = {
|
||||
TYPE_4_TAG_ISO_READ_CMD,
|
||||
TYPE_4_TAG_ISO_READ_P_BEGINNING,
|
||||
sizeof(ndef_len),
|
||||
};
|
||||
|
||||
bit_buffer_append_bytes(
|
||||
instance->tx_buffer,
|
||||
type_4_tag_read_ndef_len_apdu,
|
||||
sizeof(type_4_tag_read_ndef_len_apdu));
|
||||
|
||||
error = type_4_tag_apdu_trx(instance, instance->tx_buffer, instance->rx_buffer);
|
||||
uint8_t ndef_len_be[sizeof(ndef_len)];
|
||||
error = type_5_tag_poller_iso_read(instance, 0, sizeof(ndef_len_be), ndef_len_be);
|
||||
if(error != Type4TagErrorNone) break;
|
||||
ndef_len = bit_lib_bytes_to_num_be(ndef_len_be, sizeof(ndef_len_be));
|
||||
|
||||
ndef_len =
|
||||
bit_lib_bytes_to_num_be(bit_buffer_get_data(instance->rx_buffer), sizeof(ndef_len));
|
||||
if(ndef_len == 0) {
|
||||
FURI_LOG_D(TAG, "NDEF file is empty");
|
||||
break;
|
||||
}
|
||||
uint8_t chunk_max = MIN(instance->data->chunk_max_read, TYPE_4_TAG_CHUNK_LEN);
|
||||
if(ndef_len > TYPE_4_TAG_ISO_READ_P_OFFSET_MAX + chunk_max - sizeof(ndef_len)) {
|
||||
FURI_LOG_E(TAG, "NDEF file too long: %zu bytes", ndef_len);
|
||||
error = Type4TagErrorNotSupported;
|
||||
break;
|
||||
}
|
||||
simple_array_init(instance->data->ndef_data, ndef_len);
|
||||
|
||||
FURI_LOG_D(TAG, "Read NDEF");
|
||||
const uint8_t type_4_tag_read_ndef_apdu_1[] = {
|
||||
TYPE_4_TAG_ISO_READ_CMD,
|
||||
};
|
||||
|
||||
uint16_t ndef_pos = 0;
|
||||
uint8_t* ndef_data = simple_array_get_data(instance->data->ndef_data);
|
||||
while(ndef_len > 0) {
|
||||
uint8_t chunk_len = MIN(ndef_len, chunk_max);
|
||||
uint8_t ndef_pos_be[sizeof(ndef_pos)];
|
||||
bit_lib_num_to_bytes_be(sizeof(ndef_len) + ndef_pos, sizeof(ndef_pos_be), ndef_pos_be);
|
||||
|
||||
bit_buffer_append_bytes(
|
||||
instance->tx_buffer,
|
||||
type_4_tag_read_ndef_apdu_1,
|
||||
sizeof(type_4_tag_read_ndef_apdu_1));
|
||||
bit_buffer_append_bytes(instance->tx_buffer, ndef_pos_be, sizeof(ndef_pos_be));
|
||||
bit_buffer_append_byte(instance->tx_buffer, chunk_len);
|
||||
|
||||
error = type_4_tag_apdu_trx(instance, instance->tx_buffer, instance->rx_buffer);
|
||||
if(error != Type4TagErrorNone) break;
|
||||
if(bit_buffer_get_size_bytes(instance->rx_buffer) != chunk_len) {
|
||||
FURI_LOG_E(
|
||||
TAG,
|
||||
"Wrong NDEF chunk len: %zu != %zu",
|
||||
bit_buffer_get_size_bytes(instance->rx_buffer),
|
||||
ndef_len);
|
||||
error = Type4TagErrorWrongFormat;
|
||||
break;
|
||||
}
|
||||
memcpy(&ndef_data[ndef_pos], bit_buffer_get_data(instance->rx_buffer), chunk_len);
|
||||
|
||||
ndef_pos += chunk_len;
|
||||
ndef_len -= chunk_len;
|
||||
}
|
||||
simple_array_init(instance->data->ndef_data, ndef_len);
|
||||
uint8_t* ndef_buf = simple_array_get_data(instance->data->ndef_data);
|
||||
error = type_5_tag_poller_iso_read(instance, sizeof(ndef_len), ndef_len, ndef_buf);
|
||||
if(error != Type4TagErrorNone) break;
|
||||
|
||||
FURI_LOG_D(
|
||||
|
||||
Reference in New Issue
Block a user