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