File:  [OS/2 SDKs] / os2sdk / demos / apps / terminal / modem.c
Revision 1.1.1.2 (vendor branch): download - view: text, annotated - select for diffs
Thu Aug 9 12:26:01 2018 UTC (7 years, 9 months ago) by root
Branches: msft, MAIN
CVS tags: os2sdk-1988, HEAD
Microsoft OS/2 SDK 03-01-1988

/***	modem.c
 *
 * TITLE 
 *
 *	modem.c
 *	Created by Microsoft Corporation 1987
 *
 * DESCRIPTION
 *
 * 	This module contains routines that support Hayes compatible modem. 
 *
 ***/

#define     INCL_DOSDEVICES
#define     INCL_DOSFILEMGR
#define     INCL_DOSPROCESS

#include	<os2def.h>
#include	<bse.h>
#include	<stdio.h>	
#include	<malloc.h>
#include	<string.h>
#include 	<memory.h>
#include 	<conio.h>
#include 	"term.h"

#define min(a,b) (((a)<(b)) ? (a):(b))	/* This is pulled out of the old */
					/* v2tov3.h (c v2.0) header file */

extern char 	*ErrMsg[]; 
extern HFILE FileHndl;

make_dial_cmd(char *, int);
void flush_ques(USHORT);
void clr_com_error(void);
void com_clr_flush(void);

static char Init[]    = {'A', 'T', 'V', '0', 0x0d};
static char Attn[]    = {'A', 'T', 0x0d};
static char Esc[]     = {'+', '+', '+'};
static char OnHook[]  = {'A', 'T', 'H', '0', 0X0d};
static char OffHook[] = {'A', 'T', 'H', '1', 0x0d};
static char Reset[]   = {'A', 'T', 'Z', 0x0d};

struct s_Cmd{
        char *pCmd;
        int   CmdLen;
} Cmds[] = {
    {Init, sizeof(Init)},        	/* Initialize modem */
    {Attn, sizeof(Attn)},        	/* Attention cmd */
    {Esc, sizeof(Esc)},          	/* Modem escape sequence*/
    {OnHook, sizeof(OnHook)},    	/* Put phone on hook */
    {OffHook, sizeof(OffHook)},  	/* Take phone off hook */
    {Reset, sizeof(Reset)}       	/* Reset command */
  };



/***	make_modem_conn - make modem connection
 *
 *	This routine tries to setup the modem connection, retrying if 
 *	appropriate.
 *
 *	make_modem_conn()
 *
 *	ENTRY
 *
 *	EXIT
 *		TRUE if modem connection was made 
 *		FALSE if modem connection did not go through
 *
 *	WARNING
 *
 *	EFFECTS
 *
 ***/

make_modem_conn()
{
	USHORT		NumBytes;	/* number of bytes to be written    */
	unsigned	RetCode,	/* return code from system calls    */
			Result = FALSE; /* to be returned by this routine */
	char		OutBuffer,
			ModemRetry = TRUE,   /* retry for modem connection   */
			NumRetries = 0;      /* no. times connection retried */

	printf("trying modem connection...\n");

  	while (ModemRetry)
          switch (setup_modem_conn()) {
	    case MS_CONNECT    :
	    case MS_CONNECT1200: 
	      Result = TRUE;
	      ModemRetry = FALSE;
	      OutBuffer = '\r';
	      if ((RetCode = DosWrite(FileHndl, &OutBuffer, 1,
                                      &NumBytes)) != 0)
	        error(ERR_DOSWRITE, RetCode);
              break;
	    case MS_NOCARRIER  :
	    case MS_NODIALTONE :
	      if (++NumRetries > NUM_RETRY) {
	        printf("modem connection failed\n");
	        ModemRetry = FALSE;
	      }
	      else
	        printf("modem connection failed; retrying...\n");
	      break;
	    case MS_NOREPLY    :
            case MS_ERROR      : 
	    case OT_FAILURE    :		/* OTher failure */
            case MS_BUSY       : 
	    default            : 
	      ModemRetry = FALSE;
              printf("modem connection failed\n");
              break;
	  }		/* switch (setup_modem_conn()) */

	return(Result);

}




/***	setup_modem_conn - setup modem connection
 *
 *	This is the helper routine for the make_modem_conn(). It initialises
 *	the modem connection and sends out the dial command to the modem.
 *
 *	setup_modem_conn()
 *
 *	ENTRY
 *
 *	EXIT
 *		returns one of the following: MS_CONNECT MS_CONNECT1200 
 *	    	MS_NOCARRIER MS_NODIALTONE MS_NOREPLY MS_ERROR MS_BUSY 
 *	    	OT_FAILURE
 *
 *	WARNING
 *
 *	EFFECTS
 *
 ***/

