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