diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/MTS_IO_CellularRadio.cpp | 175 | ||||
-rw-r--r-- | src/MTS_IO_ICellularRadio.cpp | 3 | ||||
-rw-r--r-- | src/MTS_IO_LE910Radio.cpp | 65 | ||||
-rw-r--r-- | src/MTS_IO_MccMncTable.cpp | 14 | ||||
-rw-r--r-- | src/MTS_IO_QuectelRadio.cpp | 46 | ||||
-rw-r--r-- | src/MTS_IO_TelitRadio.cpp | 34 |
6 files changed, 329 insertions, 8 deletions
diff --git a/src/MTS_IO_CellularRadio.cpp b/src/MTS_IO_CellularRadio.cpp index afdfc1e..069d5fa 100644 --- a/src/MTS_IO_CellularRadio.cpp +++ b/src/MTS_IO_CellularRadio.cpp @@ -1755,3 +1755,178 @@ ICellularRadio::CODE CellularRadio::getSelectedBandsRaw(std::string& sRawBands) printTrace("%s| Acquiring selected bands: not applicable", m_sName.c_str()); return NOT_APPLICABLE; } + +ICellularRadio::CODE CellularRadio::getPdpContexts(Json::Value& jData) { + printTrace("%s| Fetching the list of PDP contexts from the radio", getName().c_str()); + CODE rc; + + const std::string sCommand = "AT+CGDCONT?"; + const int dTimeout = 1000; + std::string sResult; + + rc = sendBasicQuery(sCommand, "", sResult, dTimeout); + if (rc != SUCCESS) { + return rc; + } + + std::vector<std::string> vContexts = MTS::Text::split(sResult, "+CGDCONT: "); + std::vector<std::string> vContextParams; + + for (size_t i = 0; i < vContexts.size(); i++) { + vContexts[i] = MTS::Text::trim(vContexts[i]); + + if (vContexts[i].empty()) { + continue; + } + + vContextParams = MTS::Text::split(vContexts[i], ",", 4); + + if (vContextParams.size() < 3) { + return FAILURE; + } + + std::string sContextId = vContextParams[0]; + std::string sIpMode = MTS::Text::trim(vContextParams[1], '"'); // Remove double quotes from the start and end of the value + std::string sApn = MTS::Text::trim(vContextParams[2], '"'); // Remove double quotes from the start and end of the value + + jData[sContextId][ICellularRadio::KEY_PDP_CONTEXT_IPMODE] = sIpMode; + jData[sContextId][ICellularRadio::KEY_PDP_CONTEXT_APN] = sApn; + } + + return SUCCESS; +} + +ICellularRadio::CODE CellularRadio::setPdpContext(const std::string& sId, const Json::Value& jConfig) { + printTrace("%s| Setting context to the radio", getName().c_str()); + CODE rc; + + if (sId.empty()) { + printError("%s| PDP Context ID is not specified", getName().c_str()); + return FAILURE; + } + + std::string sCommand = "AT+CGDCONT=" + sId; + const int dTimeout = 1000; + + Json::Value jAllContexts; + + rc = getPdpContexts(jAllContexts); + if (rc != SUCCESS) { + printError("%s| Failed to retrieve the current PDP context configuration: [%d]", getName().c_str(), rc); + return rc; + } + + // Remove the context if no parameters defined + if (!jConfig.isMember(ICellularRadio::KEY_PDP_CONTEXT_IPMODE) && !jConfig.isMember(ICellularRadio::KEY_PDP_CONTEXT_APN)) { + if (jAllContexts.isMember(sId)) { + rc = sendBasicCommand(sCommand, dTimeout); + return rc; + } else { + printError("%s| PDP Context [%s] does not exist", getName().c_str(), sId.c_str()); + return FAILURE; + } + } + + std::string sIpMode; + + if (jConfig.isMember(ICellularRadio::KEY_PDP_CONTEXT_IPMODE)) { + if (jConfig[ICellularRadio::KEY_PDP_CONTEXT_IPMODE] == "IP" || jConfig[ICellularRadio::KEY_PDP_CONTEXT_IPMODE] == "PPP" || + jConfig[ICellularRadio::KEY_PDP_CONTEXT_IPMODE] == "IPV6" || jConfig[ICellularRadio::KEY_PDP_CONTEXT_IPMODE] == "IPV4V6") { + sIpMode = jConfig[ICellularRadio::KEY_PDP_CONTEXT_IPMODE].asString(); + } else { + printError("%s| Invalid IP Mode defined: [%s]", getName().c_str(), jConfig[ICellularRadio::KEY_PDP_CONTEXT_IPMODE].asString().c_str()); + return FAILURE; + } + } else if (jAllContexts.isMember(sId)) { + printInfo("%s| Re-using IP Mode [%s] for PDP context [%s]", getName().c_str(), jAllContexts[sId][ICellularRadio::KEY_PDP_CONTEXT_IPMODE].asString().c_str(), sId.c_str()); + sIpMode = jAllContexts[sId][ICellularRadio::KEY_PDP_CONTEXT_IPMODE].asString(); + } else { + printError("%s| Failed to edit PDP context [%s] - no such context defined", getName().c_str(), sId.c_str()); + return FAILURE; + } + + sCommand += ",\""; + sCommand += sIpMode; + sCommand += "\""; + + std::string sApn; + + if (jConfig.isMember(ICellularRadio::KEY_PDP_CONTEXT_APN)) { + sApn = jConfig[ICellularRadio::KEY_PDP_CONTEXT_APN].asString(); + } else if (jAllContexts.isMember(sId)) { + printInfo("%s| Re-using APN [%s] for PDP context [%s]", getName().c_str(), jAllContexts[sId][ICellularRadio::KEY_PDP_CONTEXT_APN].asString().c_str(), sId.c_str()); + sApn = jAllContexts[sId][ICellularRadio::KEY_PDP_CONTEXT_APN].asString(); + } else { + printError("%s| Failed to edit PDP context [%s] - no such context defined", getName().c_str(), sId.c_str()); + return FAILURE; + } + + sCommand += ",\""; + sCommand += sApn; + sCommand += "\""; + + rc = sendBasicCommand(sCommand, dTimeout); + + return rc; +} + +ICellularRadio::CODE CellularRadio::getDiagnostics(std::string& sReport) { + // Clear the original content before using the string as a buffer. + sReport.clear(); + + // Determine whether the SIM card is locked to select the appropriate + // list of commands for this radio. + std::string sSimLockStatus; + CODE iSimLockRet = getSimLockStatus(sSimLockStatus); + + // Re-use the SIM status detection logic from TelitRadio::getNetworkStatus. + // The SIM should be inserted and NOT locked. + bool bIsSimReady = (iSimLockRet == CODE::SUCCESS + && sSimLockStatus != "SIM PIN" + && sSimLockStatus != "SIM PUK"); + + // Determine the list of diagnostic commands required for this radio. + const auto& vCommands = getDiagCommands(bIsSimReady); + + // For all commands - set the maximum timeout to 2 seconds. + const int iMaxTimeout = 2000; + + // Allow the radio to ignore up to 2 consecutive queries before giving up. + int iMaxNoResponseCount = 2; + int iNoResponseCount = 0; + + // Execute each of the commands, add their output to the report. + for (const auto& sCmd : vCommands) { + // First line - the command to execute. + sReport.append(sCmd); + sReport.push_back(ICellularRadio::CR); + sReport.push_back(ICellularRadio::NL); + + // Execute the command. + std::string sResult = sendCommand(sCmd, ICellularRadio::DEFAULT_BAIL_STRINGS, iMaxTimeout); + + // Count the number of commands ignored by the radio. + // Normally, the radio should not ignore any of the commands, + // but radios have their own bugs. + if (sResult.empty()) { + printWarning("%s| Failed to execute the [%s] command - no response from the radio in [%d] ms", getName().c_str(), sCmd.c_str(), iMaxTimeout); + sResult = "<NO RESPONSE FROM THE RADIO>\r\n"; + ++iNoResponseCount; + } else { + iNoResponseCount = 0; + } + + // If the radio ignored too many commands - probably it is stuck and will not + // return to operation on its own. There is no point in waiting any longer. + if (iNoResponseCount >= iMaxNoResponseCount) { + printError("%s| Failed to execute the diagnostic commands - the radio has stopped responding", getName().c_str()); + return CODE::NO_RESPONSE; + } + + // Append the command output to the report. + sReport.append(sResult); + } + + // All commands returned a non-empty output. + return CODE::SUCCESS; +} diff --git a/src/MTS_IO_ICellularRadio.cpp b/src/MTS_IO_ICellularRadio.cpp index 7453662..05af28d 100644 --- a/src/MTS_IO_ICellularRadio.cpp +++ b/src/MTS_IO_ICellularRadio.cpp @@ -97,6 +97,9 @@ const char *MTS::IO::ICellularRadio::KEY_MIP_REVTUN = "revTun"; const char *MTS::IO::ICellularRadio::KEY_MIP_MNAAASS = "mnAaaSs"; //!< Mobile Node Authentication, Authorization, and Accounting Server Shared Secret const char *MTS::IO::ICellularRadio::KEY_MIP_MNHASS = "mnHaSs"; //!< Mobile Node Home Agent Shared Secret +const char *MTS::IO::ICellularRadio::KEY_PDP_CONTEXT_APN = "apn"; +const char *MTS::IO::ICellularRadio::KEY_PDP_CONTEXT_IPMODE = "ipMode"; + const char *MTS::IO::ICellularRadio::VALUE_TYPE_GSM = "GSM"; const char *MTS::IO::ICellularRadio::VALUE_TYPE_LTE = "LTE"; const char *MTS::IO::ICellularRadio::VALUE_TYPE_CDMA = "CDMA"; diff --git a/src/MTS_IO_LE910Radio.cpp b/src/MTS_IO_LE910Radio.cpp index ba03c5e..2f1debb 100644 --- a/src/MTS_IO_LE910Radio.cpp +++ b/src/MTS_IO_LE910Radio.cpp @@ -165,3 +165,68 @@ ICellularRadio::CODE LE910Radio::getUeModeOfOperation(ICellularRadio::UE_MODES_O return rc; } +const std::vector<std::string>& LE910Radio::getDiagCommands(bool bIsSimReady) { + // Declare as static to initialize only when used, but cache the results. + const static std::vector<std::string> vCommands { + // Radio model and firmware: + "AT+CGMI", "AT+CGMM", "AT+CGMR", "AT#SWPKGV", "AT#CFVR", + + // Current operator profile on the radio side: + "AT#FWSWITCH?", "AT+CGSN", + + // SIM card information: + "AT#SIMDET?", "AT#CCID", "AT+CPIN?", "AT#PCT", + + // Operating mode of the radio: + "AT+CFUN?", + + // Low-level network settings: + "AT+WS46?", "AT#RXDIV", "AT#CALLDISA?", "AT+CEMODE?", + + // Data connection configuration: + "AT+CGDCONT?", "AT#PDPAUTH?", + + // Registration and connection to the tower: + "AT+CIND?", "AT+CSQ", "AT+COPS?", "AT+CREG?", "AT+CGREG?", "AT+CEREG?", + "AT#RFSTS", "AT#PSNT?", "AT#MONI", + + // Data connection status: + "AT+CGACT?", "AT+CGCONTRDP=1", "AT+CGCONTRDP=2", "AT+CGCONTRDP=3" + }; + + const static std::vector<std::string> vSimLockedCommands { + // Radio model and firmware: + "AT+CGMI", "AT+CGMM", "AT+CGMR", "AT#SWPKGV", "AT#CFVR", + + // Current operator profile on the radio side: + "AT#FWSWITCH?", "AT+CGSN", + + // SIM card information: + "AT#SIMDET?", "AT#CCID", "AT+CPIN?", "AT#PCT", + + // Operating mode of the radio: + "AT+CFUN?", + + // Low-level network settings: + "AT+WS46?", "AT#RXDIV", "AT#CALLDISA?", "AT+CEMODE?", + + // Data connection configuration: + "AT+CGDCONT?", "AT#PDPAUTH?", + + // Registration and connection to the tower. + // The same set of commands, but AT#RFSTS is replaced with a dummy command. + "AT+CIND?", "AT+CSQ", "AT+COPS?", "AT+CREG?", "AT+CGREG?", "AT+CEREG?", + "AT#RFSTS_IGNORED", "AT#PSNT?", "AT#MONI", + + // Data connection status: + "AT+CGACT?", "AT+CGCONTRDP=1", "AT+CGCONTRDP=2", "AT+CGCONTRDP=3" + }; + + // Ignore AT#RFSTS on LE910 radios (mostly legacy ones like LAT1 and LEU1) if + // the SIM card is locked by PIN or PUK. Telit Support Portal Case #5069697. + if (bIsSimReady) { + return vCommands; + } else { + return vSimLockedCommands; + } +} diff --git a/src/MTS_IO_MccMncTable.cpp b/src/MTS_IO_MccMncTable.cpp index 97f92ab..f1940be 100644 --- a/src/MTS_IO_MccMncTable.cpp +++ b/src/MTS_IO_MccMncTable.cpp @@ -21,7 +21,7 @@ /*! \file MTS_IO_MccMncTable.cpp \brief Auto-Generated MCC-MNC Lookup Table - \date 2021-11-05 + \date 2023-01-06 \author sgodinez An Auto-Generated MCC-MNC Lookup Table @@ -614,6 +614,7 @@ void MccMncTable::createTable() { m_mTable[784][624] = "us,United States,1,T-Mobile,"; m_mTable[784][640] = "us,United States,1,AT&T Wireless Inc.,att"; m_mTable[784][656] = "us,United States,1,NEP Cellcorp Inc.,"; + m_mTable[784][783] = "us,United States,1,Centennial Communications,att"; m_mTable[784][768] = "us,United States,1,T-Mobile,"; m_mTable[784][799] = "us,United States,1,T-Mobile,"; m_mTable[784][784] = "us,United States,1,T-Mobile,"; @@ -646,14 +647,14 @@ void MccMncTable::createTable() { m_mTable[784][1376] = "us,United States,1,AT&T Wireless Inc.,att"; m_mTable[784][1392] = "us,United States,1,MTPCS LLC,"; m_mTable[784][1408] = "us,United States,1,PCS ONE,"; - m_mTable[784][1424] = "us,United States,1,Verizon Wireless,"; + m_mTable[784][1424] = "us,United States,1,Verizon Wireless,vz"; m_mTable[784][1551] = "us,United States,1,Consolidated Telcom,"; m_mTable[784][1536] = "us,United States,1,New-Cell Inc.,"; m_mTable[784][1552] = "us,United States,1,Elkhart TelCo. / Epic Touch Co.,"; m_mTable[784][1568] = "us,United States,1,Coleman County Telco /Trans TX,"; m_mTable[784][1584] = "us,United States,1,,"; m_mTable[784][1600] = "us,United States,1,,"; - m_mTable[784][1616] = "us,United States,1,Jasper,"; + m_mTable[784][1616] = "us,United States,1,Jasper,att-jasper"; m_mTable[784][1632] = "us,United States,1,T-Mobile,"; m_mTable[784][1648] = "us,United States,1,Northstar,att"; m_mTable[784][1664] = "us,United States,1,AT&T Wireless Inc.,att"; @@ -673,7 +674,7 @@ void MccMncTable::createTable() { m_mTable[784][2144] = "us,United States,1,Texas RSA 15B2 Limited Partnership,"; m_mTable[784][2160] = "us,United States,1,Kaplan Telephone Company Inc.,"; m_mTable[784][2176] = "us,United States,1,,"; - m_mTable[784][2192] = "us,United States,1,Verizon Wireless,"; + m_mTable[784][2192] = "us,United States,1,Verizon Wireless,vz"; m_mTable[784][2304] = "us,United States,1,Cable & Communications Corp.,"; m_mTable[784][2320] = "us,United States,1,Verizon Wireless,"; m_mTable[784][2336] = "us,United States,1,Get Mobile Inc.,"; @@ -707,7 +708,7 @@ void MccMncTable::createTable() { m_mTable[785][576] = "us,United States,1,,"; m_mTable[785][592] = "gu,Guam,1671,Wave Runner LLC,"; m_mTable[785][608] = "us,United States,1,SLO Cellular Inc / Cellular One of San Luis,"; - m_mTable[785][624] = "us,United States,1,Verizon Wireless,"; + m_mTable[785][624] = "us,United States,1,Verizon Wireless,vz"; m_mTable[785][625] = "us,United States,1,Verizon Wireless,"; m_mTable[785][626] = "us,United States,1,Verizon Wireless,"; m_mTable[785][627] = "us,United States,1,Verizon Wireless,"; @@ -741,7 +742,7 @@ void MccMncTable::createTable() { m_mTable[785][1072] = "us,United States,1,RSA 1 Limited Partnership,"; m_mTable[785][1088] = "us,United States,1,Bluegrass Wireless LLC,"; m_mTable[785][1120] = "us,United States,1,Fisher Wireless Services Inc.,"; - m_mTable[785][1152] = "us,United States,1,Verizon Wireless,"; + m_mTable[785][1152] = "us,United States,1,Verizon Wireless,vz"; m_mTable[785][1153] = "us,United States,1,Verizon Wireless,"; m_mTable[785][1154] = "us,United States,1,Verizon Wireless,"; m_mTable[785][1155] = "us,United States,1,Verizon Wireless,"; @@ -790,6 +791,7 @@ void MccMncTable::createTable() { m_mTable[786][1328] = "us,United States,1,Sprint Spectrum,"; m_mTable[786][1648] = "us,United States,1,AT&T Wireless Inc.,att-first"; m_mTable[786][1664] = "us,United States,1,AT&T Wireless Inc.,att"; + m_mTable[786][1904] = "us,United States,1,Verizon Wireless,vz"; m_mTable[787][256] = "us,United States,1,FirstNet,att-first"; m_mTable[787][272] = "us,United States,1,FirstNet,att-first"; m_mTable[787][288] = "us,United States,1,FirstNet,att-first"; diff --git a/src/MTS_IO_QuectelRadio.cpp b/src/MTS_IO_QuectelRadio.cpp index ae6200e..3a5924c 100644 --- a/src/MTS_IO_QuectelRadio.cpp +++ b/src/MTS_IO_QuectelRadio.cpp @@ -1627,4 +1627,48 @@ ICellularRadio::CODE QuectelRadio::setRxDiversity(const Json::Value& jArgs) { } return SUCCESS; -}
\ No newline at end of file +} + +const std::vector<std::string>& QuectelRadio::getDiagCommands(bool) { + // Declare as static to initialize only when used, but cache the results. + const static std::vector<std::string> vCommands { + // Radio model and firmware: + "AT+CGMI", "AT+CGMM", "AT+CGMR", "AT+QGMR", + + // Current operator profile on the radio side: + "AT+QMBNCFG=\"SELECT\"", "AT+CGSN", + + // SIM card information: + "AT+QSIMSTAT?", "AT+QCCID", "AT+CPIN?", "AT+QPINC=\"SC\"", + + // Operating mode of the radio: + "AT+CFUN?", + + // Cellular Mode (RAT selection): + "AT+QCFG=\"nwscanseq\"", "AT+QCFG=\"nwscanmode\"", + + // Cellular Diversity configuration: + "AT+QCFG=\"divctl\",\"lte\"", "AT+QCFG=\"divctl\",\"wcdma\"", "AT+QCFG=\"diversity\"", + + // Voice call support (AT&T, T-Mobile): + "AT+QNVFR=\"/nv/item_files/ims/IMS_enable\"", + "AT+QNVFR=\"/nv/item_files/modem/mmode/sms_only\"", + "AT+QNVR=5280,0", + + // UE Mode of Operation (CEMODE; AT&T): + "AT+QCFG=\"servicedomain\"", + "AT+QNVFR=\"/nv/item_files/modem/mmode/ue_usage_setting\"", + + // Data connection configuration: + "AT+CGDCONT?", "AT+QICSGP=1", "AT+QICSGP=2", "AT+QICSGP=3", + + // Registration and connection to the tower: + "AT+CIND?", "AT+CSQ", "AT+COPS?", "AT+CREG?", "AT+CGREG?", "AT+CEREG?", + "AT+QENG=\"servingcell\"", + + // Data connection status: + "AT+CGACT?", "AT+CGCONTRDP=1", "AT+CGCONTRDP=2", "AT+CGCONTRDP=3" + }; + + return vCommands; +} diff --git a/src/MTS_IO_TelitRadio.cpp b/src/MTS_IO_TelitRadio.cpp index 5db2ddf..4a0a8b2 100644 --- a/src/MTS_IO_TelitRadio.cpp +++ b/src/MTS_IO_TelitRadio.cpp @@ -325,7 +325,7 @@ ICellularRadio::CODE TelitRadio::getNetworkStatus(Json::Value& jData) { printTrace("%s| Network Status:\n%s\n", getName().c_str(), jData.toStyledString().c_str()); return SUCCESS; //return SUCCESS because getCommonNetworkStats() succeeded at top of this function } - if (sResult.find("SIM PIN") != std::string::npos) { + if (sResult.find("SIM PIN") != std::string::npos || sResult.find("SIM PUK") != std::string::npos) { printError("%s| The SIM is locked and must first be unlocked", getName().c_str()); printTrace("%s| Network Status:\n%s\n", getName().c_str(), jData.toStyledString().c_str()); return SUCCESS; //return SUCCESS because getCommonNetworkStats() succeeded at top of this function @@ -1179,3 +1179,35 @@ bool MTS::IO::TelitRadio::isContainsSignChar(const std::string& str) { return true; } + +const std::vector<std::string>& TelitRadio::getDiagCommands(bool) { + // Declare as static to initialize only when used, but cache the results. + const static std::vector<std::string> vCommands { + // Radio model and firmware: + "AT+CGMI", "AT+CGMM", "AT+CGMR", "AT#SWPKGV", "AT#CFVR", + + // Current operator profile on the radio side: + "AT#FWSWITCH?", "AT+CGSN", + + // SIM card information: + "AT#SIMDET?", "AT#CCID", "AT+CPIN?", "AT#PCT", + + // Operating mode of the radio: + "AT+CFUN?", + + // Low-level network settings: + "AT+WS46?", "AT#RXDIV", "AT#CALLDISA?", "AT+CEMODE?", + + // Data connection configuration: + "AT+CGDCONT?", "AT#PDPAUTH?", + + // Registration and connection to the tower: + "AT+CIND?", "AT+CSQ", "AT+COPS?", "AT+CREG?", "AT+CGREG?", "AT+CEREG?", + "AT#RFSTS", "AT#PSNT?", "AT#MONI", + + // Data connection status: + "AT+CGACT?", "AT+CGCONTRDP=1", "AT+CGCONTRDP=2", "AT+CGCONTRDP=3" + }; + + return vCommands; +} |