1 /* 2 * Copyright (c) 1992, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by the University of 16 * California, Berkeley and its contributors. 17 * 4. Neither the name of the University nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 */ 33 34 #ifndef lint 35 static char sccsid[] = "@(#)t3000.c 8.1 (Berkeley) 6/6/93"; 36 #endif /* not lint */ 37 38 /* 39 * Routines for calling up on a Telebit T3000 modem. 40 * Derived from Courier driver. 41 */ 42 #include "tipconf.h" 43 #include "tip.h" 44 #include "acucommon.h" 45 #include <stdio.h> 46 47 #define MAXRETRY 5 48 49 static void sigALRM(); 50 static int timeout = 0; 51 static int connected = 0; 52 static jmp_buf timeoutbuf, intbuf; 53 static int t3000_sync(); 54 55 t3000_dialer(num, acu) 56 register char *num; 57 char *acu; 58 { 59 register char *cp; 60 #if ACULOG 61 char line[80]; 62 #endif 63 static int t3000_connect(), t3000_swallow(); 64 65 if (boolean(value(VERBOSE))) 66 printf("Using \"%s\"\n", acu); 67 68 acu_hupcl (); 69 /* 70 * Get in synch. 71 */ 72 if (!t3000_sync()) { 73 badsynch: 74 printf("can't synchronize with t3000\n"); 75 #if ACULOG 76 logent(value(HOST), num, "t3000", "can't synch up"); 77 #endif 78 return (0); 79 } 80 t3000_write(FD, "AT E0\r", 6); /* turn off echoing */ 81 sleep(1); 82 #ifdef DEBUG 83 if (boolean(value(VERBOSE))) 84 t3000_verbose_read(); 85 #endif 86 ioctl(FD, TIOCFLUSH, 0); /* flush any clutter */ 87 t3000_write(FD, "AT E0 H0 Q0 X4 V1\r", 18); 88 if (!t3000_swallow("\r\nOK\r\n")) 89 goto badsynch; 90 fflush(stdout); 91 t3000_write(FD, "AT D", 4); 92 for (cp = num; *cp; cp++) 93 if (*cp == '=') 94 *cp = ','; 95 t3000_write(FD, num, strlen(num)); 96 t3000_write(FD, "\r", 1); 97 connected = t3000_connect(); 98 #if ACULOG 99 if (timeout) { 100 sprintf(line, "%d second dial timeout", 101 number(value(DIALTIMEOUT))); 102 logent(value(HOST), num, "t3000", line); 103 } 104 #endif 105 if (timeout) 106 t3000_disconnect(); 107 return (connected); 108 } 109 110 t3000_disconnect() 111 { 112 /* first hang up the modem*/ 113 ioctl(FD, TIOCCDTR, 0); 114 sleep(1); 115 ioctl(FD, TIOCSDTR, 0); 116 t3000_sync(); /* reset */ 117 close(FD); 118 } 119 120 t3000_abort() 121 { 122 t3000_write(FD, "\r", 1); /* send anything to abort the call */ 123 t3000_disconnect(); 124 } 125 126 static void 127 sigALRM() 128 { 129 printf("\07timeout waiting for reply\n"); 130 timeout = 1; 131 longjmp(timeoutbuf, 1); 132 } 133 134 static int 135 t3000_swallow(match) 136 register char *match; 137 { 138 sig_t f; 139 char c; 140 141 f = signal(SIGALRM, sigALRM); 142 timeout = 0; 143 do { 144 if (*match =='\0') { 145 signal(SIGALRM, f); 146 return (1); 147 } 148 if (setjmp(timeoutbuf)) { 149 signal(SIGALRM, f); 150 return (0); 151 } 152 alarm(number(value(DIALTIMEOUT))); 153 read(FD, &c, 1); 154 alarm(0); 155 c &= 0177; 156 #ifdef DEBUG 157 if (boolean(value(VERBOSE))) 158 putchar(c); 159 #endif 160 } while (c == *match++); 161 #ifdef DEBUG 162 if (boolean(value(VERBOSE))) 163 fflush(stdout); 164 #endif 165 signal(SIGALRM, SIG_DFL); 166 return (0); 167 } 168 169 #ifndef B19200 /* XXX */ 170 #define B19200 EXTA 171 #define B38400 EXTB 172 #endif 173 174 struct tbaud_msg { 175 char *msg; 176 int baud; 177 int baud2; 178 } tbaud_msg[] = { 179 "", B300, 0, 180 " 1200", B1200, 0, 181 " 2400", B2400, 0, 182 " 4800", B4800, 0, 183 " 9600", B9600, 0, 184 " 14400", B19200, B9600, 185 " 19200", B19200, B9600, 186 " 38400", B38400, B9600, 187 " 57600", B38400, B9600, 188 " 7512", B9600, 0, 189 " 1275", B2400, 0, 190 " 7200", B9600, 0, 191 " 12000", B19200, B9600, 192 0, 0, 0, 193 }; 194 195 static int 196 t3000_connect() 197 { 198 char c; 199 int nc, nl, n; 200 char dialer_buf[64]; 201 struct tbaud_msg *bm; 202 sig_t f; 203 204 if (t3000_swallow("\r\n") == 0) 205 return (0); 206 f = signal(SIGALRM, sigALRM); 207 again: 208 nc = 0; nl = sizeof(dialer_buf)-1; 209 bzero(dialer_buf, sizeof(dialer_buf)); 210 timeout = 0; 211 for (nc = 0, nl = sizeof(dialer_buf)-1 ; nl > 0 ; nc++, nl--) { 212 if (setjmp(timeoutbuf)) 213 break; 214 alarm(number(value(DIALTIMEOUT))); 215 n = read(FD, &c, 1); 216 alarm(0); 217 if (n <= 0) 218 break; 219 c &= 0x7f; 220 if (c == '\r') { 221 if (t3000_swallow("\n") == 0) 222 break; 223 if (!dialer_buf[0]) 224 goto again; 225 if (strcmp(dialer_buf, "RINGING") == 0 && 226 boolean(value(VERBOSE))) { 227 #ifdef DEBUG 228 printf("%s\r\n", dialer_buf); 229 #endif 230 goto again; 231 } 232 if (strncmp(dialer_buf, "CONNECT", 233 sizeof("CONNECT")-1) != 0) 234 break; 235 for (bm = tbaud_msg ; bm->msg ; bm++) 236 if (strcmp(bm->msg, 237 dialer_buf+sizeof("CONNECT")-1) == 0) { 238 if (!(acu_setspeed (bm->baud) || (bm->baud2 && acu_setspeed (bm->baud2)))) 239 goto error; 240 signal(SIGALRM, f); 241 #ifdef DEBUG 242 if (boolean(value(VERBOSE))) 243 printf("%s\r\n", dialer_buf); 244 #endif 245 return (1); 246 } 247 break; 248 } 249 dialer_buf[nc] = c; 250 #ifdef notdef 251 if (boolean(value(VERBOSE))) 252 putchar(c); 253 #endif 254 } 255 error1: 256 printf("%s\r\n", dialer_buf); 257 error: 258 signal(SIGALRM, f); 259 return (0); 260 } 261 262 /* 263 * This convoluted piece of code attempts to get 264 * the t3000 in sync. 265 */ 266 static int 267 t3000_sync() 268 { 269 int already = 0; 270 int len; 271 char buf[40]; 272 273 while (already++ < MAXRETRY) { 274 ioctl(FD, TIOCFLUSH, 0); /* flush any clutter */ 275 t3000_write(FD, "\rAT Z\r", 6); /* reset modem */ 276 bzero(buf, sizeof(buf)); 277 sleep(2); 278 ioctl(FD, FIONREAD, &len); 279 #if 1 280 if (len == 0) len = 1; 281 #endif 282 if (len) { 283 len = read(FD, buf, sizeof(buf)); 284 #ifdef DEBUG 285 buf[len] = '\0'; 286 printf("t3000_sync: (\"%s\")\n\r", buf); 287 #endif 288 if (index(buf, '0') || 289 (index(buf, 'O') && index(buf, 'K'))) 290 return(1); 291 } 292 /* 293 * If not strapped for DTR control, 294 * try to get command mode. 295 */ 296 sleep(1); 297 t3000_write(FD, "+++", 3); 298 sleep(1); 299 /* 300 * Toggle DTR to force anyone off that might have left 301 * the modem connected. 302 */ 303 ioctl(FD, TIOCCDTR, 0); 304 sleep(1); 305 ioctl(FD, TIOCSDTR, 0); 306 } 307 t3000_write(FD, "\rAT Z\r", 6); 308 return (0); 309 } 310 311 t3000_write(fd, cp, n) 312 int fd; 313 char *cp; 314 int n; 315 { 316 #ifdef notdef 317 if (boolean(value(VERBOSE))) 318 write(1, cp, n); 319 #endif 320 acu_flush (); 321 t3000_nap(); 322 for ( ; n-- ; cp++) { 323 write(fd, cp, 1); 324 acu_flush (); 325 t3000_nap(); 326 } 327 } 328 329 #ifdef DEBUG 330 t3000_verbose_read() 331 { 332 int n = 0; 333 char buf[BUFSIZ]; 334 335 if (ioctl(FD, FIONREAD, &n) < 0) 336 return; 337 if (n <= 0) 338 return; 339 if (read(FD, buf, n) != n) 340 return; 341 write(1, buf, n); 342 } 343 #endif 344 345 t3000_nap() 346 { 347 acu_nap (50); 348 } 349 350 /* end of t3000.c */ 351