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