From 28b673dd4db086f1957c5cdae281f54980715e36 Mon Sep 17 00:00:00 2001 From: Mykola Salomatin Date: Wed, 29 Sep 2021 16:20:21 +0300 Subject: [MTX-4206] mPower R.6.0: Making Telit and Quectel radios data-only on AT&T network. GP-1364 Add 2 functions for Telit and Quectel modems: - disableVoiceSupport: disable voice support (IMS and CSFB) and enable SMS only registration flag. - getVoiceSupport: get voice support configuration for the current radio. --- src/MTS_IO_CellularRadio.cpp | 54 +++++++++++++++++++++++++ src/MTS_IO_ICellularRadio.cpp | 2 + src/MTS_IO_LE910C4NFRadio.cpp | 76 +++++++++++++++++++++++++++++++++++ src/MTS_IO_QuectelRadio.cpp | 92 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 224 insertions(+) (limited to 'src') diff --git a/src/MTS_IO_CellularRadio.cpp b/src/MTS_IO_CellularRadio.cpp index 1850a60..6236c3f 100644 --- a/src/MTS_IO_CellularRadio.cpp +++ b/src/MTS_IO_CellularRadio.cpp @@ -1609,3 +1609,57 @@ ICellularRadio::CODE CellularRadio::getUeModeOfOperation(ICellularRadio::UE_MODE mode = ICellularRadio::UE_MODES_OF_OPERATION::UNKNOWN_MODE; return NOT_APPLICABLE; } + +ICellularRadio::CODE CellularRadio::disableVoiceSupport() { + printTrace("%s| Disable Voice Support: not applicable", m_sName.c_str()); + return NOT_APPLICABLE; +} + +ICellularRadio::CODE CellularRadio::getVoiceSupport(Json::Value& jData) { + bool bVoiceEnabled, bSmsOnly; + CODE rc; + + rc = getVoiceSupport(bVoiceEnabled, bSmsOnly); + + if (rc == SUCCESS) { + jData[KEY_VOICE_ENABLED] = bVoiceEnabled; + jData[KEY_SMS_ONLY] = bSmsOnly; + } + + return rc; +} + +ICellularRadio::CODE CellularRadio::getVoiceSupport(bool&, bool&) { + printTrace("%s| Get Voice Support: not applicable", m_sName.c_str()); + return NOT_APPLICABLE; +} + +ICellularRadio::CODE CellularRadio::sendBasicQuery(const std::string& sCmd, const std::string& sLabel, std::string& sResult, int32_t iTimeoutMillis, const char& ESC) { + sResult = sendCommand(sCmd, DEFAULT_BAIL_STRINGS, iTimeoutMillis, ESC); + printTrace("%s| Got response from the radio: [%s]", getName().c_str(), sResult.c_str()); + + if (sResult.empty()) { + return NO_RESPONSE; + } + + if (sResult.rfind(ICellularRadio::RSP_ERROR) != std::string::npos) { + return ERROR; + } + + size_t end = sResult.rfind(ICellularRadio::RSP_OK); + if (end == std::string::npos) { + printError("%s| \"OK\" not found in the response: [%s]", getName().c_str(), sResult.c_str()); + return FAILURE; + } + + size_t start = sResult.find(sLabel); + if (start == std::string::npos) { + printError("%s| Unexpected radio response: [%s]", getName().c_str(), sResult.c_str()); + return FAILURE; + } + + start += sLabel.length(); + sResult = MTS::Text::trim(sResult.substr(start, end-start)); + + return SUCCESS; +} diff --git a/src/MTS_IO_ICellularRadio.cpp b/src/MTS_IO_ICellularRadio.cpp index 0a33b59..cfb6811 100644 --- a/src/MTS_IO_ICellularRadio.cpp +++ b/src/MTS_IO_ICellularRadio.cpp @@ -54,6 +54,8 @@ const char *MTS::IO::ICellularRadio::KEY_SUPPORTED_CELL_MODES = "supportedCellul const char *MTS::IO::ICellularRadio::KEY_SIM_CARRIER_CODE = "simCarrierCode"; //!< Unique carrier identifier based on the SIM card information. const char *MTS::IO::ICellularRadio::KEY_SIM_MCC = "simMcc"; //!< MCC of the home network from the SIM. const char *MTS::IO::ICellularRadio::KEY_SIM_MNC = "simMnc"; //!< MNC of the home network from the SIM. +const char *MTS::IO::ICellularRadio::KEY_VOICE_ENABLED = "voiceEnabled"; //!< Enable/Disable support of voice calls +const char *MTS::IO::ICellularRadio::KEY_SMS_ONLY = "smsOnly"; //!< Enable/Disable "SMS only" registration flag //Dynamic Data const char *MTS::IO::ICellularRadio::KEY_ROAMING = "roaming"; //!< Indicates whether or not using Home Network const char *MTS::IO::ICellularRadio::KEY_DATETIME = "datetime"; //!< Date and Time from tower diff --git a/src/MTS_IO_LE910C4NFRadio.cpp b/src/MTS_IO_LE910C4NFRadio.cpp index 770a2c4..0f7bb92 100644 --- a/src/MTS_IO_LE910C4NFRadio.cpp +++ b/src/MTS_IO_LE910C4NFRadio.cpp @@ -128,3 +128,79 @@ CellularRadio::CODE LE910C4NFRadio::getActiveFirmware(std::string& sFwId) { TelitRadio::FOTA_GROUP LE910C4NFRadio::getFotaGroup() { return VALUE_GROUP_B; } + +CellularRadio::CODE LE910C4NFRadio::getIsVoiceSupportConfigurable() { + CellularRadio::CODE rc; + const std::string sCommand = "AT#CALLDISA=?"; + + rc = sendBasicCommand(sCommand); + if (rc == ERROR) { + printTrace("%s| This radio does not support voice call enable/disable", getName().c_str()); + return NOT_APPLICABLE; + } + + return rc; +} + +CellularRadio::CODE LE910C4NFRadio::disableVoiceSupport() { + printTrace("%s| Disable Voice Support", getName().c_str()); + + CellularRadio::CODE rc; + + rc = getIsVoiceSupportConfigurable(); + if (rc != SUCCESS) { + return rc; + } + + const int dTimeout = 1000; // ms + const std::string sCommand = "AT#CALLDISA=1,1"; + + return sendBasicCommand(sCommand, dTimeout); +} + +CellularRadio::CODE LE910C4NFRadio::getVoiceSupport(bool& bVoiceEnabled, bool& bSmsOnly) { + printTrace("%s| Get Voice Support", getName().c_str()); + + CellularRadio::CODE rc; + + bVoiceEnabled = false; + bSmsOnly = false; + + rc = getIsVoiceSupportConfigurable(); + if (rc != SUCCESS) { + return rc; + } + + const int dTimeout = 1000; // ms + const std::string sCommand = "AT#CALLDISA?"; + const std::string sLabel = "#CALLDISA: "; + std::string sResult; + + rc = sendBasicQuery(sCommand, sLabel, sResult, dTimeout); + if (rc != SUCCESS) { + return rc; + } + + std::vector vParts = MTS::Text::split(sResult, ','); + if (vParts.size() != 2) { + printError("Unexpected number of parameters in response [%s]", sResult.c_str()); + return FAILURE; + } + + /* + * vParts[0] - value indicating that "voice support" is enabled. + * Valid parameters: + * 0 - Enable voice support + * 1 - Disable voice support + * 2 - Disable voice support (same as 1) + * + * vParts[1] - value indicating that "SMS only" registration flag is enabled. + * Valid parameters: + * 0 - Disable "SMS only" registration flag + * 1 - Enable "SMS only" registration flag + */ + bVoiceEnabled = (vParts[0] == "0"); + bSmsOnly = (vParts[1] == "1"); + + return SUCCESS; +} diff --git a/src/MTS_IO_QuectelRadio.cpp b/src/MTS_IO_QuectelRadio.cpp index b6eab80..7a1a1a7 100644 --- a/src/MTS_IO_QuectelRadio.cpp +++ b/src/MTS_IO_QuectelRadio.cpp @@ -37,6 +37,7 @@ const std::string QuectelRadio::CMD_ABORT_UPLOAD = "+++"; // It is strongly recommended to use DOS 8.3 file name format for . const std::string QuectelRadio::VALUE_MTS_DELTA_NAME = "mtsdelta.zip"; const std::string QuectelRadio::VALUE_MTS_DELTA_PATH = "/data/ufs/" + QuectelRadio::VALUE_MTS_DELTA_NAME; +const std::string QuectelRadio::VALUE_QNVR_DISABLE_VOICE = "0102000000000000"; QuectelRadio::QuectelRadio(const std::string& sName, const std::string& sRadioPort) : CellularRadio (sName, sRadioPort) @@ -1376,3 +1377,94 @@ ICellularRadio::CODE QuectelRadio::getUeModeOfOperation(ICellularRadio::UE_MODES mode = ICellularRadio::UE_MODES_OF_OPERATION::UNKNOWN_MODE; return FAILURE; } + +ICellularRadio::CODE QuectelRadio::disableVoiceSupport() { + printTrace("%s| Disable Voice Support", getName().c_str()); + + CODE rc; + const int dTimeout = 1000; // ms + std::string sCommand = "AT+QNVFW=\"/nv/item_files/ims/IMS_enable\",00"; + + rc = sendBasicCommand(sCommand, dTimeout); + if (rc != SUCCESS) { + printError("%s| Failed to disable IMS support: [%d]", getName().c_str(), rc); + return rc; + } + + sCommand = "AT+QNVW=5280,0,\"0102000000000000\""; + + rc = sendBasicCommand(sCommand, dTimeout); + if (rc != SUCCESS) { + printError("%s| Failed to disable voice support via +QNVW=5280,0: [%d]", getName().c_str(), rc); + return rc; + } + + sCommand = "AT+QNVFW=\"/nv/item_files/modem/mmode/sms_only\",01"; + + rc = sendBasicCommand(sCommand, dTimeout); + if (rc != SUCCESS) { + printError("%s| Failed to enable \"SMS only\" registration flag: [%d]", getName().c_str(), rc); + return rc; + } + + return SUCCESS; +} + +ICellularRadio::CODE QuectelRadio::getVoiceSupport(bool& bVoiceEnabled, bool& bSmsOnly) { + printTrace("%s| Get Voice Support status", getName().c_str()); + + CODE rc; + + bool bImsEnabled = false; + const int dTimeout = 1000; // ms + + std::string sResult; + std::string sCommand; + std::string sLabel; + + bVoiceEnabled = false; + bSmsOnly = false; + + printTrace("%s| Get IP Multimedia Subsystem status", getName().c_str()); + sCommand = "AT+QNVFR=\"/nv/item_files/ims/IMS_enable\""; + sLabel = "+QNVFR: "; + + rc = sendBasicQuery(sCommand, sLabel, sResult, dTimeout); + if (rc != SUCCESS) { + return rc; + } + + if (sResult != "00") { + bImsEnabled = true; + } + + printTrace("%s| Get +QNVR=5280,0 status", getName().c_str()); + sCommand = "AT+QNVR=5280,0"; + sLabel = "+QNVR: "; + + rc = sendBasicQuery(sCommand, sLabel, sResult, dTimeout); + if (rc != SUCCESS) { + return rc; + } + + sResult = MTS::Text::strip(sResult, '"'); + + if (bImsEnabled || sResult != VALUE_QNVR_DISABLE_VOICE) { + bVoiceEnabled = true; + } + + printTrace("%s| Get \"SMS only\" registration status", getName().c_str()); + sCommand = "AT+QNVFR=\"/nv/item_files/modem/mmode/sms_only\""; + sLabel = "+QNVFR: "; + + rc = sendBasicQuery(sCommand, sLabel, sResult, dTimeout); + if (rc != SUCCESS) { + return rc; + } + + if (sResult == "01") { + bSmsOnly = true; + } + + return SUCCESS; +} -- cgit v1.2.3 From 1f7987d546384b6b9ef0079dac5c903148a59210 Mon Sep 17 00:00:00 2001 From: "andrii.davydenko" Date: Tue, 16 Nov 2021 11:51:32 +0200 Subject: Update MODBUS slave feature, Rogers Certification issue --- src/MTS_IO_CellularRadio.cpp | 122 +++++++++++++++++++++++++++++++++++----- src/MTS_IO_LE910EUGRadio.cpp | 2 +- src/MTS_IO_LE910NAGRadio.cpp | 2 +- src/MTS_IO_LE910SVGRadio.cpp | 1 + src/MTS_IO_MccMncTable.cpp | 10 ++-- src/MTS_IO_QuectelRadio.cpp | 60 ++++++++++++++++++++ src/MTS_IO_SerialConnection.cpp | 4 ++ src/MTS_IO_TelitRadio.cpp | 108 +++++++++++++++++++++++++++++++++-- 8 files changed, 282 insertions(+), 27 deletions(-) (limited to 'src') diff --git a/src/MTS_IO_CellularRadio.cpp b/src/MTS_IO_CellularRadio.cpp index 6236c3f..afdfc1e 100644 --- a/src/MTS_IO_CellularRadio.cpp +++ b/src/MTS_IO_CellularRadio.cpp @@ -147,7 +147,9 @@ bool CellularRadio::resetConnection(uint32_t iTimeoutMillis) { } else { printInfo("%s| Successfully re-opened radio port [%s]", m_sName.c_str(), m_sRadioPort.c_str()); printDebug("%s| Recovering 'echo' after connection reset", m_sName.c_str()); // see CellularRadio::initialize - setEcho(m_bEchoEnabled); + if (setEcho(m_bEchoEnabled) != SUCCESS) { + printWarning("%s| Failed to recover 'echo' after connection reset", m_sName.c_str()); + } break; } @@ -425,26 +427,110 @@ ICellularRadio::CODE CellularRadio::getType(std::string& sType) { ICellularRadio::CODE CellularRadio::getCarrier(std::string& sCarrier) { printTrace("%s| Get Carrier", m_sName.c_str()); - if (m_sCarrier == "") { - std::string sMcc; - std::string sMnc; - if (getSimMccMnc(sMcc, sMnc) == CODE::SUCCESS) { - Json::Value jLookup = MccMncTable::getInstance()->lookup(sMcc, sMnc); - printTrace("%s| MCC-MNC Lookup: [%s][%s][%s]", m_sName.c_str(), - sMcc.c_str(), sMnc.c_str(), jLookup.toStyledString().c_str()); - if (jLookup.isMember(ICellularRadio::KEY_CARRIER)) { - m_sCarrier = jLookup[ICellularRadio::KEY_CARRIER].asString(); - } else { - printWarning("%s| MCC-MNC Lookup did not contain carrier", m_sName.c_str()); - return FAILURE; + + CODE rc = SUCCESS; + std::string t_sCarrier; + + do { + if (m_sCarrier == "") { + rc = getCarrierFromSimSpn(t_sCarrier); + if (rc == SUCCESS) { + m_sCarrier = t_sCarrier; + break; + } + + rc = getCarrierFromSimMccMnc(t_sCarrier); + if (rc == SUCCESS) { + m_sCarrier = t_sCarrier; + break; } + } + } while (false); + + sCarrier = m_sCarrier; + return rc; +} + +ICellularRadio::CODE CellularRadio::getCarrierFromSimMccMnc(std::string& sCarrier) { + printTrace("%s| Get Carrier from SIM MCC/MNC", m_sName.c_str()); + + std::string sMcc; + std::string sMnc; + + CODE rc; + + rc = getSimMccMnc(sMcc, sMnc); + if (rc == SUCCESS) { + Json::Value jLookup = MccMncTable::getInstance()->lookup(sMcc, sMnc); + printTrace("%s| MCC-MNC Lookup: [%s][%s][%s]", m_sName.c_str(), + sMcc.c_str(), sMnc.c_str(), jLookup.toStyledString().c_str()); + if (jLookup.isMember(ICellularRadio::KEY_CARRIER)) { + sCarrier = jLookup[ICellularRadio::KEY_CARRIER].asString(); } else { - printWarning("%s| SIM did no contain MCC or MNC", m_sName.c_str()); + printWarning("%s| MCC-MNC Lookup does not contain the carrier", m_sName.c_str()); return FAILURE; } + } else { + printWarning("%s| SIM did no contain MCC or MNC", m_sName.c_str()); + return rc; + } + + return SUCCESS; +} + +ICellularRadio::CODE CellularRadio::getCarrierFromSimSpn(std::string& sCarrier) { + printTrace("%s| Get Carrier from SIM SPN", m_sName.c_str()); + + const int iEfspnId = 0x6F46; + const uint8_t iOffsetHigh = 1; + const uint8_t iOffsetLow = 0; + const uint8_t iNumBytes = 16; + + CODE rc; + std::string sEFspnContent; + + rc = simAccessReadBinary(iEfspnId, iOffsetLow, iOffsetHigh, iNumBytes, sEFspnContent); + if (rc != SUCCESS) { + printError("%s| Failed to determine the service provider name", m_sName.c_str()); + return rc; + } + + if (sEFspnContent.length() != 32) { + printError("%s| Invalid length of the service provider name: expected [32], actual: [%d]", m_sName.c_str(), sEFspnContent.length()); + return FAILURE; + } + + uint8_t iSpnPart; + + for (size_t i = 0; i < sEFspnContent.length(); i += 2) { + std::string sPart = sEFspnContent.substr(i, 2); + + // parse hex to unsigned byte + if (!MTS::Text::parseHex(iSpnPart, sPart)) { + printError("%s| Unexpected SIM EFspn content: [%s]", m_sName.c_str(), sEFspnContent.c_str()); + return FAILURE; + } + + // skip 0xFF bytes + if (iSpnPart == 0xFF) { + continue; + } + + sCarrier.push_back(iSpnPart); + } + + /** + * Example of radio response when SIM card does not contain the service provider name: + * Raw response from the radio: [ + * +CRSM: 144,0,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + * OK + * ] + */ + if (sCarrier.empty()) { + printError("%s| SIM EFspn does not contain the service provider name", m_sName.c_str()); + return FAILURE; } - sCarrier = m_sCarrier; return SUCCESS; } @@ -1663,3 +1749,9 @@ ICellularRadio::CODE CellularRadio::sendBasicQuery(const std::string& sCmd, cons return SUCCESS; } + +ICellularRadio::CODE CellularRadio::getSelectedBandsRaw(std::string& sRawBands) +{ + printTrace("%s| Acquiring selected bands: not applicable", m_sName.c_str()); + return NOT_APPLICABLE; +} diff --git a/src/MTS_IO_LE910EUGRadio.cpp b/src/MTS_IO_LE910EUGRadio.cpp index 9e970b3..1906815 100644 --- a/src/MTS_IO_LE910EUGRadio.cpp +++ b/src/MTS_IO_LE910EUGRadio.cpp @@ -27,7 +27,7 @@ A more elaborate description */ - +#include #include using namespace MTS::IO; diff --git a/src/MTS_IO_LE910NAGRadio.cpp b/src/MTS_IO_LE910NAGRadio.cpp index 602466f..73a1d08 100644 --- a/src/MTS_IO_LE910NAGRadio.cpp +++ b/src/MTS_IO_LE910NAGRadio.cpp @@ -27,6 +27,7 @@ A more elaborate description */ +#include #include using namespace MTS::IO; @@ -38,4 +39,3 @@ LE910NAGRadio::LE910NAGRadio(const std::string& sPort) { } - diff --git a/src/MTS_IO_LE910SVGRadio.cpp b/src/MTS_IO_LE910SVGRadio.cpp index a43165a..431b9c2 100644 --- a/src/MTS_IO_LE910SVGRadio.cpp +++ b/src/MTS_IO_LE910SVGRadio.cpp @@ -27,6 +27,7 @@ A more elaborate description */ +#include #include using namespace MTS::IO; diff --git a/src/MTS_IO_MccMncTable.cpp b/src/MTS_IO_MccMncTable.cpp index 054a6fa..97f92ab 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-05-27 + \date 2021-11-05 \author sgodinez An Auto-Generated MCC-MNC Lookup Table @@ -543,10 +543,10 @@ void MccMncTable::createTable() { m_mTable[663][47] = "me,Montenegro,382,Monet/T-mobile,"; m_mTable[663][63] = "me,Montenegro,382,Mtel,"; m_mTable[770][544] = "ca,Canada,1,Telus Mobility,"; - m_mTable[770][800] = "ca,Canada,1,mobilicity,"; + m_mTable[770][800] = "ca,Canada,1,Mobilicity,"; m_mTable[770][864] = "ca,Canada,1,Clearnet,"; m_mTable[770][865] = "ca,Canada,1,Clearnet,"; - m_mTable[770][880] = "ca,Canada,1,FIDO (Rogers AT&T/ Microcell),"; + m_mTable[770][880] = "ca,Canada,1,Fido,"; m_mTable[770][896] = "ca,Canada,1,DMTS Mobility,"; m_mTable[770][1168] = "ca,Canada,1,WIND,"; m_mTable[770][1280] = "ca,Canada,1,Videotron,"; @@ -567,8 +567,10 @@ void MccMncTable::createTable() { m_mTable[770][1794] = "ca,Canada,1,MT&T Mobility,"; m_mTable[770][1795] = "ca,Canada,1,New Tel Mobility,"; m_mTable[770][1808] = "ca,Canada,1,Globalstar Canada,"; - m_mTable[770][1824] = "ca,Canada,1,Rogers AT&T Wireless,"; + m_mTable[770][1824] = "ca,Canada,1,Rogers Wireless,"; + m_mTable[770][1825] = "ca,Canada,1,Rogers Wireless,"; m_mTable[770][1888] = "ca,Canada,1,Public Mobile,"; + m_mTable[770][2080] = "ca,Canada,1,Rogers Wireless,"; m_mTable[776][31] = "pm,St. Pierre & Miquelon,508,Ameris,"; m_mTable[784][3] = "us,United States,1,Unknown,"; m_mTable[784][4] = "us,United States,1,Verizon Wireless,"; diff --git a/src/MTS_IO_QuectelRadio.cpp b/src/MTS_IO_QuectelRadio.cpp index 7a1a1a7..b1e1e59 100644 --- a/src/MTS_IO_QuectelRadio.cpp +++ b/src/MTS_IO_QuectelRadio.cpp @@ -1468,3 +1468,63 @@ ICellularRadio::CODE QuectelRadio::getVoiceSupport(bool& bVoiceEnabled, bool& bS return SUCCESS; } + +ICellularRadio::CODE QuectelRadio::getSelectedBandsRaw(std::string& sRawBands) { + printTrace("%s| Acquiring selected bands", getName().c_str()); + CODE rc; + + const std::string sCommand = "AT+QCFG=\"band\""; + const std::string sLabel = "+QCFG: \"band\","; + const int dTimeout = 1000; + std::string sResult; + + rc = sendBasicQuery(sCommand, sLabel, sResult, dTimeout); + if (rc != SUCCESS) { + return rc; + } + + std::vector vParts = MTS::Text::split(sResult, ','); + uint8_t iNumBandParams = 0; + + + if (vParts.size() > 0) { + uint16_t iSelectedBands = 0; + // Duplicate the value to the first two fields + // contains information for both the GSM and WCDMA bands + if (!isContainsSignChar(vParts[0]) && MTS::Text::parseHex(iSelectedBands, MTS::Text::trim(vParts[0])) ) { + sRawBands = MTS::Text::formatHex(iSelectedBands) + "," + MTS::Text::formatHex(iSelectedBands); + iNumBandParams++; + } else { + printWarning("%s| Error during parse number from string: [%s]. Assuming that no GSM and WCDMA bands selected", getName().c_str(), vParts[0].c_str()); + sRawBands = "ffff,ffff"; + } + } else { + sRawBands = "ffff,ffff"; + } + + if (vParts.size() > 1) { + uint64_t iSelectedBands = 0; + if (!isContainsSignChar(vParts[1]) && MTS::Text::parseHex(iSelectedBands, MTS::Text::trim(vParts[1]))) { + sRawBands += "," + MTS::Text::formatHex(iSelectedBands); // LTE bands + iNumBandParams++; + } else { + printWarning("%s| Error during parse number from string: [%s]. Assuming that no LTE bands selected", getName().c_str(), vParts[0].c_str()); + sRawBands += ",ffffffffffffffff"; + } + } else { + sRawBands += ",ffffffffffffffff"; + } + + // All other fragments - ignored for now. + + // Return success if at least one band param was extracted; otherwise failure + return (iNumBandParams > 0) ? SUCCESS : FAILURE; +} + +bool MTS::IO::QuectelRadio::isContainsSignChar(const std::string& str) { + if (str.find_first_of("+-") == std::string::npos) { + return false; + } + + return true; +} diff --git a/src/MTS_IO_SerialConnection.cpp b/src/MTS_IO_SerialConnection.cpp index 936d28d..d13c565 100644 --- a/src/MTS_IO_SerialConnection.cpp +++ b/src/MTS_IO_SerialConnection.cpp @@ -546,6 +546,10 @@ int SerialConnection::doRead(char* pBuffer, const uint32_t& iSize, int32_t& time } else { if (FD_ISSET(h, &readfs)) { result = ::read(h, pBuffer, iSize); + if (result == 0) { + printTrace("SERIAL| serial port [%s] disconnected", m_sPortName.c_str()); + result = -1; + } } else { //socket closed? result = -1; diff --git a/src/MTS_IO_TelitRadio.cpp b/src/MTS_IO_TelitRadio.cpp index 1f5f4cf..5db2ddf 100644 --- a/src/MTS_IO_TelitRadio.cpp +++ b/src/MTS_IO_TelitRadio.cpp @@ -23,6 +23,7 @@ #include #include #include +#include #include @@ -1013,8 +1014,11 @@ ICellularRadio::CODE TelitRadio::abortFotaWriteABD() { } ICellularRadio::CODE TelitRadio::fumoWaitUpgradeFinished(ICellularRadio::UpdateCb& stepCb) { - const uint32_t duAttachTimeout = 6 * 60 * 1000;// wait for 6 minutes for the radio to attach - const uint32_t duUrcTimeout = 60 * 1000; // wait for 1 minutes for the next URC message + const uint32_t duFirstAttachTimeout = 6 * 60 * 1000; // wait for 6 minutes for the radio to attach + const uint32_t duSecondAttachTimeout = 60 * 1000; // wait for 1 minute for the radio to attach + const uint32_t duThirdAttachTimeout = 5 * 1000; // wait for 5 seconds for the radio to attach + const uint32_t duUrcTimeout = 60 * 1000; // wait for 1 minutes for the next URC message + const uint32_t timeoutMillis = 30 * 60 * 1000; // wait for 30 minutes in case if radio will send invalid message (garbage) const std::string sFotaUrcPrefix = "#OTAEV:"; // prefix for the URC notification messages const std::string sFotaUrcEndSuccess = "Module Upgraded To New Fw"; const std::string sFotaUrcEndFailed = "OTA Fw Upgrade Failed"; @@ -1024,17 +1028,32 @@ ICellularRadio::CODE TelitRadio::fumoWaitUpgradeFinished(ICellularRadio::UpdateC std::string sResponse; // It's now detached. Try to reconnect - if (!resetConnection(duAttachTimeout)) { - printError("Can't connect to the radio in %d ms", (duAttachTimeout)); + if (!resetConnection(duFirstAttachTimeout)) { + printError("Can't connect to the radio in %d ms", (duFirstAttachTimeout)); callNextStep(stepCb, "FUMO Error: unable to obtain radio after reset"); return ERROR; } - while (true) { + Timer timer; + timer.start(); - sResponse = sendCommand("", vFotaBailStrings, duUrcTimeout, 0x00); + while (timer.getMillis() <= (uint64_t)timeoutMillis) { + + sResponse = waitResponse(vFotaBailStrings, duUrcTimeout); printTrace("Radio response: [%s]", sResponse.c_str()); + if (sResponse.empty()) { + // Radio detached again. Try to reconnect + if (!resetConnection(duSecondAttachTimeout)) { + printError("Can't connect to the radio in %d ms", (duSecondAttachTimeout)); + callNextStep(stepCb, "FUMO Error: unable to obtain radio after second reset"); + return ERROR; + } + + sResponse = waitResponse(vFotaBailStrings, duUrcTimeout); + printTrace("Radio response: [%s]", sResponse.c_str()); + } + if (sResponse.find(sFotaUrcPrefix) == std::string::npos) { printError("No URC messages from the radio in %d ms", duUrcTimeout); callNextStep(stepCb, "FUMO Error: timeout, radio is not responding"); @@ -1058,6 +1077,13 @@ ICellularRadio::CODE TelitRadio::fumoWaitUpgradeFinished(ICellularRadio::UpdateC } + // Required to set echo to disable, so we performed resetConnection again. + if (!resetConnection(duThirdAttachTimeout)) { + printError("Can't connect to the radio in %d ms", (duThirdAttachTimeout)); + callNextStep(stepCb, "FUMO Error: unable to reset connection to radio"); + return ERROR; + } + return rc; } @@ -1083,3 +1109,73 @@ ICellularRadio::CODE TelitRadio::fumoCheckNewFirmware(ICellularRadio::UpdateCb& return rc; } + +ICellularRadio::CODE TelitRadio::getSelectedBandsRaw(std::string& sRawBands) { + printTrace("%s| Acquiring selected bands", getName().c_str()); + CODE rc; + + const std::string sCommand = "AT#BND?"; + const std::string sLabel = "#BND: "; + const int dTimeout = 1000; + std::string sResult; + + rc = sendBasicQuery(sCommand, sLabel, sResult, dTimeout); + if (rc != SUCCESS) { + return rc; + } + + std::vector vParts = MTS::Text::split(sResult, ','); + uint8_t iNumBandParams = 0; + + if (vParts.size() > 0) { + uint16_t iSelectedBands = 0; + if (!isContainsSignChar(vParts[0]) && MTS::Text::parse(iSelectedBands, MTS::Text::trim(vParts[0]))) { + sRawBands = MTS::Text::formatHex(iSelectedBands); // GSM bands + iNumBandParams++; + } else { + printWarning("%s| Error during parse number from string: [%s]. Assuming that no GSM bands selected", getName().c_str(), vParts[0].c_str()); + sRawBands = "ffff"; + } + } else { + sRawBands = "ffff"; + } + + if (vParts.size() > 1) { + uint16_t iSelectedBands = 0; + if (!isContainsSignChar(vParts[1]) && MTS::Text::parse(iSelectedBands, MTS::Text::trim(vParts[1]))) { + sRawBands += "," + MTS::Text::formatHex(iSelectedBands); // WCDMA bands + iNumBandParams++; + } else { + printWarning("%s| Error during parse number from string: [%s]. Assuming that no WCDMA bands selected", getName().c_str(), vParts[0].c_str()); + sRawBands += ",ffff"; + } + } else { + sRawBands += ",ffff"; + } + + if (vParts.size() > 2) { + uint64_t iSelectedBands = 0; + if (!isContainsSignChar(vParts[2]) && MTS::Text::parseHex(iSelectedBands, MTS::Text::trim(vParts[2]))) { + sRawBands += "," + MTS::Text::formatHex(iSelectedBands); // LTE bands + iNumBandParams++; + } else { + printWarning("%s| Error during parse number from string: [%s]. Assuming that no LTE bands selected", getName().c_str(), vParts[0].c_str()); + sRawBands += ",ffffffffffffffff"; + } + } else { + sRawBands += ",ffffffffffffffff"; + } + + // All other fragments - ignored for now. + + // Return success if at least one band param was extracted; otherwise failure + return (iNumBandParams > 0) ? SUCCESS : FAILURE; +} + +bool MTS::IO::TelitRadio::isContainsSignChar(const std::string& str) { + if (str.find_first_of("+-") == std::string::npos) { + return false; + } + + return true; +} -- cgit v1.2.3 From 733ded9a96c8e9aa13c38dd223b8b585c2801bfd Mon Sep 17 00:00:00 2001 From: Mykola Salomatin Date: Thu, 21 Apr 2022 12:14:57 +0300 Subject: [MTX-4445] mPower R.6.0.X: MTCAP3: LNA7D - cellular radio support GP-1548 Fix LNA7D delta radio firmware upgrade issue (handling double radio reset). --- src/MTS_IO_QuectelRadio.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'src') diff --git a/src/MTS_IO_QuectelRadio.cpp b/src/MTS_IO_QuectelRadio.cpp index b1e1e59..9c5b3d5 100644 --- a/src/MTS_IO_QuectelRadio.cpp +++ b/src/MTS_IO_QuectelRadio.cpp @@ -1044,6 +1044,7 @@ uint16_t QuectelRadio::getQuectelChecksum(const void* data, size_t nBytes) { ICellularRadio::CODE QuectelRadio::fumoWaitUpgradeFinished(ICellularRadio::UpdateCb& stepCb) { const uint32_t duUrcTimeout = 4 * 60 * 1000; // wait for 4 minutes for the next URC message + const uint32_t duAttachTimeout = 30 * 1000; // wait up to 30 seconds for the radio to attach const std::string sFotaUrcPrefix = "+QIND: \"FOTA\""; // prefix for the URC notification messages const std::string sFotaUrcStart = "\"START\""; const std::string sFotaUrcProgress = "\"UPDATING\""; @@ -1058,6 +1059,18 @@ ICellularRadio::CODE QuectelRadio::fumoWaitUpgradeFinished(ICellularRadio::Updat sResponse = waitResponse(vFotaBailStrings, duUrcTimeout); printTrace("Radio response: [%s]", sResponse.c_str()); + if (sResponse.empty()) { + // Radio detached again. Try to reconnect + if (!resetConnection(duAttachTimeout)) { + printError("Can't connect to the radio in %d ms", (duAttachTimeout)); + callNextStep(stepCb, "FUMO Error: unable to obtain radio after second reset"); + return ERROR; + } + + sResponse = waitResponse(vFotaBailStrings, duUrcTimeout); + printTrace("Radio response: [%s]", sResponse.c_str()); + } + if (sResponse.find(sFotaUrcPrefix) == std::string::npos) { printError("No URC messages from the radio in %d ms", duUrcTimeout); callNextStep(stepCb, "FUMO Error: timeout, radio is not responding"); -- cgit v1.2.3 From 47997c0e5aa7d32ddbba22ceead2ff553881c47c Mon Sep 17 00:00:00 2001 From: Mykola Salomatin Date: Wed, 4 May 2022 12:40:15 +0300 Subject: [MTX-4445] mPower R.6.0.X: MTCAP3: LNA7D - cellular radio support GP-1548 setRxDiversity command moved to common class for Quectel radios - QuectelRadio.cpp. Add LNA7D radio support. LNA7D radio supports only 3g and 4g network modes. Add new command for enabling/disabling diversity. Retained backward compatibility with the old diversity command. --- src/MTS_IO_EG25Radio.cpp | 11 ------ src/MTS_IO_EG95Radio.cpp | 24 +++++++----- src/MTS_IO_ICellularRadio.cpp | 3 ++ src/MTS_IO_QuectelRadio.cpp | 87 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 104 insertions(+), 21 deletions(-) (limited to 'src') diff --git a/src/MTS_IO_EG25Radio.cpp b/src/MTS_IO_EG25Radio.cpp index aa5d453..c6d1c34 100644 --- a/src/MTS_IO_EG25Radio.cpp +++ b/src/MTS_IO_EG25Radio.cpp @@ -35,17 +35,6 @@ EG25Radio::~EG25Radio() { } -ICellularRadio::CODE EG25Radio::setRxDiversity(const Json::Value& jArgs) { - /* Command string for EG25 radios: AT+QCFG="diversity",(0-1) */ - if (jArgs["enabled"].asString() != "1" && jArgs["enabled"].asString() != "0") { - return FAILURE; - } - std::string sCmd = "AT+QCFG=\"diversity\","; - sCmd += jArgs["enabled"].asString(); - - return sendBasicCommand(sCmd); -} - ICellularRadio::CODE EG25Radio::getSupportedCellularModes(CELLULAR_MODES &networks) { networks = static_cast(CELLULAR_MODE_2G | CELLULAR_MODE_3G | CELLULAR_MODE_4G); return SUCCESS; diff --git a/src/MTS_IO_EG95Radio.cpp b/src/MTS_IO_EG95Radio.cpp index 296f183..83d6489 100644 --- a/src/MTS_IO_EG95Radio.cpp +++ b/src/MTS_IO_EG95Radio.cpp @@ -19,6 +19,7 @@ */ #include +#include using namespace MTS::IO; @@ -34,18 +35,21 @@ EG95Radio::~EG95Radio() { } -ICellularRadio::CODE EG95Radio::setRxDiversity(const Json::Value& jArgs) { - /* Command string for EG95 radios: AT+QCFG="diversity",(0-1) */ - if (jArgs["enabled"].asString() != "1" && jArgs["enabled"].asString() != "0") { - return FAILURE; +ICellularRadio::CODE EG95Radio::getSupportedCellularModes(CELLULAR_MODES &networks) { + std::string sRadioCode; + ICellularRadio::CODE iCode; + + iCode = convertModelToMtsShortCode(MODEL_NAME, sRadioCode, this); + if (iCode != SUCCESS) { + printError("%s| Failed to obtain radio code: [%d]", getName().c_str(), iCode); + return iCode; } - std::string sCmd = "AT+QCFG=\"diversity\","; - sCmd += jArgs["enabled"].asString(); - return sendBasicCommand(sCmd); -} + if (sRadioCode == "LNA7D") { + networks = static_cast(CELLULAR_MODE_3G | CELLULAR_MODE_4G); + } else { + networks = static_cast(CELLULAR_MODE_2G | CELLULAR_MODE_3G | CELLULAR_MODE_4G); + } -ICellularRadio::CODE EG95Radio::getSupportedCellularModes(CELLULAR_MODES &networks) { - networks = static_cast(CELLULAR_MODE_2G | CELLULAR_MODE_3G | CELLULAR_MODE_4G); return SUCCESS; } \ No newline at end of file diff --git a/src/MTS_IO_ICellularRadio.cpp b/src/MTS_IO_ICellularRadio.cpp index cfb6811..7453662 100644 --- a/src/MTS_IO_ICellularRadio.cpp +++ b/src/MTS_IO_ICellularRadio.cpp @@ -207,6 +207,9 @@ MTS::IO::ICellularRadio::CODE MTS::IO::ICellularRadio::convertModelToMtsShortCod } else if (sValue.find("EG95E") != std::string::npos) { sCode = "LEU7"; eCode = SUCCESS; + } else if (sValue.find("EG95NAXD") != std::string::npos) { + sCode = "LNA7D"; + eCode = SUCCESS; } else if (sValue.find("EG95NA") != std::string::npos) { sCode = "LNA7"; eCode = SUCCESS; diff --git a/src/MTS_IO_QuectelRadio.cpp b/src/MTS_IO_QuectelRadio.cpp index 9c5b3d5..ae6200e 100644 --- a/src/MTS_IO_QuectelRadio.cpp +++ b/src/MTS_IO_QuectelRadio.cpp @@ -1541,3 +1541,90 @@ bool MTS::IO::QuectelRadio::isContainsSignChar(const std::string& str) { return true; } + +ICellularRadio::CODE QuectelRadio::isDivctlSupported(bool& bSupported) { + const std::string sCommand = "AT+QCFG=\"divctl\""; + const std::string sLabel = "+QCFG: \"divctl\","; + const int dTimeout = 1000; // ms + std::string sResult; + + CODE rc; + + rc = sendBasicQuery(sCommand, sLabel, sResult, dTimeout); + if (rc == ERROR) { + bSupported = false; + return SUCCESS; + } else if (rc == SUCCESS) { + if (sResult.find("(\"lte\",\"wcdma\")") != std::string::npos) { + bSupported = true; + } else { + bSupported = false; + } + return rc; + } else { + return rc; + } +} + +ICellularRadio::CODE QuectelRadio::setRxDiversity(const Json::Value& jArgs) { + if (jArgs["enabled"].asString() != "1" && jArgs["enabled"].asString() != "0") { + return FAILURE; + } + + ICellularRadio::CODE rc; + std::string sCmd; + bool bSupported; + + rc = isDivctlSupported(bSupported); + if (rc != SUCCESS) { + printError("%s| Failed to determine the AT+QCFG=\"divctl\" support: [%d]", getName().c_str(), rc); + return rc; + } + + if (!bSupported) { + /* Old command string for EG95 radios: AT+QCFG="diversity",(0-1) */ + sCmd = "AT+QCFG=\"diversity\","; + sCmd += jArgs["enabled"].asString(); + + return sendBasicCommand(sCmd); + } + + std::string sValue; + + /* Reverse obtained value because the new command string works in the following way: + 0 - enable, + 1 - disable, use the main antenna as the only antenna. + 2 - disable, use the diversity antenna as the only antenna. + */ + if (jArgs["enabled"].asString() == "1") { + sValue = "0"; + } else { + sValue = "1"; + } + + /* New command string for EG95 radios: + AT+QCFG=\"divctl\",\"lte\",(0-2) + AT+QCFG=\"divctl\",\"wcdma\",(0-2) + */ + const int dTimeout = 1000; // ms + + sCmd = "AT+QCFG=\"divctl\",\"lte\","; + sCmd += sValue; + + rc = sendBasicCommand(sCmd, dTimeout); + if (rc != SUCCESS) { + printError("%s| Failed to set diversity for LTE network mode: [%d]", getName().c_str(), rc); + return rc; + } + + sCmd = "AT+QCFG=\"divctl\",\"wcdma\","; + sCmd += sValue; + + rc = sendBasicCommand(sCmd, dTimeout); + if (rc != SUCCESS) { + printError("%s| Failed to set diversity for WCDMA network mode: [%d]", getName().c_str(), rc); + return rc; + } + + return SUCCESS; +} \ No newline at end of file -- cgit v1.2.3 From ada73244d5efe687d92b4b97cf555f2ca166f2c2 Mon Sep 17 00:00:00 2001 From: Yevhen Mykhno Date: Tue, 7 Jun 2022 15:40:48 +0300 Subject: [MTX-4503] mPower R.6.0.X: Remove Verizon FOTA feature from the code GP-1610 --- src/MTS_IO_ME910C1WWRadio.cpp | 604 +----------------------------------------- 1 file changed, 1 insertion(+), 603 deletions(-) (limited to 'src') diff --git a/src/MTS_IO_ME910C1WWRadio.cpp b/src/MTS_IO_ME910C1WWRadio.cpp index 80c2320..bf1be00 100644 --- a/src/MTS_IO_ME910C1WWRadio.cpp +++ b/src/MTS_IO_ME910C1WWRadio.cpp @@ -17,27 +17,14 @@ * along with libmts-io. If not, see . * */ -#include #include #include -#include -#include #include using namespace MTS::IO; const std::string ME910C1WWRadio::MODEL_NAME("ME910C1-WW"); -const std::string ME910C1WWRadio::KEY_FUMO_PDPID("pdpid"); // optional (default : "3") -const std::string ME910C1WWRadio::KEY_FUMO_PDPTYPE("pdptype"); // optional (default : "IPV4V6") -const std::string ME910C1WWRadio::KEY_FUMO_APN("apn"); // optional (default : "") -const std::string ME910C1WWRadio::KEY_FUMO_ADDRESS("address"); -const std::string ME910C1WWRadio::KEY_FUMO_DIR("dir"); -const std::string ME910C1WWRadio::KEY_FUMO_FILE("file"); -const std::string ME910C1WWRadio::KEY_FUMO_USER("user"); -const std::string ME910C1WWRadio::KEY_FUMO_PASSWORD("password"); -const std::string ME910C1WWRadio::KEY_FUMO_DRYRUN("dryrun"); - ME910C1WWRadio::ME910C1WWRadio(const std::string& sPort) : ME910Radio(MODEL_NAME, sPort) { @@ -129,593 +116,4 @@ ICellularRadio::CODE ME910C1WWRadio::getActiveFirmware(std::string& sFwId) { } return SUCCESS; -} - -ICellularRadio::CODE ME910C1WWRadio::doGetFirmwareNumbers(std::string &sFirmware, std::string &sFirmwareBuild) { - ICellularRadio::CODE rc = FAILURE; - - rc = getFirmware(sFirmware); - if (rc != SUCCESS){ - return rc; - } - - rc = getFirmwareBuild(sFirmwareBuild); - if (rc != SUCCESS){ - return rc; - } - - return rc; -} - -ICellularRadio::CODE ME910C1WWRadio::doFumoReadConfig(const Json::Value& jArgs, Json::Value &jConfig) { - ICellularRadio::CODE rc = INVALID_ARGS; - std::string sPath; - - do - { - if (!jArgs["config-file"].isString()) { - rc = INVALID_ARGS; - break; - } - - sPath = jArgs["config-file"].asString(); - - std::ifstream file(sPath.c_str()); - if (!file.is_open()) { - printError("Failed to open file [%s]", sPath.c_str()); - break; - } - - file.seekg(0, std::ios::end); - size_t size = file.tellg(); - std::string buffer(size, ' '); - file.seekg(0); - file.read(&buffer[0], size); - file.close(); - -#if defined(JSONCPP_VERSION_HEXA) && (JSONCPP_VERSION_HEXA > 0x010600) // > 1.6.0 - Json::CharReaderBuilder builder; - std::istringstream ss(buffer); - if (!Json::parseFromStream(builder, ss, &jConfig, NULL)) { - printError("Error parsing FOTA configuration file"); - break; - } -#else - Json::Features features = Json::Features::strictMode(); - Json::Reader reader(features); - if (!reader.parse(buffer, jConfig)) { - printError("Error parsing FOTA configuration file"); - break; - } -#endif - - // - // set default values if missing - // - if (!jConfig.isMember(KEY_FUMO_PDPID)) { - jConfig[KEY_FUMO_PDPID] = std::string("3"); - } - - if (!jConfig.isMember(KEY_FUMO_PDPTYPE)) { - jConfig[KEY_FUMO_PDPTYPE] = std::string("IPV4V6"); - } - - if (!jConfig.isMember(KEY_FUMO_APN)) { - jConfig[KEY_FUMO_APN] = std::string(""); - } - - // - // validate - // - if (!jConfig[KEY_FUMO_PDPID].isString()) { - printError("Error loading FOTA configuration: PDP context id is not set"); - break; - } - - if (jConfig[KEY_FUMO_PDPID].asString().empty()) { - printError("Error loading FOTA configuration: context id is empty"); - break; - } - - if (!jConfig[KEY_FUMO_PDPTYPE].isString()) { - printError("Error loading FOTA configuration: PDP type is not set"); - break; - } - - if (jConfig[KEY_FUMO_PDPTYPE].asString().empty()) { - printError("Error loading FOTA configuration: PDP type is empty"); - break; - } - - // Note : allow empty APN - if (!jConfig[KEY_FUMO_APN].isString()) { - printError("Error loading FOTA configuration: APN is not set"); - break; - } - - if (!jConfig[KEY_FUMO_ADDRESS].isString()) { - printError("Error loading FOTA configuration: address is not set"); - break; - } - - if (jConfig[KEY_FUMO_ADDRESS].asString().empty()) { - printError("Error loading FOTA configuration: address is empty"); - break; - } - - // Note: allow empty dir - if (!jConfig[KEY_FUMO_DIR].isString()) { - printError("Error loading FOTA configuration: directory is not set"); - break; - } - - if (!jConfig[KEY_FUMO_FILE].isString()) { - printError("Error loading FOTA configuration: filename is not set"); - break; - } - - if (jConfig[KEY_FUMO_FILE].asString().empty()) { - printError("Error loading FOTA configuration: filename is empty"); - break; - } - - // Note: allow empty username/password - if (!jConfig[KEY_FUMO_USER].isString()) { - printError("Error loading FOTA configuration: username is not set"); - break; - } - - if (!jConfig[KEY_FUMO_PASSWORD].isString()) { - printError("Error loading FOTA configuration: password is not set"); - break; - } - - rc = SUCCESS; - } - while(0); - - return rc; -} - -ICellularRadio::CODE ME910C1WWRadio::doFumoSetup(const Json::Value &jConfig, UpdateCb& stepCb) { - ICellularRadio::CODE rc = FAILURE; - std::string sCmd; - - std::string sContextId = jConfig[KEY_FUMO_PDPID].asString(); - std::string sApn = jConfig[KEY_FUMO_APN].asString(); - std::string sPdpType = jConfig[KEY_FUMO_PDPTYPE].asString(); - - - do - { - // - // Execution command is used to activate or deactivate either the GSM - // context or the specified PDP context. - // - // AT#SGACT=,[,,] - // - sCmd = "AT#SGACT=" + sContextId + ",0"; - rc = sendBasicCommand(sCmd); - if (rc != SUCCESS) { - if(stepCb) { - stepCb(Json::Value("FUMO Error: Failed to deactivate PDP context")); - } - break; - } - - // - // Read current Firmware numbers (let it be after AT#SGACT not to confuse users) - // - rc = doGetFirmwareNumbers(m_sFw, m_sFwBuild); - if (rc != SUCCESS) { - if(stepCb) { - stepCb(Json::Value("FUMO Error: Failed to obtain current firmware version")); - } - break; - } - - // - // Set command specifies PDP context parameter values for a PDP context identified by - // the (local) context identification parameter . - // - // AT+CGDCONT= [[,[,[,[,[,[,[,...[,pdN]]]]]]]]] - // - sCmd = "AT+CGDCONT=" + sContextId + ",\"" + sPdpType + "\""; - if (!sApn.empty()) { - sCmd += ",\"" + sApn + "\""; - } - rc = sendBasicCommand(sCmd, 1000); - if (rc != SUCCESS) { - if(stepCb) { - stepCb(Json::Value("FUMO Error: Failed to setup PDP context")); - } - break; - } - - // - // Set command sets the socket configuration parameters. - // - // AT#SCFG==,,,,, - // - socket connection identifier - // - PDP context identifier - // - packet size to be used by the TCP/UDP/IP stack for data sending. - // - exchange timeout (or socket inactivity timeout); if there’s no - // data exchange within this timeout period the connection is closed (timeout value in seconds). - // - connection timeout; if we can’t establish a connection to the - // remote within this timeout period, an error is raised timeout value in hundreds of milliseconds. - // - data sending timeout; after this period data are sent also if they’re - // less than max packet size (timeout value in hundreds of milliseconds). - // - sCmd = "AT#SCFG=1," + sContextId + ",300,90,600,50"; - rc = sendBasicCommand(sCmd); - if (rc != SUCCESS) { - if(stepCb) { - stepCb(Json::Value("FUMO Error: Failed to set connection configuration parameters")); - } - break; - } - - // - // Activate PDP context - // - sCmd = "AT#SGACT=" + sContextId + ",1"; - rc = sendBasicCommand(sCmd, 60 * 1000); - if (rc != SUCCESS) { - if(stepCb) { - stepCb(Json::Value("FUMO Error: Failed to activate PDP context")); - } - break; - } - } - while (0); - - return rc; -} - -ICellularRadio::CODE ME910C1WWRadio::doFumoFtp(const Json::Value &jConfig, UpdateCb& stepCb) { - ICellularRadio::CODE rc = FAILURE; - std::string sCmd; - std::string sResult; - - // - // Set command sets the time-out used when opening either the FTP control - // channel or the FTP traffic channel. - // - // AT#FTPTO= [] - // - time-out in 100 ms units - // - rc = sendBasicCommand("AT#FTPTO=2400"); - if (rc != SUCCESS) { - if(stepCb) { - stepCb(Json::Value("FUMO Error: Failed to setup connection timeout")); - } - return rc; - } - - // - // Execution command opens an FTP connection toward the FTP server. - // - // AT#FTPOPEN=[,,[,]] - // - sCmd = "AT#FTPOPEN="; - sCmd += "\"" + jConfig[KEY_FUMO_ADDRESS].asString() + "\","; - sCmd += "\"" + jConfig[KEY_FUMO_USER].asString() + "\","; - sCmd += "\"" + jConfig[KEY_FUMO_PASSWORD].asString() + "\",1"; - rc = sendBasicCommand(sCmd, 60 * 1000); - if (rc != SUCCESS) { - if(stepCb) { - stepCb(Json::Value("FUMO Error: Failed to open connection")); - } - return rc; - } - - if (stepCb) { - stepCb(Json::Value("FUMO Info: connection opened")); - } - - do - { - // - // Set command, issued during an FTP connection, sets the file transfer type. - // - // AT#FTPTYPE=[] - // - file transfer type: - // 0 - binary - // 1 - ascii - // - rc = sendBasicCommand("AT#FTPTYPE=0", 1000); - if (rc != SUCCESS) { - if(stepCb) { - stepCb(Json::Value("FUMO Error: failed to set file transfer type")); - } - break; - } - - // - // Execution command, issued during an FTP connection, changes the - // working directory on FTP server. - // - // AT#FTPCWD=[] - // - sCmd = "AT#FTPCWD=\"/"; - if (!jConfig[KEY_FUMO_DIR].asString().empty()) { - sCmd += jConfig[KEY_FUMO_DIR].asString() + "/"; - } - sCmd += "\""; - rc = sendBasicCommand(sCmd, 60 * 1000); - if (rc != SUCCESS) { - if(stepCb) { - stepCb(Json::Value("FUMO Error: failed to change working directory on the server")); - } - break; - } - - if (stepCb) { - stepCb(Json::Value("FUMO Info: downloading the firmware")); - } - - // - // Start FTP transfer - // - sCmd = "AT#FTPGETOTA="; - sCmd += "\"" + jConfig[KEY_FUMO_FILE].asString() + "\",1,1"; - sendBasicCommand(sCmd); - - // - // Noticed that after successful AT#FTPGETOTA the radio resets the connection. - // and the response code (OK, ERROR.. ) not always reach the host. Therefore - // we send the AT#FTPGETOTA with relatively small timeout and then poll with AT - // until we get valid response. After that, using AT#FTPMSG we can check the - // result of the last FTP command (which is AT#FTPGETOTA in our case). - MTS::Timer oTimer; - - oTimer.start(); - - while (oTimer.getSeconds() < (30 * 60)) // 30 min - { - MTS::Thread::sleep(5000); - - rc = sendBasicCommand("AT"); - if (rc == SUCCESS) { - break; - } - - resetConnection(1); - } - oTimer.stop(); - - if (rc != SUCCESS) { - if(stepCb) { - stepCb(Json::Value("FUMO Error: unable to obtain radio after reset")); - } - break; - } - - // - // Now check the FTP status - // - std::string sResult = sendCommand("AT#FTPMSG"); - - printTrace("RADIO| AT#FTPMSG result [%s]", sResult.c_str()); - - if (sResult.find(ICellularRadio::RSP_OK) == std::string::npos) { - rc = FAILURE; - if(stepCb) { - stepCb(Json::Value("FUMO Error: failed to download the firmware file")); - } - break; - } - if (sResult.find("#FTPMSG: 550") != std::string::npos) { - // FTP(550) : File not found - rc = FAILURE; - if(stepCb) { - stepCb(Json::Value("FUMO Error: file not found")); - } - break; - } - if (sResult.find("#FTPMSG: 226") == std::string::npos) { - // FTP(226) : Successfully transferred - rc = FAILURE; - if(stepCb) { - stepCb(Json::Value("FUMO Error: failed to download the firmware file")); - } - break; - } - } - while (0); - - // - // Execution command closes an FTP connection. - // - // AT#FTPCLOSE - // - ICellularRadio::CODE rcclose = sendBasicCommand("AT#FTPCLOSE", 60 * 1000); - if (rcclose != SUCCESS && rc == SUCCESS) { - if(stepCb) { - // Only one "FUMO Error" message should be sent - stepCb(Json::Value("FUMO Error: Failed to close FTP connection")); - } - rc = rcclose; - } - - if (rc == SUCCESS) { - if(stepCb) { - stepCb(Json::Value("FUMO Info: firmware downloaded successfully")); - } - } - - return rc; -} - -ICellularRadio::CODE ME910C1WWRadio::doFumoCleanup(const Json::Value &jConfig, UpdateCb& stepCb) { - ICellularRadio::CODE rc = FAILURE; - std::string sCmd; - - std::string sContextId = jConfig[KEY_FUMO_PDPID].asString(); - - // - // Deactivate PDP context - // - sCmd = "AT#SGACT=" + sContextId + ",0"; - rc = sendBasicCommand(sCmd, 10000); - if (rc != SUCCESS) { - if(stepCb) { - stepCb(Json::Value("FUMO Error: Failed to deactivate PDP context")); - } - } - return rc; -} - -ICellularRadio::CODE ME910C1WWRadio::doFumoApplyFirmware(const Json::Value &jConfig, UpdateCb& stepCb) { - ICellularRadio::CODE rc = FAILURE; - - if (jConfig.isMember(KEY_FUMO_DRYRUN)) { - if(stepCb) { - stepCb(Json::Value("FUMO Info: applying the radio firmware")); - } - return SUCCESS; - } - - rc = sendBasicCommand("AT#OTAUP=0", 10000); - if (rc != SUCCESS) { - if(stepCb) { - stepCb(Json::Value("FUMO Error: failed to apply the firmware")); - } - return rc; - } - - if(stepCb) { - stepCb(Json::Value("FUMO Info: applying the radio firmware")); - } - - return rc; -} - -ICellularRadio::CODE ME910C1WWRadio::doFumoWaitNewFirmware(const Json::Value &jConfig, UpdateCb& stepCb) { - std::string sFirmware; - std::string sFirmwareBuild; - ICellularRadio::CODE rc = FAILURE; - - if (jConfig.isMember(KEY_FUMO_DRYRUN)) { - if(stepCb) { - stepCb(Json::Value("FUMO done: radio firmware applied successfully")); - } - return SUCCESS; - } - - // The radio is expected to send "#OTAEV: Module Upgraded To New Fw" unsolicited message - // on success. However, for some reason, we do not see this message. - - MTS::Timer oTimer; - oTimer.start(); - - while (oTimer.getSeconds() < (5 * 60)) { // 5 minutes - - MTS::Thread::sleep(10000); - - if (doGetFirmwareNumbers(sFirmware, sFirmwareBuild) != SUCCESS) { - // The radio is probably unavailable - resetConnection(100); - continue; - } - - if (sFirmware == m_sFw && sFirmwareBuild == m_sFwBuild) { - // Have the same firmware. The radio resets several time - // before the firmware is actually get upgraded. So keep polling. - continue; - } - - // The firmware numbers have changed - rc = SUCCESS; - break; - } - oTimer.stop(); - - if (rc == SUCCESS) { - if(stepCb) { - stepCb(Json::Value("FUMO done: radio firmware applied successfully")); - } - } - else { - if(stepCb) { - stepCb(Json::Value("FUMO error: radio firmware has not been updated")); - } - } - - return rc; -} - - -ICellularRadio::CODE ME910C1WWRadio::doFumoPerform(const Json::Value &jConfig, UpdateCb& stepCb) { - ICellularRadio::CODE rc = FAILURE; - - UpdateCb dummyCb; - - // Set the PDP context for the FOTA - rc = doFumoSetup(jConfig, stepCb); - if (rc != SUCCESS) { - return rc; - } - - // Download FW over FTP - rc = doFumoFtp(jConfig, stepCb); - if (rc != SUCCESS) { - doFumoCleanup(jConfig, dummyCb); - return rc; - } - - // Clean up before applying the FW file - rc = doFumoCleanup(jConfig, stepCb); - if (rc != SUCCESS) { - return rc; - } - - // Apply the FW file - rc = doFumoApplyFirmware(jConfig, stepCb); - if (rc != SUCCESS) { - return rc; - } - - rc = doFumoWaitNewFirmware(jConfig, stepCb); - - return rc; -} - -ICellularRadio::CODE ME910C1WWRadio::updateFumo(const Json::Value& jArgs, UpdateCb& stepCb) { - Json::Value jConfig(Json::objectValue); - ICellularRadio::CODE rc = FAILURE; - std::string sFwId; - - do - { - rc = getActiveFirmware(sFwId); - if (rc != SUCCESS) { - if(stepCb) { - stepCb(Json::Value("FUMO Error: failed to obtain current active firmware id")); - } - break; - } - - // For Verizon Only - if (sFwId != "1") { - if(stepCb) { - stepCb(Json::Value("FUMO Error: fumo is not supported")); - } - break; - } - - rc = doFumoReadConfig(jArgs, jConfig); - if (rc != SUCCESS) { - if(stepCb) { - stepCb(Json::Value("FUMO Error: bad configuration parameters")); - } - break; - } - - rc = doFumoPerform(jConfig, stepCb); - } - while(0); - - return rc; -} - +} \ No newline at end of file -- cgit v1.2.3 From b8991e7f15f30ad21725b113df773db7beaa69d8 Mon Sep 17 00:00:00 2001 From: Andrii Davydenko Date: Wed, 2 Nov 2022 15:35:51 +0200 Subject: [MTX-4694][GP-1791] MTCAP3 mPower R.6.1.X: LNA7D support - APN setup behavior when provider is Verizon Implement getting the CGDCONT from the modem Implement setting the CGDCONT to the modem --- src/MTS_IO_CellularRadio.cpp | 114 ++++++++++++++++++++++++++++++++++++++++++ src/MTS_IO_ICellularRadio.cpp | 3 ++ 2 files changed, 117 insertions(+) (limited to 'src') diff --git a/src/MTS_IO_CellularRadio.cpp b/src/MTS_IO_CellularRadio.cpp index afdfc1e..3de96ce 100644 --- a/src/MTS_IO_CellularRadio.cpp +++ b/src/MTS_IO_CellularRadio.cpp @@ -1755,3 +1755,117 @@ 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 vContexts = MTS::Text::split(sResult, "+CGDCONT: "); + std::vector 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; +} \ No newline at end of file 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"; -- cgit v1.2.3 From c04f0c7224311c2b9828e653ed4014e1ccf7a82f Mon Sep 17 00:00:00 2001 From: Serhii Kostiuk Date: Fri, 16 Dec 2022 16:45:19 +0200 Subject: LE910: Do not exetute #RFSTS if the SIM card is PUK-locked Executing AT#RFSTS while the SIM card is locked by PIN or PUK causes a deadlock in the legacy LE910 (LAT1, LEU1, LVW2) firmware. Avoid executing AT#RFSTS if the SIM card is locked by PUK. --- src/MTS_IO_TelitRadio.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/MTS_IO_TelitRadio.cpp b/src/MTS_IO_TelitRadio.cpp index 5db2ddf..2a07939 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 -- cgit v1.2.3 From 4b448e3c5daf34062861d0261c5a2253638b8100 Mon Sep 17 00:00:00 2001 From: Serhii Kostiuk Date: Fri, 16 Dec 2022 17:04:08 +0200 Subject: [GP-1195] Cellular debugging - add a query Define the set of debugging AT commands and a function to execute such commands. The function executes the commands one-by-one end returns raw command outputs. To be used by radio-query --diagnostics. --- src/MTS_IO_CellularRadio.cpp | 63 +++++++++++++++++++++++++++++++++++++++++- src/MTS_IO_LE910Radio.cpp | 65 ++++++++++++++++++++++++++++++++++++++++++++ src/MTS_IO_QuectelRadio.cpp | 46 ++++++++++++++++++++++++++++++- src/MTS_IO_TelitRadio.cpp | 32 ++++++++++++++++++++++ 4 files changed, 204 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/MTS_IO_CellularRadio.cpp b/src/MTS_IO_CellularRadio.cpp index 3de96ce..069d5fa 100644 --- a/src/MTS_IO_CellularRadio.cpp +++ b/src/MTS_IO_CellularRadio.cpp @@ -1868,4 +1868,65 @@ ICellularRadio::CODE CellularRadio::setPdpContext(const std::string& sId, const rc = sendBasicCommand(sCommand, dTimeout); return rc; -} \ No newline at end of file +} + +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 = "\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_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& LE910Radio::getDiagCommands(bool bIsSimReady) { + // Declare as static to initialize only when used, but cache the results. + const static std::vector 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 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_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& QuectelRadio::getDiagCommands(bool) { + // Declare as static to initialize only when used, but cache the results. + const static std::vector 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 2a07939..4a0a8b2 100644 --- a/src/MTS_IO_TelitRadio.cpp +++ b/src/MTS_IO_TelitRadio.cpp @@ -1179,3 +1179,35 @@ bool MTS::IO::TelitRadio::isContainsSignChar(const std::string& str) { return true; } + +const std::vector& TelitRadio::getDiagCommands(bool) { + // Declare as static to initialize only when used, but cache the results. + const static std::vector 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; +} -- cgit v1.2.3 From e387c63819118455897d273114d46e8b4c053316 Mon Sep 17 00:00:00 2001 From: Serhii Kostiuk Date: Fri, 6 Jan 2023 00:39:18 +0200 Subject: MCC/MNC Table Update for Verizon and AT&T - 31030 - AT&T - from UBX-13001820 - R13; - 310590 - Verizon - from UBX-13001820 - R13; - 310650 - Cisco Jasper MVNO in AT&T network - from UBX-13001820 - R13; - 310890 - Verizon - from UBX-13001820 - R13; - 311270 - Verizon - from VZ_REQ_LTEB13NAC_12084129, IMS SIM; - 311480 - Verizon - from VZ_REQ_LTEB13NAC_12084129, IMS SIM; - 312770 - Verizon - from the output of AT#FWPLS? on a 5SG1 radio. --- src/MTS_IO_MccMncTable.cpp | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) (limited to 'src') 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"; -- cgit v1.2.3