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