summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorHarsh Sharma <harsh.sharma@multitech.com>2019-12-19 11:53:10 -0600
committerHarsh Sharma <harsh.sharma@multitech.com>2019-12-19 11:53:10 -0600
commit8ce2b9763c880084fd9d38fae6033e487fde58d9 (patch)
tree8b77e3d0c5f24bb8ba4b9ade6298684781a91665 /src
downloadmts-io-sysfs-8ce2b9763c880084fd9d38fae6033e487fde58d9.tar.gz
mts-io-sysfs-8ce2b9763c880084fd9d38fae6033e487fde58d9.tar.bz2
mts-io-sysfs-8ce2b9763c880084fd9d38fae6033e487fde58d9.zip
Initial commit
Diffstat (limited to 'src')
-rw-r--r--src/AccessoryCards/AccessoryCardLora.cpp22
-rw-r--r--src/AccessoryCards/AccessoryCardLora15.cpp142
-rw-r--r--src/Device/Device.cpp422
-rw-r--r--src/MtsIoSysfs.cpp75
-rw-r--r--src/Version.cpp4
5 files changed, 665 insertions, 0 deletions
diff --git a/src/AccessoryCards/AccessoryCardLora.cpp b/src/AccessoryCards/AccessoryCardLora.cpp
new file mode 100644
index 0000000..13bbab5
--- /dev/null
+++ b/src/AccessoryCards/AccessoryCardLora.cpp
@@ -0,0 +1,22 @@
+#include "AccessoryCardLora.h"
+
+AccessoryCardLora::AccessoryCardLora(std::string ProductId, std::string Port) {
+ port = Port;
+ productId = ProductId;
+ spiPath = "/dev/spidev0.0";
+ if ((productId.find("MTCDT3-") == 0) && (port.back() == '2')) {
+ spiPath = "/dev/spidev1.0";
+ } else if (productId.find("MTAC-LORA-G") == 0) {
+ spiPath = "/dev/spidev32766.2";
+ } else if (productId.find("MTAC-LORA-") == 0) {
+ if (port.back() == '2') {
+ spiPath = "/dev/spidev32765.2";
+ } else {
+ spiPath = "/dev/spidev32766.2";
+ }
+ }
+}
+
+std::string AccessoryCardLora::getPath() {
+ return spiPath;
+}
diff --git a/src/AccessoryCards/AccessoryCardLora15.cpp b/src/AccessoryCards/AccessoryCardLora15.cpp
new file mode 100644
index 0000000..ee99622
--- /dev/null
+++ b/src/AccessoryCards/AccessoryCardLora15.cpp
@@ -0,0 +1,142 @@
+#include "AccessoryCardLora15.h"
+
+AccessoryCardLora15::AccessoryCardLora15(std::string ProductId, std::string Port) : AccessoryCardLora(ProductId, Port) {
+}
+
+int AccessoryCardLora15::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;
+ }
+
+ /* 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;
+ }
+
+ /* 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;
+ }
+
+ /* 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 AccessoryCardLora15::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;
+ } else {
+ *data = in_buf[command_size - 1];
+ return 0;
+ }
+}
+
+int AccessoryCardLora15::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;
+ }
+}
+
+uint8_t AccessoryCardLora15::getFPGAVersion() {
+ int ret;
+ uint8_t u = 255;
+ ret = spiOpen(getPath().c_str());
+ if (ret != 0) {
+ printf("Could not open SPI port %s", getPath().c_str());
+ return u;
+ }
+ /* detect if the gateway has an FPGA with SPI mux header support */
+ ret = spiRead(MTAC_FPGA_ADDRESS, &u);
+ if (ret != 0) {
+ printf("Could not read FPGA version");
+ }
+
+ spiClose();
+ spi_target_ptr = NULL;
+ return u;
+} \ No newline at end of file
diff --git a/src/Device/Device.cpp b/src/Device/Device.cpp
new file mode 100644
index 0000000..573e10b
--- /dev/null
+++ b/src/Device/Device.cpp
@@ -0,0 +1,422 @@
+/**********************************************************************
+* COPYRIGHT 2020 MULTI-TECH SYSTEMS, INC.
+*
+* ALL RIGHTS RESERVED BY AND FOR THE EXCLUSIVE BENEFIT OF
+* MULTI-TECH SYSTEMS, INC.
+*
+* MULTI-TECH SYSTEMS, INC. - CONFIDENTIAL AND PROPRIETARY
+* INFORMATION AND/OR TRADE SECRET.
+*
+* NOTICE: ALL CODE, PROGRAM, INFORMATION, SCRIPT, INSTRUCTION,
+* DATA, AND COMMENT HEREIN IS AND SHALL REMAIN THE CONFIDENTIAL
+* INFORMATION AND PROPERTY OF MULTI-TECH SYSTEMS, INC.
+* USE AND DISCLOSURE THEREOF, EXCEPT AS STRICTLY AUTHORIZED IN A
+* WRITTEN AGREEMENT SIGNED BY MULTI-TECH SYSTEMS, INC. IS PROHIBITED.
+*
+***********************************************************************/
+
+#include "Device.h"
+
+const std::vector<std::string> Device::apIdentifiers = {"ap1", "ap2", "lora", "lora-2", "slot1", "slot2"};
+const std::regex Device::apFilters("(modalias)|(power)(.*)|(subsystem)|(uevent)");
+const std::regex Device::lora15Filters("(MTAC-LORA-)(.*)|(MTCAP-LORA-)(.*)|(MTLGA-)(.*)|(MTCDT3-)(.*)");
+const std::regex Device::loraG16Filters("(MTAC-LORA-G16)(.*)");
+const std::regex Device::loraG64Filters("(MTAC-LORA-G64)(.*)");
+const std::regex Device::gpiobFilters("(MTAC-GPIOB)|(MMTAC-GPIOI)");
+const std::regex Device::mfserFilters("(MTAC-MFSER-DTE)|(MTAC-MFSER-DCE)|(MTR-)(.*)");
+const std::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::showFilters("(modalias)|(subsystem)|(uevent)");
+
+Device::Device() {
+ isRoot = !getuid();
+}
+
+void Device::exitHandler(int code) {
+ if (code != 0) {
+ logError("exiting with " + std::to_string(code));
+ }
+ exit(code);
+}
+
+bool Device::fileExists(std::string file) {
+ struct stat buffer;
+ return (stat (file.c_str(), &buffer) == 0) ? true : false;
+}
+
+mode_t Device::fileType(std::string file) {
+ struct stat buf;
+ stat (file.c_str(), &buf);
+ return buf.st_mode & S_IFMT;
+}
+
+void Device::getSystemTreeJson(const char * dir_name) {
+ std::string fullPath = SYSFS_PLATFORM + std::string(dir_name);
+ DIR * d = opendir (fullPath.c_str());
+
+ if (!d) {
+ logError("Cannot open directory " + fullPath);
+ exitHandler(99);
+ }
+ while (1) {
+ struct dirent * entry;
+ const char * d_name;
+ entry = readdir (d); // Gets subsequent entries from "d"
+ if (!entry) { // If there are no more entries, exit
+ break;
+ }
+ d_name = entry->d_name; // Get file name
+ if (!(entry->d_type & DT_DIR)) {
+ std::string fileData;
+ MTS::System::readFile(fullPath + "/" + std::string(d_name), fileData);
+ fileData = MTS::Text::trim(fileData);
+ if (strlen(dir_name) > 0) {
+ if (std::binary_search(apIdentifiers.begin(), apIdentifiers.end(), dir_name) && !regex_match(d_name, apFilters)) {
+ if (accessoryCard.IsNull()) {
+ accessoryCard.SetObject();
+ } else if (accessoryCard.HasMember(d_name)) {
+ accessoryCards.PushBack(accessoryCard, accessoryCardsAlloc);
+ accessoryCard.SetObject();
+ }
+ if (strcmp(d_name, "product-id") == 0) {
+ if (regex_match(fileData, lora15Filters)) {
+ capabilityList["lora"] = true;
+ AccessoryCardLora15 mSPI(fileData, dir_name);
+ mSPI.getFPGAVersion();
+ accessoryCard.AddMember("loraFpgaVersion", mSPI.getFPGAVersion(), accessoryCardsAlloc);
+ } else if (regex_match(fileData, loraG16Filters)) {
+ capabilityList["lora"] = true;
+ std::string fpgaVersion;
+ MTS::System::cmd(LORA_2_1_FPGA_VERSION, fpgaVersion);
+ accessoryCard.AddMember("loraFpgaVersion", std::stoi(fpgaVersion), accessoryCardsAlloc);
+ } else if (regex_match(fileData, loraG64Filters)) {
+ capabilityList["lora"] = true;
+ std::string fpgaVersion;
+ std::string fpgaVersion2;
+ MTS::System::cmd(LORA_2_1_FPGA_VERSION, fpgaVersion);
+ MTS::System::cmd(LORA_2_1_EXT_FPGA_VERSION, fpgaVersion2);
+ accessoryCard.AddMember("loraFpgaVersion", std::stoi(fpgaVersion), accessoryCardsAlloc);
+ accessoryCard.AddMember("loraFpgaVersion2", std::stoi(fpgaVersion2), accessoryCardsAlloc);
+ } else if (regex_match(fileData, gpiobFilters)) {
+ capabilityList["adc"] = true;
+ capabilityList["din"] = true;
+ capabilityList["dout"] = true;
+ capabilityList["gpio"] = true;
+ } else if (regex_match(fileData, mfserFilters)) {
+ capabilityList["rs232"] = true;
+ capabilityList["rs422"] = true;
+ capabilityList["rs485"] = true;
+ capabilityList["serial"] = true;
+ if (!fileExists("/dev/ext_serial") && strlen(dir_name) > 0) {
+ std::string temp;
+ MTS::System::cmd("ln -s /dev/ttyAP" + std::string(dir_name + strlen(dir_name) - 1) + " /dev/ext_serial", temp);
+ }
+ }
+ }
+ 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") {
+ capabilityList[toCamelCase(d_name)] = true;
+ }
+ } 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;
+ }
+ }
+ }
+ if (entry->d_type & DT_DIR) { /* Check that the directory is not "d" or d's parent. */
+ if (strcmp (d_name, "..") != 0 && strcmp (d_name, ".") != 0) {
+ std::string path = fullPath + "/" + std::string(d_name);
+ if (path.length() >= PATH_MAX) {
+ logError("Path length has got too long.\n");
+ exitHandler(99);
+ }
+ 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));
+ exitHandler(errno);
+ }
+}
+
+void Device::init() {
+ if (!isRoot) {
+ logError("Must be root to generate device_info.json");
+ exitHandler(99);
+ }
+ load();
+ writeJson();
+ exitHandler(0);
+}
+
+void Device::json() {
+ if (!isRoot) {
+ logError("Must be root to generate json");
+ exitHandler(99);
+ }
+ load();
+ printJson();
+ exitHandler(0);
+}
+
+void Device::load() {
+ deviceInfo.SetObject();
+ capabilities.SetObject();
+ accessoryCards.SetArray();
+ getSystemTreeJson("");
+ if (!accessoryCard.IsNull()) {
+ accessoryCards.PushBack(accessoryCard, accessoryCardsAlloc);
+ }
+ mapFileToCapability();
+ mapFirmware();
+ for (const auto capability : capabilityList) {
+ capabilities.AddMember(rapidjson::Value().SetString(capability.first.c_str(),
+ capability.first.length(), accessoryCardsAlloc), capability.second, accessoryCardsAlloc);
+ }
+ 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("capabilities", capabilities, alloc);
+ 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("/dev/modem_at0") == S_IFLNK && fileType("/dev/modem_at1") == S_IFLNK) {
+ capabilityList["cell"] = true;
+ }
+ if (fileType("/dev/modem_at0") == S_IFLNK) {
+ capabilityList["cell"] = true;
+ }
+ if (fileType("/dev/ext_serial") == S_IFCHR) {
+ capabilityList["externalSerialPort"] = true;
+ }
+ if (fileType("/opt/node-red") == S_IFDIR) {
+ capabilityList["nodeRed"] = true;
+ }
+ if (fileType("/opt/lora/lora-network-server") == S_IFREG) {
+ capabilityList["loraNetworkServer"] = true;
+ }
+}
+
+void Device::mapFirmware() {
+ std::ifstream file(FIRMWARE_FILE);
+ if (!file.is_open()){
+ return;
+ }
+ std::string line;
+ 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){
+ deviceInfoList["firmwareDate"] = line.substr(line.find(" ") + 1);
+ }
+ }
+}
+
+void Device::printDir(const std::string dir_name, std::vector<std::string> &results) {
+ std::string fullPath = SYSFS_PLATFORM + std::string(dir_name);
+ DIR * d = opendir(fullPath.c_str());
+ if (!d) {
+ logError("Cannot open directory " + std::string(fullPath));
+ exitHandler(99);
+ }
+ while (1) {
+ struct dirent * entry = readdir (d);
+ if (!entry) {
+ break;
+ }
+ const char * d_name = entry->d_name;
+ if (!(entry->d_type & DT_DIR)) {
+ std::string result;
+ if (dir_name.size() > 0) {
+ result = (dir_name + "/");
+ }
+ result.append(d_name);
+ results.push_back(result);
+ }
+ if ((entry->d_type & DT_DIR) && strcmp (d_name, "..") != 0 && strcmp (d_name, ".") != 0) {
+ std::string path = fullPath + "/" + std::string(d_name);
+ if (path.length() >= PATH_MAX) {
+ logError("Path length has got too long.\n");
+ exitHandler(99);
+ }
+ printDir(d_name, results);
+ }
+ }
+ if (closedir (d)) { /* After going through all the entries, close the directory. */
+ logError("Could not close " + std::string(fullPath));
+ exitHandler(errno);
+ }
+}
+
+void Device::printJson() {
+ rapidjson::StringBuffer buffer;
+ rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
+ deviceInfo.Accept(writer);
+ std::cout << buffer.GetString();
+}
+
+void Device::printVersion (std::string name) {
+ printf("%s %s\nCopyright (C) 2019 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::printUsage(std::string program) {
+ std::vector<std::string> 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(" }\n");
+ printf("\n");
+ printf(" SHOW-NAME := {\n");
+ printDir("", showResults);
+ sort(showResults.begin(), showResults.end()); // Unix file tree is not sorted
+
+ for (std::string showResult: showResults) {
+ if (!regex_match(showResult, showFilters))
+ printf (" %s\n", showResult.c_str());
+ }
+ printf(" }\n");
+ printf("\n");
+ printf(" STORE-NAME := {\n");
+ for (std::string showResult: showResults) {
+ if (showResult == "radio-reset") {
+ 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());
+ } else if (showResult == "reset-monitor-intervals") {
+ 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());
+ } else if (!regex_match(showResult, storeFilters)) {
+ 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);
+}
+
+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());
+ exitHandler(0);
+ } else {
+ logError("cat: can't open " + std::string(SYSFS_PLATFORM) + name + ": No such file or directory");
+ exitHandler(99);
+ }
+
+}
+
+void Device::showTrigger(std::string name) {
+ std::string fileData;
+ int32_t code = MTS::System::readFile(LEDS_GPIO_DIR + name + "/trigger", fileData);
+ if (code == 0) {
+ 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");
+ exitHandler(99);
+ }
+}
+
+void Device::store(std::string name, std::string value) {
+ if (!isRoot) {
+ logError("Must be root to store to " + name);
+ exitHandler(99);
+ }
+ logInfo("setting " + name + " to " + value);
+ 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");
+ exitHandler(99);
+ }
+
+}
+
+void Device::storeTrigger(std::string name, std::string value) {
+ if (!isRoot) {
+ logError("Must be root to storeTrigger to " + name + "/trigger");
+ exitHandler(99);
+ }
+ logInfo("setting " + name + " to " + value);
+ 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");
+ exitHandler(99);
+ }
+
+}
+
+std::string Device::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] == '_'){
+ tempString = camelString.substr(x + 1, 1);
+ transform(tempString.begin(), tempString.end(), tempString.begin(), toupper);
+ camelString.erase(x, 2);
+ camelString.insert(x, tempString);
+ }
+ }
+ return camelString;
+}
+
+void Device::Verbose(bool val) {
+ verbose = val;
+}
+
+bool Device::Verbose() {
+ return verbose;
+}
+
+void Device::writeJson() {
+ rapidjson::StringBuffer buffer;
+ rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
+ deviceInfo.Accept(writer);
+ std::string json (buffer.GetString(), buffer.GetSize());
+ std::ofstream of ("/var/run/config/device_info.json");
+ of << json;
+ if (!of.good()) {
+ logError("Can't write to /var/run/config/device_info.json");
+ exitHandler(99);
+ } else {
+ exitHandler(0);
+ }
+}
diff --git a/src/MtsIoSysfs.cpp b/src/MtsIoSysfs.cpp
new file mode 100644
index 0000000..0c9dc2e
--- /dev/null
+++ b/src/MtsIoSysfs.cpp
@@ -0,0 +1,75 @@
+/**********************************************************************
+* 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[]) {
+ Device m;
+ if (argc < 2) {
+ m.printUsage(argv[0]);
+ }
+
+ 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);
+ }
+ }
+ }
+ 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]);
+ } else {
+ m.logError("show name");
+ m.exitHandler(99);
+ }
+ } else if (parameter == "show-trigger") {
+ if (argv[i + 1] && !argv[i + 2]) {
+ m.showTrigger(std::string(argv[i + 1]));
+ } else {
+ m.logError("show-trigger name");
+ m.exitHandler(99);
+ }
+ } 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 {
+ m.logError("store name value");
+ m.exitHandler(99);
+ }
+ } 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 {
+ m.logError("store name value");
+ m.exitHandler(99);
+ }
+ }
+ }
+ m.printUsage(argv[0]);
+}
diff --git a/src/Version.cpp b/src/Version.cpp
new file mode 100644
index 0000000..5585cc1
--- /dev/null
+++ b/src/Version.cpp
@@ -0,0 +1,4 @@
+//Pre-Build Auto-Generated Source
+#include "Version.h"
+
+const std::string Version::version("4.2.3-12-g42e11db");