home *** CD-ROM | disk | FTP | other *** search
- /*
- ** --- term.c ---
- **
- ** EXAMPLE CODE: Terminal emulator. Can transfer files using
- ** ASCII, XMODEM, YMODEM, and ZMODEM protocols.
- **
- ** See TERM.CFG for configuration parameters.
- **
- ** Link with ALLOCSEG, TERM_IO, MODEM_IO, DIR_IO, CRC16, CRC32, DOS,
- ** AMODEM, XYMODEM, XYPACKET, SI, OPCODES, and WIN_IO. Files SI.C and
- ** OPCODES.C used for scripts only. See TERM makefiles and TERM.CFG.
- **
- ** Do NOT select YMODEM-G when using a null modem cable unless you are
- ** certain that RTS & CTS are reversed ( this is usually not true ).
- **
- ** This example program (not the PCL4C library) is donated to
- ** the Public Domain by MarshallSoft Computing, Inc. It is
- ** provided as an example of the use of the PCL4C.
- **
- */
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <ctype.h>
- #include <fcntl.h>
- #include <string.h>
- #include <sys\types.h>
- #include <sys\stat.h>
- #include <malloc.h>
- #include <dos.h>
- #include <io.h>
- #include <conio.h>
- #include "term.cfg"
- #include "pcl4c.h"
- #include "ascii.h"
- #include "term.h"
- #include "dir_io.h"
- #include "term_io.h"
- #include "dos_io.h"
- #include "modem_io.h"
- #include "crc16.h"
- #include "crc32.h"
- #include "xymodem.h"
- #include "zmodem.h"
- #include "amodem.h"
- #include "term.h"
- #include "allocseg.h"
- #include "timing.h"
- #include "win_io.h"
- #if SCRIPTS
- #include "si.h"
- #endif
-
- #define DEBUG 0
-
- #define ATTN_CHAR 0x1a
- #define ABORT_CHAR CAN
-
- #define FALSE 0
- #define TRUE !FALSE
- #define WORD unsigned int
-
- #define NORMAL 0x07
- #define INVERSE 0x70
- #define MESSAGE_POS 48
-
- /* local prototypes */
-
- void ProcessESC(void);
- void ShowStatus(void);
- void StatusMsg(char,char *);
- void CheckWin(int);
- void SetASCII(void);
- void SetX(void);
- void SetY(void);
- void SetG(void);
- void SetZ(void);
-
- /*** Global variables ***/
-
- #define SIOBUF_SIZE 2048
- #define BLKBUF_SIZE 1024
-
- int LastError = 0; /* last reported error # */
- int Port; /* current COM port [0..3] */
- char FileSpec[15]; /* file name specification */
- char FileName[15]; /* file name buffer */
- char Buffer[BLKBUF_SIZE]; /* 1K block buffer */
- char *BaudRate[10] = {"300","600","1200","2400","4800","9600",
- "19200","38400","57600","115200"};
- int BaudCode; /* baud rate code ( index into BaudRate[] ) */
- char *ModelText[4] = {"Small","Compact","Medium","Large"};
- char NCGchar = NAK;
- int OneKflag = FALSE;
- int BatchFlag = FALSE;
- char Protocol = 'X';
- char TermChar = 0x00;
- int CharPace = 0;
- int Timeout = 10;
- int EchoFlag = TRUE;
- int TraceFlag = FALSE;
- int Stream = FALSE;
-
- int MultiUART = 0;
- int MultiIRQ = 0;
- int MultiStatus = 0;
-
- /*** main program ***/
-
- void main(int argc,char *argv[])
- {int DataFlag = FALSE;
- char c;
- int i, k;
- int n, rc;
- int Delta; /* delta port status */
- int Status; /* port status */
- int Version;
- char Temp[81];
- /* right number of parameters ? */
- if((argc<3)||(argc>4))
- {printf("Usage: 'TERM port baud' -- example 'TERM 1 9600 {script}'\n");
- exit(1);
- }
- /* get port number from command line */
- Port = atoi(argv[1]) - 1;
- if((Port<0) || (Port>15))
- {printf("Port must be 1 to 16\n");
- exit(1);
- }
- /* get baud rate from command line */
- BaudCode = BaudMatch(argv[2]);
- if(BaudCode<0)
- {printf("Cannot recognize baud rate = %s\n",argv[2]);
- exit(1);
- }
- /* can ZMODEM stream ? */
- if(BaudCode<=Baud19200) Stream = TRUE;
- else Stream = FALSE;
-
- #if 0
- /*** Custom Configuration: 4 port card ***/
- SioIRQ(COM1,IRQ4);
- SioIRQ(COM2,IRQ3);
- SioIRQ(COM3,IRQ4);
- SioIRQ(COM4,IRQ3);
- #endif
-
- #if 0
- /*** Custom Configuration: DigiBoard PC/8 ***/
- MultiUART = 0x100; MultiIRQ = IRQ5; MultiStatus = 0x140;
- printf("Configuring DigiBoard as COM1-COM8 (IRQ%d) @ 0x%x",
- MultiIRQ,MultiUART);
- SioDelay(18);
- /* use 0x140 for odd IRQs & 0x141 for even IRQs */
- SioPorts(8,COM1,MultiStatus,DIGIBOARD);
- /* set DigiBoard UART addresses */
- ErrorCheck( SioUART(Port,MultiUART+8*Port) );
- /* set DigiBoard for IRQ */
- ErrorCheck( SioIRQ(Port,MultiIRQ) );
- #endif
-
- #if 0
- /*** Custom Configuration: BOCA 16 port dumbcard ***/
- MultiUART = 0x280; MultiIRQ = IRQ11; MultiStatus = MultiUART + 7;
- printf("Configuring BOCA Board as COM1-COM16 (IRQ%d) @ 0x%x",
- MultiIRQ,MultiUART);
- SioDelay(18);
- /* use base port + 7 */
- SioPorts(16,COM1,MultiStatus,BOCABOARD);
- /* set BOCA Board UART addresses */
- ErrorCheck( SioUART(Port,MultiUART+8*Port) );
- /* set BOCA Board for IRQ */
- ErrorCheck( SioIRQ(Port,MultiIRQ) );
- #endif
-
- /********************************************************/
-
- /* setup receive buffer */
- ErrorCheck( SioRxBuf(Port,AllocSeg(2048),Size2K) );
- if(SioInfo('I'))
- {/* setup transmit buffer */
- ErrorCheck( SioTxBuf(Port,AllocSeg(2048),Size2K) );
- }
- /* set parms & reset (initialize) COM port */
- SioParms(Port,NoParity,OneStopBit,WordLength8);
- /* reset port */
- rc = SioReset(Port,BaudCode);
- if(rc<0) rc = SioReset(Port,BaudCode);
- if(rc<0)
- {printf("Cannot reset COM%d\n",1+Port);
- exit(1);
- }
- /* set DTR and RTS */
- SioDTR(Port,'S');
- SioRTS(Port,'S');
-
- /*
- ** !!! Define window screens !!!
- ** Use win_io function from now on
- */
-
- /* define main screen window */
- CheckWin( WinCreate(SCR_WIN, 0,0, 23,79) );
- CheckWin( WinNormal(SCR_WIN) );
- CheckWin( WinClear(SCR_WIN) );
- /* define left status window */
- CheckWin( WinCreate(LFT_WIN, 24,0, 24,30) );
- CheckWin( WinInverse(LFT_WIN) );
- CheckWin( WinClear(LFT_WIN) );
- /* define right status window */
- CheckWin( WinCreate(RGT_WIN, 24,32, 24,79) );
- CheckWin( WinInverse(RGT_WIN) );
- CheckWin( WinClear(RGT_WIN) );
-
- /* display status message */
- ShowStatus();
- /* display some info */
- WinPutString(SCR_WIN,"TERM: 11/11/95 [C/C++]\n\n");
- Version = SioInfo('V');
- sprintf(Temp," Library: %d.%d\n",Version>>4,0x0f&Version);
- WinPutString(SCR_WIN,Temp);
- sprintf(Temp," Memory Model: %s\n",ModelText[3&SioInfo('M')] );
- WinPutString(SCR_WIN,Temp);
- strcpy(Temp," Interrupts: ");
- if(SioInfo('I')) strcat(Temp,"YES\n");
- else strcat(Temp,"NO\n");
- WinPutString(SCR_WIN,Temp);
- WinPutString(SCR_WIN," Parameters: 8N1\n");
- #if RTS_CTS_CONTROL
- SioFlow(Port,10*ONE_SECOND);
- WinPutString(SCR_WIN," Flow Control: YES\n");
- #else
- WinPutString(SCR_WIN," Flow Control: NO\n");
- #endif
-
- /* Set FIFO level */
- WinPutString(SCR_WIN," 16550 UART: ");
- if( SioFIFO(Port,LEVEL_14) ) WinPutString(SCR_WIN,"YES\n");
- else WinPutString(SCR_WIN,"NO\n");
- /* clear PCL4C receive buffer */
- ErrorCheck( SioRxClear(Port) );
- WinPutChar(SCR_WIN,'\n');
-
- /* wait for other end to say its ready */
- WinPutString(SCR_WIN," <<Waiting for DSR>>\n");
- while( !SioDSR(Port) )
- {if(kbhit()||SioBrkKey()) MyExit(0,"Aborted by user");
- WinPutChar(SCR_WIN,'.');
- SioDelay(18);
- }
- WinPutString(SCR_WIN," <<DSR on>>\n");
-
- #if RTS_CTS_CONTROL
- WinPutString(SCR_WIN," <<Waiting for CTS>>\n");
- while( !SioCTS(Port) )
- {if(kbhit()||SioBrkKey()) MyExit(0,"Aborted by user");
- WinPutChar(SCR_WIN,'.');
- SioDelay(18);
- }
- WinPutString(SCR_WIN," <<CTS on>>\n");
- #endif
-
- #if AT_COMMAND_SET
- /* initialize (Hayes compatible) modem */
- ModemSendTo(Port,4,"AT!");
- ModemEcho(Port,10);
- ModemSendTo(Port,4,"AT E1 S7=60 S11=60 V1 X1 Q0!");
- if(ModemWaitFor(Port,5*ONE_SECOND,TRUE,"OK"))
- {/* modem is ready */
- WinPutString(SCR_WIN,"\n <<MODEM READY>>");
- }
- else WinPutString(SCR_WIN,"\n <<WARNING: Expected OK not received>>\n");
- #endif
- SetX();
-
- #if SCRIPTS
- if(argc==4)
- {/* call script interpreter */
- sprintf(Temp,"Starting script %s\n",argv[3]);
- WinPutString(SCR_WIN,Temp);
- i = si(Port,argv[3],FALSE);
- if(i<0) SaySiErr(i);
- }
- #endif
-
- /* enter terminal loop */
- SioRxClear(Port);
- WinPutString(SCR_WIN," <<Entering terminal loop>>\n");
- while(1)
- {/* Control-BREAK ? */
- if(SioBrkKey()) MyExit(0,"User pressed Ctrl-BREAK");
- /* keep TX rolling */
- SioTxFlush(Port);
- /* was key pressed ? */
- if(kbhit())
- {/* read key press */
- i = getch();
- /* ^B sends BREAK */
- if((char)i=='\02')
- {/* send break */
- WriteMsg("Sending BREAK");
- SioBrkSig(Port,'A');
- SioDelay(10);
- SioBrkSig(Port,'C');
- }
- else if((char)i==ATTN_CHAR)
- {/* process user's request */
- ProcessESC();
- ShowStatus();
- continue;
- }
- else CharPut(Port,(char)i);
- }
- /* was break detected ? */
- if( SioBrkSig(Port,'D') ) WriteMsg("BREAK detected ");
- /* check DSR */
- if(TestDSR(Port))
- {/* any incoming over serial port ? */
- i = CharGet(Port,1);
- if(i>-1)
- {/* good character */
- if(DataFlag&((i<0x20)||(i>0x7e)))
- {WinPutChar(SCR_WIN,'^');
- WinPutChar(SCR_WIN,(char)('@'+i));
- }
- else WinPutChar(SCR_WIN,(char)i);
- }
- }
- } /* end -- key pressed */
- }
-
- /*** find baud rate string in table ***/
-
- int BaudMatch(char *ptr)
- {int i;
- /* find baud rate in table */
- for(i=0;i<10;i++) if(strcmp(BaudRate[i],ptr)==0) return(i);
- return(-1);
- }
-
- /*** user pressed Escape */
-
- void ProcessESC(void)
- {int i;
- int rc;
- int c1, c2;
- char Answer[2]; /* answer array */
- /* user pressed ATTN_CHAR */
- Answer[0] = '?';
- Answer[1] = '\0';
- WriteMsg("Q)uit P)rotocol S)end R)eceive T)race: ");
- ReadMsg(Answer,1,39);
- if(strlen(Answer)) switch(toupper(Answer[0]))
- {
- case 'T':
- /*SetIOtrace(TRUE);*/
- TraceFlag = !TraceFlag;
- WriteIntMsg("Trace = ",1&TraceFlag);
- MsgEcho(TraceFlag);
- break;
- case 'P':
- WriteMsg("A)scii X)modem Y)modem Z)modem: ");
- ReadMsg(Answer,1,32);
- if(strlen(Answer)) switch( toupper(Answer[0]) )
- {case 'A':
- SetASCII();
- break;
- case 'X':
- SetX();
- break;
- case 'Y':
- SetY();
- break;
- case 'Z':
- SetZ();
- break;
- #if RTS_CTS_CONTROL
- case 'G':
- SetG();
- break;
- #endif
- default:
- WriteMsg("Must answer X, Y, or Z");
- break;
- }
- ShowStatus();
- break;
- case 'Q':
- SetIOtrace(FALSE);
- MyExit(0,"User QUIT");
- break;
- case 'R':
- StatusMsg(ABORT_CHAR,"aborts");
- *FileName = '\0';
- switch(Protocol)
- {case 'A':
- /* Ascii */
- RxAscii(Port,FileName,Buffer,BLKBUF_SIZE,SIOBUF_SIZE,FALSE,TermChar,Timeout,EchoFlag);
- break;
- case 'X':
- XmodemRx(Port,FileName,Buffer,NCGchar);
- break;
- case 'Y':
- YmodemRx(Port,Buffer,NCGchar);
- break;
- case 'Z':
- ZmodemRx(Port,Stream);
- break;
- }
- while(kbhit()) getch();
- break;
- case 'S':
- *FileName = '\0';
- StatusMsg(ABORT_CHAR,"aborts");
- switch(Protocol)
- {case 'A': /* Ascii */
- TxAscii(Port,FileName,Buffer,BLKBUF_SIZE,FALSE,CharPace,TermChar,EchoFlag);
- break;
- case 'X':
- XmodemTx(Port,FileName,Buffer,OneKflag);
- break;
- case 'Y':
- YmodemTx(Port,FileName,Buffer);
- break;
- case 'Z':
- ZmodemTx(Port,FileName,Stream);
- break;
- }
- while(kbhit()) getch();
- break;
- default:
- WriteHexMsg("Must answer Q, P, S, R, or T, not ",*Answer);
- break;
- } /* end switch */
- }
-
- /*** show menu message ***/
-
- void StatusMsg(char Attn,char *Msg)
- {char Temp[50];
- sprintf(Temp," COM%d %s %c [ ^%c %s ]",
- 1+Port,BaudRate[BaudCode],Protocol,Attn+'@',Msg);
- WinClear(LFT_WIN);
- WinPutString(LFT_WIN,Temp);
- WinGetPos(SCR_WIN,NULL,NULL);
- }
-
- void ShowStatus(void)
- {
- StatusMsg(ATTN_CHAR,"for Menu");
- }
-
- /*** exit program ***/
-
- void MyExit(int code, char *msg)
- {int i, rc;
- char Temp[80];
- if(code<0)
- {WinPutChar(SCR_WIN,' ');
- SioError(code);
- WinPutChar(SCR_WIN,'\n');
- }
- SioDone(Port);
- sprintf(Temp,"\rTERMINATING: %s\n",msg);
- WinPutString(SCR_WIN,Temp);
- SetCursor(6,7);
- exit(0);
- }
-
- /*** check for error ***/
-
- void ErrorCheck(int Code)
- {/* trap PCL error codes */
- if(Code<0)
- {
- WinPutChar(SCR_WIN,' ');
- SioError(Code);
- SioDone(Port);
- exit(1);
- }
- } /* end ErrorCheck */
-
- int GetBufSize(void)
- {int BufSize = SIOBUF_SIZE;
- return BufSize;
- }
-
- void CheckWin(int n)
- {if(n<0)
- {printf("\nWin error %d\n\n",n);
- exit(1);
- }
- }
-
- /* set protocol parameters */
-
- void SetASCII(void)
- {Protocol = 'A';
- TermChar = 0x18; /* CAN or control-X */
- CharPace = 0; /* no inter-byte delay */
- Timeout = 7; /* timeout after 7 seconds */
- EchoFlag = TRUE; /* do local echo */
- WriteMsg("Protocol = ASCII");
- }
-
- void SetX(void)
- {Protocol = 'X';
- OneKflag = FALSE;
- BatchFlag = FALSE;
- NCGchar = NAK;
- WriteMsg("Protocol = XMODEM");
- }
-
- void SetY(void)
- {Protocol = 'Y';
- OneKflag = TRUE;
- BatchFlag = TRUE;
- NCGchar = 'C';
- WriteMsg("Protocol = YMODEM");
- }
-
- void SetG()
- {Protocol = 'G';
- OneKflag = TRUE;
- BatchFlag = TRUE;
- NCGchar = 'G';
- WriteMsg("Protocol = YMODEM-G");
- }
-
- void SetZ(void)
- {Protocol = 'Z';
- WriteMsg("Protocol = ZMODEM");
- }