Program Listing for File data.hpp

Return to documentation for file (libspookyaction/include/pn532/data.hpp)

//
// Created by Pietro Saccardi on 22/12/2020.
//

#ifndef PN532_DATA_HPP
#define PN532_DATA_HPP

#include <mlab/bin_data.hpp>
#include <mlab/result.hpp>
#include <pn532/bits.hpp>
#include <pn532/log.h>
#include <pn532/msg.hpp>

namespace pn532 {
    using target_kbps106_typea = target<baudrate_modulation::kbps106_iso_iec_14443_typea>;
    using target_kbps212_felica = target<baudrate_modulation::kbps212_felica>;
    using target_kbps424_felica = target<baudrate_modulation::kbps424_felica>;
    using target_kbps106_typeb = target<baudrate_modulation::kbps106_iso_iec_14443_3_typeb>;
    using target_kbps106_jewel_tag = target<baudrate_modulation::kbps106_innovision_jewel_tag>;

    struct infty_t {
    };

    static constexpr infty_t infty{};

    template <class Integral>
    struct with_inf {
        static_assert(std::is_integral_v<Integral> and not std::is_same_v<Integral, bool>);
        Integral v = Integral{};

        with_inf() = default;

        inline with_inf(infty_t) : v{std::numeric_limits<Integral>::max()} {}

        inline with_inf(Integral n) : v{n} {}

        with_inf(bool) = delete;

        inline operator Integral() const { return v; }

        inline with_inf &operator=(infty_t) {
            v = std::numeric_limits<Integral>::max();
            return *this;
        }

        inline bool operator==(infty_t) const { return v == std::numeric_limits<Integral>::max(); }
        inline bool operator!=(infty_t) const { return v != std::numeric_limits<Integral>::max(); }
    };

    using infbyte = with_inf<std::uint8_t>;

    template <target_type Type>
    struct poll_target : public target<baudrate_modulation_of(Type)> {
    };

    struct poll_target_with_atr {
        atr_res_info atr_info;
    };

    template <baudrate_modulation BrMd>
    struct poll_target_dep_passive : public target<BrMd>, public poll_target_with_atr {
    };

    template <>
    struct poll_target<target_type::dep_passive_106kbps> : public poll_target_dep_passive<
                                                                   baudrate_modulation_of(target_type::dep_passive_106kbps)> {
    };

    template <>
    struct poll_target<target_type::dep_passive_212kbps> : public poll_target_dep_passive<
                                                                   baudrate_modulation_of(target_type::dep_passive_212kbps)> {
    };

    template <>
    struct poll_target<target_type::dep_passive_424kbps> : public poll_target_dep_passive<
                                                                   baudrate_modulation_of(target_type::dep_passive_424kbps)> {
    };

    template <>
    struct poll_target<target_type::dep_active_106kbps> : public poll_target_with_atr {
    };

    template <>
    struct poll_target<target_type::dep_active_212kbps> : public poll_target_with_atr {
    };

    template <>
    struct poll_target<target_type::dep_active_424kbps> : public poll_target_with_atr {
    };

    class any_poll_target : public mlab::any_of<target_type, poll_target> {
    public:
        using mlab::any_of<target_type, poll_target>::any_of;
        explicit any_poll_target(enum_type) = delete;
    };

    enum struct gpio_port {
        p3,
        p7,
        i0i1
    };

    struct firmware_version {
        std::uint8_t ic;
        std::uint8_t version;
        std::uint8_t revision;
        bool iso_18092;
        bool iso_iec_14443_typea;
        bool iso_iec_14443_typeb;
    };

    struct rf_status {
        bool nad_present;
        bool expect_more_info;
        internal_error_code error;

        inline explicit operator bool() const;
    };

    struct parameters {
        bool use_nad_data;
        bool use_did_data;
        bool auto_generate_atr_res;
        bool auto_generate_rats;
        bool enable_iso_14443_4_picc_emulation;
        bool remove_pre_post_amble;
    };

    struct general_status_target {
        std::uint8_t logical_index;
        baudrate baudrate_rx;
        baudrate baudrate_tx;
        modulation modulation_type;
    };

    struct general_status_sam {
        bool neg_pulse_on_clad_line;
        bool detected_rf_field_off;
        bool timeout_after_sig_act_irq;
        bool clad_line_high;
    };
    struct general_status {
        internal_error_code last_error;
        bool rf_field_present;
        std::vector<general_status_target> targets;
        general_status_sam sam;
    };

    struct status_as_target {
        nfcip1_picc_status status;
        baudrate initiator_speed;
        baudrate target_speed;
    };

