Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.23-rc6 844 lines 22 kB view raw
1/* 2 * linux/drivers/char/tty_ioctl.c 3 * 4 * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds 5 * 6 * Modified by Fred N. van Kempen, 01/29/93, to add line disciplines 7 * which can be dynamically activated and de-activated by the line 8 * discipline handling modules (like SLIP). 9 */ 10 11#include <linux/types.h> 12#include <linux/termios.h> 13#include <linux/errno.h> 14#include <linux/sched.h> 15#include <linux/kernel.h> 16#include <linux/major.h> 17#include <linux/tty.h> 18#include <linux/fcntl.h> 19#include <linux/string.h> 20#include <linux/mm.h> 21#include <linux/module.h> 22#include <linux/bitops.h> 23#include <linux/mutex.h> 24 25#include <asm/io.h> 26#include <asm/uaccess.h> 27#include <asm/system.h> 28 29#undef TTY_DEBUG_WAIT_UNTIL_SENT 30 31#undef DEBUG 32 33/* 34 * Internal flag options for termios setting behavior 35 */ 36#define TERMIOS_FLUSH 1 37#define TERMIOS_WAIT 2 38#define TERMIOS_TERMIO 4 39#define TERMIOS_OLD 8 40 41 42/** 43 * tty_wait_until_sent - wait for I/O to finish 44 * @tty: tty we are waiting for 45 * @timeout: how long we will wait 46 * 47 * Wait for characters pending in a tty driver to hit the wire, or 48 * for a timeout to occur (eg due to flow control) 49 * 50 * Locking: none 51 */ 52 53void tty_wait_until_sent(struct tty_struct * tty, long timeout) 54{ 55#ifdef TTY_DEBUG_WAIT_UNTIL_SENT 56 char buf[64]; 57 58 printk(KERN_DEBUG "%s wait until sent...\n", tty_name(tty, buf)); 59#endif 60 if (!tty->driver->chars_in_buffer) 61 return; 62 if (!timeout) 63 timeout = MAX_SCHEDULE_TIMEOUT; 64 if (wait_event_interruptible_timeout(tty->write_wait, 65 !tty->driver->chars_in_buffer(tty), timeout)) 66 return; 67 if (tty->driver->wait_until_sent) 68 tty->driver->wait_until_sent(tty, timeout); 69} 70 71EXPORT_SYMBOL(tty_wait_until_sent); 72 73static void unset_locked_termios(struct ktermios *termios, 74 struct ktermios *old, 75 struct ktermios *locked) 76{ 77 int i; 78 79#define NOSET_MASK(x,y,z) (x = ((x) & ~(z)) | ((y) & (z))) 80 81 if (!locked) { 82 printk(KERN_WARNING "Warning?!? termios_locked is NULL.\n"); 83 return; 84 } 85 86 NOSET_MASK(termios->c_iflag, old->c_iflag, locked->c_iflag); 87 NOSET_MASK(termios->c_oflag, old->c_oflag, locked->c_oflag); 88 NOSET_MASK(termios->c_cflag, old->c_cflag, locked->c_cflag); 89 NOSET_MASK(termios->c_lflag, old->c_lflag, locked->c_lflag); 90 termios->c_line = locked->c_line ? old->c_line : termios->c_line; 91 for (i=0; i < NCCS; i++) 92 termios->c_cc[i] = locked->c_cc[i] ? 93 old->c_cc[i] : termios->c_cc[i]; 94 /* FIXME: What should we do for i/ospeed */ 95} 96 97/* 98 * Routine which returns the baud rate of the tty 99 * 100 * Note that the baud_table needs to be kept in sync with the 101 * include/asm/termbits.h file. 102 */ 103static const speed_t baud_table[] = { 104 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800, 105 9600, 19200, 38400, 57600, 115200, 230400, 460800, 106#ifdef __sparc__ 107 76800, 153600, 307200, 614400, 921600 108#else 109 500000, 576000, 921600, 1000000, 1152000, 1500000, 2000000, 110 2500000, 3000000, 3500000, 4000000 111#endif 112}; 113 114#ifndef __sparc__ 115static const tcflag_t baud_bits[] = { 116 B0, B50, B75, B110, B134, B150, B200, B300, B600, 117 B1200, B1800, B2400, B4800, B9600, B19200, B38400, 118 B57600, B115200, B230400, B460800, B500000, B576000, 119 B921600, B1000000, B1152000, B1500000, B2000000, B2500000, 120 B3000000, B3500000, B4000000 121}; 122#else 123static const tcflag_t baud_bits[] = { 124 B0, B50, B75, B110, B134, B150, B200, B300, B600, 125 B1200, B1800, B2400, B4800, B9600, B19200, B38400, 126 B57600, B115200, B230400, B460800, B76800, B153600, 127 B307200, B614400, B921600 128}; 129#endif 130 131static int n_baud_table = ARRAY_SIZE(baud_table); 132 133/** 134 * tty_termios_baud_rate 135 * @termios: termios structure 136 * 137 * Convert termios baud rate data into a speed. This should be called 138 * with the termios lock held if this termios is a terminal termios 139 * structure. May change the termios data. Device drivers can call this 140 * function but should use ->c_[io]speed directly as they are updated. 141 * 142 * Locking: none 143 */ 144 145speed_t tty_termios_baud_rate(struct ktermios *termios) 146{ 147 unsigned int cbaud; 148 149 cbaud = termios->c_cflag & CBAUD; 150 151#ifdef BOTHER 152 /* Magic token for arbitary speed via c_ispeed/c_ospeed */ 153 if (cbaud == BOTHER) 154 return termios->c_ospeed; 155#endif 156 if (cbaud & CBAUDEX) { 157 cbaud &= ~CBAUDEX; 158 159 if (cbaud < 1 || cbaud + 15 > n_baud_table) 160 termios->c_cflag &= ~CBAUDEX; 161 else 162 cbaud += 15; 163 } 164 return baud_table[cbaud]; 165} 166 167EXPORT_SYMBOL(tty_termios_baud_rate); 168 169/** 170 * tty_termios_input_baud_rate 171 * @termios: termios structure 172 * 173 * Convert termios baud rate data into a speed. This should be called 174 * with the termios lock held if this termios is a terminal termios 175 * structure. May change the termios data. Device drivers can call this 176 * function but should use ->c_[io]speed directly as they are updated. 177 * 178 * Locking: none 179 */ 180 181speed_t tty_termios_input_baud_rate(struct ktermios *termios) 182{ 183#ifdef IBSHIFT 184 unsigned int cbaud = (termios->c_cflag >> IBSHIFT) & CBAUD; 185 186 if (cbaud == B0) 187 return tty_termios_baud_rate(termios); 188 189 /* Magic token for arbitary speed via c_ispeed*/ 190 if (cbaud == BOTHER) 191 return termios->c_ispeed; 192 193 if (cbaud & CBAUDEX) { 194 cbaud &= ~CBAUDEX; 195 196 if (cbaud < 1 || cbaud + 15 > n_baud_table) 197 termios->c_cflag &= ~(CBAUDEX << IBSHIFT); 198 else 199 cbaud += 15; 200 } 201 return baud_table[cbaud]; 202#else 203 return tty_termios_baud_rate(termios); 204#endif 205} 206 207EXPORT_SYMBOL(tty_termios_input_baud_rate); 208 209#ifdef BOTHER 210 211/** 212 * tty_termios_encode_baud_rate 213 * @termios: ktermios structure holding user requested state 214 * @ispeed: input speed 215 * @ospeed: output speed 216 * 217 * Encode the speeds set into the passed termios structure. This is 218 * used as a library helper for drivers os that they can report back 219 * the actual speed selected when it differs from the speed requested 220 * 221 * For maximal back compatibility with legacy SYS5/POSIX *nix behaviour 222 * we need to carefully set the bits when the user does not get the 223 * desired speed. We allow small margins and preserve as much of possible 224 * of the input intent to keep compatiblity. 225 * 226 * Locking: Caller should hold termios lock. This is already held 227 * when calling this function from the driver termios handler. 228 */ 229 230void tty_termios_encode_baud_rate(struct ktermios *termios, speed_t ibaud, speed_t obaud) 231{ 232 int i = 0; 233 int ifound = -1, ofound = -1; 234 int iclose = ibaud/50, oclose = obaud/50; 235 int ibinput = 0; 236 237 termios->c_ispeed = ibaud; 238 termios->c_ospeed = obaud; 239 240 /* If the user asked for a precise weird speed give a precise weird 241 answer. If they asked for a Bfoo speed they many have problems 242 digesting non-exact replies so fuzz a bit */ 243 244 if ((termios->c_cflag & CBAUD) == BOTHER) 245 oclose = 0; 246 if (((termios->c_cflag >> IBSHIFT) & CBAUD) == BOTHER) 247 iclose = 0; 248 if ((termios->c_cflag >> IBSHIFT) & CBAUD) 249 ibinput = 1; /* An input speed was specified */ 250 251 termios->c_cflag &= ~CBAUD; 252 253 do { 254 if (obaud - oclose >= baud_table[i] && obaud + oclose <= baud_table[i]) { 255 termios->c_cflag |= baud_bits[i]; 256 ofound = i; 257 } 258 if (ibaud - iclose >= baud_table[i] && ibaud + iclose <= baud_table[i]) { 259 /* For the case input == output don't set IBAUD bits if the user didn't do so */ 260 if (ofound != i || ibinput) 261 termios->c_cflag |= (baud_bits[i] << IBSHIFT); 262 ifound = i; 263 } 264 } while (++i < n_baud_table); 265 if (ofound == -1) 266 termios->c_cflag |= BOTHER; 267 /* Set exact input bits only if the input and output differ or the 268 user already did */ 269 if (ifound == -1 && (ibaud != obaud || ibinput)) 270 termios->c_cflag |= (BOTHER << IBSHIFT); 271} 272 273EXPORT_SYMBOL_GPL(tty_termios_encode_baud_rate); 274 275#endif 276 277/** 278 * tty_get_baud_rate - get tty bit rates 279 * @tty: tty to query 280 * 281 * Returns the baud rate as an integer for this terminal. The 282 * termios lock must be held by the caller and the terminal bit 283 * flags may be updated. 284 * 285 * Locking: none 286 */ 287 288speed_t tty_get_baud_rate(struct tty_struct *tty) 289{ 290 speed_t baud = tty_termios_baud_rate(tty->termios); 291 292 if (baud == 38400 && tty->alt_speed) { 293 if (!tty->warned) { 294 printk(KERN_WARNING "Use of setserial/setrocket to " 295 "set SPD_* flags is deprecated\n"); 296 tty->warned = 1; 297 } 298 baud = tty->alt_speed; 299 } 300 301 return baud; 302} 303 304EXPORT_SYMBOL(tty_get_baud_rate); 305 306/** 307 * change_termios - update termios values 308 * @tty: tty to update 309 * @new_termios: desired new value 310 * 311 * Perform updates to the termios values set on this terminal. There 312 * is a bit of layering violation here with n_tty in terms of the 313 * internal knowledge of this function. 314 * 315 * Locking: termios_sem 316 */ 317 318static void change_termios(struct tty_struct * tty, struct ktermios * new_termios) 319{ 320 int canon_change; 321 struct ktermios old_termios = *tty->termios; 322 struct tty_ldisc *ld; 323 324 /* 325 * Perform the actual termios internal changes under lock. 326 */ 327 328 329 /* FIXME: we need to decide on some locking/ordering semantics 330 for the set_termios notification eventually */ 331 mutex_lock(&tty->termios_mutex); 332 333 *tty->termios = *new_termios; 334 unset_locked_termios(tty->termios, &old_termios, tty->termios_locked); 335 canon_change = (old_termios.c_lflag ^ tty->termios->c_lflag) & ICANON; 336 if (canon_change) { 337 memset(&tty->read_flags, 0, sizeof tty->read_flags); 338 tty->canon_head = tty->read_tail; 339 tty->canon_data = 0; 340 tty->erasing = 0; 341 } 342 343 344 if (canon_change && !L_ICANON(tty) && tty->read_cnt) 345 /* Get characters left over from canonical mode. */ 346 wake_up_interruptible(&tty->read_wait); 347 348 /* See if packet mode change of state. */ 349 350 if (tty->link && tty->link->packet) { 351 int old_flow = ((old_termios.c_iflag & IXON) && 352 (old_termios.c_cc[VSTOP] == '\023') && 353 (old_termios.c_cc[VSTART] == '\021')); 354 int new_flow = (I_IXON(tty) && 355 STOP_CHAR(tty) == '\023' && 356 START_CHAR(tty) == '\021'); 357 if (old_flow != new_flow) { 358 tty->ctrl_status &= ~(TIOCPKT_DOSTOP | TIOCPKT_NOSTOP); 359 if (new_flow) 360 tty->ctrl_status |= TIOCPKT_DOSTOP; 361 else 362 tty->ctrl_status |= TIOCPKT_NOSTOP; 363 wake_up_interruptible(&tty->link->read_wait); 364 } 365 } 366 367 if (tty->driver->set_termios) 368 (*tty->driver->set_termios)(tty, &old_termios); 369 370 ld = tty_ldisc_ref(tty); 371 if (ld != NULL) { 372 if (ld->set_termios) 373 (ld->set_termios)(tty, &old_termios); 374 tty_ldisc_deref(ld); 375 } 376 mutex_unlock(&tty->termios_mutex); 377} 378 379/** 380 * set_termios - set termios values for a tty 381 * @tty: terminal device 382 * @arg: user data 383 * @opt: option information 384 * 385 * Helper function to prepare termios data and run neccessary other 386 * functions before using change_termios to do the actual changes. 387 * 388 * Locking: 389 * Called functions take ldisc and termios_sem locks 390 */ 391 392static int set_termios(struct tty_struct * tty, void __user *arg, int opt) 393{ 394 struct ktermios tmp_termios; 395 struct tty_ldisc *ld; 396 int retval = tty_check_change(tty); 397 398 if (retval) 399 return retval; 400 401 memcpy(&tmp_termios, tty->termios, sizeof(struct ktermios)); 402 403 if (opt & TERMIOS_TERMIO) { 404 if (user_termio_to_kernel_termios(&tmp_termios, 405 (struct termio __user *)arg)) 406 return -EFAULT; 407#ifdef TCGETS2 408 } else if (opt & TERMIOS_OLD) { 409 if (user_termios_to_kernel_termios_1(&tmp_termios, 410 (struct termios __user *)arg)) 411 return -EFAULT; 412 } else { 413 if (user_termios_to_kernel_termios(&tmp_termios, 414 (struct termios2 __user *)arg)) 415 return -EFAULT; 416 } 417#else 418 } else if (user_termios_to_kernel_termios(&tmp_termios, 419 (struct termios __user *)arg)) 420 return -EFAULT; 421#endif 422 423 /* If old style Bfoo values are used then load c_ispeed/c_ospeed with the real speed 424 so its unconditionally usable */ 425 tmp_termios.c_ispeed = tty_termios_input_baud_rate(&tmp_termios); 426 tmp_termios.c_ospeed = tty_termios_baud_rate(&tmp_termios); 427 428 ld = tty_ldisc_ref(tty); 429 430 if (ld != NULL) { 431 if ((opt & TERMIOS_FLUSH) && ld->flush_buffer) 432 ld->flush_buffer(tty); 433 tty_ldisc_deref(ld); 434 } 435 436 if (opt & TERMIOS_WAIT) { 437 tty_wait_until_sent(tty, 0); 438 if (signal_pending(current)) 439 return -EINTR; 440 } 441 442 change_termios(tty, &tmp_termios); 443 return 0; 444} 445 446static int get_termio(struct tty_struct * tty, struct termio __user * termio) 447{ 448 if (kernel_termios_to_user_termio(termio, tty->termios)) 449 return -EFAULT; 450 return 0; 451} 452 453static unsigned long inq_canon(struct tty_struct * tty) 454{ 455 int nr, head, tail; 456 457 if (!tty->canon_data || !tty->read_buf) 458 return 0; 459 head = tty->canon_head; 460 tail = tty->read_tail; 461 nr = (head - tail) & (N_TTY_BUF_SIZE-1); 462 /* Skip EOF-chars.. */ 463 while (head != tail) { 464 if (test_bit(tail, tty->read_flags) && 465 tty->read_buf[tail] == __DISABLED_CHAR) 466 nr--; 467 tail = (tail+1) & (N_TTY_BUF_SIZE-1); 468 } 469 return nr; 470} 471 472#ifdef TIOCGETP 473/* 474 * These are deprecated, but there is limited support.. 475 * 476 * The "sg_flags" translation is a joke.. 477 */ 478static int get_sgflags(struct tty_struct * tty) 479{ 480 int flags = 0; 481 482 if (!(tty->termios->c_lflag & ICANON)) { 483 if (tty->termios->c_lflag & ISIG) 484 flags |= 0x02; /* cbreak */ 485 else 486 flags |= 0x20; /* raw */ 487 } 488 if (tty->termios->c_lflag & ECHO) 489 flags |= 0x08; /* echo */ 490 if (tty->termios->c_oflag & OPOST) 491 if (tty->termios->c_oflag & ONLCR) 492 flags |= 0x10; /* crmod */ 493 return flags; 494} 495 496static int get_sgttyb(struct tty_struct * tty, struct sgttyb __user * sgttyb) 497{ 498 struct sgttyb tmp; 499 500 mutex_lock(&tty->termios_mutex); 501 tmp.sg_ispeed = tty->termios->c_ispeed; 502 tmp.sg_ospeed = tty->termios->c_ospeed; 503 tmp.sg_erase = tty->termios->c_cc[VERASE]; 504 tmp.sg_kill = tty->termios->c_cc[VKILL]; 505 tmp.sg_flags = get_sgflags(tty); 506 mutex_unlock(&tty->termios_mutex); 507 508 return copy_to_user(sgttyb, &tmp, sizeof(tmp)) ? -EFAULT : 0; 509} 510 511static void set_sgflags(struct ktermios * termios, int flags) 512{ 513 termios->c_iflag = ICRNL | IXON; 514 termios->c_oflag = 0; 515 termios->c_lflag = ISIG | ICANON; 516 if (flags & 0x02) { /* cbreak */ 517 termios->c_iflag = 0; 518 termios->c_lflag &= ~ICANON; 519 } 520 if (flags & 0x08) { /* echo */ 521 termios->c_lflag |= ECHO | ECHOE | ECHOK | 522 ECHOCTL | ECHOKE | IEXTEN; 523 } 524 if (flags & 0x10) { /* crmod */ 525 termios->c_oflag |= OPOST | ONLCR; 526 } 527 if (flags & 0x20) { /* raw */ 528 termios->c_iflag = 0; 529 termios->c_lflag &= ~(ISIG | ICANON); 530 } 531 if (!(termios->c_lflag & ICANON)) { 532 termios->c_cc[VMIN] = 1; 533 termios->c_cc[VTIME] = 0; 534 } 535} 536 537/** 538 * set_sgttyb - set legacy terminal values 539 * @tty: tty structure 540 * @sgttyb: pointer to old style terminal structure 541 * 542 * Updates a terminal from the legacy BSD style terminal information 543 * structure. 544 * 545 * Locking: termios_sem 546 */ 547 548static int set_sgttyb(struct tty_struct * tty, struct sgttyb __user * sgttyb) 549{ 550 int retval; 551 struct sgttyb tmp; 552 struct ktermios termios; 553 554 retval = tty_check_change(tty); 555 if (retval) 556 return retval; 557 558 if (copy_from_user(&tmp, sgttyb, sizeof(tmp))) 559 return -EFAULT; 560 561 mutex_lock(&tty->termios_mutex); 562 termios = *tty->termios; 563 termios.c_cc[VERASE] = tmp.sg_erase; 564 termios.c_cc[VKILL] = tmp.sg_kill; 565 set_sgflags(&termios, tmp.sg_flags); 566 /* Try and encode into Bfoo format */ 567#ifdef BOTHER 568 tty_termios_encode_baud_rate(&termios, termios.c_ispeed, termios.c_ospeed); 569#endif 570 mutex_unlock(&tty->termios_mutex); 571 change_termios(tty, &termios); 572 return 0; 573} 574#endif 575 576#ifdef TIOCGETC 577static int get_tchars(struct tty_struct * tty, struct tchars __user * tchars) 578{ 579 struct tchars tmp; 580 581 tmp.t_intrc = tty->termios->c_cc[VINTR]; 582 tmp.t_quitc = tty->termios->c_cc[VQUIT]; 583 tmp.t_startc = tty->termios->c_cc[VSTART]; 584 tmp.t_stopc = tty->termios->c_cc[VSTOP]; 585 tmp.t_eofc = tty->termios->c_cc[VEOF]; 586 tmp.t_brkc = tty->termios->c_cc[VEOL2]; /* what is brkc anyway? */ 587 return copy_to_user(tchars, &tmp, sizeof(tmp)) ? -EFAULT : 0; 588} 589 590static int set_tchars(struct tty_struct * tty, struct tchars __user * tchars) 591{ 592 struct tchars tmp; 593 594 if (copy_from_user(&tmp, tchars, sizeof(tmp))) 595 return -EFAULT; 596 tty->termios->c_cc[VINTR] = tmp.t_intrc; 597 tty->termios->c_cc[VQUIT] = tmp.t_quitc; 598 tty->termios->c_cc[VSTART] = tmp.t_startc; 599 tty->termios->c_cc[VSTOP] = tmp.t_stopc; 600 tty->termios->c_cc[VEOF] = tmp.t_eofc; 601 tty->termios->c_cc[VEOL2] = tmp.t_brkc; /* what is brkc anyway? */ 602 return 0; 603} 604#endif 605 606#ifdef TIOCGLTC 607static int get_ltchars(struct tty_struct * tty, struct ltchars __user * ltchars) 608{ 609 struct ltchars tmp; 610 611 tmp.t_suspc = tty->termios->c_cc[VSUSP]; 612 tmp.t_dsuspc = tty->termios->c_cc[VSUSP]; /* what is dsuspc anyway? */ 613 tmp.t_rprntc = tty->termios->c_cc[VREPRINT]; 614 tmp.t_flushc = tty->termios->c_cc[VEOL2]; /* what is flushc anyway? */ 615 tmp.t_werasc = tty->termios->c_cc[VWERASE]; 616 tmp.t_lnextc = tty->termios->c_cc[VLNEXT]; 617 return copy_to_user(ltchars, &tmp, sizeof(tmp)) ? -EFAULT : 0; 618} 619 620static int set_ltchars(struct tty_struct * tty, struct ltchars __user * ltchars) 621{ 622 struct ltchars tmp; 623 624 if (copy_from_user(&tmp, ltchars, sizeof(tmp))) 625 return -EFAULT; 626 627 tty->termios->c_cc[VSUSP] = tmp.t_suspc; 628 tty->termios->c_cc[VEOL2] = tmp.t_dsuspc; /* what is dsuspc anyway? */ 629 tty->termios->c_cc[VREPRINT] = tmp.t_rprntc; 630 tty->termios->c_cc[VEOL2] = tmp.t_flushc; /* what is flushc anyway? */ 631 tty->termios->c_cc[VWERASE] = tmp.t_werasc; 632 tty->termios->c_cc[VLNEXT] = tmp.t_lnextc; 633 return 0; 634} 635#endif 636 637/** 638 * send_prio_char - send priority character 639 * 640 * Send a high priority character to the tty even if stopped 641 * 642 * Locking: none for xchar method, write ordering for write method. 643 */ 644 645static int send_prio_char(struct tty_struct *tty, char ch) 646{ 647 int was_stopped = tty->stopped; 648 649 if (tty->driver->send_xchar) { 650 tty->driver->send_xchar(tty, ch); 651 return 0; 652 } 653 654 if (tty_write_lock(tty, 0) < 0) 655 return -ERESTARTSYS; 656 657 if (was_stopped) 658 start_tty(tty); 659 tty->driver->write(tty, &ch, 1); 660 if (was_stopped) 661 stop_tty(tty); 662 tty_write_unlock(tty); 663 return 0; 664} 665 666int n_tty_ioctl(struct tty_struct * tty, struct file * file, 667 unsigned int cmd, unsigned long arg) 668{ 669 struct tty_struct * real_tty; 670 void __user *p = (void __user *)arg; 671 int retval; 672 struct tty_ldisc *ld; 673 674 if (tty->driver->type == TTY_DRIVER_TYPE_PTY && 675 tty->driver->subtype == PTY_TYPE_MASTER) 676 real_tty = tty->link; 677 else 678 real_tty = tty; 679 680 switch (cmd) { 681#ifdef TIOCGETP 682 case TIOCGETP: 683 return get_sgttyb(real_tty, (struct sgttyb __user *) arg); 684 case TIOCSETP: 685 case TIOCSETN: 686 return set_sgttyb(real_tty, (struct sgttyb __user *) arg); 687#endif 688#ifdef TIOCGETC 689 case TIOCGETC: 690 return get_tchars(real_tty, p); 691 case TIOCSETC: 692 return set_tchars(real_tty, p); 693#endif 694#ifdef TIOCGLTC 695 case TIOCGLTC: 696 return get_ltchars(real_tty, p); 697 case TIOCSLTC: 698 return set_ltchars(real_tty, p); 699#endif 700 case TCSETSF: 701 return set_termios(real_tty, p, TERMIOS_FLUSH | TERMIOS_WAIT | TERMIOS_OLD); 702 case TCSETSW: 703 return set_termios(real_tty, p, TERMIOS_WAIT | TERMIOS_OLD); 704 case TCSETS: 705 return set_termios(real_tty, p, TERMIOS_OLD); 706#ifndef TCGETS2 707 case TCGETS: 708 if (kernel_termios_to_user_termios((struct termios __user *)arg, real_tty->termios)) 709 return -EFAULT; 710 return 0; 711#else 712 case TCGETS: 713 if (kernel_termios_to_user_termios_1((struct termios __user *)arg, real_tty->termios)) 714 return -EFAULT; 715 return 0; 716 case TCGETS2: 717 if (kernel_termios_to_user_termios((struct termios2 __user *)arg, real_tty->termios)) 718 return -EFAULT; 719 return 0; 720 case TCSETSF2: 721 return set_termios(real_tty, p, TERMIOS_FLUSH | TERMIOS_WAIT); 722 case TCSETSW2: 723 return set_termios(real_tty, p, TERMIOS_WAIT); 724 case TCSETS2: 725 return set_termios(real_tty, p, 0); 726#endif 727 case TCGETA: 728 return get_termio(real_tty, p); 729 case TCSETAF: 730 return set_termios(real_tty, p, TERMIOS_FLUSH | TERMIOS_WAIT | TERMIOS_TERMIO); 731 case TCSETAW: 732 return set_termios(real_tty, p, TERMIOS_WAIT | TERMIOS_TERMIO); 733 case TCSETA: 734 return set_termios(real_tty, p, TERMIOS_TERMIO); 735 case TCXONC: 736 retval = tty_check_change(tty); 737 if (retval) 738 return retval; 739 switch (arg) { 740 case TCOOFF: 741 if (!tty->flow_stopped) { 742 tty->flow_stopped = 1; 743 stop_tty(tty); 744 } 745 break; 746 case TCOON: 747 if (tty->flow_stopped) { 748 tty->flow_stopped = 0; 749 start_tty(tty); 750 } 751 break; 752 case TCIOFF: 753 if (STOP_CHAR(tty) != __DISABLED_CHAR) 754 return send_prio_char(tty, STOP_CHAR(tty)); 755 break; 756 case TCION: 757 if (START_CHAR(tty) != __DISABLED_CHAR) 758 return send_prio_char(tty, START_CHAR(tty)); 759 break; 760 default: 761 return -EINVAL; 762 } 763 return 0; 764 case TCFLSH: 765 retval = tty_check_change(tty); 766 if (retval) 767 return retval; 768 769 ld = tty_ldisc_ref(tty); 770 switch (arg) { 771 case TCIFLUSH: 772 if (ld && ld->flush_buffer) 773 ld->flush_buffer(tty); 774 break; 775 case TCIOFLUSH: 776 if (ld && ld->flush_buffer) 777 ld->flush_buffer(tty); 778 /* fall through */ 779 case TCOFLUSH: 780 if (tty->driver->flush_buffer) 781 tty->driver->flush_buffer(tty); 782 break; 783 default: 784 tty_ldisc_deref(ld); 785 return -EINVAL; 786 } 787 tty_ldisc_deref(ld); 788 return 0; 789 case TIOCOUTQ: 790 return put_user(tty->driver->chars_in_buffer ? 791 tty->driver->chars_in_buffer(tty) : 0, 792 (int __user *) arg); 793 case TIOCINQ: 794 retval = tty->read_cnt; 795 if (L_ICANON(tty)) 796 retval = inq_canon(tty); 797 return put_user(retval, (unsigned int __user *) arg); 798 case TIOCGLCKTRMIOS: 799 if (kernel_termios_to_user_termios((struct termios __user *)arg, real_tty->termios_locked)) 800 return -EFAULT; 801 return 0; 802 803 case TIOCSLCKTRMIOS: 804 if (!capable(CAP_SYS_ADMIN)) 805 return -EPERM; 806 if (user_termios_to_kernel_termios(real_tty->termios_locked, (struct termios __user *) arg)) 807 return -EFAULT; 808 return 0; 809 810 case TIOCPKT: 811 { 812 int pktmode; 813 814 if (tty->driver->type != TTY_DRIVER_TYPE_PTY || 815 tty->driver->subtype != PTY_TYPE_MASTER) 816 return -ENOTTY; 817 if (get_user(pktmode, (int __user *) arg)) 818 return -EFAULT; 819 if (pktmode) { 820 if (!tty->packet) { 821 tty->packet = 1; 822 tty->link->ctrl_status = 0; 823 } 824 } else 825 tty->packet = 0; 826 return 0; 827 } 828 case TIOCGSOFTCAR: 829 return put_user(C_CLOCAL(tty) ? 1 : 0, (int __user *)arg); 830 case TIOCSSOFTCAR: 831 if (get_user(arg, (unsigned int __user *) arg)) 832 return -EFAULT; 833 mutex_lock(&tty->termios_mutex); 834 tty->termios->c_cflag = 835 ((tty->termios->c_cflag & ~CLOCAL) | 836 (arg ? CLOCAL : 0)); 837 mutex_unlock(&tty->termios_mutex); 838 return 0; 839 default: 840 return -ENOIOCTLCMD; 841 } 842} 843 844EXPORT_SYMBOL(n_tty_ioctl);