00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include <string.h>
00019 #include "rprintf.h"
00020 #include "timer.h"
00021
00022 #include "xmodem.h"
00023
00024 #ifndef XMODEM_BUFFER_SIZE
00025 #define XMODEM_BUFFER_SIZE 1024
00026
00027 #endif
00028
00029
00030 static void (*xmodemOut)(unsigned char c);
00031 static int (*xmodemIn)(void);
00032
00033 void xmodemInit(void (*sendbyte_func)(unsigned char c), int (*getbyte_func)(void))
00034 {
00035
00036 xmodemOut = sendbyte_func;
00037 xmodemIn = getbyte_func;
00038 }
00039
00040 long xmodemReceive( int (*write)(unsigned char* buffer, int size) )
00041 {
00042
00043
00044
00045
00046 unsigned char xmbuf[XMODEM_BUFFER_SIZE+6];
00047 unsigned char seqnum=1;
00048 unsigned short pktsize=128;
00049 unsigned char response='C';
00050 char retry=XMODEM_RETRY_LIMIT;
00051 unsigned char crcflag=0;
00052 unsigned long totalbytes=0;
00053 int i,c;
00054
00055 while(retry > 0)
00056 {
00057
00058 xmodemOut(response);
00059
00060 if( (c = xmodemInTime(XMODEM_TIMEOUT_DELAY)) >= 0)
00061 {
00062 switch(c)
00063 {
00064 case SOH:
00065 pktsize = 128;
00066 break;
00067 #if(XMODEM_BUFFER_SIZE>=1024)
00068 case STX:
00069 pktsize = 1024;
00070 break;
00071 #endif
00072 case EOT:
00073 xmodemInFlush();
00074 xmodemOut(ACK);
00075
00076 return totalbytes;
00077 case CAN:
00078 if((c = xmodemInTime(XMODEM_TIMEOUT_DELAY)) == CAN)
00079 {
00080 xmodemInFlush();
00081 xmodemOut(ACK);
00082
00083 return XMODEM_ERROR_REMOTECANCEL;
00084 }
00085 default:
00086 break;
00087 }
00088 }
00089 else
00090 {
00091
00092
00093 retry--;
00094
00095 continue;
00096 }
00097
00098
00099 if(response == 'C') crcflag = 1;
00100
00101 xmbuf[0] = c;
00102
00103 for(i=0; i<(pktsize+crcflag+4-1); i++)
00104 {
00105 if((c = xmodemInTime(XMODEM_TIMEOUT_DELAY)) >= 0)
00106 {
00107 xmbuf[1+i] = c;
00108 }
00109 else
00110 {
00111
00112 retry--;
00113 xmodemInFlush();
00114 response = NAK;
00115 break;
00116 }
00117 }
00118
00119 if(i<(pktsize+crcflag+4-1))
00120 continue;
00121
00122
00123
00124 if( (xmbuf[1] == (unsigned char)(~xmbuf[2])) &&
00125 xmodemCrcCheck(crcflag, &xmbuf[3], pktsize) )
00126 {
00127
00128 if(xmbuf[1] == seqnum)
00129 {
00130
00131 write(&xmbuf[3], pktsize);
00132 totalbytes += pktsize;
00133
00134 seqnum++;
00135
00136 retry = XMODEM_RETRY_LIMIT;
00137
00138 response = ACK;
00139 continue;
00140 }
00141 else if(xmbuf[1] == (unsigned char)(seqnum-1))
00142 {
00143
00144
00145 response = ACK;
00146 continue;
00147 }
00148 else
00149 {
00150
00151
00152 xmodemInFlush();
00153 xmodemOut(CAN);
00154 xmodemOut(CAN);
00155 xmodemOut(CAN);
00156 return XMODEM_ERROR_OUTOFSYNC;
00157 }
00158 }
00159 else
00160 {
00161
00162
00163 retry--;
00164 xmodemInFlush();
00165 response = NAK;
00166 continue;
00167 }
00168 }
00169
00170
00171 xmodemInFlush();
00172 xmodemOut(CAN);
00173 xmodemOut(CAN);
00174 xmodemOut(CAN);
00175 return XMODEM_ERROR_RETRYEXCEED;
00176 }
00177
00178
00179 long xmodemTransmit( int (*read)(unsigned char* buffer, int size) )
00180 {
00181 return 0;
00182 }
00183
00184 uint16_t crc_xmodem_update(uint16_t crc, uint8_t data)
00185 {
00186 int i;
00187
00188 crc = crc ^ ((uint16_t)data << 8);
00189 for (i=0; i<8; i++)
00190 {
00191 if(crc & 0x8000)
00192 crc = (crc << 1) ^ 0x1021;
00193 else
00194 crc <<= 1;
00195 }
00196
00197 return crc;
00198 }
00199
00200 int xmodemCrcCheck(int crcflag, const unsigned char *buffer, int size)
00201 {
00202
00203
00204
00205 if(crcflag)
00206 {
00207 unsigned short crc=0;
00208 unsigned short pktcrc = (buffer[size]<<8)+buffer[size+1];
00209
00210 while(size--)
00211 crc = crc_xmodem_update(crc, *buffer++);
00212
00213 if(crc == pktcrc)
00214 return 1;
00215 }
00216 else
00217 {
00218 int i;
00219 unsigned char cksum = 0;
00220
00221 for(i=0; i<size; ++i)
00222 {
00223 cksum += buffer[i];
00224 }
00225
00226 if(cksum == buffer[size])
00227 return 1;
00228 }
00229
00230 return 0;
00231 }
00232
00233
00234 int xmodemInTime(unsigned short timeout)
00235 {
00236 int c=-1;
00237
00238 while( (timeout--) && ((c=xmodemIn()) < 0) )
00239 timerPause(1);
00240
00241 return c;
00242 }
00243
00244 void xmodemInFlush(void)
00245 {
00246 while(xmodemInTime(XMODEM_TIMEOUT_DELAY) >= 0);
00247 }