The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/kern/tty_compat.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    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  * 4. Neither the name of the University nor the names of its contributors
   14  *    may be used to endorse or promote products derived from this software
   15  *    without specific prior written permission.
   16  *
   17  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   27  * SUCH DAMAGE.
   28  *
   29  *      @(#)tty_compat.c        8.1 (Berkeley) 6/10/93
   30  */
   31 
   32 #include <sys/cdefs.h>
   33 __FBSDID("$FreeBSD: releng/6.4/sys/kern/tty_compat.c 130892 2004-06-21 22:57:16Z phk $");
   34 
   35 #include "opt_compat.h"
   36 
   37 #ifndef BURN_BRIDGES
   38 /*
   39  * mapping routines for old line discipline (yuck)
   40  */
   41 #if defined(COMPAT_43)
   42 
   43 #include <sys/param.h>
   44 #include <sys/systm.h>
   45 #include <sys/ioctl_compat.h>
   46 #include <sys/tty.h>
   47 #include <sys/kernel.h>
   48 #include <sys/sysctl.h>
   49 
   50 static int ttcompatgetflags(struct tty *tp);
   51 static void ttcompatsetflags(struct tty *tp, struct termios *t);
   52 static void ttcompatsetlflags(struct tty *tp, struct termios *t);
   53 static int ttcompatspeedtab(int speed, struct speedtab *table);
   54 
   55 static int ttydebug = 0;
   56 SYSCTL_INT(_debug, OID_AUTO, ttydebug, CTLFLAG_RW, &ttydebug, 0, "");
   57 
   58 static struct speedtab compatspeeds[] = {
   59 #define MAX_SPEED       17
   60         { 115200, 17 },
   61         { 57600, 16 },
   62         { 38400, 15 },
   63         { 19200, 14 },
   64         { 9600, 13 },
   65         { 4800, 12 },
   66         { 2400, 11 },
   67         { 1800, 10 },
   68         { 1200, 9 },
   69         { 600,  8 },
   70         { 300,  7 },
   71         { 200,  6 },
   72         { 150,  5 },
   73         { 134,  4 },
   74         { 110,  3 },
   75         { 75,   2 },
   76         { 50,   1 },
   77         { 0,    0 },
   78         { -1,   -1 },
   79 };
   80 static int compatspcodes[] = {
   81         0, 50, 75, 110, 134, 150, 200, 300, 600, 1200,
   82         1800, 2400, 4800, 9600, 19200, 38400, 57600, 115200,
   83 };
   84 
   85 static int
   86 ttcompatspeedtab(int speed, struct speedtab *table)
   87 {
   88         if (speed == 0)
   89                 return (0); /* hangup */
   90         for ( ; table->sp_speed > 0; table++)
   91                 if (table->sp_speed <= speed) /* nearest one, rounded down */
   92                         return (table->sp_code);
   93         return (1); /* 50, min and not hangup */
   94 }
   95 
   96 int
   97 ttsetcompat(struct tty *tp, u_long *com, caddr_t data, struct termios *term)
   98 {
   99         switch (*com) {
  100         case TIOCSETP:
  101         case TIOCSETN: {
  102                 struct sgttyb *sg = (struct sgttyb *)data;
  103                 int speed;
  104 
  105                 if ((speed = sg->sg_ispeed) > MAX_SPEED || speed < 0)
  106                         return(EINVAL);
  107                 else if (speed != ttcompatspeedtab(tp->t_ispeed, compatspeeds))
  108                         term->c_ispeed = compatspcodes[speed];
  109                 else
  110                         term->c_ispeed = tp->t_ispeed;
  111                 if ((speed = sg->sg_ospeed) > MAX_SPEED || speed < 0)
  112                         return(EINVAL);
  113                 else if (speed != ttcompatspeedtab(tp->t_ospeed, compatspeeds))
  114                         term->c_ospeed = compatspcodes[speed];
  115                 else
  116                         term->c_ospeed = tp->t_ospeed;
  117                 term->c_cc[VERASE] = sg->sg_erase;
  118                 term->c_cc[VKILL] = sg->sg_kill;
  119                 tp->t_flags = (tp->t_flags&0xffff0000) | (sg->sg_flags&0xffff);
  120                 ttcompatsetflags(tp, term);
  121                 *com = (*com == TIOCSETP) ? TIOCSETAF : TIOCSETA;
  122                 break;
  123         }
  124         case TIOCSETC: {
  125                 struct tchars *tc = (struct tchars *)data;
  126                 cc_t *cc;
  127 
  128                 cc = term->c_cc;
  129                 cc[VINTR] = tc->t_intrc;
  130                 cc[VQUIT] = tc->t_quitc;
  131                 cc[VSTART] = tc->t_startc;
  132                 cc[VSTOP] = tc->t_stopc;
  133                 cc[VEOF] = tc->t_eofc;
  134                 cc[VEOL] = tc->t_brkc;
  135                 if (tc->t_brkc == (char)_POSIX_VDISABLE)
  136                         cc[VEOL2] = _POSIX_VDISABLE;
  137                 *com = TIOCSETA;
  138                 break;
  139         }
  140         case TIOCSLTC: {
  141                 struct ltchars *ltc = (struct ltchars *)data;
  142                 cc_t *cc;
  143 
  144                 cc = term->c_cc;
  145                 cc[VSUSP] = ltc->t_suspc;
  146                 cc[VDSUSP] = ltc->t_dsuspc;
  147                 cc[VREPRINT] = ltc->t_rprntc;
  148                 cc[VDISCARD] = ltc->t_flushc;
  149                 cc[VWERASE] = ltc->t_werasc;
  150                 cc[VLNEXT] = ltc->t_lnextc;
  151                 *com = TIOCSETA;
  152                 break;
  153         }
  154         case TIOCLBIS:
  155         case TIOCLBIC:
  156         case TIOCLSET:
  157                 if (*com == TIOCLSET)
  158                         tp->t_flags = (tp->t_flags&0xffff) | *(int *)data<<16;
  159                 else {
  160                         tp->t_flags =
  161                          (ttcompatgetflags(tp)&0xffff0000)|(tp->t_flags&0xffff);
  162                         if (*com == TIOCLBIS)
  163                                 tp->t_flags |= *(int *)data<<16;
  164                         else
  165                                 tp->t_flags &= ~(*(int *)data<<16);
  166                 }
  167                 ttcompatsetlflags(tp, term);
  168                 *com = TIOCSETA;
  169                 break;
  170         }
  171         return 0;
  172 }
  173 
  174 /*ARGSUSED*/
  175 int
  176 ttcompat(struct tty *tp, u_long com, caddr_t data, int flag)
  177 {
  178         switch (com) {
  179         case TIOCSETP:
  180         case TIOCSETN:
  181         case TIOCSETC:
  182         case TIOCSLTC:
  183         case TIOCLBIS:
  184         case TIOCLBIC:
  185         case TIOCLSET: {
  186                 struct termios term;
  187                 int error;
  188 
  189                 term = tp->t_termios;
  190                 if ((error = ttsetcompat(tp, &com, data, &term)) != 0)
  191                         return error;
  192                 return ttioctl(tp, com, &term, flag);
  193         }
  194         case TIOCGETP: {
  195                 struct sgttyb *sg = (struct sgttyb *)data;
  196                 cc_t *cc = tp->t_cc;
  197 
  198                 sg->sg_ospeed = ttcompatspeedtab(tp->t_ospeed, compatspeeds);
  199                 if (tp->t_ispeed == 0)
  200                         sg->sg_ispeed = sg->sg_ospeed;
  201                 else
  202                         sg->sg_ispeed = ttcompatspeedtab(tp->t_ispeed, compatspeeds);
  203                 sg->sg_erase = cc[VERASE];
  204                 sg->sg_kill = cc[VKILL];
  205                 sg->sg_flags = tp->t_flags = ttcompatgetflags(tp);
  206                 break;
  207         }
  208         case TIOCGETC: {
  209                 struct tchars *tc = (struct tchars *)data;
  210                 cc_t *cc = tp->t_cc;
  211 
  212                 tc->t_intrc = cc[VINTR];
  213                 tc->t_quitc = cc[VQUIT];
  214                 tc->t_startc = cc[VSTART];
  215                 tc->t_stopc = cc[VSTOP];
  216                 tc->t_eofc = cc[VEOF];
  217                 tc->t_brkc = cc[VEOL];
  218                 break;
  219         }
  220         case TIOCGLTC: {
  221                 struct ltchars *ltc = (struct ltchars *)data;
  222                 cc_t *cc = tp->t_cc;
  223 
  224                 ltc->t_suspc = cc[VSUSP];
  225                 ltc->t_dsuspc = cc[VDSUSP];
  226                 ltc->t_rprntc = cc[VREPRINT];
  227                 ltc->t_flushc = cc[VDISCARD];
  228                 ltc->t_werasc = cc[VWERASE];
  229                 ltc->t_lnextc = cc[VLNEXT];
  230                 break;
  231         }
  232         case TIOCLGET:
  233                 tp->t_flags =
  234                  (ttcompatgetflags(tp) & 0xffff0000UL)
  235                    | (tp->t_flags & 0xffff);
  236                 *(int *)data = tp->t_flags>>16;
  237                 if (ttydebug)
  238                         printf("CLGET: returning %x\n", *(int *)data);
  239                 break;
  240 
  241         case OTIOCGETD:
  242                 *(int *)data = tp->t_line ? tp->t_line : 2;
  243                 break;
  244 
  245         case OTIOCSETD: {
  246                 int ldisczero = 0;
  247 
  248                 return (ttioctl(tp, TIOCSETD,
  249                         *(int *)data == 2 ? (caddr_t)&ldisczero : data, flag));
  250             }
  251 
  252         case OTIOCCONS:
  253                 *(int *)data = 1;
  254                 return (ttioctl(tp, TIOCCONS, data, flag));
  255 
  256         default:
  257                 return (ENOIOCTL);
  258         }
  259         return (0);
  260 }
  261 
  262 static int
  263 ttcompatgetflags(struct tty *tp)
  264 {
  265         tcflag_t iflag  = tp->t_iflag;
  266         tcflag_t lflag  = tp->t_lflag;
  267         tcflag_t oflag  = tp->t_oflag;
  268         tcflag_t cflag  = tp->t_cflag;
  269         int flags = 0;
  270 
  271         if (iflag&IXOFF)
  272                 flags |= TANDEM;
  273         if (iflag&ICRNL || oflag&ONLCR)
  274                 flags |= CRMOD;
  275         if ((cflag&CSIZE) == CS8) {
  276                 flags |= PASS8;
  277                 if (iflag&ISTRIP)
  278                         flags |= ANYP;
  279         }
  280         else if (cflag&PARENB) {
  281                 if (iflag&INPCK) {
  282                         if (cflag&PARODD)
  283                                 flags |= ODDP;
  284                         else
  285                                 flags |= EVENP;
  286                 } else
  287                         flags |= EVENP | ODDP;
  288         }
  289 
  290         if ((lflag&ICANON) == 0) {
  291                 /* fudge */
  292                 if (iflag&(INPCK|ISTRIP|IXON) || lflag&(IEXTEN|ISIG)
  293                     || (cflag&(CSIZE|PARENB)) != CS8)
  294                         flags |= CBREAK;
  295                 else
  296                         flags |= RAW;
  297         }
  298         if (!(flags&RAW) && !(oflag&OPOST) && (cflag&(CSIZE|PARENB)) == CS8)
  299                 flags |= LITOUT;
  300         if (cflag&MDMBUF)
  301                 flags |= MDMBUF;
  302         if ((cflag&HUPCL) == 0)
  303                 flags |= NOHANG;
  304         if (oflag&OXTABS)
  305                 flags |= XTABS;
  306         if (lflag&ECHOE)
  307                 flags |= CRTERA|CRTBS;
  308         if (lflag&ECHOKE)
  309                 flags |= CRTKIL|CRTBS;
  310         if (lflag&ECHOPRT)
  311                 flags |= PRTERA;
  312         if (lflag&ECHOCTL)
  313                 flags |= CTLECH;
  314         if ((iflag&IXANY) == 0)
  315                 flags |= DECCTQ;
  316         flags |= lflag&(ECHO|TOSTOP|FLUSHO|PENDIN|NOFLSH);
  317         if (ttydebug)
  318                 printf("getflags: %x\n", flags);
  319         return (flags);
  320 }
  321 
  322 static void
  323 ttcompatsetflags(struct tty *tp, struct termios *t)
  324 {
  325         int flags = tp->t_flags;
  326         tcflag_t iflag  = t->c_iflag;
  327         tcflag_t oflag  = t->c_oflag;
  328         tcflag_t lflag  = t->c_lflag;
  329         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         /* XXX don't set INPCK if RAW or PASS8? */
  377         if ((flags&(EVENP|ODDP)) == EVENP) {
  378                 iflag |= INPCK;
  379                 cflag &= ~PARODD;
  380         } else if ((flags&(EVENP|ODDP)) == ODDP) {
  381                 iflag |= INPCK;
  382                 cflag |= PARODD;
  383         } else
  384                 iflag &= ~INPCK;
  385         if (flags&TANDEM)
  386                 iflag |= IXOFF;
  387         else
  388                 iflag &= ~IXOFF;
  389         if ((flags&DECCTQ) == 0)
  390                 iflag |= IXANY;
  391         else
  392                 iflag &= ~IXANY;
  393         t->c_iflag = iflag;
  394         t->c_oflag = oflag;
  395         t->c_lflag = lflag;
  396         t->c_cflag = cflag;
  397 }
  398 
  399 static void
  400 ttcompatsetlflags(struct tty *tp, struct termios *t)
  401 {
  402         int flags = tp->t_flags;
  403         tcflag_t iflag  = t->c_iflag;
  404         tcflag_t oflag  = t->c_oflag;
  405         tcflag_t lflag  = t->c_lflag;
  406         tcflag_t cflag  = t->c_cflag;
  407 
  408         iflag &= ~(PARMRK|IGNPAR|IGNCR|INLCR);
  409         if (flags&CRTERA)
  410                 lflag |= ECHOE;
  411         else
  412                 lflag &= ~ECHOE;
  413         if (flags&CRTKIL)
  414                 lflag |= ECHOKE;
  415         else
  416                 lflag &= ~ECHOKE;
  417         if (flags&PRTERA)
  418                 lflag |= ECHOPRT;
  419         else
  420                 lflag &= ~ECHOPRT;
  421         if (flags&CTLECH)
  422                 lflag |= ECHOCTL;
  423         else
  424                 lflag &= ~ECHOCTL;
  425         if (flags&TANDEM)
  426                 iflag |= IXOFF;
  427         else
  428                 iflag &= ~IXOFF;
  429         if ((flags&DECCTQ) == 0)
  430                 iflag |= IXANY;
  431         else
  432                 iflag &= ~IXANY;
  433         if (flags & MDMBUF)
  434                 cflag |= MDMBUF;
  435         else
  436                 cflag &= ~MDMBUF;
  437         if (flags&NOHANG)
  438                 cflag &= ~HUPCL;
  439         else
  440                 cflag |= HUPCL;
  441         lflag &= ~(TOSTOP|FLUSHO|PENDIN|NOFLSH);
  442         lflag |= flags&(TOSTOP|FLUSHO|PENDIN|NOFLSH);
  443 
  444         /*
  445          * The next if-else statement is copied from above so don't bother
  446          * checking it separately.  We could avoid fiddlling with the
  447          * character size if the mode is already RAW or if neither the
  448          * LITOUT bit or the PASS8 bit is being changed, but the delta of
  449          * the change is not available here and skipping the RAW case would
  450          * make the code different from above.
  451          */
  452         cflag &= ~(CSIZE|PARENB);
  453         if (flags&(RAW|LITOUT|PASS8)) {
  454                 cflag |= CS8;
  455                 if (!(flags&(RAW|PASS8))
  456                     || (flags&(RAW|PASS8|ANYP)) == (PASS8|ANYP))
  457                         iflag |= ISTRIP;
  458                 else
  459                         iflag &= ~ISTRIP;
  460                 if (flags&(RAW|LITOUT))
  461                         oflag &= ~OPOST;
  462                 else
  463                         oflag |= OPOST;
  464         } else {
  465                 cflag |= CS7|PARENB;
  466                 iflag |= ISTRIP;
  467                 oflag |= OPOST;
  468         }
  469         t->c_iflag = iflag;
  470         t->c_oflag = oflag;
  471         t->c_lflag = lflag;
  472         t->c_cflag = cflag;
  473 }
  474 #endif  /* COMPAT_43 */
  475 
  476 #endif /* BURN_BRIDGES */

Cache object: a27fe6533823503ef470b2118032fe44


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.