tty_compat.c revision 31577
159816Smdodd/*- 259816Smdodd * Copyright (c) 1982, 1986, 1991, 1993 359816Smdodd * The Regents of the University of California. All rights reserved. 459816Smdodd * 559816Smdodd * Redistribution and use in source and binary forms, with or without 659816Smdodd * modification, are permitted provided that the following conditions 759816Smdodd * are met: 859816Smdodd * 1. Redistributions of source code must retain the above copyright 959816Smdodd * notice, this list of conditions and the following disclaimer. 1059816Smdodd * 2. Redistributions in binary form must reproduce the above copyright 1159816Smdodd * notice, this list of conditions and the following disclaimer in the 1259816Smdodd * documentation and/or other materials provided with the distribution. 1359816Smdodd * 3. All advertising materials mentioning features or use of this software 1459816Smdodd * must display the following acknowledgement: 1559816Smdodd * This product includes software developed by the University of 1659816Smdodd * California, Berkeley and its contributors. 1759816Smdodd * 4. Neither the name of the University nor the names of its contributors 1859816Smdodd * may be used to endorse or promote products derived from this software 1959816Smdodd * without specific prior written permission. 2059816Smdodd * 2159816Smdodd * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2259816Smdodd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2359816Smdodd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2459816Smdodd * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2559816Smdodd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2659816Smdodd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2759816Smdodd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28119418Sobrien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29119418Sobrien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30119418Sobrien * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3159816Smdodd * SUCH DAMAGE. 3259816Smdodd * 3359816Smdodd * @(#)tty_compat.c 8.1 (Berkeley) 6/10/93 3459816Smdodd * $Id: tty_compat.c,v 1.23 1997/08/02 14:31:39 bde Exp $ 3559816Smdodd */ 3659816Smdodd 3759816Smdodd/* 3859816Smdodd * mapping routines for old line discipline (yuck) 3959816Smdodd */ 4059816Smdodd#if defined(COMPAT_43) || defined(COMPAT_SUNOS) 4159816Smdodd 4259816Smdodd#include <sys/param.h> 4359816Smdodd#include <sys/systm.h> 4459816Smdodd#include <sys/ioctl_compat.h> 4559816Smdodd#include <sys/tty.h> 4659816Smdodd#include <sys/kernel.h> 4759816Smdodd#include <sys/sysctl.h> 4859816Smdodd 4959816Smdoddstatic int ttcompatgetflags __P((struct tty *tp)); 5059816Smdoddstatic void ttcompatsetflags __P((struct tty *tp, struct termios *t)); 5159816Smdoddstatic void ttcompatsetlflags __P((struct tty *tp, struct termios *t)); 5259816Smdoddstatic int ttcompatspeedtab __P((int speed, struct speedtab *table)); 5359816Smdodd 5459816Smdoddstatic int ttydebug = 0; 55131192SimpSYSCTL_INT(_debug, OID_AUTO, ttydebug, CTLFLAG_RW, &ttydebug, 0, ""); 56131192Simp 57131192Simpstatic struct speedtab compatspeeds[] = { 5859816Smdodd#define MAX_SPEED 17 59131192Simp { 115200, 17 }, 60131192Simp { 57600, 16 }, 6159816Smdodd { 38400, 15 }, 62131192Simp { 19200, 14 }, 6359816Smdodd { 9600, 13 }, 6459816Smdodd { 4800, 12 }, 6559816Smdodd { 2400, 11 }, 6659816Smdodd { 1800, 10 }, 67112801Smdodd { 1200, 9 }, 6859816Smdodd { 600, 8 }, 6959816Smdodd { 300, 7 }, 7059816Smdodd { 200, 6 }, 7159816Smdodd { 150, 5 }, 72112800Smdodd { 134, 4 }, 7359816Smdodd { 110, 3 }, 7459816Smdodd { 75, 2 }, 7559816Smdodd { 50, 1 }, 7659816Smdodd { 0, 0 }, 77112801Smdodd { -1, -1 }, 7859816Smdodd}; 79112801Smdoddstatic int compatspcodes[] = { 8059816Smdodd 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 8159816Smdodd 1800, 2400, 4800, 9600, 19200, 38400, 57600, 115200, 8259816Smdodd}; 83112801Smdodd 8459816Smdoddstatic int 8559816Smdoddttcompatspeedtab(speed, table) 8659816Smdodd int speed; 8759816Smdodd register struct speedtab *table; 8859816Smdodd{ 8959816Smdodd if (speed == 0) 9059816Smdodd return (0); /* hangup */ 9159816Smdodd for ( ; table->sp_speed > 0; table++) 9259816Smdodd if (table->sp_speed <= speed) /* nearest one, rounded down */ 9359816Smdodd return (table->sp_code); 94131192Simp return (1); /* 50, min and not hangup */ 9559816Smdodd} 9659816Smdodd 9759816Smdoddint 9859816Smdoddttsetcompat(tp, com, data, term) 9959816Smdodd register struct tty *tp; 10059816Smdodd int *com; 10159816Smdodd caddr_t data; 10259816Smdodd struct termios *term; 10359816Smdodd{ 10459816Smdodd switch (*com) { 10559816Smdodd case TIOCSETP: 10659816Smdodd case TIOCSETN: { 10759816Smdodd register struct sgttyb *sg = (struct sgttyb *)data; 10859816Smdodd int speed; 10959816Smdodd 11059816Smdodd if ((speed = sg->sg_ispeed) > MAX_SPEED || speed < 0) 11159816Smdodd return(EINVAL); 11259816Smdodd else if (speed != ttcompatspeedtab(tp->t_ispeed, compatspeeds)) 11359816Smdodd term->c_ispeed = compatspcodes[speed]; 11459816Smdodd else 11559816Smdodd term->c_ispeed = tp->t_ispeed; 11659816Smdodd if ((speed = sg->sg_ospeed) > MAX_SPEED || speed < 0) 11759816Smdodd return(EINVAL); 11859816Smdodd else if (speed != ttcompatspeedtab(tp->t_ospeed, compatspeeds)) 11959816Smdodd term->c_ospeed = compatspcodes[speed]; 120131192Simp else 12159816Smdodd term->c_ospeed = tp->t_ospeed; 12259816Smdodd term->c_cc[VERASE] = sg->sg_erase; 123131192Simp term->c_cc[VKILL] = sg->sg_kill; 12459816Smdodd tp->t_flags = (tp->t_flags&0xffff0000) | (sg->sg_flags&0xffff); 12559816Smdodd ttcompatsetflags(tp, term); 12659816Smdodd *com = (*com == TIOCSETP) ? TIOCSETAF : TIOCSETA; 12759816Smdodd break; 128131192Simp } 129131192Simp case TIOCSETC: { 13059816Smdodd struct tchars *tc = (struct tchars *)data; 13159816Smdodd register cc_t *cc; 13259816Smdodd 13359816Smdodd cc = term->c_cc; 13459816Smdodd cc[VINTR] = tc->t_intrc; 135131192Simp cc[VQUIT] = tc->t_quitc; 136179775Sjhb cc[VSTART] = tc->t_startc; 137131192Simp cc[VSTOP] = tc->t_stopc; 138179775Sjhb cc[VEOF] = tc->t_eofc; 139131192Simp cc[VEOL] = tc->t_brkc; 14059816Smdodd if (tc->t_brkc == -1) 14159816Smdodd cc[VEOL2] = _POSIX_VDISABLE; 142131192Simp *com = TIOCSETA; 143179775Sjhb break; 144179775Sjhb } 14559816Smdodd case TIOCSLTC: { 14659816Smdodd struct ltchars *ltc = (struct ltchars *)data; 14759816Smdodd register cc_t *cc; 14859816Smdodd 149131247Simp cc = term->c_cc; 15059816Smdodd cc[VSUSP] = ltc->t_suspc; 15159816Smdodd cc[VDSUSP] = ltc->t_dsuspc; 152131192Simp cc[VREPRINT] = ltc->t_rprntc; 15359816Smdodd cc[VDISCARD] = ltc->t_flushc; 154131192Simp cc[VWERASE] = ltc->t_werasc; 15559816Smdodd cc[VLNEXT] = ltc->t_lnextc; 15659816Smdodd *com = TIOCSETA; 157131247Simp break; 158179775Sjhb } 159179775Sjhb case TIOCLBIS: 16059816Smdodd case TIOCLBIC: 16159816Smdodd case TIOCLSET: 16259816Smdodd if (*com == TIOCLSET) 16359816Smdodd tp->t_flags = (tp->t_flags&0xffff) | *(int *)data<<16; 16459816Smdodd else { 16559816Smdodd tp->t_flags = 166131192Simp (ttcompatgetflags(tp)&0xffff0000)|(tp->t_flags&0xffff); 16759816Smdodd if (*com == TIOCLBIS) 16859816Smdodd tp->t_flags |= *(int *)data<<16; 169131192Simp else 170131192Simp tp->t_flags &= ~(*(int *)data<<16); 17159816Smdodd } 17259816Smdodd ttcompatsetlflags(tp, term); 17359816Smdodd *com = TIOCSETA; 17459816Smdodd break; 17559816Smdodd } 17659816Smdodd return 0; 17759816Smdodd} 17859816Smdodd 17959816Smdodd/*ARGSUSED*/ 18059816Smdoddint 181179775Sjhbttcompat(tp, com, data, flag) 18259816Smdodd register struct tty *tp; 18359816Smdodd int com; 18459816Smdodd caddr_t data; 18559816Smdodd int flag; 18659816Smdodd{ 18759816Smdodd switch (com) { 188131248Simp case TIOCSETP: 189131248Simp case TIOCSETN: 19059816Smdodd case TIOCSETC: 19159816Smdodd case TIOCSLTC: 19259816Smdodd case TIOCLBIS: 19359816Smdodd case TIOCLBIC: 19459816Smdodd case TIOCLSET: { 19559816Smdodd struct termios term; 19659816Smdodd int error; 19759816Smdodd 198131192Simp term = tp->t_termios; 19959816Smdodd if ((error = ttsetcompat(tp, &com, data, &term)) != 0) 20059816Smdodd return error; 20159816Smdodd return ttioctl(tp, com, &term, flag); 20259816Smdodd } 20359816Smdodd case TIOCGETP: { 20459816Smdodd register struct sgttyb *sg = (struct sgttyb *)data; 205131192Simp register cc_t *cc = tp->t_cc; 20659816Smdodd 20759816Smdodd sg->sg_ospeed = ttcompatspeedtab(tp->t_ospeed, compatspeeds); 20859816Smdodd if (tp->t_ispeed == 0) 20959816Smdodd sg->sg_ispeed = sg->sg_ospeed; 21059816Smdodd else 211131192Simp sg->sg_ispeed = ttcompatspeedtab(tp->t_ispeed, compatspeeds); 21259816Smdodd sg->sg_erase = cc[VERASE]; 21359816Smdodd sg->sg_kill = cc[VKILL]; 21459816Smdodd sg->sg_flags = tp->t_flags = ttcompatgetflags(tp); 215131192Simp break; 21659816Smdodd } 21759816Smdodd case TIOCGETC: { 218131192Simp struct tchars *tc = (struct tchars *)data; 219131192Simp register cc_t *cc = tp->t_cc; 220131192Simp 22159816Smdodd tc->t_intrc = cc[VINTR]; 222131192Simp tc->t_quitc = cc[VQUIT]; 223131192Simp tc->t_startc = cc[VSTART]; 224131247Simp tc->t_stopc = cc[VSTOP]; 225131192Simp tc->t_eofc = cc[VEOF]; 226131192Simp tc->t_brkc = cc[VEOL]; 22759816Smdodd break; 22859816Smdodd } 229131247Simp case TIOCGLTC: { 23059816Smdodd struct ltchars *ltc = (struct ltchars *)data; 23159816Smdodd register cc_t *cc = tp->t_cc; 23259816Smdodd 23359816Smdodd ltc->t_suspc = cc[VSUSP]; 234131192Simp ltc->t_dsuspc = cc[VDSUSP]; 23559816Smdodd ltc->t_rprntc = cc[VREPRINT]; 23659816Smdodd ltc->t_flushc = cc[VDISCARD]; 237131192Simp ltc->t_werasc = cc[VWERASE]; 23859816Smdodd ltc->t_lnextc = cc[VLNEXT]; 23959816Smdodd break; 24059816Smdodd } 24159816Smdodd case TIOCLGET: 24259816Smdodd tp->t_flags = 24359816Smdodd (ttcompatgetflags(tp) & 0xffff0000UL) 24459816Smdodd | (tp->t_flags & 0xffff); 24559816Smdodd *(int *)data = tp->t_flags>>16; 24659816Smdodd if (ttydebug) 24759816Smdodd printf("CLGET: returning %x\n", *(int *)data); 248131192Simp break; 24959816Smdodd 25059816Smdodd case OTIOCGETD: 25159816Smdodd *(int *)data = tp->t_line ? tp->t_line : 2; 25259816Smdodd break; 253182088Simp 254182088Simp case OTIOCSETD: { 25559816Smdodd int ldisczero = 0; 25659816Smdodd 25759816Smdodd return (ttioctl(tp, TIOCSETD, 25859816Smdodd *(int *)data == 2 ? (caddr_t)&ldisczero : data, flag)); 25959816Smdodd } 26059816Smdodd 26159816Smdodd case OTIOCCONS: 26259816Smdodd *(int *)data = 1; 26359816Smdodd return (ttioctl(tp, TIOCCONS, data, flag)); 264131192Simp 26559816Smdodd default: 26659816Smdodd return (ENOIOCTL); 267131192Simp } 268131192Simp return (0); 269182088Simp} 27059816Smdodd 27159816Smdoddstatic int 27259816Smdoddttcompatgetflags(tp) 27359816Smdodd register struct tty *tp; 27459816Smdodd{ 27559816Smdodd register tcflag_t iflag = tp->t_iflag; 27659816Smdodd register tcflag_t lflag = tp->t_lflag; 277131192Simp register tcflag_t oflag = tp->t_oflag; 27859816Smdodd register tcflag_t cflag = tp->t_cflag; 27959816Smdodd register flags = 0; 28059816Smdodd 28159816Smdodd if (iflag&IXOFF) 282182088Simp flags |= TANDEM; 28359816Smdodd if (iflag&ICRNL || oflag&ONLCR) 28459816Smdodd flags |= CRMOD; 28559816Smdodd if ((cflag&CSIZE) == CS8) { 28659816Smdodd flags |= PASS8; 28759816Smdodd if (iflag&ISTRIP) 28859816Smdodd flags |= ANYP; 28959816Smdodd } 29059816Smdodd else if (cflag&PARENB) { 29159816Smdodd if (iflag&INPCK) { 29259816Smdodd if (cflag&PARODD) 29359816Smdodd flags |= ODDP; 29459816Smdodd else 29559816Smdodd flags |= EVENP; 29659816Smdodd } else 29759816Smdodd flags |= EVENP | ODDP; 298147256Sbrooks } 29959816Smdodd 300131192Simp if ((lflag&ICANON) == 0) { 30159816Smdodd /* fudge */ 30259816Smdodd if (iflag&(INPCK|ISTRIP|IXON) || lflag&(IEXTEN|ISIG) 30359816Smdodd || cflag&(CSIZE|PARENB) != CS8) 30459816Smdodd flags |= CBREAK; 305131192Simp else 30659816Smdodd flags |= RAW; 30759816Smdodd } 30859816Smdodd if (!(flags&RAW) && !(oflag&OPOST) && cflag&(CSIZE|PARENB) == CS8) 30959816Smdodd flags |= LITOUT; 31059816Smdodd if (cflag&MDMBUF) 31159816Smdodd flags |= MDMBUF; 31259816Smdodd if ((cflag&HUPCL) == 0) 31359816Smdodd flags |= NOHANG; 31459816Smdodd if (oflag&OXTABS) 31559816Smdodd flags |= XTABS; 31659816Smdodd if (lflag&ECHOE) 31759816Smdodd flags |= CRTERA|CRTBS; 31859816Smdodd if (lflag&ECHOKE) 31959816Smdodd flags |= CRTKIL|CRTBS; 320131192Simp if (lflag&ECHOPRT) 321131192Simp flags |= PRTERA; 322131192Simp if (lflag&ECHOCTL) 323131192Simp flags |= CTLECH; 324131192Simp if ((iflag&IXANY) == 0) 325131192Simp flags |= DECCTQ; 326131192Simp flags |= lflag&(ECHO|TOSTOP|FLUSHO|PENDIN|NOFLSH); 327131192Simp if (ttydebug) 328131192Simp printf("getflags: %x\n", flags); 329131192Simp return (flags); 330131192Simp} 331131192Simp 332131192Simpstatic void 333131192Simpttcompatsetflags(tp, t) 334131192Simp register struct tty *tp; 335131192Simp register struct termios *t; 336131192Simp{ 337131192Simp register flags = tp->t_flags; 338 register tcflag_t iflag = t->c_iflag; 339 register tcflag_t oflag = t->c_oflag; 340 register tcflag_t lflag = t->c_lflag; 341 register tcflag_t cflag = t->c_cflag; 342 343 if (flags & RAW) { 344 iflag = IGNBRK; 345 lflag &= ~(ECHOCTL|ISIG|ICANON|IEXTEN); 346 } else { 347 iflag &= ~(PARMRK|IGNPAR|IGNCR|INLCR); 348 iflag |= BRKINT|IXON|IMAXBEL; 349 lflag |= ISIG|IEXTEN|ECHOCTL; /* XXX was echoctl on ? */ 350 if (flags & XTABS) 351 oflag |= OXTABS; 352 else 353 oflag &= ~OXTABS; 354 if (flags & CBREAK) 355 lflag &= ~ICANON; 356 else 357 lflag |= ICANON; 358 if (flags&CRMOD) { 359 iflag |= ICRNL; 360 oflag |= ONLCR; 361 } else { 362 iflag &= ~ICRNL; 363 oflag &= ~ONLCR; 364 } 365 } 366 if (flags&ECHO) 367 lflag |= ECHO; 368 else 369 lflag &= ~ECHO; 370 371 cflag &= ~(CSIZE|PARENB); 372 if (flags&(RAW|LITOUT|PASS8)) { 373 cflag |= CS8; 374 if (!(flags&(RAW|PASS8)) 375 || (flags&(RAW|PASS8|ANYP)) == (PASS8|ANYP)) 376 iflag |= ISTRIP; 377 else 378 iflag &= ~ISTRIP; 379 if (flags&(RAW|LITOUT)) 380 oflag &= ~OPOST; 381 else 382 oflag |= OPOST; 383 } else { 384 cflag |= CS7|PARENB; 385 iflag |= ISTRIP; 386 oflag |= OPOST; 387 } 388 /* XXX don't set INPCK if RAW or PASS8? */ 389 if ((flags&(EVENP|ODDP)) == EVENP) { 390 iflag |= INPCK; 391 cflag &= ~PARODD; 392 } else if ((flags&(EVENP|ODDP)) == ODDP) { 393 iflag |= INPCK; 394 cflag |= PARODD; 395 } else 396 iflag &= ~INPCK; 397 if (flags&TANDEM) 398 iflag |= IXOFF; 399 else 400 iflag &= ~IXOFF; 401 if ((flags&DECCTQ) == 0) 402 iflag |= IXANY; 403 else 404 iflag &= ~IXANY; 405 t->c_iflag = iflag; 406 t->c_oflag = oflag; 407 t->c_lflag = lflag; 408 t->c_cflag = cflag; 409} 410 411static void 412ttcompatsetlflags(tp, t) 413 register struct tty *tp; 414 register struct termios *t; 415{ 416 register flags = tp->t_flags; 417 register tcflag_t iflag = t->c_iflag; 418 register tcflag_t oflag = t->c_oflag; 419 register tcflag_t lflag = t->c_lflag; 420 register tcflag_t cflag = t->c_cflag; 421 422 iflag &= ~(PARMRK|IGNPAR|IGNCR|INLCR); 423 if (flags&CRTERA) 424 lflag |= ECHOE; 425 else 426 lflag &= ~ECHOE; 427 if (flags&CRTKIL) 428 lflag |= ECHOKE; 429 else 430 lflag &= ~ECHOKE; 431 if (flags&PRTERA) 432 lflag |= ECHOPRT; 433 else 434 lflag &= ~ECHOPRT; 435 if (flags&CTLECH) 436 lflag |= ECHOCTL; 437 else 438 lflag &= ~ECHOCTL; 439 if (flags&TANDEM) 440 iflag |= IXOFF; 441 else 442 iflag &= ~IXOFF; 443 if ((flags&DECCTQ) == 0) 444 iflag |= IXANY; 445 else 446 iflag &= ~IXANY; 447 if (flags & MDMBUF) 448 cflag |= MDMBUF; 449 else 450 cflag &= ~MDMBUF; 451 if (flags&NOHANG) 452 cflag &= ~HUPCL; 453 else 454 cflag |= HUPCL; 455 lflag &= ~(TOSTOP|FLUSHO|PENDIN|NOFLSH); 456 lflag |= flags&(TOSTOP|FLUSHO|PENDIN|NOFLSH); 457 458 /* 459 * The next if-else statement is copied from above so don't bother 460 * checking it separately. We could avoid fiddlling with the 461 * character size if the mode is already RAW or if neither the 462 * LITOUT bit or the PASS8 bit is being changed, but the delta of 463 * the change is not available here and skipping the RAW case would 464 * make the code different from above. 465 */ 466 cflag &= ~(CSIZE|PARENB); 467 if (flags&(RAW|LITOUT|PASS8)) { 468 cflag |= CS8; 469 if (!(flags&(RAW|PASS8)) 470 || (flags&(RAW|PASS8|ANYP)) == (PASS8|ANYP)) 471 iflag |= ISTRIP; 472 else 473 iflag &= ~ISTRIP; 474 if (flags&(RAW|LITOUT)) 475 oflag &= ~OPOST; 476 else 477 oflag |= OPOST; 478 } else { 479 cflag |= CS7|PARENB; 480 iflag |= ISTRIP; 481 oflag |= OPOST; 482 } 483 t->c_iflag = iflag; 484 t->c_oflag = oflag; 485 t->c_lflag = lflag; 486 t->c_cflag = cflag; 487} 488#endif /* COMPAT_43 || COMPAT_SUNOS */ 489