119817Sdist /* 235492Sbostic * Copyright (c) 1983 The Regents of the University of California. 335492Sbostic * All rights reserved. 435492Sbostic * 542770Sbostic * %sccs.include.redist.c% 619817Sdist */ 719817Sdist 818635Smiriam #ifndef lint 9*46867Sbostic static char sccsid[] = "@(#)hayes.c 5.4 (Berkeley) 03/02/91"; 1035492Sbostic #endif /* not lint */ 1118635Smiriam 1218635Smiriam /* 1318635Smiriam * Routines for calling up on a Hayes Modem 1418635Smiriam * (based on the old VenTel driver). 1518635Smiriam * The modem is expected to be strapped for "echo". 1618635Smiriam * Also, the switches enabling the DTR and CD lines 1718635Smiriam * must be set correctly. 1818635Smiriam * NOTICE: 1918635Smiriam * The easy way to hang up a modem is always simply to 2018635Smiriam * clear the DTR signal. However, if the +++ sequence 2118635Smiriam * (which switches the modem back to local mode) is sent 2218635Smiriam * before modem is hung up, removal of the DTR signal 2318635Smiriam * has no effect (except that it prevents the modem from 2418635Smiriam * recognizing commands). 2518635Smiriam * (by Helge Skrivervik, Calma Company, Sunnyvale, CA. 1984) 2618635Smiriam */ 2718635Smiriam /* 2818635Smiriam * TODO: 2918635Smiriam * It is probably not a good idea to switch the modem 3018635Smiriam * state between 'verbose' and terse (status messages). 3118635Smiriam * This should be kicked out and we should use verbose 3218635Smiriam * mode only. This would make it consistent with normal 3318635Smiriam * interactive use thru the command 'tip dialer'. 3418635Smiriam */ 3518635Smiriam #include "tip.h" 3618635Smiriam 3718635Smiriam #define min(a,b) ((a < b) ? a : b) 3818635Smiriam 39*46867Sbostic static void sigALRM(); 4018635Smiriam static int timeout = 0; 4118635Smiriam static jmp_buf timeoutbuf; 4218635Smiriam static char gobble(); 4318635Smiriam #define DUMBUFLEN 40 4418635Smiriam static char dumbuf[DUMBUFLEN]; 4518635Smiriam 4618635Smiriam #define DIALING 1 4718635Smiriam #define IDLE 2 4818635Smiriam #define CONNECTED 3 4918635Smiriam #define FAILED 4 5018635Smiriam static int state = IDLE; 5118635Smiriam 5218635Smiriam hay_dialer(num, acu) 5318635Smiriam register char *num; 5418635Smiriam char *acu; 5518635Smiriam { 5618635Smiriam register char *cp; 5718635Smiriam register int connected = 0; 5818635Smiriam char dummy; 5918635Smiriam #ifdef ACULOG 6018635Smiriam char line[80]; 6118635Smiriam #endif 6218635Smiriam if (hay_sync() == 0) /* make sure we can talk to the modem */ 6318635Smiriam return(0); 6418635Smiriam if (boolean(value(VERBOSE))) 6518635Smiriam printf("\ndialing..."); 6618635Smiriam fflush(stdout); 6718635Smiriam ioctl(FD, TIOCHPCL, 0); 6818635Smiriam ioctl(FD, TIOCFLUSH, 0); /* get rid of garbage */ 6918635Smiriam write(FD, "ATv0\r", 5); /* tell modem to use short status codes */ 7018635Smiriam gobble("\r"); 7118635Smiriam gobble("\r"); 7218635Smiriam write(FD, "ATTD", 4); /* send dial command */ 7318635Smiriam write(FD, num, strlen(num)); 7418635Smiriam state = DIALING; 7518635Smiriam write(FD, "\r", 1); 7618635Smiriam connected = 0; 7718635Smiriam if (gobble("\r")) { 7818635Smiriam if ((dummy = gobble("01234")) != '1') 7918635Smiriam error_rep(dummy); 8018635Smiriam else 8118635Smiriam connected = 1; 8218635Smiriam } 8318635Smiriam if (connected) 8418635Smiriam state = CONNECTED; 8518635Smiriam else { 8618635Smiriam state = FAILED; 8718635Smiriam return (connected); /* lets get out of here.. */ 8818635Smiriam } 8918635Smiriam ioctl(FD, TIOCFLUSH, 0); 9018635Smiriam #ifdef ACULOG 9118635Smiriam if (timeout) { 9218635Smiriam sprintf(line, "%d second dial timeout", 9318635Smiriam number(value(DIALTIMEOUT))); 9418635Smiriam logent(value(HOST), num, "hayes", line); 9518635Smiriam } 9618635Smiriam #endif 9718635Smiriam if (timeout) 9818635Smiriam hay_disconnect(); /* insurance */ 9918635Smiriam return (connected); 10018635Smiriam } 10118635Smiriam 10218635Smiriam 10318635Smiriam hay_disconnect() 10418635Smiriam { 10518635Smiriam char c; 10618635Smiriam int len, rlen; 10718635Smiriam 10818635Smiriam /* first hang up the modem*/ 10918635Smiriam #ifdef DEBUG 11018635Smiriam printf("\rdisconnecting modem....\n\r"); 11118635Smiriam #endif 11218635Smiriam ioctl(FD, TIOCCDTR, 0); 11318635Smiriam sleep(1); 11418635Smiriam ioctl(FD, TIOCSDTR, 0); 11518635Smiriam goodbye(); 11618635Smiriam } 11718635Smiriam 11818635Smiriam hay_abort() 11918635Smiriam { 12018635Smiriam 12118635Smiriam char c; 12218635Smiriam 12318635Smiriam write(FD, "\r", 1); /* send anything to abort the call */ 12418635Smiriam hay_disconnect(); 12518635Smiriam } 12618635Smiriam 127*46867Sbostic static void 12818635Smiriam sigALRM() 12918635Smiriam { 13018635Smiriam 13118635Smiriam printf("\07timeout waiting for reply\n\r"); 13218635Smiriam timeout = 1; 13318635Smiriam longjmp(timeoutbuf, 1); 13418635Smiriam } 13518635Smiriam 13618635Smiriam static char 13718635Smiriam gobble(match) 13818635Smiriam register char *match; 13918635Smiriam { 14018635Smiriam char c; 141*46867Sbostic sig_t f; 14218635Smiriam int i, status = 0; 14318635Smiriam 144*46867Sbostic f = signal(SIGALRM, sigALRM); 14518635Smiriam timeout = 0; 14618635Smiriam #ifdef DEBUG 14718635Smiriam printf("\ngobble: waiting for %s\n", match); 14818635Smiriam #endif 14918635Smiriam do { 15018635Smiriam if (setjmp(timeoutbuf)) { 15118635Smiriam signal(SIGALRM, f); 15218635Smiriam return (0); 15318635Smiriam } 15418635Smiriam alarm(number(value(DIALTIMEOUT))); 15518635Smiriam read(FD, &c, 1); 15618635Smiriam alarm(0); 15718635Smiriam c &= 0177; 15818635Smiriam #ifdef DEBUG 15918635Smiriam printf("%c 0x%x ", c, c); 16018635Smiriam #endif 16118635Smiriam for (i = 0; i < strlen(match); i++) 16218635Smiriam if (c == match[i]) 16318635Smiriam status = c; 16418635Smiriam } while (status == 0); 16518635Smiriam signal(SIGALRM, SIG_DFL); 16618635Smiriam #ifdef DEBUG 16718635Smiriam printf("\n"); 16818635Smiriam #endif 16918635Smiriam return (status); 17018635Smiriam } 17118635Smiriam 17218635Smiriam error_rep(c) 17318635Smiriam register char c; 17418635Smiriam { 17518635Smiriam printf("\n\r"); 17618635Smiriam switch (c) { 17718635Smiriam 17818635Smiriam case '0': 17918635Smiriam printf("OK"); 18018635Smiriam break; 18118635Smiriam 18218635Smiriam case '1': 18318635Smiriam printf("CONNECT"); 18418635Smiriam break; 18518635Smiriam 18618635Smiriam case '2': 18718635Smiriam printf("RING"); 18818635Smiriam break; 18918635Smiriam 19018635Smiriam case '3': 19118635Smiriam printf("NO CARRIER"); 19218635Smiriam break; 19318635Smiriam 19418635Smiriam case '4': 19518635Smiriam printf("ERROR in input"); 19618635Smiriam break; 19718635Smiriam 19818635Smiriam case '5': 19918635Smiriam printf("CONNECT 1200"); 20018635Smiriam break; 20118635Smiriam 20218635Smiriam default: 20318635Smiriam printf("Unknown Modem error: %c (0x%x)", c, c); 20418635Smiriam } 20518635Smiriam printf("\n\r"); 20618635Smiriam return; 20718635Smiriam } 20818635Smiriam 20918635Smiriam /* 21018635Smiriam * set modem back to normal verbose status codes. 21118635Smiriam */ 21218635Smiriam goodbye() 21318635Smiriam { 21418635Smiriam int len, rlen; 21518635Smiriam char c; 21618635Smiriam 21718635Smiriam ioctl(FD, TIOCFLUSH, &len); /* get rid of trash */ 21818635Smiriam if (hay_sync()) { 21918635Smiriam sleep(1); 22018635Smiriam #ifndef DEBUG 22118635Smiriam ioctl(FD, TIOCFLUSH, 0); 22218635Smiriam #endif 22318635Smiriam write(FD, "ATH0\r", 5); /* insurance */ 22418635Smiriam #ifndef DEBUG 22518635Smiriam c = gobble("03"); 22618635Smiriam if (c != '0' && c != '3') { 22718635Smiriam printf("cannot hang up modem\n\r"); 22818635Smiriam printf("please use 'tip dialer' to make sure the line is hung up\n\r"); 22918635Smiriam } 23018635Smiriam #endif 23118635Smiriam sleep(1); 23218635Smiriam ioctl(FD, FIONREAD, &len); 23318635Smiriam #ifdef DEBUG 23418635Smiriam printf("goodbye1: len=%d -- ", len); 23518635Smiriam rlen = read(FD, dumbuf, min(len, DUMBUFLEN)); 23618635Smiriam dumbuf[rlen] = '\0'; 23718635Smiriam printf("read (%d): %s\r\n", rlen, dumbuf); 23818635Smiriam #endif 23918635Smiriam write(FD, "ATv1\r", 5); 24018635Smiriam sleep(1); 24118635Smiriam #ifdef DEBUG 24218635Smiriam ioctl(FD, FIONREAD, &len); 24318635Smiriam printf("goodbye2: len=%d -- ", len); 24418635Smiriam rlen = read(FD, dumbuf, min(len, DUMBUFLEN)); 24518635Smiriam dumbuf[rlen] = '\0'; 24618635Smiriam printf("read (%d): %s\r\n", rlen, dumbuf); 24718635Smiriam #endif 24818635Smiriam } 24918635Smiriam ioctl(FD, TIOCFLUSH, 0); /* clear the input buffer */ 25018635Smiriam ioctl(FD, TIOCCDTR, 0); /* clear DTR (insurance) */ 25118635Smiriam close(FD); 25218635Smiriam } 25318635Smiriam 25418635Smiriam #define MAXRETRY 5 25518635Smiriam 25618635Smiriam hay_sync() 25718635Smiriam { 25818635Smiriam int len, retry = 0; 25918635Smiriam 26018635Smiriam while (retry++ <= MAXRETRY) { 26118635Smiriam write(FD, "AT\r", 3); 26218635Smiriam sleep(1); 26318635Smiriam ioctl(FD, FIONREAD, &len); 26418635Smiriam if (len) { 26518635Smiriam len = read(FD, dumbuf, min(len, DUMBUFLEN)); 26618635Smiriam if (index(dumbuf, '0') || 26718635Smiriam (index(dumbuf, 'O') && index(dumbuf, 'K'))) 26818635Smiriam return(1); 26918635Smiriam #ifdef DEBUG 27018635Smiriam dumbuf[len] = '\0'; 27118635Smiriam printf("hay_sync: (\"%s\") %d\n\r", dumbuf, retry); 27218635Smiriam #endif 27318635Smiriam } 27418635Smiriam ioctl(FD, TIOCCDTR, 0); 27518635Smiriam ioctl(FD, TIOCSDTR, 0); 27618635Smiriam } 27718635Smiriam printf("Cannot synchronize with hayes...\n\r"); 27818635Smiriam return(0); 27918635Smiriam } 280