Exemplo n.º 1
0
/* getc */
void
xyzModem_stream_terminate (bool abort, int (*getc) (void))
{
  int c;

  if (abort)
    {
      ZM_DEBUG (zm_dprintf ("!!!! TRANSFER ABORT !!!!\n"));
      switch (xyz.mode)
	{
	case xyzModem_xmodem:
	case xyzModem_ymodem:
	  /* 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. */
	  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);
	  /* Now consume the rest of what's waiting on the line. */
	  ZM_DEBUG (zm_dprintf ("Flushing serial line.\n"));
	  xyzModem_flush ();
	  xyz.at_eof = true;
	  break;
#ifdef xyzModem_zmodem
	case xyzModem_zmodem:
	  /* Might support it some day I suppose. */
#endif
	  break;
	}
    }
  else
    {
      ZM_DEBUG (zm_dprintf ("Engaging cleanup mode...\n"));
      /*
       * Consume any trailing crap left in the inbuffer from
       * previous received blocks. Since very few files are an exact multiple
       * 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.
       */
      ZM_DEBUG (zm_dprintf ("Trailing gunk:\n"));
      while ((c = (*getc) ()) > -1)
        ;
      ZM_DEBUG (zm_dprintf ("\n"));
      /*
       * Make a small delay to give terminal programs like minicom
       * time to get control again after their file transfer program
       * exits.
       */
      CYGACC_CALL_IF_DELAY_US ((cyg_int32) 250000);
    }
}
Exemplo n.º 2
0
/* getc */
void xyzModem_stream_terminate(unsigned int abort, int (*getc)(void))
{
	int c;

	if(abort){
		switch(xyz.mode){
		case xyzModem_xmodem:
		case xyzModem_ymodem:
			/* 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. */
			putc(CAN);
			putc(CAN);
			putc(CAN);
			putc(CAN);
			putc(BSP);
			putc(BSP);
			putc(BSP);
			putc(BSP);
			/* Now consume the rest of what's waiting on the line. */
			xyzModem_flush();
			xyz.at_eof = 1;
			break;
#ifdef xyzModem_zmodem
		case xyzModem_zmodem:
			/* Might support it some day I suppose. */
#endif
			break;
		}
	} else {
		/*
		 * Consume any trailing crap left in the inbuffer from
		 * previous recieved blocks. Since very few files are an exact multiple
		 * 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.
		 */

		while((c = (*getc)()) > -1);
		/*
		* Make a small delay to give terminal programs like minicom
		* time to get control again after their file transfer program
		* exits.
		*/
		udelay(250000);
	}
}
Exemplo n.º 3
0
static int
xyzModem_get_hdr (void)
{
  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;
    }
  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\n", __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;
	}
    }

  /* 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;
    }
  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;
    }
  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;
	}
    }
  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;
    }
  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;
	}
    }
  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\n", xyz.blk, xyz.cblk,
		 (xyz.blk ^ xyz.cblk)));
      ZM_DEBUG (zm_dump_buf (xyz.pkt, xyz.len));
      xyzModem_flush ();
      return xyzModem_frame;
    }
  /* Verify checksum/CRC */
  if (xyz.crc_mode)
    {
      cksum = cyg_crc16 (xyz.pkt, xyz.len);
      if (cksum != ((xyz.crc1 << 8) | xyz.crc2))
	{
	  ZM_DEBUG (zm_dprintf ("CRC error - recvd: %02x%02x, computed: %x\n",
				xyz.crc1, xyz.crc2, cksum & 0xFFFF));
	  return xyzModem_cksum;
	}
    }
  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\n", xyz.crc1,
		     cksum & 0xFF));
	  return xyzModem_cksum;
	}
    }
  /* If we get here, the message passes [structural] muster */
  return 0;
}
Exemplo n.º 4
0
int
xyzModem_stream_read (char *buf, int size, int *err)
{
    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)\n", xyz.blk, __LINE__));
                        xyz.next_blk = (xyz.next_blk + 1) & 0xFF;

