ESPHome  2024.5.5
pn7160.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 pn7160 {
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  11, // length
62  0x11, // IRQ Enable: PVDD + temp sensor IRQs
63  0x01, // RFU
64  0x01, // Power and Clock Configuration, device on (CFG1)
65  0x01, // Power and Clock Configuration, device off (CFG1)
66  0x00, // RFU
67  0x00, // DC-DC 0
68  0x00, // DC-DC 1
69  // 0x14, // TXLDO (3.3V / 4.75V)
70  // 0xBB, // TXLDO (4.7V / 4.7V)
71  0xFF, // TXLDO (5.0V / 5.0V)
72  0x00, // RFU
73  0xD0, // TXLDO check
74  0x0C, // RFU
75 };
76 
77 static const uint8_t RF_DISCOVER_MAP_CONFIG[] = { // poll modes
78  nfc::PROT_T1T, nfc::RF_DISCOVER_MAP_MODE_POLL,
79  nfc::INTF_FRAME, // poll mode
80  nfc::PROT_T2T, nfc::RF_DISCOVER_MAP_MODE_POLL,
81  nfc::INTF_FRAME, // poll mode
82  nfc::PROT_T3T, nfc::RF_DISCOVER_MAP_MODE_POLL,
83  nfc::INTF_FRAME, // poll mode
84  nfc::PROT_ISODEP, nfc::RF_DISCOVER_MAP_MODE_POLL | nfc::RF_DISCOVER_MAP_MODE_LISTEN,
85  nfc::INTF_ISODEP, // poll & listen mode
86  nfc::PROT_MIFARE, nfc::RF_DISCOVER_MAP_MODE_POLL,
87  nfc::INTF_TAGCMD}; // poll mode
88 
89 static const uint8_t RF_DISCOVERY_LISTEN_CONFIG[] = {nfc::MODE_LISTEN_MASK | nfc::TECH_PASSIVE_NFCA, // listen mode
90  nfc::MODE_LISTEN_MASK | nfc::TECH_PASSIVE_NFCB, // listen mode
91  nfc::MODE_LISTEN_MASK | nfc::TECH_PASSIVE_NFCF}; // listen mode
92 
93 static const uint8_t RF_DISCOVERY_POLL_CONFIG[] = {nfc::MODE_POLL | nfc::TECH_PASSIVE_NFCA, // poll mode
94  nfc::MODE_POLL | nfc::TECH_PASSIVE_NFCB, // poll mode
95  nfc::MODE_POLL | nfc::TECH_PASSIVE_NFCF}; // poll mode
96 
97 static const uint8_t RF_DISCOVERY_CONFIG[] = {nfc::MODE_POLL | nfc::TECH_PASSIVE_NFCA, // poll mode
98  nfc::MODE_POLL | nfc::TECH_PASSIVE_NFCB, // poll mode
99  nfc::MODE_POLL | nfc::TECH_PASSIVE_NFCF, // poll mode
100  nfc::MODE_LISTEN_MASK | nfc::TECH_PASSIVE_NFCA, // listen mode
101  nfc::MODE_LISTEN_MASK | nfc::TECH_PASSIVE_NFCB, // listen mode
102  nfc::MODE_LISTEN_MASK | nfc::TECH_PASSIVE_NFCF}; // listen mode
103 
104 static const uint8_t RF_LISTEN_MODE_ROUTING_CONFIG[] = {0x00, // "more" (another message is coming)
105  2, // number of table entries
106  0x01, // type = protocol-based
107  3, // length
108  0, // DH NFCEE ID, a static ID representing the DH-NFCEE
109  0x07, // power state
110  nfc::PROT_ISODEP, // protocol
111  0x00, // type = technology-based
112  3, // length
113  0, // DH NFCEE ID, a static ID representing the DH-NFCEE
114  0x07, // power state
115  nfc::TECH_PASSIVE_NFCA}; // technology
116 
117 enum class CardEmulationState : uint8_t {
123 };
124 
125 enum class NCIState : uint8_t {
126  NONE = 0x00,
127  NFCC_RESET,
128  NFCC_INIT,
129  NFCC_CONFIG,
132  RFST_IDLE,
140  EP_SELECTING,
141  TEST = 0XFE,
142  FAILED = 0XFF,
143 };
144 
145 enum class TestMode : uint8_t {
146  TEST_NONE = 0x00,
147  TEST_PRBS,
148  TEST_ANTENNA,
150 };
151 
153  uint8_t id;
154  uint8_t protocol;
155  uint32_t last_seen;
156  std::unique_ptr<nfc::NfcTag> tag;
158 };
159 
160 class PN7160 : public nfc::Nfcc, public Component {
161  public:
162  void setup() override;
163  void dump_config() override;
164  float get_setup_priority() const override { return setup_priority::DATA; }
165  void loop() override;
166 
167  void set_dwl_req_pin(GPIOPin *dwl_req_pin) { this->dwl_req_pin_ = dwl_req_pin; }
168  void set_irq_pin(GPIOPin *irq_pin) { this->irq_pin_ = irq_pin; }
169  void set_ven_pin(GPIOPin *ven_pin) { this->ven_pin_ = ven_pin; }
170  void set_wkup_req_pin(GPIOPin *wkup_req_pin) { this->wkup_req_pin_ = wkup_req_pin; }
171 
172  void set_tag_ttl(uint32_t ttl) { this->tag_ttl_ = ttl; }
173  void set_tag_emulation_message(std::shared_ptr<nfc::NdefMessage> message);
174  void set_tag_emulation_message(const optional<std::string> &message, optional<bool> include_android_app_record);
175  void set_tag_emulation_message(const char *message, bool include_android_app_record = true);
176  void set_tag_emulation_off();
177  void set_tag_emulation_on();
178  bool tag_emulation_enabled() { return this->listening_enabled_; }
179 
180  void set_polling_off();
181  void set_polling_on();
182  bool polling_enabled() { return this->polling_enabled_; }
183 
184  void register_ontag_trigger(nfc::NfcOnTagTrigger *trig) { this->triggers_ontag_.push_back(trig); }
185  void register_ontagremoved_trigger(nfc::NfcOnTagTrigger *trig) { this->triggers_ontagremoved_.push_back(trig); }
186 
187  void add_on_emulated_tag_scan_callback(std::function<void()> callback) {
188  this->on_emulated_tag_scan_callback_.add(std::move(callback));
189  }
190 
191  void add_on_finished_write_callback(std::function<void()> callback) {
192  this->on_finished_write_callback_.add(std::move(callback));
193  }
194 
195  bool is_writing() { return this->next_task_ != EP_READ; };
196 
197  void read_mode();
198  void clean_mode();
199  void format_mode();
200  void write_mode();
201  void set_tag_write_message(std::shared_ptr<nfc::NdefMessage> message);
202  void set_tag_write_message(optional<std::string> message, optional<bool> include_android_app_record);
203 
204  uint8_t set_test_mode(TestMode test_mode, const std::vector<uint8_t> &data, std::vector<uint8_t> &result);
205 
206  protected:
207  uint8_t reset_core_(bool reset_config, bool power);
208  uint8_t init_core_();
209  uint8_t send_init_config_();
210  uint8_t send_core_config_();
211  uint8_t refresh_core_config_();
212 
213  uint8_t set_discover_map_();
214 
215  uint8_t set_listen_mode_routing_();
216 
217  uint8_t start_discovery_();
218  uint8_t stop_discovery_();
219  uint8_t deactivate_(uint8_t type, uint16_t timeout = NFCC_DEFAULT_TIMEOUT);
220 
221  void select_endpoint_();
222 
223  uint8_t read_endpoint_data_(nfc::NfcTag &tag);
224  uint8_t clean_endpoint_(std::vector<uint8_t> &uid);
225  uint8_t format_endpoint_(std::vector<uint8_t> &uid);
226  uint8_t write_endpoint_(std::vector<uint8_t> &uid, std::shared_ptr<nfc::NdefMessage> &message);
227 
228  std::unique_ptr<nfc::NfcTag> build_tag_(uint8_t mode_tech, const std::vector<uint8_t> &data);
229  optional<size_t> find_tag_uid_(const std::vector<uint8_t> &uid);
230  void purge_old_tags_();
231  void erase_tag_(uint8_t tag_index);
232 
234  void nci_fsm_transition_();
236  void nci_fsm_set_state_(NCIState new_state);
238  bool nci_fsm_set_error_state_(NCIState new_state);
240  void process_message_();
241  void process_rf_intf_activated_oid_(nfc::NciMessage &rx);
242  void process_rf_discover_oid_(nfc::NciMessage &rx);
243  void process_rf_deactivate_oid_(nfc::NciMessage &rx);
244  void process_data_message_(nfc::NciMessage &rx);
245 
246  void card_emu_t4t_get_response_(std::vector<uint8_t> &response, std::vector<uint8_t> &ndef_response);
247 
248  uint8_t transceive_(nfc::NciMessage &tx, nfc::NciMessage &rx, uint16_t timeout = NFCC_DEFAULT_TIMEOUT,
249  bool expect_notification = true);
250  virtual uint8_t read_nfcc(nfc::NciMessage &rx, uint16_t timeout) = 0;
251  virtual uint8_t write_nfcc(nfc::NciMessage &tx) = 0;
252 
253  uint8_t wait_for_irq_(uint16_t timeout = NFCC_DEFAULT_TIMEOUT, bool pin_state = true);
254 
255  uint8_t read_mifare_classic_tag_(nfc::NfcTag &tag);
256  uint8_t read_mifare_classic_block_(uint8_t block_num, std::vector<uint8_t> &data);
257  uint8_t write_mifare_classic_block_(uint8_t block_num, std::vector<uint8_t> &data);
258  uint8_t auth_mifare_classic_block_(uint8_t block_num, uint8_t key_num, const uint8_t *key);
259  uint8_t sect_to_auth_(uint8_t block_num);
260  uint8_t format_mifare_classic_mifare_();
261  uint8_t format_mifare_classic_ndef_();
262  uint8_t write_mifare_classic_tag_(const std::shared_ptr<nfc::NdefMessage> &message);
263  uint8_t halt_mifare_classic_tag_();
264 
265  uint8_t read_mifare_ultralight_tag_(nfc::NfcTag &tag);
266  uint8_t read_mifare_ultralight_bytes_(uint8_t start_page, uint16_t num_bytes, std::vector<uint8_t> &data);
267  bool is_mifare_ultralight_formatted_(const std::vector<uint8_t> &page_3_to_6);
268  uint16_t read_mifare_ultralight_capacity_();
269  uint8_t find_mifare_ultralight_ndef_(const std::vector<uint8_t> &page_3_to_6, uint8_t &message_length,
270  uint8_t &message_start_index);
271  uint8_t write_mifare_ultralight_page_(uint8_t page_num, std::vector<uint8_t> &write_data);
272  uint8_t write_mifare_ultralight_tag_(std::vector<uint8_t> &uid, const std::shared_ptr<nfc::NdefMessage> &message);
273  uint8_t clean_mifare_ultralight_();
274 
275  enum NfcTask : uint8_t {
276  EP_READ = 0,
280  } next_task_{EP_READ};
281 
282  bool config_refresh_pending_{false};
283  bool core_config_is_solo_{false};
284  bool listening_enabled_{false};
285  bool polling_enabled_{true};
286 
287  uint8_t error_count_{0};
288  uint8_t fail_count_{0};
289  uint32_t last_nci_state_change_{0};
290  uint8_t selecting_endpoint_{0};
291  uint32_t tag_ttl_{250};
292 
293  GPIOPin *dwl_req_pin_{nullptr};
294  GPIOPin *irq_pin_{nullptr};
295  GPIOPin *ven_pin_{nullptr};
296  GPIOPin *wkup_req_pin_{nullptr};
297 
300 
301  std::vector<DiscoveredEndpoint> discovered_endpoint_;
302 
305  NCIState nci_state_error_{NCIState::NONE};
306 
307  std::shared_ptr<nfc::NdefMessage> card_emulation_message_;
308  std::shared_ptr<nfc::NdefMessage> next_task_message_to_write_;
309 
310  std::vector<nfc::NfcOnTagTrigger *> triggers_ontag_;
311  std::vector<nfc::NfcOnTagTrigger *> triggers_ontagremoved_;
312 };
313 
314 } // namespace pn7160
315 } // namespace esphome
void set_wkup_req_pin(GPIOPin *wkup_req_pin)
Definition: pn7160.h:170
void setup()
void loop()
const float DATA
For components that import data from directly connected sensors like DHT.
Definition: component.cpp:19
void set_tag_ttl(uint32_t ttl)
Definition: pn7160.h:172
std::shared_ptr< nfc::NdefMessage > next_task_message_to_write_
Definition: pn7160.h:308
CallbackManager< void()> on_finished_write_callback_
Definition: pn7160.h:299
void set_dwl_req_pin(GPIOPin *dwl_req_pin)
Definition: pn7160.h:167
std::vector< DiscoveredEndpoint > discovered_endpoint_
Definition: pn7160.h:301
std::vector< nfc::NfcOnTagTrigger * > triggers_ontagremoved_
Definition: pn7160.h:311
std::vector< nfc::NfcOnTagTrigger * > triggers_ontag_
Definition: pn7160.h:310
std::unique_ptr< nfc::NfcTag > tag
Definition: pn7160.h:156
bool tag_emulation_enabled()
Definition: pn7160.h:178
std::shared_ptr< nfc::NdefMessage > card_emulation_message_
Definition: pn7160.h:307
void set_ven_pin(GPIOPin *ven_pin)
Definition: pn7160.h:169
float get_setup_priority() const override
Definition: pn7160.h:164
uint8_t type
void set_irq_pin(GPIOPin *irq_pin)
Definition: pn7160.h:168
void add_on_finished_write_callback(std::function< void()> callback)
Definition: pn7160.h:191
void add_on_emulated_tag_scan_callback(std::function< void()> callback)
Definition: pn7160.h:187
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 register_ontag_trigger(nfc::NfcOnTagTrigger *trig)
Definition: pn7160.h:184
void register_ontagremoved_trigger(nfc::NfcOnTagTrigger *trig)
Definition: pn7160.h:185
CallbackManager< void()> on_emulated_tag_scan_callback_
Definition: pn7160.h:298