2 Copyright 2001, 2002 Georges Menie (www.menie.org)
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU Lesser General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU Lesser General Public License for more details.
14 You should have received a copy of the GNU Lesser General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 /* this code needs standard functions memcpy() and memset()
20 and input/output functions _inbyte() and _outbyte().
22 the prototypes of the input/output functions are:
23 int _inbyte(unsigned short timeout); // msec timeout
43 static int check(int crc
, const unsigned char *buf
, int sz
)
46 unsigned short crc
= crc16_ccitt(buf
, sz
);
47 unsigned short tcrc
= (buf
[sz
]<<8)+buf
[sz
+1];
52 unsigned char cks
= 0;
53 for (i
= 0; i
< sz
; ++i
) {
63 static void flushinput(void)
65 while (_inbyte(((DLY_1S
)*3)>>1) >= 0)
69 int xmodemReceive(unsigned char *dest
, int destsz
)
71 unsigned char xbuff
[1030]; /* 1024 for XModem 1k + 3 head chars + 2 crc + nul */
74 unsigned char trychar
= 'C';
75 unsigned char packetno
= 1;
77 int retry
, retrans
= MAXRETRANS
;
80 for ( retry
= 0; retry
< 16; ++retry
) {
81 if (trychar
) _outbyte(trychar
);
82 if ((c
= _inbyte((DLY_1S
)<<1)) >= 0) {
93 return len
; /* normal end */
95 if ((c
= _inbyte(DLY_1S
)) == CAN
) {
98 return -1; /* canceled by remote */
106 if (trychar
== 'C') { trychar
= NAK
; continue; }
111 return -2; /* sync error */
114 if (trychar
== 'C') crc
= 1;
118 for (i
= 0; i
< (bufsz
+(crc
?1:0)+3); ++i
) {
119 if ((c
= _inbyte(DLY_1S
)) < 0) goto reject
;
123 if (xbuff
[1] == (unsigned char)(~xbuff
[2]) &&
124 (xbuff
[1] == packetno
|| xbuff
[1] == (unsigned char)packetno
-1) &&
125 check(crc
, &xbuff
[3], bufsz
)) {
126 if (xbuff
[1] == packetno
) {
127 register int count
= destsz
- len
;
128 if (count
> bufsz
) count
= bufsz
;
130 memcpy(&dest
[len
], &xbuff
[3], count
);
134 retrans
= MAXRETRANS
+1;
136 if (--retrans
<= 0) {
141 return -3; /* too many retry error */
153 int xmodemTransmit(unsigned char *src
, int srcsz
)
155 unsigned char xbuff
[1030]; /* 1024 for XModem 1k + 3 head chars + 2 crc + nul */
157 unsigned char packetno
= 1;
162 for ( retry
= 0; retry
< 16; ++retry
) {
163 if ((c
= _inbyte((DLY_1S
)<<1)) >= 0) {
172 if ((c
= _inbyte(DLY_1S
)) == CAN
) {
175 return -1; /* canceled by remote */
187 return -2; /* no sync */
191 xbuff
[0] = SOH
; bufsz
= 128;
193 xbuff
[2] = ~packetno
;
195 if (c
> bufsz
) c
= bufsz
;
197 memset(&xbuff
[3], 0, bufsz
);
201 memcpy(&xbuff
[3], &src
[len
], c
);
202 if (c
< bufsz
) xbuff
[3+c
] = CTRLZ
;
205 unsigned short ccrc
= crc16_ccitt(&xbuff
[3], bufsz
);
206 xbuff
[bufsz
+3] = (ccrc
>>8) & 0xFF;
207 xbuff
[bufsz
+4] = ccrc
& 0xFF;
209 unsigned char ccks
= 0;
210 for (i
= 3; i
< bufsz
+3; ++i
) {
213 xbuff
[bufsz
+3] = ccks
;
215 for (retry
= 0; retry
< MAXRETRANS
; ++retry
) {
216 for (i
= 0; i
< bufsz
+4+(crc
?1:0); ++i
) {
219 if ((c
= _inbyte(DLY_1S
)) >= 0 ) {
226 if ((c
= _inbyte(DLY_1S
)) == CAN
) {
229 return -1; /* canceled by remote */
242 return -4; /* xmit error */
244 for (retry
= 0; retry
< 10; ++retry
) {
246 if ((c
= _inbyte((DLY_1S
)<<1)) == ACK
) break;
249 return (c
== ACK
)?len
:-5;
256 #ifdef TEST_XMODEM_RECEIVE
261 printf("Send data using the xmodem protocol from your terminal emulator now...\n");
262 /* the following should be changed for your environment:
263 0x30000 is the download address,
264 65536 is the maximum size to be written at this address
266 st
= xmodemReceive((char *)0x30000, 65536);
268 printf("Xmodem receive error: status: %d\n", st
);
270 printf("Xmodem successfully received %d bytes\n", st
);
276 #ifdef TEST_XMODEM_SEND
281 printf("Prepare your terminal emulator to receive data now...\n");
282 /* the following should be changed for your environment:
283 0x30000 is the download address,
284 12000 is the maximum size to be send from this address
286 st
= xmodemTransmit((char *)0x30000, 12000);
288 printf("Xmodem transmit error: status: %d\n", st
);
290 printf("Xmodem successfully transmitted %d bytes\n", st
);