Blame view

common/xyzModem.c 15.4 KB
83d290c56   Tom Rini   SPDX: Convert all...
1
  // SPDX-License-Identifier: eCos-2.0
cf48eb9ab   Wolfgang Denk   Some code cleanup
2
3
4
5
6
7
8
9
  /*
   *==========================================================================
   *
   *      xyzModem.c
   *
   *      RedBoot stream handler for xyzModem protocol
   *
   *==========================================================================
cf48eb9ab   Wolfgang Denk   Some code cleanup
10
11
12
13
14
15
16
17
18
19
20
21
22
23
   *#####DESCRIPTIONBEGIN####
   *
   * Author(s):    gthomas
   * Contributors: gthomas, tsmith, Yoshinori Sato
   * Date:         2000-07-14
   * Purpose:
   * Description:
   *
   * This code is part of RedBoot (tm).
   *
   *####DESCRIPTIONEND####
   *
   *==========================================================================
   */
f2841d377   Markus Klotzbuecher   Add support for y...
24
25
26
  #include <common.h>
  #include <xyzModem.h>
  #include <stdarg.h>
a740ee913   Philipp Tomsich   lib: merge CRC16-...
27
  #include <u-boot/crc.h>
a4773c555   Lokesh Vutla   xyz-modem: Fix ti...
28
  #include <watchdog.h>
f2841d377   Markus Klotzbuecher   Add support for y...
29

cf48eb9ab   Wolfgang Denk   Some code cleanup
30
  /* Assumption - run xyzModem protocol over the console port */
f2841d377   Markus Klotzbuecher   Add support for y...
31

cf48eb9ab   Wolfgang Denk   Some code cleanup
32
  /* Values magic to the protocol */
f2841d377   Markus Klotzbuecher   Add support for y...
33
34
35
36
37
38
39
  #define SOH 0x01
  #define STX 0x02
  #define EOT 0x04
  #define ACK 0x06
  #define BSP 0x08
  #define NAK 0x15
  #define CAN 0x18
7d0432c9e   Wolfgang Denk   Coding Style clea...
40
  #define EOF 0x1A		/* ^Z for DOS officionados */
f2841d377   Markus Klotzbuecher   Add support for y...
41

cf48eb9ab   Wolfgang Denk   Some code cleanup
42
  /* Data & state local to the protocol */
7d0432c9e   Wolfgang Denk   Coding Style clea...
43
44
  static struct
  {
7d0432c9e   Wolfgang Denk   Coding Style clea...
45
    int *__chan;
7d0432c9e   Wolfgang Denk   Coding Style clea...
46
47
48
49
50
51
    unsigned char pkt[1024], *bufp;
    unsigned char blk, cblk, crc1, crc2;
    unsigned char next_blk;	/* Expected block */
    int len, mode, total_retries;
    int total_SOH, total_STX, total_CAN;
    bool crc_mode, at_eof, tx_ack;
7d0432c9e   Wolfgang Denk   Coding Style clea...
52
    unsigned long file_length, read_length;
f2841d377   Markus Klotzbuecher   Add support for y...
53
  } xyz;
7d0432c9e   Wolfgang Denk   Coding Style clea...
54
  #define xyzModem_CHAR_TIMEOUT            2000	/* 2 seconds */
f2841d377   Markus Klotzbuecher   Add support for y...
55
56
  #define xyzModem_MAX_RETRIES             20
  #define xyzModem_MAX_RETRIES_WITH_CRC    10
7d0432c9e   Wolfgang Denk   Coding Style clea...
57
  #define xyzModem_CAN_COUNT                3	/* Wait for 3 CAN before quitting */
f2841d377   Markus Klotzbuecher   Add support for y...
58

f2841d377   Markus Klotzbuecher   Add support for y...
59
  typedef int cyg_int32;
199adb601   Kim Phillips   common/misc: spar...
60
  static int
7d0432c9e   Wolfgang Denk   Coding Style clea...
61
62
  CYGACC_COMM_IF_GETC_TIMEOUT (char chan, char *c)
  {
2c77c0d65   tomas.melin@vaisala.com   xyz-modem: Change...
63
64
  
    ulong now = get_timer(0);
a4773c555   Lokesh Vutla   xyz-modem: Fix ti...
65
    WATCHDOG_RESET();
2c77c0d65   tomas.melin@vaisala.com   xyz-modem: Change...
66
    while (!tstc ())
7d0432c9e   Wolfgang Denk   Coding Style clea...
67
      {
2c77c0d65   tomas.melin@vaisala.com   xyz-modem: Change...
68
69
        if (get_timer(now) > xyzModem_CHAR_TIMEOUT)
          break;
7d0432c9e   Wolfgang Denk   Coding Style clea...
70
71
72
73
74
75
76
      }
    if (tstc ())
      {
        *c = getc ();
        return 1;
      }
    return 0;
f2841d377   Markus Klotzbuecher   Add support for y...
77
  }
