diff options
author | Mykola Salomatin <mykola.salomatin@globallogic.com> | 2021-09-29 16:20:21 +0300 |
---|---|---|
committer | Mykola Salomatin <mykola.salomatin@globallogic.com> | 2021-09-29 16:20:21 +0300 |
commit | 28b673dd4db086f1957c5cdae281f54980715e36 (patch) | |
tree | d9e62a1a039fc9a25d67ec4ef6ad2a260ad97ce0 | |
parent | 8eb97c149a08f6ec9d938be53868ee426895bf0e (diff) | |
download | libmts-io-28b673dd4db086f1957c5cdae281f54980715e36.tar.gz libmts-io-28b673dd4db086f1957c5cdae281f54980715e36.tar.bz2 libmts-io-28b673dd4db086f1957c5cdae281f54980715e36.zip |
[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.
-rw-r--r-- | include/mts/MTS_IO_CellularRadio.h | 5 | ||||
-rw-r--r-- | include/mts/MTS_IO_ICellularRadio.h | 28 | ||||
-rw-r--r-- | include/mts/MTS_IO_LE910C4NFRadio.h | 4 | ||||
-rw-r--r-- | include/mts/MTS_IO_QuectelRadio.h | 4 | ||||
-rw-r--r-- | src/MTS_IO_CellularRadio.cpp | 54 | ||||
-rw-r--r-- | src/MTS_IO_ICellularRadio.cpp | 2 | ||||
-rw-r--r-- | src/MTS_IO_LE910C4NFRadio.cpp | 76 | ||||
-rw-r--r-- | src/MTS_IO_QuectelRadio.cpp | 92 |
8 files changed, 265 insertions, 0 deletions
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<std::string> 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 <filename>. 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; +} |