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