From b1eaaeca6fdcb38d9a247e2deabe1da788a1e1f0 Mon Sep 17 00:00:00 2001 From: Harsh Sharma Date: Thu, 3 Mar 2022 14:44:44 -0600 Subject: LoRa updates with MTAC-003 --- .gitignore | 2 + Makefile | 15 +- include/Device/Device.h | 254 ++++++----- include/Fpga/Fpga.h | 74 ++++ include/General.h | 87 ++-- include/Utility/Utility.h | 43 +- src/AccessoryCards/AccessoryCard.cpp | 26 ++ src/AccessoryCards/AcessoryCard.cpp | 21 - src/AccessoryCards/Gpiob.cpp | 36 +- src/AccessoryCards/LoraCard.cpp | 38 +- src/AccessoryCards/LoraCard03.cpp | 53 +++ src/AccessoryCards/LoraCard10.cpp | 38 ++ src/AccessoryCards/LoraCard15.cpp | 195 ++------- src/AccessoryCards/LoraCard21.cpp | 48 ++- src/AccessoryCards/LoraCard21Ext.cpp | 42 +- src/AccessoryCards/LoraCard2G4.cpp | 32 ++ src/AccessoryCards/Mfser.cpp | 47 +- src/AccessoryCards/Mtac15Fpga.cpp | 803 +++++++++++++++++++++++++++++++++++ src/Device/Device.cpp | 434 ++++++++++++------- src/MtsIoSysfs.cpp | 261 +++++++++--- src/Version.cpp | 4 - 21 files changed, 1893 insertions(+), 660 deletions(-) create mode 100644 .gitignore create mode 100644 include/Fpga/Fpga.h create mode 100644 src/AccessoryCards/AccessoryCard.cpp delete mode 100644 src/AccessoryCards/AcessoryCard.cpp create mode 100644 src/AccessoryCards/LoraCard03.cpp create mode 100644 src/AccessoryCards/LoraCard10.cpp create mode 100644 src/AccessoryCards/LoraCard2G4.cpp create mode 100644 src/AccessoryCards/Mtac15Fpga.cpp delete mode 100644 src/Version.cpp diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3c84646 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +build/ +src/Version.cpp diff --git a/Makefile b/Makefile index b0c1996..16aa846 100644 --- a/Makefile +++ b/Makefile @@ -33,11 +33,11 @@ SOURCEDIR=src CFLAGS += -Werror -Wno-unused-function -CXXFLAGS += -std=c++11 -Wno-unused-function +CXXFLAGS += -std=c++14 -Wno-unused-function -LIBS := -lmts -lrt +LIBS := -lmts -lrt -lssl -lcrypto -INC=-Iinclude -Iinclude/Utility -Iinclude/AccessoryCards -Iinclude/Device +INC=-Iinclude -Iinclude/Utility -Iinclude/AccessoryCards -Iinclude/Device -Iinclude/Fpga INCLUDES = $(wildcard include/*.h) SOURCES = $(wildcard $(SOURCEDIR)/**/*.cpp) SOURCES += $(SOURCEDIR)/Version.cpp @@ -46,7 +46,7 @@ OBJS = $(patsubst $(SOURCEDIR)/%.c,$(BUILDDIR)/%.o,$(OBJS1)) CPP_DEPPS = $(patsubst $(SOURCEDIR)/%.cpp,$(BUILDDIR)/**/%.d,$(SOURCES)) CPP_DEPPS += $(BUILDDIR)/*.o $(BUILDDIR)/*.d $(BUILDDIR)/**/*.o $(BUILDDIR)/**/*.d JS_OBJS = $(BUILDDIR)/Version.o -OUT_DIRS=build/AccessoryCards build/Device +OUT_DIRS=build/AccessoryCards build/Device build/Fpga MKDIR_P = mkdir -p ifndef MTS_CHECK @@ -85,7 +85,7 @@ mts-io-sysfs: $(OBJS) $(BUILDDIR)/MtsIoSysfs.o $(BUILDDIR)/%.o: $(SOURCEDIR)/%.cpp @echo 'Building file: $<' - $(CXX) $(CFLAGS) $(INC) -Wall -std=c++11 -c -fmessage-length=0 -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@:%.o=%.d)" -o "$@" "$<" + $(CXX) $(CFLAGS) $(INC) -Wall -std=c++14 -c -fmessage-length=0 -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@:%.o=%.d)" -o "$@" "$<" @echo 'Finished building: $<' @echo ' ' @@ -103,13 +103,10 @@ $(SOURCEDIR)/Version.cpp: $(BUILDDIR)/MtsIo.o: $(SOURCEDIR)/MtsIo.cpp @echo 'Building file: $<' - $(CXX) $(CFLAGS) $(INC) -Wall -std=c++11 -c -fmessage-length=0 -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@:%.o=%.d)" -o "$@" "$<" -DENABLE_MTS_CHECK=${MTS_CHECK} + $(CXX) $(CFLAGS) $(INC) -Wall -std=c++14 -c -fmessage-length=0 -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@:%.o=%.d)" -o "$@" "$<" -DENABLE_MTS_CHECK=${MTS_CHECK} @echo 'Finished building: $<' @echo ' ' -install: - mkdir -p $(DESTDIR)/opt/lora - strip: $(STRIP) -S --strip-unneeded --remove-section=.note.gnu.gold-version --remove-section=.comment --remove-section=.note --remove-section=.note.gnu.build-id --remove-section=.note.ABI-tag $(BUILDDIR)/mts-io-sysfs diff --git a/include/Device/Device.h b/include/Device/Device.h index 198cc67..5f2bf12 100644 --- a/include/Device/Device.h +++ b/include/Device/Device.h @@ -1,113 +1,163 @@ #ifndef DEVICE_H_ #define DEVICE_H_ +#include "Fpga.h" #include "General.h" #include "Utility.h" #include "Version.h" +#include /* ceil */ + +class Mtac15Fpga; class Device { - private: - bool verbose ; - bool isRoot; - rapidjson::Document capabilities; - rapidjson::Document ethSwitch; - rapidjson::Document deviceInfo; - static const std::vector apIdentifiers; - rapidjson::Document accessoryCards; - rapidjson::Value accessoryCard; - rapidjson::Document::AllocatorType& alloc = deviceInfo.GetAllocator(); - rapidjson::Document::AllocatorType& accessoryCardsAlloc = accessoryCards.GetAllocator(); - static std::map capabilityList; - static std::map ethSwitchList; - static std::map deviceInfoList; - - static const std::regex apFilters; - static const std::regex lora15Filters; - static const std::regex loraG16Filters; - static const std::regex loraG64Filters; - static const std::regex gpiobFilters; - static const std::regex mfserFilters; - static const std::regex serialModeFilter; - static const std::regex storeFilters; - static const std::regex showFilters; - - class AccessoryCard { - protected: - Device& device; - const std::string productId; - const std::string port; - public: - AccessoryCard(Device& d, const std::string ProductId, const std::string Port); - }; - - class LoraCard : public AccessoryCard { - protected: - std::string spiPath; - uint8_t fpgaVersion = 255; - public: - LoraCard(Device& d, const std::string ProductId, const std::string Port); - void setCapabilities(); - }; - - class Lora15Card : public LoraCard { - private: - void *spi_target_ptr = NULL; - public: - Lora15Card(Device& d, const std::string ProductId, const std::string Port); - int spiOpen(const char *spidev); - int spiRead(uint8_t address, uint8_t *data); - int spiClose(); - }; - - class Lora21Card : public LoraCard { - private: - std::string cmdFpgaVersion; - public: - Lora21Card(Device& d, const std::string ProductId, const std::string Port); - }; - - class Lora21ExtCard : public Lora21Card { - private: - std::string cmdFpgaVersion2; - public: - Lora21ExtCard(Device& d, const std::string ProductId, const std::string Port); - }; - - class Gpiob : public AccessoryCard { - public: - Gpiob(Device& d, const std::string ProductId, const std::string Port); - }; - - class Mfser : public AccessoryCard { - public: - Mfser(Device& d, const std::string ProductId, const std::string Port); - }; - - public: - Device(); - void getSystemTreeJson(const char * dir_name); - void init(); - bool isAccessoryCard(const char * d_name, const char * dir_name); - bool isValidDirectory(const struct dirent * entry, std::string fullPath, const char * d_name); - void load(); - void logInfo(std::string info); - void logError(std::string info); - void json(); - void mapFileToCapability(); - void mapFirmware(); - void mapMacAddress2(); - void printDir(const std::string dir_name, std::vector &results); - void printJson(); - void printVersion (std::string name); - void printUsage(std::string program); - void show(std::string program); - void showTrigger(std::string name); - void sortAccessoryCards(); - void store(std::string name, std::string value); - void storeTrigger(std::string name, std::string value); - void Verbose(bool val); - bool Verbose(); - void writeJson(); + private: + bool isRoot; + rapidjson::Document capabilities; + rapidjson::Document ethSwitch; + rapidjson::Document deviceInfo; + static const std::vector apIdentifiers; + rapidjson::Document accessoryCards; + rapidjson::Value accessoryCard; + rapidjson::Document::AllocatorType &alloc = deviceInfo.GetAllocator(); + rapidjson::Document::AllocatorType &acAlloc = accessoryCards.GetAllocator(); + static std::map capabilityList; + static std::map ethSwitchList; + static std::map deviceInfoList; + + static const std::regex apFilters; + static const std::regex serialModeFilter; + static const std::regex storeFilters; + static const std::regex showFilters; + static const std::regex mtcdt3Filters; + static const std::regex mtrFilters; + + const unsigned int accessoryCardsListSize = 7; + + class AccessoryCard { + protected: + Device &device; + std::regex name; + + public: + AccessoryCard(Device &d, const std::regex Name); + virtual void AddToDeviceInfo(const std::string Port, + const std::string ProductID); + const std::regex GetName(); + }; + + class LoraCard : public AccessoryCard { + protected: + std::string spiPath; + uint8_t fpgaVersion; + + public: + LoraCard(Device &d, const std::regex Name); + void AddToDeviceInfo(const std::string Port, + const std::string ProductID); + }; + + class Lora03Card : public LoraCard { + private: + std::string spiPath1261; + uint8_t tmp102; + + public: + Lora03Card(Device &d); + void AddToDeviceInfo(const std::string Port, + const std::string ProductID); + }; + + class Lora10Card : public LoraCard { + public: + Lora10Card(Device &d); + void AddToDeviceInfo(const std::string Port, + const std::string ProductID); + }; + + class Lora15Card : public LoraCard { + private: + Lora15Card(); + void *spi_target_ptr = NULL; + const char pin_high = '1'; + const char pin_low = '0'; + + public: + Lora15Card(Device &d); + void AddToDeviceInfo(const std::string Port, + const std::string ProductID); + }; + + class Lora21Card : public LoraCard { + private: + std::string cmdFpgaVersion; + + public: + Lora21Card(Device &d); + Lora21Card(Device &d, const std::regex Name); + void AddToDeviceInfo(const std::string Port, + const std::string ProductID); + }; + + class Lora21ExtCard : public Lora21Card { + private: + std::string cmdFpgaVersion2; + + public: + Lora21ExtCard(Device &d); + void AddToDeviceInfo(const std::string Port, + const std::string ProductID); + }; + + class Lora2G4Card : public LoraCard { + public: + Lora2G4Card(Device &d); + void AddToDeviceInfo(const std::string Port, + const std::string ProductID); + }; + + class Gpiob : public AccessoryCard { + public: + Gpiob(Device &d); + void AddToDeviceInfo(const std::string Port, + const std::string ProductID); + }; + + class Mfser : public AccessoryCard { + public: + Mfser(Device &d); + void AddToDeviceInfo(const std::string Port, + const std::string ProductID); + }; + + std::vector> accessoryCardsList; + + public: + Device(); + void getSystemTreeJson(const char *dir_name); + void init(); + bool isAccessoryCard(const char *d_name, const char *dir_name); + bool isValidDirectory(const struct dirent *entry, std::string fullPath, + const char *d_name); + void load(); + void logInfo(std::string info); + void logError(std::string info); + void json(); + void mapFileToCapability(); + void mapFirmware(); + void mapMacAddress2(); + void printDir(const std::string dir_name, + std::vector &results); + void printJson(); + void printVersion(std::string name); + void printUsage(std::string program); + void show(std::string program); + void showTrigger(std::string name); + void sortAccessoryCards(); + void store(std::string name, std::string value); + void storeTrigger(std::string name, std::string value); + void Verbose(bool val); + bool Verbose(); + void writeJson(); }; #endif /* DEVICE_H_ */ diff --git a/include/Fpga/Fpga.h b/include/Fpga/Fpga.h new file mode 100644 index 0000000..986a269 --- /dev/null +++ b/include/Fpga/Fpga.h @@ -0,0 +1,74 @@ +#ifndef FPGA_H_ +#define FPGA_H_ + +#include "General.h" +#include "Utility.h" +#include "Version.h" +#include /* ceil */ +#include /* generate hash */ + +#define MTAC_SX1301 0x0 +#define MTAC_FPGA 0x1 + +#define MTAC_FPGA_ADDRESS 0x1 +#define READ_ACCESS 0x00 +#define WRITE_ACCESS 0x80 +#define SPI_SPEED 8000000 + +#define MTAC_PAGE_REG 0 +#define MTAC_SOFT_RESET 1 +#define MTAC_VERSION 2 + +#define MTCDT_DEFAULT_FILE "/usr/lib/mts-flash-binaries/mtcdt-fpga-v31.hex" +#define MTCAP_DEFAULT_FILE "/usr/lib/mts-flash-binaries/mtcap-fpga-v31.hex" + +struct mtac_reg_s { + int8_t page; /*!< page containing the register (-1 for all pages) */ + uint8_t addr; /*!< base address of the register (7 bit) */ + uint8_t offs; /*!< position of the register LSB (between 0 to 7) */ + bool sign; /*!< 1 indicates the register is signed (2 complem.) */ + uint8_t leng; /*!< number of bits in the register */ + bool rdon; /*!< 1 indicates a read-only register */ + int32_t dflt; /*!< register default value */ +}; + +class Mtac15Fpga { + private: + HardwareType hardwareType = HARDWARE_INVALID; + void *spi_target_ptr = NULL; + const char pin_high = '1'; + const char pin_low = '0'; + std::string port; + std::string spiPath; + std::string input_file; + uint8_t fpgaVersion; + rapidjson::Document deviceInfo; + rapidjson::Document::AllocatorType &alloc = deviceInfo.GetAllocator(); + + void sha256_hash_string(unsigned char hash[SHA256_DIGEST_LENGTH], + char outputBuffer[65]); + void sha256(char *string, char outputBuffer[65]); + int sha256_file(const char *path); + int spiOpen(); + int spiRead(uint8_t spi_mux_target, uint8_t address, uint8_t *data); + int spiWrite(uint8_t spi_mux_target, uint8_t address, uint8_t data); + int spiClose(); + int busContention(); + int cresetWrite(char num); + int releaseDevice(); + int writeEnable(); + int chipEraseVerify(); + int chipErase(); + int mtacErase(); + int pageProgram(uint8_t adr_lower, uint8_t adr_higher, uint32_t data[256]); + int mtacProgram(const char input_file[]); + + public: + Mtac15Fpga(std::string inputFile, std::string forcedPath); + Mtac15Fpga(std::string path); + int getFpgaVersion(); + int FpgaVersion(); + int upgradeFpga(); +}; + +#endif /* FPGA_H_ */ diff --git a/include/General.h b/include/General.h index c5be2ff..e45f06a 100644 --- a/include/General.h +++ b/include/General.h @@ -2,7 +2,7 @@ #define GENERAL_HPP #ifdef _MSC_VER -#pragma warning ( disable : 4514 4512 4710 4355) +#pragma warning(disable : 4514 4512 4710 4355) #endif typedef signed char sint8; @@ -13,71 +13,68 @@ typedef signed int sint32; typedef unsigned int uint32; typedef signed long long sint64; typedef unsigned long long uint64; -typedef signed int sint; //32 bit - even on 64 bit machines -typedef unsigned int uint; //32 bit - even on 64 bit machines +typedef signed int sint; // 32 bit - even on 64 bit machines +typedef unsigned int uint; // 32 bit - even on 64 bit machines -#define memzero(ptr) memset(ptr,0,sizeof(*(ptr))) -#define ArrayZero(ptr,elements) memset(ptr,0,sizeof(*(ptr)) * (elements)) +#define memzero(ptr) memset(ptr, 0, sizeof(*(ptr))) +#define ArrayZero(ptr, elements) memset(ptr, 0, sizeof(*(ptr)) * (elements)) +#include #include #include +#include +#include /* open */ #include #include -#include -#include /* printf fprintf */ -#include /* open */ #include -#include -#include /* lseek, close */ -#include #include +#include /* printf fprintf */ +#include +#include #include - +#include /* lseek, close */ +#include /* command line parser */ #include "rapidjson/document.h" -#include "rapidjson/writer.h" -#include "rapidjson/stringbuffer.h" +#include "rapidjson/filereadstream.h" #include "rapidjson/istreamwrapper.h" +#include "rapidjson/stringbuffer.h" +#include "rapidjson/writer.h" -#define MAX_ACC_CARDS 4 - -#define VERBOSE false -#define MTS_IO_CONTROLS_STATUS_LED false -#define MTS_IO_CONTROLS_LS_LED false - -#define FIRMWARE_VERSION "Version" -#define FIRMWARE_DATE "Date" - -#define SYSFS_PLATFORM "/sys/devices/platform/mts-io/" -#define HW_VERSION_PATH "/sys/devices/platform/mts-io/hw-version" -#define LEDS_GPIO_DIR "/sys/devices/platform/leds-gpio/leds/" -#define FIRMWARE_FILE "/etc/issue" - -#define LORA_1_5_AP1_FPGA_VERSION "mts-fpga-loader -p 1 -c | grep version | awk '{printf $4}'" -#define LORA_1_5_AP2_FPGA_VERSION "mts-fpga-loader -p 2 -c | grep version | awk '{printf $4}'" -#define LORA_2_1_FPGA_VERSION "mts-fpga-loader -g | grep version | awk '{printf $4}'" -#define LORA_2_1_EXT_FPGA_VERSION "mts-fpga-loader -b 1 -g | grep version | awk '{printf $4}'" +#define MAX_ACC_CARDS 4 +#define VERBOSE false +#define MTS_IO_CONTROLS_STATUS_LED false +#define MTS_IO_CONTROLS_LS_LED false -#define MTAC_SX1301 0x0 -#define MTAC_FPGA 0x1 +#define FIRMWARE_VERSION "Version" +#define FIRMWARE_DATE "Date" +#define FIRMWARE_RELEASE "Release" -#define MTAC_FPGA_ADDRESS 0x1 +#define SYSFS_PLATFORM "/sys/devices/platform/mts-io/" +#define HW_VERSION_PATH "/sys/devices/platform/mts-io/hw-version" +#define LEDS_GPIO_DIR "/sys/devices/platform/leds-gpio/leds/" +#define FIRMWARE_FILE "/etc/issue" +#define CRESET "/creset" -#define READ_ACCESS 0x00 -#define SPI_SPEED 8000000 +#define LORA_2_1_FPGA_VERSION \ + "mts-fpga-loader -g | grep version | awk '{printf $4}'" +#define LORA_2_1_EXT_FPGA_VERSION \ + "mts-fpga-loader -b 1 -g | grep version | awk '{printf $4}'" -#define DEVICE_INFO_FILE "/var/run/config/device_info.json" -#define RESET_SHORT_CMD "reset_short_handler" -#define RESET_LONG_CMD "reset_long_handler" -#define KILL_SIGNAL "kill -l " +#define DEVICE_INFO_FILE "/var/run/config/device_info.json" +#define RESET_SHORT_CMD "reset_short_handler" +#define RESET_LONG_CMD "reset_long_handler" +#define KILL_SIGNAL "kill -l " +enum HardwareType { + HARDWARE_MTCDT, + HARDWARE_MTCDT3, + HARDWARE_MTCAP, + HARDWARE_INVALID +}; #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) - #endif - - - diff --git a/include/Utility/Utility.h b/include/Utility/Utility.h index 8d68baa..caf5661 100644 --- a/include/Utility/Utility.h +++ b/include/Utility/Utility.h @@ -6,34 +6,35 @@ #include /********************************************************************** -* COPYRIGHT 2020 MULTI-TECH SYSTEMS, INC. -* -* ALL RIGHTS RESERVED BY AND FOR THE EXCLUSIVE BENEFIT OF -* MULTI-TECH SYSTEMS, INC. -* -* MULTI-TECH SYSTEMS, INC. - CONFIDENTIAL AND PROPRIETARY -* INFORMATION AND/OR TRADE SECRET. -* -* NOTICE: ALL CODE, PROGRAM, INFORMATION, SCRIPT, INSTRUCTION, -* DATA, AND COMMENT HEREIN IS AND SHALL REMAIN THE CONFIDENTIAL -* INFORMATION AND PROPERTY OF MULTI-TECH SYSTEMS, INC. -* USE AND DISCLOSURE THEREOF, EXCEPT AS STRICTLY AUTHORIZED IN A -* WRITTEN AGREEMENT SIGNED BY MULTI-TECH SYSTEMS, INC. IS PROHIBITED. -* -***********************************************************************/ + * COPYRIGHT 2020 MULTI-TECH SYSTEMS, INC. + * + * ALL RIGHTS RESERVED BY AND FOR THE EXCLUSIVE BENEFIT OF + * MULTI-TECH SYSTEMS, INC. + * + * MULTI-TECH SYSTEMS, INC. - CONFIDENTIAL AND PROPRIETARY + * INFORMATION AND/OR TRADE SECRET. + * + * NOTICE: ALL CODE, PROGRAM, INFORMATION, SCRIPT, INSTRUCTION, + * DATA, AND COMMENT HEREIN IS AND SHALL REMAIN THE CONFIDENTIAL + * INFORMATION AND PROPERTY OF MULTI-TECH SYSTEMS, INC. + * USE AND DISCLOSURE THEREOF, EXCEPT AS STRICTLY AUTHORIZED IN A + * WRITTEN AGREEMENT SIGNED BY MULTI-TECH SYSTEMS, INC. IS PROHIBITED. + * + ***********************************************************************/ inline bool fileExists(std::string file) { struct stat buffer = {}; - return (stat (file.c_str(), &buffer) == 0) ? true : false; + return (stat(file.c_str(), &buffer) == 0) ? true : false; } -inline std::string toCamelCase(const char * d_name) { +inline std::string toCamelCase(const char *d_name) { std::string camelString = strdup(d_name); std::string tempString = ""; - for (size_t x = 0; x < camelString.length(); x++){ - if (camelString[x] == '-' || camelString[x] == '_'){ + for (size_t x = 0; x < camelString.length(); x++) { + if (camelString[x] == '-' || camelString[x] == '_') { tempString = camelString.substr(x + 1, 1); - transform(tempString.begin(), tempString.end(), tempString.begin(), toupper); + transform(tempString.begin(), tempString.end(), tempString.begin(), + toupper); camelString.erase(x, 2); camelString.insert(x, tempString); } @@ -50,7 +51,7 @@ inline void exitHandler(int code) { inline mode_t fileType(std::string file) { struct stat buf = {}; - if (stat (file.c_str(), &buf) == 0) { + if (stat(file.c_str(), &buf) == 0) { return buf.st_mode & S_IFMT; } else { return -1; diff --git a/src/AccessoryCards/AccessoryCard.cpp b/src/AccessoryCards/AccessoryCard.cpp new file mode 100644 index 0000000..0c7c2a0 --- /dev/null +++ b/src/AccessoryCards/AccessoryCard.cpp @@ -0,0 +1,26 @@ +/********************************************************************** + * COPYRIGHT 2020 MULTI-TECH SYSTEMS, INC. + * + * ALL RIGHTS RESERVED BY AND FOR THE EXCLUSIVE BENEFIT OF + * MULTI-TECH SYSTEMS, INC. + * + * MULTI-TECH SYSTEMS, INC. - CONFIDENTIAL AND PROPRIETARY + * INFORMATION AND/OR TRADE SECRET. + * + * NOTICE: ALL CODE, PROGRAM, INFORMATION, SCRIPT, INSTRUCTION, + * DATA, AND COMMENT HEREIN IS AND SHALL REMAIN THE CONFIDENTIAL + * INFORMATION AND PROPERTY OF MULTI-TECH SYSTEMS, INC. + * USE AND DISCLOSURE THEREOF, EXCEPT AS STRICTLY AUTHORIZED IN A + * WRITTEN AGREEMENT SIGNED BY MULTI-TECH SYSTEMS, INC. IS PROHIBITED. + * + ***********************************************************************/ + +#include "Device.h" + +Device::AccessoryCard::AccessoryCard(Device &d, const std::regex Name) + : device(d), name(Name) {} + +void Device::AccessoryCard::AddToDeviceInfo(const std::string Port, + const std::string ProductID) {} + +const std::regex Device::AccessoryCard::GetName() { return name; } \ No newline at end of file diff --git a/src/AccessoryCards/AcessoryCard.cpp b/src/AccessoryCards/AcessoryCard.cpp deleted file mode 100644 index 6a7a0d8..0000000 --- a/src/AccessoryCards/AcessoryCard.cpp +++ /dev/null @@ -1,21 +0,0 @@ -/********************************************************************** -* COPYRIGHT 2020 MULTI-TECH SYSTEMS, INC. -* -* ALL RIGHTS RESERVED BY AND FOR THE EXCLUSIVE BENEFIT OF -* MULTI-TECH SYSTEMS, INC. -* -* MULTI-TECH SYSTEMS, INC. - CONFIDENTIAL AND PROPRIETARY -* INFORMATION AND/OR TRADE SECRET. -* -* NOTICE: ALL CODE, PROGRAM, INFORMATION, SCRIPT, INSTRUCTION, -* DATA, AND COMMENT HEREIN IS AND SHALL REMAIN THE CONFIDENTIAL -* INFORMATION AND PROPERTY OF MULTI-TECH SYSTEMS, INC. -* USE AND DISCLOSURE THEREOF, EXCEPT AS STRICTLY AUTHORIZED IN A -* WRITTEN AGREEMENT SIGNED BY MULTI-TECH SYSTEMS, INC. IS PROHIBITED. -* -***********************************************************************/ - -#include "Device.h" - -Device::AccessoryCard::AccessoryCard(Device& d, const std::string ProductId, const std::string Port) : device(d), productId(ProductId), port(Port) { -} diff --git a/src/AccessoryCards/Gpiob.cpp b/src/AccessoryCards/Gpiob.cpp index 44728ae..c580aeb 100644 --- a/src/AccessoryCards/Gpiob.cpp +++ b/src/AccessoryCards/Gpiob.cpp @@ -1,23 +1,27 @@ /********************************************************************** -* COPYRIGHT 2020 MULTI-TECH SYSTEMS, INC. -* -* ALL RIGHTS RESERVED BY AND FOR THE EXCLUSIVE BENEFIT OF -* MULTI-TECH SYSTEMS, INC. -* -* MULTI-TECH SYSTEMS, INC. - CONFIDENTIAL AND PROPRIETARY -* INFORMATION AND/OR TRADE SECRET. -* -* NOTICE: ALL CODE, PROGRAM, INFORMATION, SCRIPT, INSTRUCTION, -* DATA, AND COMMENT HEREIN IS AND SHALL REMAIN THE CONFIDENTIAL -* INFORMATION AND PROPERTY OF MULTI-TECH SYSTEMS, INC. -* USE AND DISCLOSURE THEREOF, EXCEPT AS STRICTLY AUTHORIZED IN A -* WRITTEN AGREEMENT SIGNED BY MULTI-TECH SYSTEMS, INC. IS PROHIBITED. -* -***********************************************************************/ + * COPYRIGHT 2020 MULTI-TECH SYSTEMS, INC. + * + * ALL RIGHTS RESERVED BY AND FOR THE EXCLUSIVE BENEFIT OF + * MULTI-TECH SYSTEMS, INC. + * + * MULTI-TECH SYSTEMS, INC. - CONFIDENTIAL AND PROPRIETARY + * INFORMATION AND/OR TRADE SECRET. + * + * NOTICE: ALL CODE, PROGRAM, INFORMATION, SCRIPT, INSTRUCTION, + * DATA, AND COMMENT HEREIN IS AND SHALL REMAIN THE CONFIDENTIAL + * INFORMATION AND PROPERTY OF MULTI-TECH SYSTEMS, INC. + * USE AND DISCLOSURE THEREOF, EXCEPT AS STRICTLY AUTHORIZED IN A + * WRITTEN AGREEMENT SIGNED BY MULTI-TECH SYSTEMS, INC. IS PROHIBITED. + * + ***********************************************************************/ #include "Device.h" -Device::Gpiob::Gpiob(Device& d, const std::string ProductId, const std::string Port) : AccessoryCard(d, ProductId, Port) { +Device::Gpiob::Gpiob(Device &d) + : AccessoryCard(d, std::regex("(MTAC-GPIOB)|(MMTAC-GPIOI)")) {} + +void Device::Gpiob::AddToDeviceInfo(const std::string Port, + const std::string ProductID) { capabilityList["adc"] = true; capabilityList["din"] = true; capabilityList["dout"] = true; diff --git a/src/AccessoryCards/LoraCard.cpp b/src/AccessoryCards/LoraCard.cpp index 7a248dc..fe2a8d2 100644 --- a/src/AccessoryCards/LoraCard.cpp +++ b/src/AccessoryCards/LoraCard.cpp @@ -1,26 +1,26 @@ /********************************************************************** -* COPYRIGHT 2020 MULTI-TECH SYSTEMS, INC. -* -* ALL RIGHTS RESERVED BY AND FOR THE EXCLUSIVE BENEFIT OF -* MULTI-TECH SYSTEMS, INC. -* -* MULTI-TECH SYSTEMS, INC. - CONFIDENTIAL AND PROPRIETARY -* INFORMATION AND/OR TRADE SECRET. -* -* NOTICE: ALL CODE, PROGRAM, INFORMATION, SCRIPT, INSTRUCTION, -* DATA, AND COMMENT HEREIN IS AND SHALL REMAIN THE CONFIDENTIAL -* INFORMATION AND PROPERTY OF MULTI-TECH SYSTEMS, INC. -* USE AND DISCLOSURE THEREOF, EXCEPT AS STRICTLY AUTHORIZED IN A -* WRITTEN AGREEMENT SIGNED BY MULTI-TECH SYSTEMS, INC. IS PROHIBITED. -* -***********************************************************************/ + * COPYRIGHT 2020 MULTI-TECH SYSTEMS, INC. + * + * ALL RIGHTS RESERVED BY AND FOR THE EXCLUSIVE BENEFIT OF + * MULTI-TECH SYSTEMS, INC. + * + * MULTI-TECH SYSTEMS, INC. - CONFIDENTIAL AND PROPRIETARY + * INFORMATION AND/OR TRADE SECRET. + * + * NOTICE: ALL CODE, PROGRAM, INFORMATION, SCRIPT, INSTRUCTION, + * DATA, AND COMMENT HEREIN IS AND SHALL REMAIN THE CONFIDENTIAL + * INFORMATION AND PROPERTY OF MULTI-TECH SYSTEMS, INC. + * USE AND DISCLOSURE THEREOF, EXCEPT AS STRICTLY AUTHORIZED IN A + * WRITTEN AGREEMENT SIGNED BY MULTI-TECH SYSTEMS, INC. IS PROHIBITED. + * + ***********************************************************************/ #include "Device.h" -Device::LoraCard::LoraCard(Device& d, const std::string ProductId, const std::string Port) : AccessoryCard(d, ProductId, Port), spiPath("/dev/spidev0.0") {} +Device::LoraCard::LoraCard(Device &d, const std::regex Name) + : AccessoryCard(d, Name), spiPath("/dev/spidev0.0"), fpgaVersion(255) {} -void Device::LoraCard::setCapabilities() { +void Device::LoraCard::AddToDeviceInfo(const std::string Port, + const std::string ProductID) { device.capabilityList["lora"] = true; - device.accessoryCard.AddMember("fpgaVersion", fpgaVersion, device.accessoryCardsAlloc); - device.accessoryCard.AddMember("spiPath", rapidjson::Value().SetString(spiPath.c_str(), device.accessoryCardsAlloc), device.accessoryCardsAlloc); } \ No newline at end of file diff --git a/src/AccessoryCards/LoraCard03.cpp b/src/AccessoryCards/LoraCard03.cpp new file mode 100644 index 0000000..7e9f9ae --- /dev/null +++ b/src/AccessoryCards/LoraCard03.cpp @@ -0,0 +1,53 @@ +/********************************************************************** + * COPYRIGHT 2020 MULTI-TECH SYSTEMS, INC. + * + * ALL RIGHTS RESERVED BY AND FOR THE EXCLUSIVE BENEFIT OF + * MULTI-TECH SYSTEMS, INC. + * + * MULTI-TECH SYSTEMS, INC. - CONFIDENTIAL AND PROPRIETARY + * INFORMATION AND/OR TRADE SECRET. + * + * NOTICE: ALL CODE, PROGRAM, INFORMATION, SCRIPT, INSTRUCTION, + * DATA, AND COMMENT HEREIN IS AND SHALL REMAIN THE CONFIDENTIAL + * INFORMATION AND PROPERTY OF MULTI-TECH SYSTEMS, INC. + * USE AND DISCLOSURE THEREOF, EXCEPT AS STRICTLY AUTHORIZED IN A + * WRITTEN AGREEMENT SIGNED BY MULTI-TECH SYSTEMS, INC. IS PROHIBITED. + * + ***********************************************************************/ + +#include "Device.h" + +Device::Lora03Card::Lora03Card(Device &d) + : LoraCard(d, std::regex("(MTAC-003)(.*)|(MTCAP3-003)(.*)")) {} + +void Device::Lora03Card::AddToDeviceInfo(const std::string Port, + const std::string ProductID) { + + LoraCard::AddToDeviceInfo(Port, ProductID); + /* Map the spi path to the port/hw version */ + std::string deviceHwVersion = ""; + MTS::System::readFile(HW_VERSION_PATH, deviceHwVersion); + if (deviceHwVersion.find("MTCAP3") != std::string::npos) { + spiPath = "/dev/spidev1.0"; + spiPath1261 = "/dev/spidev1.1"; + tmp102 = 0x48; + } else if (Port.back() == '2') { + spiPath = "/dev/spidev1.0"; + spiPath1261 = "/dev/spidev1.1"; + tmp102 = 0x49; + } else { + spiPath = "/dev/spidev0.0"; + spiPath1261 = "/dev/spidev0.1"; + tmp102 = 0x48; + } + + device.accessoryCard.AddMember( + "spiPath", + rapidjson::Value().SetString(spiPath.c_str(), device.acAlloc), + device.acAlloc); + device.accessoryCard.AddMember( + "spiPath1261", + rapidjson::Value().SetString(spiPath1261.c_str(), device.acAlloc), + device.acAlloc); + device.accessoryCard.AddMember("tmp102", tmp102, device.acAlloc); +} \ No newline at end of file diff --git a/src/AccessoryCards/LoraCard10.cpp b/src/AccessoryCards/LoraCard10.cpp new file mode 100644 index 0000000..e74b848 --- /dev/null +++ b/src/AccessoryCards/LoraCard10.cpp @@ -0,0 +1,38 @@ +/********************************************************************** + * COPYRIGHT 2020 MULTI-TECH SYSTEMS, INC. + * + * ALL RIGHTS RESERVED BY AND FOR THE EXCLUSIVE BENEFIT OF + * MULTI-TECH SYSTEMS, INC. + * + * MULTI-TECH SYSTEMS, INC. - CONFIDENTIAL AND PROPRIETARY + * INFORMATION AND/OR TRADE SECRET. + * + * NOTICE: ALL CODE, PROGRAM, INFORMATION, SCRIPT, INSTRUCTION, + * DATA, AND COMMENT HEREIN IS AND SHALL REMAIN THE CONFIDENTIAL + * INFORMATION AND PROPERTY OF MULTI-TECH SYSTEMS, INC. + * USE AND DISCLOSURE THEREOF, EXCEPT AS STRICTLY AUTHORIZED IN A + * WRITTEN AGREEMENT SIGNED BY MULTI-TECH SYSTEMS, INC. IS PROHIBITED. + * + ***********************************************************************/ + +#include "Device.h" + +Device::Lora10Card::Lora10Card(Device &d) + : LoraCard(d, std::regex("(MTAC-LORA-915)|(MTAC-LORA-868)")) {} + +void Device::Lora10Card::AddToDeviceInfo(const std::string Port, + const std::string ProductID) { + + LoraCard::AddToDeviceInfo(Port, ProductID); + + if (Port.back() == '2') { + spiPath = "/dev/spidev1.2"; + } else { + spiPath = "/dev/spidev0.2"; + } + + device.accessoryCard.AddMember( + "spiPath", + rapidjson::Value().SetString(spiPath.c_str(), device.acAlloc), + device.acAlloc); +} \ No newline at end of file diff --git a/src/AccessoryCards/LoraCard15.cpp b/src/AccessoryCards/LoraCard15.cpp index a7a1dad..3ed0f31 100644 --- a/src/AccessoryCards/LoraCard15.cpp +++ b/src/AccessoryCards/LoraCard15.cpp @@ -1,172 +1,45 @@ /********************************************************************** -* COPYRIGHT 2020 MULTI-TECH SYSTEMS, INC. -* -* ALL RIGHTS RESERVED BY AND FOR THE EXCLUSIVE BENEFIT OF -* MULTI-TECH SYSTEMS, INC. -* -* MULTI-TECH SYSTEMS, INC. - CONFIDENTIAL AND PROPRIETARY -* INFORMATION AND/OR TRADE SECRET. -* -* NOTICE: ALL CODE, PROGRAM, INFORMATION, SCRIPT, INSTRUCTION, -* DATA, AND COMMENT HEREIN IS AND SHALL REMAIN THE CONFIDENTIAL -* INFORMATION AND PROPERTY OF MULTI-TECH SYSTEMS, INC. -* USE AND DISCLOSURE THEREOF, EXCEPT AS STRICTLY AUTHORIZED IN A -* WRITTEN AGREEMENT SIGNED BY MULTI-TECH SYSTEMS, INC. IS PROHIBITED. -* -***********************************************************************/ + * COPYRIGHT 2020 MULTI-TECH SYSTEMS, INC. + * + * ALL RIGHTS RESERVED BY AND FOR THE EXCLUSIVE BENEFIT OF + * MULTI-TECH SYSTEMS, INC. + * + * MULTI-TECH SYSTEMS, INC. - CONFIDENTIAL AND PROPRIETARY + * INFORMATION AND/OR TRADE SECRET. + * + * NOTICE: ALL CODE, PROGRAM, INFORMATION, SCRIPT, INSTRUCTION, + * DATA, AND COMMENT HEREIN IS AND SHALL REMAIN THE CONFIDENTIAL + * INFORMATION AND PROPERTY OF MULTI-TECH SYSTEMS, INC. + * USE AND DISCLOSURE THEREOF, EXCEPT AS STRICTLY AUTHORIZED IN A + * WRITTEN AGREEMENT SIGNED BY MULTI-TECH SYSTEMS, INC. IS PROHIBITED. + * + ***********************************************************************/ #include "Device.h" -Device::Lora15Card::Lora15Card(Device& d, const std::string ProductId, const std::string Port) : LoraCard(d, ProductId, Port) { - int ret; - std::string deviceHwVersion = ""; - /* Map the spi path to the device hw version/mtac product id, with the default being spidev0.0 */ - MTS::System::readFile(HW_VERSION_PATH, deviceHwVersion); - if (deviceHwVersion.find("MTCDT3-") != std::string::npos) { - if (port.back() == '2') { - spiPath = "/dev/spidev1.2"; - } else { - spiPath = "/dev/spidev0.2"; - } - } else if (productId.find("MTAC-LORA-") == 0) { - if (port.back() == '2') { - spiPath = "/dev/spidev32765.2"; - } else { - spiPath = "/dev/spidev32766.2"; - } - } - ret = spiOpen(spiPath.c_str()); - if (ret != 0) { - printf("Could not open SPI port %s", spiPath.c_str()); - return; - } - /* detect if the gateway has an FPGA with SPI mux header support */ - ret = spiRead(MTAC_FPGA_ADDRESS, &fpgaVersion); - if (ret != 0) { - printf("Could not read FPGA version"); - fpgaVersion = 255; - } - - spiClose(); - spi_target_ptr = NULL; - setCapabilities(); -} - -int Device::Lora15Card::spiOpen(const char *spidev) { - int *spi_device = NULL; - int dev; - int a = 0, b = 0; - int i; - - /* allocate memory for the device descriptor */ - spi_device = (int *)malloc(sizeof(int)); - if (spi_device == NULL) { - printf("ERROR: MALLOC FAIL\n"); - return -1; - } - - /* open SPI device */ - dev = open(spidev, O_RDWR); - if (dev < 0) { - printf("ERROR: failed to open SPI device %s\n", spidev); - return -1; - } +Device::Lora15Card::Lora15Card(Device &d) + : LoraCard(d, std::regex("(MTAC-LORA-H)(.*)|(MTAC-LORA-F)(.*)|(MTCAP-LORA-)" + "(.*)|(MTLGA-)(.*)|(MTCDT3-)(.*)")) {} - /* setting SPI mode to 'mode 0' */ - i = SPI_MODE_3; - a = ioctl(dev, SPI_IOC_WR_MODE, &i); - b = ioctl(dev, SPI_IOC_RD_MODE, &i); - if ((a < 0) || (b < 0)) { - printf("ERROR: SPI PORT FAIL TO SET IN MODE 0\n"); - close(dev); - free(spi_device); - return -1; - } +void Device::Lora15Card::AddToDeviceInfo(const std::string Port, + const std::string ProductID) { - /* setting SPI max clk (in Hz) */ - i = SPI_SPEED; - a = ioctl(dev, SPI_IOC_WR_MAX_SPEED_HZ, &i); - b = ioctl(dev, SPI_IOC_RD_MAX_SPEED_HZ, &i); - if ((a < 0) || (b < 0)) { - printf("ERROR: SPI PORT FAIL TO SET MAX SPEED\n"); - close(dev); - free(spi_device); - return -1; - } + LoraCard::AddToDeviceInfo(Port, ProductID); - /* setting SPI to MSB first */ - i = 0; - a = ioctl(dev, SPI_IOC_WR_LSB_FIRST, &i); - b = ioctl(dev, SPI_IOC_RD_LSB_FIRST, &i); - if ((a < 0) || (b < 0)) { - printf("ERROR: SPI PORT FAIL TO SET MSB FIRST\n"); - close(dev); - free(spi_device); - return -1; - } - - /* setting SPI to 8 bits per word */ - i = 0; - a = ioctl(dev, SPI_IOC_WR_BITS_PER_WORD, &i); - b = ioctl(dev, SPI_IOC_RD_BITS_PER_WORD, &i); - if ((a < 0) || (b < 0)) { - printf("ERROR: SPI PORT FAIL TO SET 8 BITS-PER-WORD\n"); - close(dev); - return -1; - } - - *spi_device = dev; - spi_target_ptr = (void *)spi_device; - return 0; -} -int Device::Lora15Card::spiRead(uint8_t address, uint8_t *data) { - int spi_device; - uint8_t out_buf[3]; - uint8_t in_buf[ARRAY_SIZE(out_buf)]; - uint8_t command_size; - struct spi_ioc_transfer k; - int a; - - spi_device = *(int *)spi_target_ptr; /* spi_target cannot be null beforehand */ - - /* prepare frame to be sent */ - out_buf[0] = MTAC_FPGA; - out_buf[1] = READ_ACCESS | (address & 0x7F); - out_buf[2] = 0x00; - command_size = 3; - - /* I/O transaction */ - memset(&k, 0, sizeof(k)); /* clear k */ - k.tx_buf = (unsigned long)out_buf; - k.rx_buf = (unsigned long)in_buf; - k.len = command_size; - k.cs_change = 1; - a = ioctl(spi_device, SPI_IOC_MESSAGE(1), &k); - - /* determine return code */ - if (a != (int)k.len) { - printf("ERROR: SPI READ FAILURE\n"); - return -1; + if (ProductID.rfind("MTCAP", 0) == 0) { + spiPath = "/dev/spidev0.0"; + } else if (Port.back() == '2') { + spiPath = "/dev/spidev1.2"; } else { - *data = in_buf[command_size - 1]; - return 0; + spiPath = "/dev/spidev0.2"; } -} - -int Device::Lora15Card::spiClose() { - int spi_device; - int a; - - /* close file & deallocate file descriptor */ - spi_device = *(int *)spi_target_ptr; /* check that spi_target is not null */ - a = close(spi_device); - free(spi_target_ptr); - /* determine return code */ - if (a < 0) { - printf("ERROR: SPI PORT FAILED TO CLOSE\n"); - return -1; - } else { - return 0; - } + Mtac15Fpga mtac15Fpga(spiPath); + mtac15Fpga.getFpgaVersion(); + fpgaVersion = mtac15Fpga.FpgaVersion(); + device.accessoryCard.AddMember( + "spiPath", + rapidjson::Value().SetString(spiPath.c_str(), device.acAlloc), + device.acAlloc); + device.accessoryCard.AddMember("fpgaVersion", fpgaVersion, device.acAlloc); } \ No newline at end of file diff --git a/src/AccessoryCards/LoraCard21.cpp b/src/AccessoryCards/LoraCard21.cpp index d40876b..4337bfa 100644 --- a/src/AccessoryCards/LoraCard21.cpp +++ b/src/AccessoryCards/LoraCard21.cpp @@ -1,25 +1,39 @@ /********************************************************************** -* COPYRIGHT 2020 MULTI-TECH SYSTEMS, INC. -* -* ALL RIGHTS RESERVED BY AND FOR THE EXCLUSIVE BENEFIT OF -* MULTI-TECH SYSTEMS, INC. -* -* MULTI-TECH SYSTEMS, INC. - CONFIDENTIAL AND PROPRIETARY -* INFORMATION AND/OR TRADE SECRET. -* -* NOTICE: ALL CODE, PROGRAM, INFORMATION, SCRIPT, INSTRUCTION, -* DATA, AND COMMENT HEREIN IS AND SHALL REMAIN THE CONFIDENTIAL -* INFORMATION AND PROPERTY OF MULTI-TECH SYSTEMS, INC. -* USE AND DISCLOSURE THEREOF, EXCEPT AS STRICTLY AUTHORIZED IN A -* WRITTEN AGREEMENT SIGNED BY MULTI-TECH SYSTEMS, INC. IS PROHIBITED. -* -***********************************************************************/ + * COPYRIGHT 2020 MULTI-TECH SYSTEMS, INC. + * + * ALL RIGHTS RESERVED BY AND FOR THE EXCLUSIVE BENEFIT OF + * MULTI-TECH SYSTEMS, INC. + * + * MULTI-TECH SYSTEMS, INC. - CONFIDENTIAL AND PROPRIETARY + * INFORMATION AND/OR TRADE SECRET. + * + * NOTICE: ALL CODE, PROGRAM, INFORMATION, SCRIPT, INSTRUCTION, + * DATA, AND COMMENT HEREIN IS AND SHALL REMAIN THE CONFIDENTIAL + * INFORMATION AND PROPERTY OF MULTI-TECH SYSTEMS, INC. + * USE AND DISCLOSURE THEREOF, EXCEPT AS STRICTLY AUTHORIZED IN A + * WRITTEN AGREEMENT SIGNED BY MULTI-TECH SYSTEMS, INC. IS PROHIBITED. + * + ***********************************************************************/ #include "Device.h" -Device::Lora21Card::Lora21Card(Device& d, const std::string ProductId, const std::string Port): LoraCard(d, ProductId, Port) { +Device::Lora21Card::Lora21Card(Device &d) + : LoraCard(d, std::regex("(MTAC-LORA-G16)(.*)")) {} +Device::Lora21Card::Lora21Card(Device &d, const std::regex Name) + : LoraCard(d, Name) {} + +void Device::Lora21Card::AddToDeviceInfo(const std::string Port, + const std::string ProductID) { + + LoraCard::AddToDeviceInfo(Port, ProductID); + spiPath = "/dev/spidev32766.2"; MTS::System::cmd(LORA_2_1_FPGA_VERSION, cmdFpgaVersion); fpgaVersion = std::stoi(cmdFpgaVersion); - setCapabilities(); + + device.accessoryCard.AddMember("fpgaVersion", fpgaVersion, device.acAlloc); + device.accessoryCard.AddMember( + "spiPath", + rapidjson::Value().SetString(spiPath.c_str(), device.acAlloc), + device.acAlloc); } \ No newline at end of file diff --git a/src/AccessoryCards/LoraCard21Ext.cpp b/src/AccessoryCards/LoraCard21Ext.cpp index 2595286..b25dbfe 100644 --- a/src/AccessoryCards/LoraCard21Ext.cpp +++ b/src/AccessoryCards/LoraCard21Ext.cpp @@ -1,23 +1,31 @@ /********************************************************************** -* COPYRIGHT 2020 MULTI-TECH SYSTEMS, INC. -* -* ALL RIGHTS RESERVED BY AND FOR THE EXCLUSIVE BENEFIT OF -* MULTI-TECH SYSTEMS, INC. -* -* MULTI-TECH SYSTEMS, INC. - CONFIDENTIAL AND PROPRIETARY -* INFORMATION AND/OR TRADE SECRET. -* -* NOTICE: ALL CODE, PROGRAM, INFORMATION, SCRIPT, INSTRUCTION, -* DATA, AND COMMENT HEREIN IS AND SHALL REMAIN THE CONFIDENTIAL -* INFORMATION AND PROPERTY OF MULTI-TECH SYSTEMS, INC. -* USE AND DISCLOSURE THEREOF, EXCEPT AS STRICTLY AUTHORIZED IN A -* WRITTEN AGREEMENT SIGNED BY MULTI-TECH SYSTEMS, INC. IS PROHIBITED. -* -***********************************************************************/ + * COPYRIGHT 2020 MULTI-TECH SYSTEMS, INC. + * + * ALL RIGHTS RESERVED BY AND FOR THE EXCLUSIVE BENEFIT OF + * MULTI-TECH SYSTEMS, INC. + * + * MULTI-TECH SYSTEMS, INC. - CONFIDENTIAL AND PROPRIETARY + * INFORMATION AND/OR TRADE SECRET. + * + * NOTICE: ALL CODE, PROGRAM, INFORMATION, SCRIPT, INSTRUCTION, + * DATA, AND COMMENT HEREIN IS AND SHALL REMAIN THE CONFIDENTIAL + * INFORMATION AND PROPERTY OF MULTI-TECH SYSTEMS, INC. + * USE AND DISCLOSURE THEREOF, EXCEPT AS STRICTLY AUTHORIZED IN A + * WRITTEN AGREEMENT SIGNED BY MULTI-TECH SYSTEMS, INC. IS PROHIBITED. + * + ***********************************************************************/ #include "Device.h" -Device::Lora21ExtCard::Lora21ExtCard(Device& d, const std::string ProductId, const std::string Port): Lora21Card(d, ProductId, Port) { +Device::Lora21ExtCard::Lora21ExtCard(Device &d) + : Lora21Card(d, std::regex("(MTAC-LORA-G64)(.*)")) {} + +void Device::Lora21ExtCard::AddToDeviceInfo(const std::string Port, + const std::string ProductID) { + + LoraCard::AddToDeviceInfo(Port, ProductID); + MTS::System::cmd(LORA_2_1_EXT_FPGA_VERSION, cmdFpgaVersion2); - device.accessoryCard.AddMember("fpgaVersion2", std::stoi(cmdFpgaVersion2), device.accessoryCardsAlloc); + device.accessoryCard.AddMember("fpgaVersion2", std::stoi(cmdFpgaVersion2), + device.acAlloc); } \ No newline at end of file diff --git a/src/AccessoryCards/LoraCard2G4.cpp b/src/AccessoryCards/LoraCard2G4.cpp new file mode 100644 index 0000000..10691ce --- /dev/null +++ b/src/AccessoryCards/LoraCard2G4.cpp @@ -0,0 +1,32 @@ +/********************************************************************** + * COPYRIGHT 2020 MULTI-TECH SYSTEMS, INC. + * + * ALL RIGHTS RESERVED BY AND FOR THE EXCLUSIVE BENEFIT OF + * MULTI-TECH SYSTEMS, INC. + * + * MULTI-TECH SYSTEMS, INC. - CONFIDENTIAL AND PROPRIETARY + * INFORMATION AND/OR TRADE SECRET. + * + * NOTICE: ALL CODE, PROGRAM, INFORMATION, SCRIPT, INSTRUCTION, + * DATA, AND COMMENT HEREIN IS AND SHALL REMAIN THE CONFIDENTIAL + * INFORMATION AND PROPERTY OF MULTI-TECH SYSTEMS, INC. + * USE AND DISCLOSURE THEREOF, EXCEPT AS STRICTLY AUTHORIZED IN A + * WRITTEN AGREEMENT SIGNED BY MULTI-TECH SYSTEMS, INC. IS PROHIBITED. + * + ***********************************************************************/ + +#include "Device.h" + +Device::Lora2G4Card::Lora2G4Card(Device &d) + : LoraCard(d, std::regex("(MTAC-LORA-2G4)")) {} + +void Device::Lora2G4Card::AddToDeviceInfo(const std::string Port, + const std::string ProductID) { + + LoraCard::AddToDeviceInfo(Port, ProductID); + std::string ttyPath = "/dev/ttyACM0"; + device.accessoryCard.AddMember( + "ttyPath", + rapidjson::Value().SetString(ttyPath.c_str(), device.acAlloc), + device.acAlloc); +} \ No newline at end of file diff --git a/src/AccessoryCards/Mfser.cpp b/src/AccessoryCards/Mfser.cpp index dfdfeb3..03a00b7 100644 --- a/src/AccessoryCards/Mfser.cpp +++ b/src/AccessoryCards/Mfser.cpp @@ -1,28 +1,37 @@ /********************************************************************** -* COPYRIGHT 2020 MULTI-TECH SYSTEMS, INC. -* -* ALL RIGHTS RESERVED BY AND FOR THE EXCLUSIVE BENEFIT OF -* MULTI-TECH SYSTEMS, INC. -* -* MULTI-TECH SYSTEMS, INC. - CONFIDENTIAL AND PROPRIETARY -* INFORMATION AND/OR TRADE SECRET. -* -* NOTICE: ALL CODE, PROGRAM, INFORMATION, SCRIPT, INSTRUCTION, -* DATA, AND COMMENT HEREIN IS AND SHALL REMAIN THE CONFIDENTIAL -* INFORMATION AND PROPERTY OF MULTI-TECH SYSTEMS, INC. -* USE AND DISCLOSURE THEREOF, EXCEPT AS STRICTLY AUTHORIZED IN A -* WRITTEN AGREEMENT SIGNED BY MULTI-TECH SYSTEMS, INC. IS PROHIBITED. -* -***********************************************************************/ + * COPYRIGHT 2020 MULTI-TECH SYSTEMS, INC. + * + * ALL RIGHTS RESERVED BY AND FOR THE EXCLUSIVE BENEFIT OF + * MULTI-TECH SYSTEMS, INC. + * + * MULTI-TECH SYSTEMS, INC. - CONFIDENTIAL AND PROPRIETARY + * INFORMATION AND/OR TRADE SECRET. + * + * NOTICE: ALL CODE, PROGRAM, INFORMATION, SCRIPT, INSTRUCTION, + * DATA, AND COMMENT HEREIN IS AND SHALL REMAIN THE CONFIDENTIAL + * INFORMATION AND PROPERTY OF MULTI-TECH SYSTEMS, INC. + * USE AND DISCLOSURE THEREOF, EXCEPT AS STRICTLY AUTHORIZED IN A + * WRITTEN AGREEMENT SIGNED BY MULTI-TECH SYSTEMS, INC. IS PROHIBITED. + * + ***********************************************************************/ #include "Device.h" -Device::Mfser::Mfser(Device& d, const std::string ProductId, const std::string Port) : AccessoryCard(d, ProductId, Port) { - capabilityList["rs232"] = true; + +Device::Mfser::Mfser(Device &d) + : AccessoryCard( + d, std::regex("(MTAC-MFSER-DTE)|(MTAC-MFSER-DCE)|(MTR-)(.*)")) {} + +void Device::Mfser::AddToDeviceInfo(const std::string Port, + const std::string ProductID) { + + capabilityList["rs232"] = true; capabilityList["rs422"] = true; capabilityList["rs485"] = true; capabilityList["serial"] = true; - if (!fileExists("/dev/ext_serial") && port.size() > 0) { + if (!fileExists("/dev/ext_serial") && Port.size() > 0) { std::string temp; - MTS::System::cmd(std::string("ln -s /dev/ttyAP") + port.back() + " /dev/ext_serial", temp); + MTS::System::cmd(std::string("ln -s /dev/ttyAP") + Port.back() + + " /dev/ext_serial", + temp); } } \ No newline at end of file diff --git a/src/AccessoryCards/Mtac15Fpga.cpp b/src/AccessoryCards/Mtac15Fpga.cpp new file mode 100644 index 0000000..151ff77 --- /dev/null +++ b/src/AccessoryCards/Mtac15Fpga.cpp @@ -0,0 +1,803 @@ +/********************************************************************** + * COPYRIGHT 2020 MULTI-TECH SYSTEMS, INC. + * + * ALL RIGHTS RESERVED BY AND FOR THE EXCLUSIVE BENEFIT OF + * MULTI-TECH SYSTEMS, INC. + * + * MULTI-TECH SYSTEMS, INC. - CONFIDENTIAL AND PROPRIETARY + * INFORMATION AND/OR TRADE SECRET. + * + * NOTICE: ALL CODE, PROGRAM, INFORMATION, SCRIPT, INSTRUCTION, + * DATA, AND COMMENT HEREIN IS AND SHALL REMAIN THE CONFIDENTIAL + * INFORMATION AND PROPERTY OF MULTI-TECH SYSTEMS, INC. + * USE AND DISCLOSURE THEREOF, EXCEPT AS STRICTLY AUTHORIZED IN A + * WRITTEN AGREEMENT SIGNED BY MULTI-TECH SYSTEMS, INC. IS PROHIBITED. + * + ***********************************************************************/ + +#include "Fpga.h" + +/* -------------------------------------------------------------------------- */ +/* --- Flash opcodes ---------------------------------------------------------*/ +#define WR_STATUS_REG 0x01 /* Write Status Register */ +#define PAGE_PROGRAM 0x02 /* Write up to a Page of the Memory */ +#define READ_DATA 0x03 /* Read from the Memory */ +#define WRITE_DISABLE 0x04 /* Disable Writing to the Memory */ +#define RD_STATUS_REG_1 0x05 /* Read Status Register-1 */ +#define WRITE_ENABLE 0x06 /* Enable Writing to the Memory */ +#define FAST_READ_DATA 0x0B /* Fast Read from the Memory */ +#define SECTOR_ERASE 0x20 /* Erase a Sector (4kb) */ u +#define RD_STATUS_REG_2 0x35 /* Read Status Register-2 */ +#define UNIQUE_ID 0x4B /* Read Unique ID */ +#define WE_STATUS_REG 0x50 /* Write Enable for Status Registers */ +#define BLOCK_ERASE_32 0x52 /* Erase a Block (32kb) */ +#define CHIP_ERASE 0x60 /* Erase Entire Chip */ +#define MNFTR_DEV_ID 0x90 /* Read Manufacturer ID followed by Device ID */ +#define JEDEC_ID 0x9F /* Read JEDEC ID */ +#define CHIP_RELEASE 0xAB /* Release chip from power down */ +#define BLOCK_ERASE_64 0xD8 /* Erase a Block (64kb) */ + +static const uint8_t fpga_version[] = {28, 31, 33, 35, 37}; +static const struct mtac_reg_s loregs[3] = { + {-1, 0, 0, 0, 2, 0, 0}, /* PAGE_REG */ + {-1, 0, 7, 0, 1, 0, 0}, /* SOFT_RESET */ + {-1, 1, 0, 0, 8, 1, 103} /* VERSION */ +}; + +/* -------------------------------------------------------------------------- */ +/* --- PRIVATE CONSTANTS ---------------------------------------------------- */ + +static const char + *valid_hashes[3][4] = + { + { + "d9f811fcab57947db3c2323242885a32a7f095a069d3386a148466e7f3da53" + "53", /* mtcdt v28*/ + "903c1199df46d38683b1aa9fc88310abe2f317c01c3aefa77987990874aba4" + "20", /* mtcdt v31*/ + "7c190506b969aea6198daffb6c9b47685f3a4dc3ce18565c66542bac27d6f2" + "4e", /* mtcdt v33*/ + "72bcdfda72bf8677d585330caa3d609615d08d4ca6d7951f0ebbcb5a93306b" + "3c" /* mtcdt v35*/ + }, + { + "54e41b186b2c91f1bcf249648c50357165d361101fc4fe20ee9b8f0c40dce2" + "5d" /* mtcdt3 v35*/ + }, + { + "07317fe9ca59393c074215c9d923d8d01025654883291a5e89b27d21668e22" + "63", /* mtcap v28*/ + "f208ef5cae03e703951bb8799172a5eaadb74ddb90bf3e65c32030c008a88e" + "75", /* mtcap v31*/ + "aaecd468b187703dbbf76022b00268dba2a5f25300da6486d420f476c83638" + "5c", /* mtcap v33*/ + "876cc5683f612c09f96bacb27fff170358c90f3bd76a5c61ec41504eabba83" + "13" /* mtcap v35*/ + }, +}; + +/* -------------------------------------------------------------------------- */ +/* --- PRIVATE FUNCTIONS DEFINITION ------------------------------------------ + */ + +/* hash outputBuffer */ +void Mtac15Fpga::sha256_hash_string(unsigned char hash[SHA256_DIGEST_LENGTH], + char outputBuffer[65]) { + int i = 0; + for (i = 0; i < SHA256_DIGEST_LENGTH; i++) { + sprintf(outputBuffer + (i * 2), "%02x", (unsigned char)hash[i]); + } + outputBuffer[64] = 0; + printInfo("OutputBuffer hash: %s", outputBuffer); +} + +/* Initialize, update and finalize sha256 */ +void Mtac15Fpga::sha256(char *string, char outputBuffer[65]) { + unsigned char hash[SHA256_DIGEST_LENGTH]; + int len; + SHA256_CTX sha256; + SHA256_Init(&sha256); + len = strlen(string); + SHA256_Update(&sha256, string, len); + SHA256_Final(hash, &sha256); + int i = 0; + for (i = 0; i < SHA256_DIGEST_LENGTH; i++) { + sprintf(outputBuffer + (i * 2), "%02x", (unsigned char)hash[i]); + } + outputBuffer[64] = 0; + printInfo("OutputBuffer finalized: %s", outputBuffer); +} + +/* Open input file and verify sha256 with verified list */ +int Mtac15Fpga::sha256_file(const char *path) { + printInfo("Checking hash on input file: %s", path); + + FILE *file = fopen(path, "rb"); + if (!file) { + printError("File %s not found", path); + return -1; + } else { + printInfo("Checking file %s", path); + } + + unsigned int i; + char file_hash[65]; + unsigned char hash[SHA256_DIGEST_LENGTH]; + SHA256_CTX sha256; + SHA256_Init(&sha256); + const int bufSize = 32768; + unsigned char *buffer = (unsigned char *)malloc(bufSize); + int bytesRead = 0; + + if (!buffer) + return ENOMEM; + while ((bytesRead = fread(buffer, 1, bufSize, file))) { + SHA256_Update(&sha256, buffer, bytesRead); + } + SHA256_Final(hash, &sha256); + sha256_hash_string(hash, file_hash); + fclose(file); + free(buffer); + + printInfo("Calculated input file hash: %s", file_hash); + for (i = 0; i < sizeof(valid_hashes[hardwareType]) / + sizeof(valid_hashes[hardwareType][0]); + ++i) { + if (!strcmp(valid_hashes[hardwareType][i], file_hash)) { + printInfo("File verified"); + return 0; + } + } + printError("Invalid input file"); + return -1; +} + +int Mtac15Fpga::spiOpen() { + int *spi_device = NULL; + int dev; + int a = 0, b = 0; + int i; + + /* allocate memory for the device descriptor */ + spi_device = (int *)malloc(sizeof(int)); + if (spi_device == NULL) { + printError("Malloc failed"); + return -1; + } + + /* open SPI device */ + dev = open(spiPath.c_str(), O_RDWR); + if (dev < 0) { + printError("Failed to open SPI device %s", spiPath.c_str()); + return -1; + } + + /* setting SPI mode to 'mode 0' */ + i = SPI_MODE_3; + a = ioctl(dev, SPI_IOC_WR_MODE, &i); + b = ioctl(dev, SPI_IOC_RD_MODE, &i); + if ((a < 0) || (b < 0)) { + printError("SPI port failed to set IOC MODE 0"); + close(dev); + free(spi_device); + return -1; + } + + /* setting SPI max clk (in Hz) */ + i = SPI_SPEED; + a = ioctl(dev, SPI_IOC_WR_MAX_SPEED_HZ, &i); + b = ioctl(dev, SPI_IOC_RD_MAX_SPEED_HZ, &i); + if ((a < 0) || (b < 0)) { + printError("SPI port failed to set MAX SPEED"); + close(dev); + free(spi_device); + return -1; + } + + /* setting SPI to MSB first */ + i = 0; + a = ioctl(dev, SPI_IOC_WR_LSB_FIRST, &i); + b = ioctl(dev, SPI_IOC_RD_LSB_FIRST, &i); + if ((a < 0) || (b < 0)) { + printError("SPI port failed to set MSB FIRST"); + close(dev); + free(spi_device); + return -1; + } + + /* setting SPI to 8 bits per word */ + i = 0; + a = ioctl(dev, SPI_IOC_WR_BITS_PER_WORD, &i); + b = ioctl(dev, SPI_IOC_RD_BITS_PER_WORD, &i); + if ((a < 0) || (b < 0)) { + printError("SPI port failed to set 8 bits-per-word"); + close(dev); + return -1; + } + + *spi_device = dev; + spi_target_ptr = (void *)spi_device; + return 0; +} + +int Mtac15Fpga::spiRead(uint8_t spi_mux_target, uint8_t address, + uint8_t *data) { + int spi_device; + uint8_t out_buf[3]; + uint8_t in_buf[ARRAY_SIZE(out_buf)]; + uint8_t command_size; + struct spi_ioc_transfer k; + int a; + + spi_device = + *(int *)spi_target_ptr; /* spi_target cannot be null beforehand */ + + /* prepare frame to be sent */ + out_buf[0] = spi_mux_target; + out_buf[1] = READ_ACCESS | (address & 0x7F); + out_buf[2] = 0x00; + command_size = 3; + + /* I/O transaction */ + memset(&k, 0, sizeof(k)); /* clear k */ + k.tx_buf = (unsigned long)out_buf; + k.rx_buf = (unsigned long)in_buf; + k.len = command_size; + k.cs_change = 1; + a = ioctl(spi_device, SPI_IOC_MESSAGE(1), &k); + + /* determine return code */ + if (a != (int)k.len) { + printError("SPI read failure"); + return -1; + } else { + *data = in_buf[command_size - 1]; + return 0; + } +} + +/* Simple spi write to fpga*/ +int Mtac15Fpga::spiWrite(uint8_t spi_mux_target, uint8_t address, + uint8_t data) { + int spi_device; + uint8_t out_buf[3]; + uint8_t command_size; + struct spi_ioc_transfer k; + int a; + + spi_device = + *(int *)spi_target_ptr; /* spi_target cannot be null beforehand */ + + /* prepare frame to be sent */ + out_buf[0] = spi_mux_target; + out_buf[1] = WRITE_ACCESS | (address & 0x7F); + out_buf[2] = data; + command_size = 3; + + /* I/O transaction */ + memset(&k, 0, sizeof(k)); /* clear k */ + k.tx_buf = (unsigned long)out_buf; + k.len = command_size; + k.speed_hz = SPI_SPEED; + k.cs_change = 1; + k.bits_per_word = 8; + a = ioctl(spi_device, SPI_IOC_MESSAGE(1), &k); + + /* determine return code */ + if (a != (int)k.len) { + printError("SPI write failure"); + return -1; + } else { + printDebug("SPI write success"); + return 0; + } +} + +int Mtac15Fpga::spiClose() { + int spi_device; + int a; + + /* close file & deallocate file descriptor */ + spi_device = *(int *)spi_target_ptr; /* check that spi_target is not null */ + a = close(spi_device); + free(spi_target_ptr); + + /* determine return code */ + if (a < 0) { + printError("SPI port failed to close"); + return -1; + } else { + return 0; + } +} + +/* write to creset pin */ +int Mtac15Fpga::cresetWrite(char num) { + std::string cresetPath = SYSFS_PLATFORM + port + CRESET; + int fd = open(cresetPath.c_str(), O_WRONLY); + if (fd < 0) { + printError("Unable to lock file, are you root?"); + return -1; + } + write(fd, &num, 1); + close(fd); + return 0; +} + +/* + Release Power-down instruction releases the device from + said state allowing device communication +*/ +int Mtac15Fpga::releaseDevice() { + int mtac_ret; + int spi_device; + struct spi_ioc_transfer k; + int ret; + size_t command_size = 5; + char out_buf[command_size]; + char in_buf[command_size]; + + /* prepare frame to be sent */ + out_buf[0] = CHIP_RELEASE; + out_buf[1] = 0; + out_buf[2] = 0; + out_buf[3] = 0; + out_buf[4] = 0; + + /* I/O transaction */ + mtac_ret = spiOpen(); + spi_device = + *(int *)spi_target_ptr; /* spi_target cannot be null beforehand */ + memset(&k, 0, sizeof(k)); /* clear k */ + k.tx_buf = (unsigned long)out_buf; + k.rx_buf = (unsigned long)in_buf; + k.len = command_size; + k.speed_hz = SPI_SPEED; + k.cs_change = 1; + k.bits_per_word = 8; + ret = ioctl(spi_device, SPI_IOC_MESSAGE(1), &k); + mtac_ret = spiClose(); + + /* determine return code */ + if (ret != (int)k.len) { + printError("Release failed"); + mtac_ret = -1; + } else { + usleep(1000); + mtac_ret = 0; + } + return mtac_ret; +} + +/* + Write enable instruction sets the write enable latch + in the status register to 1. It needs to be set before + a page can be programmed or chip erased +*/ +int Mtac15Fpga::writeEnable() { + int mtac_ret; + int spi_device; + struct spi_ioc_transfer k; + int ret; + size_t command_size = 1; + char out_buf[command_size]; + char in_buf[command_size]; + + /* prepare frame to be sent */ + out_buf[0] = 0x06; + + /* I/O transaction */ + mtac_ret = spiOpen(); + spi_device = + *(int *)spi_target_ptr; /* spi_target cannot be null beforehand */ + memset(&k, 0, sizeof(k)); /* clear k */ + k.tx_buf = (unsigned long)out_buf; + k.rx_buf = (unsigned long)in_buf; + k.len = command_size; + k.speed_hz = SPI_SPEED; + k.cs_change = 0; + k.bits_per_word = 8; + ret = ioctl(spi_device, SPI_IOC_MESSAGE(1), &k); + mtac_ret = spiClose(); + + /* determine return code */ + if (ret != (int)k.len) { + printError("Write Enable failed"); + mtac_ret = -1; + } else { + usleep(1000); + printDebug("Write Enable successful"); + mtac_ret = 0; + } + return mtac_ret; +} + +/* + Verify that the chip erase was successful +*/ +int Mtac15Fpga::chipEraseVerify() { + int mtac_ret; + int spi_device; + struct spi_ioc_transfer k; + int a, ret; + uint16_t command_size = 256 + 5; + char out_buf[command_size]; + char in_buf[command_size]; + + /* prepare frame to be sent */ + out_buf[0] = 0x0B; + out_buf[1] = 0x00; + out_buf[2] = 0x00; + out_buf[3] = 0x00; + out_buf[4] = 0x00; + + /* I/O transaction */ + mtac_ret = spiOpen(); + spi_device = + *(int *)spi_target_ptr; /* spi_target cannot be null beforehand */ + memset(&k, 0, sizeof(k)); /* clear k */ + k.tx_buf = (unsigned long)out_buf; + k.rx_buf = (unsigned long)in_buf; + k.len = command_size; + k.speed_hz = SPI_SPEED; + k.cs_change = 1; + k.bits_per_word = 8; + ret = ioctl(spi_device, SPI_IOC_MESSAGE(1), &k); + + /* determine return code */ + if (ret != (int)k.len) { + printError("Chip transfer failed"); + mtac_ret = -1; + } else { + printDebug("Chip transfer successful"); + mtac_ret = 0; + } + mtac_ret = spiClose(); + /* verify that the chip was erased */ + for (a = 5; a < command_size; a++) { + if (in_buf[a] != 0xFF) { + mtac_ret = spiClose(); + return mtac_ret; + } + } + return mtac_ret; +} + +/* + Chip erase instruction sets all memory within + the device to the erased state of all 1s (FFh) +*/ +int Mtac15Fpga::chipErase() { + int mtac_ret; + int spi_device; + struct spi_ioc_transfer k; + int ret; + size_t command_size = 1; + char out_buf[command_size]; + char in_buf[command_size]; + + /* prepare frame to be sent */ + out_buf[0] = CHIP_ERASE; + + /* I/O transaction */ + mtac_ret = spiOpen(); + spi_device = + *(int *)spi_target_ptr; /* spi_target cannot be null beforehand */ + memset(&k, 0, sizeof(k)); /* clear k */ + k.tx_buf = (unsigned long)out_buf; + k.rx_buf = (unsigned long)in_buf; + k.len = command_size; + k.speed_hz = SPI_SPEED; + k.cs_change = 0; + k.bits_per_word = 8; + ret = ioctl(spi_device, SPI_IOC_MESSAGE(1), &k); + sleep(5); + mtac_ret = spiClose(); + + /* determine return code */ + if (ret != (int)k.len) { + printError("Chip Erase transfer failed"); + mtac_ret = -1; + } else { + printDebug("Chip Erase transfer successful"); + chipEraseVerify(); + mtac_ret = 0; + } + return mtac_ret; +} + +/* erase entire flash */ +int Mtac15Fpga::mtacErase() { + int ret; + printInfo("Erasing flash"); + /* pull device out of powerdown state */ + ret = releaseDevice(); + if (ret != 0) { + return ret; + } + + /* enable writing to flash */ + ret = writeEnable(); + if (ret != 0) { + return ret; + } + + /* send chip erase command to flash */ + ret = chipErase(); + if (ret != 0) { + return ret; + } + /* pull device out of powerdown state */ + ret = releaseDevice(); + if (ret != 0) { + return ret; + } + return 0; +} + +/* + Page Program instruction allows writing upto 256 bytes (a page) of + data to be programmed at previously erased memory locations Write + enable must be issued first +*/ +int Mtac15Fpga::pageProgram(uint8_t adr_lower, uint8_t adr_higher, + uint32_t data[256]) { + int mtac_ret; + int spi_device; + struct spi_ioc_transfer k; + int a, h; + size_t command_size = 260; + char out_buf[command_size]; + char in_buf[command_size]; + + /* prepare frame to be sent */ + out_buf[0] = PAGE_PROGRAM; + out_buf[1] = adr_higher; + out_buf[2] = adr_lower; + out_buf[3] = 0x00; + for (h = 0; h < 256; h++) { + out_buf[h + 4] = data[h]; + } + + /* I/O transaction */ + mtac_ret = spiOpen(); + spi_device = + *(int *)spi_target_ptr; /* spi_target cannot be null beforehand */ + memset(&k, 0, sizeof(k)); /* clear k */ + k.tx_buf = (unsigned long)out_buf; + k.rx_buf = (unsigned long)in_buf; + k.len = command_size; + k.speed_hz = SPI_SPEED; + k.cs_change = 1; + k.bits_per_word = 8; + a = ioctl(spi_device, SPI_IOC_MESSAGE(1), &k); + printDebug("Writing Page %x%x to MTAC\r", adr_higher, adr_lower); + usleep(10000); + + mtac_ret = spiClose(); + + /* determine return code */ + if (a != (int)k.len) { + printError("SPI write failure"); + mtac_ret = -1; + } else { + printDebug("SPI write success"); + mtac_ret = 0; + } + return mtac_ret; +} + +/* write to mtac card with input file */ +int Mtac15Fpga::mtacProgram(const char input_file[]) { + FILE *f; + struct stat st; + size_t file_size; + int ret = 0; + uint32_t i = 0, index, result, offset, page_address, no_pages, + page_data[256]; + uint8_t adr_lower, adr_higher; + + /* get data array from file to be writen */ + f = fopen(input_file, "r"); + stat(input_file, &st); + file_size = st.st_size; + uint8_t *p_array; + p_array = (uint8_t *)malloc(sizeof(uint8_t) * file_size); + unsigned int data[file_size]; + while ((result = fscanf(f, "%x ", data + i)) == 1) { + i++; + } + fclose(f); + no_pages = ceil(i / 256.0); + + /* program one page at a time */ + for (page_address = 0x00; page_address < no_pages; page_address++) { + /* mask page address */ + adr_higher = (page_address >> 8) & 0xff; + adr_lower = page_address & 0xff; + /* calculate initial data offset */ + offset = page_address * 256; + /* enable writing to flash */ + ret = writeEnable(); + if (ret != 0) { + free(p_array); + break; + } + /* assign data for page to be written */ + for (index = 0; index < 256; index++) { + page_data[index] = index + offset > i ? 0xff : data[index + offset]; + } + /* program single page*/ + ret = pageProgram(adr_lower, adr_higher, page_data); + if (ret != 0) { + free(p_array); + break; + } + /* release device from page program powerdown */ + ret = releaseDevice(); + if (ret != 0) { + free(p_array); + break; + } + } + free(p_array); + return ret; +} + +/* Make sure no device is using the spidev bus to prevent contention*/ +int Mtac15Fpga::busContention() { + char number[1024]; + FILE *f = popen("lsof", "r"); + while (fgets(number, 1024, f) != NULL) { + if (strstr(number, "spidev") != NULL) { + printError("The accessory card is being used by another process: " + "\n %sPlease " + "close all LoRaWAN processes and try again", + number); + pclose(f); + return -1; + } + } + pclose(f); + return 0; +} + +/* -------------------------------------------------------------------------- */ +/* --- PUBLIC FUNCTIONS DEFINITION ------------------------------------------ */ + +/* Constructor used fpga upgrade utility */ +Mtac15Fpga::Mtac15Fpga(std::string inputFile, std::string forcedPath) { + FILE *fp = fopen(DEVICE_INFO_FILE, "r"); + char buf[0XFFFF]; + rapidjson::FileReadStream input(fp, buf, sizeof(buf)); + deviceInfo.ParseStream(input); + fclose(fp); + + if (!deviceInfo.HasMember("hardwareVersion")) { + printError("%s does not have hardware version info, exiting", + DEVICE_INFO_FILE); + return; + } + std::string hwVersion = deviceInfo["hardwareVersion"].GetString(); + + if (deviceInfo.HasMember("accessoryCards") && + deviceInfo["accessoryCards"].IsArray() && + deviceInfo["accessoryCards"].Size() > 0) { + if (hwVersion.find("MTCDT3") != std::string::npos) { + hardwareType = HARDWARE_MTCDT3; + } else if (hwVersion.find("MTCDT") != std::string::npos) { + hardwareType = HARDWARE_MTCDT; + } else { + return; + } + if (inputFile.empty()) { + input_file = MTCDT_DEFAULT_FILE; + } else { + input_file = inputFile; + } + port = deviceInfo["accessoryCards"][0]["port"].GetString(); + if (port.back() == '2') { + spiPath = "/dev/spidev1.2"; + } else { + spiPath = "/dev/spidev0.2"; + } + getFpgaVersion(); + printInfo("Current FPGA version: %d", fpgaVersion); + } else if (hwVersion.find("MTCAP") != std::string::npos) { + hardwareType = HARDWARE_MTCAP; + if (inputFile.empty()) { + input_file = MTCAP_DEFAULT_FILE; + } else { + input_file = inputFile; + } + spiPath = "/dev/spidev0.0"; + getFpgaVersion(); + printInfo("Current FPGA version: %d", fpgaVersion); + } +} + +/* Constructor used by device_info.json generator */ +Mtac15Fpga::Mtac15Fpga(const std::string path) { spiPath = path; } + +int Mtac15Fpga::FpgaVersion() { return fpgaVersion; } + +/* Open spi device and get fpga version from register */ +int Mtac15Fpga::getFpgaVersion() { + int ret = spiOpen(); + if (ret != 0) { + printError("Could not open SPI port %s", spiPath.c_str()); + } else { + /* detect if the gateway has an FPGA with SPI mux header support */ + ret = spiRead(MTAC_FPGA, loregs[MTAC_VERSION].addr, &fpgaVersion); + if (ret != 0) { + printError("Could not read FPGA version"); + } + spiClose(); + } + spi_target_ptr = NULL; + return ret; +} + +/* setup and upgrade the mtac card with the file specified */ +int Mtac15Fpga::upgradeFpga() { + if (hardwareType == HARDWARE_INVALID) { + printError("Invalid hardware"); + return -1; + } + + int ret; + + if (input_file.empty()) { + printError("Invalid input file %s", input_file.c_str()); + return -1; + } + /* check that no other device is using the bus */ + ret = busContention(); + if (ret != 0) { + return ret; + } + /* check MTAC Hardware Compatibility */ + printInfo("Checking hardware compatibility"); + + /* check input file checksum */ + ret = sha256_file(input_file.c_str()); + if (ret != 0) { + return ret; + } + + /* pull creset down to access spi flash */ + ret = cresetWrite('0'); + if (ret != 0) { + return ret; + } + sleep(1); + + /* erase chip before flashing new firmware */ + ret = mtacErase(); + if (ret != 0) { + return ret; + } + + /* program user specified firmware */ + printInfo("Programming flash"); + ret = mtacProgram(input_file.c_str()); + if (ret != 0) { + return ret; + } else { + printInfo("Write Complete. Resetting FPGA"); + } + + /* pull creset up to access FPGA */ + ret = cresetWrite('1'); + if (ret != 0) { + return ret; + } + sleep(5); + printInfo("Reading New FPGA configuration"); + ret = getFpgaVersion(); + if (ret != 0) { + return ret; + } + printInfo("New FPGA version: %d", fpgaVersion); + return 0; +} diff --git a/src/Device/Device.cpp b/src/Device/Device.cpp index f1ab675..04dbfef 100644 --- a/src/Device/Device.cpp +++ b/src/Device/Device.cpp @@ -1,141 +1,219 @@ /********************************************************************** -* COPYRIGHT 2020 MULTI-TECH SYSTEMS, INC. -* -* ALL RIGHTS RESERVED BY AND FOR THE EXCLUSIVE BENEFIT OF -* MULTI-TECH SYSTEMS, INC. -* -* MULTI-TECH SYSTEMS, INC. - CONFIDENTIAL AND PROPRIETARY -* INFORMATION AND/OR TRADE SECRET. -* -* NOTICE: ALL CODE, PROGRAM, INFORMATION, SCRIPT, INSTRUCTION, -* DATA, AND COMMENT HEREIN IS AND SHALL REMAIN THE CONFIDENTIAL -* INFORMATION AND PROPERTY OF MULTI-TECH SYSTEMS, INC. -* USE AND DISCLOSURE THEREOF, EXCEPT AS STRICTLY AUTHORIZED IN A -* WRITTEN AGREEMENT SIGNED BY MULTI-TECH SYSTEMS, INC. IS PROHIBITED. -* -***********************************************************************/ + * COPYRIGHT 2020 MULTI-TECH SYSTEMS, INC. + * + * ALL RIGHTS RESERVED BY AND FOR THE EXCLUSIVE BENEFIT OF + * MULTI-TECH SYSTEMS, INC. + * + * MULTI-TECH SYSTEMS, INC. - CONFIDENTIAL AND PROPRIETARY + * INFORMATION AND/OR TRADE SECRET. + * + * NOTICE: ALL CODE, PROGRAM, INFORMATION, SCRIPT, INSTRUCTION, + * DATA, AND COMMENT HEREIN IS AND SHALL REMAIN THE CONFIDENTIAL + * INFORMATION AND PROPERTY OF MULTI-TECH SYSTEMS, INC. + * USE AND DISCLOSURE THEREOF, EXCEPT AS STRICTLY AUTHORIZED IN A + * WRITTEN AGREEMENT SIGNED BY MULTI-TECH SYSTEMS, INC. IS PROHIBITED. + * + ***********************************************************************/ #include "Device.h" -const std::vector Device::apIdentifiers = {"ap1", "ap2", "lora", "lora-2", "slot1", "slot2"}; -const std::regex Device::apFilters("(modalias)|(power)(.*)|(subsystem)|(uevent)"); -const std::regex Device::lora15Filters("(MTAC-LORA-)(.*)|(MTCAP-LORA-)(.*)|(MTLGA-)(.*)|(MTCDT3-)(.*)"); -const std::regex Device::loraG16Filters("(MTAC-LORA-G16)(.*)"); -const std::regex Device::loraG64Filters("(MTAC-LORA-G64)(.*)"); -const std::regex Device::gpiobFilters("(MTAC-GPIOB)|(MMTAC-GPIOI)"); -const std::regex Device::mfserFilters("(MTAC-MFSER-DTE)|(MTAC-MFSER-DCE)|(MTR-)(.*)"); +const std::vector Device::apIdentifiers = { + "ap1", "ap2", "lora", "lora-2", "slot1", "slot2"}; +const std::regex + Device::apFilters("(modalias)|(power)(.*)|(subsystem)|(uevent)"); const std::regex Device::serialModeFilter("(.*)(serial-mode)"); -const std::regex Device::storeFilters("(.*)(mac-)(.*)|(.*)(-id)|(uuid)|(.*)(/eui)|(.*)(/cdone)|(.*)(hw-version)|(imei)|(capability)(.*)|(radio-reset-backoff-seconds)|(modalias)|(power)|((subsystem)(.*))|(uevent)|(board-temperature)|(reset)|(led3)|(led-ls)|(usbhd-ps-oc)|(.*)(adc[0-9])|(.*)(din[0-9])|(gpi[0-9])|(gpi[0-9][0-9])"); +const std::regex Device::mtcdt3Filters("(MTCDT3AC)(.*)"); +const std::regex Device::mtrFilters("(MTR-)(.*)"); +const std::regex Device::storeFilters( + "(.*)(mac-)(.*)|(.*)(-id)|(uuid)|(.*)(/eui)|(.*)(/" + "cdone)|(.*)(hw-version)|(oem-string)(.*)|(imei)|(capability)(.*)|(radio-" + "reset-backoff-seconds)|(modalias)|(power)|((subsystem)(.*))|(uevent)|(" + "board-temperature)|(reset)|(led3)|(led-ls)|(usbhd-ps-oc)|(.*)(adc[0-9])|(." + "*)(din[0-9])|(gpi[0-9])|(gpi[0-9][0-9])"); const std::regex Device::showFilters("(modalias)|(subsystem)|(uevent)"); -std::map Device::capabilityList = {{"adc", false},{"battery", false},{"bluetooth", false}, - {"cell", false},{"cellWwan", false},{"din", false},{"dout", false},{"externalSerialPort", false}, - {"gpio", false},{"gps", false},{"lora", false},{"loraNetworkServer", false}, - {"nodeRed", false},{"rs232", false},{"rs422", false},{"rs485", false},{"serial", false}, - {"supercap", false},{"wifi", false},{"docker", false},{"tpm", false}}; +std::map Device::capabilityList = { + {"adc", false}, + {"battery", false}, + {"bluetooth", false}, + {"cell", false}, + {"cellWwan", false}, + {"din", false}, + {"dout", false}, + {"externalSerialPort", false}, + {"gpio", false}, + {"gps", false}, + {"lora", false}, + {"loraLbt", false}, + {"loraNetworkServer", false}, + {"nodeRed", false}, + {"rs232", false}, + {"rs422", false}, + {"rs485", false}, + {"serial", false}, + {"supercap", false}, + {"wifi", false}, + {"docker", false}, + {"tpm", false}}; std::map Device::ethSwitchList; -std::map Device::deviceInfoList = {{"deviceId", ""},{"hardwareVersion", ""}, - {"imei", ""},{"macAddress", "00:00:00:00:00:00"},{"macBluetooth", "00:00:00:00:00:00"}, - {"macWifi", "00:00:00:00:00:00"},{"productId", ""},{"uuid", ""},{"vendorId", ""}}; +std::map Device::deviceInfoList = { + {"deviceId", ""}, + {"hardwareVersion", ""}, + {"imei", ""}, + {"macAddress", "00:00:00:00:00:00"}, + {"macBluetooth", "00:00:00:00:00:00"}, + {"macWifi", "00:00:00:00:00:00"}, + {"productId", ""}, + {"uuid", ""}, + {"vendorId", ""}, + {"oemString1", ""}, + {"oemString2", ""}}; Device::Device() { isRoot = !getuid(); - verbose = false; + accessoryCardsList.reserve(accessoryCardsListSize); + accessoryCardsList.push_back(std::make_unique(*this)); + accessoryCardsList.push_back(std::make_unique(*this)); + accessoryCardsList.push_back(std::make_unique(*this)); + accessoryCardsList.push_back(std::make_unique(*this)); + accessoryCardsList.push_back(std::make_unique(*this)); + accessoryCardsList.push_back(std::make_unique(*this)); + accessoryCardsList.push_back(std::make_unique(*this)); + accessoryCardsList.push_back(std::make_unique(*this)); } -bool Device::isAccessoryCard(const char * d_name, const char * dir_name) { - return std::binary_search(apIdentifiers.begin(), apIdentifiers.end(), dir_name) && !regex_match(d_name, apFilters); +bool Device::isAccessoryCard(const char *d_name, const char *dir_name) { + return std::binary_search(apIdentifiers.begin(), apIdentifiers.end(), + dir_name) && + !regex_match(d_name, apFilters); } void Device::sortAccessoryCards() { rapidjson::SizeType i, j; for (i = 0; i < accessoryCards.Size() - 1; i++) { for (j = 0; j < accessoryCards.Size() - i - 1; j++) { - if (accessoryCards[j]["port"].GetString() < accessoryCards[j+1]["port"].GetString()) { - accessoryCards[j].Swap( accessoryCards[j+1]); + if (accessoryCards[j]["port"].GetString() < + accessoryCards[j + 1]["port"].GetString()) { + accessoryCards[j].Swap(accessoryCards[j + 1]); } } } } -bool Device::isValidDirectory(const struct dirent * entry, std::string fullPath, const char * d_name) { +bool Device::isValidDirectory(const struct dirent *entry, std::string fullPath, + const char *d_name) { std::string path = fullPath + "/" + std::string(d_name); - return (entry->d_type & DT_DIR) && strcmp (d_name, "..") != 0 && strcmp (d_name, ".") != 0 && (path.length() < PATH_MAX); + return (entry->d_type & DT_DIR) && strcmp(d_name, "..") != 0 && + strcmp(d_name, ".") != 0 && (path.length() < PATH_MAX); } -void Device::getSystemTreeJson(const char * dir_name) { +void Device::getSystemTreeJson(const char *dir_name) { std::string fullPath = SYSFS_PLATFORM + std::string(dir_name); - DIR * d = opendir (fullPath.c_str()); + DIR *d = opendir(fullPath.c_str()); if (!d) { - logError("Cannot open directory " + fullPath); + printError("Cannot open directory %s", fullPath); exitHandler(99); } while (1) { - struct dirent * entry = readdir (d); /* Gets subsequent entries from "d" */ - if (!entry) { /* If there are no more entries, exit */ + struct dirent *entry = + readdir(d); /* Gets subsequent entries from "d" */ + if (!entry) { /* If there are no more entries, exit */ break; } - const char * d_name = entry->d_name; /* Get file name */ + const char *d_name = entry->d_name; /* Get file name */ std::string fileData; - if (!(entry->d_type & DT_DIR) && (MTS::System::readFile(fullPath + "/" + std::string(d_name), fileData) == 0)) { + if (!(entry->d_type & DT_DIR) && + (MTS::System::readFile(fullPath + "/" + std::string(d_name), + fileData) == 0)) { fileData = MTS::Text::trim(fileData); if (strlen(dir_name) > 0) { if (isAccessoryCard(d_name, dir_name)) { if (accessoryCard.IsNull()) { accessoryCard.SetObject(); - accessoryCard.AddMember("port", rapidjson::Value().SetString(dir_name, accessoryCardsAlloc), accessoryCardsAlloc); + accessoryCard.AddMember( + "port", + rapidjson::Value().SetString(dir_name, acAlloc), + acAlloc); } else if (accessoryCard["port"] != dir_name) { - accessoryCards.PushBack(accessoryCard, accessoryCardsAlloc); + accessoryCards.PushBack(accessoryCard, acAlloc); accessoryCard.SetObject(); - accessoryCard.AddMember("port", rapidjson::Value().SetString(dir_name, accessoryCardsAlloc), accessoryCardsAlloc); + accessoryCard.AddMember( + "port", + rapidjson::Value().SetString(dir_name, acAlloc), + acAlloc); } - if (strcmp(d_name, "product-id") == 0) { /* Map card specific details based on the product id */ - if (regex_match(fileData, loraG16Filters)) { - Lora21Card lora21(*this, fileData, dir_name); - } else if (regex_match(fileData, loraG64Filters)) { - Lora21ExtCard lora21Ext(*this, fileData, dir_name); - } else if (regex_match(fileData, lora15Filters)) { - Lora15Card lora15(*this, fileData, dir_name); - } else if (regex_match(fileData, gpiobFilters)) { - Gpiob ppiob(*this, fileData, dir_name); - } else if (regex_match(fileData, mfserFilters)) { - Mfser msfer(*this, fileData, dir_name); + if (strcmp(d_name, "product-id") == + 0) { /* Map card specific details based on the product + id */ + for (unsigned int i = 0; i < accessoryCardsList.size(); + i++) { + if (regex_match(fileData, + accessoryCardsList[i]->GetName())) { + accessoryCardsList[i]->AddToDeviceInfo( + dir_name, fileData); + break; + } } } - accessoryCard.AddMember(rapidjson::Value().SetString(toCamelCase(d_name).c_str(), accessoryCardsAlloc), rapidjson::Value().SetString(fileData.c_str(), accessoryCardsAlloc), accessoryCardsAlloc); - } else if (strcmp (dir_name, "capability") == 0 && fileData == "1") { + accessoryCard.AddMember( + rapidjson::Value().SetString( + toCamelCase(d_name).c_str(), acAlloc), + rapidjson::Value().SetString(fileData.c_str(), acAlloc), + acAlloc); + } else if (strcmp(dir_name, "capability") == 0 && + fileData == "1") { capabilityList[toCamelCase(d_name)] = true; - } else if (strcmp (dir_name, "eth-switch") == 0) { + } else if (strcmp(dir_name, "eth-switch") == 0) { ethSwitchList[toCamelCase(d_name)] = fileData; } - } else if ((entry->d_type != DT_LNK)){ + } else if ((entry->d_type != DT_LNK)) { if (deviceInfoList.count(toCamelCase(d_name)) > 0) { deviceInfoList[toCamelCase(d_name)] = fileData; } else if (strcmp(d_name, "hw-version") == 0) { deviceInfoList["hardwareVersion"] = fileData; } else if (strcmp(d_name, "mac-eth") == 0) { deviceInfoList["macAddress"] = fileData; - } else if (strcmp(d_name, "has-radio") == 0 && fileData == "1") { + } else if (strcmp(d_name, "has-radio") == 0 && + fileData == "1") { capabilityList["cell"] = true; + } else if (strcmp(d_name, "oem-string1") == 0) { + deviceInfoList["oemString1"] = fileData; + } else if (strcmp(d_name, "oem-string2") == 0) { + deviceInfoList["oemString2"] = fileData; + }; + if (strcmp(d_name, "product-id") == 0) { + if (regex_match(fileData, mtcdt3Filters)) { + capabilityList["rs232"] = true; + capabilityList["rs422"] = true; + capabilityList["rs485"] = true; + capabilityList["serial"] = true; + } + if (regex_match(fileData, mtrFilters)) { + capabilityList["rs232"] = true; + capabilityList["serial"] = true; + } } } } - if (isValidDirectory(entry, fullPath, d_name)) { /* Check that the directory is not "d" or d's parent */ + if (isValidDirectory(entry, fullPath, + d_name)) { /* Check that the directory is not "d" + or d's parent */ getSystemTreeJson(d_name); /* Recursively call with the new path */ } } - if (closedir (d)) { /* After going through all the entries, close the directory */ - logError("Could not close " + std::string(fullPath)); + if (closedir( + d)) { /* After going through all the entries, close the directory */ + printError("Could not close %s", fullPath); exitHandler(errno); } } void Device::init() { if (!isRoot) { - logError("Must be root to generate device_info.json"); + printError("Must be root to generate device_info.json"); exitHandler(99); } load(); @@ -145,7 +223,7 @@ void Device::init() { void Device::json() { if (!isRoot) { - logError("Must be root to generate json"); + printError("Must be root to generate json"); exitHandler(99); } load(); @@ -160,7 +238,7 @@ void Device::load() { accessoryCards.SetArray(); getSystemTreeJson(""); if (!accessoryCard.IsNull()) { - accessoryCards.PushBack(accessoryCard, accessoryCardsAlloc); + accessoryCards.PushBack(accessoryCard, acAlloc); if (accessoryCards.Size() > 1) { sortAccessoryCards(); } @@ -170,48 +248,58 @@ void Device::load() { mapFirmware(); mapMacAddress2(); for (const auto capability : capabilityList) { - capabilities.AddMember(rapidjson::Value().SetString(capability.first.c_str(), - capability.first.length(), accessoryCardsAlloc), capability.second, accessoryCardsAlloc); + capabilities.AddMember( + rapidjson::Value().SetString(capability.first.c_str(), + capability.first.length(), acAlloc), + capability.second, acAlloc); } - + if (ethSwitchList.count("chip") && ethSwitchList.count("numPorts")) { - auto& ethSwitchAlloc = ethSwitch.GetAllocator(); - const std::string& chip = ethSwitchList.at("chip"); + auto ðSwitchAlloc = ethSwitch.GetAllocator(); + const std::string &chip = ethSwitchList.at("chip"); ethSwitch.AddMember("chip", - rapidjson::Value().SetString(chip.c_str(), chip.length(), ethSwitchAlloc), - ethSwitchAlloc); + rapidjson::Value().SetString( + chip.c_str(), chip.length(), ethSwitchAlloc), + ethSwitchAlloc); rapidjson::Value ports; ports.SetObject(); - for (int i=0; i < std::stoi(ethSwitchList.at("numPorts")); ++i) { + for (int i = 0; i < std::stoi(ethSwitchList.at("numPorts")); ++i) { const std::string num = std::to_string(i); const std::string keyLabel = "port" + num + "Label"; const std::string keyId = "port" + num + "Id"; - const std::string keyMac = "port" + num + "Mac";; - if (ethSwitchList.count(keyLabel) && - ethSwitchList.count(keyId) && + const std::string keyMac = "port" + num + "Mac"; + ; + if (ethSwitchList.count(keyLabel) && ethSwitchList.count(keyId) && ethSwitchList.count(keyMac)) { rapidjson::Value port; port.SetObject(); - port.AddMember("id", rapidjson::Value().SetInt(std::stoi(ethSwitchList.at(keyId))), ethSwitchAlloc); + port.AddMember("id", + rapidjson::Value().SetInt( + std::stoi(ethSwitchList.at(keyId))), + ethSwitchAlloc); port.AddMember("mac", - rapidjson::Value().SetString(ethSwitchList.at(keyMac).c_str(), - ethSwitchList.at(keyMac).length(), - ethSwitchAlloc), - ethSwitchAlloc); - ports.AddMember(rapidjson::Value().SetString(ethSwitchList.at(keyLabel).c_str(), - ethSwitchList.at(keyLabel).length(), - ethSwitchAlloc), - std::move(port), - ethSwitchAlloc); + rapidjson::Value().SetString( + ethSwitchList.at(keyMac).c_str(), + ethSwitchList.at(keyMac).length(), + ethSwitchAlloc), + ethSwitchAlloc); + ports.AddMember(rapidjson::Value().SetString( + ethSwitchList.at(keyLabel).c_str(), + ethSwitchList.at(keyLabel).length(), + ethSwitchAlloc), + std::move(port), ethSwitchAlloc); } } ethSwitch.AddMember("ports", std::move(ports), ethSwitchAlloc); } for (const auto device : deviceInfoList) { - deviceInfo.AddMember(rapidjson::Value().SetString(device.first.c_str(), - device.first.length(), alloc), rapidjson::Value().SetString(device.second.c_str(), - device.second.length(), alloc), alloc); + deviceInfo.AddMember( + rapidjson::Value().SetString(device.first.c_str(), + device.first.length(), alloc), + rapidjson::Value().SetString(device.second.c_str(), + device.second.length(), alloc), + alloc); } deviceInfo.AddMember("capabilities", capabilities, alloc); @@ -219,40 +307,34 @@ void Device::load() { deviceInfo.AddMember("accessoryCards", accessoryCards, alloc); } -void Device::logError(std::string info) { - printf("error: %s\n", info.c_str()); -} - -void Device::logInfo(std::string info) { - if (verbose) { - printf("info: %s\n", info.c_str()); - } -} - void Device::mapFileToCapability() { - if (fileType("/opt/node-red") == S_IFDIR) { /* node-red is a directory */ + if (fileType("/opt/node-red") == S_IFDIR) { /* node-red is a directory */ capabilityList["nodeRed"] = true; } - if (fileType("/opt/lora/lora-network-server") == S_IFREG) { /* lora-network-server is a regular file */ + if (fileType("/opt/lora/lora-network-server") == + S_IFREG) { /* lora-network-server is a regular file */ capabilityList["loraNetworkServer"] = true; } - if (fileType("/dev/cdc-wdm0") == S_IFCHR) { /* Cellular modem is wwan/qmi character device */ + if (fileType("/dev/cdc-wdm0") == + S_IFCHR) { /* Cellular modem is wwan/qmi character device */ capabilityList["cellWwan"] = true; } - if (fileType("/dev/ext_serial") == S_IFCHR) { /* ext_serial is a character device */ + if (fileType("/dev/ext_serial") == + S_IFCHR) { /* ext_serial is a character device */ capabilityList["externalSerialPort"] = true; } - if (fileType("/usr/bin/dockerd") == S_IFREG) { /* Docker is a regular file */ + if (fileType("/usr/bin/dockerd") == + S_IFREG) { /* Docker is a regular file */ capabilityList["docker"] = true; } - if (findFileGlob("/dev/tpm*") == S_IFCHR) { /* tpm* is a character device */ + if (findFileGlob("/dev/tpm*") == S_IFCHR) { /* tpm* is a character device */ capabilityList["tpm"] = true; } } void Device::mapMacAddress2() { std::ifstream file("/sys/devices/platform/mts-io/base/mac-eth"); - if (file.is_open()){ + if (file.is_open()) { std::string line = ""; std::getline(file, line); deviceInfoList["macAddress1"] = line; @@ -261,32 +343,35 @@ void Device::mapMacAddress2() { void Device::mapFirmware() { std::ifstream file(FIRMWARE_FILE); - if (!file.is_open()){ + if (!file.is_open()) { return; } std::string line; - while (std::getline(file, line)){ - if (line.find(FIRMWARE_VERSION) != std::string::npos){ + while (std::getline(file, line)) { + if (line.find(FIRMWARE_VERSION) != std::string::npos) { deviceInfoList["firmware"] = line.substr(line.find(" ") + 1); - } else if (line.find(FIRMWARE_DATE) != std::string::npos){ + } else if (line.find(FIRMWARE_DATE) != std::string::npos) { deviceInfoList["firmwareDate"] = line.substr(line.find(" ") + 1); + } else if (line.find(FIRMWARE_RELEASE) != std::string::npos) { + deviceInfoList["firmwareRelease"] = line.substr(line.find(" ") + 1); } } } -void Device::printDir(const std::string dir_name, std::vector &results) { +void Device::printDir(const std::string dir_name, + std::vector &results) { std::string fullPath = SYSFS_PLATFORM + std::string(dir_name); - DIR * d = opendir(fullPath.c_str()); + DIR *d = opendir(fullPath.c_str()); if (!d) { - logError("Cannot open directory " + std::string(fullPath)); + printError("Cannot open directory %s", fullPath); exitHandler(99); } while (1) { - struct dirent * entry = readdir (d); + struct dirent *entry = readdir(d); if (!entry) { break; } - const char * d_name = entry->d_name; + const char *d_name = entry->d_name; if (!(entry->d_type & DT_DIR)) { std::string result; if (dir_name.size() > 0) { @@ -295,12 +380,15 @@ void Device::printDir(const std::string dir_name, std::vector &resu result.append(d_name); results.push_back(result); } - if (isValidDirectory(entry, fullPath, d_name)) { /* Check that the directory is not "d" or d's parent. */ + if (isValidDirectory(entry, fullPath, + d_name)) { /* Check that the directory is not "d" + or d's parent. */ printDir(d_name, results); } } - if (closedir (d)) { /* After going through all the entries, close the directory. */ - logError("Could not close " + std::string(fullPath)); + if (closedir(d)) { /* After going through all the entries, close the + directory. */ + printError("Could not close %s", fullPath); exitHandler(errno); } } @@ -312,42 +400,80 @@ void Device::printJson() { std::cout << buffer.GetString(); } -void Device::printVersion (std::string name) { - printf("%s %s\nCopyright (C) 2020 by Multi-Tech Systems\nThis program is free software; you may redistribute it under the terms of\nthe GNU General Public License version 2 or (at your option) any later version.\nThis program has absolutely no warranty.\n",name.c_str(), Version::version.c_str()); +void Device::printVersion(std::string name) { + printInfo( + "%s %s\nCopyright (C) 2021 by Multi-Tech Systems\nThis program is free " + "software; you may redistribute it under the terms of\nthe GNU General " + "Public License version 2 or (at your option) any later version.\nThis " + "program has absolutely no warranty.", + name.c_str(), Version::version.c_str()); + exitHandler(0); } void Device::printUsage(std::string program) { std::vector showResults; - printf("Usage: %s [ OPTIONS ] OBJECT [--] [ ARGUMENTS ]\n", program.c_str()); + printf("Usage: %s [ OPTIONS ] OBJECT [--] [ ARGUMENTS ]\n", + program.c_str()); printf("where OBJECT := {\n"); printf(" init |\n"); printf(" show SHOW-NAME |\n"); printf(" store STORE-NAME |\n"); printf(" json |\n"); + printf(" load-fpga FPGA-OPTIONS |\n"); printf(" }\n"); printf("\n"); + printf(" FPGA-OPTIONS := {\n"); + printf(" -c Check FPGA Version\n"); + printf(" -i Specify input file. Default is " + "mtcdt-fpga-v31.hex for a MultiConnect Conduit\n"); + printf(" and mtcap-fpga-v31.hex for MultiConnect Access " + "Point\n"); + printf(" -p Specify port 1 or 2 (MultiConnect Conduit " + "Only)\n"); + printf( + " -s Print FPGA versions supported by the utility\n"); + printf(" Examples :=\n"); + printf(" %s load-fpga -c Check existing " + "FPGA version\n", + program.c_str()); + printf(" %s load-fpga -i Upgrade the FPGA " + "on the default port using the file specified\n", + program.c_str()); + printf(" %s load-fpga -p 2 -i Upgrade the FPGA " + "on ap2 using the file specified\n", + program.c_str()); + printf(" %s Upgrade the FPGA " + "on the default port and upgrade file\n", + program.c_str()); + printf(" }\n"); printf(" SHOW-NAME := {\n"); printDir("", showResults); - sort(showResults.begin(), showResults.end()); // Unix file tree is not sorted + sort(showResults.begin(), + showResults.end()); // Unix file tree is not sorted - for (std::string showResult: showResults) { + for (std::string showResult : showResults) { if (!regex_match(showResult, showFilters)) - printf (" %s\n", showResult.c_str()); + printf(" %s\n", showResult.c_str()); } printf(" }\n"); printf("\n"); printf(" STORE-NAME := {\n"); - for (std::string showResult: showResults) { + for (std::string showResult : showResults) { if (showResult == "radio-reset") { - printf (" %s { 0 }\n", showResult.c_str()); + printf(" %s { 0 }\n", showResult.c_str()); } else if (showResult == "reset-monitor") { - printf (" %s { pid short-signal long-signal [extra-long-signal] }\n", showResult.c_str()); + printf(" %s { pid short-signal long-signal " + "[extra-long-signal] }\n", + showResult.c_str()); } else if (showResult == "reset-monitor-intervals") { - printf (" %s { short-interval long-interval }\n", showResult.c_str()); + printf(" %s { short-interval long-interval }\n", + showResult.c_str()); } else if (regex_match(showResult, serialModeFilter)) { - printf (" %s { loopback | rs232 | rs485-half | rs422-485-full }\n", showResult.c_str()); + printf(" %s { loopback | rs232 | rs485-half | " + "rs422-485-full }\n", + showResult.c_str()); } else if (!regex_match(showResult, storeFilters)) { - printf (" %s BOOLEAN\n", showResult.c_str()); + printf(" %s BOOLEAN\n", showResult.c_str()); } } printf(" OPTIONS := {\n"); @@ -365,76 +491,72 @@ void Device::show(std::string name) { std::string fileData; int32_t code = MTS::System::readFile(SYSFS_PLATFORM + name, fileData); if (code == 0) { - printf("%s",fileData.c_str()); + printf("%s", fileData.c_str()); exitHandler(0); } else { - logError("cat: can't open " + std::string(SYSFS_PLATFORM) + name + ": No such file or directory"); + printError("cat: can't open %s%s: No such file or directory", + SYSFS_PLATFORM, name.c_str()); exitHandler(99); } } void Device::showTrigger(std::string name) { std::string fileData; - int32_t code = MTS::System::readFile(LEDS_GPIO_DIR + name + "/trigger", fileData); + int32_t code = + MTS::System::readFile(LEDS_GPIO_DIR + name + "/trigger", fileData); if (code == 0) { - printf("%s",fileData.c_str()); + printf("%s", fileData.c_str()); exitHandler(0); } else { - logError("can't not open '" + std::string(LEDS_GPIO_DIR) + name + "/trigger': No such file or directory"); + printError("Can't not open %s%s/trigger': No such file or directory", + LEDS_GPIO_DIR, name.c_str()); exitHandler(99); } } void Device::store(std::string name, std::string value) { if (!isRoot) { - logError("Must be root to store to " + name); + printError("Must be root to store to %s", name.c_str()); exitHandler(99); } - logInfo("setting " + name + " to " + value); + printDebug("Setting %s to %s", name.c_str(), value.c_str()); std::ofstream fileToWrite(SYSFS_PLATFORM + name); if (!fileToWrite.bad()) { fileToWrite << value; fileToWrite.close(); exitHandler(0); } else { - logError("can't not open '" + std::string(SYSFS_PLATFORM) + name + "': No such file or directory"); + printError("Can't open %s%s: No such file or directory", SYSFS_PLATFORM, + name.c_str()); exitHandler(99); } - } void Device::storeTrigger(std::string name, std::string value) { if (!isRoot) { - logError("Must be root to storeTrigger to " + name + "/trigger"); + printError("Must be root to storeTrigger to %s/trigger", name.c_str()); exitHandler(99); } - logInfo("setting " + name + " to " + value); + printDebug("Setting %s to %s", name.c_str(), value.c_str()); std::ofstream fileToWrite(LEDS_GPIO_DIR + name + "/trigger"); if (!fileToWrite.bad()) { fileToWrite << value; fileToWrite.close(); exitHandler(0); } else { - logError("can't not open '" + std::string(LEDS_GPIO_DIR) + name + "/trigger': No such file or directory"); + printError("Can't not open %s%s/trigger': No such file or directory", + LEDS_GPIO_DIR, name.c_str()); exitHandler(99); } } -void Device::Verbose(const bool val) { - verbose = val; -} - -bool Device::Verbose() { - return verbose; -} - void Device::writeJson() { rapidjson::StringBuffer buffer; rapidjson::Writer writer(buffer); deviceInfo.Accept(writer); std::ofstream os(DEVICE_INFO_FILE); if (!os) { - logError("Can't write to " + std::string(DEVICE_INFO_FILE)); + printError("Can't write to %s", DEVICE_INFO_FILE); exitHandler(99); } else { os << buffer.GetString(); diff --git a/src/MtsIoSysfs.cpp b/src/MtsIoSysfs.cpp index 390db47..c7e892a 100644 --- a/src/MtsIoSysfs.cpp +++ b/src/MtsIoSysfs.cpp @@ -1,75 +1,230 @@ /********************************************************************** -* COPYRIGHT 2020 MULTI-TECH SYSTEMS, INC. -* -* ALL RIGHTS RESERVED BY AND FOR THE EXCLUSIVE BENEFIT OF -* MULTI-TECH SYSTEMS, INC. -* -* MULTI-TECH SYSTEMS, INC. - CONFIDENTIAL AND PROPRIETARY -* INFORMATION AND/OR TRADE SECRET. -* -* NOTICE: ALL CODE, PROGRAM, INFORMATION, SCRIPT, INSTRUCTION, -* DATA, AND COMMENT HEREIN IS AND SHALL REMAIN THE CONFIDENTIAL -* INFORMATION AND PROPERTY OF MULTI-TECH SYSTEMS, INC. -* USE AND DISCLOSURE THEREOF, EXCEPT AS STRICTLY AUTHORIZED IN A -* WRITTEN AGREEMENT SIGNED BY MULTI-TECH SYSTEMS, INC. IS PROHIBITED. -* -***********************************************************************/ + * COPYRIGHT 2020 MULTI-TECH SYSTEMS, INC. + * + * ALL RIGHTS RESERVED BY AND FOR THE EXCLUSIVE BENEFIT OF + * MULTI-TECH SYSTEMS, INC. + * + * MULTI-TECH SYSTEMS, INC. - CONFIDENTIAL AND PROPRIETARY + * INFORMATION AND/OR TRADE SECRET. + * + * NOTICE: ALL CODE, PROGRAM, INFORMATION, SCRIPT, INSTRUCTION, + * DATA, AND COMMENT HEREIN IS AND SHALL REMAIN THE CONFIDENTIAL + * INFORMATION AND PROPERTY OF MULTI-TECH SYSTEMS, INC. + * USE AND DISCLOSURE THEREOF, EXCEPT AS STRICTLY AUTHORIZED IN A + * WRITTEN AGREEMENT SIGNED BY MULTI-TECH SYSTEMS, INC. IS PROHIBITED. + * + ***********************************************************************/ #include "Device.h" -int main(int argc, char const* const argv[]) { +#define COMMMAND_EXTRA "--" +#define COMMMAND_INIT "init" +#define COMMMAND_JSON "json" +#define COMMMAND_LOAD_FPGA "load-fpga" +#define COMMMAND_SHOW "show" +#define COMMMAND_SHOW_TRIGGER "show-trigger" +#define COMMMAND_STORE "store" +#define COMMMAND_STORE_TRIGGER "store-trigger" +#define COMMMAND_VERSION "version" + +enum action_code { + ACTION_NONE, + ACTION_VERSION, + ACTION_INIT, + ACTION_JSON, + ACTION_LOAD_FPGA, + ACTION_SHOW, + ACTION_SHOW_TRIGGER, + ACTION_STORE, + ACTION_STORE_TRIGGER, +}; + +static enum action_code action; + +int main(int argc, char **argv) { Device m; + action = ACTION_NONE; if (argc < 2) { m.printUsage(argv[0]); } + std::string fpgaFilePath = ""; + std::string forcedAP = ""; + std::string name = ""; + std::string data = ""; - for (int i = 1; i < argc; i++) { - if (argv[i][0] == '-') { - std::string parameter = &argv[i][1]; - if (parameter == "-version") { - m.printVersion(argv[0]); - } else if (parameter == "-help") { - m.printUsage(argv[0]); - } else if (parameter == "-verbose") { - m.Verbose(true); - } + MTS::Logger::setPrintLevel(MTS::Logger::PrintLevel::INFO_LEVEL, true); + int c; + static struct option long_options[] = { + {"help", no_argument, nullptr, 'h'}, + {"data", required_argument, nullptr, 'd'}, + {"input", required_argument, nullptr, 'i'}, + {"init", no_argument, nullptr, 'I'}, + {"json", no_argument, nullptr, 'j'}, + {"load-fpga", optional_argument, nullptr, 'l'}, + {"path", required_argument, nullptr, 'p'}, + {"show", required_argument, nullptr, 's'}, + {"show-trigger", required_argument, nullptr, 'S'}, + {"store", required_argument, nullptr, 't'}, + {"show-trigger", required_argument, nullptr, 'T'}, + {"version", no_argument, nullptr, 'v'}, + {"verbose", no_argument, nullptr, 'V'}, + {nullptr, no_argument, nullptr, 0}}; + + for (;;) { + int option_index = 0; + + c = getopt_long(argc, argv, "d:hi:Ijl:p:s:St:T:vV", long_options, + &option_index); + if (c == -1) + break; + switch (c) { + case 'v': { + action = ACTION_VERSION; + break; + } + case 'V': { + MTS::Logger::setPrintLevel(MTS::Logger::PrintLevel::DEBUG_LEVEL, + true); + break; + } + case 'd': { + data = optarg; + break; + } + case 'i': { + fpgaFilePath = optarg; + break; + } + case 'p': { + forcedAP = optarg; + break; + } + case 'I': { + action = ACTION_INIT; + break; + } + case 'j': { + action = ACTION_JSON; + break; + } + case 's': { + action = ACTION_SHOW; + name = optarg; + break; + } + case 'S': { + action = ACTION_SHOW_TRIGGER; + name = optarg; + break; + } + case 't': { + action = ACTION_STORE; + name = optarg; + break; + } + case 'T': { + action = ACTION_STORE_TRIGGER; + name = optarg; + break; + } + case 'L': { + action = ACTION_LOAD_FPGA; + break; + } + case '?': { + printError("%s option requires arguement", optopt); + break; + } + case 'h': + default: + m.printUsage(argv[0]); + exit(0); } } - for (int i = 1; i < argc; i++) { - std::string parameter = argv[i]; - if (parameter == "init") { - m.init(); - } else if (parameter == "json") { - m.json(); - } else if (parameter == "show") { - if (argv[i + 1] && !argv[i + 2]) { - m.show(argv[i + 1]); + + /* Handle old non POSIX compliant command names. */ + int index; + for (index = optind; index < argc; index++) { + if (strcmp(argv[index], COMMMAND_INIT) == 0) { + action = ACTION_INIT; + } else if (strcmp(argv[index], COMMMAND_JSON) == 0) { + action = ACTION_JSON; + } else if (strcmp(argv[index], COMMMAND_SHOW) == 0) { + if (argv[index + 1]) { + action = ACTION_SHOW; + name = argv[index + 1]; } else { - m.logError("show name"); - exitHandler(99); + action = ACTION_NONE; } - } else if (parameter == "show-trigger") { - if (argv[i + 1] && !argv[i + 2]) { - m.showTrigger(std::string(argv[i + 1])); + } else if (strcmp(argv[index], COMMMAND_STORE) == 0) { + if (argv[index + 1]) { + action = ACTION_STORE; + name = argv[index + 1]; + if (argv[index + 2]) { + data = argv[index + 2]; + } } else { - m.logError("show-trigger name"); - exitHandler(99); + action = ACTION_NONE; } - } else if (parameter == "store") { - if (argv[i + 1] && argv[i + 2] && !argv[i + 3]) { - m.store(std::string(argv[i + 1]), std::string(argv[i + 2])); + } else if (strcmp(argv[index], COMMMAND_SHOW_TRIGGER) == 0) { + if (argv[index + 1]) { + action = ACTION_SHOW_TRIGGER; + name = argv[index + 1]; } else { - m.logError("store name value"); - exitHandler(99); + action = ACTION_NONE; } - } else if (parameter == "store-trigger") { - if (argv[i + 1] && argv[i + 2] && !argv[i + 3]) { - m.storeTrigger(std::string(argv[i + 1]), std::string(argv[i + 2])); + } else if (strcmp(argv[index], COMMMAND_STORE_TRIGGER) == 0) { + if (argv[index + 1]) { + action = ACTION_STORE_TRIGGER; + name = argv[index + 1]; + if (argv[index + 2]) { + data = argv[index + 2]; + } } else { - m.logError("store name value"); - exitHandler(99); + action = ACTION_NONE; + } + } else if (strcmp(argv[index], COMMMAND_LOAD_FPGA) == 0) { + action = ACTION_LOAD_FPGA; + } else if (strcmp(argv[index], COMMMAND_VERSION) == 0) { + action = ACTION_VERSION; + } else if (strcmp(argv[index], COMMMAND_EXTRA) == 0) { + if (argv[index + 1]) { + data = argv[index + 1]; } } } - m.printUsage(argv[0]); + + switch (action) { + case ACTION_NONE: { + m.printUsage(argv[0]); + } + case ACTION_SHOW: { + m.show(name); + } + case ACTION_SHOW_TRIGGER: { + m.showTrigger(name); + } + case ACTION_STORE: { + m.store(name, data); + } + case ACTION_STORE_TRIGGER: { + m.storeTrigger(name, data); + } + case ACTION_INIT: { + m.init(); + } + case ACTION_JSON: { + m.json(); + } + case ACTION_LOAD_FPGA: { + Mtac15Fpga mtac15Fpga(fpgaFilePath, forcedAP); + return mtac15Fpga.upgradeFpga(); + } + case ACTION_VERSION: { + m.printVersion(argv[0]); + } + default: { m.printUsage(argv[0]); } + } + + return 0; } diff --git a/src/Version.cpp b/src/Version.cpp deleted file mode 100644 index a74eb38..0000000 --- a/src/Version.cpp +++ /dev/null @@ -1,4 +0,0 @@ -//Pre-Build Auto-Generated Source -#include "Version.h" - -const std::string Version::version("v1.0.0-15-g8d80917"); -- cgit v1.2.3