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