📄 xmodemr.c
字号:
#include "mcudslbase.h"#include "timer.h"#include "serio.h"#include "crctab.h"/* * Copyright (c) 1995 by Edward A. Falk *//********** * * * @ @ @ @ @@@ @@@@ @@@@@ @ @ @@@@ * @ @ @@ @@ @ @ @ @ @ @@ @@ @ @ * @ @ @ @ @ @ @ @ @@@ @ @ @ @@@@ * @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ * @ @ @ @ @ @@@ @@@@ @@@@@ @ @ @ @ @ * * XMODEMR - receiver side of xmodem/ymodem protocol * * Caller sets flags defined in xmodem.h as appropriate. * (default is basic xmodem) * * This code is designed to be called from inside a larger * program, so it is implemented as a state machine where * practical. * * * functions: * * XmodemRInit( INT8U *BaseAddr, Protocol p) * Initiate a receive * * XmodemRTimeout() * called after timeout expired * * XmodemRRcv(char c) * called after character received * * XmodemRAbort() * abort transfer * * all functions return 0 on success, 1 on abort * * * * Edward A. Falk * * January, 1995 * * * **********/#include "xmodem.h" /* TODO: WXmodem */ bool xmodem1k = False ; Protocol protocol = Xmodem ; int xmTfd = -1 ; int xmRfd = -1 ; int xmTimeout = 0 ;typedef enum { Start, /* waiting to begin */ Init, /* sent initial NAK, 'C' or 'W' */ Packet, /* receiving a packet */ Wait, /* wait for start of next packet */ } XmodemState ;static INT8U * memAddr;static bool ymodem ;static XmodemState state = Start ;static int errorCount = 0 ;static int errorCount2 ;static int ignoreCount ;static int eotCount ; /* count EOT's, reject first one */static int inCount ; /* characters received this packet */static int pktLen ; /* length of this packet data */static int pktHdrLen ; /* id, cmpl, checksum or crc */static char packet[MAXPACKET+5], *optr ;static int packetId ; /* id of last received packet */static int packetCount ; /* # packets received *//*static FILE *ofile ; output file fd static int fileLen, fileDate, fileMode ;*/static int XmodemRStart() ;static int processPacket() ;static int rejectPacket() ;static int acceptPacket() ;int XmodemRInit( INT8U *BaseAddr, Protocol prot ){ int err ; memAddr=(INT8U*)BaseAddr; state = Start ; protocol = prot ; ymodem =( (prot == Ymodem) || (prot == YmodemG) ); eotCount = errorCount = errorCount2 = 0 ; err=XmodemRStart(); if( err!=0 ) return err ; state = Init ; packetId = ymodem ? 255 : 0 ; packetCount = 0 ; pktHdrLen = protocol == Xmodem ? 3 : 4 ; return 0 ;} /* send startup character */static intXmodemRStart(){static char pchars[5] = {NAK,'C','W','C','C'} ;static int timeouts[5] = {INITTO, INITTO2, INITTO2, INITTO, INITTO} ; char c = pchars[(int)protocol] ; int err ; err=sendFlush(c); if( err!=0 ) return err ; xmTimeout = timeouts[((int)protocol)] ; return 0 ;}intXmodemRRcv(char c){ errorCount = 0 ; switch( state ) { case Start: /* shouldn't happen, ignore */ if( c == CAN ) return XmErrCancel ; break ; case Init: /* waiting */ case Wait: switch( c ) { case SOH: case STX: pktLen = c == STX ? 1024 : 128 ; inCount = 0 ; optr = packet ; state = Packet ; xmTimeout = PKTTO ; break ; case EOT: if( ++eotCount > 1 ) { sendFlush(ACK) ; if( ymodem ) return 0;/*XmodemRInit() ; restart protocol */ else return XmDone ; } else return rejectPacket() ; /* make xmitter try again */ case CAN: return XmErrCancel ; default: /* ignore all others */ if( ++ignoreCount > 1030 ) { ignoreCount = 0 ; return sendFlush(NAK) ; } break ; } break ; case Packet: /* mid packet */ *optr++ = c ; if( ++inCount >= pktLen + pktHdrLen ) processPacket() ; break ; } return 0 ;}intXmodemRTimeout(){ if( ++errorCount > MAXERROR ) return state == Init ? XmErrInitTo : XmErrRcvTo ; switch( state ) { case Start: return -1 ; /* shouldn't happen */ case Init: if( ++errorCount2 >= 3 ) switch( protocol ) { case WXmodem: protocol = XmodemCrc ; errorCount2 = 0 ; break ; case XmodemCrc: protocol = Xmodem ; pktHdrLen = 3 ; break ; } return XmodemRStart() ; case Wait: /* timeout while waiting */ case Packet: /* timeout in mid packet */ return rejectPacket() ; } return -1;}intXmodemRAbort(){ return sendCancel() ;}static intprocessPacket(){ int id = (INT8U)packet[0] ; int idc = (INT8U)packet[1] ; int i ; if( idc != 255-id ) return rejectPacket() ; if( id == packetId ) /* duplicate */ return acceptPacket() ; if( id != (packetId+1)%256 ) { /* out of sequence */ (void) sendCancel() ; return XmErrSequence ; } if( protocol == Xmodem ) { /* compute checksum */ register int csum = calcChecksum(packet+2, pktLen) ; if( csum != (INT8U) packet[2+pktLen] ) return rejectPacket() ; } else { unsigned short crc0 = (INT8U)packet[pktLen+2] << 8 | (INT8U)packet[pktLen+3] ; unsigned short crc1 = calcrc(packet+2, pktLen) ; if( crc0 != crc1 ) return rejectPacket() ; } /* it's a good packet */ packetId = (packetId+1)%256 ; /* is this the first packet? */ if( packetCount == 0 ) { if( ymodem ) { if( packet[2] == '\0' ) /* last file */ { (void) acceptPacket() ; return XmDone ; } /*if( packet[2] == '/' ) strcpy(xmFilename, packet+2) ; else { strcpy(xmFilename, xmDefPath) ; strcat(xmFilename, packet+2) ; } fileLen = fileDate = fileMode = -1 ; sscanf(packet+2+strlen(packet)+1, "%d %o %o", &fileLen, &fileDate, &fileMode) ;*/ } /*if( (ofile = fopen(xmFilename, "w")) == NULL ) { sendCancel() ; return XmErrCantOpen ; }*/ if( ymodem ) { packetCount = 1 ; acceptPacket() ; return sendFlush('C') ; } else state = Packet ; } ++packetCount ; for(i=0;i<pktLen;i++) { memAddr[i]=packet[i+2]; } memAddr+=pktLen; return acceptPacket() ; /* TODO: ymodem: if this is last packet, truncate it */ /*if( (i=fwrite(packet+2, 1, pktLen, ofile)) != pktLen ) { sendCancel() ; return XmErrSys ; } else return acceptPacket() ;*/}static intrejectPacket(){ state = Wait ; xmTimeout = INITTO ; return sendFlush(NAK) ;}static intacceptPacket(){ state = Wait ; xmTimeout = INITTO ; return sendFlush(ACK) ;}intsendCancel(){ return sendFlush(CAN) || sendFlush(CAN) ;} /* send one character, return nonzero on error */intsendFlush(char c){ /* first, flush input port */ /* TODO: caller provide a way to do this? */ /* TODO: caller provides flush if( ioctl(xmRfd, TCFLSH, TCIFLUSH) == -1 ) return XmErrSys ;*/ return sendChr(c) ;} /* send one character, return nonzero on error */intsendChr(char c){ /* TODO: caller provide character output func? */ outbyte(c); return 0; //return write(xmTfd, &c, 1) ==1 ? 0 : XmErrSys ;}/* send some character, return nonzero on error */intsendStr(char *str, int len){ /* TODO: caller provide character output func? */ INT32S i=0; for(i=0;i<len;i++) sendChr(*str++); return 0 ;}intcalcChecksum(char *ptr, int count){ register int csum = 0 ; while( --count >= 0 ) csum += (INT8U) *ptr++ ; return csum & 255 ;}INT32U receive(INT8U * BaseAddr){ TIMER timeout; INT32U done = FALSE ; INT8U i ; //INT32S len ; settimer(&timeout,xmTimeout*1000); xmodem1k = 0 ; done = XmodemRInit( ((INT8U*)BaseAddr), XmodemCrc) != 0 ;#ifdef COMMENT// xmodem1k = 1 ;// done = XmodemRInit("./", Ymodem) != 0 ;#endif /* COMMENT */ while(!done) { INT32U tmOut=FALSE; i=inbyte_time(xmTimeout*1000,&tmOut); if( tmOut==TRUE ) done = XmodemRTimeout() != 0 ; else { done = XmodemRRcv(i) != 0 ; } } if(pktLen == 128) return (packetCount<<7); else if(pktLen == 1024) return (packetCount<<10); else return (packetCount*pktLen); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -