home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: OtherApp
/
OtherApp.zip
/
PSFAX2.ZIP
/
psfax2
/
modem.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-10-16
|
16KB
|
489 lines
/* modem.c */
/*---------------------------------------------------------------------------*/
/* This file is part of PSFax/2. */
/* */
/* Written By: Gary L. Hennigan */
/* */
/* This code can modified as much as you like provided you follow the */
/* guidelines as described in the file install.doc which you should have */
/* received with this file. If you did not please notify the author for a */
/* copy of this file via Internet email. The address is: */
/* ghenniga@NMSU.Edu */
/*---------------------------------------------------------------------------*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "psfax2.h"
#define DevIOCtl DosDevIOCtl32
/**Global variables defined in psfax2.c **/
extern char cGlobResp[];
ULONG ulTemp; /* Used by various functions in modem.c */
USHORT usTemp;
void vFlushIO( HFILE );
unsigned char swap_bits( unsigned char );
USHORT usSetTTYTime( HFILE, DCBINFO *, int );
int iGetResp( HFILE, DCBINFO *, char *, int, int, char * );
/****************************************************************************/
/*************************Used for simplifying*******************************/
/*************************IOCtl function calls*******************************/
/****************************************************************************/
USHORT DosDevIOCtl32(PVOID pData, USHORT cbData, PVOID pParms, USHORT cbParms,
USHORT usFunction, USHORT usCategory, HFILE hDevice)
{
ULONG ulParmLengthInOut = cbParms, ulDataLengthInOut = cbData;
return (USHORT)DosDevIOCtl(hDevice, usCategory, usFunction,
pParms, cbParms, &ulParmLengthInOut,
pData, cbData, &ulDataLengthInOut);
}
/****************************************************************************/
/***************************Open the COM Port********************************/
/****************************************************************************/
ULONG ulOpenPort(char *cPort, HFILE *hTTY)
{
return DosOpen(cPort, hTTY, &ulTemp, 0L, 0, FILE_OPEN,
OPEN_ACCESS_READWRITE | OPEN_SHARE_DENYREADWRITE |
OPEN_FLAGS_FAIL_ON_ERROR, 0L);
}
/****************************************************************************/
/**********************Get the current port settings*************************/
/****************************************************************************/
int iPortGetSet(HFILE hTTY, DCBINFO *dcbCom)
{
usTemp = DevIOCtl(dcbCom,sizeof(*dcbCom),NULL,0,
ASYNC_GETDCBINFO, IOCTL_ASYNC, hTTY);
if(usTemp != 0)
return 1;
return 0;
}
/****************************************************************************/
/**************************Initialize the Port*******************************/
/****************************************************************************/
int iPortInit(HFILE hTTY, DCBINFO *dcbCom)
{
MODEMSTATUS ms;
UINT data;
/*-------------------------------End Declarations---------------------------*/
/**Set XON/XOFF flow control. **/
dcbCom->fbCtlHndShake = MODE_DTR_CONTROL;
dcbCom->fbFlowReplace &= ~(MODE_AUTO_RECEIVE | MODE_AUTO_TRANSMIT |
MODE_RTS_CONTROL | MODE_RTS_HANDSHAKE);
dcbCom->fbFlowReplace |= (MODE_AUTO_RECEIVE | MODE_AUTO_TRANSMIT |
MODE_RTS_CONTROL);
ms.fbModemOn = RTS_ON;
ms.fbModemOff = 255;
usTemp = DevIOCtl(NULL,0,dcbCom,sizeof(*dcbCom),ASYNC_SETDCBINFO,
IOCTL_ASYNC, hTTY);
if(usTemp != 0)
return -1;
usTemp = DevIOCtl(&data,sizeof(data),&ms,sizeof(ms),
ASYNC_SETMODEMCTRL,IOCTL_ASYNC,hTTY);
if(usTemp != 0)
return -1;
return 0;
}
/****************************************************************************/
/**************************Initialize the Modem******************************/
/****************************************************************************/
int iModemInit(HFILE hTTY, DCBINFO *dcbCom)
{
char cBuff[256];
int iCnt=0;
/*-------------------------------End Declarations---------------------------*/
strcpy(cBuff,"ATZ\r"); /* Use the default profile of the modem. */
DosWrite(hTTY, cBuff, strlen(cBuff), &ulTemp);
if(iGetResp(hTTY, dcbCom, cBuff, 10*sizeof(char), 3, NULL) <= 0 ||
!strstr(cBuff,"OK\r") )
return 1;
strcpy(cBuff,"AT&K4V0Q0E0L2M1W2S0=0S2=255S12=255 +FCLASS=2\r");
DosWrite(hTTY, cBuff, strlen(cBuff), &ulTemp);
if(iGetResp(hTTY, dcbCom, cBuff, strlen(cBuff)+2*sizeof(char),
2, NULL) <= 0 || !strstr(cBuff,"0\r"))
return 1;
strcpy(cBuff,"ATS7=120 +FCR=1\r");
DosWrite(hTTY, cBuff, strlen(cBuff), &ulTemp); sleep(1);
if(iGetResp(hTTY, dcbCom, cBuff, 2*sizeof(char), 2, NULL) <= 0 ||
!strstr(cBuff,"0\r"))
return 1;
strcpy(cBuff,"AT+FDCC=1,3\r");
DosWrite(hTTY, cBuff, strlen(cBuff), &ulTemp); sleep(1);
if(iGetResp(hTTY, dcbCom, cBuff, 2*sizeof(char), 2, NULL) <= 0 ||
!strstr(cBuff,"0\r"))
return 1;
strcpy(cBuff,"AT+FBOR=0\r");
DosWrite(hTTY, cBuff, strlen(cBuff), &ulTemp); sleep(1);
if(iGetResp(hTTY, dcbCom, cBuff, 2*sizeof(char), 2, NULL) <= 0 ||
!strstr(cBuff,"0\r"))
return 1;
/**Flush all the I/O, set the timeout for reads, and see if the modem **/
/**is responding properly. **/
vFlushIO(hTTY);
usSetTTYTime(hTTY, dcbCom, 2);
strcpy(cBuff, "AT\r");
do
{
DosWrite(hTTY, cBuff, strlen(cBuff), &ulTemp);
iCnt++;
DosRead(hTTY, cBuff, 2, &ulTemp);
}
while(ulTemp == 0 && iCnt <= MAXTIMEOUTS);
if(ulTemp == 0 && iCnt >= MAXTIMEOUTS)return 1;
if(strncmp(cBuff,"0\r",2) != 0)
{
printf("Bad modem response while attempting to sync!\n");
return 1;
}
return 0;
}
/****************************************************************************/
/****************************Dial the Phone**********************************/
/****************************************************************************/
int iModemDial( HFILE hTTY, char *cPhoneNum, DCBINFO *dcbCom, int iWait )
{
int iRedial;
char cBuff[256];
/*-------------------------------End Declarations---------------------------*/
strcpy(cBuff,"ATD");
strcat(cBuff,cPhoneNum);
strcat(cBuff,"\r");
DosWrite(hTTY, cBuff, strlen(cBuff), &ulTemp); sleep(1);
if(iGetResp(hTTY, dcbCom, cBuff, 2, iWait, NULL) <= 0)
{
cBuff[0] = 0x1b;
cBuff[1] = 0x00;
DosWrite(hTTY, cBuff, strlen(cBuff), &ulTemp); sleep(2);
vFlushIO(hTTY);
return DIAL_NOANSWER;
}
if( cBuff[0] )
{
switch(cBuff[0])
{
case '3':
iRedial = DIAL_NOCARRIER;
vFlushIO(hTTY);
return iRedial;
case '6':
iRedial = DIAL_NODIALTONE;
vFlushIO(hTTY);
return iRedial;
case '7':
iRedial = DIAL_BUSY;
vFlushIO(hTTY);
return iRedial;
case '8':
iRedial = DIAL_NOANSWER;
vFlushIO(hTTY);
return iRedial;
default:
iRedial = 0;
break;
}
}
else
{
vFlushIO(hTTY);
return DIAL_NOANSWER;
}
/**Make sure the remote responds with a connection indication. **/
if(iGetResp(hTTY, dcbCom, &cBuff[2], 8, -20, "+FCON\r") <= 0)
{
printf("Incorrect response \"%s\" received...\n",cBuff);
vFlushIO(hTTY);
return DIAL_UNKNOWN;
}
else
strcpy(cGlobResp,cBuff);
puts("Fax connection established!");
return iRedial;
}
/****************************************************************************/
/*******************Initialize the fax-fax connection************************/
/****************************************************************************/
int iFaxInit(HFILE hTTY, DCBINFO *dcbCom, int df, int vr, int wd, int ln)
{
char cBuff[256];
/*-------------------------------End Declarations---------------------------*/
/**Make sure the remote responded correctly. **/
if(iGetResp(hTTY, dcbCom, cBuff, 50, -15, "0\r") <= 0)
{
puts("Remote fax is not responding....");
return 1;
}
/**Set transmission parameters. **/
sprintf(cBuff,"AT+FDT=%d,%d,%d,%d\r", df, vr, wd, ln);
vFlushIO(hTTY);
DosWrite(hTTY, cBuff, strlen(cBuff), &ulTemp); sleep(1);
/**Make sure the remote responds with a CONNECT. **/
if(iGetResp(hTTY, dcbCom, cBuff, 50, -15, "1\r") <= 0)
{
puts("Remote fax is not responding....");
return 1;
}
vFlushIO(hTTY);
return 0;
}
/****************************************************************************/
/*********************Send a page via the Fax/Modem**************************/
/****************************************************************************/
int iFaxSendPage(HFILE hTTY, DCBINFO *dcbCom, FILE *fStream, int iLast)
{
unsigned char cBuff[SENDCHUNK], cBuff2[2*SENDCHUNK];
int iNumRead, iNumWrite, i1, iPPRCode;
/*-------------------------------End Declarations---------------------------*/
iNumRead = fread(cBuff, sizeof(char), SENDCHUNK, fStream);
usSetTTYTime(hTTY, dcbCom, -15);
while(iNumRead > 0)
{
iNumWrite = 0;
/** Swap the bits and pad DLE characters. **/
for(i1=0; i1 < iNumRead; i1++)
{
cBuff2[iNumWrite] = swap_bits(cBuff[i1]);
if(cBuff2[iNumWrite++] == DLE)
cBuff2[iNumWrite++] = DLE;
}
/** Write the stuff out to the modem. **/
DosWrite(hTTY, cBuff2, iNumWrite, &ulTemp);
/** Check for a response, if any, from the modem. **/
DosRead(hTTY, cBuff, sizeof(cBuff), &ulTemp);
if(ulTemp != 0)
{
for(i1=0; i1 < ulTemp; i1++)
{
if((cBuff[i1] & 0x7f) == CAN)
{
printf("Remote has canceled transmission!\n");
sprintf(cBuff,"%c%c",DLE,ETX);
DosWrite(hTTY, cBuff, 2*sizeof(char), &ulTemp);
return -1;
}
}
}
iNumRead = fread(cBuff, sizeof(char), SENDCHUNK, fStream);
}
sprintf(cBuff,"%c%c",DLE,ETX);
DosWrite(hTTY, cBuff, 2*sizeof(char), &ulTemp);
i1 = iGetResp(hTTY, dcbCom, cBuff, 2, -15, "0\r");
if(i1 <= 0)
{
puts("Incorrect response from remote to end-of-page message!\n");
return -1;
}
switch(iLast)
{
case PEND_ANOTHER:
strcpy(cBuff,"AT+FET=0\r");
DosWrite(hTTY, cBuff, strlen(cBuff), &ulTemp);
break;
case PEND_ENDTRAN:
strcpy(cBuff,"AT+FET=2\r");
DosWrite(hTTY, cBuff, strlen(cBuff), &ulTemp);
break;
}
/**Get the post-page response. **/
if(iGetResp(hTTY, dcbCom, cBuff, 20, -10, "0\r") <= 0)
{
puts("No post-page response from remote!");
return -1;
}
if(iLast == PEND_ANOTHER)
DosWrite(hTTY, "AT+FDT\r", sizeof("AT+FDT\r"), &ulTemp);
strtok(&cBuff[8],"\r");
i1 = sscanf(&cBuff[8], "%d", &iPPRCode);
if(i1 <= 0)
{
puts("Incorrect post-page response from remote!");
return -1;
}
if(iLast == PEND_ANOTHER)
{
if(iGetResp(hTTY, dcbCom, cBuff, 2, -10, "1\r") <= 0)
{
puts("Unable to continue transmission!");
return -1;
}
}
else
{
if(iGetResp(hTTY, dcbCom, cBuff, 2, -15, "0\r") <= 0)
{
puts("Failed to properly end transmission!");
return -1;
}
}
return iPPRCode;
}
/****************************************************************************/
/************Tell the remote to intterrupt the transmission******************/
/****************************************************************************/
int iFaxInterrupt(HFILE hTTY, DCBINFO *dcbCom)
{
char cBuff[20];
/*-------------------------------End Declarations---------------------------*/
strcpy(cBuff,"AT+FK\r");
DosWrite(hTTY, cBuff, strlen(cBuff), &ulTemp);
return 0;
}
/****************************************************************************/
/**************************Close the COM Port********************************/
/****************************************************************************/
ULONG ulClosePort(HFILE hTTY)
{
return DosClose(hTTY);
}
/****************************************************************************/
/********************Read the response from the modem************************/
/****************************************************************************/
int iGetResp( HFILE hTTY, DCBINFO *dcbCom, char *cBuff, int iExpSize,
int iTimeout, char *cSearch )
{
int iStart=0, iCnt=0;
/**Initialize the buffer. **/
cBuff[0] = '\000';
/**Set the desired timeout for this read. **/
usSetTTYTime(hTTY, dcbCom, iTimeout);
/**Read the response. **/
if(!cSearch)
{
DosRead(hTTY, cBuff, iExpSize, &ulTemp);
cBuff[ulTemp] = '\000'; /* For string manipulation functions. */
iStart = ulTemp;
}
else
{
do
{
DosRead(hTTY, &cBuff[iStart], iExpSize, &ulTemp);
iStart += ulTemp;
cBuff[iStart] = '\000';
iCnt++;
}
while(!strstr(cBuff,cSearch) && iCnt <= MAXTIMEOUTS);
}
if(iCnt > MAXTIMEOUTS)
return -1;
return iStart;
}
/****************************************************************************/
/***********************Set the read timeout on******************************/
/******************************the COM port**********************************/
/****************************************************************************/
USHORT usSetTTYTime(HFILE hTTY, DCBINFO *dcbCom, int iTime)
{
if(iTime >= 0)
iTime *= 100;
else
iTime *= -1;
dcbCom->usReadTimeout = iTime;
return (DevIOCtl(NULL,0,dcbCom,sizeof(*dcbCom),ASYNC_SETDCBINFO,
IOCTL_ASYNC, hTTY));
}
/****************************************************************************/
/*************************Flush all pending I/O******************************/
/****************************************************************************/
void vFlushIO(HFILE hTTY)
{
UINT data;
char parm=0;
/*-------------------------------End Declarations---------------------------*/
DevIOCtl(&data,sizeof(data),&parm,sizeof(parm),
DEV_FLUSHINPUT, IOCTL_GENERAL, hTTY);
DevIOCtl(&data,sizeof(data),&parm,sizeof(parm),
DEV_FLUSHOUTPUT, IOCTL_GENERAL, hTTY);
}
/****************************************************************************/
/************************Builds table to swap the****************************/
/******************low order 4 bits with the high order**********************/
/****************************************************************************/
static void init_swaptable(unsigned char *swaptable)
{
int i, j;
/*-------------------------------End Declarations---------------------------*/
for (i = 0; i < 256; i++) {
j = ( ((i & 0x01) << 7) |
((i & 0x02) << 5) |
((i & 0x04) << 3) |
((i & 0x08) << 1) |
((i & 0x10) >> 1) |
((i & 0x20) >> 3) |
((i & 0x40) >> 5) |
((i & 0x80) >> 7) );
swaptable[i] = j;
}
}
/****************************************************************************/
/********************Reverses the low order 4 bits of a byte*****************/
/****************************************************************************/
unsigned char swap_bits(unsigned char c)
{
static unsigned char swaptable[256];
static int swaptable_init = FALSE;
/*-------------------------------End Declarations---------------------------*/
if (!swaptable_init) {
init_swaptable(swaptable);
swaptable_init = TRUE;
}
return(swaptable[c]);
}