1*18635Smiriam #ifndef lint 2*18635Smiriam static char sccsid[] = "@(#)hayes.c 1.1 (Berkeley) 85/04/11 "; 3*18635Smiriam #endif 4*18635Smiriam 5*18635Smiriam /* 6*18635Smiriam * Routines for calling up on a Hayes Modem 7*18635Smiriam * (based on the old VenTel driver). 8*18635Smiriam * The modem is expected to be strapped for "echo". 9*18635Smiriam * Also, the switches enabling the DTR and CD lines 10*18635Smiriam * must be set correctly. 11*18635Smiriam * NOTICE: 12*18635Smiriam * The easy way to hang up a modem is always simply to 13*18635Smiriam * clear the DTR signal. However, if the +++ sequence 14*18635Smiriam * (which switches the modem back to local mode) is sent 15*18635Smiriam * before modem is hung up, removal of the DTR signal 16*18635Smiriam * has no effect (except that it prevents the modem from 17*18635Smiriam * recognizing commands). 18*18635Smiriam * (by Helge Skrivervik, Calma Company, Sunnyvale, CA. 1984) 19*18635Smiriam */ 20*18635Smiriam /* 21*18635Smiriam * TODO: 22*18635Smiriam * It is probably not a good idea to switch the modem 23*18635Smiriam * state between 'verbose' and terse (status messages). 24*18635Smiriam * This should be kicked out and we should use verbose 25*18635Smiriam * mode only. This would make it consistent with normal 26*18635Smiriam * interactive use thru the command 'tip dialer'. 27*18635Smiriam */ 28*18635Smiriam #include "tip.h" 29*18635Smiriam 30*18635Smiriam #define min(a,b) ((a < b) ? a : b) 31*18635Smiriam 32*18635Smiriam static int sigALRM(); 33*18635Smiriam static int timeout = 0; 34*18635Smiriam static jmp_buf timeoutbuf; 35*18635Smiriam static char gobble(); 36*18635Smiriam #define DUMBUFLEN 40 37*18635Smiriam static char dumbuf[DUMBUFLEN]; 38*18635Smiriam 39*18635Smiriam #define DIALING 1 40*18635Smiriam #define IDLE 2 41*18635Smiriam #define CONNECTED 3 42*18635Smiriam #define FAILED 4 43*18635Smiriam static int state = IDLE; 44*18635Smiriam 45*18635Smiriam hay_dialer(num, acu) 46*18635Smiriam register char *num; 47*18635Smiriam char *acu; 48*18635Smiriam { 49*18635Smiriam register char *cp; 50*18635Smiriam register int connected = 0; 51*18635Smiriam char dummy; 52*18635Smiriam #ifdef ACULOG 53*18635Smiriam char line[80]; 54*18635Smiriam #endif 55*18635Smiriam if (hay_sync() == 0) /* make sure we can talk to the modem */ 56*18635Smiriam return(0); 57*18635Smiriam if (boolean(value(VERBOSE))) 58*18635Smiriam printf("\ndialing..."); 59*18635Smiriam fflush(stdout); 60*18635Smiriam ioctl(FD, TIOCHPCL, 0); 61*18635Smiriam ioctl(FD, TIOCFLUSH, 0); /* get rid of garbage */ 62*18635Smiriam write(FD, "ATv0\r", 5); /* tell modem to use short status codes */ 63*18635Smiriam gobble("\r"); 64*18635Smiriam gobble("\r"); 65*18635Smiriam write(FD, "ATTD", 4); /* send dial command */ 66*18635Smiriam write(FD, num, strlen(num)); 67*18635Smiriam state = DIALING; 68*18635Smiriam write(FD, "\r", 1); 69*18635Smiriam connected = 0; 70*18635Smiriam if (gobble("\r")) { 71*18635Smiriam if ((dummy = gobble("01234")) != '1') 72*18635Smiriam error_rep(dummy); 73*18635Smiriam else 74*18635Smiriam connected = 1; 75*18635Smiriam } 76*18635Smiriam if (connected) 77*18635Smiriam state = CONNECTED; 78*18635Smiriam else { 79*18635Smiriam state = FAILED; 80*18635Smiriam return (connected); /* lets get out of here.. */ 81*18635Smiriam } 82*18635Smiriam ioctl(FD, TIOCFLUSH, 0); 83*18635Smiriam #ifdef ACULOG 84*18635Smiriam if (timeout) { 85*18635Smiriam sprintf(line, "%d second dial timeout", 86*18635Smiriam number(value(DIALTIMEOUT))); 87*18635Smiriam logent(value(HOST), num, "hayes", line); 88*18635Smiriam } 89*18635Smiriam #endif 90*18635Smiriam if (timeout) 91*18635Smiriam hay_disconnect(); /* insurance */ 92*18635Smiriam return (connected); 93*18635Smiriam } 94*18635Smiriam 95*18635Smiriam 96*18635Smiriam hay_disconnect() 97*18635Smiriam { 98*18635Smiriam char c; 99*18635Smiriam int len, rlen; 100*18635Smiriam 101*18635Smiriam /* first hang up the modem*/ 102*18635Smiriam #ifdef DEBUG 103*18635Smiriam printf("\rdisconnecting modem....\n\r"); 104*18635Smiriam #endif 105*18635Smiriam ioctl(FD, TIOCCDTR, 0); 106*18635Smiriam sleep(1); 107*18635Smiriam ioctl(FD, TIOCSDTR, 0); 108*18635Smiriam goodbye(); 109*18635Smiriam } 110*18635Smiriam 111*18635Smiriam hay_abort() 112*18635Smiriam { 113*18635Smiriam 114*18635Smiriam char c; 115*18635Smiriam 116*18635Smiriam write(FD, "\r", 1); /* send anything to abort the call */ 117*18635Smiriam hay_disconnect(); 118*18635Smiriam } 119*18635Smiriam 120*18635Smiriam static int 121*18635Smiriam sigALRM() 122*18635Smiriam { 123*18635Smiriam 124*18635Smiriam printf("\07timeout waiting for reply\n\r"); 125*18635Smiriam timeout = 1; 126*18635Smiriam longjmp(timeoutbuf, 1); 127*18635Smiriam } 128*18635Smiriam 129*18635Smiriam static char 130*18635Smiriam gobble(match) 131*18635Smiriam register char *match; 132*18635Smiriam { 133*18635Smiriam char c; 134*18635Smiriam int (*f)(); 135*18635Smiriam int i, status = 0; 136*18635Smiriam 137*18635Smiriam signal(SIGALRM, sigALRM); 138*18635Smiriam timeout = 0; 139*18635Smiriam #ifdef DEBUG 140*18635Smiriam printf("\ngobble: waiting for %s\n", match); 141*18635Smiriam #endif 142*18635Smiriam do { 143*18635Smiriam if (setjmp(timeoutbuf)) { 144*18635Smiriam signal(SIGALRM, f); 145*18635Smiriam return (0); 146*18635Smiriam } 147*18635Smiriam alarm(number(value(DIALTIMEOUT))); 148*18635Smiriam read(FD, &c, 1); 149*18635Smiriam alarm(0); 150*18635Smiriam c &= 0177; 151*18635Smiriam #ifdef DEBUG 152*18635Smiriam printf("%c 0x%x ", c, c); 153*18635Smiriam #endif 154*18635Smiriam for (i = 0; i < strlen(match); i++) 155*18635Smiriam if (c == match[i]) 156*18635Smiriam status = c; 157*18635Smiriam } while (status == 0); 158*18635Smiriam signal(SIGALRM, SIG_DFL); 159*18635Smiriam #ifdef DEBUG 160*18635Smiriam printf("\n"); 161*18635Smiriam #endif 162*18635Smiriam return (status); 163*18635Smiriam } 164*18635Smiriam 165*18635Smiriam error_rep(c) 166*18635Smiriam register char c; 167*18635Smiriam { 168*18635Smiriam printf("\n\r"); 169*18635Smiriam switch (c) { 170*18635Smiriam 171*18635Smiriam case '0': 172*18635Smiriam printf("OK"); 173*18635Smiriam break; 174*18635Smiriam 175*18635Smiriam case '1': 176*18635Smiriam printf("CONNECT"); 177*18635Smiriam break; 178*18635Smiriam 179*18635Smiriam case '2': 180*18635Smiriam printf("RING"); 181*18635Smiriam break; 182*18635Smiriam 183*18635Smiriam case '3': 184*18635Smiriam printf("NO CARRIER"); 185*18635Smiriam break; 186*18635Smiriam 187*18635Smiriam case '4': 188*18635Smiriam printf("ERROR in input"); 189*18635Smiriam break; 190*18635Smiriam 191*18635Smiriam case '5': 192*18635Smiriam printf("CONNECT 1200"); 193*18635Smiriam break; 194*18635Smiriam 195*18635Smiriam default: 196*18635Smiriam printf("Unknown Modem error: %c (0x%x)", c, c); 197*18635Smiriam } 198*18635Smiriam printf("\n\r"); 199*18635Smiriam return; 200*18635Smiriam } 201*18635Smiriam 202*18635Smiriam /* 203*18635Smiriam * set modem back to normal verbose status codes. 204*18635Smiriam */ 205*18635Smiriam goodbye() 206*18635Smiriam { 207*18635Smiriam int len, rlen; 208*18635Smiriam char c; 209*18635Smiriam 210*18635Smiriam ioctl(FD, TIOCFLUSH, &len); /* get rid of trash */ 211*18635Smiriam if (hay_sync()) { 212*18635Smiriam sleep(1); 213*18635Smiriam #ifndef DEBUG 214*18635Smiriam ioctl(FD, TIOCFLUSH, 0); 215*18635Smiriam #endif 216*18635Smiriam write(FD, "ATH0\r", 5); /* insurance */ 217*18635Smiriam #ifndef DEBUG 218*18635Smiriam c = gobble("03"); 219*18635Smiriam if (c != '0' && c != '3') { 220*18635Smiriam printf("cannot hang up modem\n\r"); 221*18635Smiriam printf("please use 'tip dialer' to make sure the line is hung up\n\r"); 222*18635Smiriam } 223*18635Smiriam #endif 224*18635Smiriam sleep(1); 225*18635Smiriam ioctl(FD, FIONREAD, &len); 226*18635Smiriam #ifdef DEBUG 227*18635Smiriam printf("goodbye1: len=%d -- ", len); 228*18635Smiriam rlen = read(FD, dumbuf, min(len, DUMBUFLEN)); 229*18635Smiriam dumbuf[rlen] = '\0'; 230*18635Smiriam printf("read (%d): %s\r\n", rlen, dumbuf); 231*18635Smiriam #endif 232*18635Smiriam write(FD, "ATv1\r", 5); 233*18635Smiriam sleep(1); 234*18635Smiriam #ifdef DEBUG 235*18635Smiriam ioctl(FD, FIONREAD, &len); 236*18635Smiriam printf("goodbye2: len=%d -- ", len); 237*18635Smiriam rlen = read(FD, dumbuf, min(len, DUMBUFLEN)); 238*18635Smiriam dumbuf[rlen] = '\0'; 239*18635Smiriam printf("read (%d): %s\r\n", rlen, dumbuf); 240*18635Smiriam #endif 241*18635Smiriam } 242*18635Smiriam ioctl(FD, TIOCFLUSH, 0); /* clear the input buffer */ 243*18635Smiriam ioctl(FD, TIOCCDTR, 0); /* clear DTR (insurance) */ 244*18635Smiriam close(FD); 245*18635Smiriam } 246*18635Smiriam 247*18635Smiriam #define MAXRETRY 5 248*18635Smiriam 249*18635Smiriam hay_sync() 250*18635Smiriam { 251*18635Smiriam int len, retry = 0; 252*18635Smiriam 253*18635Smiriam while (retry++ <= MAXRETRY) { 254*18635Smiriam write(FD, "AT\r", 3); 255*18635Smiriam sleep(1); 256*18635Smiriam ioctl(FD, FIONREAD, &len); 257*18635Smiriam if (len) { 258*18635Smiriam len = read(FD, dumbuf, min(len, DUMBUFLEN)); 259*18635Smiriam if (index(dumbuf, '0') || 260*18635Smiriam (index(dumbuf, 'O') && index(dumbuf, 'K'))) 261*18635Smiriam return(1); 262*18635Smiriam #ifdef DEBUG 263*18635Smiriam dumbuf[len] = '\0'; 264*18635Smiriam printf("hay_sync: (\"%s\") %d\n\r", dumbuf, retry); 265*18635Smiriam #endif 266*18635Smiriam } 267*18635Smiriam ioctl(FD, TIOCCDTR, 0); 268*18635Smiriam ioctl(FD, TIOCSDTR, 0); 269*18635Smiriam } 270*18635Smiriam printf("Cannot synchronize with hayes...\n\r"); 271*18635Smiriam return(0); 272*18635Smiriam } 273