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

📄 xmodem.c

📁 用MINIGUI开发的维护程序.ARM编译. 上传镜像文件,下载镜像文件,下载程序文件,下载配置文件,上传日志文件 利用XMODEM 协议传输文件.
💻 C
字号:
/*	Copyright 2001, 2002 Georges Menie (www.menie.org)    This program is free software; you can redistribute it and/or modify    it under the terms of the GNU Lesser 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 Lesser General Public License for more details.    You should have received a copy of the GNU Lesser 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*//* this code needs standard functions memcpy() and memset()   and input/output functions port_inbyte() and port_outbyte().   the prototypes of the input/output functions are:     int port_inbyte(unsigned short timeout); // msec timeout     void port_outbyte(int c); */#include "crc16.h"#include <stdio.h>#include <signal.h>#include <setjmp.h>#include <fcntl.h>#include <termios.h> #include <unistd.h>#include <time.h>#include <sys/stat.h>#define SOH  0x01#define STX  0x02#define EOT  0x04#define ACK  0x06#define NAK  0x15#define CAN  0x18#define CTRLZ 0x1A#define DLY_1S 2000#define MAXRETRANS 10#define	TRUE	1#define	FALSE	0static int last_error = 0;/****************Portting Start *******************/#include "string.h"char	buff[50001];int	Comfp;struct termios oldtty;int	volatile	fAppExit	=	FALSE;//static struct sigaction sig_KILL;static struct sigaction sig_TERM;#define  ONE_SECOND     100enum {	RET_SUCESS		= 0,	RET_SYSFAILED,	RET_XMCANCEL,	RET_XMNOSYNC,	RET_XMERROR,	//send or receiv error	RET_MYCANCEL,};enum {	MODE_SEND		= 0,	MODE_RECV		= 1,};uint GetTimeTick(){    static struct timeval  stmv = {0, 0};    if (!stmv.tv_sec){        gettimeofday(&stmv, NULL);        return 0;    }    else {        struct timeval  tmv;        gettimeofday(&tmv, NULL);        return  ((tmv.tv_sec  - stmv.tv_sec)*100 +                (tmv.tv_usec - stmv.tv_usec)/100000);    }}// tick: 10 ms unitvoid SlowWait(int n10ms){    uint  etv = GetTimeTick() + n10ms;    //sched_yield();    while (1){        if (GetTimeTick() >= etv) break;       // sched_yield();    }}int lowLevel_read(unsigned char *c ,int len){	return read(Comfp,c,len);}int lowLevel_write(unsigned char *c ,int len){	return write(Comfp,c,len);}void port_outbyte(unsigned char trychar){	unsigned char buf[2];	buf[0] = trychar;	lowLevel_write(buf,1);	printf("%d,",trychar);}unsigned char port_inbyte(unsigned int time_out){	unsigned char ch;	int i;	uint  etv = GetTimeTick() + time_out/10;	 while (1){		if (GetTimeTick() >= etv) break;				if(lowLevel_read(&ch,1) == 1){			last_error = 0;			return ch;		}		   	 }	 last_error = 1;	return 0;}/****************Portting End*******************/static int check(int crc, const unsigned char *buf, int sz){	if (crc) 	{		unsigned short crc = crc16_ccitt(buf, sz);		unsigned short tcrc = (buf[sz]<<8)+buf[sz+1];		//printf("chkcrc:0x%0x, reccrc:0x%0x\n",crc,tcrc);		if (crc == tcrc)			return 1;	}	else 	{		int i;		unsigned char cks = 0;		for (i = 0; i < sz; ++i) 		{			cks += buf[i];		}		if (cks == buf[sz])		return 1;	}	return 0;}static void flushinput(void){	tcflush(Comfp, TCIFLUSH); }static void flushoutput(void){	tcflush(Comfp, TCOFLUSH); }int xmodemReceive(FILE * filep,unsigned char *dest){	unsigned char xbuff[1030]; /* 1024 for XModem 1k + 3 head chars + 2 crc + nul */	unsigned char *p;	int bufsz, crc = 0;	unsigned char trychar = 'C';	unsigned char packetno = 1;	int i, c, filelen=0,len = 0;	int	lastblk,firstpacket	= TRUE;	int retry, retrans = MAXRETRANS;	for(;;) 	{		for( retry = 0; retry < 30; ++retry) 		{			if(fAppExit)	return RET_MYCANCEL;			if (trychar) 				port_outbyte(trychar);			flushoutput();			c = port_inbyte((DLY_1S));			//printf("rec:0x%x\n",c);			if (last_error == 0) 			{				switch (c) 				{					case SOH:						bufsz = 128;						//trychar = NAK; 						goto start_recv;					case STX:						bufsz = 1024;						goto start_recv;					case EOT:						port_outbyte(ACK);						flushoutput();						//deal with file trancate the ctrlz						for(i=lastblk-1;i>=0;i--){							if(dest[i] != CTRLZ)								break;						}						//printf("xmodem last packet len:%d\n",i+1);						fwrite(dest,1,i+1,filep);						filelen -= (lastblk -i-1);						return RET_SUCESS; /* normal end */					case CAN:						c = port_inbyte(DLY_1S);						if (c == CAN) 						{							flushinput();							port_outbyte(ACK);							flushoutput();							return RET_XMCANCEL; /* canceled by remote */						}						break;					default:						break;				}			}		}		if (trychar == 'C') 		{ 			trychar = NAK; 			continue; 		}		flushinput();		port_outbyte(CAN);		port_outbyte(CAN);		port_outbyte(CAN);		flushoutput();		return RET_XMNOSYNC; /* sync error */	start_recv:				if(fAppExit)	return RET_MYCANCEL;				if (trychar == 'C') crc = 1;				trychar = 0;		p = xbuff;		*p++ = c;		for (i = 0;  i < (bufsz+(crc?1:0)+3); ++i) 		{			c = port_inbyte(DLY_1S);			//printf("%d,",c);			if (last_error != 0) 				goto reject;			*p++ = c;					}		//printf("\nrec:%d,cur:%d\n",xbuff[1],packetno);		if (xbuff[1] == (unsigned char)(~xbuff[2]) && 			(xbuff[1] == packetno || xbuff[1] == (unsigned char)packetno-1) &&			check(crc, &xbuff[3], bufsz)) 		{			if (xbuff[1] == packetno)				{				if(!firstpacket){					fwrite(&dest[len-lastblk],1,lastblk,filep);					filelen += lastblk;					len = 0;				}				memcpy (&dest[len], &xbuff[3], bufsz);				len += bufsz;				lastblk = bufsz;								++packetno;				firstpacket = FALSE;				retrans = MAXRETRANS+1;							}			if (--retrans <= 0) 			{				flushinput();				port_outbyte(CAN);				port_outbyte(CAN);				port_outbyte(CAN);				flushoutput();				return RET_XMERROR; /* too many retry error */			}			//printf("rec:%d send ack\n",xbuff[1]);			port_outbyte(ACK);			flushoutput();			continue;		}		else if(xbuff[1]  < packetno){ 			port_outbyte(ACK);			flushoutput();			continue;		}	reject:		flushinput();		port_outbyte(NAK);		flushoutput();	}}int xmodemTransmit(int	frame,unsigned char *src, int srcsz){	unsigned char xbuff[1030]; /* 1024 for XModem 1k + 3 head chars + 2 crc + nul */	int bufsz, crc = -1;	static unsigned char packetno = 1;	int i, c, len = 0;	int retry;	//printf("transmint:%d\n",srcsz);	if(frame == 0){		//printf("get handshare\n");		packetno = 1;		for( retry = 0; retry < 30; ++retry) 		{			if(fAppExit)	return RET_MYCANCEL;			c = port_inbyte((DLY_1S));			if(c <= 0) continue; 			//printf("recv:0x%0x\n",c);			if (last_error == 0) 			{				switch (c) 				{					case 'C':						crc = 1;						goto start_trans;					case NAK:						crc = 0;						goto start_trans;					case CAN:						c = port_inbyte(DLY_1S);						if (c == CAN) 						{							port_outbyte(ACK);							flushoutput();							return RET_XMCANCEL; /* canceled by remote */						}						break;					default:						break;				}			}		}		port_outbyte(CAN);		port_outbyte(CAN);		port_outbyte(CAN);		flushoutput();		return RET_XMNOSYNC; /* no sync */	}	for(;;) 	{	start_trans:		//printf("start to transfer\n");		if(fAppExit)	return RET_MYCANCEL;		/*xbuff[0] = SOH; bufsz = 128;		xbuff[1] = packetno;		xbuff[2] = ~packetno;*/		xbuff[0] = STX; bufsz = 1024;		xbuff[1] = packetno;		xbuff[2] = ~packetno;				c = srcsz - len;		if (c > bufsz) c = bufsz;		//printf("send c:%d,frame:%d\n",c,frame);		if (c > 0) 		{			memset (&xbuff[3], 0, bufsz);			if (c == 0) 			{				xbuff[3] = CTRLZ;			}			else 			{				memcpy (&xbuff[3], &src[len], c);				if (c < bufsz) xbuff[3+c] = CTRLZ;			}			if (crc) 			{				unsigned short ccrc = crc16_ccitt(&xbuff[3], bufsz);				xbuff[bufsz+3] = (ccrc>>8) & 0xFF;				xbuff[bufsz+4] = ccrc & 0xFF;			}			else 			{				unsigned char ccks = 0;				for (i = 3; i < bufsz+3; ++i) 				{					ccks += xbuff[i];				}				xbuff[bufsz+3] = ccks;			}			for (retry = 0; retry < MAXRETRANS; ++retry) 			{				if(fAppExit)	return RET_MYCANCEL;				//printf("send packet:%d\n", bufsz+4+(crc?1:0));				for (i = 0; i < bufsz+4+(crc?1:0); ++i) 				{					port_outbyte(xbuff[i]);				}				flushoutput();				c = port_inbyte(DLY_1S);				//printf("packet:%d,get:%d\n",packetno,c);				if (last_error == 0 ) 				{					switch (c) 					{						case ACK:							++packetno;							len += bufsz;							//printf("send byte:%d suc \n",bufsz);							goto start_trans;						case CAN:							c = port_inbyte(DLY_1S);							if ( c == CAN) 							{								port_outbyte(ACK);								flushoutput();								return RET_XMCANCEL; /* canceled by remote */							}							break;						case NAK:						default:							break;					}				}			}			port_outbyte(CAN);			port_outbyte(CAN);			port_outbyte(CAN);			flushoutput();			return RET_XMERROR; /* xmit error */		}		else 		{			if(frame == EOT){				for (retry = 0; retry < 6; ++retry) 				{					port_outbyte(EOT);					flushoutput();					c = port_inbyte((DLY_1S));					if (c == ACK)  break;				}				return (c == ACK)? RET_SUCESS : RET_XMERROR;			}else				return RET_SUCESS;		}	}	}int Initial_SerialPort(char	*file){	int fd;	struct termios options;	//printf("wb:Initial_SerialPort:%s\n",file);	fd = open( file , O_RDWR |O_NOCTTY |O_NDELAY);	if ( fd == -1 )	{	/*open error!*/	perror("xmodem Can't open serial port!");	return -1;	}		/*Get the current options for the port...*/	tcgetattr(fd, &options);	oldtty = options;	/*Set the baud rates to BAUDRATE...*/	cfsetispeed(&options,B115200);	cfsetospeed(&options,B115200);	tcsetattr(fd, TCSANOW, &options);	if (0 != tcgetattr(fd, &options))	{	perror("xmodem  SetupSerial error");	return -1;	}	/*	* 8bit Data,no partity,1 stop bit...	*/	options.c_cflag &= ~PARENB;	options.c_cflag &= ~CSTOPB;	options.c_cflag &= ~CSIZE;	options.c_cflag |= CS8;	 options.c_cflag  |=   CREAD;	tcflush(fd,TCIFLUSH);	//close char change	options.c_iflag = 0;	/***Choosing Raw Input*/	options.c_lflag = 0;	//options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);	options.c_oflag &= ~OPOST;	/*	* Set the new options for the port...	*/	if (0 != tcsetattr(fd, TCSANOW, &options))	{	perror("xmodem  SetupSerial error");	return -1 ;	}	return fd ;}static void compmt(char *pmt){	int	len;	len = strlen(pmt);	write(Comfp,pmt,len);	flushoutput();}static void sig_handler(int sig){	//printf("get sig:%d\n",sig);	if(sig == SIGTERM){		int	i;		printf("get sig SIGKILL\n");		fAppExit	= TRUE;	}}void 	initsiger(){	struct sigaction  siga;	siga.sa_handler = sig_handler;	siga.sa_flags = 0;	memset (&siga.sa_mask, 0, sizeof (sigset_t));	sigaction (SIGTERM, &siga, &sig_TERM);	signal(SIGCHLD, SIG_IGN);	}int main(int argc, char**argv){	unsigned char	buff[3000];	char		filename[128];	int		mode,len,ret = 0;	long		filelen = 0,pos=0;	FILE         *fp;		struct stat   st;	Comfp = Initial_SerialPort("/dev/ttyGS0");	if(Comfp < 0){		printf("open /dev/ttyGS0 failed\n");		return RET_SYSFAILED;	}		fAppExit	= FALSE;	initsiger();		tcflush(Comfp, TCIOFLUSH); 	while(!ret){		if(argc != 3){			printf("xmodem agument mode(recv/send) file(pathname)\n");			ret =  RET_SYSFAILED;			continue;		}		if(!strcmp(argv[1],"send"))			mode = MODE_SEND;		else if(!strcmp(argv[1],"recv"))			mode = MODE_RECV;		else{			ret =  RET_SYSFAILED;			continue;		}		strcpy(filename,argv[2]);		printf("xmodem %s %s\n",argv[1],argv[2]);				//check file and get filelen		  if (!stat(filename,&st)) 			filelen = st.st_size;    		 else if(mode == MODE_SEND){  //file no exist			ret =  RET_SYSFAILED;			continue;    		 }		if(mode == MODE_SEND){			int	frame=0;			printf("xmodem sending file:%s,len:%ld\n",filename,filelen);			compmt("\n[ABPM] please receive files by xmodem with one minute\n");						if ((fp=fopen(filename, "r")) == NULL){				printf("xmodem open file failed\n");				ret =  RET_SYSFAILED;				continue;			}			fseek(fp,pos,SEEK_SET);			while(filelen > 0){				printf("filelen:%d\n",filelen);				if(filelen <= 1024)	frame = EOT;				len = fread(buff, sizeof(char),1024, fp);								ret = xmodemTransmit(frame,buff,len);				printf("xmodemTransmit return :%d\n",ret);				if(ret > 0)	break;				filelen -= len;				frame = 1;			}			fclose(fp);			break;		}		else if(mode == MODE_RECV){			printf("xmodem recving file:%s\n",filename);			compmt("\n[ABPM]  please send file by xmodem with one minute\n");			if ((fp=fopen(filename, "w")) == NULL){				printf("xmodem open file failed\n");				ret =  RET_SYSFAILED;				continue;			}			fseek(fp,pos,SEEK_SET);			ret = xmodemReceive(fp,buff);			//printf("xmodem return ret:%d\n",ret);			fclose(fp);			if(ret  != 0){				//printf("xmodem recv file failed:%d\n",ret);				remove(filename);			}			break;		}			break;	}	if(ret == RET_MYCANCEL){		int	i;		for(i=0;i<3;i++){			port_outbyte(CAN);			port_outbyte(CAN);			port_outbyte(CAN);			flushoutput();		}	}	close(Comfp);	return ( ret);	}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -