Beispiel #1
0
char* lab_ymodem_receive(int* length, int ymodemg)
{
	int stop;
	int firstblk;
	unsigned char gotch;
	int pktsize;
	int size = 0;
	char* rxbuf = NULL;
	int rbytes;
	int waitpkts;
		
	stop = 0;
	firstblk = 1;
	lab_delay(6);
	rbytes = 0;
	waitpkts = 16;
	
	while (!stop)
	{
		if (firstblk)
		{
			if (ymodemg)
				lab_putc(GRC);
			else
				lab_putc(CRC);
		}
		
		gotch = getchar();
		if (gotch == 0)		// timeout
		{
			waitpkts--;
			if (!waitpkts)
			{
				printk("WARNING: YMODEM receive timed out!\n");
				if (rxbuf)
					vfree(rxbuf);
				return NULL;
			}
			
			continue;
		}
		
		switch (gotch)
		{
		case SOH:
			pktsize = 128;
			goto havesize;
		case STX:
			pktsize = 1024;
havesize:
		{
			unsigned char blk;
			unsigned char blk255;
			unsigned char dbytes[1028];
			int i;
			
			blk = getchar();
			blk255 = getchar();
			for (i=0; i<pktsize+2; i++)
				dbytes[i] = getchar();
			
			if (crc16_buf(dbytes, pktsize+2))
			{
				/* CRC failed, try again */
				lab_putc(NAK);
				break;
			}
			
			if (blk255 != (255-blk))
			{
				lab_putc(NAK);
				break;
			}
			
			if (firstblk)
			{
				int i;
				char* buf;
				buf = dbytes + strlen(dbytes) + 1;
				i = 0;
				size = 0;
				while (*buf >= '0' && *buf <= '9')
				{
					size *= 10;
					size += *buf - '0';
					buf++;
				}
				
				*length = size;
				size += 1024;
				rxbuf = vmalloc(size+1024); // a little more safety...
				// printk(">>> YMODEM: getting file of size %d (buf addr: %08X)\n", size-1024, rxbuf);
				
				lab_putc(ACK);
				if (ymodemg)
					lab_putc(GRC);
				else
					lab_putc(CRC);
				
				firstblk = 0;
				break;
			}
			
			if ((rbytes + pktsize) > size)
			{
				lab_putc(CAN);
				lab_putc(CAN);
				/* BUFFER OVERRUN!!! */
				stop = 1;
				break;
			}
			
			memcpy(rxbuf+rbytes, dbytes, pktsize);
			rbytes += pktsize;
			
			if (!ymodemg)
				lab_putc(ACK);
			
			break;
		}
		case EOT:
			lab_putc(ACK);
			lab_delay(1);
			lab_putc(CRC);
			lab_delay(1);
			lab_putc(ACK);
			lab_delay(1);
			lab_putc(CAN);
			lab_putc(CAN);
			lab_putc(CAN);
			lab_putc(CAN);
			lab_puts("\x08\x08\x08\x08    \x08\x08\x08\x08");
			
			eatbytes();
			
			stop = 1;
			
			break;
		case CAN:
			lab_putc(CAN);
			lab_putc(CAN);
			lab_putc(CAN);
			lab_putc(CAN);
			lab_puts("\x08\x08\x08\x08    \x08\x08\x08\x08");
			stop = 1;
			
			lab_delay(1);
			lab_puts("YMODEM transfer aborted\r\n");
			
			if (rxbuf)
				vfree(rxbuf);
			
			rxbuf = NULL;
			
			eatbytes();
			
			break;
		case 0x03:
		case 0xFF:
			/* Control-C. We should NAK it if it was line noise,
			 * but it's more likely to be the user banging on the
			 * keyboard trying to abort a screwup.
			 */
			lab_putc(CAN);
			lab_putc(CAN);
			lab_putc(CAN);
			lab_putc(CAN);
			lab_puts("\x08\x08\x08\x08    \x08\x08\x08\x08");
			
			eatbytes();
			
			if (rxbuf)
				vfree(rxbuf);
				
			rxbuf = NULL;
			
			stop=1;
			break;
		default:
			lab_putc(NAK);
		}
	}
	
	return rxbuf;
}
Beispiel #2
0
/* Returns 0 on success, 1 on corrupt packet, -1 on error (timeout): */
static int receive_packet(char *data, int *length, int use_crc, int timeout){
  int i;
  unsigned int packet_size, sum;
  char c;

  *length = 0;

  if(receive_byte(&c, timeout) < 0)
    return -1;

  switch(c){
  case SOH:
    packet_size = PACKET_SIZE;
    break;

  case STX:
    packet_size = PACKET_1K_SIZE;
    break;

  case EOT:
    return 0;

  case CAN:
    if(receive_byte(&c, timeout) == 0 && c == CAN){
      *length = -1;
      return 0;
    }

  default:

    /* This case could be the result of corruption on the first octet
     * of the packet, but it's more likely that it's the user banging
     * on the terminal trying to abort a transfer. Technically, the
     * former case deserves a NAK, but for now we'll just treat this
     * as an abort case.
     */

    *length = -1;
    return 0;
  }

  *data = c;

  for(i = 1; i < (packet_size + 
		  (use_crc ? PACKET_OVERHEAD_CRC : PACKET_OVERHEAD)); ++i)
    if(receive_byte(data + i, timeout) < 0)
      return -1;
  
  /* Just a sanity check on the sequence number/complement value. 
   * Caller should check for in-order arrival.
   */
  if(data[PACKET_SEQNO_INDEX] != 
     (data[PACKET_SEQNO_COMP_INDEX] ^ 0xff) & 0xff)
    return 1;

  if(use_crc){

    /* It seems odd that the CRC doesn't cover the three preamble bytes. */
    if(crc16_buf(data + PACKET_HEADER, packet_size + PACKET_TRAILER_CRC) != 0)
      return 1;

  } else {

    for(i = PACKET_HEADER, sum = 0; i < packet_size + PACKET_HEADER; ++i)
      sum += data[i];

    if((sum & 0xff) != (data[i] & 0xff))
      return 1;

  }

  *length = packet_size;

  return 0;
}