/*
* Copyright (C) 2015 by Multi-Tech Systems
*
* This file is part of radio-query.
*
* radio-query 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-query 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-query. 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 std::string DEFAULT_CACHE("/var/run/radio");
const std::string FMODEL("model");
const std::string FIMEI("imei");
const std::string FMEID("meid");
const std::string FIMSI("imsi");
const std::string FTYPE("type");
const std::string FCODE("code");
const std::string FRSSI("rssi");
const std::string FFIRMWARE("firmware");
const std::string FCARRIER("carrier");
const std::string FMDN("mdn");
const std::string FICCID("iccid");
std::string g_sCache(DEFAULT_CACHE);
std::string g_sModel;
std::string g_sType;
std::string g_sPort(DEFAULT_PORT);
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_FIRMWARE = 0x00000001;
const uint32_t OPT_IMEI = 0x00000002;
const uint32_t OPT_IMSI = 0x00000004;
const uint32_t OPT_LAC = 0x00000008;
const uint32_t OPT_MODEL = 0x00000010;
const uint32_t OPT_NETREG = 0x00000020;
const uint32_t OPT_NETWORK = 0x00000040;
const uint32_t OPT_MDN = 0x00000080;
const uint32_t OPT_PHONENUMBER = OPT_MDN;
const uint32_t OPT_RSSI = 0x00000100;
const uint32_t OPT_TOWER = 0x00000200;
const uint32_t OPT_ICCID = 0x00000400;
const uint32_t OPT_SERVICE = 0x00000800;
const uint32_t OPT_TYPE = 0x00001000;
const uint32_t OPT_CARRIER = 0x00002000;
const uint32_t OPT_DATETIME = 0x00004000;
const uint32_t OPT_ACTIVEFIRMWARE = 0x00008000;
const uint32_t OPT_LOCATION = 0x00010000;
const uint32_t OPT_SUMMARY_STATIC = 0x01000000;
const uint32_t OPT_SUMMARY_NETWORK = 0x02000000;
void handle_sigterm(int signum);
void printHelp(const std::string& sApp);
void parseOptions(int argc, char** argv);
void initializeCache();
void shutdown();
template bool writeToCache(const std::string& sFile, const T& tValue);
Json::Value getStaticData();
Json::Value getNetworkData();
bool g_bIstty = false;
int main(int argc, char** argv) {
using namespace MTS::IO;
signal(SIGTERM, handle_sigterm);
signal(SIGINT, handle_sigterm);
MTS::Logger::setPrintLevel(MTS::Logger::PrintLevel::OFF_LEVEL, true);
if (isatty(fileno(stdin)) && isatty(fileno(stdout)))
g_bIstty = true;
//Assuming cache needs to be built
bool bBuildCache = true;
parseOptions(argc, argv);
printTrace("istty: %d\n", g_bIstty);
if(!(g_iOptions & OPT_INITIALIZE)) {
std::ifstream fModel;
fModel.open(g_sCache + "/" + FMODEL);
if(fModel.is_open()) {
std::string sModel;
fModel >> sModel;
fModel.close();
if(sModel.size() > 0) {
printTrace("Pulling Model from cache: [%s]", sModel.c_str());
g_sModel = sModel;
}
bBuildCache = false;
}
}
MTS::IO::CellularRadioFactory factory;
g_apRadio.reset(factory.create(g_sModel, g_sPort));
if(g_apRadio.isNull() || !g_apRadio->initialize()) {
printf("Error creating radio interface [%s][%s]\n", g_sPort.c_str(), g_sModel.c_str());
exit(1);
}
if((g_iOptions & OPT_INITIALIZE) || bBuildCache) {
initializeCache();
if(g_iOptions & OPT_INITIALIZE) {
//Initialization was the only purpose
shutdown();
return 0;
}
}
CellularRadio::CODE result = CellularRadio::CODE::SUCCESS;
if(g_iOptions & OPT_SUMMARY_NETWORK) {
printf("%s", getNetworkData().toStyledString().c_str());
} else if(g_iOptions & OPT_SUMMARY_STATIC) {
printf("%s", getStaticData().toStyledString().c_str());
} else if(g_iOptions & OPT_RSSI) {
int32_t iValue;
result = g_apRadio->getSignalStrength(iValue);
if(result == CellularRadio::SUCCESS) {
writeToCache(FRSSI, iValue);
printf("%d", iValue);
}
}else if(g_iOptions & OPT_LOCATION) {
std::string sValue;
result = g_apRadio->getModemLocation(sValue);
if(result == CellularRadio::SUCCESS) {
printf("%s", sValue.c_str());
} else {
printf("Radio has not location support");
}
}else if(g_iOptions & OPT_NETREG) {
std::string sValue;
CellularRadio::REGISTRATION eReg;
result = g_apRadio->getRegistration(eReg);
if(result == CellularRadio::SUCCESS) {
result = g_apRadio->convertRegistrationToString(eReg, sValue);
if(result == CellularRadio::SUCCESS) {
printf("%s", sValue.c_str());
}
}
} else if(g_iOptions & OPT_LAC) {
std::string sValue;
result = g_apRadio->getLac(sValue);
if(result == CellularRadio::SUCCESS) {
printf("%s", sValue.c_str());
}
} else if(g_iOptions & OPT_TOWER) {
std::string sValue;
result = g_apRadio->getTower(sValue);
if(result == CellularRadio::SUCCESS) {
printf("%s", sValue.c_str());
}
} else if(g_iOptions & OPT_ICCID) {
std::string sValue;
result = g_apRadio->getIccid(sValue);
if(result == CellularRadio::SUCCESS) {
writeToCache(FICCID, sValue);
printf("%s", sValue.c_str());
}
} else if(g_iOptions & OPT_SERVICE) {
std::string sValue;
result = g_apRadio->getService(sValue);
if(result == CellularRadio::SUCCESS) {
printf("%s", sValue.c_str());
}
} else if(g_iOptions & OPT_NETWORK) {
std::string sValue;
result = g_apRadio->getNetwork(sValue);
if(result == CellularRadio::SUCCESS) {
printf("%s", sValue.c_str());
}
} else if(g_iOptions & OPT_MDN) {
std::string sValue;
result = g_apRadio->getMdn(sValue);
if(result == CellularRadio::SUCCESS) {
writeToCache(FMDN, sValue);
printf("%s", sValue.c_str());
}
} else if(g_iOptions & OPT_FIRMWARE) {
std::string sValue;
result = g_apRadio->getFirmware(sValue);
if(result == CellularRadio::SUCCESS) {
writeToCache(FFIRMWARE, sValue);
printf("%s", sValue.c_str());
}
} else if(g_iOptions & OPT_IMEI) {
std::string sValue;
result = g_apRadio->getImei(sValue);
if(result == CellularRadio::SUCCESS) {
printf("%s", sValue.c_str());
}
} else if(g_iOptions & OPT_IMSI) {
std::string sValue;
result = g_apRadio->getImsi(sValue);
if(result == CellularRadio::SUCCESS) {
printf("%s", sValue.c_str());
}
} else if(g_iOptions & OPT_MODEL) {
std::string sValue;
result = g_apRadio->getModel(sValue);
if(result == CellularRadio::SUCCESS) {
printf("%s", sValue.c_str());
}
} else if(g_iOptions & OPT_TYPE) {
std::string sValue;
std::string sType;
result = g_apRadio->getModel(sValue);
if(result == CellularRadio::SUCCESS) {
result = g_apRadio->convertModelToType(sValue, sType);
if(result == CellularRadio::SUCCESS) {
printf("%s", sType.c_str());
}
}
} else if(g_iOptions & OPT_CARRIER) {
std::string sValue;
result = g_apRadio->getCarrier(sValue);
if(result == CellularRadio::SUCCESS) {
writeToCache(FCARRIER, sValue);
printf("%s", sValue.c_str());
}
} else if(g_iOptions & OPT_DATETIME) {
std::string sDate, sTime, sZone;
result = g_apRadio->getTime(sDate, sTime, sZone);
if(result == CellularRadio::SUCCESS) {
printf("%s %s GMT%s", sDate.c_str(), sTime.c_str(), sZone.c_str());
}
} else if(g_iOptions & OPT_ACTIVEFIRMWARE) {
std::string sValue;
result = g_apRadio->getActiveFirmware(sValue);
if(result == CellularRadio::SUCCESS) {
printf("%s", sValue.c_str());
}
}
if (g_bIstty && result == CellularRadio::CODE::SUCCESS)
printf("\n");
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();
g_apRadio.reset();
}
}
void initializeCache() {
if(mkdir(g_sCache.c_str(), 0777) != 0) {
if(errno != EEXIST) {
printf("Error creating cache directory [%s] [%d][%s]\n", g_sCache.c_str(), errno, strerror(errno));
exit(1);
}
}
//Gather Static Information
const Json::Value jData = getStaticData();
printTrace("Static Data:\n%s\n", jData.toStyledString().c_str());
//Save to radio cache directory
std::ofstream ofile;
ofile.open(g_sCache + "/" + FMODEL);
ofile << jData[MTS::IO::CellularRadio::KEY_MODEL].asString();
ofile.close();
if(g_sType == MTS::IO::CellularRadio::VALUE_TYPE_CDMA) {
ofile.open(g_sCache + "/" + FIMEI);
ofile << jData[MTS::IO::CellularRadio::KEY_MEID].asString();
ofile.close();
ofile.open(g_sCache + "/" + FMEID);
ofile << jData[MTS::IO::CellularRadio::KEY_MEID].asString();
ofile.close();
} else {
ofile.open(g_sCache + "/" + FIMEI);
ofile << jData[MTS::IO::CellularRadio::KEY_IMEI].asString();
ofile.close();
ofile.open(g_sCache + "/" + FMEID);
ofile << jData[MTS::IO::CellularRadio::KEY_IMEI].asString();
ofile.close();
}
ofile.open(g_sCache + "/" + FIMSI);
ofile << jData[MTS::IO::CellularRadio::KEY_IMSI].asString();
ofile.close();
ofile.open(g_sCache + "/" + FTYPE);
ofile << jData[MTS::IO::CellularRadio::KEY_TYPE].asString();
ofile.close();
ofile.open(g_sCache + "/" + FCODE);
ofile << jData[MTS::IO::CellularRadio::KEY_CODE].asString();
ofile.close();
ofile.open(g_sCache + "/" + FFIRMWARE);
ofile << jData[MTS::IO::CellularRadio::KEY_FIRMWARE].asString();
ofile.close();
ofile.open(g_sCache + "/" + FCARRIER);
ofile << jData[MTS::IO::CellularRadio::KEY_CARRIER].asString();
ofile.close();
}
template
bool writeToCache(const std::string& sFile, const T& tValue) {
std::ofstream ofile;
ofile.open(g_sCache + "/" + sFile);
if(!ofile.is_open()){
return false;
}
std::stringstream ss;
ss << tValue;
ofile << ss.str();
ofile.close();
return true;
}
Json::Value getStaticData() {
using namespace MTS::IO;
Json::Value jData;
std::string sImei;
CellularRadio::CODE eCode = g_apRadio->getImei(sImei);
if(eCode != CellularRadio::SUCCESS) {
printWarning("Radio IMEI not found: %s", CellularRadio::getCodeAsString(eCode).c_str());
}
if(g_apRadio->getModel(g_sModel) == CellularRadio::SUCCESS) {
jData[CellularRadio::KEY_MODEL] = g_sModel;
} else {
printWarning("Radio model not found");
}
if(g_apRadio->convertModelToType(g_sModel, g_sType) == CellularRadio::SUCCESS) {
jData[CellularRadio::KEY_TYPE] = g_sType;
} else {
printWarning("Radio type not supported");
}
std::string sCode(CellularRadio::VALUE_UNKNOWN);
if(g_apRadio->convertModelToMtsShortCode(g_sModel, sCode) != CellularRadio::SUCCESS) {
printWarning("Radio MTS short code not supported");
}
jData[CellularRadio::KEY_CODE] = sCode;
if(g_sType == CellularRadio::VALUE_TYPE_CDMA) {
jData[CellularRadio::KEY_MEID] = sImei;
} else {
jData[CellularRadio::KEY_IMEI] = sImei;
std::string sIccid;
if(g_apRadio->getIccid(sIccid) == CellularRadio::SUCCESS) {
jData[CellularRadio::KEY_ICCID] = sIccid;
}
}
std::string sImsi(CellularRadio::VALUE_UNKNOWN);
if(g_apRadio->getImsi(sImsi) != CellularRadio::SUCCESS) {
printWarning("Radio IMSI not found");
}
jData[CellularRadio::KEY_IMSI] = sImsi;
std::string sMsid(CellularRadio::VALUE_UNKNOWN);
if(g_apRadio->getMsid(sMsid) != CellularRadio::SUCCESS) {
printWarning("Radio MSID not found");
}
jData[CellularRadio::KEY_MSID] = sMsid;
std::string sFirmware(CellularRadio::VALUE_UNKNOWN);
if(g_apRadio->getFirmware(sFirmware) != CellularRadio::SUCCESS) {
printWarning("Radio Firmware not found");
}
jData[CellularRadio::KEY_FIRMWARE] = sFirmware;
std::string sCarrier(CellularRadio::VALUE_UNKNOWN);
if(g_apRadio->getCarrier(sCarrier) != CellularRadio::SUCCESS) {
printWarning("Radio Carrier not found");
}
jData[CellularRadio::KEY_CARRIER] = sCarrier;
std::string sHardware(CellularRadio::VALUE_UNKNOWN);
if(g_apRadio->getHardware(sHardware) != CellularRadio::SUCCESS) {
printWarning("Radio Hardware Version not found");
}
jData[CellularRadio::KEY_HARDWARE] = sHardware;
std::string sManufacturer(CellularRadio::VALUE_UNKNOWN);
if(g_apRadio->getManufacturer(sManufacturer) != CellularRadio::SUCCESS) {
printWarning("Radio Manufacturer not found");
}
jData[CellularRadio::KEY_MANUFACTURER] = sManufacturer;
std::string sMdn(CellularRadio::VALUE_UNKNOWN);
if(g_apRadio->getMdn(sMdn) == CellularRadio::SUCCESS) {
//CDMA Provisioned Flag
if(g_sType == CellularRadio::VALUE_TYPE_CDMA) {
if(sMdn.size() == 0 || sMdn.find("000000") != std::string::npos) {
jData["provisioned"] = false;
} else {
jData["provisioned"] = true;
}
}
} else {
printWarning("Radio MDN not found");
}
jData[CellularRadio::KEY_MDN] = sMdn;
Json::Value jMip;
if(g_apRadio->getMipProfile(jMip) == MTS::IO::CellularRadio::SUCCESS) {
jData[MTS::IO::CellularRadio::KEY_MIP] = jMip;
}
return jData;
}
Json::Value getNetworkData() {
Json::Value jData;
g_apRadio->getNetworkStatus(jData);
return jData;
}
void parseOptions(int argc, char** argv) {
int c;
int iOption;
std::string sPath;
if(argc == 1) {
printHelp(argv[0]);
exit(0);
}
while (1) {
static struct option long_options[] =
{ { "help", no_argument, 0, '?' },
{ "version", no_argument, 0, 'v' },
{ "device", required_argument, 0, 'd' },
{ "printlvl", required_argument, 0, 'p' },
{ "init", optional_argument, 0, 'i' },
{ "cachedir", required_argument, 0, 'c' },
{ "firmware", no_argument, &iOption, OPT_FIRMWARE },
{ "imei", no_argument, &iOption, OPT_IMEI },
{ "imsi", no_argument, &iOption, OPT_IMSI },
{ "lac", no_argument, &iOption, OPT_LAC },
{ "model", no_argument, &iOption, OPT_MODEL },
{ "netreg", no_argument, &iOption, OPT_NETREG },
{ "network", no_argument, &iOption, OPT_NETWORK },
{ "phonenumber", no_argument, &iOption, OPT_PHONENUMBER },
{ "mdn", no_argument, &iOption, OPT_MDN },
{ "rssi", no_argument, &iOption, OPT_RSSI },
{ "location", no_argument, &iOption, OPT_LOCATION },
{ "tower", no_argument, &iOption, OPT_TOWER },
{ "iccid", no_argument, &iOption, OPT_ICCID },
{ "service", no_argument, &iOption, OPT_SERVICE },
{ "type", no_argument, &iOption, OPT_TYPE },
{ "carrier", no_argument, &iOption, OPT_CARRIER },
{ "datetime", no_argument, &iOption, OPT_DATETIME },
{ "active-firmware", no_argument, &iOption, OPT_ACTIVEFIRMWARE },
{ "static", no_argument, &iOption, OPT_SUMMARY_STATIC },
{ "dynamic", no_argument, &iOption, OPT_SUMMARY_NETWORK },
{ 0, 0, 0, 0 } };
/* getopt_long stores the option index here. */
int option_index = 0;
c = getopt_long(argc, argv, "d:p:ic:?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 'i':
if(optarg != 0) {
g_sModel = optarg;
}
g_iOptions |= OPT_INITIALIZE;
break;
case 'c':
if(optarg != 0) {
g_sCache = optarg;
}
break;
case 'd':
if(optarg != 0) {
g_sPort = optarg;
}
break;
default:
printf("OPTION: [%d] ABORTING!!\n", c);
abort();
break;
}
}
printTrace("OPTS: %08X\n", g_iOptions);
/* Print any remaining command line arguments (not options). */
if (optind < argc) {
fprintf(stderr, "non-option ARGV-elements: \n");
while (optind < argc)
fprintf(stderr, "%s ", argv[optind++]);
fprintf(stderr, "\n");
}
}
void printHelp(const std::string& sApp) {
printf("Usage: %s ...\n", sApp.c_str());
printf("\tSimple utility to pull info from supported radios in a consistent manner\n");
printf("\t--init (i) : initializes the utility for all future calls\n");
printf("\t--device (d) : specify modem device to query, default: /dev/modem_at1\n");
printf("\t--printlvl (p) : sets the printlvl [0-100]\n");
printf("\t--help (?) : returns this message\n");
printf("\t--version (v) : returns version\n");
printf("\n");
printf("\tQueries:\n");
printf("\t--firmware\n");
printf("\t--imei\n");
printf("\t--imsi\n");
printf("\t--lac\n");
printf("\t--model\n");
printf("\t--netreg\n");
printf("\t--network\n");
printf("\t--phonenumber\n");
printf("\t--mdn\n");
printf("\t--rssi\n");
printf("\t--location\n");
printf("\t--tower\n");
printf("\t--iccid\n");
printf("\t--service\n");
printf("\t--type\n");
printf("\t--carrier\n");
printf("\t--datetime\n");
//Applicable for LTE910-NA1 dual FW images only
//printf("\t--active-firmware\n");
printf("\n");
printf("\tSupported Radios:\n");
printf("\t\tHE910, GE910, DE910, CE910\n");
}