summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSerhii Kostiuk <serhii.o.kostiuk@globallogic.com>2020-07-15 06:06:43 -0500
committerSerhii Kostiuk <serhii.o.kostiuk@globallogic.com>2020-07-15 06:06:43 -0500
commitf0be0e4a343f9a600fe8c9fc34fa580c548a4e9e (patch)
tree34daf8e9219c894ca36dd1f7ddf4560aa395c659
parentb4b5e4958a11cc9e969355f60e08d0631b01c402 (diff)
parent8186f98913c55191b5a3610d19c8580c6a86c2f4 (diff)
downloadlibmts-io-f0be0e4a343f9a600fe8c9fc34fa580c548a4e9e.tar.gz
libmts-io-f0be0e4a343f9a600fe8c9fc34fa580c548a4e9e.tar.bz2
libmts-io-f0be0e4a343f9a600fe8c9fc34fa580c548a4e9e.zip
Merge branch 'ap/l4e1-delta-fwu' into 'delta-radio-fwu'
MTX-3404 mPower Oct20: Delta Radio Firmware Upgrade - L4E1 - libmts-io support See merge request !28
-rw-r--r--include/mts/MTS_IO_CellularRadio.h4
-rw-r--r--include/mts/MTS_IO_LE910C4EURadio.h1
-rw-r--r--include/mts/MTS_IO_QuectelRadio.h2
-rw-r--r--include/mts/MTS_IO_TelitRadio.h49
-rw-r--r--src/MTS_IO_CellularRadio.cpp76
-rw-r--r--src/MTS_IO_LE910C4EURadio.cpp4
-rw-r--r--src/MTS_IO_QuectelRadio.cpp82
-rw-r--r--src/MTS_IO_TelitRadio.cpp314
8 files changed, 455 insertions, 77 deletions
diff --git a/include/mts/MTS_IO_CellularRadio.h b/include/mts/MTS_IO_CellularRadio.h
index e3941c3..57a4de6 100644
--- a/include/mts/MTS_IO_CellularRadio.h
+++ b/include/mts/MTS_IO_CellularRadio.h
@@ -217,6 +217,10 @@ namespace MTS {
std::string m_sRadioType;
};
+ static CODE getFileSize(int fd, size_t& nBytes);
+ static CODE sizeToChunks(const size_t nBytes, const size_t chunkSize, size_t& nChunks);
+ static CODE readChunk(int fd, char* pChunk, size_t dChunkSize, size_t& nReadBytes);
+
private:
std::string m_sName;
std::string m_sRadioPort;
diff --git a/include/mts/MTS_IO_LE910C4EURadio.h b/include/mts/MTS_IO_LE910C4EURadio.h
index e872df3..a0d6baa 100644
--- a/include/mts/MTS_IO_LE910C4EURadio.h
+++ b/include/mts/MTS_IO_LE910C4EURadio.h
@@ -35,6 +35,7 @@ namespace MTS {
virtual ~LE910C4EURadio(){};
protected:
+ FOTA_GROUP getFotaGroup() override;
private:
diff --git a/include/mts/MTS_IO_QuectelRadio.h b/include/mts/MTS_IO_QuectelRadio.h
index d8228cb..6e7372b 100644
--- a/include/mts/MTS_IO_QuectelRadio.h
+++ b/include/mts/MTS_IO_QuectelRadio.h
@@ -85,8 +85,6 @@ namespace MTS {
static uint16_t getQuectelChecksum(const void* data, size_t nBytes);
static inline void updateQuectelChecksum(uint16_t& iChecksum, uint16_t iNewFragment);
static inline uint16_t bytesToUint16(uint8_t high, uint8_t low);
- static CODE getFileSize(int fd, size_t& nBytes, size_t& nFileChunks);
- static CODE readChunk(int fd, char* pChunk, size_t dChunkSize, size_t& nReadBytes);
CODE fumoWaitUpgradeFinished(UpdateCb& stepCb);
CODE fumoWaitNewFirmware(UpdateCb& stepCb);
};
diff --git a/include/mts/MTS_IO_TelitRadio.h b/include/mts/MTS_IO_TelitRadio.h
index bd542f1..a3425f9 100644
--- a/include/mts/MTS_IO_TelitRadio.h
+++ b/include/mts/MTS_IO_TelitRadio.h
@@ -44,6 +44,10 @@ namespace MTS {
CODE getSupportedCellularModes(CELLULAR_MODES &networks) override;
CODE setCellularMode(CELLULAR_MODES networks) override;
+ CODE updateFumoLocal(int fd, UpdateCb& stepCb) override;
+ CODE fumoLocalInject(int fd, UpdateCb& stepCb) override;
+ CODE fumoLocalApply(UpdateCb& stepCb) override;
+
protected:
TelitRadio(const std::string& sName, const std::string& sRadioPort);
@@ -53,10 +57,53 @@ namespace MTS {
CODE getIsSimInserted(bool& bData) override;
CODE getSimLockAttempts(int& iAttemptsPin, int& iAttemptsPuk) override;
+ enum FOTA_GROUP : uint8_t {
+ VALUE_GROUP_A = 0,
+ VALUE_GROUP_B,
+ VALUE_GROUP_C,
+ VALUE_GROUP_D,
+ VALUE_UNKNOWN
+ };
+
+ virtual FOTA_GROUP getFotaGroup();
+ virtual CODE fumoWriteGroupsABD(int fd, UpdateCb& stepCb);
+ //virtual CODE fumoWriteGroupC(int fd, UpdateCb& stepCb);
+
private:
virtual CODE getSimLockAttempts(int& iAttemptsPin, int& iAttemptsPuk, const std::string& sLockStatus);
ICellularRadio::CODE wdsList(std::set<int> &wds);
+
+ // private variable to save old firmware versions during FOTA
+ std::string m_sTelitFirmware;
+
+ static const size_t FILE_CHUNK_SIZE;
+ static const std::string CMD_ABORT_UPLOAD;
+
+ CODE getTelitFirmware(std::string& sFirmware);
+
+ CODE startWrite();
+ CODE abortWrite();
+
+ static inline void callNextStep(UpdateCb& stepCb, const char* csMessage);
+ static inline void callNextStep(UpdateCb& stepCb, const std::string& sMessage);
+
+ CODE fumoWaitUpgradeFinished(UpdateCb& stepCb);
+ CODE fumoCheckNewFirmware(UpdateCb& stepCb);
+
};
}
}
-#endif
+
+void MTS::IO::TelitRadio::callNextStep(ICellularRadio::UpdateCb& stepCb, const char* csMessage) {
+ if (stepCb) {
+ stepCb(Json::Value(csMessage));
+ }
+}
+
+void MTS::IO::TelitRadio::callNextStep(ICellularRadio::UpdateCb& stepCb, const std::string& sMessage) {
+ if (stepCb) {
+ stepCb(Json::Value(sMessage));
+ }
+}
+
+#endif /* MTS_IO_TELITRADIO_H_ */
diff --git a/src/MTS_IO_CellularRadio.cpp b/src/MTS_IO_CellularRadio.cpp
index bb7cd40..c4514e6 100644
--- a/src/MTS_IO_CellularRadio.cpp
+++ b/src/MTS_IO_CellularRadio.cpp
@@ -1262,3 +1262,79 @@ const char *CellularRadio::RadioBandMap::getRadioBandName(const std::string &cha
return band;
}
+
+ICellularRadio::CODE CellularRadio::getFileSize(int fd, size_t& nBytes) {
+ CODE rc = FAILURE;
+
+ do {
+ ssize_t dScrollPos;
+ dScrollPos = lseek(fd, 0, SEEK_SET);
+ if (dScrollPos < 0) {
+ printError("Failed to seek to the start of the file: %d", errno);
+ break;
+ }
+
+ dScrollPos = lseek(fd, 0, SEEK_END);
+ if (dScrollPos < 0) {
+ printError("Failed to determine the file size: %d", errno);
+ break;
+ }
+
+ nBytes = static_cast<size_t>(dScrollPos);
+
+ rc = SUCCESS;
+
+ } while (false);
+
+ lseek(fd, 0, SEEK_SET);
+ return rc;
+}
+
+ICellularRadio::CODE CellularRadio::sizeToChunks(const size_t nBytes, const size_t chunkSize, size_t& nChunks) {
+ nChunks = (nBytes + chunkSize - 1) / chunkSize;
+ return SUCCESS;
+}
+
+ICellularRadio::CODE CellularRadio::readChunk(int fd, char* pChunk, size_t dChunkSize, size_t& nReadBytes) {
+ size_t nUsedBuffer = 0;
+ CODE rc = FAILURE;
+
+ while (true) {
+
+ if (nUsedBuffer > dChunkSize) {
+ printError("Internal pointer error, abort upload: %d", nUsedBuffer);
+ rc = ERROR;
+ break;
+ }
+
+ if (nUsedBuffer == dChunkSize) {
+ // full chunk received
+ rc = SUCCESS;
+ nReadBytes = dChunkSize;
+ break;
+ }
+
+ char* pData = pChunk + nUsedBuffer;
+ size_t nFreeBuffer = dChunkSize - nUsedBuffer;
+
+ ssize_t dReadCount = read(fd, pData, nFreeBuffer);
+ if (dReadCount < 0) {
+ printError("Failed to read from the source file: %d", errno);
+ rc = ERROR;
+ break;
+ }
+
+ size_t duReadCount = static_cast<size_t>(dReadCount);
+ if (duReadCount == 0) {
+ // EOF. Return what was already read
+ nReadBytes = nUsedBuffer;
+ rc = SUCCESS;
+ break;
+ }
+
+ nUsedBuffer += duReadCount;
+
+ }
+
+ return rc;
+}
diff --git a/src/MTS_IO_LE910C4EURadio.cpp b/src/MTS_IO_LE910C4EURadio.cpp
index 029a921..4cf146b 100644
--- a/src/MTS_IO_LE910C4EURadio.cpp
+++ b/src/MTS_IO_LE910C4EURadio.cpp
@@ -29,3 +29,7 @@ LE910C4EURadio::LE910C4EURadio(const std::string& sPort)
{
}
+
+TelitRadio::FOTA_GROUP LE910C4EURadio::getFotaGroup() {
+ return VALUE_GROUP_B;
+}
diff --git a/src/MTS_IO_QuectelRadio.cpp b/src/MTS_IO_QuectelRadio.cpp
index 22374ee..2d1ffcd 100644
--- a/src/MTS_IO_QuectelRadio.cpp
+++ b/src/MTS_IO_QuectelRadio.cpp
@@ -603,7 +603,7 @@ ICellularRadio::CODE QuectelRadio::fumoLocalApply(ICellularRadio::UpdateCb& step
sCmd += VALUE_MTS_DELTA_PATH;
sCmd += "\"";
- rc = sendBasicCommand(sCmd, 1000);
+ rc = sendBasicCommand(sCmd, 10000);
if (rc != SUCCESS) {
printError("FUMO failed, OK not received from the radio");
@@ -837,10 +837,16 @@ ICellularRadio::CODE QuectelRadio::uploadFile(int fd, const std::string& sTarget
size_t nChunks;
CODE rc;
- rc = getFileSize(fd, dPayloadLength, nChunks);
+ rc = getFileSize(fd, dPayloadLength);
if (rc != SUCCESS) {
return rc;
}
+
+ rc = sizeToChunks(dPayloadLength, FILE_CHUNK_SIZE, nChunks);
+ if (rc != SUCCESS) {
+ return rc;
+ }
+
printTrace("File size: %d bytes and %d chunks", dPayloadLength, nChunks);
printTrace("Starting file upload...");
@@ -985,78 +991,6 @@ uint16_t QuectelRadio::getQuectelChecksum(const void* data, size_t nBytes) {
return iChecksum;
}
-ICellularRadio::CODE QuectelRadio::getFileSize(int fd, size_t& nBytes, size_t& nChunks) {
- CODE rc = FAILURE;
-
- do {
- ssize_t dScrollPos;
- dScrollPos = lseek(fd, 0, SEEK_SET);
- if (dScrollPos < 0) {
- printError("Failed to seek to the start of the file: %d", errno);
- break;
- }
-
- dScrollPos = lseek(fd, 0, SEEK_END);
- if (dScrollPos < 0) {
- printError("Failed to determine the file size: %d", errno);
- break;
- }
-
- nBytes = static_cast<size_t>(dScrollPos);
- nChunks = (nBytes + FILE_CHUNK_SIZE - 1) / FILE_CHUNK_SIZE; // round up
-
- rc = SUCCESS;
-
- } while (false);
-
- lseek(fd, 0, SEEK_SET);
- return rc;
-}
-
-ICellularRadio::CODE QuectelRadio::readChunk(int fd, char* pChunk, size_t dChunkSize, size_t& nReadBytes) {
- size_t nUsedBuffer = 0;
- CODE rc = FAILURE;
-
- while (true) {
-
- if (nUsedBuffer > dChunkSize) {
- printError("Internal pointer error, abort upload: %d", nUsedBuffer);
- rc = ERROR;
- break;
- }
-
- if (nUsedBuffer == dChunkSize) {
- // full chunk received
- rc = SUCCESS;
- nReadBytes = dChunkSize;
- break;
- }
-
- char* pData = pChunk + nUsedBuffer;
- size_t nFreeBuffer = dChunkSize - nUsedBuffer;
-
- ssize_t dReadCount = read(fd, pData, nFreeBuffer);
- if (dReadCount < 0) {
- printError("Failed to read from the source file: %d", errno);
- rc = ERROR;
- break;
- }
-
- size_t duReadCount = static_cast<size_t>(dReadCount);
- if (duReadCount == 0) {
- // EOF. Return what was already read
- nReadBytes = nUsedBuffer;
- rc = SUCCESS;
- break;
- }
-
- nUsedBuffer += duReadCount;
-
- }
-
- return rc;
-}
-
ICellularRadio::CODE QuectelRadio::fumoWaitUpgradeFinished(ICellularRadio::UpdateCb& stepCb) {
const uint32_t duUrcTimeout = 4 * 60 * 1000; // wait for 4 minutes for the next URC message
const std::string sFotaUrcPrefix = "+QIND: \"FOTA\""; // prefix for the URC notification messages
diff --git a/src/MTS_IO_TelitRadio.cpp b/src/MTS_IO_TelitRadio.cpp
index be31b03..52b5664 100644
--- a/src/MTS_IO_TelitRadio.cpp
+++ b/src/MTS_IO_TelitRadio.cpp
@@ -24,8 +24,14 @@
#include <mts/MTS_Thread.h>
#include <mts/MTS_Text.h>
+#include <unistd.h>
+
using namespace MTS::IO;
+const size_t TelitRadio::FILE_CHUNK_SIZE = 1024;
+const std::string TelitRadio::CMD_ABORT_UPLOAD = "+++";
+
+
TelitRadio::TelitRadio(const std::string& sName, const std::string& sRadioPort)
: CellularRadio(sName, sRadioPort)
{
@@ -730,3 +736,311 @@ ICellularRadio::CODE TelitRadio::setCellularMode(CELLULAR_MODES networks) {
}
return SUCCESS;
}
+
+ICellularRadio::CODE TelitRadio::updateFumoLocal(int fd, ICellularRadio::UpdateCb& stepCb) {
+ CODE rc = FAILURE;
+
+ rc = fumoLocalInject(fd, stepCb);
+ if (rc != SUCCESS) {
+ return rc;
+ }
+
+ rc = fumoLocalApply(stepCb);
+
+ return rc;
+}
+
+ICellularRadio::CODE TelitRadio::fumoLocalInject(int fd, ICellularRadio::UpdateCb& stepCb) {
+ CODE rc = FAILURE;
+ FOTA_GROUP group = getFotaGroup();
+
+ do {
+ callNextStep(stepCb, "FUMO Info: downloading the firmware");
+
+ if ((group == VALUE_GROUP_A) || (group == VALUE_GROUP_B) || (group == VALUE_GROUP_D)) {
+ rc = fumoWriteGroupsABD(fd, stepCb);
+ if (rc != SUCCESS) {
+ printError("Failed to inject the delta file.");
+ callNextStep(stepCb, "FUMO Error: failed to download the firmware file");
+ break;
+ }
+ } else if (group == VALUE_GROUP_C) {
+ //TODO Not Implemented TelitRadio::fumoWriteGroupC
+ printError("Failed to inject the delta file.");
+ callNextStep(stepCb, "FUMO Error: not implemented");
+ rc = NOT_APPLICABLE;
+ break;
+ } else {
+ printError("Delta firmware upgrade is not supported for this type of radio modem");
+ callNextStep(stepCb, "FUMO Error: delta firmware upgrade is not supported for this type of radio modem");
+ rc = NOT_APPLICABLE;
+ break;
+ }
+
+ callNextStep(stepCb, "FUMO Info: firmware downloaded successfully");
+
+ } while (false);
+
+ return rc;
+}
+
+ICellularRadio::CODE TelitRadio::fumoLocalApply(ICellularRadio::UpdateCb& stepCb) {
+ ICellularRadio::CODE rc;
+ std::string sCmd;
+ FOTA_GROUP group = getFotaGroup();
+
+ rc = getTelitFirmware(m_sTelitFirmware);
+ if (rc != SUCCESS) {
+ callNextStep(stepCb, "FUMO Error: Failed to obtain current firmware version");
+ return rc;
+ }
+ printInfo("Current firmware version: %s", m_sTelitFirmware.c_str());
+
+ if ((group == VALUE_GROUP_A) || (group == VALUE_GROUP_D)) {
+ // Send "AT#OTAUP=0,0" command to start the upgrade. OK response follows shortly.
+ sCmd = "AT#OTAUP=0,0";
+ } else if ((group == VALUE_GROUP_B) || (group == VALUE_GROUP_C)) {
+ // Send "AT#OTAUP=2" command to start the upgrade. OK response follows shortly.
+ sCmd = "AT#OTAUP=2";
+ } else {
+ printError("Delta firmware upgrade is not supported for this type of radio modem");
+ callNextStep(stepCb, "FUMO Error: delta firmware upgrade is not supported for this type of radio modem");
+ return NOT_APPLICABLE;
+ }
+
+ rc = sendBasicCommand(sCmd, 10000);
+
+ if (rc != SUCCESS) {
+ printError("FUMO failed, OK not received from the radio");
+ callNextStep(stepCb, "FUMO Error: failed to apply the firmware");
+ return rc;
+ }
+
+ const uint32_t duDetachTimeout = 10000; // wait for 10 seconds for the radio to detach
+
+ do {
+ printInfo("Applying the radio firmware");
+ callNextStep(stepCb, "FUMO Info: applying the radio firmware");
+
+ // Wait for the radio to detach from the USB bus
+ MTS::Thread::sleep(duDetachTimeout);
+
+ rc = fumoWaitUpgradeFinished(stepCb);
+
+ if (rc != SUCCESS) {
+ break;
+ }
+
+ rc = fumoCheckNewFirmware(stepCb);
+
+ } while (false);
+
+
+ if (rc == SUCCESS) {
+ printInfo("Radio firmware applied successfully");
+ callNextStep(stepCb, "FUMO Done: radio firmware applied successfully");
+ } else {
+ printError("Radio firmware has not been updated");
+ callNextStep(stepCb, "FUMO Error: radio firmware has not been updated");
+ }
+
+ return rc;
+}
+
+TelitRadio::FOTA_GROUP TelitRadio::getFotaGroup() {
+ return VALUE_UNKNOWN;
+}
+
+ICellularRadio::CODE TelitRadio::fumoWriteGroupsABD(int fd, ICellularRadio::UpdateCb& stepCb) {
+ size_t dPayloadLength;
+ size_t nChunks;
+ CODE rc;
+
+ rc = getFileSize(fd, dPayloadLength);
+ if (rc != SUCCESS) {
+ return rc;
+ }
+
+ rc = sizeToChunks(dPayloadLength, FILE_CHUNK_SIZE, nChunks);
+ if (rc != SUCCESS) {
+ return rc;
+ }
+
+ printTrace("File size: %d bytes and %d chunks", dPayloadLength, nChunks);
+ printTrace("Starting file upload...");
+
+ rc = startWrite();
+ if (rc != SUCCESS) {
+ return rc;
+ }
+
+ printTrace("File upload started.");
+ callNextStep(stepCb, "FILE Info: Started file upload");
+
+ size_t nChunksPerCent = (nChunks / 100) + 1;
+ size_t nFragmentLength = 0;
+ std::array<char, FILE_CHUNK_SIZE> vBuffer;
+
+ for (size_t iChunk = 1; iChunk < (nChunks + 1); iChunk++) {
+
+ rc = readChunk(fd, vBuffer.data(), vBuffer.size(), nFragmentLength);
+ if (rc != SUCCESS) {
+ break;
+ }
+
+ rc = sendData(vBuffer.data(), nFragmentLength);
+ if (rc != SUCCESS) {
+ break;
+ }
+
+ if (stepCb && ((iChunk % nChunksPerCent) == 0)) {
+ size_t dPercentsCompleted = iChunk / nChunksPerCent;
+ callNextStep(stepCb, "FILE Info: Uploaded " + MTS::Text::format(dPercentsCompleted) + "%");
+ }
+ }
+
+ if (rc != SUCCESS) {
+ callNextStep(stepCb, "FILE Error: Upload failed due to internal error");
+ } else {
+ callNextStep(stepCb, "FILE Info: Upload finished successfully");
+ }
+
+ // send +++
+ abortWrite();
+ return rc;
+}
+
+
+ICellularRadio::CODE TelitRadio::startWrite() {
+ const std::vector<std::string> vBailStrings{ ICellularRadio::RSP_CONNECT, ICellularRadio::RSP_ERROR };
+ const int dTimeout = 1000; //ms
+ std::string sCommand, sResult;
+
+ sCommand = "AT#OTAUPW";
+
+ sResult = sendCommand(sCommand, vBailStrings, dTimeout);
+ if (sResult.find(ICellularRadio::RSP_CONNECT) == std::string::npos) {
+ printError("Radio is not ready to accept the file: [%s]", sResult.c_str());
+ return FAILURE;
+ }
+
+ return SUCCESS;
+}
+
+ICellularRadio::CODE TelitRadio::abortWrite() {
+ /*
+ * To prevent the “+++” from being mistaken for data, the following sequence should be followed:
+ * 1) Do not input any character within 1s or longer before inputting “+++”.
+ * 2) Input “+++” within 1s, and no other characters can be inputted during the time.
+ * 3) Do not input any character within 1s after “+++” has been inputted.
+ */
+ sleep(1);
+ return sendBasicCommand(CMD_ABORT_UPLOAD, 2000, 0x00);
+}
+
+ICellularRadio::CODE TelitRadio::getTelitFirmware(std::string& sFirmware) {
+ /*
+ * Currently, AT+CGMR command is used to determine the radio firmware version.
+ *
+ * AT+CGMR
+ * M0F.670006
+ *
+ * Perhaps in the future we will use AT#SWPKGV command.
+ *
+ * AT#SWPKGV
+ * 25.20.676-P0F.670690
+ * M0F.670006
+ * P0F.670690
+ * A0F.670006
+ */
+
+ printTrace("%s| Get Telit-specific firmware version", getName().c_str());
+ sFirmware = ICellularRadio::VALUE_NOT_SUPPORTED;
+ std::string sCmd("AT+CGMR");
+ std::string sResult = sendCommand(sCmd);
+ size_t pos = sResult.find(ICellularRadio::RSP_OK);
+ if (pos == std::string::npos) {
+ printWarning("%s| Unable to get firmware from radio using command [%s]", getName().c_str(), sCmd.c_str());
+ return FAILURE;
+ }
+
+ sFirmware = MTS::Text::trim(sResult.substr(0, pos));
+ if(sFirmware.size() == 0) {
+ printWarning("%s| Unable to get firmware from radio using command [%s]", getName().c_str(), sCmd.c_str());
+ return FAILURE;
+ }
+
+ return SUCCESS;
+}
+
+ICellularRadio::CODE TelitRadio::fumoWaitUpgradeFinished(ICellularRadio::UpdateCb& stepCb) {
+ const uint32_t duAttachTimeout = 300000; // wait for 300 seconds for the radio to attach
+ const uint32_t duUrcTimeout = 60 * 1000; // wait for 1 minutes for the next URC message
+ const std::string sFotaUrcPrefix = "#OTAEV:"; // prefix for the URC notification messages
+ const std::string sFotaUrcEndSuccess = "Module Upgraded To New Fw";
+ const std::string sFotaUrcEndFailed = "OTA Fw Upgrade Failed";
+ const std::vector<std::string> vFotaBailStrings{ sFotaUrcPrefix };
+
+ CODE rc = FAILURE;
+ std::string sResponse;
+
+ // It's now detached. Try to reconnect
+ if (!resetConnection(duAttachTimeout)) {
+ printError("Can't connect to the radio in %d ms", (duAttachTimeout));
+ callNextStep(stepCb, "FUMO Error: unable to obtain radio after reset");
+ return ERROR;
+ }
+
+ while (true) {
+
+ sResponse = sendCommand("", vFotaBailStrings, duUrcTimeout, 0x00);
+ printTrace("Radio response: [%s]", sResponse.c_str());
+
+ if (sResponse.find(sFotaUrcPrefix) == std::string::npos) {
+ printError("No URC messages from the radio in %d ms", duUrcTimeout);
+ callNextStep(stepCb, "FUMO Error: timeout, radio is not responding");
+ rc = ERROR;
+ break;
+ }
+
+ if (sResponse.find(sFotaUrcEndSuccess) != std::string::npos) {
+ printTrace("Radio module upgraded to new firmware");
+ callNextStep(stepCb, "FUMO Info: radio module upgraded to new firmware");
+ rc = SUCCESS;
+ break;
+ }
+
+ if (sResponse.find(sFotaUrcEndFailed) != std::string::npos) {
+ printTrace("Radio module firmware upgrade failed");
+ callNextStep(stepCb, "FUMO Error: firmware upgrade failed");
+ rc = ERROR;
+ break;
+ }
+
+ }
+
+ return rc;
+}
+
+ICellularRadio::CODE TelitRadio::fumoCheckNewFirmware(ICellularRadio::UpdateCb& stepCb) {
+ CODE rc = SUCCESS;
+ std::string sTelitFirmware;
+
+ rc = getTelitFirmware(sTelitFirmware);
+
+ if (rc != SUCCESS) {
+ callNextStep(stepCb, "FUMO Error: Failed to obtain current firmware version");
+ return rc;
+ }
+
+ printInfo("Firmware version before the upgrade: %s", m_sTelitFirmware.c_str());
+ printInfo("Current firmware version: %s", sTelitFirmware.c_str());
+
+ if (sTelitFirmware == m_sTelitFirmware) {
+ // Radio will not reset anymore, firmware version left the same, not updated
+ printError("Radio firmware version not changed after upgrade");
+ rc = FAILURE;
+ }
+
+ return rc;
+}