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) 4/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: }