    struct jump_dep_psl {
        rf_status status{};
        std::uint8_t target_logical_index{};
        atr_res_info atr_info;
    };

    struct mifare_params {
        std::array<std::uint8_t, 2> sens_res;
        std::array<std::uint8_t, 3> nfcid_1t;
        std::uint8_t sel_res;
    };

    struct felica_params {
        std::array<std::uint8_t, 8> nfcid_2t;
        std::array<std::uint8_t, 8> pad;
        std::array<std::uint8_t, 2> syst_code;
    };

    struct activation_as_target_mode {
        baudrate speed;
        bool iso_iec_14443_4_picc;
        bool dep;
        framing_as_target framing_type;
    };

    struct activation_as_target {
        activation_as_target_mode mode;
        std::vector<std::uint8_t> initiator_command;
    };

    class gpio_status {
    private:
        std::uint8_t _p3_mask = 0x00;
        std::uint8_t _p7_mask = 0x00;
        std::uint8_t _i0i1_mask = 0x00;

    public:
        gpio_status() = default;

        inline gpio_status(std::uint8_t p3_mask, std::uint8_t p7_mask, std::uint8_t i0i1_mask);

        [[nodiscard]] inline std::uint8_t mask(gpio_port loc) const;

        inline void set_mask(gpio_port loc, std::uint8_t mask);

        [[nodiscard]] inline bool operator[](std::pair<gpio_port, std::uint8_t> const &gpio_idx) const;

        inline mlab::bit_ref operator[](std::pair<gpio_port, std::uint8_t> const &gpio_idx);
    };
}// namespace pn532

namespace mlab {
#ifndef DOXYGEN_SHOULD_SKIP_THIS
    bin_data &operator<<(bin_data &bd, pn532::reg::ciu_212_424kbps const &reg);

    bin_data &operator<<(bin_data &bd, pn532::reg::ciu_106kbps_typea const &reg);

    bin_data &operator<<(bin_data &bd, pn532::reg::ciu_typeb const &reg);

    bin_data &operator<<(bin_data &bd, pn532::reg::ciu_iso_iec_14443_4_at_baudrate const &reg);

    bin_data &operator<<(bin_data &bd, pn532::reg::ciu_iso_iec_14443_4 const &reg);

    bin_data &operator<<(bin_data &bd, pn532::nfcid_2t const &uid);

    bin_data &operator<<(bin_data &bd, pn532::nfcid_3t const &uid);

    bin_data &operator<<(bin_data &bd, pn532::bits::reg_antenna_detector const &r);

    bin_data &operator<<(bin_data &s, pn532::parameters const &p);

    bin_data &operator<<(bin_data &s, std::vector<pn532::wakeup_source> const &vws);

    bin_data &operator<<(bin_data &s, pn532::mifare_params const &p);

    bin_data &operator<<(bin_data &s, pn532::felica_params const &p);

    template <pn532::baudrate_modulation BrMd>
    bin_stream &operator>>(bin_stream &s, std::vector<pn532::target<BrMd>> &targets);

    bin_stream &operator>>(bin_stream &s, pn532::poll_target<pn532::target_type::dep_passive_106kbps> &entry);

    template <pn532::target_type Type>
    bin_stream &operator>>(bin_stream &s, pn532::poll_target<Type> &entry);

    bin_stream &operator>>(bin_stream &s, pn532::any_poll_target &t);

    bin_stream &operator>>(bin_stream &s, std::vector<pn532::any_poll_target> &targets);

    bin_stream &operator>>(bin_stream &s, std::pair<pn532::rf_status, bin_data> &status_data_pair);

    bin_stream &operator>>(bin_stream &s, pn532::rf_status &status);

    bin_stream &operator>>(bin_stream &s, pn532::gpio_status &gpio);

    bin_stream &operator>>(bin_stream &s, pn532::firmware_version &fw);

    bin_stream &operator>>(bin_stream &s, pn532::general_status &gs);

    bin_stream &operator>>(bin_stream &s, pn532::general_status_target &ts);

    bin_stream &operator>>(bin_stream &s, pn532::target_kbps106_typea &target);

    bin_stream &operator>>(bin_stream &s, pn532::target_kbps212_felica &target);

    bin_stream &operator>>(bin_stream &s, pn532::target_kbps424_felica &target);

    bin_stream &operator>>(bin_stream &s, pn532::target_kbps106_typeb &target);

    bin_stream &operator>>(bin_stream &s, pn532::target_kbps106_jewel_tag &target);

    bin_stream &operator>>(bin_stream &s, pn532::atr_res_info &atr_res);

