From bc701ae8331761cc9fd88828e6c2bb9beadbdcb0 Mon Sep 17 00:00:00 2001 From: Jaro Date: Wed, 25 Aug 2021 00:45:13 +0200 Subject: [PATCH] QT port --- CMakeLists.txt | 2 +- SerialPortYmodem | 1 + Thread.h | 44 - Ymodem.cpp | 1791 +++++++++++++++++ Ymodem.h | 143 ++ YmodemFileReceive.cpp | 231 +++ YmodemFileReceive.h | 57 + ...=> codemodel-v2-2f061e11e865d7291da7.json} | 2 +- ...on => index-2021-08-24T22-34-28-0932.json} | 4 +- ...t-timeout-Debug-d7af418a1b6c2d259633.json} | 14 +- build/Makefile | 90 +- build/compile_commands.json | 9 +- xymodem.cpp | 585 ------ xymodem.h | 141 -- ymodem.h | 63 - 15 files changed, 2305 insertions(+), 872 deletions(-) create mode 160000 SerialPortYmodem delete mode 100644 Thread.h create mode 100644 Ymodem.cpp create mode 100644 Ymodem.h create mode 100644 YmodemFileReceive.cpp create mode 100644 YmodemFileReceive.h rename build/.cmake/api/v1/reply/{codemodel-v2-4167e22d1c847713af64.json => codemodel-v2-2f061e11e865d7291da7.json} (92%) rename build/.cmake/api/v1/reply/{index-2021-08-24T14-20-32-0203.json => index-2021-08-24T22-34-28-0932.json} (91%) rename build/.cmake/api/v1/reply/{target-timeout-Debug-85a0f71a1db986bd99c5.json => target-timeout-Debug-d7af418a1b6c2d259633.json} (95%) delete mode 100644 xymodem.cpp delete mode 100644 xymodem.h delete mode 100644 ymodem.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 6c1ea47..5ce5627 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,7 +4,7 @@ project(TEST) ## Target set(CMAKE_CXX_STANDARD 11) -set(TEST_SRCS main.cpp TimeoutSerial.cpp xymodem.cpp) +set(TEST_SRCS main.cpp TimeoutSerial.cpp Ymodem.cpp YmodemFileReceive.cpp) add_definitions(-DBOOST_LOG_DYN_LINK) add_executable(timeout ${TEST_SRCS}) set(CMAKE_BUILD_TYPE Debug) diff --git a/SerialPortYmodem b/SerialPortYmodem new file mode 160000 index 0000000..dd5ce17 --- /dev/null +++ b/SerialPortYmodem @@ -0,0 +1 @@ +Subproject commit dd5ce17f9fd0620c451c66ca9aaf062b48842562 diff --git a/Thread.h b/Thread.h deleted file mode 100644 index 47cf7d3..0000000 --- a/Thread.h +++ /dev/null @@ -1,44 +0,0 @@ -#ifndef THREAD_HH -#define THREAD_HH - -#include -#include - -using namespace std; - -template -class Thread { -private: - boost::thread* thread; - bool isRunning; -public: - // Ctor - Thread() : thread(NULL), isRunning(false) { - } - virtual ~Thread() { - kill(); - } - - void start() { - T* derived = dynamic_cast(this); - thread = new boost::thread(boost::bind(&Thread::doIt, this, boost::ref(*derived))); - } - void doIt(T& derived) { - } - bool isFinished() { - return isRunning; - } - void join() { - if(thread) { - thread->join(); - } - } - void kill() { - if(thread) { - thread->interrupt(); - delete thread; - thread = NULL; - } - } -}; -#endif \ No newline at end of file diff --git a/Ymodem.cpp b/Ymodem.cpp new file mode 100644 index 0000000..7214d8b --- /dev/null +++ b/Ymodem.cpp @@ -0,0 +1,1791 @@ +/** + ****************************************************************************** + * @file Ymodem.cpp + * @author XinLi + * @version v1.0 + * @date 21-January-2018 + * @brief Ymodem protocol module source file. + ****************************************************************************** + * @attention + * + *

Copyright © 2018 XinLi

+ * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + ****************************************************************************** + */ + +/* Header includes -----------------------------------------------------------*/ +#include "Ymodem.h" +#include + +/* Macro definitions ---------------------------------------------------------*/ +/* Type definitions ----------------------------------------------------------*/ +/* Variable declarations -----------------------------------------------------*/ +/* Variable definitions ------------------------------------------------------*/ +/* Function declarations -----------------------------------------------------*/ +/* Function definitions ------------------------------------------------------*/ + +/** + * @brief Ymodem constructor. + * @param [in] timeDivide: The fractional factor of the time the ymodem is called. + * @param [in] timeMax: The maximum time when calling the ymodem. + * @param [in] errorMax: The maximum error count when calling the ymodem. + * @note The longest waiting time = call time / (@timeDivide + 1) * (@timeMax + 1). + * @return None. + */ +Ymodem::Ymodem(uint32_t timeDivide, uint32_t timeMax, uint32_t errorMax) +{ + this->timeDivide = timeDivide; + this->timeMax = timeMax; + this->errorMax = errorMax; + + this->timeCount = 0; + this->errorCount = 0; + this->dataCount = 0; + + this->code = CodeNone; + this->stage = StageNone; +} + +/** + * @brief Set the fractional factor of the time the ymodem is called. + * @param [in] timeDivide: The fractional factor of the time the ymodem is called. + * @return None. + */ +void Ymodem::setTimeDivide(uint32_t timeDivide) +{ + this->timeDivide = timeDivide; +} + +/** + * @brief Get the fractional factor of the time the ymodem is called. + * @param None. + * @return The fractional factor of the time the ymodem is called. + */ +uint32_t Ymodem::getTimeDivide() +{ + return timeDivide; +} + +/** + * @brief Set the maximum time when calling the ymodem. + * @param [in] timeMax: The maximum time when calling the ymodem. + * @return None. + */ +void Ymodem::setTimeMax(uint32_t timeMax) +{ + this->timeMax = timeMax; +} + +/** + * @brief Get the maximum time when calling the ymodem. + * @param None. + * @return The maximum time when calling the ymodem. + */ +uint32_t Ymodem::getTimeMax() +{ + return timeMax; +} + +/** + * @brief Set the maximum error count when calling the ymodem. + * @param [in] errorMax: The maximum error count when calling the ymodem. + * @return None. + */ +void Ymodem::setErrorMax(uint32_t errorMax) +{ + this->errorMax = errorMax; +} + +/** + * @brief Get the maximum error count when calling the ymodem. + * @param None. + * @return The maximum error count when calling the ymodem. + */ +uint32_t Ymodem::getErrorMax() +{ + return errorMax; +} + +/** + * @brief Ymodem receive. + * @param None. + * @return None. + */ +void Ymodem::receive() +{ + switch(stage) + { + case StageNone: + { + receiveStageNone(); + + break; + } + + case StageEstablishing: + { + receiveStageEstablishing(); + + break; + } + + case StageEstablished: + { + receiveStageEstablished(); + + break; + } + + case StageTransmitting: + { + receiveStageTransmitting(); + + break; + } + + case StageFinishing: + { + receiveStageFinishing(); + + break; + } + + default: + { + receiveStageFinished(); + } + } +} + +/** + * @brief Ymodem transmit. + * @param None. + * @return None. + */ +void Ymodem::transmit() +{ + switch(stage) + { + case StageNone: + { + transmitStageNone(); + + break; + } + + case StageEstablishing: + { + transmitStageEstablishing(); + + break; + } + + case StageEstablished: + { + transmitStageEstablished(); + + break; + } + + case StageTransmitting: + { + transmitStageTransmitting(); + + break; + } + + case StageFinishing: + { + transmitStageFinishing(); + + break; + } + + default: + { + transmitStageFinished(); + } + } +} + +/** + * @brief Ymodem abort. + * @param None. + * @return None. + */ +void Ymodem::abort() +{ + timeCount = 0; + errorCount = 0; + dataCount = 0; + code = CodeNone; + stage = StageNone; + + for(txLength = 0; txLength < YMODEM_CODE_CAN_NUMBER; txLength++) + { + txBuffer[txLength] = CodeCan; + } + + write(txBuffer, txLength); +} + +/** + * @brief Receives a packet of data. + * @param None. + * @return Packet type. + */ +Ymodem::Code Ymodem::receivePacket() +{ + if(code == CodeNone) + { + if(read(&(rxBuffer[0]), 1) > 0) + { + if(rxBuffer[0] == CodeSoh) + { + uint32_t len = read(&(rxBuffer[1]), YMODEM_PACKET_SIZE + YMODEM_PACKET_OVERHEAD - 1); + + if(len < (YMODEM_PACKET_SIZE + YMODEM_PACKET_OVERHEAD - 1)) + { + rxLength = len + 1; + code = CodeSoh; + + return CodeNone; + } + else + { + return CodeSoh; + } + } + else if(rxBuffer[0] == CodeStx) + { + uint32_t len = read(&(rxBuffer[1]), YMODEM_PACKET_1K_SIZE + YMODEM_PACKET_OVERHEAD - 1); + + if(len < (YMODEM_PACKET_1K_SIZE + YMODEM_PACKET_OVERHEAD - 1)) + { + rxLength = len + 1; + code = CodeStx; + + return CodeNone; + } + else + { + return CodeStx; + } + } + else + { + return (Code)(rxBuffer[0]); + } + } + else + { + return CodeNone; + } + } + else + { + if(code == CodeSoh) + { + uint32_t len = read(&(rxBuffer[rxLength]), YMODEM_PACKET_SIZE + YMODEM_PACKET_OVERHEAD - rxLength); + + if(len < (YMODEM_PACKET_SIZE + YMODEM_PACKET_OVERHEAD - rxLength)) + { + rxLength += len; + + return CodeNone; + } + else + { + code = CodeNone; + + return CodeSoh; + } + } + else if(code == CodeStx) + { + uint32_t len = read(&(rxBuffer[rxLength]), YMODEM_PACKET_1K_SIZE + YMODEM_PACKET_OVERHEAD - rxLength); + + if(len < (YMODEM_PACKET_1K_SIZE + YMODEM_PACKET_OVERHEAD - rxLength)) + { + rxLength += len; + + return CodeNone; + } + else + { + code = CodeNone; + + return CodeStx; + } + } + else + { + code = CodeNone; + + return CodeNone; + } + } +} + +/** + * @brief Receive none stage. + * @param None. + * @return None. + */ +void Ymodem::receiveStageNone() +{ + timeCount = 0; + errorCount = 0; + dataCount = 0; + code = CodeNone; + stage = StageEstablishing; + txBuffer[0] = CodeC; + txLength = 1; + write(txBuffer, txLength); +} + +/** + * @brief Receive establishing stage. + * @param None. + * @return None. + */ +void Ymodem::receiveStageEstablishing() +{ + switch(receivePacket()) + { + case CodeSoh: + { + uint16_t crc = ((uint16_t)(rxBuffer[YMODEM_PACKET_SIZE + YMODEM_PACKET_OVERHEAD - 2]) << 8) | + ((uint16_t)(rxBuffer[YMODEM_PACKET_SIZE + YMODEM_PACKET_OVERHEAD - 1]) << 0); + + if((rxBuffer[1] == 0x00) && (rxBuffer[2] == 0xFF) && + (crc == crc16(&(rxBuffer[YMODEM_PACKET_HEADER]), YMODEM_PACKET_SIZE))) + { + uint32_t dataLength = YMODEM_PACKET_SIZE; + + if(callback(StatusEstablish, &(rxBuffer[YMODEM_PACKET_HEADER]), &dataLength) == CodeAck) + { + timeCount = 0; + errorCount = 0; + dataCount = 0; + code = CodeNone; + stage = StageEstablished; + txBuffer[0] = CodeAck; + txBuffer[1] = CodeC; + txLength = 2; + write(txBuffer, txLength); + } + else + { + timeCount = 0; + errorCount = 0; + dataCount = 0; + code = CodeNone; + stage = StageNone; + + for(txLength = 0; txLength < YMODEM_CODE_CAN_NUMBER; txLength++) + { + txBuffer[txLength] = CodeCan; + } + + write(txBuffer, txLength); + } + } + else + { + errorCount++; + + if(errorCount > errorMax) + { + timeCount = 0; + errorCount = 0; + dataCount = 0; + code = CodeNone; + stage = StageNone; + + for(txLength = 0; txLength < YMODEM_CODE_CAN_NUMBER; txLength++) + { + txBuffer[txLength] = CodeCan; + } + + write(txBuffer, txLength); + callback(StatusError, NULL, NULL); + } + else + { + txBuffer[0] = CodeC; + txLength = 1; + write(txBuffer, txLength); + } + } + + break; + } + + case CodeA1: + case CodeA2: + case CodeCan: + { + timeCount = 0; + errorCount = 0; + dataCount = 0; + code = CodeNone; + stage = StageNone; + callback(StatusAbort, NULL, NULL); + + break; + } + + default: + { + timeCount++; + + if((timeCount / (timeDivide + 1)) > timeMax) + { + timeCount = 0; + errorCount = 0; + dataCount = 0; + code = CodeNone; + stage = StageNone; + + for(txLength = 0; txLength < YMODEM_CODE_CAN_NUMBER; txLength++) + { + txBuffer[txLength] = CodeCan; + } + + write(txBuffer, txLength); + callback(StatusTimeout, NULL, NULL); + } + else if((timeCount % (timeDivide + 1)) == 0) + { + txBuffer[0] = CodeC; + txLength = 1; + write(txBuffer, txLength); + } + } + } +} + +/** + * @brief Receive established stage. + * @param None. + * @return None. + */ +void Ymodem::receiveStageEstablished() +{ + switch(receivePacket()) + { + case CodeSoh: + { + uint16_t crc = ((uint16_t)(rxBuffer[YMODEM_PACKET_SIZE + YMODEM_PACKET_OVERHEAD - 2]) << 8) | + ((uint16_t)(rxBuffer[YMODEM_PACKET_SIZE + YMODEM_PACKET_OVERHEAD - 1]) << 0); + + if((rxBuffer[1] == 0x00) && (rxBuffer[2] == 0xFF) && + (crc == crc16(&(rxBuffer[YMODEM_PACKET_HEADER]), YMODEM_PACKET_SIZE))) + { + errorCount++; + + if(errorCount > errorMax) + { + timeCount = 0; + errorCount = 0; + dataCount = 0; + code = CodeNone; + stage = StageNone; + + for(txLength = 0; txLength < YMODEM_CODE_CAN_NUMBER; txLength++) + { + txBuffer[txLength] = CodeCan; + } + + write(txBuffer, txLength); + callback(StatusError, NULL, NULL); + } + else + { + txBuffer[0] = CodeAck; + txBuffer[1] = CodeC; + txLength = 2; + write(txBuffer, txLength); + } + } + else if((rxBuffer[1] == 0x01) && (rxBuffer[2] == 0xFE) && + (crc == crc16(&(rxBuffer[YMODEM_PACKET_HEADER]), YMODEM_PACKET_SIZE))) + { + uint32_t dataLength = YMODEM_PACKET_SIZE; + + if(callback(StatusTransmit, &(rxBuffer[YMODEM_PACKET_HEADER]), &dataLength) == CodeAck) + { + timeCount = 0; + errorCount = 0; + dataCount = 1; + code = CodeNone; + stage = StageTransmitting; + txBuffer[0] = CodeAck; + txLength = 1; + write(txBuffer, txLength); + } + else + { + timeCount = 0; + errorCount = 0; + dataCount = 0; + code = CodeNone; + stage = StageNone; + + for(txLength = 0; txLength < YMODEM_CODE_CAN_NUMBER; txLength++) + { + txBuffer[txLength] = CodeCan; + } + + write(txBuffer, txLength); + } + } + else + { + errorCount++; + + if(errorCount > errorMax) + { + timeCount = 0; + errorCount = 0; + dataCount = 0; + code = CodeNone; + stage = StageNone; + + for(txLength = 0; txLength < YMODEM_CODE_CAN_NUMBER; txLength++) + { + txBuffer[txLength] = CodeCan; + } + + write(txBuffer, txLength); + callback(StatusError, NULL, NULL); + } + else + { + txBuffer[0] = CodeNak; + txLength = 1; + write(txBuffer, txLength); + } + } + + break; + } + + case CodeStx: + { + uint16_t crc = ((uint16_t)(rxBuffer[YMODEM_PACKET_1K_SIZE + YMODEM_PACKET_OVERHEAD - 2]) << 8) | + ((uint16_t)(rxBuffer[YMODEM_PACKET_1K_SIZE + YMODEM_PACKET_OVERHEAD - 1]) << 0); + + if((rxBuffer[1] == 0x01) && (rxBuffer[2] == 0xFE) && + (crc == crc16(&(rxBuffer[YMODEM_PACKET_HEADER]), YMODEM_PACKET_1K_SIZE))) + { + uint32_t dataLength = YMODEM_PACKET_1K_SIZE; + + if(callback(StatusTransmit, &(rxBuffer[YMODEM_PACKET_HEADER]), &dataLength) == CodeAck) + { + timeCount = 0; + errorCount = 0; + dataCount = 1; + code = CodeNone; + stage = StageTransmitting; + txBuffer[0] = CodeAck; + txLength = 1; + write(txBuffer, txLength); + } + else + { + timeCount = 0; + errorCount = 0; + dataCount = 0; + code = CodeNone; + stage = StageNone; + + for(txLength = 0; txLength < YMODEM_CODE_CAN_NUMBER; txLength++) + { + txBuffer[txLength] = CodeCan; + } + + write(txBuffer, txLength); + } + } + else + { + errorCount++; + + if(errorCount > errorMax) + { + timeCount = 0; + errorCount = 0; + dataCount = 0; + code = CodeNone; + stage = StageNone; + + for(txLength = 0; txLength < YMODEM_CODE_CAN_NUMBER; txLength++) + { + txBuffer[txLength] = CodeCan; + } + + write(txBuffer, txLength); + callback(StatusError, NULL, NULL); + } + else + { + txBuffer[0] = CodeNak; + txLength = 1; + write(txBuffer, txLength); + } + } + + break; + } + + case CodeEot: + { + timeCount = 0; + errorCount = 0; + dataCount = 0; + code = CodeNone; + stage = StageFinishing; + txBuffer[0] = CodeNak; + txLength = 1; + write(txBuffer, txLength); + + break; + } + + case CodeA1: + case CodeA2: + case CodeCan: + { + timeCount = 0; + errorCount = 0; + dataCount = 0; + code = CodeNone; + stage = StageNone; + callback(StatusAbort, NULL, NULL); + + break; + } + + default: + { + timeCount++; + + if((timeCount / (timeDivide + 1)) > timeMax) + { + timeCount = 0; + errorCount = 0; + dataCount = 0; + code = CodeNone; + stage = StageNone; + + for(txLength = 0; txLength < YMODEM_CODE_CAN_NUMBER; txLength++) + { + txBuffer[txLength] = CodeCan; + } + + write(txBuffer, txLength); + callback(StatusError, NULL, NULL); + } + else if((timeCount % (timeDivide + 1)) == 0) + { + txBuffer[0] = CodeNak; + txLength = 1; + write(txBuffer, txLength); + } + } + } +} + +/** + * @brief Receive transmitting stage. + * @param None. + * @return None. + */ +void Ymodem::receiveStageTransmitting() +{ + switch(receivePacket()) + { + case CodeSoh: + { + uint16_t crc = ((uint16_t)(rxBuffer[YMODEM_PACKET_SIZE + YMODEM_PACKET_OVERHEAD - 2]) << 8) | + ((uint16_t)(rxBuffer[YMODEM_PACKET_SIZE + YMODEM_PACKET_OVERHEAD - 1]) << 0); + + if((rxBuffer[1] == (uint8_t)(dataCount)) && (rxBuffer[2] == (uint8_t)(0xFF - dataCount)) && + (crc == crc16(&(rxBuffer[YMODEM_PACKET_HEADER]), YMODEM_PACKET_SIZE))) + { + errorCount++; + + if(errorCount > errorMax) + { + timeCount = 0; + errorCount = 0; + dataCount = 0; + code = CodeNone; + stage = StageNone; + + for(txLength = 0; txLength < YMODEM_CODE_CAN_NUMBER; txLength++) + { + txBuffer[txLength] = CodeCan; + } + + write(txBuffer, txLength); + callback(StatusError, NULL, NULL); + } + else + { + txBuffer[0] = CodeAck; + txLength = 1; + write(txBuffer, txLength); + } + } + else if((rxBuffer[1] == (uint8_t)(dataCount + 1)) && (rxBuffer[2] == (uint8_t)(0xFE - dataCount)) && + (crc == crc16(&(rxBuffer[YMODEM_PACKET_HEADER]), YMODEM_PACKET_SIZE))) + { + uint32_t dataLength = YMODEM_PACKET_SIZE; + + if(callback(StatusTransmit, &(rxBuffer[YMODEM_PACKET_HEADER]), &dataLength) == CodeAck) + { + timeCount = 0; + errorCount = 0; + dataCount = dataCount + 1; + code = CodeNone; + stage = StageTransmitting; + txBuffer[0] = CodeAck; + txLength = 1; + write(txBuffer, txLength); + } + else + { + timeCount = 0; + errorCount = 0; + dataCount = 0; + code = CodeNone; + stage = StageNone; + + for(txLength = 0; txLength < YMODEM_CODE_CAN_NUMBER; txLength++) + { + txBuffer[txLength] = CodeCan; + } + + write(txBuffer, txLength); + } + } + else + { + errorCount++; + + if(errorCount > errorMax) + { + timeCount = 0; + errorCount = 0; + dataCount = 0; + code = CodeNone; + stage = StageNone; + + for(txLength = 0; txLength < YMODEM_CODE_CAN_NUMBER; txLength++) + { + txBuffer[txLength] = CodeCan; + } + + write(txBuffer, txLength); + callback(StatusError, NULL, NULL); + } + else + { + txBuffer[0] = CodeNak; + txLength = 1; + write(txBuffer, txLength); + } + } + + break; + } + + case CodeStx: + { + uint16_t crc = ((uint16_t)(rxBuffer[YMODEM_PACKET_1K_SIZE + YMODEM_PACKET_OVERHEAD - 2]) << 8) | + ((uint16_t)(rxBuffer[YMODEM_PACKET_1K_SIZE + YMODEM_PACKET_OVERHEAD - 1]) << 0); + + if((rxBuffer[1] == (uint8_t)(dataCount)) && (rxBuffer[2] == (uint8_t)(0xFF - dataCount)) && + (crc == crc16(&(rxBuffer[YMODEM_PACKET_HEADER]), YMODEM_PACKET_1K_SIZE))) + { + errorCount++; + + if(errorCount > errorMax) + { + timeCount = 0; + errorCount = 0; + dataCount = 0; + code = CodeNone; + stage = StageNone; + + for(txLength = 0; txLength < YMODEM_CODE_CAN_NUMBER; txLength++) + { + txBuffer[txLength] = CodeCan; + } + + write(txBuffer, txLength); + callback(StatusError, NULL, NULL); + } + else + { + txBuffer[0] = CodeAck; + txLength = 1; + write(txBuffer, txLength); + } + } + else if((rxBuffer[1] == (uint8_t)(dataCount + 1)) && (rxBuffer[2] == (uint8_t)(0xFE - dataCount)) && + (crc == crc16(&(rxBuffer[YMODEM_PACKET_HEADER]), YMODEM_PACKET_1K_SIZE))) + { + uint32_t dataLength = YMODEM_PACKET_1K_SIZE; + + if(callback(StatusTransmit, &(rxBuffer[YMODEM_PACKET_HEADER]), &dataLength) == CodeAck) + { + timeCount = 0; + errorCount = 0; + dataCount = dataCount + 1; + code = CodeNone; + stage = StageTransmitting; + txBuffer[0] = CodeAck; + txLength = 1; + write(txBuffer, txLength); + } + else + { + timeCount = 0; + errorCount = 0; + dataCount = 0; + code = CodeNone; + stage = StageNone; + + for(txLength = 0; txLength < YMODEM_CODE_CAN_NUMBER; txLength++) + { + txBuffer[txLength] = CodeCan; + } + + write(txBuffer, txLength); + } + } + else + { + errorCount++; + + if(errorCount > errorMax) + { + timeCount = 0; + errorCount = 0; + dataCount = 0; + code = CodeNone; + stage = StageNone; + + for(txLength = 0; txLength < YMODEM_CODE_CAN_NUMBER; txLength++) + { + txBuffer[txLength] = CodeCan; + } + + write(txBuffer, txLength); + callback(StatusError, NULL, NULL); + } + else + { + txBuffer[0] = CodeNak; + txLength = 1; + write(txBuffer, txLength); + } + } + + break; + } + + case CodeEot: + { + timeCount = 0; + errorCount = 0; + dataCount = 0; + code = CodeNone; + stage = StageFinishing; + txBuffer[0] = CodeNak; + txLength = 1; + write(txBuffer, txLength); + + break; + } + + case CodeA1: + case CodeA2: + case CodeCan: + { + timeCount = 0; + errorCount = 0; + dataCount = 0; + code = CodeNone; + stage = StageNone; + callback(StatusAbort, NULL, NULL); + + break; + } + + default: + { + timeCount++; + + if((timeCount / (timeDivide + 1)) > timeMax) + { + timeCount = 0; + errorCount = 0; + dataCount = 0; + code = CodeNone; + stage = StageNone; + + for(txLength = 0; txLength < YMODEM_CODE_CAN_NUMBER; txLength++) + { + txBuffer[txLength] = CodeCan; + } + + write(txBuffer, txLength); + callback(StatusError, NULL, NULL); + } + else if((timeCount % (timeDivide + 1)) == 0) + { + txBuffer[0] = CodeNak; + txLength = 1; + write(txBuffer, txLength); + } + } + } +} + +/** + * @brief Receive finishing stage. + * @param None. + * @return None. + */ +void Ymodem::receiveStageFinishing() +{ + switch(receivePacket()) + { + case CodeEot: + { + timeCount = 0; + errorCount = 0; + dataCount = 0; + code = CodeNone; + stage = StageFinished; + txBuffer[0] = CodeAck; + txBuffer[1] = CodeC; + txLength = 2; + write(txBuffer, txLength); + + break; + } + + case CodeA1: + case CodeA2: + case CodeCan: + { + timeCount = 0; + errorCount = 0; + dataCount = 0; + code = CodeNone; + stage = StageNone; + callback(StatusAbort, NULL, NULL); + + break; + } + + default: + { + timeCount++; + + if((timeCount / (timeDivide + 1)) > timeMax) + { + timeCount = 0; + errorCount = 0; + dataCount = 0; + code = CodeNone; + stage = StageNone; + + for(txLength = 0; txLength < YMODEM_CODE_CAN_NUMBER; txLength++) + { + txBuffer[txLength] = CodeCan; + } + + write(txBuffer, txLength); + callback(StatusError, NULL, NULL); + } + else if((timeCount % (timeDivide + 1)) == 0) + { + txBuffer[0] = CodeNak; + txLength = 1; + write(txBuffer, txLength); + } + } + } +} + +/** + * @brief Receive finished stage. + * @param None. + * @return None. + */ +void Ymodem::receiveStageFinished() +{ + switch(receivePacket()) + { + case CodeSoh: + { + uint16_t crc = ((uint16_t)(rxBuffer[YMODEM_PACKET_SIZE + YMODEM_PACKET_OVERHEAD - 2]) << 8) | + ((uint16_t)(rxBuffer[YMODEM_PACKET_SIZE + YMODEM_PACKET_OVERHEAD - 1]) << 0); + + if((rxBuffer[1] == 0x00) && (rxBuffer[2] == 0xFF) && + (crc == crc16(&(rxBuffer[YMODEM_PACKET_HEADER]), YMODEM_PACKET_SIZE))) + { + timeCount = 0; + errorCount = 0; + dataCount = 0; + code = CodeNone; + stage = StageNone; + txBuffer[0] = CodeAck; + txLength = 1; + write(txBuffer, txLength); + callback(StatusFinish, NULL, NULL); + } + else + { + errorCount++; + + if(errorCount > errorMax) + { + timeCount = 0; + errorCount = 0; + dataCount = 0; + code = CodeNone; + stage = StageNone; + + for(txLength = 0; txLength < YMODEM_CODE_CAN_NUMBER; txLength++) + { + txBuffer[txLength] = CodeCan; + } + + write(txBuffer, txLength); + callback(StatusError, NULL, NULL); + } + else + { + txBuffer[0] = CodeNak; + txLength = 1; + write(txBuffer, txLength); + } + } + + break; + } + + case CodeEot: + { + errorCount++; + + if(errorCount > errorMax) + { + timeCount = 0; + errorCount = 0; + dataCount = 0; + code = CodeNone; + stage = StageNone; + + for(txLength = 0; txLength < YMODEM_CODE_CAN_NUMBER; txLength++) + { + txBuffer[txLength] = CodeCan; + } + + write(txBuffer, txLength); + callback(StatusError, NULL, NULL); + } + else + { + txBuffer[0] = CodeAck; + txBuffer[1] = CodeC; + txLength = 2; + write(txBuffer, txLength); + } + + break; + } + + case CodeA1: + case CodeA2: + case CodeCan: + { + timeCount = 0; + errorCount = 0; + dataCount = 0; + code = CodeNone; + stage = StageNone; + callback(StatusAbort, NULL, NULL); + + break; + } + + default: + { + timeCount++; + + if((timeCount / (timeDivide + 1)) > timeMax) + { + timeCount = 0; + errorCount = 0; + dataCount = 0; + code = CodeNone; + stage = StageNone; + + for(txLength = 0; txLength < YMODEM_CODE_CAN_NUMBER; txLength++) + { + txBuffer[txLength] = CodeCan; + } + + write(txBuffer, txLength); + callback(StatusError, NULL, NULL); + } + else if((timeCount % (timeDivide + 1)) == 0) + { + txBuffer[0] = CodeNak; + txLength = 1; + write(txBuffer, txLength); + } + } + } +} + +/** + * @brief Transmit none stage. + * @param None. + * @return None. + */ +void Ymodem::transmitStageNone() +{ + timeCount = 0; + errorCount = 0; + dataCount = 0; + code = CodeNone; + stage = StageEstablishing; +} + +/** + * @brief Transmit establishing stage. + * @param None. + * @return None. + */ +void Ymodem::transmitStageEstablishing() +{ + switch(receivePacket()) + { + case CodeC: + { + memset(&(txBuffer[YMODEM_PACKET_HEADER]), NULL, YMODEM_PACKET_SIZE); + + if(callback(StatusEstablish, &(txBuffer[YMODEM_PACKET_HEADER]), &(txLength)) == CodeAck) + { + uint16_t crc = crc16(&(txBuffer[YMODEM_PACKET_HEADER]), txLength); + + timeCount = 0; + errorCount = 0; + dataCount = 0; + code = CodeNone; + stage = StageEstablished; + txBuffer[0] = CodeSoh; + txBuffer[1] = 0x00; + txBuffer[2] = 0xFF; + txBuffer[txLength + YMODEM_PACKET_OVERHEAD - 2] = (uint8_t)(crc >> 8); + txBuffer[txLength + YMODEM_PACKET_OVERHEAD - 1] = (uint8_t)(crc >> 0); + txLength = txLength + YMODEM_PACKET_OVERHEAD; + write(txBuffer, txLength); + } + else + { + timeCount = 0; + errorCount = 0; + dataCount = 0; + code = CodeNone; + stage = StageNone; + + for(txLength = 0; txLength < YMODEM_CODE_CAN_NUMBER; txLength++) + { + txBuffer[txLength] = CodeCan; + } + + write(txBuffer, txLength); + } + + break; + } + + case CodeA1: + case CodeA2: + case CodeCan: + { + timeCount = 0; + errorCount = 0; + dataCount = 0; + code = CodeNone; + stage = StageNone; + callback(StatusAbort, NULL, NULL); + + break; + } + + default: + { + timeCount++; + + if((timeCount / (timeDivide + 1)) > timeMax) + { + timeCount = 0; + errorCount = 0; + dataCount = 0; + code = CodeNone; + stage = StageNone; + + for(txLength = 0; txLength < YMODEM_CODE_CAN_NUMBER; txLength++) + { + txBuffer[txLength] = CodeCan; + } + + write(txBuffer, txLength); + callback(StatusTimeout, NULL, NULL); + } + } + } +} + +/** + * @brief Transmit established stage. + * @param None. + * @return None. + */ +void Ymodem::transmitStageEstablished() +{ + switch(receivePacket()) + { + case CodeNak: + { + errorCount++; + + if(errorCount > errorMax) + { + timeCount = 0; + errorCount = 0; + dataCount = 0; + code = CodeNone; + stage = StageNone; + + for(txLength = 0; txLength < YMODEM_CODE_CAN_NUMBER; txLength++) + { + txBuffer[txLength] = CodeCan; + } + + write(txBuffer, txLength); + callback(StatusError, NULL, NULL); + } + else + { + write(txBuffer, txLength); + } + + break; + } + + case CodeC: + { + errorCount++; + + if(errorCount > errorMax) + { + timeCount = 0; + errorCount = 0; + dataCount = 0; + code = CodeNone; + stage = StageNone; + + for(txLength = 0; txLength < YMODEM_CODE_CAN_NUMBER; txLength++) + { + txBuffer[txLength] = CodeCan; + } + + write(txBuffer, txLength); + callback(StatusError, NULL, NULL); + } + else + { + timeCount = 0; + errorCount = 0; + dataCount = dataCount; + code = CodeNone; + stage = (Stage)(stage + dataCount); + write(txBuffer, txLength); + } + + break; + } + + case CodeAck: + { + memset(&(txBuffer[YMODEM_PACKET_HEADER]), NULL, YMODEM_PACKET_1K_SIZE); + + switch(callback(StatusTransmit, &(txBuffer[YMODEM_PACKET_HEADER]), &(txLength))) + { + case CodeAck: + { + uint16_t crc = crc16(&(txBuffer[YMODEM_PACKET_HEADER]), txLength); + + timeCount = 0; + errorCount = 0; + dataCount = 1; + code = CodeNone; + stage = StageEstablished; + txBuffer[0] = txLength > YMODEM_PACKET_SIZE ? CodeStx : CodeSoh; + txBuffer[1] = 0x01; + txBuffer[2] = 0xFE; + txBuffer[txLength + YMODEM_PACKET_OVERHEAD - 2] = (uint8_t)(crc >> 8); + txBuffer[txLength + YMODEM_PACKET_OVERHEAD - 1] = (uint8_t)(crc >> 0); + txLength = txLength + YMODEM_PACKET_OVERHEAD; + + break; + } + + case CodeEot: + { + timeCount = 0; + errorCount = 0; + dataCount = 2; + code = CodeNone; + stage = StageEstablished; + txBuffer[0] = CodeEot; + txLength = 1; + write(txBuffer, txLength); + + break; + } + + default: + { + timeCount = 0; + errorCount = 0; + dataCount = 0; + code = CodeNone; + stage = StageNone; + + for(txLength = 0; txLength < YMODEM_CODE_CAN_NUMBER; txLength++) + { + txBuffer[txLength] = CodeCan; + } + + write(txBuffer, txLength); + } + } + + break; + } + + case CodeA1: + case CodeA2: + case CodeCan: + { + timeCount = 0; + errorCount = 0; + dataCount = 0; + code = CodeNone; + stage = StageNone; + callback(StatusAbort, NULL, NULL); + + break; + } + + default: + { + timeCount++; + + if((timeCount / (timeDivide + 1)) > timeMax) + { + timeCount = 0; + errorCount = 0; + dataCount = 0; + code = CodeNone; + stage = StageNone; + + for(txLength = 0; txLength < YMODEM_CODE_CAN_NUMBER; txLength++) + { + txBuffer[txLength] = CodeCan; + } + + write(txBuffer, txLength); + callback(StatusError, NULL, NULL); + } + else if((timeCount % (timeDivide + 1)) == 0) + { + write(txBuffer, txLength); + } + } + } +} + +/** + * @brief Transmit transmitting stage. + * @param None. + * @return None. + */ +void Ymodem::transmitStageTransmitting() +{ + switch(receivePacket()) + { + case CodeNak: + { + errorCount++; + + if(errorCount > errorMax) + { + timeCount = 0; + errorCount = 0; + dataCount = 0; + code = CodeNone; + stage = StageNone; + + for(txLength = 0; txLength < YMODEM_CODE_CAN_NUMBER; txLength++) + { + txBuffer[txLength] = CodeCan; + } + + write(txBuffer, txLength); + callback(StatusError, NULL, NULL); + } + else + { + write(txBuffer, txLength); + } + + break; + } + + case CodeAck: + { + memset(&(txBuffer[YMODEM_PACKET_HEADER]), NULL, YMODEM_PACKET_1K_SIZE); + + switch(callback(StatusTransmit, &(txBuffer[YMODEM_PACKET_HEADER]), &(txLength))) + { + case CodeAck: + { + uint16_t crc = crc16(&(txBuffer[YMODEM_PACKET_HEADER]), txLength); + + timeCount = 0; + errorCount = 0; + dataCount = dataCount + 1; + code = CodeNone; + stage = StageTransmitting; + txBuffer[0] = txLength > YMODEM_PACKET_SIZE ? CodeStx : CodeSoh; + txBuffer[1] = dataCount; + txBuffer[2] = 0xFF - dataCount; + txBuffer[txLength + YMODEM_PACKET_OVERHEAD - 2] = (uint8_t)(crc >> 8); + txBuffer[txLength + YMODEM_PACKET_OVERHEAD - 1] = (uint8_t)(crc >> 0); + txLength = txLength + YMODEM_PACKET_OVERHEAD; + write(txBuffer, txLength); + + break; + } + + case CodeEot: + { + timeCount = 0; + errorCount = 0; + dataCount = 0; + code = CodeNone; + stage = StageFinishing; + txBuffer[0] = CodeEot; + txLength = 1; + write(txBuffer, txLength); + + break; + } + + default: + { + timeCount = 0; + errorCount = 0; + dataCount = 0; + code = CodeNone; + stage = StageNone; + + for(txLength = 0; txLength < YMODEM_CODE_CAN_NUMBER; txLength++) + { + txBuffer[txLength] = CodeCan; + } + + write(txBuffer, txLength); + } + } + + break; + } + + case CodeA1: + case CodeA2: + case CodeCan: + { + timeCount = 0; + errorCount = 0; + dataCount = 0; + code = CodeNone; + stage = StageNone; + callback(StatusAbort, NULL, NULL); + + break; + } + + default: + { + timeCount++; + + if((timeCount / (timeDivide + 1)) > timeMax) + { + timeCount = 0; + errorCount = 0; + dataCount = 0; + code = CodeNone; + stage = StageNone; + + for(txLength = 0; txLength < YMODEM_CODE_CAN_NUMBER; txLength++) + { + txBuffer[txLength] = CodeCan; + } + + write(txBuffer, txLength); + callback(StatusError, NULL, NULL); + } + else if((timeCount % (timeDivide + 1)) == 0) + { + write(txBuffer, txLength); + } + } + } +} + +/** + * @brief Transmit finishing stage. + * @param None. + * @return None. + */ +void Ymodem::transmitStageFinishing() +{ + switch(receivePacket()) + { + case CodeNak: + { + timeCount = 0; + errorCount = 0; + dataCount = 0; + code = CodeNone; + stage = StageFinishing; + txBuffer[0] = CodeEot; + txLength = 1; + write(txBuffer, txLength); + + break; + } + + case CodeC: + { + memset(&(txBuffer[YMODEM_PACKET_HEADER]), NULL, YMODEM_PACKET_SIZE); + uint16_t crc = crc16(&(txBuffer[YMODEM_PACKET_HEADER]), YMODEM_PACKET_SIZE); + + timeCount = 0; + errorCount = 0; + dataCount = 0; + code = CodeNone; + stage = StageFinished; + txBuffer[0] = CodeSoh; + txBuffer[1] = 0x00; + txBuffer[2] = 0xFF; + txBuffer[YMODEM_PACKET_SIZE + YMODEM_PACKET_OVERHEAD - 2] = (uint8_t)(crc >> 8); + txBuffer[YMODEM_PACKET_SIZE + YMODEM_PACKET_OVERHEAD - 1] = (uint8_t)(crc >> 0); + txLength = YMODEM_PACKET_SIZE + YMODEM_PACKET_OVERHEAD; + write(txBuffer, txLength); + + break; + } + + case CodeA1: + case CodeA2: + case CodeCan: + { + timeCount = 0; + errorCount = 0; + dataCount = 0; + code = CodeNone; + stage = StageNone; + callback(StatusAbort, NULL, NULL); + + break; + } + + default: + { + timeCount++; + + if((timeCount / (timeDivide + 1)) > timeMax) + { + timeCount = 0; + errorCount = 0; + dataCount = 0; + code = CodeNone; + stage = StageNone; + + for(txLength = 0; txLength < YMODEM_CODE_CAN_NUMBER; txLength++) + { + txBuffer[txLength] = CodeCan; + } + + write(txBuffer, txLength); + callback(StatusError, NULL, NULL); + } + else if((timeCount % (timeDivide + 1)) == 0) + { + write(txBuffer, txLength); + } + } + } +} + +/** + * @brief Transmit finished stage. + * @param None. + * @return None. + */ +void Ymodem::transmitStageFinished() +{ + switch(receivePacket()) + { + case CodeC: + case CodeNak: + { + errorCount++; + + if(errorCount > errorMax) + { + timeCount = 0; + errorCount = 0; + dataCount = 0; + code = CodeNone; + stage = StageNone; + + for(txLength = 0; txLength < YMODEM_CODE_CAN_NUMBER; txLength++) + { + txBuffer[txLength] = CodeCan; + } + + write(txBuffer, txLength); + callback(StatusError, NULL, NULL); + } + else + { + write(txBuffer, txLength); + } + + break; + } + + case CodeAck: + { + timeCount = 0; + errorCount = 0; + dataCount = 0; + code = CodeNone; + stage = StageNone; + callback(StatusFinish, NULL, NULL); + + break; + } + + case CodeA1: + case CodeA2: + case CodeCan: + { + timeCount = 0; + errorCount = 0; + dataCount = 0; + code = CodeNone; + stage = StageNone; + callback(StatusAbort, NULL, NULL); + + break; + } + + default: + { + timeCount++; + + if((timeCount / (timeDivide + 1)) > timeMax) + { + timeCount = 0; + errorCount = 0; + dataCount = 0; + code = CodeNone; + stage = StageNone; + + for(txLength = 0; txLength < YMODEM_CODE_CAN_NUMBER; txLength++) + { + txBuffer[txLength] = CodeCan; + } + + write(txBuffer, txLength); + callback(StatusError, NULL, NULL); + } + else if((timeCount % (timeDivide + 1)) == 0) + { + write(txBuffer, txLength); + } + } + } +} + +/** + * @brief Calculate CRC16 checksum. + * @param [in] buff: The data to be calculated. + * @param [in] len: The length of the data to be calculated. + * @return Calculated CRC16 checksum. + */ +uint16_t Ymodem::crc16(uint8_t *buff, uint32_t len) +{ + uint16_t crc = 0; + + while(len--) + { + crc ^= (uint16_t)(*(buff++)) << 8; + + for(int i = 0; i < 8; i++) + { + if(crc & 0x8000) + { + crc = (crc << 1) ^ 0x1021; + } + else + { + crc = crc << 1; + } + } + } + + return crc; +} diff --git a/Ymodem.h b/Ymodem.h new file mode 100644 index 0000000..8939537 --- /dev/null +++ b/Ymodem.h @@ -0,0 +1,143 @@ +/** + ****************************************************************************** + * @file Ymodem.h + * @author XinLi + * @version v1.0 + * @date 21-January-2018 + * @brief Header file for Ymodem.cpp module. + ****************************************************************************** + * @attention + * + *

