From 4d2d44f2b7d0f299ca485b9686eeb970083bca99 Mon Sep 17 00:00:00 2001 From: Jesse Gilles Date: Thu, 30 Apr 2015 14:00:41 -0500 Subject: initial commit --- main.cpp | 597 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 597 insertions(+) create mode 100644 main.cpp (limited to 'main.cpp') diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000..56c9c61 --- /dev/null +++ b/main.cpp @@ -0,0 +1,597 @@ +/* + * Copyright (C) 2015 by Multi-Tech Systems + * + * This file is part of radio-cmd. + * + * radio-cmd is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * radio-cmd is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with radio-cmd. If not, see . + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "Version.h" + +const std::string DEFAULT_PORT("/dev/modem_at1"); +const int32_t DEFAULT_TIMEOUT = 100; +const std::string DEFAULT_COMMAND("AT"); +const std::string DEFAULT_CACHE("/var/run/radio"); +const std::string FMODEL("model"); +const std::string FMSL("msl"); + +std::string g_sTimeout; +std::string g_sDevice(DEFAULT_PORT); +std::string g_sAtCommand(DEFAULT_COMMAND); +std::string g_sCache(DEFAULT_CACHE); +std::string g_sModel; + +std::string g_sMDN; +std::string g_sMSID; +std::string g_sMSL; +std::string g_sMIPActiveProfile; +std::string g_sMIPNai; +std::string g_sMIPHomeAddr; +std::string g_sMIPPrimaryHa; +std::string g_sMIPSecondaryHa; +std::string g_sMIPMnAaaSpi; +std::string g_sMIPMnHaSpi; +std::string g_sMIPRevTun; +std::string g_sMIPMnAaaSs; +std::string g_sMIPMnHaSs; +Json::Value g_jData; + +MTS::AutoPtr g_apRadio; + +int32_t g_iOptions = 0; + +const uint32_t OPT_INDIVIDUAL = 0x00FFFFFF; +const uint32_t OPT_SUMMARY = 0x7F000000; +const uint32_t OPT_INITIALIZE = 0x10000000; + +const uint32_t OPT_TIMEOUT = 0x00000001; +const uint32_t OPT_DEVICE = 0x00000002; +const uint32_t OPT_COMMAND = 0x00000004; +const uint32_t OPT_MSL = 0x00000008; +const uint32_t OPT_SETMDN = 0x00000010; +const uint32_t OPT_SETMSID = 0x00000020; +const uint32_t OPT_SETMSL = 0x00000040; +const uint32_t OPT_SETMIPACTIVEPROFILE = 0x00000080; +const uint32_t OPT_SETMIPNAI = 0x00000100; +const uint32_t OPT_SETMIPHOMEADDR = 0x00000200; +const uint32_t OPT_SETMIPPRIMARYHA = 0x00000400; +const uint32_t OPT_SETMIPSECONDARYHA = 0x00000800; +const uint32_t OPT_SETMIPMNAAASPI = 0x00001000; +const uint32_t OPT_SETMIPMNHASPI = 0x00002000; +const uint32_t OPT_SETMIPREVTUN = 0x00004000; +const uint32_t OPT_SETMIPMNAAASS = 0x00008000; +const uint32_t OPT_SETMIPMNHASS = 0x00010000; +const uint32_t OPT_INIT_DC = 0x00020000; +const uint32_t OPT_INIT_FUMO = 0x00040000; +const uint32_t OPT_INIT_PRL = 0x00080000; +const uint32_t OPT_INIT_RTN = 0x00100000; +const uint32_t OPT_INIT_ACTIVATION = 0x00200000; +const uint32_t OPT_MDN = 0x00400000; +const uint32_t OPT_MSID = 0x00800000; + +void handle_sigterm(int signum); +void printHelp(const std::string& sApp); +void parseOptions(int argc, char** argv); +void initializeCache(); +void shutdown(); +const char *code2str(MTS::IO::CellularRadio::CODE code); +std::string loadImeiFromDeviceInfo(); + +Json::Value getStaticData(); +Json::Value getNetworkData(); + +MTS::IO::CellularRadio::UpdateCb cb = [](const Json::Value& s)->void { + if(s.isString()) { + printf("%s\n", s.asCString()); + } +}; + +int main(int argc, char** argv) { + using namespace MTS::IO; + + //Disable stdout buffering so this process can pipe out data as needed + // * otherwise entire stdout is buffered until process is closed using popen + setbuf(stdout, NULL); + + signal(SIGTERM, handle_sigterm); + signal(SIGINT, handle_sigterm); + + MTS::Logger::setPrintLevel(MTS::Logger::PrintLevel::OFF_LEVEL, true); + + parseOptions(argc, argv); + + if(!(g_iOptions & OPT_INITIALIZE)) { + // get model from cache + std::ifstream fModel((g_sCache + "/" + FMODEL).c_str()); + if(fModel.is_open()) { + std::string sModel; + fModel >> sModel; + if(sModel.size() > 0) { + printTrace("Pulling Model from cache: [%s]", sModel.c_str()); + g_sModel = sModel; + } + } + // get msl from cache + std::ifstream fMSL((g_sCache + "/" + FMSL).c_str()); + if(fMSL.is_open()) { + std::string sMSL; + fMSL >> sMSL; + if(sMSL.size() > 0) { + printTrace("Pulling Msl from cache: [%s]", sMSL.c_str()); + g_sMSL = sMSL; + g_iOptions |= OPT_MSL; + } + } + } + + MTS::IO::CellularRadioFactory factory; + g_apRadio.reset(factory.create(g_sModel, g_sDevice)); + + if(g_apRadio.isNull() || !g_apRadio->initialize()) { + printf("Error creating radio interface [%s][%s]\n", g_sDevice.c_str(), g_sModel.c_str()); + return EXIT_FAILURE; + } + + CellularRadio::CODE result = CellularRadio::CODE::SUCCESS; + + if(g_iOptions & OPT_COMMAND) { + int32_t timeoutMillis = DEFAULT_TIMEOUT; + if(g_iOptions & OPT_TIMEOUT) { + timeoutMillis = atoi(g_sTimeout.c_str()); + if(!timeoutMillis) { + printError("Timeout: invalid, use default timeout\n"); + timeoutMillis = DEFAULT_TIMEOUT; + } + } + printDebug("AT Command: %s\n", g_sAtCommand.c_str()); + std::string sResult = g_apRadio->sendCommand(g_sAtCommand, MTS::IO::CellularRadio::DEFAULT_BAIL_STRINGS, timeoutMillis); + printDebug("RESULT: %s\n", sResult.c_str()); + // skip first line + std::size_t pos = sResult.find('\n'); + if(pos == std::string::npos) { + pos = 0; + } else { + ++pos; + } + printf("%s", sResult.substr(pos).c_str()); + } else if(g_iOptions & OPT_SETMDN) { + Json::Value jArgs(Json::objectValue); + printDebug("SET MDN: %s\n", g_sMDN.c_str()); + jArgs["mdn"] = g_sMDN; + if(g_iOptions & OPT_MSL) { + printDebug("MSL: %s\n", g_sMSL.c_str()); + jArgs["msl"] = g_sMSL; + } + result = g_apRadio->setMdn(jArgs); + printf("%s\n", code2str(result)); + } else if(g_iOptions & OPT_SETMSID) { + Json::Value jArgs(Json::objectValue); + printDebug("SET MSID: %s\n", g_sMSID.c_str()); + jArgs["msid"] = g_sMSID; + if(g_iOptions & OPT_MSL) { + printDebug("MSL: %s\n", g_sMSL.c_str()); + jArgs["msl"] = g_sMSL; + } + result = g_apRadio->setMsid(jArgs); + printf("%s\n", code2str(result)); + } else if(g_iOptions & OPT_SETMIPACTIVEPROFILE) { + Json::Value jArgs(Json::objectValue); + printDebug("SET MIP ACTIVE PROFILE: %s\n", g_sMIPActiveProfile.c_str()); + jArgs["activeProfile"] = g_sMIPActiveProfile; + result = g_apRadio->setMipActiveProfile(jArgs); + printf("%s\n", code2str(result)); + } else if(g_iOptions & OPT_SETMIPNAI) { + Json::Value jArgs(Json::objectValue); + printDebug("SET MIP NAI: %s\n", g_sMIPNai.c_str()); + jArgs["nai"] = g_sMIPNai; + result = g_apRadio->setMipNai(jArgs); + printf("%s\n", code2str(result)); + } else if(g_iOptions & OPT_SETMIPHOMEADDR) { + Json::Value jArgs(Json::objectValue); + printDebug("SET MIP HOME ADDR: %s\n", g_sMIPHomeAddr.c_str()); + jArgs["homeIp"] = g_sMIPHomeAddr; + result = g_apRadio->setMipHomeIp(jArgs); + printf("%s\n", code2str(result)); + } else if(g_iOptions & OPT_SETMIPPRIMARYHA) { + Json::Value jArgs(Json::objectValue); + printDebug("SET MIP PRIMARY HA: %s\n", g_sMIPPrimaryHa.c_str()); + jArgs["primaryHa"] = g_sMIPPrimaryHa; + result = g_apRadio->setMipPrimaryHa(jArgs); + printf("%s\n", code2str(result)); + } else if(g_iOptions & OPT_SETMIPSECONDARYHA) { + Json::Value jArgs(Json::objectValue); + printDebug("SET MIP SECONDARY HA: %s\n", g_sMIPSecondaryHa.c_str()); + jArgs["secondaryHa"] = g_sMIPSecondaryHa; + result = g_apRadio->setMipSecondaryHa(jArgs); + printf("%s\n", code2str(result)); + } else if(g_iOptions & OPT_SETMIPMNAAASPI) { + Json::Value jArgs(Json::objectValue); + printDebug("SET MIP MN-AAA SPI: %s\n", g_sMIPMnAaaSpi.c_str()); + jArgs["mnAaaSpi"] = g_sMIPMnAaaSpi; + result = g_apRadio->setMipMnAaaSpi(jArgs); + printf("%s\n", code2str(result)); + } else if(g_iOptions & OPT_SETMIPMNHASPI) { + Json::Value jArgs(Json::objectValue); + printDebug("SET MIP MN-HA SPI: %s\n", g_sMIPMnHaSpi.c_str()); + jArgs["mnHaSpi"] = g_sMIPMnHaSpi; + result = g_apRadio->setMipMnHaSpi(jArgs); + printf("%s\n", code2str(result)); + } else if(g_iOptions & OPT_SETMIPREVTUN) { + Json::Value jArgs(Json::objectValue); + printDebug("SET MIP REV TUN: %s\n", g_sMIPRevTun.c_str()); + jArgs["revTun"] = g_sMIPRevTun; + result = g_apRadio->setMipRevTun(jArgs); + printf("%s\n", code2str(result)); + } else if(g_iOptions & OPT_SETMIPMNAAASS) { + Json::Value jArgs(Json::objectValue); + printDebug("SET MIP MN-AAA SS: %s\n", g_sMIPMnAaaSs.c_str()); + jArgs["mnAaaSs"] = g_sMIPMnAaaSs; + result = g_apRadio->setMipMnAaaSs(jArgs); + printf("%s\n", code2str(result)); + } else if(g_iOptions & OPT_SETMIPMNHASS) { + Json::Value jArgs(Json::objectValue); + printDebug("SET MIP MN-HA SS: %s\n", g_sMIPMnHaSs.c_str()); + jArgs["mnHaSs"] = g_sMIPMnHaSs; + result = g_apRadio->setMipMnHaSs(jArgs); + printf("%s\n", code2str(result)); + } else if(g_iOptions & OPT_SETMSL) { + Json::Value jArgs(Json::objectValue); + jArgs["msl"] = g_sMSL; + result = g_apRadio->validateMsl(jArgs); + if(result == MTS::IO::CellularRadio::CODE::SUCCESS) { + std::ofstream fMSL((g_sCache + "/" + FMSL).c_str(), std::ios_base::trunc | std::ios_base::out); + if(fMSL.is_open()) { + std::string sMSL; + fMSL << g_sMSL; + } + } + printf("%s\n", code2str(result)); + } else if(g_iOptions & OPT_INIT_DC) { + Json::Value jArgs(Json::nullValue); + result = g_apRadio->updateDc(jArgs, cb); + printf("%s\n", code2str(result)); + } else if(g_iOptions & OPT_INIT_PRL) { + Json::Value jArgs(Json::nullValue); + result = g_apRadio->updatePrl(jArgs, cb); + printf("%s\n", code2str(result)); + } else if(g_iOptions & OPT_INIT_FUMO) { + Json::Value jArgs(Json::nullValue); + result = g_apRadio->updateFumo(jArgs, cb); + printf("%s\n", code2str(result)); + } else if(g_iOptions & OPT_INIT_RTN) { + Json::Value jArgs(Json::objectValue); + if(g_iOptions & OPT_MSL) { + printDebug("MSL: %s\n", g_sMSL.c_str()); + jArgs["msl"] = g_sMSL; + } + result = g_apRadio->resetHfa(jArgs, cb); + printf("%s\n", code2str(result)); + } else if(g_iOptions & OPT_INIT_ACTIVATION) { + Json::Value jArgs(Json::objectValue); + if(g_iOptions & OPT_MSID) { + printDebug("MSID: %s", g_sMSID.c_str()); + jArgs["msid"] = g_sMSID; + } + if(g_iOptions & OPT_MDN) { + printDebug("MDN: %s", g_sMDN.c_str()); + jArgs["mdn"] = g_sMDN; + } + result = g_apRadio->activate(jArgs, cb); + printf("%s\n", code2str(result)); + } + + shutdown(); + + return (result == CellularRadio::CODE::SUCCESS) ? 0 : 1; +} + +void handle_sigterm(int signum) { + if(signum == SIGTERM) { + shutdown(); + } +} + +void shutdown() { + printDebug("Shutting Down"); + if(!g_apRadio.isNull()) { + g_apRadio->shutdown(); + } +} + +void parseOptions(int argc, char** argv) { + int c; + int iOption = 0; + + if(argc == 1) { + printHelp(argv[0]); + exit(0); + } + + while (1) { + static struct option long_options[] = + { { "help", no_argument, 0, '?' }, + { "version", no_argument, 0, 'v' }, + { "printlvl", required_argument, 0, 'p' }, + { "device", required_argument, 0, 'd' }, + { "set-mdn", required_argument, 0, 'n' }, + { "set-msl", required_argument, 0, 'm' }, + { "set-msid", required_argument, 0, 's' }, + { "msl", required_argument, 0, 'l' }, + { "mdn", required_argument, 0, 'k' }, + { "msid", required_argument, 0, 'j' }, + { "set-mip-active-profile", required_argument, 0, '0' }, + { "set-mip-nai", required_argument, 0, '1' }, + { "set-mip-home-ip", required_argument, 0, '2' }, + { "set-mip-primary-ha", required_argument, 0, '3' }, + { "set-mip-secondary-ha", required_argument, 0, '4' }, + { "set-mip-mn-aaa-spi", required_argument, 0, '5' }, + { "set-mip-mn-ha-spi", required_argument, 0, '6' }, + { "set-mip-rev-tun", required_argument, 0, '7' }, + { "set-mip-mn-aaa-ss", required_argument, 0, '8' }, + { "set-mip-mn-ha-ss", required_argument, 0, '9' }, + { "init-dc", no_argument, &iOption, OPT_INIT_DC }, + { "init-fumo", no_argument, &iOption, OPT_INIT_FUMO }, + { "init-prl", no_argument, &iOption, OPT_INIT_PRL }, + { "init-activation", no_argument, &iOption, OPT_INIT_ACTIVATION }, + { "factory-default", no_argument, &iOption, OPT_INIT_RTN }, + { 0, 0, 0, 0 } }; + + /* getopt_long stores the option index here. */ + int option_index = 0; + + c = getopt_long(argc, argv, "t:d:p:?v", long_options, &option_index); + + /* Detect the end of the options. */ + if(c == -1) { + break; + } + + if(c == 0) { + g_iOptions |= iOption; + continue; + } + + switch (c) { + + case '?': + printHelp(argv[0]); + exit(0); + break; + + case 'v': + printf("Version: %s\n", Version::version.c_str()); + exit(0); + break; + + case 'p': + int iPrintLvl; + if(MTS::Text::parse(iPrintLvl, optarg) && iPrintLvl >= 0 && iPrintLvl <= 100) { + MTS::Logger::setPrintLevel(iPrintLvl); + } else { + printf("print level out of range [0-100]\n"); + exit(1); + } + break; + + case 't': + if(optarg != 0) { + g_sTimeout = optarg; + } + g_iOptions |= OPT_TIMEOUT; + break; + + case 'd': + if(optarg != 0) { + g_sDevice = optarg; + } + g_iOptions |= OPT_DEVICE; + break; + + case 'n': + if(optarg != 0) { + g_sMDN = optarg; + } + g_iOptions |= OPT_SETMDN; + break; + + case 's': + if(optarg != 0) { + g_sMSID = optarg; + } + g_iOptions |= OPT_SETMSID; + break; + + case 'm': + if(optarg != 0) { + g_sMSL = optarg; + } + g_iOptions |= OPT_SETMSL; + break; + + case 'l': + if(optarg != 0) { + g_sMSL = optarg; + } + g_iOptions |= OPT_MSL; + break; + + case 'k': + if(optarg != 0) { + g_sMDN = optarg; + } + g_iOptions |= OPT_MDN; + break; + case 'j': + if(optarg != 0) { + g_sMSID = optarg; + } + g_iOptions |= OPT_MSID; + break; + case '0': + if(optarg != 0) { + g_sMIPActiveProfile = optarg; + } + g_iOptions |= OPT_SETMIPACTIVEPROFILE; + break; + + case '1': + if(optarg != 0) { + g_sMIPNai = optarg; + } + g_iOptions |= OPT_SETMIPNAI; + break; + + case '2': + if(optarg != 0) { + g_sMIPHomeAddr = optarg; + } + g_iOptions |= OPT_SETMIPHOMEADDR; + break; + + case '3': + if(optarg != 0) { + g_sMIPPrimaryHa = optarg; + } + g_iOptions |= OPT_SETMIPPRIMARYHA; + break; + + case '4': + if(optarg != 0) { + g_sMIPSecondaryHa = optarg; + } + g_iOptions |= OPT_SETMIPSECONDARYHA; + break; + + case '5': + if(optarg != 0) { + g_sMIPMnAaaSpi = optarg; + } + g_iOptions |= OPT_SETMIPMNAAASPI; + break; + + case '6': + if(optarg != 0) { + g_sMIPMnHaSpi = optarg; + } + g_iOptions |= OPT_SETMIPMNHASPI; + break; + + case '7': + if(optarg != 0) { + g_sMIPRevTun = optarg; + } + g_iOptions |= OPT_SETMIPREVTUN; + break; + + case '8': + if(optarg != 0) { + g_sMIPMnAaaSs = optarg; + } + g_iOptions |= OPT_SETMIPMNAAASS; + break; + + case '9': + if(optarg != 0) { + g_sMIPMnHaSs = optarg; + } + g_iOptions |= OPT_SETMIPMNHASS; + break; + + default: + printf("OPTION: [%d] ABORTING!!\n", c); + abort(); + break; + } + } + + if((g_iOptions & (OPT_TIMEOUT | OPT_DEVICE)) || !g_iOptions) { + /* Assume that any remaining command line arguments is AT Command */ + if(optind < argc) { + g_sAtCommand = argv[optind]; + g_iOptions |= OPT_COMMAND; + } + } + + printDebug("OPTS: %08X\n", g_iOptions); + +} + +void printHelp(const std::string& sApp) { + printf("Usage: %s [OPTION] [] ...\n", sApp.c_str()); + printf("\tSimple utility to send either general AT command or predefined specific command to radio module\n"); + printf("\t [ -t -d ] : send AT command. Timeout and device are optional\n"); + printf("\t--device (d) : modem device to use, default: /dev/modem_at1\n"); + printf("\t--init-dc : initiate device configuration update\n"); + printf("\t--init-fumo : initiate module/modem firmware update\n"); + printf("\t--init-prl : initiate PRL update\n"); + printf("\t--init-activation [ --msid --mdn ]\n"); + printf("\t : initiate account activation. Some carriers require MDN and MSID\n"); + printf("\n"); + printf("\t--set-mdn [ --msl ] : set MDN value. Some carriers require MSL\n"); + printf("\t--set-msid [ --msl ] : set MSID value. Some carriers require MSL\n"); + printf("\t--set-msl : validate and save Master Subsidy Lock (MSL) in cache\n"); + printf("\t--set-mip-active-profile : set active MIP profile\n"); + printf("\t--set-mip-nai : set MIP Network Access Identifier\n"); + printf("\t--set-mip-home-ip : set MIP Home Address\n"); + printf("\t--set-mip-primary-ha : set MIP Primary Home Agent\n"); + printf("\t--set-mip-secondary-ha : set MIP Secondary Home Agent\n"); + printf("\t--set-mip-mn-aaa-spi : set MIP MN AAA SPI\n"); + printf("\t--set-mip-mn-ha-spi : set MIP MN HA SPI\n"); + printf("\t--set-mip-rev-tun : set MIP Reverse Tunneling\n"); + printf("\t--set-mip-mn-aaa-ss : set MIP MN AAA SS\n"); + printf("\t--set-mip-mn-ha-ss : set MIP MN HA SS\n"); + printf("\t--factory-default [ --msl ] : reset to factory defaults\n"); + printf("\n"); + printf("\t--printlvl (p) : sets the printlvl [0-100]\n"); + printf("\t--version (v) : returns version\n"); + printf("\t--help (?) : returns this message\n"); + printf("\n"); + printf("\tSupported Radios:\n"); + printf("\t\tHE910, GE910, DE910, CE910\n"); +} + +const char *code2str(MTS::IO::CellularRadio::CODE code) { + switch (code) { + case MTS::IO::CellularRadio::CODE::SUCCESS: + return "Success"; + case MTS::IO::CellularRadio::CODE::ERROR: + return "Error"; + case MTS::IO::CellularRadio::CODE::FAILURE: + return "Failure"; + case MTS::IO::CellularRadio::CODE::NO_RESPONSE: + return "No Response"; + case MTS::IO::CellularRadio::CODE::NOT_APPLICABLE: + return "Not Applicable"; + case MTS::IO::CellularRadio::CODE::INVALID_ARGS: + return "Invalid Arguments"; + } + return "Unknown"; +} -- cgit v1.2.3