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