📄 xmodem.c
字号:
#include "xmodem.h"
#include <stdio.h>
#include <ioLib.h>
#include <selectLib.h>
#include <string.h>
static const int MAX_RETRY_TIMES_FOR_STARTUP = 100;
static const int MAX_RETRY_TIMES = 10;
static const int WAIT_FRAME_TIME = 10;
static const int WAIT_DATA_TIME = 1;
static const int SOH_DATA_LENGTH = 128;
static const int STX_DATA_LENGTH = 1024;
/* the control character in Xmodem */
#define SOH ( 0x01 )
#define STX ( 0x02 )
#define EOT ( 0x04 )
#define ACK ( 0x06 )
#define DLE ( 0x10 )
#define XON ( 0x11 )
#define XOFF ( 0x13 )
#define NAK ( 0x15 )
#define SYN ( 0x16 )
#define CAN ( 0x18 )
#define OUTC ( 0x43 )
static int gXmodemComPort = -1;
static int gRecvFileId = -1;
static xmodemFrame gstrXmodemFrame;
static int xmodemTransCancel( void );
static int xmodemDInit( void )
{
if( gXmodemComPort != -1 )
{
close( gXmodemComPort );
gXmodemComPort = -1;
}
if( gRecvFileId != -1 )
{
if( remove( "revcfile" ) == ERROR )
{
printf( "[fileTransCancel]:remove file failed\n" );
}
gRecvFileId = -1;
}
return( 0 );
}
static int xmodemInit( void )
{
if( gXmodemComPort == -1 )
{
if( ( gXmodemComPort = open( "/tyCo/4", O_RDWR , 0 ) ) == ERROR )
{
printf("[ xmodemDownLoad ] : open Com failure\n" );
xmodemDInit( );
return( -1 );
}
if( ioctl( gXmodemComPort, FIOBAUDRATE, 115200 ) == ERROR )
{
printf(" [ comRcvFileInit ]: set the BAUD ERROR\n");
xmodemDInit( );
return( -1 );
}
}
if( ( gRecvFileId = open ( "revcfile", O_RDWR | O_CREAT , 0644 ) ) == ERROR )
{
printf(" [ comRcvFileInit ]: creat file failed\n");
return( -1 );
}
return( 0 );
}
static int xmodemPutChar( char cSendChar )
{
if( gXmodemComPort == -1 )
{
printf( "[xmodemPutChar]:the com potr is not open\n" );
return( -1 );
}
if( write( gXmodemComPort, &cSendChar, 1 ) == ERROR )
{
printf( "[xmodemPutChar]:write one byte failed\n" );
return( -1 );
}
return( 0 );
}
static int xmodemGetCharInTime( int iOverTime, unsigned char *pucData )
{
fd_set readFds;
struct timeval strTimeOut;
FD_ZERO( &readFds );
FD_SET( gXmodemComPort, &readFds );
strTimeOut.tv_sec = iOverTime;
strTimeOut.tv_usec = 0;
if( select( sizeof( fd_set ), &readFds, NULL, NULL, &strTimeOut ) <= 0 )
{
return( -1 );
}
if( FD_ISSET( gXmodemComPort, &readFds ) )
{
if( read( gXmodemComPort, pucData, 1 ) == 1 )
{
return( 0 );
}
}
return( -1 );
}
static unsigned short xmodemGetCrc( unsigned char *pucDataBuff, int iDataBuffLength )
{
int i, j;
unsigned short usCrc;
for( i = 0; i < iDataBuffLength; i++ )
{
usCrc = usCrc ^ pucDataBuff[ i ] << 8;
for( j = 0; j < 8; ++j )
{
if( usCrc & 0x8000 )
{
usCrc = usCrc << 1 ^ 0x1021;
}
else
{
usCrc = usCrc << 1;
}
}
}
usCrc &= 0xffff;
return( usCrc );
}
static int xmodemCopyDataToFile( unsigned char *pucDataBuff, int iBuffLength )
{
if( ( pucDataBuff == NULL ) || ( iBuffLength <= 0 ) )
{
printf( "[xmodemCopyDataToFile]:the para is invalid\n" );
return( -1 );
}
return( write( gRecvFileId, pucDataBuff, iBuffLength ) );
}
static int xmodemPurge( void )
{
if( ioctl( gXmodemComPort, FIOFLUSH, 0 ) == ERROR )
{
printf( "[xmodemPurge]:Port buff flush error\n" );
return( -1 );
}
return( 0 );
}
static int xmodemStartup( void )
{
int i;
unsigned char ucFrameType;
for( i = 0; i < MAX_RETRY_TIMES_FOR_STARTUP; i++ )
{
xmodemPutChar( OUTC );
if( xmodemGetCharInTime( WAIT_FRAME_TIME, &ucFrameType ) == -1 )
{
continue;
}
switch( ucFrameType )
{
case SOH:
case STX:
gstrXmodemFrame.ucframeType = ucFrameType;
printf( "[xmodemStartup]:xmodem startup succeed\n" );
return( 0 );
default:
xmodemPurge( );
break;
}
}
printf( "[xmodemStartup]:xmodem startup overtime\n" );
xmodemTransCancel( );
return( -1 );
}
static int xmodemGetHead( void )
{
unsigned char ucHead;
int i;
for( i = 0; i < MAX_RETRY_TIMES; i++ )
{
if( xmodemGetCharInTime( WAIT_FRAME_TIME, &ucHead ) == -1 )
{
xmodemPutChar( NAK );
continue;
}
switch( ucHead )
{
case SOH:
case STX:
gstrXmodemFrame.ucframeType = ucHead;
return( 0 );
case EOT:
xmodemPutChar( ACK );
if( gXmodemComPort != -1 )
{
close( gXmodemComPort );
gXmodemComPort = -1;
}
return( EOT );
case CAN:
xmodemDInit( );
return( CAN );
default:
xmodemPurge( );
xmodemPutChar( NAK );
break;
}
}
printf( "[xmodemGetHead]:xmodem Get Head overtime\n" );
xmodemTransCancel( );
return( -1 );
}
static int xmodemGetFrameId( void )
{
unsigned char ucFrameId, ucCmpFrameId;
static int iRetryTime = 0;
while( iRetryTime < MAX_RETRY_TIMES )
{
if( xmodemGetCharInTime( WAIT_DATA_TIME, &ucFrameId ) == -1 )
{
iRetryTime++;
continue;
}
iRetryTime = 0;
break;
}
while( iRetryTime < MAX_RETRY_TIMES )
{
if( xmodemGetCharInTime( WAIT_DATA_TIME, &ucCmpFrameId ) == -1 )
{
iRetryTime++;
continue;
}
iRetryTime = 0;
break;
}
if( ucFrameId != ( 0xff - ucCmpFrameId ) )
{
iRetryTime++;
if( iRetryTime == 10 )
{
printf( "[xmodemStartup]:Recv frame ID is overtime\n" );
return( -1 );
}
xmodemPurge( );
xmodemPutChar( NAK );
return( NAK );
}
if( ( gstrXmodemFrame.ucframeNo + 1 ) != ucFrameId )
{
printf( "[xmodemStartup]:frame ID is not expectation\n" );
xmodemTransCancel( );
return( -1 );
}
gstrXmodemFrame.ucframeNo++;
return( 0 );
}
static int xmodemGetData( void )
{
int i;
unsigned short usCrc;
unsigned char pucGetDataBuff[ STX_DATA_LENGTH + 2 ];
static int iRetryTime = 0;
if( gstrXmodemFrame.ucframeType == SOH )
{
for( i = 0; i < SOH_DATA_LENGTH + 2; i++ )
{
if( xmodemGetCharInTime( WAIT_DATA_TIME, &pucGetDataBuff[ i ] ) == -1 )
{
if( iRetryTime == 10 )
{
printf( "[xmodemGetData]:xmodem Get SOH data overtime\n" );
xmodemTransCancel( );
return( -1 );
}
iRetryTime++;
}
}
usCrc = xmodemGetCrc( pucGetDataBuff, SOH_DATA_LENGTH );
if( ( ( unsigned char )( usCrc >> 8 ) != pucGetDataBuff[ SOH_DATA_LENGTH ] ) ||
( ( unsigned char ) usCrc != pucGetDataBuff[ SOH_DATA_LENGTH + 1 ] ) )
{
printf( "[xmodemGetData]:SOH crc is error\n" );
iRetryTime++;
if( iRetryTime == 10 )
{
printf( "[xmodemGetData]:xmodem Get SOH data overtime\n" );
xmodemTransCancel( );
return( -1 );
}
xmodemPurge( );
xmodemPutChar( NAK );
return( NAK );
}
if( xmodemCopyDataToFile( pucGetDataBuff, SOH_DATA_LENGTH ) == ERROR )
{
printf( "[xmodemGetData]:write file error\n" );
xmodemTransCancel( );
return( -1 );
}
}
else if( gstrXmodemFrame.ucframeType == STX )
{
for( i = 0; i < STX_DATA_LENGTH + 2; i++ )
{
if( xmodemGetCharInTime( WAIT_DATA_TIME, &pucGetDataBuff[ i ] ) == -1 )
{
if( iRetryTime == 10 )
{
printf( "[xmodemGetData]:xmodem Get STX data overtime\n" );
return( -1 );
}
iRetryTime++;
}
}
usCrc = xmodemGetCrc( pucGetDataBuff, SOH_DATA_LENGTH );
if( ( ( unsigned char )( usCrc >> 8 ) != pucGetDataBuff[ SOH_DATA_LENGTH ] ) ||
( ( unsigned char ) usCrc != pucGetDataBuff[ SOH_DATA_LENGTH + 1 ] ) )
{
printf( "[xmodemGetData]:STX crc is error\n" );
iRetryTime++;
if( iRetryTime == 10 )
{
printf( "[xmodemGetData]:xmodem Get STX data overtime\n" );
return( -1 );
}
xmodemPurge( );
xmodemPutChar( NAK );
return( NAK );
}
if( xmodemCopyDataToFile( pucGetDataBuff, SOH_DATA_LENGTH ) == ERROR )
{
printf( "[xmodemGetData]:write file error\n" );
return( -1 );
}
}
xmodemPutChar( ACK );
return( 0 );
}
static int xmodemTransCancel( void )
{
xmodemPutChar( CAN );
if( xmodemDInit( ) == -1 )
{
printf( "[xmodemDownLoad]:xmodem DInit failed\n" );
return( -1 );
}
return( 0 );
}
int xmodemDownLoad( void )
{
int iIsStartupFlag = 0;
gstrXmodemFrame.ucframeNo = -1;
if( xmodemInit( ) == 0 )
{
printf( " init failed " );
return( 0 );
}
while( 1 )
{
if( iIsStartupFlag == 0 )
{
if( xmodemStartup( ) == -1 )
{
return( -1 );
}
iIsStartupFlag = 1;
}
else
{
switch( xmodemGetHead( ) )
{
case 0:
break;
case EOT:
return( 0 );
case CAN:
case -1:
return( -1 );
}
}
switch( xmodemGetFrameId( ) )
{
case 0:
break;
case NAK:
continue;
case -1:
return( -1 );
}
switch( xmodemGetData( ) )
{
case 0:
break;
case NAK:
continue;
case -1:
return( -1 );
}
}
return( 0 );
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -