#help_index "Comm" #define RMT_MAX_PKT_LEN 64 //Must be less then PKT_SYNC #define RMT_PKT_ACK 0xA5 #define RMT_PKT_NACK 0x5A #define RMT_PKT_SYNC 0xA3 #define RMT_PKT_SYNC2 0xA7 #define RMT_PKT_CHAR 0xA4 #define RMT_PKT_REQUEST 0xA6 #define RMT_PKT_RESET 0xA8 #define RMT_FILE_ACK 0x87566565 #define RMT_RQST_NONE 0x00 #define RMT_RQST_GETMSG 0x01 #define RMT_RQST_TX_FILE 0x02 #define RMT_RQST_RX_FILE 0x03 #define RMT_RQST_TX_BUF 0x04 #define RMT_RQST_RX_BUF 0x05 #define RMT_RQST_EXE_LOCAL 0x06 #define RMT_RQST_PUTS_CNT 0x07 #define RMT_NUM_RQST_TYPES 0x08 #define RMT_CHAR_DELAY (JIFFY_FREQ/50) #define RMT_TX_TIMEOUT_DELAY (JIFFY_FREQ) #define RMT_RX_TIMEOUT_DELAY (JIFFY_FREQ) #define RMT_NULL_MSG_DELAY (JIFFY_FREQ/20) public void RmtFlushRxFifo(LTChnl *chnl) { if (!chnl || !chnl->type) return; U1FifoFlush(comm_Rx_fifos[chnl->port]); if (Bt(&comm_flags[chnl->port],COMMf_INCOMING_XOFFED)) { Bts(&comm_flags[chnl->port],COMMf_INCOMING_XOFFED2); Bts(&comm_flags[chnl->port],COMMf_INCOMING_XOFFED3); chnl->PutChar(chnl,CH_XON); } } public I8 RmtTxFifoCnt(LTChnl *chnl) { if (!chnl || !chnl->type) return 0; return U1FifoCnt(comm_Tx_fifos[chnl->port]); } public void RmtWaitTxDone(LTChnl *chnl) { U8 base=comm_base[chnl->port]; if (!chnl || !chnl->type) return; while (RmtTxFifoCnt(chnl)) SwapInNext; while (Bt(&comm_flags[chnl->port],COMMf_OUTGOING_XOFFED)) SwapInNext; while (Bt(&comm_flags[chnl->port],COMMf_TX_XOFF)) SwapInNext; while (Bt(&comm_flags[chnl->port],COMMf_TX_XON)) SwapInNext; while (!(InP(base+UART_LSR) & 0x20)) SwapInNext; } public void RmtFlushTxFifo(LTChnl *chnl) { U8 base=comm_base[chnl->port]; if (!chnl || !chnl->type) return; U1FifoFlush(comm_Tx_fifos[chnl->port]); RmtWaitTxDone(chnl); } void RmtReset(LTChnl *chnl) { RmtFlushTxFifo(chnl); RmtFlushRxFifo(chnl); comm_flags[chnl->port]=0; } public void RmtPrintF(LTChnl *chnl,I1 *src,...) { I1 *buf,*ptr; if (!chnl || !chnl->type) return; buf=SPrintFJoin(NULL,src,argc,argv); ptr=buf; while (*ptr) chnl->PutChar(chnl,*ptr++); Free(buf); } public I8 RmtRxFifoCnt(LTChnl *chnl) { if (!chnl || !chnl->type) return 0; return U1FifoCnt(comm_Rx_fifos[chnl->port]); } public U1 RmtGetChar(LTChnl *chnl) { if (!chnl || !chnl->type) return 0; return CommGetChar(chnl->port); } public BoolU4 RmtScanChar(LTChnl *chnl,U1 *ch) { if (!chnl || !chnl->type) return 0; return CommScanChar(chnl->port,ch); } U8 RmtTxPktU1(LTChnl *chnl,U1 b) { if (!chnl || !chnl->type) return 0; if (b==CH_XOFF || b==CH_XON || b==CH_ESC || b==RMT_PKT_CHAR || b==RMT_PKT_REQUEST || b==RMT_PKT_RESET) { chnl->PutChar(chnl,CH_ESC); chnl->PutChar(chnl,b^0x80); return 2; } else { chnl->PutChar(chnl,b); return 1; } } BoolU8 RmtRxPktU1(LTChnl *chnl,U1 *b, U8 timeout_jiffies,BoolU4 *esc=NULL) { U1 b1; U8 timeout; *b=RMT_PKT_NACK; if (esc) *esc=FALSE; if (!chnl || !chnl->type) return FALSE; timeout=Jiffies+timeout_jiffies; while (JiffiesScanChar(chnl,&b1)) { if (b1==CH_ESC) { timeout=Jiffies+timeout_jiffies; while (JiffiesScanChar(chnl,&b1)) { *b=b1^0x80; if (esc) *esc=TRUE; return TRUE; } SwapInNext; } return FALSE; } else { if (b1==RMT_PKT_RESET) { RmtReset(chnl); throw(EXCP_RESET); } *b=b1; return TRUE; } } SwapInNext; } return FALSE; } #define ERR_DELAY 1 void RmtTxPkt(LTChnl *chnl,U1 *p,U8 size,U8 rqst=RMT_RQST_NONE, U8 timeout_delay=0) { //zero timeout_delay=none U1 b,xsum; U8 i,timeout_jiffy; if (!chnl || !chnl->type) return; if (!timeout_delay && (Fs->rmt_chnl==chnl || Fs->local_chnl==chnl)) { timeout_delay=RMT_TX_TIMEOUT_DELAY; if (Fs->rmt_chnl==chnl && chnl->pkt_rx_jiffy+RMT_NULL_MSG_DELAY<<1timeout_jiffy) throw(EXCP_TIMEOUT); RmtFlushTxFifo(chnl); RmtFlushRxFifo(chnl); chnl->PutChar(chnl,RMT_PKT_REQUEST); RmtWaitTxDone(chnl); if (RmtScanChar(chnl,&b)) { Sleep(ERR_DELAY); goto rt_err1; } RmtTxPktU1(chnl,rqst); RmtWaitTxDone(chnl); RmtRxPktU1(chnl,&b,RMT_CHAR_DELAY); if (b!=(RMT_PKT_ACK^RMT_PKT_REQUEST^rqst)&0xFF) { Sleep(ERR_DELAY); goto rt_err1; } } else if (size==1) { rt_err2: if (Jiffies>timeout_jiffy) throw(EXCP_TIMEOUT); RmtFlushTxFifo(chnl); RmtFlushRxFifo(chnl); chnl->PutChar(chnl,RMT_PKT_CHAR); RmtWaitTxDone(chnl); if (RmtScanChar(chnl,&b)) { Sleep(ERR_DELAY); goto rt_err2; } RmtTxPktU1(chnl,p[0]); RmtWaitTxDone(chnl); RmtRxPktU1(chnl,&b,RMT_CHAR_DELAY); if (b!=RMT_PKT_ACK^RMT_PKT_CHAR^p[0]) { Sleep(ERR_DELAY); goto rt_err2; } } else { rt_err3: if (Jiffies>timeout_jiffy) throw(EXCP_TIMEOUT); RmtFlushTxFifo(chnl); RmtFlushRxFifo(chnl); RmtTxPktU1(chnl,RMT_PKT_SYNC); RmtWaitTxDone(chnl); if (RmtScanChar(chnl,&b)) { Sleep(ERR_DELAY); goto rt_err3; } RmtTxPktU1(chnl,RMT_PKT_SYNC2); RmtWaitTxDone(chnl); RmtRxPktU1(chnl,&b,RMT_CHAR_DELAY); if (b!=RMT_PKT_ACK^RMT_PKT_SYNC) { Sleep(ERR_DELAY); goto rt_err3; } if (RmtScanChar(chnl,&b)) { Sleep(ERR_DELAY); goto rt_err3; } RmtTxPktU1(chnl,size); RmtWaitTxDone(chnl); RmtRxPktU1(chnl,&b,RMT_CHAR_DELAY); if (b!=(RMT_PKT_ACK^size)&0xFF) { Sleep(ERR_DELAY); goto rt_err3; } xsum=0x3A; for (i=0;ipkt_tx_jiffy=Jiffies; } void RmtRxPkt(LTChnl *chnl,U1 *p,U8 *size=NULL,U8 *rqst=NULL, U8 timeout_delay=0) { //zero timeout_delay=none U1 b,b1,xsum; U8 i=0,s,r,timeout_jiffy; BoolU4 esc; if (!chnl || !chnl->type) { if (size) *size=0; if (rqst) *rqst=0; return; } if (!timeout_delay && (Fs->rmt_chnl==chnl || Fs->local_chnl==chnl)) { timeout_delay=RMT_RX_TIMEOUT_DELAY; if (Fs->rmt_chnl==chnl && chnl->pkt_rx_jiffy+RMT_NULL_MSG_DELAY<<12) RmtFlushRxFifo(chnl); s=0; r=0; RmtRxPktU1(chnl,&b,RMT_CHAR_DELAY); rr_cont: if (Jiffies>timeout_jiffy) throw(EXCP_TIMEOUT); RmtRxPktU1(chnl,&b1,RMT_CHAR_DELAY,&esc); if (b==RMT_PKT_REQUEST) { if (b1>=RMT_NUM_RQST_TYPES) { if (b1==RMT_PKT_REQUEST && !esc) goto rr_cont; else goto rr_err; } r=b1; s=0; if (RmtScanChar(chnl,&b)) goto rt_err; RmtTxPktU1(chnl,RMT_PKT_ACK^RMT_PKT_REQUEST^b1); goto rr_exit; } else if (b==RMT_PKT_CHAR) { if (b1==RMT_PKT_CHAR && !esc) goto rr_cont; *p=b1; s=1; if (RmtScanChar(chnl,&b)) goto rt_err; RmtTxPktU1(chnl,RMT_PKT_ACK^RMT_PKT_CHAR^b1); goto rr_exit; } else if (b==RMT_PKT_SYNC) { if (b1!=RMT_PKT_SYNC2) { if (b1==RMT_PKT_SYNC) goto rr_cont; else goto rr_err; } if (RmtScanChar(chnl,&b)) goto rt_err; RmtTxPktU1(chnl,RMT_PKT_ACK^RMT_PKT_SYNC); RmtWaitTxDone(chnl); RmtRxPktU1(chnl,&s,RMT_CHAR_DELAY); if (s>RMT_MAX_PKT_LEN) goto rr_err; if (RmtScanChar(chnl,&b)) goto rt_err; RmtTxPktU1(chnl,(RMT_PKT_ACK^s)&0xFF); RmtWaitTxDone(chnl); xsum=0x3A; for (i=0;ipkt_rx_jiffy=Jiffies; } public void RmtTxBlk(LTChnl *chnl,U1 *buf,I8 cnt) { U1 b[RMT_MAX_PKT_LEN]; U8 size; if (!chnl || !chnl->type) return; while (cnt>0) { if (cnttype) return NULL; result=MAlloc(cnt); buf=result; while (cnt>0) { RmtRxPkt(chnl,b,&size); MemCpy(buf,b,size); cnt-=size; buf+=size; progress1=cnt; } return result; } public U8 RmtGetMsg(LTChnl *chnl,I8 *p1,I8 *p2) { U8 cmd=0,size; U1 b[RMT_MAX_PKT_LEN]; *p1=0; *p2=0; if (!chnl || !chnl->type) return 0; if (Jiffiesnull_msg_jiffy) return 0; try { RmtTxPkt(chnl,NULL,0,RMT_RQST_GETMSG); RmtRxPkt(chnl,b,&size); if (size==sizeof(U8)*3) { cmd=b[0]><(U8); *p1=b[8]><(U8); *p2=b[16]><(U8); } } catch { if (Fs->except_argc==1) { if (Fs->except_argv[0]==EXCP_TIMEOUT) Fs->catch_except=TRUE; } } if (cmd) chnl->null_msg_jiffy=0; else chnl->null_msg_jiffy=Jiffies+RMT_NULL_MSG_DELAY; return cmd; } public void RmtSendMsg(LTChnl *chnl,U8 cmd,I8 p1,I8 p2) { U1 b[RMT_MAX_PKT_LEN]; if (!chnl || !chnl->type) return; if (cmd) { b[0]><(U8)=cmd; b[8]><(U8)=p1; b[16]><(U8)=p2; RmtTxPkt(chnl,b,sizeof(U8)*3); } else { RmtTxPkt(chnl,b,1); chnl->null_msg_cnt++; } } public BoolU4 RmtPutKey(I8 ch,U8 sc) { nounusedwarn sc; if (ch && Fs->rmt_chnl) { try { RmtTxPkt(Fs->rmt_chnl,&ch,1); } catch { if (Fs->except_argc==1) { if (Fs->except_argv[0]==EXCP_TIMEOUT) Fs->catch_except=TRUE; } } } return FALSE; } public void RmtTxBuf(LTChnl *chnl,U1 *buf,U8 size) { if (!chnl || !chnl->type) return; if (buf) { RmtTxBlk(chnl,&size,sizeof(U8)); RmtTxBlk(chnl,buf,size); } } public U1 *RmtRxBuf(LTChnl *chnl,U8 *size=NULL) { U1 *buf; U8 *size2; if (size) *size=0; if (!chnl || !chnl->type) return NULL; size2=RmtRxBlk(chnl,sizeof(U8)); buf=RmtRxBlk(chnl,*size2); if (size) *size=*size2; Free(size2); return buf; } public BoolU4 RmtTxFile(LTChnl *chnl,I1 *filename, BoolU4 raw=TRUE) { U8 size,tries=3; U1 *buf; U4 *good; U1 b[RMT_MAX_PKT_LEN]; LTDirEntry de; if (!chnl || !chnl->type) return; start_tx: if (FindFile(filename,&de)) { buf=ReadFile(filename,&size,NULL,raw); if (buf) { RmtTxBuf(chnl,&de.start,LT_DIR_ENTRY_SIZE); RmtTxBuf(chnl,buf,size); Free(buf); } } RmtRxPkt(chnl,b,&size); good=b; if (size==4 && *good==RMT_FILE_ACK) return TRUE; else { if (!--tries) { coutln "Failed!"; return FALSE; } else { coutln "Retry"; goto start_tx; } } } public U8 RmtRxFile(LTChnl *chnl,I1 *filename, BoolU4 raw=TRUE) { U8 size,tries=3; U4 good; U1 *buf,*buf1; LTDirEntry *de; if (!chnl || !chnl->type) return 0; start_rx: good=0; buf1=RmtRxBuf(chnl); de=buf1-offset(LTDirEntry.start); if (buf=RmtRxBuf(chnl,&size)) { good=RMT_FILE_ACK; if (de->xsum) { if ((de->xsum^ArcCheckSum(buf,de->size))!=LT_XSUM) good=0; } if (good) WriteFile(filename,buf,size,de->datetime,de->attr,raw); else coutln "Bad XSUM"; Free(buf); } Free(buf1); RmtTxPkt(chnl,&good,sizeof(BoolU4)); if (!good) { if (!--tries) { coutln "Failed!"; return 0; } else { coutln "Retry"; goto start_rx; } } else return size; } public void RmtTxPutS(LTChnl *chnl,I1 *st) { U8 len; if (!chnl || !chnl->type) return; if (st) { len=StrLen(st); if (len) { if (len>RMT_MAX_PKT_LEN) { RmtTxPkt(chnl,NULL,0,RMT_RQST_PUTS_CNT); RmtTxBuf(chnl,st,len+1); } else RmtTxBlk(chnl,st,len); } } } public void RmtTxPutChar(LTChnl *chnl,I8 ch) { if (!chnl || !chnl->type) return; if (ch) RmtTxPkt(chnl,&ch,1); } public I1 *RmtRxPutS(LTChnl *chnl,U8 *rqst=NULL) { U1 b[RMT_MAX_PKT_LEN]; U8 size; U1 *buf=NULL; if (!chnl || !chnl->type) return NULL; if (RmtRxFifoCnt(chnl)>=2) { RmtRxPkt(chnl,b,&size,rqst); if (size) { buf=MAlloc(size+1); MemCpy(buf,b,size); buf[size]=0; } else buf=MAllocZ(1); } return buf; } public U1 *RmtRqstTxBuf() { //Remote must fill-in remote's chnl->tx_buf //and remote's chnl->tx_size before calling. LTChnl *chnl=Fs->rmt_chnl; U1 *result; if (!chnl || !chnl->type) return NULL; RmtTxPkt(chnl,NULL,0,RMT_RQST_TX_BUF); result=RmtRxBuf(chnl); return result; } public void RmtRqstRxBuf(U1 *src_local_buf,U8 size) { //Dst buf address is placed in remote's chnl->rx_buf LTChnl *chnl=Fs->rmt_chnl; if (!chnl || !chnl->type) return; RmtTxPkt(chnl,NULL,0,RMT_RQST_RX_BUF); RmtTxBuf(chnl,src_local_buf,size); } public void RmtRqstTxFile(I1 *dst_local_filename,I1 *src_remote_filename) { LTChnl *chnl=Fs->rmt_chnl; if (!chnl || !chnl->type) return; RmtTxPkt(chnl,NULL,0,RMT_RQST_TX_FILE); RmtTxBuf(chnl,src_remote_filename,StrLen(src_remote_filename)+1); RmtRxFile(chnl,dst_local_filename); } public void RmtRqstRxFile(I1 *src_local_filename,I1 *dst_remote_filename) { LTChnl *chnl=Fs->rmt_chnl; if (!chnl || !chnl->type) return; RmtTxPkt(chnl,NULL,0,RMT_RQST_RX_FILE); RmtTxBuf(chnl,dst_remote_filename,StrLen(dst_remote_filename)+1); RmtTxFile(chnl,src_local_filename); } public void RmtRqstExeLocal(I1 *st) { LTChnl *chnl=Fs->rmt_chnl; if (!chnl || !chnl->type) return; RmtTxPkt(chnl,NULL,0,RMT_RQST_EXE_LOCAL); RmtTxBuf(chnl,st,StrLen(st)+1); } public void TelnetHostOpen(LTChnl *chnl) //Allows remote telnet user to control //this task. Will still allow local //control. { if (!chnl || !chnl->type) return; Fs->rmt_chnl=chnl; } public void TelnetHostClose() { Fs->rmt_chnl=NULL; } public void TelnetGuestOpen(LTChnl *chnl) { U8 i,cmd,p1,p2,rqst; U1 *st,*st2; BoolU4 cont=TRUE,msg_sent=TRUE; BoolU4 old_preempt=Preempt(OFF); if (!chnl || !chnl->type) return; Fs->local_chnl=chnl; coutln "$$BK 1$$CTRL-ALT-B to break$$BK 0$$"; for (i=0;i<4;i++) { chnl->PutChar(chnl,RMT_PKT_RESET); chnl->PutChar(chnl,RMT_PKT_RESET); Sleep(100); } while (cont) { try { Fs->task_flags&=~(1<task_flags&=~(1<null_msg_cnt=0; switch (rqst) { case RMT_RQST_NONE: PutS(st2); break; case RMT_RQST_GETMSG: if (msg_sent) cmd=ScanMsg(&p1,&p2, 1<task_flags|=1<tx_buf,chnl->tx_size); break; case RMT_RQST_RX_BUF: chnl->rx_buf=RmtRxBuf(chnl); break; case RMT_RQST_EXE_LOCAL: st=RmtRxBuf(chnl); ExecuteStr(st); Free(st); break; case RMT_RQST_PUTS_CNT: Free(st2); st2=RmtRxBuf(chnl); PutS(st2); break; } Free(st2); st2=NULL; } else { Fs->task_flags|=1<except_argc==1) { if (Fs->except_argv[0]==EXCP_TIMEOUT) { Fs->catch_except=TRUE; cont=TRUE; } } if (!cont) { Fs->local_chnl=NULL; Preempt(old_preempt); } } } Fs->local_chnl=NULL; Preempt(old_preempt); } BoolU8 RmtPutS(I1 *st) { if (Fs->rmt_chnl) { try RmtTxPutS(Fs->rmt_chnl,st); catch { if (Fs->except_argc==1) { if (Fs->except_argv[0]==EXCP_TIMEOUT) Fs->catch_except=TRUE; } } } return FALSE; } AddKeyDev(&RmtPutKey,&RmtPutS,0xA0000000); #help_index ""