Program Listing for File helper.hpp
↰ Return to documentation for file (libspookyaction/include/pn532/helper.hpp
)
//
// Created by spak on 1/18/23.
//
#ifndef PN532_SCAN_HELPER_HPP
#define PN532_SCAN_HELPER_HPP
#include <pn532/controller.hpp>
namespace pn532::helper {
struct scanned_target {
std::uint8_t index = std::numeric_limits<std::uint8_t>::max();
target_type type = target_type::generic_passive_106kbps;
std::vector<std::uint8_t> nfcid{};
scanned_target() = default;
template <target_type Type>
scanned_target(std::uint8_t index_, poll_target<Type> const &entry);
scanned_target(std::uint8_t index_, any_poll_target const &entry);
[[nodiscard]] bool operator==(scanned_target const &other) const;
[[nodiscard]] bool operator!=(scanned_target const &other) const;
[[nodiscard]] bool operator<(scanned_target const &other) const;
[[nodiscard]] bool operator>(scanned_target const &other) const;
[[nodiscard]] bool operator<=(scanned_target const &other) const;
[[nodiscard]] bool operator>=(scanned_target const &other) const;
[[nodiscard]] inline explicit operator bool() const noexcept;
};
struct autorelease_target : scanned_target {
std::weak_ptr<controller> ctrl = {};
autorelease_target() = default;
inline autorelease_target(std::shared_ptr<controller> const &ctrl_, scanned_target target_);
template <target_type Type>
autorelease_target(std::shared_ptr<controller> const &ctrl_, std::uint8_t index_, poll_target<Type> const &entry);
inline autorelease_target(std::shared_ptr<controller> const &ctrl_, std::uint8_t index_, any_poll_target const &entry);
inline result<rf_status> release(ms timeout = default_timeout);
inline ~autorelease_target();
};
[[nodiscard]] result<autorelease_target> scan(
std::shared_ptr<controller> const &ctrl,
scanned_target const &skip_prev_target = scanned_target{},
std::vector<target_type> const &targets = controller::poll_all_targets,
ms timeout = long_timeout);
}// namespace pn532::helper
namespace pn532::helper {
template <target_type Type>
scanned_target::scanned_target(std::uint8_t index_, poll_target<Type> const &entry) : index{index_}, type{Type} {
static constexpr auto BM = baudrate_modulation_of(Type);
if constexpr (std::is_base_of_v<poll_target_dep_passive<BM>, poll_target<Type>>) {
// Obtain NFCID3t from the atr_res_info, and the index from the target bit
index = entry.logical_index;
nfcid.resize(entry.atr_info.nfcid.size());
std::copy(std::begin(entry.atr_info.nfcid), std::end(entry.atr_info.nfcid), std::begin(nfcid));
} else if constexpr (std::is_base_of_v<target<BM>, poll_target<Type>>) {
// Obtain the logical index from the target bit, and then differentiate
index = entry.logical_index;
if constexpr (BM == baudrate_modulation::kbps106_iso_iec_14443_typea) {
nfcid = entry.nfcid;
} else if constexpr (BM == baudrate_modulation::kbps212_felica or BM == baudrate_modulation::kbps424_felica) {
nfcid.resize(entry.nfcid_2t.size());
std::copy(std::begin(entry.nfcid_2t), std::end(entry.nfcid_2t), std::begin(nfcid));
} else if constexpr (BM == baudrate_modulation::kbps106_iso_iec_14443_3_typeb) {
// Slice off the PUPI (Pseudo-Unique PICC Identifier) out of the atqb response
if (entry.atqb_response.size() >= 5) {
nfcid.resize(4);
std::copy_n(std::begin(entry.atqb_response) + 1, 4, std::begin(nfcid));
} else {
// Just use the whole atqb response
nfcid.resize(entry.atqb_response.size());
std::copy(std::begin(entry.atqb_response), std::end(entry.atqb_response), std::begin(nfcid));
}
} else if constexpr (BM == baudrate_modulation::kbps106_innovision_jewel_tag) {
// Use jewel id
nfcid.resize(entry.jewel_id.size());
std::copy(std::begin(entry.jewel_id), std::end(entry.jewel_id), std::begin(nfcid));
}
} else {
static_assert(std::is_base_of_v<poll_target_with_atr, poll_target<Type>>);
// Obtain NFCID3t from the atr_res_info, we cannot do anything about the index
nfcid.resize(entry.atr_info.nfcid.size());
std::copy(std::begin(entry.atr_info.nfcid), std::end(entry.atr_info.nfcid), std::begin(nfcid));
}
}
inline scanned_target::operator bool() const noexcept {
return index < std::numeric_limits<std::uint8_t>::max();
}
template <target_type Type>
autorelease_target::autorelease_target(std::shared_ptr<controller> const &ctrl_, std::uint8_t index_, poll_target<Type> const &entry)
: scanned_target{index_, entry}, ctrl{ctrl_->weak_from_this()} {}
autorelease_target::autorelease_target(std::shared_ptr<controller> const &ctrl_, std::uint8_t index_, any_poll_target const &entry)
: scanned_target{index_, entry}, ctrl{ctrl_->weak_from_this()} {}
autorelease_target::autorelease_target(std::shared_ptr<controller> const &ctrl_, scanned_target target_)
: scanned_target{std::move(target_)}, ctrl{ctrl_->weak_from_this()} {}
result<rf_status> autorelease_target::release(ms timeout) {
if (index < std::numeric_limits<std::uint8_t>::max()) {
if (const auto ctrl_strong_ref = ctrl.lock(); ctrl_strong_ref) {
auto r = ctrl_strong_ref->initiator_release(index);
if (r) {
// Done, the weak ref can be destroyed
ctrl = {};
}
return r;
}
return channel_error::app_error;
}
return channel_error::malformed;
}
autorelease_target::~autorelease_target() {
release();
}
}// namespace pn532::helper
#endif//PN532_SCAN_HELPER_HPP