Move the processing to the layer side(NFCA), Fixes ReadWrite example

This commit is contained in:
GOB
2026-01-07 19:13:20 +09:00
parent c20023c7a8
commit 781e4f0e2d
7 changed files with 83 additions and 163 deletions
+1 -1
View File
@@ -268,7 +268,7 @@ void loop()
if (clicked) {
M5.Speaker.tone(2000, 30);
lcd.fillScreen(TFT_BLUE);
nfc_a.dump();
// nfc_a.dump();
read_ndef();
} else if (held) {
M5.Speaker.tone(4000, 30);
@@ -89,7 +89,7 @@ bool read_write(const uint8_t sblock, const char* msg, const Key& key)
uint16_t rx_len = sizeof(buf);
// Write
M5.Log.printf("================================ WRITE\n");
M5.Log.printf("================================ WRITE %u len:%zu\n", sblock, sizeof(buf));
if (nfc_a.write(sblock, (const uint8_t*)msg, len, key)) {
lcd.fillScreen(TFT_ORANGE);
nfc_a.dump();
@@ -98,7 +98,10 @@ bool read_write(const uint8_t sblock, const char* msg, const Key& key)
if (nfc_a.read(buf, rx_len, sblock, key)) {
lcd.fillScreen(TFT_BLUE);
M5.Log.printf("================================ VERIFY:%s\n", memcmp(buf, msg, len) == 0 ? "OK" : "NG");
m5::utility::log::dump(buf, rx_len, false);
if (memcmp(buf, msg, len)) {
m5::utility::log::dump(buf, rx_len, false);
M5_LOGE("VERIFY NG!!");
}
// Clear
memset(buf, 0, sizeof(buf));
@@ -162,7 +165,7 @@ void read_write_sector_structure(const uint8_t block, const Key& key)
nfc_a.dump(block);
}
// Using read4,16/write4 for Ultralight,NTAG
// Using read4,write4 for Ultralight,NTAG
void read_write_page_structure(const PICC& picc, const uint8_t page)
{
constexpr char msg[] = "M5";
@@ -181,21 +184,19 @@ void read_write_page_structure(const PICC& picc, const uint8_t page)
nfc_a.dump(aligned_page);
// Read
uint8_t rbuf[16]{};
if (picc.isNTAG()) {
if (!nfc_a.read4(rbuf, page)) {
M5_LOGE("Failed to read");
return;
}
} else {
if (!nfc_a.read16(rbuf, aligned_page)) {
M5_LOGE("Failed to read");
return;
}
uint8_t rbuf[4]{};
if (!nfc_a.read4(rbuf, page)) {
M5_LOGE("Failed to read");
return;
}
bool verify = std::memcmp(rbuf, (const uint8_t*)msg, sizeof(msg)) == 0;
M5.Log.printf("Verify %s\n", verify ? "OK" : "NG");
M5.Log.printf("Verify %u %s\n", picc.isNTAG(), verify ? "OK" : "NG");
if (!verify) {
M5_LOGE("VERIFY NG!!");
m5::utility::log::dump(msg, sizeof(msg), false);
m5::utility::log::dump(rbuf, sizeof(rbuf), false);
}
// Clear
M5.Log.printf("Clear\n");
@@ -285,7 +286,8 @@ void loop()
M5.Speaker.tone(2000, 30);
// Need key if MIFARE classic, Ignore key if not MIFARE classic
read_all_user_area(keyA);
auto ret = read_write(0, picc.userAreaSize() >= 120 ? long_msg : short_msg, keyA);
auto ret =
read_write(picc.firstUserBlock(), picc.userAreaSize() >= 120 ? long_msg : short_msg, keyA);
lcd.fillScreen(ret ? 0 : TFT_RED);
} else if (held) {
M5.Speaker.tone(4000, 30);
+57 -18
View File
@@ -297,7 +297,7 @@ bool NFCLayerA::read4(uint8_t rx[4], const uint8_t addr)
uint16_t rx_len{4};
if (_activePICC.canFastRead()) {
return _impl->ntag_read_page(rx, rx_len, addr, addr);
return ntag_read_page(rx, rx_len, addr, addr);
}
uint8_t tmp[16]{};
if (_impl->nfca_read_block(tmp, addr & ~0x03)) {
@@ -311,7 +311,7 @@ bool NFCLayerA::read16(uint8_t rx[16], const uint8_t addr)
{
uint16_t rx_len{16};
return rx && _activePICC.valid() &&
(_activePICC.canFastRead() ? (_impl->ntag_read_page(rx, rx_len, addr, addr + 3) && rx_len == 16)
(_activePICC.canFastRead() ? (ntag_read_page(rx, rx_len, addr, addr + 3) && rx_len == 16)
: _impl->nfca_read_block(rx, addr));
}
@@ -331,10 +331,9 @@ bool NFCLayerA::read_using_fast(uint8_t* rx, uint16_t& rx_len, const uint8_t add
const uint16_t last = get_last_user_block(t);
uint16_t need_page = ((rx_len + 3) >> 2);
// uint16_t from = std::min<uint16_t>(last, std::max<uint16_t>(addr, get_first_user_block(t)));
uint16_t from = addr;
uint16_t to = std::min<uint16_t>(from + need_page - 1, last);
uint16_t pages = to - from + 1;
uint16_t from = addr;
uint16_t to = std::min<uint16_t>(from + need_page - 1, last);
uint16_t pages = to - from + 1;
uint16_t read_size = pages << 2; // 4 byte unit
if (read_size > rx_len) {
@@ -360,7 +359,7 @@ bool NFCLayerA::read_using_fast(uint8_t* rx, uint16_t& rx_len, const uint8_t add
M5_LIB_LOGD(" READ:%u-%u %u %u/%u", spage, epage, len, actual, pages);
if (!_impl->ntag_read_page(rx + rx_len, len, spage, epage) || len != (ps << 2)) {
if (!ntag_read_page(rx + rx_len, len, spage, epage) || len != (ps << 2)) {
M5_LIB_LOGD("Failed to read %u-%u", spage, epage);
return false;
}
@@ -440,7 +439,7 @@ bool NFCLayerA::write4(const uint8_t addr, const uint8_t* tx, const uint16_t tx_
uint8_t buf[4]{};
memcpy(buf, tx, std::min<uint16_t>(4, tx_len));
return _impl->nfca_write_page(addr, buf);
return ntag_write_page(addr, buf);
}
bool NFCLayerA::write16(const uint8_t addr, const uint8_t* tx, const uint16_t tx_len, const bool safety)
@@ -460,7 +459,7 @@ bool NFCLayerA::write16(const uint8_t addr, const uint8_t* tx, const uint16_t tx
return false;
}
for (uint_fast8_t i = 0; i < 4; ++i) {
if (!_impl->nfca_write_page(addr + i, buf + i * 4)) {
if (!ntag_write_page(addr + i, buf + i * 4)) {
return false;
}
}
@@ -574,15 +573,6 @@ bool NFCLayerA::write_using_write16(const uint8_t addr, const uint8_t* tx, const
return written == tx_len;
}
bool NFCLayerA::write(const uint8_t saddr, const uint8_t* tx, const uint16_t tx_len)
{
if (!tx || !tx_len || !_activePICC.valid()) {
return false;
}
return _activePICC.supportsNFC() ? write_using_write4(saddr, tx, tx_len)
: write_using_write16(saddr, tx, tx_len, DEFAULT_KEY);
}
bool NFCLayerA::dump(const Key& mkey)
{
if (_activePICC.valid()) {
@@ -1087,6 +1077,7 @@ bool NFCLayerA::mifare_classic_value_block(const m5::nfc::a::Command cmd, const
return _impl->mifare_classic_value_block(cmd, block, arg);
}
// for ndef
bool NFCLayerA::read(uint8_t* rx, uint16_t& rx_len, const uint8_t saddr)
{
if (!rx || !rx_len || !_activePICC.valid()) {
@@ -1096,6 +1087,17 @@ bool NFCLayerA::read(uint8_t* rx, uint16_t& rx_len, const uint8_t saddr)
: read_using_read16(rx, rx_len, saddr, DEFAULT_KEY);
}
// for NDEF
bool NFCLayerA::write(const uint8_t saddr, const uint8_t* tx, const uint16_t tx_len)
{
if (!tx || !tx_len || !_activePICC.valid()) {
return false;
}
return _activePICC.supportsNFC() ? write_using_write4(saddr, tx, tx_len)
: write_using_write16(saddr, tx, tx_len, DEFAULT_KEY);
}
//
bool NFCLayerA::mifare_ultralightC_authenticate1(uint8_t ek[8])
{
uint8_t cmd[2] = {m5::stl::to_underlying(Command::AUTHENTICATE_1), 0x00};
@@ -1255,5 +1257,42 @@ bool NFCLayerA::mifare_get_version_L4(uint8_t* ver, uint16_t& ver_len)
}
return false;
}
bool NFCLayerA::ntag_read_page(uint8_t* rx, uint16_t& rx_len, const uint8_t spage, const uint8_t epage)
{
if (!rx || !rx_len || spage > epage || !_activePICC.valid()) {
return false;
}
uint8_t cmd[3] = {m5::stl::to_underlying(Command::FAST_READ), spage, epage};
const uint8_t pages = epage - spage + 1;
uint16_t timeout = (pages == 1) ? TIMEOUT_FAST_READ
: (pages < 4) ? TIMEOUT_FAST_READ_4PAGE
: (pages < 12) ? TIMEOUT_FAST_READ_12PAGE
: (pages < 32) ? TIMEOUT_FAST_READ_32PAGE
: TIMEOUT_FAST_READ_32PAGE * 2;
if (!_impl->transceive(rx, rx_len, cmd, sizeof(cmd), timeout)) {
M5_LIB_LOGD("Failed to transceive");
return false;
}
return true;
}
bool NFCLayerA::ntag_write_page(const uint8_t page, const uint8_t tx[4])
{
if (!tx || !_activePICC.valid()) {
return false;
}
// M5_LIB_LOGD("WRITE_PAGE:%u", page);
// m5::utility::log::dump(tx, 4, false);
uint8_t cmd[6]{m5::stl::to_underlying(m5::nfc::a::Command::WRITE_PAGE), page};
std::memcpy(cmd + 2, tx, 4);
uint8_t rx[1]{};
uint16_t rx_len{1};
return _impl->transceive(rx, rx_len, cmd, sizeof(cmd), TIMEOUT_WRITE1);
}
} // namespace nfc
} // namespace m5
+7 -10
View File
@@ -501,6 +501,9 @@ protected:
bool mifare_ultralightC_authenticate1(uint8_t ek[8]);
bool mifare_ultralightC_authenticate2(uint8_t rx_ek[8], const uint8_t tx_ek[16]);
bool ntag_read_page(uint8_t* rx, uint16_t& rx_len, const uint8_t spage, const uint8_t epage);
bool ntag_write_page(const uint8_t page, const uint8_t tx[4]); // NTAG,UL,ULC
bool dump_sector_structure(const m5::nfc::a::PICC& picc, const m5::nfc::a::mifare::classic::Key& key);
bool dump_sector(const uint8_t sector);
bool dump_page_structure(const uint16_t maxPage);
@@ -527,27 +530,21 @@ struct NFCLayerA::Adapter {
virtual bool transceive(uint8_t* rx, uint16_t& rx_len, const uint8_t* tx, const uint16_t tx_len,
const uint32_t timeout_ms) = 0;
// virtual bool mifare_transceive(uint8_t* rx, uint16_t& rx_len, const uint8_t* tx, const uint16_t tx_len,
// const uint32_t timeout_ms) = 0;
virtual bool request(uint16_t& atqa) = 0;
virtual bool wakeup(uint16_t& atqa) = 0;
virtual bool select(m5::nfc::a::PICC& picc) = 0;
virtual bool activate(const m5::nfc::a::PICC& picc) = 0;
virtual bool hlt() = 0;
virtual bool nfca_read_block(uint8_t rx[16], const uint8_t addr) = 0; // READ
virtual bool nfca_write_block(const uint8_t addr, const uint8_t tx[16]) = 0; // WRITE_BLOCK
virtual bool nfca_write_page(const uint8_t addr, const uint8_t tx[4]) = 0; // WRITE_PAGE
virtual bool hlt() = 0;
// Due to the chip-side cryptographic mechanism, the following shall be treated as an independent API
virtual bool nfca_read_block(uint8_t rx[16], const uint8_t addr) = 0;
virtual bool nfca_write_block(const uint8_t addr, const uint8_t tx[16]) = 0;
virtual bool mifare_classic_authenticate(const bool auth_a, const m5::nfc::a::PICC& picc, const uint8_t block,
const m5::nfc::a::mifare::classic::Key& key) = 0;
virtual bool mifare_classic_value_block(const m5::nfc::a::Command cmd, const uint8_t block,
const uint32_t arg = 0) = 0;
virtual bool ntag_read_page(uint8_t* rx, uint16_t& rx_len, const uint8_t spage,
const uint8_t epage) = 0; // FAST_READ
};
///@endcond
-14
View File
@@ -47,16 +47,12 @@ struct PollerST25R3916ForA final : NFCLayerA::Adapter {
virtual bool nfca_read_block(uint8_t rx[16], const uint8_t addr) override; // READ
virtual bool nfca_write_block(const uint8_t addr, const uint8_t tx[16]) override; // WRITE_BLOCK
virtual bool nfca_write_page(const uint8_t addr, const uint8_t tx[4]) override; // WRITE_PAGE
virtual bool mifare_classic_authenticate(const bool auth_a, const m5::nfc::a::PICC& picc, const uint8_t block,
const m5::nfc::a::mifare::classic::Key& key) override;
virtual bool mifare_classic_value_block(const m5::nfc::a::Command cmd, const uint8_t block,
const uint32_t arg = 0) override;
virtual bool ntag_read_page(uint8_t* rx, uint16_t& rx_len, const uint8_t spage,
const uint8_t epage) override; // FAST_READ
UnitST25R3916& _u;
};
@@ -111,11 +107,6 @@ bool PollerST25R3916ForA::nfca_write_block(const uint8_t addr, const uint8_t tx[
return _u.nfcaWriteBlock(addr, tx);
}
bool PollerST25R3916ForA::nfca_write_page(const uint8_t addr, const uint8_t tx[4])
{
return _u.nfcaWritePage(addr, tx);
}
bool PollerST25R3916ForA::mifare_classic_authenticate(const bool auth_a, const PICC& picc, const uint8_t block,
const Key& key)
{
@@ -128,11 +119,6 @@ bool PollerST25R3916ForA::mifare_classic_value_block(const m5::nfc::a::Command c
return _u.mifareClassicValueBlock(cmd, block, arg);
}
bool PollerST25R3916ForA::ntag_read_page(uint8_t* rx, uint16_t& rx_len, const uint8_t spage, const uint8_t epage)
{
return _u.ntagReadPage(rx, rx_len, spage, epage);
}
//
namespace {
std::unique_ptr<NFCLayerA::Adapter> make_st25r3916_adapter(UnitST25R3916& u)
-23
View File
@@ -1799,20 +1799,11 @@ public:
@pre The block must be authenticated if MIFARE classic
*/
bool nfcaWriteBlock(const uint8_t block, const uint8_t tx[16]);
/*!
@brief Write the 1 page (4 bytes)
@param tx Send buffer (at least 4 bytes)
@return True if successful
@pre The block must be authenticated if MIFARE classic
*/
bool nfcaWritePage(const uint8_t page, const uint8_t tx[4]);
/*!
@brief Hlt for PICC
@return True if successful
*/
bool nfcaHlt();
///@}
// ----------------------------------------------------------------------------------------------
@@ -1854,20 +1845,6 @@ public:
bool mifareClassicValueBlock(const m5::nfc::a::Command cmd, const uint8_t block, const uint32_t arg = 0);
///@}
///@name NTAG
///@{
/*!
@brief Read between specified pages
@param rx Receiver buffer
@param[in/out] rx_len in:Size of receive buffer out:actual read size
@param spage Start reading page
@param epage End reading page
@return True if successful
@warning Only PICC with the FAST_READ command
*/
bool ntagReadPage(uint8_t* rx, uint16_t& rx_len, const uint8_t spage, const uint8_t epage);
///@}
// ----------------------------------------------------------------------------------------------
///@name NFC-B
///@{
-81
View File
@@ -218,41 +218,7 @@ bool UnitST25R3916::configure_emulation_a()
uint32_t UnitST25R3916::nfcaTransceive(uint8_t* rx, uint16_t& rx_len, const uint8_t* tx, const uint16_t tx_len,
const uint32_t timeout_ms)
{
#if 0
CHECK_MODE();
const auto rx_len_org = rx_len;
rx_len = 0;
if (!rx || !rx_len_org || !tx || !tx_len) {
return false;
}
// m5::utility::log::dump(tx, tx_len, false);
if ((timeout_ms ? !write_fwt_timer(timeout_ms) : false) || //
!writeSettingsISO14443A(0x00 /*standard*/) || !clear_bit_register8(REG_AUXILIARY_DEFINITION,no_crc_rx) || //
!clearInterrupts() || !writeDirectCommand(CMD_CLEAR_FIFO) || !writeFIFO(tx, tx_len) ||
!writeNumberOfTransmittedBytes(tx_len, 0) || !writeDirectCommand(CMD_TRANSMIT_WITH_CRC)) {
return false;
}
if (!wait_for_FIFO(timeout_ms, rx_len_org)) {
M5_LIB_LOGD("Timeout");
return false;
}
uint16_t actual{};
auto bb = readFIFO(actual, rx, rx_len_org);
if (bb) {
M5_LIB_LOGV("readFIFO %u/%u %u/%u %02X", actual, rx_len_org, bb >> 16, bb & 0xFFFF, rx[0]);
rx_len = actual;
return bb;
}
M5_LIB_LOGD("Failed to readFIFO %u/%u", actual, rx_len_org);
return false;
#else
return nfcaTransmit(tx, tx_len, timeout_ms) && nfcaReceive(rx, rx_len, timeout_ms);
#endif
}
bool UnitST25R3916::nfcaTransmit(const uint8_t* tx, const uint16_t tx_len, const uint32_t timeout_ms)
@@ -619,29 +585,6 @@ bool UnitST25R3916::nfcaWriteBlock(const uint8_t addr, const uint8_t tx[16])
return false;
}
bool UnitST25R3916::nfcaWritePage(const uint8_t page, const uint8_t tx[4])
{
CHECK_MODE();
if (!tx) {
return false;
}
// M5_LIB_LOGD("WRITE_PAGE:%u", page);
// m5::utility::log::dump(tx, 4, false);
uint8_t cmd[6]{m5::stl::to_underlying(m5::nfc::a::Command::WRITE_PAGE), page};
std::memcpy(cmd + 2, tx, 4);
uint8_t rx[2]{};
uint16_t rx_len{2};
if (nfcaTransceive(rx, rx_len, cmd, sizeof(cmd), TIMEOUT_WRITE2)) {
return true;
}
M5_LIB_LOGD("Failed to write page");
return false;
}
// -------------------------------- For MIFARE classic
bool UnitST25R3916::mifare_transceive(uint8_t* rx, uint16_t& rx_len, const uint8_t* tx, const uint16_t tx_len,
const uint32_t timeout_ms)
@@ -896,29 +839,5 @@ bool UnitST25R3916::mifareClassicValueBlock(const m5::nfc::a::Command cmd, const
return !wait_for_FIFO(TIMEOUT_VALUE_BLOCK); // Consider the timeout a success
}
// -------------------------------- For NTAG
bool UnitST25R3916::ntagReadPage(uint8_t* rx, uint16_t& rx_len, const uint8_t spage, const uint8_t epage)
{
CHECK_MODE();
if (spage > epage) {
return false;
}
uint8_t cmd[3] = {m5::stl::to_underlying(Command::FAST_READ), spage, epage};
const uint8_t pages = epage - spage + 1;
uint16_t timeout = (pages == 1) ? TIMEOUT_FAST_READ
: (pages < 4) ? TIMEOUT_FAST_READ_4PAGE
: (pages < 12) ? TIMEOUT_FAST_READ_12PAGE
: (pages < 32) ? TIMEOUT_FAST_READ_32PAGE
: TIMEOUT_FAST_READ_32PAGE * 2;
if (!nfcaTransceive(rx, rx_len, cmd, sizeof(cmd), timeout)) {
M5_LIB_LOGD("Failed to transceive");
return false;
}
return true;
}
} // namespace unit
} // namespace m5