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