Copyright © 2018 XinLi

+ * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + ****************************************************************************** + */ + +#ifndef __YMODEM_H +#define __YMODEM_H + +/* Header includes -----------------------------------------------------------*/ +#include + +/* Macro definitions ---------------------------------------------------------*/ +#define YMODEM_PACKET_HEADER (3) +#define YMODEM_PACKET_TRAILER (2) +#define YMODEM_PACKET_OVERHEAD (YMODEM_PACKET_HEADER + YMODEM_PACKET_TRAILER) +#define YMODEM_PACKET_SIZE (128) +#define YMODEM_PACKET_1K_SIZE (1024) + +#define YMODEM_CODE_CAN_NUMBER (5) + +/* Type definitions ----------------------------------------------------------*/ +class Ymodem +{ +public: + enum Code + { + CodeNone = 0x00, + CodeSoh = 0x01, + CodeStx = 0x02, + CodeEot = 0x04, + CodeAck = 0x06, + CodeNak = 0x15, + CodeCan = 0x18, + CodeC = 0x43, + CodeA1 = 0x41, + CodeA2 = 0x61 + }; + + enum Stage + { + StageNone, + StageEstablishing, + StageEstablished, + StageTransmitting, + StageFinishing, + StageFinished + }; + + enum Status + { + StatusEstablish, + StatusTransmit, + StatusFinish, + StatusAbort, + StatusTimeout, + StatusError + }; + + Ymodem(uint32_t timeDivide = 499, uint32_t timeMax = 5, uint32_t errorMax = 999); + + void setTimeDivide(uint32_t timeDivide); + uint32_t getTimeDivide(); + + void setTimeMax(uint32_t timeMax); + uint32_t getTimeMax(); + + void setErrorMax(uint32_t errorMax); + uint32_t getErrorMax(); + + void receive(); + void transmit(); + void abort(); + +private: + Code receivePacket(); + + void receiveStageNone(); + void receiveStageEstablishing(); + void receiveStageEstablished(); + void receiveStageTransmitting(); + void receiveStageFinishing(); + void receiveStageFinished(); + + void transmitStageNone(); + void transmitStageEstablishing(); + void transmitStageEstablished(); + void transmitStageTransmitting(); + void transmitStageFinishing(); + void transmitStageFinished(); + + uint16_t crc16(uint8_t *buff, uint32_t len); + + virtual Code callback(Status status, uint8_t *buff, uint32_t *len) = 0; + + virtual uint32_t read(uint8_t *buff, uint32_t len) = 0; + virtual uint32_t write(uint8_t *buff, uint32_t len) = 0; + + uint32_t timeDivide; + uint32_t timeMax; + uint32_t errorMax; + + uint32_t timeCount; + uint32_t errorCount; + uint8_t dataCount; + + Code code; + Stage stage; + + uint8_t rxBuffer[YMODEM_PACKET_1K_SIZE + YMODEM_PACKET_OVERHEAD]; + uint8_t txBuffer[YMODEM_PACKET_1K_SIZE + YMODEM_PACKET_OVERHEAD]; + uint32_t rxLength; + uint32_t txLength; +}; + +/* Variable declarations -----------------------------------------------------*/ +/* Variable definitions ------------------------------------------------------*/ +/* Function declarations -----------------------------------------------------*/ +/* Function definitions ------------------------------------------------------*/ + +#endif /* __YMODEM_H */ diff --git a/YmodemFileReceive.cpp b/YmodemFileReceive.cpp new file mode 100644 index 0000000..8252fab --- /dev/null +++ b/YmodemFileReceive.cpp @@ -0,0 +1,231 @@ +#include "YmodemFileReceive.h" +#include +#include +#include + +#include +#include +#include "TimeoutSerial.h" + +using namespace std; +using namespace boost; + +#define READ_TIME_OUT (10) +#define WRITE_TIME_OUT (100) + +YmodemFileReceive::YmodemFileReceive() : +{ + setTimeDivide(499); + setTimeMax(5); + setErrorMax(999); + + //connect(readTimer, SIGNAL(timeout()), this, SLOT(readTimeOut())); + //connect(writeTimer, SIGNAL(timeout()), this, SLOT(writeTimeOut())); +} + +YmodemFileReceive::~YmodemFileReceive() +{ + delete file; + delete readTimer; + delete writeTimer; + delete serialPort; +} + +void YmodemFileReceive::setFilePath(const string &path) +{ + filePath = path + "/"; +} + +void YmodemFileReceive::setSerialPort(TimeoutSerial *port) +{ + serialPort = port; +} + +TimeoutSerial *YmodemFileReceive::getSerialPort() +{ + return serialPort; +} + +bool YmodemFileReceive::startReceive() +{ + progress = 0; + status = StatusEstablish; + + serialPort->setTimeout(posix_time::seconds(10)); + return true; +} + +void YmodemFileReceive::stopReceive() +{ + file->close(); + abort(); + status = StatusAbort; +} + +int YmodemFileReceive::getReceiveProgress() +{ + return progress; +} + +Ymodem::Status YmodemFileReceive::getReceiveStatus() +{ + return status; +} + +/* +void YmodemFileReceive::readTimeOut() +{ + readTimer->stop(); + + receive(); + + if((status == StatusEstablish) || (status == StatusTransmit)) + { + readTimer->start(READ_TIME_OUT); + } +} + +void YmodemFileReceive::writeTimeOut() +{ + writeTimer->stop(); + serialPort->close(); + receiveStatus(status); +} +*/ +Ymodem::Code YmodemFileReceive::callback(Status status, uint8_t *buff, uint32_t *len) +{ + switch(status) + { + case StatusEstablish: + { + if(buff[0] != 0) + { + int i = 0; + char name[128] = {0}; + char size[128] = {0}; + + for(int j = 0; buff[i] != 0; i++, j++) + { + name[j] = buff[i]; + } + + i++; + + for(int j = 0; buff[i] != 0; i++, j++) + { + size[j] = buff[i]; + } + + fileName = name; + string file_desc(size); + string sizeStr = file_desc.substr(0,file_desc.find_first_of(' ')); + fileSize = stol(sizeStr); + fileCount = 0; + + file.open(filePath + fileName, ios::out | ios::binary); + + if(file.is_open() == true) + { + YmodemFileReceive::status = StatusEstablish; + + receiveStatus(StatusEstablish); + + return CodeAck; + } + else + { + YmodemFileReceive::status = StatusError; + + writeTimer->start(WRITE_TIME_OUT); + + return CodeCan; + } + } + else + { + YmodemFileReceive::status = StatusError; + + writeTimer->start(WRITE_TIME_OUT); + + return CodeCan; + } + } + + case StatusTransmit: + { + if((fileSize - fileCount) > *len) + { + file->write((char *)buff, *len); + + fileCount += *len; + } + else + { + file->write((char *)buff, fileSize - fileCount); + + fileCount += fileSize - fileCount; + } + + progress = (int)(fileCount * 100 / fileSize); + + YmodemFileReceive::status = StatusTransmit; + + receiveProgress(progress); + receiveStatus(StatusTransmit); + + return CodeAck; + } + + case StatusFinish: + { + file->close(); + + YmodemFileReceive::status = StatusFinish; + + writeTimer->start(WRITE_TIME_OUT); + + return CodeAck; + } + + case StatusAbort: + { + file->close(); + + YmodemFileReceive::status = StatusAbort; + + writeTimer->start(WRITE_TIME_OUT); + + return CodeCan; + } + + case StatusTimeout: + { + YmodemFileReceive::status = StatusTimeout; + + writeTimer->start(WRITE_TIME_OUT); + + return CodeCan; + } + + default: + { + file->close(); + + YmodemFileReceive::status = StatusError; + + writeTimer->start(WRITE_TIME_OUT); + + return CodeCan; + } + } +} + +uint32_t YmodemFileReceive::read(uint8_t *buff, uint32_t len) +{ + return serialPort->read((char *)buff, len); +} + +uint32_t YmodemFileReceive::write(uint8_t *buff, uint32_t len) +{ + return serialPort->write((char *)buff, len); +} diff --git a/YmodemFileReceive.h b/YmodemFileReceive.h new file mode 100644 index 0000000..f216dcb --- /dev/null +++ b/YmodemFileReceive.h @@ -0,0 +1,57 @@ +#ifndef YMODEMFILERECEIVE_H +#define YMODEMFILERECEIVE_H + +#include "TimeoutSerial.h" +#include "Ymodem.h" +#include +#include +#include +#include + +using namespace std; + +class YmodemFileReceive : public Ymodem +{ + +public: + explicit YmodemFileReceive(); + ~YmodemFileReceive(); + + void setFilePath(const string &path); + + void setSerialPort(TimeoutSerial *port); + TimeoutSerial *getSerialPort(); + + bool startReceive(); + void stopReceive(); + + int getReceiveProgress(); + Status getReceiveStatus(); + + boost::signals2::signal receiveProgress; + boost::signals2::signal receiveStatus; +/* +private slots: + void readTimeOut(); + void writeTimeOut(); +*/ +private: + Code callback(Status status, uint8_t *buff, uint32_t *len); + + uint32_t read(uint8_t *buff, uint32_t len); + uint32_t write(uint8_t *buff, uint32_t len); + + ofstream file; + QTimer *readTimer; + QTimer *writeTimer; + TimeoutSerial *serialPort; + + int progress; + Status status; + string filePath; + string fileName; + uint64_t fileSize; + uint64_t fileCount; +}; + +#endif // YMODEMFILERECEIVE_H diff --git a/build/.cmake/api/v1/reply/codemodel-v2-4167e22d1c847713af64.json b/build/.cmake/api/v1/reply/codemodel-v2-2f061e11e865d7291da7.json similarity index 92% rename from build/.cmake/api/v1/reply/codemodel-v2-4167e22d1c847713af64.json rename to build/.cmake/api/v1/reply/codemodel-v2-2f061e11e865d7291da7.json index 84dec2f..fde9746 100644 --- a/build/.cmake/api/v1/reply/codemodel-v2-4167e22d1c847713af64.json +++ b/build/.cmake/api/v1/reply/codemodel-v2-2f061e11e865d7291da7.json @@ -38,7 +38,7 @@ { "directoryIndex" : 0, "id" : "timeout::@6890427a1f51a3e7e1df", - "jsonFile" : "target-timeout-Debug-85a0f71a1db986bd99c5.json", + "jsonFile" : "target-timeout-Debug-d7af418a1b6c2d259633.json", "name" : "timeout", "projectIndex" : 0 } diff --git a/build/.cmake/api/v1/reply/index-2021-08-24T14-20-32-0203.json b/build/.cmake/api/v1/reply/index-2021-08-24T22-34-28-0932.json similarity index 91% rename from build/.cmake/api/v1/reply/index-2021-08-24T14-20-32-0203.json rename to build/.cmake/api/v1/reply/index-2021-08-24T22-34-28-0932.json index 677b1e2..99e330d 100644 --- a/build/.cmake/api/v1/reply/index-2021-08-24T14-20-32-0203.json +++ b/build/.cmake/api/v1/reply/index-2021-08-24T22-34-28-0932.json @@ -25,7 +25,7 @@ "objects" : [ { - "jsonFile" : "codemodel-v2-4167e22d1c847713af64.json", + "jsonFile" : "codemodel-v2-2f061e11e865d7291da7.json", "kind" : "codemodel", "version" : { @@ -76,7 +76,7 @@ } }, { - "jsonFile" : "codemodel-v2-4167e22d1c847713af64.json", + "jsonFile" : "codemodel-v2-2f061e11e865d7291da7.json", "kind" : "codemodel", "version" : { diff --git a/build/.cmake/api/v1/reply/target-timeout-Debug-85a0f71a1db986bd99c5.json b/build/.cmake/api/v1/reply/target-timeout-Debug-d7af418a1b6c2d259633.json similarity index 95% rename from build/.cmake/api/v1/reply/target-timeout-Debug-85a0f71a1db986bd99c5.json rename to build/.cmake/api/v1/reply/target-timeout-Debug-d7af418a1b6c2d259633.json index 1409cbe..ae304ad 100644 --- a/build/.cmake/api/v1/reply/target-timeout-Debug-85a0f71a1db986bd99c5.json +++ b/build/.cmake/api/v1/reply/target-timeout-Debug-d7af418a1b6c2d259633.json @@ -99,7 +99,8 @@ [ 0, 1, - 2 + 2, + 3 ] } ], @@ -182,7 +183,8 @@ [ 0, 1, - 2 + 2, + 3 ] } ], @@ -203,7 +205,13 @@ { "backtrace" : 1, "compileGroupIndex" : 0, - "path" : "xymodem.cpp", + "path" : "Ymodem.cpp", + "sourceGroupIndex" : 0 + }, + { + "backtrace" : 1, + "compileGroupIndex" : 0, + "path" : "YmodemFileReceive.cpp", "sourceGroupIndex" : 0 } ], diff --git a/build/Makefile b/build/Makefile index bfc17ae..d9dfb45 100644 --- a/build/Makefile +++ b/build/Makefile @@ -150,6 +150,60 @@ TimeoutSerial.cpp.s: $(MAKE) -f CMakeFiles/timeout.dir/build.make CMakeFiles/timeout.dir/TimeoutSerial.cpp.s .PHONY : TimeoutSerial.cpp.s +Ymodem.o: Ymodem.cpp.o + +.PHONY : Ymodem.o + +# target to build an object file +Ymodem.cpp.o: + $(MAKE) -f CMakeFiles/timeout.dir/build.make CMakeFiles/timeout.dir/Ymodem.cpp.o +.PHONY : Ymodem.cpp.o + +Ymodem.i: Ymodem.cpp.i + +.PHONY : Ymodem.i + +# target to preprocess a source file +Ymodem.cpp.i: + $(MAKE) -f CMakeFiles/timeout.dir/build.make CMakeFiles/timeout.dir/Ymodem.cpp.i +.PHONY : Ymodem.cpp.i + +Ymodem.s: Ymodem.cpp.s + +.PHONY : Ymodem.s + +# target to generate assembly for a file +Ymodem.cpp.s: + $(MAKE) -f CMakeFiles/timeout.dir/build.make CMakeFiles/timeout.dir/Ymodem.cpp.s +.PHONY : Ymodem.cpp.s + +YmodemFileReceive.o: YmodemFileReceive.cpp.o + +.PHONY : YmodemFileReceive.o + +# target to build an object file +YmodemFileReceive.cpp.o: + $(MAKE) -f CMakeFiles/timeout.dir/build.make CMakeFiles/timeout.dir/YmodemFileReceive.cpp.o +.PHONY : YmodemFileReceive.cpp.o + +YmodemFileReceive.i: YmodemFileReceive.cpp.i + +.PHONY : YmodemFileReceive.i + +# target to preprocess a source file +YmodemFileReceive.cpp.i: + $(MAKE) -f CMakeFiles/timeout.dir/build.make CMakeFiles/timeout.dir/YmodemFileReceive.cpp.i +.PHONY : YmodemFileReceive.cpp.i + +YmodemFileReceive.s: YmodemFileReceive.cpp.s + +.PHONY : YmodemFileReceive.s + +# target to generate assembly for a file +YmodemFileReceive.cpp.s: + $(MAKE) -f CMakeFiles/timeout.dir/build.make CMakeFiles/timeout.dir/YmodemFileReceive.cpp.s +.PHONY : YmodemFileReceive.cpp.s + main.o: main.cpp.o .PHONY : main.o @@ -177,33 +231,6 @@ main.cpp.s: $(MAKE) -f CMakeFiles/timeout.dir/build.make CMakeFiles/timeout.dir/main.cpp.s .PHONY : main.cpp.s -xymodem.o: xymodem.cpp.o - -.PHONY : xymodem.o - -# target to build an object file -xymodem.cpp.o: - $(MAKE) -f CMakeFiles/timeout.dir/build.make CMakeFiles/timeout.dir/xymodem.cpp.o -.PHONY : xymodem.cpp.o - -xymodem.i: xymodem.cpp.i - -.PHONY : xymodem.i - -# target to preprocess a source file -xymodem.cpp.i: - $(MAKE) -f CMakeFiles/timeout.dir/build.make CMakeFiles/timeout.dir/xymodem.cpp.i -.PHONY : xymodem.cpp.i - -xymodem.s: xymodem.cpp.s - -.PHONY : xymodem.s - -# target to generate assembly for a file -xymodem.cpp.s: - $(MAKE) -f CMakeFiles/timeout.dir/build.make CMakeFiles/timeout.dir/xymodem.cpp.s -.PHONY : xymodem.cpp.s - # Help Target help: @echo "The following are some of the valid targets for this Makefile:" @@ -216,12 +243,15 @@ help: @echo "... TimeoutSerial.o" @echo "... TimeoutSerial.i" @echo "... TimeoutSerial.s" + @echo "... Ymodem.o" + @echo "... Ymodem.i" + @echo "... Ymodem.s" + @echo "... YmodemFileReceive.o" + @echo "... YmodemFileReceive.i" + @echo "... YmodemFileReceive.s" @echo "... main.o" @echo "... main.i" @echo "... main.s" - @echo "... xymodem.o" - @echo "... xymodem.i" - @echo "... xymodem.s" .PHONY : help diff --git a/build/compile_commands.json b/build/compile_commands.json index 7d389de..f88a7a5 100644 --- a/build/compile_commands.json +++ b/build/compile_commands.json @@ -11,7 +11,12 @@ }, { "directory": "/home/jaro/serialport-downloader/build", - "command": "/bin/c++ -DBOOST_ALL_NO_LIB -DBOOST_ATOMIC_DYN_LINK -DBOOST_CHRONO_DYN_LINK -DBOOST_DATE_TIME_DYN_LINK -DBOOST_FILESYSTEM_DYN_LINK -DBOOST_LOG_DYN_LINK -DBOOST_REGEX_DYN_LINK -DBOOST_SYSTEM_DYN_LINK -DBOOST_THREAD_DYN_LINK -g -std=gnu++11 -o CMakeFiles/timeout.dir/xymodem.cpp.o -c /home/jaro/serialport-downloader/xymodem.cpp", - "file": "/home/jaro/serialport-downloader/xymodem.cpp" + "command": "/bin/c++ -DBOOST_ALL_NO_LIB -DBOOST_ATOMIC_DYN_LINK -DBOOST_CHRONO_DYN_LINK -DBOOST_DATE_TIME_DYN_LINK -DBOOST_FILESYSTEM_DYN_LINK -DBOOST_LOG_DYN_LINK -DBOOST_REGEX_DYN_LINK -DBOOST_SYSTEM_DYN_LINK -DBOOST_THREAD_DYN_LINK -g -std=gnu++11 -o CMakeFiles/timeout.dir/Ymodem.cpp.o -c /home/jaro/serialport-downloader/Ymodem.cpp", + "file": "/home/jaro/serialport-downloader/Ymodem.cpp" +}, +{ + "directory": "/home/jaro/serialport-downloader/build", + "command": "/bin/c++ -DBOOST_ALL_NO_LIB -DBOOST_ATOMIC_DYN_LINK -DBOOST_CHRONO_DYN_LINK -DBOOST_DATE_TIME_DYN_LINK -DBOOST_FILESYSTEM_DYN_LINK -DBOOST_LOG_DYN_LINK -DBOOST_REGEX_DYN_LINK -DBOOST_SYSTEM_DYN_LINK -DBOOST_THREAD_DYN_LINK -g -std=gnu++11 -o CMakeFiles/timeout.dir/YmodemFileReceive.cpp.o -c /home/jaro/serialport-downloader/YmodemFileReceive.cpp", + "file": "/home/jaro/serialport-downloader/YmodemFileReceive.cpp" } ] \ No newline at end of file diff --git a/xymodem.cpp b/xymodem.cpp deleted file mode 100644 index d46aa9d..0000000 --- a/xymodem.cpp +++ /dev/null @@ -1,585 +0,0 @@ -/* - * xymodem file transferts - * - * (C) Copyright 2011 Angelo Dureghello - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "xymodem.h" -#include "Thread.h" - -using namespace std; -using namespace boost; - -static const unsigned char ZPAD = 0x2a; -static const unsigned char ZDLE = 0x18; -static const unsigned char ZBIN = 0x41; -static const unsigned char ZHEX = 0x42; -static const unsigned char XON = 0x11; - -static const unsigned char ZMABORT[] = {ZDLE,ZDLE,ZDLE,ZDLE,ZDLE}; - -static const unsigned char ESC_HEXHDR[] = {ZPAD,ZPAD,ZDLE,ZHEX}; -static const unsigned char ZRQINIT[] = "0000000000195E"; -static const unsigned char ZTERM[]= {0x0d,0x0a,XON}; - - -class __tools { -public: - __tools () {} - -public: - unsigned short crc16_ccitt( char *buf, int len ) - { - unsigned short crc = 0; - while( len-- ) { - int i; - crc ^= *(char *)buf++ << 8; - for( i = 0; i < 8; ++i ) { - if( crc & 0x8000 ) - crc = (crc << 1) ^ 0x1021; - else - crc = crc << 1; - } - } - return crc; - } - unsigned char calc_xmodem_checksum (unsigned char *buf, int sz) - { - int i; - int cks = 0; - - for (i = 0; i < sz; ++i) { - cks += (int)buf[i]; - } - return cks%256; - } -}; - - -/* XMODEM */ -static const unsigned char SOH = 0x01; -static const unsigned char STX = 0x02; -static const unsigned char EOT = 0x04; -static const unsigned char ACK = 0x06; -static const unsigned char NAK = 0x15; -static const unsigned char ETB = 0x17; -static const unsigned char CAN = 0x18; -static const unsigned char SYN = 0x43; -static const unsigned char CPMEOF = 0x1a; - -Operator::Operator (TimeoutSerial &c) : com(&c) -{ - obuff.resize (512 , 0); - obuff.resize (2048, 0); -} - -void Operator::SessionStartup (const string &file) -{ - fname = file; - - f.open(file.c_str(), fstream::binary | fstream::in); - - /* adding a cr, C was probably on the screen */ - if (!f.is_open()) - { - BOOST_LOG_TRIVIAL(debug) << "Cannot open file " << file << " please check the path"; - } - BOOST_LOG_TRIVIAL(debug) << "File: " << file; - - /* getting file size */ - f.seekg (0, ios::end); - fsize = f.tellg(); - f.seekg (0, ios::beg); - - stringstream ss; - string size; - - ss << fsize; - ss >> size; - BOOST_LOG_TRIVIAL(debug) << "Size: " << size << " bytes"; -} - -void Operator::StartTransfert () -{ - BOOST_LOG_TRIVIAL(debug) << "Starting file transfer ..."; - - Entry(); -} - -void Operator::SendBlock(char *block, int size) -{ - int hsz, csz; - - /* prepare block header */ - hsz = SetupBlockHdr(); - - /* prepare block binary data */ - memcpy (&obuff[hsz], block, size); - csz = SetupCheckSum (&obuff[hsz], &obuff[hsz+size]); - - q->write (&obuff[0], hsz+size+csz); -} - -/* - * A thread process the entire transfert and allows UI to be free of operating - */ - -enum states { - SESSION_START, - SESSION_BLOCKS, - SESSION_CLOSE, - SESSION_CLOSE_WAIT_ACK, - SESSION_END, -}; - -bool Operator::GetChar() -{ - try { - q->read(&ibuff[0], 1); - return true; - } catch(boost::system::system_error& e) - { - return false; - } -} - -bool Operator::IsChar () -{ return (ibuff[0]!=0); } - -bool Operator::IsAck () -{ - return (ibuff[0] == GetAck()); -} - -bool Operator::IsSync () -{ - return (ibuff[0] == GetSync()); -} - -bool Operator::IsNack () -{ - return (ibuff[0] == GetNack()); -} - -bool Operator::IsCan () -{ - return (ibuff[0] == GetCan()); -} - -void Operator::SendEot () -{ - char c[2]; - - c[0] = GetEot(); - q->write (c, 1); -} - -void Operator::SetupInfoBlock (string &block) -{ - stringstream ss; - - unsigned int i = fname.rfind('/'); - - if (i==string::npos) - i = fname.rfind('\\'); - - if (i!=string::npos) - { - fname = fname.substr(i+1); - } - - i=fname.size(); - - ss << fsize; - pkt = 0; - - /* prepare first block */ - memcpy(&block[0],&fname[0], i); - block[i++]=0; - memcpy(&block[i],ss.str().c_str(),ss.str().size()); - /* - * space after length should be needed only if mod date is sent - * but some receiver (u-boot) need it. - */ - block[i+ss.str().size()] = ' '; -} - -void Operator::UpdateProgress (int size) -{ - stringstream ss; - - if (!size) { - psize = GetBlockSize() * count++; - } else - psize += size; - - ss << psize << "/" << fsize; - - // EvtDel (); - // EvtMsg (ss.str()); -} - -int Operator::Entry() -{ - string block(1024,0); - - struct y_modem_data ymd; - - int state = SESSION_START; - int bsize = GetBlockSize(); - int blnum = fsize / bsize; - int reminder=0; - - count=1; - - /* progress size */ - psize=0; - - stringstream ss; - string ascii_bsize; - - ss << bsize; - ss >> ascii_bsize; - - /* clone */ - q = com; - - pkt = 1; - - if (GetProto()=='Y') - { - /* - * always sending file size allows a faster close of - * the session from the receiver. - * - * = SPEC = - * The pathname (conventionally, the file name) is sent as a null - * terminated ASCII string. - * No spaces are included in the pathname. Normally only the file name - * stem (no directory prefix) is transmitted unless the sender has - * selected YAM's f option to send the full pathname. The source drive - * (A:, B:, etc.) is not sent. - * - */ - SetupInfoBlock(block); - blnum++; - - /* signal to skip update progress for first info block */ - ymd.first_pkt = true; - } - else - /* read first block from file*/ - f.read(&block[0], bsize); - - for (;;) { - /* always, wait for tranfert occour and proper replies */ - boost::this_thread::sleep(posix_time::milliseconds(10)); - - if (GetChar()==false) continue; - - switch (state) { - case SESSION_START: - if (IsSync()) { - if (ymd.first_ack) { - BOOST_LOG_TRIVIAL(debug) << "Entry() : YMODEM FIRST C after ACK"; - /* - * YMODEM, as per spec we expect receiver - * sends this furhter 'C' - */ - state++; - /* - * clear rx data for walkthrough and - * send 1st block - */ - ibuff[0]=0; - } - else { - if (GetProto()=='X') - { - /* - * C here mean receiver wants - * 16bit CRC mode and - * assumes we know it if we send - * a block - */ - SetMode(XMODEMCRC); - /* send and promote */ - state++; - } - /* received SYN */ - BOOST_LOG_TRIVIAL(debug) << "Sync received, transfert start"; - /* - * resend same initial packet - * note: non sense for Y-MODEM use 1024 - */ - SetSize(128); - SendBlock (&block[0], 128); - if (GetProto()=='Y') SetSize(1024); - boost::this_thread::sleep(posix_time::milliseconds(10));; - - continue; - } - } - else - if (IsAck()) { - if (GetProto()=='Y') { - BOOST_LOG_TRIVIAL(debug) << "Entry() : YMODEM FIRST ACK"; - - ymd.first_ack=true; - /* back up to get C after ack */ - continue; - } - else - state++; - } - else - if (IsNack()) { - /* - * note ! programs as rx or lrz need filename as - * additional parameter, otherwise they sends - * C.. C and a CAN just after. - */ - if (GetProto()=='X') { - - BOOST_LOG_TRIVIAL(debug) << "Nack received, transfert start\r\n"; - /* resend same initial packet*/ - SendBlock (&block[0], bsize); - boost::this_thread::sleep(posix_time::milliseconds(10)); - /* promoted */ - state++; - } - else - { - BOOST_LOG_TRIVIAL(debug) << "Entry() : NACK FIRST"; - } - } - // NO BREAK, - // FALL THROUGH IS INTENTIONAL - case SESSION_BLOCKS: - if (IsChar() && !IsAck()) { - if (IsSync()) { - if (GetProto()=='Y') - { - /* - * first synch after first - * block sent, do nothing here - */ - } - } - else - if (IsNack()) { - //EvtMsg("Nack/Sync\r\n"); - /* resend */ - if (GetProto()=='Y' || - (GetProto()=='X' && pkt!=1)) - { - BOOST_LOG_TRIVIAL(debug) << "entry() : NACK, RESEND"; - SendBlock (&block[0], bsize); - boost::this_thread::sleep(posix_time::milliseconds(10)); - } - } - else - if (IsCan()) - { - BOOST_LOG_TRIVIAL(debug) << "Transfert canceled from receiver"; - boost::this_thread::sleep(posix_time::milliseconds(100)); - /* destroy object and the thread */ - return (void*)1; - } - else - { - /* to do, if some other chances */ - } - continue; - } - // ACK received, so progress - if (blnum) - { - if (GetProto()=='Y') - { - if (ymd.first_pkt) ymd.first_pkt=false; - else - UpdateProgress(); - } - else - // XMODEM, always - UpdateProgress(); - - /* if multiple of 256/1024 close */ - if (blnum==1 && psize==fsize) { - blnum--; - goto close_session; - } - } - else - { -close_session: - /* completed */ - UpdateProgress (reminder); - BOOST_LOG_TRIVIAL(debug) << "Closing session ..."; - SendEot(); - if (GetProto()=='X') state=SESSION_END; else state++; - continue; - } - blnum--; - pkt++; - /* end of blocks ? */ - if (blnum>0) { - f.read(&block[0], bsize); - SendBlock (&block[0], bsize); - } - else { - reminder=fsize%bsize; - if (reminder) - { - f.read(&block[0], reminder); - memset (&block[reminder],CPMEOF,bsize-reminder); - SendBlock (&block[0], bsize); - } - } - break; - case SESSION_CLOSE: - /* YMODEM ONLY */ - if (IsAck()) state++; - else - if (IsNack()) - { - /* - * in YMODEM termination is EOT-> NACK<-, - * EOT-> ACK<- - */ - SendEot(); - } - break; - case SESSION_CLOSE_WAIT_ACK: - /* YMODEM ONLY */ - if (IsSync()) - { - /* Synch, terminating.. */ - memset (&block[0], 0, 128); - SetSize(128); - pkt=0; - SendBlock (&block[0], 128); - - state++; - } - break; - case SESSION_END: - if (!IsAck()) continue; - BOOST_LOG_TRIVIAL(debug) << "Transfert complete"; - boost::this_thread::sleep(posix_time::milliseconds(100)); - /* destroy object and the thread */ - //delete q; - //EvtEnd (); - return (void*)1; - - break; - } - } - - return 0; -} - -XModem::XModem (TimeoutSerial &c) : Operator (c), t(*new __tools) -{ - xmodem_mode = 0; - psize = LEN_B_XMODEM; -} - -int XModem::SetupBlockHdr() -{ - obuff[0]=(xmodem_mode&XMODEM1K)?STX:SOH; - obuff[1]=pkt; - obuff[2]=0xff-pkt; - - return 3; -} - -int XModem::SetupCheckSum (char *data, char *dest) -{ - if (xmodem_mode&XMODEMCRC) - { - unsigned short crc = t.crc16_ccitt(data, psize); - - *(unsigned short*)dest = (unsigned short) - ((crc<<8)&0xFF00) | ((crc>>8)&0xff); - - return 2; - } - else - { - unsigned char crc = - t.calc_xmodem_checksum((unsigned char*)data, psize); - - *dest = crc; - - return 1; - } -} - -inline char XModem::GetSync () { return SYN; } -inline char XModem::GetAck () { return ACK; } -inline char XModem::GetNack () { return NAK; } -inline char XModem::GetCan () { return CAN; } -inline char XModem::GetEot () { return EOT; } -inline char XModem::GetProto() { return 'X'; } - -inline void XModem::SetSize (int size) { psize = size; } - -YModem::YModem (TimeoutSerial &c) : Operator (c), t(*new __tools) -{ - psize = LEN_B_YMODEM; -} - -/* YModem allows 128 (std) blocks or 1024 - */ -int YModem::SetupBlockHdr() -{ - obuff[0]=(psize==LEN_B_YMODEM)?STX:SOH; - obuff[1]=pkt; - obuff[2]=0xff-pkt; - - return 3; -} - -int YModem::SetupCheckSum (char *data, char *dest) -{ - unsigned short crc = t.crc16_ccitt(data, psize); - - *(unsigned short*)dest = (unsigned short)((crc<<8)&0xFF00) | ((crc>>8)&0xff); - - return 2; -} - -inline char YModem::GetSync () { return SYN; } -inline char YModem::GetAck () { return ACK; } -inline char YModem::GetNack () { return NAK; } -inline char YModem::GetCan () { return CAN; } -inline char YModem::GetEot () { return EOT; } -inline char YModem::GetProto() { return 'Y'; } - -inline void YModem::SetSize (int size) { psize = size; } diff --git a/xymodem.h b/xymodem.h deleted file mode 100644 index 54939ff..0000000 --- a/xymodem.h +++ /dev/null @@ -1,141 +0,0 @@ -#ifndef modem_HH -#define modem_HH - -#include -#include -#include "Thread.h" -#include "TimeoutSerial.h" - -using std::fstream; -using std::string; - -class __tools; - -struct y_modem_data -{ - y_modem_data() : first_ack(false) {} - - bool first_ack; - bool first_pkt; -}; - -class Operator: public Thread< Operator > -{ -public: - Operator (TimeoutSerial &c); -private: - int Entry(); //Strting point - - void SetupInfoBlock (string &block); - void UpdateProgress (int = 0); - - bool GetChar(); - bool IsChar (); - bool IsAck (); - bool IsSync (); - bool IsNack (); - bool IsCan (); - -protected: - void SendBlock(char *p, int size); - void SendEot (); - - virtual int GetBlockSize () = 0; - virtual int SetupBlockHdr () = 0; - virtual int SetupCheckSum (char *data, char *dest) = 0; - virtual char GetSync () = 0; - virtual char GetAck () = 0; - virtual char GetCan () = 0; - virtual char GetNack () = 0; - virtual char GetEot () = 0; - virtual char GetProto() = 0; - - virtual void SetSize (int) {} - virtual void SetMode (int) {} - virtual int GetMode () { return 0; } - - -public: - void SessionStartup (const string &); - void StartTransfert (); - -protected: - TimeoutSerial *com, *q; - fstream f; - int pkt; - int fsize,psize; - int count; - string fname; - string ibuff; - string obuff; -}; - - -static const int LEN_B_XMODEM = 128; - -// bitmask -enum { - XMODEM1K=0x01, - XMODEMCRC=0x02, -}; - -class XModem : public Operator { -public: - XModem (TimeoutSerial &c); - -private: - int GetBlockSize () { return psize; } - int SetupBlockHdr (); - int SetupCheckSum (char *data, char *dest); - - char GetSync (); - char GetAck (); - char GetNack (); - char GetCan (); - char GetProto(); - char GetEot (); - int GetMode () {return xmodem_mode;} - - void SetSize (int size); - void SetMode (int mode) { - xmodem_mode|=mode; - if (mode&XMODEM1K) psize=1024; - } - -public: - int xmodem_mode; - -private: - __tools &t; - int psize; -}; - -/* we don't use the standard 128 block but 1024 only - */ -static const int LEN_B_YMODEM = 1024; - -class YModem : public Operator { -public: - YModem (TimeoutSerial &c); - -private: - int GetBlockSize () { return psize; } - int SetupBlockHdr (); - int SetupCheckSum (char *data, char *dest); - - char GetSync (); - char GetAck (); - char GetNack (); - char GetCan (); - char GetProto(); - char GetEot (); - - void SetSize (int size); - -private: - __tools &t; - int psize; -}; - - -#endif // modem_HH diff --git a/ymodem.h b/ymodem.h deleted file mode 100644 index ee59de4..0000000 --- a/ymodem.h +++ /dev/null @@ -1,63 +0,0 @@ -/** - ****************************************************************************** - * @file IAP/inc/ymodem.h - * @author MCD Application Team - * @version V3.3.0 - * @date 10/15/2010 - * @brief This file provides all the software function headers of the ymodem.c - * file. - ****************************************************************************** - * @copy - * - * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS - * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE - * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY - * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING - * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE - * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. - * - *

