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 const char rcsid[] = 36 "$FreeBSD$"; 37 #endif 38 39 /* 40 * Routines for calling up on a Telebit T3000 modem. 41 * Derived from Courier driver. 42 */ 43 #include "tipconf.h" 44 #include "tip.h" 45 #include "acucommon.h" 46 #include <stdio.h> 47 #include <unistd.h> 48 49 #define MAXRETRY 5 50 51 static void sigALRM(); 52 static int timeout = 0; 53 static int connected = 0; 54 static jmp_buf timeoutbuf, intbuf; 55 static int t3000_sync(); 56 57 t3000_dialer(num, acu) 58 register char *num; 59 char *acu; 60 { 61 register char *cp; 62 #if ACULOG 63 char line[80]; 64 #endif 65 static int t3000_connect(), t3000_swallow(); 66 67 if (boolean(value(VERBOSE))) 68 printf("Using \"%s\"\n", acu); 69 70 acu_hupcl (); 71 /* 72 * Get in synch. 73 */ 74 if (!t3000_sync()) { 75 badsynch: 76 printf("can't synchronize with t3000\n"); 77 #if ACULOG 78 logent(value(HOST), num, "t3000", "can't synch up"); 79 #endif 80 return (0); 81 } 82 t3000_write(FD, "AT E0\r", 6); /* turn off echoing */ 83 sleep(1); 84 #ifdef DEBUG 85 if (boolean(value(VERBOSE))) 86 t3000_verbose_read(); 87 #endif 88 ioctl(FD, TIOCFLUSH, 0); /* flush any clutter */ 89 t3000_write(FD, "AT E0 H0 Q0 X4 V1\r", 18); 90 if (!t3000_swallow("\r\nOK\r\n")) 91 goto badsynch; 92 fflush(stdout); 93 t3000_write(FD, "AT D", 4); 94 for (cp = num; *cp; cp++) 95 if (*cp == '=') 96 *cp = ','; 97 t3000_write(FD, num, strlen(num)); 98 t3000_write(FD, "\r", 1); 99 connected = t3000_connect(); 100 #if ACULOG 101 if (timeout) { 102 sprintf(line, "%d second dial timeout", 103 number(value(DIALTIMEOUT))); 104 logent(value(HOST), num, "t3000", line); 105 } 106 #endif 107 if (timeout) 108 t3000_disconnect(); 109 return (connected); 110 } 111 112 t3000_disconnect() 113 { 114 /* first hang up the modem*/ 115 ioctl(FD, TIOCCDTR, 0); 116 sleep(1); 117 ioctl(FD, TIOCSDTR, 0); 118 t3000_sync(); /* reset */ 119 close(FD); 120 } 121 122 t3000_abort() 123 { 124 t3000_write(FD, "\r", 1); /* send anything to abort the call */ 125 t3000_disconnect(); 126 } 127 128 static void 129 sigALRM() 130 { 131 printf("\07timeout waiting for reply\n"); 132 timeout = 1; 133 longjmp(timeoutbuf, 1); 134 } 135 136 static int 137 t3000_swallow(match) 138 register char *match; 139 { 140 sig_t f; 141 char c; 142 143 f = signal(SIGALRM, sigALRM); 144 timeout = 0; 145 do { 146 if (*match =='\0') { 147 signal(SIGALRM, f); 148 return (1); 149 } 150 if (setjmp(timeoutbuf)) { 151 signal(SIGALRM, f); 152 return (0); 153 } 154 alarm(number(value(DIALTIMEOUT))); 155 read(FD, &c, 1); 156 alarm(0); 157 c &= 0177; 158 #ifdef DEBUG 159 if (boolean(value(VERBOSE))) 160 putchar(c); 161 #endif 162 } while (c == *match++); 163 #ifdef DEBUG 164 if (boolean(value(VERBOSE))) 165 fflush(stdout); 166 #endif 167 signal(SIGALRM, SIG_DFL); 168 return (0); 169 } 170 171 #ifndef B19200 /* XXX */ 172 #define B19200 EXTA 173 #define B38400 EXTB 174 #endif 175 176 struct tbaud_msg { 177 char *msg; 178 int baud; 179 int baud2; 180 } tbaud_msg[] = { 181 "", B300, 0, 182 " 1200", B1200, 0, 183 " 2400", B2400, 0, 184 " 4800", B4800, 0, 185 " 9600", B9600, 0, 186 " 14400", B19200, B9600, 187 " 19200", B19200, B9600, 188 " 38400", B38400, B9600, 189 " 57600", B38400, B9600, 190 " 7512", B9600, 0, 191 " 1275", B2400, 0, 192 " 7200", B9600, 0, 193 " 12000", B19200, B9600, 194 0, 0, 0, 195 }; 196 197 static int 198 t3000_connect() 199 { 200 char c; 201 int nc, nl, n; 202 char dialer_buf[64]; 203 struct tbaud_msg *bm; 204 sig_t f; 205 206 if (t3000_swallow("\r\n") == 0) 207 return (0); 208 f = signal(SIGALRM, sigALRM); 209 again: 210 nc = 0; nl = sizeof(dialer_buf)-1; 211 bzero(dialer_buf, sizeof(dialer_buf)); 212 timeout = 0; 213 for (nc = 0, nl = sizeof(dialer_buf)-1 ; nl > 0 ; nc++, nl--) { 214 if (setjmp(timeoutbuf)) 215 break; 216 alarm(number(value(DIALTIMEOUT))); 217 n = read(FD, &c, 1); 218 alarm(0); 219 if (n <= 0) 220 break; 221 c &= 0x7f; 222 if (c == '\r') { 223 if (t3000_swallow("\n") == 0) 224 break; 225 if (!dialer_buf[0]) 226 goto again; 227 if (strcmp(dialer_buf, "RINGING") == 0 && 228 boolean(value(VERBOSE))) { 229 #ifdef DEBUG 230 printf("%s\r\n", dialer_buf); 231 #endif 232 goto again; 233 } 234 if (strncmp(dialer_buf, "CONNECT", 235 sizeof("CONNECT")-1) != 0) 236 break; 237 for (bm = tbaud_msg ; bm->msg ; bm++) 238 if (strcmp(bm->msg, 239 dialer_buf+sizeof("CONNECT")-1) == 0) { 240 if (!(acu_setspeed (bm->baud) || (bm->baud2 && acu_setspeed (bm->baud2)))) 241 goto error; 242 signal(SIGALRM, f); 243 #ifdef DEBUG 244 if (boolean(value(VERBOSE))) 245 printf("%s\r\n", dialer_buf); 246 #endif 247 return (1); 248 } 249 break; 250 } 251 dialer_buf[nc] = c; 252 #ifdef notdef 253 if (boolean(value(VERBOSE))) 254 putchar(c); 255 #endif 256 } 257 error1: 258 printf("%s\r\n", dialer_buf); 259 error: 260 signal(SIGALRM, f); 261 return (0); 262 } 263 264 /* 265 * This convoluted piece of code attempts to get 266 * the t3000 in sync. 267 */ 268 static int 269 t3000_sync() 270 { 271 int already = 0; 272 int len; 273 char buf[40]; 274 275 while (already++ < MAXRETRY) { 276 ioctl(FD, TIOCFLUSH, 0); /* flush any clutter */ 277 t3000_write(FD, "\rAT Z\r", 6); /* reset modem */ 278 bzero(buf, sizeof(buf)); 279 sleep(2); 280 ioctl(FD, FIONREAD, &len); 281 #if 1 282 if (len == 0) len = 1; 283 #endif 284 if (len) { 285 len = read(FD, buf, sizeof(buf)); 286 #ifdef DEBUG 287 buf[len] = '\0'; 288 printf("t3000_sync: (\"%s\")\n\r", buf); 289 #endif 290 if (index(buf, '0') || 291 (index(buf, 'O') && index(buf, 'K'))) 292 return(1); 293 } 294 /* 295 * If not strapped for DTR control, 296 * try to get command mode. 297 */ 298 sleep(1); 299 t3000_write(FD, "+++", 3); 300 sleep(1); 301 /* 302 * Toggle DTR to force anyone off that might have left 303 * the modem connected. 304 */ 305 ioctl(FD, TIOCCDTR, 0); 306 sleep(1); 307 ioctl(FD, TIOCSDTR, 0); 308 } 309 t3000_write(FD, "\rAT Z\r", 6); 310 return (0); 311 } 312 313 t3000_write(fd, cp, n) 314 int fd; 315 char *cp; 316 int n; 317 { 318 #ifdef notdef 319 if (boolean(value(VERBOSE))) 320 write(STDOUT_FILENO, cp, n); 321 #endif 322 acu_flush (); 323 t3000_nap(); 324 for ( ; n-- ; cp++) { 325 write(fd, cp, 1); 326 acu_flush (); 327 t3000_nap(); 328 } 329 } 330 331 #ifdef DEBUG 332 t3000_verbose_read() 333 { 334 int n = 0; 335 char buf[BUFSIZ]; 336 337 if (ioctl(FD, FIONREAD, &n) < 0) 338 return; 339 if (n <= 0) 340 return; 341 if (read(FD, buf, n) != n) 342 return; 343 write(STDOUT_FILENO, buf, n); 344 } 345 #endif 346 347 t3000_nap() 348 { 349 acu_nap (50); 350 } 351 352 /* end of t3000.c */ 353