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
00025 #define XMODEM_BUFFER_SIZE 1024
00026
00027
00028 static void (*xmodemOut)(unsigned char c);
00029 static int (*xmodemIn)(void);
00030
00031 void xmodemInit(void (*sendbyte_func)(unsigned char c), int (*getbyte_func)(void))
00032 {
00033
00034 xmodemOut = sendbyte_func;
00035 xmodemIn = getbyte_func;
00036 }
00037
00038 long xmodemReceive( int (*write)(unsigned char* buffer, int size) )
00039 {
00040
00041
00042
00043
00044 unsigned char xmbuf[XMODEM_BUFFER_SIZE+6];
00045 unsigned char seqnum=1;
00046 unsigned short pktsize=128;
00047 unsigned char response='C';
00048 char retry=XMODEM_RETRY_LIMIT;
00049 unsigned char crcflag=0;
00050 unsigned long totalbytes=0;
00051 int i,c;
00052
00053 while(retry > 0)
00054 {
00055
00056 xmodemOut(response);
00057
00058 if( (c = xmodemInTime(XMODEM_TIMEOUT_DELAY)) >= 0)
00059 {
00060 switch(c)
00061 {
00062 case SOH:
00063 pktsize = 128;
00064 break;
00065 #if(XMODEM_BUFFER_SIZE>=1024)
00066 case STX:
00067 pktsize = 1024;
00068 break;
00069 #endif
00070 case EOT:
00071 xmodemInFlush();
00072 xmodemOut(ACK);
00073
00074 return totalbytes;
00075 case CAN:
00076 if((c = xmodemInTime(XMODEM_TIMEOUT_DELAY)) == CAN)
00077 {
00078 xmodemInFlush();
00079 xmodemOut(ACK);
00080
00081 return XMODEM_ERROR_REMOTECANCEL;
00082 }
00083 default:
00084 break;
00085 }
00086 }
00087 else
00088 {
00089
00090
00091 retry--;
00092
00093 continue;
00094 }
00095
00096
00097 if(response == 'C') crcflag = 1;
00098
00099 xmbuf[0] = c;
00100
00101 for(i=0; i<(pktsize+crcflag+4-1); i++)
00102 {
00103 if((c = xmodemInTime(XMODEM_TIMEOUT_DELAY)) >= 0)
00104 {
00105 xmbuf[1+i] = c;
00106 }
00107 else
00108 {
00109
00110 retry--;
00111 xmodemInFlush();
00112 response = NAK;
00113 break;
00114 }
00115 }
00116
00117 if(i<(pktsize+crcflag+4-1))
00118 continue;
00119
00120
00121
00122 if( (xmbuf[1] == (unsigned char)(~xmbuf[2])) &&
00123 xmodemCrcCheck(crcflag, &xmbuf[3], pktsize) )
00124 {
00125
00126 if(xmbuf[1] == seqnum)
00127 {
00128
00129 write(&xmbuf[3], pktsize);
00130
00131 totalbytes += pktsize;
00132
00133 seqnum++;
00134
00135 retry = XMODEM_RETRY_LIMIT;
00136
00137 response = ACK;
00138 continue;
00139 }
00140 else if(xmbuf[1] == (unsigned char)(seqnum-1))
00141 {
00142
00143
00144 response = ACK;
00145 continue;
00146 }
00147 else
00148 {
00149
00150
00151 xmodemInFlush();
00152 xmodemOut(CAN);
00153 xmodemOut(CAN);
00154 xmodemOut(CAN);
00155 return XMODEM_ERROR_OUTOFSYNC;
00156 }
00157 }
00158 else
00159 {
00160
00161
00162 retry--;
00163 xmodemInFlush();
00164 response = NAK;
00165 continue;
00166 }
00167 }
00168
00169
00170 xmodemInFlush();
00171 xmodemOut(CAN);
00172 xmodemOut(CAN);
00173 xmodemOut(CAN);
00174 return XMODEM_ERROR_RETRYEXCEED;
00175 }
00176
00177
00178 long xmodemTransmit( int (*read)(unsigned char* buffer, int size) )
00179 {
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 }