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