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