© COPYRIGHT 2010 STMicroelectronics

- */ - -/* Define to prevent recursive inclusion -------------------------------------*/ -#ifndef _YMODEM_H_ -#define _YMODEM_H_ - -/* Includes ------------------------------------------------------------------*/ - -/* Exported types ------------------------------------------------------------*/ -/* Exported constants --------------------------------------------------------*/ -#define PACKET_SEQNO_INDEX (1) -#define PACKET_SEQNO_COMP_INDEX (2) - -#define PACKET_HEADER (3) -#define PACKET_TRAILER (2) -#define PACKET_OVERHEAD (PACKET_HEADER + PACKET_TRAILER) -#define PACKET_SIZE (128) -#define PACKET_1K_SIZE (1024) - -#define FILE_NAME_LENGTH (256) -#define FILE_SIZE_LENGTH (16) - -#define SOH (0x01) /* start of 128-byte data packet */ -#define STX (0x02) /* start of 1024-byte data packet */ -#define EOT (0x04) /* end of transmission */ -#define ACK (0x06) /* acknowledge */ -#define NAK (0x15) /* negative acknowledge */ -#define CA (0x18) /* two of these in succession aborts transfer */ -#define CRC16 (0x43) /* 'C' == 0x43, request 16-bit CRC */ - -#define ABORT1 (0x41) /* 'A' == 0x41, abort by user */ -#define ABORT2 (0x61) /* 'a' == 0x61, abort by user */ - -#define NAK_TIMEOUT (0x100000) -#define MAX_ERRORS (5) - -/* Exported macro ------------------------------------------------------------*/ -/* Exported functions ------------------------------------------------------- */ -int32_t Ymodem_Receive (uint8_t *); -uint8_t Ymodem_Transmit (uint8_t *,const uint8_t* , uint32_t ); - -#endif /* _YMODEM_H_ */ - -/*******************(C)COPYRIGHT 2010 STMicroelectronics *****END OF FILE****/