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