int	setup_modem_conn()
{
	int		Result = OT_FAILURE;

	/* initialise modem connection */
	if (!(send_modem_cmd(MC_INIT)))
	  return(Result);
	if (get_modem_reply() != MS_OK)
	  return(Result);
	DosSleep(100L);

	/* write AT string to the modem. This will cause the modem to
	 * determine the communications rate of the terminal as well
	 * as its parity setting.
 	 */
	if (!(send_modem_cmd(MC_ATTN)))
	  return(Result);
	if (get_modem_reply() != MS_OK)
	  return(Result);
	DosSleep(100L);

	/* send DIAL command to the modem */
	if (!(send_modem_cmd(MC_DIAL)))
	  return(Result);

	return(get_modem_reply());
};




/***	send_modem_cmd - send a command to modem
 *
 *	This routine sends a command to the modem and ensures that the echo 
 *	from the modem matches the input command.
 *
 *	send_modem_cmd(CmdType)
 *
 *	ENTRY
 *		CmdType - type of modem command: MC_INIT MC_ATTN MC_ESC 
 *		          	MC_ONHOOK MC_OFFHOOK MC_RESET MC_DIAL
 *
 *	EXIT
 *		TRUE if command was sent succesfully
 *		FALSE if command failed
 *
 *	WARNING
 *
 *	EFFECTS
 *
 ***/

send_modem_cmd(CmdType)
int 	CmdType;            	/* The command to send */
{
    	int  		Result = TRUE,
			RetCode;
	USHORT		WriteCnt,
			ReadCnt,
			CmdLen;
    	char 		Buf[80],
    			Cmd[80],
    			*pDst,
    			*pCmd;
	

	/* clear COM error and flush transmit/receive queues */
	com_clr_flush();

        if (CmdType == MC_INIT) {
	  send_modem_cmd(MC_RESET);	/* modem command: ATZ */
	  /* clear COM error and flush transmit/receive queues */
	  com_clr_flush();
	};

	/* set pCmd -> command string; CmdLen = length of command string */
    	if (CmdType == MC_DIAL) {
          CmdLen = make_dial_cmd(Cmd, sizeof(Cmd));
          pCmd = Cmd;
        }
    	else {
          pCmd = Cmds[CmdType].pCmd;
          CmdLen = Cmds[CmdType].CmdLen;
        };

	/* write the command out to the modem */
	if (((RetCode = DosWrite(FileHndl, pCmd, CmdLen, &WriteCnt)) != 0)
	    || (WriteCnt != CmdLen))
	  return(FALSE);

        /* wait for the echo & wait for the command to clear */
	DosSleep(250L);
        if (CmdType == MC_DIAL || CmdType == MC_RESET)
	  DosSleep(750L);

	/* read back the echo from the modem & check if it matches the input */
	RetCode = 
	  DosRead(FileHndl, Buf, min(WriteCnt, sizeof(Buf)), &ReadCnt);
	if ((RetCode != 0) || (ReadCnt != WriteCnt))
	  Result = FALSE;
        else {
          pDst = Buf;
          while (--ReadCnt >= 0) {
            if (*pDst++ != *pCmd++) {
	      printf("send_modem_cmd: error in echo of modem input\n");
              Result = FALSE;
              break;
            }
          } /* while (--ReadCnt >= 0) */
        } 

    	return(Result);
}




/***	make_dial_cmd - create a modem command for dialing 
 *
 *	builds the dial command string and returns its length in bytes
 *
 *	make_dial_cmd(pBuf, BufLen)
 *
 *	ENTRY
 *		pBuf - ptr to buffer
 *	        BufLen - length of buffer in bytes
 *
 *	EXIT
 *		pBuf -> dial command string
 *	        make_dial_cmd = length of dial command string in bytes 
 *
 *	WARNING
 *
 *	EFFECTS
 *
 ***/

make_dial_cmd(pBuf, BufLen)
char 	*pBuf;
int  	BufLen;
{
    	char 		*pSrc,
    			*pDst,
    			Ch,
    			Cmd[80],  	/* allocate a huge command buffer */
			*bin_to_dec();
    	int   		Len;
	structModemOptions sModemOptions;		/* modem options */

	get_modem_options(&sModemOptions);
    	pDst = Cmd;
    	*pDst++ = 'A';          /* get Modem's attention */
    	*pDst++ = 'T';
    	*pDst++ = 'S';          /* set R6 for wait for dial tone */
    	*pDst++ = '6';
    	*pDst++ = '=';
    	pDst = bin_to_dec(pDst, sModemOptions.iWaitTone);
    	*pDst++ = B_PAUSE;
    	*pDst++ = 'S';          /* set R7 for wait for carrier time */
    	*pDst++ = '7';
    	*pDst++ = '=';
    	pDst = bin_to_dec(pDst, sModemOptions.iWaitCarrier); 
    	*pDst++ = B_PAUSE;
    	*pDst++ = 'D';
    	*pDst++ = (sModemOptions.chDialType == PULSE) ? 'P' : 'T';
    	pSrc = sModemOptions.pPhoneNumber;
    	while (Ch = *pSrc++) 
          if ((Ch >= '0' && Ch <= '9') || (Ch == ','))
            *pDst++ = Ch;
    	*pDst++ = 0x0d;
    	*pDst = 0;

    	/* copy the command string into caller's buffer */
    	pSrc = Cmd;
    	pDst = pBuf;
    	for (Len = 0; Len <= BufLen; ++Len)
          if (*pSrc==0)
            break;
          else
            *pDst++ = *pSrc++;
    	return(Len);
}




