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.