xref: /illumos-gate/usr/src/cmd/tip/aculib/hayes.c (revision 20a7641f9918de8574b8b3b47dbe35c4bfc78df1)
1 /*
2  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
3  * Use is subject to license terms.
4  */
5 
6 /*
7  * Copyright (c) 1983 Regents of the University of California.
8  * All rights reserved. The Berkeley software License Agreement
9  * specifies the terms and conditions for redistribution.
10  */
11 
12 #include "tip.h"
13 
14 static int	hayes_sync(int);
15 static void	sigALRM(void);
16 static sigjmp_buf	timeoutbuf;
17 
18 void	hayes_disconnect(void);
19 
20 /*
21  * Dial up on a Hayes Smart Modem 1200 or 2400
22  */
23 /* ARGSUSED */
24 int
25 hayes_dialer(char *num, char *acu)
26 {
27 	char code = 0, cr = 0;
28 	sig_handler_t	f;
29 	struct termios buf;
30 
31 	f = signal(SIGALRM, (sig_handler_t)sigALRM);
32 
33 	if (!hayes_sync(FD)) {
34 		(void) printf("can't synchronize with hayes\n");
35 #ifdef ACULOG
36 		logent(value(HOST), num, "hayes", "can't synch up");
37 #endif
38 		(void) signal(SIGALRM, f);
39 		return (0);
40 	}
41 	if (boolean(value(VERBOSE)))
42 		(void) printf("\ndialing...");
43 	(void) fflush(stdout);
44 	(void) ioctl(FD, TCGETS, &buf);
45 	buf.c_cflag |= HUPCL;
46 	(void) ioctl(FD, TCSETS, &buf);
47 	(void) ioctl(FD, TCFLSH, TCIOFLUSH);
48 
49 	if (sigsetjmp(timeoutbuf, 1)) {
50 #ifdef ACULOG
51 		char line[80];
52 
53 		(void) sprintf(line, "%d second dial timeout",
54 		    number(value(DIALTIMEOUT)));
55 		logent(value(HOST), num, "hayes", line);
56 #endif
57 		hayes_disconnect();
58 		(void) signal(SIGALRM, f);
59 		return (0);
60 	}
61 	(void) alarm(number(value(DIALTIMEOUT)));
62 	(void) ioctl(FD, TCFLSH, TCIOFLUSH);
63 	if (*num == 'S')
64 		(void) write(FD, "AT", 2);
65 	else
66 		(void) write(FD, "ATDT", 4);	/* use tone dialing */
67 	(void) write(FD, num, strlen(num));
68 	(void) write(FD, "\r", 1);
69 	(void) read(FD, &code, 1);
70 	(void) read(FD, &cr, 1);
71 	if (code == '1' && cr == '0')
72 		(void) read(FD, &cr, 1);
73 	(void) alarm(0);
74 	(void) signal(SIGALRM, f);
75 	if ((code == '1' || code == '5') && cr == '\r')
76 		return (1);
77 	return (0);
78 }
79 
80 void
81 hayes_disconnect(void)
82 {
83 	(void) close(FD);
84 }
85 
86 void
87 hayes_abort(void)
88 {
89 	int dtr = TIOCM_DTR;
90 
91 	(void) alarm(0);
92 	(void) ioctl(FD, TIOCMBIC, &dtr);
93 	(void) sleep(2);
94 	(void) ioctl(FD, TCFLSH, TCIOFLUSH);
95 	(void) close(FD);
96 }
97 
98 static void
99 sigALRM(void)
100 {
101 	siglongjmp(timeoutbuf, 1);
102 }
103 
104 /*
105  * This piece of code attempts to get the hayes in sync.
106  */
107 static int
108 hayes_sync(int fd)
109 {
110 	int tries;
111 	char code = 0, cr = 0;
112 	int dtr = TIOCM_DTR;
113 
114 	/*
115 	 * Toggle DTR to force anyone off that might have left
116 	 * the modem connected, and insure a consistent state
117 	 * to start from.
118 	 */
119 	(void) ioctl(fd, TIOCMBIC, &dtr);
120 	(void) sleep(1);
121 	(void) ioctl(fd, TIOCMBIS, &dtr);
122 	for (tries = 0; tries < 3; tries++) {
123 		/*
124 		 * After reseting the modem, initialize all
125 		 * parameters to required vaules:
126 		 *
127 		 *	V0	- result codes are single digits
128 		 *	Q0	- result codes ARE sent
129 		 *	E0	- do not echo
130 		 *	S0=1	- automatically answer phone
131 		 *	S2=255	- disable escape character
132 		 *	S12=255	- longest possible escape guard time
133 		 */
134 		(void) write(fd, "ATV0Q0E0S0=1S2=255S12=255\r", 26);
135 		(void) sleep(1);
136 		/* flush any echoes or return codes */
137 		(void) ioctl(fd, TCFLSH, TCIOFLUSH);
138 		/* now see if the modem is talking to us properly */
139 		(void) write(fd, "AT\r", 3);
140 		if (sigsetjmp(timeoutbuf, 1) == 0) {
141 			(void) alarm(2);
142 			(void) read(FD, &code, 1);
143 			(void) read(FD, &cr, 1);
144 			if (code == '0' && cr == '\r')
145 				return (1);
146 		}
147 	}
148 	return (0);
149 }
150