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. --- include/mts/MTS_IO_CellularRadio.h | 5 ++ include/mts/MTS_IO_ICellularRadio.h | 28 +++++++++++ include/mts/MTS_IO_LE910C4NFRadio.h | 4 ++ include/mts/MTS_IO_QuectelRadio.h | 4 ++ src/MTS_IO_CellularRadio.cpp | 54 ++++++++++++++++++++++ src/MTS_IO_ICellularRadio.cpp | 2 + src/MTS_IO_LE910C4NFRadio.cpp | 76 ++++++++++++++++++++++++++++++ src/MTS_IO_QuectelRadio.cpp | 92 +++++++++++++++++++++++++++++++++++++ 8 files changed, 265 insertions(+) diff --git a/include/mts/MTS_IO_CellularRadio.h b/include/mts/MTS_IO_CellularRadio.h index daefcd1..4d1cd12 100644 --- a/include/mts/MTS_IO_CellularRadio.h +++ b/include/mts/MTS_IO_CellularRadio.h @@ -140,6 +140,10 @@ namespace MTS { CODE getSimMccMnc(std::string& sMccMnc) override; CODE getSimMccMnc(std::string& sMcc, std::string& sMnc) override; + CODE disableVoiceSupport() override; + CODE getVoiceSupport(Json::Value& jData) override; + CODE getVoiceSupport(bool& bVoiceEnabled, bool& bSmsOnly) override; + protected: CellularRadio(const std::string& sName, const std::string& sRadioPort); @@ -231,6 +235,7 @@ namespace MTS { CODE getRegistration(REGISTRATION& eRegistration, const std::string& sType); virtual CODE sendData(const char* pData, size_t nBytes); + virtual CODE sendBasicQuery(const std::string& sCmd, const std::string& sLabel, std::string& sResult, int32_t timeoutMillis = 100, const char& ESC = ICellularRadio::CR); class RadioBandMap : public MTS::NonCopyable { public: diff --git a/include/mts/MTS_IO_ICellularRadio.h b/include/mts/MTS_IO_ICellularRadio.h index 58329c4..e061636 100644 --- a/include/mts/MTS_IO_ICellularRadio.h +++ b/include/mts/MTS_IO_ICellularRadio.h @@ -153,6 +153,8 @@ namespace MTS { static const char *KEY_SIM_CARRIER_CODE; //!< Unique carrier identifier based on the SIM card information. static const char *KEY_SIM_MCC; //!< MCC of the home network from the SIM. static const char *KEY_SIM_MNC; //!< MNC of the home network from the SIM. + static const char *KEY_VOICE_ENABLED; //!< Enable/Disable support of voice calls + static const char *KEY_SMS_ONLY; //!< Enable/Disable "SMS only" registration flag //Network Status Data @@ -592,6 +594,32 @@ namespace MTS { */ virtual CODE getSimMccMnc(std::string& sMccMnc) = 0; virtual CODE getSimMccMnc(std::string& sMcc, std::string& sMnc) = 0; + + /** + * @brief disableVoiceSupport - disable voice support (IMS and CSFB) and enable "SMS only" registration flag. + * + * @return CODE::SUCCESS when disabled successfully, + * CODE::NOT_APPLICABLE when the modem doesn't support this feature, + * CODE::NO_RESPONSE when the modem doesn't respond, + * CODE::ERROR when the radio returns "ERROR", + * CODE::FAILURE otherwise (unexpected response). + */ + virtual CODE disableVoiceSupport() = 0; + + /** + * @brief getVoiceSupport - get voice support configuration for the current radio. + * + * @param bVoiceEnabled - a boolean value indicating that "voice support" is enabled. + * @param bSmsOnly - a boolean value indicating that "SMS only" registration flag is enabled. + * + * @return CODE::SUCCESS when fetched successfully, + * CODE::NOT_APPLICABLE when the modem doesn't support this feature, + * CODE::NO_RESPONSE when the modem doesn't respond, + * CODE::ERROR when the radio returns "ERROR", + * CODE::FAILURE otherwise (unexpected response). + */ + virtual CODE getVoiceSupport(Json::Value& jData) = 0; + virtual CODE getVoiceSupport(bool& bVoiceEnabled, bool& bSmsOnly) = 0; }; } } diff --git a/include/mts/MTS_IO_LE910C4NFRadio.h b/include/mts/MTS_IO_LE910C4NFRadio.h index afd1c24..1ae61a7 100644 --- a/include/mts/MTS_IO_LE910C4NFRadio.h +++ b/include/mts/MTS_IO_LE910C4NFRadio.h @@ -38,10 +38,14 @@ namespace MTS { virtual CODE getActiveFirmware(std::string& sFwId); + CODE disableVoiceSupport() override; + CODE getVoiceSupport(bool& bVoiceEnabled, bool& bSmsOnly) override; + protected: FOTA_GROUP getFotaGroup() override; private: + CODE getIsVoiceSupportConfigurable(); }; } diff --git a/include/mts/MTS_IO_QuectelRadio.h b/include/mts/MTS_IO_QuectelRadio.h index c46b39b..4e82261 100644 --- a/include/mts/MTS_IO_QuectelRadio.h +++ b/include/mts/MTS_IO_QuectelRadio.h @@ -54,6 +54,9 @@ namespace MTS { CODE setUeModeOfOperation(ICellularRadio::UE_MODES_OF_OPERATION mode) override; CODE getUeModeOfOperation(ICellularRadio::UE_MODES_OF_OPERATION& mode) override; + CODE disableVoiceSupport() override; + CODE getVoiceSupport(bool& bVoiceEnabled, bool& bSmsOnly) override; + protected: enum class UE_USAGE_SETTING : uint8_t { UNKNOWN_MODE = 0, // Unknown mode @@ -84,6 +87,7 @@ namespace MTS { static const std::string CMD_ABORT_UPLOAD; static const std::string VALUE_MTS_DELTA_NAME; static const std::string VALUE_MTS_DELTA_PATH; + static const std::string VALUE_QNVR_DISABLE_VOICE; CODE startFileUpload(const std::string& sTargetFilename, size_t nBytes, uint16_t uRxTimeout = 5, bool bAckEnabled = false); CODE abortFileUpload(); 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 --- data/MccMncTable.csv | 8 ++- include/mts/MTS_IO_CellularRadio.h | 27 ++++++++ include/mts/MTS_IO_ICellularRadio.h | 36 +++++++++++ include/mts/MTS_IO_QuectelRadio.h | 4 ++ include/mts/MTS_IO_TelitRadio.h | 4 ++ 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 +++++++++++++++++++++++++++++-- 13 files changed, 358 insertions(+), 30 deletions(-) diff --git a/data/MccMncTable.csv b/data/MccMncTable.csv index f0246e2..968dbc1 100644 --- a/data/MccMncTable.csv +++ b/data/MccMncTable.csv @@ -463,10 +463,10 @@ "297","02","me","Montenegro","382","Monet/T-mobile", "297","03","me","Montenegro","382","Mtel", "302","220","ca","Canada","1","Telus Mobility", -"302","320","ca","Canada","1","mobilicity", +"302","320","ca","Canada","1","Mobilicity", "302","360","ca","Canada","1","Clearnet", "302","361","ca","Canada","1","Clearnet", -"302","370","ca","Canada","1","FIDO (Rogers AT&T/ Microcell)", +"302","370","ca","Canada","1","Fido", "302","380","ca","Canada","1","DMTS Mobility", "302","490","ca","Canada","1","WIND", "302","500","ca","Canada","1","Videotron", @@ -487,8 +487,10 @@ "302","702","ca","Canada","1","MT&T Mobility", "302","703","ca","Canada","1","New Tel Mobility", "302","710","ca","Canada","1","Globalstar Canada", -"302","720","ca","Canada","1","Rogers AT&T Wireless", +"302","720","ca","Canada","1","Rogers Wireless", +"302","721","ca","Canada","1","Rogers Wireless", "302","760","ca","Canada","1","Public Mobile", +"302","820","ca","Canada","1","Rogers Wireless", "308","01","pm","St. Pierre & Miquelon","508","Ameris", "310","003","us","United States","1","Unknown", "310","004","us","United States","1","Verizon Wireless", diff --git a/include/mts/MTS_IO_CellularRadio.h b/include/mts/MTS_IO_CellularRadio.h index 4d1cd12..f32251c 100644 --- a/include/mts/MTS_IO_CellularRadio.h +++ b/include/mts/MTS_IO_CellularRadio.h @@ -72,6 +72,7 @@ namespace MTS { CODE getTime(std::string& sDate, std::string& sTime, std::string& sTimeZone) override; CODE getRoaming(bool& bRoaming) override; CODE getCellularMode(CELLULAR_MODES &networks) override; + CODE getSelectedBandsRaw(std::string& sRawBands) override; CODE getSignalStrength(int32_t& iRssi) override; CODE getModemLocation(std::string& sLocation) override; @@ -223,6 +224,32 @@ namespace MTS { */ virtual CODE getSimMncLength(uint8_t& iLength); + /** + * @brief getCarrierFromSimMccMnc - get a carrier name based on the MCC/MNC values. + * + * @param sCarrier - a string to be filled with carrier based on the MCC/MNC values. + * + * @return CODE::SUCCESS when the read is completed successfully, + * CODE::NOT_APPLICABLE when the modem doesn't support this feature, + * CODE::NO_RESPONSE when the modem doesn't respond, + * CODE::ERROR when the radio returns "ERROR" (SIM card removed, SIM card locked etc), + * CODE::FAILURE otherwise (unexpected response, no data in SIM etc). + */ + virtual CODE getCarrierFromSimMccMnc(std::string& sCarrier); + + /** + * @brief getCarrierFromSimSpn - get a carrier name from SIM EFspn. + * + * @param sCarrier - a string to be filled with carrier obtained from SIM EFspn. + * + * @return CODE::SUCCESS when the read is completed successfully, + * CODE::NOT_APPLICABLE when the modem doesn't support this feature, + * CODE::NO_RESPONSE when the modem doesn't respond, + * CODE::ERROR when the radio returns "ERROR" (SIM card removed, SIM card locked etc), + * CODE::FAILURE otherwise (unexpected response, no data in SIM etc). + */ + virtual CODE getCarrierFromSimSpn(std::string& sCarrier); + void initMipProfile(Json::Value& jData); bool splitAndAssign(const std::string& sLine, const std::string& sKey, Json::Value& jParent, const std::string& sJsonKey, Json::ValueType eType = Json::ValueType::stringValue); diff --git a/include/mts/MTS_IO_ICellularRadio.h b/include/mts/MTS_IO_ICellularRadio.h index e061636..f3e15e2 100644 --- a/include/mts/MTS_IO_ICellularRadio.h +++ b/include/mts/MTS_IO_ICellularRadio.h @@ -620,6 +620,42 @@ namespace MTS { */ virtual CODE getVoiceSupport(Json::Value& jData) = 0; virtual CODE getVoiceSupport(bool& bVoiceEnabled, bool& bSmsOnly) = 0; + + /** + * @brief getSelectedBandsRaw - get the raw Selected Bands value for the current radio. + * + * This commands sends the query to the radio, selects first 3 values from the response, + * parses the numbers as dec (Telit GSM and WCDMA fiels) or hex (Quectel GW_band and LTE, + * Telit LTE), formats them as comma-separated hex values and saves the result to sRawBands. + * + * WARNING: The response format is radio-dependent. Please consult the AT command manual + * to interpet the resulting values. + * + * For Telit radios: + * + * - command: `AT#BND?`; + * - example radio response: `#BND: 5,15,800C5`; + * - `sRawBands` format: `[,[,]]`; + * - example `sRawBands` content: `5,F,800C5`. + * + * For Quectel radios: + * + * - command: `AT+QCFG="band"`; + * - example radio response: `+QCFG: "band",0x93,0x80800c5,0x0`; + * - `sRawBands` format: `,,`, + * NOTE: the `` value is duplicated for the first two fields; + * - example `sRawBands` content: `93,93,80800c5`. + * + * @param sRawBands - radio-depended string value, shows the currently selected bands. + * + * @return CODE::SUCCESS when fetched successfully, + * CODE::NOT_APPLICABLE when the modem doesn't support this feature, + * CODE::NO_RESPONSE when the modem doesn't respond, + * CODE::ERROR when the radio returns "ERROR", + * CODE::FAILURE otherwise (unexpected response). + */ + virtual CODE getSelectedBandsRaw(std::string& sRawBands) = 0; + }; } } diff --git a/include/mts/MTS_IO_QuectelRadio.h b/include/mts/MTS_IO_QuectelRadio.h index 4e82261..c54e560 100644 --- a/include/mts/MTS_IO_QuectelRadio.h +++ b/include/mts/MTS_IO_QuectelRadio.h @@ -57,6 +57,8 @@ namespace MTS { CODE disableVoiceSupport() override; CODE getVoiceSupport(bool& bVoiceEnabled, bool& bSmsOnly) override; + CODE getSelectedBandsRaw(std::string& sRawBands) override; + protected: enum class UE_USAGE_SETTING : uint8_t { UNKNOWN_MODE = 0, // Unknown mode @@ -79,6 +81,8 @@ namespace MTS { virtual CODE getUeUsageSetting(QuectelRadio::UE_USAGE_SETTING& us); virtual CODE convertToUeUsageSetting(const std::string& sSetting, QuectelRadio::UE_USAGE_SETTING& us); + static bool isContainsSignChar(const std::string& str); + private: // private variable to save old firmware versions during FOTA std::string m_sQuectelFirmware; diff --git a/include/mts/MTS_IO_TelitRadio.h b/include/mts/MTS_IO_TelitRadio.h index ffdddd9..a06da54 100644 --- a/include/mts/MTS_IO_TelitRadio.h +++ b/include/mts/MTS_IO_TelitRadio.h @@ -50,6 +50,8 @@ namespace MTS { CODE fumoLocalInject(int fd, UpdateCb& stepCb) override; CODE fumoLocalApply(UpdateCb& stepCb) override; + CODE getSelectedBandsRaw(std::string& sRawBands) override; + protected: TelitRadio(const std::string& sName, const std::string& sRadioPort); @@ -71,6 +73,8 @@ namespace MTS { virtual CODE fumoWriteGroupsABD(int fd, UpdateCb& stepCb); //virtual CODE fumoWriteGroupC(int fd, UpdateCb& stepCb); + static bool isContainsSignChar(const std::string& str); + private: virtual CODE getSimLockAttempts(int& iAttemptsPin, int& iAttemptsPuk, const std::string& sLockStatus); ICellularRadio::CODE wdsList(std::set &wds); 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(+) 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. --- include/mts/MTS_IO_EG25Radio.h | 1 - include/mts/MTS_IO_EG95Radio.h | 1 - include/mts/MTS_IO_QuectelRadio.h | 4 ++ src/MTS_IO_EG25Radio.cpp | 11 ----- src/MTS_IO_EG95Radio.cpp | 24 ++++++----- src/MTS_IO_ICellularRadio.cpp | 3 ++ src/MTS_IO_QuectelRadio.cpp | 87 +++++++++++++++++++++++++++++++++++++++ 7 files changed, 108 insertions(+), 23 deletions(-) diff --git a/include/mts/MTS_IO_EG25Radio.h b/include/mts/MTS_IO_EG25Radio.h index 46bff20..e05fa7d 100644 --- a/include/mts/MTS_IO_EG25Radio.h +++ b/include/mts/MTS_IO_EG25Radio.h @@ -34,7 +34,6 @@ namespace MTS { EG25Radio(const std::string& sPort); virtual ~EG25Radio(); - CODE setRxDiversity(const Json::Value& jArgs) override; protected: diff --git a/include/mts/MTS_IO_EG95Radio.h b/include/mts/MTS_IO_EG95Radio.h index 17c413e..6fb47c8 100644 --- a/include/mts/MTS_IO_EG95Radio.h +++ b/include/mts/MTS_IO_EG95Radio.h @@ -34,7 +34,6 @@ namespace MTS { EG95Radio(const std::string& sPort); virtual ~EG95Radio(); - CODE setRxDiversity(const Json::Value& jArgs) override; protected: diff --git a/include/mts/MTS_IO_QuectelRadio.h b/include/mts/MTS_IO_QuectelRadio.h index c54e560..bd312b8 100644 --- a/include/mts/MTS_IO_QuectelRadio.h +++ b/include/mts/MTS_IO_QuectelRadio.h @@ -83,6 +83,8 @@ namespace MTS { static bool isContainsSignChar(const std::string& str); + CODE setRxDiversity(const Json::Value& jArgs) override; + private: // private variable to save old firmware versions during FOTA std::string m_sQuectelFirmware; @@ -117,6 +119,8 @@ namespace MTS { return vector[index]; } } + + CODE isDivctlSupported(bool& bSupported); }; } } 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 --- include/mts/MTS_IO_ME910C1WWRadio.h | 22 -- src/MTS_IO_ME910C1WWRadio.cpp | 604 +----------------------------------- 2 files changed, 1 insertion(+), 625 deletions(-) diff --git a/include/mts/MTS_IO_ME910C1WWRadio.h b/include/mts/MTS_IO_ME910C1WWRadio.h index 9605862..d4b4098 100644 --- a/include/mts/MTS_IO_ME910C1WWRadio.h +++ b/include/mts/MTS_IO_ME910C1WWRadio.h @@ -36,33 +36,11 @@ namespace MTS { ICellularRadio::CODE setActiveFirmware(const Json::Value& jArgs); ICellularRadio::CODE getActiveFirmware(std::string& sFwId); - virtual CODE updateFumo(const Json::Value& jArgs, UpdateCb& stepCb); - protected: - CODE doGetFirmwareNumbers(std::string &sFirmware, std::string &sFirmwareBuild); - private: - static const std::string KEY_FUMO_PDPID; //!< PDP context id (default 3) - static const std::string KEY_FUMO_PDPTYPE; //!< PDP context type (default IPV4V6) - static const std::string KEY_FUMO_APN; //!< APN (default empty) - static const std::string KEY_FUMO_ADDRESS; //!< FTP server address - static const std::string KEY_FUMO_DIR; //!< Directory - static const std::string KEY_FUMO_FILE; //!< Name of the upgrade file - static const std::string KEY_FUMO_USER; //!< Username - static const std::string KEY_FUMO_PASSWORD; //!< Password - static const std::string KEY_FUMO_DRYRUN; //!< If set, do not apply the downloaded firmware - CODE doFumoPerform(const Json::Value &jConfig, UpdateCb& stepCb); - CODE doFumoReadConfig(const Json::Value& jArgs, Json::Value &jConfig); - CODE doFumoSetup(const Json::Value &jConfig, UpdateCb& stepCb); - CODE doFumoFtp(const Json::Value &jConfig, UpdateCb& stepCb); - CODE doFumoCleanup(const Json::Value &jConfig, UpdateCb& stepCb); - CODE doFumoApplyFirmware(const Json::Value &jConfig, UpdateCb& stepCb); - CODE doFumoWaitNewFirmware(const Json::Value &jConfig, UpdateCb& stepCb); - std::string m_sFw; - std::string m_sFwBuild; }; } } 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 --- include/mts/MTS_IO_CellularRadio.h | 3 + include/mts/MTS_IO_ICellularRadio.h | 41 +++++++++++++ src/MTS_IO_CellularRadio.cpp | 114 ++++++++++++++++++++++++++++++++++++ src/MTS_IO_ICellularRadio.cpp | 3 + 4 files changed, 161 insertions(+) diff --git a/include/mts/MTS_IO_CellularRadio.h b/include/mts/MTS_IO_CellularRadio.h index f32251c..60659dc 100644 --- a/include/mts/MTS_IO_CellularRadio.h +++ b/include/mts/MTS_IO_CellularRadio.h @@ -145,6 +145,9 @@ namespace MTS { CODE getVoiceSupport(Json::Value& jData) override; CODE getVoiceSupport(bool& bVoiceEnabled, bool& bSmsOnly) override; + CODE getPdpContexts(Json::Value& jData) override; + CODE setPdpContext(const std::string& sId, const Json::Value& jConfig) override; + protected: CellularRadio(const std::string& sName, const std::string& sRadioPort); diff --git a/include/mts/MTS_IO_ICellularRadio.h b/include/mts/MTS_IO_ICellularRadio.h index f3e15e2..91ab782 100644 --- a/include/mts/MTS_IO_ICellularRadio.h +++ b/include/mts/MTS_IO_ICellularRadio.h @@ -205,6 +205,10 @@ namespace MTS { static const char *KEY_ATTEMPTS_PIN; //!< The number of attempts left to unlock the SIM card using PIN code static const char *KEY_ATTEMPTS_PUK; //!< The number of attempts left to unlock the SIM card using PUK code + //PDP Context + static const char *KEY_PDP_CONTEXT_APN; + static const char *KEY_PDP_CONTEXT_IPMODE; + //Values - Type static const char *VALUE_TYPE_LTE; static const char *VALUE_TYPE_GSM; @@ -656,6 +660,43 @@ namespace MTS { */ virtual CODE getSelectedBandsRaw(std::string& sRawBands) = 0; + /** + * @brief Get the list of PDP contexts from the radio + * + * @param jData - an object to be filled with data. + * { + * "": { + * "apn": "", + * "ipMode": "" + * } + * } + * + * @return CODE::SUCCESS when fetched successfully, + * CODE::NO_RESPONSE when the modem doesn't respond, + * CODE::ERROR when the radio returns "ERROR", + * CODE::FAILURE otherwise (unexpected response). + */ + virtual CODE getPdpContexts(Json::Value& jData) = 0; + + /** + * @brief Set the PDP context to the radio + * + * @param sId - a string value that contains an ID of the PDP context to change. + * @param jConfig - a JSON-object that contains: + * an IP mode for the specified PDP context, + * an APN for the specified PDP context. + * { + * "apn": "", + * "ipMode": "" + * } + * + * @return CODE::SUCCESS when fetched successfully, + * CODE::NO_RESPONSE when the modem doesn't respond, + * CODE::ERROR when the radio returns "ERROR", + * CODE::FAILURE otherwise (unexpected response). + */ + virtual CODE setPdpContext(const std::string& sId, const Json::Value& jConfig) = 0; + }; } } 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(-) 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. --- include/mts/MTS_IO_CellularRadio.h | 11 +++++++ include/mts/MTS_IO_ICellularRadio.h | 21 ++++++++++++ include/mts/MTS_IO_LE910Radio.h | 2 ++ include/mts/MTS_IO_QuectelRadio.h | 2 ++ include/mts/MTS_IO_TelitRadio.h | 2 ++ src/MTS_IO_CellularRadio.cpp | 63 ++++++++++++++++++++++++++++++++++- src/MTS_IO_LE910Radio.cpp | 65 +++++++++++++++++++++++++++++++++++++ src/MTS_IO_QuectelRadio.cpp | 46 +++++++++++++++++++++++++- src/MTS_IO_TelitRadio.cpp | 32 ++++++++++++++++++ 9 files changed, 242 insertions(+), 2 deletions(-) diff --git a/include/mts/MTS_IO_CellularRadio.h b/include/mts/MTS_IO_CellularRadio.h index 60659dc..e985c21 100644 --- a/include/mts/MTS_IO_CellularRadio.h +++ b/include/mts/MTS_IO_CellularRadio.h @@ -148,6 +148,8 @@ namespace MTS { CODE getPdpContexts(Json::Value& jData) override; CODE setPdpContext(const std::string& sId, const Json::Value& jConfig) override; + CODE getDiagnostics(std::string& sReport) override; + protected: CellularRadio(const std::string& sName, const std::string& sRadioPort); @@ -267,6 +269,15 @@ namespace MTS { virtual CODE sendData(const char* pData, size_t nBytes); virtual CODE sendBasicQuery(const std::string& sCmd, const std::string& sLabel, std::string& sResult, int32_t timeoutMillis = 100, const char& ESC = ICellularRadio::CR); + /** + * @brief getDiagCommands - returns the list of Cellular Diagnostics commands for this radio. + * + * @param bIsSimReady - set to "true" if the SIM card is inserted and NOT locked by PIN or PUK. + * + * @return the list of AT commands (strings). + */ + virtual const std::vector& getDiagCommands(bool bIsSimReady = true) = 0; + class RadioBandMap : public MTS::NonCopyable { public: RadioBandMap() diff --git a/include/mts/MTS_IO_ICellularRadio.h b/include/mts/MTS_IO_ICellularRadio.h index 91ab782..0523236 100644 --- a/include/mts/MTS_IO_ICellularRadio.h +++ b/include/mts/MTS_IO_ICellularRadio.h @@ -697,6 +697,27 @@ namespace MTS { */ virtual CODE setPdpContext(const std::string& sId, const Json::Value& jConfig) = 0; + /** + * @brief Execute the diagnostics AT commands and capture their output + * + * NOTE: The list of diagnostic AT commands is radio-specific and changes + * depending on the radio model (code). + * + * NOTE: The method stops its execution if the radio repeatedly ignores + * the commands (returns no execution result for several of them). This + * is required to limit the maximum execution time of the function and + * prevent the process from occupying the radio for too long. In case + * of timeout, the report will contain the output of all commands that + * it managed to execute before the failure. + * + * @param sDiagReport - the AT commands execution report. + * + * @return CODE::SUCCESS when fetched successfully, + * CODE::NO_RESPONSE when the radio ignored several of the AT commands, + * CODE::FAILURE otherwise. + */ + virtual CODE getDiagnostics(std::string& sDiagReport) = 0; + }; } } diff --git a/include/mts/MTS_IO_LE910Radio.h b/include/mts/MTS_IO_LE910Radio.h index 2ba423d..6700ee3 100644 --- a/include/mts/MTS_IO_LE910Radio.h +++ b/include/mts/MTS_IO_LE910Radio.h @@ -50,6 +50,8 @@ namespace MTS { protected: + const std::vector& getDiagCommands(bool bIsSimReady = true) override; + private: diff --git a/include/mts/MTS_IO_QuectelRadio.h b/include/mts/MTS_IO_QuectelRadio.h index bd312b8..4315cb3 100644 --- a/include/mts/MTS_IO_QuectelRadio.h +++ b/include/mts/MTS_IO_QuectelRadio.h @@ -85,6 +85,8 @@ namespace MTS { CODE setRxDiversity(const Json::Value& jArgs) override; + const std::vector& getDiagCommands(bool bIsSimReady = true) override; + private: // private variable to save old firmware versions during FOTA std::string m_sQuectelFirmware; diff --git a/include/mts/MTS_IO_TelitRadio.h b/include/mts/MTS_IO_TelitRadio.h index a06da54..d198969 100644 --- a/include/mts/MTS_IO_TelitRadio.h +++ b/include/mts/MTS_IO_TelitRadio.h @@ -73,6 +73,8 @@ namespace MTS { virtual CODE fumoWriteGroupsABD(int fd, UpdateCb& stepCb); //virtual CODE fumoWriteGroupC(int fd, UpdateCb& stepCb); + const std::vector& getDiagCommands(bool bIsSimReady = true) override; + static bool isContainsSignChar(const std::string& str); private: 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. --- data/MccMncTable.csv | 12 +++++++----- src/MTS_IO_MccMncTable.cpp | 14 ++++++++------ 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/data/MccMncTable.csv b/data/MccMncTable.csv index 968dbc1..e79ef10 100644 --- a/data/MccMncTable.csv +++ b/data/MccMncTable.csv @@ -534,6 +534,7 @@ "310","270","us","United States","1","T-Mobile", "310","280","us","United States","1","AT&T Wireless Inc.","att" "310","290","us","United States","1","NEP Cellcorp Inc.", +"310","30","us","United States","1","Centennial Communications","att" "310","300","us","United States","1","T-Mobile", "310","31","us","United States","1","T-Mobile", "310","310","us","United States","1","T-Mobile", @@ -566,14 +567,14 @@ "310","560","us","United States","1","AT&T Wireless Inc.","att" "310","570","us","United States","1","MTPCS LLC", "310","580","us","United States","1","PCS ONE", -"310","590","us","United States","1","Verizon Wireless", +"310","590","us","United States","1","Verizon Wireless","vz" "310","60","us","United States","1","Consolidated Telcom", "310","600","us","United States","1","New-Cell Inc.", "310","610","us","United States","1","Elkhart TelCo. / Epic Touch Co.", "310","620","us","United States","1","Coleman County Telco /Trans TX", "310","630","us","United States","1",, "310","640","us","United States","1",, -"310","650","us","United States","1","Jasper", +"310","650","us","United States","1","Jasper","att-jasper" "310","660","us","United States","1","T-Mobile", "310","670","us","United States","1","Northstar","att" "310","680","us","United States","1","AT&T Wireless Inc.","att" @@ -593,7 +594,7 @@ "310","860","us","United States","1","Texas RSA 15B2 Limited Partnership", "310","870","us","United States","1","Kaplan Telephone Company Inc.", "310","880","us","United States","1",, -"310","890","us","United States","1","Verizon Wireless", +"310","890","us","United States","1","Verizon Wireless","vz" "310","900","us","United States","1","Cable & Communications Corp.", "310","910","us","United States","1","Verizon Wireless", "310","920","us","United States","1","Get Mobile Inc.", @@ -627,7 +628,7 @@ "311","240","us","United States","1",, "311","250","gu","Guam","1671","Wave Runner LLC", "311","260","us","United States","1","SLO Cellular Inc / Cellular One of San Luis", -"311","270","us","United States","1","Verizon Wireless", +"311","270","us","United States","1","Verizon Wireless","vz" "311","271","us","United States","1","Verizon Wireless", "311","272","us","United States","1","Verizon Wireless", "311","273","us","United States","1","Verizon Wireless", @@ -661,7 +662,7 @@ "311","430","us","United States","1","RSA 1 Limited Partnership", "311","440","us","United States","1","Bluegrass Wireless LLC", "311","460","us","United States","1","Fisher Wireless Services Inc.", -"311","480","us","United States","1","Verizon Wireless", +"311","480","us","United States","1","Verizon Wireless","vz" "311","481","us","United States","1","Verizon Wireless", "311","482","us","United States","1","Verizon Wireless", "311","483","us","United States","1","Verizon Wireless", @@ -710,6 +711,7 @@ "312","530","us","United States","1","Sprint Spectrum", "312","670","us","United States","1","AT&T Wireless Inc.","att-first" "312","680","us","United States","1","AT&T Wireless Inc.","att" +"312","770","us","United States","1","Verizon Wireless","vz" "313","100","us","United States","1","FirstNet","att-first" "313","110","us","United States","1","FirstNet","att-first" "313","120","us","United States","1","FirstNet","att-first" 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