From e09f54c6b6fe35dc022fcea66935f5269866bff1 Mon Sep 17 00:00:00 2001 From: Andrii Pientsov Date: Fri, 10 Jul 2020 15:40:48 +0300 Subject: MTX-3404 mPower Oct20: Delta Radio Firmware Upgrade - L4E1 - libmts-io support --- src/MTS_IO_TelitRadio.cpp | 383 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 383 insertions(+) (limited to 'src/MTS_IO_TelitRadio.cpp') diff --git a/src/MTS_IO_TelitRadio.cpp b/src/MTS_IO_TelitRadio.cpp index be31b03..967baae 100644 --- a/src/MTS_IO_TelitRadio.cpp +++ b/src/MTS_IO_TelitRadio.cpp @@ -24,8 +24,14 @@ #include #include +#include + 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,380 @@ ICellularRadio::CODE TelitRadio::setCellularMode(CELLULAR_MODES networks) { } return SUCCESS; } + +ICellularRadio::CODE TelitRadio::updateFumoLocal(int fd, ICellularRadio::UpdateCb& stepCb) { + CODE rc = FAILURE; + FOTA_GROUP group = getFotaGroup(); + + if (group == VALUE_UNKNOWN) { + 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 rc; + } + + 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 = uploadFile(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 + printError("Failed to inject the delta file."); + callNextStep(stepCb, "FUMO Error: not implemented"); + 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"; + } + + rc = sendBasicCommand(sCmd, 2000); + + 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 + const uint32_t duAttachTimeout = 300000; // wait for 300 seconds for the radio to attach + + do { + 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); + + printInfo("Firmware update in progress"); + callNextStep(stepCb, "FUMO Info: firmware update in progress"); + + // 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"); + rc = ERROR; + break; + } + + // Wait for the radio to finish update and reboot + printTrace("Waiting for the radio to come up"); + callNextStep(stepCb, "FUMO Info: waiting for the radio to enter normal mode"); + rc = fumoWaitRadioBooted(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::uploadFile(int fd, ICellularRadio::UpdateCb& stepCb) { + size_t dPayloadLength; + size_t nChunks; + CODE rc; + + rc = getFileSize(fd, dPayloadLength, nChunks); + if (rc != SUCCESS) { + return rc; + } + printTrace("File size: %d bytes and %d chunks", dPayloadLength, nChunks); + printTrace("Starting file upload..."); + + rc = startFileUpload(); + 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 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 +++ + abortFileUpload(); + return rc; +} + +ICellularRadio::CODE TelitRadio::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(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 TelitRadio::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(dReadCount); + if (duReadCount == 0) { + // EOF. Return what was already read + nReadBytes = nUsedBuffer; + rc = SUCCESS; + break; + } + + nUsedBuffer += duReadCount; + + } + + return rc; +} + +ICellularRadio::CODE TelitRadio::startFileUpload() { + const std::vector 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::abortFileUpload() { + /* + * 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::fumoWaitRadioBooted(ICellularRadio::UpdateCb& stepCb) { + 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 vFotaBailStrings{ sFotaUrcPrefix }; + + CODE rc = FAILURE; + std::string sResponse; + + 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; +} -- cgit v1.2.3 From ccd41677d998134ff501a8d6ac3a154dcaca9321 Mon Sep 17 00:00:00 2001 From: Andrii Pientsov Date: Mon, 13 Jul 2020 15:29:38 +0300 Subject: MTX-3404 Code Review --- src/MTS_IO_TelitRadio.cpp | 138 +++++++++++----------------------------------- 1 file changed, 31 insertions(+), 107 deletions(-) (limited to 'src/MTS_IO_TelitRadio.cpp') diff --git a/src/MTS_IO_TelitRadio.cpp b/src/MTS_IO_TelitRadio.cpp index 967baae..86c3565 100644 --- a/src/MTS_IO_TelitRadio.cpp +++ b/src/MTS_IO_TelitRadio.cpp @@ -28,7 +28,6 @@ using namespace MTS::IO; -const size_t TelitRadio::FILE_CHUNK_SIZE = 1024; const std::string TelitRadio::CMD_ABORT_UPLOAD = "+++"; @@ -739,13 +738,6 @@ ICellularRadio::CODE TelitRadio::setCellularMode(CELLULAR_MODES networks) { ICellularRadio::CODE TelitRadio::updateFumoLocal(int fd, ICellularRadio::UpdateCb& stepCb) { CODE rc = FAILURE; - FOTA_GROUP group = getFotaGroup(); - - if (group == VALUE_UNKNOWN) { - 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 rc; - } rc = fumoLocalInject(fd, stepCb); if (rc != SUCCESS) { @@ -765,16 +757,22 @@ ICellularRadio::CODE TelitRadio::fumoLocalInject(int fd, ICellularRadio::UpdateC callNextStep(stepCb, "FUMO Info: downloading the firmware"); if ((group == VALUE_GROUP_A) || (group == VALUE_GROUP_B) || (group == VALUE_GROUP_D)) { - rc = uploadFile(fd, stepCb); + 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 + //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; } @@ -803,9 +801,13 @@ ICellularRadio::CODE TelitRadio::fumoLocalApply(ICellularRadio::UpdateCb& stepCb } 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, 2000); + rc = sendBasicCommand(sCmd, 10000); if (rc != SUCCESS) { printError("FUMO failed, OK not received from the radio"); @@ -814,30 +816,15 @@ ICellularRadio::CODE TelitRadio::fumoLocalApply(ICellularRadio::UpdateCb& stepCb } const uint32_t duDetachTimeout = 10000; // wait for 10 seconds for the radio to detach - const uint32_t duAttachTimeout = 300000; // wait for 300 seconds for the radio to attach do { - printInfo("Waiting for the radio to enter recovery mode"); - callNextStep(stepCb, "FUMO Info: waiting for the radio to enter recovery mode"); + 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); - printInfo("Firmware update in progress"); - callNextStep(stepCb, "FUMO Info: firmware update in progress"); - - // 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"); - rc = ERROR; - break; - } - - // Wait for the radio to finish update and reboot - printTrace("Waiting for the radio to come up"); - callNextStep(stepCb, "FUMO Info: waiting for the radio to enter normal mode"); - rc = fumoWaitRadioBooted(stepCb); + rc = fumoWaitUpgradeFinished(stepCb); if (rc != SUCCESS) { break; @@ -863,7 +850,7 @@ TelitRadio::FOTA_GROUP TelitRadio::getFotaGroup() { return VALUE_UNKNOWN; } -ICellularRadio::CODE TelitRadio::uploadFile(int fd, ICellularRadio::UpdateCb& stepCb) { +ICellularRadio::CODE TelitRadio::fumoWriteGroupsABD(int fd, ICellularRadio::UpdateCb& stepCb) { size_t dPayloadLength; size_t nChunks; CODE rc; @@ -875,7 +862,7 @@ ICellularRadio::CODE TelitRadio::uploadFile(int fd, ICellularRadio::UpdateCb& st printTrace("File size: %d bytes and %d chunks", dPayloadLength, nChunks); printTrace("Starting file upload..."); - rc = startFileUpload(); + rc = startWrite(); if (rc != SUCCESS) { return rc; } @@ -912,83 +899,12 @@ ICellularRadio::CODE TelitRadio::uploadFile(int fd, ICellularRadio::UpdateCb& st } // send +++ - abortFileUpload(); - return rc; -} - -ICellularRadio::CODE TelitRadio::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(dScrollPos); - nChunks = (nBytes + FILE_CHUNK_SIZE - 1) / FILE_CHUNK_SIZE; // round up - - rc = SUCCESS; - - } while (false); - - lseek(fd, 0, SEEK_SET); + abortWrite(); return rc; } -ICellularRadio::CODE TelitRadio::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(dReadCount); - if (duReadCount == 0) { - // EOF. Return what was already read - nReadBytes = nUsedBuffer; - rc = SUCCESS; - break; - } - - nUsedBuffer += duReadCount; - } - - return rc; -} - -ICellularRadio::CODE TelitRadio::startFileUpload() { +ICellularRadio::CODE TelitRadio::startWrite() { const std::vector vBailStrings{ ICellularRadio::RSP_CONNECT, ICellularRadio::RSP_ERROR }; const int dTimeout = 1000; //ms std::string sCommand, sResult; @@ -1004,7 +920,7 @@ ICellularRadio::CODE TelitRadio::startFileUpload() { return SUCCESS; } -ICellularRadio::CODE TelitRadio::abortFileUpload() { +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 “+++”. @@ -1050,8 +966,9 @@ ICellularRadio::CODE TelitRadio::getTelitFirmware(std::string& sFirmware) { return SUCCESS; } -ICellularRadio::CODE TelitRadio::fumoWaitRadioBooted(ICellularRadio::UpdateCb& stepCb) { - const uint32_t duUrcTimeout = 60 * 1000; // wait for 1 minutes for the next URC message +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"; @@ -1060,6 +977,13 @@ ICellularRadio::CODE TelitRadio::fumoWaitRadioBooted(ICellularRadio::UpdateCb& s 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); -- cgit v1.2.3 From 8186f98913c55191b5a3610d19c8580c6a86c2f4 Mon Sep 17 00:00:00 2001 From: Andrii Pientsov Date: Wed, 15 Jul 2020 13:49:59 +0300 Subject: MTX-3404 Code Review --- src/MTS_IO_TelitRadio.cpp | 39 +++++++++++++++++++++++---------------- 1 file changed, 23 insertions(+), 16 deletions(-) (limited to 'src/MTS_IO_TelitRadio.cpp') diff --git a/src/MTS_IO_TelitRadio.cpp b/src/MTS_IO_TelitRadio.cpp index 86c3565..52b5664 100644 --- a/src/MTS_IO_TelitRadio.cpp +++ b/src/MTS_IO_TelitRadio.cpp @@ -28,6 +28,7 @@ using namespace MTS::IO; +const size_t TelitRadio::FILE_CHUNK_SIZE = 1024; const std::string TelitRadio::CMD_ABORT_UPLOAD = "+++"; @@ -855,10 +856,16 @@ ICellularRadio::CODE TelitRadio::fumoWriteGroupsABD(int fd, ICellularRadio::Upda 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..."); @@ -927,25 +934,25 @@ ICellularRadio::CODE TelitRadio::abortWrite() { * 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); + 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 + * 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 - * - * Perhaps in the future we will use AT#SWPKGV command. - * - * AT#SWPKGV - * 25.20.676-P0F.670690 - * M0F.670006 - * P0F.670690 - * A0F.670006 - */ + * P0F.670690 + * A0F.670006 + */ printTrace("%s| Get Telit-specific firmware version", getName().c_str()); sFirmware = ICellularRadio::VALUE_NOT_SUPPORTED; @@ -968,7 +975,7 @@ ICellularRadio::CODE TelitRadio::getTelitFirmware(std::string& sFirmware) { 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 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"; -- cgit v1.2.3 From 1986b67d54e8e6a3f8176f5b4cb78786ac3ee496 Mon Sep 17 00:00:00 2001 From: Andrii Pientsov Date: Thu, 16 Jul 2020 19:23:40 +0300 Subject: Add vendor firmware version --- src/MTS_IO_TelitRadio.cpp | 69 ++++++++++++++++++++++++++--------------------- 1 file changed, 39 insertions(+), 30 deletions(-) (limited to 'src/MTS_IO_TelitRadio.cpp') diff --git a/src/MTS_IO_TelitRadio.cpp b/src/MTS_IO_TelitRadio.cpp index 52b5664..8d762be 100644 --- a/src/MTS_IO_TelitRadio.cpp +++ b/src/MTS_IO_TelitRadio.cpp @@ -789,7 +789,7 @@ ICellularRadio::CODE TelitRadio::fumoLocalApply(ICellularRadio::UpdateCb& stepCb std::string sCmd; FOTA_GROUP group = getFotaGroup(); - rc = getTelitFirmware(m_sTelitFirmware); + rc = getVendorFirmware(m_sTelitFirmware); if (rc != SUCCESS) { callNextStep(stepCb, "FUMO Error: Failed to obtain current firmware version"); return rc; @@ -938,39 +938,48 @@ ICellularRadio::CODE TelitRadio::abortWrite() { 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 - */ - +ICellularRadio::CODE TelitRadio::getVendorFirmware(std::string& sVendorFirmware) { printTrace("%s| Get Telit-specific firmware version", getName().c_str()); - sFirmware = ICellularRadio::VALUE_NOT_SUPPORTED; - std::string sCmd("AT+CGMR"); + ICellularRadio::CODE rc = FAILURE; + sVendorFirmware = ICellularRadio::VALUE_NOT_SUPPORTED; + std::string sFirmware; + std::string sFirmwareBuild; + std::string sCmd("AT#SWPKGV"); 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; - } + do { - return SUCCESS; + if (pos != std::string::npos) { + // Found + std::vector vLine = MTS::Text::split(sResult, "\r"); + if(vLine[1].size() == 0) { + printWarning("%s| Unable to get firmware from radio using command [%s]", getName().c_str(), sCmd.c_str()); + rc = FAILURE; + } else { + sVendorFirmware = MTS::Text::trim(vLine[1]); + rc = SUCCESS; + } + break; + } + + // Not Found. Then we will use "AT+CGMR" + "AT#CFVR" + rc = getFirmware(sFirmware); + if (rc != SUCCESS){ + break; + } + + rc = getFirmwareBuild(sFirmwareBuild); + if (rc != SUCCESS){ + break; + } + + sVendorFirmware = sFirmware + "," + sFirmwareBuild; + + } while (false); + + + return rc; } ICellularRadio::CODE TelitRadio::fumoWaitUpgradeFinished(ICellularRadio::UpdateCb& stepCb) { @@ -1026,7 +1035,7 @@ ICellularRadio::CODE TelitRadio::fumoCheckNewFirmware(ICellularRadio::UpdateCb& CODE rc = SUCCESS; std::string sTelitFirmware; - rc = getTelitFirmware(sTelitFirmware); + rc = getVendorFirmware(sTelitFirmware); if (rc != SUCCESS) { callNextStep(stepCb, "FUMO Error: Failed to obtain current firmware version"); -- cgit v1.2.3 From a05854f5d389f67001b7ecc4cda62c7320433349 Mon Sep 17 00:00:00 2001 From: Andrii Pientsov Date: Fri, 17 Jul 2020 10:03:48 +0300 Subject: Code review --- src/MTS_IO_TelitRadio.cpp | 34 ++++++++++++++++++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) (limited to 'src/MTS_IO_TelitRadio.cpp') diff --git a/src/MTS_IO_TelitRadio.cpp b/src/MTS_IO_TelitRadio.cpp index 8d762be..599c71e 100644 --- a/src/MTS_IO_TelitRadio.cpp +++ b/src/MTS_IO_TelitRadio.cpp @@ -51,6 +51,36 @@ bool TelitRadio::resetRadio(uint32_t iTimeoutMillis) { return false; } +ICellularRadio::CODE TelitRadio::getFirmwareBuild(std::string& sFirmwareBuild) { + std::string sCmd("AT#CFVR"); + + std::string sResult = sendCommand(sCmd); + + size_t end = sResult.find(ICellularRadio::RSP_OK); + if (end == std::string::npos) { + printWarning("%s| Unable to get firmware build number [%s]", + getName().c_str(), + sCmd.c_str()); + return FAILURE; + } + + size_t start = sResult.find("#CFVR:"); + if (start == std::string::npos) { + printWarning("%s| Command returned unexpected response [%s]", + getName().c_str(), + sCmd.c_str()); + return FAILURE; + } + + start += sizeof("#CFVR:"); + + sFirmwareBuild = MTS::Text::trim(sResult.substr(start, end-start)); + if(sFirmwareBuild.size() == 0) { + printWarning("%s| Firmware Build Version is empty", getName().c_str()); + return FAILURE; + } + return SUCCESS; +} ICellularRadio::CODE TelitRadio::getModel(std::string& sModel) { printTrace("%s| Get Model", getName().c_str()); @@ -953,11 +983,11 @@ ICellularRadio::CODE TelitRadio::getVendorFirmware(std::string& sVendorFirmware) if (pos != std::string::npos) { // Found std::vector vLine = MTS::Text::split(sResult, "\r"); - if(vLine[1].size() == 0) { + sVendorFirmware = MTS::Text::trim(vLine[1]); + if(sVendorFirmware.size() == 0) { printWarning("%s| Unable to get firmware from radio using command [%s]", getName().c_str(), sCmd.c_str()); rc = FAILURE; } else { - sVendorFirmware = MTS::Text::trim(vLine[1]); rc = SUCCESS; } break; -- cgit v1.2.3 From 298efe4e17d3665f9ddbb9298a37b563c60de735 Mon Sep 17 00:00:00 2001 From: Andrii Pientsov Date: Fri, 17 Jul 2020 10:42:16 +0300 Subject: Code review --- src/MTS_IO_TelitRadio.cpp | 88 +++++++++++++++++++++++------------------------ 1 file changed, 44 insertions(+), 44 deletions(-) (limited to 'src/MTS_IO_TelitRadio.cpp') diff --git a/src/MTS_IO_TelitRadio.cpp b/src/MTS_IO_TelitRadio.cpp index 599c71e..a82004c 100644 --- a/src/MTS_IO_TelitRadio.cpp +++ b/src/MTS_IO_TelitRadio.cpp @@ -82,6 +82,50 @@ ICellularRadio::CODE TelitRadio::getFirmwareBuild(std::string& sFirmwareBuild) { return SUCCESS; } +ICellularRadio::CODE TelitRadio::getVendorFirmware(std::string& sVendorFirmware) { + printTrace("%s| Get Telit-specific firmware version", getName().c_str()); + ICellularRadio::CODE rc = FAILURE; + sVendorFirmware = ICellularRadio::VALUE_NOT_SUPPORTED; + std::string sFirmware; + std::string sFirmwareBuild; + std::string sCmd("AT#SWPKGV"); + std::string sResult = sendCommand(sCmd); + size_t pos = sResult.find(ICellularRadio::RSP_OK); + + do { + + if (pos != std::string::npos) { + // Found + std::vector vLine = MTS::Text::split(sResult, "\r"); + sVendorFirmware = MTS::Text::trim(vLine[1]); + if(sVendorFirmware.size() == 0) { + printWarning("%s| Unable to get firmware from radio using command [%s]", getName().c_str(), sCmd.c_str()); + rc = FAILURE; + } else { + rc = SUCCESS; + } + break; + } + + // Not Found. Then we will use "AT+CGMR" + "AT#CFVR" + rc = getFirmware(sFirmware); + if (rc != SUCCESS){ + break; + } + + rc = getFirmwareBuild(sFirmwareBuild); + if (rc != SUCCESS){ + break; + } + + sVendorFirmware = sFirmware + "," + sFirmwareBuild; + + } while (false); + + + return rc; +} + ICellularRadio::CODE TelitRadio::getModel(std::string& sModel) { printTrace("%s| Get Model", getName().c_str()); //Always returns SUCCESS because the model should be m_sName @@ -968,50 +1012,6 @@ ICellularRadio::CODE TelitRadio::abortWrite() { return sendBasicCommand(CMD_ABORT_UPLOAD, 2000, 0x00); } -ICellularRadio::CODE TelitRadio::getVendorFirmware(std::string& sVendorFirmware) { - printTrace("%s| Get Telit-specific firmware version", getName().c_str()); - ICellularRadio::CODE rc = FAILURE; - sVendorFirmware = ICellularRadio::VALUE_NOT_SUPPORTED; - std::string sFirmware; - std::string sFirmwareBuild; - std::string sCmd("AT#SWPKGV"); - std::string sResult = sendCommand(sCmd); - size_t pos = sResult.find(ICellularRadio::RSP_OK); - - do { - - if (pos != std::string::npos) { - // Found - std::vector vLine = MTS::Text::split(sResult, "\r"); - sVendorFirmware = MTS::Text::trim(vLine[1]); - if(sVendorFirmware.size() == 0) { - printWarning("%s| Unable to get firmware from radio using command [%s]", getName().c_str(), sCmd.c_str()); - rc = FAILURE; - } else { - rc = SUCCESS; - } - break; - } - - // Not Found. Then we will use "AT+CGMR" + "AT#CFVR" - rc = getFirmware(sFirmware); - if (rc != SUCCESS){ - break; - } - - rc = getFirmwareBuild(sFirmwareBuild); - if (rc != SUCCESS){ - break; - } - - sVendorFirmware = sFirmware + "," + sFirmwareBuild; - - } while (false); - - - return rc; -} - 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 -- cgit v1.2.3 From b9a5e7ab27ad313b95fe6642f08e230091efef0f Mon Sep 17 00:00:00 2001 From: Serhii Kostiuk Date: Tue, 21 Jul 2020 20:24:00 +0300 Subject: Telit Delta Radio Firmware Upgrade support - libmts-io implementation Changes after code review: 1. Handle cases when the number of bytes written is different from the number of bytes requested to transfer. 2. Use fstat instead of lseek to determine the firmware size. 3. Renamed TelitRadio::startWrite and TelitRadio::abortWrite functions to better represent their applicability scope. --- src/MTS_IO_TelitRadio.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src/MTS_IO_TelitRadio.cpp') diff --git a/src/MTS_IO_TelitRadio.cpp b/src/MTS_IO_TelitRadio.cpp index a82004c..8c7e174 100644 --- a/src/MTS_IO_TelitRadio.cpp +++ b/src/MTS_IO_TelitRadio.cpp @@ -943,7 +943,7 @@ ICellularRadio::CODE TelitRadio::fumoWriteGroupsABD(int fd, ICellularRadio::Upda printTrace("File size: %d bytes and %d chunks", dPayloadLength, nChunks); printTrace("Starting file upload..."); - rc = startWrite(); + rc = startFotaWriteABD(); if (rc != SUCCESS) { return rc; } @@ -980,12 +980,12 @@ ICellularRadio::CODE TelitRadio::fumoWriteGroupsABD(int fd, ICellularRadio::Upda } // send +++ - abortWrite(); + abortFotaWriteABD(); return rc; } -ICellularRadio::CODE TelitRadio::startWrite() { +ICellularRadio::CODE TelitRadio::startFotaWriteABD() { const std::vector vBailStrings{ ICellularRadio::RSP_CONNECT, ICellularRadio::RSP_ERROR }; const int dTimeout = 1000; //ms std::string sCommand, sResult; @@ -1001,7 +1001,7 @@ ICellularRadio::CODE TelitRadio::startWrite() { return SUCCESS; } -ICellularRadio::CODE TelitRadio::abortWrite() { +ICellularRadio::CODE TelitRadio::abortFotaWriteABD() { /* * 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 “+++”. -- cgit v1.2.3 From beb3f36c5dcc70beed900859d6426dc74e4bccc8 Mon Sep 17 00:00:00 2001 From: Serhii Kostiuk Date: Wed, 22 Jul 2020 09:55:55 +0300 Subject: Telit Delta Radio Firmware Upgrade support - libmts-io implementation During testing it was discovered that the radio is detached for 4 minutes 40 seconds while the upgrade is in progress. This was too close to the time limit of 5 minutes set before. This commit increases attach timeout to 6 minutes to be on the safe side. --- src/MTS_IO_TelitRadio.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/MTS_IO_TelitRadio.cpp') diff --git a/src/MTS_IO_TelitRadio.cpp b/src/MTS_IO_TelitRadio.cpp index 8c7e174..457dfdc 100644 --- a/src/MTS_IO_TelitRadio.cpp +++ b/src/MTS_IO_TelitRadio.cpp @@ -1013,7 +1013,7 @@ ICellularRadio::CODE TelitRadio::abortFotaWriteABD() { } ICellularRadio::CODE TelitRadio::fumoWaitUpgradeFinished(ICellularRadio::UpdateCb& stepCb) { - const uint32_t duAttachTimeout = 300000; // wait for 300 seconds for the radio to attach + const uint32_t duAttachTimeout = 6 * 60 * 1000;// wait for 6 minutes 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"; -- cgit v1.2.3