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

📄 xcxmdm.c

📁 支持X/YModem和cis_b+协议的串口通讯程序
💻 C
📖 第 1 页 / 共 2 页
字号:
/*      xcxmdm.c -- XMODEM Protocol module for XC        This file uses 4-character tabstops*/#include <stdio.h>#include <stdlib.h>#include <string.h>#include <ctype.h>#include <sys/types.h>#include <utime.h>#include <sys/stat.h>#include <signal.h>#include <setjmp.h>#include "xc.h"#define WANTCRG 'G'#define WANTCRC 'C'#define FALLBACK 16#define CPMEOF  032		/* ^Z */#define OK       0#define TIMEOUT -1		/* -1 is returned by readbyte() upon timeout */#define ERROR   -2#define WCEOT   -3#define RETRYMAX 10#define Maxtime 10#define SECSIZ  1025#define Resume_Not_Allowed 1#define RxUpdcrc(c,crc) (crc_xmodem_tab[((crc>>8)&0xff)]^(crc<<8)^c)&0xffff#define TxUpdcrc(c,crc) (crc_xmodem_tab[((crc>>8)^c)&0xff]^(crc<<8))#include <assert.h>   static short int smallhdr = FALSE;static short int badline  = FALSE;static short int g_flag   = FALSE;static short int y_done   = FALSE;       short int y_flag   = FALSE;  /* global used in xcmain.c *//* define storage for info from decoding ymodem rx header */static struct yinfo {	char *fnam ;	long int fsiz ;	time_t fdat ;	unsigned long fprm ;}  phdr ;/* crc_xmodem_tab calculated by Mark G. Mendel, Network Systems Corporation */unsigned short crc_xmodem_tab[256] ={    0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,    0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,    0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,    0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,    0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,    0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,    0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,    0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,    0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,    0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,    0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,    0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,    0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,    0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,    0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,    0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,    0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,    0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,    0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,    0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,    0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,    0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,    0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,    0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,    0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,    0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,    0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,    0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,    0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,    0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,    0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,    0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0};static short crcheck = TRUE;	/* CRC check enabled? */static FILE *xfp;		/* buffered file pointer */static short firstsec,		/* first sector of file or not? */  ksecsize,			/* for Xmodem or old Ymodem packet */  stx_soh,			/* SOH = Xmodem ; STX = old Ymodem */  amdone = FALSE,		/* flag: xfer almost finished */  sync,				/* flag for negotiating crc or checksum */  textmode = FALSE;		/* Text translations enabled? */static char wcbuf[SECSIZ];	/* Ward Christensen sector buffer */static jmp_buf our_env;static char *p, sendchar;/* send cancel string to get the other end to shut up */voidcanit P_((void)){	char canistr[] = {	 24,24,24,24,24,24,24,24,24,24,8,8,8,8,8,8,8,8,8,8,0	};	send_string(canistr);}static RETSIGTYPExmsigint(junk)int junk;{    signal (SIGINT, SIG_IGN);	/* Ignore subsequent DEL's */    show_abort ();    canit ();			/* Abort the transmission */    longjmp (our_env, 1);}/*      fill the CP/M sector buffer from the UNIX file        do text adjustments if necessary        return 1 if more sectors are to be read, or 0 if this is the last*/static intgetsec P_((void)){    int i;    register c = 0 ;    static int j, fbinit, fback;    if ( firstsec && y_flag ) /* build ymodem header */      {	return y_done? 0 : 1 ;      }    else if (amdone == FALSE)      {	  i = 0;	  j = 8;	  fbinit = fback = TRUE;	  while (i < ksecsize && (c = getc (xfp)) != EOF)	    {		if (textmode && c == '\n')		  {		      wcbuf[i++] = '\r';		      if (i >= ksecsize)			{	/* handle a newline on the last byte */			    ungetc (c, xfp);	/* of the sector */			    return (1);			}		  }		wcbuf[i++] = c;	    }	  /* make sure that an extra blank sector is not sent */	  if (c != EOF && (c = getc (xfp)) != EOF)	    {		ungetc (c, xfp);		return (1);	    }	  /* fill up the last sector with ^Z's if text mode or 0's if binary mode */	  j = i;	  while (i < ksecsize)	      wcbuf[i++] = textmode ? CPMEOF : '\0'; 	  amdone = TRUE;	  fback = FALSE;	  if ( y_flag || stx_soh == SOH || j > 896)	/* done, send whole sector */	      return (0);	  j += 127;	  j >>= 7;		/* calculate number of 128 bytes sectors to send */	  fbinit = TRUE;      }				/* end of "amdone" */    if (fbinit)      {	  p = wcbuf;		/* save old buffer base address */	  p -= 128;	  stx_soh = SOH;	/* switch to 128 byte blocks    */	  ksecsize = 128;	  fbinit = FALSE;      }				/* end of "fbinit" */    p += 128;    memcpy (wcbuf, p, 128);    if (--j > 0)		/* more packets remain */	return (1);    else      {	  if (fback)	    {		amdone = FALSE;		return (1);	    }	  else	      return (0);      }}/* automatically negotiate crc or checksum reception */static charsyncem P_((void)){    int ct = 2;    char c;    purge ();    while (ct)      {	  /* try to negotiate a CRC transfer */	  sendbyte ( g_flag ? WANTCRG : WANTCRC );	  c = readbyte (10);	  if (c != CAN && c != SOH && c != STX)	      ct--;	  else	    {		sendchar = ACK;		crcheck = g_flag ? WANTCRG : WANTCRC ;		return (c);	    }	    if ( g_flag ) { ct = 2, g_flag = FALSE ;} /* try again without "G" */      }    ct = 2;    purge ();    while (ct)      {				/* maybe we can initiate a checksum transfer */	  sendbyte (NAK);	  c = readbyte (10);	  if (c != CAN && c != SOH && c != STX)	      ct--;	  else	    {		sendchar = ACK;		crcheck = FALSE;		return (c);	    }      }    purge ();    return (TIMEOUT);}/*      wcgetsec() inputs an XMODEM "sector".        This routine returns the sector number encountered, or ERROR if a valid        sector is not received or CAN received; or WCEOT if EOT sector.        Maxtime is the timeout for the first character, set to 10 seconds for        retries. No ACK is sent if the sector is received ok. This must be        done by the caller when it is ready to receive the next sector.*/static intwcgetsec (maxtime)     unsigned maxtime;{    register unsigned oldcrc;    register checksum, j, c = 0;    int sectcurr, sectcomp, attempts;    if (sync == FALSE)      {				/* negotiate crc or checksum error detection */	  c = syncem ();	  if (crcheck == FALSE)	      show (1, "ATTENTION: sender demands CHECKSUM error detection ");	  else	      show (1, "CRC packet validation enabled   ");      }    for (attempts = 0; attempts < RETRYMAX; attempts++)      {	  if (sync == TRUE)	    {		do		  {		      c = readbyte (maxtime);		  }		while (c != STX && c != SOH && c != EOT && c != CAN && c != TIMEOUT);	    }	  else	      sync = TRUE;	  switch (c)	    {	    case STX:	    case SOH:		if (c == SOH)		    ksecsize = 128;	/* xmodem packet size  */		else		    ksecsize = 1024;	/* ymodem packet size  */		sectcurr = readbyte (3);		sectcomp = readbyte (3);		if ((sectcurr + sectcomp) == 0xff)		  {		      oldcrc = checksum = 0;		      for (j = 0; j < ksecsize; j++)			{			    if ((c = readbyte (3)) == TIMEOUT)				goto timeout;			    wcbuf[j] = c;			    oldcrc = RxUpdcrc (c, oldcrc);			    checksum += c;			}		      if ((c = readbyte (3)) < 0)			  goto timeout;		      if (crcheck)			{			    oldcrc = RxUpdcrc (c, oldcrc);			    if ((c = readbyte (3)) == TIMEOUT)				goto timeout;			    if (RxUpdcrc (c, oldcrc))			      {				  show(2,"CRC error     ");				  if(g_flag) {					show(2,"G-mode cancel ");					goto gquit ;				  }				  break;			      }			}		      else if (((checksum - c) & 0xff) != 0)			{			    show(2,"Checksum error");			    break;			}		      return (sectcurr);		  } 		else  /* packet header garbled */		  {		    sprintf (Msg, "Packet number garbled %03d %03d",			     sectcurr, sectcomp);		    show (2,Msg);		    if(g_flag) {			show(2,"G-mode cancel");			goto gquit ;		    }		  }		break;	    case EOT:		if (readbyte (3) == TIMEOUT)		    return (WCEOT);		break;	    case CAN:		show(2,"Sender CANcelled");		return (ERROR);	    case TIMEOUT:	      timeout:		show(2,"Timeout");		break;	    }	  show(2,"Trying again on this sector");	  purge ();	  maxtime = 6,	  sendbyte (NAK);      }    show(2,"Retry count exceeded");gquit:    canit ();    return (ERROR);}static intputsec P_((void)){    int i;    register c;    /* for y_modem: only write the exact number of chars */    if ( y_flag && 0 < phdr.fsiz ) {	phdr.fsiz -= ksecsize ;	if ( phdr.fsiz < 0 )		ksecsize += phdr.fsiz ;    }    for (i = 0; i < ksecsize; i++)      {	  c = wcbuf[i];	  if (textmode)	    {		if (c == CPMEOF)		    return (1);		if (c == '\r')		    continue;	    }	  putc (c, xfp);      }    return (0);}static voidset_dp( name_fl, time_fl, perm_fl )   const char *name_fl;   const time_t time_fl;   const unsigned long perm_fl;{	struct utimbuf utb ;	if ( name_fl != NULL ) {		if ( time_fl != 0 ) {			utb.actime = utb.modtime = time_fl ;			if ( utime( name_fl, &utb ))				perror(name_fl);		}		if ( perm_fl != 0 ) {			if ( chmod( name_fl, (mode_t) perm_fl ))				perror(name_fl);		}	}}/*      wcputsec outputs a Ward Christensen type sector.        it returns OK or ERROR*/static intwcputsec (sectnum)     int sectnum;{  unsigned short oldcrc;  int checksum, j, c, attempts, errct = 0;  oldcrc = checksum = 0;  for (j = 0; j < (smallhdr ? 128 : ksecsize); j++)    {      c = wcbuf[j];      oldcrc = TxUpdcrc (c, oldcrc);      checksum += c;    }  for (attempts = 0; attempts < RETRYMAX; attempts++)    {      sendbyte (smallhdr ? SOH : stx_soh);      sendbyte (sectnum);      sendbyte (-sectnum - 1);      for (j = 0; j < (smallhdr ? 128 : ksecsize); j++)	sendbyte (wcbuf[j]);      /*          Wait for output to drain before sending checksum/crc.         Clear input buffer of any noise in anticipation of an         acknowledgement after we send the checksum/crc.        */      xc_drain (DRAIN_FLAG);      if (crcheck)	{	  sendbyte ((int) (oldcrc >> 8));	  sendbyte ((int) oldcrc);	}      else	sendbyte (checksum);      /* check for response */      if (firstsec && y_flag)	{	  if (g_flag)	    {			/* Ymodem-g */	      int ack_ct = 12;	/* arbitrary max ACKS before error */	      int timeout_ct = 4;	/* arbitrary max number of timeouts */	      if (y_done)		{		  purge ();	/* delete any extraneous trailing ACKs */		  return OK;		}	      do		{		  c = readbyte (10);		  if (c == WANTCRG || c == CAN)		    break;		  else if (c == TIMEOUT)		    timeout_ct--;		  else		    c = TIMEOUT;		}	      while (--ack_ct && timeout_ct);	      /* according to Forsberg any response other than the following	         is undefined at this sequence point in the ymodem-g protocol:  	       */	      assert (c == TIMEOUT || c == WANTCRG || c == CAN);	    }	  else	    {			/* normal non-streaming ymodem */	      c = readbyte (10);	      if (c == ACK)		{		  firstsec = smallhdr = FALSE;		  if (y_done)		    return OK;		  c = readbyte (20);		}	    }	  if (crcheck && c == crcheck)	    {	      assert (c == WANTCRC || c == WANTCRG);	      firstsec = smallhdr = FALSE;	      return OK;	    }	}      else	{	  c = readbyte (g_flag ? RB_POLL : 10);	}      /* detect false CAN, require 2 in a row */      if (c == CAN)	c = readbyte (g_flag ? 1 : 10);      if (g_flag && c != CAN && (!firstsec || !y_flag))	return OK;      switch (c)

⌨️ 快捷键说明

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