mirror of
https://github.com/m5stack/M5Unit-NFC.git
synced 2026-05-20 11:48:34 -07:00
Fixes isoDEP chain RX R-ACK block number and NFC-B ATTRIB PARAM2
This commit is contained in:
+1
-1
@@ -186,7 +186,7 @@ enum class Command : uint8_t {
|
|||||||
///@name Timeout
|
///@name Timeout
|
||||||
///@{
|
///@{
|
||||||
constexpr uint32_t TIMEOUT_REQ_WUP_B{5};
|
constexpr uint32_t TIMEOUT_REQ_WUP_B{5};
|
||||||
constexpr uint32_t TIMEOUT_ATTRIB{5};
|
constexpr uint32_t TIMEOUT_ATTRIB{50};
|
||||||
constexpr uint32_t TIMEOUT_HLTB{5};
|
constexpr uint32_t TIMEOUT_HLTB{5};
|
||||||
constexpr uint32_t TIMEOUT_DESELECT{5};
|
constexpr uint32_t TIMEOUT_DESELECT{5};
|
||||||
///@}
|
///@}
|
||||||
|
|||||||
@@ -276,7 +276,7 @@ bool FileSystem::readBinary(std::vector<uint8_t>& out, const uint16_t offset,
|
|||||||
// m5::utility::log::dump(cmd.data(), cmd.size(), false);
|
// m5::utility::log::dump(cmd.data(), cmd.size(), false);
|
||||||
|
|
||||||
std::vector<uint8_t> rx;
|
std::vector<uint8_t> rx;
|
||||||
rx.resize(le + 2 + 16);
|
rx.resize(le * 2 + 64); // generous margin for PICC chain overshoot
|
||||||
|
|
||||||
uint16_t rx_len = clamp_u16_size(rx.size());
|
uint16_t rx_len = clamp_u16_size(rx.size());
|
||||||
if (!_isoDEP.transceiveAPDU(rx.data(), rx_len, cmd.data(), static_cast<uint16_t>(cmd.size())) || rx_len < 2) {
|
if (!_isoDEP.transceiveAPDU(rx.data(), rx_len, cmd.data(), static_cast<uint16_t>(cmd.size())) || rx_len < 2) {
|
||||||
|
|||||||
@@ -169,7 +169,7 @@ bool IsoDEP::transceiveINF(uint8_t* rx_inf, uint16_t& rx_inf_len, const uint8_t*
|
|||||||
const uint32_t timeout_ms = _cfg.fwt_ms;
|
const uint32_t timeout_ms = _cfg.fwt_ms;
|
||||||
|
|
||||||
// Send I-Block and receive first frame
|
// Send I-Block and receive first frame
|
||||||
// M5_LIB_LOGE("I-Block TX: %u bytes, timeout=%u", tpos, timeout_ms);
|
M5_LIB_LOGV("isoDEP TX I-block[%u] timeout=%u max_rx=%u", tpos, timeout_ms, max_frame_size_rx);
|
||||||
if (!_layer.transceive(rx_buf, rlen, tx_buf, tpos, timeout_ms)) {
|
if (!_layer.transceive(rx_buf, rlen, tx_buf, tpos, timeout_ms)) {
|
||||||
M5_LIB_LOGE("transceive failed, rlen=%u", rlen);
|
M5_LIB_LOGE("transceive failed, rlen=%u", rlen);
|
||||||
if (rlen > 0) {
|
if (rlen > 0) {
|
||||||
@@ -181,6 +181,7 @@ bool IsoDEP::transceiveINF(uint8_t* rx_inf, uint16_t& rx_inf_len, const uint8_t*
|
|||||||
PRINT_ERROR(">>>>ERROR 1 %u %02X", rlen, rx_buf[0]);
|
PRINT_ERROR(">>>>ERROR 1 %u %02X", rlen, rx_buf[0]);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
M5_LIB_LOGV("isoDEP RX[%u] PCB=%02X", rlen, rx_buf[0]);
|
||||||
|
|
||||||
// Parse loop: WTX can replace rx_buf/rlen and we continue parsing without re-sending I-Block.
|
// Parse loop: WTX can replace rx_buf/rlen and we continue parsing without re-sending I-Block.
|
||||||
for (;;) {
|
for (;;) {
|
||||||
@@ -206,7 +207,7 @@ bool IsoDEP::transceiveINF(uint8_t* rx_inf, uint16_t& rx_inf_len, const uint8_t*
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const uint8_t pcb = rx_buf[0];
|
uint8_t pcb = rx_buf[0];
|
||||||
|
|
||||||
// --- S-Block (WTX) ---
|
// --- S-Block (WTX) ---
|
||||||
if (is_s_wtx(pcb)) {
|
if (is_s_wtx(pcb)) {
|
||||||
@@ -314,15 +315,19 @@ bool IsoDEP::transceiveINF(uint8_t* rx_inf, uint16_t& rx_inf_len, const uint8_t*
|
|||||||
// Response chaining: send R-ACK and receive next I-Block (WTX may appear)
|
// Response chaining: send R-ACK and receive next I-Block (WTX may appear)
|
||||||
while (resp_more) {
|
while (resp_more) {
|
||||||
uint8_t r_ack[2]{};
|
uint8_t r_ack[2]{};
|
||||||
uint16_t rp = 0;
|
uint16_t rp = 0;
|
||||||
r_ack[rp++] = make_r_ack(i_bn(pcb), _cfg.use_cid);
|
const uint8_t ack_bn = i_bn(pcb) ^ 0x01;
|
||||||
|
r_ack[rp++] = make_r_ack(ack_bn, _cfg.use_cid);
|
||||||
if (_cfg.use_cid) r_ack[rp++] = (uint8_t)(_cfg.cid & 0x0F);
|
if (_cfg.use_cid) r_ack[rp++] = (uint8_t)(_cfg.cid & 0x0F);
|
||||||
|
|
||||||
|
M5_LIB_LOGV("isoDEP chain TX R-ACK bn=%u (collected=%u)", ack_bn, rx_written);
|
||||||
uint16_t rlen2 = sizeof(rx_buf);
|
uint16_t rlen2 = sizeof(rx_buf);
|
||||||
if (!_layer.transceive(rx_buf, rlen2, r_ack, rp, _cfg.fwt_ms)) {
|
if (!_layer.transceive(rx_buf, rlen2, r_ack, rp, _cfg.fwt_ms)) {
|
||||||
|
M5_LIB_LOGE("isoDEP chain RX failed, rlen=%u", rlen2);
|
||||||
PRINT_ERROR(">>>>ERROR 12");
|
PRINT_ERROR(">>>>ERROR 12");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
M5_LIB_LOGV("isoDEP chain RX[%u] PCB=%02X", rlen2, rx_buf[0]);
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if (_cfg.rx_crc && rlen2 >= 3) rlen2 -= 2;
|
if (_cfg.rx_crc && rlen2 >= 3) rlen2 -= 2;
|
||||||
@@ -381,8 +386,8 @@ bool IsoDEP::transceiveINF(uint8_t* rx_inf, uint16_t& rx_inf_len, const uint8_t*
|
|||||||
|
|
||||||
const uint16_t inf_len2 = (uint16_t)(rlen2 - idx2);
|
const uint16_t inf_len2 = (uint16_t)(rlen2 - idx2);
|
||||||
if (rx_written + inf_len2 > rx_inf_len_org) {
|
if (rx_written + inf_len2 > rx_inf_len_org) {
|
||||||
PRINT_ERROR("rx_written %u inf_len2 %u rx_inf_len %u", rx_written, inf_len2,
|
PRINT_ERROR("rx_written %u inf_len2 %u rx_inf_len_org %u", rx_written, inf_len2,
|
||||||
rx_inf_len);
|
rx_inf_len_org);
|
||||||
// m5::utility::log::dump(rx_inf, rx_written, false);
|
// m5::utility::log::dump(rx_inf, rx_written, false);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
@@ -391,6 +396,7 @@ bool IsoDEP::transceiveINF(uint8_t* rx_inf, uint16_t& rx_inf_len, const uint8_t*
|
|||||||
memcpy(rx_inf + rx_written, rx_buf + idx2, inf_len2);
|
memcpy(rx_inf + rx_written, rx_buf + idx2, inf_len2);
|
||||||
rx_written = (uint16_t)(rx_written + inf_len2);
|
rx_written = (uint16_t)(rx_written + inf_len2);
|
||||||
|
|
||||||
|
pcb = pcb2;
|
||||||
resp_more = i_has_more(pcb2);
|
resp_more = i_has_more(pcb2);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,6 +43,20 @@ constexpr uint8_t required_slots(const Require slots)
|
|||||||
{
|
{
|
||||||
return 1U << m5::stl::to_underlying(slots);
|
return 1U << m5::stl::to_underlying(slots);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ISO/IEC 14443-4 FSDI table (Frame Size for Device Index, bit[7:4] of ATTRIB PARAM2)
|
||||||
|
constexpr uint8_t fsdi_for_size(const uint16_t bytes)
|
||||||
|
{
|
||||||
|
return (bytes >= 256) ? 8
|
||||||
|
: (bytes >= 128) ? 7
|
||||||
|
: (bytes >= 96) ? 6
|
||||||
|
: (bytes >= 64) ? 5
|
||||||
|
: (bytes >= 48) ? 4
|
||||||
|
: (bytes >= 40) ? 3
|
||||||
|
: (bytes >= 32) ? 2
|
||||||
|
: (bytes >= 24) ? 1
|
||||||
|
: 0;
|
||||||
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
namespace m5 {
|
namespace m5 {
|
||||||
@@ -69,10 +83,11 @@ bool NFCLayerB::receive(uint8_t* rx, uint16_t& rx_len, const uint32_t timeout_ms
|
|||||||
return _impl->receive(rx, rx_len, timeout_ms);
|
return _impl->receive(rx, rx_len, timeout_ms);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NFCLayerB::detect(m5::nfc::b::PICC& picc, const uint8_t afi, const uint32_t timeout_ms)
|
bool NFCLayerB::detect(m5::nfc::b::PICC& picc, const uint8_t afi, const uint32_t timeout_ms,
|
||||||
|
const uint32_t req_timeout_ms)
|
||||||
{
|
{
|
||||||
std::vector<PICC> piccs{};
|
std::vector<PICC> piccs{};
|
||||||
if (detect(piccs, afi, 1, timeout_ms)) {
|
if (detect(piccs, afi, 1, timeout_ms, req_timeout_ms)) {
|
||||||
picc = piccs.front();
|
picc = piccs.front();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -80,7 +95,7 @@ bool NFCLayerB::detect(m5::nfc::b::PICC& picc, const uint8_t afi, const uint32_t
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool NFCLayerB::detect(std::vector<m5::nfc::b::PICC>& piccs, const uint8_t afi, const uint8_t max_piccs,
|
bool NFCLayerB::detect(std::vector<m5::nfc::b::PICC>& piccs, const uint8_t afi, const uint8_t max_piccs,
|
||||||
const uint32_t timeout_ms)
|
const uint32_t timeout_ms, const uint32_t req_timeout_ms)
|
||||||
{
|
{
|
||||||
piccs.clear();
|
piccs.clear();
|
||||||
|
|
||||||
@@ -88,7 +103,7 @@ bool NFCLayerB::detect(std::vector<m5::nfc::b::PICC>& piccs, const uint8_t afi,
|
|||||||
do {
|
do {
|
||||||
uint8_t rx[ATQB_LENGTH]{};
|
uint8_t rx[ATQB_LENGTH]{};
|
||||||
uint16_t rx_len = sizeof(rx);
|
uint16_t rx_len = sizeof(rx);
|
||||||
if (!request(rx, rx_len, afi, Require::Slot1)) {
|
if (!request(rx, rx_len, afi, Require::Slot1, req_timeout_ms)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -110,7 +125,7 @@ bool NFCLayerB::detect(std::vector<m5::nfc::b::PICC>& piccs, const uint8_t afi,
|
|||||||
return !piccs.empty();
|
return !piccs.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NFCLayerB::select(m5::nfc::b::PICC& picc)
|
bool NFCLayerB::select(m5::nfc::b::PICC& picc, const uint32_t timeout_ms)
|
||||||
{
|
{
|
||||||
// Wakeup for READY
|
// Wakeup for READY
|
||||||
uint16_t len = ATQB_LENGTH;
|
uint16_t len = ATQB_LENGTH;
|
||||||
@@ -118,21 +133,35 @@ bool NFCLayerB::select(m5::nfc::b::PICC& picc)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
M5_LIB_LOGI("ATQB protocol: %02X %02X %02X (FSCI=%u, ISO14443-4=%d, FWI=%u)", picc.protocol[0], picc.protocol[1],
|
||||||
|
picc.protocol[2], (picc.protocol[1] >> 4) & 0x0F, (picc.protocol[1] & 0x01),
|
||||||
|
(picc.protocol[2] >> 4) & 0x0F);
|
||||||
|
|
||||||
|
// ATTRIB PARAM2 (per ISO/IEC 14443-3 §7.10.2 with b1 = LSB):
|
||||||
|
// bit[3:0] = FSDI (PCD's max receive frame size index)
|
||||||
|
// bit[5:4] = PCD->PICC bit rate divisor
|
||||||
|
// bit[7:6] = PICC->PCD bit rate divisor
|
||||||
|
// Take min(PCD FIFO, PICC FSCI) so the PICC chains I-blocks within what we can receive.
|
||||||
|
const uint16_t pcd_rx_cap = maximum_fifo_depth() - 2 /*CRC*/;
|
||||||
|
const uint8_t pcd_fsdi = fsdi_for_size(pcd_rx_cap);
|
||||||
|
const uint8_t picc_fsci = picc.maximumFrameLengthBits();
|
||||||
|
const uint8_t fsdi = std::min<uint8_t>(pcd_fsdi, picc_fsci);
|
||||||
|
|
||||||
// ATTRIB
|
// ATTRIB
|
||||||
uint8_t cmd[1 + 4 + 1 + 1 + 1 + 1] = {m5::stl::to_underlying(Command::ATTRIB)}; // without option
|
uint8_t cmd[1 + 4 + 1 + 1 + 1 + 1] = {m5::stl::to_underlying(Command::ATTRIB)}; // without option
|
||||||
memcpy(cmd + 1, picc.pupi, 4);
|
memcpy(cmd + 1, picc.pupi, 4);
|
||||||
cmd[5] = 0x00; // PARAM1
|
cmd[5] = 0x00; // PARAM1
|
||||||
cmd[6] = picc.maximumFrameLengthBits(); // PARAM2 | com speed
|
cmd[6] = (uint8_t)(fsdi & 0x0F); // PARAM2: FSDI(PCD cap) bit[3:0] | rates=0 (106k both)
|
||||||
cmd[7] = picc.protocol[1] & 0x0F; // PARAM 3protocol type
|
cmd[7] = picc.protocol[1] & 0x0F; // PARAM3 protocol type
|
||||||
cmd[8] = 0x00; // PARAM 4
|
cmd[8] = 0x00; // PARAM 4
|
||||||
|
|
||||||
std::vector<uint8_t> frame;
|
std::vector<uint8_t> frame;
|
||||||
frame.assign(cmd, cmd + sizeof(cmd));
|
frame.assign(cmd, cmd + sizeof(cmd));
|
||||||
|
|
||||||
uint8_t rx[128]{};
|
uint8_t rx[128]{};
|
||||||
uint16_t rx_len = sizeof(rx);
|
uint16_t rx_len = sizeof(rx);
|
||||||
if (!transceive(rx, rx_len, frame.data(), frame.size(), TIMEOUT_ATTRIB) || !rx_len) {
|
if (!transceive(rx, rx_len, frame.data(), frame.size(), timeout_ms) || !rx_len) {
|
||||||
M5_LIB_LOGE("Failed to select");
|
M5_LIB_LOGE("Failed to select: rx_len=%u", rx_len);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -140,14 +169,14 @@ bool NFCLayerB::select(m5::nfc::b::PICC& picc)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NFCLayerB::hlt(const uint8_t pupi[4])
|
bool NFCLayerB::hlt(const uint8_t pupi[4], const uint32_t timeout_ms)
|
||||||
{
|
{
|
||||||
if (pupi) {
|
if (pupi) {
|
||||||
uint8_t cmd[1 + 4] = {m5::stl::to_underlying(Command::HLTB)};
|
uint8_t cmd[1 + 4] = {m5::stl::to_underlying(Command::HLTB)};
|
||||||
memcpy(cmd + 1, pupi, 4);
|
memcpy(cmd + 1, pupi, 4);
|
||||||
uint8_t rx[1]{};
|
uint8_t rx[1 + 2]{}; // 1 byte payload + 2 byte CRC_B
|
||||||
uint16_t rx_len = sizeof(rx);
|
uint16_t rx_len = sizeof(rx);
|
||||||
if (!transceive(rx, rx_len, cmd, sizeof(cmd), TIMEOUT_HLTB) || rx_len < 1) {
|
if (!transceive(rx, rx_len, cmd, sizeof(cmd), timeout_ms) || rx_len < 1) {
|
||||||
M5_LIB_LOGE("Failed to hlt %02X%02X%02X%02X", cmd[1], cmd[2], cmd[3], cmd[4]);
|
M5_LIB_LOGE("Failed to hlt %02X%02X%02X%02X", cmd[1], cmd[2], cmd[3], cmd[4]);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -156,17 +185,18 @@ bool NFCLayerB::hlt(const uint8_t pupi[4])
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NFCLayerB::deselect(const uint8_t pupi[4], const uint8_t cid)
|
bool NFCLayerB::deselect(const uint8_t pupi[4], const uint8_t cid, const uint32_t timeout_ms)
|
||||||
{
|
{
|
||||||
uint8_t cmd[2] = {m5::stl::to_underlying(cid != 0xFF ? Command::DESELECT_WITH_CID : Command::DESELECT)};
|
uint8_t cmd[2] = {m5::stl::to_underlying(cid != 0xFF ? Command::DESELECT_WITH_CID : Command::DESELECT)};
|
||||||
uint16_t cmd_len = 1 + (cid != 0xFF);
|
uint16_t cmd_len = 1 + (cid != 0xFF);
|
||||||
if (cid != 0xFF) {
|
if (cid != 0xFF) {
|
||||||
cmd[1] = cid;
|
cmd[1] = cid;
|
||||||
}
|
}
|
||||||
uint8_t rx[2]{};
|
uint8_t rx[2 + 2]{}; // payload (1 or 2) + 2 byte CRC_B
|
||||||
uint16_t rx_len = cmd_len;
|
uint16_t rx_len =
|
||||||
|
cmd_len + 2; // Match actual response size to keep wait_for_FIFO fallback equivalent to the old behavior
|
||||||
|
|
||||||
if (!transceive(rx, rx_len, cmd, cmd_len, TIMEOUT_DESELECT) || rx_len < cmd_len) {
|
if (!transceive(rx, rx_len, cmd, cmd_len, timeout_ms) || rx_len < cmd_len) {
|
||||||
M5_LIB_LOGE("Failed to deselecte %02X:%02X", cmd[0], cmd[1]);
|
M5_LIB_LOGE("Failed to deselecte %02X:%02X", cmd[0], cmd[1]);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -188,7 +218,7 @@ bool NFCLayerB::deactivate()
|
|||||||
|
|
||||||
//
|
//
|
||||||
bool NFCLayerB::request_wakeup(uint8_t* atqb, uint16_t& atqb_len, const uint8_t afi, const Require slots,
|
bool NFCLayerB::request_wakeup(uint8_t* atqb, uint16_t& atqb_len, const uint8_t afi, const Require slots,
|
||||||
const bool wakeup)
|
const bool wakeup, const uint32_t timeout_ms)
|
||||||
{
|
{
|
||||||
if (!atqb || atqb_len < ATQB_LENGTH) {
|
if (!atqb || atqb_len < ATQB_LENGTH) {
|
||||||
return false;
|
return false;
|
||||||
@@ -204,7 +234,7 @@ bool NFCLayerB::request_wakeup(uint8_t* atqb, uint16_t& atqb_len, const uint8_t
|
|||||||
atqb_len = 0;
|
atqb_len = 0;
|
||||||
|
|
||||||
// Ignore non-responsive slots and proceed to the next one.
|
// Ignore non-responsive slots and proceed to the next one.
|
||||||
if (transceive(rx, rx_len, cmd, sizeof(cmd), TIMEOUT_REQ_WUP_B) && rx_len == sizeof(rx) && rx[0] == 0x50) {
|
if (transceive(rx, rx_len, cmd, sizeof(cmd), timeout_ms) && rx_len == sizeof(rx) && rx[0] == 0x50) {
|
||||||
// Occur collision if CRC error
|
// Occur collision if CRC error
|
||||||
const uint16_t crc = crc16.range(rx, ATQB_LENGTH + 1);
|
const uint16_t crc = crc16.range(rx, ATQB_LENGTH + 1);
|
||||||
if (crc == ((uint16_t)rx[13] << 8 | rx[12])) {
|
if (crc == ((uint16_t)rx[13] << 8 | rx[12])) {
|
||||||
@@ -219,7 +249,7 @@ bool NFCLayerB::request_wakeup(uint8_t* atqb, uint16_t& atqb_len, const uint8_t
|
|||||||
rx_len = sizeof(rx);
|
rx_len = sizeof(rx);
|
||||||
slot_marker[0] = ((uint8_t)i << 4) | 0x05;
|
slot_marker[0] = ((uint8_t)i << 4) | 0x05;
|
||||||
// Ignore non-responsive slots and proceed to the next one.
|
// Ignore non-responsive slots and proceed to the next one.
|
||||||
if (!transceive(rx, rx_len, slot_marker, sizeof(slot_marker), TIMEOUT_REQ_WUP_B) || rx[0] != 0x50 ||
|
if (!transceive(rx, rx_len, slot_marker, sizeof(slot_marker), timeout_ms) || rx[0] != 0x50 ||
|
||||||
rx_len < sizeof(rx)) {
|
rx_len < sizeof(rx)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ namespace m5 {
|
|||||||
namespace unit {
|
namespace unit {
|
||||||
class UnitST25R3916;
|
class UnitST25R3916;
|
||||||
class CapST25R3916;
|
class CapST25R3916;
|
||||||
|
class UnitWS1850S;
|
||||||
} // namespace unit
|
} // namespace unit
|
||||||
namespace nfc {
|
namespace nfc {
|
||||||
|
|
||||||
@@ -40,6 +41,7 @@ public:
|
|||||||
struct Adapter;
|
struct Adapter;
|
||||||
explicit NFCLayerB(m5::unit::UnitST25R3916& u);
|
explicit NFCLayerB(m5::unit::UnitST25R3916& u);
|
||||||
explicit NFCLayerB(m5::unit::CapST25R3916& u);
|
explicit NFCLayerB(m5::unit::CapST25R3916& u);
|
||||||
|
explicit NFCLayerB(m5::unit::UnitWS1850S& u);
|
||||||
|
|
||||||
virtual bool transceive(uint8_t* rx, uint16_t& rx_len, const uint8_t* tx, const uint16_t tx_len,
|
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;
|
const uint32_t timeout_ms) override;
|
||||||
@@ -83,9 +85,10 @@ public:
|
|||||||
@post PICC transitions: IDLE -> READY on successful response
|
@post PICC transitions: IDLE -> READY on successful response
|
||||||
*/
|
*/
|
||||||
inline bool request(uint8_t* atqb, uint16_t& atqb_len, const uint8_t afi = 0x00,
|
inline bool request(uint8_t* atqb, uint16_t& atqb_len, const uint8_t afi = 0x00,
|
||||||
const m5::nfc::b::Require slots = m5::nfc::b::Require::Slot1)
|
const m5::nfc::b::Require slots = m5::nfc::b::Require::Slot1,
|
||||||
|
const uint32_t timeout_ms = m5::nfc::b::TIMEOUT_REQ_WUP_B)
|
||||||
{
|
{
|
||||||
return request_wakeup(atqb, atqb_len, afi, slots, false);
|
return request_wakeup(atqb, atqb_len, afi, slots, false, timeout_ms);
|
||||||
}
|
}
|
||||||
/*!
|
/*!
|
||||||
@brief Send WUPB to wake a PICC from IDLE or HALT
|
@brief Send WUPB to wake a PICC from IDLE or HALT
|
||||||
@@ -98,9 +101,10 @@ public:
|
|||||||
@post PICC transitions: IDLE/HALT -> READY on successful response
|
@post PICC transitions: IDLE/HALT -> READY on successful response
|
||||||
*/
|
*/
|
||||||
inline bool wakeup(uint8_t* atqb, uint16_t& atqb_len, const uint8_t afi = 0x00,
|
inline bool wakeup(uint8_t* atqb, uint16_t& atqb_len, const uint8_t afi = 0x00,
|
||||||
const m5::nfc::b::Require slots = m5::nfc::b::Require::Slot1)
|
const m5::nfc::b::Require slots = m5::nfc::b::Require::Slot1,
|
||||||
|
const uint32_t timeout_ms = m5::nfc::b::TIMEOUT_REQ_WUP_B)
|
||||||
{
|
{
|
||||||
return request_wakeup(atqb, atqb_len, afi, slots, true);
|
return request_wakeup(atqb, atqb_len, afi, slots, true, timeout_ms);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@@ -111,7 +115,8 @@ public:
|
|||||||
@return True if detected
|
@return True if detected
|
||||||
@note The detected PICC is typically put into HALT during enumeration to allow discovering others
|
@note The detected PICC is typically put into HALT during enumeration to allow discovering others
|
||||||
*/
|
*/
|
||||||
bool detect(m5::nfc::b::PICC& picc, const uint8_t afi = 0x00, const uint32_t timeout_ms = 100U);
|
bool detect(m5::nfc::b::PICC& picc, const uint8_t afi = 0x00, const uint32_t timeout_ms = 50U,
|
||||||
|
const uint32_t req_timeout_ms = m5::nfc::b::TIMEOUT_REQ_WUP_B);
|
||||||
/*!
|
/*!
|
||||||
@brief Detect idle PICCs
|
@brief Detect idle PICCs
|
||||||
@param[out] piccs Detected PICC PICCs (one per activated PICC candidate)
|
@param[out] piccs Detected PICC PICCs (one per activated PICC candidate)
|
||||||
@@ -122,11 +127,11 @@ public:
|
|||||||
@note The detected PICC is typically put into HALT during enumeration to allow discovering others
|
@note The detected PICC is typically put into HALT during enumeration to allow discovering others
|
||||||
*/
|
*/
|
||||||
bool detect(std::vector<m5::nfc::b::PICC>& piccs, const uint8_t afi = 0x00, const uint8_t max_piccs = 4,
|
bool detect(std::vector<m5::nfc::b::PICC>& piccs, const uint8_t afi = 0x00, const uint8_t max_piccs = 4,
|
||||||
const uint32_t timeout_ms = 1000U);
|
const uint32_t timeout_ms = 1000U, const uint32_t req_timeout_ms = m5::nfc::b::TIMEOUT_REQ_WUP_B);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
*/
|
*/
|
||||||
bool select(m5::nfc::b::PICC& picc);
|
bool select(m5::nfc::b::PICC& picc, const uint32_t timeout_ms = m5::nfc::b::TIMEOUT_ATTRIB);
|
||||||
#if 0
|
#if 0
|
||||||
bool activate(m5::nfc::b::PICC& picc);
|
bool activate(m5::nfc::b::PICC& picc);
|
||||||
bool reactivate(const m5::nfc::b::PICC& picc);
|
bool reactivate(const m5::nfc::b::PICC& picc);
|
||||||
@@ -140,14 +145,15 @@ public:
|
|||||||
|
|
||||||
///@name For activated PICC
|
///@name For activated PICC
|
||||||
///@{
|
///@{
|
||||||
bool hlt(const uint8_t pupi[4]);
|
bool hlt(const uint8_t pupi[4], const uint32_t timeout_ms = m5::nfc::b::TIMEOUT_HLTB);
|
||||||
bool deselect(const uint8_t pupi[4], const uint8_t cid = 0xFF);
|
bool deselect(const uint8_t pupi[4], const uint8_t cid = 0xFF,
|
||||||
|
const uint32_t timeout_ms = m5::nfc::b::TIMEOUT_DESELECT);
|
||||||
bool deactivate();
|
bool deactivate();
|
||||||
///@}
|
///@}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool request_wakeup(uint8_t* atqb, uint16_t& atqb_len, const uint8_t afi, const m5::nfc::b::Require slots,
|
bool request_wakeup(uint8_t* atqb, uint16_t& atqb_len, const uint8_t afi, const m5::nfc::b::Require slots,
|
||||||
const bool wakeup);
|
const bool wakeup, const uint32_t timeout_ms = m5::nfc::b::TIMEOUT_REQ_WUP_B);
|
||||||
|
|
||||||
virtual bool read(uint8_t* rx, uint16_t& rx_len, const uint16_t saddr) override
|
virtual bool read(uint8_t* rx, uint16_t& rx_len, const uint16_t saddr) override
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user