#if defined(xyzModem_zmodem) || defined(USE_YMODEM_LENGTH)
                        if (xyz.mode == xyzModem_xmodem || xyz.file_length == 0)
                        {
#else
                        if (1)
                        {
#endif
                            /* 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--;
                                }
                            }
                        }

#ifdef USE_YMODEM_LENGTH
                        /*
                         * 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);
                            }
                        }
#endif
                        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)\n", __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\n"));
                        stat = xyzModem_get_hdr ();
                        CYGACC_COMM_IF_PUTC (*xyz.__chan, ACK);
                        ZM_DEBUG (zm_dprintf ("FINAL ACK (%d)\n", __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)\n", __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;
        }
    }
    return total;
}

int
xyzModem_stream_write(ulong src,long size)
{
    char c;
    unsigned char  *psrc;
    unsigned short cksum;
    int ultlen = 0;
    int total = 0;
    int retry, i, res;
    int flag_ok = 0;
    int flag_frame = 0;
    psrc =(unsigned char *)src;
    xyz.blk  = 1;
    xyz.cblk = ~xyz.blk;
    xyz.len  = xyzModem_1k;

    for (retry = 0; retry < 300; ++retry) {
        res = CYGACC_COMM_IF_GETC_TIMEOUT (*xyz.__chan, &c);
        if (res) {
            switch (c) {
            case 'C':
                xyz.crc_mode = true;
                flag_ok = 1;
                ZM_DEBUG (zm_dprintf ("Receive char CRC***\n"));
                break;
            case NAK:
                xyz.crc_mode = false;
                flag_ok = 1;
                ZM_DEBUG (zm_dprintf ("Receive char NAK***\n"));
                break;
            case CAN:
                ZM_DEBUG (zm_dprintf ("Receive char cancel***\n"));
                CYGACC_COMM_IF_GETC_TIMEOUT (*xyz.__chan, &c);
                if (c == CAN) {
                    serial_putc_raw(ACK);
                    xyzModem_flush ();
                    return -1;
                }
                break;
            default:
                ZM_DEBUG (zm_dprintf ("Receive  char %x***\n",c));
                break;
            }
        }
        if (flag_ok == 1)
            break;
    }

    if (flag_ok == 0) {
        serial_putc_raw(CAN);
        serial_putc_raw(CAN);
        serial_putc_raw(CAN);
        xyzModem_flush ();
        return -2;
    }

    while(1) {
        flag_frame = 0;
        ultlen = size - total;

        if (ultlen > xyz.len)
            ultlen = xyz.len;

        if (ultlen > 0) {
            memcpy (xyz.pkt, &psrc[total], ultlen);
            if (ultlen < xyz.len) {
                memset (&xyz.pkt[ultlen], EOF, xyz.len-ultlen);
            }

            if (xyz.crc_mode) {
                cksum = cyg_crc16(xyz.pkt, xyz.len);
                xyz.crc1 = (cksum >> 8) & 0xFF;
                xyz.crc2 = cksum & 0xFF;
                ZM_DEBUG (zm_dprintf ("add crc check***\n"));
            } else {
Exemplo n.º 5
0
static int xyzModem_get_hdr(void)
{
	char c;
	int res;
	unsigned int hdr_found = 0;
	int i, can_total, hdr_chars;
	unsigned short cksum;

	/* Find the start of a header */
	can_total = 0;
	hdr_chars = 0;

	if(xyz.tx_ack){
		putc(ACK);
		xyz.tx_ack = 0;
	}

	while(!hdr_found){
		res = comm_if_getc_tout(&c);

		if(res){
			hdr_chars++;

			switch(c){
			case SOH:
				xyz.total_SOH++;
			case STX:
				if(c == STX)
					xyz.total_STX++;

				hdr_found = 1;
				break;
			case CAN:
				xyz.total_CAN++;

				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){
					putc(ACK);
					return xyzModem_eof;
				}
			default:
				/* Ignore, waiting for start of header */
				;
			}
		} else {
			/* Data stream timed out */
			xyzModem_flush(); /* Toss any current input */
			udelay(250000);
			return xyzModem_timeout;
		}
	}

	/* Header found, now read the data */
	res = comm_if_getc_tout((char *)&xyz.blk);
	if(!res){
		return xyzModem_timeout;
	}

	res = comm_if_getc_tout((char *)&xyz.cblk);
	if(!res){
		return xyzModem_timeout;
	}

	xyz.len = (c == SOH) ? 128 : 1024;
	xyz.bufp = xyz.pkt;
	for(i = 0;  i < xyz.len;  i++){
		res = comm_if_getc_tout(&c);
		if(res){
			xyz.pkt[i] = c;
		} else {
			return xyzModem_timeout;
		}
	}

	res = comm_if_getc_tout((char *)&xyz.crc1);
	if(!res){
		return xyzModem_timeout;
	}

	if(xyz.crc_mode){
		res = comm_if_getc_tout((char *)&xyz.crc2);
		if(!res){
			return xyzModem_timeout;
		}
	}

	/* Validate the message */
	if((xyz.blk ^ xyz.cblk) != (unsigned char)0xFF){
		xyzModem_flush();
		return xyzModem_frame;
	}

	/* Verify checksum/CRC */
	if(xyz.crc_mode){
		cksum = cyg_crc16(xyz.pkt, xyz.len);
		if(cksum != ((xyz.crc1 << 8) | xyz.crc2)){
			return xyzModem_cksum;
		}
	} else {
		cksum = 0;
		for(i = 0;  i < xyz.len;  i++){
			cksum += xyz.pkt[i];
		}

		if(xyz.crc1 != (cksum & 0xFF)){
			return xyzModem_cksum;
		}
	}

	/* If we get here, the message passes [structural] muster */
	return 0;
}