⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ymodem.c

📁 上一次项目的vivi 代码
💻 C
字号:
/*  * YMODEM  *  * Copyright (C) 2001  John G Dorsey * * 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. * * The author may be contacted via electronic mail at <john+@cs.cmu.edu>, * or at the following address: * *   John Dorsey *   Carnegie Mellon University *   HbH2201 - ICES *   5000 Forbes Avenue *   Pittsburgh, PA  15213 * * * Notes: * ^^^^^^ * Tested against lsz (`sb') from within Minicom. The YMODEM spec says * that the receiver should just keep sending CRC/NAKs to the sender  * until the transfer begins, but something breaks if a CRC/NAK is * sent out while the user is typing in a filename to Minicom. Best * solution currently is just to repeat the transfer. * * History: * ^^^^^^^^ * 12 March, 2001 - created. (jd) * *//*  * Hacked to work with vivi by Janghoon Lyu <nandy@mizi.com>, Oct 16 2002  *  * - The vivi does not use CRC or checksum for error dectecion anymore *   because these days the sereial communication is very stable. */#include <config.h>#include <machine.h>#include <serial.h>#include <types.h>#include <printk.h>#include <vivi_string.h>#include <time.h>#include <priv_data.h>#include "ymodem.h"static intreceive_byte(char *c, unsigned long timeout){	int error = 0;	*c = do_getc_with_timeout(timeout, &error);	return error ? -1 : 0;}/* Returns 0 on success, 1 on corrupt packet, -1 on error (timeout): */static int receive_packet(char *data, int *length, unsigned long timeout){	int i;	unsigned int packet_size;	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;		}	/* 	 * 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.	 */	default:		*length = -1;		return 0;	}	*data = c;	/*	 * Note by nandy:	 * I assumed that the minicom send checksum bits. So the receiver(the vivi)	 * receive checksum bits.	 */	for (i = 1; i < (packet_size + PACKET_OVERHEAD); ++i)		if (receive_byte(data + i, timeout) < 0)			return -1;#if 0 /* Note by nandy: Below codes must be disabled in the vivi. Why? */	/* 	 * 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;#endif	*length = packet_size;	return 0;}/* Returns the length of the file received, or 0 on error: */intymodem_receive(char *buf, unsigned int length, char *name){	unsigned char packet_data[PACKET_1K_SIZE + PACKET_OVERHEAD];	int packet_length, i, file_done, session_done;	unsigned int packets_received, errors;	char file_name[FILE_NAME_LENGTH], file_size[FILE_SIZE_LENGTH], *file_ptr;	char *buf_ptr;	unsigned long size = 0;	unsigned long timeout, initial_timeout, nak_timeout; 	int ret;	initial_timeout = get_param_value("ymodem_initial_timeout", &ret);	if (ret) initial_timeout = INITIAL_TIMEOUT;	nak_timeout = NAK_TIMEOUT;	/* Give the user time to frantically type in the file name: */	timeout = initial_timeout;	for (session_done = 0, errors = 0; ; ) {		for (packets_received = 0, file_done = 0, buf_ptr = buf; ; ) {			switch (receive_packet(packet_data, &packet_length, timeout)) {			case 0:				errors = 0;				switch (packet_length) {				case -1:  /* abort */					putc(ACK);					return 0;	  				case 0:   /* end of transmission */					putc(ACK);	  					/* 					 * Should add some sort of sanity check on the 					 * number of packets received and the advertised 					 * file length.  					 */ 					file_done = 1;					break;	  				default:  /* normal packet */					if ((packet_data[PACKET_SEQNO_INDEX] & 0xff) !=						(packets_received & 0xff)) {						putc(NAK);					} else {						if (packets_received == 0) {						/* The spec suggests that the whole data 						 * section should be zeroed, but I don't 						 * think all senders do this. If we have 						 * a NULL filename and the first few digits 						 * of the file length are zero, we'll call 						 * it empty. */							for (i = PACKET_HEADER; i < PACKET_HEADER + 4; ++i)								if(packet_data[i] != 0)									break;							if (i < PACKET_HEADER + 4) {  /* filename packet has data */								for (file_ptr = packet_data + PACKET_HEADER, i = 0; *file_ptr && i < FILE_NAME_LENGTH;)									file_name[i++] = *file_ptr++;								file_name[i++] = '\0';								if (name != NULL)									strcpy(name, file_name);								for (++file_ptr, i = 0; *file_ptr != ' ' && i < FILE_SIZE_LENGTH;)									file_size[i++] = *file_ptr++;								file_size[i++] = '\0';								size = strtoul(file_size, NULL, 0, NULL);								if (size > length) {									putc(CAN);									putc(CAN);									mdelay(3000);									printk("Receive buffer too small (%d) to accept file size %d\n", length, size);									return 0;								}										putc(ACK);								/* Note by nandy: Why? */								putc(NAK);							} else {  /* filename packet is empty; end session */								putc(ACK);								file_done = 1;								session_done = 1;								break;							}						} else {						/* This shouldn't happen, but we check 						 * anyway in case the * sender lied in 						 * its filename packet: */							if ((buf_ptr + packet_length) - buf > length) {								putc(CAN);								putc(CAN);								mdelay(3000);								printk("Sender exceeded size of receive buffer: %d", length);								return 0;							}							memcpy(buf_ptr, packet_data + PACKET_HEADER, packet_length);							buf_ptr += packet_length;							putc(ACK);						}	    						++packets_received;	    					}  /* sequence number ok */				}				break;			default:				if (++errors >= ((packets_received == 0 ? MAX_CRC_TRIES : 0) + MAX_ERRORS)) {					putc(CAN);					putc(CAN);					mdelay(1000);					printk("Too many errors during receive; giving up.\n");					return 0;				}				if (packets_received == 0) {					timeout = nak_timeout;				}				/* Note by nandy: Why? */				putc(NAK);			}      			if (file_done)				break;		}  /* receive packets */		if(session_done)			break;	}  /* receive files */	return size;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -