root/compat/linux/linux_termios.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. linux_termio_to_bsd_termios
  2. bsd_termios_to_linux_termio
  3. linux_termios_to_bsd_termios
  4. bsd_termios_to_linux_termios
  5. linux_ioctl_termios

    1 /*      $OpenBSD: linux_termios.c,v 1.15 2003/04/05 20:30:18 millert Exp $      */
    2 /*      $NetBSD: linux_termios.c,v 1.3 1996/04/05 00:01:54 christos Exp $       */
    3 
    4 /*
    5  * Copyright (c) 1995 Frank van der Linden
    6  * All rights reserved.
    7  *
    8  * Redistribution and use in source and binary forms, with or without
    9  * modification, are permitted provided that the following conditions
   10  * are met:
   11  * 1. Redistributions of source code must retain the above copyright
   12  *    notice, this list of conditions and the following disclaimer.
   13  * 2. Redistributions in binary form must reproduce the above copyright
   14  *    notice, this list of conditions and the following disclaimer in the
   15  *    documentation and/or other materials provided with the distribution.
   16  * 3. All advertising materials mentioning features or use of this software
   17  *    must display the following acknowledgement:
   18  *      This product includes software developed for the NetBSD Project
   19  *      by Frank van der Linden
   20  * 4. The name of the author may not be used to endorse or promote products
   21  *    derived from this software without specific prior written permission
   22  *
   23  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   24  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   25  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   26  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   27  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   28  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   29  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   30  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   31  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   32  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   33  */
   34 
   35 #include <sys/param.h>
   36 #include <sys/proc.h>
   37 #include <sys/systm.h>
   38 #include <sys/file.h>
   39 #include <sys/filedesc.h>
   40 #include <sys/ioctl.h>
   41 #include <sys/mount.h>
   42 #include <sys/termios.h>
   43 
   44 #include <sys/syscallargs.h>
   45 
   46 #include <compat/linux/linux_types.h>
   47 #include <compat/linux/linux_ioctl.h>
   48 #include <compat/linux/linux_signal.h>
   49 #include <compat/linux/linux_syscallargs.h>
   50 #include <compat/linux/linux_util.h>
   51 #include <compat/linux/linux_termios.h>
   52 
   53 static speed_t linux_speeds[] = {
   54         0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
   55         9600, 19200, 38400, 57600, 115200, 230400
   56 };
   57 
   58 static const int linux_spmasks[] = {
   59         LINUX_B0, LINUX_B50, LINUX_B75, LINUX_B110, LINUX_B134, LINUX_B150,
   60         LINUX_B200, LINUX_B300, LINUX_B600, LINUX_B1200, LINUX_B1800,
   61         LINUX_B2400, LINUX_B4800, LINUX_B9600, LINUX_B19200, LINUX_B38400,
   62         LINUX_B57600, LINUX_B115200, LINUX_B230400
   63 };
   64 
   65 static void linux_termio_to_bsd_termios(struct linux_termio *,
   66     struct termios *);
   67 static void bsd_termios_to_linux_termio(struct termios *,
   68     struct linux_termio *);
   69 static void linux_termios_to_bsd_termios(struct linux_termios *,
   70     struct termios *);
   71 static void bsd_termios_to_linux_termios(struct termios *,
   72     struct linux_termios *);
   73 
   74 /*
   75  * Deal with termio ioctl cruft. This doesn't look very good..
   76  * XXX too much code duplication, obviously..
   77  *
   78  * The conversion routines between Linux and BSD structures assume
   79  * that the fields are already filled with the current values,
   80  * so that fields present in BSD but not in Linux keep their current
   81  * values.
   82  */
   83 
   84 static void
   85 linux_termio_to_bsd_termios(lt, bts)
   86         struct linux_termio *lt;
   87         struct termios *bts;
   88 {
   89         int index;
   90 
   91         bts->c_iflag = 0;
   92         bts->c_iflag |= cvtto_bsd_mask(lt->c_iflag, LINUX_IGNBRK, IGNBRK);
   93         bts->c_iflag |= cvtto_bsd_mask(lt->c_iflag, LINUX_BRKINT, BRKINT);
   94         bts->c_iflag |= cvtto_bsd_mask(lt->c_iflag, LINUX_IGNPAR, IGNPAR);
   95         bts->c_iflag |= cvtto_bsd_mask(lt->c_iflag, LINUX_INPCK, INPCK);
   96         bts->c_iflag |= cvtto_bsd_mask(lt->c_iflag, LINUX_ISTRIP, ISTRIP);
   97         bts->c_iflag |= cvtto_bsd_mask(lt->c_iflag, LINUX_INLCR, INLCR);
   98         bts->c_iflag |= cvtto_bsd_mask(lt->c_iflag, LINUX_IGNCR, IGNCR);
   99         bts->c_iflag |= cvtto_bsd_mask(lt->c_iflag, LINUX_ICRNL, ICRNL);
  100         bts->c_iflag |= cvtto_bsd_mask(lt->c_iflag, LINUX_IXON, IXON);
  101         bts->c_iflag |= cvtto_bsd_mask(lt->c_iflag, LINUX_IXANY, IXANY);
  102         bts->c_iflag |= cvtto_bsd_mask(lt->c_iflag, LINUX_IXOFF, IXOFF);
  103         bts->c_iflag |= cvtto_bsd_mask(lt->c_iflag, LINUX_IMAXBEL, IMAXBEL);
  104 
  105         bts->c_oflag = 0;
  106         bts->c_oflag |= cvtto_bsd_mask(lt->c_oflag, LINUX_OPOST, OPOST);
  107         bts->c_oflag |= cvtto_bsd_mask(lt->c_oflag, LINUX_ONLCR, ONLCR);
  108         bts->c_oflag |= cvtto_bsd_mask(lt->c_oflag, LINUX_XTABS, OXTABS);
  109 
  110         /*
  111          * This could have been:
  112          * bts->c_cflag = (lt->c_flag & LINUX_CSIZE) << 4
  113          * But who knows, those values might perhaps change one day.
  114          */
  115         switch (lt->c_cflag & LINUX_CSIZE) {
  116         case LINUX_CS5:
  117                 bts->c_cflag = CS5;
  118                 break;
  119         case LINUX_CS6:
  120                 bts->c_cflag = CS6;
  121                 break;
  122         case LINUX_CS7:
  123                 bts->c_cflag = CS7;
  124                 break;
  125         case LINUX_CS8:
  126                 bts->c_cflag = CS8;
  127                 break;
  128         }
  129         bts->c_cflag |= cvtto_bsd_mask(lt->c_cflag, LINUX_CSTOPB, CSTOPB);
  130         bts->c_cflag |= cvtto_bsd_mask(lt->c_cflag, LINUX_CREAD, CREAD);
  131         bts->c_cflag |= cvtto_bsd_mask(lt->c_cflag, LINUX_PARENB, PARENB);
  132         bts->c_cflag |= cvtto_bsd_mask(lt->c_cflag, LINUX_PARODD, PARODD);
  133         bts->c_cflag |= cvtto_bsd_mask(lt->c_cflag, LINUX_HUPCL, HUPCL);
  134         bts->c_cflag |= cvtto_bsd_mask(lt->c_cflag, LINUX_CLOCAL, CLOCAL);
  135         bts->c_cflag |= cvtto_bsd_mask(lt->c_cflag, LINUX_CRTSCTS, CRTSCTS);
  136 
  137         bts->c_lflag = 0;
  138         bts->c_lflag |= cvtto_bsd_mask(lt->c_lflag, LINUX_ISIG, ISIG);
  139         bts->c_lflag |= cvtto_bsd_mask(lt->c_lflag, LINUX_ICANON, ICANON);
  140         bts->c_lflag |= cvtto_bsd_mask(lt->c_lflag, LINUX_ECHO, ECHO);
  141         bts->c_lflag |= cvtto_bsd_mask(lt->c_lflag, LINUX_ECHOE, ECHOE);
  142         bts->c_lflag |= cvtto_bsd_mask(lt->c_lflag, LINUX_ECHOK, ECHOK);
  143         bts->c_lflag |= cvtto_bsd_mask(lt->c_lflag, LINUX_ECHONL, ECHONL);
  144         bts->c_lflag |= cvtto_bsd_mask(lt->c_lflag, LINUX_NOFLSH, NOFLSH);
  145         bts->c_lflag |= cvtto_bsd_mask(lt->c_lflag, LINUX_TOSTOP, TOSTOP);
  146         bts->c_lflag |= cvtto_bsd_mask(lt->c_lflag, LINUX_ECHOCTL, ECHOCTL);
  147         bts->c_lflag |= cvtto_bsd_mask(lt->c_lflag, LINUX_ECHOPRT, ECHOPRT);
  148         bts->c_lflag |= cvtto_bsd_mask(lt->c_lflag, LINUX_ECHOKE, ECHOKE);
  149         bts->c_lflag |= cvtto_bsd_mask(lt->c_lflag, LINUX_FLUSHO, FLUSHO);
  150         bts->c_lflag |= cvtto_bsd_mask(lt->c_lflag, LINUX_PENDIN, PENDIN);
  151         bts->c_lflag |= cvtto_bsd_mask(lt->c_lflag, LINUX_IEXTEN, IEXTEN);
  152 
  153         index = lt->c_cflag & LINUX_CBAUD;
  154         if (index & LINUX_CBAUDEX)
  155                 index = (index & ~LINUX_CBAUDEX) + LINUX_NSPEEDS - 1;
  156         bts->c_ispeed = bts->c_ospeed = linux_speeds[index];
  157 
  158         bts->c_cc[VINTR] = lt->c_cc[LINUX_VINTR];
  159         bts->c_cc[VQUIT] = lt->c_cc[LINUX_VQUIT];
  160         bts->c_cc[VERASE] = lt->c_cc[LINUX_VERASE];
  161         bts->c_cc[VKILL] = lt->c_cc[LINUX_VKILL];
  162         bts->c_cc[VEOF] = lt->c_cc[LINUX_VEOF];
  163         bts->c_cc[VTIME] = lt->c_cc[LINUX_VTIME];
  164         bts->c_cc[VMIN] = lt->c_cc[LINUX_VMIN];
  165 }
  166 
  167 static void
  168 bsd_termios_to_linux_termio(bts, lt)
  169         struct termios *bts;
  170         struct linux_termio *lt;
  171 {
  172         int i, mask;
  173 
  174         lt->c_iflag = 0;
  175         lt->c_iflag |= cvtto_linux_mask(bts->c_iflag, IGNBRK, LINUX_IGNBRK);
  176         lt->c_iflag |= cvtto_linux_mask(bts->c_iflag, BRKINT, LINUX_BRKINT);
  177         lt->c_iflag |= cvtto_linux_mask(bts->c_iflag, IGNPAR, LINUX_IGNPAR);
  178         lt->c_iflag |= cvtto_linux_mask(bts->c_iflag, INPCK, LINUX_INPCK);
  179         lt->c_iflag |= cvtto_linux_mask(bts->c_iflag, ISTRIP, LINUX_ISTRIP);
  180         lt->c_iflag |= cvtto_linux_mask(bts->c_iflag, INLCR, LINUX_INLCR);
  181         lt->c_iflag |= cvtto_linux_mask(bts->c_iflag, IGNCR, LINUX_IGNCR);
  182         lt->c_iflag |= cvtto_linux_mask(bts->c_iflag, ICRNL, LINUX_ICRNL);
  183         lt->c_iflag |= cvtto_linux_mask(bts->c_iflag, IXON, LINUX_IXON);
  184         lt->c_iflag |= cvtto_linux_mask(bts->c_iflag, IXANY, LINUX_IXANY);
  185         lt->c_iflag |= cvtto_linux_mask(bts->c_iflag, IXOFF, LINUX_IXOFF);
  186         lt->c_iflag |= cvtto_linux_mask(bts->c_iflag, IMAXBEL, LINUX_IMAXBEL);
  187 
  188         lt->c_oflag = 0;
  189         lt->c_oflag |= cvtto_linux_mask(bts->c_oflag, OPOST, LINUX_OPOST);
  190         lt->c_oflag |= cvtto_linux_mask(bts->c_oflag, ONLCR, LINUX_ONLCR);
  191         lt->c_oflag |= cvtto_linux_mask(bts->c_oflag, OXTABS, LINUX_XTABS);
  192 
  193         switch (bts->c_cflag & CSIZE) {
  194         case CS5:
  195                 lt->c_cflag = LINUX_CS5;
  196                 break;
  197         case CS6:
  198                 lt->c_cflag = LINUX_CS6;
  199                 break;
  200         case CS7:
  201                 lt->c_cflag = LINUX_CS7;
  202                 break;
  203         case CS8:
  204                 lt->c_cflag = LINUX_CS8;
  205                 break;
  206         }
  207         lt->c_cflag |= cvtto_linux_mask(bts->c_cflag, CSTOPB, LINUX_CSTOPB);
  208         lt->c_cflag |= cvtto_linux_mask(bts->c_cflag, CREAD, LINUX_CREAD);
  209         lt->c_cflag |= cvtto_linux_mask(bts->c_cflag, PARENB, LINUX_PARENB);
  210         lt->c_cflag |= cvtto_linux_mask(bts->c_cflag, PARODD, LINUX_PARODD);
  211         lt->c_cflag |= cvtto_linux_mask(bts->c_cflag, HUPCL, LINUX_HUPCL);
  212         lt->c_cflag |= cvtto_linux_mask(bts->c_cflag, CLOCAL, LINUX_CLOCAL);
  213         lt->c_cflag |= cvtto_linux_mask(bts->c_cflag, CRTSCTS, LINUX_CRTSCTS);
  214 
  215         lt->c_lflag = 0;
  216         lt->c_lflag |= cvtto_linux_mask(bts->c_lflag, ISIG, LINUX_ISIG);
  217         lt->c_lflag |= cvtto_linux_mask(bts->c_lflag, ICANON, LINUX_ICANON);
  218         lt->c_lflag |= cvtto_linux_mask(bts->c_lflag, ECHO, LINUX_ECHO);
  219         lt->c_lflag |= cvtto_linux_mask(bts->c_lflag, ECHOE, LINUX_ECHOE);
  220         lt->c_lflag |= cvtto_linux_mask(bts->c_lflag, ECHOK, LINUX_ECHOK);
  221         lt->c_lflag |= cvtto_linux_mask(bts->c_lflag, ECHONL, LINUX_ECHONL);
  222         lt->c_lflag |= cvtto_linux_mask(bts->c_lflag, NOFLSH, LINUX_NOFLSH);
  223         lt->c_lflag |= cvtto_linux_mask(bts->c_lflag, TOSTOP, LINUX_TOSTOP);
  224         lt->c_lflag |= cvtto_linux_mask(bts->c_lflag, ECHOCTL, LINUX_ECHOCTL);
  225         lt->c_lflag |= cvtto_linux_mask(bts->c_lflag, ECHOPRT, LINUX_ECHOPRT);
  226         lt->c_lflag |= cvtto_linux_mask(bts->c_lflag, ECHOKE, LINUX_ECHOKE);
  227         lt->c_lflag |= cvtto_linux_mask(bts->c_lflag, FLUSHO, LINUX_FLUSHO);
  228         lt->c_lflag |= cvtto_linux_mask(bts->c_lflag, PENDIN, LINUX_PENDIN);
  229         lt->c_lflag |= cvtto_linux_mask(bts->c_lflag, IEXTEN, LINUX_IEXTEN);
  230 
  231         mask = LINUX_B9600;     /* XXX default value should this be 0? */
  232         for (i = 0; i < sizeof (linux_speeds) / sizeof (speed_t); i++) {
  233                 if (bts->c_ospeed == linux_speeds[i]) {
  234                         mask = linux_spmasks[i];
  235                         break;
  236                 }
  237         }
  238         lt->c_cflag |= mask;
  239 
  240         lt->c_cc[LINUX_VINTR] = bts->c_cc[VINTR];
  241         lt->c_cc[LINUX_VQUIT] = bts->c_cc[VQUIT];
  242         lt->c_cc[LINUX_VERASE] = bts->c_cc[VERASE];
  243         lt->c_cc[LINUX_VKILL] = bts->c_cc[VKILL];
  244         lt->c_cc[LINUX_VEOF] = bts->c_cc[VEOF];
  245         lt->c_cc[LINUX_VTIME] = bts->c_cc[VTIME];
  246         lt->c_cc[LINUX_VMIN] = bts->c_cc[VMIN];
  247         lt->c_cc[LINUX_VSWTC] = 0;
  248 
  249         /* XXX should be fixed someday */
  250         lt->c_line = 0;
  251 }
  252 
  253 static void
  254 linux_termios_to_bsd_termios(lts, bts)
  255         struct linux_termios *lts;
  256         struct termios *bts;
  257 {
  258         int index;
  259 
  260         bts->c_iflag = 0;
  261         bts->c_iflag |= cvtto_bsd_mask(lts->c_iflag, LINUX_IGNBRK, IGNBRK);
  262         bts->c_iflag |= cvtto_bsd_mask(lts->c_iflag, LINUX_BRKINT, BRKINT);
  263         bts->c_iflag |= cvtto_bsd_mask(lts->c_iflag, LINUX_IGNPAR, IGNPAR);
  264         bts->c_iflag |= cvtto_bsd_mask(lts->c_iflag, LINUX_INPCK, INPCK);
  265         bts->c_iflag |= cvtto_bsd_mask(lts->c_iflag, LINUX_ISTRIP, ISTRIP);
  266         bts->c_iflag |= cvtto_bsd_mask(lts->c_iflag, LINUX_INLCR, INLCR);
  267         bts->c_iflag |= cvtto_bsd_mask(lts->c_iflag, LINUX_IGNCR, IGNCR);
  268         bts->c_iflag |= cvtto_bsd_mask(lts->c_iflag, LINUX_ICRNL, ICRNL);
  269         bts->c_iflag |= cvtto_bsd_mask(lts->c_iflag, LINUX_IXON, IXON);
  270         bts->c_iflag |= cvtto_bsd_mask(lts->c_iflag, LINUX_IXANY, IXANY);
  271         bts->c_iflag |= cvtto_bsd_mask(lts->c_iflag, LINUX_IXOFF, IXOFF);
  272         bts->c_iflag |= cvtto_bsd_mask(lts->c_iflag, LINUX_IMAXBEL, IMAXBEL);
  273 
  274         bts->c_oflag = 0;
  275         bts->c_oflag |= cvtto_bsd_mask(lts->c_oflag, LINUX_OPOST, OPOST);
  276         bts->c_oflag |= cvtto_bsd_mask(lts->c_oflag, LINUX_ONLCR, ONLCR);
  277         bts->c_oflag |= cvtto_bsd_mask(lts->c_oflag, LINUX_XTABS, OXTABS);
  278 
  279         bts->c_cflag = 0;
  280         switch (lts->c_cflag & LINUX_CSIZE) {
  281         case LINUX_CS5:
  282                 bts->c_cflag = CS5;
  283                 break;
  284         case LINUX_CS6:
  285                 bts->c_cflag = CS6;
  286                 break;
  287         case LINUX_CS7:
  288                 bts->c_cflag = CS7;
  289                 break;
  290         case LINUX_CS8:
  291                 bts->c_cflag = CS8;
  292                 break;
  293         }
  294         bts->c_cflag |= cvtto_bsd_mask(lts->c_cflag, LINUX_CSTOPB, CSTOPB);
  295         bts->c_cflag |= cvtto_bsd_mask(lts->c_cflag, LINUX_CREAD, CREAD);
  296         bts->c_cflag |= cvtto_bsd_mask(lts->c_cflag, LINUX_PARENB, PARENB);
  297         bts->c_cflag |= cvtto_bsd_mask(lts->c_cflag, LINUX_PARODD, PARODD);
  298         bts->c_cflag |= cvtto_bsd_mask(lts->c_cflag, LINUX_HUPCL, HUPCL);
  299         bts->c_cflag |= cvtto_bsd_mask(lts->c_cflag, LINUX_CLOCAL, CLOCAL);
  300         bts->c_cflag |= cvtto_bsd_mask(lts->c_cflag, LINUX_CRTSCTS, CRTSCTS);
  301 
  302         bts->c_lflag = 0;
  303         bts->c_lflag |= cvtto_bsd_mask(lts->c_lflag, LINUX_ISIG, ISIG);
  304         bts->c_lflag |= cvtto_bsd_mask(lts->c_lflag, LINUX_ICANON, ICANON);
  305         bts->c_lflag |= cvtto_bsd_mask(lts->c_lflag, LINUX_ECHO, ECHO);
  306         bts->c_lflag |= cvtto_bsd_mask(lts->c_lflag, LINUX_ECHOE, ECHOE);
  307         bts->c_lflag |= cvtto_bsd_mask(lts->c_lflag, LINUX_ECHOK, ECHOK);
  308         bts->c_lflag |= cvtto_bsd_mask(lts->c_lflag, LINUX_ECHONL, ECHONL);
  309         bts->c_lflag |= cvtto_bsd_mask(lts->c_lflag, LINUX_NOFLSH, NOFLSH);
  310         bts->c_lflag |= cvtto_bsd_mask(lts->c_lflag, LINUX_TOSTOP, TOSTOP);
  311         bts->c_lflag |= cvtto_bsd_mask(lts->c_lflag, LINUX_ECHOCTL, ECHOCTL);
  312         bts->c_lflag |= cvtto_bsd_mask(lts->c_lflag, LINUX_ECHOPRT, ECHOPRT);
  313         bts->c_lflag |= cvtto_bsd_mask(lts->c_lflag, LINUX_ECHOKE, ECHOKE);
  314         bts->c_lflag |= cvtto_bsd_mask(lts->c_lflag, LINUX_FLUSHO, FLUSHO);
  315         bts->c_lflag |= cvtto_bsd_mask(lts->c_lflag, LINUX_PENDIN, PENDIN);
  316         bts->c_lflag |= cvtto_bsd_mask(lts->c_lflag, LINUX_IEXTEN, IEXTEN);
  317 
  318         index = lts->c_cflag & LINUX_CBAUD;
  319         if (index & LINUX_CBAUDEX)
  320                 index = (index & ~LINUX_CBAUDEX) + LINUX_NSPEEDS - 1;
  321         bts->c_ispeed = bts->c_ospeed = linux_speeds[index];
  322 
  323         bts->c_cc[VINTR] = lts->c_cc[LINUX_VINTR];
  324         bts->c_cc[VQUIT] = lts->c_cc[LINUX_VQUIT];
  325         bts->c_cc[VERASE] = lts->c_cc[LINUX_VERASE];
  326         bts->c_cc[VKILL] = lts->c_cc[LINUX_VKILL];
  327         bts->c_cc[VEOF] = lts->c_cc[LINUX_VEOF];
  328         bts->c_cc[VTIME] = lts->c_cc[LINUX_VTIME];
  329         bts->c_cc[VMIN] = lts->c_cc[LINUX_VMIN];
  330         bts->c_cc[VEOL] = lts->c_cc[LINUX_VEOL];
  331         bts->c_cc[VEOL2] = lts->c_cc[LINUX_VEOL2];
  332         bts->c_cc[VWERASE] = lts->c_cc[LINUX_VWERASE];
  333         bts->c_cc[VSUSP] = lts->c_cc[LINUX_VSUSP];
  334         bts->c_cc[VSTART] = lts->c_cc[LINUX_VSTART];
  335         bts->c_cc[VSTOP] = lts->c_cc[LINUX_VSTOP];
  336         bts->c_cc[VLNEXT] = lts->c_cc[LINUX_VLNEXT];
  337         bts->c_cc[VDISCARD] = lts->c_cc[LINUX_VDISCARD];
  338         bts->c_cc[VREPRINT] = lts->c_cc[LINUX_VREPRINT];
  339 }
  340 
  341 static void
  342 bsd_termios_to_linux_termios(bts, lts)
  343         struct termios *bts;
  344         struct linux_termios *lts;
  345 {
  346         int i, mask;
  347 
  348         lts->c_iflag = 0;
  349         lts->c_iflag |= cvtto_linux_mask(bts->c_iflag, IGNBRK, LINUX_IGNBRK);
  350         lts->c_iflag |= cvtto_linux_mask(bts->c_iflag, BRKINT, LINUX_BRKINT);
  351         lts->c_iflag |= cvtto_linux_mask(bts->c_iflag, IGNPAR, LINUX_IGNPAR);
  352         lts->c_iflag |= cvtto_linux_mask(bts->c_iflag, INPCK, LINUX_INPCK);
  353         lts->c_iflag |= cvtto_linux_mask(bts->c_iflag, ISTRIP, LINUX_ISTRIP);
  354         lts->c_iflag |= cvtto_linux_mask(bts->c_iflag, INLCR, LINUX_INLCR);
  355         lts->c_iflag |= cvtto_linux_mask(bts->c_iflag, IGNCR, LINUX_IGNCR);
  356         lts->c_iflag |= cvtto_linux_mask(bts->c_iflag, ICRNL, LINUX_ICRNL);
  357         lts->c_iflag |= cvtto_linux_mask(bts->c_iflag, IXON, LINUX_IXON);
  358         lts->c_iflag |= cvtto_linux_mask(bts->c_iflag, IXANY, LINUX_IXANY);
  359         lts->c_iflag |= cvtto_linux_mask(bts->c_iflag, IXOFF, LINUX_IXOFF);
  360         lts->c_iflag |= cvtto_linux_mask(bts->c_iflag, IMAXBEL, LINUX_IMAXBEL);
  361 
  362         lts->c_oflag = 0;
  363         lts->c_oflag |= cvtto_linux_mask(bts->c_oflag, OPOST, LINUX_OPOST);
  364         lts->c_oflag |= cvtto_linux_mask(bts->c_oflag, ONLCR, LINUX_ONLCR);
  365         lts->c_oflag |= cvtto_linux_mask(bts->c_oflag, OXTABS, LINUX_XTABS);
  366 
  367         switch (bts->c_cflag & CSIZE) {
  368         case CS5:
  369                 lts->c_cflag = LINUX_CS5;
  370                 break;
  371         case CS6:
  372                 lts->c_cflag = LINUX_CS6;
  373                 break;
  374         case CS7:
  375                 lts->c_cflag = LINUX_CS7;
  376                 break;
  377         case CS8:
  378                 lts->c_cflag = LINUX_CS8;
  379                 break;
  380         }
  381         lts->c_cflag |= cvtto_linux_mask(bts->c_cflag, CS5, LINUX_CS5);
  382         lts->c_cflag |= cvtto_linux_mask(bts->c_cflag, CS6, LINUX_CS6);
  383         lts->c_cflag |= cvtto_linux_mask(bts->c_cflag, CS7, LINUX_CS7);
  384         lts->c_cflag |= cvtto_linux_mask(bts->c_cflag, CS8, LINUX_CS8);
  385         lts->c_cflag |= cvtto_linux_mask(bts->c_cflag, CSTOPB, LINUX_CSTOPB);
  386         lts->c_cflag |= cvtto_linux_mask(bts->c_cflag, CREAD, LINUX_CREAD);
  387         lts->c_cflag |= cvtto_linux_mask(bts->c_cflag, PARENB, LINUX_PARENB);
  388         lts->c_cflag |= cvtto_linux_mask(bts->c_cflag, PARODD, LINUX_PARODD);
  389         lts->c_cflag |= cvtto_linux_mask(bts->c_cflag, HUPCL, LINUX_HUPCL);
  390         lts->c_cflag |= cvtto_linux_mask(bts->c_cflag, CLOCAL, LINUX_CLOCAL);
  391         lts->c_cflag |= cvtto_linux_mask(bts->c_cflag, CRTSCTS, LINUX_CRTSCTS);
  392 
  393         lts->c_lflag = 0;
  394         lts->c_lflag |= cvtto_linux_mask(bts->c_lflag, ISIG, LINUX_ISIG);
  395         lts->c_lflag |= cvtto_linux_mask(bts->c_lflag, ICANON, LINUX_ICANON);
  396         lts->c_lflag |= cvtto_linux_mask(bts->c_lflag, ECHO, LINUX_ECHO);
  397         lts->c_lflag |= cvtto_linux_mask(bts->c_lflag, ECHOE, LINUX_ECHOE);
  398         lts->c_lflag |= cvtto_linux_mask(bts->c_lflag, ECHOK, LINUX_ECHOK);
  399         lts->c_lflag |= cvtto_linux_mask(bts->c_lflag, ECHONL, LINUX_ECHONL);
  400         lts->c_lflag |= cvtto_linux_mask(bts->c_lflag, NOFLSH, LINUX_NOFLSH);
  401         lts->c_lflag |= cvtto_linux_mask(bts->c_lflag, TOSTOP, LINUX_TOSTOP);
  402         lts->c_lflag |= cvtto_linux_mask(bts->c_lflag, ECHOCTL, LINUX_ECHOCTL);
  403         lts->c_lflag |= cvtto_linux_mask(bts->c_lflag, ECHOPRT, LINUX_ECHOPRT);
  404         lts->c_lflag |= cvtto_linux_mask(bts->c_lflag, ECHOKE, LINUX_ECHOKE);
  405         lts->c_lflag |= cvtto_linux_mask(bts->c_lflag, FLUSHO, LINUX_FLUSHO);
  406         lts->c_lflag |= cvtto_linux_mask(bts->c_lflag, PENDIN, LINUX_PENDIN);
  407         lts->c_lflag |= cvtto_linux_mask(bts->c_lflag, IEXTEN, LINUX_IEXTEN);
  408 
  409         mask = LINUX_B9600;     /* XXX default value */
  410         for (i = 0; i < sizeof (linux_speeds) / sizeof (speed_t); i++) {
  411                 if (bts->c_ospeed == linux_speeds[i]) {
  412                         mask = linux_spmasks[i];
  413                         break;
  414                 }
  415         }
  416         lts->c_cflag |= mask;
  417 
  418         lts->c_cc[LINUX_VINTR] = bts->c_cc[VINTR];
  419         lts->c_cc[LINUX_VQUIT] = bts->c_cc[VQUIT];
  420         lts->c_cc[LINUX_VERASE] = bts->c_cc[VERASE];
  421         lts->c_cc[LINUX_VKILL] = bts->c_cc[VKILL];
  422         lts->c_cc[LINUX_VEOF] = bts->c_cc[VEOF];
  423         lts->c_cc[LINUX_VTIME] = bts->c_cc[VTIME];
  424         lts->c_cc[LINUX_VMIN] = bts->c_cc[VMIN];
  425         lts->c_cc[LINUX_VEOL] = bts->c_cc[VEOL];
  426         lts->c_cc[LINUX_VEOL2] = bts->c_cc[VEOL2];
  427         lts->c_cc[LINUX_VWERASE] = bts->c_cc[VWERASE];
  428         lts->c_cc[LINUX_VSUSP] = bts->c_cc[VSUSP];
  429         lts->c_cc[LINUX_VSTART] = bts->c_cc[VSTART];
  430         lts->c_cc[LINUX_VSTOP] = bts->c_cc[VSTOP];
  431         lts->c_cc[LINUX_VLNEXT] = bts->c_cc[VLNEXT];
  432         lts->c_cc[LINUX_VDISCARD] = bts->c_cc[VDISCARD];
  433         lts->c_cc[LINUX_VREPRINT] = bts->c_cc[VREPRINT];
  434         lts->c_cc[LINUX_VSWTC] = 0;
  435 
  436         /* XXX should be fixed someday */
  437         lts->c_line = 0;
  438 }
  439 
  440 int
  441 linux_ioctl_termios(p, v, retval)
  442         struct proc *p;
  443         void *v;
  444         register_t *retval;
  445 {
  446         struct linux_sys_ioctl_args /* {
  447                 syscallarg(int) fd;
  448                 syscallarg(u_long) com;
  449                 syscallarg(caddr_t) data;
  450         } */ *uap = v;
  451         struct file *fp;
  452         struct filedesc *fdp;
  453         u_long com;
  454         struct linux_termio tmplt;
  455         struct linux_termios tmplts;
  456         struct termios tmpbts;
  457         caddr_t sg;
  458         int idat;
  459         struct sys_ioctl_args ia;
  460         char tioclinux;
  461         int error = 0;
  462 
  463         fdp = p->p_fd;
  464         if ((fp = fd_getfile(fdp, SCARG(uap, fd))) == NULL)
  465                 return (EBADF);
  466         FREF(fp);
  467 
  468         if ((fp->f_flag & (FREAD | FWRITE)) == 0) {
  469                 error = EBADF;
  470                 goto out;
  471         }
  472 
  473         com = SCARG(uap, com);
  474         retval[0] = 0;
  475                 
  476         switch (com) {
  477         case LINUX_TCGETS:
  478                 error = (*fp->f_ops->fo_ioctl)(fp, TIOCGETA, (caddr_t)&tmpbts,
  479                     p);
  480                 if (error)
  481                         goto out;
  482                 bsd_termios_to_linux_termios(&tmpbts, &tmplts);
  483                 error = copyout(&tmplts, SCARG(uap, data), sizeof tmplts);
  484                 goto out;
  485         case LINUX_TCSETS:
  486         case LINUX_TCSETSW:
  487         case LINUX_TCSETSF:
  488                 /*
  489                  * First fill in all fields, so that we keep the current
  490                  * values for fields that Linux doesn't know about.
  491                  */
  492                 error = (*fp->f_ops->fo_ioctl)(fp, TIOCGETA, (caddr_t)&tmpbts,
  493                     p);
  494                 if (error)
  495                         goto out;
  496                 error = copyin(SCARG(uap, data), &tmplts, sizeof tmplts);
  497                 if (error)
  498                         goto out;
  499                 linux_termios_to_bsd_termios(&tmplts, &tmpbts);
  500                 switch (com) {
  501                 case LINUX_TCSETS:
  502                         com = TIOCSETA;
  503                         break;
  504                 case LINUX_TCSETSW:
  505                         com = TIOCSETAW;
  506                         break;
  507                 case LINUX_TCSETSF:
  508                         com = TIOCSETAF;
  509                         break;
  510                 }
  511                 error = (*fp->f_ops->fo_ioctl)(fp, com, (caddr_t)&tmpbts, p);
  512                 goto out;
  513         case LINUX_TCGETA:
  514                 error = (*fp->f_ops->fo_ioctl)(fp, TIOCGETA, (caddr_t)&tmpbts,
  515                     p);
  516                 if (error)
  517                         goto out;
  518                 bsd_termios_to_linux_termio(&tmpbts, &tmplt);
  519                 error = copyout(&tmplt, SCARG(uap, data), sizeof tmplt);
  520                 goto out;
  521         case LINUX_TCSETA:
  522         case LINUX_TCSETAW:
  523         case LINUX_TCSETAF:
  524                 /*
  525                  * First fill in all fields, so that we keep the current
  526                  * values for fields that Linux doesn't know about.
  527                  */
  528                 error = (*fp->f_ops->fo_ioctl)(fp, TIOCGETA, (caddr_t)&tmpbts,
  529                     p);
  530                 if (error)
  531                         goto out;
  532                 error = copyin(SCARG(uap, data), &tmplt, sizeof tmplt);
  533                 if (error)
  534                         goto out;
  535                 linux_termio_to_bsd_termios(&tmplt, &tmpbts);
  536                 switch (com) {
  537                 case LINUX_TCSETA:
  538                         com = TIOCSETA;
  539                         break;
  540                 case LINUX_TCSETAW:
  541                         com = TIOCSETAW;
  542                         break;
  543                 case LINUX_TCSETAF:
  544                         com = TIOCSETAF;
  545                         break;
  546                 }
  547                 error = (*fp->f_ops->fo_ioctl)(fp, com, (caddr_t)&tmpbts, p);
  548                 goto out;
  549         case LINUX_TIOCGETD:
  550                 error = (*fp->f_ops->fo_ioctl)(fp, TIOCGETD, (caddr_t)&idat, p);
  551                 if (error)
  552                         goto out;
  553                 switch (idat) {
  554                 case TTYDISC:
  555                         idat = LINUX_N_TTY;
  556                         break;
  557                 case SLIPDISC:
  558                         idat = LINUX_N_SLIP;
  559                         break;
  560                 case PPPDISC:
  561                         idat = LINUX_N_PPP;
  562                         break;
  563                 /*
  564                  * Linux does not have the tablet line discipline.
  565                  */
  566                 case TABLDISC:
  567                 default:
  568                         idat = -1;      /* XXX What should this be? */
  569                         break;
  570                 }
  571                 error = copyout(&idat, SCARG(uap, data), sizeof idat);
  572                 goto out;
  573         case LINUX_TIOCSETD:
  574                 error = copyin(SCARG(uap, data), &idat, sizeof idat);
  575                 if (error)
  576                         goto out;
  577                 switch (idat) {
  578                 case LINUX_N_TTY:
  579                         idat = TTYDISC;
  580                         break;
  581                 case LINUX_N_SLIP:
  582                         idat = SLIPDISC;
  583                         break;
  584                 case LINUX_N_PPP:
  585                         idat = PPPDISC;
  586                         break;
  587                 /*
  588                  * We can't handle the mouse line discipline Linux has.
  589                  */
  590                 case LINUX_N_MOUSE:
  591                 default:
  592                         error = EINVAL;
  593                         goto out;
  594                 }
  595                 error = (*fp->f_ops->fo_ioctl)(fp, TIOCSETD, (caddr_t)&idat, p);
  596                 goto out;
  597         case LINUX_TIOCLINUX:
  598                 error = copyin(SCARG(uap, data), &tioclinux, sizeof tioclinux);
  599                 if (error != 0)
  600                         goto out;
  601                 switch (tioclinux) {
  602                 case LINUX_TIOCLINUX_KERNMSG:
  603                         /*
  604                          * XXX needed to not fail for some things. Could
  605                          * try to use TIOCCONS, but the char argument
  606                          * specifies the VT #, not an fd.
  607                          */
  608                         goto out;
  609                 case LINUX_TIOCLINUX_COPY:
  610                 case LINUX_TIOCLINUX_PASTE:
  611                 case LINUX_TIOCLINUX_UNBLANK:
  612                 case LINUX_TIOCLINUX_LOADLUT:
  613                 case LINUX_TIOCLINUX_READSHIFT:
  614                 case LINUX_TIOCLINUX_READMOUSE:
  615                 case LINUX_TIOCLINUX_VESABLANK:
  616                 case LINUX_TIOCLINUX_CURCONS:   /* could use VT_GETACTIVE */
  617                         error = EINVAL;
  618                         goto out;
  619                 }
  620                 break;
  621         case LINUX_TIOCGWINSZ:
  622                 SCARG(&ia, com) = TIOCGWINSZ;
  623                 break;
  624         case LINUX_TIOCSWINSZ:
  625                 SCARG(&ia, com) = TIOCSWINSZ;
  626                 break;
  627         case LINUX_TIOCMGET:
  628                 SCARG(&ia, com) = TIOCMGET;
  629                 break;
  630         case LINUX_TIOCMBIS:
  631                 SCARG(&ia, com) = TIOCMBIS;
  632                 break;
  633         case LINUX_TIOCMBIC:
  634                 SCARG(&ia, com) = TIOCMBIC;
  635                 break;
  636         case LINUX_TIOCMSET:
  637                 SCARG(&ia, com) = TIOCMSET;
  638                 break;
  639         case LINUX_TIOCGPGRP:
  640                 SCARG(&ia, com) = TIOCGPGRP;
  641                 break;
  642         case LINUX_TIOCSPGRP:
  643                 SCARG(&ia, com) = TIOCSPGRP;
  644                 break;
  645         case LINUX_FIONREAD:
  646                 SCARG(&ia, com) = FIONREAD;
  647                 break;
  648         case LINUX_FIONBIO:
  649                 SCARG(&ia, com) = FIONBIO;
  650                 break;
  651         case LINUX_FIOASYNC:
  652                 SCARG(&ia, com) = FIOASYNC;
  653                 break;
  654         case LINUX_TIOCEXCL:
  655                 SCARG(&ia, com) = TIOCEXCL;
  656                 break;
  657         case LINUX_TIOCNXCL:
  658                 SCARG(&ia, com) = TIOCNXCL;
  659                 break;
  660         case LINUX_TIOCSCTTY:
  661                 SCARG(&ia, com) = TIOCSCTTY;
  662                 break;
  663         case LINUX_TIOCCONS:
  664                 SCARG(&ia, com) = TIOCCONS;
  665                 break;
  666         case LINUX_TIOCNOTTY:
  667                 SCARG(&ia, com) = TIOCNOTTY;
  668                 break;
  669         case LINUX_TCSBRK:
  670                 SCARG(&ia, com) = SCARG(uap, data) ? TIOCDRAIN : TIOCSBRK;
  671                 break;
  672         case LINUX_TCXONC:
  673                 switch ((int)SCARG(uap, data)) {
  674                 case LINUX_TCOOFF:
  675                         SCARG(&ia, com) = TIOCSTOP;
  676                         break;
  677                 case LINUX_TCOON:
  678                         SCARG(&ia, com) = TIOCSTART;
  679                         break;
  680                 case LINUX_TCIOFF:
  681                 case LINUX_TCION: {
  682                         u_char c, *cp;
  683                         struct sys_write_args wa;
  684 
  685                         error = (*fp->f_ops->fo_ioctl)(fp, TIOCGETA,
  686                             (caddr_t)&tmpbts, p);
  687                         if (error)
  688                                 goto out;
  689                         if ((int)SCARG(uap, data) == LINUX_TCIOFF)
  690                                 c = tmpbts.c_cc[VSTOP];
  691                         else
  692                                 c = tmpbts.c_cc[VSTART];
  693                         if (c == _POSIX_VDISABLE)
  694                                 goto out;
  695 
  696                         sg = stackgap_init(p->p_emul);
  697                         cp = (char *) stackgap_alloc(&sg, 1);
  698                         if ((error = copyout(&c, cp, 1)))
  699                                 goto out;
  700 
  701                         SCARG(&wa, fd) = SCARG(uap, fd);
  702                         SCARG(&wa, buf) = cp;
  703                         SCARG(&wa, nbyte) = 1;
  704                         error = sys_write(p, &wa, retval);
  705                         goto out;
  706                     }
  707                 default:
  708                         error = EINVAL;
  709                         goto out;
  710                 }
  711                 SCARG(uap, data) = 0;
  712                 break;
  713         default:
  714                 error = EINVAL;
  715                 goto out;
  716         }
  717 
  718         SCARG(&ia, fd) = SCARG(uap, fd);
  719         SCARG(&ia, data) = SCARG(uap, data);
  720         error = sys_ioctl(p, &ia, retval);
  721 
  722 out:
  723         FRELE(fp);
  724         return (error);
  725 }

/* [<][>][^][v][top][bottom][index][help] */