1 /*- 2 * Copyright (c) 1982, 1986, 1991, 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 * @(#)tty_compat.c 8.1 (Berkeley) 6/10/93 34 * $Id: tty_compat.c,v 1.6 1994/10/11 20:04:49 ache Exp $ 35 */ 36 37 /* 38 * mapping routines for old line discipline (yuck) 39 */ 40 #if defined(COMPAT_43) || defined(COMPAT_SUNOS) 41 42 #include <sys/param.h> 43 #include <sys/systm.h> 44 #include <sys/ioctl.h> 45 #include <sys/proc.h> 46 #include <sys/tty.h> 47 #include <sys/termios.h> 48 #include <sys/file.h> 49 #include <sys/conf.h> 50 #include <sys/kernel.h> 51 #include <sys/syslog.h> 52 53 static int ttcompatgetflags __P((struct tty *tp)); 54 static void ttcompatsetflags __P((struct tty *tp, struct termios *t)); 55 static void ttcompatsetlflags __P((struct tty *tp, struct termios *t)); 56 57 int ttydebug = 0; 58 59 static struct speedtab compatspeeds[] = { 60 #define MAX_SPEED 17 61 { 115200, 17 }, 62 { 57600, 16 }, 63 { 38400, 15 }, 64 { 19200, 14 }, 65 { 9600, 13 }, 66 { 4800, 12 }, 67 { 2400, 11 }, 68 { 1800, 10 }, 69 { 1200, 9 }, 70 { 600, 8 }, 71 { 300, 7 }, 72 { 200, 6 }, 73 { 150, 5 }, 74 { 134, 4 }, 75 { 110, 3 }, 76 { 75, 2 }, 77 { 50, 1 }, 78 { 0, 0 }, 79 { -1, -1 }, 80 }; 81 static int compatspcodes[] = { 82 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 83 1800, 2400, 4800, 9600, 19200, 38400, 57600, 115200, 84 }; 85 86 /*ARGSUSED*/ 87 int 88 ttcompat(tp, com, data, flag) 89 register struct tty *tp; 90 int com; 91 caddr_t data; 92 int flag; 93 { 94 95 switch (com) { 96 case TIOCGETP: { 97 register struct sgttyb *sg = (struct sgttyb *)data; 98 register u_char *cc = tp->t_cc; 99 register speed; 100 101 speed = ttspeedtab(tp->t_ospeed, compatspeeds); 102 sg->sg_ospeed = (speed == -1) ? MAX_SPEED : speed; 103 if (tp->t_ispeed == 0) 104 sg->sg_ispeed = sg->sg_ospeed; 105 else { 106 speed = ttspeedtab(tp->t_ispeed, compatspeeds); 107 sg->sg_ispeed = (speed == -1) ? MAX_SPEED : speed; 108 } 109 sg->sg_erase = cc[VERASE]; 110 sg->sg_kill = cc[VKILL]; 111 sg->sg_flags = tp->t_flags = ttcompatgetflags(tp); 112 break; 113 } 114 115 case TIOCSETP: 116 case TIOCSETN: { 117 register struct sgttyb *sg = (struct sgttyb *)data; 118 struct termios term; 119 int speed; 120 121 term = tp->t_termios; 122 if ((speed = sg->sg_ispeed) > MAX_SPEED || speed < 0) 123 term.c_ispeed = speed; 124 else 125 term.c_ispeed = compatspcodes[speed]; 126 if ((speed = sg->sg_ospeed) > MAX_SPEED || speed < 0) 127 term.c_ospeed = speed; 128 else 129 term.c_ospeed = compatspcodes[speed]; 130 term.c_cc[VERASE] = sg->sg_erase; 131 term.c_cc[VKILL] = sg->sg_kill; 132 tp->t_flags = (tp->t_flags&0xffff0000) | (sg->sg_flags&0xffff); 133 ttcompatsetflags(tp, &term); 134 return (ttioctl(tp, com == TIOCSETP ? TIOCSETAF : TIOCSETA, 135 &term, flag)); 136 } 137 138 case TIOCGETC: { 139 struct tchars *tc = (struct tchars *)data; 140 register u_char *cc = tp->t_cc; 141 142 tc->t_intrc = cc[VINTR]; 143 tc->t_quitc = cc[VQUIT]; 144 tc->t_startc = cc[VSTART]; 145 tc->t_stopc = cc[VSTOP]; 146 tc->t_eofc = cc[VEOF]; 147 tc->t_brkc = cc[VEOL]; 148 break; 149 } 150 case TIOCSETC: { 151 struct tchars *tc = (struct tchars *)data; 152 register u_char *cc = tp->t_cc; 153 154 cc[VINTR] = tc->t_intrc; 155 cc[VQUIT] = tc->t_quitc; 156 cc[VSTART] = tc->t_startc; 157 cc[VSTOP] = tc->t_stopc; 158 cc[VEOF] = tc->t_eofc; 159 cc[VEOL] = tc->t_brkc; 160 if (tc->t_brkc == -1) 161 cc[VEOL2] = _POSIX_VDISABLE; 162 break; 163 } 164 case TIOCSLTC: { 165 struct ltchars *ltc = (struct ltchars *)data; 166 register u_char *cc = tp->t_cc; 167 168 cc[VSUSP] = ltc->t_suspc; 169 cc[VDSUSP] = ltc->t_dsuspc; 170 cc[VREPRINT] = ltc->t_rprntc; 171 cc[VDISCARD] = ltc->t_flushc; 172 cc[VWERASE] = ltc->t_werasc; 173 cc[VLNEXT] = ltc->t_lnextc; 174 break; 175 } 176 case TIOCGLTC: { 177 struct ltchars *ltc = (struct ltchars *)data; 178 register u_char *cc = tp->t_cc; 179 180 ltc->t_suspc = cc[VSUSP]; 181 ltc->t_dsuspc = cc[VDSUSP]; 182 ltc->t_rprntc = cc[VREPRINT]; 183 ltc->t_flushc = cc[VDISCARD]; 184 ltc->t_werasc = cc[VWERASE]; 185 ltc->t_lnextc = cc[VLNEXT]; 186 break; 187 } 188 case TIOCLBIS: 189 case TIOCLBIC: 190 case TIOCLSET: { 191 struct termios term; 192 193 term = tp->t_termios; 194 if (com == TIOCLSET) 195 tp->t_flags = (tp->t_flags&0xffff) | *(int *)data<<16; 196 else { 197 tp->t_flags = 198 (ttcompatgetflags(tp)&0xffff0000)|(tp->t_flags&0xffff); 199 if (com == TIOCLBIS) 200 tp->t_flags |= *(int *)data<<16; 201 else 202 tp->t_flags &= ~(*(int *)data<<16); 203 } 204 ttcompatsetlflags(tp, &term); 205 return (ttioctl(tp, TIOCSETA, &term, flag)); 206 } 207 case TIOCLGET: 208 tp->t_flags = 209 (ttcompatgetflags(tp) & 0xffff0000UL) 210 | (tp->t_flags & 0xffff); 211 *(int *)data = tp->t_flags>>16; 212 if (ttydebug) 213 printf("CLGET: returning %x\n", *(int *)data); 214 break; 215 216 case OTIOCGETD: 217 *(int *)data = tp->t_line ? tp->t_line : 2; 218 break; 219 220 case OTIOCSETD: { 221 int ldisczero = 0; 222 223 return (ttioctl(tp, TIOCSETD, 224 *(int *)data == 2 ? (caddr_t)&ldisczero : data, flag)); 225 } 226 227 case OTIOCCONS: 228 *(int *)data = 1; 229 return (ttioctl(tp, TIOCCONS, data, flag)); 230 231 default: 232 return (-1); 233 } 234 return (0); 235 } 236 237 static int 238 ttcompatgetflags(tp) 239 register struct tty *tp; 240 { 241 register long iflag = tp->t_iflag; 242 register long lflag = tp->t_lflag; 243 register long oflag = tp->t_oflag; 244 register long cflag = tp->t_cflag; 245 register flags = 0; 246 247 if (iflag&IXOFF) 248 flags |= TANDEM; 249 if (iflag&ICRNL || oflag&ONLCR) 250 flags |= CRMOD; 251 if ((cflag&CSIZE) == CS8) { 252 flags |= PASS8; 253 if (iflag&ISTRIP) 254 flags |= ANYP; 255 } 256 else if (cflag&PARENB) { 257 if (iflag&INPCK) { 258 if (cflag&PARODD) 259 flags |= ODDP; 260 else 261 flags |= EVENP; 262 } else 263 flags |= EVENP | ODDP; 264 } 265 266 if ((lflag&ICANON) == 0) { 267 /* fudge */ 268 if (iflag&(INPCK|ISTRIP|IXON) || lflag&(IEXTEN|ISIG) 269 || cflag&(CSIZE|PARENB) != CS8) 270 flags |= CBREAK; 271 else 272 flags |= RAW; 273 } 274 if (!(flags&RAW) && !(oflag&OPOST) && cflag&(CSIZE|PARENB) == CS8) 275 flags |= LITOUT; 276 if (cflag&MDMBUF) 277 flags |= MDMBUF; 278 if ((cflag&HUPCL) == 0) 279 flags |= NOHANG; 280 if (oflag&OXTABS) 281 flags |= XTABS; 282 if (lflag&ECHOE) 283 flags |= CRTERA|CRTBS; 284 if (lflag&ECHOKE) 285 flags |= CRTKIL|CRTBS; 286 if (lflag&ECHOPRT) 287 flags |= PRTERA; 288 if (lflag&ECHOCTL) 289 flags |= CTLECH; 290 if ((iflag&IXANY) == 0) 291 flags |= DECCTQ; 292 flags |= lflag&(ECHO|TOSTOP|FLUSHO|PENDIN|NOFLSH); 293 if (ttydebug) 294 printf("getflags: %x\n", flags); 295 return (flags); 296 } 297 298 static void 299 ttcompatsetflags(tp, t) 300 register struct tty *tp; 301 register struct termios *t; 302 { 303 register flags = tp->t_flags; 304 register long iflag = t->c_iflag; 305 register long oflag = t->c_oflag; 306 register long lflag = t->c_lflag; 307 register long cflag = t->c_cflag; 308 309 if (flags & RAW) { 310 iflag = 0; 311 lflag &= ~(ECHOCTL|ISIG|ICANON|IEXTEN); 312 } else { 313 iflag |= BRKINT|IXON|IMAXBEL; 314 lflag |= ISIG|IEXTEN|ECHOCTL; /* XXX was echoctl on ? */ 315 if (flags & XTABS) 316 oflag |= OXTABS; 317 else 318 oflag &= ~OXTABS; 319 if (flags & CBREAK) 320 lflag &= ~ICANON; 321 else 322 lflag |= ICANON; 323 if (flags&CRMOD) { 324 iflag |= ICRNL; 325 oflag |= ONLCR; 326 } else { 327 iflag &= ~ICRNL; 328 oflag &= ~ONLCR; 329 } 330 } 331 if (flags&ECHO) 332 lflag |= ECHO; 333 else 334 lflag &= ~ECHO; 335 336 cflag &= ~(CSIZE|PARENB); 337 if (flags&(RAW|LITOUT|PASS8)) { 338 cflag |= CS8; 339 if (!(flags&(RAW|PASS8)) 340 || (flags&(RAW|PASS8|ANYP)) == (PASS8|ANYP)) 341 iflag |= ISTRIP; 342 else 343 iflag &= ~ISTRIP; 344 if (flags&(RAW|LITOUT)) 345 oflag &= ~OPOST; 346 else 347 oflag |= OPOST; 348 } else { 349 cflag |= CS7|PARENB; 350 iflag |= ISTRIP; 351 oflag |= OPOST; 352 } 353 if ((flags&(EVENP|ODDP)) == EVENP) { 354 iflag |= INPCK; 355 cflag &= ~PARODD; 356 } else if ((flags&(EVENP|ODDP)) == ODDP) { 357 iflag |= INPCK; 358 cflag |= PARODD; 359 } else 360 iflag &= ~INPCK; 361 if (flags&TANDEM) 362 iflag |= IXOFF; 363 else 364 iflag &= ~IXOFF; 365 if ((flags&DECCTQ) == 0) 366 iflag |= IXANY; 367 else 368 iflag &= ~IXANY; 369 t->c_iflag = iflag; 370 t->c_oflag = oflag; 371 t->c_lflag = lflag; 372 t->c_cflag = cflag; 373 } 374 375 static void 376 ttcompatsetlflags(tp, t) 377 register struct tty *tp; 378 register struct termios *t; 379 { 380 register flags = tp->t_flags; 381 register long iflag = t->c_iflag; 382 register long oflag = t->c_oflag; 383 register long lflag = t->c_lflag; 384 register long cflag = t->c_cflag; 385 386 if (flags&CRTERA) 387 lflag |= ECHOE; 388 else 389 lflag &= ~ECHOE; 390 if (flags&CRTKIL) 391 lflag |= ECHOKE; 392 else 393 lflag &= ~ECHOKE; 394 if (flags&PRTERA) 395 lflag |= ECHOPRT; 396 else 397 lflag &= ~ECHOPRT; 398 if (flags&CTLECH) 399 lflag |= ECHOCTL; 400 else 401 lflag &= ~ECHOCTL; 402 if (flags&TANDEM) 403 iflag |= IXOFF; 404 else 405 iflag &= ~IXOFF; 406 if ((flags&DECCTQ) == 0) 407 iflag |= IXANY; 408 else 409 iflag &= ~IXANY; 410 if (flags & MDMBUF) 411 cflag |= MDMBUF; 412 else 413 cflag &= ~MDMBUF; 414 if (flags&NOHANG) 415 cflag &= ~HUPCL; 416 else 417 cflag |= HUPCL; 418 lflag &= ~(TOSTOP|FLUSHO|PENDIN|NOFLSH); 419 lflag |= flags&(TOSTOP|FLUSHO|PENDIN|NOFLSH); 420 421 /* 422 * The next if-else statement is copied from above so don't bother 423 * checking it separately. We could avoid fiddlling with the 424 * character size if the mode is already RAW or if neither the 425 * LITOUT bit or the PASS8 bit is being changed, but the delta of 426 * the change is not available here and skipping the RAW case would 427 * make the code different from above. 428 */ 429 cflag &= ~(CSIZE|PARENB); 430 if (flags&(RAW|LITOUT|PASS8)) { 431 cflag |= CS8; 432 if (!(flags&(RAW|PASS8)) 433 || (flags&(RAW|PASS8|ANYP)) == (PASS8|ANYP)) 434 iflag |= ISTRIP; 435 else 436 iflag &= ~ISTRIP; 437 if (flags&(RAW|LITOUT)) 438 oflag &= ~OPOST; 439 else 440 oflag |= OPOST; 441 } else { 442 cflag |= CS7|PARENB; 443 iflag |= ISTRIP; 444 oflag |= OPOST; 445 } 446 t->c_iflag = iflag; 447 t->c_oflag = oflag; 448 t->c_lflag = lflag; 449 t->c_cflag = cflag; 450 } 451 #endif /* COMPAT_43 || COMPAT_SUNOS */ 452