⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 xmodem.c

📁 vxworks下的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 + -