/* XMODEM support for GDB, the GNU debugger.
   Copyright 1995 Free Software Foundation, Inc.

   This file is part of GDB.

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place - Suite 330,
   Boston, MA 02111-1307, USA.  */

#include "defs.h"
#include "serial.h"
#include "target.h"
#include "xmodem.h"

/* These definitions are for xmodem protocol. */

#define SOH	0x01
#define STX	0x02
#define ACK	0x06
#define NAK	0x15
#define EOT	0x04
#define CANCEL	0x18

static int blknum;		/* XMODEM block number */
static int crcflag;		/* Sez we are using CRC's instead of cksums */

static int
readchar (desc, timeout)
     serial_t desc;
     int timeout;
{
  int c;

  c = SERIAL_READCHAR (desc, timeout);

  if (remote_debug > 0)
    fputc_unfiltered (c, gdb_stdlog);

  if (c >= 0)
    return c;

  if (c == SERIAL_TIMEOUT)
    error ("Timeout reading from remote system.");

  perror_with_name ("xmodem.c:readchar()");
}

#define CRC16 0x1021		/* Generator polynomial (X^16 + X^12 + X^5 + 1) */

static unsigned short *crctab;

/* Call this to init the fast CRC-16 calculation table.  */

static void
crcinit ()
{
  static int crctab_inited = 0;
  int val;

  if (crctab_inited == 1)
    return;

  crctab = xmalloc (256 * sizeof (short));

  for (val = 0; val <= 255; val++)
    {
      int i;
      unsigned int crc;

      crc = val << 8;

      for (i = 0; i < 8; ++i)
	{
	  crc <<= 1;

	  if (crc & 0x10000)
	    crc ^= CRC16;
	}

      crctab[val] = crc;
    }

  crctab_inited = 1;
}

/* Calculate a CRC-16 for the LEN byte message pointed at by P.  */

static unsigned short
docrc (p, len)
     unsigned char *p;
     int len;
{
  unsigned short crc = 0;

  while (len-- > 0)
    crc = (crc << 8) ^ crctab[(crc >> 8) ^ *p++];

  return crc;
}

/* Start up the transmit process.  Reset state variables.  Wait for receiver to
   send NAK or CRC request.  */

int
xmodem_init_xfer (desc)
     serial_t desc;
{
  int c;
  int i;

  blknum = 1;
  crcflag = 0;
  crcinit ();

  for (i = 1; i <= 10; i++)
    {
      c = readchar (desc, 6);

      switch (c)
	{
	case 'C':
	  crcflag = 1;
	case NAK:
	  return 0;
	default:
	  fprintf_unfiltered (gdb_stderr, "xmodem_init_xfer: Got unexpected character %c (0%o)\n", c, c);
	  continue;
	case CANCEL:		/* target aborted load */
	  fprintf_unfiltered (gdb_stderr, "Got a CANCEL from the target.\n");
	  continue;
	}
    }
  error ("xmodem_init_xfer:  Too many unexpected characters.");
}

/* Take 128 bytes of data and make a packet out of it.

 *      Each packet looks like this:
 *      +-----+-------+-------+------+-----+
 *      | SOH | Seq1. | Seq2. | data | SUM |
 *      +-----+-------+-------+------+-----+
 *      SOH  = 0x01
 *      Seq1 = The sequence number.
 *      Seq2 = The complement of the sequence number.
 *      Data = A 128 bytes of data.
 *      SUM  = Add the contents of the 128 bytes and use the low-order
 *             8 bits of the result.
 *
 * send_xmodem_packet fills in the XMODEM fields of PACKET and sends it to the
 * remote system.  PACKET must be XMODEM_PACKETSIZE bytes long.  The data must
 * start 3 bytes after the beginning of the packet to leave room for the
 * XMODEM header.  LEN is the length of the data portion of the packet (and
 * must be <= 128 bytes).  If it is < 128 bytes, ^Z padding will be added.
 */

void
xmodem_send_packet (desc, packet, len, hashmark)
     serial_t desc;
     unsigned char *packet;
     int len;
     int hashmark;
{
  int i;
  int retries;
  int pktlen;
  int datasize;

  /* build the packet header */

  packet[1] = blknum;
  packet[2] = ~blknum;

  blknum++;

  if (len <= XMODEM_DATASIZE)
    {
      packet[0] = SOH;
      datasize = XMODEM_DATASIZE;
    }
  else if (len <= XMODEM_1KDATASIZE)
    {
      packet[0] = STX;
      datasize = XMODEM_1KDATASIZE;
    }
  else
    abort ();			/* Packet way too large */

  /* Add ^Z padding if packet < 128 (or 1024) bytes */

  memset (packet + 3 + len, '\026', datasize - len);

  if (crcflag)
    {
      int crc;

      crc = docrc (packet + 3, datasize);

      packet[3 + datasize] = crc >> 8;
      packet[3 + datasize + 1] = crc;
      pktlen = datasize + 5;
    }
  else
    {
      int sum;

      sum = 0;
      for (i = 3; i < datasize + 3; i++)
	sum += packet[i];

      packet[3 + datasize] = sum;	/* add the checksum */
      pktlen = datasize + 4;
    }

  for (retries = 3; retries >= 0; retries--)
    {
      int c;

      SERIAL_WRITE (desc, packet, pktlen);

      c = readchar (desc, 3);
      switch (c)
	{
	case ACK:
	  return;
	case NAK:
	  if (!hashmark)
	    continue;
	  putchar_unfiltered ('-');
	  gdb_flush (gdb_stdout);
	  continue;
	case CANCEL:
	  error ("xmodem_send_packet: Transfer aborted by receiver.");
	default:
	  fprintf_unfiltered (gdb_stderr, "xmodem_send_packet: Got unexpected character %c (0%o)\n", c, c);
	  continue;
	}
    }

  SERIAL_WRITE (desc, "\004", 1);	/* Send an EOT */

  error ("xmodem_send_packet:  Excessive retries.");
}

/* Finish off the transfer.  Send out the EOT, and wait for an ACK.  */

void
xmodem_finish_xfer (desc)
     serial_t desc;
{
  int retries;

  for (retries = 10; retries >= 0; retries--)
    {
      int c;

      SERIAL_WRITE (desc, "\004", 1);	/* Send an EOT */

      c = readchar (desc, 3);
      switch (c)
	{
	case ACK:
	  return;
	case NAK:
	  continue;
	case CANCEL:
	  error ("xmodem_finish_xfer: Transfer aborted by receiver.");
	default:
	  fprintf_unfiltered (gdb_stderr, "xmodem_send_packet: Got unexpected character %c (0%o)\n", c, c);
	  continue;
	}
    }

  error ("xmodem_finish_xfer:  Excessive retries.");
}
