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