This is DialOut.m in view mode; [Download] [Up]
//
// quick and dirty:
// dialing with the ZyXEL modem
// by: Olaf Mueller <olaf@orest.escape.de>
//
#import "DialOut.h"
#include "device.h"
#define DIALOUT "cuf"
#define TSLICE 100
#define INTERVAL ((double)TSLICE/1000.0)
static int readRX (int line,RX *rp)
{
char buffer [rp->untillength] ;
int buflen , ii ;
/* read bytes immediately */
ii = fcntl (line,F_GETFL,0);
fcntl (line,F_SETFL,ii|O_NDELAY) ;
buflen = read (line,buffer,rp->untillength-rp->untilpos) ;
fcntl (line,F_SETFL,ii) ;
//printf ("readRX: buflen = %d space = %d\n",buflen,rp->untillength-rp->untilpos) ;
if (buflen > 0)
{
for (ii = 0 ; ii < buflen ; ii++)
{
//printf ("readRX: %c (%02x)\n",buffer[ii]<32?' ':buffer[ii],buffer[ii]) ;
if (rp->answer && rp->answerpos < rp->answerlength)
*(rp->answer+rp->answerpos++) = buffer[ii] ;
if (*(rp->until+rp->untilpos) == buffer[ii])
rp->untilpos++ ;
else if (*(rp->until) == buffer[ii])
rp->untilpos = 1 ;
else
rp->untilpos = 0 ;
}
}
rp->tcnt += rp->tslice ;
if (rp->untilpos == rp->untillength)
{
if (rp->answer)
rp->answerpos -= rp->untillength ;
return 0 ;
}
else if (rp->tcnt >= rp->tlimit)
return -1 ;
else
return 1 ;
}
static void initRX (char *until,long msec,char *answer,int answerlength,RX *rp)
{
rp->until = until ;
rp->untillength = strlen (until) ;
rp->tlimit = msec ;
rp->tslice = TSLICE ;
rp->untilpos = rp->answerpos = 0 ;
rp->tcnt = 0L ;
if (answer)
rp->answer = answer ;
else
rp->answer = NULL ;
rp->answerlength = answerlength ;
}
static void dialog (int line,long msec,RX *rp,char *until,char *question,...)
{
va_list ap ;
char buffer [1000] ;
va_start (ap,question) ;
vsprintf (buffer,question,ap) ;
va_end (ap) ;
initRX (until,msec,NULL,0,rp) ;
//printf ("dialog write bytes = %d\n",write(line,buffer,strlen(buffer))) ;
write (line,buffer,strlen(buffer)) ;
}
static void dialogAnswer (int line,long msec,RX *rp,char *until,char *answer,int answerlength,char *question,...)
{
va_list ap ;
char buffer [1000] ;
va_start (ap,question) ;
vsprintf (buffer,question,ap) ;
va_end (ap) ;
initRX (until,msec,answer,answerlength,rp) ;
//printf ("dialog write bytes = %d\n",write(line,buffer,strlen(buffer))) ;
write (line,buffer,strlen(buffer)) ;
}
static void clearLine (int line)
{
int ii ;
char cc ;
ii = fcntl (line,F_GETFL,0);
fcntl (line,F_SETFL,ii|O_NDELAY) ;
while (read(line,&cc,1) > 0)
// printf ("* %c(%02x)\n",cc<32?' ':cc,cc)
;
fcntl (line,F_SETFL,ii) ;
usleep (1000000L) ;
}
@interface DialOut (PrivateDialOutMethods)
- nextData ;
- processModem: (int) lastrc ;
- closeDev ;
- (BOOL) convertNumber: (const char*)number ;
@end
@implementation DialOut
// init
- init
{
[super init] ;
[NXApp loadNibSection:"DialOut.nib" owner:self] ;
[myWindow setFrameAutosaveName: "DialOut"] ;
return self ;
}
- newNumber: (const char*)number
{
if (number)
[myNumberField setStringValue: number] ;
[myNumberField selectText: self] ;
[myWindow makeKeyAndOrderFront: self] ;
return self ;
}
static void ReadIt (DPSTimedEntry te,double timeNow,void *data)
{
/* we set data to self so we can call this method from the timed entry */
[(id)data nextData] ;
}
- doDial: sender
{
[myNumberField selectText: self] ;
if (line > 0)
{
if (readTimedEntry)
{
DPSRemoveTimedEntry (readTimedEntry) ;
readTimedEntry = NULL ;
}
if (pstate == 100)
{
dialog (line,4000L,&rx,"OK\r\n","ATH\r") ;
readTimedEntry = DPSAddTimedEntry (INTERVAL,&ReadIt,self,NX_BASETHRESHOLD) ;
}
else
{
[myReportField setStringValue: "interrupted"] ;
// clearLine (line) ;
[self closeDev] ;
}
}
else
{
if (![self convertNumber: [myNumberField stringValue]])
{
//NXRunAlertPanel ("Aufgemerkt","Schlechte Nummer",NULL,NULL,NULL) ;
NXRunAlertPanel ("Alert","Bad number",NULL,NULL,NULL) ;
return self ;
}
if (lockDevice(DIALOUT,'b') != 0)
{
[myReportField setStringValue: "Port b cannot be locked"] ;
return self ;
}
if ((line = openDevice(DIALOUT,'b')) <= 0)
{
unlockDevice (DIALOUT,'b') ;
[myReportField setStringValue: "Port b cannot be opened"] ;
return self ;
}
[myDialButton setTitle: "Hangup"] ;
initDevice (line,B38400) ;
pstate = 1 ; ringcount = 1 ;
[myReportField setStringValue: "preparing modem"] ;
dialog (line,2000L,&rx,"OK\r\n","AT\r") ;
readTimedEntry = DPSAddTimedEntry (INTERVAL,&ReadIt,self,NX_BASETHRESHOLD) ;
}
return self ;
}
// ------------------- private methods -------------------------
- nextData
{
int rc = readRX (line,&rx) ;
if (rc < 1)
{
DPSRemoveTimedEntry (readTimedEntry) ;
readTimedEntry = NULL ;
[self processModem: rc] ;
}
return self ;
}
- closeDev
{
if (line > 0)
{
closeDevice (line) ;
unlockDevice (DIALOUT,'b') ;
line = 0 ;
[myDialButton setTitle: "Dial"] ;
}
return self ;
}
- processModem: (int) lastrc
{
// printf ("state = %d lastrc = %d\n",pstate,lastrc) ;
if (lastrc < 0)
{
//printf ("state = %d lastrc = %d\n",pstate,lastrc) ;
[myReportField setStringValue: "Error: timeout"] ;
[self closeDev] ;
return self ;
}
switch (pstate)
{
case 1:
dialog (line,4000L,&rx,"OK\r\n","ATZ\r") ;
readTimedEntry = DPSAddTimedEntry (INTERVAL,&ReadIt,self,NX_BASETHRESHOLD) ;
break ;
case 2:
dialog (line,2000L,&rx,"OK\r\n","ATE1M2L5&D3S0=0\r") ;
readTimedEntry = DPSAddTimedEntry (INTERVAL,&ReadIt,self,NX_BASETHRESHOLD) ;
break ;
case 3:
dialog (line,2000L,&rx,"OK\r\n","AT+FCLASS=8\r") ;
readTimedEntry = DPSAddTimedEntry (INTERVAL,&ReadIt,self,NX_BASETHRESHOLD) ;
break ;
case 4:
[myReportField setStringValue: "dialing..."] ;
dialogAnswer (line,40000L,&rx,"\r\n",readbuf,sizeof(readbuf),"ATDT%s\r",realNumber) ;
readTimedEntry = DPSAddTimedEntry (INTERVAL,&ReadIt,self,NX_BASETHRESHOLD) ;
break ;
default:
if (pstate == 100)
{
[myReportField setStringValue: "hung up"] ;
[self closeDev] ;
}
else if (pstate % 2)
{
initRX ("\r\n",2000L,readbuf,sizeof(readbuf),&rx) ;
readTimedEntry = DPSAddTimedEntry (INTERVAL,&ReadIt,self,NX_BASETHRESHOLD) ;
}
else
{
*(rx.answer+rx.answerpos) = '\0' ;
if (!strcmp(rx.answer,"BUSY"))
{
[myReportField setStringValue: "Sorry: line busy"] ;
[self closeDev] ;
}
else if (!strcmp(rx.answer,"NO DIALTONE"))
{
[myReportField setStringValue: "Sorry: no dial tone"] ;
[self closeDev] ;
}
else if (!strcmp(rx.answer,"NO CARRIER"))
{
[myReportField setStringValue: "Sorry: no carrier"] ;
[self closeDev] ;
}
else if (!strcmp(rx.answer,"NO ANSWER"))
{
[myReportField setStringValue: "Sorry: no answer"] ;
[self closeDev] ;
}
else if (!strcmp(rx.answer,"VCON"))
{
[myReportField setStringValue: "voice connection"] ;
pstate = 99 ;
}
else if (!strcmp(rx.answer,"RINGING"))
{
char buf [40] ;
sprintf (buf,"ringing %d",++ringcount) ;
[myReportField setStringValue: buf] ;
initRX ("\r\n",7000L,readbuf,sizeof(readbuf),&rx) ;
readTimedEntry = DPSAddTimedEntry (INTERVAL,&ReadIt,self,NX_BASETHRESHOLD) ;
}
}
break ;
}
pstate++ ;
return self ;
}
- (BOOL) convertNumber: (const char*)number
{
const char *ignore = NXGetDefaultValue([NXApp appName],"charsToIgnore") ;
const char *idcountry = NXGetDefaultValue([NXApp appName],"countryCode") ;
const char *country = NXGetDefaultValue([NXApp appName],"thisCountry") ;
const char *idcity = NXGetDefaultValue([NXApp appName],"cityCode") ;
const char *city = NXGetDefaultValue([NXApp appName],"thisCity") ;
char *icp , *rcp ;
BOOL firstValid = NO ;
char buffer [20] ;
int buflen ;
rcp = realNumber ;
while (*number)
{
for (icp = (char*)ignore ; *icp ; icp++)
if (*icp == *number)
break ;
if (*icp == '\0')
{
if (!firstValid && *number == '+')
{
strcpy (rcp,idcountry) ;
rcp += strlen (idcountry) ;
}
else
*rcp++ = *number ;
firstValid = YES ;
}
number++ ;
}
*rcp = '\0' ;
for (rcp = realNumber ; *rcp ; rcp++)
if (*rcp < '0' || *rcp > '9')
return NO ;
/* check this country */
strcpy (buffer,idcountry) ; strcat (buffer,country) ; buflen = strlen (buffer) ;
if (!strncmp(realNumber,buffer,buflen))
{
memcpy (realNumber,idcity,strlen(idcity)) ;
memmove (realNumber+strlen(idcity),realNumber+buflen,strlen(realNumber)-buflen+1) ;
}
/* check this city */
strcpy (buffer,idcity) ; strcat (buffer,city) ; buflen = strlen (buffer) ;
if (!strncmp(realNumber,buffer,buflen))
memmove (realNumber,realNumber+buflen,strlen(realNumber)-buflen+1) ;
return YES ;
}
@end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.