#include "nfc.h" #include #include "esphome/core/helpers.h" #include "esphome/core/log.h" namespace esphome { namespace nfc { static const char *const TAG = "nfc"; char *format_uid_to(char *buffer, std::span uid) { return format_hex_pretty_to(buffer, FORMAT_UID_BUFFER_SIZE, uid.data(), uid.size(), '-'); } char *format_bytes_to(char *buffer, std::span bytes) { return format_hex_pretty_to(buffer, FORMAT_BYTES_BUFFER_SIZE, bytes.data(), bytes.size(), ' '); } #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wdeprecated-declarations" // Deprecated wrappers intentionally use heap-allocating version for backward compatibility std::string format_uid(std::span uid) { return format_hex_pretty(uid.data(), uid.size(), '-', false); // NOLINT } std::string format_bytes(std::span bytes) { return format_hex_pretty(bytes.data(), bytes.size(), ' ', false); // NOLINT } #pragma GCC diagnostic pop uint8_t guess_tag_type(uint8_t uid_length) { if (uid_length == 4) { return TAG_TYPE_MIFARE_CLASSIC; } else { return TAG_TYPE_2; } } int8_t get_mifare_classic_ndef_start_index(std::vector &data) { for (uint8_t i = 0; i < MIFARE_CLASSIC_BLOCK_SIZE; i++) { if (data[i] == 0x00) { // Do nothing, skip } else if (data[i] == 0x03) { return i; } else { return -2; } } return -1; } bool decode_mifare_classic_tlv(std::vector &data, uint32_t &message_length, uint8_t &message_start_index) { if (data.size() < MIFARE_CLASSIC_BLOCK_SIZE) { ESP_LOGE(TAG, "Error, data too short for NDEF detection."); return false; } auto i = get_mifare_classic_ndef_start_index(data); if (i < 0 || data[i] != 0x03) { ESP_LOGE(TAG, "Error, Can't decode message length."); return false; } uint8_t idx = static_cast(i); if (idx + 4 <= data.size() && data[idx + 1] == 0xFF) { message_length = ((0xFF & data[idx + 2]) << 8) | (0xFF & data[idx + 3]); message_start_index = idx + MIFARE_CLASSIC_LONG_TLV_SIZE; } else if (idx + 2 <= data.size()) { message_length = data[idx + 1]; message_start_index = idx + MIFARE_CLASSIC_SHORT_TLV_SIZE; } else { ESP_LOGE(TAG, "Error, TLV data too short."); return false; } return true; } uint32_t get_mifare_ultralight_buffer_size(uint32_t message_length) { uint32_t buffer_size = message_length + 2 + 1; if (buffer_size % MIFARE_ULTRALIGHT_READ_SIZE != 0) buffer_size = ((buffer_size / MIFARE_ULTRALIGHT_READ_SIZE) + 1) * MIFARE_ULTRALIGHT_READ_SIZE; return buffer_size; } uint32_t get_mifare_classic_buffer_size(uint32_t message_length) { uint32_t buffer_size = message_length; if (message_length < 255) { buffer_size += MIFARE_CLASSIC_SHORT_TLV_SIZE + 1; } else { buffer_size += MIFARE_CLASSIC_LONG_TLV_SIZE + 1; } if (buffer_size % MIFARE_CLASSIC_BLOCK_SIZE != 0) { buffer_size = ((buffer_size / MIFARE_CLASSIC_BLOCK_SIZE) + 1) * MIFARE_CLASSIC_BLOCK_SIZE; } return buffer_size; } bool mifare_classic_is_first_block(uint8_t block_num) { if (block_num < MIFARE_CLASSIC_BLOCKS_PER_SECT_LOW * MIFARE_CLASSIC_16BLOCK_SECT_START) { return (block_num % MIFARE_CLASSIC_BLOCKS_PER_SECT_LOW == 0); } else { return (block_num % MIFARE_CLASSIC_BLOCKS_PER_SECT_HIGH == 0); } } bool mifare_classic_is_trailer_block(uint8_t block_num) { if (block_num < MIFARE_CLASSIC_BLOCKS_PER_SECT_LOW * MIFARE_CLASSIC_16BLOCK_SECT_START) { return ((block_num + 1) % MIFARE_CLASSIC_BLOCKS_PER_SECT_LOW == 0); } else { return ((block_num + 1) % MIFARE_CLASSIC_BLOCKS_PER_SECT_HIGH == 0); } } } // namespace nfc } // namespace esphome