RT-AC66 3.0.0.4.374.130 core
[tomato.git] / release / src-rt-6.x / linux / linux-2.6 / drivers / char / tty_ioctl.c
blobe78befc282eacec112bd9152e22bb78e2db1ce99
1 /*
2 * linux/drivers/char/tty_ioctl.c
4 * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds
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 */
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>
25 #include <asm/io.h>
26 #include <asm/uaccess.h>
27 #include <asm/system.h>
29 #undef TTY_DEBUG_WAIT_UNTIL_SENT
31 #undef DEBUG
34 * Internal flag options for termios setting behavior
36 #define TERMIOS_FLUSH 1
37 #define TERMIOS_WAIT 2
38 #define TERMIOS_TERMIO 4
39 #define TERMIOS_OLD 8
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
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)
50 * Locking: none
53 void tty_wait_until_sent(struct tty_struct *tty, long timeout)
55 #ifdef TTY_DEBUG_WAIT_UNTIL_SENT
56 char buf[64];
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) < 0)
66 return;
67 if (tty->driver->wait_until_sent)
68 tty->driver->wait_until_sent(tty, timeout);
70 EXPORT_SYMBOL(tty_wait_until_sent);
72 static void unset_locked_termios(struct ktermios *termios,
73 struct ktermios *old,
74 struct ktermios *locked)
76 int i;
78 #define NOSET_MASK(x, y, z) (x = ((x) & ~(z)) | ((y) & (z)))
80 if (!locked) {
81 printk(KERN_WARNING "Warning?!? termios_locked is NULL.\n");
82 return;
85 NOSET_MASK(termios->c_iflag, old->c_iflag, locked->c_iflag);
86 NOSET_MASK(termios->c_oflag, old->c_oflag, locked->c_oflag);
87 NOSET_MASK(termios->c_cflag, old->c_cflag, locked->c_cflag);
88 NOSET_MASK(termios->c_lflag, old->c_lflag, locked->c_lflag);
89 termios->c_line = locked->c_line ? old->c_line : termios->c_line;
90 for (i = 0; i < NCCS; i++)
91 termios->c_cc[i] = locked->c_cc[i] ?
92 old->c_cc[i] : termios->c_cc[i];
93 /* FIXME: What should we do for i/ospeed */
97 * Routine which returns the baud rate of the tty
99 * Note that the baud_table needs to be kept in sync with the
100 * include/asm/termbits.h file.
102 static const speed_t baud_table[] = {
103 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
104 9600, 19200, 38400, 57600, 115200, 230400, 460800,
105 #ifdef __sparc__
106 76800, 153600, 307200, 614400, 921600
107 #else
108 500000, 576000, 921600, 1000000, 1152000, 1500000, 2000000,
109 2500000, 3000000, 3500000, 4000000
110 #endif
113 #ifndef __sparc__
114 static const tcflag_t baud_bits[] = {
115 B0, B50, B75, B110, B134, B150, B200, B300, B600,
116 B1200, B1800, B2400, B4800, B9600, B19200, B38400,
117 B57600, B115200, B230400, B460800, B500000, B576000,
118 B921600, B1000000, B1152000, B1500000, B2000000, B2500000,
119 B3000000, B3500000, B4000000
121 #else
122 static const tcflag_t baud_bits[] = {
123 B0, B50, B75, B110, B134, B150, B200, B300, B600,
124 B1200, B1800, B2400, B4800, B9600, B19200, B38400,
125 B57600, B115200, B230400, B460800, B76800, B153600,
126 B307200, B614400, B921600
128 #endif
130 static int n_baud_table = ARRAY_SIZE(baud_table);
133 * tty_termios_baud_rate
134 * @termios: termios structure
136 * Convert termios baud rate data into a speed. This should be called
137 * with the termios lock held if this termios is a terminal termios
138 * structure. May change the termios data. Device drivers can call this
139 * function but should use ->c_[io]speed directly as they are updated.
141 * Locking: none
144 speed_t tty_termios_baud_rate(struct ktermios *termios)
146 unsigned int cbaud;
148 cbaud = termios->c_cflag & CBAUD;
150 #ifdef BOTHER
151 /* Magic token for arbitary speed via c_ispeed/c_ospeed */
152 if (cbaud == BOTHER)
153 return termios->c_ospeed;
154 #endif
155 if (cbaud & CBAUDEX) {
156 cbaud &= ~CBAUDEX;
158 if (cbaud < 1 || cbaud + 15 > n_baud_table)
159 termios->c_cflag &= ~CBAUDEX;
160 else
161 cbaud += 15;
163 return baud_table[cbaud];
165 EXPORT_SYMBOL(tty_termios_baud_rate);
168 * tty_termios_input_baud_rate
169 * @termios: termios structure
171 * Convert termios baud rate data into a speed. This should be called
172 * with the termios lock held if this termios is a terminal termios
173 * structure. May change the termios data. Device drivers can call this
174 * function but should use ->c_[io]speed directly as they are updated.
176 * Locking: none
179 speed_t tty_termios_input_baud_rate(struct ktermios *termios)
181 #ifdef IBSHIFT
182 unsigned int cbaud = (termios->c_cflag >> IBSHIFT) & CBAUD;
184 if (cbaud == B0)
185 return tty_termios_baud_rate(termios);
187 /* Magic token for arbitary speed via c_ispeed*/
188 if (cbaud == BOTHER)
189 return termios->c_ispeed;
191 if (cbaud & CBAUDEX) {
192 cbaud &= ~CBAUDEX;
194 if (cbaud < 1 || cbaud + 15 > n_baud_table)
195 termios->c_cflag &= ~(CBAUDEX << IBSHIFT);
196 else
197 cbaud += 15;
199 return baud_table[cbaud];
200 #else
201 return tty_termios_baud_rate(termios);
202 #endif
204 EXPORT_SYMBOL(tty_termios_input_baud_rate);
207 * tty_termios_encode_baud_rate
208 * @termios: ktermios structure holding user requested state
209 * @ispeed: input speed
210 * @ospeed: output speed
212 * Encode the speeds set into the passed termios structure. This is
213 * used as a library helper for drivers os that they can report back
214 * the actual speed selected when it differs from the speed requested
216 * For maximal back compatibility with legacy SYS5/POSIX *nix behaviour
217 * we need to carefully set the bits when the user does not get the
218 * desired speed. We allow small margins and preserve as much of possible
219 * of the input intent to keep compatiblity.
221 * Locking: Caller should hold termios lock. This is already held
222 * when calling this function from the driver termios handler.
224 * The ifdefs deal with platforms whose owners have yet to update them
225 * and will all go away once this is done.
228 void tty_termios_encode_baud_rate(struct ktermios *termios,
229 speed_t ibaud, speed_t obaud)
231 int i = 0;
232 int ifound = -1, ofound = -1;
233 int iclose = ibaud/50, oclose = obaud/50;
234 int ibinput = 0;
236 if (obaud == 0) /* CD dropped */
237 ibaud = 0; /* Clear ibaud to be sure */
239 termios->c_ispeed = ibaud;
240 termios->c_ospeed = obaud;
242 #ifdef BOTHER
243 /* If the user asked for a precise weird speed give a precise weird
244 answer. If they asked for a Bfoo speed they many have problems
245 digesting non-exact replies so fuzz a bit */
247 if ((termios->c_cflag & CBAUD) == BOTHER)
248 oclose = 0;
249 if (((termios->c_cflag >> IBSHIFT) & CBAUD) == BOTHER)
250 iclose = 0;
251 if ((termios->c_cflag >> IBSHIFT) & CBAUD)
252 ibinput = 1; /* An input speed was specified */
253 #endif
254 termios->c_cflag &= ~CBAUD;
257 * Our goal is to find a close match to the standard baud rate
258 * returned. Walk the baud rate table and if we get a very close
259 * match then report back the speed as a POSIX Bxxxx value by
260 * preference
263 do {
264 if (obaud - oclose <= baud_table[i] &&
265 obaud + oclose >= baud_table[i]) {
266 termios->c_cflag |= baud_bits[i];
267 ofound = i;
269 if (ibaud - iclose <= baud_table[i] &&
270 ibaud + iclose >= baud_table[i]) {
271 /* For the case input == output don't set IBAUD bits
272 if the user didn't do so */
273 if (ofound == i && !ibinput)
274 ifound = i;
275 #ifdef IBSHIFT
276 else {
277 ifound = i;
278 termios->c_cflag |= (baud_bits[i] << IBSHIFT);
280 #endif
282 } while (++i < n_baud_table);
285 * If we found no match then use BOTHER if provided or warn
286 * the user their platform maintainer needs to wake up if not.
288 #ifdef BOTHER
289 if (ofound == -1)
290 termios->c_cflag |= BOTHER;
291 /* Set exact input bits only if the input and output differ or the
292 user already did */
293 if (ifound == -1 && (ibaud != obaud || ibinput))
294 termios->c_cflag |= (BOTHER << IBSHIFT);
295 #else
296 if (ifound == -1 || ofound == -1) {
297 static int warned;
298 if (!warned++)
299 printk(KERN_WARNING "tty: Unable to return correct "
300 "speed data as your architecture needs updating.\n");
302 #endif
304 EXPORT_SYMBOL_GPL(tty_termios_encode_baud_rate);
306 void tty_encode_baud_rate(struct tty_struct *tty, speed_t ibaud, speed_t obaud)
308 tty_termios_encode_baud_rate(tty->termios, ibaud, obaud);
310 EXPORT_SYMBOL_GPL(tty_encode_baud_rate);
313 * tty_get_baud_rate - get tty bit rates
314 * @tty: tty to query
316 * Returns the baud rate as an integer for this terminal. The
317 * termios lock must be held by the caller and the terminal bit
318 * flags may be updated.
320 * Locking: none
323 speed_t tty_get_baud_rate(struct tty_struct *tty)
325 speed_t baud = tty_termios_baud_rate(tty->termios);
327 if (baud == 38400 && tty->alt_speed) {
328 if (!tty->warned) {
329 printk(KERN_WARNING "Use of setserial/setrocket to "
330 "set SPD_* flags is deprecated\n");
331 tty->warned = 1;
333 baud = tty->alt_speed;
336 return baud;
338 EXPORT_SYMBOL(tty_get_baud_rate);
341 * tty_termios_copy_hw - copy hardware settings
342 * @new: New termios
343 * @old: Old termios
345 * Propogate the hardware specific terminal setting bits from
346 * the old termios structure to the new one. This is used in cases
347 * where the hardware does not support reconfiguration or as a helper
348 * in some cases where only minimal reconfiguration is supported
351 void tty_termios_copy_hw(struct ktermios *new, struct ktermios *old)
353 /* The bits a dumb device handles in software. Smart devices need
354 to always provide a set_termios method */
355 new->c_cflag &= HUPCL | CREAD | CLOCAL;
356 new->c_cflag |= old->c_cflag & ~(HUPCL | CREAD | CLOCAL);
357 new->c_ispeed = old->c_ispeed;
358 new->c_ospeed = old->c_ospeed;
360 EXPORT_SYMBOL(tty_termios_copy_hw);
363 * tty_termios_hw_change - check for setting change
364 * @a: termios
365 * @b: termios to compare
367 * Check if any of the bits that affect a dumb device have changed
368 * between the two termios structures, or a speed change is needed.
371 int tty_termios_hw_change(struct ktermios *a, struct ktermios *b)
373 if (a->c_ispeed != b->c_ispeed || a->c_ospeed != b->c_ospeed)
374 return 1;
375 if ((a->c_cflag ^ b->c_cflag) & ~(HUPCL | CREAD | CLOCAL))
376 return 1;
377 return 0;
379 EXPORT_SYMBOL(tty_termios_hw_change);
382 * change_termios - update termios values
383 * @tty: tty to update
384 * @new_termios: desired new value
386 * Perform updates to the termios values set on this terminal. There
387 * is a bit of layering violation here with n_tty in terms of the
388 * internal knowledge of this function.
390 * Locking: termios_sem
393 static void change_termios(struct tty_struct *tty, struct ktermios *new_termios)
395 int canon_change;
396 struct ktermios old_termios = *tty->termios;
397 struct tty_ldisc *ld;
400 * Perform the actual termios internal changes under lock.
404 /* FIXME: we need to decide on some locking/ordering semantics
405 for the set_termios notification eventually */
406 mutex_lock(&tty->termios_mutex);
408 *tty->termios = *new_termios;
409 unset_locked_termios(tty->termios, &old_termios, tty->termios_locked);
410 canon_change = (old_termios.c_lflag ^ tty->termios->c_lflag) & ICANON;
411 if (canon_change) {
412 memset(&tty->read_flags, 0, sizeof tty->read_flags);
413 tty->canon_head = tty->read_tail;
414 tty->canon_data = 0;
415 tty->erasing = 0;
418 /* This bit should be in the ldisc code */
419 if (canon_change && !L_ICANON(tty) && tty->read_cnt)
420 /* Get characters left over from canonical mode. */
421 wake_up_interruptible(&tty->read_wait);
423 /* See if packet mode change of state. */
424 if (tty->link && tty->link->packet) {
425 int old_flow = ((old_termios.c_iflag & IXON) &&
426 (old_termios.c_cc[VSTOP] == '\023') &&
427 (old_termios.c_cc[VSTART] == '\021'));
428 int new_flow = (I_IXON(tty) &&
429 STOP_CHAR(tty) == '\023' &&
430 START_CHAR(tty) == '\021');
431 if (old_flow != new_flow) {
432 tty->ctrl_status &= ~(TIOCPKT_DOSTOP | TIOCPKT_NOSTOP);
433 if (new_flow)
434 tty->ctrl_status |= TIOCPKT_DOSTOP;
435 else
436 tty->ctrl_status |= TIOCPKT_NOSTOP;
437 wake_up_interruptible(&tty->link->read_wait);
441 if (tty->driver->set_termios)
442 (*tty->driver->set_termios)(tty, &old_termios);
443 else
444 tty_termios_copy_hw(tty->termios, &old_termios);
446 ld = tty_ldisc_ref(tty);
447 if (ld != NULL) {
448 if (ld->set_termios)
449 (ld->set_termios)(tty, &old_termios);
450 tty_ldisc_deref(ld);
452 mutex_unlock(&tty->termios_mutex);
456 * set_termios - set termios values for a tty
457 * @tty: terminal device
458 * @arg: user data
459 * @opt: option information
461 * Helper function to prepare termios data and run neccessary other
462 * functions before using change_termios to do the actual changes.
464 * Locking:
465 * Called functions take ldisc and termios_sem locks
468 static int set_termios(struct tty_struct *tty, void __user *arg, int opt)
470 struct ktermios tmp_termios;
471 struct tty_ldisc *ld;
472 int retval = tty_check_change(tty);
474 if (retval)
475 return retval;
477 memcpy(&tmp_termios, tty->termios, sizeof(struct ktermios));
479 if (opt & TERMIOS_TERMIO) {
480 if (user_termio_to_kernel_termios(&tmp_termios,
481 (struct termio __user *)arg))
482 return -EFAULT;
483 #ifdef TCGETS2
484 } else if (opt & TERMIOS_OLD) {
485 if (user_termios_to_kernel_termios_1(&tmp_termios,
486 (struct termios __user *)arg))
487 return -EFAULT;
488 } else {
489 if (user_termios_to_kernel_termios(&tmp_termios,
490 (struct termios2 __user *)arg))
491 return -EFAULT;
493 #else
494 } else if (user_termios_to_kernel_termios(&tmp_termios,
495 (struct termios __user *)arg))
496 return -EFAULT;
497 #endif
499 /* If old style Bfoo values are used then load c_ispeed/c_ospeed
500 * with the real speed so its unconditionally usable */
501 tmp_termios.c_ispeed = tty_termios_input_baud_rate(&tmp_termios);
502 tmp_termios.c_ospeed = tty_termios_baud_rate(&tmp_termios);
504 ld = tty_ldisc_ref(tty);
506 if (ld != NULL) {
507 if ((opt & TERMIOS_FLUSH) && ld->flush_buffer)
508 ld->flush_buffer(tty);
509 tty_ldisc_deref(ld);
512 if (opt & TERMIOS_WAIT) {
513 tty_wait_until_sent(tty, 0);
514 if (signal_pending(current))
515 return -EINTR;
518 change_termios(tty, &tmp_termios);
520 /* FIXME: Arguably if tmp_termios == tty->termios AND the
521 actual requested termios was not tmp_termios then we may
522 want to return an error as no user requested change has
523 succeeded */
524 return 0;
527 static int get_termio(struct tty_struct *tty, struct termio __user *termio)
529 if (kernel_termios_to_user_termio(termio, tty->termios))
530 return -EFAULT;
531 return 0;
534 static unsigned long inq_canon(struct tty_struct *tty)
536 int nr, head, tail;
538 if (!tty->canon_data || !tty->read_buf)
539 return 0;
540 head = tty->canon_head;
541 tail = tty->read_tail;
542 nr = (head - tail) & (N_TTY_BUF_SIZE-1);
543 /* Skip EOF-chars.. */
544 while (head != tail) {
545 if (test_bit(tail, tty->read_flags) &&
546 tty->read_buf[tail] == __DISABLED_CHAR)
547 nr--;
548 tail = (tail+1) & (N_TTY_BUF_SIZE-1);
550 return nr;
553 #ifdef TIOCGETP
555 * These are deprecated, but there is limited support..
557 * The "sg_flags" translation is a joke..
559 static int get_sgflags(struct tty_struct *tty)
561 int flags = 0;
563 if (!(tty->termios->c_lflag & ICANON)) {
564 if (tty->termios->c_lflag & ISIG)
565 flags |= 0x02; /* cbreak */
566 else
567 flags |= 0x20; /* raw */
569 if (tty->termios->c_lflag & ECHO)
570 flags |= 0x08; /* echo */
571 if (tty->termios->c_oflag & OPOST)
572 if (tty->termios->c_oflag & ONLCR)
573 flags |= 0x10; /* crmod */
574 return flags;
577 static int get_sgttyb(struct tty_struct *tty, struct sgttyb __user *sgttyb)
579 struct sgttyb tmp;
581 mutex_lock(&tty->termios_mutex);
582 tmp.sg_ispeed = tty->termios->c_ispeed;
583 tmp.sg_ospeed = tty->termios->c_ospeed;
584 tmp.sg_erase = tty->termios->c_cc[VERASE];
585 tmp.sg_kill = tty->termios->c_cc[VKILL];
586 tmp.sg_flags = get_sgflags(tty);
587 mutex_unlock(&tty->termios_mutex);
589 return copy_to_user(sgttyb, &tmp, sizeof(tmp)) ? -EFAULT : 0;
592 static void set_sgflags(struct ktermios *termios, int flags)
594 termios->c_iflag = ICRNL | IXON;
595 termios->c_oflag = 0;
596 termios->c_lflag = ISIG | ICANON;
597 if (flags & 0x02) { /* cbreak */
598 termios->c_iflag = 0;
599 termios->c_lflag &= ~ICANON;
601 if (flags & 0x08) { /* echo */
602 termios->c_lflag |= ECHO | ECHOE | ECHOK |
603 ECHOCTL | ECHOKE | IEXTEN;
605 if (flags & 0x10) { /* crmod */
606 termios->c_oflag |= OPOST | ONLCR;
608 if (flags & 0x20) { /* raw */
609 termios->c_iflag = 0;
610 termios->c_lflag &= ~(ISIG | ICANON);
612 if (!(termios->c_lflag & ICANON)) {
613 termios->c_cc[VMIN] = 1;
614 termios->c_cc[VTIME] = 0;
619 * set_sgttyb - set legacy terminal values
620 * @tty: tty structure
621 * @sgttyb: pointer to old style terminal structure
623 * Updates a terminal from the legacy BSD style terminal information
624 * structure.
626 * Locking: termios_sem
629 static int set_sgttyb(struct tty_struct *tty, struct sgttyb __user *sgttyb)
631 int retval;
632 struct sgttyb tmp;
633 struct ktermios termios;
635 retval = tty_check_change(tty);
636 if (retval)
637 return retval;
639 if (copy_from_user(&tmp, sgttyb, sizeof(tmp)))
640 return -EFAULT;
642 mutex_lock(&tty->termios_mutex);
643 termios = *tty->termios;
644 termios.c_cc[VERASE] = tmp.sg_erase;
645 termios.c_cc[VKILL] = tmp.sg_kill;
646 set_sgflags(&termios, tmp.sg_flags);
647 /* Try and encode into Bfoo format */
648 #ifdef BOTHER
649 tty_termios_encode_baud_rate(&termios, termios.c_ispeed,
650 termios.c_ospeed);
651 #endif
652 mutex_unlock(&tty->termios_mutex);
653 change_termios(tty, &termios);
654 return 0;
656 #endif
658 #ifdef TIOCGETC
659 static int get_tchars(struct tty_struct *tty, struct tchars __user *tchars)
661 struct tchars tmp;
663 tmp.t_intrc = tty->termios->c_cc[VINTR];
664 tmp.t_quitc = tty->termios->c_cc[VQUIT];
665 tmp.t_startc = tty->termios->c_cc[VSTART];
666 tmp.t_stopc = tty->termios->c_cc[VSTOP];
667 tmp.t_eofc = tty->termios->c_cc[VEOF];
668 tmp.t_brkc = tty->termios->c_cc[VEOL2]; /* what is brkc anyway? */
669 return copy_to_user(tchars, &tmp, sizeof(tmp)) ? -EFAULT : 0;
672 static int set_tchars(struct tty_struct *tty, struct tchars __user *tchars)
674 struct tchars tmp;
676 if (copy_from_user(&tmp, tchars, sizeof(tmp)))
677 return -EFAULT;
678 tty->termios->c_cc[VINTR] = tmp.t_intrc;
679 tty->termios->c_cc[VQUIT] = tmp.t_quitc;
680 tty->termios->c_cc[VSTART] = tmp.t_startc;
681 tty->termios->c_cc[VSTOP] = tmp.t_stopc;
682 tty->termios->c_cc[VEOF] = tmp.t_eofc;
683 tty->termios->c_cc[VEOL2] = tmp.t_brkc; /* what is brkc anyway? */
684 return 0;
686 #endif
688 #ifdef TIOCGLTC
689 static int get_ltchars(struct tty_struct *tty, struct ltchars __user *ltchars)
691 struct ltchars tmp;
693 tmp.t_suspc = tty->termios->c_cc[VSUSP];
694 /* what is dsuspc anyway? */
695 tmp.t_dsuspc = tty->termios->c_cc[VSUSP];
696 tmp.t_rprntc = tty->termios->c_cc[VREPRINT];
697 /* what is flushc anyway? */
698 tmp.t_flushc = tty->termios->c_cc[VEOL2];
699 tmp.t_werasc = tty->termios->c_cc[VWERASE];
700 tmp.t_lnextc = tty->termios->c_cc[VLNEXT];
701 return copy_to_user(ltchars, &tmp, sizeof(tmp)) ? -EFAULT : 0;
704 static int set_ltchars(struct tty_struct *tty, struct ltchars __user *ltchars)
706 struct ltchars tmp;
708 if (copy_from_user(&tmp, ltchars, sizeof(tmp)))
709 return -EFAULT;
711 tty->termios->c_cc[VSUSP] = tmp.t_suspc;
712 /* what is dsuspc anyway? */
713 tty->termios->c_cc[VEOL2] = tmp.t_dsuspc;
714 tty->termios->c_cc[VREPRINT] = tmp.t_rprntc;
715 /* what is flushc anyway? */
716 tty->termios->c_cc[VEOL2] = tmp.t_flushc;
717 tty->termios->c_cc[VWERASE] = tmp.t_werasc;
718 tty->termios->c_cc[VLNEXT] = tmp.t_lnextc;
719 return 0;
721 #endif
724 * send_prio_char - send priority character
726 * Send a high priority character to the tty even if stopped
728 * Locking: none for xchar method, write ordering for write method.
731 static int send_prio_char(struct tty_struct *tty, char ch)
733 int was_stopped = tty->stopped;
735 if (tty->driver->send_xchar) {
736 tty->driver->send_xchar(tty, ch);
737 return 0;
740 if (tty_write_lock(tty, 0) < 0)
741 return -ERESTARTSYS;
743 if (was_stopped)
744 start_tty(tty);
745 tty->driver->write(tty, &ch, 1);
746 if (was_stopped)
747 stop_tty(tty);
748 tty_write_unlock(tty);
749 return 0;
753 * tty_change_softcar - carrier change ioctl helper
754 * @tty: tty to update
755 * @arg: enable/disable CLOCAL
757 * Perform a change to the CLOCAL state and call into the driver
758 * layer to make it visible. All done with the termios mutex
761 static int tty_change_softcar(struct tty_struct *tty, int arg)
763 int ret = 0;
764 int bit = arg ? CLOCAL : 0;
765 struct ktermios old = *tty->termios;
767 mutex_lock(&tty->termios_mutex);
768 tty->termios->c_cflag &= ~CLOCAL;
769 tty->termios->c_cflag |= bit;
770 if (tty->driver->set_termios)
771 tty->driver->set_termios(tty, &old);
772 if ((tty->termios->c_cflag & CLOCAL) != bit)
773 ret = -EINVAL;
774 mutex_unlock(&tty->termios_mutex);
775 return ret;
779 * tty_mode_ioctl - mode related ioctls
780 * @tty: tty for the ioctl
781 * @file: file pointer for the tty
782 * @cmd: command
783 * @arg: ioctl argument
785 * Perform non line discipline specific mode control ioctls. This
786 * is designed to be called by line disciplines to ensure they provide
787 * consistent mode setting.
790 int tty_mode_ioctl(struct tty_struct *tty, struct file *file,
791 unsigned int cmd, unsigned long arg)
793 struct tty_struct *real_tty;
794 void __user *p = (void __user *)arg;
796 if (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
797 tty->driver->subtype == PTY_TYPE_MASTER)
798 real_tty = tty->link;
799 else
800 real_tty = tty;
802 switch (cmd) {
803 #ifdef TIOCGETP
804 case TIOCGETP:
805 return get_sgttyb(real_tty, (struct sgttyb __user *) arg);
806 case TIOCSETP:
807 case TIOCSETN:
808 return set_sgttyb(real_tty, (struct sgttyb __user *) arg);
809 #endif
810 #ifdef TIOCGETC
811 case TIOCGETC:
812 return get_tchars(real_tty, p);
813 case TIOCSETC:
814 return set_tchars(real_tty, p);
815 #endif
816 #ifdef TIOCGLTC
817 case TIOCGLTC:
818 return get_ltchars(real_tty, p);
819 case TIOCSLTC:
820 return set_ltchars(real_tty, p);
821 #endif
822 case TCSETSF:
823 return set_termios(real_tty, p, TERMIOS_FLUSH | TERMIOS_WAIT | TERMIOS_OLD);
824 case TCSETSW:
825 return set_termios(real_tty, p, TERMIOS_WAIT | TERMIOS_OLD);
826 case TCSETS:
827 return set_termios(real_tty, p, TERMIOS_OLD);
828 #ifndef TCGETS2
829 case TCGETS:
830 if (kernel_termios_to_user_termios((struct termios __user *)arg, real_tty->termios))
831 return -EFAULT;
832 return 0;
833 #else
834 case TCGETS:
835 if (kernel_termios_to_user_termios_1((struct termios __user *)arg, real_tty->termios))
836 return -EFAULT;
837 return 0;
838 case TCGETS2:
839 if (kernel_termios_to_user_termios((struct termios2 __user *)arg, real_tty->termios))
840 return -EFAULT;
841 return 0;
842 case TCSETSF2:
843 return set_termios(real_tty, p, TERMIOS_FLUSH | TERMIOS_WAIT);
844 case TCSETSW2:
845 return set_termios(real_tty, p, TERMIOS_WAIT);
846 case TCSETS2:
847 return set_termios(real_tty, p, 0);
848 #endif
849 case TCGETA:
850 return get_termio(real_tty, p);
851 case TCSETAF:
852 return set_termios(real_tty, p, TERMIOS_FLUSH | TERMIOS_WAIT | TERMIOS_TERMIO);
853 case TCSETAW:
854 return set_termios(real_tty, p, TERMIOS_WAIT | TERMIOS_TERMIO);
855 case TCSETA:
856 return set_termios(real_tty, p, TERMIOS_TERMIO);
857 #ifndef TCGETS2
858 case TIOCGLCKTRMIOS:
859 if (kernel_termios_to_user_termios((struct termios __user *)arg, real_tty->termios_locked))
860 return -EFAULT;
861 return 0;
862 case TIOCSLCKTRMIOS:
863 if (!capable(CAP_SYS_ADMIN))
864 return -EPERM;
865 if (user_termios_to_kernel_termios(real_tty->termios_locked,
866 (struct termios __user *) arg))
867 return -EFAULT;
868 return 0;
869 #else
870 case TIOCGLCKTRMIOS:
871 if (kernel_termios_to_user_termios_1((struct termios __user *)arg, real_tty->termios_locked))
872 return -EFAULT;
873 return 0;
874 case TIOCSLCKTRMIOS:
875 if (!capable(CAP_SYS_ADMIN))
876 return -EPERM;
877 if (user_termios_to_kernel_termios_1(real_tty->termios_locked,
878 (struct termios __user *) arg))
879 return -EFAULT;
880 return 0;
881 #endif
882 case TIOCGSOFTCAR:
883 /* FIXME: for correctness we may need to take the termios
884 lock here - review */
885 return put_user(C_CLOCAL(real_tty) ? 1 : 0,
886 (int __user *)arg);
887 case TIOCSSOFTCAR:
888 if (get_user(arg, (unsigned int __user *) arg))
889 return -EFAULT;
890 return tty_change_softcar(real_tty, arg);
891 default:
892 return -ENOIOCTLCMD;
895 EXPORT_SYMBOL_GPL(tty_mode_ioctl);
897 int tty_perform_flush(struct tty_struct *tty, unsigned long arg)
899 struct tty_ldisc *ld;
900 int retval = tty_check_change(tty);
901 if (retval)
902 return retval;
904 ld = tty_ldisc_ref(tty);
905 switch (arg) {
906 case TCIFLUSH:
907 if (ld && ld->flush_buffer)
908 ld->flush_buffer(tty);
909 break;
910 case TCIOFLUSH:
911 if (ld && ld->flush_buffer)
912 ld->flush_buffer(tty);
913 /* fall through */
914 case TCOFLUSH:
915 if (tty->driver->flush_buffer)
916 tty->driver->flush_buffer(tty);
917 break;
918 default:
919 tty_ldisc_deref(ld);
920 return -EINVAL;
922 tty_ldisc_deref(ld);
923 return 0;
925 EXPORT_SYMBOL_GPL(tty_perform_flush);
927 int n_tty_ioctl(struct tty_struct *tty, struct file *file,
928 unsigned int cmd, unsigned long arg)
930 struct tty_struct *real_tty;
931 int retval;
933 if (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
934 tty->driver->subtype == PTY_TYPE_MASTER)
935 real_tty = tty->link;
936 else
937 real_tty = tty;
939 switch (cmd) {
940 case TCXONC:
941 retval = tty_check_change(tty);
942 if (retval)
943 return retval;
944 switch (arg) {
945 case TCOOFF:
946 if (!tty->flow_stopped) {
947 tty->flow_stopped = 1;
948 stop_tty(tty);
950 break;
951 case TCOON:
952 if (tty->flow_stopped) {
953 tty->flow_stopped = 0;
954 start_tty(tty);
956 break;
957 case TCIOFF:
958 if (STOP_CHAR(tty) != __DISABLED_CHAR)
959 return send_prio_char(tty, STOP_CHAR(tty));
960 break;
961 case TCION:
962 if (START_CHAR(tty) != __DISABLED_CHAR)
963 return send_prio_char(tty, START_CHAR(tty));
964 break;
965 default:
966 return -EINVAL;
968 return 0;
969 case TCFLSH:
970 return tty_perform_flush(tty, arg);
971 case TIOCOUTQ:
972 return put_user(tty->driver->chars_in_buffer ?
973 tty->driver->chars_in_buffer(tty) : 0,
974 (int __user *) arg);
975 case TIOCINQ:
976 retval = tty->read_cnt;
977 if (L_ICANON(tty))
978 retval = inq_canon(tty);
979 return put_user(retval, (unsigned int __user *) arg);
980 case TIOCPKT:
982 int pktmode;
984 if (tty->driver->type != TTY_DRIVER_TYPE_PTY ||
985 tty->driver->subtype != PTY_TYPE_MASTER)
986 return -ENOTTY;
987 if (get_user(pktmode, (int __user *) arg))
988 return -EFAULT;
989 if (pktmode) {
990 if (!tty->packet) {
991 tty->packet = 1;
992 tty->link->ctrl_status = 0;
994 } else
995 tty->packet = 0;
996 return 0;
998 default:
999 /* Try the mode commands */
1000 return tty_mode_ioctl(tty, file, cmd, arg);
1003 EXPORT_SYMBOL(n_tty_ioctl);