diff options
| -rw-r--r-- | include/mts/MTS_IO_ICellularRadio.h | 10 | ||||
| -rw-r--r-- | include/mts/MTS_IO_QuectelRadio.h | 12 | ||||
| -rw-r--r-- | src/MTS_IO_ICellularRadio.cpp | 14 | ||||
| -rw-r--r-- | src/MTS_IO_QuectelRadio.cpp | 153 | 
4 files changed, 185 insertions, 4 deletions
| diff --git a/include/mts/MTS_IO_ICellularRadio.h b/include/mts/MTS_IO_ICellularRadio.h index e8ae891..c35e903 100644 --- a/include/mts/MTS_IO_ICellularRadio.h +++ b/include/mts/MTS_IO_ICellularRadio.h @@ -70,10 +70,12 @@ namespace MTS {                  enum UE_MODES_OF_OPERATION : uint8_t {                      UNKNOWN_MODE = 0, // current mode of operation is not available -                    PS_MODE1, // only EPS (LTE) services are allowed, the usage is “voice centric” -                    PS_MODE2, // only EPS (LTE) services are allowed, the usage is “data centric” -                    CS_PS_MODE1, // both EPS and non-EPS services are allowed, the usage is “voice centric” -                    CS_PS_MODE2 // both EPS and non-EPS services are allowed, the usage is “data centric” +                    PS_MODE1, // only EPS (LTE) services are allowed, the usage is "voice centric" +                    PS_MODE2, // only EPS (LTE) services are allowed, the usage is "data centric" +                    CS_PS_MODE1, // both EPS and non-EPS services are allowed, the usage is "voice centric" +                    CS_PS_MODE2, // both EPS and non-EPS services are allowed, the usage is "data centric" +                    CS_MODE1, // only non-EPS services are allowed, the usage is "voice centric" +                    CS_MODE2 // only non-EPS services are allowed, the usage is "data centric"                  };                  static CODE convertModelToType(const std::string& sModel, std::string& sType); diff --git a/include/mts/MTS_IO_QuectelRadio.h b/include/mts/MTS_IO_QuectelRadio.h index 9713f48..04c0ef9 100644 --- a/include/mts/MTS_IO_QuectelRadio.h +++ b/include/mts/MTS_IO_QuectelRadio.h @@ -51,7 +51,16 @@ namespace MTS {                  CODE fumoLocalCleanup() override;                  CODE fumoLocalApply(UpdateCb& stepCb) override; +                CODE setUeModeOfOperation(UE_MODES_OF_OPERATION mode) override; +                CODE getUeModeOfOperation(UE_MODES_OF_OPERATION& mode) override; +              protected: +                enum class UE_USAGE_SETTING : uint8_t { +                    UNKNOWN_MODE = 0, // Unknown mode +                    MODE_1, // Voice centric mode +                    MODE_2 // Data centric mode +                }; +                  QuectelRadio(const std::string& sName, const std::string& sRadioPort);                  CODE getIsSimInserted(bool& bData) override; @@ -64,6 +73,9 @@ namespace MTS {                  virtual CODE removeFile(const std::string& sTargetFilename);                  virtual CODE checkFile(bool& bFilePresent, const std::string& sTargetFilename); +                virtual CODE getUeUsageSetting(UE_USAGE_SETTING& us); +                virtual CODE convertToUeUsageSetting(const std::string& sSetting, UE_USAGE_SETTING& us); +              private:                  // private variable to save old firmware versions during FOTA                  std::string m_sQuectelFirmware; diff --git a/src/MTS_IO_ICellularRadio.cpp b/src/MTS_IO_ICellularRadio.cpp index 9f63408..1fbad0c 100644 --- a/src/MTS_IO_ICellularRadio.cpp +++ b/src/MTS_IO_ICellularRadio.cpp @@ -532,6 +532,14 @@ MTS::IO::ICellularRadio::CODE MTS::IO::ICellularRadio::convertUeModeToString(MTS              string = "csps_2";              rc = CODE::SUCCESS;              break; +        case ICellularRadio::UE_MODES_OF_OPERATION::CS_MODE1: +            string = "cs_1"; +            rc = CODE::SUCCESS; +            break; +        case ICellularRadio::UE_MODES_OF_OPERATION::CS_MODE2: +            string = "cs_2"; +            rc = CODE::SUCCESS; +            break;          default:              string = MTS::IO::ICellularRadio::VALUE_UNKNOWN;              rc = CODE::FAILURE; @@ -555,6 +563,12 @@ MTS::IO::ICellularRadio::CODE MTS::IO::ICellularRadio::convertStringToUeMode(con      } else if (sMode == "csps_2") {          mode = ICellularRadio::UE_MODES_OF_OPERATION::CS_PS_MODE2;          rc = CODE::SUCCESS; +    } else if (sMode == "cs_1") { +        mode = ICellularRadio::UE_MODES_OF_OPERATION::CS_MODE1; +        rc = CODE::SUCCESS; +    } else if (sMode == "cs_2") { +        mode = ICellularRadio::UE_MODES_OF_OPERATION::CS_MODE2; +        rc = CODE::SUCCESS;      } else {          mode = ICellularRadio::UNKNOWN_MODE;          rc = CODE::FAILURE; diff --git a/src/MTS_IO_QuectelRadio.cpp b/src/MTS_IO_QuectelRadio.cpp index aeb06ab..4f20627 100644 --- a/src/MTS_IO_QuectelRadio.cpp +++ b/src/MTS_IO_QuectelRadio.cpp @@ -1221,3 +1221,156 @@ ICellularRadio::CODE QuectelRadio::abortFileUpload() {      sleep(1);      return sendBasicCommand(CMD_ABORT_UPLOAD, 2000, 0x00);  } + +ICellularRadio::CODE QuectelRadio::setUeModeOfOperation(UE_MODES_OF_OPERATION mode) { +    std::string sDomain, sPreference; + +    switch (mode) { +        case UE_MODES_OF_OPERATION::CS_MODE1: +            sDomain = "0"; +            sPreference = "00"; +            break; +        case UE_MODES_OF_OPERATION::CS_MODE2: +            sDomain = "0"; +            sPreference = "01"; +            break; +        case UE_MODES_OF_OPERATION::PS_MODE1: +            sDomain = "1"; +            sPreference = "00"; +            break; +        case UE_MODES_OF_OPERATION::PS_MODE2: +            sDomain = "1"; +            sPreference = "01"; +            break; +        case UE_MODES_OF_OPERATION::CS_PS_MODE1: +            sDomain = "2"; +            sPreference = "00"; +            break; +        case UE_MODES_OF_OPERATION::CS_PS_MODE2: +            sDomain = "2"; +            sPreference = "01"; +            break; +        default: +            printTrace("Set UE Mode Of Operation: invalid argument"); +            return INVALID_ARGS; +    } + +    CODE rc; +    const int dTimeout = 1000; // ms +    std::string sCommand = "AT+QNVFW=\"/nv/item_files/modem/mmode/ue_usage_setting\"," + sPreference; + +    rc = sendBasicCommand(sCommand, dTimeout); +    if (rc != SUCCESS) { +        printError("Voice/data preference configuration failed with code [%d]", rc); +        return rc; +    } + +    sCommand = "AT+QCFG=\"servicedomain\"," + sDomain + ",0"; + +    rc = sendBasicCommand(sCommand, dTimeout); +    if (rc != SUCCESS) { +        printError("Service domain configuration failed with code [%d]", rc); +        return rc; +    } + +    return SUCCESS; +} + +ICellularRadio::CODE QuectelRadio::getUeUsageSetting(UE_USAGE_SETTING& us) { +    printTrace("%s| Get UE Usage Setting", getName().c_str()); + +    std::string sCmd("AT+QNVFR=\"/nv/item_files/modem/mmode/ue_usage_setting\""); +    std::string sResult = sendCommand(sCmd); +    size_t end = sResult.find(ICellularRadio::RSP_OK); + +    if (end == std::string::npos) { +        printError("%s| Unable to get UE Usage Setting [%s]", getName().c_str(), sResult.c_str()); +        return FAILURE; +    } + +    // +QNVFR: <voice/data preference> +    const std::string sLabel = "+QNVFR: "; +    size_t start = sResult.find(sLabel); +    if (start == std::string::npos) { +        printError("%s| Failed to parse UE Usage Setting from output [%s]", getName().c_str(), sResult.c_str()); +        return FAILURE; +    } + +    start += sLabel.length(); +    const std::string sPreference = MTS::Text::trim(sResult.substr(start, end - start)); + +    if (convertToUeUsageSetting(sPreference, us) != SUCCESS) { +        printError("%s| Unable to convert [%s] to UE Usage Setting", getName().c_str(), sPreference.c_str()); +        return FAILURE; +    } + +    return SUCCESS; +} + +ICellularRadio::CODE QuectelRadio::convertToUeUsageSetting(const std::string& sSetting, UE_USAGE_SETTING& us) { +    if (sSetting == "00") { +        us = UE_USAGE_SETTING::MODE_1; +        return SUCCESS; +    } + +    if (sSetting == "01") { +        us = UE_USAGE_SETTING::MODE_2; +        return SUCCESS; +    } + +    us = UE_USAGE_SETTING::UNKNOWN_MODE; +    return FAILURE; +} + +ICellularRadio::CODE QuectelRadio::getUeModeOfOperation(UE_MODES_OF_OPERATION& mode) { +    printTrace("%s| Get UE Mode Of Operation", getName().c_str()); + +    SERVICEDOMAIN sd; +    UE_USAGE_SETTING us; + +    if (getServiceDomain(sd) != SUCCESS) { +        return FAILURE; +    } + +    printTrace("%s| Retrieved servicedomain [%d]", getName().c_str(), sd); + +    if (getUeUsageSetting(us) != SUCCESS) { +        return FAILURE; +    } + +    printTrace("%s| Retrieved ue_usage_setting [%d]", getName().c_str(), us); + +    if (sd == SERVICEDOMAIN::CS_ONLY && us == UE_USAGE_SETTING::MODE_1) { +        mode = UE_MODES_OF_OPERATION::CS_MODE1; +        return SUCCESS; +    } + +    if (sd == SERVICEDOMAIN::CS_ONLY && us == UE_USAGE_SETTING::MODE_2) { +        mode = UE_MODES_OF_OPERATION::CS_MODE2; +        return SUCCESS; +    } + +    if (sd == SERVICEDOMAIN::PS_ONLY && us == UE_USAGE_SETTING::MODE_1) { +        mode = UE_MODES_OF_OPERATION::PS_MODE1; +        return SUCCESS; +    } + +    if (sd == SERVICEDOMAIN::PS_ONLY && us == UE_USAGE_SETTING::MODE_2) { +        mode = UE_MODES_OF_OPERATION::PS_MODE2; +        return SUCCESS; +    } + +    if (sd == SERVICEDOMAIN::CSPS && us == UE_USAGE_SETTING::MODE_1) { +        mode = UE_MODES_OF_OPERATION::CS_PS_MODE1; +        return SUCCESS; +    } + +    if (sd == SERVICEDOMAIN::CSPS && us == UE_USAGE_SETTING::MODE_2) { +        mode = UE_MODES_OF_OPERATION::CS_PS_MODE2; +        return SUCCESS; +    } + +    printError("%s| Unknown combination of servicedomain [%d] and ue_usage_setting [%d]", getName().c_str(), sd, us); +    mode = UE_MODES_OF_OPERATION::UNKNOWN_MODE; +    return FAILURE; +} | 
