summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorYevhen Mykhno <yevhen.mykhno@globallogic.com>2023-02-09 20:25:11 +0200
committerJohn Klug <john.klug@multitech.com>2023-03-13 11:07:41 -0500
commitc3417c195b41b580ba62197fff6cf891936749c9 (patch)
treea1b556855040dcf34670b755d514271c1a4e5ff2 /src
parent5617399e837fff93c008cd18939896d80808833b (diff)
downloadlibmts-io-c3417c195b41b580ba62197fff6cf891936749c9.tar.gz
libmts-io-c3417c195b41b580ba62197fff6cf891936749c9.tar.bz2
libmts-io-c3417c195b41b580ba62197fff6cf891936749c9.zip
[GP-1597] mPower R.6.3.X: Cellular Provider Profiles - LTE Authentication
Diffstat (limited to 'src')
-rw-r--r--src/MTS_IO_CellularRadio.cpp299
-rw-r--r--src/MTS_IO_ICellularRadio.cpp11
-rw-r--r--src/MTS_IO_QuectelRadio.cpp108
-rw-r--r--src/MTS_IO_SequansRadio.cpp21
-rw-r--r--src/MTS_IO_TelitRadio.cpp103
5 files changed, 489 insertions, 53 deletions
diff --git a/src/MTS_IO_CellularRadio.cpp b/src/MTS_IO_CellularRadio.cpp
index 3ce97ec..7200658 100644
--- a/src/MTS_IO_CellularRadio.cpp
+++ b/src/MTS_IO_CellularRadio.cpp
@@ -22,6 +22,7 @@
#include <unistd.h>
#include <sys/stat.h>
+#include <algorithm>
#include <mts/MTS_IO_MccMncTable.h>
#include <mts/MTS_Thread.h>
@@ -1760,27 +1761,81 @@ ICellularRadio::CODE CellularRadio::sendBasicQuery(const std::string& sCmd, cons
return SUCCESS;
}
+ICellularRadio::CODE CellularRadio::isCommandSupported(const std::string& sCmd, bool& bIsSupported) {
+ CODE rc;
+ bIsSupported = false;
+
+ rc = sendBasicCommand(sCmd);
+
+ if (SUCCESS == rc) {
+ bIsSupported = true;
+ } else if (ERROR == rc) {
+ // if not applicable
+ rc = SUCCESS;
+ }
+
+ return rc;
+}
+
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());
+ICellularRadio::CODE CellularRadio::convertPdpContextAuthTypeToString(PDP_CONTEXT_AUTH_TYPE eAuthType, std::string& sAuthType) {
+ CODE rc = FAILURE;
+
+ switch (eAuthType) {
+ case NONE: sAuthType = VALUE_PDP_CONTEXT_AUTH_TYPE_NONE; rc = SUCCESS; break;
+ case PAP: sAuthType = VALUE_PDP_CONTEXT_AUTH_TYPE_PAP; rc = SUCCESS; break;
+ case CHAP: sAuthType = VALUE_PDP_CONTEXT_AUTH_TYPE_CHAP; rc = SUCCESS; break;
+ case PAP_CHAP: sAuthType = VALUE_PDP_CONTEXT_AUTH_TYPE_PAP_CHAP; rc = SUCCESS; break;
+ default: sAuthType = ICellularRadio::VALUE_UNKNOWN; break;
+ }
+ return rc;
+}
+
+ICellularRadio::CODE MTS::IO::CellularRadio::convertStringToPdpContextAuthType(const std::string& sAuthType, PDP_CONTEXT_AUTH_TYPE& eAuthType) {
+ CODE rc = FAILURE;
+ if (VALUE_PDP_CONTEXT_AUTH_TYPE_NONE == sAuthType) {
+ eAuthType = PDP_CONTEXT_AUTH_TYPE::NONE;
+ rc = SUCCESS;
+ } else if (VALUE_PDP_CONTEXT_AUTH_TYPE_PAP == sAuthType) {
+ eAuthType = PDP_CONTEXT_AUTH_TYPE::PAP;
+ rc = SUCCESS;
+ } else if (VALUE_PDP_CONTEXT_AUTH_TYPE_CHAP == sAuthType) {
+ eAuthType = PDP_CONTEXT_AUTH_TYPE::CHAP;
+ rc = SUCCESS;
+ } else if (VALUE_PDP_CONTEXT_AUTH_TYPE_PAP_CHAP == sAuthType) {
+ eAuthType = PDP_CONTEXT_AUTH_TYPE::PAP_CHAP;
+ rc = SUCCESS;
+ }
+ return rc;
+}
+
+// When there are no defined contexts
+// Telit returns:
+// OK
+// Quectel returns:
+// +CGDCONT:
+//
+// OK
+ICellularRadio::CODE CellularRadio::getPdpContextsBase(Json::Value& jData) {
CODE rc;
const std::string sCommand = "AT+CGDCONT?";
const int dTimeout = 1000;
std::string sResult;
+ jData = Json::objectValue;
+
rc = sendBasicQuery(sCommand, "", sResult, dTimeout);
if (rc != SUCCESS) {
return rc;
}
- std::vector<std::string> vContexts = MTS::Text::split(sResult, "+CGDCONT: ");
- std::vector<std::string> vContextParams;
+ std::vector<std::string> vContexts = MTS::Text::split(sResult, "+CGDCONT:");
for (size_t i = 0; i < vContexts.size(); i++) {
vContexts[i] = MTS::Text::trim(vContexts[i]);
@@ -1789,7 +1844,7 @@ ICellularRadio::CODE CellularRadio::getPdpContexts(Json::Value& jData) {
continue;
}
- vContextParams = MTS::Text::split(vContexts[i], ",", 4);
+ std::vector<std::string> vContextParams = MTS::Text::split(vContexts[i], ",", 4);
if (vContextParams.size() < 3) {
return FAILURE;
@@ -1806,78 +1861,216 @@ ICellularRadio::CODE CellularRadio::getPdpContexts(Json::Value& jData) {
return SUCCESS;
}
-ICellularRadio::CODE CellularRadio::setPdpContext(const std::string& sId, const Json::Value& jConfig) {
- printTrace("%s| Setting context to the radio", getName().c_str());
+ICellularRadio::CODE CellularRadio::getPdpContexts(Json::Value& jData) {
+ printTrace("%s| Fetching the list of PDP contexts from the radio", getName().c_str());
CODE rc;
+ bool bPdpAuthSupported;
- if (sId.empty()) {
- printError("%s| PDP Context ID is not specified", getName().c_str());
- return FAILURE;
+ // check if pdp context authentication is applicable
+ rc = isPdpContextAuthSupported(bPdpAuthSupported);
+ if (SUCCESS != rc) {
+ return rc;
}
- std::string sCommand = "AT+CGDCONT=" + sId;
- const int dTimeout = 1000;
-
- Json::Value jAllContexts;
+ rc = getPdpContextsBase(jData);
- rc = getPdpContexts(jAllContexts);
- if (rc != SUCCESS) {
- printError("%s| Failed to retrieve the current PDP context configuration: [%d]", getName().c_str(), rc);
+ if (SUCCESS != rc) {
+ printError("%s| Failed to fetch the list of the defined PDP contexts from the radio", getName().c_str());
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);
+ if (bPdpAuthSupported) {
+ rc = fillPdpContextAuthFields(jData);
+
+ if (SUCCESS != rc) {
+ printError("%s| Failed to fetch the authentication parameters for PDP contexts", getName().c_str());
return rc;
- } else {
- printError("%s| PDP Context [%s] does not exist", getName().c_str(), sId.c_str());
- return FAILURE;
}
}
- std::string sIpMode;
+ return SUCCESS;
+}
- 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;
+ICellularRadio::CODE CellularRadio::mergePdpContexts(const std::string& sId, const Json::Value& jCurrentContext, const Json::Value& jChanges, Json::Value& jResult) {
+ jResult[KEY_PDP_CONTEXT_ID] = sId;
+
+ if (jChanges.isMember(KEY_PDP_CONTEXT_IPMODE)) {
+ jResult[KEY_PDP_CONTEXT_IPMODE] = jChanges[KEY_PDP_CONTEXT_IPMODE].asString();
+ } else if (jCurrentContext.isMember(KEY_PDP_CONTEXT_IPMODE)) {
+ printInfo("%s| Re-using IP Mode [%s] for PDP context [%s]", getName().c_str(), jCurrentContext[KEY_PDP_CONTEXT_IPMODE].asString().c_str(), sId.c_str());
+ jResult[KEY_PDP_CONTEXT_IPMODE] = jCurrentContext[KEY_PDP_CONTEXT_IPMODE].asString();
+ }
+
+ if (jChanges.isMember(KEY_PDP_CONTEXT_APN)) {
+ jResult[KEY_PDP_CONTEXT_APN] = jChanges[KEY_PDP_CONTEXT_APN].asString();
+ } else if (jCurrentContext.isMember(KEY_PDP_CONTEXT_APN)) {
+ printInfo("%s| Re-using APN [%s] for PDP context [%s]", getName().c_str(), jCurrentContext[KEY_PDP_CONTEXT_APN].asString().c_str(), sId.c_str());
+ jResult[KEY_PDP_CONTEXT_APN] = jCurrentContext[KEY_PDP_CONTEXT_APN].asString();
+ }
+
+ if (jChanges.isMember(KEY_PDP_CONTEXT_AUTH_TYPE)) {
+ jResult[KEY_PDP_CONTEXT_AUTH_TYPE] = jChanges[KEY_PDP_CONTEXT_AUTH_TYPE].asString();
+ }
+
+ if (jChanges.isMember(KEY_PDP_CONTEXT_AUTH_USERNAME)) {
+ jResult[KEY_PDP_CONTEXT_AUTH_USERNAME] = jChanges[KEY_PDP_CONTEXT_AUTH_USERNAME].asString();
+ }
+
+ if (jChanges.isMember(KEY_PDP_CONTEXT_AUTH_PASSWORD)) {
+ jResult[KEY_PDP_CONTEXT_AUTH_PASSWORD] = jChanges[KEY_PDP_CONTEXT_AUTH_PASSWORD].asString();
+ }
+
+ return SUCCESS;
+}
+
+ICellularRadio::CODE CellularRadio::initPdpContextInfo(const Json::Value& jConfig, PdpContextInfo& pdpContextResult) {
+ // validate IP mode
+ if (jConfig[KEY_PDP_CONTEXT_IPMODE].asString() != VALUE_PDP_CONTEXT_IP_MODE_IP &&
+ jConfig[KEY_PDP_CONTEXT_IPMODE].asString() != VALUE_PDP_CONTEXT_IP_MODE_IPV6 &&
+ jConfig[KEY_PDP_CONTEXT_IPMODE].asString() != VALUE_PDP_CONTEXT_IP_MODE_IPV4V6) {
+ printError("%s| The PDP context IP mode value is invalid [%s]", getName().c_str(), jConfig[KEY_PDP_CONTEXT_IPMODE].asString().c_str());
+ return INVALID_ARGS;
+ }
+
+ // validate authentication fields only if it is present
+ if (jConfig.isMember(KEY_PDP_CONTEXT_AUTH_TYPE)) {
+
+ // check if the PDP context authentication is supported by the radio
+ const auto& sRequested = jConfig[KEY_PDP_CONTEXT_AUTH_TYPE].asString();
+ const auto& vSupported = getSupportedPdpContextAuthTypes();
+
+ auto supportCheck = [sRequested](const std::string& sElement) {
+ return sRequested == sElement;
+ };
+
+ if (std::none_of(vSupported.begin(), vSupported.end(), supportCheck)) {
+ printError("%s| PDP context parameters: authentication type [%s] is not supported", getName().c_str(), jConfig[KEY_PDP_CONTEXT_AUTH_TYPE].asString().c_str());
+ return INVALID_ARGS;
}
- } 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 += "\"";
+ if (! jConfig.isMember(KEY_PDP_CONTEXT_AUTH_TYPE) && (jConfig.isMember(KEY_PDP_CONTEXT_AUTH_USERNAME) || jConfig.isMember(KEY_PDP_CONTEXT_AUTH_PASSWORD))) {
+ printError("%s| PDP context authentication type is not provided, but username or password are given", getName().c_str());
+ return INVALID_ARGS;
+ }
- std::string sApn;
+ if (jConfig.isMember(KEY_PDP_CONTEXT_AUTH_TYPE) && jConfig[KEY_PDP_CONTEXT_AUTH_TYPE].asString() != VALUE_PDP_CONTEXT_AUTH_TYPE_NONE &&
+ ! (jConfig.isMember(KEY_PDP_CONTEXT_AUTH_USERNAME) && jConfig.isMember(KEY_PDP_CONTEXT_AUTH_PASSWORD))) {
+ printError("%s| PDP context authentication type [%s]. The username or password are not provided", getName().c_str(), jConfig[KEY_PDP_CONTEXT_AUTH_TYPE].asString().c_str());
+ return INVALID_ARGS;
+ }
- 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;
+ // fills with empty string if there are no such fields
+ pdpContextResult.sId = jConfig[KEY_PDP_CONTEXT_ID].asString();
+ pdpContextResult.sIpMode = jConfig[KEY_PDP_CONTEXT_IPMODE].asString();
+ pdpContextResult.sApn = jConfig[KEY_PDP_CONTEXT_APN].asString();
+ pdpContextResult.sAuthType = jConfig[KEY_PDP_CONTEXT_AUTH_TYPE].asString();
+ pdpContextResult.sUsername = jConfig[KEY_PDP_CONTEXT_AUTH_USERNAME].asString();
+ pdpContextResult.sPassword = jConfig[KEY_PDP_CONTEXT_AUTH_PASSWORD].asString();
+
+ return SUCCESS;
+}
+
+ICellularRadio::CODE CellularRadio::isPdpContextAuthEditRequired(const Json::Value& jConfig, bool& bIsAuthEditRequired) {
+ bIsAuthEditRequired = false;
+
+ if (jConfig.isMember(KEY_PDP_CONTEXT_AUTH_TYPE) ||
+ jConfig.isMember(KEY_PDP_CONTEXT_AUTH_PASSWORD) ||
+ jConfig.isMember(KEY_PDP_CONTEXT_AUTH_USERNAME)) {
+ bIsAuthEditRequired = true;
}
+ return SUCCESS;
+}
+
+ICellularRadio::CODE CellularRadio::setPdpContextBase(const PdpContextInfo& pdpContext) {
+ std::string sCommand = "AT+CGDCONT=";
+ const int dTimeout = 1000;
+
+ sCommand += pdpContext.sId;
sCommand += ",\"";
- sCommand += sApn;
+ sCommand += pdpContext.sIpMode;
+ sCommand += "\",\"";
+ sCommand += pdpContext.sApn;
sCommand += "\"";
- rc = sendBasicCommand(sCommand, dTimeout);
+ return sendBasicCommand(sCommand, dTimeout);
+}
+
+ICellularRadio::CODE CellularRadio::deletePdpContext(const std::string& sId) {
+ std::string sCommand = "AT+CGDCONT=" + sId;
+ const int dTimeout = 1000;
- return rc;
+ return sendBasicCommand(sCommand, dTimeout);
+}
+
+ICellularRadio::CODE CellularRadio::setPdpContext(const std::string& sId, const Json::Value& jConfig) {
+ printTrace("%s| Setting PDP context [%s] to the radio", getName().c_str(), sId.c_str());
+
+ CODE rc;
+ Json::Value jCurrentContexts;
+ bool bPdpAuthSupported;
+ bool bPdpAuthEditRequired;
+ PdpContextInfo pdpContext;
+
+ if (sId.empty()) {
+ printError("%s| PDP Context ID is not specified", getName().c_str());
+ return INVALID_ARGS;
+ }
+
+ rc = getPdpContexts(jCurrentContexts);
+ if (SUCCESS != rc) {
+ return rc;
+ }
+
+ // DELETE context
+
+ if (jConfig.empty()) {
+ rc = deletePdpContext(sId);
+ if (SUCCESS != rc) {
+ printError("%s| Failed to delete PDP context [%s]", getName().c_str(), sId.c_str());
+ }
+ return rc;
+ }
+
+ // ADD or EDIT context
+
+ // check if PDP context authentication is applicable
+
+ (void) isPdpContextAuthEditRequired(jConfig, bPdpAuthEditRequired);
+
+ rc = isPdpContextAuthSupported(bPdpAuthSupported);
+ if (SUCCESS != rc) {
+ return rc;
+ }
+
+ if (! bPdpAuthSupported && bPdpAuthEditRequired) {
+ printError("%s| PDP context authentication is not supported by this radio, but arguments are provided", getName().c_str());
+ return INVALID_ARGS;
+ }
+
+ Json::Value jResult;
+
+ // Edit - fetch missing arguments from the current state.
+ (void) mergePdpContexts(sId, jCurrentContexts[sId], jConfig, jResult);
+
+ // validate fields and create a PDP context structure to use in the commands
+ rc = initPdpContextInfo(jResult, pdpContext);
+ if (SUCCESS != rc) {
+ return rc;
+ }
+
+ // setting context
+ rc = setPdpContextBase(pdpContext);
+ if (SUCCESS != rc) {
+ return rc;
+ }
+
+ if (bPdpAuthSupported && bPdpAuthEditRequired) {
+ return setPdpContextAuth(pdpContext);
+ }
+
+ return SUCCESS;
}
ICellularRadio::CODE CellularRadio::getDiagnostics(std::string& sReport) {
diff --git a/src/MTS_IO_ICellularRadio.cpp b/src/MTS_IO_ICellularRadio.cpp
index e42713d..f93cb21 100644
--- a/src/MTS_IO_ICellularRadio.cpp
+++ b/src/MTS_IO_ICellularRadio.cpp
@@ -97,8 +97,19 @@ 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_ID = "id";
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::KEY_PDP_CONTEXT_AUTH_TYPE = "authType";
+const char *MTS::IO::ICellularRadio::KEY_PDP_CONTEXT_AUTH_USERNAME = "username";
+const char *MTS::IO::ICellularRadio::KEY_PDP_CONTEXT_AUTH_PASSWORD = "password";
+const char *MTS::IO::ICellularRadio::VALUE_PDP_CONTEXT_IP_MODE_IP = "IP";
+const char *MTS::IO::ICellularRadio::VALUE_PDP_CONTEXT_IP_MODE_IPV6 = "IPV6";
+const char *MTS::IO::ICellularRadio::VALUE_PDP_CONTEXT_IP_MODE_IPV4V6 = "IPV4V6";
+const char *MTS::IO::ICellularRadio::VALUE_PDP_CONTEXT_AUTH_TYPE_NONE = "NONE";
+const char *MTS::IO::ICellularRadio::VALUE_PDP_CONTEXT_AUTH_TYPE_PAP = "PAP";
+const char *MTS::IO::ICellularRadio::VALUE_PDP_CONTEXT_AUTH_TYPE_CHAP = "CHAP";
+const char *MTS::IO::ICellularRadio::VALUE_PDP_CONTEXT_AUTH_TYPE_PAP_CHAP = "PAP-CHAP";
const char *MTS::IO::ICellularRadio::VALUE_TYPE_GSM = "GSM";
const char *MTS::IO::ICellularRadio::VALUE_TYPE_LTE = "LTE";
diff --git a/src/MTS_IO_QuectelRadio.cpp b/src/MTS_IO_QuectelRadio.cpp
index 0c0c8ab..b01bbb1 100644
--- a/src/MTS_IO_QuectelRadio.cpp
+++ b/src/MTS_IO_QuectelRadio.cpp
@@ -1629,6 +1629,114 @@ ICellularRadio::CODE QuectelRadio::setRxDiversity(const Json::Value& jArgs) {
return SUCCESS;
}
+ICellularRadio::CODE QuectelRadio::convertStringToPdpContextType(const std::string& sStringType, std::string& sIntType) {
+ CODE rc = FAILURE;
+
+ if ("IP" == sStringType) {
+ sIntType = "1";
+ rc = SUCCESS;
+ } else if ("IPV6" == sStringType) {
+ sIntType = "2";
+ rc = SUCCESS;
+ } else if ("IPV4V6" == sStringType) {
+ sIntType = "3";
+ rc = SUCCESS;
+ }
+
+ return rc;
+}
+
+std::vector<std::string> QuectelRadio::getSupportedPdpContextAuthTypes() const {
+ return {
+ VALUE_PDP_CONTEXT_AUTH_TYPE_NONE,
+ VALUE_PDP_CONTEXT_AUTH_TYPE_PAP,
+ VALUE_PDP_CONTEXT_AUTH_TYPE_CHAP,
+ VALUE_PDP_CONTEXT_AUTH_TYPE_PAP_CHAP
+ };
+}
+
+ICellularRadio::CODE QuectelRadio::isPdpContextAuthSupported(bool& isSupported) {
+ std::string sCmd("AT+QICSGP=?");
+ return isCommandSupported(sCmd, isSupported);
+}
+
+ICellularRadio::CODE QuectelRadio::fillPdpContextAuthFields(Json::Value& jData) {
+ CODE rc;
+ std::string sCmd("AT+QICSGP=");
+ std::string sResult;
+ uint8_t iValue;
+
+ // iterate over PDP contex IDs to get context settings
+ for (std::string & sContextId : jData.getMemberNames()) {
+ // +QICSGP: <context_type>,<APN>,<username>,<password>,<authentication>
+ // +QICSGP: 0,"","","",0 -- if the context does not exist
+
+ rc = sendBasicQuery(sCmd+sContextId, "+QICSGP:", sResult, 300);
+
+ if (SUCCESS != rc) {
+ return rc;
+ }
+
+ // 1,"test","login","password",1
+ // [0] [1] [2] [3] [4]
+ auto vAuthParams = MTS::Text::split(sResult, ",");
+
+ if (vAuthParams.size() < 5) {
+ printError("%s| Failed to parse PDP context authentication string [%s]", getName().c_str(), sResult.c_str());
+ return FAILURE;
+ }
+
+ if (! MTS::Text::parse(iValue, vAuthParams[4])) {
+ printError("%s| Failed to parse PDP context authentication type [%s]", getName().c_str(), vAuthParams[4].c_str());
+ return FAILURE;
+ }
+
+ rc = convertPdpContextAuthTypeToString(static_cast<PDP_CONTEXT_AUTH_TYPE>(iValue), sResult);
+ if (SUCCESS != rc) {
+ return rc;
+ }
+
+ jData[sContextId][KEY_PDP_CONTEXT_AUTH_TYPE] = sResult;
+
+ if (iValue != PDP_CONTEXT_AUTH_TYPE::NONE) {
+ jData[sContextId][KEY_PDP_CONTEXT_AUTH_USERNAME] = MTS::Text::trim(vAuthParams[2], '"');
+ jData[sContextId][KEY_PDP_CONTEXT_AUTH_PASSWORD] = MTS::Text::trim(vAuthParams[3], '"');
+ }
+ }
+
+ return SUCCESS;
+}
+
+// AT+QICSGP=<contextID>[,<context_type>,<APN>[,<username>,<password>)[,<authentication>[,<cdma_pwd>]]]]
+ICellularRadio::CODE QuectelRadio::setPdpContextAuth(const PdpContextInfo& pdpContext) {
+ printTrace("%s| Setting PDP context authentication to the radio", getName().c_str());
+
+ CODE rc;
+ std::string sContextType;
+ std::string sCmd = "AT+QICSGP=";
+ PDP_CONTEXT_AUTH_TYPE eAuthType;
+
+ rc = convertStringToPdpContextType(pdpContext.sIpMode, sContextType);
+ if (SUCCESS != rc) {
+ return rc;
+ }
+
+ rc = convertStringToPdpContextAuthType(pdpContext.sAuthType, eAuthType);
+ if (SUCCESS != rc) {
+ return rc;
+ }
+
+ sCmd += pdpContext.sId + "," + sContextType + ",\"" + pdpContext.sApn + "\"";
+
+ if (PDP_CONTEXT_AUTH_TYPE::NONE == eAuthType) {
+ sCmd += ",\"\",\"\"," + std::to_string(eAuthType);
+ } else {
+ sCmd += ",\"" + pdpContext.sUsername + "\",\"" + pdpContext.sPassword +"\"," + std::to_string(eAuthType);
+ }
+
+ return sendBasicCommand(sCmd);
+}
+
const std::vector<std::string>& QuectelRadio::getDiagCommands(bool) {
// Declare as static to initialize only when used, but cache the results.
const static std::vector<std::string> vCommands {
diff --git a/src/MTS_IO_SequansRadio.cpp b/src/MTS_IO_SequansRadio.cpp
index a48a309..8133bbf 100644
--- a/src/MTS_IO_SequansRadio.cpp
+++ b/src/MTS_IO_SequansRadio.cpp
@@ -534,6 +534,27 @@ ICellularRadio::CODE SequansRadio::getSimLockAttemptsByType(const std::string& s
return SUCCESS;
}
+std::vector<std::string> SequansRadio::getSupportedPdpContextAuthTypes() const {
+ return {
+ VALUE_PDP_CONTEXT_AUTH_TYPE_NONE,
+ VALUE_PDP_CONTEXT_AUTH_TYPE_PAP,
+ VALUE_PDP_CONTEXT_AUTH_TYPE_CHAP
+ };
+}
+
+ICellularRadio::CODE SequansRadio::isPdpContextAuthSupported(bool& isSupported) {
+ isSupported = false;
+ return SUCCESS;
+}
+
+ICellularRadio::CODE SequansRadio::fillPdpContextAuthFields(Json::Value& jData) {
+ return NOT_APPLICABLE;
+}
+
+ICellularRadio::CODE SequansRadio::setPdpContextAuth(const PdpContextInfo& pdpContext) {
+ return NOT_APPLICABLE;
+}
+
const std::vector<std::string>& SequansRadio::getDiagCommands(bool) {
// Declare as static to initialize only when used, but cache the results.
const static std::vector<std::string> vCommands {
diff --git a/src/MTS_IO_TelitRadio.cpp b/src/MTS_IO_TelitRadio.cpp
index 21af65d..00c1686 100644
--- a/src/MTS_IO_TelitRadio.cpp
+++ b/src/MTS_IO_TelitRadio.cpp
@@ -1178,6 +1178,109 @@ bool MTS::IO::TelitRadio::isContainsSignChar(const std::string& str) {
return true;
}
+std::vector<std::string> TelitRadio::getSupportedPdpContextAuthTypes() const {
+ return {
+ VALUE_PDP_CONTEXT_AUTH_TYPE_NONE,
+ VALUE_PDP_CONTEXT_AUTH_TYPE_PAP,
+ VALUE_PDP_CONTEXT_AUTH_TYPE_CHAP
+ };
+}
+
+ICellularRadio::CODE TelitRadio::isPdpContextAuthSupported(bool& isSupported) {
+ std::string sCmd("AT#PDPAUTH=?");
+ return isCommandSupported(sCmd, isSupported);
+}
+
+ICellularRadio::CODE TelitRadio::fillPdpContextAuthFields(Json::Value& jData) {
+ CODE rc;
+ std::string sCmd("AT#PDPAUTH?");
+ std::string sResult;
+
+ // #PDPAUTH: 1,0
+ // #PDPAUTH: 2,0
+ // #PDPAUTH: 3,0
+ // #PDPAUTH: 4,1,"admin"
+ rc = sendBasicQuery(sCmd, "", sResult, 300);
+
+ if (SUCCESS != rc) {
+ return rc;
+ }
+
+ std::vector<std::string> vContexts = MTS::Text::split(sResult, "#PDPAUTH:");
+ std::string sContextId;
+
+ for (std::string& sLine : vContexts) {
+ sLine = MTS::Text::trim(sLine);
+
+ if (sLine.empty()) {
+ continue;
+ }
+
+ // 4,1,"admin"
+ // [0][1] [2]
+ auto vAuthParams = MTS::Text::split(sLine, ",");
+
+ // Contains 2 elements when the authentication type is NONE, contains 3 elements in other cases
+ if (vAuthParams.size() < 2) {
+ printError("%s| Failed to parse PDP context authentication string [%s]", getName().c_str(), sLine.c_str());
+ return FAILURE;
+ }
+
+ sContextId = vAuthParams[0];
+
+ uint8_t iValue;
+ if (! MTS::Text::parse(iValue, vAuthParams[1])) {
+ printError("%s| Failed to parse PDP context authentication type [%s]", getName().c_str(), vAuthParams[1].c_str());
+ return FAILURE;
+ }
+
+ rc = convertPdpContextAuthTypeToString(static_cast<PDP_CONTEXT_AUTH_TYPE>(iValue), sResult);
+ if (SUCCESS != rc) {
+ printError("%s| Failed to convert PDP context authentication type to string [%d]", getName().c_str(), iValue);
+ return rc;
+ }
+
+ jData[sContextId][KEY_PDP_CONTEXT_AUTH_TYPE] = sResult;
+
+ if (iValue == PDP_CONTEXT_AUTH_TYPE::NONE) {
+ continue;
+ }
+
+ if (vAuthParams.size() < 3) {
+ printError("%s| Failed to parse PDP context authentication string [%s]", getName().c_str(), sLine.c_str());
+ return FAILURE;
+ }
+
+ jData[sContextId][KEY_PDP_CONTEXT_AUTH_USERNAME] = MTS::Text::trim(vAuthParams[2], '"');
+ }
+
+ return SUCCESS;
+}
+
+ICellularRadio::CODE TelitRadio::setPdpContextAuth(const PdpContextInfo& pdpContext) {
+ printTrace("%s| Setting PDP context authentication to the radio", getName().c_str());
+
+ CODE rc;
+ std::string sCmd = "AT#PDPAUTH=";
+ PDP_CONTEXT_AUTH_TYPE eAuthType;
+
+ sCmd += pdpContext.sId + ",";
+
+ rc = convertStringToPdpContextAuthType(pdpContext.sAuthType, eAuthType);
+
+ if (SUCCESS != rc) {
+ return rc;
+ }
+
+ sCmd += std::to_string(eAuthType);
+
+ if (PDP_CONTEXT_AUTH_TYPE::NONE != eAuthType) {
+ sCmd += "," + pdpContext.sUsername + "," + pdpContext.sPassword;
+ }
+
+ return sendBasicCommand(sCmd);
+}
+
const std::vector<std::string>& TelitRadio::getDiagCommands(bool) {
// Declare as static to initialize only when used, but cache the results.
const static std::vector<std::string> vCommands {