199adb601   Kim Phillips   common/misc: spar...
78
  static void
7d0432c9e   Wolfgang Denk   Coding Style clea...
79
80
81
  CYGACC_COMM_IF_PUTC (char x, char y)
  {
    putc (y);
f2841d377   Markus Klotzbuecher   Add support for y...
82
  }
cf48eb9ab   Wolfgang Denk   Some code cleanup
83
  /* Validate a hex character */
f2841d377   Markus Klotzbuecher   Add support for y...
84
  __inline__ static bool
7d0432c9e   Wolfgang Denk   Coding Style clea...
85
  _is_hex (char c)
f2841d377   Markus Klotzbuecher   Add support for y...
86
  {
7d0432c9e   Wolfgang Denk   Coding Style clea...
87
88
    return (((c >= '0') && (c <= '9')) ||
  	  ((c >= 'A') && (c <= 'F')) || ((c >= 'a') && (c <= 'f')));
f2841d377   Markus Klotzbuecher   Add support for y...
89
  }
cf48eb9ab   Wolfgang Denk   Some code cleanup
90
  /* Convert a single hex nibble */
f2841d377   Markus Klotzbuecher   Add support for y...
91
  __inline__ static int
7d0432c9e   Wolfgang Denk   Coding Style clea...
92
  _from_hex (char c)
f2841d377   Markus Klotzbuecher   Add support for y...
93
  {
7d0432c9e   Wolfgang Denk   Coding Style clea...
94
95
96
97
98
99
100
101
102
    int ret = 0;
  
    if ((c >= '0') && (c <= '9'))
      {
        ret = (c - '0');
      }
    else if ((c >= 'a') && (c <= 'f'))
      {
        ret = (c - 'a' + 0x0a);
f2841d377   Markus Klotzbuecher   Add support for y...
103
      }
7d0432c9e   Wolfgang Denk   Coding Style clea...
104
105
106
107
108
    else if ((c >= 'A') && (c <= 'F'))
      {
        ret = (c - 'A' + 0x0A);
      }
    return ret;
f2841d377   Markus Klotzbuecher   Add support for y...
109
  }
cf48eb9ab   Wolfgang Denk   Some code cleanup
110
  /* Convert a character to lower case */
f2841d377   Markus Klotzbuecher   Add support for y...
111
  __inline__ static char
7d0432c9e   Wolfgang Denk   Coding Style clea...
112
  _tolower (char c)
f2841d377   Markus Klotzbuecher   Add support for y...
113
  {
7d0432c9e   Wolfgang Denk   Coding Style clea...
114
115
116
    if ((c >= 'A') && (c <= 'Z'))
      {
        c = (c - 'A') + 'a';
f2841d377   Markus Klotzbuecher   Add support for y...
117
      }
7d0432c9e   Wolfgang Denk   Coding Style clea...
118
    return c;
f2841d377   Markus Klotzbuecher   Add support for y...
119
  }
cf48eb9ab   Wolfgang Denk   Some code cleanup
120
  /* Parse (scan) a number */
199adb601   Kim Phillips   common/misc: spar...
121
  static bool
7d0432c9e   Wolfgang Denk   Coding Style clea...
122
  parse_num (char *s, unsigned long *val, char **es, char *delim)
f2841d377   Markus Klotzbuecher   Add support for y...
123
  {
7d0432c9e   Wolfgang Denk   Coding Style clea...
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
    bool first = true;
    int radix = 10;
    char c;
    unsigned long result = 0;
    int digit;
  
    while (*s == ' ')
      s++;
    while (*s)
      {
        if (first && (s[0] == '0') && (_tolower (s[1]) == 'x'))
  	{
  	  radix = 16;
  	  s += 2;
  	}
        first = false;
        c = *s++;
        if (_is_hex (c) && ((digit = _from_hex (c)) < radix))
  	{
  	  /* Valid digit */
7d0432c9e   Wolfgang Denk   Coding Style clea...
144
  	  result = (result * radix) + digit;
7d0432c9e   Wolfgang Denk   Coding Style clea...
145
146
147
148
149
150
151
152
153
154
155
156
157
158
  	}
        else
  	{
  	  if (delim != (char *) 0)
  	    {
  	      /* See if this character is one of the delimiters */
  	      char *dp = delim;
  	      while (*dp && (c != *dp))
  		dp++;
  	      if (*dp)
  		break;		/* Found a good delimiter */
  	    }
  	  return false;		/* Malformatted number */
  	}
f2841d377   Markus Klotzbuecher   Add support for y...
159
      }
7d0432c9e   Wolfgang Denk   Coding Style clea...
160
161
162
163
    *val = result;
    if (es != (char **) 0)
      {
        *es = s;
f2841d377   Markus Klotzbuecher   Add support for y...
164
      }
7d0432c9e   Wolfgang Denk   Coding Style clea...
165
    return true;
f2841d377   Markus Klotzbuecher   Add support for y...
166
  }
