diff --git a/.gitignore b/.gitignore index 64f9553..905cdbd 100644 --- a/.gitignore +++ b/.gitignore @@ -65,4 +65,7 @@ Makefile # Editor *.orig -*.rej \ No newline at end of file +*.rej + +# build dirs +build-* diff --git a/CMakeLists.txt b/CMakeLists.txt index 5f6aea0..f5fc2a5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,14 +5,25 @@ project(libnfcnci DESCRIPTION "NFC NCI library adapted for use with EVerest" LANGUAGES C CXX) +include(GNUInstallDirs) + find_package(everest-cmake 0.1 REQUIRED PATHS ../everest-cmake ) find_package(Threads REQUIRED) -find_library(LIBRT rt) + option(LIBNFCNCI_BUILD_EXAMPLES "enable building of examples" OFF) option(LIBNFCNCI_INSTALL "Install the library (shared data might be installed anyway)" ${EVC_MAIN_PROJECT}) +option(LIBNFCNCI_LIBGPIOD "Build with libgpiod support" OFF) + +if (LIBNFCNCI_LIBGPIOD) + # search for package PkgConfig + find_package(PkgConfig REQUIRED) + + # search for libgpiod + pkg_search_module(LIBGPIOD REQUIRED libgpiodcxx) +endif() if (NOT LIBNFCNCI_CONFIG_INSTALL_PATH) set (LIBNFCNCI_CONFIG_INSTALL_PATH "${CMAKE_INSTALL_SYSCONFDIR}/everest/libnfc_config/") @@ -23,6 +34,14 @@ set (LIBNFCNCI_CONFIG_FILES conf/libnfc-nxp.conf ) +set(LIBNFCNCI_PUBLIC_HEADERS + src/include/linux_nfc_api.h + src/include/linux_nfc_api_compatibility.h + src/include/linux_nfc_factory_api.h +) + +set(LIBNFCNCI_SOVERSION 1) + set (LIBNFCNCI_SOURCES src/android/utility/base/file.cpp src/libnfc-utils/src/ConfigPathProvider.cc @@ -227,10 +246,11 @@ set (COMPILE_DEFINITIONS -DSNEP_ENABLED ) + # # library target # -add_library(libnfc_nci) +add_library(libnfc_nci SHARED) add_library(libnfc_nci::libnfc_nci ALIAS libnfc_nci) target_sources(libnfc_nci @@ -242,7 +262,9 @@ target_sources(libnfc_nci target_compile_definitions(libnfc_nci PRIVATE - ${COMPILE_DEFINITIONS}) + ${COMPILE_DEFINITIONS} + $<$:USE_LIBGPIOD> +) # NOTE (aw): this is dangerous target_compile_options(libnfc_nci @@ -261,9 +283,27 @@ target_include_directories(libnfc_nci target_link_libraries(libnfc_nci PRIVATE Threads::Threads - ${LIBRT} ) +set_target_properties(libnfc_nci + PROPERTIES + VERSION ${PROJECT_VERSION} + SOVERSION ${LIBNFCNCI_SOVERSION} + OUTPUT_NAME nfc_nci +) + +if(LIBNFCNCI_LIBGPIOD) + target_include_directories(libnfc_nci + PRIVATE + ${LIBGPIOD_INCLUDE_DIRS} + ) + + target_link_libraries(libnfc_nci + PRIVATE + ${LIBGPIOD_LIBRARIES} + ) +endif() + # # examples # @@ -277,6 +317,10 @@ if(LIBNFCNCI_BUILD_EXAMPLES) PRIVATE libnfc_nci ) + install( + TARGETS nfc_cb_example + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} + ) add_executable(nfc_demo) target_sources(nfc_demo @@ -288,6 +332,10 @@ if(LIBNFCNCI_BUILD_EXAMPLES) PRIVATE libnfc_nci ) + install( + TARGETS nfc_demo + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} + ) endif() # @@ -297,10 +345,14 @@ if (LIBNFCNCI_INSTALL) install( TARGETS libnfc_nci EXPORT libnfc_nci-targets + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} + INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} ) install( - DIRECTORY src/include/ + FILES ${LIBNFCNCI_PUBLIC_HEADERS} TYPE INCLUDE ) @@ -314,6 +366,10 @@ if (LIBNFCNCI_INSTALL) NAMESPACE libnfc_nci ADDITIONAL_CONTENT "find_dependency(Threads)" + "set(LIBNFCNCI_LIBGPIOD @LIBNFCNCI_LIBGPIOD@)" + "if(LIBNFCNCI_LIBGPIOD)" + " find_dependency(PkgConfig)" + " pkg_search_module(LIBGPIOD REQUIRED libgpiodcxx)" + "endif()" ) endif() - diff --git a/README.md b/README.md index b151f56..749ef10 100755 --- a/README.md +++ b/README.md @@ -12,6 +12,7 @@ The [original upstream source code](https://github.com/NXPNFCLinux/linux_libnfc- - Added CMakeLists.txt - Allow for runtime configuration of interface properties for alternative I²C/SPI interface - Allow configuration files to be in a custom path +- Added support for using GPIO line names via libgpiod ## Building @@ -51,6 +52,13 @@ cmake --install . ``` This will also install the configuration files into the expected folder. +### libgpiod + +Building against `libgpiod` can be enabled by passing the property `LIBNFCNCI_LIBGPIOD` set to `ON` to cmake. +By default, this is disabled. +Using libgpiod and GPIO line names should be the preferred way to access GPIO lines from user-space since +the older Linux' sysfs interface is deprecated since ages. + ## Runtime Configuration Runtime configuration (debug output levels, detailled NFC behaviour, interface specification) happens via the above-mentioned files. @@ -65,7 +73,6 @@ Relevant settings are: ``` NXP_TRANSPORT=0x02 -NXP_NFC_DEV_NODE="/dev/nxpnfc" PIN_INT=535 PIN_ENABLE=536 PIN_FWDNLD=537 @@ -74,6 +81,20 @@ I2C_BUS="/dev/i2c-1" SPI_BUS="/dev/spidev0.0" ``` +When compiled with libgpiod support, then instead of using integers for Linux' legacy sysfs interface, +it is possible to use GPIO line names. These are usually defined via Device Tree for your board. +Such line names must be enclosed in quotation marks to indicate that the configuration value is a string. +And it cannot be mixed: all pin configuration values needs to be GPIO line names. + +``` +NXP_TRANSPORT=0x02 +PIN_INT="RFID_IRQ" +PIN_ENABLE="nRESET_RFID" +PIN_FWDNLD="RFID_DWL_REQ" +I2C_ADDRESS=0x28 +I2C_BUS="/dev/i2c-1" +``` + --- diff --git a/conf/libnfc-nxp.conf b/conf/libnfc-nxp.conf old mode 100755 new mode 100644 index 1d0a16c..17a82bc --- a/conf/libnfc-nxp.conf +++ b/conf/libnfc-nxp.conf @@ -29,19 +29,34 @@ NXPLOG_FWDNLD_LOGLEVEL=0x00 NXPLOG_TML_LOGLEVEL=0x00 ############################################################################### # TRANSPORT Type -# 0x00 - I2C /SPI for noraml nxpnfc driver +# 0x00 - I2C / SPI for normal nxpnfc driver # 0x01 - Not Used, kept to align with Android code -# 0x02 - ALT_I2C -# 0x03 - ALT_SPI +# 0x02 - ALT_I2C: standard I2C Linux interface +# 0x03 - ALT_SPI: standard SPIDEV Linux interface NXP_TRANSPORT=0x02 ############################################################################### -# Nfc Device Node name +# Nfc Device Node name (only used for NXP_TRANSPORT=0x00) NXP_NFC_DEV_NODE="/dev/nxpnfc" ############################################################################### # ALT_I2C/SPI Interface Configuration # [PINs defined as GPIO23/24/25 on RPi4 (choose 594, 595, 596 for RPi5)] +# +# Integer numbers are used for Linux' deprecated sysfs GPIO interface. When +# the library is built against libgpiod, then use GPIO line names. Prefixing +# a line name with '!' signals to libgpiod that the line should be handled with +# ACTIVE_LOW semantic. In the following example, however, the 'reset pin' +# has inverted logic and gives thus 'enable' functionality without the need +# to mark it as active-low. +# Note: Mixing plain integers and GPIO line names is not supported and results +# in undefined behavior. +# +# Example for GPIO line names usage: +# PIN_INT="RFID_IRQ" +# PIN_ENABLE="nRESET_RFID" +# PIN_FWDNLD="RFID_DWL_REQ" +# PIN_INT=535 PIN_ENABLE=536 PIN_FWDNLD=537 diff --git a/demoapp/nfc_cb_example.cpp b/demoapp/nfc_cb_example.cpp index e034a01..4e435fa 100644 --- a/demoapp/nfc_cb_example.cpp +++ b/demoapp/nfc_cb_example.cpp @@ -40,7 +40,7 @@ NfcHandler::NfcHandler() { throw std::runtime_error("Only one global nfc handler instance allowed"); } - setConfigPath("../../build/dist/etc/everest/libnfc_config") + setConfigPath("../../build/dist/etc/everest/libnfc_config"); InitializeLogLevel(); diff --git a/src/nfcandroid_nfc_hidlimpl/halimpl/tml/transport/NfccAltI2cTransport.cc b/src/nfcandroid_nfc_hidlimpl/halimpl/tml/transport/NfccAltI2cTransport.cc index 085e6fb..8fb55b0 100644 --- a/src/nfcandroid_nfc_hidlimpl/halimpl/tml/transport/NfccAltI2cTransport.cc +++ b/src/nfcandroid_nfc_hidlimpl/halimpl/tml/transport/NfccAltI2cTransport.cc @@ -275,26 +275,3 @@ int NfccAltI2cTransport::Write(void* pDevHandle, uint8_t* pBuffer, NXPLOG_TML_D("%s exit", __func__); return numWrote; } - -/******************************************************************************* -** -** Function Close -** -** Description Closes NFCC device -** -** Parameters pDevHandle - device handle -** -** Returns None -** -*******************************************************************************/ -void NfccAltI2cTransport::Close(void* pDevHandle) { - NXPLOG_TML_D("%s Enter", __func__); - if (NULL != pDevHandle) { - close((intptr_t)pDevHandle); - } - if (iEnableFd) close(iEnableFd); - if (iInterruptFd) close(iInterruptFd); - if (iFwDnldFd) close(iFwDnldFd); - NXPLOG_TML_D("%s exit", __func__); - return; -} diff --git a/src/nfcandroid_nfc_hidlimpl/halimpl/tml/transport/NfccAltI2cTransport.h b/src/nfcandroid_nfc_hidlimpl/halimpl/tml/transport/NfccAltI2cTransport.h index 0877a10..6cb4934 100644 --- a/src/nfcandroid_nfc_hidlimpl/halimpl/tml/transport/NfccAltI2cTransport.h +++ b/src/nfcandroid_nfc_hidlimpl/halimpl/tml/transport/NfccAltI2cTransport.h @@ -21,7 +21,7 @@ #include class NfccAltI2cTransport : public NfccAltTransport { - public: +public: /***************************************************************************** ** ** Function OpenAndConfigure @@ -36,7 +36,7 @@ class NfccAltI2cTransport : public NfccAltTransport { ** NFCSTATUS_INVALID_DEVICE - device open operation failure ** ****************************************************************************/ - NFCSTATUS OpenAndConfigure(pphTmlNfc_Config_t pConfig, void** pLinkHandle); + virtual NFCSTATUS OpenAndConfigure(pphTmlNfc_Config_t pConfig, void** pLinkHandle) override; /***************************************************************************** ** @@ -54,7 +54,7 @@ class NfccAltI2cTransport : public NfccAltTransport { ** -1 - read operation failure ** ****************************************************************************/ - int Read(void* pDevHandle, uint8_t* pBuffer, int nNbBytesToRead); + virtual int Read(void* pDevHandle, uint8_t* pBuffer, int nNbBytesToRead) override; /***************************************************************************** ** @@ -71,6 +71,5 @@ class NfccAltI2cTransport : public NfccAltTransport { ** -1 - write operation failure ** *****************************************************************************/ - int Write(void* pDevHandle, uint8_t* pBuffer, int nNbBytesToWrite); - void Close(void* pDevHandle); + virtual int Write(void* pDevHandle, uint8_t* pBuffer, int nNbBytesToWrite) override; }; diff --git a/src/nfcandroid_nfc_hidlimpl/halimpl/tml/transport/NfccAltSpiTransport.cc b/src/nfcandroid_nfc_hidlimpl/halimpl/tml/transport/NfccAltSpiTransport.cc index 03dfb86..ae52511 100644 --- a/src/nfcandroid_nfc_hidlimpl/halimpl/tml/transport/NfccAltSpiTransport.cc +++ b/src/nfcandroid_nfc_hidlimpl/halimpl/tml/transport/NfccAltSpiTransport.cc @@ -390,26 +390,3 @@ int NfccAltSpiTransport::Write(void* pDevHandle, uint8_t* pBuffer, NXPLOG_TML_D("%s exit", __func__); return numWrote - PREFIX_LENGTH; } - -/******************************************************************************* -** -** Function Close -** -** Description Closes NFCC device -** -** Parameters pDevHandle - device handle -** -** Returns None -** -*******************************************************************************/ -void NfccAltSpiTransport::Close(void* pDevHandle) { - NXPLOG_TML_D("%s Enter", __func__); - if (NULL != pDevHandle) { - close((intptr_t)pDevHandle); - } - if (iEnableFd) close(iEnableFd); - if (iInterruptFd) close(iInterruptFd); - if (iFwDnldFd) close(iFwDnldFd); - NXPLOG_TML_D("%s exit", __func__); - return; -} diff --git a/src/nfcandroid_nfc_hidlimpl/halimpl/tml/transport/NfccAltSpiTransport.h b/src/nfcandroid_nfc_hidlimpl/halimpl/tml/transport/NfccAltSpiTransport.h index f806475..96cca7a 100644 --- a/src/nfcandroid_nfc_hidlimpl/halimpl/tml/transport/NfccAltSpiTransport.h +++ b/src/nfcandroid_nfc_hidlimpl/halimpl/tml/transport/NfccAltSpiTransport.h @@ -21,7 +21,7 @@ #include class NfccAltSpiTransport : public NfccAltTransport { - public: +public: /***************************************************************************** ** ** Function OpenAndConfigure @@ -36,7 +36,7 @@ class NfccAltSpiTransport : public NfccAltTransport { ** NFCSTATUS_INVALID_DEVICE - device open operation failure ** ****************************************************************************/ - NFCSTATUS OpenAndConfigure(pphTmlNfc_Config_t pConfig, void** pLinkHandle); + virtual NFCSTATUS OpenAndConfigure(pphTmlNfc_Config_t pConfig, void** pLinkHandle) override; /***************************************************************************** ** @@ -54,7 +54,7 @@ class NfccAltSpiTransport : public NfccAltTransport { ** -1 - read operation failure ** ****************************************************************************/ - int Read(void* pDevHandle, uint8_t* pBuffer, int nNbBytesToRead); + virtual int Read(void* pDevHandle, uint8_t* pBuffer, int nNbBytesToRead) override; /***************************************************************************** ** @@ -71,6 +71,5 @@ class NfccAltSpiTransport : public NfccAltTransport { ** -1 - write operation failure ** *****************************************************************************/ - int Write(void* pDevHandle, uint8_t* pBuffer, int nNbBytesToWrite); - void Close(void* pDevHandle); + virtual int Write(void* pDevHandle, uint8_t* pBuffer, int nNbBytesToWrite) override; }; diff --git a/src/nfcandroid_nfc_hidlimpl/halimpl/tml/transport/NfccAltTransport.cc b/src/nfcandroid_nfc_hidlimpl/halimpl/tml/transport/NfccAltTransport.cc index d1dbd4a..6ce94be 100644 --- a/src/nfcandroid_nfc_hidlimpl/halimpl/tml/transport/NfccAltTransport.cc +++ b/src/nfcandroid_nfc_hidlimpl/halimpl/tml/transport/NfccAltTransport.cc @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -38,6 +39,10 @@ #include #include #include "phNxpNciHal_utils.h" +#include +#include +#include +#include #define CRC_LEN 2 #define NORMAL_MODE_HEADER_LEN 3 @@ -49,46 +54,6 @@ extern phTmlNfc_i2cfragmentation_t fragmentation_enabled; extern phTmlNfc_Context_t* gpphTmlNfc_Context; NfccAltTransport::NfccAltTransport() { - iEnableFd = 0; - iInterruptFd = 0; -} - -/******************************************************************************* -** -** Function Flushdata -** -** Description Reads payload of FW rsp from NFCC device into given buffer -** -** Parameters pDevHandle - valid device handle -** pBuffer - buffer for read data -** numRead - number of bytes read by calling function -** -** Returns always returns -1 -** -*******************************************************************************/ -int NfccAltTransport::Flushdata(void* pDevHandle, uint8_t* pBuffer, - int numRead) { - int retRead = 0; - uint16_t totalBtyesToRead = - pBuffer[FW_DNLD_LEN_OFFSET] + FW_DNLD_HEADER_LEN + CRC_LEN; - /* we shall read totalBtyesToRead-1 as one byte is already read by calling - * function*/ - retRead = read((intptr_t)pDevHandle, pBuffer + numRead, totalBtyesToRead - 1); - if (retRead > 0) { - numRead += retRead; - phNxpNciHal_print_packet("RECV", pBuffer, numRead); - } else if (retRead == 0) { - NXPLOG_TML_E("%s _i2c_read() [pyld] EOF", __func__); - } else { - if (bFwDnldFlag == false) { - NXPLOG_TML_D("%s _i2c_read() [hdr] received", __func__); - phNxpNciHal_print_packet("RECV", pBuffer - numRead, - NORMAL_MODE_HEADER_LEN); - } - NXPLOG_TML_E("%s _i2c_read() [pyld] errno : %x", __func__, errno); - } - SemPost(); - return -1; } /******************************************************************************* @@ -149,28 +114,6 @@ int NfccAltTransport::NfccReset(void* pDevHandle, NfccResetType eType) { return ret; } -/******************************************************************************* -** -** Function GetNfcState -** -** Description Get NFC state -** -** Parameters pDevHandle - valid device handle -** Returns 0 - unknown -** 1 - FW DWL -** 2 - NCI -** -*******************************************************************************/ -int NfccAltTransport::GetNfcState(void* pDevHandle) { - int ret = NFC_STATE_UNKNOWN; - NXPLOG_TML_D("%s ", __func__); - if (NULL == pDevHandle) { - return ret; - } - ret = ioctl((intptr_t)pDevHandle, NFC_GET_NFC_STATE); - NXPLOG_TML_D("%s :nfc state = %d", __func__, ret); - return ret; -} /******************************************************************************* ** ** Function EnableFwDnldMode @@ -255,13 +198,25 @@ int NfccAltTransport::SemTimedWait() { ** *******************************************************************************/ int NfccAltTransport::GetIrqState(void* pDevHandle) { + (void)pDevHandle; + +#ifdef USE_LIBGPIOD + if (m_GpioDInUse) { + return GetIrqStateLibGpioD(); + } +#endif + + return GetIrqStateSysFS(); +} + +int NfccAltTransport::GetIrqStateSysFS() { int ret = -1; NXPLOG_TML_D("%s Enter", __func__); int len; char buf[2]; - if (iInterruptFd <= 0) { + if (iInterruptFd < 0) { NXPLOG_TML_E("Error with interrupt-detect pin (%d)", iInterruptFd); return (-1); } @@ -289,10 +244,10 @@ int NfccAltTransport::verifyPin(int pin, int isoutput, int edge) { sprintf(buf, "/sys/class/gpio/gpio%d", pin); NXPLOG_TML_D("Pin %s\n", buf); int fd = open(buf, O_RDONLY); - if (fd <= 0) { + if (fd < 0) { // Pin not exported yet NXPLOG_TML_D("Create pin %s\n", buf); - if ((fd = open("/sys/class/gpio/export", O_WRONLY)) > 0) { + if ((fd = open("/sys/class/gpio/export", O_WRONLY)) >= 0) { sprintf(buf, "%d", pin); if (write(fd, buf, strlen(buf)) == strlen(buf)) { hasGpio = 1; @@ -313,7 +268,7 @@ int NfccAltTransport::verifyPin(int pin, int isoutput, int edge) { sprintf(buf, "/sys/class/gpio/gpio%d/direction", pin); NXPLOG_TML_D("Direction %s\n", buf); fd = open(buf, O_WRONLY); - if (fd <= 0) { + if (fd < 0) { NXPLOG_TML_E("Could not open direction port '%s' (%s)", buf, strerror(errno)); return -1; @@ -327,14 +282,14 @@ int NfccAltTransport::verifyPin(int pin, int isoutput, int edge) { // Open pin and make sure it is off sprintf(buf, "/sys/class/gpio/gpio%d/value", pin); fd = open(buf, O_RDWR); - if (fd <= 0) { + if (fd < 0) { } close(fd); // Open pin and make sure it is off sprintf(buf, "/sys/class/gpio/gpio%d/value", pin); fd = open(buf, O_RDWR); - if (fd <= 0) { + if (fd < 0) { NXPLOG_TML_E("Could not open value port '%s' (%s)", buf, strerror(errno)); return -1; @@ -355,7 +310,7 @@ int NfccAltTransport::verifyPin(int pin, int isoutput, int edge) { sprintf(buf, "/sys/class/gpio/gpio%d/edge", pin); NXPLOG_TML_D("Edge %s\n", buf); fd = open(buf, O_RDWR); - if (fd <= 0) { + if (fd < 0) { NXPLOG_TML_E("Could not open edge port '%s' (%s)", buf, strerror(errno)); return -1; @@ -385,7 +340,7 @@ int NfccAltTransport::verifyPin(int pin, int isoutput, int edge) { sprintf(buf, "/sys/class/gpio/gpio%d/value", pin); NXPLOG_TML_D("Value %s\n", buf); fd = open(buf, O_RDONLY); - if (fd <= 0) { + if (fd < 0) { NXPLOG_TML_E("Could not open value port '%s' (%s)", buf, strerror(errno)); return -1; @@ -397,8 +352,17 @@ int NfccAltTransport::verifyPin(int pin, int isoutput, int edge) { } return (0); } + void NfccAltTransport::gpio_set_ven(int value) { - if (iEnableFd > 0) { +#ifdef USE_LIBGPIOD + if (m_GpioDInUse) { + SetGpioDPin(*mEnableLineRequest, "Enable", value); + usleep(10 * 1000); + return; + } +#endif + + if (iEnableFd >= 0) { if (value == 0) { write(iEnableFd, "0", 1); } else { @@ -409,7 +373,15 @@ void NfccAltTransport::gpio_set_ven(int value) { } void NfccAltTransport::gpio_set_fwdl(int value) { - if (iFwDnldFd > 0) { +#ifdef USE_LIBGPIOD + if (m_GpioDInUse) { + SetGpioDPin(*mFWDownloadLineRequest, "FW DL", value); + usleep(10 * 1000); + return; + } +#endif + + if (iFwDnldFd >= 0) { if (value == 0) { write(iFwDnldFd, "0", 1); } else { @@ -420,6 +392,20 @@ void NfccAltTransport::gpio_set_fwdl(int value) { } void NfccAltTransport::wait4interrupt(void) { +#ifdef USE_LIBGPIOD + if (m_GpioDInUse) { + gpiod::edge_event_buffer event_buffer(1); + + while (mIRQLineRequest->get_value(mIRQLineRequest->offsets()[0]) != gpiod::line::value::ACTIVE) { + // negative timeout -> sleep until an event is ready + mIRQLineRequest->wait_edge_events(std::chrono::nanoseconds{-1}); + mIRQLineRequest->read_edge_events(event_buffer, 1); + } + + return; + } +#endif + /* Open STREAMS device. */ struct pollfd fds[1]; fds[0].fd = iInterruptFd; @@ -436,6 +422,9 @@ void NfccAltTransport::wait4interrupt(void) { } } +// use kernel's GPIO_MAX_NAME_SIZE (32 byte) plus potential '!' and plus trailing NUL byte +#define NFCCALTTRANSPORT_MAX_NAME_SIZE (GPIO_MAX_NAME_SIZE + 1 + 1) + /***************************************************************************** ** ** Function ConfigurePin @@ -448,6 +437,76 @@ void NfccAltTransport::wait4interrupt(void) { ****************************************************************************/ int NfccAltTransport::ConfigurePin() { +#ifdef USE_LIBGPIOD + NXPLOG_TML_D("ConfigurePin: compiled w/ libgpiod support"); +#else + NXPLOG_TML_D("ConfigurePin: compiled w/o libgpiod support"); +#endif +#ifdef USE_LIBGPIOD + char enable_linename[NFCCALTTRANSPORT_MAX_NAME_SIZE]; + char fwdl_linename[NFCCALTTRANSPORT_MAX_NAME_SIZE]; + char irq_linename[NFCCALTTRANSPORT_MAX_NAME_SIZE]; + + + // check whether all three config options are strings and only then try to + // acquire all via libgpiod, otherwise just fallback and let the old code + // handle errors + bool cfgstr_irq = GetNxpStrValue(NAME_EXT_PIN_INT, irq_linename, sizeof(irq_linename)); + bool cfgstr_enable = GetNxpStrValue(NAME_EXT_PIN_ENABLE, enable_linename, sizeof(enable_linename)); + bool cfgstr_fwdl = GetNxpStrValue(NAME_EXT_PIN_FWDNLD, fwdl_linename, sizeof(fwdl_linename)); + NXPLOG_TML_D("ConfigurePin: GPIO line names: %s=%d (%s), %s=%d (%s), %s=%d (%s)", + NAME_EXT_PIN_INT, cfgstr_irq, cfgstr_irq ? irq_linename : "", + NAME_EXT_PIN_ENABLE, cfgstr_enable, cfgstr_enable ? enable_linename : "", + NAME_EXT_PIN_FWDNLD, cfgstr_fwdl, cfgstr_fwdl ? fwdl_linename : ""); + + if (cfgstr_irq && cfgstr_enable && cfgstr_fwdl) { + try { + gpiod::line_settings line_settings; + line_settings.set_direction(gpiod::line::direction::OUTPUT); + line_settings.set_output_value(gpiod::line::value::INACTIVE); + + mEnableLineRequest = + std::make_unique(GetGpioDByName(enable_linename, "Enable", line_settings)); + } + catch (const std::runtime_error& e) { + NXPLOG_TML_E("ConfigurePin(Enable): %s", e.what()); + return NFCSTATUS_INVALID_DEVICE; + } + + try { + gpiod::line_settings line_settings; + line_settings.set_direction(gpiod::line::direction::OUTPUT); + line_settings.set_output_value(gpiod::line::value::INACTIVE); + + mFWDownloadLineRequest = + std::make_unique(GetGpioDByName(fwdl_linename, "FWDLReq", line_settings)); + } + catch (const std::runtime_error& e) { + NXPLOG_TML_E("ConfigurePin(FW DL Req): %s", e.what()); + mEnableLineRequest->release(); + return NFCSTATUS_INVALID_DEVICE; + } + + try { + gpiod::line_settings line_settings; + line_settings.set_direction(gpiod::line::direction::INPUT); + line_settings.set_edge_detection(gpiod::line::edge::RISING); + + mIRQLineRequest = + std::make_unique(GetGpioDByName(irq_linename, "IRQ", line_settings)); + } + catch (const std::runtime_error& e) { + NXPLOG_TML_E("ConfigurePin(IRQ): %s", e.what()); + mFWDownloadLineRequest->release(); + mEnableLineRequest->release(); + return NFCSTATUS_INVALID_DEVICE; + } + + m_GpioDInUse = true; + return NFCSTATUS_SUCCESS; + } +#endif + int pin_int = loadIntValueOrDefault(NAME_EXT_PIN_INT, DEFAULT_PIN_INT); int pin_ena = loadIntValueOrDefault(NAME_EXT_PIN_ENABLE, DEFAULT_PIN_ENABLE); int pin_fwd = loadIntValueOrDefault(NAME_EXT_PIN_FWDNLD, DEFAULT_PIN_FWDNLD); @@ -461,3 +520,96 @@ int NfccAltTransport::ConfigurePin() if (iFwDnldFd < 0) return (NFCSTATUS_INVALID_DEVICE); return NFCSTATUS_SUCCESS; } + +/******************************************************************************* +** +** Function Close +** +** Description Closes NFCC device +** +** Parameters pDevHandle - device handle +** +** Returns None +** +*******************************************************************************/ +void NfccAltTransport::Close(void* pDevHandle) { + NXPLOG_TML_D("%s Enter", __func__); + if (NULL != pDevHandle) { + close((intptr_t)pDevHandle); + } + if (iEnableFd >= 0) { + close(iEnableFd); + iEnableFd = -1; + } + if (iInterruptFd >= 0) { + close(iInterruptFd); + iInterruptFd = -1; + } + if (iFwDnldFd >= 0) { + close(iFwDnldFd); + iFwDnldFd = -1; + } +#ifdef USE_LIBGPIOD + if (m_GpioDInUse) { + mEnableLineRequest->release(); + mFWDownloadLineRequest->release(); + mIRQLineRequest->release(); + } +#endif + NXPLOG_TML_D("%s exit", __func__); +} + +#ifdef USE_LIBGPIOD + +gpiod::line_request NfccAltTransport::GetGpioLineByName(const std::string& name, + const std::string& consumer, + const gpiod::line_settings& settings) { + + for (const auto& entry : std::filesystem::directory_iterator("/dev/")) { + if (gpiod::is_gpiochip_device(entry.path())) { + gpiod::chip chip(entry.path()); + + auto offset = chip.get_line_offset_from_name(name); + if (offset >= 0) { + return chip + .prepare_request() + .set_consumer("libnfc-nci: " + consumer) + .add_line_settings(offset, settings) + .do_request(); + } + } + } + + throw std::runtime_error("No GPIO line with name '" + name + "' found."); +} + +gpiod::line_request NfccAltTransport::GetGpioDByName(const std::string& name, + const std::string& consumer, + gpiod::line_settings& line_settings) { + std::string line_name = name; + bool active_low = false; + + if (!line_name.empty() && line_name.front() == '!') { + active_low = true; + line_name.erase(0, 1); + } + + line_settings.set_active_low(active_low); + + return GetGpioLineByName(line_name, consumer, line_settings); +} + +int NfccAltTransport::GetIrqStateLibGpioD() { + return mIRQLineRequest->get_value(mIRQLineRequest->offsets()[0]) == gpiod::line::value::ACTIVE; +} + +void NfccAltTransport::SetGpioDPin(gpiod::line_request& lq, const char* line_descr, int value) { + try { + lq.set_value(lq.offsets()[0], value ? gpiod::line::value::ACTIVE : gpiod::line::value::INACTIVE); + } + catch (const std::runtime_error& e) { + NXPLOG_TML_E("SetGpioDPin(%s) to '%d' failed: %s\n", line_descr, value, e.what()); + } +} + +#endif // USE_LIBGPIOD diff --git a/src/nfcandroid_nfc_hidlimpl/halimpl/tml/transport/NfccAltTransport.h b/src/nfcandroid_nfc_hidlimpl/halimpl/tml/transport/NfccAltTransport.h index 335e2b4..c2f95cd 100755 --- a/src/nfcandroid_nfc_hidlimpl/halimpl/tml/transport/NfccAltTransport.h +++ b/src/nfcandroid_nfc_hidlimpl/halimpl/tml/transport/NfccAltTransport.h @@ -27,6 +27,10 @@ #include #include #include +#include +#ifdef USE_LIBGPIOD +#include +#endif #define EDGE_NONE 0 #define EDGE_RISING 1 @@ -41,22 +45,10 @@ extern phTmlNfc_i2cfragmentation_t fragmentation_enabled; class NfccAltTransport : public NfccTransport { - public: +public: NfccAltTransport(); - bool_t bFwDnldFlag = false; - sem_t mTxRxSemaphore; - int iEnableFd; - int iInterruptFd; - int iFwDnldFd; + virtual ~NfccAltTransport() = default; - public: - void gpio_set_ven(int value); - void gpio_set_fwdl(int value); - int verifyPin(int pin, int isoutput, int edge); - void wait4interrupt(void); - int SemTimedWait(); - void SemPost(); - int Flushdata(void* pDevHandle, uint8_t* pBuffer, int numRead); /***************************************************************************** ** ** Function Reset @@ -70,7 +62,7 @@ class NfccAltTransport : public NfccTransport { ** -1 - reset operation failure ** ****************************************************************************/ - int NfccReset(void* pDevHandle, NfccResetType eType); + virtual int NfccReset(void* pDevHandle, NfccResetType eType) override; /***************************************************************************** ** @@ -82,7 +74,7 @@ class NfccAltTransport : public NfccTransport { ** ** Returns None ****************************************************************************/ - void EnableFwDnldMode(bool mode); + virtual void EnableFwDnldMode(bool mode) override; /***************************************************************************** ** @@ -94,9 +86,9 @@ class NfccAltTransport : public NfccTransport { ** ** Returns Current mode download/NCI ****************************************************************************/ - bool_t IsFwDnldModeEnabled(void); + virtual bool_t IsFwDnldModeEnabled(void) override; - /******************************************************************************* + /***************************************************************************** ** ** Function GetIrqState ** @@ -108,9 +100,36 @@ class NfccAltTransport : public NfccTransport { *Zer0. ** In the case of IOCTL error, it returns -ve value. ** - *******************************************************************************/ - int GetIrqState(void* pDevHandle); - int GetNfcState(void* pDevHandle); + ****************************************************************************/ + virtual int GetIrqState(void* pDevHandle) override; + + /***************************************************************************** + ** + ** Function Close + ** + ** Description Closes NFCC device + ** + ** Parameters pDevHandle - device handle + ** + ** Returns None + ** + ****************************************************************************/ + virtual void Close(void *pDevHandle) override; + +protected: + bool_t bFwDnldFlag = false; + sem_t mTxRxSemaphore; + int iEnableFd{-1}; + int iInterruptFd{-1}; + int iFwDnldFd{-1}; + + void gpio_set_ven(int value); + void gpio_set_fwdl(int value); + int verifyPin(int pin, int isoutput, int edge); + void wait4interrupt(void); + int SemTimedWait(); + void SemPost(); + /***************************************************************************** ** ** Function ConfigurePin @@ -122,4 +141,26 @@ class NfccAltTransport : public NfccTransport { ** Returns NFCSTATUS_SUCCESS - on Success/ -1 on Failure ****************************************************************************/ int ConfigurePin(); + + // flag whether libgpiod members are in use instead of deprecated + // file descriptors above + bool_t m_GpioDInUse{false}; + + int GetIrqStateSysFS(); + +#ifdef USE_LIBGPIOD + std::unique_ptr mEnableLineRequest; + std::unique_ptr mFWDownloadLineRequest; + std::unique_ptr mIRQLineRequest; + + gpiod::line_request GetGpioLineByName(const std::string& name, + const std::string& consumer, + const gpiod::line_settings& settings); + gpiod::line_request GetGpioDByName(const std::string& name, + const std::string& consumer, + gpiod::line_settings& settings); + int GetIrqStateLibGpioD(); + void SetGpioDPin(gpiod::line_request& lq, const char* line_descr, int value); +#endif + }; diff --git a/src/nfcandroid_nfc_hidlimpl/halimpl/tml/transport/NfccI2cTransport.cc b/src/nfcandroid_nfc_hidlimpl/halimpl/tml/transport/NfccI2cTransport.cc index 2f22a3b..c69b726 100644 --- a/src/nfcandroid_nfc_hidlimpl/halimpl/tml/transport/NfccI2cTransport.cc +++ b/src/nfcandroid_nfc_hidlimpl/halimpl/tml/transport/NfccI2cTransport.cc @@ -442,6 +442,7 @@ int NfccI2cTransport::GetNfcState(void *pDevHandle) { NXPLOG_TML_D("%s :nfc state = %d", __func__, ret); return ret; } + /******************************************************************************* ** ** Function EnableFwDnldMode diff --git a/src/nfcandroid_nfc_hidlimpl/halimpl/tml/transport/NfccI2cTransport.h b/src/nfcandroid_nfc_hidlimpl/halimpl/tml/transport/NfccI2cTransport.h index 2721052..d9e1060 100644 --- a/src/nfcandroid_nfc_hidlimpl/halimpl/tml/transport/NfccI2cTransport.h +++ b/src/nfcandroid_nfc_hidlimpl/halimpl/tml/transport/NfccI2cTransport.h @@ -58,7 +58,7 @@ extern phTmlNfc_i2cfragmentation_t fragmentation_enabled; class NfccI2cTransport : public NfccTransport { - private: +private: bool_t bFwDnldFlag = false; sem_t mTxRxSemaphore; /***************************************************************************** @@ -87,7 +87,7 @@ class NfccI2cTransport : public NfccTransport { int Flushdata(void* pDevHandle, uint8_t* pBuffer, int numRead); - public: +public: /***************************************************************************** ** ** Function Close @@ -99,7 +99,7 @@ class NfccI2cTransport : public NfccTransport { ** Returns None ** *****************************************************************************/ - void Close(void *pDevHandle); + virtual void Close(void *pDevHandle) override; /***************************************************************************** ** @@ -115,7 +115,7 @@ class NfccI2cTransport : public NfccTransport { ** NFCSTATUS_INVALID_DEVICE - device open operation failure ** ****************************************************************************/ - NFCSTATUS OpenAndConfigure(pphTmlNfc_Config_t pConfig, void **pLinkHandle); + virtual NFCSTATUS OpenAndConfigure(pphTmlNfc_Config_t pConfig, void **pLinkHandle) override; /***************************************************************************** ** @@ -133,7 +133,7 @@ class NfccI2cTransport : public NfccTransport { ** -1 - read operation failure ** ****************************************************************************/ - int Read(void *pDevHandle, uint8_t *pBuffer, int nNbBytesToRead); + virtual int Read(void *pDevHandle, uint8_t *pBuffer, int nNbBytesToRead) override; /***************************************************************************** ** @@ -150,7 +150,7 @@ class NfccI2cTransport : public NfccTransport { ** -1 - write operation failure ** *****************************************************************************/ - int Write(void *pDevHandle, uint8_t *pBuffer, int nNbBytesToWrite); + virtual int Write(void *pDevHandle, uint8_t *pBuffer, int nNbBytesToWrite) override; /***************************************************************************** ** @@ -165,7 +165,7 @@ class NfccI2cTransport : public NfccTransport { ** -1 - reset operation failure ** ****************************************************************************/ - int NfccReset(void *pDevHandle, NfccResetType eType); + virtual int NfccReset(void *pDevHandle, NfccResetType eType) override; /***************************************************************************** ** @@ -180,7 +180,7 @@ class NfccI2cTransport : public NfccTransport { ** else - reset operation failure ** ****************************************************************************/ - int EseReset(void *pDevHandle, EseResetType eType); + virtual int EseReset(void *pDevHandle, EseResetType eType) override; /***************************************************************************** ** @@ -195,7 +195,7 @@ class NfccI2cTransport : public NfccTransport { ** else - reset operation failure ** ****************************************************************************/ - int EseGetPower(void *pDevHandle, long level); + virtual int EseGetPower(void *pDevHandle, long level) override; /***************************************************************************** ** @@ -209,7 +209,7 @@ class NfccI2cTransport : public NfccTransport { ** 1 - i3c ** ****************************************************************************/ - int GetPlatform(void *pDevHandle); + virtual int GetPlatform(void *pDevHandle) override; /***************************************************************************** ** @@ -223,7 +223,7 @@ class NfccI2cTransport : public NfccTransport { ** 2 - NCI ** *****************************************************************************/ - int GetNfcState(void *pDevHandle); + virtual int GetNfcState(void *pDevHandle) override; /***************************************************************************** ** @@ -235,7 +235,7 @@ class NfccI2cTransport : public NfccTransport { ** ** Returns None ****************************************************************************/ - void EnableFwDnldMode(bool mode); + virtual void EnableFwDnldMode(bool mode) override; /***************************************************************************** ** @@ -247,9 +247,9 @@ class NfccI2cTransport : public NfccTransport { ** ** Returns Current mode download/NCI ****************************************************************************/ - bool_t IsFwDnldModeEnabled(void); + virtual bool_t IsFwDnldModeEnabled(void) override; - /******************************************************************************* + /***************************************************************************** ** ** Function GetIrqState ** @@ -260,6 +260,6 @@ class NfccI2cTransport : public NfccTransport { ** Returns The state of IRQ line i.e. +ve if read is pending else Zer0. ** In the case of IOCTL error, it returns -ve value. ** - *******************************************************************************/ - int GetIrqState(void *pDevHandle); + ****************************************************************************/ + virtual int GetIrqState(void *pDevHandle) override; }; diff --git a/src/nfcandroid_nfc_hidlimpl/halimpl/tml/transport/NfccTransport.h b/src/nfcandroid_nfc_hidlimpl/halimpl/tml/transport/NfccTransport.h index 2d2f2d3..e5cc7b2 100644 --- a/src/nfcandroid_nfc_hidlimpl/halimpl/tml/transport/NfccTransport.h +++ b/src/nfcandroid_nfc_hidlimpl/halimpl/tml/transport/NfccTransport.h @@ -65,7 +65,7 @@ class NfccTransport { ** ** Returns None ** - *****************************************************************************/ + ****************************************************************************/ virtual void Close(void *pDevHandle) = 0; /***************************************************************************** @@ -117,7 +117,7 @@ class NfccTransport { ** Returns numWrote - number of successfully written bytes ** -1 - write operation failure ** - *****************************************************************************/ + ****************************************************************************/ virtual int Write(void *pDevHandle, uint8_t *pBuffer, int nNbBytesToWrite) = 0; @@ -217,7 +217,7 @@ class NfccTransport { ****************************************************************************/ virtual bool_t IsFwDnldModeEnabled(void); - /******************************************************************************* + /***************************************************************************** ** ** Function GetIrqState ** @@ -229,7 +229,7 @@ class NfccTransport { *Zer0. ** In the case of IOCTL error, it returns -ve value. ** - *******************************************************************************/ + ****************************************************************************/ virtual int GetIrqState(void *pDevHandle); /***************************************************************************** diff --git a/src/nfcandroid_nfc_hidlimpl/halimpl/utils/phNxpConfig.cpp b/src/nfcandroid_nfc_hidlimpl/halimpl/utils/phNxpConfig.cpp index 42f901f..e824f61 100644 --- a/src/nfcandroid_nfc_hidlimpl/halimpl/utils/phNxpConfig.cpp +++ b/src/nfcandroid_nfc_hidlimpl/halimpl/utils/phNxpConfig.cpp @@ -578,7 +578,7 @@ bool CNxpNfcConfig::getValue(const char* name, char* pValue, size_t len) const if (pParam->str_len() > 0) { memset(pValue, 0, len); - memcpy(pValue, pParam->str_value(), pParam->str_len()); + memcpy(pValue, pParam->str_value(), (len - 1 < pParam->str_len()) ? len - 1 : pParam->str_len()); return true; } return false; @@ -1085,7 +1085,7 @@ extern "C" int GetNxpNumValue(const char* name, void* pValue, unsigned long len) *******************************************************************************/ extern "C" int loadIntValueOrDefault(const char* name, int default_value) { int value; - int isfound = GetNxpNumValue(name, &value, sizeof(&value)); + int isfound = GetNxpNumValue(name, &value, sizeof(value)); if (isfound > 0) { return value; }