|
|
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);
}
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.