ESPHome 2026.3.3
Loading...
Searching...
No Matches
nfc.cpp
Go to the documentation of this file.
1#include "nfc.h"
2#include <cstdio>
4#include "esphome/core/log.h"
5
6namespace esphome {
7namespace nfc {
8
9static const char *const TAG = "nfc";
10
11char *format_uid_to(char *buffer, std::span<const uint8_t> uid) {
12 return format_hex_pretty_to(buffer, FORMAT_UID_BUFFER_SIZE, uid.data(), uid.size(), '-');
13}
14
15char *format_bytes_to(char *buffer, std::span<const uint8_t> bytes) {
16 return format_hex_pretty_to(buffer, FORMAT_BYTES_BUFFER_SIZE, bytes.data(), bytes.size(), ' ');
17}
18
19#pragma GCC diagnostic push
20#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
21// Deprecated wrappers intentionally use heap-allocating version for backward compatibility
22std::string format_uid(std::span<const uint8_t> uid) {
23 return format_hex_pretty(uid.data(), uid.size(), '-', false); // NOLINT
24}
25std::string format_bytes(std::span<const uint8_t> bytes) {
26 return format_hex_pretty(bytes.data(), bytes.size(), ' ', false); // NOLINT
27}
28#pragma GCC diagnostic pop
29
30uint8_t guess_tag_type(uint8_t uid_length) {
31 if (uid_length == 4) {
32 return TAG_TYPE_MIFARE_CLASSIC;
33 } else {
34 return TAG_TYPE_2;
35 }
36}
37
38int8_t get_mifare_classic_ndef_start_index(std::vector<uint8_t> &data) {
39 for (uint8_t i = 0; i < MIFARE_CLASSIC_BLOCK_SIZE; i++) {
40 if (data[i] == 0x00) {
41 // Do nothing, skip
42 } else if (data[i] == 0x03) {
43 return i;
44 } else {
45 return -2;
46 }
47 }
48 return -1;
49}
50
51bool decode_mifare_classic_tlv(std::vector<uint8_t> &data, uint32_t &message_length, uint8_t &message_start_index) {
52 if (data.size() < MIFARE_CLASSIC_BLOCK_SIZE) {
53 ESP_LOGE(TAG, "Error, data too short for NDEF detection.");
54 return false;
55 }
57 if (i < 0 || data[i] != 0x03) {
58 ESP_LOGE(TAG, "Error, Can't decode message length.");
59 return false;
60 }
61 uint8_t idx = static_cast<uint8_t>(i);
62 if (idx + 4 <= data.size() && data[idx + 1] == 0xFF) {
63 message_length = ((0xFF & data[idx + 2]) << 8) | (0xFF & data[idx + 3]);
64 message_start_index = idx + MIFARE_CLASSIC_LONG_TLV_SIZE;
65 } else if (idx + 2 <= data.size()) {
66 message_length = data[idx + 1];
67 message_start_index = idx + MIFARE_CLASSIC_SHORT_TLV_SIZE;
68 } else {
69 ESP_LOGE(TAG, "Error, TLV data too short.");
70 return false;
71 }
72 return true;
73}
74
76 uint32_t buffer_size = message_length + 2 + 1;
77 if (buffer_size % MIFARE_ULTRALIGHT_READ_SIZE != 0)
78 buffer_size = ((buffer_size / MIFARE_ULTRALIGHT_READ_SIZE) + 1) * MIFARE_ULTRALIGHT_READ_SIZE;
79 return buffer_size;
80}
81
83 uint32_t buffer_size = message_length;
84 if (message_length < 255) {
85 buffer_size += MIFARE_CLASSIC_SHORT_TLV_SIZE + 1;
86 } else {
87 buffer_size += MIFARE_CLASSIC_LONG_TLV_SIZE + 1;
88 }
89 if (buffer_size % MIFARE_CLASSIC_BLOCK_SIZE != 0) {
90 buffer_size = ((buffer_size / MIFARE_CLASSIC_BLOCK_SIZE) + 1) * MIFARE_CLASSIC_BLOCK_SIZE;
91 }
92 return buffer_size;
93}
94
95bool mifare_classic_is_first_block(uint8_t block_num) {
96 if (block_num < MIFARE_CLASSIC_BLOCKS_PER_SECT_LOW * MIFARE_CLASSIC_16BLOCK_SECT_START) {
97 return (block_num % MIFARE_CLASSIC_BLOCKS_PER_SECT_LOW == 0);
98 } else {
99 return (block_num % MIFARE_CLASSIC_BLOCKS_PER_SECT_HIGH == 0);
100 }
101}
102
103bool mifare_classic_is_trailer_block(uint8_t block_num) {
104 if (block_num < MIFARE_CLASSIC_BLOCKS_PER_SECT_LOW * MIFARE_CLASSIC_16BLOCK_SECT_START) {
105 return ((block_num + 1) % MIFARE_CLASSIC_BLOCKS_PER_SECT_LOW == 0);
106 } else {
107 return ((block_num + 1) % MIFARE_CLASSIC_BLOCKS_PER_SECT_HIGH == 0);
108 }
109}
110
111} // namespace nfc
112} // namespace esphome
bool decode_mifare_classic_tlv(std::vector< uint8_t > &data, uint32_t &message_length, uint8_t &message_start_index)
Definition nfc.cpp:51
char * format_bytes_to(char *buffer, std::span< const uint8_t > bytes)
Format bytes to buffer with ' ' separator (e.g., "04 11 22 33"). Returns buffer for inline use.
Definition nfc.cpp:15
uint32_t get_mifare_ultralight_buffer_size(uint32_t message_length)
Definition nfc.cpp:75
std::string format_uid(std::span< const uint8_t > uid)
Definition nfc.cpp:22
std::string format_bytes(std::span< const uint8_t > bytes)
Definition nfc.cpp:25
char * format_uid_to(char *buffer, std::span< const uint8_t > uid)
Format UID to buffer with '-' separator (e.g., "04-11-22-33"). Returns buffer for inline use.
Definition nfc.cpp:11
uint8_t guess_tag_type(uint8_t uid_length)
Definition nfc.cpp:30
bool mifare_classic_is_trailer_block(uint8_t block_num)
Definition nfc.cpp:103
uint32_t get_mifare_classic_buffer_size(uint32_t message_length)
Definition nfc.cpp:82
int8_t get_mifare_classic_ndef_start_index(std::vector< uint8_t > &data)
Definition nfc.cpp:38
bool mifare_classic_is_first_block(uint8_t block_num)
Definition nfc.cpp:95
Providing packet encoding functions for exchanging data with a remote host.
Definition a01nyub.cpp:7
char * format_hex_pretty_to(char *buffer, size_t buffer_size, const uint8_t *data, size_t length, char separator)
Format byte array as uppercase hex to buffer (base implementation).
Definition helpers.cpp:353
std::string format_hex_pretty(const uint8_t *data, size_t length, char separator, bool show_length)
Format a byte array in pretty-printed, human-readable hex format.
Definition helpers.cpp:401
static void uint32_t