Files
geomative/GeomativeStudio/cpp/Tools/Zmodem.cpp
T
coco df489d5640 a
2026-07-03 16:05:30 +08:00

1940 lines
50 KiB
C++

// Zmodem.cpp: implementation of the Zmodem class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "Zmodem.h"
#include "CtrlProtocolDef.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
extern SYSTEMTIME g_sysCurTime;
extern int g_iUILanguage;
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
//
// Zmodem::Zmodem()
// {
//
// }
//
Zmodem::~Zmodem()
{
//str = NULL;
}
Zmodem::Zmodem( CSComPort *rs232_port )
{
port = rs232_port;
// str = NULL;
// m_BuffCount = 0;
// m_BufReadIndex = 0;
ClearReadBuf();
file_count = 0;
file_name[ 0 ] = '\0';
file_length = -1L;
file = NULL;
receiver_buffer_length = 16384;
wake_up_sender_header_type = ZRINIT;
memset(m_WriteBuff, 0, 8192);
m_WriteBuffLength = 0;
m_ByteTransfer = 0;
m_FileSize = 0;
nIndex = 0;
// nTestID = 123456;
}
// The public Send functionsends a batch of files one at a time
// via the SendSingleFile function. When a normal completion
// occurs, it is flagged with a ZFIN frame.
BOOL Zmodem::Send( char *files[] )
{
//log
zmodemLog = fopen("log\\zmodemSZLog.txt","ab");
if (!zmodemLog)
{
zmodemLog = fopen("zmodemSZLog.txt","ab");
}
dwBegin = GetTickCount();
memset(cReadLog,0,2048);
nLogLength = sprintf(cReadLog,"\r\n");
fwrite(cReadLog,nLogLength,1,zmodemLog);
fflush(zmodemLog);
nLogLength = sprintf(cReadLog,*files);
fwrite(cReadLog,nLogLength,1,zmodemLog);
fflush(zmodemLog);
nLogLength = sprintf(cReadLog,"\r\n");
fwrite(cReadLog,nLogLength,1,zmodemLog);
fflush(zmodemLog);
//log
PackLongIntoHeader( 0L );
SendHexHeader(4, ZRQINIT, transmitted_header);
GetRinitHeader();
byte_count = -1;
while ( *files )
{
int n = SendSingleFile( *files );
if ( n == ZERROR )
{
if (file)
{
//log
nLogLength = sprintf(cReadLog,"SendSingleFile = %d\r\n",n);
fwrite(cReadLog,nLogLength,1,zmodemLog);
fflush(zmodemLog);
//log
fclose(file);
fclose(zmodemLog);
return FALSE;
}
//log
nLogLength = sprintf(cReadLog,"SendSingleFile = %d\r\n",n);
fwrite(cReadLog,nLogLength,1,zmodemLog);
fflush(zmodemLog);
//log
}
files++;
}
SendZFIN();
if (file)
fclose(file);
if (zmodemLog)
fclose(zmodemLog);
return TRUE;
}
// This function is used *everywhere*, and benefits from being
// declared as inline.
inline int Zmodem::ReadChar( long timeout )
{
// int c = ReadBuff( timeout );
// return ( c < 0 ) ? TIMEOUT : c;
if ((0 == m_BuffCount) || (m_nBufReadIndex == m_BuffCount))//除非已经读取完毕,再进行缓存的读取
{
if (ReadBuff(timeout) != TIMEOUT)
{
return buff[m_nBufReadIndex++ ] & 0377;
}
else
return TIMEOUT;
}
return buff[m_nBufReadIndex++ ] & 0377;
}
// This is the worker routine that transmits a single file.
int Zmodem::SendSingleFile( char *name )
{
int c;
unsigned long crc_value;
long lastcrcrq = -1;
int length;
//add by waston
int nnlen;//log
char *FileName;
int nLogCode = 0;
CString strLogTmp = _T("");
//add by waston
file = fopen( name, "rb" );
FileName = strrchr(name,'\\');
FileName++;
if ( file == NULL) {
error( "Failed to open %s", name );
return OK;
}
file_at_eof = 0;
fseek( file, 0, SEEK_END );
file_length = ftell( file );
fseek( file, 0, SEEK_SET );
m_FileSize = file_length; //将文件大小写到接口
length = sprintf( buffer,
"%s%c%u 0 0 0 0 0",
FileName,
0,
file_length );
for ( ; ; ) {
PackLongIntoHeader( 0L );
SendBinaryHeader( 4, ZFILE, transmitted_header );
SendDataFrame( buffer, length, ZCRCW );
//log
strLogTmp.Empty();
strLogTmp.Format(_T("[%d] Duration: %d\t\t\t\t\t\tRUN: send ZFILE DATA FRAME: %s"), __LINE__,
GetTickCount() - dwBegin,buffer);
PrintLogLast(strLogTmp);
//log
again:
c = ReadHeader( received_header );
//log
strLogTmp.Empty();
strLogTmp.Format(_T("[%d] Duration: %d\t\t\t\t\t\tswitch = %d"), __LINE__,
GetTickCount() - dwBegin, c);
PrintLogLast(strLogTmp);
//log
switch ( c ) {
case ZRINIT:
while ( ( c = ReadChar( 5000L ) ) > 0 )
if ( c == ZPAD )
goto again;
/* **** FALL THRU TO **** */
default:
continue;
case ZCAN:
case TIMEOUT:
case ZABORT:
case ZFIN:
return ZERROR;
case ZCRC:
if ( received_file_position != lastcrcrq ) {
Crc32 crc( 0xFFFFFFFFL );
lastcrcrq = received_file_position;
fseek( file, 0L, SEEK_SET );
while ( ( ( c = getc( file ) ) != EOF )
&& --lastcrcrq )
crc.update(c );
crc_value = ~crc.value();
fseek( file, 0L, SEEK_SET );
lastcrcrq = received_file_position;
}
PackLongIntoHeader( crc_value );
SendBinaryHeader( 4, ZCRC, transmitted_header );
goto again;
case ZSKIP:
fclose( file );
return OK;
case ZRPOS:
nLogCode = fseek(file,received_file_position,SEEK_SET);
if (nLogCode)
{
//log
strLogTmp.Empty();
strLogTmp.Format(_T("[%d] Duration: %d\t\t\t\t\t\t case ZRPOS = %d,fseek = %d"), __LINE__,
GetTickCount() - dwBegin, received_file_position,nLogCode);
PrintLogLast(strLogTmp);
//log
return ZERROR;
}
last_sync_position =
(byte_count=transmitted_file_position=
last_reported_position=
received_file_position) - 1;
return SendFileContents();
}
}
}
int Zmodem::SendFileContents( void )
{
int c;
int e;
int n;
int junkcount;
int newcnt;
junkcount = 0;
CString strLogTmp = _T("");
start_read:
receiver_buffer_length = 2048;
newcnt = receiver_buffer_length;
PackLongIntoHeader( transmitted_file_position );
SendBinaryHeader( 4, ZDATA, transmitted_header );
do {
n = fread( buffer, 1, 1024, file );
if ( n < 1024 )
file_at_eof = 1;
if ( file_at_eof )
e = ZCRCE;
else if ( junkcount > 3 )
e = ZCRCW;
else if ( byte_count == last_sync_position )
e = ZCRCW;
else if ( receiver_buffer_length && ( newcnt -= n ) <= 0 )
e = ZCRCW;
else
e = ZCRCG;
SendDataFrame( buffer, n, e );
//log
strLogTmp.Empty();
strLogTmp.Format(_T("[%d] Duration: %d\t\t\t\t\t\tSendData: %d, fread = %d"), __LINE__,
GetTickCount() - dwBegin, e,n);
PrintLogLast(strLogTmp);
//log
m_ByteTransfer = byte_count = transmitted_file_position += n;
if ( e == ZCRCW )
goto waitack;
while ( /*port->RXSpaceUsed()*/ m_nBufReadIndex < m_BuffCount) {
switch ( ReadChar( 100 ) ) {
case CAN:
case ZPAD:
c = SyncWithReceiver( 1 );
if ( c == ZACK )
break;
SendDataFrame( buffer, 0, ZCRCE );
goto gotack;
case XOFF:
case XOFF | 0x80 :
ReadChar( 10000L );
default:
junkcount++;
}
}
} while ( !file_at_eof );
int nnlen;
for ( ; ; ) {
PackLongIntoHeader( transmitted_file_position );
SendBinaryHeader( 4, ZEOF, transmitted_header );
switch ( SyncWithReceiver( 0 ) ) {
case ZACK:
continue;
case ZRPOS:
goto start_read;
case ZRINIT:
return OK;
case ZSKIP:
fclose( file );
return c;
default:
fclose( file );
return ZERROR;
}
}
//Backchannel processing
waitack:
junkcount = 0;
c = SyncWithReceiver( 0 );
gotack:
switch ( c ) {
default:
case ZCAN:
fclose( file );
return ZERROR;
case ZSKIP:
fclose( file );
return c;
case ZACK:
case ZRPOS:
break;
case ZRINIT:
return OK;
}
while ( /*port->RXSpaceUsed()*/ m_nBufReadIndex < m_BuffCount) {
switch ( ReadChar( 100 ) ) {
case CAN:
case ZPAD:
c = SyncWithReceiver( 1 );
goto gotack;
case XOFF :
case XOFF | 0x80 :
ReadChar( 10000L );
}
}
goto start_read;
}
// If all goes well, the public receive function just calls
// WakeUpSender(), then ReceiveFiles(). If both of those
// do what they are supposed to do, a batch of files will
// have been properly transferred.
BOOL Zmodem::Receive( CString Path )
{
//log
zmodemLog = fopen("log\\zmodemRZLog.txt","ab");
if (!zmodemLog)
{
zmodemLog = fopen("zmodemRZLog.txt","ab");
}
dwBegin = GetTickCount();
memset(cReadLog,0,2048);
nLogLength = sprintf(cReadLog,"\r\n");
fwrite(cReadLog,nLogLength,1,zmodemLog);
fflush(zmodemLog);
nLogLength = sprintf(cReadLog,"\r\n");
fwrite(cReadLog,nLogLength,1,zmodemLog);
fflush(zmodemLog);
//log
memset(buffer,0,BUFFSIZE);
static char CancelString[] = {
CAN, CAN, CAN, CAN, CAN, CAN, CAN, CAN, CAN, CAN,
BS, BS, BS, BS, BS, BS, BS, BS, BS, BS };
switch ( WakeUpSender() )
{
case 0 :
case ZCOMPL : return OK;
case ZERROR : break;
default : if ( ReceiveFiles(Path) == OK )
{
if ( file )
{
if (0 != fclose(file))
{
CString strTmp = _T("");
strTmp.Format(_T("{Zmodem} [%d] close file failed!!!,ErrorNo = %d"), __LINE__, GetLastError());
PrintLogLast(strTmp);
}
file = NULL;
}
fclose(zmodemLog);//log;
return TRUE;
}
}
port->ZmodemSendDataDirectly( CancelString, sizeof CancelString);//tmp
if ( file )
{
if (0 != fclose(file))
{
CString strTmp = _T("");
strTmp.Format(_T("{Zmodem} [%d] close file failed!!!,ErrorNo = %d"), __LINE__, GetLastError());
PrintLogLast(strTmp);
}
file = NULL;
}
fclose(zmodemLog);//log;
return FALSE;
}
// This is the general purpose receiver function. It calls the
// ReceiveSingleFile function repeatedly as long as the wakeup
// function keeps receiving ZFILE frames.
int Zmodem::ReceiveFiles( CString Path )
{
int return_status ;
for ( ; ; ) {
switch ( return_status = ReceiveSingleFile(Path) )
{
case ZEOF:
case ZSKIP:
switch ( WakeUpSender() ) {
case ZCOMPL:
return OK;
default:
return ZERROR;
case ZFILE:
break;
}
continue;
default:
return return_status;
case ZERROR:
return ZERROR;
}
}
}
// Some data used various places in the class
static char *Zendnames[] = { "ZCRCE", "ZCRCG", "ZCRCQ", "ZCRCW"};
static char *frametypes[] = {
"No Response to Error Correction Request",
"No Carrier Detect",
"TIMEOUT",
"ZERROR",
"ZRQINIT", "ZRINIT", "ZSINIT", "ZACK", "ZFILE",
"ZSKIP", "ZNAK", "ZABORT", "ZFIN", "ZRPOS",
"ZDATA", "ZEOF", "ZFERR", "ZCRC", "ZCHALLENGE",
"ZCOMPL", "ZCAN", "ZFREECNT", "ZCOMMAND", "ZSTDERR"
};
// This function is used when receiving files. It sends out the
// initial frame and waits for a response from the sender. If
// things go properly it will get the file data subpacket and
// return ZFILE. If the sender has no more files it will send a
// ZFIN, which is handled here.
int Zmodem::WakeUpSender( void )
{
int c;
int n;
for ( n = 0 ; n < 16 ; n++ ) {
PackLongIntoHeader( 3072L );
transmitted_header[ZF0] = CANFC32|CANFDX|CANOVIO|CANBRK;
SendHexHeader( 4,
wake_up_sender_header_type,
transmitted_header );
if ( wake_up_sender_header_type == ZSKIP )
wake_up_sender_header_type = ZRINIT;
for ( int try_again = 1 ; try_again ; ) {
switch ( ReadHeader( received_header ) ) {
case ZRQINIT :
case ZEOF :
case TIMEOUT :
default :
try_again = 0;
break;
case ZFILE :
wake_up_sender_header_type = ZRINIT;
c = ReadDataFrame( buffer, 1024 );
if ( c == GOTCRCW )
return ZFILE;
SendHexHeader( 4, ZNAK, transmitted_header );
break;
case ZSINIT :
if (ReadDataFrame(attention_string, ZATTNLEN)
== GOTCRCW ) {
PackLongIntoHeader( 1L );
SendHexHeader(4,ZACK,transmitted_header);
} else
SendHexHeader(4,ZNAK,transmitted_header);
break;
case ZCOMPL :
break;
case ZFIN :
AckZFIN();
return ZCOMPL;
case ZCAN :
return ZERROR;
}
}
}
return 0;
}
// This is the workhorse routine that reads a single file from the
// sender. It reads in headers until it gets a ZDATA header, then
// it switches over to reading data subpackets until it gets one
// of the end of supbacket codes.
int Zmodem::ReceiveSingleFile( CString Path )
{
int c;
int error_count;
long rxbytes;
if ( OpenInputFile( Path, buffer ) == ZERROR )
return wake_up_sender_header_type = ZSKIP;
error_count = 0;
rxbytes = 0L;
long log_data2;
// char chLog[200] = "";
CString strLogTmp = _T("");
for ( ; ; ) {
PackLongIntoHeader( rxbytes );
SendHexHeader( 4, ZRPOS, transmitted_header );
//log
strLogTmp.Empty();
strLogTmp.Format(_T("[%d] Duration: %d\t\t\t\t\t\tRUN: send ZPROS:rxbytes = %d"), __LINE__,
GetTickCount() - dwBegin, rxbytes);
PrintLogLast(strLogTmp);
//log
nxthdr:
c = ReadHeader( received_header );
//log
strLogTmp.Empty();
strLogTmp.Format(_T("[%d] Duration: %d\t\t\t\t\t\tRUN: read ReadHeader c = %d"), __LINE__,
GetTickCount() - dwBegin, c);
PrintLogLast(strLogTmp);
//log
switch (c) {
default:
error( "ReceiveSingleFile: ReadHeader returned %d",
c );
//log
strLogTmp.Empty();
strLogTmp.Format(_T("[%d] Duration: %d\t\t\t\t\t\tRUN: default:"), __LINE__, GetTickCount() - dwBegin);
PrintLogLast(strLogTmp);
//log
// return ZERROR;3
goto nxthdr;
case ZNAK:
{
strLogTmp.Empty();
strLogTmp.Format(_T("[%d] Duration: %d \t\t\t\t\t\ Receice ZANK!!!"), __LINE__, GetTickCount() - dwBegin);
PrintLogLast(strLogTmp);
continue;
}
case TIMEOUT:
if ( ++error_count >= 20 )
{
error("ReceiveSingleFile: ReadHeader returned %d",
c );
//log
strLogTmp.Empty();
strLogTmp.Format(_T("[%d] Duration: %d \t\t\t\t\t\ Receice TIMEOUT"), __LINE__, GetTickCount() - dwBegin);
PrintLogLast(strLogTmp);
//log
return ZERROR;
}
continue;
case ZFILE:
ReadDataFrame( buffer, 1024 );
//log
strLogTmp.Empty();
strLogTmp.Format(_T("[%d] Duration: %d \t\t\t\t\t\tRUN: ZFILE:"), __LINE__, GetTickCount() - dwBegin);
PrintLogLast(strLogTmp);
//log
continue;
case ZEOF:
log_data2 = UnpackHeaderIntoLong(received_header);
//log
strLogTmp.Empty();
strLogTmp.Format(_T("[%d] Duration: %d \t\t\t\t\t\tRUN: ZEOF:log_data2 = %d, rxbytes = %d"), __LINE__,
GetTickCount() - dwBegin, log_data2, rxbytes);
PrintLogLast(strLogTmp);
//log
if (log_data2 != rxbytes)
goto nxthdr;
// continue;
// if ( fclose( file ) != 0 )
// {
// wake_up_sender_header_type = ZFERR;
// error( "ReceiveSingleFile: fclose() "
// "returned error" );
// return ZERROR;
// }
return c;
case ZERROR:
//log
strLogTmp.Empty();
strLogTmp.Format(_T("[%d] Duration: %d \t\t\t\t\t\tRUN: ZERROR:"), __LINE__, GetTickCount() - dwBegin);
PrintLogLast(strLogTmp);
//log
if ( ++error_count >= 20 ) {
error( "ReceiveSingleFile: ReadHeader "
"returned %d", c );
return ZERROR;
}
// SendAttentionString();
// continue;1
goto nxthdr;
case ZSKIP:
//log
strLogTmp.Empty();
strLogTmp.Format(_T("[%d] Duration: %d \t\t\t\t\t\tRUN: ZSKIP:"), __LINE__, GetTickCount() - dwBegin);
PrintLogLast(strLogTmp);
//log
status("ReceiveSingleFile: Sender SKIPPED file");
return c;
case ZDATA:
long log_data = UnpackHeaderIntoLong( received_header );
//log
strLogTmp.Empty();
strLogTmp.Format(_T("[%d] Duration: %d \t\t\t\t\t\tRUN: recv ZDATA:log_data = %d, rxbytes = %d"), __LINE__,
GetTickCount() - dwBegin, log_data,rxbytes);
PrintLogLast(strLogTmp);
//log
if ( log_data != rxbytes )
{
if ( ++error_count >= 20 )
return ZERROR;
// SendAttentionString();
continue;
}
// if ( UnpackHeaderIntoLong( received_header ) != rxbytes )
// {
// if ( ++error_count >= 20 )
// return ZERROR;
//
// SendAttentionString();
// continue;
// }
moredata:
switch ( c = ReadDataFrame( buffer, 1024 ) ) {
case ZCAN:
error( "ReceiveSingleFile: ReadData returned %d",
c );
return ZERROR;
case ZERROR:
if ( ++error_count >= 20 ) {
error( "ReceiveSingleFile: ReadData "
"returned %d", c );
return ZERROR;
}
// SendAttentionString();
continue;
case TIMEOUT:
if ( ++error_count >= 20 ) {
error( "ReceiveSingleFile: ReadData "
"returned %d", c );
return ZERROR;
}
continue;
case GOTCRCW:
error_count = 0;
fwrite( buffer, 1, Rxcount, file );
rxbytes += Rxcount;
m_ByteTransfer = rxbytes;
PackLongIntoHeader( rxbytes );
SendHexHeader( 4, ZACK, transmitted_header );
//log
strLogTmp.Empty();
strLogTmp.Format(_T("[%d] Duration: %d \t\t\t\t\t\tRUN: send ZACK:rxbytes = %d"), __LINE__,
GetTickCount() - dwBegin, rxbytes);
PrintLogLast(strLogTmp);
//log
SendChar( XON );
SendCharToComm();
goto nxthdr;
case GOTCRCQ:
error_count = 0;
fwrite( buffer, 1, Rxcount, file );
rxbytes += Rxcount;
m_ByteTransfer = rxbytes;
PackLongIntoHeader( rxbytes );
//log
strLogTmp.Empty();
strLogTmp.Format(_T("[%d] Duration: %d \t\t\t\t\t\tRUN: send ZACK:rxbytes = %d"), __LINE__,
GetTickCount() - dwBegin, rxbytes);
PrintLogLast(strLogTmp);
//log
SendHexHeader( 4, ZACK, transmitted_header );
goto moredata;
case GOTCRCG:
error_count = 0;
fwrite( buffer, 1, Rxcount, file );
rxbytes += Rxcount;
m_ByteTransfer = rxbytes;
goto moredata;
case GOTCRCE:
error_count = 0;
fwrite( buffer, 1, Rxcount, file );
rxbytes += Rxcount;
m_ByteTransfer = rxbytes;
goto nxthdr;
}
// return ZERROR;
}
}
#ifdef _MSC_VER
return 0; // MSC 7.0 generates an error w/o this line,
// although it can never be reached
#endif
}
// This routine just has to decide whether to send the binary
// header using CRC-16 or CRC-32. After that it just spits out
// the data.
void Zmodem::SendBinaryHeader( int length,
int type,
char *header )
{
CString strLogTmp = _T("");
//log
strLogTmp.Empty();
strLogTmp.Format(_T("[%d] Duration: %d\t\t\t\t\t\tSend: %d"), __LINE__,
GetTickCount() - dwBegin, type);
PrintLogLast(strLogTmp);
//log
int i;
Crc32 crc32( 0xFFFFFFFFL );
unsigned long crc32val;
Crc16 crc16( 0 );
status( "SendBinaryHeader: %d %s %lx",
length,
frametypes[ type + 4 ],
UnpackHeaderIntoLong( header ) );
SendChar( ZPAD );
SendChar( ZDLE );
if ( receiver_wants_crc32 ) {
SendChar( ZBIN32 );
SendEncodedChar( type );
crc32.update( type );
for ( i = 0; i < length; i++ ) {
crc32.update( 0xff & header[ i ] );
SendEncodedChar( header[ i ] );
}
crc32val = ~crc32.value();
for ( i = 0 ; i < 4 ; i++ ) {
SendEncodedChar( (int) crc32val );
crc32val >>= 8;
}
} else {
SendChar( ZBIN );
SendEncodedChar( type );
crc16.update( type );
for ( i = 0 ; i < length ; i++ ) {
SendEncodedChar( header[ i ] );
crc16.update( header[ i ] & 0xff );
}
crc16.update( 0 );
crc16.update( 0 );
SendEncodedChar( crc16.value() >> 8 );
SendEncodedChar( crc16.value() );
}
SendCharToComm();
}
// Sending the hex header involves no decisions whatsoever.
void Zmodem::SendHexHeader( int len, int type, char *header )
{
CString strLogTmp = _T("");
if (type == ZRPOS)
{
//log
strLogTmp.Empty();
strLogTmp.Format(_T("[%d] Duration: %d\t\t\t\t\t\tSend:%d\tZrposIndex = %d"), __LINE__,
GetTickCount() - dwBegin, type,nIndex);
PrintLogLast(strLogTmp);
//log
nIndex++;
}
else
{
//log
strLogTmp.Empty();
strLogTmp.Format(_T("[%d] Duration: %d\t\t\t\t\t\tSend: %d"), __LINE__,
GetTickCount() - dwBegin, type);
PrintLogLast(strLogTmp);
//log
}
int n;
Crc16 crc( 0 );
status( "SendHexHeader: %d %s %lx", len,
frametypes[type+4], UnpackHeaderIntoLong( header ) );
SendChar( ZPAD );
SendChar( ZPAD );
SendChar( ZDLE );
SendChar( ZHEX );
SendHexEncodedChar( type );
crc.update( type );
for ( n = 0 ; n < len ; n++ ) {
SendHexEncodedChar( header[ n ] );
crc.update( 0xff & header[ n ] );
}
crc.update( 0 );
crc.update( 0 );
SendHexEncodedChar( crc.value() >> 8 );
SendHexEncodedChar( crc.value() );
SendChar( CR );
SendChar( LF | 0x80 );
if ( type != ZFIN && type != ZACK )
SendChar( XON );
SendCharToComm();
}
// Reading in headers and data subpackets is a relatively
// difficult job. The next four routines combine to read in
// headers. The first routine dispatches one of the next three,
// depending on what the header type is.
int Zmodem::ReadHeader( char *header )
{
int c;
int n;
int cancount;
Settings settings;
ReadSettings( settings );
n = 1400;
n += ( settings.BaudRate > 19200L ) ?
19200 : (int) settings.BaudRate;
startover:
cancount = 0;
again:
switch ( c = ReadChar( 10000L ) ) {
case TIMEOUT:
goto finished;
case CAN:
gotcan:
if ( ++cancount >= 5 ) {
c = ZCAN;
goto finished;
}
switch ( c = ReadChar( 100 ) ) {
case TIMEOUT:
goto again;
case ZCRCW:
switch ( ReadChar( 100 ) )
{
case TIMEOUT:
c = ZERROR;
goto finished;
default:
goto agn2;
}
default:
break;
case CAN:
if ( ++cancount >= 5 ) {
c = ZCAN;
goto finished;
}
goto again;
}
default:
agn2:
if ( --n == 0 ) {
c = GARBAGE_COUNT;
goto finished;
}
goto startover;
case ZPAD | 0x80: /* This is what we want. */
case ZPAD:
break;
}
cancount = 0;
splat:
switch ( c = ReadUnencodedByte() ) {
case ZPAD:
goto splat;
case TIMEOUT:
goto finished;
default:
goto agn2;
case ZDLE: /* This is what we want. */
break;
}
c = ReadUnencodedByte();
switch ( c ) {
case ZBIN32:
current_frame_uses_crc32 = 1;
c = ReadBinaryHeaderCRC32( header );
break;
case TIMEOUT:
goto finished;
case ZBIN:
current_frame_uses_crc32 = 0;
c = ReadBinaryHeaderCRC16( header );
break;
case ZHEX:
current_frame_uses_crc32 = 0;
c = ReadHexHeaderCRC16( header );
break;
case CAN:
goto gotcan;
default:
goto agn2;
}
received_file_position = header[ ZP3 ] & 0xff;
received_file_position <<= 8;
received_file_position += header[ ZP2 ] & 0xff;
received_file_position <<= 8;
received_file_position += header[ ZP1 ] & 0xff;
received_file_position <<= 8;
received_file_position += header[ ZP0 ] & 0xff;
finished:
switch ( c ) {
case GOTCAN:
c = ZCAN;
/* **** FALL THRU TO **** */
case ZNAK:
case ZCAN:
case ZERROR:
case TIMEOUT:
case GARBAGE_COUNT:
error( "Got %s", frametypes[ c + 4 ] );
/* **** FALL THRU TO **** */
default:
if ( c >= -4 && c <= 22 )
error( "ReadHeader: %s %lx",
frametypes[ c + 4 ],
received_file_position );
else
error( "ReadHeader: %d %lx",
c,
received_file_position );
}
return c;
}
// At this point most of the hard work has been done. The next
//three routines just read in the type of header and the data
// associated with it, then check to see if the CRC is correct.
int Zmodem::ReadBinaryHeaderCRC16( char *header )
{
int c;
int i;
Crc16 crc( 0 );
int header_type;
CString strLogTmp=_T("");
if ( ( c = ReadEncodedByte() ) & ~0xff )
return c;
header_type = c;
//log
strLogTmp.Empty();
strLogTmp.Format(_T("[%d] Duration: %d\t\t\t\t\t\tRead: %d\t\t\t\tin ReadBinaryHeaderCRC16"), __LINE__,
GetTickCount() - dwBegin, header_type);
PrintLogLast(strLogTmp);
//log
crc.update( c );
for ( i = 0 ; i < 4 ; i++ ) {
if ( ( c = ReadEncodedByte() ) & ~0xff )
return c;
crc.update( c );
header[ i ] = (char) c;
}
if ( ( c = ReadEncodedByte() ) & ~0xff )
return c;
crc.update( c );
if ( ( c = ReadEncodedByte() ) & ~0xff )
return c;
crc.update( c );
if ( crc.value() & 0xFFFF ) {
error( "Bad CRC" );
return ZERROR;
}
return header_type;
}
int Zmodem::ReadBinaryHeaderCRC32( char *header )
{
int c;
int i;
Crc32 crc( 0xFFFFFFFFL );
int header_type;
CString strLogTmp=_T("");
if ( ( c = ReadEncodedByte() ) & ~0xff )
return c;
header_type = c;
//log
strLogTmp.Empty();
strLogTmp.Format(_T("[%d] Duration: %d\t\t\t\t\t\tRead: %d\t\t\t\tin ReadBinaryHeaderCRC32"), __LINE__,
GetTickCount() - dwBegin, header_type);
PrintLogLast(strLogTmp);
//log
crc.update( c );
for ( i = 0 ; i < 4 ; i++ ) {
if ( ( c = ReadEncodedByte() ) & ~0xff )
return c;
crc.update( c );
header[ i ] = (char) c;
}
for ( i = 0; i < 4 ; i++ ) {
if ( ( c = ReadEncodedByte() ) & ~0xff )
return c;
crc.update( c );
}
if ( crc.value() != 0xDEBB20E3L ) {
error( "Bad CRC" );
return ZERROR;
}
return header_type;
}
int Zmodem::ReadHexHeaderCRC16( char *header )
{
int c;
Crc16 crc( 0 );
int i;
int header_type;
CString strLogTmp = _T("");
if ( ( c = ReadHexByte() ) < 0 )
return c;
header_type = c;
//log
strLogTmp.Empty();
strLogTmp.Format(_T("[%d] Duration: %d\t\t\t\t\t\tRead: %d\t\t\t\tin ReadHexHeaderCRC16"), __LINE__,
GetTickCount() - dwBegin, header_type);
PrintLogLast(strLogTmp);
//log
crc.update( c );
for ( i = 0 ; i < 4 ; i++ ) {
if ( ( c = ReadHexByte() ) < 0 )
return c;
crc.update( c );
header[ i ] = (char) c;
}
if ( ( c = ReadHexByte() ) < 0 )
return c;
crc.update( c );
if ( ( c = ReadHexByte() ) < 0 )
return c;
crc.update( c );
if ( crc.value() & 0xFFFF ) {
error( "Bad CRC" );
return ZERROR;
}
switch ( c = ReadChar( 100 ) ) {
case CR :
case CR | 0x80 :
ReadChar( 100 );
}
return header_type;
}
// The next three routines are used to read in binary data
// subpackets. This code is somewhat simpler than the code
// used to read in a header, mostly because there are fewer
// things to go wrong.
int Zmodem::ReadDataFrame( char *buffer, int length )
{
int typee;
CString strLogTmp = _T("");
if ( current_frame_uses_crc32 )
{
typee = ReadDataFrameCRC32( buffer, length );
//log
strLogTmp.Empty();
strLogTmp.Format(_T("[%d] Duration: %d\t\t\t\t\t\tRead: %d\t\t\t\tin ReadDataFrame CRC32"), __LINE__,
GetTickCount() - dwBegin, typee);
PrintLogLast(strLogTmp);
//log
return typee;
}
else
{
typee = ReadDataFrameCRC16( buffer, length );
//log
strLogTmp.Empty();
strLogTmp.Format(_T("[%d] Duration: %d\t\t\t\t\t\tRead: %d\t\t\t\tin ReadDataFrame CRC16"), __LINE__,
GetTickCount() - dwBegin, typee);
PrintLogLast(strLogTmp);
//log
return typee;
}
}
int Zmodem::ReadDataFrameCRC32( char *buffer, int length )
{
int c;
Crc32 crc( 0xFFFFFFFFL );
char *end;
int d;
CString strLogTmp = _T("");
Rxcount = 0;
end = buffer + length;
while ( buffer <= end ) {
if ( ( c = ReadEncodedByte() ) & ~0xff ) {
crcfoo:
switch ( c ) {
case GOTCRCE:
case GOTCRCG:
case GOTCRCQ:
case GOTCRCW:
d = c;
c &= 0xff;
crc.update( c );
if ( ( c = ReadEncodedByte() ) & ~0xff )
goto crcfoo;
crc.update( c );
if ( ( c = ReadEncodedByte() ) & ~0xff )
goto crcfoo;
crc.update( c );
if ( ( c = ReadEncodedByte() ) & ~0xff )
goto crcfoo;
crc.update( c );
if ( ( c = ReadEncodedByte() ) & ~0xff )
goto crcfoo;
crc.update( c );
if ( crc.value() != 0xDEBB20E3L ) {
error( "Bad CRC" );
//log
strLogTmp.Empty();
strLogTmp.Format(_T("[%d] Duration: %d\t\t\t\t\t\tRead:\t\tCRC32:Bad CRC"), __LINE__,
GetTickCount() - dwBegin);
PrintLogLast(strLogTmp);
//log
return ZERROR;
}
Rxcount = (int) ( length - (end - buffer) );
error( "ReadDataFrameCRC32: %d %s",
Rxcount,
Zendnames[ d - GOTCRCE & 3 ] );
return d;
case GOTCAN:
error( "Sender Canceled" );
return ZCAN;
case TIMEOUT:
error( "TIMEOUT" );
return c;
default:
error( "Garbled data subpacket" );
//log
strLogTmp.Empty();
strLogTmp.Format(_T("[%d] Duration: %d\t\t\t\t\t\tRead:\t\tCRC32:Garbled data subpacket"), __LINE__,
GetTickCount() - dwBegin);
PrintLogLast(strLogTmp);
//log
return c;
}
}
*buffer++ = (char) c;
crc.update( c );
}
error( "Data subpacket too long" );
//log
strLogTmp.Empty();
strLogTmp.Format(_T("[%d] Duration: %d\t\t\t\t\t\tRead:\t\tCRC32:subpacket too long"), __LINE__,
GetTickCount() - dwBegin);
PrintLogLast(strLogTmp);
//log
return ZERROR;
}
int Zmodem::ReadDataFrameCRC16( char *buffer, int length )
{
int c;
Crc16 crc( 0 );
char *end;
int d;
CString strLogTmp = _T("");
Rxcount = 0;
end = buffer + length;
while ( buffer <= end ) {
if ( ( c = ReadEncodedByte() ) & ~0xff ) {
crcfoo:
switch ( c ) {
case GOTCRCE:
case GOTCRCG:
case GOTCRCQ:
case GOTCRCW:
crc.update( (d = c) & 0xff );
if ( ( c = ReadEncodedByte()) & ~0xff )
goto crcfoo;
crc.update( c );
if ( ( c = ReadEncodedByte() ) & ~0xff )
goto crcfoo;
crc.update( c );
if ( crc.value() & 0xFFFF ) {
error( "Bad CRC");
//log
strLogTmp.Empty();
strLogTmp.Format(_T("[%d] Duration: %d\t\t\t\t\t\tRead:\t\tCRC16:Bad CRC"), __LINE__,
GetTickCount() - dwBegin);
PrintLogLast(strLogTmp);
//log
return ZERROR;
}
Rxcount = (int) ( length - ( end - buffer ) );
error( "ReadDataFrame: %d %s",
Rxcount,
Zendnames[ d - GOTCRCE & 3 ] );
return d;
case GOTCAN:
error( "Sender Canceled" );
return ZCAN;
case TIMEOUT:
error( "TIMEOUT" );
return c;
default:
error( "Garbled data subpacket" );
//log
strLogTmp.Empty();
strLogTmp.Format(_T("[%d] Duration: %d\t\t\t\t\t\tRead:\t\tCRC16:Garbled data subpacket"), __LINE__,
GetTickCount() - dwBegin);
PrintLogLast(strLogTmp);
//log
return c;
}
}
*buffer++ = (char) c;
crc.update( c );
}
error( "Data subpacket too long" );
//log
strLogTmp.Empty();
strLogTmp.Format(_T("[%d] Duration: %d\t\t\t\t\t\tRead:\t\tCRC16:subpacket too long"), __LINE__,
GetTickCount() - dwBegin);
PrintLogLast(strLogTmp);
//log
return ZERROR;
}
// The attention string processor has to process a couple of
// special characters used to sleep and send breaks.
void Zmodem::SendAttentionString()
{
int i = 0;
int c;
long timer;
while ( TXSpaceUsed() > 0 )
//port->IdleFunction();
while ( ( c = attention_string[ i++ ] ) != 0 ) {
switch ( c ) {
case 0xde :
timer = ReadTime() + 1000L;
while ( ReadTime() < timer )
// port->IdleFunction();
break;
case 0xdd :
//port->Break();
break;
default:
SendChar( c );
}
}
}
// This function is called by the receiver before exiting.
void Zmodem::AckZFIN( void )
{
int n;
status( "AckZFIN" );
PackLongIntoHeader( 0L );
for ( n = 0 ; n < 7 ; n++ ) {
/*port->FlushRXBuffer();*/
SendHexHeader( 4, ZFIN, transmitted_header );
switch ( ReadChar( 10000L ) ) {
case 'O':
ReadChar( 120 ); /* Discard 2nd 'O' */
status( "AckZFIN complete" );
return;
case TIMEOUT:
default:
break;
}
}
}
// This utility routine has to scan the incoming data subpacket
// for the file name and length.
int Zmodem::OpenInputFile( CString Path, char *data )
{
CString szFileName(data);
Path+=szFileName;
m_FileSize = GetFileSize(data + szFileName.GetLength() + 1);//这个地方把文件名之后的信息传进去
//log
CString strLogTmp = _T("");
// strcpy( file_name, data );
strLogTmp.Empty();
strLogTmp.Format(_T("[%d] Duration: %d\t\t\t\t\t\tRead: %s"), __LINE__,
GetTickCount() - dwBegin,data);
PrintLogLast(strLogTmp);
//log
strcpy( file_name, data );
if (sscanf(data+strlen(data)+1, "%ld", &file_length ) < 1 )
file_length = -1L;
file = fopen( Path.GetBuffer(Path.GetLength()), "wb" );
if (NULL == file)
{
DWORD dwErrNo = GetLastError();
CString strTmp = _T("");
if (LANG_ZHCN == g_iUILanguage)
{
strTmp.Format(_T("[%d] 打开文件失败!, 错误码 = %d"), __LINE__, dwErrNo);
AfxMessageBox(strTmp.GetBuffer(0));
}
else
{
strTmp.Format(_T("[%d] Open file failed!, error = %d"), __LINE__, dwErrNo);
MessageBoxEx(NULL, strTmp, STRING_MESSAGEBOXEX_TITLE, MB_OK, MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US));
}
PrintLogLast(strTmp);
return ZERROR;
}
return OK;
}
// File position values are longs packed into a four byt header.
// The following two routines are resposible for packing and
// unpacking the data.
void Zmodem::PackLongIntoHeader( long header_data )
{
transmitted_header[ ZP0 ] = (char) header_data;
transmitted_header[ ZP1 ] = (char) ( header_data >> 8 );
transmitted_header[ ZP2 ] = (char) ( header_data >> 16 );
transmitted_header[ ZP3 ] = (char) ( header_data >> 24 );
}
long Zmodem::UnpackHeaderIntoLong( char *header )
{
long l;
l = header[ ZP3 ] & 0xff;
l = ( l << 8 ) | ( header[ ZP2 ] & 0xff );
l = ( l << 8 ) | ( header[ ZP1 ] & 0xff );
l = ( l << 8 ) | ( header[ ZP0 ] & 0xff );
return l;
}
// Hex headers need to send data in hex format.
void Zmodem::SendHexEncodedChar( int c )
{
static char *digits = "0123456789abcdef";
SendChar( digits[ ( c & 0xF0 ) >> 4 ] );
SendChar( digits[ c & 0xF ] );
}
// This routine handles all the escape sequences necessary to send
// control characters.
void Zmodem::SendEncodedChar( int c ,bool b)
{
if ( c & 0x60 )
SendChar( last_char_sent = c ,b);
else {
switch ( c &= 0xff ) {
case CR :
case CR | 0x80 :
if ( ( last_char_sent & 0x7f ) != '@' ) {
SendChar( last_char_sent = c ,b);
break;
} // else fall through
case ZDLE :
case DLE :
case XON :
case XOFF :
case DLE | 0x80 :
case XON | 0x80 :
case XOFF | 0x80 :
SendChar( ZDLE ,b);
c ^= 0x40;
SendChar( last_char_sent = c ,b);
break;
default:
SendChar( last_char_sent = c ,b);
}
}
}
// Read a byte, taking into account escape sequences, and checking
// for the 5*CAN abort sequence.
int Zmodem::ReadEncodedByte( void )
{
int c;
for ( ; ; ) {
c = ReadChar( 10000L );
if ( c == ZDLE )
break;
switch ( c ) {
case XON :
case XON | 0x80 :
case XOFF :
case XOFF | 0x80 :
break;
default:
return c;
}
}
for ( ; ; ) {
if ( ( c = ReadChar( 10000L ) ) < 0 )
return c;
if ( c == CAN && ( c = ReadChar( 10000L ) ) < 0 )
return c;
if ( c == CAN && ( c = ReadChar( 10000L ) ) < 0 )
return c;
if ( c == CAN && ( c = ReadChar( 10000L ) ) < 0 )
return c;
switch ( c ) {
case CAN:
return GOTCAN;
case ZCRCE:
case ZCRCG:
case ZCRCQ:
case ZCRCW:
return c | GOTFLAG;
case ZRUB0:
return 0x7f;
case ZRUB1:
return 0xff;
case XOFF :
case XOFF | 0x80 :
case XON :
case XON | 0x80 :
break;
default:
if ( ( c & 0x60 ) == 0x40 )
return ( c ^ 0x40 );
else
return ZERROR;
}
}
}
// This routine reads a raw data byte, throws out the parity bit and
// ignores handshaking characters.
int Zmodem::ReadUnencodedByte( void )
{
int c;
for ( ; ; ) {
if ( ( c = ReadChar( 10000L ) ) < 0 )
return c;
switch ( c &= 0x7f ) {
case XON:
case XOFF:
continue;
default:
return c;
}
}
}
// When reading Hex headers, we need to convert hex values to a
// usable format.
int Zmodem::ReadHexByte( void )
{
int c;
int n;
if ( ( c = ReadUnencodedByte() ) < 0 )
return c;
n = c - '0';
if ( n > 9 )
n -= ( 'a' - ':' );
if ( n & ~0xF )
return ZERROR;
if ( ( c = ReadUnencodedByte( )) < 0 )
return c;
c -= '0';
if ( c > 9 )
c -= ( 'a' - ':' );
if ( c & ~0xF )
return ZERROR;
c += ( n << 4 );
return c;
}
// The sender needs to get the RINIT frame before it can start
// sending the file. This routine takes care of that.
int Zmodem::GetRinitHeader( void )
{
int i;
for ( i = 0 ; i < 10 ; i++ ) {
switch ( ReadHeader( received_header ) ) {
case ZCHALLENGE: // Echo receiver's challenge number
PackLongIntoHeader( received_file_position );
SendHexHeader( 4, ZACK, transmitted_header );
continue;
case ZCOMMAND: // They didn't see our ZRQINIT
PackLongIntoHeader( 0L );
SendHexHeader( 4, ZRQINIT, transmitted_header );
continue;
case ZRINIT:
receiver_wants_crc32 = received_header[ ZF0 ] & CANFC32;
receiver_buffer_length =
( received_header[ ZP0 ] & 0xff ) +
( ( received_header[ ZP1 ] & 0xff ) << 8 );
return OK;
case ZCAN:
case TIMEOUT:
return ZERROR;
case ZRQINIT:
if ( received_header[ ZF0 ] == ZCOMMAND )
continue;
default:
SendHexHeader( 4, ZNAK, transmitted_header );
continue;
}
}
return ZERROR;
}
// This routine sends a data subpacket, which is used here to send
// file names and file data.
void Zmodem::SendDataFrame( char *buffer, int length, int frameend )
{
Crc32 crc32( 0xFFFFFFFFL );
unsigned long crc32val;
Crc16 crc16( 0 );
int i;
status( "SendDataFrame: %d %s",
length, Zendnames[ frameend - ZCRCE & 3 ] );
int nnlen = 0;
if ( receiver_wants_crc32 ) {
for ( i = 0 ; i < length ; i++ )
{
SendEncodedChar( buffer[ i ] ,TRUE);
crc32.update( buffer[ i ] & 0xff );
}
SendChar( ZDLE ,TRUE);
SendChar( frameend ,TRUE);
crc32.update( frameend );
crc32val = ~crc32.value();
for ( i = 0 ; i < 4 ; i++ ) {
SendEncodedChar( (int) crc32val ,TRUE);
crc32val >>= 8;
}
}
else
{
for ( i = 0 ; i < length ; i++ )
{
SendEncodedChar( buffer[ i ] ,TRUE);
crc16.update( buffer[ i ] & 0xff );
}
SendChar( ZDLE ,TRUE);
SendChar( frameend ,TRUE);
crc16.update( frameend );
crc16.update( 0 );
crc16.update( 0 );
SendEncodedChar( crc16.value() >> 8 ,TRUE);
SendEncodedChar( crc16.value() ,TRUE);
}
if ( frameend == ZCRCW )
SendChar( XON ,TRUE);
SendCharToComm();
}
// The sender sends a ZFIN frame just before exiting.
void Zmodem::SendZFIN( void )
{
for ( ; ; ) {
PackLongIntoHeader( 0L );
SendHexHeader( 4, ZFIN, transmitted_header );
switch ( ReadHeader( received_header ) ) {
case ZFIN:
SendChar( 'O');
SendChar( 'O');
SendCharToComm();
case ZCAN:
case TIMEOUT:
return;
}
}
}
int Zmodem::SyncWithReceiver( int flag )
{
int c;
for ( ; ; ) {
c = ReadHeader( received_header );
switch ( c ) {
case ZCAN:
case ZABORT:
case ZFIN:
case TIMEOUT:
return ZERROR;
case ZRPOS:
if ( fseek( file, received_file_position, SEEK_SET ) )
return ZERROR;
file_at_eof = 0;
byte_count = last_reported_position
= transmitted_file_position = received_file_position;
last_sync_position = received_file_position;
return c;
case ZACK:
last_reported_position = received_file_position;
if ( flag || transmitted_file_position ==
received_file_position )
return ZACK;
continue;
case ZRINIT:
case ZSKIP:
fclose( file );
return c;
case ZERROR:
default:
SendBinaryHeader( 4, ZNAK, transmitted_header );
continue;
}
}
}
long Zmodem::ReadTime( void )
{
return 0;
}
//----------------------------------------------------------------------------------
int Zmodem::ReadBuff(long timeout)
{
/*暂时注释用新写法来写
int nCountError;
nCountError = 0;
if (m_BuffCount > 0)
{
m_BuffCount -= 1;
if(m_BuffCount == 0)
{
return (*str & 0377);
}
else
{
return (*str++ & 0377);
}
}
m_BuffCount = 0;
memset(buff,0,BUFFSIZE);
do
{
port->ZmodemReceiveDataDirectly(buff,&m_BuffCount);
if (m_BuffCount != 0)
{
nCountError = 0;
str = buff;
break;
}
else
{
nCountError++;
Sleep(50);
}
}while(nCountError < 40);
if( nCountError == 40 )
{
return TIMEOUT;
}
m_BuffCount -=1;
if(m_BuffCount == 0)
{
return (*str & 0377);
}
else
{
return (*str++ & 0377);
}
*/
int nCountError = 0;
CString strTmp = _T("");
ClearReadBuf();
do
{
port->ZmodemReceiveDataDirectly(buff,&m_BuffCount);
if (0 == m_BuffCount)
{
nCountError++;
Sleep(50);
}
else if (m_BuffCount > BUFFSIZE)
{
strTmp.Format(_T("[%d] read buffersize is too big than 8K, read_buffer_size = %d"), __LINE__, m_BuffCount);
PrintLogLast(strTmp);
return 1;
}
else
{
return 1;
}
}while(nCountError < 240);
strTmp.Format(_T("[%d] read buffersize is TIMEOUT"), __LINE__);
PrintLogLast(strTmp);
return TIMEOUT;
}
void Zmodem::ReadSettings(Settings &copy)
{
copy.BaudRate = 115200;
copy.Parity = 'N';
copy.WordLength = 8;
copy.StopBits = 1;
copy.Dtr = 1;
copy.Rts = 0;
copy.XonXoff = 0;
copy.RtsCts = 0;
copy.DtrDsr = 0;
}
int Zmodem::TXSpaceUsed( void )
{
return (m_BuffCount - BUFFSIZE);
}
int Zmodem::GetFileSize(char *buffer)
{
char cFileSize[64];
memset(cFileSize, 0, 64);
int nIndex = 0;
while(buffer[nIndex] != ' ')
{
cFileSize[nIndex] = buffer[nIndex];
nIndex++;
}
return atoi(cFileSize);
}
void Zmodem::SendCharToComm()
{
port->ZmodemSendDataDirectly(m_WriteBuff, m_WriteBuffLength);
memset(m_WriteBuff, 0, 8192);
m_WriteBuffLength = 0;
}
void Zmodem::ClearReadBuf()
{
m_BuffCount = 0;
m_nBufReadIndex = 0;
memset(buff,0,BUFFSIZE);
}
void Zmodem::PrintLog(char *chPrtlog, int nLogLen)
{
ASSERT(NULL != chPrtlog);
fwrite(chPrtlog,nLogLen,1,zmodemLog);
fflush(zmodemLog);
}
void Zmodem::PrintLogLast(CString& strLog)
{
if (NULL == zmodemLog)
{
if (LANG_ZHCN == g_iUILanguage)
AfxMessageBox(_T("无法写入device_log,日志文件点为空"));
else
MessageBoxEx(NULL, _T("Can't write device_log, log File point is NULL"), _T("LOG_ERROR"), MB_OK, MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US));
return;
}
CString strOutPut = _T("");
strOutPut.Format(_T("%04d-%02d-%02d %02d:%02d:%02d.%03d %s \r\n"),g_sysCurTime.wYear, g_sysCurTime.wMonth, g_sysCurTime.wDay,
g_sysCurTime.wHour, g_sysCurTime.wMinute, g_sysCurTime.wSecond, g_sysCurTime.wMilliseconds, strLog.GetBuffer(0));
fwrite(strOutPut.GetBuffer(0), 1, strOutPut.GetLength(), zmodemLog);
fflush(zmodemLog);
}
int Zmodem::GetFileSize()
{
return m_FileSize;
}
int Zmodem::GetTransferPosit()
{
return m_ByteTransfer;
}
BOOL Zmodem::SendCancelString()
{
char chCancelString[] = {
CAN, CAN, CAN, CAN, CAN, CAN, CAN, CAN, CAN, CAN,
BS, BS, BS, BS, BS, BS, BS, BS, BS, BS };
return port->ZmodemSendDataDirectly( chCancelString, sizeof(chCancelString));//tmp
}