From 5c529e115394ba3d04c7531d046776293e2bf06c Mon Sep 17 00:00:00 2001 From: Serhii Kostiuk Date: Fri, 7 Aug 2020 11:07:48 +0300 Subject: Quectel EG25-G Delta Radio Firmware Upgrade support - libmts-io implementation This commit fixes additional issue discrovered after implementation of ACK mode. When a single 1024 bytes long chunk of data is sent to the radio - the radio reports that it received nothing. Which is a lie according to Wireshark USB logs, data is actually sent over USB and looks like radio acknowledged it in USB packet. This issue is reproducible when chunk size is set to 1024 or 512 bytes. This issue is not reproducible with chunk size of 256 bytes. When 1025 or 2048 bytes are sent to the radio - all bytes are received just fine and we get an ACK string for each 1024 bytes of data. This commit allows to send 2048 bytes long chunks of data, wait for two ACK strings from the radio and finish transmission successfully. --- src/MTS_IO_QuectelRadio.cpp | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/src/MTS_IO_QuectelRadio.cpp b/src/MTS_IO_QuectelRadio.cpp index a41e6fc..67a8d71 100644 --- a/src/MTS_IO_QuectelRadio.cpp +++ b/src/MTS_IO_QuectelRadio.cpp @@ -31,7 +31,7 @@ using namespace MTS::IO; -const size_t QuectelRadio::FILE_CHUNK_SIZE = 1024; +const size_t QuectelRadio::FILE_CHUNK_SIZE = 2048; const std::string QuectelRadio::CMD_ABORT_UPLOAD = "+++"; // It is strongly recommended to use DOS 8.3 file name format for . @@ -874,6 +874,11 @@ ICellularRadio::CODE QuectelRadio::uploadFile(int fd, const std::string& sTarget const uint16_t uFileTimeout = 2; // s const int32_t iUploadResultTimeout = uFileTimeout * 2 * 1000; // ms + // Quectel radios return ACK string every 1024 bytes + const size_t nChunksPerAck = std::max(static_cast(1), (1024 / FILE_CHUNK_SIZE)); + const size_t nAcksPerChunk = std::max(static_cast(1), (FILE_CHUNK_SIZE / 1024)); + const std::string sAckString(nAcksPerChunk, 'A'); + size_t dPayloadLength; size_t nChunks; CODE rc; @@ -907,8 +912,8 @@ ICellularRadio::CODE QuectelRadio::uploadFile(int fd, const std::string& sTarget std::string sResponse; // ACK waiter callback - wait for ACK and populate result code - IsNeedMoreData waitAck = [&rc](const std::string& iterationData, const std::string&/*allData*/)->bool { - if (iterationData.find('A') != std::string::npos) { + IsNeedMoreData waitAck = [&rc, &sAckString](const std::string& /*iterationData*/, const std::string& allData)->bool { + if (allData.find(sAckString) != std::string::npos) { // No data needed rc = SUCCESS; return false; @@ -919,7 +924,7 @@ ICellularRadio::CODE QuectelRadio::uploadFile(int fd, const std::string& sTarget return true; }; - for (size_t iChunk = 1; iChunk < (nChunks + 1); iChunk++) { + for (size_t iChunk = 0; iChunk < nChunks; iChunk++) { rc = readChunk(fd, vBuffer.data(), vBuffer.size(), nFragmentLength); if (rc != SUCCESS) { @@ -936,11 +941,14 @@ ICellularRadio::CODE QuectelRadio::uploadFile(int fd, const std::string& sTarget break; } - // Wait for ACK for up to 1 second and populate rc variable - sResponse = waitResponse(waitAck, 1000); - if (rc != SUCCESS) { - // timeout or end of execution - check later - break; + // Every 1024 bytes + if ((iChunk) && (iChunk % nChunksPerAck == 0)) { + // Wait for ACK for up to 1 second and populate rc variable + sResponse = waitResponse(waitAck, 1000); + if (rc != SUCCESS) { + // timeout or end of execution - check later + break; + } } if (stepCb && ((iChunk % nChunksPerCent) == 0)) { -- cgit v1.2.3