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

Cache object: 70ee908bd1045330306ac9f4f814973b


[ 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.