M5Unit-NFC 0.0.3 git rev:59f5362
Loading...
Searching...
No Matches
nfc_layer_a.hpp
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2025 M5Stack Technology CO LTD
3 *
4 * SPDX-License-Identifier: MIT
5 */
17#ifndef M5_UNIT_NFC_NFC_LAYER_NFC_LAYER_A_HPP
18#define M5_UNIT_NFC_NFC_LAYER_NFC_LAYER_A_HPP
19
21#include "nfc/a/nfca.hpp"
22#include "nfc/isoDEP/isoDEP.hpp"
24#include "nfc/ndef/ndef.hpp"
25#include <vector>
26#include <memory>
27
28namespace m5 {
29
30namespace unit {
31class UnitMFRC522; // M5Unit-RFID
32class UnitWS1850S; // M5Unit-RFID
33class UnitST25R3916;
34class CapST25R3916;
35} // namespace unit
36
37namespace nfc {
38
44public:
45 struct Adapter;
46 explicit NFCLayerA(m5::unit::UnitMFRC522& u); // The implementation of this function is located in M5Unit-RFID
47 explicit NFCLayerA(m5::unit::UnitWS1850S& u); // The implementation of this function is located in M5Unit-RFID
50
53 virtual bool transceive(uint8_t* rx, uint16_t& rx_len, const uint8_t* tx, const uint16_t tx_len,
54 const uint32_t timeout_ms) override;
55 // virtual bool transmit(const uint8_t* tx, const uint16_t tx_len, const uint32_t timeout_ms) override;
56 // virtual bool receive(uint8_t* rx, uint16_t& rx_len, const uint32_t timeout_ms) override;
57 virtual m5::nfc::NFCForumTag supportsNFCTag() const override;
58 virtual file_system_feature_t supportsFilesystem() const override;
59 virtual m5::nfc::isodep::IsoDEP* isoDEP() override
60 {
61 return &_isoDEP;
62 }
63 virtual uint16_t maximum_fifo_depth() const override;
65
71 inline bool isActive(const m5::nfc::a::PICC& picc) const
72 {
73 return _activePICC.valid() && _activePICC == picc;
74 }
81 {
82 return _activePICC;
83 }
84
87
93 bool request(uint16_t& atqa);
100 bool wakeup(uint16_t& atqa);
101
111 bool detect(m5::nfc::a::PICC& picc, const uint32_t timeout_ms = 100U);
121 bool detect(std::vector<m5::nfc::a::PICC>& piccs, const uint32_t timeout_ms = 1000U);
131 bool select(m5::nfc::a::PICC& picc);
140 bool activate(const m5::nfc::a::PICC& picc, const bool force_rats = false);
148 bool reactivate(const m5::nfc::a::PICC& picc, const bool force_rats = false);
160 inline bool reactivate()
161 {
162 return reactivate(_activePICC);
163 }
165
168
174 bool deactivate();
175
183 bool identify(m5::nfc::a::PICC& picc);
184
192 bool read4(uint8_t rx[4], const uint8_t addr);
200 bool read16(uint8_t rx[16], const uint8_t addr);
211 bool read(uint8_t* rx, uint16_t& rx_len, const uint8_t saddr,
212 const m5::nfc::a::mifare::classic::Key& key = m5::nfc::a::mifare::classic::DEFAULT_KEY);
223 bool read(uint8_t* rx, uint16_t& rx_len, const uint8_t saddr, const m5::nfc::a::mifare::plus::AESKey& key);
224
236 bool write4(const uint8_t addr, const uint8_t* tx, const uint16_t tx_len, const bool safety = true);
248 bool write16(const uint8_t addr, const uint8_t* tx, const uint16_t tx_len, const bool safety = true);
260 bool write(const uint8_t saddr, const uint8_t* tx, const uint16_t tx_len,
261 const m5::nfc::a::mifare::classic::Key& key = m5::nfc::a::mifare::classic::DEFAULT_KEY);
272 bool write(const uint8_t addr, const uint8_t* tx, const uint16_t tx_len,
274
281 bool dump(const m5::nfc::a::mifare::classic::Key& mkey = m5::nfc::a::mifare::classic::DEFAULT_KEY);
289 bool dump(const uint8_t block);
291
295
302 const uint8_t block, const m5::nfc::a::mifare::classic::Key& key = m5::nfc::a::mifare::classic::DEFAULT_KEY);
310 const uint8_t block, const m5::nfc::a::mifare::classic::Key& key = m5::nfc::a::mifare::classic::DEFAULT_KEY);
311
341 bool mifareClassicReadAccessCondition(uint8_t& c123, const uint8_t block);
353 bool mifareClassicWriteAccessCondition(const uint8_t block, const uint8_t c123,
356
365 bool mifareClassicIsValueBlock(bool& is_value_block, const uint8_t block);
373 bool mifareClassicReadValueBlock(int32_t& value, const uint8_t block);
381 bool mifareClassicWriteValueBlock(const uint8_t block, const int32_t value);
393 bool mifareClassicDecrementValueBlock(const uint8_t block, const uint32_t delta, const bool transfer = true);
405 bool mifareClassicIncrementValueBlock(const uint8_t block, const uint32_t delta, const bool transfer = true);
413 bool mifareClassicTransferValueBlock(const uint8_t block);
421 bool mifareClassicRestoreValueBlock(const uint8_t block);
423
427
437
441
444 bool mifareUltralightCAuthenticate(const uint8_t key[16]);
446
450
463 const m5::nfc::a::mifare::plus::AESKey& card_config_key = m5::nfc::a::mifare::plus::DEFAULT_KEY,
464 const m5::nfc::a::mifare::plus::AESKey& card_master_key = m5::nfc::a::mifare::plus::DEFAULT_KEY,
465 const m5::nfc::a::mifare::plus::AESKey& l2_switch_key = m5::nfc::a::mifare::plus::DEFAULT_KEY,
466 const m5::nfc::a::mifare::plus::AESKey& l3_switch_key = m5::nfc::a::mifare::plus::DEFAULT_KEY,
467 const m5::nfc::a::mifare::plus::AESKey& aes_sector_key = m5::nfc::a::mifare::plus::DEFAULT_FF_KEY,
468 const m5::nfc::a::mifare::classic::Key& key_a = m5::nfc::a::mifare::classic::DEFAULT_KEY,
469 const m5::nfc::a::mifare::classic::Key& key_b = m5::nfc::a::mifare::classic::DEFAULT_KEY);
477 const m5::nfc::a::mifare::plus::AESKey& sl2_switch_key = m5::nfc::a::mifare::plus::DEFAULT_KEY);
485 const m5::nfc::a::mifare::plus::AESKey& l3_switch_key = m5::nfc::a::mifare::plus::DEFAULT_KEY);
486
488
492
497 bool ndefIsValidFormat(bool& valid);
508 bool ndefPrepareDesfire(const uint32_t max_ndef_size);
516 bool ndefRead(m5::nfc::ndef::TLV& msg);
524 bool ndefRead(std::vector<m5::nfc::ndef::TLV>& tlvs,
525 const m5::nfc::ndef::TagBits tagBits = m5::nfc::ndef::tagBitsAll);
534 bool ndefWrite(const m5::nfc::ndef::TLV& msg);
544 bool ndefWrite(const std::vector<m5::nfc::ndef::TLV>& tlvs);
546
547protected:
548 virtual bool read(uint8_t* rx, uint16_t& rx_len, const uint16_t saddr) override;
549 virtual bool write(const uint16_t saddr, const uint8_t* tx, const uint16_t tx_len) override;
550 inline virtual uint16_t first_user_block() const override
551 {
552 return _activePICC.firstUserBlock();
553 }
554 inline virtual uint16_t last_user_block() const override
555 {
556 return _activePICC.lastUserBlock();
557 }
558 inline virtual uint16_t user_area_size() const
559 {
560 return _activePICC.userAreaSize();
561 }
562 inline virtual uint16_t unit_size_read() const override
563 {
564 return _activePICC.supportsNFC() ? (_activePICC.isMifareUltralight() ? 16 : 4) : 16;
565 }
566 inline virtual uint16_t unit_size_write() const override
567 {
568 return (_activePICC.supportsNFC()) ? 4 : 16;
569 }
570
571 bool identify_picc(m5::nfc::a::PICC& picc);
572 m5::nfc::a::Type identify_picc_st25ta();
573 uint8_t identify_plus_sl03();
574
575 bool read_using_fast(uint8_t* rx, uint16_t& rx_len, const uint8_t saddr);
576 bool read_using_read16(uint8_t* rx, uint16_t& rx_len, const uint8_t saddr,
578 bool write_using_write4(const uint8_t addr, const uint8_t* tx, const uint16_t tx_len);
579 bool write_using_write16(const uint8_t addr, const uint8_t* tx, const uint16_t tx_len,
581
582 bool nfca_request_ats(m5::nfc::a::ATS& ats, const uint8_t fsdi = 5, const uint8_t cid = 0);
583 bool nfca_deselect();
584
585 bool mifare_get_version_L3(uint8_t ver[8]);
586 bool mifare_get_version_L4_raw(uint8_t* ver, uint16_t& ver_len);
587 bool mifare_get_version_L4_wrapped(uint8_t* ver, uint16_t& ver_len);
588
589 bool mifare_plus_authenticateAES(const uint16_t key_no, const m5::nfc::a::mifare::plus::AESKey& key);
590 bool mifare_plus_authenticateAES_L3(const uint16_t key_no, const m5::nfc::a::mifare::plus::AESKey& key);
591 bool mifare_plus_read_plain_nomac(const uint16_t block, const uint8_t count, std::vector<uint8_t>& out);
592 bool mifare_plus_read_plain_mac(const uint16_t block, const uint8_t count, std::vector<uint8_t>& out);
593 bool mifare_plus_read_mac_l4(const uint16_t block, const uint8_t count, std::vector<uint8_t>& out,
594 const bool plain);
595 bool mifare_plus_write_mac_l4(const uint16_t block, const uint8_t* data, const uint16_t data_len, const bool plain);
596
597 bool mifare_classic_value_block(const m5::nfc::a::Command cmd, const uint8_t block, const uint32_t arg = 0);
598
599 bool mifare_ultralightC_authenticate1(uint8_t ek[8]);
600 bool mifare_ultralightC_authenticate2(uint8_t rx_ek[8], const uint8_t tx_ek[16]);
601
602 bool ntag_read_page(uint8_t* rx, uint16_t& rx_len, const uint8_t spage, const uint8_t epage);
603 bool ntag_write_page(const uint8_t page, const uint8_t tx[4]); // NTAG,UL,ULC
604
605 bool dump_sector_structure(const m5::nfc::a::PICC& picc, const m5::nfc::a::mifare::classic::Key& key);
606 bool dump_sector(const uint8_t sector);
607 bool dump_sector_mifare_plus_sl3(const uint8_t sector);
608 bool dump_page_structure(const uint16_t maxPage);
609 bool dump_page(const uint8_t page, const uint16_t maxPage);
610 bool dump_mifare_plus_sl3(const m5::nfc::a::mifare::plus::AESKey& key);
611 bool dump_desfire();
612 bool dump_desfire_light();
613 bool dump_st25ta();
614
615 static bool push_back_picc(std::vector<m5::nfc::a::PICC>& v, const m5::nfc::a::PICC& picc);
616
617protected:
618 m5::nfc::a::PICC _activePICC{};
621
622private:
623 bool mifare_plus_transceive_raw(uint8_t* rx, uint16_t& rx_len, const uint8_t* tx, const uint16_t tx_len);
624
629 struct MifarePlusSession {
630 bool authenticated{};
631 uint16_t key_no{};
632 uint16_t r_ctr{};
633 uint16_t w_ctr{};
634 uint8_t frame_num{};
635 std::array<uint8_t, 4> ti{};
636 std::array<uint8_t, 16> kenc{};
637 std::array<uint8_t, 16> kmac{};
638 };
639
640 MifarePlusSession _mfp_session{};
641 std::unique_ptr<Adapter> _impl;
642};
643
645// Impl for units
646struct NFCLayerA::Adapter {
647 virtual ~Adapter() = default;
648
649 virtual uint16_t max_fifo_depth() const = 0;
650
651 virtual bool transceive(uint8_t* rx, uint16_t& rx_len, const uint8_t* tx, const uint16_t tx_len,
652 const uint32_t timeout_ms) = 0;
653
654 virtual bool request(uint16_t& atqa) = 0;
655 virtual bool wakeup(uint16_t& atqa) = 0;
656
657 virtual bool select(m5::nfc::a::PICC& picc) = 0;
658 virtual bool activate(const m5::nfc::a::PICC& picc) = 0;
659 virtual bool hlt() = 0;
660
661 virtual bool nfca_read_block(uint8_t rx[16], const uint8_t addr) = 0;
662 virtual bool nfca_write_block(const uint8_t addr, const uint8_t tx[16]) = 0;
663 virtual bool mifare_classic_authenticate(const bool auth_a, const m5::nfc::a::PICC& picc, const uint8_t block,
664 const m5::nfc::a::mifare::classic::Key& key) = 0;
665 virtual bool mifare_classic_value_block(const m5::nfc::a::Command cmd, const uint8_t block,
666 const uint32_t arg = 0) = 0;
667};
669
670} // namespace nfc
671} // namespace m5
672
673#endif
Common interface layer for each chip of the NFC-A reader.
Definition nfc_layer_a.hpp:43
bool dump(const m5::nfc::a::mifare::classic::Key &mkey=m5::nfc::a::mifare::classic::DEFAULT_KEY)
Dump all blocks/files.
Definition nfc_layer_a.cpp:906
bool mifareClassicTransferValueBlock(const uint8_t block)
Transfer inner buffer value to block.
Definition nfc_layer_a.cpp:1104
bool request(uint16_t &atqa)
Send REQA to discover a PICC in IDLE.
Definition nfc_layer_a.cpp:199
virtual uint16_t first_user_block() const override
First user block.
Definition nfc_layer_a.hpp:550
bool mifareClassicReadValueBlock(int32_t &value, const uint8_t block)
Read the specific block as the value block.
Definition nfc_layer_a.cpp:1050
bool mifareClassicIsValueBlock(bool &is_value_block, const uint8_t block)
Is specific block the value block?
Definition nfc_layer_a.cpp:1018
bool detect(m5::nfc::a::PICC &picc, const uint32_t timeout_ms=100U)
Detect single idle PICC.
Definition nfc_layer_a.cpp:211
bool mifarePlusUpgradeSecurityLevel2(const m5::nfc::a::mifare::plus::AESKey &sl2_switch_key=m5::nfc::a::mifare::plus::DEFAULT_KEY)
Upgrade security level to SL2 (AES over CRYPTO1)
Definition nfc_layer_a.cpp:1312
bool mifarePlusUpgradeSecurityLevel1(const m5::nfc::a::mifare::plus::AESKey &card_config_key=m5::nfc::a::mifare::plus::DEFAULT_KEY, const m5::nfc::a::mifare::plus::AESKey &card_master_key=m5::nfc::a::mifare::plus::DEFAULT_KEY, const m5::nfc::a::mifare::plus::AESKey &l2_switch_key=m5::nfc::a::mifare::plus::DEFAULT_KEY, const m5::nfc::a::mifare::plus::AESKey &l3_switch_key=m5::nfc::a::mifare::plus::DEFAULT_KEY, const m5::nfc::a::mifare::plus::AESKey &aes_sector_key=m5::nfc::a::mifare::plus::DEFAULT_FF_KEY, const m5::nfc::a::mifare::classic::Key &key_a=m5::nfc::a::mifare::classic::DEFAULT_KEY, const m5::nfc::a::mifare::classic::Key &key_b=m5::nfc::a::mifare::classic::DEFAULT_KEY)
Upgrade security level to SL1 (Classic compatibility mode)
Definition nfc_layer_a.cpp:1222
bool write(const uint8_t saddr, const uint8_t *tx, const uint16_t tx_len, const m5::nfc::a::mifare::classic::Key &key=m5::nfc::a::mifare::classic::DEFAULT_KEY)
Write any bytes to user area.
Definition nfc_layer_a.cpp:746
bool isActive(const m5::nfc::a::PICC &picc) const
Is the specified PICC currently active?
Definition nfc_layer_a.hpp:71
virtual uint16_t last_user_block() const override
Last user block.
Definition nfc_layer_a.hpp:554
virtual file_system_feature_t supportsFilesystem() const override
activePICC's File system
Definition nfc_layer_a.cpp:194
bool activate(const m5::nfc::a::PICC &picc, const bool force_rats=false)
Activate a specific PICC (anti-collision against the given PICC)
Definition nfc_layer_a.cpp:274
bool mifareUltralightCAuthenticate(const uint8_t key[16])
Authentication for MIFARE UltralightC.
Definition nfc_layer_a.cpp:1144
bool mifareUltralightChangeFormatToNDEF()
Write change to NFC Type-2 (NDEF) format for MIFARE Ultralight/C.
Definition nfc_layer_a.cpp:1114
virtual uint16_t user_area_size() const
User area size (bytes)
Definition nfc_layer_a.hpp:558
bool ndefPrepareDesfire(const uint32_t max_ndef_size)
Prepare NDEF files on MIFARE DESFire (EV1/EV2/EV3)
Definition nfc_layer_a.cpp:1362
bool mifareClassicWriteValueBlock(const uint8_t block, const int32_t value)
Write the specific block as the value block.
Definition nfc_layer_a.cpp:1077
bool ndefIsValidFormat(bool &valid)
Is the PICC data in NDEF format?
Definition nfc_layer_a.cpp:1348
bool select(m5::nfc::a::PICC &picc)
Select a PICC (anti-collision + SELECT cascade to ACTIVE)
Definition nfc_layer_a.cpp:259
virtual m5::nfc::isodep::IsoDEP * isoDEP() override
ISO-DEP interface (nullptr if not supported)
Definition nfc_layer_a.hpp:59
bool read16(uint8_t rx[16], const uint8_t addr)
Read the 1 block / 4 page (16 bytes)
Definition nfc_layer_a.cpp:520
bool mifareClassicDecrementValueBlock(const uint8_t block, const uint32_t delta, const bool transfer=true)
Decrement value of the value block.
Definition nfc_layer_a.cpp:1088
const m5::nfc::a::PICC & activatedPICC() const
Retrieve the currently activated PICC.
Definition nfc_layer_a.hpp:80
bool ndefRead(m5::nfc::ndef::TLV &msg)
Read NDEF Message TLV.
Definition nfc_layer_a.cpp:1370
bool write4(const uint8_t addr, const uint8_t *tx, const uint16_t tx_len, const bool safety=true)
Write the 1 page (4 bytes)
Definition nfc_layer_a.cpp:698
bool reactivate()
Reactivate the previously selected PICC.
Definition nfc_layer_a.hpp:160
virtual uint16_t unit_size_read() const override
Unit size for read.
Definition nfc_layer_a.hpp:562
bool identify(m5::nfc::a::PICC &picc)
Identify the specified PICC type.
Definition nfc_layer_a.cpp:331
bool read4(uint8_t rx[4], const uint8_t addr)
Read the 1 page.
Definition nfc_layer_a.cpp:502
bool mifareClassicAuthenticateB(const uint8_t block, const m5::nfc::a::mifare::classic::Key &key=m5::nfc::a::mifare::classic::DEFAULT_KEY)
Authentication by KeyB for MIFARE classic.
Definition nfc_layer_a.cpp:951
bool deactivate()
Send HLTA to the currently selected PICC (deactivate)
Definition nfc_layer_a.cpp:316
bool mifareClassicWriteAccessCondition(const uint8_t block, const uint8_t c123, const m5::nfc::a::mifare::classic::Key &akey, const m5::nfc::a::mifare::classic::Key &bkey)
Write the specific block access conditions.
Definition nfc_layer_a.cpp:982
virtual m5::nfc::NFCForumTag supportsNFCTag() const override
activePICC's NDEF type
Definition nfc_layer_a.cpp:189
bool ndefPrepareDesfireLight()
Prepare NDEF files on MIFARE DESFire Light.
Definition nfc_layer_a.cpp:1354
bool mifareClassicAuthenticateA(const uint8_t block, const m5::nfc::a::mifare::classic::Key &key=m5::nfc::a::mifare::classic::DEFAULT_KEY)
Authentication by KeyA for MIFARE classic.
Definition nfc_layer_a.cpp:946
bool ndefWrite(const m5::nfc::ndef::TLV &msg)
Write NDEF message.
Definition nfc_layer_a.cpp:1387
virtual uint16_t unit_size_write() const override
Unit size for write.
Definition nfc_layer_a.hpp:566
bool mifarePlusUpgradeSecurityLevel3(const m5::nfc::a::mifare::plus::AESKey &l3_switch_key=m5::nfc::a::mifare::plus::DEFAULT_KEY)
Upgrade security level to SL3 (AES)
Definition nfc_layer_a.cpp:1330
virtual uint16_t maximum_fifo_depth() const override
Maximum FIFO depth.
Definition nfc_layer_a.cpp:184
bool mifareClassicReadAccessCondition(uint8_t &c123, const uint8_t block)
Read the specific block access conditions.
Definition nfc_layer_a.cpp:956
bool mifareClassicRestoreValueBlock(const uint8_t block)
Restore block value to inner buffer.
Definition nfc_layer_a.cpp:1109
bool read(uint8_t *rx, uint16_t &rx_len, const uint8_t saddr, const m5::nfc::a::mifare::classic::Key &key=m5::nfc::a::mifare::classic::DEFAULT_KEY)
Read any bytes from user area.
Definition nfc_layer_a.cpp:528
bool wakeup(uint16_t &atqa)
Send WUPA to wake a PICC from IDLE or HALT.
Definition nfc_layer_a.cpp:204
bool write16(const uint8_t addr, const uint8_t *tx, const uint16_t tx_len, const bool safety=true)
Write the 1 block / 4 page (16 bytes)
Definition nfc_layer_a.cpp:714
virtual bool transceive(uint8_t *rx, uint16_t &rx_len, const uint8_t *tx, const uint16_t tx_len, const uint32_t timeout_ms) override
Transceive (RF command)
Definition nfc_layer_a.cpp:178
bool mifareClassicIncrementValueBlock(const uint8_t block, const uint32_t delta, const bool transfer=true)
Increment value of the value block.
Definition nfc_layer_a.cpp:1096
Common interface for NFC layer.
Definition nfc_layer.hpp:26
ISO Data Exchange Protocol.
Definition isoDEP.hpp:190
NDEF operations layer.
Definition ndef_layer.hpp:35
NDEF TLV container.
Definition ndef_tlv.hpp:27
ST25R3916 unit in CapCC1101 (SPI)
Definition unit_ST25R3916.hpp:2062
ST25R3916 Unit.
Definition unit_ST25R3916.hpp:38
ISO Data Exchange Protocol.
std::array< uint8_t, 16 > AESKey
MIFARE Plus SL2/3 Key (AES)
Definition mifare.hpp:279
std::array< uint8_t, 6 > Key
MIFARE classic Key.
Definition mifare.hpp:50
Top level namespace of M5stack.
NFC related definitions.
Unit-related namespace.
NFC-V definitions.
NDEF related.
uint8_t TagBits
TLV(Tag,Length,Value) tag bit group for type2/5.
Definition ndef.hpp:55
Common layer for NDEF related.
uint8_t file_system_feature_t
Alias for file_system_feature_t.
Definition nfc.hpp:62
NFCForumTag
NFC Forum Tag Type.
Definition nfc.hpp:39
Common layer for NFC related units.
NFC-A definitions.
Command
ISO-14443-3/4,MIFARE,NTAG commands.
Definition nfca.hpp:538
Type
Type of the PICC.
Definition nfca.hpp:31
Answer to request.
Definition nfca.hpp:256
PICC for NFC-A.
Definition nfca.hpp:335
uint16_t userAreaSize() const
Total user area size.
Definition nfca.hpp:458
bool supportsNFC() const
Supports NFC?
Definition nfca.hpp:487
uint16_t lastUserBlock() const
Total size.
Definition nfca.hpp:473
bool valid() const
Valid?
Definition nfca.hpp:356
uint16_t firstUserBlock() const
Gets the first user block/page address.
Definition nfca.hpp:469
bool isMifareUltralight() const
Is MIFARE Ultralight series?
Definition nfca.hpp:393