f2841d377   Markus Klotzbuecher   Add support for y...
167

27084c03d   Simon Glass   spl: Allow tiny p...
168
  #if defined(DEBUG) && !CONFIG_IS_ENABLED(USE_TINY_PRINTF)
cf48eb9ab   Wolfgang Denk   Some code cleanup
169
170
171
  /*
   * Note: this debug setup works by storing the strings in a fixed buffer
   */
b09ece083   Alexandru Gagniuc   common/xyzModem.c...
172
173
174
  static char zm_debug_buf[8192];
  static char *zm_out = zm_debug_buf;
  static char *zm_out_start = zm_debug_buf;
f2841d377   Markus Klotzbuecher   Add support for y...
175

f2841d377   Markus Klotzbuecher   Add support for y...
176
  static int
23c648982   Heinrich Schuchardt   xyz-modem: va_sta...
177
  zm_dprintf(char *fmt, ...)
f2841d377   Markus Klotzbuecher   Add support for y...
178
  {
23c648982   Heinrich Schuchardt   xyz-modem: va_sta...
179
180
181
182
183
184
185
186
  	int len;
  	va_list args;
  
  	va_start(args, fmt);
  	len = diag_vsprintf(zm_out, fmt, args);
  	va_end(args);
  	zm_out += len;
  	return len;
f2841d377   Markus Klotzbuecher   Add support for y...
187
188
189
  }
  
  static void
7d0432c9e   Wolfgang Denk   Coding Style clea...
190
  zm_flush (void)
f2841d377   Markus Klotzbuecher   Add support for y...
191
  {
7d0432c9e   Wolfgang Denk   Coding Style clea...
192
    zm_out = zm_out_start;
f2841d377   Markus Klotzbuecher   Add support for y...
193
  }
f2841d377   Markus Klotzbuecher   Add support for y...
194
195
  
  static void
7d0432c9e   Wolfgang Denk   Coding Style clea...
196
  zm_dump_buf (void *buf, int len)
f2841d377   Markus Klotzbuecher   Add support for y...
197
  {
f2841d377   Markus Klotzbuecher   Add support for y...
198

f2841d377   Markus Klotzbuecher   Add support for y...
199
200
201
202
203
204
  }
  
  static unsigned char zm_buf[2048];
  static unsigned char *zm_bp;
  
  static void
7d0432c9e   Wolfgang Denk   Coding Style clea...
205
  zm_new (void)
f2841d377   Markus Klotzbuecher   Add support for y...
206
  {
7d0432c9e   Wolfgang Denk   Coding Style clea...
207
    zm_bp = zm_buf;
f2841d377   Markus Klotzbuecher   Add support for y...
208
209
210
  }
  
  static void
7d0432c9e   Wolfgang Denk   Coding Style clea...
211
  zm_save (unsigned char c)
f2841d377   Markus Klotzbuecher   Add support for y...
212
  {
7d0432c9e   Wolfgang Denk   Coding Style clea...
213
    *zm_bp++ = c;
f2841d377   Markus Klotzbuecher   Add support for y...
214
215
216
  }
  
  static void
7d0432c9e   Wolfgang Denk   Coding Style clea...
217
  zm_dump (int line)
