Add extracted tools: CitrineOS, OpenOCPP, ShapeShifter
- CitrineOS core extracted (CSMS OCPP 2.0.1) - OpenOCPP extracted (firmware OCPP 1.6J/2.0.1) - ShapeShifter library installed (pip install -e) - ShapeShifter specification extracted - EVerest extracted TODO updated with progress
This commit is contained in:
@@ -0,0 +1,47 @@
|
||||
#
|
||||
# AUTO GENERATED - MARKED REGIONS WILL BE KEPT
|
||||
# template version 3
|
||||
#
|
||||
|
||||
# module setup:
|
||||
# - ${MODULE_NAME}: module name
|
||||
ev_setup_cpp_module()
|
||||
|
||||
# ev@bcc62523-e22b-41d7-ba2f-825b493a3c97:v1
|
||||
|
||||
set(EXTERNAL_NXPNFCRDLIB_ZIP_PATH_${MODULE_NAME} "" CACHE PATH "Set the path to NxpNfcRdLib_Linux_v07.10.00_PUB.zip to enable building the wrapper.")
|
||||
|
||||
target_include_directories(${MODULE_NAME}
|
||||
PRIVATE
|
||||
include/
|
||||
)
|
||||
|
||||
target_link_libraries(${MODULE_NAME}
|
||||
PRIVATE
|
||||
everest::helpers)
|
||||
|
||||
# Use either the named pipe implementation as source, or the real-hardware-interfacing NxpNfcFrontend class
|
||||
|
||||
if(EXTERNAL_NXPNFCRDLIB_ZIP_PATH_${MODULE_NAME} AND EXISTS "${EXTERNAL_NXPNFCRDLIB_ZIP_PATH_${MODULE_NAME}}")
|
||||
set(EXTERNAL_NXPNFCRDLIB_ZIP_PATH "${EXTERNAL_NXPNFCRDLIB_ZIP_PATH_${MODULE_NAME}}")
|
||||
add_subdirectory(nxpnfcrdlib_wrapper)
|
||||
|
||||
target_link_libraries(${MODULE_NAME} PRIVATE NxpNfcFrontend)
|
||||
else()
|
||||
add_library(namedPipeDataSource)
|
||||
target_sources(namedPipeDataSource PRIVATE namedPipeDataSource/namedPipeDataSource.cpp)
|
||||
target_link_libraries(${MODULE_NAME} PRIVATE namedPipeDataSource)
|
||||
target_include_directories(namedPipeDataSource PUBLIC ${CMAKE_CURRENT_LIST_DIR}/namedPipeDataSource/)
|
||||
|
||||
target_compile_definitions(${MODULE_NAME} PRIVATE BUILD_WITH_NAMED_PIPE_DATASOURCE)
|
||||
endif()
|
||||
# ev@bcc62523-e22b-41d7-ba2f-825b493a3c97:v1
|
||||
|
||||
target_sources(${MODULE_NAME}
|
||||
PRIVATE
|
||||
"main/auth_token_providerImpl.cpp"
|
||||
)
|
||||
|
||||
# ev@c55432ab-152c-45a9-9d2e-7281d50c69c3:v1
|
||||
# insert other things like install cmds etc here
|
||||
# ev@c55432ab-152c-45a9-9d2e-7281d50c69c3:v1
|
||||
@@ -0,0 +1,16 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// Copyright 2020 - 2025 Pionix GmbH and Contributors to EVerest
|
||||
|
||||
#include "NxpNfcFrontendTokenProvider.hpp"
|
||||
|
||||
namespace module {
|
||||
|
||||
void NxpNfcFrontendTokenProvider::init() {
|
||||
invoke_init(*p_main);
|
||||
}
|
||||
|
||||
void NxpNfcFrontendTokenProvider::ready() {
|
||||
invoke_ready(*p_main);
|
||||
}
|
||||
|
||||
} // namespace module
|
||||
@@ -0,0 +1,59 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// Copyright 2020 - 2025 Pionix GmbH and Contributors to EVerest
|
||||
#ifndef NXP_NFC_FRONTEND_TOKEN_PROVIDER_HPP
|
||||
#define NXP_NFC_FRONTEND_TOKEN_PROVIDER_HPP
|
||||
|
||||
//
|
||||
// AUTO GENERATED - MARKED REGIONS WILL BE KEPT
|
||||
// template version 2
|
||||
//
|
||||
|
||||
#include "ld-ev.hpp"
|
||||
|
||||
// headers for provided interface implementations
|
||||
#include <generated/interfaces/auth_token_provider/Implementation.hpp>
|
||||
|
||||
// ev@4bf81b14-a215-475c-a1d3-0a484ae48918:v1
|
||||
// insert your custom include headers here
|
||||
// ev@4bf81b14-a215-475c-a1d3-0a484ae48918:v1
|
||||
|
||||
namespace module {
|
||||
|
||||
struct Conf {};
|
||||
|
||||
class NxpNfcFrontendTokenProvider : public Everest::ModuleBase {
|
||||
public:
|
||||
NxpNfcFrontendTokenProvider() = delete;
|
||||
NxpNfcFrontendTokenProvider(const ModuleInfo& info, std::unique_ptr<auth_token_providerImplBase> p_main,
|
||||
Conf& config) :
|
||||
ModuleBase(info), p_main(std::move(p_main)), config(config){};
|
||||
|
||||
const std::unique_ptr<auth_token_providerImplBase> p_main;
|
||||
const Conf& config;
|
||||
|
||||
// ev@1fce4c5e-0ab8-41bb-90f7-14277703d2ac:v1
|
||||
// insert your public definitions here
|
||||
// ev@1fce4c5e-0ab8-41bb-90f7-14277703d2ac:v1
|
||||
|
||||
protected:
|
||||
// ev@4714b2ab-a24f-4b95-ab81-36439e1478de:v1
|
||||
// insert your protected definitions here
|
||||
// ev@4714b2ab-a24f-4b95-ab81-36439e1478de:v1
|
||||
|
||||
private:
|
||||
friend class LdEverest;
|
||||
void init();
|
||||
void ready();
|
||||
|
||||
// ev@211cfdbe-f69a-4cd6-a4ec-f8aaa3d1b6c8:v1
|
||||
// insert your private definitions here
|
||||
// ev@211cfdbe-f69a-4cd6-a4ec-f8aaa3d1b6c8:v1
|
||||
};
|
||||
|
||||
// ev@087e516b-124c-48df-94fb-109508c7cda9:v1
|
||||
// insert other definitions here
|
||||
// ev@087e516b-124c-48df-94fb-109508c7cda9:v1
|
||||
|
||||
} // namespace module
|
||||
|
||||
#endif // NXP_NFC_FRONTEND_TOKEN_PROVIDER_HPP
|
||||
@@ -0,0 +1,82 @@
|
||||
.. _everest_modules_handwritten_NxpNfcFrontendTokenProvider:
|
||||
|
||||
.. ***************************
|
||||
.. NxpNfcFrontendTokenProvider
|
||||
.. ***************************
|
||||
|
||||
The module ``NxpNfcFrontendTokenProvider`` implements the ``auth_token_provider`` interface.
|
||||
It reads data from NXP NFC frontend chips like CLRC663.
|
||||
It relies on **NxpNfcRdLib_Linux_v07.10.00_PUB.zip** which users need to obtain from NXP: `nxp.com <https://www.nxp.com/design/design-center/development-boards-and-designs/nfc-reader-library-software-support-for-nfc-frontend-solutions:NFC-READER-LIBRARY>`_.
|
||||
The variety of hardware supported by ``NxpNfcFrontendTokenProvider`` is limited at the time of writing but could be extended by modification of the ``nxpnfcrdlib_wrapper``.
|
||||
|
||||
Building the module
|
||||
===================
|
||||
The module can be built in two ways:
|
||||
|
||||
* Setting *CMake* variable ``EXTERNAL_NXPNFCRDLIB_ZIP_PATH_NxpNfcFrontendTokenProvider`` to the path to ``NxpNfcRdLib_Linux_v07.10.00_PUB.zip``.
|
||||
* Leaving this option undefined uses the included ``NamedPipeDataSource`` which acts as a drop-in replacement without any external build dependencies but does not support real NFC hardware.
|
||||
|
||||
To enable users who do not use NxpNfcFrontend to build EVerest without having to explicitly set variables or options, the variable is undefined by default.
|
||||
|
||||
NamedPipeDataSource
|
||||
-------------------
|
||||
|
||||
Cannot interface real NFC hardware.
|
||||
During runtime it creates a named pipe (FIFO) at ``/tmp/EV_NXP_NFC_FRONTEND_TOKEN_PROVIDER_FIFO_SUBSTITUTE`` and tries to read from it.
|
||||
As soon, as it can read a ``\n``-terminated line, it tries to parse it as ``<protocol>:<uid>`` (see examples below).
|
||||
|
||||
Configuring the module
|
||||
======================
|
||||
|
||||
Runtime configuration allows to
|
||||
|
||||
* *token_debounce_interval_ms*: select a minimum intervall between publishes
|
||||
|
||||
See ``manifest.yaml`` for details.
|
||||
|
||||
Testing the module
|
||||
==================
|
||||
|
||||
The module does not implement any commands.
|
||||
|
||||
Using NamedPipeDataSource
|
||||
-------------------------
|
||||
|
||||
Possible input for ISO14443 (MIFARE card) emulation:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
echo "ISO14443:44332211" > /tmp/EV_NXP_NFC_FRONTEND_TOKEN_PROVIDER_FIFO_SUBSTITUTE
|
||||
|
||||
Possible input for ISO15693 (Vicinity card) emulation:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
echo "ISO15693:8877665544332211" > /tmp/EV_NXP_NFC_FRONTEND_TOKEN_PROVIDER_FIFO_SUBSTITUTE
|
||||
|
||||
It publishes an ``types::authorization::ProvidedIdToken`` to the topic ``everest/tokenprovider/main/var``.
|
||||
|
||||
It publishes whenever the NFC chip is able to detect a RFID card of the supported types.
|
||||
|
||||
``Published JSON:``
|
||||
|
||||
.. code-block:: JSON
|
||||
|
||||
{
|
||||
"data": {
|
||||
"authorization_type" : "RFID",
|
||||
"id_token" : {
|
||||
"type" : "ISO14443",
|
||||
"value" : "74F2EF5B"
|
||||
}
|
||||
},
|
||||
"name" : "provided_token"
|
||||
}
|
||||
|
||||
|
||||
Using NxpNfcFrontendWrapper
|
||||
---------------------------
|
||||
|
||||
Requires NFC hardware from NXP.
|
||||
A hardware setup similar to the one shown in the ``nxpnfcrdlib_wrapper`` documentation can be used.
|
||||
Detection of an RFID card of the supported type will trigger publishing of a ``types::authorization::ProvidedIdToken``.
|
||||
@@ -0,0 +1,76 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// Copyright 2020 - 2025 Pionix GmbH and Contributors to EVerest
|
||||
|
||||
#include "auth_token_providerImpl.hpp"
|
||||
|
||||
#include <everest/helpers/helpers.hpp>
|
||||
|
||||
#include <iomanip>
|
||||
#include <sstream>
|
||||
|
||||
namespace module {
|
||||
namespace main {
|
||||
|
||||
static std::string nfcidToString(const std::vector<std::uint8_t>& nfcid) {
|
||||
std::ostringstream oss;
|
||||
|
||||
for (std::uint16_t byte : nfcid) {
|
||||
oss << std::setfill('0') << std::setw(2) << std::uppercase << std::hex << byte;
|
||||
}
|
||||
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
void auth_token_providerImpl::detected_rfid_token_callback(
|
||||
const std::pair<std::string, std::vector<std::uint8_t>>& reply) {
|
||||
auto& [protocol, nfcid] = reply;
|
||||
|
||||
const auto now = std::chrono::steady_clock::now();
|
||||
const auto debounce_interval = std::chrono::milliseconds(config.token_debounce_interval_ms);
|
||||
|
||||
types::authorization::ProvidedIdToken provided_token;
|
||||
|
||||
try {
|
||||
provided_token.id_token = {nfcidToString(nfcid), types::authorization::string_to_id_token_type(protocol)};
|
||||
} catch (const std::out_of_range& e) {
|
||||
return;
|
||||
}
|
||||
|
||||
provided_token.authorization_type = types::authorization::AuthorizationType::RFID;
|
||||
|
||||
if (now < last_rfid_submit + debounce_interval) {
|
||||
EVLOG_debug << "Ignoring rfid/nfc token (debouncing): " << protocol << ": "
|
||||
<< everest::helpers::redact(provided_token);
|
||||
return;
|
||||
}
|
||||
|
||||
EVLOG_debug << "Publishing new rfid/nfc token: " << protocol << ": " << everest::helpers::redact(provided_token);
|
||||
|
||||
publish_provided_token(provided_token);
|
||||
last_rfid_submit = now;
|
||||
}
|
||||
|
||||
void auth_token_providerImpl::error_log_callback(const std::string& message) {
|
||||
EVLOG_warning << "NxpNfcFrontend: " << message;
|
||||
}
|
||||
|
||||
void auth_token_providerImpl::init() {
|
||||
try {
|
||||
nxpNfcFrontend = std::make_unique<NxpNfcFrontendDataSource>();
|
||||
} catch (const std::exception& e) {
|
||||
EVLOG_error << "Failed to initialize NxpNfcFrontend: " << e.what();
|
||||
}
|
||||
nxpNfcFrontend->setDetectionCallback(
|
||||
[this](auto&&... args) { this->detected_rfid_token_callback(std::forward<decltype(args)>(args)...); });
|
||||
nxpNfcFrontend->setErrorLogCallback(
|
||||
[this](auto&&... args) { this->error_log_callback(std::forward<decltype(args)>(args)...); });
|
||||
}
|
||||
|
||||
void auth_token_providerImpl::ready() {
|
||||
if (nxpNfcFrontend) {
|
||||
nxpNfcFrontend->run();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace main
|
||||
} // namespace module
|
||||
@@ -0,0 +1,81 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// Copyright 2020 - 2025 Pionix GmbH and Contributors to EVerest
|
||||
#ifndef MAIN_AUTH_TOKEN_PROVIDER_IMPL_HPP
|
||||
#define MAIN_AUTH_TOKEN_PROVIDER_IMPL_HPP
|
||||
|
||||
//
|
||||
// AUTO GENERATED - MARKED REGIONS WILL BE KEPT
|
||||
// template version 3
|
||||
//
|
||||
|
||||
#include <generated/interfaces/auth_token_provider/Implementation.hpp>
|
||||
|
||||
#include "../NxpNfcFrontendTokenProvider.hpp"
|
||||
|
||||
// ev@75ac1216-19eb-4182-a85c-820f1fc2c091:v1
|
||||
// insert your custom include headers here
|
||||
#include <atomic>
|
||||
#include <chrono>
|
||||
#include <memory>
|
||||
|
||||
#ifndef BUILD_WITH_NAMED_PIPE_DATASOURCE
|
||||
#include <nxpnfcfrontend.hpp>
|
||||
using NxpNfcFrontendDataSource = NxpNfcFrontendWrapper::NxpNfcFrontend;
|
||||
#endif // BUILD_WITH_NAMED_PIPE_DATASOURCE
|
||||
|
||||
#ifdef BUILD_WITH_NAMED_PIPE_DATASOURCE
|
||||
#include <namedPipeDataSource.hpp>
|
||||
using NxpNfcFrontendDataSource = NamedPipeDataSource;
|
||||
#endif // BUILD_WITH_NAMED_PIPE_DATASOURCE
|
||||
// ev@75ac1216-19eb-4182-a85c-820f1fc2c091:v1
|
||||
|
||||
namespace module {
|
||||
namespace main {
|
||||
|
||||
struct Conf {
|
||||
int token_debounce_interval_ms;
|
||||
};
|
||||
|
||||
class auth_token_providerImpl : public auth_token_providerImplBase {
|
||||
public:
|
||||
auth_token_providerImpl() = delete;
|
||||
auth_token_providerImpl(Everest::ModuleAdapter* ev, const Everest::PtrContainer<NxpNfcFrontendTokenProvider>& mod,
|
||||
Conf& config) :
|
||||
auth_token_providerImplBase(ev, "main"), mod(mod), config(config){};
|
||||
|
||||
// ev@8ea32d28-373f-4c90-ae5e-b4fcc74e2a61:v1
|
||||
// insert your public definitions here
|
||||
// ev@8ea32d28-373f-4c90-ae5e-b4fcc74e2a61:v1
|
||||
|
||||
protected:
|
||||
// no commands defined for this interface
|
||||
|
||||
// ev@d2d1847a-7b88-41dd-ad07-92785f06f5c4:v1
|
||||
// insert your protected definitions here
|
||||
// ev@d2d1847a-7b88-41dd-ad07-92785f06f5c4:v1
|
||||
|
||||
private:
|
||||
const Everest::PtrContainer<NxpNfcFrontendTokenProvider>& mod;
|
||||
const Conf& config;
|
||||
|
||||
virtual void init() override;
|
||||
virtual void ready() override;
|
||||
|
||||
// ev@3370e4dd-95f4-47a9-aaec-ea76f34a66c9:v1
|
||||
// insert your private definitions here
|
||||
void detected_rfid_token_callback(const std::pair<std::string, std::vector<std::uint8_t>>&);
|
||||
void error_log_callback(const std::string&);
|
||||
|
||||
std::unique_ptr<NxpNfcFrontendDataSource> nxpNfcFrontend;
|
||||
std::chrono::steady_clock::time_point last_rfid_submit{};
|
||||
// ev@3370e4dd-95f4-47a9-aaec-ea76f34a66c9:v1
|
||||
};
|
||||
|
||||
// ev@3d7da0ad-02c2-493d-9920-0bbbd56b9876:v1
|
||||
// insert other definitions here
|
||||
// ev@3d7da0ad-02c2-493d-9920-0bbbd56b9876:v1
|
||||
|
||||
} // namespace main
|
||||
} // namespace module
|
||||
|
||||
#endif // MAIN_AUTH_TOKEN_PROVIDER_IMPL_HPP
|
||||
@@ -0,0 +1,18 @@
|
||||
description: NXP NFC Reader Library token provider returning the token as soon as the tag can be read by the reader
|
||||
provides:
|
||||
main:
|
||||
description: Implementation of NXP NFC Reader Library based token provider
|
||||
interface: auth_token_provider
|
||||
config:
|
||||
token_debounce_interval_ms:
|
||||
description: Minimal wait time in ms until next token will be published (debounce interval).
|
||||
type: integer
|
||||
default: 2000
|
||||
minimum: 500
|
||||
maximum: 10000
|
||||
metadata:
|
||||
license: https://opensource.org/licenses/Apache-2.0
|
||||
authors:
|
||||
- Christoph Burandt
|
||||
- Cornelius Claussen
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
# This is a standalone file, to compile the namedPipeTokenProvider as standalone executable
|
||||
|
||||
cmake_minimum_required(VERSION 3.15)
|
||||
|
||||
project(testNamedPipeDataSource)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED True)
|
||||
|
||||
add_library(namedPipeDataSource)
|
||||
target_sources(namedPipeDataSource PRIVATE namedPipeDataSource.cpp)
|
||||
target_include_directories(namedPipeDataSource PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
@@ -0,0 +1,216 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// Copyright 2020 - 2025 Pionix GmbH and Contributors to EVerest
|
||||
|
||||
#include "namedPipeDataSource.hpp"
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
#include <fcntl.h>
|
||||
#include <filesystem>
|
||||
#include <stdexcept>
|
||||
#include <string_view>
|
||||
#include <sys/epoll.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
namespace {
|
||||
static bool createdFifo = false;
|
||||
|
||||
constexpr mode_t fifo_permissions = 0666;
|
||||
|
||||
bool isHexCoded(const std::string& input) {
|
||||
return std::all_of(input.begin(), input.end(), [](unsigned char byte) { return std::isxdigit(byte); });
|
||||
}
|
||||
|
||||
void createFifoFile(const std::string& pathToNamedPipe) {
|
||||
const std::filesystem::path path = {pathToNamedPipe};
|
||||
if (not std::filesystem::is_fifo(path)) {
|
||||
if (std::filesystem::exists(path)) {
|
||||
throw std::runtime_error("Could not create FIFO at '" + path.string() + "': file exists as non-FIFO");
|
||||
}
|
||||
// Create FIFO:
|
||||
const int ret = mkfifo(pathToNamedPipe.c_str(), fifo_permissions);
|
||||
if (ret == -1) {
|
||||
throw std::runtime_error("Could not create FIFO at '" + path.string() + "': mkfifo returned '-1'");
|
||||
}
|
||||
createdFifo = true;
|
||||
}
|
||||
}
|
||||
|
||||
class FilePoller {
|
||||
public:
|
||||
explicit FilePoller(const std::string_view& filename) : m_filename(filename) {
|
||||
openFileAndConfigureEpoll();
|
||||
}
|
||||
|
||||
FilePoller(const FilePoller&) = delete;
|
||||
FilePoller(const FilePoller&&) = delete;
|
||||
FilePoller operator=(const FilePoller&) = delete;
|
||||
FilePoller operator=(const FilePoller&&) = delete;
|
||||
|
||||
~FilePoller() {
|
||||
closeFileAndEpoll();
|
||||
}
|
||||
|
||||
std::string wait(int timeout_ms) {
|
||||
std::array<struct epoll_event, EVENT_BUFFER_SIZE> m_epoll_event_buffer{};
|
||||
const int eventCount = epoll_wait(m_epoll_list_fd, m_epoll_event_buffer.data(), EVENT_BUFFER_SIZE, timeout_ms);
|
||||
std::string partialLine;
|
||||
if (eventCount > 0) {
|
||||
std::array<char, READ_BUFFER_SIZE> buffer{};
|
||||
|
||||
for (int i = 0; i < eventCount; i++) {
|
||||
if ((m_epoll_event_buffer.at(i).events & EPOLLIN) != 0) {
|
||||
const struct epoll_event& event = m_epoll_event_buffer.at(i);
|
||||
const std::size_t readCount = read(event.data.fd, buffer.data(), READ_BUFFER_SIZE - 1);
|
||||
buffer.at(readCount) = '\0';
|
||||
partialLine.append(buffer.data());
|
||||
}
|
||||
}
|
||||
// After treating EPOLLIN (input) events, look for EPOLLHUP (Hang-up) events
|
||||
// If the exist, reopen file and reconfigure EPoll,
|
||||
// otherwise, HUP will happen forever and use the full CPU
|
||||
for (int i = 0; i < eventCount; i++) {
|
||||
if ((m_epoll_event_buffer.at(i).events & EPOLLHUP) != 0) {
|
||||
reOpenFileAndConfigureEpoll();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return partialLine;
|
||||
}
|
||||
|
||||
private:
|
||||
void openFileAndConfigureEpoll() {
|
||||
m_fifo_fd = open(m_filename.c_str(), O_RDONLY | O_NONBLOCK);
|
||||
|
||||
m_epoll_list_fd = epoll_create1(EPOLL_CLOEXEC);
|
||||
struct epoll_event m_epoll_event = {};
|
||||
m_epoll_event.events = EPOLLIN;
|
||||
m_epoll_event.data.fd = m_fifo_fd;
|
||||
|
||||
epoll_ctl(m_epoll_list_fd, EPOLL_CTL_ADD, m_fifo_fd, &m_epoll_event);
|
||||
}
|
||||
|
||||
void reOpenFileAndConfigureEpoll() {
|
||||
closeFileAndEpoll();
|
||||
openFileAndConfigureEpoll();
|
||||
}
|
||||
|
||||
void closeFileAndEpoll() const {
|
||||
close(m_epoll_list_fd);
|
||||
close(m_fifo_fd);
|
||||
}
|
||||
|
||||
std::string m_filename;
|
||||
int m_fifo_fd{0};
|
||||
int m_epoll_list_fd{0};
|
||||
|
||||
static const std::size_t READ_BUFFER_SIZE = 64;
|
||||
static const std::size_t EVENT_BUFFER_SIZE = 16;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
NamedPipeDataSource::NamedPipeDataSource(const std::string& filename) : m_filename(filename) {
|
||||
createFifoFile(filename);
|
||||
}
|
||||
|
||||
NamedPipeDataSource::NamedPipeDataSource() :
|
||||
NamedPipeDataSource("/tmp/EV_NXP_NFC_FRONTEND_TOKEN_PROVIDER_FIFO_SUBSTITUTE") {
|
||||
}
|
||||
|
||||
NamedPipeDataSource::~NamedPipeDataSource() {
|
||||
stopped = true;
|
||||
|
||||
m_line_reader->join();
|
||||
|
||||
if (createdFifo) {
|
||||
std::remove(m_filename.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
void NamedPipeDataSource::setDetectionCallback(
|
||||
const std::function<void(const std::pair<std::string, std::vector<std::uint8_t>>&)>& callback) {
|
||||
m_callback = callback;
|
||||
}
|
||||
|
||||
void NamedPipeDataSource::setErrorLogCallback(const std::function<void(const std::string&)>& callback) {
|
||||
m_err_callback = callback;
|
||||
}
|
||||
|
||||
void NamedPipeDataSource::run() {
|
||||
m_line_reader = std::make_unique<std::thread>(&NamedPipeDataSource::getLinesForever, this);
|
||||
}
|
||||
|
||||
void NamedPipeDataSource::getLinesForever() {
|
||||
constexpr int wait_timeout_ms = 1000;
|
||||
constexpr std::size_t max_line_length = 128;
|
||||
std::string line{};
|
||||
FilePoller poller(m_filename);
|
||||
|
||||
while (not stopped) {
|
||||
const std::string partialLine = poller.wait(wait_timeout_ms);
|
||||
|
||||
if (not partialLine.empty()) {
|
||||
line.append(partialLine);
|
||||
|
||||
const std::size_t cr_pos = line.find('\n');
|
||||
if (cr_pos != std::string::npos) {
|
||||
if (auto result = parseInput(line)) {
|
||||
m_callback(*result);
|
||||
} else {
|
||||
m_err_callback("Could not parse '" + line + "'");
|
||||
}
|
||||
|
||||
line.clear();
|
||||
} else {
|
||||
if (line.size() > max_line_length) {
|
||||
line.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::optional<std::pair<std::string, std::vector<std::uint8_t>>>
|
||||
NamedPipeDataSource::parseInput(const std::string& input) {
|
||||
constexpr std::size_t protocol_designator_len = 8;
|
||||
constexpr std::size_t iso14443_uid_len = 8;
|
||||
constexpr std::size_t iso15693_uid_len = 16;
|
||||
|
||||
if (input.size() < protocol_designator_len + 1) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
const std::string protocol = input.substr(0, protocol_designator_len);
|
||||
|
||||
std::size_t expectedUidSize{0};
|
||||
if (protocol == "ISO14443") {
|
||||
expectedUidSize = iso14443_uid_len;
|
||||
} else if (protocol == "ISO15693") {
|
||||
expectedUidSize = iso15693_uid_len;
|
||||
} else {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
// "+2" accounts for the ':' and '\n'
|
||||
const std::size_t expectedStringSize = protocol_designator_len + expectedUidSize + 2;
|
||||
|
||||
if (input.size() != expectedStringSize) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
const std::string uid_str = input.substr(9, expectedUidSize);
|
||||
if (not isHexCoded(uid_str)) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::vector<std::uint8_t> nfcid;
|
||||
for (std::size_t i = 0; i < uid_str.length(); i += 2) {
|
||||
const std::string single_byte_str = uid_str.substr(i, 2);
|
||||
const std::uint8_t byte = static_cast<std::uint8_t>(std::stoi(single_byte_str, nullptr, 16));
|
||||
nfcid.push_back(byte);
|
||||
}
|
||||
|
||||
return std::make_pair(protocol, nfcid);
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// Copyright 2020 - 2025 Pionix GmbH and Contributors to EVerest
|
||||
|
||||
#ifndef NAMED_PIPE_TOKEN_PROVIDER_IMPL_HPP
|
||||
#define NAMED_PIPE_TOKEN_PROVIDER_IMPL_HPP
|
||||
|
||||
#include <atomic>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
class NamedPipeDataSource {
|
||||
public:
|
||||
NamedPipeDataSource();
|
||||
explicit NamedPipeDataSource(const std::string& filename);
|
||||
NamedPipeDataSource(const NamedPipeDataSource&) = delete;
|
||||
NamedPipeDataSource(const NamedPipeDataSource&&) = delete;
|
||||
NamedPipeDataSource operator=(const NamedPipeDataSource&) = delete;
|
||||
NamedPipeDataSource operator=(const NamedPipeDataSource&&) = delete;
|
||||
~NamedPipeDataSource();
|
||||
|
||||
void setDetectionCallback(const std::function<void(const std::pair<std::string, std::vector<std::uint8_t>>&)>&);
|
||||
void setErrorLogCallback(const std::function<void(const std::string&)>&);
|
||||
void run();
|
||||
|
||||
private:
|
||||
void getLinesForever();
|
||||
std::optional<std::pair<std::string, std::vector<std::uint8_t>>> parseInput(const std::string& input);
|
||||
|
||||
std::string m_filename;
|
||||
|
||||
std::function<void(const std::pair<std::string, std::vector<std::uint8_t>>&)> m_callback;
|
||||
std::function<void(const std::string&)> m_err_callback;
|
||||
|
||||
std::unique_ptr<std::thread> m_line_reader;
|
||||
std::atomic<bool> stopped{false};
|
||||
};
|
||||
|
||||
#endif // NAMED_PIPE_TOKEN_PROVIDER_IMPL_HPP
|
||||
@@ -0,0 +1,55 @@
|
||||
cmake_minimum_required(VERSION 3.15)
|
||||
project(
|
||||
NxpNfcFrontendLib
|
||||
VERSION 07.10.00
|
||||
DESCRIPTION "NXP NFC Frontend Lib"
|
||||
LANGUAGES CXX C
|
||||
)
|
||||
|
||||
find_package(Threads REQUIRED)
|
||||
|
||||
set(EXTRACTION_PATH ${CMAKE_CURRENT_BINARY_DIR}/_deps)
|
||||
set(PATH_NXPNFCRDLIB "${EXTRACTION_PATH}/NxpNfcRdLib_Linux_v07.10.00_PUB/")
|
||||
|
||||
if(EXTERNAL_NXPNFCRDLIB_ZIP_PATH AND EXISTS "${EXTERNAL_NXPNFCRDLIB_ZIP_PATH}")
|
||||
file(ARCHIVE_EXTRACT
|
||||
INPUT
|
||||
"${EXTERNAL_NXPNFCRDLIB_ZIP_PATH}"
|
||||
DESTINATION
|
||||
"${EXTRACTION_PATH}")
|
||||
else()
|
||||
message(FATAL_ERROR "EXTERNAL_NXPNFCRDLIB_ZIP_PATH not set or invalid. Cannot build the NxpNfcFrontendLib wrapper library.")
|
||||
endif()
|
||||
|
||||
if (NOT EXISTS "${PATH_NXPNFCRDLIB}/CMakeLists.txt")
|
||||
message(FATAL_ERROR "Path to NxpNfcRdLib looks empty: Did not find ${PATH_NXPNFCRDLIB}/CMakeLists.txt")
|
||||
endif()
|
||||
|
||||
add_subdirectory(lib)
|
||||
|
||||
add_library(NxpNfcFrontend)
|
||||
target_sources(NxpNfcFrontend
|
||||
PRIVATE
|
||||
src/errorDecoding.cpp
|
||||
src/nxpnfcfrontend.cpp
|
||||
src/NxpNfcRdLibIncludes.hpp
|
||||
src/NxpNfcRdLibIfc.hpp
|
||||
src/NxpNfcRdLibIfc.cpp
|
||||
)
|
||||
target_compile_features(NxpNfcFrontend
|
||||
INTERFACE
|
||||
cxx_std_17
|
||||
)
|
||||
target_include_directories(NxpNfcFrontend
|
||||
PRIVATE
|
||||
src
|
||||
PUBLIC
|
||||
inc
|
||||
)
|
||||
target_link_libraries(NxpNfcFrontend
|
||||
PRIVATE
|
||||
NxpRdLib
|
||||
Threads::Threads
|
||||
)
|
||||
|
||||
add_subdirectory(testApplication)
|
||||
@@ -0,0 +1,118 @@
|
||||
# nxpnfcrdlib_wrapper
|
||||
|
||||
This library provides elementary RFID functionality using NXP's Nfc Reader Library for Nfc frontend chips.
|
||||
These so called frontend chips require tight control from the host controller in order to execute standard conforming NFC communication.
|
||||
The proprietary `NXP Nfc Reader Library` is therefore used.
|
||||
It underlies an EULA and therefore not be shipped with `EVerest`.
|
||||
It needs to be configured at compile-time to match the target device (both Linux host and interfaced NFC chip).
|
||||
|
||||
## Folder Structure
|
||||
|
||||
```
|
||||
nxpnfcrdlib_wrapper
|
||||
├── doc
|
||||
├── inc
|
||||
├── lib/customization
|
||||
├── src
|
||||
├── testApplication
|
||||
├── CMakeLists.txt
|
||||
└── README.md
|
||||
```
|
||||
|
||||
- `doc`: Documentation (graphics)
|
||||
- `inc`: Public include file required be users of ``nxpnfcrdlib_wrapper``
|
||||
- `lib/customization`: Build scripts and suplemental C code for a customized build of the `NXP Nfc Reader Library` within `EVerest`
|
||||
- `src`: C++ code of this module
|
||||
- `testApplication`: Minimal application which shows how to use ``nxpnfcrdlib_wrapper``
|
||||
- `CMakeLists.txt`: Build file
|
||||
- `README.MD`: This file
|
||||
|
||||
## Use
|
||||
|
||||
At this time this code only works for **RC663** NFC Frontend Chips.
|
||||
It could be extended to support different chips (**PN51[8,9]0**).
|
||||
|
||||
### Building
|
||||
|
||||
1. Setup environment for EVerest as usual
|
||||
2. Get **NxpNfcRdLib_Linux_v07.10.00_PUB.zip** from [nxp.com](https://www.nxp.com/design/design-center/development-boards-and-designs/nfc-reader-library-software-support-for-nfc-frontend-solutions:NFC-READER-LIBRARY)
|
||||
3. Store zip file at arbitrary location
|
||||
4. Provide this location to your EVerest build at configuration time: ``-DEXTERNAL_NXPNFCRDLIB_ZIP_PATH_NxpNfcFrontendTokenProvider=/<path>/<to>/<your>/NxpNfcRdLib_Linux_v07.10.00_PUB.zip``
|
||||
5. EVerest will automatically choose to include these sources into the build of the ``NxpNfcFrontendTokenProvider``
|
||||
|
||||
### Example
|
||||
|
||||
```
|
||||
git clone git@github.com:EVerest/EVerest.git
|
||||
# download NxpNfcRdLib_Linux_v07.10.00_PUB.zip
|
||||
mkdir build
|
||||
cmake -S EVerest -B build -DEXTERNAL_NXPNFCRDLIB_ZIP_PATH_NxpNfcFrontendTokenProvider=/<path>/<to>/<your>/NxpNfcRdLib_Linux_v07.10.00_PUB.zip
|
||||
cmake --build build --parallel -j
|
||||
cmake --install build/
|
||||
```
|
||||
|
||||
The use with different boards/chips requires customization **before** compilation (see below)!
|
||||
|
||||
## Customization
|
||||
|
||||
The code delivered by NXP implements SPI interfaced chips only.
|
||||
As an example GPIO access has been implemented by NXP with userspace code for the Raspberry Pi 3.
|
||||
|
||||
Adaptions to different Linux boards can be done by adding files to ```lib/customization/```.
|
||||
|
||||
While ```RTOS/phOsal``` (OS abstraction layer) can usually be left as is, ```Platform/DAL``` (Device abstraction layer) will most likely need additional code.
|
||||
|
||||
### Example Raspberry Pi 4
|
||||
|
||||
As a minmal adaption example, this repository contains a customization for Raspberry Pi 4.
|
||||
|
||||
A new ```Platform/DAL/cfg/BoardSelection.h``` has been provided, in order to choose a different board specific header file (```Platform/DAL/boards/Board_Pi4Rc663.h```).
|
||||
The latter contains a changed GPIO pinount (compared to the Raspberry Pi 3).
|
||||
|
||||
Function wrappers (to provide neutral naming) and convenience functions are provided in ```Platform/DAL/src/rpi4_gpio.c```.
|
||||
They call functions from the original ```external/Platform/DAL/src/Linux/phDriver_Linux_Int.c```.
|
||||
|
||||
### General
|
||||
|
||||
* Provide new device-specific (=fitting the individual board/chip combination) ```Platform/DAL/boards/Board_xyz.h```.
|
||||
* Allow it to be chosen in ```Platform/DAL/cfg/BoardSelection.h```
|
||||
* Change compile definition in ```Platform/DAL/CMakeLists.txt``` from the given ```PHDRIVER_PI4RC663_BOARD``` to the one required by the modified ```BoardSelection.h```
|
||||
* If required, add c-files in ```Platform/DAL/src``` which implement hardware access differently, i.e. access to GPIOs, SPI/I²C. Use ```lib/external/Platform/DAL/src/Linux/*.c``` as templates.
|
||||
* Register access (via I²C or SPI) requires implementation of (cmp. ```external/Platform/DAL/inc/phbalReg.h```):
|
||||
* ```phStatus_t phbalReg_Init(...)```
|
||||
* ```phStatus_t phbalReg_Exchange(...)```
|
||||
* ```phStatus_t phbalReg_SetConfig(...)```
|
||||
* ```phStatus_t phbalReg_GetConfig(...)```
|
||||
* GPIO access requires implementation of (cmp. ```external/Platform/DAL/inc/phDriver_Gpio.h```):
|
||||
* ```phStatus_t phDriver_PinConfig(...)```
|
||||
* ```uint8_t phDriver_PinRead(...)```
|
||||
* ```phStatus_t phDriver_IRQPinRead(...)```
|
||||
* ```phStatus_t phDriver_IRQPinPoll(...)```
|
||||
* ```void phDriver_PinWrite(...)```
|
||||
* ```void phDriver_PinClearIntStatus(...)```
|
||||
* GPIO access also requires implementation of (cmp. ```Platform/DAL/boards/Board_Pi4Rc663.h```) - these can be implemented based on existing functions like in ```external/Platform/DAL/src/Linux/phDriver_Linux_Int.c``` or from scratch:
|
||||
* ```void GPIO_reconfigure_pin(size_t gpio, int output_int)```
|
||||
* ```phStatus_t GPIO_read_pin(size_t gpio, uint8_t *pGpioVal)```
|
||||
* ```phStatus_t GPIO_poll_pin(size_t gpio, int timeOutms)```
|
||||
* Change ```Platform/DAL/CMakeLists.txt``` in order to include the customized files in the build, in addition and/or instead of the ones provided by NXP
|
||||
|
||||
## Example Hardware Setup
|
||||
|
||||
The NxpNfcFrontendLib has been tested with a *Raspberry Pi 4* (SPI needs to be activated) and the [CLEV6630B](https://www.nxp.com/part/CLEV6630B) development board.
|
||||
The *CLEV6630B* was powered from the Raspberry Pi via USB (jumpers need to be set accordingly: "USB", "VDD: +3.3V", "TVDD: +5V"); the onboard LPC microcontroller has beed detached from the NFC chip (solder bridges removed).
|
||||
|
||||
There are 9 electrical connections to the Raspberry Pi required:
|
||||
|
||||
| CLEV6630B Pin | Raspberry Pi Pin |
|
||||
|:--------------|:------------------|
|
||||
| MOSI | SPI-MOSI (GPIO 10)|
|
||||
| MISO | SPI-MISO (GPIO 9) |
|
||||
| SCK | SPI-CLK (GPIO 11) |
|
||||
| SSEL | SPI-CE0 (GPIO 8) |
|
||||
| CLRC_NRST | GPIO 24 |
|
||||
| IRQ | GPIO 23 |
|
||||
| IFSEL0 (F0) | GPIO 27 |
|
||||
| IFSEL1 (F1) | GPIO 22 |
|
||||
| GND | GND |
|
||||
|
||||

|
||||
@@ -0,0 +1,801 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
width="195.28593mm"
|
||||
height="103.53428mm"
|
||||
viewBox="0 0 195.28593 103.53428"
|
||||
version="1.1"
|
||||
id="svg5"
|
||||
xml:space="preserve"
|
||||
inkscape:version="1.2.2 (b0a8486541, 2022-12-01)"
|
||||
sodipodi:docname="NxpNfc_CLEV6630B.svg"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"><sodipodi:namedview
|
||||
id="namedview7"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#000000"
|
||||
borderopacity="0.25"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
inkscape:document-units="mm"
|
||||
showgrid="false"
|
||||
inkscape:zoom="2.0384476"
|
||||
inkscape:cx="378.71957"
|
||||
inkscape:cy="209.47313"
|
||||
inkscape:window-width="2560"
|
||||
inkscape:window-height="1371"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="layer1" /><defs
|
||||
id="defs2"><marker
|
||||
style="overflow:visible"
|
||||
id="TriangleStart"
|
||||
refX="0"
|
||||
refY="0"
|
||||
orient="auto-start-reverse"
|
||||
inkscape:stockid="TriangleStart"
|
||||
markerWidth="2"
|
||||
markerHeight="2"
|
||||
viewBox="0 0 5.3244081 6.1553851"
|
||||
inkscape:isstock="true"
|
||||
inkscape:collect="always"
|
||||
preserveAspectRatio="xMidYMid"><path
|
||||
transform="scale(0.5)"
|
||||
style="fill:context-stroke;fill-rule:evenodd;stroke:context-stroke;stroke-width:1pt"
|
||||
d="M 5.77,0 -2.88,5 V -5 Z"
|
||||
id="path135" /></marker><rect
|
||||
x="35.53083"
|
||||
y="171.24704"
|
||||
width="285.69534"
|
||||
height="112.51573"
|
||||
id="rect9461" /><rect
|
||||
x="35.53083"
|
||||
y="171.24704"
|
||||
width="285.69534"
|
||||
height="112.51573"
|
||||
id="rect9571" /><rect
|
||||
x="35.53083"
|
||||
y="171.24704"
|
||||
width="285.69534"
|
||||
height="112.51573"
|
||||
id="rect10353" /><rect
|
||||
x="35.53083"
|
||||
y="171.24704"
|
||||
width="285.69534"
|
||||
height="112.51573"
|
||||
id="rect10365" /><rect
|
||||
x="35.53083"
|
||||
y="171.24704"
|
||||
width="285.69534"
|
||||
height="112.51573"
|
||||
id="rect10371" /><rect
|
||||
x="35.53083"
|
||||
y="171.24704"
|
||||
width="285.69534"
|
||||
height="112.51573"
|
||||
id="rect10377" /><rect
|
||||
x="35.53083"
|
||||
y="171.24704"
|
||||
width="285.69534"
|
||||
height="112.51573"
|
||||
id="rect10383" /><rect
|
||||
x="35.53083"
|
||||
y="171.24704"
|
||||
width="285.69534"
|
||||
height="112.51573"
|
||||
id="rect10389" /><rect
|
||||
x="35.53083"
|
||||
y="171.24704"
|
||||
width="285.69534"
|
||||
height="112.51573"
|
||||
id="rect10395" /><rect
|
||||
x="35.53083"
|
||||
y="171.24704"
|
||||
width="285.69534"
|
||||
height="112.51573"
|
||||
id="rect10389-2" /><rect
|
||||
x="35.53083"
|
||||
y="171.24704"
|
||||
width="285.69534"
|
||||
height="112.51573"
|
||||
id="rect11910" /><rect
|
||||
x="35.53083"
|
||||
y="171.24704"
|
||||
width="285.69534"
|
||||
height="112.51573"
|
||||
id="rect11918" /><rect
|
||||
x="35.53083"
|
||||
y="171.24704"
|
||||
width="285.69534"
|
||||
height="112.51573"
|
||||
id="rect10389-2-1" /><rect
|
||||
x="35.53083"
|
||||
y="171.24704"
|
||||
width="285.69534"
|
||||
height="112.51573"
|
||||
id="rect14078" /><rect
|
||||
x="35.53083"
|
||||
y="171.24704"
|
||||
width="285.69534"
|
||||
height="112.51573"
|
||||
id="rect14259" /><rect
|
||||
x="35.53083"
|
||||
y="171.24704"
|
||||
width="285.69534"
|
||||
height="112.51573"
|
||||
id="rect14269" /><rect
|
||||
x="35.53083"
|
||||
y="171.24704"
|
||||
width="285.69534"
|
||||
height="112.51573"
|
||||
id="rect15395" /><rect
|
||||
x="35.53083"
|
||||
y="171.24704"
|
||||
width="285.69534"
|
||||
height="112.51573"
|
||||
id="rect15692" /><rect
|
||||
x="35.53083"
|
||||
y="171.24704"
|
||||
width="285.69534"
|
||||
height="112.51573"
|
||||
id="rect15818" /><rect
|
||||
x="35.53083"
|
||||
y="171.24704"
|
||||
width="285.69534"
|
||||
height="112.51573"
|
||||
id="rect15820" /><rect
|
||||
x="35.53083"
|
||||
y="171.24704"
|
||||
width="285.69534"
|
||||
height="112.51573"
|
||||
id="rect15840" /><rect
|
||||
x="35.53083"
|
||||
y="171.24704"
|
||||
width="285.69534"
|
||||
height="112.51573"
|
||||
id="rect15842" /><rect
|
||||
x="35.53083"
|
||||
y="171.24704"
|
||||
width="285.69534"
|
||||
height="112.51573"
|
||||
id="rect15862" /><rect
|
||||
x="35.53083"
|
||||
y="171.24704"
|
||||
width="285.69534"
|
||||
height="112.51573"
|
||||
id="rect15892" /><rect
|
||||
x="35.53083"
|
||||
y="171.24704"
|
||||
width="285.69534"
|
||||
height="112.51573"
|
||||
id="rect15894" /><rect
|
||||
x="35.53083"
|
||||
y="171.24704"
|
||||
width="285.69534"
|
||||
height="112.51573"
|
||||
id="rect17088" /></defs><g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(-34.225212,14.492536)"><rect
|
||||
style="fill:#71d281;fill-opacity:1;stroke:none;stroke-width:1.05202;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect15680"
|
||||
width="95.316772"
|
||||
height="16.347263"
|
||||
x="34.225212"
|
||||
y="72.694481" /><g
|
||||
id="g7345"
|
||||
transform="translate(-0.52916667,-25.400001)"><path
|
||||
style="fill:#004794;fill-opacity:1;stroke-width:0.264583"
|
||||
d="m 34.969861,16.060045 v 74.26147 h 87.165169 v -11.47322 h 22.27385 v 16.11313 h 85.63143 v -84.05396 h -85.63143 v 14.94651 h -22.27385 v -9.79393 z"
|
||||
id="path242"
|
||||
sodipodi:nodetypes="ccccccccccccc" /><path
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#b2c1d7;stroke-width:0.5;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 188.35712,21.178215 v 63.51245"
|
||||
id="path3377" /><path
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#b2c1d7;stroke-width:0.5;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 156.60089,52.934445 h 63.51245"
|
||||
id="path6193" /><rect
|
||||
style="fill:#303030;fill-opacity:1;stroke:#000000;stroke-width:0.499999;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect6247"
|
||||
width="17.534277"
|
||||
height="17.534277"
|
||||
x="59.52792"
|
||||
y="52.54977" /></g><text
|
||||
xml:space="preserve"
|
||||
transform="matrix(0,-0.26458333,0.26458333,0,36.528052,47.73313)"
|
||||
id="text10387-5-9"
|
||||
style="font-size:8px;letter-spacing:0px;word-spacing:0px;white-space:pre;shape-inside:url(#rect10389-2-1);display:inline;fill:#ff0000;fill-opacity:1;stroke:#000000;stroke-width:1.88976;stroke-dasharray:none;stroke-opacity:1"><tspan
|
||||
x="35.53125"
|
||||
y="178.5251"
|
||||
id="tspan17661"><tspan
|
||||
style="font-weight:bold;-inkscape-font-specification:'sans-serif Bold';stroke:none"
|
||||
id="tspan17659">Removed</tspan></tspan></text><text
|
||||
xml:space="preserve"
|
||||
transform="matrix(0.26458333,0,0,0.26458333,59.817081,-40.970561)"
|
||||
id="text10387-5"
|
||||
style="font-size:8px;letter-spacing:0px;word-spacing:0px;white-space:pre;shape-inside:url(#rect10389-2);display:inline;fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.88976;stroke-dasharray:none;stroke-opacity:1"><tspan
|
||||
x="35.53125"
|
||||
y="178.5251"
|
||||
id="tspan17665"><tspan
|
||||
style="font-weight:bold;-inkscape-font-specification:'sans-serif Bold';fill:#e0e0e0;stroke:none"
|
||||
id="tspan17663">USB</tspan></tspan></text><circle
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0.499999;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="path8125"
|
||||
cx="48.940239"
|
||||
cy="62.953655"
|
||||
r="1.4523464" /><circle
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0.499999;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="circle8647"
|
||||
cx="52.115238"
|
||||
cy="62.953655"
|
||||
r="1.4523464" /><circle
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0.499999;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="circle8649"
|
||||
cx="55.290237"
|
||||
cy="62.953655"
|
||||
r="1.4523464" /><circle
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0.499999;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="circle8651"
|
||||
cx="58.465237"
|
||||
cy="62.953655"
|
||||
r="1.4523464" /><circle
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0.499999;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="circle8653"
|
||||
cx="73.281898"
|
||||
cy="62.953655"
|
||||
r="1.4523464" /><circle
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0.499999;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="circle8655"
|
||||
cx="76.456902"
|
||||
cy="62.953655"
|
||||
r="1.4523464" /><circle
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0.499999;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="circle8657"
|
||||
cx="79.631897"
|
||||
cy="62.953655"
|
||||
r="1.4523464" /><circle
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0.499999;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="circle8659"
|
||||
cx="82.806892"
|
||||
cy="62.953655"
|
||||
r="1.4523464" /><circle
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0.499999;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="circle8661"
|
||||
cx="85.981888"
|
||||
cy="62.953655"
|
||||
r="1.4523464" /><circle
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0.499999;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="circle8663"
|
||||
cx="89.156891"
|
||||
cy="62.953655"
|
||||
r="1.4523464" /><circle
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0.499999;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="circle8665"
|
||||
cx="92.331886"
|
||||
cy="62.953655"
|
||||
r="1.4523464" /><circle
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0.499999;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="circle8667"
|
||||
cx="95.506882"
|
||||
cy="62.953655"
|
||||
r="1.4523464" /><circle
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0.499999;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="circle8669"
|
||||
cx="102.38605"
|
||||
cy="52.899487"
|
||||
r="1.4523464" /><circle
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0.499999;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="circle8671"
|
||||
cx="105.56105"
|
||||
cy="52.899487"
|
||||
r="1.4523464" /><circle
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0.499999;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="circle8673"
|
||||
cx="108.73605"
|
||||
cy="52.899487"
|
||||
r="1.4523464" /><circle
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0.499999;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="circle8675"
|
||||
cx="111.91106"
|
||||
cy="52.899487"
|
||||
r="1.4523464" /><circle
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0.499999;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="circle8677"
|
||||
cx="115.08603"
|
||||
cy="52.899487"
|
||||
r="1.4523464" /><circle
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0.499999;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="circle8679"
|
||||
cx="118.26105"
|
||||
cy="52.899487"
|
||||
r="1.4523464" /><text
|
||||
xml:space="preserve"
|
||||
transform="matrix(0,-0.26458333,0.26458333,0,2.0710406,70.384326)"
|
||||
id="text9459"
|
||||
style="font-size:10.6667px;white-space:pre;shape-inside:url(#rect9461);display:inline;fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.88976;stroke-dasharray:none;stroke-opacity:1"><tspan
|
||||
x="35.53125"
|
||||
y="180.95146"
|
||||
id="tspan17669"><tspan
|
||||
style="font-weight:bold;-inkscape-font-specification:'sans-serif Bold';fill:#e0e0e0;stroke:none"
|
||||
id="tspan17667">GND</tspan></tspan></text><text
|
||||
xml:space="preserve"
|
||||
transform="matrix(0,-0.26458333,0.26458333,0,5.0216731,70.384326)"
|
||||
id="text9569"
|
||||
style="font-size:10.6667px;white-space:pre;shape-inside:url(#rect9571);display:inline;fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.88976;stroke-dasharray:none;stroke-opacity:1"><tspan
|
||||
x="35.53125"
|
||||
y="180.95146"
|
||||
id="tspan17673"><tspan
|
||||
style="font-weight:bold;-inkscape-font-specification:'sans-serif Bold';fill:#e0e0e0;stroke:none"
|
||||
id="tspan17671">IRQ</tspan></tspan></text><text
|
||||
xml:space="preserve"
|
||||
transform="matrix(0,-0.26458333,0.26458333,0,29.378859,70.384326)"
|
||||
id="text10351"
|
||||
style="font-size:10.6667px;letter-spacing:0px;word-spacing:0px;white-space:pre;shape-inside:url(#rect10353);display:inline;fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.88976;stroke-dasharray:none;stroke-opacity:1"><tspan
|
||||
x="35.53125"
|
||||
y="180.95146"
|
||||
id="tspan17677"><tspan
|
||||
style="font-weight:bold;-inkscape-font-specification:'sans-serif Bold';fill:#e0e0e0;stroke:none"
|
||||
id="tspan17675">CLRC_NRST</tspan></tspan></text><text
|
||||
xml:space="preserve"
|
||||
transform="matrix(0,-0.26458333,0.26458333,0,32.553858,70.384326)"
|
||||
id="text10363"
|
||||
style="font-size:10.6667px;letter-spacing:0px;word-spacing:0px;white-space:pre;shape-inside:url(#rect10365);display:inline;fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.88976;stroke-dasharray:none;stroke-opacity:1"><tspan
|
||||
x="35.53125"
|
||||
y="180.95146"
|
||||
id="tspan17681"><tspan
|
||||
style="font-weight:bold;-inkscape-font-specification:'sans-serif Bold';fill:#e0e0e0;stroke:none"
|
||||
id="tspan17679">SSEL</tspan></tspan></text><text
|
||||
xml:space="preserve"
|
||||
transform="matrix(0,-0.26458333,0.26458333,0,35.728857,70.384326)"
|
||||
id="text10369"
|
||||
style="font-size:10.6667px;letter-spacing:0px;word-spacing:0px;white-space:pre;shape-inside:url(#rect10371);display:inline;fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.88976;stroke-dasharray:none;stroke-opacity:1"><tspan
|
||||
x="35.53125"
|
||||
y="180.95146"
|
||||
id="tspan17685"><tspan
|
||||
style="font-weight:bold;-inkscape-font-specification:'sans-serif Bold';fill:#e0e0e0;stroke:none"
|
||||
id="tspan17683">MOSI</tspan></tspan></text><text
|
||||
xml:space="preserve"
|
||||
transform="matrix(0,-0.26458333,0.26458333,0,38.903856,70.384326)"
|
||||
id="text10375"
|
||||
style="font-size:10.6667px;letter-spacing:0px;word-spacing:0px;white-space:pre;shape-inside:url(#rect10377);display:inline;fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.88976;stroke-dasharray:none;stroke-opacity:1"><tspan
|
||||
x="35.53125"
|
||||
y="180.95146"
|
||||
id="tspan17689"><tspan
|
||||
style="font-weight:bold;-inkscape-font-specification:'sans-serif Bold';fill:#e0e0e0;stroke:none"
|
||||
id="tspan17687">MISO</tspan></tspan></text><text
|
||||
xml:space="preserve"
|
||||
transform="matrix(0,-0.26458333,0.26458333,0,42.078855,70.384326)"
|
||||
id="text10381"
|
||||
style="font-size:10.6667px;letter-spacing:0px;word-spacing:0px;white-space:pre;shape-inside:url(#rect10383);display:inline;fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.88976;stroke-dasharray:none;stroke-opacity:1"><tspan
|
||||
x="35.53125"
|
||||
y="180.95146"
|
||||
id="tspan17693"><tspan
|
||||
style="font-weight:bold;-inkscape-font-specification:'sans-serif Bold';fill:#e0e0e0;stroke:none"
|
||||
id="tspan17691">SCK</tspan></tspan></text><text
|
||||
xml:space="preserve"
|
||||
transform="matrix(0,-0.26458333,0.26458333,0,71.391844,59.800992)"
|
||||
id="text10387"
|
||||
style="font-size:10.6667px;letter-spacing:0px;word-spacing:0px;white-space:pre;shape-inside:url(#rect10389);display:inline;fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.88976;stroke-dasharray:none;stroke-opacity:1"><tspan
|
||||
x="35.53125"
|
||||
y="180.95146"
|
||||
id="tspan17697"><tspan
|
||||
style="font-weight:bold;-inkscape-font-specification:'sans-serif Bold';fill:#e0e0e0;stroke:none"
|
||||
id="tspan17695">F1</tspan></tspan></text><text
|
||||
xml:space="preserve"
|
||||
transform="matrix(0,-0.26458333,0.26458333,0,68.216845,59.800992)"
|
||||
id="text10393"
|
||||
style="font-size:10.6667px;letter-spacing:0px;word-spacing:0px;white-space:pre;shape-inside:url(#rect10395);display:inline;fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.88976;stroke-dasharray:none;stroke-opacity:1"><tspan
|
||||
x="35.53125"
|
||||
y="180.95146"
|
||||
id="tspan17701"><tspan
|
||||
style="font-weight:bold;-inkscape-font-specification:'sans-serif Bold';fill:#e0e0e0;stroke:none"
|
||||
id="tspan17699">F0</tspan></tspan></text><g
|
||||
id="g10455"
|
||||
transform="matrix(0.89267452,0,0,0.89267452,9.2600959,3.1549247)"><rect
|
||||
style="fill:#ffa0a0;fill-opacity:1;stroke:none;stroke-width:0.499999;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect10449"
|
||||
width="4.6956158"
|
||||
height="2.1317554"
|
||||
x="83.932693"
|
||||
y="29.395861" /><rect
|
||||
style="fill:#802020;fill-opacity:1;stroke:none;stroke-width:0.335498;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect10451"
|
||||
width="2.114136"
|
||||
height="2.1317554"
|
||||
x="85.223434"
|
||||
y="29.395861" /></g><g
|
||||
id="g10479"
|
||||
transform="matrix(0.89267452,0,0,0.89267452,9.2600959,5.2715915)"><rect
|
||||
style="fill:#ffa0a0;fill-opacity:1;stroke:none;stroke-width:0.499999;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect10475"
|
||||
width="4.6956158"
|
||||
height="2.1317554"
|
||||
x="83.932693"
|
||||
y="29.395861" /><rect
|
||||
style="fill:#802020;fill-opacity:1;stroke:none;stroke-width:0.335498;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect10477"
|
||||
width="2.114136"
|
||||
height="2.1317554"
|
||||
x="85.223434"
|
||||
y="29.395861" /></g><g
|
||||
id="g10485"
|
||||
transform="matrix(0.89267452,0,0,0.89267452,9.2600959,7.3882583)"><rect
|
||||
style="fill:#ffa0a0;fill-opacity:1;stroke:none;stroke-width:0.499999;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect10481"
|
||||
width="4.6956158"
|
||||
height="2.1317554"
|
||||
x="83.932693"
|
||||
y="29.395861" /><rect
|
||||
style="fill:#802020;fill-opacity:1;stroke:none;stroke-width:0.335498;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect10483"
|
||||
width="2.114136"
|
||||
height="2.1317554"
|
||||
x="85.223434"
|
||||
y="29.395861" /></g><g
|
||||
id="g10491"
|
||||
transform="matrix(0.89267452,0,0,0.89267452,9.2600959,9.5049251)"><rect
|
||||
style="fill:#ffa0a0;fill-opacity:1;stroke:none;stroke-width:0.499999;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect10487"
|
||||
width="4.6956158"
|
||||
height="2.1317554"
|
||||
x="83.932693"
|
||||
y="29.395861" /><rect
|
||||
style="fill:#802020;fill-opacity:1;stroke:none;stroke-width:0.335498;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect10489"
|
||||
width="2.114136"
|
||||
height="2.1317554"
|
||||
x="85.223434"
|
||||
y="29.395861" /></g><g
|
||||
id="g10497"
|
||||
transform="matrix(0.89267452,0,0,0.89267452,14.022596,3.1549247)"><rect
|
||||
style="fill:#e0e0e0;fill-opacity:1;stroke:none;stroke-width:0.499999;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect10493"
|
||||
width="4.6956158"
|
||||
height="2.1317554"
|
||||
x="83.932693"
|
||||
y="29.395861" /><rect
|
||||
style="fill:#202020;fill-opacity:1;stroke:none;stroke-width:0.335498;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect10495"
|
||||
width="2.114136"
|
||||
height="2.1317554"
|
||||
x="85.223434"
|
||||
y="29.395861" /></g><g
|
||||
id="g10503"
|
||||
transform="matrix(0.89267452,0,0,0.89267452,14.022596,5.2715915)"><rect
|
||||
style="fill:#e0e0e0;fill-opacity:1;stroke:none;stroke-width:0.499999;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect10499"
|
||||
width="4.6956158"
|
||||
height="2.1317554"
|
||||
x="83.932693"
|
||||
y="29.395861" /><rect
|
||||
style="fill:#202020;fill-opacity:1;stroke:none;stroke-width:0.335498;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect10501"
|
||||
width="2.114136"
|
||||
height="2.1317554"
|
||||
x="85.223434"
|
||||
y="29.395861" /></g><g
|
||||
id="g10509"
|
||||
transform="matrix(0.89267452,0,0,0.89267452,14.022596,7.3882583)"><rect
|
||||
style="fill:#e0e0e0;fill-opacity:1;stroke:none;stroke-width:0.499999;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect10505"
|
||||
width="4.6956158"
|
||||
height="2.1317554"
|
||||
x="83.932693"
|
||||
y="29.395861" /><rect
|
||||
style="fill:#202020;fill-opacity:1;stroke:none;stroke-width:0.335498;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect10507"
|
||||
width="2.114136"
|
||||
height="2.1317554"
|
||||
x="85.223434"
|
||||
y="29.395861" /></g><g
|
||||
id="g10515"
|
||||
transform="matrix(0.89267452,0,0,0.89267452,14.022596,9.5049251)"><rect
|
||||
style="fill:#e0e0e0;fill-opacity:1;stroke:none;stroke-width:0.499999;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect10511"
|
||||
width="4.6956158"
|
||||
height="2.1317554"
|
||||
x="83.932693"
|
||||
y="29.395861" /><rect
|
||||
style="fill:#202020;fill-opacity:1;stroke:none;stroke-width:0.335498;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect10513"
|
||||
width="2.114136"
|
||||
height="2.1317554"
|
||||
x="85.223434"
|
||||
y="29.395861" /></g><g
|
||||
id="g10581"><rect
|
||||
style="fill:#202020;fill-opacity:1;stroke:none;stroke-width:0.499999;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect10569"
|
||||
width="9.4519472"
|
||||
height="2.9962199"
|
||||
x="71.574905"
|
||||
y="7.2480688" /><rect
|
||||
style="fill:#e0e0e0;fill-opacity:1;stroke:none;stroke-width:0.123038;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect10571"
|
||||
width="1.3334424"
|
||||
height="1.2860498"
|
||||
x="75.634155"
|
||||
y="8.1031542" /><rect
|
||||
style="fill:#e0e0e0;fill-opacity:1;stroke:none;stroke-width:0.123038;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect10573"
|
||||
width="1.3334424"
|
||||
height="1.2860498"
|
||||
x="78.809151"
|
||||
y="8.1031542" /><rect
|
||||
style="fill:#e0e0e0;fill-opacity:1;stroke:none;stroke-width:0.123038;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect10575"
|
||||
width="1.3334424"
|
||||
height="1.2860498"
|
||||
x="72.459152"
|
||||
y="8.1031542" /></g><g
|
||||
id="g10591"
|
||||
transform="translate(15.875)"><rect
|
||||
style="fill:#202020;fill-opacity:1;stroke:none;stroke-width:0.499999;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect10583"
|
||||
width="9.4519472"
|
||||
height="2.9962199"
|
||||
x="71.574905"
|
||||
y="7.2480688" /><rect
|
||||
style="fill:#e0e0e0;fill-opacity:1;stroke:none;stroke-width:0.123038;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect10585"
|
||||
width="1.3334424"
|
||||
height="1.2860498"
|
||||
x="75.634155"
|
||||
y="8.1031542" /><rect
|
||||
style="fill:#e0e0e0;fill-opacity:1;stroke:none;stroke-width:0.123038;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect10587"
|
||||
width="1.3334424"
|
||||
height="1.2860498"
|
||||
x="78.809151"
|
||||
y="8.1031542" /><rect
|
||||
style="fill:#e0e0e0;fill-opacity:1;stroke:none;stroke-width:0.123038;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect10589"
|
||||
width="1.3334424"
|
||||
height="1.2860498"
|
||||
x="72.459152"
|
||||
y="8.1031542" /></g><g
|
||||
id="g10601"
|
||||
transform="translate(26.458334)"><rect
|
||||
style="fill:#202020;fill-opacity:1;stroke:none;stroke-width:0.499999;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect10593"
|
||||
width="9.4519472"
|
||||
height="2.9962199"
|
||||
x="71.574905"
|
||||
y="7.2480688" /><rect
|
||||
style="fill:#e0e0e0;fill-opacity:1;stroke:none;stroke-width:0.123038;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect10595"
|
||||
width="1.3334424"
|
||||
height="1.2860498"
|
||||
x="75.634155"
|
||||
y="8.1031542" /><rect
|
||||
style="fill:#e0e0e0;fill-opacity:1;stroke:none;stroke-width:0.123038;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect10597"
|
||||
width="1.3334424"
|
||||
height="1.2860498"
|
||||
x="78.809151"
|
||||
y="8.1031542" /><rect
|
||||
style="fill:#e0e0e0;fill-opacity:1;stroke:none;stroke-width:0.123038;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect10599"
|
||||
width="1.3334424"
|
||||
height="1.2860498"
|
||||
x="72.459152"
|
||||
y="8.1031542" /></g><rect
|
||||
style="fill:none;fill-opacity:1;stroke:#0080ff;stroke-width:0.974908;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect10603"
|
||||
width="6.0848989"
|
||||
height="2.8062096"
|
||||
x="71.658791"
|
||||
y="7.3430738" /><rect
|
||||
style="fill:none;fill-opacity:1;stroke:#0080ff;stroke-width:0.974908;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect11749"
|
||||
width="6.0848989"
|
||||
height="2.8062096"
|
||||
x="87.533783"
|
||||
y="7.3430738" /><rect
|
||||
style="fill:none;fill-opacity:1;stroke:#0080ff;stroke-width:0.974908;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect11751"
|
||||
width="6.0848989"
|
||||
height="2.8062096"
|
||||
x="101.29211"
|
||||
y="7.3430738" /><text
|
||||
xml:space="preserve"
|
||||
transform="matrix(0,-0.26458333,0.26458333,0,41.339154,16.299122)"
|
||||
id="text11908"
|
||||
style="font-size:8px;letter-spacing:0px;word-spacing:0px;white-space:pre;shape-inside:url(#rect11910);display:inline;fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.88976;stroke-dasharray:none;stroke-opacity:1"><tspan
|
||||
x="35.53125"
|
||||
y="178.5251"
|
||||
id="tspan17705"><tspan
|
||||
style="font-weight:bold;-inkscape-font-specification:'sans-serif Bold';fill:#e0e0e0;stroke:none"
|
||||
id="tspan17703">+3,3V</tspan></tspan></text><text
|
||||
xml:space="preserve"
|
||||
transform="matrix(0,-0.26458333,0.26458333,0,61.185024,15.805938)"
|
||||
id="text11916"
|
||||
style="font-size:8px;letter-spacing:0px;word-spacing:0px;white-space:pre;shape-inside:url(#rect11918);display:inline;fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.88976;stroke-dasharray:none;stroke-opacity:1"><tspan
|
||||
x="35.53125"
|
||||
y="178.5251"
|
||||
id="tspan17709"><tspan
|
||||
style="font-weight:bold;-inkscape-font-specification:'sans-serif Bold';fill:#e0e0e0;stroke:none"
|
||||
id="tspan17707">+5V</tspan></tspan></text><g
|
||||
id="g14282"
|
||||
transform="translate(-0.83994341,1.7318017)"><rect
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.688959;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect13758"
|
||||
width="4.9264355"
|
||||
height="2.0696454"
|
||||
x="74.677605"
|
||||
y="1.7462211" /><text
|
||||
xml:space="preserve"
|
||||
transform="matrix(0.26458333,0,0,0.26458333,65.795687,-43.708654)"
|
||||
id="text14076"
|
||||
style="font-size:8px;letter-spacing:0px;word-spacing:0px;white-space:pre;shape-inside:url(#rect14078);display:inline;fill:#004794;fill-opacity:1;stroke:#000000;stroke-width:1.88976;stroke-dasharray:none;stroke-opacity:1"><tspan
|
||||
x="35.53125"
|
||||
y="178.5251"
|
||||
id="tspan17713"><tspan
|
||||
style="font-weight:bold;-inkscape-font-specification:'sans-serif Bold';stroke:none"
|
||||
id="tspan17711">+5V</tspan></tspan></text></g><g
|
||||
id="g14288"
|
||||
transform="translate(-0.83993578,1.7318017)"><rect
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.688959;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect14251"
|
||||
width="4.9264355"
|
||||
height="2.0696454"
|
||||
x="90.552597"
|
||||
y="1.7462211" /><text
|
||||
xml:space="preserve"
|
||||
transform="matrix(0.26458333,0,0,0.26458333,81.421972,-43.69807)"
|
||||
id="text14257"
|
||||
style="font-size:8px;letter-spacing:0px;word-spacing:0px;white-space:pre;shape-inside:url(#rect14259);display:inline;fill:#004794;fill-opacity:1;stroke:#000000;stroke-width:1.88976;stroke-dasharray:none;stroke-opacity:1"><tspan
|
||||
x="35.53125"
|
||||
y="178.5251"
|
||||
id="tspan17717"><tspan
|
||||
style="font-weight:bold;-inkscape-font-specification:'sans-serif Bold';stroke:none"
|
||||
id="tspan17715">VDD</tspan></tspan></text></g><g
|
||||
id="g14294"
|
||||
transform="translate(-1.608386,1.7318017)"><rect
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.789142;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect14261"
|
||||
width="6.4633322"
|
||||
height="2.0696454"
|
||||
x="101.13593"
|
||||
y="1.7462211" /><text
|
||||
xml:space="preserve"
|
||||
transform="matrix(0.26458333,0,0,0.26458333,92.139814,-43.69807)"
|
||||
id="text14267"
|
||||
style="font-size:8px;letter-spacing:0px;word-spacing:0px;white-space:pre;shape-inside:url(#rect14269);display:inline;fill:#004794;fill-opacity:1;stroke:#000000;stroke-width:1.88976;stroke-dasharray:none;stroke-opacity:1"><tspan
|
||||
x="35.53125"
|
||||
y="178.5251"
|
||||
id="tspan17721"><tspan
|
||||
style="font-weight:bold;-inkscape-font-specification:'sans-serif Bold';stroke:none"
|
||||
id="tspan17719">TVDD</tspan></tspan></text></g><path
|
||||
style="fill:#004794;fill-opacity:1;stroke:#ff0080;stroke-width:1;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#TriangleStart)"
|
||||
d="m 48.940239,63.213981 v 8.087728"
|
||||
id="path14490"
|
||||
sodipodi:nodetypes="cc" /><text
|
||||
xml:space="preserve"
|
||||
transform="matrix(0,-0.26458333,0.26458333,0,2.0710406,88.905159)"
|
||||
id="text15393"
|
||||
style="font-size:10.6667px;white-space:pre;shape-inside:url(#rect15395);display:inline;fill:#ff0080;fill-opacity:1;stroke:#000000;stroke-width:1.88976;stroke-dasharray:none;stroke-opacity:1"><tspan
|
||||
x="35.53125"
|
||||
y="180.95146"
|
||||
id="tspan17725"><tspan
|
||||
style="font-weight:bold;-inkscape-font-specification:'sans-serif Bold';stroke:none"
|
||||
id="tspan17723">GND</tspan></tspan></text><path
|
||||
style="fill:#004794;fill-opacity:1;stroke:#ff0080;stroke-width:1;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#TriangleStart)"
|
||||
d="m 52.115238,63.213981 v 8.087728"
|
||||
id="path15686"
|
||||
sodipodi:nodetypes="cc" /><text
|
||||
xml:space="preserve"
|
||||
transform="matrix(0,-0.26458333,0.26458333,0,5.2460405,93.652153)"
|
||||
id="text15690"
|
||||
style="font-size:10.6667px;white-space:pre;shape-inside:url(#rect15692);display:inline;fill:#ff0080;fill-opacity:1;stroke:#000000;stroke-width:1.88976;stroke-dasharray:none;stroke-opacity:1"><tspan
|
||||
x="35.53125"
|
||||
y="180.95146"
|
||||
id="tspan17729"><tspan
|
||||
style="font-weight:bold;-inkscape-font-specification:'sans-serif Bold';stroke:none"
|
||||
id="tspan17727">GPIO 23</tspan></tspan></text><path
|
||||
style="fill:#004794;fill-opacity:1;stroke:#ff0080;stroke-width:1;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#TriangleStart)"
|
||||
d="m 76.456908,63.213981 v 8.087728"
|
||||
id="path15806"
|
||||
sodipodi:nodetypes="cc" /><text
|
||||
xml:space="preserve"
|
||||
transform="matrix(0,-0.26458333,0.26458333,0,29.587709,93.652153)"
|
||||
id="text15810"
|
||||
style="font-size:10.6667px;white-space:pre;shape-inside:url(#rect15818);display:inline;fill:#ff0080;fill-opacity:1;stroke:#000000;stroke-width:1.88976;stroke-dasharray:none;stroke-opacity:1"><tspan
|
||||
x="35.53125"
|
||||
y="180.95146"
|
||||
id="tspan17733"><tspan
|
||||
style="font-weight:bold;-inkscape-font-specification:'sans-serif Bold';stroke:none"
|
||||
id="tspan17731">GPIO 24</tspan></tspan></text><path
|
||||
style="fill:#004794;fill-opacity:1;stroke:#ff0080;stroke-width:1;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#TriangleStart)"
|
||||
d="m 79.631907,63.213981 v 8.087728"
|
||||
id="path15812"
|
||||
sodipodi:nodetypes="cc" /><text
|
||||
xml:space="preserve"
|
||||
transform="matrix(0,-0.26458333,0.26458333,0,32.762709,93.652153)"
|
||||
id="text15816"
|
||||
style="font-size:10.6667px;white-space:pre;shape-inside:url(#rect15820);display:inline;fill:#ff0080;fill-opacity:1;stroke:#000000;stroke-width:1.88976;stroke-dasharray:none;stroke-opacity:1"><tspan
|
||||
x="35.53125"
|
||||
y="180.95146"
|
||||
id="tspan17737"><tspan
|
||||
style="font-weight:bold;-inkscape-font-specification:'sans-serif Bold';stroke:none"
|
||||
id="tspan17735">GPIO 8</tspan></tspan></text><path
|
||||
style="fill:#004794;fill-opacity:1;stroke:#ff0080;stroke-width:1;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#TriangleStart)"
|
||||
d="m 82.806909,63.213981 v 8.087728"
|
||||
id="path15828"
|
||||
sodipodi:nodetypes="cc" /><text
|
||||
xml:space="preserve"
|
||||
transform="matrix(0,-0.26458333,0.26458333,0,35.93771,93.652153)"
|
||||
id="text15832"
|
||||
style="font-size:10.6667px;white-space:pre;shape-inside:url(#rect15840);display:inline;fill:#ff0080;fill-opacity:1;stroke:#000000;stroke-width:1.88976;stroke-dasharray:none;stroke-opacity:1"><tspan
|
||||
x="35.53125"
|
||||
y="180.95146"
|
||||
id="tspan17741"><tspan
|
||||
style="font-weight:bold;-inkscape-font-specification:'sans-serif Bold';stroke:none"
|
||||
id="tspan17739">GPIO 10</tspan></tspan></text><path
|
||||
style="fill:#004794;fill-opacity:1;stroke:#ff0080;stroke-width:1;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#TriangleStart)"
|
||||
d="m 85.981908,63.213981 v 8.087728"
|
||||
id="path15834"
|
||||
sodipodi:nodetypes="cc" /><text
|
||||
xml:space="preserve"
|
||||
transform="matrix(0,-0.26458333,0.26458333,0,39.11271,93.652153)"
|
||||
id="text15838"
|
||||
style="font-size:10.6667px;white-space:pre;shape-inside:url(#rect15842);display:inline;fill:#ff0080;fill-opacity:1;stroke:#000000;stroke-width:1.88976;stroke-dasharray:none;stroke-opacity:1"><tspan
|
||||
x="35.53125"
|
||||
y="180.95146"
|
||||
id="tspan17745"><tspan
|
||||
style="font-weight:bold;-inkscape-font-specification:'sans-serif Bold';stroke:none"
|
||||
id="tspan17743">GPIO 9</tspan></tspan></text><path
|
||||
style="fill:#004794;fill-opacity:1;stroke:#ff0080;stroke-width:1;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#TriangleStart)"
|
||||
d="m 89.15691,63.213981 v 8.087728"
|
||||
id="path15850"
|
||||
sodipodi:nodetypes="cc" /><text
|
||||
xml:space="preserve"
|
||||
transform="matrix(0,-0.26458333,0.26458333,0,42.287711,93.652153)"
|
||||
id="text15854"
|
||||
style="font-size:10.6667px;white-space:pre;shape-inside:url(#rect15862);display:inline;fill:#ff0080;fill-opacity:1;stroke:#000000;stroke-width:1.88976;stroke-dasharray:none;stroke-opacity:1"><tspan
|
||||
x="35.53125"
|
||||
y="180.95146"
|
||||
id="tspan17749"><tspan
|
||||
style="font-weight:bold;-inkscape-font-specification:'sans-serif Bold';stroke:none"
|
||||
id="tspan17747">GPIO 11</tspan></tspan></text><path
|
||||
style="fill:#004794;fill-opacity:1;stroke:#ff0080;stroke-width:1;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#TriangleStart)"
|
||||
d="M 115.08607,53.159814 V 71.301709"
|
||||
id="path15880"
|
||||
sodipodi:nodetypes="cc" /><text
|
||||
xml:space="preserve"
|
||||
transform="matrix(0,-0.26458333,0.26458333,0,68.216877,93.652153)"
|
||||
id="text15884"
|
||||
style="font-size:10.6667px;white-space:pre;shape-inside:url(#rect15892);display:inline;fill:#ff0080;fill-opacity:1;stroke:#000000;stroke-width:1.88976;stroke-dasharray:none;stroke-opacity:1"><tspan
|
||||
x="35.53125"
|
||||
y="180.95146"
|
||||
id="tspan17753"><tspan
|
||||
style="font-weight:bold;-inkscape-font-specification:'sans-serif Bold';stroke:none"
|
||||
id="tspan17751">GPIO 27</tspan></tspan></text><path
|
||||
style="fill:#004794;fill-opacity:1;stroke:#ff0080;stroke-width:1;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#TriangleStart)"
|
||||
d="M 118.26107,53.159814 V 71.301709"
|
||||
id="path15886"
|
||||
sodipodi:nodetypes="cc" /><text
|
||||
xml:space="preserve"
|
||||
transform="matrix(0,-0.26458333,0.26458333,0,71.391878,93.652153)"
|
||||
id="text15890"
|
||||
style="font-size:10.6667px;white-space:pre;shape-inside:url(#rect15894);display:inline;fill:#ff0080;fill-opacity:1;stroke:#000000;stroke-width:1.88976;stroke-dasharray:none;stroke-opacity:1"><tspan
|
||||
x="35.53125"
|
||||
y="180.95146"
|
||||
id="tspan17757"><tspan
|
||||
style="font-weight:bold;-inkscape-font-specification:'sans-serif Bold';stroke:none"
|
||||
id="tspan17755">GPIO 22</tspan></tspan></text><text
|
||||
xml:space="preserve"
|
||||
transform="matrix(0.26458333,0,0,0.26458333,60.612676,39.760335)"
|
||||
id="text17086"
|
||||
style="font-size:10.6667px;letter-spacing:1px;white-space:pre;shape-inside:url(#rect17088);display:inline;fill:#006000;fill-opacity:1;stroke:#000000;stroke-width:1.88976;stroke-dasharray:none;stroke-opacity:1"><tspan
|
||||
x="35.53125"
|
||||
y="180.95146"
|
||||
id="tspan17761"><tspan
|
||||
style="font-weight:bold;-inkscape-font-specification:'sans-serif Bold';stroke:none"
|
||||
id="tspan17759">Raspberry Pi 4</tspan></tspan></text></g></svg>
|
||||
|
After Width: | Height: | Size: 37 KiB |
@@ -0,0 +1,36 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// Copyright 2020 - 2025 Pionix GmbH and Contributors to EVerest
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <atomic>
|
||||
#include <cstdint>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
namespace NxpNfcFrontendWrapper {
|
||||
// Forward declarations, to keep headers private
|
||||
class NxpNfcRdLibIfc;
|
||||
|
||||
class NxpNfcFrontend {
|
||||
public:
|
||||
NxpNfcFrontend();
|
||||
~NxpNfcFrontend();
|
||||
|
||||
NxpNfcFrontend(const NxpNfcFrontend&) = delete;
|
||||
NxpNfcFrontend& operator=(const NxpNfcFrontend&) = delete;
|
||||
|
||||
void setDetectionCallback(const std::function<void(const std::pair<std::string, std::vector<std::uint8_t>>&)>&);
|
||||
void setErrorLogCallback(const std::function<void(const std::string&)>&);
|
||||
void run();
|
||||
|
||||
private:
|
||||
std::unique_ptr<NxpNfcRdLibIfc> m_nfclib_ifc;
|
||||
|
||||
static inline std::atomic<bool> s_someInstanceExists{false};
|
||||
};
|
||||
|
||||
} // namespace NxpNfcFrontendWrapper
|
||||
@@ -0,0 +1,12 @@
|
||||
cmake_minimum_required(VERSION 3.15)
|
||||
|
||||
set(DAL_PATH ${PATH_NXPNFCRDLIB}/Platform/DAL)
|
||||
set(PHOSAL_PATH ${PATH_NXPNFCRDLIB}/RTOS/phOsal)
|
||||
set(NXPLIB_PATH ${PATH_NXPNFCRDLIB}/NxpNfcRdLib)
|
||||
|
||||
|
||||
# NOTE: The original CMake build files from NXP's NFC READER LIB are ignored.
|
||||
# The build is defined completely in the 'customization' folder:
|
||||
|
||||
add_subdirectory(customization)
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
cmake_minimum_required(VERSION 3.15)
|
||||
|
||||
set(CUSTOM_DAL_PATH ${CMAKE_CURRENT_SOURCE_DIR}/Platform/DAL)
|
||||
set(CUSTOM_NXPLIB_PATH ${CMAKE_CURRENT_SOURCE_DIR}/NxpNfcRdLib)
|
||||
|
||||
add_subdirectory(Platform/DAL)
|
||||
add_subdirectory(RTOS/phOsal)
|
||||
add_subdirectory(NxpNfcRdLib)
|
||||
|
||||
add_library(NxpRdLib INTERFACE)
|
||||
target_link_libraries(NxpRdLib
|
||||
INTERFACE
|
||||
phOsal
|
||||
DAL
|
||||
NxpRdLib_phNfcLib
|
||||
NxpRdLib_acDiscLoop
|
||||
)
|
||||
@@ -0,0 +1,264 @@
|
||||
cmake_minimum_required(VERSION 3.15)
|
||||
|
||||
|
||||
# Interface library to hold common includes and compile definitions
|
||||
add_library(NxpNfcRdLibCommon INTERFACE)
|
||||
target_include_directories(NxpNfcRdLibCommon
|
||||
# INTERFACE
|
||||
# $<BUILD_INTERFACE:${NXPLIB_PATH}/intfs>
|
||||
# $<BUILD_INTERFACE:${NXPLIB_PATH}/types>
|
||||
# $<BUILD_INTERFACE:${PHOSAL_PATH}/inc>
|
||||
# $<BUILD_INTERFACE:${CUSTOM_NXPLIB_PATH}/types>
|
||||
# $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}/intfs>
|
||||
# $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}/types>
|
||||
# $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}/inc>
|
||||
INTERFACE
|
||||
$<BUILD_INTERFACE:${NXPLIB_PATH}/intfs>
|
||||
$<BUILD_INTERFACE:${NXPLIB_PATH}/types>
|
||||
$<BUILD_INTERFACE:${PHOSAL_PATH}/inc>
|
||||
$<BUILD_INTERFACE:${CUSTOM_NXPLIB_PATH}/types>
|
||||
)
|
||||
target_compile_definitions(NxpNfcRdLibCommon
|
||||
INTERFACE
|
||||
PH_OSAL_LINUX
|
||||
NXPBUILD_CUSTOMER_HEADER_INCLUDED
|
||||
)
|
||||
|
||||
|
||||
add_library(NxpRdLib_phTools)
|
||||
target_sources(NxpRdLib_phTools
|
||||
PRIVATE
|
||||
${NXPLIB_PATH}/comps/phTools/src/phTools.c
|
||||
${NXPLIB_PATH}/comps/phTools/src/phTools_Q.c
|
||||
)
|
||||
target_link_libraries(NxpRdLib_phTools
|
||||
PUBLIC
|
||||
NxpNfcRdLibCommon
|
||||
)
|
||||
|
||||
|
||||
add_library(NxpRdLib_phhalHw)
|
||||
target_sources(NxpRdLib_phhalHw
|
||||
PRIVATE
|
||||
${NXPLIB_PATH}/comps/phhalHw/src/phhalHw.c
|
||||
${NXPLIB_PATH}/comps/phhalHw/src/Rc663/phhalHw_Rc663.c
|
||||
${NXPLIB_PATH}/comps/phhalHw/src/Rc663/phhalHw_Rc663_Cmd.c
|
||||
${NXPLIB_PATH}/comps/phhalHw/src/Rc663/phhalHw_Rc663_Int.c
|
||||
${NXPLIB_PATH}/comps/phhalHw/src/Rc663/phhalHw_Rc663_Wait.c
|
||||
)
|
||||
target_include_directories(NxpRdLib_phhalHw
|
||||
PRIVATE
|
||||
${NXPLIB_PATH}/comps/phhalHw/src/Rc663
|
||||
${DAL_PATH}/inc
|
||||
${CUSTOM_DAL_PATH}/cfg
|
||||
PUBLIC
|
||||
$<BUILD_INTERFACE:${DAL_PATH}/boards>
|
||||
$<BUILD_INTERFACE:${CUSTOM_DAL_PATH}/boards>
|
||||
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}/boards>
|
||||
)
|
||||
target_compile_definitions(NxpRdLib_phhalHw
|
||||
PUBLIC
|
||||
NXPBUILD__PHHAL_HW_RC663
|
||||
PHDRIVER_PI4RC663_BOARD
|
||||
)
|
||||
target_link_libraries(NxpRdLib_phhalHw
|
||||
PRIVATE
|
||||
NxpRdLib_phTools
|
||||
PUBLIC
|
||||
NxpNfcRdLibCommon
|
||||
)
|
||||
|
||||
|
||||
add_library(NxpRdLib_palI14443p3a)
|
||||
target_sources(NxpRdLib_palI14443p3a
|
||||
PRIVATE
|
||||
${NXPLIB_PATH}/comps/phpalI14443p3a/src/phpalI14443p3a.c
|
||||
${NXPLIB_PATH}/comps/phpalI14443p3a/src/Sw/phpalI14443p3a_Sw.c
|
||||
)
|
||||
target_include_directories(NxpRdLib_palI14443p3a
|
||||
PRIVATE
|
||||
${NXPLIB_PATH}/comps/phpalI14443p3a/src/Sw
|
||||
)
|
||||
target_link_libraries(NxpRdLib_palI14443p3a
|
||||
PRIVATE
|
||||
NxpRdLib_phhalHw
|
||||
PUBLIC
|
||||
NxpNfcRdLibCommon
|
||||
)
|
||||
|
||||
|
||||
add_library(NxpRdLib_palMifare)
|
||||
target_sources(NxpRdLib_palMifare
|
||||
PRIVATE
|
||||
${NXPLIB_PATH}/comps/phpalMifare/src/phpalMifare.c
|
||||
${NXPLIB_PATH}/comps/phpalMifare/src/Sw/phpalMifare_Sw.c
|
||||
)
|
||||
target_include_directories(NxpRdLib_palMifare
|
||||
PRIVATE
|
||||
${NXPLIB_PATH}/comps/NxpRdLib_palMifare/src/Sw
|
||||
)
|
||||
target_link_libraries(NxpRdLib_palMifare
|
||||
PRIVATE
|
||||
NxpRdLib_phhalHw
|
||||
PUBLIC
|
||||
NxpNfcRdLibCommon
|
||||
)
|
||||
|
||||
|
||||
add_library(NxpRdLib_palSli15693)
|
||||
target_sources(NxpRdLib_palSli15693
|
||||
PRIVATE
|
||||
${NXPLIB_PATH}/comps/phpalSli15693/src/phpalSli15693.c
|
||||
${NXPLIB_PATH}/comps/phpalSli15693/src/Sw/phpalSli15693_Sw.c
|
||||
)
|
||||
target_include_directories(NxpRdLib_palSli15693
|
||||
PRIVATE
|
||||
${NXPLIB_PATH}/comps/phpalSli15693/src/Sw
|
||||
)
|
||||
target_link_libraries(NxpRdLib_palSli15693
|
||||
PRIVATE
|
||||
NxpRdLib_phhalHw
|
||||
PUBLIC
|
||||
NxpNfcRdLibCommon
|
||||
)
|
||||
|
||||
|
||||
add_library(NxpRdLib_alMfc)
|
||||
target_sources(NxpRdLib_alMfc
|
||||
PRIVATE
|
||||
${NXPLIB_PATH}/comps/phalMfc/src/phalMfc.c
|
||||
${NXPLIB_PATH}/comps/phalMfc/src/phalMfc_Int.c
|
||||
${NXPLIB_PATH}/comps/phalMfc/src/Sw/phalMfc_Sw.c
|
||||
)
|
||||
target_include_directories(NxpRdLib_alMfc
|
||||
PRIVATE
|
||||
${NXPLIB_PATH}/comps/phalMfc/src
|
||||
${NXPLIB_PATH}/comps/phalMfc/src/Sw
|
||||
)
|
||||
target_compile_definitions(NxpRdLib_alMfc
|
||||
PUBLIC
|
||||
NXPBUILD__PHHAL_HW_RC663
|
||||
)
|
||||
target_link_libraries(NxpRdLib_alMfc
|
||||
PRIVATE
|
||||
NxpRdLib_palMifare
|
||||
PUBLIC
|
||||
NxpNfcRdLibCommon
|
||||
)
|
||||
|
||||
|
||||
add_library(NxpRdLib_KeyStore)
|
||||
target_sources(NxpRdLib_KeyStore
|
||||
PRIVATE
|
||||
${NXPLIB_PATH}/comps/phKeyStore/src/phKeyStore.c
|
||||
${NXPLIB_PATH}/comps/phKeyStore/src/Rc663/phKeyStore_Rc663.c
|
||||
${NXPLIB_PATH}/comps/phKeyStore/src/Sw/phKeyStore_Sw.c
|
||||
)
|
||||
target_include_directories(NxpRdLib_KeyStore
|
||||
PRIVATE
|
||||
${NXPLIB_PATH}/comps/phKeyStore/src
|
||||
${NXPLIB_PATH}/comps/phKeyStore/src/Rc663
|
||||
${NXPLIB_PATH}/comps/phKeyStore/src/Sw
|
||||
)
|
||||
target_link_libraries(NxpRdLib_KeyStore
|
||||
PUBLIC
|
||||
NxpNfcRdLibCommon
|
||||
)
|
||||
|
||||
|
||||
add_library(NxpRdLib_phNfcLib)
|
||||
target_sources(NxpRdLib_phNfcLib
|
||||
PRIVATE
|
||||
${NXPLIB_PATH}/comps/phNfcLib/src/phNfcLib.c
|
||||
${NXPLIB_PATH}/comps/phNfcLib/src/phNfcLib_15693.c
|
||||
${NXPLIB_PATH}/comps/phNfcLib/src/phNfcLib_Initialization.c
|
||||
)
|
||||
target_include_directories(NxpRdLib_phNfcLib
|
||||
PRIVATE
|
||||
${NXPLIB_PATH}/comps/phNfcLib/src
|
||||
)
|
||||
target_link_libraries(NxpRdLib_phNfcLib
|
||||
PUBLIC
|
||||
NxpRdLib_phhalHw
|
||||
NxpRdLib_palI14443p3a
|
||||
NxpRdLib_palMifare
|
||||
NxpRdLib_palSli15693
|
||||
NxpRdLib_alMfc
|
||||
NxpRdLib_KeyStore
|
||||
NxpNfcRdLibCommon
|
||||
)
|
||||
|
||||
|
||||
add_library(NxpRdLib_alT1T)
|
||||
target_sources(NxpRdLib_alT1T
|
||||
PRIVATE
|
||||
${NXPLIB_PATH}/comps/phalT1T/src/phalT1T.c
|
||||
${NXPLIB_PATH}/comps/phalT1T/src/Sw/phalT1T_Sw.c
|
||||
)
|
||||
target_include_directories(NxpRdLib_alT1T
|
||||
PRIVATE
|
||||
${NXPLIB_PATH}/comps/phalT1T/src/Sw
|
||||
)
|
||||
target_link_libraries(NxpRdLib_alT1T
|
||||
PUBLIC
|
||||
NxpNfcRdLibCommon
|
||||
)
|
||||
|
||||
|
||||
add_library(NxpRdLib_acDiscLoop)
|
||||
target_sources(NxpRdLib_acDiscLoop
|
||||
PRIVATE
|
||||
${NXPLIB_PATH}/comps/phacDiscLoop/src/phacDiscLoop.c
|
||||
${NXPLIB_PATH}/comps/phacDiscLoop/src/Sw/phacDiscLoop_Sw.c
|
||||
${NXPLIB_PATH}/comps/phacDiscLoop/src/Sw/phacDiscLoop_Sw_Int.c
|
||||
${NXPLIB_PATH}/comps/phacDiscLoop/src/Sw/phacDiscLoop_Sw_Int_A.c
|
||||
${NXPLIB_PATH}/comps/phacDiscLoop/src/Sw/phacDiscLoop_Sw_Int_B.c
|
||||
${NXPLIB_PATH}/comps/phacDiscLoop/src/Sw/phacDiscLoop_Sw_Int_F.c
|
||||
${NXPLIB_PATH}/comps/phacDiscLoop/src/Sw/phacDiscLoop_Sw_Int_I18000p3m3.c
|
||||
${NXPLIB_PATH}/comps/phacDiscLoop/src/Sw/phacDiscLoop_Sw_Int_ECP.c
|
||||
${NXPLIB_PATH}/comps/phacDiscLoop/src/Sw/phacDiscLoop_Sw_Int_V.c
|
||||
)
|
||||
target_include_directories(NxpRdLib_acDiscLoop
|
||||
PRIVATE
|
||||
${NXPLIB_PATH}/comps/phacDiscLoop/src
|
||||
)
|
||||
target_link_libraries(NxpRdLib_acDiscLoop
|
||||
PRIVATE
|
||||
NxpRdLib_phhalHw
|
||||
NxpRdLib_palI14443p3a
|
||||
PUBLIC
|
||||
NxpNfcRdLibCommon
|
||||
)
|
||||
|
||||
|
||||
|
||||
# Theses components have been left out for now.
|
||||
# phalFelica
|
||||
# phalI18000p3m3
|
||||
# phalICode
|
||||
# phalMfdf
|
||||
# phalMfdfEVx
|
||||
# phalMfdfLight
|
||||
# phalMfNtag42XDna
|
||||
# phalMfp
|
||||
# phalMfpEVx
|
||||
# phalMful
|
||||
# phalTop
|
||||
# phalVca
|
||||
# phceT4T
|
||||
# phCidManager
|
||||
# phCryptoRng
|
||||
# phCryptoSym
|
||||
# phlnLlcp
|
||||
# phLog
|
||||
# phnpSnep
|
||||
# phpalEpcUid
|
||||
# phpalFelica
|
||||
# phpalI14443p3b
|
||||
# phpalI14443p4
|
||||
# phpalI14443p4a
|
||||
# phpalI14443p4mC
|
||||
# phpalI18000p3m3
|
||||
# phpalI18092mPI
|
||||
# phpalI18092mT
|
||||
# phTMIUtils
|
||||
@@ -0,0 +1,35 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// Copyright 2020 - 2025 Pionix GmbH and Contributors to EVerest
|
||||
|
||||
/* Definitions for the build of the NXP NFC Reader Library */
|
||||
/* Additional protocols, etc, need to be added here, if required*/
|
||||
|
||||
#ifndef PH_NXPBUILD_APP_H_INC
|
||||
#define PH_NXPBUILD_APP_H_INC
|
||||
|
||||
/** Protocol Abstraction Layer Components */
|
||||
|
||||
#define NXPBUILD__PHPAL_I14443P3A_SW /** ISO 14443-3A SW Component */
|
||||
|
||||
//#define NXPBUILD__PHPAL_MIFARE_SW /**< MIFARE SW Component */
|
||||
|
||||
#define NXPBUILD__PHPAL_SLI15693_SW /**< SLI 15693 Component */
|
||||
|
||||
/** Discovery Loop Properties */
|
||||
|
||||
#define NXPBUILD__PHAC_DISCLOOP_SW /**< Discovery Loop Activity */
|
||||
#define NXPBUILD__PHAC_DISCLOOP_LPCD /**< Low Power Card Detection */
|
||||
#ifdef NXPBUILD__PHPAL_I14443P3A_SW
|
||||
#define NXPBUILD__PHAC_DISCLOOP_TYPEA_I3P3_TAGS /**< SRC/DATA to Detect/Collision Resolute/Activate cards such as MFC, MFUL, MFP SL1 */
|
||||
#endif /* NXPBUILD__PHPAL_I14443P3A_SW */
|
||||
#ifdef NXPBUILD__PHPAL_SLI15693_SW
|
||||
#define NXPBUILD__PHAC_DISCLOOP_TYPEV_TAGS /**< SRC/DATA to Detect Type V Cards */
|
||||
#endif /* NXPBUILD__PHPAL_SLI15693_SW */
|
||||
|
||||
/** Simplified API */
|
||||
|
||||
#define NXPBUILD__PHNFCLIB /**< Simplified API Interface */
|
||||
|
||||
#define NXPBUILD__PH_KEYSTORE_SW /**< SW KeyStore Component */
|
||||
|
||||
#endif /* PH_NXPBUILD_APP_H_INC */
|
||||
@@ -0,0 +1,28 @@
|
||||
cmake_minimum_required(VERSION 3.15)
|
||||
|
||||
project(DAL)
|
||||
|
||||
add_library(DAL)
|
||||
target_sources(DAL
|
||||
PRIVATE
|
||||
${DAL_PATH}/src/Linux/phDriver_Linux_Int.c
|
||||
${DAL_PATH}/src/Linux/phbalReg_Linux_UserSpi.c
|
||||
${DAL_PATH}/src/Linux/phDriver_Linux.c
|
||||
# Add c files in src to provide custom implementation of the GPIO and register access (SPI/I²C) interface
|
||||
# Remove the files given above individually, if a replacement is added below.
|
||||
# Individual replacements:
|
||||
src/rpi4_gpio.c
|
||||
)
|
||||
target_include_directories(DAL
|
||||
PUBLIC
|
||||
$<BUILD_INTERFACE:${DAL_PATH}/src/Linux>
|
||||
$<BUILD_INTERFACE:${DAL_PATH}/inc>
|
||||
$<BUILD_INTERFACE:${DAL_PATH}/boards>
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/boards>
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/cfg>
|
||||
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}/inc>
|
||||
)
|
||||
target_compile_definitions(DAL
|
||||
PUBLIC
|
||||
PHDRIVER_PI4RC663_BOARD
|
||||
)
|
||||
@@ -0,0 +1,44 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// Copyright 2020 - 2025 Pionix GmbH and Contributors to EVerest
|
||||
|
||||
#ifndef CUSTOMIZATION_BOARD_PI4RC663_H
|
||||
#define CUSTOMIZATION_BOARD_PI4RC663_H
|
||||
|
||||
/** Provide RPi4 specific functions (implemented by c-file in src and using existing functions from the NXP DAL)*/
|
||||
void GPIO_reconfigure_pin(size_t gpio, int output_int);
|
||||
phStatus_t GPIO_read_pin(size_t gpio, uint8_t *pGpioVal);
|
||||
phStatus_t GPIO_poll_pin(size_t gpio, int timeOutms);
|
||||
|
||||
/** Enable User space SPI. (Required for RC663 frontend chip) */
|
||||
#define PHDRIVER_LINUX_USER_SPI
|
||||
|
||||
/** Choose GPIOs */
|
||||
#define PHDRIVER_PIN_RESET 536 /** GPIO24 **/
|
||||
#define PHDRIVER_PIN_IRQ 535 /** GPIO23 */
|
||||
|
||||
/** Configure RESET and IRQ pins to pull up/down */
|
||||
#define PHDRIVER_PIN_RESET_PULL_CFG PH_DRIVER_PULL_DOWN
|
||||
#define PHDRIVER_PIN_IRQ_PULL_CFG PH_DRIVER_PULL_UP
|
||||
|
||||
/** Choose trigger type */
|
||||
#define PIN_IRQ_TRIGGER_TYPE PH_DRIVER_INTERRUPT_RISINGEDGE
|
||||
|
||||
/** Front End Reset logic level settings */
|
||||
#define PH_DRIVER_SET_HIGH 1
|
||||
#define PH_DRIVER_SET_LOW 0
|
||||
#define RESET_POWERDOWN_LEVEL PH_DRIVER_SET_HIGH
|
||||
#define RESET_POWERUP_LEVEL PH_DRIVER_SET_LOW
|
||||
|
||||
/** SPI Configuration: "/dev/spidev0.0" @ 5MHz */
|
||||
#define PHDRIVER_USER_SPI_BUS 0
|
||||
#define PHDRIVER_USER_SPI_CS 0
|
||||
#define PHDRIVER_USER_SPI_FREQ 5000000
|
||||
#define PHDRIVER_USER_SPI_CFG_DIR "/dev/spidev"
|
||||
#define PHDRIVER_USER_SPI_CFG_MODE SPI_MODE_0
|
||||
#define PHDRIVER_USER_SPI_CFG_BITS_PER_WORD 8
|
||||
|
||||
/** No functionality in this setup (Linux, SPI); just to suppress build errors */
|
||||
#define PHDRIVER_PIN_SSEL 0xFFFF
|
||||
#define PHDRIVER_PIN_NSS_PULL_CFG PH_DRIVER_PULL_UP
|
||||
|
||||
#endif /* CUSTOMIZATION_BOARD_PI4RC663_H */
|
||||
@@ -0,0 +1,11 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// Copyright 2020 - 2025 Pionix GmbH and Contributors to EVerest
|
||||
|
||||
#ifndef CUSTOMIZATION_BOARDSELECTION_H
|
||||
#define CUSTOMIZATION_BOARDSELECTION_H
|
||||
|
||||
#ifdef PHDRIVER_PI4RC663_BOARD
|
||||
# include <Board_Pi4Rc663.h>
|
||||
#endif
|
||||
|
||||
#endif /* CUSTOMIZATION_BOARDSELECTION_H */
|
||||
@@ -0,0 +1,26 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// Copyright 2020 - 2025 Pionix GmbH and Contributors to EVerest
|
||||
|
||||
#include <phDriver_Linux_Int.h>
|
||||
#include <Board_Pi4Rc663.h>
|
||||
|
||||
// argument output as char, in order to avoid the bool from <stdbool.h> to be carried into the c++ user code
|
||||
void GPIO_reconfigure_pin(size_t gpio, int output_int) {
|
||||
PiGpio_unexport(gpio);
|
||||
PiGpio_export(gpio);
|
||||
bool output = (output_int == 0 ? false : true);
|
||||
PiGpio_set_direction(gpio, output);
|
||||
if (PIN_IRQ_TRIGGER_TYPE == PH_DRIVER_INTERRUPT_RISINGEDGE) {
|
||||
PiGpio_set_edge(gpio, true, false);
|
||||
} else {
|
||||
PiGpio_set_edge(gpio, false, true);
|
||||
}
|
||||
}
|
||||
|
||||
phStatus_t GPIO_read_pin(size_t gpio, uint8_t *pGpioVal) {
|
||||
return PiGpio_read(gpio, pGpioVal);
|
||||
}
|
||||
|
||||
phStatus_t GPIO_poll_pin(size_t gpio, int timeOutms) {
|
||||
return PiGpio_poll(PHDRIVER_PIN_IRQ, 1, timeOutms);
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
cmake_minimum_required(VERSION 3.15)
|
||||
|
||||
project(phOsal)
|
||||
|
||||
find_package(Threads REQUIRED)
|
||||
|
||||
add_library(phOsal)
|
||||
target_sources(phOsal
|
||||
PRIVATE
|
||||
${PHOSAL_PATH}/src/Linux/phOsal_Linux.c
|
||||
)
|
||||
target_include_directories(phOsal
|
||||
PUBLIC
|
||||
$<BUILD_INTERFACE:${PHOSAL_PATH}/inc>
|
||||
$<BUILD_INTERFACE:${PHOSAL_PATH}/src/Linux>
|
||||
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
|
||||
)
|
||||
target_link_libraries(phOsal
|
||||
PRIVATE
|
||||
Threads::Threads -lrt
|
||||
)
|
||||
target_compile_definitions(phOsal
|
||||
PUBLIC
|
||||
PH_OSAL_LINUX
|
||||
)
|
||||
@@ -0,0 +1,297 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// Copyright 2020 - 2025 Pionix GmbH and Contributors to EVerest
|
||||
|
||||
#include <sstream>
|
||||
#include <stdexcept>
|
||||
|
||||
#include <NxpNfcRdLibIfc.hpp>
|
||||
|
||||
using NxpNfcRdLibIfc = NxpNfcFrontendWrapper::NxpNfcRdLibIfc;
|
||||
|
||||
NxpNfcRdLibIfc::NxpNfcRdLibIfc() {
|
||||
phStatus_t status = PH_ERR_INTERNAL_ERROR;
|
||||
|
||||
/* Pre-library initialization phase */
|
||||
/* 1. Prepare OS abstraction layer */
|
||||
status = phOsal_Init();
|
||||
if (status != PH_OSAL_SUCCESS) {
|
||||
std::string error_message = formatErrorInfo("phOsal_Init() failed! (Initialization of "
|
||||
"Operating System Abstraction Layer)",
|
||||
decodeErrorCode(status));
|
||||
throw std::runtime_error(error_message);
|
||||
}
|
||||
|
||||
/* 2. Prepare Bus abstraction layer */
|
||||
status = phbalReg_Init(&m_sBalParams, sizeof(phbalReg_Type_t));
|
||||
if (status != PH_DRIVER_SUCCESS) {
|
||||
std::string error_message = formatErrorInfo("phbalReg_Init() failed! (Initialization of Bus Abstraction Layer)",
|
||||
decodeErrorCode(status));
|
||||
throw std::runtime_error(error_message);
|
||||
}
|
||||
|
||||
/* 3. Tell phNfcLib about Bus abstraction layer */
|
||||
phNfcLib_AppContext_t appContext = {0};
|
||||
appContext.pBalDataparams = &m_sBalParams;
|
||||
status = phNfcLib_SetContext(&appContext);
|
||||
if (status != PH_NFCLIB_STATUS_SUCCESS) {
|
||||
std::string error_message = formatErrorInfo("phNfcLib_SetContext() failed!", decodeErrorCode(status));
|
||||
throw std::runtime_error(error_message);
|
||||
}
|
||||
|
||||
/* Initialize library */
|
||||
status = phNfcLib_Init();
|
||||
if (status != PH_NFCLIB_STATUS_SUCCESS) {
|
||||
std::string error_message = formatErrorInfo("phNfcLib_Init() failed!", decodeErrorCode(status));
|
||||
throw std::runtime_error(error_message);
|
||||
}
|
||||
|
||||
/* Store ptrs to library's internal components' dataparams structs for HAL and DISCLOOP */
|
||||
m_pHal = static_cast<phhalHw_Rc663_DataParams_t*>(phNfcLib_GetDataParams(PH_COMP_HAL));
|
||||
m_pDiscLoop = static_cast<phacDiscLoop_Sw_DataParams_t*>(phNfcLib_GetDataParams(PH_COMP_AC_DISCLOOP));
|
||||
}
|
||||
|
||||
void NxpNfcRdLibIfc::setCallback(const callback_func_t& callback) {
|
||||
m_callback = callback;
|
||||
}
|
||||
|
||||
void NxpNfcRdLibIfc::setErrorCallback(const error_callback_func_t& callback) {
|
||||
m_err_callback = callback;
|
||||
}
|
||||
|
||||
void NxpNfcRdLibIfc::startThreads() {
|
||||
m_irq_poll_thread = std::make_unique<std::thread>(&NxpNfcRdLibIfc::runIrqPollThread, this);
|
||||
m_discloop_thread = std::make_unique<std::thread>(&NxpNfcRdLibIfc::runDiscoveryLoopThread, this);
|
||||
}
|
||||
|
||||
void NxpNfcRdLibIfc::stopThreads() {
|
||||
m_stopFlag = true;
|
||||
|
||||
m_irq_poll_thread->join();
|
||||
m_discloop_thread->join();
|
||||
}
|
||||
|
||||
void NxpNfcRdLibIfc::runDiscoveryLoopThread() {
|
||||
phStatus_t status;
|
||||
|
||||
/* Get RFID Poll Configuration */
|
||||
status = phacDiscLoop_GetConfig(m_pDiscLoop, PHAC_DISCLOOP_CONFIG_PAS_POLL_TECH_CFG, &m_bSavePollTechCfg);
|
||||
if (status != PH_ERR_SUCCESS) {
|
||||
std::string error_message = formatErrorInfo("phacDiscLoop_GetConfig() failed!", decodeErrorCode(status));
|
||||
throw std::runtime_error(error_message);
|
||||
}
|
||||
|
||||
/* Switch off RF field */
|
||||
status = phhalHw_FieldOff(m_pHal);
|
||||
if (status != PH_ERR_SUCCESS) {
|
||||
std::string error_message = formatErrorInfo("Initial phhalHw_FieldOff() failed!", decodeErrorCode(status));
|
||||
throw std::runtime_error(error_message);
|
||||
}
|
||||
|
||||
// From now on, no more exception throwing, because the loop should keep running
|
||||
uint16_t wEntryPoint = PHAC_DISCLOOP_ENTRY_POINT_POLL;
|
||||
while (!m_stopFlag) {
|
||||
status = phacDiscLoop_SetConfig(m_pDiscLoop, PHAC_DISCLOOP_CONFIG_NEXT_POLL_STATE,
|
||||
PHAC_DISCLOOP_POLL_STATE_DETECTION);
|
||||
if (status != PH_ERR_SUCCESS) {
|
||||
doErrorCallback("Discovery Loop: phacDiscLoop_SetConfig: ", decodeErrorCode(status));
|
||||
}
|
||||
|
||||
/* Start discovery loop */
|
||||
status = phacDiscLoop_Run(m_pDiscLoop, wEntryPoint);
|
||||
decodeDiscLoopStatusAndCallback(status);
|
||||
|
||||
/* Set Poll Configuration */
|
||||
status = phacDiscLoop_SetConfig(m_pDiscLoop, PHAC_DISCLOOP_CONFIG_PAS_POLL_TECH_CFG, m_bSavePollTechCfg);
|
||||
if (status != PH_ERR_SUCCESS) {
|
||||
doErrorCallback("Discovery Loop: phacDiscLoop_SetConfig: ", decodeErrorCode(status));
|
||||
}
|
||||
|
||||
/* Switch off RF field */
|
||||
status = phhalHw_FieldOff(m_pHal);
|
||||
if (status != PH_ERR_SUCCESS) {
|
||||
doErrorCallback("Discovery Loop: phhalHw_FieldOff: ", decodeErrorCode(status));
|
||||
}
|
||||
|
||||
/* Wait for field-off time-out */
|
||||
status = phhalHw_Wait(m_pHal, PHHAL_HW_TIME_MICROSECONDS, 5100);
|
||||
if (status != PH_ERR_SUCCESS) {
|
||||
doErrorCallback("Discovery Loop: phhalHw_Wait: ", decodeErrorCode(status));
|
||||
}
|
||||
|
||||
phOsal_ThreadDelay(HI_LEVEL_LOOP_DELAY_MS);
|
||||
}
|
||||
/* Switch off RF field */
|
||||
phhalHw_FieldOff(m_pHal);
|
||||
}
|
||||
|
||||
void NxpNfcRdLibIfc::runIrqPollThread() {
|
||||
uint8_t gpioValue = 0;
|
||||
|
||||
while (GPIO_read_pin(PHDRIVER_PIN_IRQ, &gpioValue) != PH_ERR_SUCCESS) {
|
||||
GPIO_reconfigure_pin(PHDRIVER_PIN_IRQ, false);
|
||||
}
|
||||
|
||||
// If it happens to be necessary call the IRQ handler now
|
||||
if (gpioValue == 1) {
|
||||
IrqHandler();
|
||||
}
|
||||
|
||||
while (!m_stopFlag) {
|
||||
// Wait for the IRQ PIN to change, but wait until the timeout only
|
||||
if (GPIO_poll_pin(PHDRIVER_PIN_IRQ, 1000) == PH_ERR_SUCCESS) {
|
||||
IrqHandler();
|
||||
} else {
|
||||
GPIO_reconfigure_pin(PHDRIVER_PIN_IRQ, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GPIO_reconfigure_pin(size_t gpio) {
|
||||
PiGpio_unexport(PHDRIVER_PIN_IRQ);
|
||||
PiGpio_export(PHDRIVER_PIN_IRQ);
|
||||
PiGpio_set_direction(PHDRIVER_PIN_IRQ, false);
|
||||
if (PIN_IRQ_TRIGGER_TYPE == PH_DRIVER_INTERRUPT_RISINGEDGE) {
|
||||
PiGpio_set_edge(PHDRIVER_PIN_IRQ, true, false);
|
||||
} else {
|
||||
PiGpio_set_edge(PHDRIVER_PIN_IRQ, false, true);
|
||||
}
|
||||
}
|
||||
|
||||
void NxpNfcRdLibIfc::IrqHandler() {
|
||||
if (phDriver_PinRead(PHDRIVER_PIN_IRQ, PH_DRIVER_PINFUNC_INTERRUPT)) {
|
||||
phDriver_PinClearIntStatus(PHDRIVER_PIN_IRQ);
|
||||
|
||||
if (m_pHal->pRFISRCallback != NULL) {
|
||||
m_pHal->pRFISRCallback(m_pHal);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NxpNfcRdLibIfc::decodeDiscLoopStatusAndCallback(phStatus_t discLoopStatus) {
|
||||
switch (discLoopStatus & PH_ERR_MASK) {
|
||||
case PHAC_DISCLOOP_MULTI_TECH_DETECTED: // Do not try to resolve multi-tech collision
|
||||
case PHAC_DISCLOOP_MULTI_DEVICES_RESOLVED: // Do not try to resolve multi-device collision
|
||||
case PHAC_DISCLOOP_NO_TECH_DETECTED: // Nothing to be done here
|
||||
case PHAC_DISCLOOP_NO_DEVICE_RESOLVED: // Nothing to be done here
|
||||
case PHAC_DISCLOOP_EXTERNAL_RFON: // External RF is ignored
|
||||
case PHAC_DISCLOOP_MERGED_SEL_RES_FOUND: // T4T or NFC-DEP devices are ignored
|
||||
break;
|
||||
case PHAC_DISCLOOP_DEVICE_ACTIVATED:
|
||||
handleActivatedDevice();
|
||||
break;
|
||||
case PHAC_DISCLOOP_ACTIVE_TARGET_ACTIVATED: // Do not try to connect to active targets
|
||||
case PHAC_DISCLOOP_PASSIVE_TARGET_ACTIVATED: // Do not try to connect to passive targets
|
||||
case PHAC_DISCLOOP_LPCD_NO_TECH_DETECTED: // Nothing to be done here
|
||||
break;
|
||||
case PHAC_DISCLOOP_FAILURE: {
|
||||
handleDiscoveryLoopFailure();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
doErrorCallback("Decoding discovery loop status failed", decodeErrorCode(0x00));
|
||||
}
|
||||
}
|
||||
|
||||
void NxpNfcRdLibIfc::handleActivatedDevice() {
|
||||
uint16_t noOfTagsDetected = 0;
|
||||
phStatus_t status = phacDiscLoop_GetConfig(m_pDiscLoop, PHAC_DISCLOOP_CONFIG_NR_TAGS_FOUND, &noOfTagsDetected);
|
||||
|
||||
if (status != PH_ERR_SUCCESS or noOfTagsDetected > 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Get Detected Technology Type */
|
||||
uint16_t technologyCodeDetected = 0;
|
||||
status = phacDiscLoop_GetConfig(m_pDiscLoop, PHAC_DISCLOOP_CONFIG_TECH_DETECTED, &technologyCodeDetected);
|
||||
|
||||
if (status != PH_ERR_SUCCESS) {
|
||||
return;
|
||||
}
|
||||
|
||||
NxpNfcRdLibIfc::Technology technology = NxpNfcRdLibIfc::decodeTechnology(m_pDiscLoop, technologyCodeDetected);
|
||||
|
||||
if (technology == NxpNfcRdLibIfc::Technology::UNKNOWN) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<std::uint8_t> uid = NxpNfcRdLibIfc::getUID(m_pDiscLoop, technology);
|
||||
|
||||
if (m_callback) {
|
||||
m_callback(technology, uid);
|
||||
}
|
||||
}
|
||||
|
||||
void NxpNfcRdLibIfc::handleDiscoveryLoopFailure() {
|
||||
uint16_t additionalInfo;
|
||||
phStatus_t status = phacDiscLoop_GetConfig(m_pDiscLoop, PHAC_DISCLOOP_CONFIG_ADDITIONAL_INFO, &additionalInfo);
|
||||
if (status != PH_ERR_SUCCESS) {
|
||||
doErrorCallback("PHAC_DISCLOOP_FAILURE: Trying to get additional Information failed: ",
|
||||
decodeErrorCode(status));
|
||||
return;
|
||||
}
|
||||
doErrorCallback("Decoding discovery loop status failed (PHAC_DISCLOOP_FAILURE)", decodeErrorCode(additionalInfo));
|
||||
}
|
||||
|
||||
void NxpNfcRdLibIfc::doErrorCallback(std::string customText, ErrorInfo errorInfo) {
|
||||
std::string formattedMessage = formatErrorInfo(customText, errorInfo);
|
||||
|
||||
if (m_err_callback) {
|
||||
m_err_callback(formattedMessage);
|
||||
}
|
||||
}
|
||||
|
||||
// static helpers
|
||||
std::string NxpNfcRdLibIfc::formatErrorInfo(const std::string& customText, const ErrorInfo& errorInfo) {
|
||||
return customText + ": Error in component '" + errorInfo.component + "': " + errorInfo.type;
|
||||
}
|
||||
|
||||
NxpNfcRdLibIfc::Technology NxpNfcRdLibIfc::decodeTechnology(phacDiscLoop_Sw_DataParams_t* pDataParams,
|
||||
uint16_t techCode) {
|
||||
if (PHAC_DISCLOOP_CHECK_ANDMASK(techCode, PHAC_DISCLOOP_POS_BIT_MASK_A)) {
|
||||
if (pDataParams->sTypeATargetInfo.bT1TFlag) {
|
||||
return NxpNfcRdLibIfc::Technology::ISO14443A_T1;
|
||||
} else {
|
||||
if ((pDataParams->sTypeATargetInfo.aTypeA_I3P3[0].aSak & (uint8_t)0x04) == 0) {
|
||||
uint8_t tagType = (pDataParams->sTypeATargetInfo.aTypeA_I3P3[0].aSak & 0x60) >> 5;
|
||||
|
||||
switch (tagType) {
|
||||
case PHAC_DISCLOOP_TYPEA_TYPE2_TAG_CONFIG_MASK:
|
||||
return NxpNfcRdLibIfc::Technology::ISO14443A_T2;
|
||||
case PHAC_DISCLOOP_TYPEA_TYPE4A_TAG_CONFIG_MASK:
|
||||
return NxpNfcRdLibIfc::Technology::ISO14443A_T4A;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (PHAC_DISCLOOP_CHECK_ANDMASK(techCode, PHAC_DISCLOOP_POS_BIT_MASK_V)) {
|
||||
return NxpNfcRdLibIfc::Technology::ISO15693;
|
||||
}
|
||||
|
||||
return NxpNfcRdLibIfc::Technology::UNKNOWN;
|
||||
}
|
||||
|
||||
std::vector<std::uint8_t> NxpNfcRdLibIfc::getUID(phacDiscLoop_Sw_DataParams_t* pDataParams,
|
||||
NxpNfcRdLibIfc::Technology technology) {
|
||||
int length = 0;
|
||||
uint8_t* uidArray = nullptr;
|
||||
|
||||
switch (technology) {
|
||||
case NxpNfcRdLibIfc::Technology::ISO14443A_T1:
|
||||
case NxpNfcRdLibIfc::Technology::ISO14443A_T2:
|
||||
case NxpNfcRdLibIfc::Technology::ISO14443A_T4A:
|
||||
length = pDataParams->sTypeATargetInfo.aTypeA_I3P3[0].bUidSize;
|
||||
uidArray = pDataParams->sTypeATargetInfo.aTypeA_I3P3[0].aUid;
|
||||
break;
|
||||
case NxpNfcRdLibIfc::Technology::ISO15693:
|
||||
length = 8;
|
||||
uidArray = pDataParams->sTypeVTargetInfo.aTypeV[0].aUid;
|
||||
break;
|
||||
case NxpNfcRdLibIfc::Technology::UNKNOWN: {
|
||||
}
|
||||
}
|
||||
|
||||
if (uidArray) {
|
||||
return std::vector<uint8_t>(uidArray, uidArray + length);
|
||||
} else {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// Copyright 2020 - 2025 Pionix GmbH and Contributors to EVerest
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <atomic>
|
||||
#include <cstdint>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
|
||||
#include "NxpNfcRdLibIncludes.hpp"
|
||||
|
||||
namespace NxpNfcFrontendWrapper {
|
||||
|
||||
class NxpNfcRdLibIfc {
|
||||
public:
|
||||
enum class Technology {
|
||||
UNKNOWN,
|
||||
ISO14443A_T1,
|
||||
ISO14443A_T2,
|
||||
ISO14443A_T4A,
|
||||
ISO15693,
|
||||
};
|
||||
|
||||
NxpNfcRdLibIfc();
|
||||
|
||||
using callback_func_t = std::function<void(const NxpNfcRdLibIfc::Technology&, const std::vector<std::uint8_t>&)>;
|
||||
using error_callback_func_t = std::function<void(const std::string&)>;
|
||||
|
||||
void setCallback(const callback_func_t& callback);
|
||||
void setErrorCallback(const error_callback_func_t& callback);
|
||||
void startThreads();
|
||||
void stopThreads();
|
||||
|
||||
private:
|
||||
void decodeDiscLoopStatusAndCallback(phStatus_t);
|
||||
void handleActivatedDevice();
|
||||
void handleDiscoveryLoopFailure();
|
||||
void IrqHandler();
|
||||
void runIrqPollThread();
|
||||
void runDiscoveryLoopThread();
|
||||
void doErrorCallback(std::string, ErrorInfo);
|
||||
|
||||
static std::string formatErrorInfo(const std::string&, const ErrorInfo&);
|
||||
static NxpNfcRdLibIfc::Technology decodeTechnology(phacDiscLoop_Sw_DataParams_t*, uint16_t);
|
||||
static std::vector<std::uint8_t> getUID(phacDiscLoop_Sw_DataParams_t*, NxpNfcRdLibIfc::Technology);
|
||||
|
||||
callback_func_t m_callback;
|
||||
error_callback_func_t m_err_callback;
|
||||
std::atomic<bool> m_stopFlag{false};
|
||||
|
||||
// Nxp Nfc Rd Lib Context
|
||||
uint16_t m_bSavePollTechCfg =
|
||||
PHAC_DISCLOOP_POS_BIT_MASK_A | PHAC_DISCLOOP_POS_BIT_MASK_V; // Configure to detect ISO14443A and 15693 cards
|
||||
phbalReg_Type_t m_sBalParams;
|
||||
phhalHw_Rc663_DataParams_t* m_pHal;
|
||||
phacDiscLoop_Profile_t m_bProfile = PHAC_DISCLOOP_PROFILE_UNKNOWN;
|
||||
phacDiscLoop_Sw_DataParams_t* m_pDiscLoop;
|
||||
|
||||
std::unique_ptr<std::thread> m_irq_poll_thread;
|
||||
std::unique_ptr<std::thread> m_discloop_thread;
|
||||
};
|
||||
|
||||
} // namespace NxpNfcFrontendWrapper
|
||||
@@ -0,0 +1,32 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// Copyright 2020 - 2025 Pionix GmbH and Contributors to EVerest
|
||||
|
||||
#ifndef SRC_NXPNFCRDLIBINCLUDES_HPP_
|
||||
#define SRC_NXPNFCRDLIBINCLUDES_HPP_
|
||||
|
||||
#include <string>
|
||||
|
||||
extern "C" {
|
||||
#include <phDriver.h>
|
||||
#include <phDriver_Linux_Int.h>
|
||||
#include <phNfcLib.h>
|
||||
#include <ph_Status.h>
|
||||
|
||||
#include <BoardSelection.h>
|
||||
}
|
||||
|
||||
// undo definition from NxpNfcRdLib which defines bool as unsigned char
|
||||
#ifdef bool
|
||||
#undef bool
|
||||
#endif
|
||||
|
||||
#define HI_LEVEL_LOOP_DELAY_MS 200
|
||||
|
||||
struct ErrorInfo {
|
||||
std::string component;
|
||||
std::string type;
|
||||
};
|
||||
|
||||
ErrorInfo decodeErrorCode(phStatus_t);
|
||||
|
||||
#endif // SRC_NXPNFCRDLIBINCLUDES_HPP_
|
||||
@@ -0,0 +1,106 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// Copyright 2020 - 2025 Pionix GmbH and Contributors to EVerest
|
||||
|
||||
#include <iomanip>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "NxpNfcRdLibIncludes.hpp"
|
||||
|
||||
namespace {
|
||||
const std::unordered_map<phStatus_t, std::string> componentMapping = {{PH_COMP_BAL, "BAL"},
|
||||
{PH_COMP_HAL, "HAL"},
|
||||
{PH_COMP_PAL_ISO14443P3A, "PAL_ISO14443P3A"},
|
||||
{PH_COMP_PAL_ISO14443P3B, "PAL_ISO14443P3B"},
|
||||
{PH_COMP_PAL_ISO14443P4A, "PAL_ISO14443P4A"},
|
||||
{PH_COMP_PAL_ISO14443P4, "PAL_ISO14443P4"},
|
||||
{PH_COMP_PAL_FELICA, "PAL_FELICA"},
|
||||
{PH_COMP_PAL_EPCUID, "PAL_EPCUID"},
|
||||
{PH_COMP_PAL_SLI15693, "PAL_SLI15693"},
|
||||
{PH_COMP_PAL_I18000P3M3, "PAL_I18000P3M3"},
|
||||
{PH_COMP_PAL_I18092MPI, "PAL_I18092MPI"},
|
||||
{PH_COMP_PAL_I18092MT, "PAL_I18092MT"},
|
||||
{PH_COMP_PAL_I14443P4MC, "PAL_I14443P4MC"},
|
||||
{PH_COMP_AC_DISCLOOP, "AC_DISCLOOP"},
|
||||
{PH_COMP_OSAL, "OSAL"},
|
||||
{PH_COMP_DRIVER, "DRIVER"}};
|
||||
|
||||
static const std::unordered_map<phStatus_t, std::string> phOsalErrorTypeMapping = {
|
||||
{PH_OSAL_IO_TIMEOUT, "IO_TIMEOUT"},
|
||||
{PH_OSAL_ERROR, "ERROR"},
|
||||
{PH_OSAL_FAILURE, "FAILURE"},
|
||||
{PH_OSAL_UNSUPPORTED_COMMAND, "UNSUPPORTED_COMMAND"}};
|
||||
|
||||
static const std::unordered_map<phStatus_t, std::string> balErrorTypeMapping = {{PH_DRIVER_TIMEOUT, "TIMEOUT"},
|
||||
{PH_DRIVER_ABORTED, "ABORTED"},
|
||||
{PH_DRIVER_ERROR, "ERROR"},
|
||||
{PH_DRIVER_FAILURE, "FAILURE"}};
|
||||
|
||||
static const std::unordered_map<phStatus_t, std::string> errorTypeMapping = {
|
||||
{PH_ERR_IO_TIMEOUT, "IO_TIMEOUT"},
|
||||
{PH_ERR_INTEGRITY_ERROR, "INTEGRITY_ERROR"},
|
||||
{PH_ERR_COLLISION_ERROR, "COLLISION_ERROR"},
|
||||
{PH_ERR_BUFFER_OVERFLOW, "BUFFER_OVERFLOW"},
|
||||
{PH_ERR_FRAMING_ERROR, "FRAMING_ERROR"},
|
||||
{PH_ERR_PROTOCOL_ERROR, "PROTOCOL_ERROR"},
|
||||
{PH_ERR_AUTH_ERROR, "AUTH_ERROR"},
|
||||
{PH_ERR_READ_WRITE_ERROR, "READ_WRITE_ERROR"},
|
||||
{PH_ERR_TEMPERATURE_ERROR, "TEMPERATURE_ERROR"},
|
||||
{PH_ERR_RF_ERROR, "RF_ERROR"},
|
||||
{PH_ERR_INTERFACE_ERROR, "INTERFACE_ERROR"},
|
||||
{PH_ERR_LENGTH_ERROR, "LENGTH_ERROR"},
|
||||
{PH_ERR_RESOURCE_ERROR, "RESOURCE_ERROR"},
|
||||
{PH_ERR_TX_NAK_ERROR, "TX_NAK_ERROR"},
|
||||
{PH_ERR_RX_NAK_ERROR, "RX_NAK_ERROR"},
|
||||
{PH_ERR_EXT_RF_ERROR, "EXT_RF_ERROR"},
|
||||
{PH_ERR_NOISE_ERROR, "NOISE_ERROR"},
|
||||
{PH_ERR_ABORTED, "ABORTED"},
|
||||
{PH_ERR_LPCD_ABORTED, "LPCD_ABORTED"},
|
||||
|
||||
{PH_ERR_INTERNAL_ERROR, "INTERNAL_ERROR"},
|
||||
{PH_ERR_INVALID_DATA_PARAMS, "INVALID_DATA_PARAMS"},
|
||||
{PH_ERR_INVALID_PARAMETER, "INVALID_PARAMETER"},
|
||||
{PH_ERR_PARAMETER_OVERFLOW, "PARAMETER_OVERFLOW"},
|
||||
{PH_ERR_UNSUPPORTED_PARAMETER, "UNSUPPORTED_PARAMETER"},
|
||||
{PH_ERR_UNSUPPORTED_COMMAND, "UNSUPPORTED_COMMAND"},
|
||||
{PH_ERR_USE_CONDITION, "USE_CONDITION"},
|
||||
{PH_ERR_KEY, "KEY"},
|
||||
{PH_ERR_PARAMETER_SIZE, "PARAMETER_SIZE"},
|
||||
{PH_ERR_UNKNOWN, "UNKNOWN"},
|
||||
|
||||
{PH_ERR_INTERNAL_ERROR, "INTERNAL_ERROR"},
|
||||
{PH_ERR_AUTH_DELAY, "AUTH_DELAY"}};
|
||||
} // namespace
|
||||
|
||||
ErrorInfo decodeErrorCode(phStatus_t wStatus) {
|
||||
phStatus_t componentCode = wStatus & PH_COMP_MASK;
|
||||
phStatus_t errorTypeCode = wStatus & PH_ERR_MASK;
|
||||
|
||||
std::string component;
|
||||
std::string type;
|
||||
|
||||
try {
|
||||
component = componentMapping.at(componentCode);
|
||||
} catch (const std::out_of_range& e) {
|
||||
std::ostringstream oss;
|
||||
oss << std::setfill('0') << std::setw(2) << "0x" << std::uppercase << std::hex << componentCode;
|
||||
component = oss.str();
|
||||
}
|
||||
|
||||
try {
|
||||
if (componentCode == PH_COMP_OSAL) {
|
||||
type = phOsalErrorTypeMapping.at(errorTypeCode);
|
||||
} else if (componentCode == PH_COMP_DRIVER) {
|
||||
type = balErrorTypeMapping.at(errorTypeCode);
|
||||
} else {
|
||||
type = errorTypeMapping.at(errorTypeCode);
|
||||
}
|
||||
} catch (const std::out_of_range& e) {
|
||||
std::ostringstream oss;
|
||||
oss << std::setfill('0') << std::setw(2) << "0x" << std::uppercase << std::hex << errorTypeCode;
|
||||
type = oss.str();
|
||||
}
|
||||
|
||||
return {component, type};
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// Copyright 2020 - 2025 Pionix GmbH and Contributors to EVerest
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <NxpNfcRdLibIfc.hpp>
|
||||
#include <nxpnfcfrontend.hpp>
|
||||
#include <stdexcept>
|
||||
|
||||
using NxpNfcFrontend = NxpNfcFrontendWrapper::NxpNfcFrontend;
|
||||
|
||||
NxpNfcFrontend::NxpNfcFrontend() {
|
||||
if (s_someInstanceExists) {
|
||||
throw std::runtime_error("Only one NxpNfcFrontend Instance allowed!");
|
||||
}
|
||||
|
||||
s_someInstanceExists = true;
|
||||
|
||||
m_nfclib_ifc = std::make_unique<NxpNfcRdLibIfc>();
|
||||
}
|
||||
|
||||
NxpNfcFrontend::~NxpNfcFrontend() {
|
||||
m_nfclib_ifc->stopThreads();
|
||||
|
||||
s_someInstanceExists = false;
|
||||
}
|
||||
|
||||
void NxpNfcFrontend::setDetectionCallback(
|
||||
const std::function<void(const std::pair<std::string, std::vector<std::uint8_t>>&)>& callback) {
|
||||
m_nfclib_ifc->setCallback([callback](NxpNfcRdLibIfc::Technology technology, std::vector<std::uint8_t> uid_vec) {
|
||||
std::string protocol;
|
||||
switch (technology) {
|
||||
case NxpNfcRdLibIfc::Technology::ISO14443A_T1:
|
||||
case NxpNfcRdLibIfc::Technology::ISO14443A_T2:
|
||||
case NxpNfcRdLibIfc::Technology::ISO14443A_T4A:
|
||||
protocol = "ISO14443";
|
||||
break;
|
||||
case NxpNfcRdLibIfc::Technology::ISO15693:
|
||||
protocol = "ISO15693";
|
||||
break;
|
||||
default:
|
||||
protocol = "UNKNOWN";
|
||||
}
|
||||
callback({protocol, uid_vec});
|
||||
});
|
||||
}
|
||||
|
||||
void NxpNfcFrontend::setErrorLogCallback(const std::function<void(const std::string&)>& callback) {
|
||||
m_nfclib_ifc->setErrorCallback(callback);
|
||||
}
|
||||
|
||||
void NxpNfcFrontend::run() {
|
||||
m_nfclib_ifc->startThreads();
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
cmake_minimum_required(VERSION 3.15)
|
||||
project(nxpnfcfrontendDemo
|
||||
LANGUAGES CXX)
|
||||
|
||||
add_executable(nfc_test_application)
|
||||
target_sources(nfc_test_application PRIVATE src/nfc_test_application.cpp)
|
||||
target_compile_definitions(nfc_test_application PRIVATE DEBUG)
|
||||
|
||||
target_include_directories(nfc_test_application
|
||||
PRIVATE
|
||||
include
|
||||
)
|
||||
|
||||
target_link_libraries(nfc_test_application PRIVATE NxpNfcFrontend)
|
||||
@@ -0,0 +1,50 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// Copyright 2020 - 2025 Pionix GmbH and Contributors to EVerest
|
||||
|
||||
#include <chrono>
|
||||
#include <csignal>
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <thread>
|
||||
|
||||
#include <nxpnfcfrontend.hpp>
|
||||
|
||||
bool stop = false;
|
||||
|
||||
void handleSigInt(int sig) {
|
||||
std::cout << "Caught signal " << sig << " (Ctrl+C)" << std::endl;
|
||||
stop = true;
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
std::signal(SIGINT, handleSigInt);
|
||||
|
||||
auto callback = [](const std::pair<std::string, std::vector<std::uint8_t>>& reply) {
|
||||
auto& [protocol, nfcid] = reply;
|
||||
std::cout << "Detected Card\n Type : '" << protocol << "'\n";
|
||||
std::cout << " Length: " << nfcid.size() << "\n";
|
||||
std::cout << " UID : ";
|
||||
for (std::uint16_t byte : nfcid) {
|
||||
std::cout << std::setfill('0') << std::setw(2) << std::uppercase << std::hex << byte;
|
||||
}
|
||||
std::cout << std::endl;
|
||||
};
|
||||
|
||||
auto error_callback = [](const std::string& error_message) {
|
||||
std::cerr << "ERROR: " << error_message << std::endl;
|
||||
};
|
||||
|
||||
std::cout << "NFC client:" << std::endl;
|
||||
NxpNfcFrontendWrapper::NxpNfcFrontend frontend{};
|
||||
frontend.setDetectionCallback(callback);
|
||||
frontend.setErrorLogCallback(error_callback);
|
||||
std::cout << "Starting the loop" << std::endl;
|
||||
frontend.run();
|
||||
while (!stop) {
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(200));
|
||||
}
|
||||
// destructor of NxpNfcFrontend will stop the internal threads
|
||||
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user