886 lines
18 KiB
C
886 lines
18 KiB
C
/*
|
|
* File : rz.c
|
|
* the core functions of implementing zmodem protocol
|
|
* Change Logs:
|
|
* Date Author Notes
|
|
* 2011-03-29 itspy
|
|
*/
|
|
|
|
#include <rtthread.h>
|
|
#include <finsh.h>
|
|
#include <shell.h>
|
|
#include <rtdef.h>
|
|
#include <dfs.h>
|
|
#include <dfs_file.h>
|
|
#include <dfs_posix.h>
|
|
#include <stdio.h>
|
|
#include "zdef.h"
|
|
|
|
char ZF0_CMD; /* file conversion request */
|
|
char ZF1_CMD; /* file management request */
|
|
char ZF2_CMD; /* file transport request */
|
|
char ZF3_CMD;
|
|
rt_uint8_t Rxframeind; /* ZBIN ZBIN32, or ZHEX type of frame */
|
|
rt_uint16_t Rxcount; /* received count*/
|
|
char header_type; /* header type */
|
|
rt_uint8_t rx_header[4]; /* received header */
|
|
rt_uint8_t tx_header[4]; /* transmitted header */
|
|
rt_uint32_t Rxpos; /* received file position */
|
|
rt_uint32_t Txpos; /* transmitted file position */
|
|
rt_uint8_t Txfcs32; /* TURE means send binary frames with 32 bit FCS */
|
|
rt_uint8_t TxCRC; /* controls 32 bit CRC being sent */
|
|
rt_uint8_t RxCRC; /* indicates/controls 32 bit CRC being received */
|
|
/* 0 == CRC16, 1 == CRC32, 2 == CRC32 + RLE */
|
|
char Attn[ZATTNLEN+1]; /* attention string rx sends to tx on err */
|
|
|
|
void zinit_parameter(void);
|
|
void zsend_bin_header(rt_uint8_t type, rt_uint8_t *hdr);
|
|
void zsend_hex_header(rt_uint8_t type, rt_uint8_t *hdr);
|
|
void zsend_bin_data(rt_uint8_t *buf, rt_int16_t len, rt_uint8_t frameend);
|
|
static rt_int16_t zrec_data16(rt_uint8_t *buf, rt_uint16_t len);
|
|
static rt_int16_t zrec_data32(rt_uint8_t *buf, rt_int16_t len);
|
|
static rt_int16_t zrec_data32r(rt_uint8_t *buf, rt_int16_t len);
|
|
rt_int16_t zget_data(rt_uint8_t *buf, rt_uint16_t len);
|
|
rt_int16_t zget_header(rt_uint8_t *hdr);
|
|
static rt_int16_t zget_bin_header(rt_uint8_t *hdr);
|
|
static rt_int16_t zget_bin_fcs(rt_uint8_t *hdr);
|
|
rt_int16_t zget_hex_header(rt_uint8_t *hdr);
|
|
static void zsend_ascii(rt_uint8_t c);
|
|
void zsend_zdle_char(rt_uint16_t ch);
|
|
static rt_int16_t zget_hex(void);
|
|
rt_int16_t zread_byte(void);
|
|
rt_int16_t zxor_read(void);
|
|
void zput_pos(rt_uint32_t pos);
|
|
void zget_pos(rt_uint32_t pos);
|
|
|
|
|
|
|
|
|
|
void zinit_parameter(void)
|
|
{
|
|
rt_uint8_t i;
|
|
|
|
ZF0_CMD = CANFC32|CANFDX|CANOVIO; /* not chose CANFC32,CANRLE,although it have been supported */
|
|
ZF1_CMD = 0; /* fix header length,not support CANVHDR */
|
|
ZF2_CMD = 0;
|
|
ZF3_CMD = 0;
|
|
Rxframeind =0;
|
|
header_type = 0;
|
|
Rxcount = 0;
|
|
for (i=0;i<4;i++) rx_header[i] = tx_header[i] = 0;
|
|
Rxpos = Txpos = 0;
|
|
RxCRC = 0;
|
|
Txfcs32 = 0;
|
|
|
|
return ;
|
|
}
|
|
|
|
/* send binary header */
|
|
void zsend_bin_header(rt_uint8_t type, rt_uint8_t *hdr)
|
|
{
|
|
rt_uint8_t i;
|
|
rt_uint32_t crc;
|
|
|
|
zsend_byte(ZPAD);
|
|
zsend_byte(ZDLE);
|
|
TxCRC = Txfcs32;
|
|
if (TxCRC == 0)
|
|
{
|
|
zsend_byte(ZBIN);
|
|
zsend_zdle_char(type);
|
|
/* add 16bits crc */
|
|
crc = 0L;
|
|
crc = updcrc16(type, 0);
|
|
for (i=0;i<4;i++)
|
|
{
|
|
zsend_zdle_char(*hdr);
|
|
crc = updcrc16((0377 & *hdr++),crc);
|
|
}
|
|
crc = updcrc16(0,updcrc16(0,crc));
|
|
zsend_zdle_char(((int)(crc>>8)));
|
|
zsend_zdle_char(crc);
|
|
}
|
|
else if(TxCRC == 1)
|
|
{
|
|
zsend_byte(ZBIN32);
|
|
zsend_zdle_char(type);
|
|
/* add 32bits crc */
|
|
crc = 0xffffffffL;
|
|
crc = updcrc32(type, crc);
|
|
for (i=0;i<4;i++)
|
|
{
|
|
zsend_zdle_char(*hdr);
|
|
crc = updcrc32((0377 & *hdr++), crc);
|
|
}
|
|
crc = ~crc;
|
|
for (i=0; i<4;i++)
|
|
{
|
|
zsend_zdle_char(crc);
|
|
crc >>= 8;
|
|
}
|
|
}
|
|
else if (TxCRC == 2)
|
|
{
|
|
zsend_byte(ZBINR32);
|
|
zsend_zdle_char(type);
|
|
/* add 32bits crc */
|
|
crc = 0xffffffffL;
|
|
crc = updcrc32(type, crc);
|
|
for (i=0;i<4;i++)
|
|
{
|
|
zsend_zdle_char(*hdr);
|
|
crc = updcrc32((0377 & *hdr++), crc);
|
|
}
|
|
crc = ~crc;
|
|
for (i=0; i<4;i++)
|
|
{
|
|
zsend_zdle_char(crc);
|
|
crc >>= 8;
|
|
}
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
/* send hex header */
|
|
void zsend_hex_header(rt_uint8_t type, rt_uint8_t *hdr)
|
|
{
|
|
rt_uint8_t i;
|
|
rt_uint16_t crc;
|
|
|
|
zsend_line(ZPAD); zsend_line(ZPAD); zsend_line(ZDLE);
|
|
zsend_line(ZHEX);
|
|
zsend_ascii(type);
|
|
crc = updcrc16(type, 0);
|
|
for (i=0; i<4; i++)
|
|
{
|
|
zsend_ascii(*hdr);
|
|
crc = updcrc16((0377 & *hdr++), crc);
|
|
}
|
|
crc = updcrc16(0,updcrc16(0,crc));
|
|
zsend_ascii(crc>>8);
|
|
zsend_ascii(crc);
|
|
/* send display control cmd */
|
|
zsend_line(015); zsend_line(0212);
|
|
if (type != ZFIN && type != ZACK)
|
|
zsend_line(021);
|
|
TxCRC = 0; /* clear tx crc type */
|
|
|
|
return;
|
|
}
|
|
|
|
/* send binary data,with frameend */
|
|
void zsend_bin_data(rt_uint8_t *buf, rt_int16_t len, rt_uint8_t frameend)
|
|
{
|
|
rt_int16_t i,c,tmp;
|
|
rt_uint32_t crc;
|
|
|
|
if (TxCRC == 0) /* send binary data with 16bits crc check */
|
|
{
|
|
crc = 0x0L;
|
|
for (i=0;i<len;i++)
|
|
{
|
|
zsend_zdle_char(*buf);
|
|
crc = updcrc16((0377 & *buf++), crc);
|
|
}
|
|
zsend_byte(ZDLE); zsend_byte(frameend);
|
|
crc = updcrc16(frameend, crc);
|
|
crc = updcrc16(0,updcrc16(0,crc));
|
|
zsend_zdle_char(crc>>8);
|
|
zsend_zdle_char(crc);
|
|
}
|
|
else if (TxCRC == 1) /* send binary data with 32 bits crc check */
|
|
{
|
|
crc = 0xffffffffL;
|
|
for (i=0;i<len;i++)
|
|
{
|
|
c = *buf++ & 0377;
|
|
zsend_zdle_char(c);
|
|
crc = updcrc32(c, crc);
|
|
}
|
|
zsend_byte(ZDLE); zsend_byte(frameend);
|
|
crc = updcrc32(frameend, crc);
|
|
crc = ~crc;
|
|
for (i=0;i<4;i++)
|
|
{
|
|
zsend_zdle_char((int)crc); crc >>= 8;
|
|
}
|
|
}
|
|
else if (TxCRC == 2) /* send binary data with 32bits crc check,RLE encode */
|
|
{
|
|
crc = 0xffffffffL;
|
|
tmp = *buf++ & 0377;
|
|
for (i = 0; --len >= 0; ++buf)
|
|
{
|
|
if ((c = *buf & 0377) == tmp && i < 126 && len>0)
|
|
{
|
|
++i; continue;
|
|
}
|
|
if (i==0)
|
|
{
|
|
zsend_zdle_char(tmp);
|
|
crc = updcrc32(tmp, crc);
|
|
if (tmp == ZRESC)
|
|
{
|
|
zsend_zdle_char(0100); crc = updcrc32(0100, crc);
|
|
}
|
|
tmp = c;
|
|
}
|
|
else if (i == 1)
|
|
{
|
|
if (tmp != ZRESC)
|
|
{
|
|
zsend_zdle_char(tmp); zsend_zdle_char(tmp);
|
|
crc = updcrc32(tmp, crc);
|
|
crc = updcrc32(tmp, crc);
|
|
i = 0; tmp = c;
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
zsend_zdle_char(ZRESC); crc = updcrc32(ZRESC, crc);
|
|
if (tmp == 040 && i < 34)
|
|
{
|
|
i += 036;
|
|
zsend_zdle_char(i);
|
|
crc = updcrc32(i, crc);
|
|
}
|
|
else
|
|
{
|
|
i += 0101;
|
|
zsend_zdle_char(i); crc = updcrc32(i, crc);
|
|
zsend_zdle_char(tmp); crc = updcrc32(tmp, crc);
|
|
}
|
|
i = 0; tmp = c;
|
|
}
|
|
}
|
|
zsend_byte(ZDLE); zsend_byte(frameend);
|
|
crc = updcrc32(frameend, crc);
|
|
crc = ~crc;
|
|
for (i=0;i<4;i++)
|
|
{
|
|
zsend_zdle_char(crc);
|
|
crc >>= 8;
|
|
}
|
|
}
|
|
if (frameend == ZCRCW)
|
|
zsend_byte(XON);
|
|
|
|
return;
|
|
}
|
|
|
|
/* receive data,with 16bits CRC check */
|
|
static rt_int16_t zrec_data16(rt_uint8_t *buf, rt_uint16_t len)
|
|
{
|
|
rt_int16_t c,crc_cnt;
|
|
rt_uint16_t crc;
|
|
rt_err_t res = -RT_ERROR;
|
|
rt_uint8_t *p,flag = 0;
|
|
|
|
p = buf;
|
|
crc_cnt = 0; crc = 0L;
|
|
Rxcount = 0;
|
|
while(buf <= p+len)
|
|
{
|
|
if ((res = zread_byte()) & ~0377)
|
|
{
|
|
if (res == GOTCRCE || res == GOTCRCG ||
|
|
res == GOTCRCQ || res == GOTCRCW)
|
|
{
|
|
c = res;
|
|
c = res;
|
|
crc = updcrc16(res&0377, crc);
|
|
flag = 1;
|
|
continue;
|
|
}
|
|
else if (res == GOTCAN) return ZCAN;
|
|
else if (res == TIMEOUT) return TIMEOUT;
|
|
else return res;
|
|
|
|
}
|
|
else
|
|
{
|
|
if (flag)
|
|
{
|
|
crc = updcrc16(res, crc);
|
|
crc_cnt++;
|
|
if (crc_cnt < 2) continue;
|
|
if ((crc & 0xffff))
|
|
{
|
|
#ifdef ZDEBUG
|
|
rt_kprintf("error code: CRC16 error \r\n");
|
|
#endif
|
|
return -RT_ERROR;
|
|
}
|
|
return c;
|
|
}
|
|
else
|
|
{
|
|
*buf++ = res;
|
|
Rxcount++;
|
|
crc = updcrc16(res, crc);
|
|
}
|
|
}
|
|
}
|
|
|
|
return -RT_ERROR;
|
|
}
|
|
|
|
/* receive data,with 32bits CRC check */
|
|
static rt_int16_t zrec_data32(rt_uint8_t *buf, rt_int16_t len)
|
|
{
|
|
rt_int16_t c,crc_cnt;
|
|
rt_uint32_t crc;
|
|
rt_err_t res = -RT_ERROR;
|
|
rt_uint8_t *p,flag = 0;
|
|
|
|
crc_cnt = 0; crc = 0xffffffffL;
|
|
Rxcount = 0;
|
|
while (buf <= p+len)
|
|
{
|
|
if ((res = zread_byte()) & ~0377)
|
|
{
|
|
if (res == GOTCRCE || res == GOTCRCG ||
|
|
res == GOTCRCQ || res == GOTCRCW)
|
|
{
|
|
c = res;
|
|
crc = updcrc32(res&0377, crc);
|
|
flag = 1;
|
|
continue;
|
|
}
|
|
else if (res == GOTCAN) return ZCAN;
|
|
else if (res == TIMEOUT) return TIMEOUT;
|
|
else return res;
|
|
|
|
}
|
|
else
|
|
{
|
|
if (flag)
|
|
{
|
|
crc = updcrc32(res, crc);
|
|
crc_cnt++;
|
|
if (crc_cnt < 4) continue;
|
|
if ((crc & 0xDEBB20E3))
|
|
{
|
|
#ifdef ZDEBUG
|
|
rt_kprintf("error code: CRC32 error \r\n");
|
|
#endif
|
|
return -RT_ERROR;
|
|
}
|
|
return c;
|
|
}
|
|
else
|
|
{
|
|
*buf++ = res;
|
|
Rxcount++;
|
|
crc = updcrc32(res, crc);
|
|
}
|
|
}
|
|
}
|
|
|
|
return -RT_ERROR;
|
|
}
|
|
/* receive data,with RLE encoded,32bits CRC check */
|
|
static rt_int16_t zrec_data32r(rt_uint8_t *buf, rt_int16_t len)
|
|
{
|
|
rt_int16_t c,crc_cnt;
|
|
rt_uint32_t crc;
|
|
rt_err_t res = -RT_ERROR;
|
|
rt_uint8_t *p,flag = 0;
|
|
|
|
crc_cnt = 0; crc = 0xffffffffL;
|
|
Rxcount = 0;
|
|
p = buf;
|
|
while (buf <= p+len)
|
|
{
|
|
if ((res = zread_byte()) & ~0377)
|
|
{
|
|
if (res == GOTCRCE || res == GOTCRCG ||
|
|
res == GOTCRCQ || res == GOTCRCW)
|
|
{
|
|
c = res;
|
|
crc = updcrc32(res&0377, crc);
|
|
flag = 1;
|
|
continue;
|
|
}
|
|
else if (res == GOTCAN) return ZCAN;
|
|
else if (res == TIMEOUT) return TIMEOUT;
|
|
else return res;
|
|
|
|
}
|
|
else
|
|
{
|
|
if (flag)
|
|
{
|
|
crc = updcrc32(res, crc);
|
|
crc_cnt++;
|
|
if (crc_cnt < 4) continue;
|
|
if ((crc & 0xDEBB20E3))
|
|
{
|
|
#ifdef ZDEBUG
|
|
rt_kprintf("error code: CRC32 error \r\n");
|
|
#endif
|
|
return -RT_ERROR;
|
|
}
|
|
return c;
|
|
}
|
|
else
|
|
{
|
|
crc = updcrc32(res, crc);
|
|
switch (c)
|
|
{
|
|
case 0:
|
|
if (res == ZRESC)
|
|
{
|
|
c = -1; continue;
|
|
}
|
|
*buf++ = res;
|
|
Rxcount++;
|
|
continue;
|
|
case -1:
|
|
if (res >= 040 && res < 0100)
|
|
{
|
|
c = res - 035; res = 040;
|
|
goto spaces;
|
|
}
|
|
if (res == 0100)
|
|
{
|
|
c = 0;
|
|
*buf++ = ZRESC;
|
|
Rxcount++;
|
|
continue;
|
|
}
|
|
c = res; continue;
|
|
default:
|
|
c -= 0100;
|
|
if (c < 1)
|
|
goto end;
|
|
spaces:
|
|
if ((buf + c) > p+len)
|
|
goto end;
|
|
while ( --res >= 0)
|
|
{
|
|
*buf++ = res;
|
|
Rxcount++;
|
|
}
|
|
c = 0; continue;
|
|
}
|
|
}
|
|
} // if -else
|
|
|
|
}
|
|
end:
|
|
return -RT_ERROR;
|
|
}
|
|
rt_int16_t zget_data(rt_uint8_t *buf, rt_uint16_t len)
|
|
{
|
|
rt_int16_t res = -RT_ERROR;
|
|
|
|
if (RxCRC == 0)
|
|
{
|
|
res = zrec_data16(buf,len);
|
|
}
|
|
else if (RxCRC == 1)
|
|
{
|
|
res = zrec_data32(buf, len);
|
|
}
|
|
else if (RxCRC == 2)
|
|
{
|
|
res = zrec_data32r(buf, len);
|
|
}
|
|
|
|
return res;
|
|
}
|
|
/* get type and cmd of header, fix lenght */
|
|
rt_int16_t zget_header(rt_uint8_t *hdr)
|
|
{
|
|
rt_int16_t c,prev_char;
|
|
rt_uint32_t bit;
|
|
rt_uint16_t get_can,step_out;
|
|
|
|
bit = get_device_baud(); /* get console baud rate */
|
|
Rxframeind = header_type = 0;
|
|
step_out = 0;
|
|
prev_char = 0xff;
|
|
for (;;)
|
|
{
|
|
c = zread_line(100);
|
|
switch(c)
|
|
{
|
|
case 021:
|
|
case 0221:
|
|
if (prev_char == CAN) break;
|
|
if (prev_char == ZCRCW) goto start_again;
|
|
break;
|
|
case RCDO:
|
|
goto end;
|
|
case TIMEOUT:
|
|
if (prev_char == CAN) break;
|
|
if (prev_char == ZCRCW)
|
|
{
|
|
c = -RT_ERROR; goto end;
|
|
}
|
|
goto end;
|
|
case ZCRCW:
|
|
if (prev_char == CAN) goto start_again;
|
|
break;
|
|
case CAN:
|
|
get_can:
|
|
if (++get_can > 5)
|
|
{
|
|
c = ZCAN; goto end;
|
|
}
|
|
break;
|
|
case ZPAD:
|
|
if (prev_char == CAN) break;
|
|
if (prev_char == ZCRCW) goto start_again;
|
|
step_out = 1;
|
|
break;
|
|
default:
|
|
if (prev_char == CAN) break;
|
|
if (prev_char == ZCRCW) goto start_again;
|
|
start_again:
|
|
if (--bit == 0)
|
|
{
|
|
c = GCOUNT; goto end;
|
|
}
|
|
get_can = 0;
|
|
break;
|
|
}
|
|
prev_char = c;
|
|
if (step_out) break; /* exit loop */
|
|
}
|
|
step_out = get_can = 0;
|
|
for (;;)
|
|
{
|
|
c = zxor_read();
|
|
switch(c)
|
|
{
|
|
case ZPAD:
|
|
break;
|
|
case RCDO:
|
|
case TIMEOUT:
|
|
goto end;
|
|
case ZDLE:
|
|
step_out = 1;
|
|
break;
|
|
default:
|
|
goto start_again;
|
|
}
|
|
if (step_out) break;
|
|
}
|
|
|
|
Rxframeind = c = zxor_read();
|
|
switch (c)
|
|
{
|
|
case ZBIN32:
|
|
RxCRC = 1; c = zget_bin_fcs(hdr); break;
|
|
case ZBINR32:
|
|
RxCRC = 2; c = zget_bin_fcs(hdr); break;
|
|
case ZBIN:
|
|
RxCRC = 0; c = zget_bin_header(hdr); break;
|
|
case ZHEX:
|
|
RxCRC = 0; c = zget_hex_header(hdr); break;
|
|
case CAN:
|
|
goto get_can;
|
|
case RCDO:
|
|
case TIMEOUT:
|
|
goto end;
|
|
default:
|
|
goto start_again;
|
|
}
|
|
end:
|
|
return c;
|
|
}
|
|
|
|
/* receive a binary header */
|
|
static rt_int16_t zget_bin_header(rt_uint8_t *hdr)
|
|
{
|
|
rt_int16_t res, i;
|
|
rt_uint16_t crc;
|
|
|
|
if ((res = zread_byte()) & ~0377)
|
|
return res;
|
|
header_type = res;
|
|
crc = updcrc16(res, 0);
|
|
|
|
for (i=0;i<4;i++)
|
|
{
|
|
if ((res = zread_byte()) & ~0377)
|
|
return res;
|
|
crc = updcrc16(res, crc);
|
|
*hdr++ = res;
|
|
}
|
|
if ((res = zread_byte()) & ~0377)
|
|
return res;
|
|
crc = updcrc16(res, crc);
|
|
if ((res = zread_byte()) & ~0377)
|
|
return res;
|
|
crc = updcrc16(res, crc);
|
|
if (crc & 0xFFFF)
|
|
{
|
|
rt_kprintf("CRC error\n");
|
|
return -RT_ERROR;
|
|
}
|
|
|
|
return header_type;
|
|
}
|
|
|
|
/* receive a binary header,with 32bits FCS */
|
|
static rt_int16_t zget_bin_fcs(rt_uint8_t *hdr)
|
|
{
|
|
rt_int16_t res, i;
|
|
rt_uint32_t crc;
|
|
|
|
if ((res = zread_byte()) & ~0377)
|
|
return res;
|
|
header_type = res;
|
|
crc = 0xFFFFFFFFL;
|
|
crc = updcrc32(res, crc);
|
|
|
|
for (i=0;i<4;i++) /* 4headers */
|
|
{
|
|
if ((res = zread_byte()) & ~0377)
|
|
return res;
|
|
crc = updcrc32(res, crc);
|
|
*hdr++ = res;
|
|
|
|
}
|
|
for (i=0;i<4;i++) /* 4bytes crc */
|
|
{
|
|
if ((res = zread_byte()) & ~0377)
|
|
return res;
|
|
crc = updcrc32(res, crc);
|
|
|
|
}
|
|
if (crc != 0xDEBB20E3)
|
|
{
|
|
#ifdef ZDEBUG
|
|
rt_kprintf("CRC error\n");
|
|
#endif
|
|
return -RT_ERROR;
|
|
}
|
|
|
|
return header_type;
|
|
}
|
|
|
|
|
|
/* receive a hex style header (type and position) */
|
|
rt_int16_t zget_hex_header(rt_uint8_t *hdr)
|
|
{
|
|
rt_int16_t res,i;
|
|
rt_uint16_t crc;
|
|
|
|
if ((res = zget_hex()) < 0)
|
|
return res;
|
|
header_type = res;
|
|
crc = updcrc16(res, 0);
|
|
|
|
for (i=0;i<4;i++)
|
|
{
|
|
if ((res = zget_hex()) < 0)
|
|
return res;
|
|
crc = updcrc16(res, crc);
|
|
*hdr++ = res;
|
|
}
|
|
if ((res = zget_hex()) < 0)
|
|
return res;
|
|
crc = updcrc16(res, crc);
|
|
if ((res = zget_hex()) < 0)
|
|
return res;
|
|
crc = updcrc16(res, crc);
|
|
if (crc & 0xFFFF)
|
|
{
|
|
#ifdef ZDEBUG
|
|
rt_kprintf("error code : CRC error\r\n");
|
|
#endif
|
|
return -RT_ERROR;
|
|
}
|
|
res = zread_line(100);
|
|
if (res < 0)
|
|
return res;
|
|
res = zread_line(100);
|
|
if (res < 0)
|
|
return res;
|
|
|
|
return header_type;
|
|
}
|
|
|
|
/* convert to ascii */
|
|
static void zsend_ascii(rt_uint8_t c)
|
|
{
|
|
const char hex[] = "0123456789abcdef";
|
|
|
|
zsend_line(hex[(c&0xF0)>>4]);
|
|
zsend_line(hex[(c)&0xF]);
|
|
|
|
return;
|
|
}
|
|
|
|
/*
|
|
* aend character c with ZMODEM escape sequence encoding.
|
|
*/
|
|
void zsend_zdle_char(rt_uint16_t ch)
|
|
{
|
|
rt_uint16_t res;
|
|
|
|
res = ch & 0377;
|
|
switch (res)
|
|
{
|
|
case 0377:
|
|
zsend_byte(res);
|
|
break;
|
|
case ZDLE:
|
|
zsend_byte(ZDLE);
|
|
res ^= 0100;
|
|
zsend_byte(res);
|
|
break;
|
|
case 021:
|
|
case 023:
|
|
case 0221:
|
|
case 0223:
|
|
zsend_byte(ZDLE);
|
|
res ^= 0100;
|
|
zsend_byte(res);
|
|
break;
|
|
default:
|
|
zsend_byte(res);
|
|
}
|
|
}
|
|
|
|
/* decode two lower case hex digits into an 8 bit byte value */
|
|
static rt_int16_t zget_hex(void)
|
|
{
|
|
rt_int16_t res,n;
|
|
|
|
if ((res = zxor_read()) < 0)
|
|
return res;
|
|
n = res - '0';
|
|
if (n > 9)
|
|
n -= ('a' - ':');
|
|
if (n & ~0x0f)
|
|
return -RT_ERROR;
|
|
if ((res = zxor_read()) < 0)
|
|
return res;
|
|
res -= '0';
|
|
if (res > 9)
|
|
res -= ('a' - ':');
|
|
if (res & ~0x0f)
|
|
return -RT_ERROR;
|
|
res += (n<<4);
|
|
|
|
return res;
|
|
}
|
|
|
|
|
|
/*
|
|
* read a byte, checking for ZMODEM escape encoding
|
|
* including CAN*5 which represents a quick abort
|
|
*/
|
|
rt_int16_t zread_byte(void)
|
|
{
|
|
register int res;
|
|
|
|
again:
|
|
/* Quick check for non control characters */
|
|
if ((res = zread_line(100)) & 0140)
|
|
return res;
|
|
switch (res)
|
|
{
|
|
case ZDLE:
|
|
break;
|
|
case 023:
|
|
case 0223:
|
|
case 021:
|
|
case 0221:
|
|
goto again;
|
|
default:
|
|
return res;
|
|
}
|
|
again2:
|
|
if ((res = zread_line(100)) < 0)
|
|
return res;
|
|
if (res == CAN && (res = zread_line(100)) < 0)
|
|
return res;
|
|
if (res == CAN && (res = zread_line(100)) < 0)
|
|
return res;
|
|
if (res == CAN && (res = zread_line(100)) < 0)
|
|
return res;
|
|
switch (res)
|
|
{
|
|
case CAN:
|
|
return GOTCAN;
|
|
case ZCRCE:
|
|
case ZCRCG:
|
|
case ZCRCQ:
|
|
case ZCRCW:
|
|
return (res | GOTOR);
|
|
case ZRUB0:
|
|
return 0177;
|
|
case ZRUB1:
|
|
return 0377;
|
|
case 023:
|
|
case 0223:
|
|
case 021:
|
|
case 0221:
|
|
goto again2;
|
|
default:
|
|
if ((res & 0140) == 0100)
|
|
return (res ^ 0100);
|
|
break;
|
|
}
|
|
|
|
return -RT_ERROR;
|
|
}
|
|
|
|
/*
|
|
* @read a character from the modem line with timeout.
|
|
* @eat parity, XON and XOFF characters.
|
|
*/
|
|
rt_int16_t zxor_read(void)
|
|
{
|
|
rt_int16_t res;
|
|
|
|
for (;;)
|
|
{
|
|
if ((res = zread_line(100)) < 0)
|
|
return res;
|
|
switch (res &= 0177) {
|
|
case XON:
|
|
case XOFF:
|
|
continue;
|
|
case '\r':
|
|
case '\n':
|
|
case ZDLE:
|
|
default:
|
|
return res;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
/* put file posistion into the header*/
|
|
void zput_pos(rt_uint32_t pos)
|
|
{
|
|
tx_header[ZP0] = pos;
|
|
tx_header[ZP1] = pos>>8;
|
|
tx_header[ZP2] = pos>>16;
|
|
tx_header[ZP3] = pos>>24;
|
|
|
|
return;
|
|
}
|
|
|
|
/* Recover a long integer from a header */
|
|
void zget_pos(rt_uint32_t pos)
|
|
{
|
|
Rxpos = (rx_header[ZP3] & 0377);
|
|
Rxpos = (Rxpos << 8) | (rx_header[ZP2] & 0377);
|
|
Rxpos = (Rxpos << 8) | (rx_header[ZP1] & 0377);
|
|
Rxpos = (Rxpos << 8) | (rx_header[ZP0] & 0377);
|
|
|
|
return;
|
|
}
|
|
|
|
/* end of zcore.c */
|