/* init the parameters */ static void zsend_init(void) { rt_err_t res = -RT_ERROR; zinit_parameter(); for(;;) /* wait ZPAD */ { res = zread_line(800); if (res == ZPAD) break; } for (;;) { res = zget_header(rx_header); if (res == ZRINIT) break; } if ((rx_header[ZF1] & ZRQNVH)) { zput_pos(0x80L); /* Show we can var header */ zsend_hex_header(ZRQINIT, tx_header); } Rxflags = rx_header[ZF0] & 0377; if (Rxflags & CANFC32) Txfcs32 = 1; /* used 32bits CRC check */ if (ZF2_OP == ZTRLE && (Rxflags & CANRLE)) /* for RLE packet */ Txfcs32 = 2; else ZF2_OP = 0; /* send SINIT cmd */ return; }
/* wait sync(ack) from the receiver */ static rt_err_t zget_sync(void) { rt_err_t res = -RT_ERROR; for (;;) { res = zget_header(rx_header); switch (res) { case ZCAN: case ZABORT: case ZFIN: case TIMEOUT: return -RT_ERROR; case ZRPOS: /* get pos, need to resend */ zget_pos(Rxpos); Txpos = Rxpos; return res; case ZACK: return res; case ZRINIT: /* get ZRINIT indicate that the prev file send completed */ return res; case ZSKIP: return res; case -RT_ERROR: default: zsend_bin_header(ZNAK, tx_header); continue; } } }
/* receive file */ static rt_err_t zrec_file(rt_uint8_t *rxbuf, struct zfile *zf) { rt_err_t res = - RT_ERROR; rt_uint16_t err_cnt = 0; do { zput_pos(zf->bytes_received); zsend_hex_header(ZRPOS, tx_header); again: res = zget_header(rx_header); switch (res) { case ZDATA: zget_pos(Rxpos); if (Rxpos != zf->bytes_received) { zsend_break(Attn); continue; } err_cnt = 0; res = zrec_file_data(rxbuf,zf); if (res == -RT_ERROR) { zsend_break(Attn); continue; } else if (res == GOTCAN) return res; else goto again; case ZRPOS: zget_pos(Rxpos); continue; case ZEOF: err_cnt = 0; zget_pos(Rxpos); if (Rxpos != zf->bytes_received || Rxpos != zf->bytes_total) { continue; } return (zrec_init(rxbuf,zf)); /* resend ZRINIT packet,ready to receive next file */ case ZFIN: zrec_ack_bibi(); return ZCOMPL; case ZCAN: #if 1==ZDEBUG rt_kprintf("error code: sender cancelled \r\n"); #endif zf->bytes_received = 0L; /* throw the received data */ return res; case ZSKIP: return res; case -RT_ERROR: zsend_break(Attn); continue; case ZNAK: case TIMEOUT: default: continue; } } while(++err_cnt < 100); return res; }
/* receiver init, wait for ack */ static rt_err_t zrec_init(rt_uint8_t *rxbuf, struct zfile *zf) { rt_uint8_t err_cnt = 0; rt_err_t res = -RT_ERROR; for (;;) { zput_pos(0L); tx_header[ZF0] = ZF0_CMD; tx_header[ZF1] = ZF1_CMD; tx_header[ZF2] = ZF2_CMD; zsend_hex_header(ZRINIT, tx_header); again: res = zget_header(rx_header); switch(res) { case ZFILE: ZF0_CMD = rx_header[ZF0]; ZF1_CMD = rx_header[ZF1]; ZF2_CMD = rx_header[ZF2]; ZF3_CMD = rx_header[ZF3]; res = zget_data(rxbuf, RX_BUFFER_SIZE); if (res == GOTCRCW) { if ((res =zget_file_info((char*)rxbuf,zf))!= RT_EOK) { zsend_hex_header(ZSKIP, tx_header); return (res); } return RT_EOK;; } zsend_hex_header(ZNAK, tx_header); goto again; case ZSINIT: if (zget_data((rt_uint8_t*)Attn, ZATTNLEN) == GOTCRCW) /* send zack */ { zsend_hex_header(ZACK, tx_header); goto again; } zsend_hex_header(ZNAK, tx_header); /* send znak */ goto again; case ZRQINIT: continue; case ZEOF: continue; case ZCOMPL: goto again; case ZFIN: /* end file session */ zrec_ack_bibi(); return res; default: if (++err_cnt >1000) return -RT_ERROR; continue; } } }
/* send file name and related info */ static rt_err_t zsend_file(struct zfile *zf, rt_uint8_t *buf, rt_uint16_t len) { rt_uint8_t cnt; rt_err_t res = -RT_ERROR; for (cnt=0;cnt<5;cnt++) { tx_header[ZF0] = ZF0_CMD; /* file conversion option */ tx_header[ZF1] = ZF1_CMD; /* file management option */ tx_header[ZF2] = (ZF3_CMD|ZF2_OP); /* file transfer option */ tx_header[ZF3] = ZF3_CMD; zsend_bin_header(ZFILE, tx_header); zsend_bin_data(buf, len, ZCRCW); loop: res = zget_header(rx_header); switch (res) { case ZRINIT: while ((res = zread_line(50)) > 0) { if (res == ZPAD) { goto loop; } } break; case ZCAN: case TIMEOUT: case ZABORT: case ZFIN: break; case -RT_ERROR: case ZNAK: break; case ZCRC: /* no CRC request */ goto loop; case ZFERR: case ZSKIP: break; case ZRPOS: /* here we want */ zget_pos(Rxpos); Txpos = Rxpos; return(zsend_file_data(zf)); default: break; } } return res; }
/* say "bibi" to the receiver */ static void zsay_bibi(void) { for (;;) { zput_pos(0L); /* reninit position of next file*/ zsend_hex_header(ZFIN, tx_header); /* send finished session cmd */ switch (zget_header(rx_header)) { case ZFIN: zsend_line('O'); zsend_line('O'); case ZCAN: case TIMEOUT: return; } } }