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

📄 xcb+.c

📁 支持X/YModem和cis_b+协议的串口通讯程序
💻 C
📖 第 1 页 / 共 2 页
字号:
/*	xcb+.c -- CIS B+ Protocol module for XC	This file uses 4-character tabstops */#include <stdio.h>#include <stdlib.h>#include <string.h>#include <sys/types.h>#include <sys/stat.h>#include <unistd.h>#include <signal.h>#include <fcntl.h>#include <ctype.h>#define NODEBUG 1	/* prevents xc.h from defining DEBUG */#include "xc.h"#define min(x,y)	((int)(x)<(int)(y)?(x):(y))#define max(x,y)	((int)(x)>(int)(y)?(x):(y))#define MaskLowRange 0x01#define MaskHiRange 0x10#define Send_Ahead_Buffers	5enum {	Check_B,	Check_CRC	} ;enum {	Quote_Default,	Quote_Not_NULL,	Quote_Extended,	Quote_Full,	Quote_Mask	} ;enum {	Overwrite,	Resume	} ;enum {	Resume_Allowed,	Resume_Not_Allowed,	Resume_Failed,	Resume_Denied	} ;typedef enum {	S_Get_DLE,	S_DLE_Seen,	S_DLE_B_Seen,	S_Get_Data,	S_Get_check,	S_Get_CRC,	S_Verify_CRC,	S_VErify_CKS,	S_VerIfy_Packet,	S_Send_NAK,	S_SenD_ACK,	S_SEnd_ENQ,	S_Resend_Packets} Sender_Action;extern short cr_add;extern void cl_line();static char S_Buffer[2064], R_Buffer[2064], tdir[32];char	Name[SM_BUFF];static unsigned char Mask[32];static unsigned Checksum;static	Ch,				/* last char read from remote */		Quoting,		/* quoting level requested by the user */		Window_Size,	/* Send size of send ahead window */		PackeT_Size,	/* Maximum block size. */		R_BUffer_Len, S_Bytes, R_Bytes, Seq_Num, PendinG_Count,		Next_Packet, Packets_Btwn_ACKs, Last_ACK, textmode, Last_Chr,		Send_Errors, Read_Errors;static short Max_Errors=10, Abort_Flag, Not_Masked, Sent_ENQ, Actual_Check,			Valid_To_Resume_Download, ValiD_To_Resume_Upload,			Send_FIle_Information, Packet_Received, Result;static FILE *Data_File;static long	already_have, data, total_read, total_sent,			fsize, carriage_return;static time_t start;static struct {	int Seq;	int PackeT_Size;	char *packet;} Pending[Send_Ahead_Buffers];extern unsigned short crc_xmodem_tab[256];static voidinit_check(){	Checksum=Actual_Check ? 0xffff : 0;}static voiddo_checksum(ch)unsigned ch;{	if (Actual_Check==Check_B){		Checksum<<=1;		if (Checksum>255)			Checksum=(Checksum&0xFF)+1;		Checksum+=ch&0xFF;		if (Checksum>255)			Checksum=(Checksum&0xFF)+1;	} else	Checksum=(crc_xmodem_tab[((Checksum>>8)^ch)&0xff]^(Checksum<<8))&0xffff;}/* #define CIS_DEBUG */ /* for B+ logging */#ifdef CIS_DEBUGstatic FILE *bfp = NIL(FILE);static voidxclog(dir, val)char dir;int val;{	static int cnt, lastdir;	if (!bfp)		bfp=fopen("xc.log","w"),		cnt=0,		lastdir=dir;	if (++cnt>20||lastdir!=dir)		fputc('\n',bfp),		cnt=1;	if (lastdir!=dir)		fputc('\n',bfp);	if (val>'~'||val<' ')		fprintf(bfp,"%c%1x%1x ",dir,val/16,val%16);	else		fprintf(bfp,"%c%c  ",dir,val);	lastdir=dir;}static voidWhy_NAK(reason)char *reason;{	sprintf(Msg,"Sending NAK, %s",reason);	S0(Msg);}#else#define xclog(dir,val)#define Why_NAK(reason)#endifstatic voidstats(count)int count;{	int rate, minutes, sec, data_percent/*, rate_percent*/;	long chars, rem;	time_t elapsed, now;	data+=count;	if (!fsize)		data_percent=0;	else		data_percent=100*(data+carriage_return)/fsize;	if (data_percent>100)		data_percent=100;	now=mtime();	elapsed=now-start;	chars=data+carriage_return-already_have-(tdir[0]=='T'?PackeT_Size:0);	if (elapsed<1000 || !chars)		ttgoto(LI-6,26),		fputs("estimating",tfp);	else		rate=(1000*chars)/elapsed,		rem=(fsize-(data+carriage_return-already_have))/rate,		minutes=rem/60,		sec=rem%60,		ttgoto(LI-6,26),		fprintf(tfp,"%8.1d:%2.2d",minutes,sec),		elapsed/=1000,		minutes=elapsed/60,		sec=elapsed%60,		ttgoto(LI-6,61),		fprintf(tfp,"%8.1d:%2.2d",minutes,sec),		ttgoto(LI-4,23),		fprintf(tfp,"Rate: %d characters per second ", rate);	ttgoto(LI-8,0),	fprintf(tfp,"%8.1ld",total_sent),	ttgoto(LI-8,20),	fprintf(tfp,"%8.1ld",total_read),	ttgoto(LI-8,40);	if (!data_percent)		fprintf(tfp,"%8.1ld",data);	else		fprintf(tfp,"%8.1ld %3.1u %%",data,data_percent);	if (carriage_return)		ttgoto(LI-8,60),		fprintf(tfp,"%+7.1ld",carriage_return);}static voidshowmode(){	int l;	sprintf(Msg,"%s %s (%ld bytes) as %s",tdir,Name,fsize,		textmode?"ASCII":"BINARY");	ttgoto(LI-12,0);	cl_line();	if ((l=strlen(Msg)) < CO)		ttgoto(LI-12,(CO-l)/2 -1);	fputs(Msg,tfp);	start=mtime();}static voidDiscard_ACKed_Packets(){	int i, n;	short Packet_Acked=FALSE;	Last_ACK=Ch;	n=(Next_Packet+PendinG_Count)%Send_Ahead_Buffers;	for (i=PendinG_Count;i>0;i--){		n--;		if (n<0)			n+=5;		if (Pending[n].Seq==Ch-'0')			Packet_Acked=TRUE,			Next_Packet=(n+1)%Send_Ahead_Buffers;		if (Packet_Acked==TRUE)			free(Pending[n].packet),			Pending[n].packet=NIL(char),			PendinG_Count--;	}}static voidSend_Byte(ch)int ch;{	sendbyte(ch);	total_sent++;	xclog('>',ch);}static voidSend_Masked_Byte(ch)int ch;{	if (ch<0x20){		if (Quoting==Quote_Full||(Mask[ch]&MaskLowRange))			Send_Byte(DLE),			ch+='@';	} else if (ch>=0x80&&ch<0xA0&&		(Quoting==Quote_Full||(Mask[ch-0x80]&MaskHiRange)))			Send_Byte(DLE),			ch=ch+'`'-0x80;	Send_Byte(ch);}static intRead_Byte(){	if ((Ch=readbyte(10))== -1)		return FAILURE;	total_read++;	xclog('<',Ch);	return SUCCESS;}static intRead_Masked_Byte(){	Not_Masked=TRUE;	if (!Read_Byte())		return FAILURE;	if (Ch==DLE){		if (!Read_Byte())			return FAILURE;		Not_Masked=FALSE;		if (Ch>='`')			Ch+=0x80;		Ch&=0x9F;	}	return SUCCESS;}static voidSend_ACK(){	Send_Byte(DLE);	Send_Byte(Seq_Num+'0');}static voidInit(){	int i;	R_BUffer_Len=Window_Size=PendinG_Count=Next_Packet=		R_Bytes=S_Bytes=Seq_Num=Packets_Btwn_ACKs=Last_ACK=0;	i=mrate(NIL(char));	PackeT_Size=(i>2400) ? 2048 : (i>1200) ? 1024 : 512;	Quoting=Quote_Mask;	for (i=0;i<Send_Ahead_Buffers;i++)		Pending[i].packet=NIL(char);	Actual_Check=Check_B;	Abort_Flag=Sent_ENQ=FALSE;	memset(Mask,0,32);	Mask[ETX]=Mask[ENQ]=Mask[DLE]=Mask[NAK]=Mask[XON]=Mask[XOFF]=MaskLowRange;	total_sent=total_read=data=fsize=Read_Errors=Send_Errors=		already_have=carriage_return=0;	fputs("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n",tfp);	ttgoto(LI-14,25);	S1("CIS B-Plus Protocol Transfer");	ttgoto(LI-10,0);	fputs("B+ Bytes Sent       B+ Bytes Rcvd",tfp);	ttgoto(LI-10,40);	fputs("Data Bytes          Carriage Returns",tfp);	ttgoto(LI-6,10);	fputs("Time Remaining:",tfp);	ttgoto(LI-6,48);	fputs("Elapsed Time:",tfp);}static voidXmit_Packet(Size, Seq, Packet)int Size, Seq;unsigned char *Packet;{	register I;	init_check();	Send_Byte(DLE);	Send_Byte('B');	Send_Byte(Seq+'0');	do_checksum(Seq+'0');	for (I=0;I<Size;I++)		Send_Masked_Byte(Packet[I]),		do_checksum(Packet[I]);	Send_Byte(ETX);	do_checksum(ETX);	if (Actual_Check==Check_B)		Send_Masked_Byte(Checksum);	else		Send_Masked_Byte(Checksum>>8),		Send_Masked_Byte(Checksum&0xff);}static intWait_For_ACK(Have_DLE_B, Acknowledge, Resend)short Have_DLE_B, Acknowledge, Resend;{	Sender_Action Action;	int i=0, n, RCV_Num=0, Errors=0;	R_BUffer_Len=0;	Packet_Received=FALSE;	if (Have_DLE_B)		Action=S_DLE_B_Seen;	else		Action=S_Get_DLE;	while (Errors<Max_Errors)		switch (Action){		case S_Get_Data:			if (Read_Masked_Byte()==FAILURE){				Action=S_Send_NAK;				Why_NAK("couldn't read next data byte");			} else if (Not_Masked && Ch==ETX)				Action=S_Get_check;			else if (Not_Masked && Ch==ENQ)				Action=S_SenD_ACK;			else if (i>PackeT_Size){				Action=S_Send_NAK;				Why_NAK("incoming buffer overflow");			} else				R_Buffer[i++]=Ch,				do_checksum(Ch);			break;		case S_Get_DLE:			if (Packets_Btwn_ACKs>Window_Size+2&&PendinG_Count){				Packets_Btwn_ACKs=0;				Action=S_SEnd_ENQ;				continue;			}			if (!Read_Byte())				Action=S_SEnd_ENQ;			else if (Ch==DLE)				Action=S_DLE_Seen;			else if (Ch==NAK)				Action=S_SEnd_ENQ;			else if (Ch==ENQ)				Action=S_SenD_ACK;			else if (Ch==ETX){				Action=S_Send_NAK;				Why_NAK("awaiting DLE, got ETX");			}			break;		case S_DLE_Seen:			if (!Read_Byte())				Action=S_SEnd_ENQ;			else if (Ch>='0'&&Ch<='9')				if (Sent_ENQ&&Ch==Last_ACK){					Sent_ENQ=FALSE;					if (!PendinG_Count)						return SUCCESS;					else						Action=S_Resend_Packets;				} else {					Discard_ACKed_Packets();					if (Sent_ENQ)						Action=S_Get_DLE;					else						return SUCCESS;				}			else if (Ch==';')				Action=S_Get_DLE;			else if (Ch=='B')				Action=S_DLE_B_Seen;			else if (Ch==ENQ)				Action=S_SenD_ACK;			else				Action=S_Get_DLE;			break;		case S_DLE_B_Seen:			if (!Read_Byte()){				Action=S_Send_NAK;				Why_NAK("no data byte after DLE-B");			} else if (Ch==ENQ)				Action=S_SenD_ACK;			else {				init_check();				RCV_Num=Ch-'0';				do_checksum(Ch);				i=0;				Action=S_Get_Data;			}			break;		case S_Get_check:			do_checksum(ETX);			if (Read_Masked_Byte()==FAILURE){				Action=S_Send_NAK;				Why_NAK("no incoming checksum");			} else if (Not_Masked&&Ch==ENQ)				Action=S_SenD_ACK;			else if (Actual_Check==Check_CRC)				Action=S_Get_CRC;			else				Action=S_VErify_CKS;			break;		case S_Get_CRC:			do_checksum(Ch);			if (Read_Masked_Byte()==FAILURE){				Action=S_Send_NAK;				Why_NAK("no incoming CRC value");			} else if (Not_Masked&&Ch==ENQ)				Action=S_SenD_ACK;			else				Action=S_Verify_CRC;			break;		case S_Verify_CRC:			do_checksum(Ch);			if (!Checksum)				Action=S_VerIfy_Packet;			else {				Action=S_Send_NAK;				Why_NAK("CRC error");			}			break;		case S_VErify_CKS:			if (Checksum==Ch)				Action=S_VerIfy_Packet;			else {				Action=S_Send_NAK;				Why_NAK("Checksum error");			}			break;		case S_VerIfy_Packet:			if (RCV_Num==((Seq_Num+1)%10)||R_Buffer[0]=='F'){				Packets_Btwn_ACKs++;				Seq_Num=RCV_Num;				if (Acknowledge)					Send_ACK();				R_BUffer_Len=i;				Packet_Received=TRUE;				return FAILURE;			} else if (RCV_Num==Seq_Num)				Action=S_SenD_ACK;			else {				Action=S_Send_NAK;				Why_NAK("packet out of sequence");			}			break;		case S_Send_NAK:			ttgoto(LI-2,20);			sprintf(Msg,"Read Errors: %2.1d",++Read_Errors);			S;			Errors++;			Send_Byte(NAK);			Action=S_Get_DLE;			break;		case S_SenD_ACK:			Send_ACK();			Action=S_Get_DLE;			break;		case S_SEnd_ENQ:			ttgoto(LI-2,40);			sprintf(Msg,"Send Errors: %2.1d",++Send_Errors);			S;			Errors++;			Sent_ENQ=TRUE;			Send_Byte(ENQ);			Send_Byte(ENQ);			Action=S_Get_DLE;			break;		case S_Resend_Packets:			if (Resend)				for (i=0;i<PendinG_Count;i++)					n=(Next_Packet+i)%Send_Ahead_Buffers,					Xmit_Packet(						Pending[n].PackeT_Size,						Pending[n].Seq,						Pending[n].packet);			else				return FAILURE;			Action=S_Get_DLE;			break;		}	return FAILURE;}static voidSend_Failure(Code, Text)char Code;char *Text;{	int Len, Seq;	S_Buffer[0]='F';	S_Buffer[1]=Code;	Len=2;	while (*Text)		S_Buffer[Len++]= *Text++;	Seq=(Seq_Num+1)%10;	while (PendinG_Count&&Wait_For_ACK(FALSE,FALSE,FALSE))		;	Xmit_Packet(Len,Seq,S_Buffer);	do		Wait_For_ACK(FALSE,FALSE,FALSE);	while (Packet_Received);}static intFlush_Pending(){	while (PendinG_Count)		if (!Wait_For_ACK(FALSE,TRUE,TRUE))			return FAILURE;	return SUCCESS;}static voidSend_Abort(){	fclose(Data_File);	sprintf(Msg,"Transfer abort requested");	S0(Msg);	Send_Failure('A',Msg);}static intSend_Packet(Size)int Size;{	int Next, Next_Seq;	while ((PendinG_Count>Window_Size))		if (!Wait_For_ACK(FALSE,TRUE,TRUE)){			Send_Abort();			return FAILURE;		}	Next=(Next_Packet+PendinG_Count)%Send_Ahead_Buffers;

⌨️ 快捷键说明

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