diff options
| -rw-r--r-- | .gitignore | 2 | ||||
| -rw-r--r-- | Makefile | 15 | ||||
| -rw-r--r-- | include/Device/Device.h | 254 | ||||
| -rw-r--r-- | include/Fpga/Fpga.h | 74 | ||||
| -rw-r--r-- | include/General.h | 87 | ||||
| -rw-r--r-- | include/Utility/Utility.h | 43 | ||||
| -rw-r--r-- | src/AccessoryCards/AccessoryCard.cpp | 26 | ||||
| -rw-r--r-- | src/AccessoryCards/AcessoryCard.cpp | 21 | ||||
| -rw-r--r-- | src/AccessoryCards/Gpiob.cpp | 36 | ||||
| -rw-r--r-- | src/AccessoryCards/LoraCard.cpp | 38 | ||||
| -rw-r--r-- | src/AccessoryCards/LoraCard03.cpp | 53 | ||||
| -rw-r--r-- | src/AccessoryCards/LoraCard10.cpp | 38 | ||||
| -rw-r--r-- | src/AccessoryCards/LoraCard15.cpp | 195 | ||||
| -rw-r--r-- | src/AccessoryCards/LoraCard21.cpp | 48 | ||||
| -rw-r--r-- | src/AccessoryCards/LoraCard21Ext.cpp | 42 | ||||
| -rw-r--r-- | src/AccessoryCards/LoraCard2G4.cpp | 32 | ||||
| -rw-r--r-- | src/AccessoryCards/Mfser.cpp | 47 | ||||
| -rw-r--r-- | src/AccessoryCards/Mtac15Fpga.cpp | 803 | ||||
| -rw-r--r-- | src/Device/Device.cpp | 434 | ||||
| -rw-r--r-- | src/MtsIoSysfs.cpp | 261 | ||||
| -rw-r--r-- | src/Version.cpp | 4 | 
21 files changed, 1893 insertions, 660 deletions
| 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 @@ -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 <math.h> /* ceil */ + +class Mtac15Fpga;  class Device { -	private: -        bool verbose ; -        bool isRoot; -        rapidjson::Document capabilities; -        rapidjson::Document ethSwitch; -        rapidjson::Document deviceInfo; -        static const std::vector<std::string> apIdentifiers; -        rapidjson::Document accessoryCards; -        rapidjson::Value accessoryCard; -        rapidjson::Document::AllocatorType& alloc = deviceInfo.GetAllocator(); -        rapidjson::Document::AllocatorType& accessoryCardsAlloc = accessoryCards.GetAllocator(); -        static std::map<std::string, bool> capabilityList; -        static std::map<std::string, std::string> ethSwitchList; -        static std::map<std::string, std::string> 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<std::string> &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<std::string> apIdentifiers; +    rapidjson::Document accessoryCards; +    rapidjson::Value accessoryCard; +    rapidjson::Document::AllocatorType &alloc = deviceInfo.GetAllocator(); +    rapidjson::Document::AllocatorType &acAlloc = accessoryCards.GetAllocator(); +    static std::map<std::string, bool> capabilityList; +    static std::map<std::string, std::string> ethSwitchList; +    static std::map<std::string, std::string> 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<std::unique_ptr<AccessoryCard>> 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<std::string> &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 <math.h>        /* ceil */ +#include <openssl/sha.h> /* 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 <mts/MTS_Logger.h>  #include <mts/MTS_System.h>  #include <mts/MTS_Text.h> +#include <dirent.h> +#include <fcntl.h> /* open */  #include <fstream>  #include <iostream> -#include <stdlib.h> -#include <stdio.h>  /* printf fprintf */ -#include <fcntl.h> /* open */  #include <linux/spi/spidev.h> -#include <sys/ioctl.h> -#include <unistd.h> /* lseek, close */ -#include <dirent.h>  #include <regex> +#include <stdio.h> /* printf fprintf */ +#include <stdlib.h> +#include <sys/ioctl.h>  #include <sys/stat.h> - +#include <unistd.h> /* lseek, close */ +#include <getopt.h> /* 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 <glob.h>  /********************************************************************** -* 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<std::string> 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<std::string> 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<std::string, bool> 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<std::string, bool> 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<std::string, std::string> Device::ethSwitchList; -std::map<std::string, std::string> 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<std::string, std::string> 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<Lora21Card>(*this)); +    accessoryCardsList.push_back(std::make_unique<Lora21ExtCard>(*this)); +    accessoryCardsList.push_back(std::make_unique<Lora03Card>(*this)); +    accessoryCardsList.push_back(std::make_unique<Lora10Card>(*this)); +    accessoryCardsList.push_back(std::make_unique<Lora15Card>(*this)); +    accessoryCardsList.push_back(std::make_unique<Lora2G4Card>(*this)); +    accessoryCardsList.push_back(std::make_unique<Gpiob>(*this)); +    accessoryCardsList.push_back(std::make_unique<Mfser>(*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<std::string> &results) { +void Device::printDir(const std::string dir_name, +                      std::vector<std::string> &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<std::string> &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<std::string> 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 file>        Upgrade the FPGA " +           "on the default port using the file specified\n", +           program.c_str()); +    printf("          %s load-fpga -p 2 -i <upgrade file>   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<rapidjson::StringBuffer> 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"); | 