/***	bin_to_dec - convert a binary number to ASCII decimal 
 *
 *	bin_to_dec(pDst, i)
 *
 *	ENTRY
 *		pDst -> buffer to place the ASCII decimal
 *		i = integer to be converted to ASCII decimal
 *
 *	EXIT
 *		ASCII decimal placed in the buffer pointed by pDst
 *		bin_to_dec -> byte next to ASCII decimal in the buffer
 *
 *	WARNING
 *
 *	EFFECTS
 *
 ***/

char *bin_to_dec(pDst, i)
char 	*pDst;
int  	i;
{
    	if (i > 10)
          pDst = bin_to_dec (pDst, i/10);
    	*pDst++ = '0' + (i % 10);
    	return(pDst);
}




/***	get_modem_reply - get reply from modem
 *
 *	get_modem_reply()
 *
 *	ENTRY
 *
 *	EXIT
 *		get_modem_reply = MS_CONNECT MS_CONNECT1200 MS_NOCARRIER 
 *				  MS_NODIALTONE MS_NOREPLY MS_ERROR MS_BUSY
 *
 *	WARNING
 *
 *	EFFECTS
 *
 ***/

int get_modem_reply()
{
    	char 		Ch;
	USHORT		Cnt;
	int		Result,
	     		RetCode;

    	do  		/* skip CR, LF and get resultcode */
	  if ((RetCode = DosRead(FileHndl, &Ch, 1, &Cnt)) != 0)
            Error(ERR_DOSREAD, RetCode);
        while ((Cnt == 1) && ((Ch == 0x0d) || (Ch == 0x0a)));

    	switch(Cnt) {
          case 0:  Result = MS_NOREPLY;
            	   break;
          case 1:  if ((Ch >= '0') && (Ch <= '7'))
                     Result = Ch - '0';
                   else
                     Result = MS_ERROR;
                   break;
          default: Result = MS_ERROR;
                   break;
        }

    	return(Result);
}




/***	discon_modem - disconnect the modem 
 *
 *	discon_modem()
 *
 *	ENTRY
 *
 *	EXIT
 *		modem disconnected
 *
 *	WARNING
 *
 *	EFFECTS
 *
 ***/

void discon_modem()
{
    	/* Wait for the last command to clear, then be quiet for 1.5 seconds */
	DosSleep(1000L);		/* wait 1. second */
    	flush_ques(FLUSHOUTPUT);        /* flush the transmit que */
	DosSleep(1500L);		/* wait 1.5 seconds */

    	send_modem_cmd(MC_ESC);    	/* put modem in command mode */
	DosSleep(2000L);		/* wait 2 seconds */

    	send_modem_cmd(MC_ONHOOK);     	/* place phone back on hook */
	DosSleep(200L); 	  /* wait for command to clear*/
}




/***	com_clr_flush - clear COM error and flush transmit/receive queues
 *
 *	com_clr_flush()
 *
 *	ENTRY
 *
 *	EXIT
 *		com error cleared
 *		transmit and receive queues of com port flushed out
 *
 *	WARNING
 *
 *	EFFECTS
 *
 ***/

void com_clr_flush()
{
	/* retrieve and clear the com error information */
	clr_com_error();
	/* flush transmit and receive queues */
	flush_ques(FLUSHINPUT);
	flush_ques(FLUSHOUTPUT);
}




/***	flush_ques - flush COM transmit/receive queue 
 *
 *	flush_ques(FuncId)
 *
 *	ENTRY
 *		FuncId - set to one of: FLUSHINPUT FLUSHOUTPUT
 *
 *	EXIT
 *		transmit or receive queue of com port flushed
 *
 *	WARNING
 *
 *	EFFECTS
 *
 ***/

void flush_ques(FuncId)
USHORT	FuncId;
{	
	char	FlushData,	/* data returned by flush IOCTL function */
		FlushParm = FLUSH_CMDINFO; /* param to flush IOCTL function */
	int	RetCode;
	
	/* flush transmit/receive queue */
	if ((RetCode = DosDevIOCtl(&FlushData, &FlushParm,
			           FuncId, GENERIC, FileHndl)) != 0) 
	  Error(ERR_IOCTLFLUSHQUE, RetCode);
}




/***	clr_com_error - retrieve and clear COM error information
 *
 *	clr_com_error()
 *
 *	ENTRY
 *
 *	EXIT
 *		com error cleared
 *
 *	WARNING
 *
 *	EFFECTS
 *
 ***/

void clr_com_error()

{
	int  	ComError,
        	RetCode;

	if ((RetCode = DosDevIOCtl(&ComError, 0L, GETCOMERROR,
                                   SERIAL, FileHndl)) != 0)
	  Error(ERR_IOCTLGETCOMERROR, RetCode);
}

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.