ESPHome  2024.5.0
pn7150.h
Go to the documentation of this file.
1 #pragma once
2 
9 #include "esphome/core/gpio.h"
10 #include "esphome/core/helpers.h"
11 
12 #include <functional>
13 
14 namespace esphome {
15 namespace pn7150 {
16 
17 static const uint16_t NFCC_DEFAULT_TIMEOUT = 10;
18 static const uint16_t NFCC_INIT_TIMEOUT = 50;
19 static const uint16_t NFCC_TAG_WRITE_TIMEOUT = 15;
20 
21 static const uint8_t NFCC_MAX_COMM_FAILS = 3;
22 static const uint8_t NFCC_MAX_ERROR_COUNT = 10;
23 
24 static const uint8_t XCHG_DATA_OID = 0x10;
25 static const uint8_t MF_SECTORSEL_OID = 0x32;
26 static const uint8_t MFC_AUTHENTICATE_OID = 0x40;
27 static const uint8_t TEST_PRBS_OID = 0x30;
28 static const uint8_t TEST_ANTENNA_OID = 0x3D;
29 static const uint8_t TEST_GET_REGISTER_OID = 0x33;
30 
31 static const uint8_t MFC_AUTHENTICATE_PARAM_KS_A = 0x00; // key select A
32 static const uint8_t MFC_AUTHENTICATE_PARAM_KS_B = 0x80; // key select B
33 static const uint8_t MFC_AUTHENTICATE_PARAM_EMBED_KEY = 0x10;
34 
35 static const uint8_t CARD_EMU_T4T_APP_SELECT[] = {0x00, 0xA4, 0x04, 0x00, 0x07, 0xD2, 0x76,
36  0x00, 0x00, 0x85, 0x01, 0x01, 0x00};
37 static const uint8_t CARD_EMU_T4T_CC[] = {0x00, 0x0F, 0x20, 0x00, 0xFF, 0x00, 0xFF, 0x04,
38  0x06, 0xE1, 0x04, 0x00, 0xFF, 0x00, 0x00};
39 static const uint8_t CARD_EMU_T4T_CC_SELECT[] = {0x00, 0xA4, 0x00, 0x0C, 0x02, 0xE1, 0x03};
40 static const uint8_t CARD_EMU_T4T_NDEF_SELECT[] = {0x00, 0xA4, 0x00, 0x0C, 0x02, 0xE1, 0x04};
41 static const uint8_t CARD_EMU_T4T_READ[] = {0x00, 0xB0};
42 static const uint8_t CARD_EMU_T4T_WRITE[] = {0x00, 0xD6};
43 static const uint8_t CARD_EMU_T4T_OK[] = {0x90, 0x00};
44 static const uint8_t CARD_EMU_T4T_NOK[] = {0x6A, 0x82};
45 
46 static const uint8_t CORE_CONFIG_SOLO[] = {0x01, // Number of parameter fields
47  0x00, // config param identifier (TOTAL_DURATION)
48  0x02, // length of value
49  0x01, // TOTAL_DURATION (low)...
50  0x00}; // TOTAL_DURATION (high): 1 ms
51 
52 static const uint8_t CORE_CONFIG_RW_CE[] = {0x01, // Number of parameter fields
53  0x00, // config param identifier (TOTAL_DURATION)
54  0x02, // length of value
55  0xF8, // TOTAL_DURATION (low)...
56  0x02}; // TOTAL_DURATION (high): 760 ms
57 
58 static const uint8_t PMU_CFG[] = {
59  0x01, // Number of parameters
60  0xA0, 0x0E, // ext. tag
61  3, // length
62  0x06, // VBAT1 connected to 5V (CFG2)
63  0x64, // TVDD monitoring threshold = 5.0V; TxLDO voltage = 4.7V (in reader & card modes)
64  0x01, // RFU; must be 0x00 for CFG1 and 0x01 for CFG2
65 };
66 
67 static const uint8_t RF_DISCOVER_MAP_CONFIG[] = { // poll modes
68  nfc::PROT_T1T, nfc::RF_DISCOVER_MAP_MODE_POLL,
69  nfc::INTF_FRAME, // poll mode
70  nfc::PROT_T2T, nfc::RF_DISCOVER_MAP_MODE_POLL,
71  nfc::INTF_FRAME, // poll mode
72  nfc::PROT_T3T, nfc::RF_DISCOVER_MAP_MODE_POLL,
73  nfc::INTF_FRAME, // poll mode
74  nfc::PROT_ISODEP, nfc::RF_DISCOVER_MAP_MODE_POLL | nfc::RF_DISCOVER_MAP_MODE_LISTEN,
75  nfc::INTF_ISODEP, // poll & listen mode
76  nfc::PROT_MIFARE, nfc::RF_DISCOVER_MAP_MODE_POLL,
77  nfc::INTF_TAGCMD}; // poll mode
78 
79 static const uint8_t RF_DISCOVERY_LISTEN_CONFIG[] = {nfc::MODE_LISTEN_MASK | nfc::TECH_PASSIVE_NFCA, // listen mode
80  nfc::MODE_LISTEN_MASK | nfc::TECH_PASSIVE_NFCB, // listen mode
81  nfc::MODE_LISTEN_MASK | nfc::TECH_PASSIVE_NFCF}; // listen mode
82 
83 static const uint8_t RF_DISCOVERY_POLL_CONFIG[] = {nfc::MODE_POLL | nfc::TECH_PASSIVE_NFCA, // poll mode
84  nfc::MODE_POLL | nfc::TECH_PASSIVE_NFCB, // poll mode
85  nfc::MODE_POLL | nfc::TECH_PASSIVE_NFCF}; // poll mode
86 
87 static const uint8_t RF_DISCOVERY_CONFIG[] = {nfc::MODE_POLL | nfc::TECH_PASSIVE_NFCA, // poll mode
88  nfc::MODE_POLL | nfc::TECH_PASSIVE_NFCB, // poll mode
89  nfc::MODE_POLL | nfc::TECH_PASSIVE_NFCF, // poll mode
90  nfc::MODE_LISTEN_MASK | nfc::TECH_PASSIVE_NFCA, // listen mode
91  nfc::MODE_LISTEN_MASK | nfc::TECH_PASSIVE_NFCB, // listen mode
92  nfc::MODE_LISTEN_MASK | nfc::TECH_PASSIVE_NFCF}; // listen mode
93 
94 static const uint8_t RF_LISTEN_MODE_ROUTING_CONFIG[] = {0x00, // "more" (another message is coming)
95  1, // number of table entries
96  0x01, // type = protocol-based
97  3, // length
98  0, // DH NFCEE ID, a static ID representing the DH-NFCEE
99  0x01, // power state
100  nfc::PROT_ISODEP}; // protocol
101 
102 enum class CardEmulationState : uint8_t {
108 };
109 
110 enum class NCIState : uint8_t {
111  NONE = 0x00,
112  NFCC_RESET,
113  NFCC_INIT,
114  NFCC_CONFIG,
117  RFST_IDLE,
125  EP_SELECTING,
126  TEST = 0XFE,
127  FAILED = 0XFF,
128 };
129 
130 enum class TestMode : uint8_t {
131  TEST_NONE = 0x00,
132  TEST_PRBS,
133  TEST_ANTENNA,
135 };
136 
138  uint8_t id;
139  uint8_t protocol;
140  uint32_t last_seen;
141  std::unique_ptr<nfc::NfcTag> tag;
143 };
144 
145 class PN7150 : public nfc::Nfcc, public Component {
146  public:
147  void setup() override;
148  void dump_config() override;
149  float get_setup_priority() const override { return setup_priority::DATA; }
150  void loop() override;
151 
152  void set_irq_pin(GPIOPin *irq_pin) { this->irq_pin_ = irq_pin; }
153  void set_ven_pin(GPIOPin *ven_pin) { this->ven_pin_ = ven_pin; }
154 
155  void set_tag_ttl(uint32_t ttl) { this->tag_ttl_ = ttl; }
156  void set_tag_emulation_message(std::shared_ptr<nfc::NdefMessage> message);
157  void set_tag_emulation_message(const optional<std::string> &message, optional<bool> include_android_app_record);
158  void set_tag_emulation_message(const char *message, bool include_android_app_record = true);
159  void set_tag_emulation_off();
160  void set_tag_emulation_on();
161  bool tag_emulation_enabled() { return this->listening_enabled_; }
162 
163  void set_polling_off();
164  void set_polling_on();
165  bool polling_enabled() { return this->polling_enabled_; }
166 
167  void register_ontag_trigger(nfc::NfcOnTagTrigger *trig) { this->triggers_ontag_.push_back(trig); }
168  void register_ontagremoved_trigger(nfc::NfcOnTagTrigger *trig) { this->triggers_ontagremoved_.push_back(trig); }
169 
170  void add_on_emulated_tag_scan_callback(std::function<void()> callback) {
171  this->on_emulated_tag_scan_callback_.add(std::move(callback));
172  }
173 
174  void add_on_finished_write_callback(std::function<void()> callback) {
175  this->on_finished_write_callback_.add(std::move(callback));
176  }
177 
178  bool is_writing() { return this->next_task_ != EP_READ; };
179 
180  void read_mode();
181  void clean_mode();
182  void format_mode();
183  void write_mode();
184  void set_tag_write_message(std::shared_ptr<nfc::NdefMessage> message);
185  void set_tag_write_message(optional<std::string> message, optional<bool> include_android_app_record);
186 
187  uint8_t set_test_mode(TestMode test_mode, const std::vector<uint8_t> &data, std::vector<uint8_t> &result);
188 
189  protected:
190  uint8_t reset_core_(bool reset_config, bool power);
191  uint8_t init_core_();
192  uint8_t send_init_config_();
193  uint8_t send_core_config_();
194  uint8_t refresh_core_config_();
195 
196  uint8_t set_discover_map_();
197 
198  uint8_t set_listen_mode_routing_();
199 
200  uint8_t start_discovery_();
201  uint8_t stop_discovery_();
202  uint8_t deactivate_(uint8_t type, uint16_t timeout = NFCC_DEFAULT_TIMEOUT);
203 
204  void select_endpoint_();
205 
206  uint8_t read_endpoint_data_(nfc::NfcTag &tag);
207  uint8_t clean_endpoint_(std::vector<uint8_t> &uid);
208  uint8_t format_endpoint_(std::vector<uint8_t> &uid);
209  uint8_t write_endpoint_(std::vector<uint8_t> &uid, std::shared_ptr<nfc::NdefMessage> &message);
210 
211  std::unique_ptr<nfc::NfcTag> build_tag_(uint8_t mode_tech, const std::vector<uint8_t> &data);
212  optional<size_t> find_tag_uid_(const std::vector<uint8_t> &uid);
213  void purge_old_tags_();
214  void erase_tag_(uint8_t tag_index);
215 
217  void nci_fsm_transition_();
219  void nci_fsm_set_state_(NCIState new_state);
221  bool nci_fsm_set_error_state_(NCIState new_state);
223  void process_message_();
224  void process_rf_intf_activated_oid_(nfc::NciMessage &rx);
225  void process_rf_discover_oid_(nfc::NciMessage &rx);
226  void process_rf_deactivate_oid_(nfc::NciMessage &rx);
227  void process_data_message_(nfc::NciMessage &rx);
228 
229  void card_emu_t4t_get_response_(std::vector<uint8_t> &response, std::vector<uint8_t> &ndef_response);
230 
231  uint8_t transceive_(nfc::NciMessage &tx, nfc::NciMessage &rx, uint16_t timeout = NFCC_DEFAULT_TIMEOUT,
232  bool expect_notification = true);
233  virtual uint8_t read_nfcc(nfc::NciMessage &rx, uint16_t timeout) = 0;
234  virtual uint8_t write_nfcc(nfc::NciMessage &tx) = 0;
235 
236  uint8_t wait_for_irq_(uint16_t timeout = NFCC_DEFAULT_TIMEOUT, bool pin_state = true);
237 
238  uint8_t read_mifare_classic_tag_(nfc::NfcTag &tag);
239  uint8_t read_mifare_classic_block_(uint8_t block_num, std::vector<uint8_t> &data);
240  uint8_t write_mifare_classic_block_(uint8_t block_num, std::vector<uint8_t> &data);
241  uint8_t auth_mifare_classic_block_(uint8_t block_num, uint8_t key_num, const uint8_t *key);
242  uint8_t sect_to_auth_(uint8_t block_num);
243  uint8_t format_mifare_classic_mifare_();
244  uint8_t format_mifare_classic_ndef_();
245  uint8_t write_mifare_classic_tag_(const std::shared_ptr<nfc::NdefMessage> &message);
246  uint8_t halt_mifare_classic_tag_();
247 
248  uint8_t read_mifare_ultralight_tag_(nfc::NfcTag &tag);
249  uint8_t read_mifare_ultralight_bytes_(uint8_t start_page, uint16_t num_bytes, std::vector<uint8_t> &data);
250  bool is_mifare_ultralight_formatted_(const std::vector<uint8_t> &page_3_to_6);
251  uint16_t read_mifare_ultralight_capacity_();
252  uint8_t find_mifare_ultralight_ndef_(const std::vector<uint8_t> &page_3_to_6, uint8_t &message_length,
253  uint8_t &message_start_index);
254  uint8_t write_mifare_ultralight_page_(uint8_t page_num, std::vector<uint8_t> &write_data);
255  uint8_t write_mifare_ultralight_tag_(std::vector<uint8_t> &uid, const std::shared_ptr<nfc::NdefMessage> &message);
256  uint8_t clean_mifare_ultralight_();
257 
258  enum NfcTask : uint8_t {
259  EP_READ = 0,
263  } next_task_{EP_READ};
264 
265  bool config_refresh_pending_{false};
266  bool core_config_is_solo_{false};
267  bool listening_enabled_{false};
268  bool polling_enabled_{true};
269 
270  uint8_t error_count_{0};
271  uint8_t fail_count_{0};
272  uint32_t last_nci_state_change_{0};
273  uint8_t selecting_endpoint_{0};
274  uint32_t tag_ttl_{250};
275 
276  GPIOPin *irq_pin_{nullptr};
277  GPIOPin *ven_pin_{nullptr};
278 
281 
282  std::vector<DiscoveredEndpoint> discovered_endpoint_;
283 
286  NCIState nci_state_error_{NCIState::NONE};
287 
288  std::shared_ptr<nfc::NdefMessage> card_emulation_message_;
289  std::shared_ptr<nfc::NdefMessage> next_task_message_to_write_;
290 
291  std::vector<nfc::NfcOnTagTrigger *> triggers_ontag_;
292  std::vector<nfc::NfcOnTagTrigger *> triggers_ontagremoved_;
293 };
294 
295 } // namespace pn7150
296 } // namespace esphome
void setup()
void loop()
const float DATA
For components that import data from directly connected sensors like DHT.
Definition: component.cpp:19
float get_setup_priority() const override
Definition: pn7150.h:149
CallbackManager< void()> on_finished_write_callback_
Definition: pn7150.h:280
CallbackManager< void()> on_emulated_tag_scan_callback_
Definition: pn7150.h:279
bool tag_emulation_enabled()
Definition: pn7150.h:161
std::vector< nfc::NfcOnTagTrigger * > triggers_ontag_
Definition: pn7150.h:291
void set_irq_pin(GPIOPin *irq_pin)
Definition: pn7150.h:152
std::unique_ptr< nfc::NfcTag > tag
Definition: pn7150.h:141
void set_ven_pin(GPIOPin *ven_pin)
Definition: pn7150.h:153
std::shared_ptr< nfc::NdefMessage > next_task_message_to_write_
Definition: pn7150.h:289
void register_ontagremoved_trigger(nfc::NfcOnTagTrigger *trig)
Definition: pn7150.h:168
std::vector< nfc::NfcOnTagTrigger * > triggers_ontagremoved_
Definition: pn7150.h:292
uint8_t type
void set_tag_ttl(uint32_t ttl)
Definition: pn7150.h:155
void register_ontag_trigger(nfc::NfcOnTagTrigger *trig)
Definition: pn7150.h:167
std::vector< DiscoveredEndpoint > discovered_endpoint_
Definition: pn7150.h:282
void add_on_finished_write_callback(std::function< void()> callback)
Definition: pn7150.h:174
This is a workaround until we can figure out a way to get the tflite-micro idf component code availab...
Definition: a01nyub.cpp:7
void add_on_emulated_tag_scan_callback(std::function< void()> callback)
Definition: pn7150.h:170
std::shared_ptr< nfc::NdefMessage > card_emulation_message_
Definition: pn7150.h:288