ESPHome 2025.5.0
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
130void PN7150::set_tag_write_message(optional<std::string> message, optional<bool> include_android_app_record) {
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 ESP_LOGW(TAG, "Test results: %s", nfc::format_bytes(result).c_str());
207 }
208 }
209 return status;
210}
211
212uint8_t PN7150::reset_core_(const bool reset_config, const bool power) {
213 if (power) {
214 this->ven_pin_->digital_write(true);
215 delay(NFCC_DEFAULT_TIMEOUT);
216 this->ven_pin_->digital_write(false);
217 delay(NFCC_DEFAULT_TIMEOUT);
218 this->ven_pin_->digital_write(true);
219 delay(NFCC_INIT_TIMEOUT);
220 }
221
223 nfc::NciMessage tx(nfc::NCI_PKT_MT_CTRL_COMMAND, nfc::NCI_CORE_GID, nfc::NCI_CORE_RESET_OID,
224 {(uint8_t) reset_config});
225
226 if (this->transceive_(tx, rx, NFCC_INIT_TIMEOUT) != nfc::STATUS_OK) {
227 ESP_LOGE(TAG, "Error sending reset command");
228 return nfc::STATUS_FAILED;
229 }
230
231 if (!rx.simple_status_response_is(nfc::STATUS_OK)) {
232 ESP_LOGE(TAG, "Invalid reset response: %s", nfc::format_bytes(rx.get_message()).c_str());
233 return rx.get_simple_status_response();
234 }
235 // verify reset response
236 if ((!rx.message_type_is(nfc::NCI_PKT_MT_CTRL_RESPONSE)) || (!rx.message_length_is(3)) ||
237 (rx.get_message()[nfc::NCI_PKT_PAYLOAD_OFFSET + 1] != 0x11) ||
238 (rx.get_message()[nfc::NCI_PKT_PAYLOAD_OFFSET + 2] != (uint8_t) reset_config)) {
239 ESP_LOGE(TAG, "Reset response was malformed: %s", nfc::format_bytes(rx.get_message()).c_str());
240 return nfc::STATUS_FAILED;
241 }
242
243 ESP_LOGD(TAG, "Configuration %s", rx.get_message()[nfc::NCI_PKT_PAYLOAD_OFFSET + 2] ? "reset" : "retained");
244 ESP_LOGD(TAG, "NCI version: %s", rx.get_message()[nfc::NCI_PKT_PAYLOAD_OFFSET + 1] == 0x20 ? "2.0" : "1.0");
245
246 return nfc::STATUS_OK;
247}
248
251 nfc::NciMessage tx(nfc::NCI_PKT_MT_CTRL_COMMAND, nfc::NCI_CORE_GID, nfc::NCI_CORE_INIT_OID);
252
253 if (this->transceive_(tx, rx) != nfc::STATUS_OK) {
254 ESP_LOGE(TAG, "Error sending initialise command");
255 return nfc::STATUS_FAILED;
256 }
257
258 if (!rx.simple_status_response_is(nfc::STATUS_OK)) {
259 ESP_LOGE(TAG, "Invalid initialise response: %s", nfc::format_bytes(rx.get_message()).c_str());
260 return nfc::STATUS_FAILED;
261 }
262
263 uint8_t manf_id = rx.get_message()[15 + rx.get_message()[8]];
264 uint8_t hw_version = rx.get_message()[16 + rx.get_message()[8]];
265 uint8_t rom_code_version = rx.get_message()[17 + rx.get_message()[8]];
266 uint8_t flash_major_version = rx.get_message()[18 + rx.get_message()[8]];
267 uint8_t flash_minor_version = rx.get_message()[19 + rx.get_message()[8]];
268
269 ESP_LOGD(TAG, "Manufacturer ID: 0x%02X", manf_id);
270 ESP_LOGD(TAG, "Hardware version: 0x%02X", hw_version);
271 ESP_LOGD(TAG, "ROM code version: 0x%02X", rom_code_version);
272 ESP_LOGD(TAG, "FLASH major version: 0x%02X", flash_major_version);
273 ESP_LOGD(TAG, "FLASH minor version: 0x%02X", flash_minor_version);
274
275 return rx.get_simple_status_response();
276}
277
280 nfc::NciMessage tx(nfc::NCI_PKT_MT_CTRL_COMMAND, nfc::NCI_PROPRIETARY_GID, nfc::NCI_CORE_SET_CONFIG_OID);
281
282 if (this->transceive_(tx, rx) != nfc::STATUS_OK) {
283 ESP_LOGE(TAG, "Error enabling proprietary extensions");
284 return nfc::STATUS_FAILED;
285 }
286
287 tx.set_message(nfc::NCI_PKT_MT_CTRL_COMMAND, nfc::NCI_CORE_GID, nfc::NCI_CORE_SET_CONFIG_OID,
288 std::vector<uint8_t>(std::begin(PMU_CFG), std::end(PMU_CFG)));
289
290 if (this->transceive_(tx, rx) != nfc::STATUS_OK) {
291 ESP_LOGE(TAG, "Error sending PMU config");
292 return nfc::STATUS_FAILED;
293 }
294
295 return this->send_core_config_();
296}
297
299 const auto *core_config_begin = std::begin(CORE_CONFIG_SOLO);
300 const auto *core_config_end = std::end(CORE_CONFIG_SOLO);
301 this->core_config_is_solo_ = true;
302
303 if (this->listening_enabled_ && this->polling_enabled_) {
304 core_config_begin = std::begin(CORE_CONFIG_RW_CE);
305 core_config_end = std::end(CORE_CONFIG_RW_CE);
306 this->core_config_is_solo_ = false;
307 }
308
310 nfc::NciMessage tx(nfc::NCI_PKT_MT_CTRL_COMMAND, nfc::NCI_CORE_GID, nfc::NCI_CORE_SET_CONFIG_OID,
311 std::vector<uint8_t>(core_config_begin, core_config_end));
312
313 if (this->transceive_(tx, rx) != nfc::STATUS_OK) {
314 ESP_LOGW(TAG, "Error sending core config");
315 return nfc::STATUS_FAILED;
316 }
317
318 return nfc::STATUS_OK;
319}
320
322 bool core_config_should_be_solo = !(this->listening_enabled_ && this->polling_enabled_);
323
325 if (this->stop_discovery_() != nfc::STATUS_OK) {
327 return nfc::STATUS_FAILED;
328 }
330 }
331
332 if (this->core_config_is_solo_ != core_config_should_be_solo) {
333 if (this->send_core_config_() != nfc::STATUS_OK) {
334 ESP_LOGV(TAG, "Failed to refresh core config");
335 return nfc::STATUS_FAILED;
336 }
337 }
338 this->config_refresh_pending_ = false;
339 return nfc::STATUS_OK;
340}
341
343 std::vector<uint8_t> discover_map = {sizeof(RF_DISCOVER_MAP_CONFIG) / 3};
344 discover_map.insert(discover_map.end(), std::begin(RF_DISCOVER_MAP_CONFIG), std::end(RF_DISCOVER_MAP_CONFIG));
345
347 nfc::NciMessage tx(nfc::NCI_PKT_MT_CTRL_COMMAND, nfc::RF_GID, nfc::RF_DISCOVER_MAP_OID, discover_map);
348
349 if (this->transceive_(tx, rx, NFCC_INIT_TIMEOUT) != nfc::STATUS_OK) {
350 ESP_LOGE(TAG, "Error sending discover map poll config");
351 return nfc::STATUS_FAILED;
352 }
353 return nfc::STATUS_OK;
354}
355
359 nfc::NCI_PKT_MT_CTRL_COMMAND, nfc::RF_GID, nfc::RF_SET_LISTEN_MODE_ROUTING_OID,
360 std::vector<uint8_t>(std::begin(RF_LISTEN_MODE_ROUTING_CONFIG), std::end(RF_LISTEN_MODE_ROUTING_CONFIG)));
361
362 if (this->transceive_(tx, rx, NFCC_INIT_TIMEOUT) != nfc::STATUS_OK) {
363 ESP_LOGE(TAG, "Error setting listen mode routing config");
364 return nfc::STATUS_FAILED;
365 }
366 return nfc::STATUS_OK;
367}
368
370 const uint8_t *rf_discovery_config = RF_DISCOVERY_CONFIG;
371 uint8_t length = sizeof(RF_DISCOVERY_CONFIG);
372
373 if (!this->listening_enabled_) {
374 length = sizeof(RF_DISCOVERY_POLL_CONFIG);
375 rf_discovery_config = RF_DISCOVERY_POLL_CONFIG;
376 } else if (!this->polling_enabled_) {
377 length = sizeof(RF_DISCOVERY_LISTEN_CONFIG);
378 rf_discovery_config = RF_DISCOVERY_LISTEN_CONFIG;
379 }
380
381 std::vector<uint8_t> discover_config = std::vector<uint8_t>((length * 2) + 1);
382
383 discover_config[0] = length;
384 for (uint8_t i = 0; i < length; i++) {
385 discover_config[(i * 2) + 1] = rf_discovery_config[i];
386 discover_config[(i * 2) + 2] = 0x01; // RF Technology and Mode will be executed in every discovery period
387 }
388
390 nfc::NciMessage tx(nfc::NCI_PKT_MT_CTRL_COMMAND, nfc::RF_GID, nfc::RF_DISCOVER_OID, discover_config);
391
392 if (this->transceive_(tx, rx) != nfc::STATUS_OK) {
393 switch (rx.get_simple_status_response()) {
394 // in any of these cases, we are either already in or will remain in discovery, which satisfies the function call
395 case nfc::STATUS_OK:
396 case nfc::DISCOVERY_ALREADY_STARTED:
397 case nfc::DISCOVERY_TARGET_ACTIVATION_FAILED:
398 case nfc::DISCOVERY_TEAR_DOWN:
399 return nfc::STATUS_OK;
400
401 default:
402 ESP_LOGE(TAG, "Error starting discovery");
403 return nfc::STATUS_FAILED;
404 }
405 }
406
407 return nfc::STATUS_OK;
408}
409
410uint8_t PN7150::stop_discovery_() { return this->deactivate_(nfc::DEACTIVATION_TYPE_IDLE, NFCC_TAG_WRITE_TIMEOUT); }
411
412uint8_t PN7150::deactivate_(const uint8_t type, const uint16_t timeout) {
414 nfc::NciMessage tx(nfc::NCI_PKT_MT_CTRL_COMMAND, nfc::RF_GID, nfc::RF_DEACTIVATE_OID, {type});
415
416 auto status = this->transceive_(tx, rx, timeout);
417 // if (status != nfc::STATUS_OK) {
418 // ESP_LOGE(TAG, "Error sending deactivate type %u", type);
419 // return nfc::STATUS_FAILED;
420 // }
421 return status;
422}
423
425 if (this->discovered_endpoint_.empty()) {
426 ESP_LOGW(TAG, "No cached tags to select");
427 this->stop_discovery_();
429 return;
430 }
431 std::vector<uint8_t> endpoint_data = {this->discovered_endpoint_[0].id, this->discovered_endpoint_[0].protocol,
432 0x01}; // that last byte is the interface ID
433 for (size_t i = 0; i < this->discovered_endpoint_.size(); i++) {
434 if (!this->discovered_endpoint_[i].trig_called) {
435 endpoint_data = {this->discovered_endpoint_[i].id, this->discovered_endpoint_[i].protocol,
436 0x01}; // that last byte is the interface ID
437 this->selecting_endpoint_ = i;
438 break;
439 }
440 }
441
443 nfc::NciMessage tx(nfc::NCI_PKT_MT_CTRL_COMMAND, nfc::RF_GID, nfc::RF_DISCOVER_SELECT_OID, endpoint_data);
444
445 if (this->transceive_(tx, rx) != nfc::STATUS_OK) {
446 ESP_LOGE(TAG, "Error selecting endpoint");
447 } else {
449 }
450}
451
453 uint8_t type = nfc::guess_tag_type(tag.get_uid().size());
454
455 switch (type) {
456 case nfc::TAG_TYPE_MIFARE_CLASSIC:
457 ESP_LOGV(TAG, "Reading Mifare classic");
458 return this->read_mifare_classic_tag_(tag);
459
460 case nfc::TAG_TYPE_2:
461 ESP_LOGV(TAG, "Reading Mifare ultralight");
462 return this->read_mifare_ultralight_tag_(tag);
463
464 case nfc::TAG_TYPE_UNKNOWN:
465 default:
466 ESP_LOGV(TAG, "Cannot determine tag type");
467 break;
468 }
469 return nfc::STATUS_FAILED;
470}
471
472uint8_t PN7150::clean_endpoint_(std::vector<uint8_t> &uid) {
473 uint8_t type = nfc::guess_tag_type(uid.size());
474 switch (type) {
475 case nfc::TAG_TYPE_MIFARE_CLASSIC:
476 return this->format_mifare_classic_mifare_();
477
478 case nfc::TAG_TYPE_2:
479 return this->clean_mifare_ultralight_();
480
481 default:
482 ESP_LOGE(TAG, "Unsupported tag for cleaning");
483 break;
484 }
485 return nfc::STATUS_FAILED;
486}
487
488uint8_t PN7150::format_endpoint_(std::vector<uint8_t> &uid) {
489 uint8_t type = nfc::guess_tag_type(uid.size());
490 switch (type) {
491 case nfc::TAG_TYPE_MIFARE_CLASSIC:
492 return this->format_mifare_classic_ndef_();
493
494 case nfc::TAG_TYPE_2:
495 return this->clean_mifare_ultralight_();
496
497 default:
498 ESP_LOGE(TAG, "Unsupported tag for formatting");
499 break;
500 }
501 return nfc::STATUS_FAILED;
502}
503
504uint8_t PN7150::write_endpoint_(std::vector<uint8_t> &uid, std::shared_ptr<nfc::NdefMessage> &message) {
505 uint8_t type = nfc::guess_tag_type(uid.size());
506 switch (type) {
507 case nfc::TAG_TYPE_MIFARE_CLASSIC:
508 return this->write_mifare_classic_tag_(message);
509
510 case nfc::TAG_TYPE_2:
511 return this->write_mifare_ultralight_tag_(uid, message);
512
513 default:
514 ESP_LOGE(TAG, "Unsupported tag for writing");
515 break;
516 }
517 return nfc::STATUS_FAILED;
518}
519
520std::unique_ptr<nfc::NfcTag> PN7150::build_tag_(const uint8_t mode_tech, const std::vector<uint8_t> &data) {
521 switch (mode_tech) {
522 case (nfc::MODE_POLL | nfc::TECH_PASSIVE_NFCA): {
523 uint8_t uid_length = data[2];
524 if (!uid_length) {
525 ESP_LOGE(TAG, "UID length cannot be zero");
526 return nullptr;
527 }
528 std::vector<uint8_t> uid(data.begin() + 3, data.begin() + 3 + uid_length);
529 const auto *tag_type_str =
530 nfc::guess_tag_type(uid_length) == nfc::TAG_TYPE_MIFARE_CLASSIC ? nfc::MIFARE_CLASSIC : nfc::NFC_FORUM_TYPE_2;
531 return make_unique<nfc::NfcTag>(uid, tag_type_str);
532 }
533 }
534 return nullptr;
535}
536
537optional<size_t> PN7150::find_tag_uid_(const std::vector<uint8_t> &uid) {
538 if (!this->discovered_endpoint_.empty()) {
539 for (size_t i = 0; i < this->discovered_endpoint_.size(); i++) {
540 auto existing_tag_uid = this->discovered_endpoint_[i].tag->get_uid();
541 bool uid_match = (uid.size() == existing_tag_uid.size());
542
543 if (uid_match) {
544 for (size_t i = 0; i < uid.size(); i++) {
545 uid_match &= (uid[i] == existing_tag_uid[i]);
546 }
547 if (uid_match) {
548 return i;
549 }
550 }
551 }
552 }
553 return nullopt;
554}
555
557 for (size_t i = 0; i < this->discovered_endpoint_.size(); i++) {
558 if (millis() - this->discovered_endpoint_[i].last_seen > this->tag_ttl_) {
559 this->erase_tag_(i);
560 }
561 }
562}
563
564void PN7150::erase_tag_(const uint8_t tag_index) {
565 if (tag_index < this->discovered_endpoint_.size()) {
566 for (auto *trigger : this->triggers_ontagremoved_) {
567 trigger->process(this->discovered_endpoint_[tag_index].tag);
568 }
569 for (auto *listener : this->tag_listeners_) {
570 listener->tag_off(*this->discovered_endpoint_[tag_index].tag);
571 }
572 ESP_LOGI(TAG, "Tag %s removed", nfc::format_uid(this->discovered_endpoint_[tag_index].tag->get_uid()).c_str());
573 this->discovered_endpoint_.erase(this->discovered_endpoint_.begin() + tag_index);
574 }
575}
576
578 switch (this->nci_state_) {
580 if (this->reset_core_(true, true) != nfc::STATUS_OK) {
581 ESP_LOGE(TAG, "Failed to reset NCI core");
583 return;
584 } else {
586 }
587 // fall through
588
590 if (this->init_core_() != nfc::STATUS_OK) {
591 ESP_LOGE(TAG, "Failed to initialise NCI core");
593 return;
594 } else {
596 }
597 // fall through
598
600 if (this->send_init_config_() != nfc::STATUS_OK) {
601 ESP_LOGE(TAG, "Failed to send initial config");
603 return;
604 } else {
605 this->config_refresh_pending_ = false;
607 }
608 // fall through
609
611 if (this->set_discover_map_() != nfc::STATUS_OK) {
612 ESP_LOGE(TAG, "Failed to set discover map");
614 return;
615 } else {
617 }
618 // fall through
619
621 if (this->set_listen_mode_routing_() != nfc::STATUS_OK) {
622 ESP_LOGE(TAG, "Failed to set listen mode routing");
624 return;
625 } else {
627 }
628 // fall through
629
632 this->stop_discovery_();
633 }
634
635 if (this->config_refresh_pending_) {
636 this->refresh_core_config_();
637 }
638
639 if (!this->listening_enabled_ && !this->polling_enabled_) {
640 return;
641 }
642
643 if (this->start_discovery_() != nfc::STATUS_OK) {
644 ESP_LOGV(TAG, "Failed to start discovery");
646 } else {
648 }
649 return;
650
653 // fall through
654
655 // All cases below are waiting for NOTIFICATION messages
657 if (this->config_refresh_pending_) {
658 this->refresh_core_config_();
659 }
660 // fall through
661
667 if (this->irq_pin_->digital_read()) {
668 this->process_message_();
669 }
670 break;
671
672 case NCIState::TEST:
673 case NCIState::FAILED:
674 case NCIState::NONE:
675 default:
676 return;
677 }
678}
679
681 ESP_LOGVV(TAG, "nci_fsm_set_state_(%u)", (uint8_t) new_state);
682 this->nci_state_ = new_state;
684 this->error_count_ = 0;
686}
687
689 ESP_LOGVV(TAG, "nci_fsm_set_error_state_(%u); error_count_ = %u", (uint8_t) new_state, this->error_count_);
690 this->nci_state_error_ = new_state;
691 if (this->error_count_++ > NFCC_MAX_ERROR_COUNT) {
694 ESP_LOGE(TAG, "Too many initialization failures -- check device connections");
695 this->mark_failed();
697 } else {
698 ESP_LOGW(TAG, "Too many errors transitioning to state %u; resetting NFCC", (uint8_t) this->nci_state_error_);
700 }
701 }
702 return this->error_count_ > NFCC_MAX_ERROR_COUNT;
703}
704
707 if (this->read_nfcc(rx, NFCC_DEFAULT_TIMEOUT) != nfc::STATUS_OK) {
708 return; // No data
709 }
710
711 switch (rx.get_message_type()) {
712 case nfc::NCI_PKT_MT_CTRL_NOTIFICATION:
713 if (rx.get_gid() == nfc::RF_GID) {
714 switch (rx.get_oid()) {
715 case nfc::RF_INTF_ACTIVATED_OID:
716 ESP_LOGVV(TAG, "RF_INTF_ACTIVATED_OID");
718 return;
719
720 case nfc::RF_DISCOVER_OID:
721 ESP_LOGVV(TAG, "RF_DISCOVER_OID");
722 this->process_rf_discover_oid_(rx);
723 return;
724
725 case nfc::RF_DEACTIVATE_OID:
726 ESP_LOGVV(TAG, "RF_DEACTIVATE_OID: type: 0x%02X, reason: 0x%02X", rx.get_message()[3], rx.get_message()[4]);
728 return;
729
730 default:
731 ESP_LOGV(TAG, "Unimplemented RF OID received: 0x%02X", rx.get_oid());
732 }
733 } else if (rx.get_gid() == nfc::NCI_CORE_GID) {
734 switch (rx.get_oid()) {
735 case nfc::NCI_CORE_GENERIC_ERROR_OID:
736 ESP_LOGV(TAG, "NCI_CORE_GENERIC_ERROR_OID:");
737 switch (rx.get_simple_status_response()) {
738 case nfc::DISCOVERY_ALREADY_STARTED:
739 ESP_LOGV(TAG, " DISCOVERY_ALREADY_STARTED");
740 break;
741
742 case nfc::DISCOVERY_TARGET_ACTIVATION_FAILED:
743 // Tag removed too soon
744 ESP_LOGV(TAG, " DISCOVERY_TARGET_ACTIVATION_FAILED");
745 if (this->nci_state_ == NCIState::EP_SELECTING) {
747 if (!this->discovered_endpoint_.empty()) {
748 this->erase_tag_(this->selecting_endpoint_);
749 }
750 } else {
751 this->stop_discovery_();
753 }
754 break;
755
756 case nfc::DISCOVERY_TEAR_DOWN:
757 ESP_LOGV(TAG, " DISCOVERY_TEAR_DOWN");
758 break;
759
760 default:
761 ESP_LOGW(TAG, "Unknown error: 0x%02X", rx.get_simple_status_response());
762 break;
763 }
764 break;
765
766 default:
767 ESP_LOGV(TAG, "Unimplemented NCI Core OID received: 0x%02X", rx.get_oid());
768 }
769 } else {
770 ESP_LOGV(TAG, "Unimplemented notification: %s", nfc::format_bytes(rx.get_message()).c_str());
771 }
772 break;
773
774 case nfc::NCI_PKT_MT_CTRL_RESPONSE:
775 ESP_LOGV(TAG, "Unimplemented GID: 0x%02X OID: 0x%02X Full response: %s", rx.get_gid(), rx.get_oid(),
776 nfc::format_bytes(rx.get_message()).c_str());
777 break;
778
779 case nfc::NCI_PKT_MT_CTRL_COMMAND:
780 ESP_LOGV(TAG, "Unimplemented command: %s", nfc::format_bytes(rx.get_message()).c_str());
781 break;
782
783 case nfc::NCI_PKT_MT_DATA:
784 this->process_data_message_(rx);
785 break;
786
787 default:
788 ESP_LOGV(TAG, "Unimplemented message type: %s", nfc::format_bytes(rx.get_message()).c_str());
789 break;
790 }
791}
792
793void PN7150::process_rf_intf_activated_oid_(nfc::NciMessage &rx) { // an endpoint was activated
794 uint8_t discovery_id = rx.get_message_byte(nfc::RF_INTF_ACTIVATED_NTF_DISCOVERY_ID);
795 uint8_t interface = rx.get_message_byte(nfc::RF_INTF_ACTIVATED_NTF_INTERFACE);
796 uint8_t protocol = rx.get_message_byte(nfc::RF_INTF_ACTIVATED_NTF_PROTOCOL);
797 uint8_t mode_tech = rx.get_message_byte(nfc::RF_INTF_ACTIVATED_NTF_MODE_TECH);
798 uint8_t max_size = rx.get_message_byte(nfc::RF_INTF_ACTIVATED_NTF_MAX_SIZE);
799
800 ESP_LOGVV(TAG, "Endpoint activated -- interface: 0x%02X, protocol: 0x%02X, mode&tech: 0x%02X, max payload: %u",
801 interface, protocol, mode_tech, max_size);
802
803 if (mode_tech & nfc::MODE_LISTEN_MASK) {
804 ESP_LOGVV(TAG, "Tag activated in listen mode");
805 this->nci_fsm_set_state_(NCIState::RFST_LISTEN_ACTIVE);
806 return;
807 }
808
810 auto incoming_tag =
811 this->build_tag_(mode_tech, std::vector<uint8_t>(rx.get_message().begin() + 10, rx.get_message().end()));
812
813 if (incoming_tag == nullptr) {
814 ESP_LOGE(TAG, "Could not build tag");
815 } else {
816 auto tag_loc = this->find_tag_uid_(incoming_tag->get_uid());
817 if (tag_loc.has_value()) {
818 this->discovered_endpoint_[tag_loc.value()].id = discovery_id;
819 this->discovered_endpoint_[tag_loc.value()].protocol = protocol;
820 this->discovered_endpoint_[tag_loc.value()].last_seen = millis();
821 ESP_LOGVV(TAG, "Tag cache updated");
822 } else {
823 this->discovered_endpoint_.emplace_back(
824 DiscoveredEndpoint{discovery_id, protocol, millis(), std::move(incoming_tag), false});
825 tag_loc = this->discovered_endpoint_.size() - 1;
826 ESP_LOGVV(TAG, "Tag added to cache");
827 }
828
829 auto &working_endpoint = this->discovered_endpoint_[tag_loc.value()];
830
831 switch (this->next_task_) {
832 case EP_CLEAN:
833 ESP_LOGD(TAG, " Tag cleaning...");
834 if (this->clean_endpoint_(working_endpoint.tag->get_uid()) != nfc::STATUS_OK) {
835 ESP_LOGE(TAG, " Tag cleaning incomplete");
836 }
837 ESP_LOGD(TAG, " Tag cleaned!");
838 break;
839
840 case EP_FORMAT:
841 ESP_LOGD(TAG, " Tag formatting...");
842 if (this->format_endpoint_(working_endpoint.tag->get_uid()) != nfc::STATUS_OK) {
843 ESP_LOGE(TAG, "Error formatting tag as NDEF");
844 }
845 ESP_LOGD(TAG, " Tag formatted!");
846 break;
847
848 case EP_WRITE:
849 if (this->next_task_message_to_write_ != nullptr) {
850 ESP_LOGD(TAG, " Tag writing...");
851 ESP_LOGD(TAG, " Tag formatting...");
852 if (this->format_endpoint_(working_endpoint.tag->get_uid()) != nfc::STATUS_OK) {
853 ESP_LOGE(TAG, " Tag could not be formatted for writing");
854 } else {
855 ESP_LOGD(TAG, " Writing NDEF data");
856 if (this->write_endpoint_(working_endpoint.tag->get_uid(), this->next_task_message_to_write_) !=
857 nfc::STATUS_OK) {
858 ESP_LOGE(TAG, " Failed to write message to tag");
859 }
860 ESP_LOGD(TAG, " Finished writing NDEF data");
861 this->next_task_message_to_write_ = nullptr;
862 this->on_finished_write_callback_.call();
863 }
864 }
865 break;
866
867 case EP_READ:
868 default:
869 if (!working_endpoint.trig_called) {
870 ESP_LOGI(TAG, "Read tag type %s with UID %s", working_endpoint.tag->get_tag_type().c_str(),
871 nfc::format_uid(working_endpoint.tag->get_uid()).c_str());
872 if (this->read_endpoint_data_(*working_endpoint.tag) != nfc::STATUS_OK) {
873 ESP_LOGW(TAG, " Unable to read NDEF record(s)");
874 } else if (working_endpoint.tag->has_ndef_message()) {
875 const auto message = working_endpoint.tag->get_ndef_message();
876 const auto records = message->get_records();
877 ESP_LOGD(TAG, " NDEF record(s):");
878 for (const auto &record : records) {
879 ESP_LOGD(TAG, " %s - %s", record->get_type().c_str(), record->get_payload().c_str());
880 }
881 } else {
882 ESP_LOGW(TAG, " No NDEF records found");
883 }
884 for (auto *trigger : this->triggers_ontag_) {
885 trigger->process(working_endpoint.tag);
886 }
887 for (auto *listener : this->tag_listeners_) {
888 listener->tag_on(*working_endpoint.tag);
889 }
890 working_endpoint.trig_called = true;
891 break;
892 }
893 }
894 if (working_endpoint.tag->get_tag_type() == nfc::MIFARE_CLASSIC) {
896 }
897 }
898 if (this->next_task_ != EP_READ) {
899 this->read_mode();
900 }
901
902 this->stop_discovery_();
904}
905
907 auto incoming_tag = this->build_tag_(rx.get_message_byte(nfc::RF_DISCOVER_NTF_MODE_TECH),
908 std::vector<uint8_t>(rx.get_message().begin() + 7, rx.get_message().end()));
909
910 if (incoming_tag == nullptr) {
911 ESP_LOGE(TAG, "Could not build tag!");
912 } else {
913 auto tag_loc = this->find_tag_uid_(incoming_tag->get_uid());
914 if (tag_loc.has_value()) {
915 this->discovered_endpoint_[tag_loc.value()].id = rx.get_message_byte(nfc::RF_DISCOVER_NTF_DISCOVERY_ID);
916 this->discovered_endpoint_[tag_loc.value()].protocol = rx.get_message_byte(nfc::RF_DISCOVER_NTF_PROTOCOL);
917 this->discovered_endpoint_[tag_loc.value()].last_seen = millis();
918 ESP_LOGVV(TAG, "Tag found & updated");
919 } else {
920 this->discovered_endpoint_.emplace_back(DiscoveredEndpoint{rx.get_message_byte(nfc::RF_DISCOVER_NTF_DISCOVERY_ID),
921 rx.get_message_byte(nfc::RF_DISCOVER_NTF_PROTOCOL),
922 millis(), std::move(incoming_tag), false});
923 ESP_LOGVV(TAG, "Tag saved");
924 }
925 }
926
927 if (rx.get_message().back() != nfc::RF_DISCOVER_NTF_NT_MORE) {
929 ESP_LOGVV(TAG, "Discovered %u endpoints", this->discovered_endpoint_.size());
930 }
931}
932
935
936 switch (rx.get_simple_status_response()) {
937 case nfc::DEACTIVATION_TYPE_DISCOVERY:
939 break;
940
941 case nfc::DEACTIVATION_TYPE_IDLE:
943 break;
944
945 case nfc::DEACTIVATION_TYPE_SLEEP:
946 case nfc::DEACTIVATION_TYPE_SLEEP_AF:
949 } else if (this->nci_state_ == NCIState::RFST_POLL_ACTIVE) {
951 } else {
953 }
954 break;
955
956 default:
957 break;
958 }
959}
960
962 ESP_LOGVV(TAG, "Received data message: %s", nfc::format_bytes(rx.get_message()).c_str());
963
964 std::vector<uint8_t> ndef_response;
965 this->card_emu_t4t_get_response_(rx.get_message(), ndef_response);
966
967 uint16_t ndef_response_size = ndef_response.size();
968 if (!ndef_response_size) {
969 return; // no message returned, we cannot respond
970 }
971
972 std::vector<uint8_t> tx_msg = {nfc::NCI_PKT_MT_DATA, uint8_t((ndef_response_size & 0xFF00) >> 8),
973 uint8_t(ndef_response_size & 0x00FF)};
974 tx_msg.insert(tx_msg.end(), ndef_response.begin(), ndef_response.end());
975 nfc::NciMessage tx(tx_msg);
976 ESP_LOGVV(TAG, "Sending data message: %s", nfc::format_bytes(tx.get_message()).c_str());
977 if (this->transceive_(tx, rx, NFCC_DEFAULT_TIMEOUT, false) != nfc::STATUS_OK) {
978 ESP_LOGE(TAG, "Sending reply for card emulation failed");
979 }
980}
981
982void PN7150::card_emu_t4t_get_response_(std::vector<uint8_t> &response, std::vector<uint8_t> &ndef_response) {
983 if (this->card_emulation_message_ == nullptr) {
984 ESP_LOGE(TAG, "No NDEF message is set; tag emulation not possible");
985 ndef_response.clear();
986 return;
987 }
988
989 if (equal(response.begin() + nfc::NCI_PKT_HEADER_SIZE, response.end(), std::begin(CARD_EMU_T4T_APP_SELECT))) {
990 // CARD_EMU_T4T_APP_SELECT
991 ESP_LOGVV(TAG, "CARD_EMU_NDEF_APP_SELECTED");
993 ndef_response.insert(ndef_response.begin(), std::begin(CARD_EMU_T4T_OK), std::end(CARD_EMU_T4T_OK));
994 } else if (equal(response.begin() + nfc::NCI_PKT_HEADER_SIZE, response.end(), std::begin(CARD_EMU_T4T_CC_SELECT))) {
995 // CARD_EMU_T4T_CC_SELECT
997 ESP_LOGVV(TAG, "CARD_EMU_CC_SELECTED");
999 ndef_response.insert(ndef_response.begin(), std::begin(CARD_EMU_T4T_OK), std::end(CARD_EMU_T4T_OK));
1000 }
1001 } else if (equal(response.begin() + nfc::NCI_PKT_HEADER_SIZE, response.end(), std::begin(CARD_EMU_T4T_NDEF_SELECT))) {
1002 // CARD_EMU_T4T_NDEF_SELECT
1003 ESP_LOGVV(TAG, "CARD_EMU_NDEF_SELECTED");
1005 ndef_response.insert(ndef_response.begin(), std::begin(CARD_EMU_T4T_OK), std::end(CARD_EMU_T4T_OK));
1006 } else if (equal(response.begin() + nfc::NCI_PKT_HEADER_SIZE,
1007 response.begin() + nfc::NCI_PKT_HEADER_SIZE + sizeof(CARD_EMU_T4T_READ),
1008 std::begin(CARD_EMU_T4T_READ))) {
1009 // CARD_EMU_T4T_READ
1011 // CARD_EMU_T4T_READ with CARD_EMU_CC_SELECTED
1012 ESP_LOGVV(TAG, "CARD_EMU_T4T_READ with CARD_EMU_CC_SELECTED");
1013 uint16_t offset = (response[nfc::NCI_PKT_HEADER_SIZE + 2] << 8) + response[nfc::NCI_PKT_HEADER_SIZE + 3];
1014 uint8_t length = response[nfc::NCI_PKT_HEADER_SIZE + 4];
1015
1016 if (length <= (sizeof(CARD_EMU_T4T_CC) + offset + 2)) {
1017 ndef_response.insert(ndef_response.begin(), std::begin(CARD_EMU_T4T_CC) + offset,
1018 std::begin(CARD_EMU_T4T_CC) + offset + length);
1019 ndef_response.insert(ndef_response.end(), std::begin(CARD_EMU_T4T_OK), std::end(CARD_EMU_T4T_OK));
1020 }
1022 // CARD_EMU_T4T_READ with CARD_EMU_NDEF_SELECTED
1023 ESP_LOGVV(TAG, "CARD_EMU_T4T_READ with CARD_EMU_NDEF_SELECTED");
1024 auto ndef_message = this->card_emulation_message_->encode();
1025 uint16_t ndef_msg_size = ndef_message.size();
1026 uint16_t offset = (response[nfc::NCI_PKT_HEADER_SIZE + 2] << 8) + response[nfc::NCI_PKT_HEADER_SIZE + 3];
1027 uint8_t length = response[nfc::NCI_PKT_HEADER_SIZE + 4];
1028
1029 ESP_LOGVV(TAG, "Encoded NDEF message: %s", nfc::format_bytes(ndef_message).c_str());
1030
1031 if (length <= (ndef_msg_size + offset + 2)) {
1032 if (offset == 0) {
1033 ndef_response.resize(2);
1034 ndef_response[0] = (ndef_msg_size & 0xFF00) >> 8;
1035 ndef_response[1] = (ndef_msg_size & 0x00FF);
1036 if (length > 2) {
1037 ndef_response.insert(ndef_response.end(), ndef_message.begin(), ndef_message.begin() + length - 2);
1038 }
1039 } else if (offset == 1) {
1040 ndef_response.resize(1);
1041 ndef_response[0] = (ndef_msg_size & 0x00FF);
1042 if (length > 1) {
1043 ndef_response.insert(ndef_response.end(), ndef_message.begin(), ndef_message.begin() + length - 1);
1044 }
1045 } else {
1046 ndef_response.insert(ndef_response.end(), ndef_message.begin(), ndef_message.begin() + length);
1047 }
1048
1049 ndef_response.insert(ndef_response.end(), std::begin(CARD_EMU_T4T_OK), std::end(CARD_EMU_T4T_OK));
1050
1051 if ((offset + length) >= (ndef_msg_size + 2)) {
1052 ESP_LOGD(TAG, "NDEF message sent");
1053 this->on_emulated_tag_scan_callback_.call();
1054 }
1055 }
1056 }
1057 } else if (equal(response.begin() + nfc::NCI_PKT_HEADER_SIZE,
1058 response.begin() + nfc::NCI_PKT_HEADER_SIZE + sizeof(CARD_EMU_T4T_WRITE),
1059 std::begin(CARD_EMU_T4T_WRITE))) {
1060 // CARD_EMU_T4T_WRITE
1062 ESP_LOGVV(TAG, "CARD_EMU_T4T_WRITE");
1063 uint8_t length = response[nfc::NCI_PKT_HEADER_SIZE + 4];
1064 std::vector<uint8_t> ndef_msg_written;
1065
1066 ndef_msg_written.insert(ndef_msg_written.end(), response.begin() + nfc::NCI_PKT_HEADER_SIZE + 5,
1067 response.begin() + nfc::NCI_PKT_HEADER_SIZE + 5 + length);
1068 ESP_LOGD(TAG, "Received %u-byte NDEF message: %s", length, nfc::format_bytes(ndef_msg_written).c_str());
1069 ndef_response.insert(ndef_response.end(), std::begin(CARD_EMU_T4T_OK), std::end(CARD_EMU_T4T_OK));
1070 }
1071 }
1072}
1073
1074uint8_t PN7150::transceive_(nfc::NciMessage &tx, nfc::NciMessage &rx, const uint16_t timeout,
1075 const bool expect_notification) {
1076 uint8_t retries = NFCC_MAX_COMM_FAILS;
1077
1078 while (retries) {
1079 // first, send the message we need to send
1080 if (this->write_nfcc(tx) != nfc::STATUS_OK) {
1081 ESP_LOGE(TAG, "Error sending message");
1082 return nfc::STATUS_FAILED;
1083 }
1084 ESP_LOGVV(TAG, "Wrote: %s", nfc::format_bytes(tx.get_message()).c_str());
1085 // next, the NFCC should send back a response
1086 if (this->read_nfcc(rx, timeout) != nfc::STATUS_OK) {
1087 ESP_LOGW(TAG, "Error receiving message");
1088 if (!retries--) {
1089 ESP_LOGE(TAG, " ...giving up");
1090 return nfc::STATUS_FAILED;
1091 }
1092 } else {
1093 break;
1094 }
1095 }
1096 ESP_LOGVV(TAG, "Read: %s", nfc::format_bytes(rx.get_message()).c_str());
1097 // validate the response based on the message type that was sent (command vs. data)
1098 if (!tx.message_type_is(nfc::NCI_PKT_MT_DATA)) {
1099 // for commands, the GID and OID should match and the status should be OK
1100 if ((rx.get_gid() != tx.get_gid()) || (rx.get_oid()) != tx.get_oid()) {
1101 ESP_LOGE(TAG, "Incorrect response to command: %s", nfc::format_bytes(rx.get_message()).c_str());
1102 return nfc::STATUS_FAILED;
1103 }
1104
1105 if (!rx.simple_status_response_is(nfc::STATUS_OK)) {
1106 ESP_LOGE(TAG, "Error in response to command: %s", nfc::format_bytes(rx.get_message()).c_str());
1107 }
1108 return rx.get_simple_status_response();
1109 } else {
1110 // when requesting data from the endpoint, the first response is from the NFCC; we must validate this, first
1111 if ((!rx.message_type_is(nfc::NCI_PKT_MT_CTRL_NOTIFICATION)) || (!rx.gid_is(nfc::NCI_CORE_GID)) ||
1112 (!rx.oid_is(nfc::NCI_CORE_CONN_CREDITS_OID)) || (!rx.message_length_is(3))) {
1113 ESP_LOGE(TAG, "Incorrect response to data message: %s", nfc::format_bytes(rx.get_message()).c_str());
1114 return nfc::STATUS_FAILED;
1115 }
1116
1117 if (expect_notification) {
1118 // if the NFCC said "OK", there will be additional data to read; this comes back in a notification message
1119 if (this->read_nfcc(rx, timeout) != nfc::STATUS_OK) {
1120 ESP_LOGE(TAG, "Error receiving data from endpoint");
1121 return nfc::STATUS_FAILED;
1122 }
1123 ESP_LOGVV(TAG, "Read: %s", nfc::format_bytes(rx.get_message()).c_str());
1124 }
1125
1126 return nfc::STATUS_OK;
1127 }
1128}
1129
1130uint8_t PN7150::wait_for_irq_(uint16_t timeout, bool pin_state) {
1131 auto start_time = millis();
1132
1133 while (millis() - start_time < timeout) {
1134 if (this->irq_pin_->digital_read() == pin_state) {
1135 return nfc::STATUS_OK;
1136 }
1137 }
1138 ESP_LOGW(TAG, "Timed out waiting for IRQ state");
1139 return nfc::STATUS_FAILED;
1140}
1141
1142} // namespace pn7150
1143} // 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:80
bool has_value() const
Definition optional.h:87
value_type const & value() const
Definition optional.h:89
void process_message_()
parse & process incoming messages from the NFCC
Definition pn7150.cpp:705
uint8_t wait_for_irq_(uint16_t timeout=NFCC_DEFAULT_TIMEOUT, bool pin_state=true)
Definition pn7150.cpp:1130
std::vector< nfc::NfcOnTagTrigger * > triggers_ontagremoved_
Definition pn7150.h:292
std::shared_ptr< nfc::NdefMessage > next_task_message_to_write_
Definition pn7150.h:289
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:1074
std::unique_ptr< nfc::NfcTag > build_tag_(uint8_t mode_tech, const std::vector< uint8_t > &data)
Definition pn7150.cpp:520
void nci_fsm_transition_()
advance controller state as required
Definition pn7150.cpp:577
uint8_t read_mifare_ultralight_tag_(nfc::NfcTag &tag)
CardEmulationState ce_state_
Definition pn7150.h:284
std::vector< DiscoveredEndpoint > discovered_endpoint_
Definition pn7150.h:282
void process_rf_intf_activated_oid_(nfc::NciMessage &rx)
Definition pn7150.cpp:793
void card_emu_t4t_get_response_(std::vector< uint8_t > &response, std::vector< uint8_t > &ndef_response)
Definition pn7150.cpp:982
void loop() override
Definition pn7150.cpp:28
uint8_t deactivate_(uint8_t type, uint16_t timeout=NFCC_DEFAULT_TIMEOUT)
Definition pn7150.cpp:412
void process_data_message_(nfc::NciMessage &rx)
Definition pn7150.cpp:961
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:688
uint8_t clean_endpoint_(std::vector< uint8_t > &uid)
Definition pn7150.cpp:472
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:356
NCIState nci_state_error_
Definition pn7150.h:286
uint8_t format_endpoint_(std::vector< uint8_t > &uid)
Definition pn7150.cpp:488
void process_rf_deactivate_oid_(nfc::NciMessage &rx)
Definition pn7150.cpp:933
uint8_t refresh_core_config_()
Definition pn7150.cpp:321
uint8_t write_endpoint_(std::vector< uint8_t > &uid, std::shared_ptr< nfc::NdefMessage > &message)
Definition pn7150.cpp:504
uint8_t selecting_endpoint_
Definition pn7150.h:273
uint8_t send_init_config_()
Definition pn7150.cpp:278
void erase_tag_(uint8_t tag_index)
Definition pn7150.cpp:564
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:280
uint8_t read_mifare_classic_tag_(nfc::NfcTag &tag)
uint8_t reset_core_(bool reset_config, bool power)
Definition pn7150.cpp:212
void setup() override
Definition pn7150.cpp:15
uint8_t send_core_config_()
Definition pn7150.cpp:298
optional< size_t > find_tag_uid_(const std::vector< uint8_t > &uid)
Definition pn7150.cpp:537
void nci_fsm_set_state_(NCIState new_state)
set new controller state
Definition pn7150.cpp:680
uint8_t stop_discovery_()
Definition pn7150.cpp:410
uint8_t read_endpoint_data_(nfc::NfcTag &tag)
Definition pn7150.cpp:452
std::vector< nfc::NfcOnTagTrigger * > triggers_ontag_
Definition pn7150.h:291
void dump_config() override
Definition pn7150.cpp:22
uint8_t set_discover_map_()
Definition pn7150.cpp:342
CallbackManager< void()> on_emulated_tag_scan_callback_
Definition pn7150.h:279
uint32_t last_nci_state_change_
Definition pn7150.h:272
uint8_t start_discovery_()
Definition pn7150.cpp:369
void process_rf_discover_oid_(nfc::NciMessage &rx)
Definition pn7150.cpp:906
std::shared_ptr< nfc::NdefMessage > card_emulation_message_
Definition pn7150.h:288
enum esphome::pn7150::PN7150::NfcTask EP_READ
virtual uint8_t write_nfcc(nfc::NciMessage &tx)=0
uint8_t type
std::string format_uid(std::vector< uint8_t > &uid)
Definition nfc.cpp:10
uint8_t guess_tag_type(uint8_t uid_length)
Definition nfc.cpp:34
std::string format_bytes(std::vector< uint8_t > &bytes)
Definition nfc.cpp:22
Providing packet encoding functions for exchanging data with a remote host.
Definition a01nyub.cpp:7
std::unique_ptr< T > make_unique(Args &&...args)
Definition helpers.h:85
void IRAM_ATTR HOT delay(uint32_t ms)
Definition core.cpp:28
uint32_t IRAM_ATTR HOT millis()
Definition core.cpp:27
const nullopt_t nullopt((nullopt_t::init()))
uint16_t length
Definition tt21100.cpp:0