Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  *  Copyright (C) 1991, 1992, 1993, 1994  Linus Torvalds
0004  *
0005  * Modified by Fred N. van Kempen, 01/29/93, to add line disciplines
0006  * which can be dynamically activated and de-activated by the line
0007  * discipline handling modules (like SLIP).
0008  */
0009 
0010 #include <linux/types.h>
0011 #include <linux/termios.h>
0012 #include <linux/errno.h>
0013 #include <linux/sched/signal.h>
0014 #include <linux/kernel.h>
0015 #include <linux/major.h>
0016 #include <linux/tty.h>
0017 #include <linux/fcntl.h>
0018 #include <linux/string.h>
0019 #include <linux/mm.h>
0020 #include <linux/module.h>
0021 #include <linux/bitops.h>
0022 #include <linux/mutex.h>
0023 #include <linux/compat.h>
0024 #include "tty.h"
0025 
0026 #include <asm/io.h>
0027 #include <linux/uaccess.h>
0028 
0029 #undef TTY_DEBUG_WAIT_UNTIL_SENT
0030 
0031 #ifdef TTY_DEBUG_WAIT_UNTIL_SENT
0032 # define tty_debug_wait_until_sent(tty, f, args...)    tty_debug(tty, f, ##args)
0033 #else
0034 # define tty_debug_wait_until_sent(tty, f, args...)    do {} while (0)
0035 #endif
0036 
0037 #undef  DEBUG
0038 
0039 /*
0040  * Internal flag options for termios setting behavior
0041  */
0042 #define TERMIOS_FLUSH   1
0043 #define TERMIOS_WAIT    2
0044 #define TERMIOS_TERMIO  4
0045 #define TERMIOS_OLD 8
0046 
0047 
0048 /**
0049  *  tty_chars_in_buffer -   characters pending
0050  *  @tty: terminal
0051  *
0052  *  Return the number of bytes of data in the device private
0053  *  output queue. If no private method is supplied there is assumed
0054  *  to be no queue on the device.
0055  */
0056 
0057 unsigned int tty_chars_in_buffer(struct tty_struct *tty)
0058 {
0059     if (tty->ops->chars_in_buffer)
0060         return tty->ops->chars_in_buffer(tty);
0061     return 0;
0062 }
0063 EXPORT_SYMBOL(tty_chars_in_buffer);
0064 
0065 /**
0066  *  tty_write_room      -   write queue space
0067  *  @tty: terminal
0068  *
0069  *  Return the number of bytes that can be queued to this device
0070  *  at the present time. The result should be treated as a guarantee
0071  *  and the driver cannot offer a value it later shrinks by more than
0072  *  the number of bytes written. If no method is provided 2K is always
0073  *  returned and data may be lost as there will be no flow control.
0074  */
0075  
0076 unsigned int tty_write_room(struct tty_struct *tty)
0077 {
0078     if (tty->ops->write_room)
0079         return tty->ops->write_room(tty);
0080     return 2048;
0081 }
0082 EXPORT_SYMBOL(tty_write_room);
0083 
0084 /**
0085  *  tty_driver_flush_buffer -   discard internal buffer
0086  *  @tty: terminal
0087  *
0088  *  Discard the internal output buffer for this device. If no method
0089  *  is provided then either the buffer cannot be hardware flushed or
0090  *  there is no buffer driver side.
0091  */
0092 void tty_driver_flush_buffer(struct tty_struct *tty)
0093 {
0094     if (tty->ops->flush_buffer)
0095         tty->ops->flush_buffer(tty);
0096 }
0097 EXPORT_SYMBOL(tty_driver_flush_buffer);
0098 
0099 /**
0100  *  tty_unthrottle      -   flow control
0101  *  @tty: terminal
0102  *
0103  *  Indicate that a tty may continue transmitting data down the stack.
0104  *  Takes the termios rwsem to protect against parallel throttle/unthrottle
0105  *  and also to ensure the driver can consistently reference its own
0106  *  termios data at this point when implementing software flow control.
0107  *
0108  *  Drivers should however remember that the stack can issue a throttle,
0109  *  then change flow control method, then unthrottle.
0110  */
0111 
0112 void tty_unthrottle(struct tty_struct *tty)
0113 {
0114     down_write(&tty->termios_rwsem);
0115     if (test_and_clear_bit(TTY_THROTTLED, &tty->flags) &&
0116         tty->ops->unthrottle)
0117         tty->ops->unthrottle(tty);
0118     tty->flow_change = 0;
0119     up_write(&tty->termios_rwsem);
0120 }
0121 EXPORT_SYMBOL(tty_unthrottle);
0122 
0123 /**
0124  *  tty_throttle_safe   -   flow control
0125  *  @tty: terminal
0126  *
0127  *  Indicate that a tty should stop transmitting data down the stack.
0128  *  tty_throttle_safe will only attempt throttle if tty->flow_change is
0129  *  TTY_THROTTLE_SAFE. Prevents an accidental throttle due to race
0130  *  conditions when throttling is conditional on factors evaluated prior to
0131  *  throttling.
0132  *
0133  *  Returns 0 if tty is throttled (or was already throttled)
0134  */
0135 
0136 int tty_throttle_safe(struct tty_struct *tty)
0137 {
0138     int ret = 0;
0139 
0140     mutex_lock(&tty->throttle_mutex);
0141     if (!tty_throttled(tty)) {
0142         if (tty->flow_change != TTY_THROTTLE_SAFE)
0143             ret = 1;
0144         else {
0145             set_bit(TTY_THROTTLED, &tty->flags);
0146             if (tty->ops->throttle)
0147                 tty->ops->throttle(tty);
0148         }
0149     }
0150     mutex_unlock(&tty->throttle_mutex);
0151 
0152     return ret;
0153 }
0154 
0155 /**
0156  *  tty_unthrottle_safe -   flow control
0157  *  @tty: terminal
0158  *
0159  *  Similar to tty_unthrottle() but will only attempt unthrottle
0160  *  if tty->flow_change is TTY_UNTHROTTLE_SAFE. Prevents an accidental
0161  *  unthrottle due to race conditions when unthrottling is conditional
0162  *  on factors evaluated prior to unthrottling.
0163  *
0164  *  Returns 0 if tty is unthrottled (or was already unthrottled)
0165  */
0166 
0167 int tty_unthrottle_safe(struct tty_struct *tty)
0168 {
0169     int ret = 0;
0170 
0171     mutex_lock(&tty->throttle_mutex);
0172     if (tty_throttled(tty)) {
0173         if (tty->flow_change != TTY_UNTHROTTLE_SAFE)
0174             ret = 1;
0175         else {
0176             clear_bit(TTY_THROTTLED, &tty->flags);
0177             if (tty->ops->unthrottle)
0178                 tty->ops->unthrottle(tty);
0179         }
0180     }
0181     mutex_unlock(&tty->throttle_mutex);
0182 
0183     return ret;
0184 }
0185 
0186 /**
0187  *  tty_wait_until_sent -   wait for I/O to finish
0188  *  @tty: tty we are waiting for
0189  *  @timeout: how long we will wait
0190  *
0191  *  Wait for characters pending in a tty driver to hit the wire, or
0192  *  for a timeout to occur (eg due to flow control)
0193  *
0194  *  Locking: none
0195  */
0196 
0197 void tty_wait_until_sent(struct tty_struct *tty, long timeout)
0198 {
0199     tty_debug_wait_until_sent(tty, "wait until sent, timeout=%ld\n", timeout);
0200 
0201     if (!timeout)
0202         timeout = MAX_SCHEDULE_TIMEOUT;
0203 
0204     timeout = wait_event_interruptible_timeout(tty->write_wait,
0205             !tty_chars_in_buffer(tty), timeout);
0206     if (timeout <= 0)
0207         return;
0208 
0209     if (timeout == MAX_SCHEDULE_TIMEOUT)
0210         timeout = 0;
0211 
0212     if (tty->ops->wait_until_sent)
0213         tty->ops->wait_until_sent(tty, timeout);
0214 }
0215 EXPORT_SYMBOL(tty_wait_until_sent);
0216 
0217 
0218 /*
0219  *      Termios Helper Methods
0220  */
0221 
0222 static void unset_locked_termios(struct tty_struct *tty, struct ktermios *old)
0223 {
0224     struct ktermios *termios = &tty->termios;
0225     struct ktermios *locked  = &tty->termios_locked;
0226     int i;
0227 
0228 #define NOSET_MASK(x, y, z) (x = ((x) & ~(z)) | ((y) & (z)))
0229 
0230     NOSET_MASK(termios->c_iflag, old->c_iflag, locked->c_iflag);
0231     NOSET_MASK(termios->c_oflag, old->c_oflag, locked->c_oflag);
0232     NOSET_MASK(termios->c_cflag, old->c_cflag, locked->c_cflag);
0233     NOSET_MASK(termios->c_lflag, old->c_lflag, locked->c_lflag);
0234     termios->c_line = locked->c_line ? old->c_line : termios->c_line;
0235     for (i = 0; i < NCCS; i++)
0236         termios->c_cc[i] = locked->c_cc[i] ?
0237             old->c_cc[i] : termios->c_cc[i];
0238     /* FIXME: What should we do for i/ospeed */
0239 }
0240 
0241 /**
0242  *  tty_termios_copy_hw -   copy hardware settings
0243  *  @new: New termios
0244  *  @old: Old termios
0245  *
0246  *  Propagate the hardware specific terminal setting bits from
0247  *  the old termios structure to the new one. This is used in cases
0248  *  where the hardware does not support reconfiguration or as a helper
0249  *  in some cases where only minimal reconfiguration is supported
0250  */
0251 
0252 void tty_termios_copy_hw(struct ktermios *new, struct ktermios *old)
0253 {
0254     /* The bits a dumb device handles in software. Smart devices need
0255        to always provide a set_termios method */
0256     new->c_cflag &= HUPCL | CREAD | CLOCAL;
0257     new->c_cflag |= old->c_cflag & ~(HUPCL | CREAD | CLOCAL);
0258     new->c_ispeed = old->c_ispeed;
0259     new->c_ospeed = old->c_ospeed;
0260 }
0261 EXPORT_SYMBOL(tty_termios_copy_hw);
0262 
0263 /**
0264  *  tty_termios_hw_change   -   check for setting change
0265  *  @a: termios
0266  *  @b: termios to compare
0267  *
0268  *  Check if any of the bits that affect a dumb device have changed
0269  *  between the two termios structures, or a speed change is needed.
0270  */
0271 
0272 int tty_termios_hw_change(const struct ktermios *a, const struct ktermios *b)
0273 {
0274     if (a->c_ispeed != b->c_ispeed || a->c_ospeed != b->c_ospeed)
0275         return 1;
0276     if ((a->c_cflag ^ b->c_cflag) & ~(HUPCL | CREAD | CLOCAL))
0277         return 1;
0278     return 0;
0279 }
0280 EXPORT_SYMBOL(tty_termios_hw_change);
0281 
0282 /**
0283  *  tty_get_char_size   -   get size of a character
0284  *  @cflag: termios cflag value
0285  *
0286  *  Get the size (in bits) of a character depending on @cflag's %CSIZE
0287  *  setting.
0288  */
0289 unsigned char tty_get_char_size(unsigned int cflag)
0290 {
0291     switch (cflag & CSIZE) {
0292     case CS5:
0293         return 5;
0294     case CS6:
0295         return 6;
0296     case CS7:
0297         return 7;
0298     case CS8:
0299     default:
0300         return 8;
0301     }
0302 }
0303 EXPORT_SYMBOL_GPL(tty_get_char_size);
0304 
0305 /**
0306  *  tty_get_frame_size  -   get size of a frame
0307  *  @cflag: termios cflag value
0308  *
0309  *  Get the size (in bits) of a frame depending on @cflag's %CSIZE, %CSTOPB,
0310  *  and %PARENB setting. The result is a sum of character size, start and
0311  *  stop bits -- one bit each -- second stop bit (if set), and parity bit
0312  *  (if set).
0313  */
0314 unsigned char tty_get_frame_size(unsigned int cflag)
0315 {
0316     unsigned char bits = 2 + tty_get_char_size(cflag);
0317 
0318     if (cflag & CSTOPB)
0319         bits++;
0320     if (cflag & PARENB)
0321         bits++;
0322     if (cflag & ADDRB)
0323         bits++;
0324 
0325     return bits;
0326 }
0327 EXPORT_SYMBOL_GPL(tty_get_frame_size);
0328 
0329 /**
0330  *  tty_set_termios     -   update termios values
0331  *  @tty: tty to update
0332  *  @new_termios: desired new value
0333  *
0334  *  Perform updates to the termios values set on this terminal.
0335  *  A master pty's termios should never be set.
0336  *
0337  *  Locking: termios_rwsem
0338  */
0339 
0340 int tty_set_termios(struct tty_struct *tty, struct ktermios *new_termios)
0341 {
0342     struct ktermios old_termios;
0343     struct tty_ldisc *ld;
0344 
0345     WARN_ON(tty->driver->type == TTY_DRIVER_TYPE_PTY &&
0346         tty->driver->subtype == PTY_TYPE_MASTER);
0347     /*
0348      *  Perform the actual termios internal changes under lock.
0349      */
0350 
0351 
0352     /* FIXME: we need to decide on some locking/ordering semantics
0353        for the set_termios notification eventually */
0354     down_write(&tty->termios_rwsem);
0355     old_termios = tty->termios;
0356     tty->termios = *new_termios;
0357     unset_locked_termios(tty, &old_termios);
0358     /* Reset any ADDRB changes, ADDRB is changed through ->rs485_config() */
0359     tty->termios.c_cflag ^= (tty->termios.c_cflag ^ old_termios.c_cflag) & ADDRB;
0360 
0361     if (tty->ops->set_termios)
0362         tty->ops->set_termios(tty, &old_termios);
0363     else
0364         tty_termios_copy_hw(&tty->termios, &old_termios);
0365 
0366     ld = tty_ldisc_ref(tty);
0367     if (ld != NULL) {
0368         if (ld->ops->set_termios)
0369             ld->ops->set_termios(tty, &old_termios);
0370         tty_ldisc_deref(ld);
0371     }
0372     up_write(&tty->termios_rwsem);
0373     return 0;
0374 }
0375 EXPORT_SYMBOL_GPL(tty_set_termios);
0376 
0377 /**
0378  *  set_termios     -   set termios values for a tty
0379  *  @tty: terminal device
0380  *  @arg: user data
0381  *  @opt: option information
0382  *
0383  *  Helper function to prepare termios data and run necessary other
0384  *  functions before using tty_set_termios to do the actual changes.
0385  *
0386  *  Locking:
0387  *      Called functions take ldisc and termios_rwsem locks
0388  */
0389 
0390 static int set_termios(struct tty_struct *tty, void __user *arg, int opt)
0391 {
0392     struct ktermios tmp_termios;
0393     struct tty_ldisc *ld;
0394     int retval = tty_check_change(tty);
0395 
0396     if (retval)
0397         return retval;
0398 
0399     down_read(&tty->termios_rwsem);
0400     tmp_termios = tty->termios;
0401     up_read(&tty->termios_rwsem);
0402 
0403     if (opt & TERMIOS_TERMIO) {
0404         if (user_termio_to_kernel_termios(&tmp_termios,
0405                         (struct termio __user *)arg))
0406             return -EFAULT;
0407 #ifdef TCGETS2
0408     } else if (opt & TERMIOS_OLD) {
0409         if (user_termios_to_kernel_termios_1(&tmp_termios,
0410                         (struct termios __user *)arg))
0411             return -EFAULT;
0412     } else {
0413         if (user_termios_to_kernel_termios(&tmp_termios,
0414                         (struct termios2 __user *)arg))
0415             return -EFAULT;
0416     }
0417 #else
0418     } else if (user_termios_to_kernel_termios(&tmp_termios,
0419                     (struct termios __user *)arg))
0420         return -EFAULT;
0421 #endif
0422 
0423     /* If old style Bfoo values are used then load c_ispeed/c_ospeed
0424      * with the real speed so its unconditionally usable */
0425     tmp_termios.c_ispeed = tty_termios_input_baud_rate(&tmp_termios);
0426     tmp_termios.c_ospeed = tty_termios_baud_rate(&tmp_termios);
0427 
0428     ld = tty_ldisc_ref(tty);
0429 
0430     if (ld != NULL) {
0431         if ((opt & TERMIOS_FLUSH) && ld->ops->flush_buffer)
0432             ld->ops->flush_buffer(tty);
0433         tty_ldisc_deref(ld);
0434     }
0435 
0436     if (opt & TERMIOS_WAIT) {
0437         tty_wait_until_sent(tty, 0);
0438         if (signal_pending(current))
0439             return -ERESTARTSYS;
0440     }
0441 
0442     tty_set_termios(tty, &tmp_termios);
0443 
0444     /* FIXME: Arguably if tmp_termios == tty->termios AND the
0445        actual requested termios was not tmp_termios then we may
0446        want to return an error as no user requested change has
0447        succeeded */
0448     return 0;
0449 }
0450 
0451 static void copy_termios(struct tty_struct *tty, struct ktermios *kterm)
0452 {
0453     down_read(&tty->termios_rwsem);
0454     *kterm = tty->termios;
0455     up_read(&tty->termios_rwsem);
0456 }
0457 
0458 static void copy_termios_locked(struct tty_struct *tty, struct ktermios *kterm)
0459 {
0460     down_read(&tty->termios_rwsem);
0461     *kterm = tty->termios_locked;
0462     up_read(&tty->termios_rwsem);
0463 }
0464 
0465 static int get_termio(struct tty_struct *tty, struct termio __user *termio)
0466 {
0467     struct ktermios kterm;
0468     copy_termios(tty, &kterm);
0469     if (kernel_termios_to_user_termio(termio, &kterm))
0470         return -EFAULT;
0471     return 0;
0472 }
0473 
0474 #ifdef TIOCGETP
0475 /*
0476  * These are deprecated, but there is limited support..
0477  *
0478  * The "sg_flags" translation is a joke..
0479  */
0480 static int get_sgflags(struct tty_struct *tty)
0481 {
0482     int flags = 0;
0483 
0484     if (!L_ICANON(tty)) {
0485         if (L_ISIG(tty))
0486             flags |= 0x02;      /* cbreak */
0487         else
0488             flags |= 0x20;      /* raw */
0489     }
0490     if (L_ECHO(tty))
0491         flags |= 0x08;          /* echo */
0492     if (O_OPOST(tty))
0493         if (O_ONLCR(tty))
0494             flags |= 0x10;      /* crmod */
0495     return flags;
0496 }
0497 
0498 static int get_sgttyb(struct tty_struct *tty, struct sgttyb __user *sgttyb)
0499 {
0500     struct sgttyb tmp;
0501 
0502     down_read(&tty->termios_rwsem);
0503     tmp.sg_ispeed = tty->termios.c_ispeed;
0504     tmp.sg_ospeed = tty->termios.c_ospeed;
0505     tmp.sg_erase = tty->termios.c_cc[VERASE];
0506     tmp.sg_kill = tty->termios.c_cc[VKILL];
0507     tmp.sg_flags = get_sgflags(tty);
0508     up_read(&tty->termios_rwsem);
0509 
0510     return copy_to_user(sgttyb, &tmp, sizeof(tmp)) ? -EFAULT : 0;
0511 }
0512 
0513 static void set_sgflags(struct ktermios *termios, int flags)
0514 {
0515     termios->c_iflag = ICRNL | IXON;
0516     termios->c_oflag = 0;
0517     termios->c_lflag = ISIG | ICANON;
0518     if (flags & 0x02) { /* cbreak */
0519         termios->c_iflag = 0;
0520         termios->c_lflag &= ~ICANON;
0521     }
0522     if (flags & 0x08) {     /* echo */
0523         termios->c_lflag |= ECHO | ECHOE | ECHOK |
0524                     ECHOCTL | ECHOKE | IEXTEN;
0525     }
0526     if (flags & 0x10) {     /* crmod */
0527         termios->c_oflag |= OPOST | ONLCR;
0528     }
0529     if (flags & 0x20) { /* raw */
0530         termios->c_iflag = 0;
0531         termios->c_lflag &= ~(ISIG | ICANON);
0532     }
0533     if (!(termios->c_lflag & ICANON)) {
0534         termios->c_cc[VMIN] = 1;
0535         termios->c_cc[VTIME] = 0;
0536     }
0537 }
0538 
0539 /**
0540  *  set_sgttyb      -   set legacy terminal values
0541  *  @tty: tty structure
0542  *  @sgttyb: pointer to old style terminal structure
0543  *
0544  *  Updates a terminal from the legacy BSD style terminal information
0545  *  structure.
0546  *
0547  *  Locking: termios_rwsem
0548  */
0549 
0550 static int set_sgttyb(struct tty_struct *tty, struct sgttyb __user *sgttyb)
0551 {
0552     int retval;
0553     struct sgttyb tmp;
0554     struct ktermios termios;
0555 
0556     retval = tty_check_change(tty);
0557     if (retval)
0558         return retval;
0559 
0560     if (copy_from_user(&tmp, sgttyb, sizeof(tmp)))
0561         return -EFAULT;
0562 
0563     down_write(&tty->termios_rwsem);
0564     termios = tty->termios;
0565     termios.c_cc[VERASE] = tmp.sg_erase;
0566     termios.c_cc[VKILL] = tmp.sg_kill;
0567     set_sgflags(&termios, tmp.sg_flags);
0568     /* Try and encode into Bfoo format */
0569     tty_termios_encode_baud_rate(&termios, termios.c_ispeed,
0570                         termios.c_ospeed);
0571     up_write(&tty->termios_rwsem);
0572     tty_set_termios(tty, &termios);
0573     return 0;
0574 }
0575 #endif
0576 
0577 #ifdef TIOCGETC
0578 static int get_tchars(struct tty_struct *tty, struct tchars __user *tchars)
0579 {
0580     struct tchars tmp;
0581 
0582     down_read(&tty->termios_rwsem);
0583     tmp.t_intrc = tty->termios.c_cc[VINTR];
0584     tmp.t_quitc = tty->termios.c_cc[VQUIT];
0585     tmp.t_startc = tty->termios.c_cc[VSTART];
0586     tmp.t_stopc = tty->termios.c_cc[VSTOP];
0587     tmp.t_eofc = tty->termios.c_cc[VEOF];
0588     tmp.t_brkc = tty->termios.c_cc[VEOL2];  /* what is brkc anyway? */
0589     up_read(&tty->termios_rwsem);
0590     return copy_to_user(tchars, &tmp, sizeof(tmp)) ? -EFAULT : 0;
0591 }
0592 
0593 static int set_tchars(struct tty_struct *tty, struct tchars __user *tchars)
0594 {
0595     struct tchars tmp;
0596 
0597     if (copy_from_user(&tmp, tchars, sizeof(tmp)))
0598         return -EFAULT;
0599     down_write(&tty->termios_rwsem);
0600     tty->termios.c_cc[VINTR] = tmp.t_intrc;
0601     tty->termios.c_cc[VQUIT] = tmp.t_quitc;
0602     tty->termios.c_cc[VSTART] = tmp.t_startc;
0603     tty->termios.c_cc[VSTOP] = tmp.t_stopc;
0604     tty->termios.c_cc[VEOF] = tmp.t_eofc;
0605     tty->termios.c_cc[VEOL2] = tmp.t_brkc;  /* what is brkc anyway? */
0606     up_write(&tty->termios_rwsem);
0607     return 0;
0608 }
0609 #endif
0610 
0611 #ifdef TIOCGLTC
0612 static int get_ltchars(struct tty_struct *tty, struct ltchars __user *ltchars)
0613 {
0614     struct ltchars tmp;
0615 
0616     down_read(&tty->termios_rwsem);
0617     tmp.t_suspc = tty->termios.c_cc[VSUSP];
0618     /* what is dsuspc anyway? */
0619     tmp.t_dsuspc = tty->termios.c_cc[VSUSP];
0620     tmp.t_rprntc = tty->termios.c_cc[VREPRINT];
0621     /* what is flushc anyway? */
0622     tmp.t_flushc = tty->termios.c_cc[VEOL2];
0623     tmp.t_werasc = tty->termios.c_cc[VWERASE];
0624     tmp.t_lnextc = tty->termios.c_cc[VLNEXT];
0625     up_read(&tty->termios_rwsem);
0626     return copy_to_user(ltchars, &tmp, sizeof(tmp)) ? -EFAULT : 0;
0627 }
0628 
0629 static int set_ltchars(struct tty_struct *tty, struct ltchars __user *ltchars)
0630 {
0631     struct ltchars tmp;
0632 
0633     if (copy_from_user(&tmp, ltchars, sizeof(tmp)))
0634         return -EFAULT;
0635 
0636     down_write(&tty->termios_rwsem);
0637     tty->termios.c_cc[VSUSP] = tmp.t_suspc;
0638     /* what is dsuspc anyway? */
0639     tty->termios.c_cc[VEOL2] = tmp.t_dsuspc;
0640     tty->termios.c_cc[VREPRINT] = tmp.t_rprntc;
0641     /* what is flushc anyway? */
0642     tty->termios.c_cc[VEOL2] = tmp.t_flushc;
0643     tty->termios.c_cc[VWERASE] = tmp.t_werasc;
0644     tty->termios.c_cc[VLNEXT] = tmp.t_lnextc;
0645     up_write(&tty->termios_rwsem);
0646     return 0;
0647 }
0648 #endif
0649 
0650 /**
0651  *  tty_change_softcar  -   carrier change ioctl helper
0652  *  @tty: tty to update
0653  *  @arg: enable/disable CLOCAL
0654  *
0655  *  Perform a change to the CLOCAL state and call into the driver
0656  *  layer to make it visible. All done with the termios rwsem
0657  */
0658 
0659 static int tty_change_softcar(struct tty_struct *tty, int arg)
0660 {
0661     int ret = 0;
0662     int bit = arg ? CLOCAL : 0;
0663     struct ktermios old;
0664 
0665     down_write(&tty->termios_rwsem);
0666     old = tty->termios;
0667     tty->termios.c_cflag &= ~CLOCAL;
0668     tty->termios.c_cflag |= bit;
0669     if (tty->ops->set_termios)
0670         tty->ops->set_termios(tty, &old);
0671     if (C_CLOCAL(tty) != bit)
0672         ret = -EINVAL;
0673     up_write(&tty->termios_rwsem);
0674     return ret;
0675 }
0676 
0677 /**
0678  *  tty_mode_ioctl      -   mode related ioctls
0679  *  @tty: tty for the ioctl
0680  *  @cmd: command
0681  *  @arg: ioctl argument
0682  *
0683  *  Perform non line discipline specific mode control ioctls. This
0684  *  is designed to be called by line disciplines to ensure they provide
0685  *  consistent mode setting.
0686  */
0687 
0688 int tty_mode_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg)
0689 {
0690     struct tty_struct *real_tty;
0691     void __user *p = (void __user *)arg;
0692     int ret = 0;
0693     struct ktermios kterm;
0694 
0695     if (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
0696         tty->driver->subtype == PTY_TYPE_MASTER)
0697         real_tty = tty->link;
0698     else
0699         real_tty = tty;
0700 
0701     switch (cmd) {
0702 #ifdef TIOCGETP
0703     case TIOCGETP:
0704         return get_sgttyb(real_tty, (struct sgttyb __user *) arg);
0705     case TIOCSETP:
0706     case TIOCSETN:
0707         return set_sgttyb(real_tty, (struct sgttyb __user *) arg);
0708 #endif
0709 #ifdef TIOCGETC
0710     case TIOCGETC:
0711         return get_tchars(real_tty, p);
0712     case TIOCSETC:
0713         return set_tchars(real_tty, p);
0714 #endif
0715 #ifdef TIOCGLTC
0716     case TIOCGLTC:
0717         return get_ltchars(real_tty, p);
0718     case TIOCSLTC:
0719         return set_ltchars(real_tty, p);
0720 #endif
0721     case TCSETSF:
0722         return set_termios(real_tty, p,  TERMIOS_FLUSH | TERMIOS_WAIT | TERMIOS_OLD);
0723     case TCSETSW:
0724         return set_termios(real_tty, p, TERMIOS_WAIT | TERMIOS_OLD);
0725     case TCSETS:
0726         return set_termios(real_tty, p, TERMIOS_OLD);
0727 #ifndef TCGETS2
0728     case TCGETS:
0729         copy_termios(real_tty, &kterm);
0730         if (kernel_termios_to_user_termios((struct termios __user *)arg, &kterm))
0731             ret = -EFAULT;
0732         return ret;
0733 #else
0734     case TCGETS:
0735         copy_termios(real_tty, &kterm);
0736         if (kernel_termios_to_user_termios_1((struct termios __user *)arg, &kterm))
0737             ret = -EFAULT;
0738         return ret;
0739     case TCGETS2:
0740         copy_termios(real_tty, &kterm);
0741         if (kernel_termios_to_user_termios((struct termios2 __user *)arg, &kterm))
0742             ret = -EFAULT;
0743         return ret;
0744     case TCSETSF2:
0745         return set_termios(real_tty, p,  TERMIOS_FLUSH | TERMIOS_WAIT);
0746     case TCSETSW2:
0747         return set_termios(real_tty, p, TERMIOS_WAIT);
0748     case TCSETS2:
0749         return set_termios(real_tty, p, 0);
0750 #endif
0751     case TCGETA:
0752         return get_termio(real_tty, p);
0753     case TCSETAF:
0754         return set_termios(real_tty, p, TERMIOS_FLUSH | TERMIOS_WAIT | TERMIOS_TERMIO);
0755     case TCSETAW:
0756         return set_termios(real_tty, p, TERMIOS_WAIT | TERMIOS_TERMIO);
0757     case TCSETA:
0758         return set_termios(real_tty, p, TERMIOS_TERMIO);
0759 #ifndef TCGETS2
0760     case TIOCGLCKTRMIOS:
0761         copy_termios_locked(real_tty, &kterm);
0762         if (kernel_termios_to_user_termios((struct termios __user *)arg, &kterm))
0763             ret = -EFAULT;
0764         return ret;
0765     case TIOCSLCKTRMIOS:
0766         if (!capable(CAP_SYS_ADMIN))
0767             return -EPERM;
0768         copy_termios_locked(real_tty, &kterm);
0769         if (user_termios_to_kernel_termios(&kterm,
0770                            (struct termios __user *) arg))
0771             return -EFAULT;
0772         down_write(&real_tty->termios_rwsem);
0773         real_tty->termios_locked = kterm;
0774         up_write(&real_tty->termios_rwsem);
0775         return 0;
0776 #else
0777     case TIOCGLCKTRMIOS:
0778         copy_termios_locked(real_tty, &kterm);
0779         if (kernel_termios_to_user_termios_1((struct termios __user *)arg, &kterm))
0780             ret = -EFAULT;
0781         return ret;
0782     case TIOCSLCKTRMIOS:
0783         if (!capable(CAP_SYS_ADMIN))
0784             return -EPERM;
0785         copy_termios_locked(real_tty, &kterm);
0786         if (user_termios_to_kernel_termios_1(&kterm,
0787                            (struct termios __user *) arg))
0788             return -EFAULT;
0789         down_write(&real_tty->termios_rwsem);
0790         real_tty->termios_locked = kterm;
0791         up_write(&real_tty->termios_rwsem);
0792         return ret;
0793 #endif
0794 #ifdef TCGETX
0795     case TCGETX:
0796     case TCSETX:
0797     case TCSETXW:
0798     case TCSETXF:
0799         return -ENOTTY;
0800 #endif
0801     case TIOCGSOFTCAR:
0802         copy_termios(real_tty, &kterm);
0803         ret = put_user((kterm.c_cflag & CLOCAL) ? 1 : 0,
0804                         (int __user *)arg);
0805         return ret;
0806     case TIOCSSOFTCAR:
0807         if (get_user(arg, (unsigned int __user *) arg))
0808             return -EFAULT;
0809         return tty_change_softcar(real_tty, arg);
0810     default:
0811         return -ENOIOCTLCMD;
0812     }
0813 }
0814 EXPORT_SYMBOL_GPL(tty_mode_ioctl);
0815 
0816 
0817 /* Caller guarantees ldisc reference is held */
0818 static int __tty_perform_flush(struct tty_struct *tty, unsigned long arg)
0819 {
0820     struct tty_ldisc *ld = tty->ldisc;
0821 
0822     switch (arg) {
0823     case TCIFLUSH:
0824         if (ld && ld->ops->flush_buffer) {
0825             ld->ops->flush_buffer(tty);
0826             tty_unthrottle(tty);
0827         }
0828         break;
0829     case TCIOFLUSH:
0830         if (ld && ld->ops->flush_buffer) {
0831             ld->ops->flush_buffer(tty);
0832             tty_unthrottle(tty);
0833         }
0834         fallthrough;
0835     case TCOFLUSH:
0836         tty_driver_flush_buffer(tty);
0837         break;
0838     default:
0839         return -EINVAL;
0840     }
0841     return 0;
0842 }
0843 
0844 int tty_perform_flush(struct tty_struct *tty, unsigned long arg)
0845 {
0846     struct tty_ldisc *ld;
0847     int retval = tty_check_change(tty);
0848     if (retval)
0849         return retval;
0850 
0851     ld = tty_ldisc_ref_wait(tty);
0852     retval = __tty_perform_flush(tty, arg);
0853     if (ld)
0854         tty_ldisc_deref(ld);
0855     return retval;
0856 }
0857 EXPORT_SYMBOL_GPL(tty_perform_flush);
0858 
0859 int n_tty_ioctl_helper(struct tty_struct *tty, unsigned int cmd,
0860         unsigned long arg)
0861 {
0862     int retval;
0863 
0864     switch (cmd) {
0865     case TCXONC:
0866         retval = tty_check_change(tty);
0867         if (retval)
0868             return retval;
0869         switch (arg) {
0870         case TCOOFF:
0871             spin_lock_irq(&tty->flow.lock);
0872             if (!tty->flow.tco_stopped) {
0873                 tty->flow.tco_stopped = true;
0874                 __stop_tty(tty);
0875             }
0876             spin_unlock_irq(&tty->flow.lock);
0877             break;
0878         case TCOON:
0879             spin_lock_irq(&tty->flow.lock);
0880             if (tty->flow.tco_stopped) {
0881                 tty->flow.tco_stopped = false;
0882                 __start_tty(tty);
0883             }
0884             spin_unlock_irq(&tty->flow.lock);
0885             break;
0886         case TCIOFF:
0887             if (STOP_CHAR(tty) != __DISABLED_CHAR)
0888                 retval = tty_send_xchar(tty, STOP_CHAR(tty));
0889             break;
0890         case TCION:
0891             if (START_CHAR(tty) != __DISABLED_CHAR)
0892                 retval = tty_send_xchar(tty, START_CHAR(tty));
0893             break;
0894         default:
0895             return -EINVAL;
0896         }
0897         return retval;
0898     case TCFLSH:
0899         retval = tty_check_change(tty);
0900         if (retval)
0901             return retval;
0902         return __tty_perform_flush(tty, arg);
0903     default:
0904         /* Try the mode commands */
0905         return tty_mode_ioctl(tty, cmd, arg);
0906     }
0907 }
0908 EXPORT_SYMBOL(n_tty_ioctl_helper);