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