summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMykola Salomatin <mykola.salomatin@globallogic.com>2021-09-29 16:20:21 +0300
committerJohn Klug <john.klug@multitech.com>2022-04-18 13:46:51 -0500
commit166af1c1bd7c9a0368d046261bab2162a37a7dc2 (patch)
treed9e62a1a039fc9a25d67ec4ef6ad2a260ad97ce0
parent8eb97c149a08f6ec9d938be53868ee426895bf0e (diff)
downloadlibmts-io-166af1c1bd7c9a0368d046261bab2162a37a7dc2.tar.gz
libmts-io-166af1c1bd7c9a0368d046261bab2162a37a7dc2.tar.bz2
libmts-io-166af1c1bd7c9a0368d046261bab2162a37a7dc2.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.h5
-rw-r--r--include/mts/MTS_IO_ICellularRadio.h28
-rw-r--r--include/mts/MTS_IO_LE910C4NFRadio.h4
-rw-r--r--include/mts/MTS_IO_QuectelRadio.h4
-rw-r--r--src/MTS_IO_CellularRadio.cpp54
-rw-r--r--src/MTS_IO_ICellularRadio.cpp2
-rw-r--r--src/MTS_IO_LE910C4NFRadio.cpp76
-rw-r--r--src/MTS_IO_QuectelRadio.cpp92
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;
+}