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

📄 zmodem.cpp

📁 这是G.723和G.729的音频编解码的源代码
💻 CPP
📖 第 1 页 / 共 5 页
字号:
Czmodem::fd_exit()

{
	//tcsetattr(0,TCSANOW,&old_termios);
	return;
}

/*
 * read bytes as long as rdchk indicates that
 * more data is available.
 */

void
Czmodem::rx_purge(void)

{
	/*
	struct timeval t;
	fd_set f;
	unsigned char c;

	t.tv_sec = 0;
	t.tv_usec = 0;

	FD_ZERO(&f);
	FD_SET(0,&f);

	while (select(1,&f,NULL,NULL,&t)) {
		read(0,&c,1);		
	}
	*/
}

int last_sent = -1;

/* 
 * transmit a character. 
 * this is the raw modem interface
 */

void Czmodem::tx_raw(int c)
{

	if (raw_trace) {
		TRACE("%02x ",c);
	}


	last_sent = c & 0x7f;

	//putchar(c);
}

/*
 * transmit a character ZDLE escaped
 */

void
Czmodem::tx_esc(int c)

{
	tx_raw(ZDLE);
	/*
	 * exclusive or; not an or so ZDLE becomes ZDLEE
	 */
	tx_raw(c ^ 0x40);
}

/*
 * transmit a character; ZDLE escaping if appropriate
 */

void
Czmodem::tx(unsigned char c)

{
	switch (c) {
		case ZDLE:
			tx_esc(c);
			return;
			break;
		case 0x8d:
		case 0x0d:
			if (escape_all_control_characters && last_sent == '@') {
				tx_esc(c);
				return;
			}
			break;
		case 0x10:
		case 0x90:
		case 0x11:
		case 0x91:
		case 0x13:
		case 0x93:
			tx_esc(c);
			return;
			break;
		default:
			if (escape_all_control_characters && (c & 0x60) == 0) {
				tx_esc(c);
				return;
			}
			break;
	}
	/*
	 * anything that ends here is so normal we might as well transmit it.
	 */
	tx_raw((int) c);
}

/*
 * send the bytes accumulated in the output buffer.
 */
void Czmodem::tx_flush(void)

{
	fflush(stdout);
}

/* 
 * transmit a hex header.
 * these routines use tx_raw because we're sure that all the
 * characters are not to be escaped.
 */

void
Czmodem::tx_nibble(int n)

{
	n &= 0x0f;
	if (n < 10) {
		n += '0';
	}
	else {
		n += 'a' - 10;
	}

	tx_raw(n);
}

void
Czmodem::tx_hex(int h)

{
	tx_nibble(h >> 4);
	tx_nibble(h);
}

void
Czmodem::tx_hex_header(unsigned char *p)

{
	int i;
	unsigned short int crc;


	TRACE("tx_hheader : ");


	tx_raw(ZPAD);
	tx_raw(ZPAD);
	tx_raw(ZDLE);

	if (use_variable_headers) {
		tx_raw(ZVHEX);
		tx_hex(HDRLEN);
	}
	else {
		tx_raw(ZHEX);
	}

	/*
 	 * initialise the crc
	 */

	crc = 0;

	/*
 	 * transmit the header
	 */

	for (i=0;i<HDRLEN;i++) {
		tx_hex(*p);
		crc = UPDCRC16(*p, crc);
		p++;
	}

	/*
 	 * update the crc as though it were zero
	 */

	crc = UPDCRC16(0,crc);
	crc = UPDCRC16(0,crc);

	/* 
	 * transmit the crc
	 */

	tx_hex(crc >> 8);
	tx_hex(crc);

	/*
	 * end of line sequence
	 */

	tx_raw(0x0d);
	tx_raw(0x0a);

	tx_raw(XON);

	tx_flush();


	TRACE("\n");

}

/*
 * Send ZMODEM binary header hdr
 */

void Czmodem::tx_bin32_header(unsigned char * p)

{
	int i;
	unsigned long crc;


	TRACE("tx binary header 32 bits crc\n");
	raw_trace = 1;


	tx_raw(ZPAD);
	tx_raw(ZPAD);
	tx_raw(ZDLE);

	if (use_variable_headers) {
		tx_raw(ZVBIN32);
		tx(HDRLEN);
	}
	else {
		tx_raw(ZBIN32);
	}

	crc = 0xffffffffL;

	for (i=0;i<HDRLEN;i++) {
		crc = UPDCRC32(*p,crc);
		tx(*p++);
	}

	crc = ~crc;

	tx((unsigned char)crc);
	tx((unsigned char)(crc >> 8));
	tx((unsigned char)(crc >> 16));
	tx((unsigned char)(crc >> 24));
}

void
Czmodem::tx_bin16_header(unsigned char * p)

{
	int i;
	unsigned int crc;


	TRACE("tx binary header 16 bits crc\n");


	tx_raw(ZPAD);
	tx_raw(ZPAD);
	tx_raw(ZDLE);

	if (use_variable_headers) {
		tx_raw(ZVBIN);
		tx(HDRLEN);
	}
	else {
		tx_raw(ZBIN);
	}

	crc = 0;

	for (i=0;i<HDRLEN;i++) {
		crc = UPDCRC16(*p,crc);
		tx(*p++);
	}

	crc = UPDCRC16(0,crc);
	crc = UPDCRC16(0,crc);

	tx(crc >> 8);
	tx(crc);
}


/* 
 * transmit a header using either hex 16 bit crc or binary 32 bit crc
 * depending on the receivers capabilities
 * we dont bother with variable length headers. I dont really see their
 * advantage and they would clutter the code unneccesarily
 */

