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