/* ** ASCII text file transfer using XON / OFF flow control protocol. ** Transfer ASCII files only. Do not attempt to transfer binary files. */ #include #include #include #include #include #include #include #include "pcl4c.h" #include "ascii.h" #include "term_io.h" #include "xymodem.h" #include "amodem.h" #include "term.h" #define FALSE 0 #define TRUE !FALSE #define ONE_SECOND 18 char lastXchar; /* last XON or XOFF sent */ int TxAscii( int Port, /* COM port [0..3] */ char Filename[], /* filename buffer */ char Buffer[], /* data buffer */ int Length, /* size of Buffer */ int SyncFlag, /* synchronize with XON 1st */ int CharPace, /* millisecond delay after sending each character */ int TermChar, /* termination character (0x00 ==> none) */ int EchoFlag) /* do local echo if TRUE */ {int i; int Code; /* return code */ int Handle; /* file Handle */ char LastChar; /* last character sent */ int TxChars = 0; /* # characters transmitted */ int Count; /* # bytes read from disk */ char Temp[81]; /* temporary buffer */ /* begin */ Handle = open(Filename,O_RDONLY|O_BINARY,S_IREAD); if(Handle<0) {strcpy(Temp,"Cannot open "); strcat(Temp,Filename); DisplayLine(Temp,NULL,0); return(FALSE); } /* do we wait for XON before starting ? */ if(SyncFlag) {/* wait for incoming XON */ DisplayLine("ASCII: Waiting for XON",NULL,0); while(1) {if(SioBrkKey()) {DisplayLine("Canceled by USER",NULL,0); return(FALSE); } Code = SioGetc(Port,ONE_SECOND); if(Code==-1) continue; if(Code<0) return(FALSE); if((char)Code==XON) {DisplayLine("ASCII: initial XON received",NULL,0); /* slight delay */ SioDelay(ONE_SECOND/2); break; } /* received character not XON */ MyCrtWrite((char)Code); } } /* begin transfer */ lastXchar = XON; DisplayLine("ASCII: Starting send",NULL,0); while(SioKeyPress()) SioKeyRead(); /* clear comm port */ SioRxFlush(Port); /* send ascii file ( stop at ^Z ) */ while(1) {/* read next buffer from disk */ Count = read(Handle,Buffer,Length); if(Count==0) break; if(Count<0) {SayError(Port,"Error on disk read"); return(FALSE); } /* send one byte at a time */ for(i=0;i0) SioDelay(CharPace); /* slight delay after each line */ if(LastChar==LF) SioDelay(4*(CharPace+1)); TxChars++; /* ^Z marks the end of a text file */ if(LastChar==CTLZ) break; /* check for incoming XON */ if(lastXchar==XON) {/* check for incoming XON / XOFF */ Code = GetChar(Port,0); if(Code>0) {/* is byte a XOFF ? */ if((char)Code==XOFF) {/* wait for XON */ DisplayLine("XOFF received",NULL,0); lastXchar = XOFF; /* wait for XON */ while(1) {/* user want to quit ? */ if(SioBrkKey()) {DisplayLine("Canceled by USER",NULL,0); return(FALSE); } Code = GetChar(Port,ONE_SECOND); if((char)Code==XON) {DisplayLine("XON received",NULL,0); lastXchar = XON; break; } } /* end -- while */ } /* end -- if(XOFF) */ } /* end -- if(Code) */ } /* end -- if(XON) */ } /* end -- for(i) */ } /* end -- while */ close(Handle); /* send termination character */ if(TermChar) PutChar(Port,(char)TermChar); DisplayLine("ASCII: Transfer Complete",NULL,0); return(TRUE); } /* end -- TxAcsii */ int RxAscii( int Port, /* COM port [0..3] */ char Filename[], /* filename buffer */ char Buffer[], /* data buffer */ int Length, /* length of data buffer */ int RxQueSize, /* size of PCL receive buffer */ int SyncFlag, /* synchronize with XON 1st */ int TermChar, /* termination character (0x00 ==> none) */ int TimeOut, /* delay (seconds) before assuming that sender is done */ int EchoFlag) /* do local echo if TRUE */ {int i; int Handle; /* file Handle */ int Code; /* return code */ int lo; /* receive queue low water mark */ int hi; /* receive queue high water mark */ int Index; /* buffer index */ int QueSize; /* current PCL receive queue size */ int RxChars = 0; /* # received chars */ int Count; /* # characters written to disk */ char Temp[81]; /* temporary buffer */ long LastTime; /* time last character was received */ /* begin */ lastXchar = XON; lo = RxQueSize / 8; hi = 5 * lo; DisplayLine("ASCII: Starting receive ",NULL,0); while(SioKeyPress()) SioKeyRead(); /* clear comm port */ SioRxFlush(Port); /* open file passed in Filename[] for write */ Handle = open(Filename,O_CREAT|O_TRUNC|O_WRONLY|O_BINARY,S_IWRITE); if(Handle<0) {strcpy(Temp,"Cannot open "); strcat(Temp,Filename); DisplayLine(Temp,NULL,0); return(FALSE); } /* sync with XON 1st ? */ if(SyncFlag) {DisplayLine("ASCII: Sending initial XON",NULL,0); while(1) {SioPutc(Port,XON); Code = SioGetc(Port,ONE_SECOND); if(Code==-1) continue; /* transmitter is sending ! */ SioUnGetc(Port,Code); break; } } /* receive text */ LastTime = SioTimer(); Index = 0; while(1) {/* user want to quit ? */ if(SioBrkKey()) {DisplayLine("Canceled by USER",NULL,0); return(FALSE); } /* check on PCL receive queue size */ QueSize = SioRxQue(Port); if((QueSize>hi)&&(lastXchar==XON)) {PutChar(Port,XOFF); lastXchar = XOFF; DisplayLine("sending XOFF(1)",NULL,0); /*printf("\nQueSize=%d lo=%d hi=%d\n",QueSize,lo,hi);*/ } if((QueSizeONE_SECOND*TimeOut) {/* sender must be done */ Buffer[Index] = CTLZ; break; } continue; } /* ignore 1st character if it is a 0 */ if((RxChars==0)&&((char)Code=='\0')) continue; LastTime = SioTimer(); /* ignore XON & XOFF ( since we are the receiver ) */ if((char)Code==XON) continue; if((char)Code==XOFF) continue; /* received a character */ Buffer[Index++] = (char)Code; RxChars++; /* TermChar marks the end of a text file */ if((char)Code==TermChar) {/* replace TermChar with ^Z */ Buffer[Index-1] = CTLZ; RxChars++; break; } if(EchoFlag) MyCrtWrite((char)Code); if(Index==Length) {/* send XOFF to transmitter */ PutChar(Port,XOFF); lastXchar = XOFF; DisplayLine("sending XOFF(2)",NULL,0); /* write disk file */ Count = write(Handle,Buffer,Index); if(Count<0) {SayError(Port,"Disk read error"); SioDelay(ONE_SECOND); return(FALSE); } /* send XON to sender */ PutChar(Port,XON); lastXchar = XON; DisplayLine("sending XON ",NULL,0); Index = 0; } /* end -- if */ } /* end -- while */ /* write any remaining data in buffer */ if(Index>0) {Count = write(Handle,Buffer,Index); if(Count<0) {SayError(Port,"Disk read error"); SioDelay(ONE_SECOND); return(FALSE); } } /* end -- if */ close(Handle); DisplayLine("ASCII: Transfer Complete",NULL,0); return(TRUE); } /* RxAscii */ int UserAborts(int Port) {char UserChar; /* user aborts ? */ if(SioKeyPress()) {UserChar = (char)SioKeyRead(); if(UserChar==CAN) {TxCAN(Port); SioPutc(Port,ETX); DisplayLine("*** Canceled by USER ***",NULL,0); return(TRUE); } /* send user char */ SioPutc(Port,UserChar); } return(FALSE); } /* UserAborts */