    bin_stream &operator>>(bin_stream &s, std::pair<pn532::rf_status, pn532::atr_res_info> &status_atr_res);

    bin_stream &operator>>(bin_stream &s, pn532::bits::reg_antenna_detector &r);

    bin_stream &operator>>(bin_stream &s, pn532::jump_dep_psl &r);

    bin_stream &operator>>(bin_stream &s, pn532::general_status_sam &sams);

    bin_stream &operator>>(bin_stream &s, pn532::status_as_target &st);

    bin_stream &operator>>(bin_stream &s, pn532::activation_as_target_mode &mt);

    bin_stream &operator>>(bin_stream &s, pn532::activation_as_target &mt);
#endif
}// namespace mlab

namespace pn532 {

    rf_status::operator bool() const {
        return error == internal_error_code::none;
    }

    bool gpio_status::operator[](std::pair<gpio_port, std::uint8_t> const &gpio_idx) const {
        switch (gpio_idx.first) {
            case gpio_port::p3:
                return 0 != (_p3_mask & (1 << gpio_idx.second));
            case gpio_port::p7:
                return 0 != (_p7_mask & (1 << gpio_idx.second));
            case gpio_port::i0i1:
                return 0 != (_i0i1_mask & (1 << gpio_idx.second));
        }
    }

    mlab::bit_ref gpio_status::operator[](std::pair<gpio_port, std::uint8_t> const &gpio_idx) {
        static std::uint8_t _garbage = 0x00;
        switch (gpio_idx.first) {
            case gpio_port::p3:
                return mlab::bit_ref{_p3_mask, gpio_idx.second, bits::gpio_p3_pin_mask};
            case gpio_port::p7:
                return mlab::bit_ref{_p7_mask, gpio_idx.second, bits::gpio_p7_pin_mask};
            case gpio_port::i0i1:
                return mlab::bit_ref{_i0i1_mask, gpio_idx.second, bits::gpio_i0i1_pin_mask};
        }
        return mlab::bit_ref{_garbage, gpio_idx.second, 0xff};
    }

    gpio_status::gpio_status(std::uint8_t p3_mask, std::uint8_t p7_mask, std::uint8_t i0i1_mask) : _p3_mask{p3_mask}, _p7_mask{p7_mask}, _i0i1_mask{i0i1_mask} {}

    inline std::uint8_t gpio_status::mask(gpio_port loc) const {
        switch (loc) {
            case gpio_port::p3:
                return _p3_mask;
            case gpio_port::p7:
                return _p7_mask;
            case gpio_port::i0i1:
                return _i0i1_mask;
        }
        return 0x00;
    }

    void gpio_status::set_mask(gpio_port loc, std::uint8_t mask) {
        switch (loc) {
            case gpio_port::p3:
                _p3_mask = mask & bits::gpio_p3_pin_mask;
                break;
            case gpio_port::p7:
                _p7_mask = mask & bits::gpio_p7_pin_mask;
                break;
            case gpio_port::i0i1:
                _i0i1_mask = mask & bits::gpio_i0i1_pin_mask;
                break;
        }
    }

}// namespace pn532

namespace mlab {
    template <pn532::baudrate_modulation BrMd>
    bin_stream &operator>>(bin_stream &s, std::vector<pn532::target<BrMd>> &targets) {
        if (s.remaining() < 1) {
            PN532_LOGE("Parsing vector<target<%s>>: not enough data.", pn532::to_string(BrMd));
            s.set_bad();
            return s;
        }
        const auto num_targets = s.pop();
        if (num_targets > pn532::bits::max_num_targets) {
            PN532_LOGW("Parsing vector<target<%s>>: found %u targets, which is more than the number of supported targets %u.",
                       pn532::to_string(BrMd), num_targets, pn532::bits::max_num_targets);
        }
        targets.resize(num_targets);
        for (auto &target : targets) {
            if (not s.good()) {
                break;
            }
            s >> target;
        }
        return s;
    }

    template <pn532::target_type Type>
    bin_stream &operator>>(bin_stream &s, pn532::poll_target<Type> &entry) {
        static constexpr pn532::baudrate_modulation BrMod = pn532::baudrate_modulation_of(Type);
        if constexpr (std::is_base_of_v<pn532::target<BrMod>, pn532::poll_target<Type>>) {
            s >> static_cast<pn532::target<BrMod> &>(entry);
        }
        if constexpr (std::is_base_of_v<pn532::poll_target_with_atr, pn532::poll_target<Type>>) {
            s >> static_cast<pn532::poll_target_with_atr &>(entry).atr_info;
        }
        return s;
    }

}// namespace mlab

#endif//PN532_DATA_HPP