Linux 2.6.21.1
[linux/fpc-iii.git] / drivers / char / tty_ioctl.c
blobfd471cb3338fbd1d008c936f5d44cfe5691a952b
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 DECLARE_WAITQUEUE(wait, current);
57 #ifdef TTY_DEBUG_WAIT_UNTIL_SENT
58 char buf[64];
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);
81 stop_waiting:
82 set_current_state(TASK_RUNNING);
83 remove_wait_queue(&tty->write_wait, &wait);
86 EXPORT_SYMBOL(tty_wait_until_sent);
88 static void unset_locked_termios(struct ktermios *termios,
89 struct ktermios *old,
90 struct ktermios *locked)
92 int i;
94 #define NOSET_MASK(x,y,z) (x = ((x) & ~(z)) | ((y) & (z)))
96 if (!locked) {
97 printk(KERN_WARNING "Warning?!? termios_locked is NULL.\n");
98 return;
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 */
113 * Routine which returns the baud rate of the tty
115 * Note that the baud_table needs to be kept in sync with the
116 * include/asm/termbits.h file.
118 static 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
129 #ifndef __sparc__
130 static 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
137 #else
138 static 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
144 #endif
146 static int n_baud_table = ARRAY_SIZE(baud_table);
149 * tty_termios_baud_rate
150 * @termios: termios structure
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.
157 * Locking: none
160 speed_t tty_termios_baud_rate(struct ktermios *termios)
162 unsigned int cbaud;
164 cbaud = termios->c_cflag & CBAUD;
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;
174 if (cbaud < 1 || cbaud + 15 > n_baud_table)
175 termios->c_cflag &= ~CBAUDEX;
176 else
177 cbaud += 15;
179 return baud_table[cbaud];
182 EXPORT_SYMBOL(tty_termios_baud_rate);
185 * tty_termios_input_baud_rate
186 * @termios: termios structure
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.
193 * Locking: none
196 speed_t tty_termios_input_baud_rate(struct ktermios *termios)
198 #ifdef IBSHIFT
199 unsigned int cbaud = (termios->c_cflag >> IBSHIFT) & CBAUD;
201 if (cbaud == B0)
202 return tty_termios_baud_rate(termios);
204 /* Magic token for arbitary speed via c_ispeed*/
205 if (cbaud == BOTHER)
206 return termios->c_ispeed;
208 if (cbaud & CBAUDEX) {
209 cbaud &= ~CBAUDEX;
211 if (cbaud < 1 || cbaud + 15 > n_baud_table)
212 termios->c_cflag &= ~(CBAUDEX << IBSHIFT);
213 else
214 cbaud += 15;
216 return baud_table[cbaud];
217 #else
218 return tty_termios_baud_rate(termios);
219 #endif
222 EXPORT_SYMBOL(tty_termios_input_baud_rate);
224 #ifdef BOTHER
227 * tty_termios_encode_baud_rate
228 * @termios: ktermios structure holding user requested state
229 * @ispeed: input speed
230 * @ospeed: output speed
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
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.
241 * Locking: Caller should hold termios lock. This is already held
242 * when calling this function from the driver termios handler.
245 void tty_termios_encode_baud_rate(struct ktermios *termios, speed_t ibaud, speed_t obaud)
247 int i = 0;
248 int ifound = -1, ofound = -1;
249 int iclose = ibaud/50, oclose = obaud/50;
250 int ibinput = 0;
252 termios->c_ispeed = ibaud;
253 termios->c_ospeed = obaud;
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 */
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 */
266 termios->c_cflag &= ~CBAUD;
268 do {
269 if (obaud - oclose >= baud_table[i] && obaud + oclose <= baud_table[i]) {
270 termios->c_cflag |= baud_bits[i];
271 ofound = i;
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;
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);
289 EXPORT_SYMBOL_GPL(tty_termios_encode_baud_rate);
291 #endif
294 * tty_get_baud_rate - get tty bit rates
295 * @tty: tty to query
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.
301 * Locking: none
304 speed_t tty_get_baud_rate(struct tty_struct *tty)
306 speed_t baud = tty_termios_baud_rate(tty->termios);
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;
314 baud = tty->alt_speed;
317 return baud;
320 EXPORT_SYMBOL(tty_get_baud_rate);
323 * change_termios - update termios values
324 * @tty: tty to update
325 * @new_termios: desired new value
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.
331 * Locking: termios_sem
334 static void change_termios(struct tty_struct * tty, struct ktermios * new_termios)
336 int canon_change;
337 struct ktermios old_termios = *tty->termios;
338 struct tty_ldisc *ld;
341 * Perform the actual termios internal changes under lock.
345 /* FIXME: we need to decide on some locking/ordering semantics
346 for the set_termios notification eventually */
347 mutex_lock(&tty->termios_mutex);
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;
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);
364 /* See if packet mode change of state. */
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);
383 if (tty->driver->set_termios)
384 (*tty->driver->set_termios)(tty, &old_termios);
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);
392 mutex_unlock(&tty->termios_mutex);
396 * set_termios - set termios values for a tty
397 * @tty: terminal device
398 * @arg: user data
399 * @opt: option information
401 * Helper function to prepare termios data and run neccessary other
402 * functions before using change_termios to do the actual changes.
404 * Locking:
405 * Called functions take ldisc and termios_sem locks
408 static int set_termios(struct tty_struct * tty, void __user *arg, int opt)
410 struct ktermios tmp_termios;
411 struct tty_ldisc *ld;
412 int retval = tty_check_change(tty);
414 if (retval)
415 return retval;
417 memcpy(&tmp_termios, tty->termios, sizeof(struct ktermios));
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;
433 #else
434 } else if (user_termios_to_kernel_termios(&tmp_termios,
435 (struct termios __user *)arg))
436 return -EFAULT;
437 #endif
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);
444 ld = tty_ldisc_ref(tty);
446 if (ld != NULL) {
447 if ((opt & TERMIOS_FLUSH) && ld->flush_buffer)
448 ld->flush_buffer(tty);
449 tty_ldisc_deref(ld);
452 if (opt & TERMIOS_WAIT) {
453 tty_wait_until_sent(tty, 0);
454 if (signal_pending(current))
455 return -EINTR;
458 change_termios(tty, &tmp_termios);
459 return 0;
462 static int get_termio(struct tty_struct * tty, struct termio __user * termio)
464 if (kernel_termios_to_user_termio(termio, tty->termios))
465 return -EFAULT;
466 return 0;
469 static unsigned long inq_canon(struct tty_struct * tty)
471 int nr, head, tail;
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);
485 return nr;
488 #ifdef TIOCGETP
490 * These are deprecated, but there is limited support..
492 * The "sg_flags" translation is a joke..
494 static int get_sgflags(struct tty_struct * tty)
496 int flags = 0;
498 if (!(tty->termios->c_lflag & ICANON)) {
499 if (tty->termios->c_lflag & ISIG)
500 flags |= 0x02; /* cbreak */
501 else
502 flags |= 0x20; /* raw */
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;
512 static int get_sgttyb(struct tty_struct * tty, struct sgttyb __user * sgttyb)
514 struct sgttyb tmp;
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);
524 return copy_to_user(sgttyb, &tmp, sizeof(tmp)) ? -EFAULT : 0;
527 static void set_sgflags(struct ktermios * termios, int flags)
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;
536 if (flags & 0x08) { /* echo */
537 termios->c_lflag |= ECHO | ECHOE | ECHOK |
538 ECHOCTL | ECHOKE | IEXTEN;
540 if (flags & 0x10) { /* crmod */
541 termios->c_oflag |= OPOST | ONLCR;
543 if (flags & 0x20) { /* raw */
544 termios->c_iflag = 0;
545 termios->c_lflag &= ~(ISIG | ICANON);
547 if (!(termios->c_lflag & ICANON)) {
548 termios->c_cc[VMIN] = 1;
549 termios->c_cc[VTIME] = 0;
554 * set_sgttyb - set legacy terminal values
555 * @tty: tty structure
556 * @sgttyb: pointer to old style terminal structure
558 * Updates a terminal from the legacy BSD style terminal information
559 * structure.
561 * Locking: termios_sem
564 static int set_sgttyb(struct tty_struct * tty, struct sgttyb __user * sgttyb)
566 int retval;
567 struct sgttyb tmp;
568 struct ktermios termios;
570 retval = tty_check_change(tty);
571 if (retval)
572 return retval;
574 if (copy_from_user(&tmp, sgttyb, sizeof(tmp)))
575 return -EFAULT;
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;
590 #endif
592 #ifdef TIOCGETC
593 static int get_tchars(struct tty_struct * tty, struct tchars __user * tchars)
595 struct tchars tmp;
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;
606 static int set_tchars(struct tty_struct * tty, struct tchars __user * tchars)
608 struct tchars tmp;
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;
620 #endif
622 #ifdef TIOCGLTC
623 static int get_ltchars(struct tty_struct * tty, struct ltchars __user * ltchars)
625 struct ltchars tmp;
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;
636 static int set_ltchars(struct tty_struct * tty, struct ltchars __user * ltchars)
638 struct ltchars tmp;
640 if (copy_from_user(&tmp, ltchars, sizeof(tmp)))
641 return -EFAULT;
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;
651 #endif
654 * send_prio_char - send priority character
656 * Send a high priority character to the tty even if stopped
658 * Locking: none for xchar method, write ordering for write method.
661 static int send_prio_char(struct tty_struct *tty, char ch)
663 int was_stopped = tty->stopped;
665 if (tty->driver->send_xchar) {
666 tty->driver->send_xchar(tty, ch);
667 return 0;
670 if (mutex_lock_interruptible(&tty->atomic_write_lock))
671 return -ERESTARTSYS;
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;
682 int n_tty_ioctl(struct tty_struct * tty, struct file * file,
683 unsigned int cmd, unsigned long arg)
685 struct tty_struct * real_tty;
686 void __user *p = (void __user *)arg;
687 int retval;
688 struct tty_ldisc *ld;
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;
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);
761 break;
762 case TCOON:
763 if (tty->flow_stopped) {
764 tty->flow_stopped = 0;
765 start_tty(tty);
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;
779 return 0;
780 case TCFLSH:
781 retval = tty_check_change(tty);
782 if (retval)
783 return retval;
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;
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;
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;
826 case TIOCPKT:
828 int pktmode;
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;
840 } else
841 tty->packet = 0;
842 return 0;
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;
860 EXPORT_SYMBOL(n_tty_ioctl);