20static constexpr uint16_t NFCC_DEFAULT_TIMEOUT = 100;
21static constexpr uint16_t NFCC_INIT_TIMEOUT = 50;
22static constexpr uint16_t NFCC_TAG_WRITE_TIMEOUT = 100;
24static constexpr uint16_t NFCC_IRQ_CLEAR_TIMEOUT = 5;
26static constexpr uint16_t NFCC_RESET_DELAY = 10;
28static constexpr uint16_t NFCC_WRITE_RETRY_DELAY = 5;
30static constexpr uint32_t NFCC_STATE_TIMEOUT = 1000;
32static constexpr uint8_t NFCC_MAX_COMM_FAILS = 3;
33static constexpr uint8_t NFCC_MAX_ERROR_COUNT = 10;
35static constexpr uint8_t XCHG_DATA_OID = 0x10;
36static constexpr uint8_t MF_SECTORSEL_OID = 0x32;
37static constexpr uint8_t MFC_AUTHENTICATE_OID = 0x40;
38static constexpr uint8_t TEST_PRBS_OID = 0x30;
39static constexpr uint8_t TEST_ANTENNA_OID = 0x3D;
40static constexpr uint8_t TEST_GET_REGISTER_OID = 0x33;
42static constexpr uint8_t MFC_AUTHENTICATE_PARAM_KS_A = 0x00;
43static constexpr uint8_t MFC_AUTHENTICATE_PARAM_KS_B = 0x80;
44static constexpr uint8_t MFC_AUTHENTICATE_PARAM_EMBED_KEY = 0x10;
46static constexpr uint8_t CARD_EMU_T4T_APP_SELECT[] = {0x00, 0xA4, 0x04, 0x00, 0x07, 0xD2, 0x76,
47 0x00, 0x00, 0x85, 0x01, 0x01, 0x00};
49static constexpr uint8_t CARD_EMU_T4T_CC[] = {0x00, 0x0F, 0x20, 0x00, 0xFD, 0x00, 0xFF, 0x04,
50 0x06, 0xE1, 0x04, 0x00, 0xFF, 0x00, 0x00};
52static constexpr uint16_t CARD_EMU_T4T_MAX_NDEF_SIZE = 0xFF - 2;
53static constexpr uint8_t CARD_EMU_T4T_CC_SELECT[] = {0x00, 0xA4, 0x00, 0x0C, 0x02, 0xE1, 0x03};
54static constexpr uint8_t CARD_EMU_T4T_NDEF_SELECT[] = {0x00, 0xA4, 0x00, 0x0C, 0x02, 0xE1, 0x04};
55static constexpr uint8_t CARD_EMU_T4T_READ[] = {0x00, 0xB0};
56static constexpr uint8_t CARD_EMU_T4T_WRITE[] = {0x00, 0xD6};
57static constexpr uint8_t CARD_EMU_T4T_OK[] = {0x90, 0x00};
58static constexpr uint8_t CARD_EMU_T4T_NOK[] = {0x6A, 0x82};
60static constexpr uint8_t CORE_CONFIG_SOLO[] = {0x01,
66static constexpr uint8_t CORE_CONFIG_RW_CE[] = {0x01,
72static constexpr uint8_t RF_DISCOVER_MAP_CONFIG[] = {
74 nfc::PROT_T1T, nfc::RF_DISCOVER_MAP_MODE_POLL,
76 nfc::PROT_T2T, nfc::RF_DISCOVER_MAP_MODE_POLL,
78 nfc::PROT_T3T, nfc::RF_DISCOVER_MAP_MODE_POLL,
80 nfc::PROT_ISODEP, nfc::RF_DISCOVER_MAP_MODE_POLL | nfc::RF_DISCOVER_MAP_MODE_LISTEN,
82 nfc::PROT_MIFARE, nfc::RF_DISCOVER_MAP_MODE_POLL,
85static constexpr uint8_t RF_DISCOVERY_LISTEN_CONFIG[] = {
86 nfc::MODE_LISTEN_MASK | nfc::TECH_PASSIVE_NFCA,
87 nfc::MODE_LISTEN_MASK | nfc::TECH_PASSIVE_NFCB,
88 nfc::MODE_LISTEN_MASK | nfc::TECH_PASSIVE_NFCF};
90static constexpr uint8_t RF_DISCOVERY_POLL_CONFIG[] = {nfc::MODE_POLL | nfc::TECH_PASSIVE_NFCA,
91 nfc::MODE_POLL | nfc::TECH_PASSIVE_NFCB,
92 nfc::MODE_POLL | nfc::TECH_PASSIVE_NFCF};
94static constexpr uint8_t RF_DISCOVERY_CONFIG[] = {nfc::MODE_POLL | nfc::TECH_PASSIVE_NFCA,
95 nfc::MODE_POLL | nfc::TECH_PASSIVE_NFCB,
96 nfc::MODE_POLL | nfc::TECH_PASSIVE_NFCF,
97 nfc::MODE_LISTEN_MASK | nfc::TECH_PASSIVE_NFCA,
98 nfc::MODE_LISTEN_MASK | nfc::TECH_PASSIVE_NFCB,
99 nfc::MODE_LISTEN_MASK | nfc::TECH_PASSIVE_NFCF};
141static constexpr uint32_t MIFARE_CLASSIC_MAX_NDEF_SIZE = 3440;
144static constexpr size_t MAX_DISCOVERED_ENDPOINTS = 8;
148 std::unique_ptr<nfc::NfcTag>
tag;
158 void setup()
override;
160 void loop()
override;
177#ifdef PN71XX_ON_TAG_TRIGGER_COUNT
180#ifdef PN71XX_ON_TAG_REMOVED_TRIGGER_COUNT
201 uint8_t
set_test_mode(
TestMode test_mode,
const std::vector<uint8_t> &data, std::vector<uint8_t> &result);
204 uint8_t
reset_core_(
bool reset_config,
bool power);
229 uint8_t
deactivate_(uint8_t
type, uint16_t timeout = NFCC_DEFAULT_TIMEOUT);
264 bool expect_notification =
true);
268 uint8_t
wait_for_irq_(uint16_t timeout = NFCC_DEFAULT_TIMEOUT,
bool pin_state =
true);
285 uint8_t &message_start_index);
303#ifdef PN71XX_ON_TAG_TRIGGER_COUNT
306#ifdef PN71XX_ON_TAG_REMOVED_TRIGGER_COUNT
Fixed-capacity vector - sized once through init() or try_init(); push_back never reallocates This avo...
Minimal static vector - saves memory by avoiding std::vector overhead.
One NCI packet, held in a fixed buffer so building and reading messages never allocates.
Fires with the formatted UID and the tag itself; the tag is passed by reference so no copy is made pe...
Common driver for the NXP PN71xx family of NCI NFC controllers.
uint8_t write_mifare_classic_tag_(const std::shared_ptr< nfc::NdefMessage > &message)
void set_ven_pin(GPIOPin *ven_pin)
void set_tag_emulation_off()
StaticVector< DiscoveredEndpoint, MAX_DISCOVERED_ENDPOINTS > discovered_endpoint_
uint8_t set_test_mode(TestMode test_mode, const std::vector< uint8_t > &data, std::vector< uint8_t > &result)
bool tag_emulation_enabled()
bool core_config_is_solo_
uint8_t sect_to_auth_(uint8_t block_num)
uint8_t find_mifare_ultralight_ndef_(std::span< const uint8_t > page_3_to_6, uint8_t &message_length, uint8_t &message_start_index)
StaticVector< nfc::NfcOnTagTrigger *, PN71XX_ON_TAG_TRIGGER_COUNT > triggers_ontag_
uint8_t wait_for_irq_(uint16_t timeout=NFCC_DEFAULT_TIMEOUT, bool pin_state=true)
virtual void prepare_reset()
Chip hooks Called before the NFCC is reset, e.g.
uint8_t auth_mifare_classic_block_(uint8_t block_num, uint8_t key_num, const uint8_t *key)
void add_on_emulated_tag_scan_callback(F &&callback)
uint32_t last_nci_state_change_
uint8_t write_mifare_ultralight_tag_(nfc::NfcTagUid &uid, const std::shared_ptr< nfc::NdefMessage > &message)
uint8_t send_core_config_()
uint8_t stop_discovery_()
void process_message_()
parse & process incoming messages from the NFCC
StaticVector< nfc::NfcOnTagTrigger *, PN71XX_ON_TAG_REMOVED_TRIGGER_COUNT > triggers_ontagremoved_
size_t find_or_add_tag_(uint8_t protocol, const nfc::NfcTagUid &uid)
Finds a cached endpoint by UID, or caches a new one, evicting the entry seen longest ago if the cache...
uint8_t transceive_(nfc::NciMessage &tx, nfc::NciMessage &rx, uint16_t timeout=NFCC_DEFAULT_TIMEOUT, bool expect_notification=true)
void register_ontagremoved_trigger(nfc::NfcOnTagTrigger *trig)
std::unique_ptr< nfc::NfcTag > build_tag_(uint8_t protocol, const nfc::NfcTagUid &uid)
uint8_t deactivate_(uint8_t type, uint16_t timeout=NFCC_DEFAULT_TIMEOUT)
void set_tag_emulation_message(const std::shared_ptr< nfc::NdefMessage > &message)
uint8_t set_discover_map_()
void set_irq_pin(GPIOPin *irq_pin)
void nci_fsm_set_state_(NCIState new_state)
set new controller state
uint8_t clean_mifare_ultralight_()
void nci_fsm_transition_()
advance controller state as required
optional< size_t > find_tag_uid_(const nfc::NfcTagUid &uid)
uint8_t send_init_config_()
uint8_t refresh_core_config_()
uint8_t read_mifare_classic_tag_(nfc::NfcTag &tag)
bool card_emu_t4t_read_ndef_(uint16_t offset, uint8_t length, CardEmuResponse &ndef_response)
uint8_t format_endpoint_(uint8_t protocol)
void process_rf_deactivate_oid_(nfc::NciMessage &rx)
virtual uint8_t verify_reset(nfc::NciMessage &rx, bool reset_config)=0
Validates what follows a successful CORE_RESET_RSP (in rx); may read more messages from the NFCC.
uint8_t read_mifare_classic_block_(uint8_t block_num, std::array< uint8_t, nfc::MIFARE_CLASSIC_BLOCK_SIZE > &data)
uint8_t read_endpoint_data_(uint8_t protocol, nfc::NfcTag &tag)
virtual std::span< const uint8_t > listen_mode_routing_config() const =0
Payload of the RF_SET_LISTEN_MODE_ROUTING_CMD.
bool is_mifare_ultralight_formatted_(std::span< const uint8_t > page_3_to_6)
void set_tag_write_message(std::shared_ptr< nfc::NdefMessage > message)
uint8_t clean_endpoint_(uint8_t protocol)
uint8_t read_mifare_ultralight_bytes_(uint8_t start_page, uint16_t num_bytes, UltralightReadBuffer &data)
uint8_t format_mifare_classic_ndef_()
void process_data_message_(nfc::NciMessage &rx)
std::shared_ptr< nfc::NdefMessage > next_task_message_to_write_
LazyCallbackManager< void()> on_emulated_tag_scan_callback_
uint8_t halt_mifare_classic_tag_()
virtual uint8_t process_init_response(nfc::NciMessage &rx)=0
Logs chip information from a successful CORE_INIT_RSP.
virtual std::span< const uint8_t > pmu_config() const =0
Parameters for the CORE_SET_CONFIG_CMD that configures the power management unit.
void process_rf_discover_oid_(nfc::NciMessage &rx)
uint8_t reset_core_(bool reset_config, bool power)
uint8_t write_endpoint_(uint8_t protocol, nfc::NfcTagUid &uid, std::shared_ptr< nfc::NdefMessage > &message)
uint16_t read_mifare_ultralight_capacity_()
void register_ontag_trigger(nfc::NfcOnTagTrigger *trig)
uint8_t set_listen_mode_routing_()
void set_tag_emulation_on()
void dump_config() override
uint8_t write_mifare_classic_block_(uint8_t block_num, const uint8_t *data, size_t len)
LazyCallbackManager< void()> on_finished_write_callback_
void add_on_finished_write_callback(F &&callback)
uint8_t read_mifare_ultralight_tag_(nfc::NfcTag &tag)
void process_rf_intf_activated_oid_(nfc::NciMessage &rx)
FixedVector< uint8_t > card_emulation_ndef_
virtual uint8_t write_nfcc(nfc::NciMessage &tx)=0
void set_tag_ttl(uint32_t ttl)
bool nci_fsm_set_error_state_(NCIState new_state)
setting controller to this state caused an error; returns true if too many errors/failures
uint8_t selecting_endpoint_
virtual uint8_t read_nfcc(nfc::NciMessage &rx, uint16_t timeout)=0
CardEmulationState ce_state_
void card_emu_t4t_get_response_(std::span< const uint8_t > response, CardEmuResponse &ndef_response)
uint8_t start_discovery_()
void erase_tag_(uint8_t tag_index)
uint8_t format_mifare_classic_mifare_()
bool parse_uid_(uint8_t mode_tech, std::span< const uint8_t > rf_tech_params, nfc::NfcTagUid &uid)
Reads the UID from the RF technology parameters of a discovery or activation notification.
bool config_refresh_pending_
uint8_t write_mifare_ultralight_page_(uint8_t page_num, const uint8_t *write_data, size_t len)
NCIState nci_state_error_
const LogString * message
@ RFST_W4_ALL_DISCOVERIES
@ NFCC_SET_LISTEN_MODE_ROUTING
@ CARD_EMU_NDEF_APP_SELECTED
std::unique_ptr< nfc::NfcTag > tag