linux/drivers/tty/tty_ioctl.c
<<
>>
Prefs
   1/*
   2 *  Copyright (C) 1991, 1992, 1993, 1994  Linus Torvalds
   3 *
   4 * Modified by Fred N. van Kempen, 01/29/93, to add line disciplines
   5 * which can be dynamically activated and de-activated by the line
   6 * discipline handling modules (like SLIP).
   7 */
   8
   9#include <linux/types.h>
  10#include <linux/termios.h>
  11#include <linux/errno.h>
  12#include <linux/sched.h>
  13#include <linux/kernel.h>
  14#include <linux/major.h>
  15#include <linux/tty.h>
  16#include <linux/fcntl.h>
  17#include <linux/string.h>
  18#include <linux/mm.h>
  19#include <linux/module.h>
  20#include <linux/bitops.h>
  21#include <linux/mutex.h>
  22#include <linux/compat.h>
  23
  24#include <asm/io.h>
  25#include <linux/uaccess.h>
  26
  27#undef TTY_DEBUG_WAIT_UNTIL_SENT
  28
  29#ifdef TTY_DEBUG_WAIT_UNTIL_SENT
  30# define tty_debug_wait_until_sent(tty, f, args...)    tty_debug(tty, f, ##args)
  31#else
  32# define tty_debug_wait_until_sent(tty, f, args...)    do {} while (0)
  33#endif
  34
  35#undef  DEBUG
  36
  37/*
  38 * Internal flag options for termios setting behavior
  39 */
  40#define TERMIOS_FLUSH   1
  41#define TERMIOS_WAIT    2
  42#define TERMIOS_TERMIO  4
  43#define TERMIOS_OLD     8
  44
  45
  46/**
  47 *      tty_chars_in_buffer     -       characters pending
  48 *      @tty: terminal
  49 *
  50 *      Return the number of bytes of data in the device private
  51 *      output queue. If no private method is supplied there is assumed
  52 *      to be no queue on the device.
  53 */
  54
  55int tty_chars_in_buffer(struct tty_struct *tty)
  56{
  57        if (tty->ops->chars_in_buffer)
  58                return tty->ops->chars_in_buffer(tty);
  59        else
  60                return 0;
  61}
  62EXPORT_SYMBOL(tty_chars_in_buffer);
  63
  64/**
  65 *      tty_write_room          -       write queue space
  66 *      @tty: terminal
  67 *
  68 *      Return the number of bytes that can be queued to this device
  69 *      at the present time. The result should be treated as a guarantee
  70 *      and the driver cannot offer a value it later shrinks by more than
  71 *      the number of bytes written. If no method is provided 2K is always
  72 *      returned and data may be lost as there will be no flow control.
  73 */
  74 
  75int tty_write_room(struct tty_struct *tty)
  76{
  77        if (tty->ops->write_room)
  78                return tty->ops->write_room(tty);
  79        return 2048;
  80}
  81EXPORT_SYMBOL(tty_write_room);
  82
  83/**
  84 *      tty_driver_flush_buffer -       discard internal buffer
  85 *      @tty: terminal
  86 *
  87 *      Discard the internal output buffer for this device. If no method
  88 *      is provided then either the buffer cannot be hardware flushed or
  89 *      there is no buffer driver side.
  90 */
  91void tty_driver_flush_buffer(struct tty_struct *tty)
  92{
  93        if (tty->ops->flush_buffer)
  94                tty->ops->flush_buffer(tty);
  95}
  96EXPORT_SYMBOL(tty_driver_flush_buffer);
  97
  98/**
  99 *      tty_throttle            -       flow control
 100 *      @tty: terminal
 101 *
 102 *      Indicate that a tty should stop transmitting data down the stack.
 103 *      Takes the termios rwsem to protect against parallel throttle/unthrottle
 104 *      and also to ensure the driver can consistently reference its own
 105 *      termios data at this point when implementing software flow control.
 106 */
 107
 108void tty_throttle(struct tty_struct *tty)
 109{
 110        down_write(&tty->termios_rwsem);
 111        /* check TTY_THROTTLED first so it indicates our state */
 112        if (!test_and_set_bit(TTY_THROTTLED, &tty->flags) &&
 113            tty->ops->throttle)
 114                tty->ops->throttle(tty);
 115        tty->flow_change = 0;
 116        up_write(&tty->termios_rwsem);
 117}
 118EXPORT_SYMBOL(tty_throttle);
 119
 120/**
 121 *      tty_unthrottle          -       flow control
 122 *      @tty: terminal
 123 *
 124 *      Indicate that a tty may continue transmitting data down the stack.
 125 *      Takes the termios rwsem to protect against parallel throttle/unthrottle
 126 *      and also to ensure the driver can consistently reference its own
 127 *      termios data at this point when implementing software flow control.
 128 *
 129 *      Drivers should however remember that the stack can issue a throttle,
 130 *      then change flow control method, then unthrottle.
 131 */
 132
 133void tty_unthrottle(struct tty_struct *tty)
 134{
 135        down_write(&tty->termios_rwsem);
 136        if (test_and_clear_bit(TTY_THROTTLED, &tty->flags) &&
 137            tty->ops->unthrottle)
 138                tty->ops->unthrottle(tty);
 139        tty->flow_change = 0;
 140        up_write(&tty->termios_rwsem);
 141}
 142EXPORT_SYMBOL(tty_unthrottle);
 143
 144/**
 145 *      tty_throttle_safe       -       flow control
 146 *      @tty: terminal
 147 *
 148 *      Similar to tty_throttle() but will only attempt throttle
 149 *      if tty->flow_change is TTY_THROTTLE_SAFE. Prevents an accidental
 150 *      throttle due to race conditions when throttling is conditional
 151 *      on factors evaluated prior to throttling.
 152 *
 153 *      Returns 0 if tty is throttled (or was already throttled)
 154 */
 155
 156int tty_throttle_safe(struct tty_struct *tty)
 157{
 158        int ret = 0;
 159
 160        mutex_lock(&tty->throttle_mutex);
 161        if (!tty_throttled(tty)) {
 162                if (tty->flow_change != TTY_THROTTLE_SAFE)
 163                        ret = 1;
 164                else {
 165                        set_bit(TTY_THROTTLED, &tty->flags);
 166                        if (tty->ops->throttle)
 167                                tty->ops->throttle(tty);
 168                }
 169        }
 170        mutex_unlock(&tty->throttle_mutex);
 171
 172        return ret;
 173}
 174
 175/**
 176 *      tty_unthrottle_safe     -       flow control
 177 *      @tty: terminal
 178 *
 179 *      Similar to tty_unthrottle() but will only attempt unthrottle
 180 *      if tty->flow_change is TTY_UNTHROTTLE_SAFE. Prevents an accidental
 181 *      unthrottle due to race conditions when unthrottling is conditional
 182 *      on factors evaluated prior to unthrottling.
 183 *
 184 *      Returns 0 if tty is unthrottled (or was already unthrottled)
 185 */
 186
 187int tty_unthrottle_safe(struct tty_struct *tty)
 188{
 189        int ret = 0;
 190
 191        mutex_lock(&tty->throttle_mutex);
 192        if (tty_throttled(tty)) {
 193                if (tty->flow_change != TTY_UNTHROTTLE_SAFE)
 194                        ret = 1;
 195                else {
 196                        clear_bit(TTY_THROTTLED, &tty->flags);
 197                        if (tty->ops->unthrottle)
 198                                tty->ops->unthrottle(tty);
 199                }
 200        }
 201        mutex_unlock(&tty->throttle_mutex);
 202
 203        return ret;
 204}
 205
 206/**
 207 *      tty_wait_until_sent     -       wait for I/O to finish
 208 *      @tty: tty we are waiting for
 209 *      @timeout: how long we will wait
 210 *
 211 *      Wait for characters pending in a tty driver to hit the wire, or
 212 *      for a timeout to occur (eg due to flow control)
 213 *
 214 *      Locking: none
 215 */
 216
 217void tty_wait_until_sent(struct tty_struct *tty, long timeout)
 218{
 219        tty_debug_wait_until_sent(tty, "wait until sent, timeout=%ld\n", timeout);
 220
 221        if (!timeout)
 222                timeout = MAX_SCHEDULE_TIMEOUT;
 223
 224        timeout = wait_event_interruptible_timeout(tty->write_wait,
 225                        !tty_chars_in_buffer(tty), timeout);
 226        if (timeout <= 0)
 227                return;
 228
 229        if (timeout == MAX_SCHEDULE_TIMEOUT)
 230                timeout = 0;
 231
 232        if (tty->ops->wait_until_sent)
 233                tty->ops->wait_until_sent(tty, timeout);
 234}
 235EXPORT_SYMBOL(tty_wait_until_sent);
 236
 237
 238/*
 239 *              Termios Helper Methods
 240 */
 241
 242static void unset_locked_termios(struct tty_struct *tty, struct ktermios *old)
 243{
 244        struct ktermios *termios = &tty->termios;
 245        struct ktermios *locked  = &tty->termios_locked;
 246        int     i;
 247
 248#define NOSET_MASK(x, y, z) (x = ((x) & ~(z)) | ((y) & (z)))
 249
 250        NOSET_MASK(termios->c_iflag, old->c_iflag, locked->c_iflag);
 251        NOSET_MASK(termios->c_oflag, old->c_oflag, locked->c_oflag);
 252        NOSET_MASK(termios->c_cflag, old->c_cflag, locked->c_cflag);
 253        NOSET_MASK(termios->c_lflag, old->c_lflag, locked->c_lflag);
 254        termios->c_line = locked->c_line ? old->c_line : termios->c_line;
 255        for (i = 0; i < NCCS; i++)
 256                termios->c_cc[i] = locked->c_cc[i] ?
 257                        old->c_cc[i] : termios->c_cc[i];
 258        /* FIXME: What should we do for i/ospeed */
 259}
 260
 261/*
 262 * Routine which returns the baud rate of the tty
 263 *
 264 * Note that the baud_table needs to be kept in sync with the
 265 * include/asm/termbits.h file.
 266 */
 267static const speed_t baud_table[] = {
 268        0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
 269        9600, 19200, 38400, 57600, 115200, 230400, 460800,
 270#ifdef __sparc__
 271        76800, 153600, 307200, 614400, 921600
 272#else
 273        500000, 576000, 921600, 1000000, 1152000, 1500000, 2000000,
 274        2500000, 3000000, 3500000, 4000000
 275#endif
 276};
 277
 278#ifndef __sparc__
 279static const tcflag_t baud_bits[] = {
 280        B0, B50, B75, B110, B134, B150, B200, B300, B600,
 281        B1200, B1800, B2400, B4800, B9600, B19200, B38400,
 282        B57600, B115200, B230400, B460800, B500000, B576000,
 283        B921600, B1000000, B1152000, B1500000, B2000000, B2500000,
 284        B3000000, B3500000, B4000000
 285};
 286#else
 287static const tcflag_t baud_bits[] = {
 288        B0, B50, B75, B110, B134, B150, B200, B300, B600,
 289        B1200, B1800, B2400, B4800, B9600, B19200, B38400,
 290        B57600, B115200, B230400, B460800, B76800, B153600,
 291        B307200, B614400, B921600
 292};
 293#endif
 294
 295static int n_baud_table = ARRAY_SIZE(baud_table);
 296
 297/**
 298 *      tty_termios_baud_rate
 299 *      @termios: termios structure
 300 *
 301 *      Convert termios baud rate data into a speed. This should be called
 302 *      with the termios lock held if this termios is a terminal termios
 303 *      structure. May change the termios data. Device drivers can call this
 304 *      function but should use ->c_[io]speed directly as they are updated.
 305 *
 306 *      Locking: none
 307 */
 308
 309speed_t tty_termios_baud_rate(struct ktermios *termios)
 310{
 311        unsigned int cbaud;
 312
 313        cbaud = termios->c_cflag & CBAUD;
 314
 315#ifdef BOTHER
 316        /* Magic token for arbitrary speed via c_ispeed/c_ospeed */
 317        if (cbaud == BOTHER)
 318                return termios->c_ospeed;
 319#endif
 320        if (cbaud & CBAUDEX) {
 321                cbaud &= ~CBAUDEX;
 322
 323                if (cbaud < 1 || cbaud + 15 > n_baud_table)
 324                        termios->c_cflag &= ~CBAUDEX;
 325                else
 326                        cbaud += 15;
 327        }
 328        return baud_table[cbaud];
 329}
 330EXPORT_SYMBOL(tty_termios_baud_rate);
 331
 332/**
 333 *      tty_termios_input_baud_rate
 334 *      @termios: termios structure
 335 *
 336 *      Convert termios baud rate data into a speed. This should be called
 337 *      with the termios lock held if this termios is a terminal termios
 338 *      structure. May change the termios data. Device drivers can call this
 339 *      function but should use ->c_[io]speed directly as they are updated.
 340 *
 341 *      Locking: none
 342 */
 343
 344speed_t tty_termios_input_baud_rate(struct ktermios *termios)
 345{
 346#ifdef IBSHIFT
 347        unsigned int cbaud = (termios->c_cflag >> IBSHIFT) & CBAUD;
 348
 349        if (cbaud == B0)
 350                return tty_termios_baud_rate(termios);
 351
 352        /* Magic token for arbitrary speed via c_ispeed*/
 353        if (cbaud == BOTHER)
 354                return termios->c_ispeed;
 355
 356        if (cbaud & CBAUDEX) {
 357                cbaud &= ~CBAUDEX;
 358
 359                if (cbaud < 1 || cbaud + 15 > n_baud_table)
 360                        termios->c_cflag &= ~(CBAUDEX << IBSHIFT);
 361                else
 362                        cbaud += 15;
 363        }
 364        return baud_table[cbaud];
 365#else
 366        return tty_termios_baud_rate(termios);
 367#endif
 368}
 369EXPORT_SYMBOL(tty_termios_input_baud_rate);
 370
 371/**
 372 *      tty_termios_encode_baud_rate
 373 *      @termios: ktermios structure holding user requested state
 374 *      @ispeed: input speed
 375 *      @ospeed: output speed
 376 *
 377 *      Encode the speeds set into the passed termios structure. This is
 378 *      used as a library helper for drivers so that they can report back
 379 *      the actual speed selected when it differs from the speed requested
 380 *
 381 *      For maximal back compatibility with legacy SYS5/POSIX *nix behaviour
 382 *      we need to carefully set the bits when the user does not get the
 383 *      desired speed. We allow small margins and preserve as much of possible
 384 *      of the input intent to keep compatibility.
 385 *
 386 *      Locking: Caller should hold termios lock. This is already held
 387 *      when calling this function from the driver termios handler.
 388 *
 389 *      The ifdefs deal with platforms whose owners have yet to update them
 390 *      and will all go away once this is done.
 391 */
 392
 393void tty_termios_encode_baud_rate(struct ktermios *termios,
 394                                  speed_t ibaud, speed_t obaud)
 395{
 396        int i = 0;
 397        int ifound = -1, ofound = -1;
 398        int iclose = ibaud/50, oclose = obaud/50;
 399        int ibinput = 0;
 400
 401        if (obaud == 0)                 /* CD dropped             */
 402                ibaud = 0;              /* Clear ibaud to be sure */
 403
 404        termios->c_ispeed = ibaud;
 405        termios->c_ospeed = obaud;
 406
 407#ifdef BOTHER
 408        /* If the user asked for a precise weird speed give a precise weird
 409           answer. If they asked for a Bfoo speed they may have problems
 410           digesting non-exact replies so fuzz a bit */
 411
 412        if ((termios->c_cflag & CBAUD) == BOTHER)
 413                oclose = 0;
 414        if (((termios->c_cflag >> IBSHIFT) & CBAUD) == BOTHER)
 415                iclose = 0;
 416        if ((termios->c_cflag >> IBSHIFT) & CBAUD)
 417                ibinput = 1;    /* An input speed was specified */
 418#endif
 419        termios->c_cflag &= ~CBAUD;
 420
 421        /*
 422         *      Our goal is to find a close match to the standard baud rate
 423         *      returned. Walk the baud rate table and if we get a very close
 424         *      match then report back the speed as a POSIX Bxxxx value by
 425         *      preference
 426         */
 427
 428        do {
 429                if (obaud - oclose <= baud_table[i] &&
 430                    obaud + oclose >= baud_table[i]) {
 431                        termios->c_cflag |= baud_bits[i];
 432                        ofound = i;
 433                }
 434                if (ibaud - iclose <= baud_table[i] &&
 435                    ibaud + iclose >= baud_table[i]) {
 436                        /* For the case input == output don't set IBAUD bits
 437                           if the user didn't do so */
 438                        if (ofound == i && !ibinput)
 439                                ifound  = i;
 440#ifdef IBSHIFT
 441                        else {
 442                                ifound = i;
 443                                termios->c_cflag |= (baud_bits[i] << IBSHIFT);
 444                        }
 445#endif
 446                }
 447        } while (++i < n_baud_table);
 448
 449        /*
 450         *      If we found no match then use BOTHER if provided or warn
 451         *      the user their platform maintainer needs to wake up if not.
 452         */
 453#ifdef BOTHER
 454        if (ofound == -1)
 455                termios->c_cflag |= BOTHER;
 456        /* Set exact input bits only if the input and output differ or the
 457           user already did */
 458        if (ifound == -1 && (ibaud != obaud || ibinput))
 459                termios->c_cflag |= (BOTHER << IBSHIFT);
 460#else
 461        if (ifound == -1 || ofound == -1)
 462                pr_warn_once("tty: Unable to return correct speed data as your architecture needs updating.\n");
 463#endif
 464}
 465EXPORT_SYMBOL_GPL(tty_termios_encode_baud_rate);
 466
 467/**
 468 *      tty_encode_baud_rate            -       set baud rate of the tty
 469 *      @ibaud: input baud rate
 470 *      @obad: output baud rate
 471 *
 472 *      Update the current termios data for the tty with the new speed
 473 *      settings. The caller must hold the termios_rwsem for the tty in
 474 *      question.
 475 */
 476
 477void tty_encode_baud_rate(struct tty_struct *tty, speed_t ibaud, speed_t obaud)
 478{
 479        tty_termios_encode_baud_rate(&tty->termios, ibaud, obaud);
 480}
 481EXPORT_SYMBOL_GPL(tty_encode_baud_rate);
 482
 483/**
 484 *      tty_termios_copy_hw     -       copy hardware settings
 485 *      @new: New termios
 486 *      @old: Old termios
 487 *
 488 *      Propagate the hardware specific terminal setting bits from
 489 *      the old termios structure to the new one. This is used in cases
 490 *      where the hardware does not support reconfiguration or as a helper
 491 *      in some cases where only minimal reconfiguration is supported
 492 */
 493
 494void tty_termios_copy_hw(struct ktermios *new, struct ktermios *old)
 495{
 496        /* The bits a dumb device handles in software. Smart devices need
 497           to always provide a set_termios method */
 498        new->c_cflag &= HUPCL | CREAD | CLOCAL;
 499        new->c_cflag |= old->c_cflag & ~(HUPCL | CREAD | CLOCAL);
 500        new->c_ispeed = old->c_ispeed;
 501        new->c_ospeed = old->c_ospeed;
 502}
 503EXPORT_SYMBOL(tty_termios_copy_hw);
 504
 505/**
 506 *      tty_termios_hw_change   -       check for setting change
 507 *      @a: termios
 508 *      @b: termios to compare
 509 *
 510 *      Check if any of the bits that affect a dumb device have changed
 511 *      between the two termios structures, or a speed change is needed.
 512 */
 513
 514int tty_termios_hw_change(struct ktermios *a, struct ktermios *b)
 515{
 516        if (a->c_ispeed != b->c_ispeed || a->c_ospeed != b->c_ospeed)
 517                return 1;
 518        if ((a->c_cflag ^ b->c_cflag) & ~(HUPCL | CREAD | CLOCAL))
 519                return 1;
 520        return 0;
 521}
 522EXPORT_SYMBOL(tty_termios_hw_change);
 523
 524/**
 525 *      tty_set_termios         -       update termios values
 526 *      @tty: tty to update
 527 *      @new_termios: desired new value
 528 *
 529 *      Perform updates to the termios values set on this terminal.
 530 *      A master pty's termios should never be set.
 531 *
 532 *      Locking: termios_rwsem
 533 */
 534
 535int tty_set_termios(struct tty_struct *tty, struct ktermios *new_termios)
 536{
 537        struct ktermios old_termios;
 538        struct tty_ldisc *ld;
 539
 540        WARN_ON(tty->driver->type == TTY_DRIVER_TYPE_PTY &&
 541                tty->driver->subtype == PTY_TYPE_MASTER);
 542        /*
 543         *      Perform the actual termios internal changes under lock.
 544         */
 545
 546
 547        /* FIXME: we need to decide on some locking/ordering semantics
 548           for the set_termios notification eventually */
 549        down_write(&tty->termios_rwsem);
 550        old_termios = tty->termios;
 551        tty->termios = *new_termios;
 552        unset_locked_termios(tty, &old_termios);
 553
 554        if (tty->ops->set_termios)
 555                tty->ops->set_termios(tty, &old_termios);
 556        else
 557                tty_termios_copy_hw(&tty->termios, &old_termios);
 558
 559        ld = tty_ldisc_ref(tty);
 560        if (ld != NULL) {
 561                if (ld->ops->set_termios)
 562                        ld->ops->set_termios(tty, &old_termios);
 563                tty_ldisc_deref(ld);
 564        }
 565        up_write(&tty->termios_rwsem);
 566        return 0;
 567}
 568EXPORT_SYMBOL_GPL(tty_set_termios);
 569
 570/**
 571 *      set_termios             -       set termios values for a tty
 572 *      @tty: terminal device
 573 *      @arg: user data
 574 *      @opt: option information
 575 *
 576 *      Helper function to prepare termios data and run necessary other
 577 *      functions before using tty_set_termios to do the actual changes.
 578 *
 579 *      Locking:
 580 *              Called functions take ldisc and termios_rwsem locks
 581 */
 582
 583static int set_termios(struct tty_struct *tty, void __user *arg, int opt)
 584{
 585        struct ktermios tmp_termios;
 586        struct tty_ldisc *ld;
 587        int retval = tty_check_change(tty);
 588
 589        if (retval)
 590                return retval;
 591
 592        down_read(&tty->termios_rwsem);
 593        tmp_termios = tty->termios;
 594        up_read(&tty->termios_rwsem);
 595
 596        if (opt & TERMIOS_TERMIO) {
 597                if (user_termio_to_kernel_termios(&tmp_termios,
 598                                                (struct termio __user *)arg))
 599                        return -EFAULT;
 600#ifdef TCGETS2
 601        } else if (opt & TERMIOS_OLD) {
 602                if (user_termios_to_kernel_termios_1(&tmp_termios,
 603                                                (struct termios __user *)arg))
 604                        return -EFAULT;
 605        } else {
 606                if (user_termios_to_kernel_termios(&tmp_termios,
 607                                                (struct termios2 __user *)arg))
 608                        return -EFAULT;
 609        }
 610#else
 611        } else if (user_termios_to_kernel_termios(&tmp_termios,
 612                                        (struct termios __user *)arg))
 613                return -EFAULT;
 614#endif
 615
 616        /* If old style Bfoo values are used then load c_ispeed/c_ospeed
 617         * with the real speed so its unconditionally usable */
 618        tmp_termios.c_ispeed = tty_termios_input_baud_rate(&tmp_termios);
 619        tmp_termios.c_ospeed = tty_termios_baud_rate(&tmp_termios);
 620
 621        ld = tty_ldisc_ref(tty);
 622
 623        if (ld != NULL) {
 624                if ((opt & TERMIOS_FLUSH) && ld->ops->flush_buffer)
 625                        ld->ops->flush_buffer(tty);
 626                tty_ldisc_deref(ld);
 627        }
 628
 629        if (opt & TERMIOS_WAIT) {
 630                tty_wait_until_sent(tty, 0);
 631                if (signal_pending(current))
 632                        return -ERESTARTSYS;
 633        }
 634
 635        tty_set_termios(tty, &tmp_termios);
 636
 637        /* FIXME: Arguably if tmp_termios == tty->termios AND the
 638           actual requested termios was not tmp_termios then we may
 639           want to return an error as no user requested change has
 640           succeeded */
 641        return 0;
 642}
 643
 644static void copy_termios(struct tty_struct *tty, struct ktermios *kterm)
 645{
 646        down_read(&tty->termios_rwsem);
 647        *kterm = tty->termios;
 648        up_read(&tty->termios_rwsem);
 649}
 650
 651static void copy_termios_locked(struct tty_struct *tty, struct ktermios *kterm)
 652{
 653        down_read(&tty->termios_rwsem);
 654        *kterm = tty->termios_locked;
 655        up_read(&tty->termios_rwsem);
 656}
 657
 658static int get_termio(struct tty_struct *tty, struct termio __user *termio)
 659{
 660        struct ktermios kterm;
 661        copy_termios(tty, &kterm);
 662        if (kernel_termios_to_user_termio(termio, &kterm))
 663                return -EFAULT;
 664        return 0;
 665}
 666
 667
 668#ifdef TCGETX
 669
 670/**
 671 *      set_termiox     -       set termiox fields if possible
 672 *      @tty: terminal
 673 *      @arg: termiox structure from user
 674 *      @opt: option flags for ioctl type
 675 *
 676 *      Implement the device calling points for the SYS5 termiox ioctl
 677 *      interface in Linux
 678 */
 679
 680static int set_termiox(struct tty_struct *tty, void __user *arg, int opt)
 681{
 682        struct termiox tnew;
 683        struct tty_ldisc *ld;
 684
 685        if (tty->termiox == NULL)
 686                return -EINVAL;
 687        if (copy_from_user(&tnew, arg, sizeof(struct termiox)))
 688                return -EFAULT;
 689
 690        ld = tty_ldisc_ref(tty);
 691        if (ld != NULL) {
 692                if ((opt & TERMIOS_FLUSH) && ld->ops->flush_buffer)
 693                        ld->ops->flush_buffer(tty);
 694                tty_ldisc_deref(ld);
 695        }
 696        if (opt & TERMIOS_WAIT) {
 697                tty_wait_until_sent(tty, 0);
 698                if (signal_pending(current))
 699                        return -ERESTARTSYS;
 700        }
 701
 702        down_write(&tty->termios_rwsem);
 703        if (tty->ops->set_termiox)
 704                tty->ops->set_termiox(tty, &tnew);
 705        up_write(&tty->termios_rwsem);
 706        return 0;
 707}
 708
 709#endif
 710
 711
 712#ifdef TIOCGETP
 713/*
 714 * These are deprecated, but there is limited support..
 715 *
 716 * The "sg_flags" translation is a joke..
 717 */
 718static int get_sgflags(struct tty_struct *tty)
 719{
 720        int flags = 0;
 721
 722        if (!L_ICANON(tty)) {
 723                if (L_ISIG(tty))
 724                        flags |= 0x02;          /* cbreak */
 725                else
 726                        flags |= 0x20;          /* raw */
 727        }
 728        if (L_ECHO(tty))
 729                flags |= 0x08;                  /* echo */
 730        if (O_OPOST(tty))
 731                if (O_ONLCR(tty))
 732                        flags |= 0x10;          /* crmod */
 733        return flags;
 734}
 735
 736static int get_sgttyb(struct tty_struct *tty, struct sgttyb __user *sgttyb)
 737{
 738        struct sgttyb tmp;
 739
 740        down_read(&tty->termios_rwsem);
 741        tmp.sg_ispeed = tty->termios.c_ispeed;
 742        tmp.sg_ospeed = tty->termios.c_ospeed;
 743        tmp.sg_erase = tty->termios.c_cc[VERASE];
 744        tmp.sg_kill = tty->termios.c_cc[VKILL];
 745        tmp.sg_flags = get_sgflags(tty);
 746        up_read(&tty->termios_rwsem);
 747
 748        return copy_to_user(sgttyb, &tmp, sizeof(tmp)) ? -EFAULT : 0;
 749}
 750
 751static void set_sgflags(struct ktermios *termios, int flags)
 752{
 753        termios->c_iflag = ICRNL | IXON;
 754        termios->c_oflag = 0;
 755        termios->c_lflag = ISIG | ICANON;
 756        if (flags & 0x02) {     /* cbreak */
 757                termios->c_iflag = 0;
 758                termios->c_lflag &= ~ICANON;
 759        }
 760        if (flags & 0x08) {             /* echo */
 761                termios->c_lflag |= ECHO | ECHOE | ECHOK |
 762                                    ECHOCTL | ECHOKE | IEXTEN;
 763        }
 764        if (flags & 0x10) {             /* crmod */
 765                termios->c_oflag |= OPOST | ONLCR;
 766        }
 767        if (flags & 0x20) {     /* raw */
 768                termios->c_iflag = 0;
 769                termios->c_lflag &= ~(ISIG | ICANON);
 770        }
 771        if (!(termios->c_lflag & ICANON)) {
 772                termios->c_cc[VMIN] = 1;
 773                termios->c_cc[VTIME] = 0;
 774        }
 775}
 776
 777/**
 778 *      set_sgttyb              -       set legacy terminal values
 779 *      @tty: tty structure
 780 *      @sgttyb: pointer to old style terminal structure
 781 *
 782 *      Updates a terminal from the legacy BSD style terminal information
 783 *      structure.
 784 *
 785 *      Locking: termios_rwsem
 786 */
 787
 788static int set_sgttyb(struct tty_struct *tty, struct sgttyb __user *sgttyb)
 789{
 790        int retval;
 791        struct sgttyb tmp;
 792        struct ktermios termios;
 793
 794        retval = tty_check_change(tty);
 795        if (retval)
 796                return retval;
 797
 798        if (copy_from_user(&tmp, sgttyb, sizeof(tmp)))
 799                return -EFAULT;
 800
 801        down_write(&tty->termios_rwsem);
 802        termios = tty->termios;
 803        termios.c_cc[VERASE] = tmp.sg_erase;
 804        termios.c_cc[VKILL] = tmp.sg_kill;
 805        set_sgflags(&termios, tmp.sg_flags);
 806        /* Try and encode into Bfoo format */
 807#ifdef BOTHER
 808        tty_termios_encode_baud_rate(&termios, termios.c_ispeed,
 809                                                termios.c_ospeed);
 810#endif
 811        up_write(&tty->termios_rwsem);
 812        tty_set_termios(tty, &termios);
 813        return 0;
 814}
 815#endif
 816
 817#ifdef TIOCGETC
 818static int get_tchars(struct tty_struct *tty, struct tchars __user *tchars)
 819{
 820        struct tchars tmp;
 821
 822        down_read(&tty->termios_rwsem);
 823        tmp.t_intrc = tty->termios.c_cc[VINTR];
 824        tmp.t_quitc = tty->termios.c_cc[VQUIT];
 825        tmp.t_startc = tty->termios.c_cc[VSTART];
 826        tmp.t_stopc = tty->termios.c_cc[VSTOP];
 827        tmp.t_eofc = tty->termios.c_cc[VEOF];
 828        tmp.t_brkc = tty->termios.c_cc[VEOL2];  /* what is brkc anyway? */
 829        up_read(&tty->termios_rwsem);
 830        return copy_to_user(tchars, &tmp, sizeof(tmp)) ? -EFAULT : 0;
 831}
 832
 833static int set_tchars(struct tty_struct *tty, struct tchars __user *tchars)
 834{
 835        struct tchars tmp;
 836
 837        if (copy_from_user(&tmp, tchars, sizeof(tmp)))
 838                return -EFAULT;
 839        down_write(&tty->termios_rwsem);
 840        tty->termios.c_cc[VINTR] = tmp.t_intrc;
 841        tty->termios.c_cc[VQUIT] = tmp.t_quitc;
 842        tty->termios.c_cc[VSTART] = tmp.t_startc;
 843        tty->termios.c_cc[VSTOP] = tmp.t_stopc;
 844        tty->termios.c_cc[VEOF] = tmp.t_eofc;
 845        tty->termios.c_cc[VEOL2] = tmp.t_brkc;  /* what is brkc anyway? */
 846        up_write(&tty->termios_rwsem);
 847        return 0;
 848}
 849#endif
 850
 851#ifdef TIOCGLTC
 852static int get_ltchars(struct tty_struct *tty, struct ltchars __user *ltchars)
 853{
 854        struct ltchars tmp;
 855
 856        down_read(&tty->termios_rwsem);
 857        tmp.t_suspc = tty->termios.c_cc[VSUSP];
 858        /* what is dsuspc anyway? */
 859        tmp.t_dsuspc = tty->termios.c_cc[VSUSP];
 860        tmp.t_rprntc = tty->termios.c_cc[VREPRINT];
 861        /* what is flushc anyway? */
 862        tmp.t_flushc = tty->termios.c_cc[VEOL2];
 863        tmp.t_werasc = tty->termios.c_cc[VWERASE];
 864        tmp.t_lnextc = tty->termios.c_cc[VLNEXT];
 865        up_read(&tty->termios_rwsem);
 866        return copy_to_user(ltchars, &tmp, sizeof(tmp)) ? -EFAULT : 0;
 867}
 868
 869static int set_ltchars(struct tty_struct *tty, struct ltchars __user *ltchars)
 870{
 871        struct ltchars tmp;
 872
 873        if (copy_from_user(&tmp, ltchars, sizeof(tmp)))
 874                return -EFAULT;
 875
 876        down_write(&tty->termios_rwsem);
 877        tty->termios.c_cc[VSUSP] = tmp.t_suspc;
 878        /* what is dsuspc anyway? */
 879        tty->termios.c_cc[VEOL2] = tmp.t_dsuspc;
 880        tty->termios.c_cc[VREPRINT] = tmp.t_rprntc;
 881        /* what is flushc anyway? */
 882        tty->termios.c_cc[VEOL2] = tmp.t_flushc;
 883        tty->termios.c_cc[VWERASE] = tmp.t_werasc;
 884        tty->termios.c_cc[VLNEXT] = tmp.t_lnextc;
 885        up_write(&tty->termios_rwsem);
 886        return 0;
 887}
 888#endif
 889
 890/**
 891 *      tty_change_softcar      -       carrier change ioctl helper
 892 *      @tty: tty to update
 893 *      @arg: enable/disable CLOCAL
 894 *
 895 *      Perform a change to the CLOCAL state and call into the driver
 896 *      layer to make it visible. All done with the termios rwsem
 897 */
 898
 899static int tty_change_softcar(struct tty_struct *tty, int arg)
 900{
 901        int ret = 0;
 902        int bit = arg ? CLOCAL : 0;
 903        struct ktermios old;
 904
 905        down_write(&tty->termios_rwsem);
 906        old = tty->termios;
 907        tty->termios.c_cflag &= ~CLOCAL;
 908        tty->termios.c_cflag |= bit;
 909        if (tty->ops->set_termios)
 910                tty->ops->set_termios(tty, &old);
 911        if (C_CLOCAL(tty) != bit)
 912                ret = -EINVAL;
 913        up_write(&tty->termios_rwsem);
 914        return ret;
 915}
 916
 917/**
 918 *      tty_mode_ioctl          -       mode related ioctls
 919 *      @tty: tty for the ioctl
 920 *      @file: file pointer for the tty
 921 *      @cmd: command
 922 *      @arg: ioctl argument
 923 *
 924 *      Perform non line discipline specific mode control ioctls. This
 925 *      is designed to be called by line disciplines to ensure they provide
 926 *      consistent mode setting.
 927 */
 928
 929int tty_mode_ioctl(struct tty_struct *tty, struct file *file,
 930                        unsigned int cmd, unsigned long arg)
 931{
 932        struct tty_struct *real_tty;
 933        void __user *p = (void __user *)arg;
 934        int ret = 0;
 935        struct ktermios kterm;
 936
 937        BUG_ON(file == NULL);
 938
 939        if (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
 940            tty->driver->subtype == PTY_TYPE_MASTER)
 941                real_tty = tty->link;
 942        else
 943                real_tty = tty;
 944
 945        switch (cmd) {
 946#ifdef TIOCGETP
 947        case TIOCGETP:
 948                return get_sgttyb(real_tty, (struct sgttyb __user *) arg);
 949        case TIOCSETP:
 950        case TIOCSETN:
 951                return set_sgttyb(real_tty, (struct sgttyb __user *) arg);
 952#endif
 953#ifdef TIOCGETC
 954        case TIOCGETC:
 955                return get_tchars(real_tty, p);
 956        case TIOCSETC:
 957                return set_tchars(real_tty, p);
 958#endif
 959#ifdef TIOCGLTC
 960        case TIOCGLTC:
 961                return get_ltchars(real_tty, p);
 962        case TIOCSLTC:
 963                return set_ltchars(real_tty, p);
 964#endif
 965        case TCSETSF:
 966                return set_termios(real_tty, p,  TERMIOS_FLUSH | TERMIOS_WAIT | TERMIOS_OLD);
 967        case TCSETSW:
 968                return set_termios(real_tty, p, TERMIOS_WAIT | TERMIOS_OLD);
 969        case TCSETS:
 970                return set_termios(real_tty, p, TERMIOS_OLD);
 971#ifndef TCGETS2
 972        case TCGETS:
 973                copy_termios(real_tty, &kterm);
 974                if (kernel_termios_to_user_termios((struct termios __user *)arg, &kterm))
 975                        ret = -EFAULT;
 976                return ret;
 977#else
 978        case TCGETS:
 979                copy_termios(real_tty, &kterm);
 980                if (kernel_termios_to_user_termios_1((struct termios __user *)arg, &kterm))
 981                        ret = -EFAULT;
 982                return ret;
 983        case TCGETS2:
 984                copy_termios(real_tty, &kterm);
 985                if (kernel_termios_to_user_termios((struct termios2 __user *)arg, &kterm))
 986                        ret = -EFAULT;
 987                return ret;
 988        case TCSETSF2:
 989                return set_termios(real_tty, p,  TERMIOS_FLUSH | TERMIOS_WAIT);
 990        case TCSETSW2:
 991                return set_termios(real_tty, p, TERMIOS_WAIT);
 992        case TCSETS2:
 993                return set_termios(real_tty, p, 0);
 994#endif
 995        case TCGETA:
 996                return get_termio(real_tty, p);
 997        case TCSETAF:
 998                return set_termios(real_tty, p, TERMIOS_FLUSH | TERMIOS_WAIT | TERMIOS_TERMIO);
 999        case TCSETAW:
1000                return set_termios(real_tty, p, TERMIOS_WAIT | TERMIOS_TERMIO);
1001        case TCSETA:
1002                return set_termios(real_tty, p, TERMIOS_TERMIO);
1003#ifndef TCGETS2
1004        case TIOCGLCKTRMIOS:
1005                copy_termios_locked(real_tty, &kterm);
1006                if (kernel_termios_to_user_termios((struct termios __user *)arg, &kterm))
1007                        ret = -EFAULT;
1008                return ret;
1009        case TIOCSLCKTRMIOS:
1010                if (!capable(CAP_SYS_ADMIN))
1011                        return -EPERM;
1012                copy_termios_locked(real_tty, &kterm);
1013                if (user_termios_to_kernel_termios(&kterm,
1014                                               (struct termios __user *) arg))
1015                        return -EFAULT;
1016                down_write(&real_tty->termios_rwsem);
1017                real_tty->termios_locked = kterm;
1018                up_write(&real_tty->termios_rwsem);
1019                return 0;
1020#else
1021        case TIOCGLCKTRMIOS:
1022                copy_termios_locked(real_tty, &kterm);
1023                if (kernel_termios_to_user_termios_1((struct termios __user *)arg, &kterm))
1024                        ret = -EFAULT;
1025                return ret;
1026        case TIOCSLCKTRMIOS:
1027                if (!capable(CAP_SYS_ADMIN))
1028                        return -EPERM;
1029                copy_termios_locked(real_tty, &kterm);
1030                if (user_termios_to_kernel_termios_1(&kterm,
1031                                               (struct termios __user *) arg))
1032                        return -EFAULT;
1033                down_write(&real_tty->termios_rwsem);
1034                real_tty->termios_locked = kterm;
1035                up_write(&real_tty->termios_rwsem);
1036                return ret;
1037#endif
1038#ifdef TCGETX
1039        case TCGETX: {
1040                struct termiox ktermx;
1041                if (real_tty->termiox == NULL)
1042                        return -EINVAL;
1043                down_read(&real_tty->termios_rwsem);
1044                memcpy(&ktermx, real_tty->termiox, sizeof(struct termiox));
1045                up_read(&real_tty->termios_rwsem);
1046                if (copy_to_user(p, &ktermx, sizeof(struct termiox)))
1047                        ret = -EFAULT;
1048                return ret;
1049        }
1050        case TCSETX:
1051                return set_termiox(real_tty, p, 0);
1052        case TCSETXW:
1053                return set_termiox(real_tty, p, TERMIOS_WAIT);
1054        case TCSETXF:
1055                return set_termiox(real_tty, p, TERMIOS_FLUSH);
1056#endif          
1057        case TIOCGSOFTCAR:
1058                copy_termios(real_tty, &kterm);
1059                ret = put_user((kterm.c_cflag & CLOCAL) ? 1 : 0,
1060                                                (int __user *)arg);
1061                return ret;
1062        case TIOCSSOFTCAR:
1063                if (get_user(arg, (unsigned int __user *) arg))
1064                        return -EFAULT;
1065                return tty_change_softcar(real_tty, arg);
1066        default:
1067                return -ENOIOCTLCMD;
1068        }
1069}
1070EXPORT_SYMBOL_GPL(tty_mode_ioctl);
1071
1072
1073/* Caller guarantees ldisc reference is held */
1074static int __tty_perform_flush(struct tty_struct *tty, unsigned long arg)
1075{
1076        struct tty_ldisc *ld = tty->ldisc;
1077
1078        switch (arg) {
1079        case TCIFLUSH:
1080                if (ld && ld->ops->flush_buffer) {
1081                        ld->ops->flush_buffer(tty);
1082                        tty_unthrottle(tty);
1083                }
1084                break;
1085        case TCIOFLUSH:
1086                if (ld && ld->ops->flush_buffer) {
1087                        ld->ops->flush_buffer(tty);
1088                        tty_unthrottle(tty);
1089                }
1090                /* fall through */
1091        case TCOFLUSH:
1092                tty_driver_flush_buffer(tty);
1093                break;
1094        default:
1095                return -EINVAL;
1096        }
1097        return 0;
1098}
1099
1100int tty_perform_flush(struct tty_struct *tty, unsigned long arg)
1101{
1102        struct tty_ldisc *ld;
1103        int retval = tty_check_change(tty);
1104        if (retval)
1105                return retval;
1106
1107        ld = tty_ldisc_ref_wait(tty);
1108        retval = __tty_perform_flush(tty, arg);
1109        if (ld)
1110                tty_ldisc_deref(ld);
1111        return retval;
1112}
1113EXPORT_SYMBOL_GPL(tty_perform_flush);
1114
1115int n_tty_ioctl_helper(struct tty_struct *tty, struct file *file,
1116                       unsigned int cmd, unsigned long arg)
1117{
1118        int retval;
1119
1120        switch (cmd) {
1121        case TCXONC:
1122                retval = tty_check_change(tty);
1123                if (retval)
1124                        return retval;
1125                switch (arg) {
1126                case TCOOFF:
1127                        spin_lock_irq(&tty->flow_lock);
1128                        if (!tty->flow_stopped) {
1129                                tty->flow_stopped = 1;
1130                                __stop_tty(tty);
1131                        }
1132                        spin_unlock_irq(&tty->flow_lock);
1133                        break;
1134                case TCOON:
1135                        spin_lock_irq(&tty->flow_lock);
1136                        if (tty->flow_stopped) {
1137                                tty->flow_stopped = 0;
1138                                __start_tty(tty);
1139                        }
1140                        spin_unlock_irq(&tty->flow_lock);
1141                        break;
1142                case TCIOFF:
1143                        if (STOP_CHAR(tty) != __DISABLED_CHAR)
1144                                retval = tty_send_xchar(tty, STOP_CHAR(tty));
1145                        break;
1146                case TCION:
1147                        if (START_CHAR(tty) != __DISABLED_CHAR)
1148                                retval = tty_send_xchar(tty, START_CHAR(tty));
1149                        break;
1150                default:
1151                        return -EINVAL;
1152                }
1153                return retval;
1154        case TCFLSH:
1155                retval = tty_check_change(tty);
1156                if (retval)
1157                        return retval;
1158                return __tty_perform_flush(tty, arg);
1159        default:
1160                /* Try the mode commands */
1161                return tty_mode_ioctl(tty, file, cmd, arg);
1162        }
1163}
1164EXPORT_SYMBOL(n_tty_ioctl_helper);
1165
1166#ifdef CONFIG_COMPAT
1167long n_tty_compat_ioctl_helper(struct tty_struct *tty, struct file *file,
1168                                        unsigned int cmd, unsigned long arg)
1169{
1170        switch (cmd) {
1171        case TIOCGLCKTRMIOS:
1172        case TIOCSLCKTRMIOS:
1173                return tty_mode_ioctl(tty, file, cmd, (unsigned long) compat_ptr(arg));
1174        default:
1175                return -ENOIOCTLCMD;
1176        }
1177}
1178EXPORT_SYMBOL(n_tty_compat_ioctl_helper);
1179#endif
1180
1181