mirror of
https://github.com/Next-Flip/Momentum-Firmware.git
synced 2026-07-25 01:38:11 -07:00
Refactor CC parsing and dumping
This commit is contained in:
@@ -1,5 +1,7 @@
|
||||
#include "type_4_tag_i.h"
|
||||
|
||||
#include <bit_lib/bit_lib.h>
|
||||
|
||||
#define TAG "Type4Tag"
|
||||
|
||||
#define TYPE_4_TAG_FFF_NDEF_DATA_SIZE_KEY "NDEF Data Size"
|
||||
@@ -20,6 +22,88 @@ Type4TagError type_4_tag_process_error(Iso14443_4aError error) {
|
||||
}
|
||||
}
|
||||
|
||||
void type_4_tag_cc_dump(const Type4TagData* data, uint8_t* buf, size_t len) {
|
||||
furi_check(len >= TYPE_4_TAG_T4T_CC_MIN_SIZE);
|
||||
Type4TagCc* cc = (Type4TagCc*)buf;
|
||||
|
||||
bit_lib_num_to_bytes_be(TYPE_4_TAG_T4T_CC_MIN_SIZE, sizeof(cc->len), (void*)&cc->len);
|
||||
cc->t4t_vno = TYPE_4_TAG_T4T_CC_VNO;
|
||||
bit_lib_num_to_bytes_be(
|
||||
data->is_tag_specific ? MIN(data->chunk_max_read, TYPE_4_TAG_CHUNK_LEN) :
|
||||
TYPE_4_TAG_CHUNK_LEN,
|
||||
sizeof(cc->mle),
|
||||
(void*)&cc->mle);
|
||||
bit_lib_num_to_bytes_be(
|
||||
data->is_tag_specific ? MIN(data->chunk_max_write, TYPE_4_TAG_CHUNK_LEN) :
|
||||
TYPE_4_TAG_CHUNK_LEN,
|
||||
sizeof(cc->mlc),
|
||||
(void*)&cc->mlc);
|
||||
|
||||
cc->tlv[0].type = Type4TagCcTlvTypeNdefFileCtrl;
|
||||
cc->tlv[0].len = sizeof(cc->tlv[0].value.ndef_file_ctrl);
|
||||
|
||||
bit_lib_num_to_bytes_be(
|
||||
data->is_tag_specific ? data->ndef_file_id : TYPE_4_TAG_T4T_DEFAULT_FILE_ID,
|
||||
sizeof(cc->tlv[0].value.ndef_file_ctrl.file_id),
|
||||
(void*)&cc->tlv[0].value.ndef_file_ctrl.file_id);
|
||||
bit_lib_num_to_bytes_be(
|
||||
data->is_tag_specific ? data->ndef_max_len : TYPE_4_TAG_DEFAULT_SIZE,
|
||||
sizeof(cc->tlv[0].value.ndef_file_ctrl.max_len),
|
||||
(void*)&cc->tlv[0].value.ndef_file_ctrl.max_len);
|
||||
cc->tlv[0].value.ndef_file_ctrl.read_perm =
|
||||
data->is_tag_specific ? data->ndef_read_lock : TYPE_4_TAG_T4T_CC_RW_LOCK_NONE;
|
||||
cc->tlv[0].value.ndef_file_ctrl.write_perm =
|
||||
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) {
|
||||
FURI_LOG_E(TAG, "Unsupported T4T version");
|
||||
return Type4TagErrorWrongFormat;
|
||||
}
|
||||
|
||||
const Type4TagCc* cc = (const Type4TagCc*)bit_buffer_get_data(buf);
|
||||
if(cc->t4t_vno != TYPE_4_TAG_T4T_CC_VNO) {
|
||||
FURI_LOG_E(TAG, "Unsupported T4T version");
|
||||
return Type4TagErrorNotSupported;
|
||||
}
|
||||
|
||||
const Type4TagCcTlv* tlv = cc->tlv;
|
||||
const Type4TagCcTlvNdefFileCtrl* ndef_file_ctrl = NULL;
|
||||
const void* end = MIN((void*)cc + cc->len, (void*)cc + cc_len);
|
||||
while((void*)tlv < end) {
|
||||
if(tlv->type == Type4TagCcTlvTypeNdefFileCtrl) {
|
||||
ndef_file_ctrl = &tlv->value.ndef_file_ctrl;
|
||||
break;
|
||||
}
|
||||
|
||||
if(tlv->len < 0xFF) {
|
||||
tlv = (void*)&tlv->value + tlv->len;
|
||||
} else {
|
||||
uint16_t len = bit_lib_bytes_to_num_be((void*)&tlv->len + 1, sizeof(uint16_t));
|
||||
tlv = (void*)&tlv->value + sizeof(len) + len;
|
||||
}
|
||||
}
|
||||
if(!ndef_file_ctrl) {
|
||||
FURI_LOG_E(TAG, "No NDEF file ctrl TLV");
|
||||
return Type4TagErrorWrongFormat;
|
||||
}
|
||||
|
||||
data->t4t_version.value = cc->t4t_vno;
|
||||
data->chunk_max_read = bit_lib_bytes_to_num_be((void*)&cc->mle, sizeof(cc->mle));
|
||||
data->chunk_max_write = bit_lib_bytes_to_num_be((void*)&cc->mlc, sizeof(cc->mlc));
|
||||
data->ndef_file_id =
|
||||
bit_lib_bytes_to_num_be((void*)&ndef_file_ctrl->file_id, sizeof(ndef_file_ctrl->file_id));
|
||||
data->ndef_max_len =
|
||||
bit_lib_bytes_to_num_be((void*)&ndef_file_ctrl->max_len, sizeof(ndef_file_ctrl->max_len)) -
|
||||
sizeof(uint16_t);
|
||||
data->ndef_read_lock = ndef_file_ctrl->read_perm;
|
||||
data->ndef_write_lock = ndef_file_ctrl->write_perm;
|
||||
|
||||
return Type4TagErrorNone;
|
||||
}
|
||||
|
||||
bool type_4_tag_ndef_data_load(Type4TagData* data, FlipperFormat* ff) {
|
||||
uint32_t ndef_data_size;
|
||||
if(!flipper_format_read_uint32(ff, TYPE_4_TAG_FFF_NDEF_DATA_SIZE_KEY, &ndef_data_size, 1)) {
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#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
|
||||
#define TYPE_4_TAG_T4T_CC_MIN_SIZE (sizeof(Type4TagCc) + sizeof(Type4TagCcTlv))
|
||||
|
||||
// 4a layer adds 1..3 byte prefix, 3a layer adds 2 byte suffix and has 256 byte buffer
|
||||
#define TYPE_4_TAG_BUF_SIZE (256U - 3U - 2U)
|
||||
@@ -77,6 +78,10 @@ typedef struct FURI_PACKED {
|
||||
|
||||
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);
|
||||
|
||||
// Load internal Type4Tag structures
|
||||
|
||||
bool type_4_tag_ndef_data_load(Type4TagData* data, FlipperFormat* ff);
|
||||
|
||||
@@ -104,7 +104,7 @@ static Type4TagError type_4_tag_listener_iso_read(
|
||||
}
|
||||
|
||||
if(instance->state == Type4TagListenerStateSelectedCapabilityContainer) {
|
||||
uint8_t cc_buf[sizeof(Type4TagCc) + sizeof(Type4TagCcTlv)];
|
||||
uint8_t cc_buf[TYPE_4_TAG_T4T_CC_MIN_SIZE];
|
||||
if(offset >= sizeof(cc_buf)) {
|
||||
bit_buffer_append_bytes(
|
||||
instance->tx_buffer,
|
||||
@@ -112,39 +112,7 @@ static Type4TagError type_4_tag_listener_iso_read(
|
||||
sizeof(type_4_tag_offset_error_apdu));
|
||||
return Type4TagErrorWrongFormat;
|
||||
}
|
||||
Type4TagCc* cc = (Type4TagCc*)cc_buf;
|
||||
bit_lib_num_to_bytes_be(sizeof(cc_buf), sizeof(cc->len), (void*)&cc->len);
|
||||
cc->t4t_vno = TYPE_4_TAG_T4T_CC_VNO;
|
||||
bit_lib_num_to_bytes_be(
|
||||
instance->data->is_tag_specific ?
|
||||
MIN(instance->data->chunk_max_read, TYPE_4_TAG_CHUNK_LEN) :
|
||||
TYPE_4_TAG_CHUNK_LEN,
|
||||
sizeof(cc->mle),
|
||||
(void*)&cc->mle);
|
||||
bit_lib_num_to_bytes_be(
|
||||
instance->data->is_tag_specific ?
|
||||
MIN(instance->data->chunk_max_write, TYPE_4_TAG_CHUNK_LEN) :
|
||||
TYPE_4_TAG_CHUNK_LEN,
|
||||
sizeof(cc->mlc),
|
||||
(void*)&cc->mlc);
|
||||
cc->tlv[0].type = Type4TagCcTlvTypeNdefFileCtrl;
|
||||
cc->tlv[0].len = sizeof(cc->tlv[0].value.ndef_file_ctrl);
|
||||
bit_lib_num_to_bytes_be(
|
||||
instance->data->is_tag_specific ? instance->data->ndef_file_id :
|
||||
TYPE_4_TAG_T4T_DEFAULT_FILE_ID,
|
||||
sizeof(cc->tlv[0].value.ndef_file_ctrl.file_id),
|
||||
(void*)&cc->tlv[0].value.ndef_file_ctrl.file_id);
|
||||
bit_lib_num_to_bytes_be(
|
||||
instance->data->is_tag_specific ? instance->data->ndef_max_len :
|
||||
TYPE_4_TAG_DEFAULT_SIZE,
|
||||
sizeof(cc->tlv[0].value.ndef_file_ctrl.max_len),
|
||||
(void*)&cc->tlv[0].value.ndef_file_ctrl.max_len);
|
||||
cc->tlv[0].value.ndef_file_ctrl.read_perm = instance->data->is_tag_specific ?
|
||||
instance->data->ndef_read_lock :
|
||||
TYPE_4_TAG_T4T_CC_RW_LOCK_NONE;
|
||||
cc->tlv[0].value.ndef_file_ctrl.write_perm = instance->data->is_tag_specific ?
|
||||
instance->data->ndef_write_lock :
|
||||
TYPE_4_TAG_T4T_CC_RW_LOCK_NONE;
|
||||
type_4_tag_cc_dump(instance->data, cc_buf, sizeof(cc_buf));
|
||||
|
||||
bit_buffer_append_bytes(
|
||||
instance->tx_buffer, cc_buf + offset, MIN(sizeof(cc_buf) - offset, le));
|
||||
|
||||
@@ -93,47 +93,9 @@ Type4TagError type_4_tag_poller_read_cc(Type4TagPoller* instance) {
|
||||
error = type_4_tag_apdu_trx(instance, instance->tx_buffer, instance->rx_buffer);
|
||||
if(error != Type4TagErrorNone) break;
|
||||
|
||||
const Type4TagCc* cc = (const Type4TagCc*)bit_buffer_get_data(instance->rx_buffer);
|
||||
if(cc->t4t_vno != TYPE_4_TAG_T4T_CC_VNO) {
|
||||
FURI_LOG_E(TAG, "Unsupported T4T version");
|
||||
error = Type4TagErrorNotSupported;
|
||||
break;
|
||||
}
|
||||
|
||||
const Type4TagCcTlv* tlv = cc->tlv;
|
||||
const Type4TagCcTlvNdefFileCtrl* ndef_file_ctrl = NULL;
|
||||
while((void*)tlv < (void*)cc + cc->len) {
|
||||
if(tlv->type == Type4TagCcTlvTypeNdefFileCtrl) {
|
||||
ndef_file_ctrl = &tlv->value.ndef_file_ctrl;
|
||||
break;
|
||||
}
|
||||
|
||||
if(tlv->len < 0xFF) {
|
||||
tlv = (void*)&tlv->value + tlv->len;
|
||||
} else {
|
||||
uint16_t len = bit_lib_bytes_to_num_be((void*)&tlv->len + 1, sizeof(uint16_t));
|
||||
tlv = (void*)&tlv->value + sizeof(len) + len;
|
||||
}
|
||||
}
|
||||
if(!ndef_file_ctrl) {
|
||||
FURI_LOG_E(TAG, "No NDEF file ctrl TLV");
|
||||
error = Type4TagErrorWrongFormat;
|
||||
break;
|
||||
}
|
||||
|
||||
error = type_4_tag_cc_parse(instance->data, instance->rx_buffer);
|
||||
if(error != Type4TagErrorNone) break;
|
||||
instance->data->is_tag_specific = true;
|
||||
instance->data->t4t_version.value = cc->t4t_vno;
|
||||
instance->data->chunk_max_read = bit_lib_bytes_to_num_be((void*)&cc->mle, sizeof(cc->mle));
|
||||
instance->data->chunk_max_write =
|
||||
bit_lib_bytes_to_num_be((void*)&cc->mlc, sizeof(cc->mlc));
|
||||
instance->data->ndef_file_id = bit_lib_bytes_to_num_be(
|
||||
(void*)&ndef_file_ctrl->file_id, sizeof(ndef_file_ctrl->file_id));
|
||||
instance->data->ndef_max_len =
|
||||
bit_lib_bytes_to_num_be(
|
||||
(void*)&ndef_file_ctrl->max_len, sizeof(ndef_file_ctrl->max_len)) -
|
||||
sizeof(uint16_t);
|
||||
instance->data->ndef_read_lock = ndef_file_ctrl->read_perm;
|
||||
instance->data->ndef_write_lock = ndef_file_ctrl->write_perm;
|
||||
|
||||
FURI_LOG_D(TAG, "Detected NDEF file ID 0x%04X", instance->data->ndef_file_id);
|
||||
} while(false);
|
||||
|
||||
Reference in New Issue
Block a user