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