void Czmodem::tx_header(unsigned char * p)

{
	if (can_fcs_32) {
		if (want_fcs_32) {
			tx_bin32_header(p);
		}
		else {
			tx_bin16_header(p);
		}
	}
	else {
		tx_hex_header(p);
	}
}

/*
 * data subpacket transmission
 */

void
Czmodem::tx_32_data(int sub_frame_type,unsigned char * p,int l)

{
//	int c;
	unsigned long crc;


	TRACE("tx_32_data\n");


	crc = 0xffffffffl;

	while (l > 0) {
		crc = UPDCRC32(*p,crc);
		tx(*p++);
		l--;
	}

	crc = UPDCRC32(sub_frame_type, crc);

	tx_raw(ZDLE);
	tx_raw(sub_frame_type);

	crc = ~crc;

	tx((int) (crc      ) & 0xff);
	tx((int) (crc >> 8 ) & 0xff);
	tx((int) (crc >> 16) & 0xff);
	tx((int) (crc >> 24) & 0xff);
}

void Czmodem::
tx_16_data(int sub_frame_type,unsigned char * p,int l)

{
	unsigned short crc;


	TRACE("tx_16_data\n");


	crc = 0;

	while (l > 0) {
		crc = UPDCRC16(*p,crc);
		tx(*p++);
		l--;
	}

	crc = UPDCRC16(sub_frame_type,crc);

	tx_raw(ZDLE); 
	tx_raw(sub_frame_type);
	
	crc = UPDCRC16(0,crc);
	crc = UPDCRC16(0,crc);

	tx((unsigned char)crc >> 8);
	tx((unsigned char)crc);
}

/*
 * send a data subpacket using crc 16 or crc 32 as desired by the receiver
 */

void Czmodem::
tx_data(int sub_frame_type,unsigned char * p, int l)

{
	if (want_fcs_32 && can_fcs_32) {
		tx_32_data(sub_frame_type,p,l);
	}
	else {	
		tx_16_data(sub_frame_type,p,l);
	}

	if (sub_frame_type == ZCRCW) {
		tx_raw(XON);
	}

	tx_flush();
}

void Czmodem::tx_pos_header(int type,long pos) 
{
	char header[5];

	header[0]   = type;
	header[ZP0] =  pos        & 0xff;
	header[ZP1] = (pos >>  8) & 0xff;
	header[ZP2] = (pos >> 16) & 0xff;
	header[ZP3] = (pos >> 24) & 0xff;

	tx_hex_header((unsigned char*)header);
}

void Czmodem::tx_znak()

{
	TRACE("tx_znak\n");

	tx_pos_header(ZNAK,ack_file_pos);
	tx_raw(XON);//1999.10.21, add by lhf, for cdemultiplex can locate on frame zack
}

void Czmodem::tx_zskip()

{
	tx_pos_header(ZSKIP,0L);
	tx_raw(XON);//1999.10.21, add by lhf, for cdemultiplex can locate on frame zack
}

/*
 * receive any style header within timeout milliseconds
 */

void Czmodem::alarm(int a)

{
	//signal(SIGALRM,SIG_IGN);
}

int
Czmodem::rx_poll()

{
	/*
	struct timeval t;
	fd_set f;
	unsigned char c;

	t.tv_sec = 0;
	t.tv_usec = 0;

	FD_ZERO(&f);
	FD_SET(0,&f);

	if (select(1,&f,NULL,NULL,&t)) {
		return 1;
	}
	*/

	return 0;
}

/*
 * rx_raw ; receive a single byte from the line.
 * reads as many are available and then processes them one at a time
 * check the data stream for 5 consecutive CAN characters;
 * and if you see them abort. this saves a lot of clutter in
 * the rest of the code; even though it is a very strange place
 * for an exit. (but that was wat session abort was all about.)
 */

int Czmodem::rx_raw(int to)

{
	//int n;
	unsigned char c;
	static int n_cans = 0;
	clock_t start = 0, finish = 0;
	double duration = 0;

	if (n_in_inputbuffer == 0) {
		start = ::clock();
		/*
		 * change the timeout into seconds; minimum is 1
		 */

		to /= 1000;
		if (to == 0) {
			to++;
		}

		/*
	 	 * setup an alarm in case io takes too long
		 */

		//signal(SIGALRM,alrm);

		to /= 1000;

		if (to == 0) {
			to = 2;
		}

		alarm(to);

		do{
			n_in_inputbuffer = ReadRawData(inputbuffer,MAXFILETRANSMITPACKETLENGTH);
			if(n_in_inputbuffer == 0)
				Sleep(to * 500);//
			finish = ::clock();
			duration = (finish - start) / CLOCKS_PER_SEC;
		}while(n_in_inputbuffer==0 && (duration < to));

		if (n_in_inputbuffer <= 0) {
			n_in_inputbuffer = 0;
		}

		/*
	 	 * cancel the alarm in case it did not go off yet
		 */

		//signal(SIGALRM,SIG_IGN);

		if (n_in_inputbuffer < 0 && (errno != 0 && errno != EINTR)) {
			TRACE("zmdm : fatal error reading device\n");
			//return TIMEOUT;//exit(1);
			::ExitThread(1);
		}

		if (n_in_inputbuffer == 0) {
			return TIMEOUT;
		}

		inputbuffer_index = 0;
	}

	c = inputbuffer[inputbuffer_index++];
	n_in_inputbuffer--;

	if (c == CAN) {
		n_cans++;
		if (n_cans == 5) {
			/*
			 * the other side is serious about this. just shut up;
			 * clean up and exit.

⌨️ 快捷键说明

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