ESPHome 2026.1.5
Loading...
Searching...
No Matches
pn7150.cpp
Go to the documentation of this file.
1#include "automation.h"
2#include "pn7150.h"
3
4#include <utility>
5
6#include "esphome/core/hal.h"
8#include "esphome/core/log.h"
9
10namespace esphome {
11namespace pn7150 {
12
13static const char *const TAG = "pn7150";
14
16 this->irq_pin_->setup();
17 this->ven_pin_->setup();
18
19 this->nci_fsm_transition_(); // kick off reset & init processes
20}
21
23 ESP_LOGCONFIG(TAG, "PN7150:");
24 LOG_PIN(" IRQ pin: ", this->irq_pin_);
25 LOG_PIN(" VEN pin: ", this->ven_pin_);
26}
27
29 this->nci_fsm_transition_();
30 this->purge_old_tags_();
31}
32
33void PN7150::set_tag_emulation_message(std::shared_ptr<nfc::NdefMessage> message) {
34 this->card_emulation_message_ = std::move(message);
35 ESP_LOGD(TAG, "Tag emulation message set");
36}
37
39 const optional<bool> include_android_app_record) {
40 if (!message.has_value()) {
41 return;
42 }
43
44 auto ndef_message = make_unique<nfc::NdefMessage>();
45
46 ndef_message->add_uri_record(message.value());
47
48 if (!include_android_app_record.has_value() || include_android_app_record.value()) {
49 auto ext_record = make_unique<nfc::NdefRecord>();
50 ext_record->set_tnf(nfc::TNF_EXTERNAL_TYPE);
51 ext_record->set_type(nfc::HA_TAG_ID_EXT_RECORD_TYPE);
52 ext_record->set_payload(nfc::HA_TAG_ID_EXT_RECORD_PAYLOAD);
53 ndef_message->add_record(std::move(ext_record));
54 }
55
56 this->card_emulation_message_ = std::move(ndef_message);
57 ESP_LOGD(TAG, "Tag emulation message set");
58}
59
60void PN7150::set_tag_emulation_message(const char *message, const bool include_android_app_record) {
61 this->set_tag_emulation_message(std::string(message), include_android_app_record);
62}
63
65 if (this->listening_enabled_) {
66 this->listening_enabled_ = false;
67 this->config_refresh_pending_ = true;
68 }
69 ESP_LOGD(TAG, "Tag emulation disabled");
70}
71
73 if (this->card_emulation_message_ == nullptr) {
74 ESP_LOGE(TAG, "No NDEF message is set; tag emulation cannot be enabled");
75 return;
76 }
77 if (!this->listening_enabled_) {
78 this->listening_enabled_ = true;
79 this->config_refresh_pending_ = true;
80 }
81 ESP_LOGD(TAG, "Tag emulation enabled");
82}
83
85 if (this->polling_enabled_) {
86 this->polling_enabled_ = false;
87 this->config_refresh_pending_ = true;
88 }
89 ESP_LOGD(TAG, "Tag polling disabled");
90}
91
93 if (!this->polling_enabled_) {
94 this->polling_enabled_ = true;
95 this->config_refresh_pending_ = true;
96 }
97 ESP_LOGD(TAG, "Tag polling enabled");
98}
99
101 this->next_task_ = EP_READ;
102 ESP_LOGD(TAG, "Waiting to read next tag");
103}
104
106 this->next_task_ = EP_CLEAN;
107 ESP_LOGD(TAG, "Waiting to clean next tag");
108}
109
111 this->next_task_ = EP_FORMAT;
112 ESP_LOGD(TAG, "Waiting to format next tag");
113}
114
116 if (this->next_task_message_to_write_ == nullptr) {
117 ESP_LOGW(TAG, "Message to write must be set before setting write mode");
118 return;
119 }
120
121 this->next_task_ = EP_WRITE;
122 ESP_LOGD(TAG, "Waiting to write next tag");
123}
124
125void PN7150::set_tag_write_message(std::shared_ptr<nfc::NdefMessage> message) {
126 this->next_task_message_to_write_ = std::move(message);
127 ESP_LOGD(TAG, "Message to write has been set");
128}
129
131 if (!message.has_value()) {
132 return;
133 }
134
135 auto ndef_message = make_unique<nfc::NdefMessage>();
136
137 ndef_message->add_uri_record(message.value());
138
139 if (!include_android_app_record.has_value() || include_android_app_record.value()) {
140 auto ext_record = make_unique<nfc::NdefRecord>();
141 ext_record->set_tnf(nfc::TNF_EXTERNAL_TYPE);
142 ext_record->set_type(nfc::HA_TAG_ID_EXT_RECORD_TYPE);
143 ext_record->set_payload(nfc::HA_TAG_ID_EXT_RECORD_PAYLOAD);
144 ndef_message->add_record(std::move(ext_record));
145 }
146
147 this->next_task_message_to_write_ = std::move(ndef_message);
148 ESP_LOGD(TAG, "Message to write has been set");
149}
150
151uint8_t PN7150::set_test_mode(const TestMode test_mode, const std::vector<uint8_t> &data,
152 std::vector<uint8_t> &result) {
153 auto test_oid = TEST_PRBS_OID;
154
155 switch (test_mode) {
157 // test_oid = TEST_PRBS_OID;
158 break;
159
161 test_oid = TEST_ANTENNA_OID;
162 break;
163
165 test_oid = TEST_GET_REGISTER_OID;
166 break;
167
169 default:
170 ESP_LOGD(TAG, "Exiting test mode");
172 return nfc::STATUS_OK;
173 }
174
175 if (this->reset_core_(true, true) != nfc::STATUS_OK) {
176 ESP_LOGE(TAG, "Failed to reset NCI core");
178 result.clear();
179 return nfc::STATUS_FAILED;
180 } else {
182 }
183 if (this->init_core_() != nfc::STATUS_OK) {
184 ESP_LOGE(TAG, "Failed to initialise NCI core");
186 result.clear();
187 return nfc::STATUS_FAILED;
188 } else {
190 }
191
193 nfc::NciMessage tx(nfc::NCI_PKT_MT_CTRL_COMMAND, nfc::NCI_PROPRIETARY_GID, test_oid, data);
194
195 ESP_LOGW(TAG, "Starting test mode, OID 0x%02X", test_oid);
196 auto status = this->transceive_(tx, rx, NFCC_INIT_TIMEOUT);
197
198 if (status != nfc::STATUS_OK) {
199 ESP_LOGE(TAG, "Failed to start test mode, OID 0x%02X", test_oid);
201 result.clear();
202 } else {
203 result = rx.get_message();
204 result.erase(result.begin(), result.begin() + 4); // remove NCI header
205 if (!result.empty()) {
206 char buf[nfc::FORMAT_BYTES_BUFFER_SIZE];
207 ESP_LOGW(TAG, "Test results: %s", nfc::format_bytes_to(buf, result));
208 }
209 }
210 return status;
211}
212
213uint8_t PN7150::reset_core_(const bool reset_config, const bool power) {
214 if (power) {
215 this->ven_pin_->digital_write(true);
216 delay(NFCC_DEFAULT_TIMEOUT);
217 this->ven_pin_->digital_write(false);
218 delay(NFCC_DEFAULT_TIMEOUT);
219 this->ven_pin_->digital_write(true);
220 delay(NFCC_INIT_TIMEOUT);
221 }
222
224 nfc::NciMessage tx(nfc::NCI_PKT_MT_CTRL_COMMAND, nfc::NCI_CORE_GID, nfc::NCI_CORE_RESET_OID,
225 {(uint8_t) reset_config});
226
227 if (this->transceive_(tx, rx, NFCC_INIT_TIMEOUT) != nfc::STATUS_OK) {
228 ESP_LOGE(TAG, "Error sending reset command");
229 return nfc::STATUS_FAILED;
230 }
231
232 if (!rx.simple_status_response_is(nfc::STATUS_OK)) {
233 char buf[nfc::FORMAT_BYTES_BUFFER_SIZE];
234 ESP_LOGE(TAG, "Invalid reset response: %s", nfc::format_bytes_to(buf, rx.get_message()));
235 return rx.get_simple_status_response();
236 }
237 // verify reset response
238 if ((!rx.message_type_is(nfc::NCI_PKT_MT_CTRL_RESPONSE)) || (!rx.message_length_is(3)) ||
239 (rx.get_message()[nfc::NCI_PKT_PAYLOAD_OFFSET + 1] != 0x11) ||
240 (rx.get_message()[nfc::NCI_PKT_PAYLOAD_OFFSET + 2] != (uint8_t) reset_config)) {
241 char buf[nfc::FORMAT_BYTES_BUFFER_SIZE];
242 ESP_LOGE(TAG, "Reset response was malformed: %s", nfc::format_bytes_to(buf, rx.get_message()));
243 return nfc::STATUS_FAILED;
244 }
245
246 ESP_LOGD(TAG,
247 "Configuration %s\n"
248 "NCI version: %s",
249 rx.get_message()[nfc::NCI_PKT_PAYLOAD_OFFSET + 2] ? "reset" : "retained",
250 rx.get_message()[nfc::NCI_PKT_PAYLOAD_OFFSET + 1] == 0x20 ? "2.0" : "1.0");
251
252 return nfc::STATUS_OK;
253}
254
257 nfc::NciMessage tx(nfc::NCI_PKT_MT_CTRL_COMMAND, nfc::NCI_CORE_GID, nfc::NCI_CORE_INIT_OID);
258
259 if (this->transceive_(tx, rx) != nfc::STATUS_OK) {
260 ESP_LOGE(TAG, "Error sending initialise command");
261 return nfc::STATUS_FAILED;
262 }
263
264 if (!rx.simple_status_response_is(nfc::STATUS_OK)) {
265 char buf[nfc::FORMAT_BYTES_BUFFER_SIZE];
266 ESP_LOGE(TAG, "Invalid initialise response: %s", nfc::format_bytes_to(buf, rx.get_message()));
267 return nfc::STATUS_FAILED;
268 }
269
270 uint8_t manf_id = rx.get_message()[15 + rx.get_message()[8]];
271 uint8_t hw_version = rx.get_message()[16 + rx.get_message()[8]];
272 uint8_t rom_code_version = rx.get_message()[17 + rx.get_message()[8]];
273 uint8_t flash_major_version = rx.get_message()[18 + rx.get_message()[8]];
274 uint8_t flash_minor_version = rx.get_message()[19 + rx.get_message()[8]];
275
276 ESP_LOGD(TAG,
277 "Manufacturer ID: 0x%02X\n"
278 "Hardware version: 0x%02X\n"
279 "ROM code version: 0x%02X\n"
280 "FLASH major version: 0x%02X\n"
281 "FLASH minor version: 0x%02X",
282 manf_id, hw_version, rom_code_version, flash_major_version, flash_minor_version);
283
284 return rx.get_simple_status_response();
285}
286
289 nfc::NciMessage tx(nfc::NCI_PKT_MT_CTRL_COMMAND, nfc::NCI_PROPRIETARY_GID, nfc::NCI_CORE_SET_CONFIG_OID);
290
291 if (this->transceive_(tx, rx) != nfc::STATUS_OK) {
292 ESP_LOGE(TAG, "Error enabling proprietary extensions");
293 return nfc::STATUS_FAILED;
294 }
295
296 tx.set_message(nfc::NCI_PKT_MT_CTRL_COMMAND, nfc::NCI_CORE_GID, nfc::NCI_CORE_SET_CONFIG_OID,
297 std::vector<uint8_t>(std::begin(PMU_CFG), std::end(PMU_CFG)));
298
299 if (this->transceive_(tx, rx) != nfc::STATUS_OK) {
300 ESP_LOGE(TAG, "Error sending PMU config");
301 return nfc::STATUS_FAILED;
302 }
303
304 return this->send_core_config_();
305}
306
308 const auto *core_config_begin = std::begin(CORE_CONFIG_SOLO);
309 const auto *core_config_end = std::end(CORE_CONFIG_SOLO);
310 this->core_config_is_solo_ = true;
311
312 if (this->listening_enabled_ && this->polling_enabled_) {
313 core_config_begin = std::begin(CORE_CONFIG_RW_CE);
314 core_config_end = std::end(CORE_CONFIG_RW_CE);
315 this->core_config_is_solo_ = false;
316 }
317
319 nfc::NciMessage tx(nfc::NCI_PKT_MT_CTRL_COMMAND, nfc::NCI_CORE_GID, nfc::NCI_CORE_SET_CONFIG_OID,
320 std::vector<uint8_t>(core_config_begin, core_config_end));
321
322 if (this->transceive_(tx, rx) != nfc::STATUS_OK) {
323 ESP_LOGW(TAG, "Error sending core config");
324 return nfc::STATUS_FAILED;
325 }
326
327 return nfc::STATUS_OK;
328}
329
331 bool core_config_should_be_solo = !(this->listening_enabled_ && this->polling_enabled_);
332
334 if (this->stop_discovery_() != nfc::STATUS_OK) {
336 return nfc::STATUS_FAILED;
337 }
339 }
340
341 if (this->core_config_is_solo_ != core_config_should_be_solo) {
342 if (this->send_core_config_() != nfc::STATUS_OK) {
343 ESP_LOGV(TAG, "Failed to refresh core config");
344 return nfc::STATUS_FAILED;
345 }
346 }
347 this->config_refresh_pending_ = false;
348 return nfc::STATUS_OK;
349}
350
352 std::vector<uint8_t> discover_map = {sizeof(RF_DISCOVER_MAP_CONFIG) / 3};
353 discover_map.insert(discover_map.end(), std::begin(RF_DISCOVER_MAP_CONFIG), std::end(RF_DISCOVER_MAP_CONFIG));
354
356 nfc::NciMessage tx(nfc::NCI_PKT_MT_CTRL_COMMAND, nfc::RF_GID, nfc::RF_DISCOVER_MAP_OID, discover_map);
357
358 if (this->transceive_(tx, rx, NFCC_INIT_TIMEOUT) != nfc::STATUS_OK) {
359 ESP_LOGE(TAG, "Error sending discover map poll config");
360 return nfc::STATUS_FAILED;
361 }
362 return nfc::STATUS_OK;
363}
364
368 nfc::NCI_PKT_MT_CTRL_COMMAND, nfc::RF_GID, nfc::RF_SET_LISTEN_MODE_ROUTING_OID,
369 std::vector<uint8_t>(std::begin(RF_LISTEN_MODE_ROUTING_CONFIG), std::end(RF_LISTEN_MODE_ROUTING_CONFIG)));
370
371 if (this->transceive_(tx, rx, NFCC_INIT_TIMEOUT) != nfc::STATUS_OK) {
372 ESP_LOGE(TAG, "Error setting listen mode routing config");
373 return nfc::STATUS_FAILED;
374 }
375 return nfc::STATUS_OK;
376}
377
379 const uint8_t *rf_discovery_config = RF_DISCOVERY_CONFIG;
380 uint8_t length = sizeof(RF_DISCOVERY_CONFIG);
381
382 if (!this->listening_enabled_) {
383 length = sizeof(RF_DISCOVERY_POLL_CONFIG);
384 rf_discovery_config = RF_DISCOVERY_POLL_CONFIG;
385 } else if (!this->polling_enabled_) {
386 length = sizeof(RF_DISCOVERY_LISTEN_CONFIG);
387 rf_discovery_config = RF_DISCOVERY_LISTEN_CONFIG;
388 }
389
390 std::vector<uint8_t> discover_config = std::vector<uint8_t>((length * 2) + 1);
391
392 discover_config[0] = length;
393 for (uint8_t i = 0; i < length; i++) {
394 discover_config[(i * 2) + 1] = rf_discovery_config[i];
395 discover_config[(i * 2) + 2] = 0x01; // RF Technology and Mode will be executed in every discovery period
396 }
397
399 nfc::NciMessage tx(nfc::NCI_PKT_MT_CTRL_COMMAND, nfc::RF_GID, nfc::RF_DISCOVER_OID, discover_config);
400
401 if (this->transceive_(tx, rx) != nfc::STATUS_OK) {
402 switch (rx.get_simple_status_response()) {
403 // in any of these cases, we are either already in or will remain in discovery, which satisfies the function call
404 case nfc::STATUS_OK:
405 case nfc::DISCOVERY_ALREADY_STARTED:
406 case nfc::DISCOVERY_TARGET_ACTIVATION_FAILED:
407 case nfc::DISCOVERY_TEAR_DOWN:
408 return nfc::STATUS_OK;
409
410 default:
411 ESP_LOGE(TAG, "Error starting discovery");
412 return nfc::STATUS_FAILED;
413 }
414 }
415
416 return nfc::STATUS_OK;
417}
418
419uint8_t PN7150::stop_discovery_() { return this->deactivate_(nfc::DEACTIVATION_TYPE_IDLE, NFCC_TAG_WRITE_TIMEOUT); }
420
421uint8_t PN7150::deactivate_(const uint8_t type, const uint16_t timeout) {
423 nfc::NciMessage tx(nfc::NCI_PKT_MT_CTRL_COMMAND, nfc::RF_GID, nfc::RF_DEACTIVATE_OID, {type});
424
425 auto status = this->transceive_(tx, rx, timeout);
426 // if (status != nfc::STATUS_OK) {
427 // ESP_LOGE(TAG, "Error sending deactivate type %u", type);
428 // return nfc::STATUS_FAILED;
429 // }
430 return status;
431}
432
434 if (this->discovered_endpoint_.empty()) {
435 ESP_LOGW(TAG, "No cached tags to select");
436 this->stop_discovery_();
438 return;
439 }
440 std::vector<uint8_t> endpoint_data = {this->discovered_endpoint_[0].id, this->discovered_endpoint_[0].protocol,
441 0x01}; // that last byte is the interface ID
442 for (size_t i = 0; i < this->discovered_endpoint_.size(); i++) {
443 if (!this->discovered_endpoint_[i].trig_called) {
444 endpoint_data = {this->discovered_endpoint_[i].id, this->discovered_endpoint_[i].protocol,
445 0x01}; // that last byte is the interface ID
446 this->selecting_endpoint_ = i;
447 break;
448 }
449 }
450
452 nfc::NciMessage tx(nfc::NCI_PKT_MT_CTRL_COMMAND, nfc::RF_GID, nfc::RF_DISCOVER_SELECT_OID, endpoint_data);
453
454 if (this->transceive_(tx, rx) != nfc::STATUS_OK) {
455 ESP_LOGE(TAG, "Error selecting endpoint");
456 } else {
458 }
459}
460
462 uint8_t type = nfc::guess_tag_type(tag.get_uid().size());
463
464 switch (type) {
465 case nfc::TAG_TYPE_MIFARE_CLASSIC:
466 ESP_LOGV(TAG, "Reading Mifare classic");
467 return this->read_mifare_classic_tag_(tag);
468
469 case nfc::TAG_TYPE_2:
470 ESP_LOGV(TAG, "Reading Mifare ultralight");
471 return this->read_mifare_ultralight_tag_(tag);
472
473 case nfc::TAG_TYPE_UNKNOWN:
474 default:
475 ESP_LOGV(TAG, "Cannot determine tag type");
476 break;
477 }
478 return nfc::STATUS_FAILED;
479}
480
481uint8_t PN7150::clean_endpoint_(std::vector<uint8_t> &uid) {
482 uint8_t type = nfc::guess_tag_type(uid.size());
483 switch (type) {
484 case nfc::TAG_TYPE_MIFARE_CLASSIC:
485 return this->format_mifare_classic_mifare_();
486
487 case nfc::TAG_TYPE_2:
488 return this->clean_mifare_ultralight_();
489
490 default:
491 ESP_LOGE(TAG, "Unsupported tag for cleaning");
492 break;
493 }
494 return nfc::STATUS_FAILED;
495}
496
497uint8_t PN7150::format_endpoint_(std::vector<uint8_t> &uid) {
498 uint8_t type = nfc::guess_tag_type(uid.size());
499 switch (type) {
500 case nfc::TAG_TYPE_MIFARE_CLASSIC:
501 return this->format_mifare_classic_ndef_();
502
503 case nfc::TAG_TYPE_2:
504 return this->clean_mifare_ultralight_();
505
506 default:
507 ESP_LOGE(TAG, "Unsupported tag for formatting");
508 break;
509 }
510 return nfc::STATUS_FAILED;
511}
512
513uint8_t PN7150::write_endpoint_(std::vector<uint8_t> &uid, std::shared_ptr<nfc::NdefMessage> &message) {
514 uint8_t type = nfc::guess_tag_type(uid.size());
515 switch (type) {
516 case nfc::TAG_TYPE_MIFARE_CLASSIC:
517 return this->write_mifare_classic_tag_(message);
518
519 case nfc::TAG_TYPE_2:
520 return this->write_mifare_ultralight_tag_(uid, message);
521
522 default:
523 ESP_LOGE(TAG, "Unsupported tag for writing");
524 break;
525 }
526 return nfc::STATUS_FAILED;
527}
528
529std::unique_ptr<nfc::NfcTag> PN7150::build_tag_(const uint8_t mode_tech, const std::vector<uint8_t> &data) {
530 switch (mode_tech) {
531 case (nfc::MODE_POLL | nfc::TECH_PASSIVE_NFCA): {
532 uint8_t uid_length = data[2];
533 if (!uid_length) {
534 ESP_LOGE(TAG, "UID length cannot be zero");
535 return nullptr;
536 }
537 std::vector<uint8_t> uid(data.begin() + 3, data.begin() + 3 + uid_length);
538 const auto *tag_type_str =
539 nfc::guess_tag_type(uid_length) == nfc::TAG_TYPE_MIFARE_CLASSIC ? nfc::MIFARE_CLASSIC : nfc::NFC_FORUM_TYPE_2;
540 return make_unique<nfc::NfcTag>(uid, tag_type_str);
541 }
542 }
543 return nullptr;
544}
545
546optional<size_t> PN7150::find_tag_uid_(const std::vector<uint8_t> &uid) {
547 if (!this->discovered_endpoint_.empty()) {
548 for (size_t i = 0; i < this->discovered_endpoint_.size(); i++) {
549 auto existing_tag_uid = this->discovered_endpoint_[i].tag->get_uid();
550 bool uid_match = (uid.size() == existing_tag_uid.size());
551
552 if (uid_match) {
553 for (size_t i = 0; i < uid.size(); i++) {
554 uid_match &= (uid[i] == existing_tag_uid[i]);
555 }
556 if (uid_match) {
557 return i;
558 }
559 }
560 }
561 }
562 return nullopt;
563}
564
566 for (size_t i = 0; i < this->discovered_endpoint_.size(); i++) {
567 if (millis() - this->discovered_endpoint_[i].last_seen > this->tag_ttl_) {
568 this->erase_tag_(i);
569 }
570 }
571}
572
573void PN7150::erase_tag_(const uint8_t tag_index) {
574 if (tag_index < this->discovered_endpoint_.size()) {
575 for (auto *trigger : this->triggers_ontagremoved_) {
576 trigger->process(this->discovered_endpoint_[tag_index].tag);
577 }
578 for (auto *listener : this->tag_listeners_) {
579 listener->tag_off(*this->discovered_endpoint_[tag_index].tag);
580 }
581 char uid_buf[nfc::FORMAT_UID_BUFFER_SIZE];
582 ESP_LOGI(TAG, "Tag %s removed", nfc::format_uid_to(uid_buf, this->discovered_endpoint_[tag_index].tag->get_uid()));
583 this->discovered_endpoint_.erase(this->discovered_endpoint_.begin() + tag_index);
584 }
585}
586
588 switch (this->nci_state_) {
590 if (this->reset_core_(true, true) != nfc::STATUS_OK) {
591 ESP_LOGE(TAG, "Failed to reset NCI core");
593 return;
594 } else {
596 }
597 [[fallthrough]];
598
600 if (this->init_core_() != nfc::STATUS_OK) {
601 ESP_LOGE(TAG, "Failed to initialise NCI core");
603 return;
604 } else {
606 }
607 [[fallthrough]];
608
610 if (this->send_init_config_() != nfc::STATUS_OK) {
611 ESP_LOGE(TAG, "Failed to send initial config");
613 return;
614 } else {
615 this->config_refresh_pending_ = false;
617 }
618 [[fallthrough]];
619
621 if (this->set_discover_map_() != nfc::STATUS_OK) {
622 ESP_LOGE(TAG, "Failed to set discover map");
624 return;
625 } else {
627 }
628 [[fallthrough]];
629
631 if (this->set_listen_mode_routing_() != nfc::STATUS_OK) {
632 ESP_LOGE(TAG, "Failed to set listen mode routing");
634 return;
635 } else {
637 }
638 [[fallthrough]];
639
642 this->stop_discovery_();
643 }
644
645 if (this->config_refresh_pending_) {
646 this->refresh_core_config_();
647 }
648
649 if (!this->listening_enabled_ && !this->polling_enabled_) {
650 return;
651 }
652
653 if (this->start_discovery_() != nfc::STATUS_OK) {
654 ESP_LOGV(TAG, "Failed to start discovery");
656 } else {
658 }
659 return;
660
663 [[fallthrough]];
664
665 // All cases below are waiting for NOTIFICATION messages
667 if (this->config_refresh_pending_) {
668 this->refresh_core_config_();
669 }
670 [[fallthrough]];
671
677 if (this->irq_pin_->digital_read()) {
678 this->process_message_();
679 }
680 break;
681
682 case NCIState::TEST:
683 case NCIState::FAILED:
684 case NCIState::NONE:
685 default:
686 return;
687 }
688}
689
691 ESP_LOGVV(TAG, "nci_fsm_set_state_(%u)", (uint8_t) new_state);
692 this->nci_state_ = new_state;
694 this->error_count_ = 0;
696}
697
699 ESP_LOGVV(TAG, "nci_fsm_set_error_state_(%u); error_count_ = %u", (uint8_t) new_state, this->error_count_);
700 this->nci_state_error_ = new_state;
701 if (this->error_count_++ > NFCC_MAX_ERROR_COUNT) {
704 ESP_LOGE(TAG, "Too many initialization failures -- check device connections");
705 this->mark_failed();
707 } else {
708 ESP_LOGW(TAG, "Too many errors transitioning to state %u; resetting NFCC", (uint8_t) this->nci_state_error_);
710 }
711 }
712 return this->error_count_ > NFCC_MAX_ERROR_COUNT;
713}
714
717 if (this->read_nfcc(rx, NFCC_DEFAULT_TIMEOUT) != nfc::STATUS_OK) {
718 return; // No data
719 }
720
721 switch (rx.get_message_type()) {
722 case nfc::NCI_PKT_MT_CTRL_NOTIFICATION:
723 if (rx.get_gid() == nfc::RF_GID) {
724 switch (rx.get_oid()) {
725 case nfc::RF_INTF_ACTIVATED_OID:
726 ESP_LOGVV(TAG, "RF_INTF_ACTIVATED_OID");
728 return;
729
730 case nfc::RF_DISCOVER_OID:
731 ESP_LOGVV(TAG, "RF_DISCOVER_OID");
732 this->process_rf_discover_oid_(rx);
733 return;
734
735 case nfc::RF_DEACTIVATE_OID:
736 ESP_LOGVV(TAG, "RF_DEACTIVATE_OID: type: 0x%02X, reason: 0x%02X", rx.get_message()[3], rx.get_message()[4]);
738 return;
739
740 default:
741 ESP_LOGV(TAG, "Unimplemented RF OID received: 0x%02X", rx.get_oid());
742 }
743 } else if (rx.get_gid() == nfc::NCI_CORE_GID) {
744 switch (rx.get_oid()) {
745 case nfc::NCI_CORE_GENERIC_ERROR_OID:
746 ESP_LOGV(TAG, "NCI_CORE_GENERIC_ERROR_OID:");
747 switch (rx.get_simple_status_response()) {
748 case nfc::DISCOVERY_ALREADY_STARTED:
749 ESP_LOGV(TAG, " DISCOVERY_ALREADY_STARTED");
750 break;
751
752 case nfc::DISCOVERY_TARGET_ACTIVATION_FAILED:
753 // Tag removed too soon
754 ESP_LOGV(TAG, " DISCOVERY_TARGET_ACTIVATION_FAILED");
755 if (this->nci_state_ == NCIState::EP_SELECTING) {
757 if (!this->discovered_endpoint_.empty()) {
758 this->erase_tag_(this->selecting_endpoint_);
759 }
760 } else {
761 this->stop_discovery_();
763 }
764 break;
765
766 case nfc::DISCOVERY_TEAR_DOWN:
767 ESP_LOGV(TAG, " DISCOVERY_TEAR_DOWN");
768 break;
769
770 default:
771 ESP_LOGW(TAG, "Unknown error: 0x%02X", rx.get_simple_status_response());
772 break;
773 }
774 break;
775
776 default:
777 ESP_LOGV(TAG, "Unimplemented NCI Core OID received: 0x%02X", rx.get_oid());
778 }
779 } else {
780 char buf[nfc::FORMAT_BYTES_BUFFER_SIZE];
781 ESP_LOGV(TAG, "Unimplemented notification: %s", nfc::format_bytes_to(buf, rx.get_message()));
782 }
783 break;
784
785 case nfc::NCI_PKT_MT_CTRL_RESPONSE: {
786 char buf[nfc::FORMAT_BYTES_BUFFER_SIZE];
787 ESP_LOGV(TAG, "Unimplemented GID: 0x%02X OID: 0x%02X Full response: %s", rx.get_gid(), rx.get_oid(),
789 break;
790 }
791
792 case nfc::NCI_PKT_MT_CTRL_COMMAND: {
793 char buf[nfc::FORMAT_BYTES_BUFFER_SIZE];
794 ESP_LOGV(TAG, "Unimplemented command: %s", nfc::format_bytes_to(buf, rx.get_message()));
795 break;
796 }
797
798 case nfc::NCI_PKT_MT_DATA:
799 this->process_data_message_(rx);
800 break;
801
802 default: {
803 char buf[nfc::FORMAT_BYTES_BUFFER_SIZE];
804 ESP_LOGV(TAG, "Unimplemented message type: %s", nfc::format_bytes_to(buf, rx.get_message()));
805 break;
806 }
807 }
808}
809
810void PN7150::process_rf_intf_activated_oid_(nfc::NciMessage &rx) { // an endpoint was activated
811 uint8_t discovery_id = rx.get_message_byte(nfc::RF_INTF_ACTIVATED_NTF_DISCOVERY_ID);
812 uint8_t interface = rx.get_message_byte(nfc::RF_INTF_ACTIVATED_NTF_INTERFACE);
813 uint8_t protocol = rx.get_message_byte(nfc::RF_INTF_ACTIVATED_NTF_PROTOCOL);
814 uint8_t mode_tech = rx.get_message_byte(nfc::RF_INTF_ACTIVATED_NTF_MODE_TECH);
815 uint8_t max_size = rx.get_message_byte(nfc::RF_INTF_ACTIVATED_NTF_MAX_SIZE);
816
817 ESP_LOGVV(TAG, "Endpoint activated -- interface: 0x%02X, protocol: 0x%02X, mode&tech: 0x%02X, max payload: %u",
818 interface, protocol, mode_tech, max_size);
819
820 if (mode_tech & nfc::MODE_LISTEN_MASK) {
821 ESP_LOGVV(TAG, "Tag activated in listen mode");
822 this->nci_fsm_set_state_(NCIState::RFST_LISTEN_ACTIVE);
823 return;
824 }
825
827 auto incoming_tag =
828 this->build_tag_(mode_tech, std::vector<uint8_t>(rx.get_message().begin() + 10, rx.get_message().end()));
829
830 if (incoming_tag == nullptr) {
831 ESP_LOGE(TAG, "Could not build tag");
832 } else {
833 auto tag_loc = this->find_tag_uid_(incoming_tag->get_uid());
834 if (tag_loc.has_value()) {
835 this->discovered_endpoint_[tag_loc.value()].id = discovery_id;
836 this->discovered_endpoint_[tag_loc.value()].protocol = protocol;
837 this->discovered_endpoint_[tag_loc.value()].last_seen = millis();
838 ESP_LOGVV(TAG, "Tag cache updated");
839 } else {
840 this->discovered_endpoint_.emplace_back(
841 DiscoveredEndpoint{discovery_id, protocol, millis(), std::move(incoming_tag), false});
842 tag_loc = this->discovered_endpoint_.size() - 1;
843 ESP_LOGVV(TAG, "Tag added to cache");
844 }
845
846 auto &working_endpoint = this->discovered_endpoint_[tag_loc.value()];
847
848 switch (this->next_task_) {
849 case EP_CLEAN:
850 ESP_LOGD(TAG, " Tag cleaning");
851 if (this->clean_endpoint_(working_endpoint.tag->get_uid()) != nfc::STATUS_OK) {
852 ESP_LOGE(TAG, " Tag cleaning incomplete");
853 }
854 ESP_LOGD(TAG, " Tag cleaned!");
855 break;
856
857 case EP_FORMAT:
858 ESP_LOGD(TAG, " Tag formatting");
859 if (this->format_endpoint_(working_endpoint.tag->get_uid()) != nfc::STATUS_OK) {
860 ESP_LOGE(TAG, "Error formatting tag as NDEF");
861 }
862 ESP_LOGD(TAG, " Tag formatted!");
863 break;
864
865 case EP_WRITE:
866 if (this->next_task_message_to_write_ != nullptr) {
867 ESP_LOGD(TAG, " Tag writing\n"
868 " Tag formatting");
869 if (this->format_endpoint_(working_endpoint.tag->get_uid()) != nfc::STATUS_OK) {
870 ESP_LOGE(TAG, " Tag could not be formatted for writing");
871 } else {
872 ESP_LOGD(TAG, " Writing NDEF data");
873 if (this->write_endpoint_(working_endpoint.tag->get_uid(), this->next_task_message_to_write_) !=
874 nfc::STATUS_OK) {
875 ESP_LOGE(TAG, " Failed to write message to tag");
876 }
877 ESP_LOGD(TAG, " Finished writing NDEF data");
878 this->next_task_message_to_write_ = nullptr;
879 this->on_finished_write_callback_.call();
880 }
881 }
882 break;
883
884 case EP_READ:
885 default:
886 if (!working_endpoint.trig_called) {
887 char uid_buf[nfc::FORMAT_UID_BUFFER_SIZE];
888 ESP_LOGI(TAG, "Read tag type %s with UID %s", working_endpoint.tag->get_tag_type().c_str(),
889 nfc::format_uid_to(uid_buf, working_endpoint.tag->get_uid()));
890 if (this->read_endpoint_data_(*working_endpoint.tag) != nfc::STATUS_OK) {
891 ESP_LOGW(TAG, " Unable to read NDEF record(s)");
892 } else if (working_endpoint.tag->has_ndef_message()) {
893 const auto message = working_endpoint.tag->get_ndef_message();
894 const auto records = message->get_records();
895 ESP_LOGD(TAG, " NDEF record(s):");
896 for (const auto &record : records) {
897 ESP_LOGD(TAG, " %s - %s", record->get_type().c_str(), record->get_payload().c_str());
898 }
899 } else {
900 ESP_LOGW(TAG, " No NDEF records found");
901 }
902 for (auto *trigger : this->triggers_ontag_) {
903 trigger->process(working_endpoint.tag);
904 }
905 for (auto *listener : this->tag_listeners_) {
906 listener->tag_on(*working_endpoint.tag);
907 }
908 working_endpoint.trig_called = true;
909 break;
910 }
911 }
912 if (working_endpoint.tag->get_tag_type() == nfc::MIFARE_CLASSIC) {
914 }
915 }
916 if (this->next_task_ != EP_READ) {
917 this->read_mode();
918 }
919
920 this->stop_discovery_();
922}
923
925 auto incoming_tag = this->build_tag_(rx.get_message_byte(nfc::RF_DISCOVER_NTF_MODE_TECH),
926 std::vector<uint8_t>(rx.get_message().begin() + 7, rx.get_message().end()));
927
928 if (incoming_tag == nullptr) {
929 ESP_LOGE(TAG, "Could not build tag!");
930 } else {
931 auto tag_loc = this->find_tag_uid_(incoming_tag->get_uid());
932 if (tag_loc.has_value()) {
933 this->discovered_endpoint_[tag_loc.value()].id = rx.get_message_byte(nfc::RF_DISCOVER_NTF_DISCOVERY_ID);
934 this->discovered_endpoint_[tag_loc.value()].protocol = rx.get_message_byte(nfc::RF_DISCOVER_NTF_PROTOCOL);
935 this->discovered_endpoint_[tag_loc.value()].last_seen = millis();
936 ESP_LOGVV(TAG, "Tag found & updated");
937 } else {
938 this->discovered_endpoint_.emplace_back(DiscoveredEndpoint{rx.get_message_byte(nfc::RF_DISCOVER_NTF_DISCOVERY_ID),
939 rx.get_message_byte(nfc::RF_DISCOVER_NTF_PROTOCOL),
940 millis(), std::move(incoming_tag), false});
941 ESP_LOGVV(TAG, "Tag saved");
942 }
943 }
944
945 if (rx.get_message().back() != nfc::RF_DISCOVER_NTF_NT_MORE) {
947 ESP_LOGVV(TAG, "Discovered %u endpoints", this->discovered_endpoint_.size());
948 }
949}
950
953
954 switch (rx.get_simple_status_response()) {
955 case nfc::DEACTIVATION_TYPE_DISCOVERY:
957 break;
958
959 case nfc::DEACTIVATION_TYPE_IDLE:
961 break;
962
963 case nfc::DEACTIVATION_TYPE_SLEEP:
964 case nfc::DEACTIVATION_TYPE_SLEEP_AF:
967 } else if (this->nci_state_ == NCIState::RFST_POLL_ACTIVE) {
969 } else {
971 }
972 break;
973
974 default:
975 break;
976 }
977}
978
980 char buf[nfc::FORMAT_BYTES_BUFFER_SIZE];
981 ESP_LOGVV(TAG, "Received data message: %s", nfc::format_bytes_to(buf, rx.get_message()));
982
983 std::vector<uint8_t> ndef_response;
984 this->card_emu_t4t_get_response_(rx.get_message(), ndef_response);
985
986 uint16_t ndef_response_size = ndef_response.size();
987 if (!ndef_response_size) {
988 return; // no message returned, we cannot respond
989 }
990
991 std::vector<uint8_t> tx_msg = {nfc::NCI_PKT_MT_DATA, uint8_t((ndef_response_size & 0xFF00) >> 8),
992 uint8_t(ndef_response_size & 0x00FF)};
993 tx_msg.insert(tx_msg.end(), ndef_response.begin(), ndef_response.end());
994 nfc::NciMessage tx(tx_msg);
995 ESP_LOGVV(TAG, "Sending data message: %s", nfc::format_bytes_to(buf, tx.get_message()));
996 if (this->transceive_(tx, rx, NFCC_DEFAULT_TIMEOUT, false) != nfc::STATUS_OK) {
997 ESP_LOGE(TAG, "Sending reply for card emulation failed");
998 }
999}
1000
1001void PN7150::card_emu_t4t_get_response_(std::vector<uint8_t> &response, std::vector<uint8_t> &ndef_response) {
1002 if (this->card_emulation_message_ == nullptr) {
1003 ESP_LOGE(TAG, "No NDEF message is set; tag emulation not possible");
1004 ndef_response.clear();
1005 return;
1006 }
1007
1008 if (equal(response.begin() + nfc::NCI_PKT_HEADER_SIZE, response.end(), std::begin(CARD_EMU_T4T_APP_SELECT))) {
1009 // CARD_EMU_T4T_APP_SELECT
1010 ESP_LOGVV(TAG, "CARD_EMU_NDEF_APP_SELECTED");
1012 ndef_response.insert(ndef_response.begin(), std::begin(CARD_EMU_T4T_OK), std::end(CARD_EMU_T4T_OK));
1013 } else if (equal(response.begin() + nfc::NCI_PKT_HEADER_SIZE, response.end(), std::begin(CARD_EMU_T4T_CC_SELECT))) {
1014 // CARD_EMU_T4T_CC_SELECT
1016 ESP_LOGVV(TAG, "CARD_EMU_CC_SELECTED");
1018 ndef_response.insert(ndef_response.begin(), std::begin(CARD_EMU_T4T_OK), std::end(CARD_EMU_T4T_OK));
1019 }
1020 } else if (equal(response.begin() + nfc::NCI_PKT_HEADER_SIZE, response.end(), std::begin(CARD_EMU_T4T_NDEF_SELECT))) {
1021 // CARD_EMU_T4T_NDEF_SELECT
1022 ESP_LOGVV(TAG, "CARD_EMU_NDEF_SELECTED");
1024 ndef_response.insert(ndef_response.begin(), std::begin(CARD_EMU_T4T_OK), std::end(CARD_EMU_T4T_OK));
1025 } else if (equal(response.begin() + nfc::NCI_PKT_HEADER_SIZE,
1026 response.begin() + nfc::NCI_PKT_HEADER_SIZE + sizeof(CARD_EMU_T4T_READ),
1027 std::begin(CARD_EMU_T4T_READ))) {
1028 // CARD_EMU_T4T_READ
1030 // CARD_EMU_T4T_READ with CARD_EMU_CC_SELECTED
1031 ESP_LOGVV(TAG, "CARD_EMU_T4T_READ with CARD_EMU_CC_SELECTED");
1032 uint16_t offset = (response[nfc::NCI_PKT_HEADER_SIZE + 2] << 8) + response[nfc::NCI_PKT_HEADER_SIZE + 3];
1033 uint8_t length = response[nfc::NCI_PKT_HEADER_SIZE + 4];
1034
1035 if (length <= (sizeof(CARD_EMU_T4T_CC) + offset + 2)) {
1036 ndef_response.insert(ndef_response.begin(), std::begin(CARD_EMU_T4T_CC) + offset,
1037 std::begin(CARD_EMU_T4T_CC) + offset + length);
1038 ndef_response.insert(ndef_response.end(), std::begin(CARD_EMU_T4T_OK), std::end(CARD_EMU_T4T_OK));
1039 }
1041 // CARD_EMU_T4T_READ with CARD_EMU_NDEF_SELECTED
1042 ESP_LOGVV(TAG, "CARD_EMU_T4T_READ with CARD_EMU_NDEF_SELECTED");
1043 auto ndef_message = this->card_emulation_message_->encode();
1044 uint16_t ndef_msg_size = ndef_message.size();
1045 uint16_t offset = (response[nfc::NCI_PKT_HEADER_SIZE + 2] << 8) + response[nfc::NCI_PKT_HEADER_SIZE + 3];
1046 uint8_t length = response[nfc::NCI_PKT_HEADER_SIZE + 4];
1047
1048 char ndef_buf[nfc::FORMAT_BYTES_BUFFER_SIZE];
1049 ESP_LOGVV(TAG, "Encoded NDEF message: %s", nfc::format_bytes_to(ndef_buf, ndef_message));
1050
1051 if (length <= (ndef_msg_size + offset + 2)) {
1052 if (offset == 0) {
1053 ndef_response.resize(2);
1054 ndef_response[0] = (ndef_msg_size & 0xFF00) >> 8;
1055 ndef_response[1] = (ndef_msg_size & 0x00FF);
1056 if (length > 2) {
1057 ndef_response.insert(ndef_response.end(), ndef_message.begin(), ndef_message.begin() + length - 2);
1058 }
1059 } else if (offset == 1) {
1060 ndef_response.resize(1);
1061 ndef_response[0] = (ndef_msg_size & 0x00FF);
1062 if (length > 1) {
1063 ndef_response.insert(ndef_response.end(), ndef_message.begin(), ndef_message.begin() + length - 1);
1064 }
1065 } else {
1066 ndef_response.insert(ndef_response.end(), ndef_message.begin(), ndef_message.begin() + length);
1067 }
1068
1069 ndef_response.insert(ndef_response.end(), std::begin(CARD_EMU_T4T_OK), std::end(CARD_EMU_T4T_OK));
1070
1071 if ((offset + length) >= (ndef_msg_size + 2)) {
1072 ESP_LOGD(TAG, "NDEF message sent");
1073 this->on_emulated_tag_scan_callback_.call();
1074 }
1075 }
1076 }
1077 } else if (equal(response.begin() + nfc::NCI_PKT_HEADER_SIZE,
1078 response.begin() + nfc::NCI_PKT_HEADER_SIZE + sizeof(CARD_EMU_T4T_WRITE),
1079 std::begin(CARD_EMU_T4T_WRITE))) {
1080 // CARD_EMU_T4T_WRITE
1082 ESP_LOGVV(TAG, "CARD_EMU_T4T_WRITE");
1083 uint8_t length = response[nfc::NCI_PKT_HEADER_SIZE + 4];
1084 std::vector<uint8_t> ndef_msg_written;
1085
1086 ndef_msg_written.insert(ndef_msg_written.end(), response.begin() + nfc::NCI_PKT_HEADER_SIZE + 5,
1087 response.begin() + nfc::NCI_PKT_HEADER_SIZE + 5 + length);
1088 char ndef_buf[nfc::FORMAT_BYTES_BUFFER_SIZE];
1089 ESP_LOGD(TAG, "Received %u-byte NDEF message: %s", length, nfc::format_bytes_to(ndef_buf, ndef_msg_written));
1090 ndef_response.insert(ndef_response.end(), std::begin(CARD_EMU_T4T_OK), std::end(CARD_EMU_T4T_OK));
1091 }
1092 }
1093}
1094
1095uint8_t PN7150::transceive_(nfc::NciMessage &tx, nfc::NciMessage &rx, const uint16_t timeout,
1096 const bool expect_notification) {
1097 uint8_t retries = NFCC_MAX_COMM_FAILS;
1098 char buf[nfc::FORMAT_BYTES_BUFFER_SIZE];
1099
1100 while (retries) {
1101 // first, send the message we need to send
1102 if (this->write_nfcc(tx) != nfc::STATUS_OK) {
1103 ESP_LOGE(TAG, "Error sending message");
1104 return nfc::STATUS_FAILED;
1105 }
1106 ESP_LOGVV(TAG, "Wrote: %s", nfc::format_bytes_to(buf, tx.get_message()));
1107 // next, the NFCC should send back a response
1108 if (this->read_nfcc(rx, timeout) != nfc::STATUS_OK) {
1109 ESP_LOGW(TAG, "Error receiving message");
1110 if (!retries--) {
1111 ESP_LOGE(TAG, " ...giving up");
1112 return nfc::STATUS_FAILED;
1113 }
1114 } else {
1115 break;
1116 }
1117 }
1118 ESP_LOGVV(TAG, "Read: %s", nfc::format_bytes_to(buf, rx.get_message()));
1119 // validate the response based on the message type that was sent (command vs. data)
1120 if (!tx.message_type_is(nfc::NCI_PKT_MT_DATA)) {
1121 // for commands, the GID and OID should match and the status should be OK
1122 if ((rx.get_gid() != tx.get_gid()) || (rx.get_oid()) != tx.get_oid()) {
1123 ESP_LOGE(TAG, "Incorrect response to command: %s", nfc::format_bytes_to(buf, rx.get_message()));
1124 return nfc::STATUS_FAILED;
1125 }
1126
1127 if (!rx.simple_status_response_is(nfc::STATUS_OK)) {
1128 ESP_LOGE(TAG, "Error in response to command: %s", nfc::format_bytes_to(buf, rx.get_message()));
1129 }
1130 return rx.get_simple_status_response();
1131 } else {
1132 // when requesting data from the endpoint, the first response is from the NFCC; we must validate this, first
1133 if ((!rx.message_type_is(nfc::NCI_PKT_MT_CTRL_NOTIFICATION)) || (!rx.gid_is(nfc::NCI_CORE_GID)) ||
1134 (!rx.oid_is(nfc::NCI_CORE_CONN_CREDITS_OID)) || (!rx.message_length_is(3))) {
1135 ESP_LOGE(TAG, "Incorrect response to data message: %s", nfc::format_bytes_to(buf, rx.get_message()));
1136 return nfc::STATUS_FAILED;
1137 }
1138
1139 if (expect_notification) {
1140 // if the NFCC said "OK", there will be additional data to read; this comes back in a notification message
1141 if (this->read_nfcc(rx, timeout) != nfc::STATUS_OK) {
1142 ESP_LOGE(TAG, "Error receiving data from endpoint");
1143 return nfc::STATUS_FAILED;
1144 }
1145 ESP_LOGVV(TAG, "Read: %s", nfc::format_bytes_to(buf, rx.get_message()));
1146 }
1147
1148 return nfc::STATUS_OK;
1149 }
1150}
1151
1152uint8_t PN7150::wait_for_irq_(uint16_t timeout, bool pin_state) {
1153 auto start_time = millis();
1154
1155 while (millis() - start_time < timeout) {
1156 if (this->irq_pin_->digital_read() == pin_state) {
1157 return nfc::STATUS_OK;
1158 }
1159 }
1160 ESP_LOGW(TAG, "Timed out waiting for IRQ state");
1161 return nfc::STATUS_FAILED;
1162}
1163
1164} // namespace pn7150
1165} // namespace esphome
uint8_t status
Definition bl0942.h:8
virtual void mark_failed()
Mark this component as failed.
virtual void setup()=0
virtual void digital_write(bool value)=0
virtual bool digital_read()=0
bool message_type_is(uint8_t message_type) const
uint8_t get_oid() const
bool simple_status_response_is(uint8_t response) const
uint8_t get_message_byte(uint8_t offset) const
bool gid_is(uint8_t gid) const
std::vector< uint8_t > & get_message()
void set_message(uint8_t message_type, const std::vector< uint8_t > &payload)
bool message_length_is(uint8_t message_length, bool recompute=false)
uint8_t get_gid() const
uint8_t get_simple_status_response() const
bool oid_is(uint8_t oid) const
uint8_t get_message_type() const
std::vector< uint8_t > & get_uid()
Definition nfc_tag.h:44
std::vector< NfcTagListener * > tag_listeners_
Definition nfc.h:94
bool has_value() const
Definition optional.h:92
value_type const & value() const
Definition optional.h:94
void process_message_()
parse & process incoming messages from the NFCC
Definition pn7150.cpp:715
uint8_t wait_for_irq_(uint16_t timeout=NFCC_DEFAULT_TIMEOUT, bool pin_state=true)
Definition pn7150.cpp:1152
std::vector< nfc::NfcOnTagTrigger * > triggers_ontagremoved_
Definition pn7150.h:291
std::shared_ptr< nfc::NdefMessage > next_task_message_to_write_
Definition pn7150.h:288
uint8_t write_mifare_classic_tag_(const std::shared_ptr< nfc::NdefMessage > &message)
uint8_t transceive_(nfc::NciMessage &tx, nfc::NciMessage &rx, uint16_t timeout=NFCC_DEFAULT_TIMEOUT, bool expect_notification=true)
Definition pn7150.cpp:1095
std::unique_ptr< nfc::NfcTag > build_tag_(uint8_t mode_tech, const std::vector< uint8_t > &data)
Definition pn7150.cpp:529
void nci_fsm_transition_()
advance controller state as required
Definition pn7150.cpp:587
uint8_t read_mifare_ultralight_tag_(nfc::NfcTag &tag)
CardEmulationState ce_state_
Definition pn7150.h:283
std::vector< DiscoveredEndpoint > discovered_endpoint_
Definition pn7150.h:281
void process_rf_intf_activated_oid_(nfc::NciMessage &rx)
Definition pn7150.cpp:810
void card_emu_t4t_get_response_(std::vector< uint8_t > &response, std::vector< uint8_t > &ndef_response)
Definition pn7150.cpp:1001
void loop() override
Definition pn7150.cpp:28
uint8_t deactivate_(uint8_t type, uint16_t timeout=NFCC_DEFAULT_TIMEOUT)
Definition pn7150.cpp:421
void process_data_message_(nfc::NciMessage &rx)
Definition pn7150.cpp:979
virtual uint8_t read_nfcc(nfc::NciMessage &rx, uint16_t timeout)=0
bool nci_fsm_set_error_state_(NCIState new_state)
setting controller to this state caused an error; returns true if too many errors/failures
Definition pn7150.cpp:698
uint8_t clean_endpoint_(std::vector< uint8_t > &uid)
Definition pn7150.cpp:481
uint8_t write_mifare_ultralight_tag_(std::vector< uint8_t > &uid, const std::shared_ptr< nfc::NdefMessage > &message)
void set_tag_emulation_message(std::shared_ptr< nfc::NdefMessage > message)
Definition pn7150.cpp:33
void set_tag_write_message(std::shared_ptr< nfc::NdefMessage > message)
Definition pn7150.cpp:125
uint8_t set_listen_mode_routing_()
Definition pn7150.cpp:365
NCIState nci_state_error_
Definition pn7150.h:285
uint8_t format_endpoint_(std::vector< uint8_t > &uid)
Definition pn7150.cpp:497
void process_rf_deactivate_oid_(nfc::NciMessage &rx)
Definition pn7150.cpp:951
uint8_t refresh_core_config_()
Definition pn7150.cpp:330
uint8_t write_endpoint_(std::vector< uint8_t > &uid, std::shared_ptr< nfc::NdefMessage > &message)
Definition pn7150.cpp:513
uint8_t selecting_endpoint_
Definition pn7150.h:272
uint8_t send_init_config_()
Definition pn7150.cpp:287
void erase_tag_(uint8_t tag_index)
Definition pn7150.cpp:573
uint8_t set_test_mode(TestMode test_mode, const std::vector< uint8_t > &data, std::vector< uint8_t > &result)
Definition pn7150.cpp:151
CallbackManager< void()> on_finished_write_callback_
Definition pn7150.h:279
uint8_t read_mifare_classic_tag_(nfc::NfcTag &tag)
uint8_t reset_core_(bool reset_config, bool power)
Definition pn7150.cpp:213
void setup() override
Definition pn7150.cpp:15
uint8_t send_core_config_()
Definition pn7150.cpp:307
optional< size_t > find_tag_uid_(const std::vector< uint8_t > &uid)
Definition pn7150.cpp:546
void nci_fsm_set_state_(NCIState new_state)
set new controller state
Definition pn7150.cpp:690
uint8_t stop_discovery_()
Definition pn7150.cpp:419
uint8_t read_endpoint_data_(nfc::NfcTag &tag)
Definition pn7150.cpp:461
std::vector< nfc::NfcOnTagTrigger * > triggers_ontag_
Definition pn7150.h:290
void dump_config() override
Definition pn7150.cpp:22
uint8_t set_discover_map_()
Definition pn7150.cpp:351
CallbackManager< void()> on_emulated_tag_scan_callback_
Definition pn7150.h:278
uint32_t last_nci_state_change_
Definition pn7150.h:271
uint8_t start_discovery_()
Definition pn7150.cpp:378
void process_rf_discover_oid_(nfc::NciMessage &rx)
Definition pn7150.cpp:924
std::shared_ptr< nfc::NdefMessage > card_emulation_message_
Definition pn7150.h:287
enum esphome::pn7150::PN7150::NfcTask EP_READ
virtual uint8_t write_nfcc(nfc::NciMessage &tx)=0
const char * message
Definition component.cpp:38
uint16_t type
char * format_bytes_to(char *buffer, const std::vector< uint8_t > &bytes)
Format bytes to buffer with ' ' separator (e.g., "04 11 22 33"). Returns buffer for inline use.
Definition nfc.cpp:15
char * format_uid_to(char *buffer, const std::vector< 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:26
Providing packet encoding functions for exchanging data with a remote host.
Definition a01nyub.cpp:7
void IRAM_ATTR HOT delay(uint32_t ms)
Definition core.cpp:26
uint32_t IRAM_ATTR HOT millis()
Definition core.cpp:25
const nullopt_t nullopt((nullopt_t::init()))
uint16_t length
Definition tt21100.cpp:0