📄 zmodem.cpp
字号:
*/
cleanup();
//return TIMEOUT;//exit(CAN);
::ExitThread(CAN);//0x18
}
}
else {
n_cans = 0;
}
return c;
}
/*
* rx; receive a single byte undoing any escaping at the
* sending site. this bit looks like a mess. sorry for that
* but there seems to be no other way without incurring a lot
* of overhead. at least like this the path for a normal character
* is relatively short.
*/
int
Czmodem::rx(int to)
{
int c;
/*
* outer loop for ever so for sure something valid
* will come in; a timeout will occur or a session abort
* will be received.
*/
while (TRUE) {
/*
* fake do loop so we may continue
* in case a character should be dropped.
*/
do {
c = rx_raw(to);
if (c == TIMEOUT) {
return c;
}
switch (c) {
case ZDLE:
break;
case 0x11://XON
case 0x91:
case 0x13:
case 0x93:
continue;
break;
default:
/*
* if all control characters should be escaped and
* this one wasnt then its spurious and should be dropped.
*/
if (escape_all_control_characters && (c & 0x60) == 0) {
continue;
}
/*
* normal character; return it.
*/
return c;
}
} while (FALSE);
/*
* ZDLE encoded sequence or session abort.
* (or something illegal; then back to the top)
*/
do {
c = rx_raw(to);
if (c == 0x11 || c == 0x13 || c == 0x91 || c == 0x93 || c == ZDLE) {
/*
* these can be dropped.
*/
continue;
}
switch (c) {
/*
* these four are really nasty.
* for convenience we just change them into
* special characters by setting a bit outside the
* first 8. that way they can be recognized and still
* be processed as characters by the rest of the code.
*/
case ZCRCE:
case ZCRCG:
case ZCRCQ:
case ZCRCW:
return (c | ZDLEESC);
break;
case ZRUB0:
return 0x7f;
break;
case ZRUB1:
return 0xff;
break;
default:
if (escape_all_control_characters && (c & 0x60) == 0) {
/*
* a not escaped control character; probably
* something from a network. just drop it.
*/
continue;
}
/*
* legitimate escape sequence.
* rebuild the orignal and return it.
*/
if ((c & 0x60) == 0x40) {
return c ^ 0x40;
}
break;
}
} while (FALSE);
}
/*
* not reached.
*/
return 0;
}
/*
* receive a data subpacket as dictated by the last received header.
* return 2 with correct packet and end of frame
* return 1 with correct packet frame continues
* return 0 with incorrect frame.
* return TIMEOUT with a timeout
* if an acknowledgement is requested it is generated automatically
* here.
*/
/*
* data subpacket reception
*/
int Czmodem::rx_32_data(unsigned char * p,int * l)
{
int c;
unsigned long rxd_crc;
unsigned long crc;
int sub_frame_type;
TRACE("rx_32_data\n");
crc = 0xffffffffl;
do {
c = rx(1000);
if (c == TIMEOUT) {
return TIMEOUT;
}
if (c < 0x100) {
crc = UPDCRC32(c,crc);
*p++ = c;
(*l)++;
continue;
}
} while (c < 0x100);
sub_frame_type = c & 0xff;
crc = UPDCRC32(sub_frame_type, crc);
crc = ~crc;
rxd_crc = rx(1000);
rxd_crc |= rx(1000) << 8;
rxd_crc |= rx(1000) << 16;
rxd_crc |= rx(1000) << 24;
if (rxd_crc != crc) {
return FALSE;
}
ack_file_pos += *l;
return sub_frame_type;
}
int
Czmodem::rx_16_data(register unsigned char * p,int * l)
{
register int c;
int sub_frame_type;
register unsigned short crc;
unsigned short rxd_crc;
TRACE("rx_16_data\n");
crc = 0;
do {
c = rx(5000);
if (c == TIMEOUT) {
return TIMEOUT;
}
if (c < 0x100) {
crc = UPDCRC16(c,crc);
*p++ = c;
(*l)++;
}
} while (c < 0x100);
sub_frame_type = c & 0xff;
crc = UPDCRC16(sub_frame_type,crc);
crc = UPDCRC16(0,crc);
crc = UPDCRC16(0,crc);
rxd_crc = rx(1000) << 8;
rxd_crc |= rx(1000);
if (rxd_crc != crc) {
return FALSE;
}
ack_file_pos += *l;
return sub_frame_type;
}
int Czmodem::rx_data(unsigned char * p, int * l)
{
unsigned char zack_header[] = { ZACK, 0, 0, 0, 0 };
int sub_frame_type;
long pos;
/*
* fill in the file pointer in case acknowledgement is requested.
* the ack file pointer will be updated in the subpacket read routine;
* so we need to get it now
*/
pos = ack_file_pos;
/*
* receive the right type of frame
*/
*l = 0;
if (receive_32_bit_data) {
sub_frame_type = rx_32_data(p,l);
}
else {
sub_frame_type = rx_16_data(p,l);
}
switch (sub_frame_type) {
case TIMEOUT:
return TIMEOUT;
break;
/*
* frame continues non-stop
*/
case ZCRCG:
return FRAMEOK;
break;
/*
* frame ends
*/
case ZCRCE:
return ENDOFFRAME;
break;
/*
* frame continues; ZACK expected
*/
case ZCRCQ:
tx_pos_header(ZACK,pos);
tx_raw(XON);//1999.10.21, add by lhf, for cdemultiplex can locate on frame zack
return FRAMEOK;
break;
/*
* frame ends; ZACK expected
*/
case ZCRCW:
tx_pos_header(ZACK,pos);
tx_raw(XON);//1999.10.21, add by lhf, for cdemultiplex can locate on frame zack
return ENDOFFRAME;
break;
}
return FALSE;
}
int Czmodem::rx_nibble(int to)
{
int c;
c = rx(to);
if (c == TIMEOUT) {
return c;
}
if (c > '9') {
if (c < 'a' || c > 'f') {
/*
* illegal hex; different than expected.
* we might as well time out.
*/
return TIMEOUT;
}
c -= 'a' - 10;
}
else {
if (c < '0') {
/*
* illegal hex; different than expected.
* we might as well time out.
*/
return TIMEOUT;
}
c -= '0';
}
return c;
}
int
Czmodem::rx_hex(int to)
{
int n1;
int n0;
n1 = rx_nibble(to);
if (n1 == TIMEOUT) {
return n1;
}
n0 = rx_nibble(to);
if (n0 == TIMEOUT) {
return n0;
}
return (n1 << 4) | n0;
}
/*
* receive routines for each of the six different styles of header.
* each of these leaves rxd_header_len set to 0 if the end result is
* not a valid header.
*/
void Czmodem::rx_bin16_header(int to)
{
int c;
int n;
unsigned short int crc;
unsigned short int rxd_crc;
TRACE("rx binary header 16 bits crc\n");
crc = 0;
for (n=0;n<5;n++) {
c = rx(to);
if (c == TIMEOUT) {
TRACE("timeout\n");
return;
}
crc = UPDCRC16(c,crc);
rxd_header[n] = c;
}
crc = UPDCRC16(0,crc);
crc = UPDCRC16(0,crc);
rxd_crc = rx(1000) << 8;
rxd_crc |= rx(1000);
if (rxd_crc != crc) {
TRACE("bad crc %4.4x %4.4x\n",rxd_crc,crc);
return;
}
rxd_header_len = 5;
}
void Czmodem::rx_hex_header(int to)
{
int c;
int i;
unsigned short int crc = 0;
unsigned short int rxd_crc;
TRACE("rx_hex_header : ");
for (i=0;i<5;i++) {
c = rx_hex(to);
if (c == TIMEOUT) {
return;
}
crc = UPDCRC16(c,crc);
rxd_header[i] = c;
}
crc = UPDCRC16(0,crc);
crc = UPDCRC16(0,crc);
/*
* receive the crc
*/
c = rx_hex(to);
if (c == TIMEOUT) {
return;
}
rxd_crc = c << 8;
c = rx_hex(to);
if (c == TIMEOUT) {
return;
}
rxd_crc |= c;
if (rxd_crc == crc) {
rxd_header_len = 5;
}
else {
TRACE("bad crc.\n");
}
/*
* drop the end of line sequence after a hex header
*/
c = rx(to);
if (c == CR) {
/*
* both are expected with CR
*/
c = rx(to);
}
}
void Czmodem::rx_bin32_header(int to)
{
int c;
int n;
unsigned long crc;
unsigned long rxd_crc;
TRACE("rx binary header 32 bits crc\n");
crc = 0xffffffffL;
for (n=0;n<5;n++) {
c = rx(1000);
if (c == TIMEOUT) {
return;
}
crc = UPDCRC32(c,crc);
rxd_header[n] = c;
}
crc = ~crc;
rxd_crc = rx(1000);
rxd_crc |= rx(1000) << 8;
rxd_crc |= rx(1000) << 16;
rxd_crc |= rx(1000) << 24;
if (rxd_crc != crc) {
return;
}
rxd_header_len = 5;
}
/*
* receive any style header
* if the errors flag is set than whenever an invalid header packet is
* received INVHDR will be returned. otherwise we wait for a good header
* also; a flag (receive_32_bit_data) will be set to indicate whether data
* packets following this header will have 16 or 32 bit data attached.
* variable headers are not implemented.
*/
int
Czmodem::rx_header_raw(int to,int errors)
{
int c;
TRACE("rx header : ");
rxd_header_len = 0;
do {
do {
c = rx_raw(to);
if (c == TIMEOUT) {
return c;
}
} while (c != ZPAD);
c = rx_raw(to);
if (c == TIMEOUT) {
return c;
}
if (c == ZPAD) {
c = rx_raw(to);
if (c == TIMEOUT) {
return c;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -