10 static const char *
const TAG =
"pn7160.mifare_ultralight";
13 std::vector<uint8_t> data;
16 data) != nfc::STATUS_OK) {
17 return nfc::STATUS_FAILED;
21 ESP_LOGW(TAG,
"Not NDEF formatted");
22 return nfc::STATUS_FAILED;
25 uint8_t message_length;
26 uint8_t message_start_index;
28 ESP_LOGW(TAG,
"Couldn't find NDEF message");
29 return nfc::STATUS_FAILED;
31 ESP_LOGVV(TAG,
"NDEF message length: %u, start: %u", message_length, message_start_index);
33 if (message_length == 0) {
34 return nfc::STATUS_FAILED;
37 const uint8_t read_length = message_length + message_start_index > 12 ? message_length + message_start_index - 12 : 0;
41 ESP_LOGE(TAG,
"Error reading tag data");
42 return nfc::STATUS_FAILED;
46 data.erase(data.begin(), data.begin() + message_start_index + nfc::MIFARE_ULTRALIGHT_PAGE_SIZE);
50 return nfc::STATUS_OK;
54 const uint8_t read_increment = nfc::MIFARE_ULTRALIGHT_READ_SIZE * nfc::MIFARE_ULTRALIGHT_PAGE_SIZE;
56 nfc::NciMessage tx(nfc::NCI_PKT_MT_DATA, {nfc::MIFARE_CMD_READ, start_page});
58 for (
size_t i = 0; i * read_increment < num_bytes; i++) {
59 tx.
get_message().back() = i * nfc::MIFARE_ULTRALIGHT_READ_SIZE + start_page;
62 ESP_LOGE(TAG,
"Error reading tag data");
63 return nfc::STATUS_FAILED;
66 uint16_t bytes_offset = (i + 1) * read_increment;
67 auto pages_in_end_itr = bytes_offset <= num_bytes ? rx.
get_message().end() - 1
68 : rx.
get_message().end() - (bytes_offset - num_bytes + 1);
71 data.insert(data.end(), rx.
get_message().begin() + nfc::NCI_PKT_HEADER_SIZE, pages_in_end_itr);
77 return nfc::STATUS_OK;
81 const uint8_t p4_offset = nfc::MIFARE_ULTRALIGHT_PAGE_SIZE;
83 return (page_3_to_6.size() > p4_offset + 3) &&
84 !((page_3_to_6[p4_offset + 0] == 0xFF) && (page_3_to_6[p4_offset + 1] == 0xFF) &&
85 (page_3_to_6[p4_offset + 2] == 0xFF) && (page_3_to_6[p4_offset + 3] == 0xFF));
89 std::vector<uint8_t> data;
91 ESP_LOGV(TAG,
"Tag capacity is %u bytes", data[2] * 8U);
98 uint8_t &message_start_index) {
99 const uint8_t p4_offset = nfc::MIFARE_ULTRALIGHT_PAGE_SIZE;
101 if (!(page_3_to_6.size() > p4_offset + 5)) {
102 return nfc::STATUS_FAILED;
105 if (page_3_to_6[p4_offset + 0] == 0x03) {
106 message_length = page_3_to_6[p4_offset + 1];
107 message_start_index = 2;
108 return nfc::STATUS_OK;
109 }
else if (page_3_to_6[p4_offset + 5] == 0x03) {
110 message_length = page_3_to_6[p4_offset + 6];
111 message_start_index = 7;
112 return nfc::STATUS_OK;
114 return nfc::STATUS_FAILED;
118 const std::shared_ptr<nfc::NdefMessage> &message) {
121 auto encoded = message->encode();
123 uint32_t message_length = encoded.size();
126 if (buffer_length > capacity) {
127 ESP_LOGE(TAG,
"Message length exceeds tag capacity %" PRIu32
" > %" PRIu32, buffer_length, capacity);
128 return nfc::STATUS_FAILED;
131 encoded.insert(encoded.begin(), 0x03);
132 if (message_length < 255) {
133 encoded.insert(encoded.begin() + 1, message_length);
135 encoded.insert(encoded.begin() + 1, 0xFF);
136 encoded.insert(encoded.begin() + 2, (message_length >> 8) & 0xFF);
137 encoded.insert(encoded.begin() + 2, message_length & 0xFF);
139 encoded.push_back(0xFE);
141 encoded.resize(buffer_length, 0);
144 uint8_t current_page = nfc::MIFARE_ULTRALIGHT_DATA_START_PAGE;
146 while (index < buffer_length) {
147 std::vector<uint8_t> data(encoded.begin() + index, encoded.begin() + index + nfc::MIFARE_ULTRALIGHT_PAGE_SIZE);
149 return nfc::STATUS_FAILED;
151 index += nfc::MIFARE_ULTRALIGHT_PAGE_SIZE;
154 return nfc::STATUS_OK;
159 uint8_t pages = (capacity / nfc::MIFARE_ULTRALIGHT_PAGE_SIZE) + nfc::MIFARE_ULTRALIGHT_DATA_START_PAGE;
161 std::vector<uint8_t> blank_data = {0x00, 0x00, 0x00, 0x00};
163 for (
int i = nfc::MIFARE_ULTRALIGHT_DATA_START_PAGE; i < pages; i++) {
165 return nfc::STATUS_FAILED;
168 return nfc::STATUS_OK;
172 std::vector<uint8_t> payload = {nfc::MIFARE_CMD_WRITE_ULTRALIGHT, page_num};
173 payload.insert(payload.end(), write_data.begin(), write_data.end());
178 if (this->
transceive_(tx, rx, NFCC_TAG_WRITE_TIMEOUT) != nfc::STATUS_OK) {
179 ESP_LOGE(TAG,
"Error writing page %u", page_num);
180 return nfc::STATUS_FAILED;
182 return nfc::STATUS_OK;
uint8_t read_mifare_ultralight_tag_(nfc::NfcTag &tag)
uint8_t read_mifare_ultralight_bytes_(uint8_t start_page, uint16_t num_bytes, std::vector< uint8_t > &data)
uint8_t write_mifare_ultralight_page_(uint8_t page_num, std::vector< uint8_t > &write_data)
void set_ndef_message(std::unique_ptr< NdefMessage > ndef_message)
uint16_t read_mifare_ultralight_capacity_()
uint8_t find_mifare_ultralight_ndef_(const std::vector< uint8_t > &page_3_to_6, uint8_t &message_length, uint8_t &message_start_index)
bool is_mifare_ultralight_formatted_(const std::vector< uint8_t > &page_3_to_6)
std::vector< uint8_t > & get_message()
uint8_t write_mifare_ultralight_tag_(std::vector< uint8_t > &uid, const std::shared_ptr< nfc::NdefMessage > &message)
uint8_t get_payload_size(bool recompute=false)
uint8_t transceive_(nfc::NciMessage &tx, nfc::NciMessage &rx, uint16_t timeout=NFCC_DEFAULT_TIMEOUT, bool expect_notification=true)
Implementation of SPI Controller mode.
uint32_t get_mifare_ultralight_buffer_size(uint32_t message_length)
uint8_t clean_mifare_ultralight_()
std::string format_bytes(std::vector< uint8_t > &bytes)