summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSerhii Kostiuk <serhii.o.kostiuk@globallogic.com>2020-08-04 10:20:54 +0300
committerSerhii Kostiuk <serhii.o.kostiuk@globallogic.com>2020-08-04 12:32:04 +0300
commit1afb3c7bb338eba0410f85be8e5eaf192a7c4857 (patch)
treea5ad26622f3a5dd43c7fa1dfbdc865b9c0cbc345
parent64d8e39ac05a89acfb9173fad05d0aab948032c6 (diff)
downloadlibmts-io-1afb3c7bb338eba0410f85be8e5eaf192a7c4857.tar.gz
libmts-io-1afb3c7bb338eba0410f85be8e5eaf192a7c4857.tar.bz2
libmts-io-1afb3c7bb338eba0410f85be8e5eaf192a7c4857.zip
Quectel EG25-G Delta Radio Firmware Upgrade support - libmts-io implementation
During testing with L4G1 device I discovered some inconsistencies in behaviour between EG25-G device and EG95 devices (EG95-NA and EG95-E). EG25-G device that I have on hands does not allow to perform downgrades using delta images. When there is an attempt to apply a downgrade delta image it behaves as the following: - radio prints `OK` - radio prints `+QIND: "FOTA",502` - radio is not rebooted While EG95 radios always reboot at least once to apply the firmware image. Even if it is not valid. Also I noticed that detach from the serial bus may take more than 10 seconds in some rare cases. Thus we need to wait not a fixed amount of time but until the radio actually detaches from the bus. This commit attempts to address the findings described above.
-rw-r--r--include/mts/MTS_IO_QuectelRadio.h3
-rw-r--r--src/MTS_IO_QuectelRadio.cpp49
2 files changed, 48 insertions, 4 deletions
diff --git a/include/mts/MTS_IO_QuectelRadio.h b/include/mts/MTS_IO_QuectelRadio.h
index 58e3d25..0f24db8 100644
--- a/include/mts/MTS_IO_QuectelRadio.h
+++ b/include/mts/MTS_IO_QuectelRadio.h
@@ -86,6 +86,9 @@ namespace MTS {
CODE fumoWaitUpgradeFinished(UpdateCb& stepCb);
CODE fumoWaitNewFirmware(UpdateCb& stepCb);
+ /// Parse error code in early FUMO URC result received before the first attempt to flash the firmware
+ std::string getFumoEarlyErrorCode(const std::string& sRadioInput);
+
/// Get value from container by its index, use default value if not found. Non-template version.
const std::string& getByIndex(const std::vector<std::string>& vector, size_t index, const std::string& defaultValue) {
if (index >= vector.size()) {
diff --git a/src/MTS_IO_QuectelRadio.cpp b/src/MTS_IO_QuectelRadio.cpp
index 601674b..7d205e7 100644
--- a/src/MTS_IO_QuectelRadio.cpp
+++ b/src/MTS_IO_QuectelRadio.cpp
@@ -608,8 +608,12 @@ ICellularRadio::CODE QuectelRadio::fumoLocalCleanup() {
}
ICellularRadio::CODE QuectelRadio::fumoLocalApply(ICellularRadio::UpdateCb& stepCb) {
+ const std::string sFotaUrcPrefix = "+QIND: \"FOTA\""; // prefix for URC notification messages
+ const std::vector<std::string> vFotaBailStrings{ sFotaUrcPrefix };
+
ICellularRadio::CODE rc;
std::string sCmd;
+ std::string sResponse;
rc = getVendorFirmware(m_sQuectelFirmware);
if (rc != SUCCESS) {
@@ -631,8 +635,8 @@ ICellularRadio::CODE QuectelRadio::fumoLocalApply(ICellularRadio::UpdateCb& step
return rc;
}
- const uint32_t duDetachTimeout = 10000; // wait for 10 seconds for the radio to detach
- const uint32_t duAttachTimeout = 30000; // wait for 30 seconds for the radio to attach
+ const uint32_t duDetachTimeout = 15000; // wait up to 15 seconds for the radio to detach
+ const uint32_t duAttachTimeout = 30000; // wait up to 30 seconds for the radio to attach
const int dMaxAttempts = 5; // the radio makes 5 attempts to update the firmware
for (int i = 0; i < dMaxAttempts; i++) {
@@ -640,8 +644,22 @@ ICellularRadio::CODE QuectelRadio::fumoLocalApply(ICellularRadio::UpdateCb& step
printInfo("Waiting for the radio to enter recovery mode");
callNextStep(stepCb, "FUMO Info: waiting for the radio to enter recovery mode");
- // Wait for the radio to detach from the USB bus
- MTS::Thread::sleep(duDetachTimeout);
+ // Wait for new FOTA responses. Exits preliminary if radio detached.
+ sResponse = sendCommand("", vFotaBailStrings, duDetachTimeout, 0x00);
+ printTrace("Radio response: [%s]", sResponse.c_str());
+
+ if (i == 0 && sResponse.find(sFotaUrcPrefix) != std::string::npos) {
+ // FOTA responce code received before radio detach, image can't be applied.
+ // EG25-G radio prints a message in +QIND: "FOTA",ERR_CODE format in this case.
+ std::string sErrorCode = getFumoEarlyErrorCode(sResponse);
+
+ printError("Preliminary termination of FUMO procedure: [%s]", sErrorCode.c_str());
+ callNextStep(stepCb, "FUMO Error: radio returned error code " + sErrorCode);
+
+ // We got a response from the radio but FOTA failed
+ rc = FAILURE;
+ break;
+ }
// It's now detached. Try to reconnect
if (!resetConnection(duAttachTimeout)) {
@@ -1116,6 +1134,29 @@ ICellularRadio::CODE QuectelRadio::fumoWaitNewFirmware(ICellularRadio::UpdateCb&
return rc;
}
+std::string QuectelRadio::getFumoEarlyErrorCode(const std::string& sRadioInput) {
+ const std::string sFotaPrefix = "+QIND: \"FOTA\",";
+ const char cLineEnd = ICellularRadio::CR;
+
+ // sRadioInput may contain several lines. We need to find the line with '+QIND: "FOTA",' in it
+ auto pLineStart = sRadioInput.find(sFotaPrefix);
+
+ if (pLineStart == std::string::npos) {
+ // FOTA line not found at all
+ return "-1";
+ }
+
+ // Parse the error code
+ auto pErrorStart = pLineStart + sFotaPrefix.length();
+ auto pLineEnd = sRadioInput.find(cLineEnd, pErrorStart);
+
+ // Filter the error code
+ std::string sSubString = sRadioInput.substr(pErrorStart, pLineEnd - pErrorStart);
+ std::string sResult = MTS::Text::trim(sSubString);
+
+ return sResult;
+}
+
ICellularRadio::CODE QuectelRadio::startFileUpload(const std::string& sTargetFilename, size_t nBytes) {
const std::vector<std::string> vBailStrings{ ICellularRadio::RSP_CONNECT, ICellularRadio::RSP_ERROR };
const int dTimeout = 1000; //ms