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