tty_compat.c revision 33825
1251607Sdim/*- 2251607Sdim * Copyright (c) 1982, 1986, 1991, 1993 3251607Sdim * The Regents of the University of California. All rights reserved. 4251607Sdim * 5251607Sdim * Redistribution and use in source and binary forms, with or without 6251607Sdim * modification, are permitted provided that the following conditions 7251607Sdim * are met: 8251607Sdim * 1. Redistributions of source code must retain the above copyright 9251607Sdim * notice, this list of conditions and the following disclaimer. 10251607Sdim * 2. Redistributions in binary form must reproduce the above copyright 11251607Sdim * notice, this list of conditions and the following disclaimer in the 12251607Sdim * documentation and/or other materials provided with the distribution. 13251607Sdim * 3. All advertising materials mentioning features or use of this software 14251607Sdim * must display the following acknowledgement: 15251607Sdim * This product includes software developed by the University of 16251607Sdim * California, Berkeley and its contributors. 17251607Sdim * 4. Neither the name of the University nor the names of its contributors 18251607Sdim * may be used to endorse or promote products derived from this software 19251607Sdim * without specific prior written permission. 20251607Sdim * 21251607Sdim * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22251607Sdim * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23251607Sdim * 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.26 1998/01/25 17:25:34 steve Exp $ 35 */ 36 37#include "opt_compat.h" 38 39/* 40 * mapping routines for old line discipline (yuck) 41 */ 42#if defined(COMPAT_43) || defined(COMPAT_SUNOS) 43 44#include <sys/param.h> 45#include <sys/systm.h> 46#include <sys/ioctl_compat.h> 47#include <sys/tty.h> 48#include <sys/kernel.h> 49#include <sys/sysctl.h> 50 51static int ttcompatgetflags __P((struct tty *tp)); 52static void ttcompatsetflags __P((struct tty *tp, struct termios *t)); 53static void ttcompatsetlflags __P((struct tty *tp, struct termios *t)); 54static int ttcompatspeedtab __P((int speed, struct speedtab *table)); 55 56static int ttydebug = 0; 57SYSCTL_INT(_debug, OID_AUTO, ttydebug, CTLFLAG_RW, &ttydebug, 0, ""); 58 59static 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}; 81static int compatspcodes[] = { 82 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 83 1800, 2400, 4800, 9600, 19200, 38400, 57600, 115200, 84}; 85 86static int 87ttcompatspeedtab(speed, table) 88 int speed; 89 register struct speedtab *table; 90{ 91 if (speed == 0) 92 return (0); /* hangup */ 93 for ( ; table->sp_speed > 0; table++) 94 if (table->sp_speed <= speed) /* nearest one, rounded down */ 95 return (table->sp_code); 96 return (1); /* 50, min and not hangup */ 97} 98 99int 100ttsetcompat(tp, com, data, term) 101 register struct tty *tp; 102 int *com; 103 caddr_t data; 104 struct termios *term; 105{ 106 switch (*com) { 107 case TIOCSETP: 108 case TIOCSETN: { 109 register struct sgttyb *sg = (struct sgttyb *)data; 110 int speed; 111 112 if ((speed = sg->sg_ispeed) > MAX_SPEED || speed < 0) 113 return(EINVAL); 114 else if (speed != ttcompatspeedtab(tp->t_ispeed, compatspeeds)) 115 term->c_ispeed = compatspcodes[speed]; 116 else 117 term->c_ispeed = tp->t_ispeed; 118 if ((speed = sg->sg_ospeed) > MAX_SPEED || speed < 0) 119 return(EINVAL); 120 else if (speed != ttcompatspeedtab(tp->t_ospeed, compatspeeds)) 121 term->c_ospeed = compatspcodes[speed]; 122 else 123 term->c_ospeed = tp->t_ospeed; 124 term->c_cc[VERASE] = sg->sg_erase; 125 term->c_cc[VKILL] = sg->sg_kill; 126 tp->t_flags = (tp->t_flags&0xffff0000) | (sg->sg_flags&0xffff); 127 ttcompatsetflags(tp, term); 128 *com = (*com == TIOCSETP) ? TIOCSETAF : TIOCSETA; 129 break; 130 } 131 case TIOCSETC: { 132 struct tchars *tc = (struct tchars *)data; 133 register cc_t *cc; 134 135 cc = term->c_cc; 136 cc[VINTR] = tc->t_intrc; 137 cc[VQUIT] = tc->t_quitc; 138 cc[VSTART] = tc->t_startc; 139 cc[VSTOP] = tc->t_stopc; 140 cc[VEOF] = tc->t_eofc; 141 cc[VEOL] = tc->t_brkc; 142 if (tc->t_brkc == -1) 143 cc[VEOL2] = _POSIX_VDISABLE; 144 *com = TIOCSETA; 145 break; 146 } 147 case TIOCSLTC: { 148 struct ltchars *ltc = (struct ltchars *)data; 149 register cc_t *cc; 150 151 cc = term->c_cc; 152 cc[VSUSP] = ltc->t_suspc; 153 cc[VDSUSP] = ltc->t_dsuspc; 154 cc[VREPRINT] = ltc->t_rprntc; 155 cc[VDISCARD] = ltc->t_flushc; 156 cc[VWERASE] = ltc->t_werasc; 157 cc[VLNEXT] = ltc->t_lnextc; 158 *com = TIOCSETA; 159 break; 160 } 161 case TIOCLBIS: 162 case TIOCLBIC: 163 case TIOCLSET: 164 if (*com == TIOCLSET) 165 tp->t_flags = (tp->t_flags&0xffff) | *(int *)data<<16; 166 else { 167 tp->t_flags = 168 (ttcompatgetflags(tp)&0xffff0000)|(tp->t_flags&0xffff); 169 if (*com == TIOCLBIS) 170 tp->t_flags |= *(int *)data<<16; 171 else 172 tp->t_flags &= ~(*(int *)data<<16); 173 } 174 ttcompatsetlflags(tp, term); 175 *com = TIOCSETA; 176 break; 177 } 178 return 0; 179} 180 181/*ARGSUSED*/ 182int 183ttcompat(tp, com, data, flag) 184 register struct tty *tp; 185 int com; 186 caddr_t data; 187 int flag; 188{ 189 switch (com) { 190 case TIOCSETP: 191 case TIOCSETN: 192 case TIOCSETC: 193 case TIOCSLTC: 194 case TIOCLBIS: 195 case TIOCLBIC: 196 case TIOCLSET: { 197 struct termios term; 198 int error; 199 200 term = tp->t_termios; 201 if ((error = ttsetcompat(tp, &com, data, &term)) != 0) 202 return error; 203 return ttioctl(tp, com, &term, flag); 204 } 205 case TIOCGETP: { 206 register struct sgttyb *sg = (struct sgttyb *)data; 207 register cc_t *cc = tp->t_cc; 208 209 sg->sg_ospeed = ttcompatspeedtab(tp->t_ospeed, compatspeeds); 210 if (tp->t_ispeed == 0) 211 sg->sg_ispeed = sg->sg_ospeed; 212 else 213 sg->sg_ispeed = ttcompatspeedtab(tp->t_ispeed, compatspeeds); 214 sg->sg_erase = cc[VERASE]; 215 sg->sg_kill = cc[VKILL]; 216 sg->sg_flags = tp->t_flags = ttcompatgetflags(tp); 217 break; 218 } 219 case TIOCGETC: { 220 struct tchars *tc = (struct tchars *)data; 221 register cc_t *cc = tp->t_cc; 222 223 tc->t_intrc = cc[VINTR]; 224 tc->t_quitc = cc[VQUIT]; 225 tc->t_startc = cc[VSTART]; 226 tc->t_stopc = cc[VSTOP]; 227 tc->t_eofc = cc[VEOF]; 228 tc->t_brkc = cc[VEOL]; 229 break; 230 } 231 case TIOCGLTC: { 232 struct ltchars *ltc = (struct ltchars *)data; 233 register cc_t *cc = tp->t_cc; 234 235 ltc->t_suspc = cc[VSUSP]; 236 ltc->t_dsuspc = cc[VDSUSP]; 237 ltc->t_rprntc = cc[VREPRINT]; 238 ltc->t_flushc = cc[VDISCARD]; 239 ltc->t_werasc = cc[VWERASE]; 240 ltc->t_lnextc = cc[VLNEXT]; 241 break; 242 } 243 case TIOCLGET: 244 tp->t_flags = 245 (ttcompatgetflags(tp) & 0xffff0000UL) 246 | (tp->t_flags & 0xffff); 247 *(int *)data = tp->t_flags>>16; 248 if (ttydebug) 249 printf("CLGET: returning %x\n", *(int *)data); 250 break; 251 252 case OTIOCGETD: 253 *(int *)data = tp->t_line ? tp->t_line : 2; 254 break; 255 256 case OTIOCSETD: { 257 int ldisczero = 0; 258 259 return (ttioctl(tp, TIOCSETD, 260 *(int *)data == 2 ? (caddr_t)&ldisczero : data, flag)); 261 } 262 263 case OTIOCCONS: 264 *(int *)data = 1; 265 return (ttioctl(tp, TIOCCONS, data, flag)); 266 267 default: 268 return (ENOIOCTL); 269 } 270 return (0); 271} 272 273static int 274ttcompatgetflags(tp) 275 register struct tty *tp; 276{ 277 register tcflag_t iflag = tp->t_iflag; 278 register tcflag_t lflag = tp->t_lflag; 279 register tcflag_t oflag = tp->t_oflag; 280 register tcflag_t cflag = tp->t_cflag; 281 register int flags = 0; 282 283 if (iflag&IXOFF) 284 flags |= TANDEM; 285 if (iflag&ICRNL || oflag&ONLCR) 286 flags |= CRMOD; 287 if ((cflag&CSIZE) == CS8) { 288 flags |= PASS8; 289 if (iflag&ISTRIP) 290 flags |= ANYP; 291 } 292 else if (cflag&PARENB) { 293 if (iflag&INPCK) { 294 if (cflag&PARODD) 295 flags |= ODDP; 296 else 297 flags |= EVENP; 298 } else 299 flags |= EVENP | ODDP; 300 } 301 302 if ((lflag&ICANON) == 0) { 303 /* fudge */ 304 if (iflag&(INPCK|ISTRIP|IXON) || lflag&(IEXTEN|ISIG) 305 || (cflag&(CSIZE|PARENB)) != CS8) 306 flags |= CBREAK; 307 else 308 flags |= RAW; 309 } 310 if (!(flags&RAW) && !(oflag&OPOST) && (cflag&(CSIZE|PARENB)) == CS8) 311 flags |= LITOUT; 312 if (cflag&MDMBUF) 313 flags |= MDMBUF; 314 if ((cflag&HUPCL) == 0) 315 flags |= NOHANG; 316 if (oflag&OXTABS) 317 flags |= XTABS; 318 if (lflag&ECHOE) 319 flags |= CRTERA|CRTBS; 320 if (lflag&ECHOKE) 321 flags |= CRTKIL|CRTBS; 322 if (lflag&ECHOPRT) 323 flags |= PRTERA; 324 if (lflag&ECHOCTL) 325 flags |= CTLECH; 326 if ((iflag&IXANY) == 0) 327 flags |= DECCTQ; 328 flags |= lflag&(ECHO|TOSTOP|FLUSHO|PENDIN|NOFLSH); 329 if (ttydebug) 330 printf("getflags: %x\n", flags); 331 return (flags); 332} 333 334static void 335ttcompatsetflags(tp, t) 336 register struct tty *tp; 337 register struct termios *t; 338{ 339 register int flags = tp->t_flags; 340 register tcflag_t iflag = t->c_iflag; 341 register tcflag_t oflag = t->c_oflag; 342 register tcflag_t lflag = t->c_lflag; 343 register tcflag_t cflag = t->c_cflag; 344 345 if (flags & RAW) { 346 iflag = IGNBRK; 347 lflag &= ~(ECHOCTL|ISIG|ICANON|IEXTEN); 348 } else { 349 iflag &= ~(PARMRK|IGNPAR|IGNCR|INLCR); 350 iflag |= BRKINT|IXON|IMAXBEL; 351 lflag |= ISIG|IEXTEN|ECHOCTL; /* XXX was echoctl on ? */ 352 if (flags & XTABS) 353 oflag |= OXTABS; 354 else 355 oflag &= ~OXTABS; 356 if (flags & CBREAK) 357 lflag &= ~ICANON; 358 else 359 lflag |= ICANON; 360 if (flags&CRMOD) { 361 iflag |= ICRNL; 362 oflag |= ONLCR; 363 } else { 364 iflag &= ~ICRNL; 365 oflag &= ~ONLCR; 366 } 367 } 368 if (flags&ECHO) 369 lflag |= ECHO; 370 else 371 lflag &= ~ECHO; 372 373 cflag &= ~(CSIZE|PARENB); 374 if (flags&(RAW|LITOUT|PASS8)) { 375 cflag |= CS8; 376 if (!(flags&(RAW|PASS8)) 377 || (flags&(RAW|PASS8|ANYP)) == (PASS8|ANYP)) 378 iflag |= ISTRIP; 379 else 380 iflag &= ~ISTRIP; 381 if (flags&(RAW|LITOUT)) 382 oflag &= ~OPOST; 383 else 384 oflag |= OPOST; 385 } else { 386 cflag |= CS7|PARENB; 387 iflag |= ISTRIP; 388 oflag |= OPOST; 389 } 390 /* XXX don't set INPCK if RAW or PASS8? */ 391 if ((flags&(EVENP|ODDP)) == EVENP) { 392 iflag |= INPCK; 393 cflag &= ~PARODD; 394 } else if ((flags&(EVENP|ODDP)) == ODDP) { 395 iflag |= INPCK; 396 cflag |= PARODD; 397 } else 398 iflag &= ~INPCK; 399 if (flags&TANDEM) 400 iflag |= IXOFF; 401 else 402 iflag &= ~IXOFF; 403 if ((flags&DECCTQ) == 0) 404 iflag |= IXANY; 405 else 406 iflag &= ~IXANY; 407 t->c_iflag = iflag; 408 t->c_oflag = oflag; 409 t->c_lflag = lflag; 410 t->c_cflag = cflag; 411} 412 413static void 414ttcompatsetlflags(tp, t) 415 register struct tty *tp; 416 register struct termios *t; 417{ 418 register int flags = tp->t_flags; 419 register tcflag_t iflag = t->c_iflag; 420 register tcflag_t oflag = t->c_oflag; 421 register tcflag_t lflag = t->c_lflag; 422 register tcflag_t cflag = t->c_cflag; 423 424 iflag &= ~(PARMRK|IGNPAR|IGNCR|INLCR); 425 if (flags&CRTERA) 426 lflag |= ECHOE; 427 else 428 lflag &= ~ECHOE; 429 if (flags&CRTKIL) 430 lflag |= ECHOKE; 431 else 432 lflag &= ~ECHOKE; 433 if (flags&PRTERA) 434 lflag |= ECHOPRT; 435 else 436 lflag &= ~ECHOPRT; 437 if (flags&CTLECH) 438 lflag |= ECHOCTL; 439 else 440 lflag &= ~ECHOCTL; 441 if (flags&TANDEM) 442 iflag |= IXOFF; 443 else 444 iflag &= ~IXOFF; 445 if ((flags&DECCTQ) == 0) 446 iflag |= IXANY; 447 else 448 iflag &= ~IXANY; 449 if (flags & MDMBUF) 450 cflag |= MDMBUF; 451 else 452 cflag &= ~MDMBUF; 453 if (flags&NOHANG) 454 cflag &= ~HUPCL; 455 else 456 cflag |= HUPCL; 457 lflag &= ~(TOSTOP|FLUSHO|PENDIN|NOFLSH); 458 lflag |= flags&(TOSTOP|FLUSHO|PENDIN|NOFLSH); 459 460 /* 461 * The next if-else statement is copied from above so don't bother 462 * checking it separately. We could avoid fiddlling with the 463 * character size if the mode is already RAW or if neither the 464 * LITOUT bit or the PASS8 bit is being changed, but the delta of 465 * the change is not available here and skipping the RAW case would 466 * make the code different from above. 467 */ 468 cflag &= ~(CSIZE|PARENB); 469 if (flags&(RAW|LITOUT|PASS8)) { 470 cflag |= CS8; 471 if (!(flags&(RAW|PASS8)) 472 || (flags&(RAW|PASS8|ANYP)) == (PASS8|ANYP)) 473 iflag |= ISTRIP; 474 else 475 iflag &= ~ISTRIP; 476 if (flags&(RAW|LITOUT)) 477 oflag &= ~OPOST; 478 else 479 oflag |= OPOST; 480 } else { 481 cflag |= CS7|PARENB; 482 iflag |= ISTRIP; 483 oflag |= OPOST; 484 } 485 t->c_iflag = iflag; 486 t->c_oflag = oflag; 487 t->c_lflag = lflag; 488 t->c_cflag = cflag; 489} 490#endif /* COMPAT_43 || COMPAT_SUNOS */ 491