📄 zmodem.cpp
字号:
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 + -