This commit is contained in:
2021-08-25 00:45:13 +02:00
parent 2b2cbe655d
commit bc701ae833
15 changed files with 2305 additions and 872 deletions

View File

@@ -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)

1
SerialPortYmodem Submodule

Submodule SerialPortYmodem added at dd5ce17f9f

View File

@@ -1,44 +0,0 @@
#ifndef THREAD_HH
#define THREAD_HH
#include <boost/thread.hpp>
#include <iostream>
using namespace std;
template<typename T>
class Thread {
private:
boost::thread* thread;
bool isRunning;
public:
// Ctor
Thread() : thread(NULL), isRunning(false) {
}
virtual ~Thread() {
kill();
}
void start() {
T* derived = dynamic_cast<T*>(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

1791
Ymodem.cpp Normal file

File diff suppressed because it is too large Load Diff

143
Ymodem.h Normal file
View File

@@ -0,0 +1,143 @@
/**
******************************************************************************
* @file Ymodem.h
* @author XinLi
* @version v1.0
* @date 21-January-2018
* @brief Header file for Ymodem.cpp module.
******************************************************************************
* @attention
*
* <h2><center>Copyright &copy; 2018 XinLi</center></h2>
*
* 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 <https://www.gnu.org/licenses/>.
*
******************************************************************************
*/
#ifndef __YMODEM_H
#define __YMODEM_H
/* Header includes -----------------------------------------------------------*/
#include <stdint.h>
/* 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 */

231
YmodemFileReceive.cpp Normal file
View File

@@ -0,0 +1,231 @@
#include "YmodemFileReceive.h"
#include <iostream>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/thread/thread.hpp>
#include <boost/algorithm/string.hpp>
#include <boost/algorithm/string/split.hpp>
#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);
}

57
YmodemFileReceive.h Normal file
View File

@@ -0,0 +1,57 @@
#ifndef YMODEMFILERECEIVE_H
#define YMODEMFILERECEIVE_H
#include "TimeoutSerial.h"
#include "Ymodem.h"
#include <boost/signals2.hpp>
#include <iostream>
#include <fstream>
#include <string>
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<void (int)> receiveProgress;
boost::signals2::signal<void (YmodemFileReceive::Status status)> 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

View File

@@ -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
}

View File

@@ -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" :
{

View File

@@ -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
}
],

View File

@@ -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

View File

@@ -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"
}
]

View File

@@ -1,585 +0,0 @@
/*
* xymodem file transferts
*
* (C) Copyright 2011 Angelo Dureghello <angelo70@gmail.com>
*
* 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 <cstring>
#include <sstream>
#include <stdexcept>
#include <boost/utility.hpp>
#include <boost/asio.hpp>
#include <boost/algorithm/string.hpp>
#include <boost/algorithm/string/split.hpp>
#include <boost/log/trivial.hpp>
#include <boost/thread/future.hpp>
#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; }

141
xymodem.h
View File

@@ -1,141 +0,0 @@
#ifndef modem_HH
#define modem_HH
#include <string>
#include <fstream>
#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

View File

@@ -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.
*
* <h2><center>&copy; COPYRIGHT 2010 STMicroelectronics</center></h2>
*/
/* 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****/