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