summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeff Hatch <jhatch@multitech.com>2019-08-13 08:02:32 -0500
committerJeff Hatch <jhatch@multitech.com>2019-08-13 08:02:32 -0500
commit07eb755bbdc2700f31ff4e5fd9a7ac04a14e69e8 (patch)
treed1b30c78bbb2e81576cf193a7be809c0a2e0676b
parentf6f7d0e174d2bf5eb4494e2508c17d3d7fbdc4e9 (diff)
parent4e5c4eb9d3b9a8974429810ebe5afc3387753643 (diff)
downloadlibmts-io-07eb755bbdc2700f31ff4e5fd9a7ac04a14e69e8.tar.gz
libmts-io-07eb755bbdc2700f31ff4e5fd9a7ac04a14e69e8.tar.bz2
libmts-io-07eb755bbdc2700f31ff4e5fd9a7ac04a14e69e8.zip
Merge branch 'MTX-2891-mpower-2g-3g-4g' into 'master'
Mtx 2891 mpower 2g 3g 4g See merge request !2
-rw-r--r--Makefile5
-rw-r--r--include/mts/MTS_IO_CellularRadio.h1
-rw-r--r--include/mts/MTS_IO_EG95Radio.h5
-rw-r--r--include/mts/MTS_IO_ICellularRadio.h18
-rw-r--r--include/mts/MTS_IO_QuectelRadio.h2
-rw-r--r--include/mts/MTS_IO_TelitRadio.h6
-rw-r--r--src/MTS_IO_CellularRadio.cpp28
-rw-r--r--src/MTS_IO_EG95Radio.cpp43
-rw-r--r--src/MTS_IO_QuectelRadio.cpp42
-rw-r--r--src/MTS_IO_TelitRadio.cpp148
10 files changed, 203 insertions, 95 deletions
diff --git a/Makefile b/Makefile
index 8472075..8e71154 100644
--- a/Makefile
+++ b/Makefile
@@ -41,8 +41,7 @@ OBJS += \
src/MTS_IO_SerialConnection.o
CC := $(CXX)
-#-Werror
-CXXFLAGS += -Wall -std=c++0x -fmessage-length=0 -fPIC -fvisibility=hidden -fvisibility-inlines-hidden
+CXXFLAGS += -Wall -Werror -std=c++0x -fmessage-length=0 -fPIC -fvisibility=hidden -fvisibility-inlines-hidden
CPPFLAGS += -I=/usr/include/jsoncpp -Iinclude
LDFLAGS += -s -shared -Wl,-soname,$(APPNAME).so.0
@@ -54,7 +53,7 @@ $(APPNAME).a: $(OBJS)
$(AR) -rs $@ $?
$(SONAME): $(OBJS)
- $(CC) $(LDFLAGS) -o $@ $? $(LDLIBS)
+ $(CC) $(LDFLAGS) -o $@ $+ $(LDLIBS)
# Handle header dependencies
DEPS = $(OBJS:.o=.d)
diff --git a/include/mts/MTS_IO_CellularRadio.h b/include/mts/MTS_IO_CellularRadio.h
index eecefee..1e80274 100644
--- a/include/mts/MTS_IO_CellularRadio.h
+++ b/include/mts/MTS_IO_CellularRadio.h
@@ -70,6 +70,7 @@ namespace MTS {
CODE getTower(std::string& sTower) override;
CODE getTime(std::string& sDate, std::string& sTime, std::string& sTimeZone) override;
CODE getRoaming(bool& bRoaming) override;
+ CODE getCellularMode(CELLULAR_MODES &networks) override;
CODE getSignalStrength(int32_t& iRssi) override;
CODE getModemLocation(std::string& sLocation) override;
diff --git a/include/mts/MTS_IO_EG95Radio.h b/include/mts/MTS_IO_EG95Radio.h
index f3021cc..5296e16 100644
--- a/include/mts/MTS_IO_EG95Radio.h
+++ b/include/mts/MTS_IO_EG95Radio.h
@@ -34,12 +34,13 @@ namespace MTS {
EG95Radio(const std::string& sPort);
virtual ~EG95Radio();
- CODE setRxDiversity(const Json::Value& jArgs);
+ CODE setRxDiversity(const Json::Value& jArgs) override;
protected:
private:
-
+ CODE getSupportedCellularModes(CELLULAR_MODES &networks) override;
+ CODE setCellularMode(CELLULAR_MODES networks) override;
};
}
}
diff --git a/include/mts/MTS_IO_ICellularRadio.h b/include/mts/MTS_IO_ICellularRadio.h
index e2bf652..57d6f53 100644
--- a/include/mts/MTS_IO_ICellularRadio.h
+++ b/include/mts/MTS_IO_ICellularRadio.h
@@ -60,12 +60,12 @@ namespace MTS {
NOT_INSERTED
};
- enum RADIO_NETWORK_MODE : uint8_t {
- RADIO_NETWORK_MODE_UNKNOWN = 0,
- RADIO_NETWORK_MODE_AUTO,
- RADIO_NETWORK_MODE_GSM_ONLY,
- RADIO_NETWORK_MODE_UMTS_ONLY,
- RADIO_NETWORK_MODE_LTE_ONLY
+ enum CELLULAR_MODES : uint8_t {
+ CELLULAR_MODE_NA = 0, // NOT AVAILABLE
+ CELLULAR_MODE_2G = 1 << 0, // GSM
+ CELLULAR_MODE_3G = 1 << 1, // WCDMA
+ CELLULAR_MODE_4G = 1 << 2, // LTE
+ CELLULAR_MODE_5G = 1 << 3 // 5G
};
static CODE convertModelToType(const std::string& sModel, std::string& sType);
@@ -220,6 +220,10 @@ namespace MTS {
virtual CODE getImsi(std::string& sImsi) = 0;
virtual CODE getSimStatus(std::string& sSimStatus) = 0;
+ virtual CODE getSupportedCellularModes(CELLULAR_MODES &networks) = 0;
+ virtual CODE getCellularMode(CELLULAR_MODES &networks) = 0;
+ virtual CODE setCellularMode(CELLULAR_MODES networks) = 0;
+
/**
* @brief getSimStatusSummary - get summary on the SIM card status
* (if there is a SIM card inserted, is it locked, etc).
@@ -281,8 +285,6 @@ namespace MTS {
* or on any other error).
*/
virtual CODE unlockSimCard(const Json::Value& jArgs) = 0;
- virtual CODE getRadioNetworkMode(RADIO_NETWORK_MODE &mode) = 0;
- virtual CODE setRadioNetworkMode(RADIO_NETWORK_MODE mode) = 0;
//! Gather details of the radio's Mobile IP Profile
/*!
diff --git a/include/mts/MTS_IO_QuectelRadio.h b/include/mts/MTS_IO_QuectelRadio.h
index 3b1ba5a..df3b5b5 100644
--- a/include/mts/MTS_IO_QuectelRadio.h
+++ b/include/mts/MTS_IO_QuectelRadio.h
@@ -41,8 +41,6 @@ namespace MTS {
CODE convertdBmToSignalStrength(const int32_t& dBm, int32_t& iRssi) override;
CODE setMdn(const Json::Value& jArgs) override;
- CODE getRadioNetworkMode(RADIO_NETWORK_MODE &mode) override;
- CODE setRadioNetworkMode(RADIO_NETWORK_MODE mode) override;
protected:
QuectelRadio(const std::string& sName, const std::string& sRadioPort);
diff --git a/include/mts/MTS_IO_TelitRadio.h b/include/mts/MTS_IO_TelitRadio.h
index 6382696..b81cd7d 100644
--- a/include/mts/MTS_IO_TelitRadio.h
+++ b/include/mts/MTS_IO_TelitRadio.h
@@ -39,8 +39,9 @@ namespace MTS {
CODE convertdBmToSignalStrength(const int32_t& dBm, int32_t& iRssi) override;
CODE setMdn(const Json::Value& jArgs) override;
- CODE getRadioNetworkMode(RADIO_NETWORK_MODE &mode) override;
- CODE setRadioNetworkMode(RADIO_NETWORK_MODE mode) override;
+
+ CODE getSupportedCellularModes(CELLULAR_MODES &networks) override;
+ CODE setCellularMode(CELLULAR_MODES networks) override;
protected:
TelitRadio(const std::string& sName, const std::string& sRadioPort);
@@ -53,6 +54,7 @@ namespace MTS {
private:
virtual CODE getSimLockAttempts(int& iAttemptsPin, int& iAttemptsPuk, const std::string& sLockStatus);
+ static ICellularRadio::CELLULAR_MODES preferredNetwork(CELLULAR_MODES prefNetwork, int wds);
};
}
diff --git a/src/MTS_IO_CellularRadio.cpp b/src/MTS_IO_CellularRadio.cpp
index 3f0c037..6df92e0 100644
--- a/src/MTS_IO_CellularRadio.cpp
+++ b/src/MTS_IO_CellularRadio.cpp
@@ -770,6 +770,34 @@ ICellularRadio::CODE CellularRadio::getRegistration(REGISTRATION& eRegistration)
return SUCCESS;
}
+ICellularRadio::CODE CellularRadio::getCellularMode(CELLULAR_MODES &networks) {
+ networks = CELLULAR_MODE_NA;
+ std::string cmdResult = sendCommand("AT+COPS?");
+ if (cmdResult.find(ICellularRadio::RSP_OK) == std::string::npos) {
+ printError("%s| AT+COPS returned unexpected response: AT+COPS? [%s]", getName().c_str(), cmdResult.c_str());
+ return FAILURE;
+ }
+
+ size_t cursor = 0;
+ const std::vector<std::string> &reply = MTS::Text::split(MTS::Text::getLine(MTS::Text::trim(cmdResult), cursor, cursor), ',');
+ uint8_t op;
+ if (reply.size() < 4 || !MTS::Text::parse(op, reply[3])) {
+ printError("%s| AT+COPS Error parsing reply [AT+COPS?][%s]", getName().c_str(), cmdResult.c_str());
+ return FAILURE;
+ }
+ if (op == 0) {
+ networks = CELLULAR_MODE_2G;
+ } else if (op >= 2 && op <= 6) {
+ networks = CELLULAR_MODE_3G;
+ } else if (op == 7) {
+ networks = CELLULAR_MODE_4G;
+ } else {
+ printError("%s| AT+COPS unknown Radio Access Technology [AT+COPS?][%s]", getName().c_str(), cmdResult.c_str());
+ return FAILURE;
+ }
+ return SUCCESS;
+}
+
ICellularRadio::CODE CellularRadio::convertRegistrationToString(REGISTRATION eRegistration, std::string& sRegistration) {
ICellularRadio::CODE eCode = FAILURE;
diff --git a/src/MTS_IO_EG95Radio.cpp b/src/MTS_IO_EG95Radio.cpp
index 5c9ed69..aff53d2 100644
--- a/src/MTS_IO_EG95Radio.cpp
+++ b/src/MTS_IO_EG95Radio.cpp
@@ -21,6 +21,11 @@
#include <mts/MTS_IO_EG95Radio.h>
+#include <climits>
+
+#include <mts/MTS_Logger.h>
+#include <mts/MTS_Text.h>
+
using namespace MTS::IO;
const std::string EG95Radio::MODEL_NAME("EG95");
@@ -45,3 +50,41 @@ ICellularRadio::CODE EG95Radio::setRxDiversity(const Json::Value& jArgs) {
return sendBasicCommand(sCmd);
}
+
+ICellularRadio::CODE EG95Radio::getSupportedCellularModes(CELLULAR_MODES &networks) {
+ networks = static_cast<CELLULAR_MODES>(CELLULAR_MODE_2G | CELLULAR_MODE_3G | CELLULAR_MODE_4G);
+ return SUCCESS;
+}
+
+ICellularRadio::CODE EG95Radio::setCellularMode(CELLULAR_MODES networks) {
+ std::string prefNet;
+ unsigned int prefOnly = 0;
+ for (int i = sizeof(networks)*CHAR_BIT-1; i>=0; --i){
+ switch (1<<i & networks) {
+ case ICellularRadio::CELLULAR_MODE_2G: prefNet += "01" ; prefOnly = 1; break;
+ case ICellularRadio::CELLULAR_MODE_3G: prefNet += "0302"; prefOnly = 2; break;
+ case ICellularRadio::CELLULAR_MODE_4G: prefNet += "04" ; prefOnly = 3; break;
+ default: printError("Unhandled preferred network flag.");
+ }
+ }
+
+ std::string sCmd;
+ if (prefNet.size() == 2) { // *g-only
+ sCmd = "AT+QCFG=\"nwscanmode\"," + std::to_string(prefOnly);
+ } else { // preferred
+ sCmd = "AT+QCFG=\"nwscanmode\",0";
+ }
+ std::string cmdResult = sendCommand(sCmd);
+ if (cmdResult.find(ICellularRadio::RSP_OK) == std::string::npos) {
+ printError("%s| AT+QCFG=\"nwscanmode\" returned unexpected response: [%s][%s]", getName().c_str(), sCmd.c_str(), cmdResult.c_str());
+ return FAILURE;
+ }
+
+ sCmd = "AT+QCFG=\"nwscanseq\"," + prefNet;
+ cmdResult = sendCommand(sCmd);
+ if (cmdResult.find(ICellularRadio::RSP_OK) == std::string::npos) {
+ printError("%s| AT+QCFG=\"nwscanseq\" returned unexpected response: [%s][%s]", getName().c_str(), sCmd.c_str(), cmdResult.c_str());
+ return FAILURE;
+ }
+ return SUCCESS;
+}
diff --git a/src/MTS_IO_QuectelRadio.cpp b/src/MTS_IO_QuectelRadio.cpp
index f3227a5..c4bdc56 100644
--- a/src/MTS_IO_QuectelRadio.cpp
+++ b/src/MTS_IO_QuectelRadio.cpp
@@ -215,7 +215,6 @@ CellularRadio::CODE QuectelRadio::getNetworkStatus(Json::Value& jData) {
const std::string RAT_WCDMA = "WCDMA";
const std::string RAT_LTE = "LTE";
- int32_t iValue;
ACTIVEBAND abnd;
SERVICEDOMAIN sd;
std::string sValue;
@@ -569,44 +568,3 @@ ICellularRadio::CODE QuectelRadio::convertToActiveBand(const std::string& sQuect
return SUCCESS;
}
-
-ICellularRadio::CODE QuectelRadio::getRadioNetworkMode(RADIO_NETWORK_MODE &mode)
-{
- // AT+QCFG="nwscanmode" execution can take up to 300ms according to the datasheet. Setting timeout to 500ms just for sure.
- std::string sCmd("AT+QCFG=\"nwscanmode\"");
- std::string cmdResult = sendCommand(sCmd, DEFAULT_BAIL_STRINGS, 500);
-
- if (cmdResult.find(ICellularRadio::RSP_OK) == std::string::npos) {
- printDebug("%s| AT+QCFG? returned unexpected response: [%s][%s]", getName().c_str(), sCmd.c_str(), cmdResult.c_str());
- return FAILURE;
- }
- switch (stoi(MTS::Text::split(cmdResult, ',')[1])) {
- case 1: mode = ICellularRadio::RADIO_NETWORK_MODE_GSM_ONLY; break;
- case 5: mode = ICellularRadio::RADIO_NETWORK_MODE_UMTS_ONLY; break;
- case 0: mode = ICellularRadio::RADIO_NETWORK_MODE_AUTO; break;
- default: mode = ICellularRadio::RADIO_NETWORK_MODE_UNKNOWN; break;
- }
- return SUCCESS;
-}
-
-ICellularRadio::CODE QuectelRadio::setRadioNetworkMode(RADIO_NETWORK_MODE mode)
-{
- std::string value;
- switch (mode) {
- case ICellularRadio::RADIO_NETWORK_MODE_GSM_ONLY: value = "1"; break;
- case ICellularRadio::RADIO_NETWORK_MODE_UMTS_ONLY: value = "5"; break;
- case ICellularRadio::RADIO_NETWORK_MODE_AUTO: value = "0"; break;
- default: return FAILURE;
- }
- std::string sCmd("AT+QCFG=\"nwscanmode\",");
- sCmd += value;
-
- // AT+QCFG="nwscanmode" execution can take up to 300ms according to the datasheet. Setting timeout to 500ms just for sure.
- std::string cmdResult = sendCommand(sCmd, DEFAULT_BAIL_STRINGS, 500);
-
- if (cmdResult.find(ICellularRadio::RSP_OK) == std::string::npos) {
- printDebug("%s| AT+QCFG? returned unexpected response: [%s][%s]", getName().c_str(), sCmd.c_str(), cmdResult.c_str());
- return FAILURE;
- }
- return SUCCESS;
-}
diff --git a/src/MTS_IO_TelitRadio.cpp b/src/MTS_IO_TelitRadio.cpp
index 340c0ac..5b8e55d 100644
--- a/src/MTS_IO_TelitRadio.cpp
+++ b/src/MTS_IO_TelitRadio.cpp
@@ -538,42 +538,6 @@ bool TelitRadio::getHardwareVersionFromFirmware(const std::string& sFirmware, st
}
-ICellularRadio::CODE TelitRadio::getRadioNetworkMode(RADIO_NETWORK_MODE &mode)
-{
- std::string sCmd("AT+WS46?");
- std::string cmdResult = sendCommand(sCmd);
- if (cmdResult.find("+WS46:") == std::string::npos) {
- printDebug("%s| AT+WS46? returned unexpected response: [%s][%s]", getName().c_str(), sCmd.c_str(), cmdResult.c_str());
- return FAILURE;
- }
- switch (stoi(MTS::Text::split(cmdResult, ':')[1])) {
- case 12: mode = ICellularRadio::RADIO_NETWORK_MODE_GSM_ONLY; break;
- case 22: mode = ICellularRadio::RADIO_NETWORK_MODE_UMTS_ONLY; break;
- case 25: mode = ICellularRadio::RADIO_NETWORK_MODE_AUTO; break;
- default: mode = ICellularRadio::RADIO_NETWORK_MODE_UNKNOWN; break;
- }
- return SUCCESS;
-}
-
-ICellularRadio::CODE TelitRadio::setRadioNetworkMode(RADIO_NETWORK_MODE mode)
-{
- std::string value;
- switch (mode) {
- case ICellularRadio::RADIO_NETWORK_MODE_GSM_ONLY: value = "12"; break;
- case ICellularRadio::RADIO_NETWORK_MODE_UMTS_ONLY: value = "22"; break;
- case ICellularRadio::RADIO_NETWORK_MODE_AUTO: value = "25"; break;
- default: return FAILURE;
- }
- std::string sCmd("AT+WS46=");
- sCmd += value;
- std::string cmdResult = sendCommand(sCmd);
- if (cmdResult.find(ICellularRadio::RSP_OK) == std::string::npos) {
- printDebug("%s| AT+WS46? returned unexpected response: [%s][%s]", getName().c_str(), sCmd.c_str(), cmdResult.c_str());
- return FAILURE;
- }
- return SUCCESS;
-}
-
ICellularRadio::CODE TelitRadio::getIsSimInserted(bool& bData) {
printTrace("%s| Get SIM insertion status", getName().c_str());
std::string sCmd("AT#SIMDET?");
@@ -664,3 +628,115 @@ ICellularRadio::CODE TelitRadio::getSimLockAttempts(int& iAttemptsPin, int& iAtt
return SUCCESS;
}
+
+ICellularRadio::CODE TelitRadio::getSupportedCellularModes(CELLULAR_MODES &networks) {
+ networks = CELLULAR_MODE_NA;
+ std::string sCmd("AT+WS46=?");
+ std::string cmdResult = sendCommand(sCmd);
+ if (cmdResult.find("+WS46:") == std::string::npos) {
+ printError("%s| AT+WS46=? returned unexpected response: [%s][%s]", getName().c_str(), sCmd.c_str(), cmdResult.c_str());
+ return FAILURE;
+ }
+
+ if (cmdResult.find('(') == std::string::npos) {
+ printError("AT+WS46: error responce %s", cmdResult.c_str());
+ return FAILURE;
+ }
+ std::string s = MTS::Text::split(cmdResult, '(')[1];
+ s = MTS::Text::split(s, ')')[0];
+ std::vector<std::string>v = MTS::Text::split(s, ',');
+ std::vector<int> m;
+ for(const auto &it : v)
+ {
+ if (it.find("-") != std::string::npos) {
+ const std::vector<std::string> &r = MTS::Text::split(it, "-");
+ int begin, end;
+ if ( ! MTS::Text::parse(begin, r[0]) || ! MTS::Text::parse(end, r[1])) {
+ printError("AT+WS46: error parsing network mode range: %s-%s", r[0].c_str(), r[1].c_str());
+ return FAILURE;
+ }
+ for (int i = begin; i<=end; ++i) {
+ m.push_back(i);
+ if (m.size()>1024)
+ break;
+ }
+ } else {
+ int v;
+ if ( ! MTS::Text::parse(v, it)) {
+ printError("AT+WS46: error parsing network mode: %s", it.c_str());
+ return FAILURE;
+ }
+ m.push_back(v);
+ }
+ }
+ if (m.size()>1024) {
+ printError("AT+WS46: network modes count overflow, parsing error");
+ return FAILURE;
+ }
+
+ // Now m contains all network modes
+ for(const auto &it : m) {
+ networks = preferredNetwork(networks, it);
+ }
+
+ return SUCCESS;
+}
+
+ICellularRadio::CODE TelitRadio::setCellularMode(CELLULAR_MODES networks) {
+ int wds = 0;
+ // 3GPP TS 27.007
+ // https://portal.3gpp.org/desktopmodules/Specifications/SpecificationDetails.aspx?specificationId=1515
+ switch (static_cast<int>(networks)) {
+ case CELLULAR_MODE_2G : wds = 12; break;
+ case CELLULAR_MODE_3G : wds = 22; break;
+ case CELLULAR_MODE_2G | CELLULAR_MODE_3G | CELLULAR_MODE_4G : wds = 25; break;
+ case CELLULAR_MODE_4G : wds = 28; break;
+ case CELLULAR_MODE_2G | CELLULAR_MODE_3G : wds = 29; break;
+ case CELLULAR_MODE_2G | CELLULAR_MODE_4G : wds = 30; break;
+ case CELLULAR_MODE_3G | CELLULAR_MODE_4G : wds = 31; break;
+ case CELLULAR_MODE_2G | CELLULAR_MODE_3G | CELLULAR_MODE_4G | CELLULAR_MODE_5G: wds = 35; break;
+ case CELLULAR_MODE_5G: wds = 36; break;
+ case CELLULAR_MODE_4G | CELLULAR_MODE_5G: wds = 37; break;
+ case CELLULAR_MODE_3G | CELLULAR_MODE_4G | CELLULAR_MODE_5G: wds = 38; break;
+ case CELLULAR_MODE_2G | CELLULAR_MODE_4G | CELLULAR_MODE_5G: wds = 39; break;
+ case CELLULAR_MODE_3G | CELLULAR_MODE_5G: wds = 40; break;
+ case CELLULAR_MODE_2G | CELLULAR_MODE_3G | CELLULAR_MODE_5G: wds = 41; break;
+ case CELLULAR_MODE_2G | CELLULAR_MODE_5G: wds = 42; break;
+ }
+ std::string sCmd("AT+WS46=");
+ sCmd += std::to_string(wds);
+ std::string cmdResult = sendCommand(sCmd);
+ if (cmdResult.find(ICellularRadio::RSP_OK) == std::string::npos) {
+ printError("%s| AT+WS46= returned unexpected response: [%s][%s]", getName().c_str(), sCmd.c_str(), cmdResult.c_str());
+ return FAILURE;
+ }
+ return SUCCESS;
+}
+
+ICellularRadio::CELLULAR_MODES TelitRadio::preferredNetwork(CELLULAR_MODES prefNetwork, int wds)
+{
+ int result = prefNetwork;
+ // 3GPP TS 27.007
+ // https://portal.3gpp.org/desktopmodules/Specifications/SpecificationDetails.aspx?specificationId=1515
+ switch (wds) {
+ case 12: result |= CELLULAR_MODE_2G; break;
+ case 22: result |= CELLULAR_MODE_3G; break;
+ case 25: result |= CELLULAR_MODE_2G | CELLULAR_MODE_3G | CELLULAR_MODE_4G; break;
+ case 28: result |= CELLULAR_MODE_4G; break;
+ case 29: result |= CELLULAR_MODE_2G | CELLULAR_MODE_3G; break;
+ case 30: result |= CELLULAR_MODE_2G | CELLULAR_MODE_4G; break;
+ case 31: result |= CELLULAR_MODE_3G | CELLULAR_MODE_4G; break;
+ case 35: result |= CELLULAR_MODE_2G | CELLULAR_MODE_3G | CELLULAR_MODE_4G | CELLULAR_MODE_5G; break;
+ case 36: result |= CELLULAR_MODE_5G; break;
+ case 37: result |= CELLULAR_MODE_4G | CELLULAR_MODE_5G; break;
+ case 38: result |= CELLULAR_MODE_3G | CELLULAR_MODE_4G | CELLULAR_MODE_5G; break;
+ case 39: result |= CELLULAR_MODE_2G | CELLULAR_MODE_4G | CELLULAR_MODE_5G; break;
+ case 40: result |= CELLULAR_MODE_3G | CELLULAR_MODE_5G; break;
+ case 41: result |= CELLULAR_MODE_2G | CELLULAR_MODE_3G | CELLULAR_MODE_5G; break;
+ case 42: result |= CELLULAR_MODE_2G | CELLULAR_MODE_5G; break;
+ default:
+ printError("AT+WS46: unhandled network mode: %d", wds);
+ break;
+ }
+ return static_cast<CELLULAR_MODES>(result);
+}