f2841d377   Markus Klotzbuecher   Add support for y...
218
  {
7d0432c9e   Wolfgang Denk   Coding Style clea...
219
220
221
    zm_dprintf ("Packet at line: %d
  ", line);
    zm_dump_buf (zm_buf, zm_bp - zm_buf);
f2841d377   Markus Klotzbuecher   Add support for y...
222
223
224
225
226
227
  }
  
  #define ZM_DEBUG(x) x
  #else
  #define ZM_DEBUG(x)
  #endif
cf48eb9ab   Wolfgang Denk   Some code cleanup
228
  /* Wait for the line to go idle */
f2841d377   Markus Klotzbuecher   Add support for y...
229
  static void
7d0432c9e   Wolfgang Denk   Coding Style clea...
230
  xyzModem_flush (void)
f2841d377   Markus Klotzbuecher   Add support for y...
231
  {
7d0432c9e   Wolfgang Denk   Coding Style clea...
232
233
234
235
236
237
238
    int res;
    char c;
    while (true)
      {
        res = CYGACC_COMM_IF_GETC_TIMEOUT (*xyz.__chan, &c);
        if (!res)
  	return;
f2841d377   Markus Klotzbuecher   Add support for y...
239
240
241
242
      }
  }
  
  static int
7d0432c9e   Wolfgang Denk   Coding Style clea...
243
  xyzModem_get_hdr (void)
f2841d377   Markus Klotzbuecher   Add support for y...
244
  {
7d0432c9e   Wolfgang Denk   Coding Style clea...
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
    char c;
    int res;
    bool hdr_found = false;
    int i, can_total, hdr_chars;
    unsigned short cksum;
  
    ZM_DEBUG (zm_new ());
    /* Find the start of a header */
    can_total = 0;
    hdr_chars = 0;
  
    if (xyz.tx_ack)
      {
        CYGACC_COMM_IF_PUTC (*xyz.__chan, ACK);
        xyz.tx_ack = false;
f2841d377   Markus Klotzbuecher   Add support for y...
260
      }
7d0432c9e   Wolfgang Denk   Coding Style clea...
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
    while (!hdr_found)
      {
        res = CYGACC_COMM_IF_GETC_TIMEOUT (*xyz.__chan, &c);
        ZM_DEBUG (zm_save (c));
        if (res)
  	{
  	  hdr_chars++;
  	  switch (c)
  	    {
  	    case SOH:
  	      xyz.total_SOH++;
  	    case STX:
  	      if (c == STX)
  		xyz.total_STX++;
  	      hdr_found = true;
  	      break;
  	    case CAN:
  	      xyz.total_CAN++;
  	      ZM_DEBUG (zm_dump (__LINE__));
  	      if (++can_total == xyzModem_CAN_COUNT)
  		{
  		  return xyzModem_cancel;
  		}
  	      else
  		{
  		  /* Wait for multiple CAN to avoid early quits */
  		  break;
  		}
  	    case EOT:
  	      /* EOT only supported if no noise */
  	      if (hdr_chars == 1)
  		{
  		  CYGACC_COMM_IF_PUTC (*xyz.__chan, ACK);
  		  ZM_DEBUG (zm_dprintf ("ACK on EOT #%d
  ", __LINE__));
  		  ZM_DEBUG (zm_dump (__LINE__));
  		  return xyzModem_eof;
  		}
  	    default:
  	      /* Ignore, waiting for start of header */
  	      ;
  	    }
  	}
        else
  	{
  	  /* Data stream timed out */
  	  xyzModem_flush ();	/* Toss any current input */
  	  ZM_DEBUG (zm_dump (__LINE__));
  	  CYGACC_CALL_IF_DELAY_US ((cyg_int32) 250000);
  	  return xyzModem_timeout;
  	}
f2841d377   Markus Klotzbuecher   Add support for y...
312
      }
7d0432c9e   Wolfgang Denk   Coding Style clea...
313
314
315
316
317
318
319
    /* Header found, now read the data */
    res = CYGACC_COMM_IF_GETC_TIMEOUT (*xyz.__chan, (char *) &xyz.blk);
    ZM_DEBUG (zm_save (xyz.blk));
    if (!res)
      {
        ZM_DEBUG (zm_dump (__LINE__));
        return xyzModem_timeout;
f2841d377   Markus Klotzbuecher   Add support for y...
320
      }
7d0432c9e   Wolfgang Denk   Coding Style clea...
321
322
323
324
325
326
    res = CYGACC_COMM_IF_GETC_TIMEOUT (*xyz.__chan, (char *) &xyz.cblk);
    ZM_DEBUG (zm_save (xyz.cblk));
    if (!res)
      {
        ZM_DEBUG (zm_dump (__LINE__));
        return xyzModem_timeout;
f2841d377   Markus Klotzbuecher   Add support for y...
327
      }
7d0432c9e   Wolfgang Denk   Coding Style clea...
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
    xyz.len = (c == SOH) ? 128 : 1024;
    xyz.bufp = xyz.pkt;
    for (i = 0; i < xyz.len; i++)
      {
        res = CYGACC_COMM_IF_GETC_TIMEOUT (*xyz.__chan, &c);
        ZM_DEBUG (zm_save (c));
        if (res)
  	{
  	  xyz.pkt[i] = c;
  	}
        else
  	{
  	  ZM_DEBUG (zm_dump (__LINE__));
  	  return xyzModem_timeout;
  	}
f2841d377   Markus Klotzbuecher   Add support for y...
343
      }
7d0432c9e   Wolfgang Denk   Coding Style clea...
344
345
346
347
348
349
    res = CYGACC_COMM_IF_GETC_TIMEOUT (*xyz.__chan, (char *) &xyz.crc1);
    ZM_DEBUG (zm_save (xyz.crc1));
    if (!res)
      {
        ZM_DEBUG (zm_dump (__LINE__));
        return xyzModem_timeout;
f2841d377   Markus Klotzbuecher   Add support for y...
350
      }
7d0432c9e   Wolfgang Denk   Coding Style clea...
351
352
353
354
355
356
357
358
359
    if (xyz.crc_mode)
      {
        res = CYGACC_COMM_IF_GETC_TIMEOUT (*xyz.__chan, (char *) &xyz.crc2);
        ZM_DEBUG (zm_save (xyz.crc2));
        if (!res)
  	{
  	  ZM_DEBUG (zm_dump (__LINE__));
  	  return xyzModem_timeout;
  	}
f2841d377   Markus Klotzbuecher   Add support for y...
360
      }
7d0432c9e   Wolfgang Denk   Coding Style clea...
361
362
363
364
365
366
367
368
369
370
371
    ZM_DEBUG (zm_dump (__LINE__));
    /* Validate the message */
    if ((xyz.blk ^ xyz.cblk) != (unsigned char) 0xFF)
      {
        ZM_DEBUG (zm_dprintf
  		("Framing error - blk: %x/%x/%x
  ", xyz.blk, xyz.cblk,
  		 (xyz.blk ^ xyz.cblk)));
        ZM_DEBUG (zm_dump_buf (xyz.pkt, xyz.len));
        xyzModem_flush ();
        return xyzModem_frame;
f2841d377   Markus Klotzbuecher   Add support for y...
372
      }
7d0432c9e   Wolfgang Denk   Coding Style clea...
373
374
375
    /* Verify checksum/CRC */
    if (xyz.crc_mode)
      {
ecb57f69b   Stefan Roese   lib/crc16.c: Rena...
376
        cksum = crc16_ccitt(0, xyz.pkt, xyz.len);
7d0432c9e   Wolfgang Denk   Coding Style clea...
377
378
379
380
381
382
383
        if (cksum != ((xyz.crc1 << 8) | xyz.crc2))
  	{
  	  ZM_DEBUG (zm_dprintf ("CRC error - recvd: %02x%02x, computed: %x
  ",
  				xyz.crc1, xyz.crc2, cksum & 0xFFFF));
  	  return xyzModem_cksum;
  	}
f2841d377   Markus Klotzbuecher   Add support for y...
384
      }
7d0432c9e   Wolfgang Denk   Coding Style clea...
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
    else
      {
        cksum = 0;
        for (i = 0; i < xyz.len; i++)
  	{
  	  cksum += xyz.pkt[i];
  	}
        if (xyz.crc1 != (cksum & 0xFF))
  	{
  	  ZM_DEBUG (zm_dprintf
  		    ("Checksum error - recvd: %x, computed: %x
  ", xyz.crc1,
  		     cksum & 0xFF));
  	  return xyzModem_cksum;
  	}
      }
    /* If we get here, the message passes [structural] muster */
    return 0;
f2841d377   Markus Klotzbuecher   Add support for y...
403
  }
cf48eb9ab   Wolfgang Denk   Some code cleanup
404
  int
7d0432c9e   Wolfgang Denk   Coding Style clea...
405
  xyzModem_stream_open (connection_info_t * info, int *err)
f2841d377   Markus Klotzbuecher   Add support for y...
406
  {
7d0432c9e   Wolfgang Denk   Coding Style clea...
407
408
409
    int stat = 0;
    int retries = xyzModem_MAX_RETRIES;
    int crc_retries = xyzModem_MAX_RETRIES_WITH_CRC;
f2841d377   Markus Klotzbuecher   Add support for y...
410

cf48eb9ab   Wolfgang Denk   Some code cleanup
411
  /*    ZM_DEBUG(zm_out = zm_out_start); */
f2841d377   Markus Klotzbuecher   Add support for y...
412
  #ifdef xyzModem_zmodem
7d0432c9e   Wolfgang Denk   Coding Style clea...
413
414
415
416
    if (info->mode == xyzModem_zmodem)
      {
        *err = xyzModem_noZmodem;
        return -1;
f2841d377   Markus Klotzbuecher   Add support for y...
417
418
      }
  #endif
cf48eb9ab   Wolfgang Denk   Some code cleanup
419
  /* TODO: CHECK ! */
2a2ed845c   Kim Phillips   common: fix 'dumm...
420
    int dummy = 0;
7d0432c9e   Wolfgang Denk   Coding Style clea...
421
    xyz.__chan = &dummy;
7d0432c9e   Wolfgang Denk   Coding Style clea...
422
423
424
425
426
427
428
429
430
    xyz.len = 0;
    xyz.crc_mode = true;
    xyz.at_eof = false;
    xyz.tx_ack = false;
    xyz.mode = info->mode;
    xyz.total_retries = 0;
    xyz.total_SOH = 0;
    xyz.total_STX = 0;
    xyz.total_CAN = 0;
7d0432c9e   Wolfgang Denk   Coding Style clea...
431
432
    xyz.read_length = 0;
    xyz.file_length = 0;
cf48eb9ab   Wolfgang Denk   Some code cleanup
433

7d0432c9e   Wolfgang Denk   Coding Style clea...
434
    CYGACC_COMM_IF_PUTC (*xyz.__chan, (xyz.crc_mode ? 'C' : NAK));
f2841d377   Markus Klotzbuecher   Add support for y...
435

7d0432c9e   Wolfgang Denk   Coding Style clea...
436
437
438
439
440
    if (xyz.mode == xyzModem_xmodem)
      {
        /* X-modem doesn't have an information header - exit here */
        xyz.next_blk = 1;
        return 0;
f2841d377   Markus Klotzbuecher   Add support for y...
441
      }
7d0432c9e   Wolfgang Denk   Coding Style clea...
442
443
444
445
446
447
448
449
    while (retries-- > 0)
      {
        stat = xyzModem_get_hdr ();
        if (stat == 0)
  	{
  	  /* Y-modem file information header */
  	  if (xyz.blk == 0)
  	    {
7d0432c9e   Wolfgang Denk   Coding Style clea...
450
451
452
453
  	      /* skip filename */
  	      while (*xyz.bufp++);
  	      /* get the length */
  	      parse_num ((char *) xyz.bufp, &xyz.file_length, NULL, " ");
7d0432c9e   Wolfgang Denk   Coding Style clea...
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
  	      /* The rest of the file name data block quietly discarded */
  	      xyz.tx_ack = true;
  	    }
  	  xyz.next_blk = 1;
  	  xyz.len = 0;
  	  return 0;
  	}
        else if (stat == xyzModem_timeout)
  	{
  	  if (--crc_retries <= 0)
  	    xyz.crc_mode = false;
  	  CYGACC_CALL_IF_DELAY_US (5 * 100000);	/* Extra delay for startup */
  	  CYGACC_COMM_IF_PUTC (*xyz.__chan, (xyz.crc_mode ? 'C' : NAK));
  	  xyz.total_retries++;
  	  ZM_DEBUG (zm_dprintf ("NAK (%d)
  ", __LINE__));
  	}
        if (stat == xyzModem_cancel)
  	{
  	  break;
  	}
f2841d377   Markus Klotzbuecher   Add support for y...
475
      }
7d0432c9e   Wolfgang Denk   Coding Style clea...
476
477
478
    *err = stat;
    ZM_DEBUG (zm_flush ());
    return -1;
f2841d377   Markus Klotzbuecher   Add support for y...
479
  }
cf48eb9ab   Wolfgang Denk   Some code cleanup
480
  int
7d0432c9e   Wolfgang Denk   Coding Style clea...
481
  xyzModem_stream_read (char *buf, int size, int *err)
f2841d377   Markus Klotzbuecher   Add support for y...
482
  {
7d0432c9e   Wolfgang Denk   Coding Style clea...
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
    int stat, total, len;
    int retries;
  
    total = 0;
    stat = xyzModem_cancel;
    /* Try and get 'size' bytes into the buffer */
    while (!xyz.at_eof && (size > 0))
      {
        if (xyz.len == 0)
  	{
  	  retries = xyzModem_MAX_RETRIES;
  	  while (retries-- > 0)
  	    {
  	      stat = xyzModem_get_hdr ();
  	      if (stat == 0)
  		{
  		  if (xyz.blk == xyz.next_blk)
  		    {
  		      xyz.tx_ack = true;
  		      ZM_DEBUG (zm_dprintf
  				("ACK block %d (%d)
  ", xyz.blk, __LINE__));
  		      xyz.next_blk = (xyz.next_blk + 1) & 0xFF;
f2841d377   Markus Klotzbuecher   Add support for y...
506

7d0432c9e   Wolfgang Denk   Coding Style clea...
507
508
  		      if (xyz.mode == xyzModem_xmodem || xyz.file_length == 0)
  			{
7d0432c9e   Wolfgang Denk   Coding Style clea...
509
510
511
512
513
514
515
516
517
518
519
520
521
  			  /* Data blocks can be padded with ^Z (EOF) characters */
  			  /* This code tries to detect and remove them */
  			  if ((xyz.bufp[xyz.len - 1] == EOF) &&
  			      (xyz.bufp[xyz.len - 2] == EOF) &&
  			      (xyz.bufp[xyz.len - 3] == EOF))
  			    {
  			      while (xyz.len
  				     && (xyz.bufp[xyz.len - 1] == EOF))
  				{
  				  xyz.len--;
  				}
  			    }
  			}
f2841d377   Markus Klotzbuecher   Add support for y...
522

7d0432c9e   Wolfgang Denk   Coding Style clea...
523
524
525
526
527
528
529
530
531
532
533
534
535
536
  		      /*
  		       * See if accumulated length exceeds that of the file.
  		       * If so, reduce size (i.e., cut out pad bytes)
  		       * Only do this for Y-modem (and Z-modem should it ever
  		       * be supported since it can fall back to Y-modem mode).
  		       */
  		      if (xyz.mode != xyzModem_xmodem && 0 != xyz.file_length)
  			{
  			  xyz.read_length += xyz.len;
  			  if (xyz.read_length > xyz.file_length)
  			    {
  			      xyz.len -= (xyz.read_length - xyz.file_length);
  			    }
  			}
7d0432c9e   Wolfgang Denk   Coding Style clea...
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
  		      break;
  		    }
  		  else if (xyz.blk == ((xyz.next_blk - 1) & 0xFF))
  		    {
  		      /* Just re-ACK this so sender will get on with it */
  		      CYGACC_COMM_IF_PUTC (*xyz.__chan, ACK);
  		      continue;	/* Need new header */
  		    }
  		  else
  		    {
  		      stat = xyzModem_sequence;
  		    }
  		}
  	      if (stat == xyzModem_cancel)
  		{
  		  break;
  		}
  	      if (stat == xyzModem_eof)
  		{
  		  CYGACC_COMM_IF_PUTC (*xyz.__chan, ACK);
  		  ZM_DEBUG (zm_dprintf ("ACK (%d)
  ", __LINE__));
  		  if (xyz.mode == xyzModem_ymodem)
  		    {
  		      CYGACC_COMM_IF_PUTC (*xyz.__chan,
  					   (xyz.crc_mode ? 'C' : NAK));
  		      xyz.total_retries++;
  		      ZM_DEBUG (zm_dprintf ("Reading Final Header
  "));
  		      stat = xyzModem_get_hdr ();
  		      CYGACC_COMM_IF_PUTC (*xyz.__chan, ACK);
  		      ZM_DEBUG (zm_dprintf ("FINAL ACK (%d)
  ", __LINE__));
  		    }
  		  xyz.at_eof = true;
  		  break;
  		}
  	      CYGACC_COMM_IF_PUTC (*xyz.__chan, (xyz.crc_mode ? 'C' : NAK));
  	      xyz.total_retries++;
  	      ZM_DEBUG (zm_dprintf ("NAK (%d)
  ", __LINE__));
  	    }
  	  if (stat < 0)
  	    {
  	      *err = stat;
  	      xyz.len = -1;
  	      return total;
  	    }
  	}
        /* Don't "read" data from the EOF protocol package */
        if (!xyz.at_eof)
  	{
  	  len = xyz.len;
  	  if (size < len)
  	    len = size;
  	  memcpy (buf, xyz.bufp, len);
  	  size -= len;
  	  buf += len;
  	  total += len;
  	  xyz.len -= len;
  	  xyz.bufp += len;
  	}
f2841d377   Markus Klotzbuecher   Add support for y...
599
      }
7d0432c9e   Wolfgang Denk   Coding Style clea...
600
    return total;
f2841d377   Markus Klotzbuecher   Add support for y...
601
602
603
  }
  
  void
7d0432c9e   Wolfgang Denk   Coding Style clea...
604
  xyzModem_stream_close (int *err)
f2841d377   Markus Klotzbuecher   Add support for y...
605
  {
7d0432c9e   Wolfgang Denk   Coding Style clea...
606
607
608
609
610
611
    diag_printf
      ("xyzModem - %s mode, %d(SOH)/%d(STX)/%d(CAN) packets, %d retries
  ",
       xyz.crc_mode ? "CRC" : "Cksum", xyz.total_SOH, xyz.total_STX,
       xyz.total_CAN, xyz.total_retries);
    ZM_DEBUG (zm_flush ());
f2841d377   Markus Klotzbuecher   Add support for y...
612
  }
cf48eb9ab   Wolfgang Denk   Some code cleanup
613
614
  /* Need to be able to clean out the input buffer, so have to take the */
  /* getc */
7d0432c9e   Wolfgang Denk   Coding Style clea...
615
616
  void
  xyzModem_stream_terminate (bool abort, int (*getc) (void))
f2841d377   Markus Klotzbuecher   Add support for y...
617
618
  {
    int c;
7d0432c9e   Wolfgang Denk   Coding Style clea...
619
620
621
622
623
624
    if (abort)
      {
        ZM_DEBUG (zm_dprintf ("!!!! TRANSFER ABORT !!!!
  "));
        switch (xyz.mode)
  	{
f2841d377   Markus Klotzbuecher   Add support for y...
625
626
  	case xyzModem_xmodem:
  	case xyzModem_ymodem:
cf48eb9ab   Wolfgang Denk   Some code cleanup
627
628
  	  /* The X/YMODEM Spec seems to suggest that multiple CAN followed by an equal */
  	  /* number of Backspaces is a friendly way to get the other end to abort. */
7d0432c9e   Wolfgang Denk   Coding Style clea...
629
630
631
632
633
634
635
636
  	  CYGACC_COMM_IF_PUTC (*xyz.__chan, CAN);
  	  CYGACC_COMM_IF_PUTC (*xyz.__chan, CAN);
  	  CYGACC_COMM_IF_PUTC (*xyz.__chan, CAN);
  	  CYGACC_COMM_IF_PUTC (*xyz.__chan, CAN);
  	  CYGACC_COMM_IF_PUTC (*xyz.__chan, BSP);
  	  CYGACC_COMM_IF_PUTC (*xyz.__chan, BSP);
  	  CYGACC_COMM_IF_PUTC (*xyz.__chan, BSP);
  	  CYGACC_COMM_IF_PUTC (*xyz.__chan, BSP);
cf48eb9ab   Wolfgang Denk   Some code cleanup
637
  	  /* Now consume the rest of what's waiting on the line. */
7d0432c9e   Wolfgang Denk   Coding Style clea...
638
639
640
641
642
  	  ZM_DEBUG (zm_dprintf ("Flushing serial line.
  "));
  	  xyzModem_flush ();
  	  xyz.at_eof = true;
  	  break;
f2841d377   Markus Klotzbuecher   Add support for y...
643
644
  #ifdef xyzModem_zmodem
  	case xyzModem_zmodem:
cf48eb9ab   Wolfgang Denk   Some code cleanup
645
  	  /* Might support it some day I suppose. */
f2841d377   Markus Klotzbuecher   Add support for y...
646
  #endif
7d0432c9e   Wolfgang Denk   Coding Style clea...
647
648
649
650
651
652
653
  	  break;
  	}
      }
    else
      {
        ZM_DEBUG (zm_dprintf ("Engaging cleanup mode...
  "));
cf48eb9ab   Wolfgang Denk   Some code cleanup
654
655
        /*
         * Consume any trailing crap left in the inbuffer from
162630879   Mike Williams   cleanup: Fix typo...
656
         * previous received blocks. Since very few files are an exact multiple
cf48eb9ab   Wolfgang Denk   Some code cleanup
657
658
659
         * of the transfer block size, there will almost always be some gunk here.
         * If we don't eat it now, RedBoot will think the user typed it.
         */
7d0432c9e   Wolfgang Denk   Coding Style clea...
660
661
        ZM_DEBUG (zm_dprintf ("Trailing gunk:
  "));
e153b13c8   Jeroen Hofstee   common/xyzModem.c...
662
663
        while ((c = (*getc) ()) > -1)
          ;
7d0432c9e   Wolfgang Denk   Coding Style clea...
664
665
        ZM_DEBUG (zm_dprintf ("
  "));
cf48eb9ab   Wolfgang Denk   Some code cleanup
666
667
668
669
670
        /*
         * Make a small delay to give terminal programs like minicom
         * time to get control again after their file transfer program
         * exits.
         */
7d0432c9e   Wolfgang Denk   Coding Style clea...
671
672
        CYGACC_CALL_IF_DELAY_US ((cyg_int32) 250000);
      }
f2841d377   Markus Klotzbuecher   Add support for y...
673
674
675
  }
  
  char *
7d0432c9e   Wolfgang Denk   Coding Style clea...
676
  xyzModem_error (int err)
f2841d377   Markus Klotzbuecher   Add support for y...
677
  {
7d0432c9e   Wolfgang Denk   Coding Style clea...
678
679
    switch (err)
      {
f2841d377   Markus Klotzbuecher   Add support for y...
680
      case xyzModem_access:
7d0432c9e   Wolfgang Denk   Coding Style clea...
681
682
        return "Can't access file";
        break;
f2841d377   Markus Klotzbuecher   Add support for y...
683
      case xyzModem_noZmodem:
7d0432c9e   Wolfgang Denk   Coding Style clea...
684
685
        return "Sorry, zModem not available yet";
        break;
f2841d377   Markus Klotzbuecher   Add support for y...
686
      case xyzModem_timeout:
7d0432c9e   Wolfgang Denk   Coding Style clea...
687
688
        return "Timed out";
        break;
f2841d377   Markus Klotzbuecher   Add support for y...
689
      case xyzModem_eof:
7d0432c9e   Wolfgang Denk   Coding Style clea...
690
691
        return "End of file";
        break;
f2841d377   Markus Klotzbuecher   Add support for y...
692
      case xyzModem_cancel:
7d0432c9e   Wolfgang Denk   Coding Style clea...
693
694
        return "Cancelled";
        break;
f2841d377   Markus Klotzbuecher   Add support for y...
695
      case xyzModem_frame:
7d0432c9e   Wolfgang Denk   Coding Style clea...
696
697
        return "Invalid framing";
        break;
f2841d377   Markus Klotzbuecher   Add support for y...
698
      case xyzModem_cksum:
7d0432c9e   Wolfgang Denk   Coding Style clea...
699
700
        return "CRC/checksum error";
        break;
f2841d377   Markus Klotzbuecher   Add support for y...
701
      case xyzModem_sequence:
7d0432c9e   Wolfgang Denk   Coding Style clea...
702
703
        return "Block sequence error";
        break;
f2841d377   Markus Klotzbuecher   Add support for y...
704
      default:
7d0432c9e   Wolfgang Denk   Coding Style clea...
705
706
        return "Unknown error";
        break;
f2841d377   Markus Klotzbuecher   Add support for y...
707
708
      }
  }
cf48eb9ab   Wolfgang Denk   Some code cleanup
709
710
711
  /*
   * RedBoot interface
   */