tty_io: fix remaining pid struct locking
[linux-2.6-block.git] / drivers / char / tty_ioctl.c
CommitLineData
1da177e4
LT
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>
5785c95b 23#include <linux/mutex.h>
1da177e4
LT
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
edc6afc5 39#define TERMIOS_OLD 8
1da177e4 40
af9b897e
AC
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
355d95a1 53void tty_wait_until_sent(struct tty_struct *tty, long timeout)
1da177e4 54{
1da177e4
LT
55#ifdef TTY_DEBUG_WAIT_UNTIL_SENT
56 char buf[64];
355d95a1 57
1da177e4
LT
58 printk(KERN_DEBUG "%s wait until sent...\n", tty_name(tty, buf));
59#endif
60 if (!tty->driver->chars_in_buffer)
61 return;
1da177e4
LT
62 if (!timeout)
63 timeout = MAX_SCHEDULE_TIMEOUT;
5a52bd4a 64 if (wait_event_interruptible_timeout(tty->write_wait,
db99247a 65 !tty->driver->chars_in_buffer(tty), timeout) < 0)
5a52bd4a 66 return;
1da177e4
LT
67 if (tty->driver->wait_until_sent)
68 tty->driver->wait_until_sent(tty, timeout);
1da177e4 69}
1da177e4
LT
70EXPORT_SYMBOL(tty_wait_until_sent);
71
edc6afc5
AC
72static void unset_locked_termios(struct ktermios *termios,
73 struct ktermios *old,
74 struct ktermios *locked)
1da177e4
LT
75{
76 int i;
355d95a1
AC
77
78#define NOSET_MASK(x, y, z) (x = ((x) & ~(z)) | ((y) & (z)))
1da177e4
LT
79
80 if (!locked) {
81 printk(KERN_WARNING "Warning?!? termios_locked is NULL.\n");
82 return;
83 }
84
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;
355d95a1 90 for (i = 0; i < NCCS; i++)
1da177e4
LT
91 termios->c_cc[i] = locked->c_cc[i] ?
92 old->c_cc[i] : termios->c_cc[i];
edc6afc5 93 /* FIXME: What should we do for i/ospeed */
1da177e4
LT
94}
95
edc6afc5
AC
96/*
97 * Routine which returns the baud rate of the tty
98 *
99 * Note that the baud_table needs to be kept in sync with the
100 * include/asm/termbits.h file.
101 */
102static 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
111};
112
113#ifndef __sparc__
114static 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
120};
121#else
122static 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
127};
128#endif
129
130static int n_baud_table = ARRAY_SIZE(baud_table);
131
132/**
133 * tty_termios_baud_rate
134 * @termios: termios structure
135 *
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.
140 *
141 * Locking: none
142 */
143
144speed_t tty_termios_baud_rate(struct ktermios *termios)
145{
146 unsigned int cbaud;
147
148 cbaud = termios->c_cflag & CBAUD;
149
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;
157
158 if (cbaud < 1 || cbaud + 15 > n_baud_table)
159 termios->c_cflag &= ~CBAUDEX;
160 else
161 cbaud += 15;
162 }
163 return baud_table[cbaud];
164}
edc6afc5
AC
165EXPORT_SYMBOL(tty_termios_baud_rate);
166
167/**
168 * tty_termios_input_baud_rate
169 * @termios: termios structure
170 *
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.
175 *
176 * Locking: none
177 */
178
179speed_t tty_termios_input_baud_rate(struct ktermios *termios)
180{
181#ifdef IBSHIFT
182 unsigned int cbaud = (termios->c_cflag >> IBSHIFT) & CBAUD;
183
184 if (cbaud == B0)
185 return tty_termios_baud_rate(termios);
186
187 /* Magic token for arbitary speed via c_ispeed*/
188 if (cbaud == BOTHER)
189 return termios->c_ispeed;
190
191 if (cbaud & CBAUDEX) {
192 cbaud &= ~CBAUDEX;
193
194 if (cbaud < 1 || cbaud + 15 > n_baud_table)
195 termios->c_cflag &= ~(CBAUDEX << IBSHIFT);
196 else
197 cbaud += 15;
198 }
199 return baud_table[cbaud];
200#else
201 return tty_termios_baud_rate(termios);
202#endif
203}
edc6afc5
AC
204EXPORT_SYMBOL(tty_termios_input_baud_rate);
205
edc6afc5
AC
206/**
207 * tty_termios_encode_baud_rate
78137e3b 208 * @termios: ktermios structure holding user requested state
edc6afc5
AC
209 * @ispeed: input speed
210 * @ospeed: output speed
211 *
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
215 *
78137e3b
AC
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.
edc6afc5
AC
220 *
221 * Locking: Caller should hold termios lock. This is already held
222 * when calling this function from the driver termios handler.
5f519d72
AC
223 *
224 * The ifdefs deal with platforms whose owners have yet to update them
225 * and will all go away once this is done.
edc6afc5
AC
226 */
227
75e8b71d
MR
228void tty_termios_encode_baud_rate(struct ktermios *termios,
229 speed_t ibaud, speed_t obaud)
edc6afc5
AC
230{
231 int i = 0;
78137e3b
AC
232 int ifound = -1, ofound = -1;
233 int iclose = ibaud/50, oclose = obaud/50;
234 int ibinput = 0;
edc6afc5 235
5f519d72
AC
236 if (obaud == 0) /* CD dropped */
237 ibaud = 0; /* Clear ibaud to be sure */
238
edc6afc5
AC
239 termios->c_ispeed = ibaud;
240 termios->c_ospeed = obaud;
241
5f519d72 242#ifdef BOTHER
78137e3b
AC
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 */
246
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 */
5f519d72 253#endif
edc6afc5 254 termios->c_cflag &= ~CBAUD;
edc6afc5 255
5f519d72
AC
256 /*
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
261 */
262
edc6afc5 263 do {
75e8b71d
MR
264 if (obaud - oclose <= baud_table[i] &&
265 obaud + oclose >= baud_table[i]) {
edc6afc5 266 termios->c_cflag |= baud_bits[i];
78137e3b 267 ofound = i;
edc6afc5 268 }
75e8b71d
MR
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 */
5f519d72
AC
273 if (ofound == i && !ibinput)
274 ifound = i;
275#ifdef IBSHIFT
276 else {
277 ifound = i;
78137e3b 278 termios->c_cflag |= (baud_bits[i] << IBSHIFT);
5f519d72
AC
279 }
280#endif
edc6afc5 281 }
6804396f 282 } while (++i < n_baud_table);
5f519d72
AC
283
284 /*
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.
287 */
288#ifdef BOTHER
78137e3b 289 if (ofound == -1)
edc6afc5 290 termios->c_cflag |= BOTHER;
78137e3b
AC
291 /* Set exact input bits only if the input and output differ or the
292 user already did */
6804396f 293 if (ifound == -1 && (ibaud != obaud || ibinput))
edc6afc5 294 termios->c_cflag |= (BOTHER << IBSHIFT);
5f519d72
AC
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");
301 }
302#endif
edc6afc5 303}
edc6afc5
AC
304EXPORT_SYMBOL_GPL(tty_termios_encode_baud_rate);
305
5f519d72
AC
306void tty_encode_baud_rate(struct tty_struct *tty, speed_t ibaud, speed_t obaud)
307{
308 tty_termios_encode_baud_rate(tty->termios, ibaud, obaud);
309}
310EXPORT_SYMBOL_GPL(tty_encode_baud_rate);
edc6afc5
AC
311
312/**
313 * tty_get_baud_rate - get tty bit rates
314 * @tty: tty to query
315 *
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.
319 *
320 * Locking: none
321 */
322
323speed_t tty_get_baud_rate(struct tty_struct *tty)
324{
325 speed_t baud = tty_termios_baud_rate(tty->termios);
326
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;
332 }
333 baud = tty->alt_speed;
334 }
335
336 return baud;
337}
edc6afc5
AC
338EXPORT_SYMBOL(tty_get_baud_rate);
339
5f519d72
AC
340/**
341 * tty_termios_copy_hw - copy hardware settings
342 * @new: New termios
343 * @old: Old termios
344 *
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
349 */
350
351void tty_termios_copy_hw(struct ktermios *new, struct ktermios *old)
352{
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;
359}
5f519d72
AC
360EXPORT_SYMBOL(tty_termios_copy_hw);
361
bf5e5834
AC
362/**
363 * tty_termios_hw_change - check for setting change
364 * @a: termios
365 * @b: termios to compare
366 *
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.
369 */
370
371int tty_termios_hw_change(struct ktermios *a, struct ktermios *b)
372{
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;
378}
379EXPORT_SYMBOL(tty_termios_hw_change);
380
af9b897e
AC
381/**
382 * change_termios - update termios values
383 * @tty: tty to update
384 * @new_termios: desired new value
385 *
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.
389 *
390 * Locking: termios_sem
391 */
392
355d95a1 393static void change_termios(struct tty_struct *tty, struct ktermios *new_termios)
1da177e4
LT
394{
395 int canon_change;
edc6afc5 396 struct ktermios old_termios = *tty->termios;
1da177e4 397 struct tty_ldisc *ld;
04f378b1 398 unsigned long flags;
355d95a1 399
1da177e4
LT
400 /*
401 * Perform the actual termios internal changes under lock.
402 */
355d95a1 403
1da177e4
LT
404
405 /* FIXME: we need to decide on some locking/ordering semantics
406 for the set_termios notification eventually */
5785c95b 407 mutex_lock(&tty->termios_mutex);
1da177e4
LT
408
409 *tty->termios = *new_termios;
410 unset_locked_termios(tty->termios, &old_termios, tty->termios_locked);
411 canon_change = (old_termios.c_lflag ^ tty->termios->c_lflag) & ICANON;
412 if (canon_change) {
413 memset(&tty->read_flags, 0, sizeof tty->read_flags);
414 tty->canon_head = tty->read_tail;
415 tty->canon_data = 0;
416 tty->erasing = 0;
417 }
355d95a1 418
5f519d72 419 /* This bit should be in the ldisc code */
1da177e4
LT
420 if (canon_change && !L_ICANON(tty) && tty->read_cnt)
421 /* Get characters left over from canonical mode. */
422 wake_up_interruptible(&tty->read_wait);
423
424 /* See if packet mode change of state. */
1da177e4
LT
425 if (tty->link && tty->link->packet) {
426 int old_flow = ((old_termios.c_iflag & IXON) &&
427 (old_termios.c_cc[VSTOP] == '\023') &&
428 (old_termios.c_cc[VSTART] == '\021'));
429 int new_flow = (I_IXON(tty) &&
430 STOP_CHAR(tty) == '\023' &&
431 START_CHAR(tty) == '\021');
432 if (old_flow != new_flow) {
04f378b1 433 spin_lock_irqsave(&tty->ctrl_lock, flags);
1da177e4
LT
434 tty->ctrl_status &= ~(TIOCPKT_DOSTOP | TIOCPKT_NOSTOP);
435 if (new_flow)
436 tty->ctrl_status |= TIOCPKT_DOSTOP;
437 else
438 tty->ctrl_status |= TIOCPKT_NOSTOP;
04f378b1 439 spin_unlock_irqrestore(&tty->ctrl_lock, flags);
1da177e4
LT
440 wake_up_interruptible(&tty->link->read_wait);
441 }
442 }
355d95a1 443
1da177e4
LT
444 if (tty->driver->set_termios)
445 (*tty->driver->set_termios)(tty, &old_termios);
5f519d72
AC
446 else
447 tty_termios_copy_hw(tty->termios, &old_termios);
1da177e4
LT
448
449 ld = tty_ldisc_ref(tty);
450 if (ld != NULL) {
451 if (ld->set_termios)
452 (ld->set_termios)(tty, &old_termios);
453 tty_ldisc_deref(ld);
454 }
5785c95b 455 mutex_unlock(&tty->termios_mutex);
1da177e4
LT
456}
457
af9b897e
AC
458/**
459 * set_termios - set termios values for a tty
460 * @tty: terminal device
461 * @arg: user data
462 * @opt: option information
463 *
3a4fa0a2 464 * Helper function to prepare termios data and run necessary other
af9b897e
AC
465 * functions before using change_termios to do the actual changes.
466 *
467 * Locking:
468 * Called functions take ldisc and termios_sem locks
469 */
470
355d95a1 471static int set_termios(struct tty_struct *tty, void __user *arg, int opt)
1da177e4 472{
edc6afc5 473 struct ktermios tmp_termios;
1da177e4
LT
474 struct tty_ldisc *ld;
475 int retval = tty_check_change(tty);
476
477 if (retval)
478 return retval;
479
64bb6c5e
AC
480 memcpy(&tmp_termios, tty->termios, sizeof(struct ktermios));
481
1da177e4 482 if (opt & TERMIOS_TERMIO) {
1da177e4
LT
483 if (user_termio_to_kernel_termios(&tmp_termios,
484 (struct termio __user *)arg))
485 return -EFAULT;
edc6afc5
AC
486#ifdef TCGETS2
487 } else if (opt & TERMIOS_OLD) {
edc6afc5 488 if (user_termios_to_kernel_termios_1(&tmp_termios,
64bb6c5e 489 (struct termios __user *)arg))
edc6afc5 490 return -EFAULT;
1da177e4
LT
491 } else {
492 if (user_termios_to_kernel_termios(&tmp_termios,
64bb6c5e 493 (struct termios2 __user *)arg))
1da177e4
LT
494 return -EFAULT;
495 }
64bb6c5e
AC
496#else
497 } else if (user_termios_to_kernel_termios(&tmp_termios,
498 (struct termios __user *)arg))
499 return -EFAULT;
500#endif
1da177e4 501
355d95a1
AC
502 /* If old style Bfoo values are used then load c_ispeed/c_ospeed
503 * with the real speed so its unconditionally usable */
edc6afc5
AC
504 tmp_termios.c_ispeed = tty_termios_input_baud_rate(&tmp_termios);
505 tmp_termios.c_ospeed = tty_termios_baud_rate(&tmp_termios);
506
1da177e4 507 ld = tty_ldisc_ref(tty);
355d95a1 508
1da177e4
LT
509 if (ld != NULL) {
510 if ((opt & TERMIOS_FLUSH) && ld->flush_buffer)
511 ld->flush_buffer(tty);
512 tty_ldisc_deref(ld);
513 }
355d95a1 514
1da177e4
LT
515 if (opt & TERMIOS_WAIT) {
516 tty_wait_until_sent(tty, 0);
517 if (signal_pending(current))
518 return -EINTR;
519 }
520
521 change_termios(tty, &tmp_termios);
5f519d72
AC
522
523 /* FIXME: Arguably if tmp_termios == tty->termios AND the
524 actual requested termios was not tmp_termios then we may
525 want to return an error as no user requested change has
526 succeeded */
1da177e4
LT
527 return 0;
528}
529
355d95a1 530static int get_termio(struct tty_struct *tty, struct termio __user *termio)
1da177e4
LT
531{
532 if (kernel_termios_to_user_termio(termio, tty->termios))
533 return -EFAULT;
534 return 0;
535}
536
355d95a1 537static unsigned long inq_canon(struct tty_struct *tty)
1da177e4
LT
538{
539 int nr, head, tail;
540
541 if (!tty->canon_data || !tty->read_buf)
542 return 0;
543 head = tty->canon_head;
544 tail = tty->read_tail;
545 nr = (head - tail) & (N_TTY_BUF_SIZE-1);
546 /* Skip EOF-chars.. */
547 while (head != tail) {
548 if (test_bit(tail, tty->read_flags) &&
549 tty->read_buf[tail] == __DISABLED_CHAR)
550 nr--;
551 tail = (tail+1) & (N_TTY_BUF_SIZE-1);
552 }
553 return nr;
554}
555
556#ifdef TIOCGETP
557/*
558 * These are deprecated, but there is limited support..
559 *
560 * The "sg_flags" translation is a joke..
561 */
355d95a1 562static int get_sgflags(struct tty_struct *tty)
1da177e4
LT
563{
564 int flags = 0;
565
566 if (!(tty->termios->c_lflag & ICANON)) {
567 if (tty->termios->c_lflag & ISIG)
568 flags |= 0x02; /* cbreak */
569 else
570 flags |= 0x20; /* raw */
571 }
572 if (tty->termios->c_lflag & ECHO)
573 flags |= 0x08; /* echo */
574 if (tty->termios->c_oflag & OPOST)
575 if (tty->termios->c_oflag & ONLCR)
576 flags |= 0x10; /* crmod */
577 return flags;
578}
579
355d95a1 580static int get_sgttyb(struct tty_struct *tty, struct sgttyb __user *sgttyb)
1da177e4
LT
581{
582 struct sgttyb tmp;
583
5785c95b 584 mutex_lock(&tty->termios_mutex);
606d099c
AC
585 tmp.sg_ispeed = tty->termios->c_ispeed;
586 tmp.sg_ospeed = tty->termios->c_ospeed;
1da177e4
LT
587 tmp.sg_erase = tty->termios->c_cc[VERASE];
588 tmp.sg_kill = tty->termios->c_cc[VKILL];
589 tmp.sg_flags = get_sgflags(tty);
5785c95b 590 mutex_unlock(&tty->termios_mutex);
355d95a1 591
1da177e4
LT
592 return copy_to_user(sgttyb, &tmp, sizeof(tmp)) ? -EFAULT : 0;
593}
594
355d95a1 595static void set_sgflags(struct ktermios *termios, int flags)
1da177e4
LT
596{
597 termios->c_iflag = ICRNL | IXON;
598 termios->c_oflag = 0;
599 termios->c_lflag = ISIG | ICANON;
600 if (flags & 0x02) { /* cbreak */
601 termios->c_iflag = 0;
602 termios->c_lflag &= ~ICANON;
603 }
604 if (flags & 0x08) { /* echo */
605 termios->c_lflag |= ECHO | ECHOE | ECHOK |
606 ECHOCTL | ECHOKE | IEXTEN;
607 }
608 if (flags & 0x10) { /* crmod */
609 termios->c_oflag |= OPOST | ONLCR;
610 }
611 if (flags & 0x20) { /* raw */
612 termios->c_iflag = 0;
613 termios->c_lflag &= ~(ISIG | ICANON);
614 }
615 if (!(termios->c_lflag & ICANON)) {
616 termios->c_cc[VMIN] = 1;
617 termios->c_cc[VTIME] = 0;
618 }
619}
620
af9b897e
AC
621/**
622 * set_sgttyb - set legacy terminal values
623 * @tty: tty structure
624 * @sgttyb: pointer to old style terminal structure
625 *
626 * Updates a terminal from the legacy BSD style terminal information
627 * structure.
628 *
629 * Locking: termios_sem
630 */
631
355d95a1 632static int set_sgttyb(struct tty_struct *tty, struct sgttyb __user *sgttyb)
1da177e4
LT
633{
634 int retval;
635 struct sgttyb tmp;
edc6afc5 636 struct ktermios termios;
1da177e4
LT
637
638 retval = tty_check_change(tty);
639 if (retval)
640 return retval;
355d95a1 641
1da177e4
LT
642 if (copy_from_user(&tmp, sgttyb, sizeof(tmp)))
643 return -EFAULT;
644
5785c95b 645 mutex_lock(&tty->termios_mutex);
6804396f 646 termios = *tty->termios;
1da177e4
LT
647 termios.c_cc[VERASE] = tmp.sg_erase;
648 termios.c_cc[VKILL] = tmp.sg_kill;
649 set_sgflags(&termios, tmp.sg_flags);
edc6afc5
AC
650 /* Try and encode into Bfoo format */
651#ifdef BOTHER
355d95a1
AC
652 tty_termios_encode_baud_rate(&termios, termios.c_ispeed,
653 termios.c_ospeed);
edc6afc5 654#endif
5785c95b 655 mutex_unlock(&tty->termios_mutex);
1da177e4
LT
656 change_termios(tty, &termios);
657 return 0;
658}
659#endif
660
661#ifdef TIOCGETC
355d95a1 662static int get_tchars(struct tty_struct *tty, struct tchars __user *tchars)
1da177e4
LT
663{
664 struct tchars tmp;
665
666 tmp.t_intrc = tty->termios->c_cc[VINTR];
667 tmp.t_quitc = tty->termios->c_cc[VQUIT];
668 tmp.t_startc = tty->termios->c_cc[VSTART];
669 tmp.t_stopc = tty->termios->c_cc[VSTOP];
670 tmp.t_eofc = tty->termios->c_cc[VEOF];
671 tmp.t_brkc = tty->termios->c_cc[VEOL2]; /* what is brkc anyway? */
672 return copy_to_user(tchars, &tmp, sizeof(tmp)) ? -EFAULT : 0;
673}
674
355d95a1 675static int set_tchars(struct tty_struct *tty, struct tchars __user *tchars)
1da177e4
LT
676{
677 struct tchars tmp;
678
679 if (copy_from_user(&tmp, tchars, sizeof(tmp)))
680 return -EFAULT;
681 tty->termios->c_cc[VINTR] = tmp.t_intrc;
682 tty->termios->c_cc[VQUIT] = tmp.t_quitc;
683 tty->termios->c_cc[VSTART] = tmp.t_startc;
684 tty->termios->c_cc[VSTOP] = tmp.t_stopc;
685 tty->termios->c_cc[VEOF] = tmp.t_eofc;
686 tty->termios->c_cc[VEOL2] = tmp.t_brkc; /* what is brkc anyway? */
687 return 0;
688}
689#endif
690
691#ifdef TIOCGLTC
355d95a1 692static int get_ltchars(struct tty_struct *tty, struct ltchars __user *ltchars)
1da177e4
LT
693{
694 struct ltchars tmp;
695
696 tmp.t_suspc = tty->termios->c_cc[VSUSP];
355d95a1
AC
697 /* what is dsuspc anyway? */
698 tmp.t_dsuspc = tty->termios->c_cc[VSUSP];
1da177e4 699 tmp.t_rprntc = tty->termios->c_cc[VREPRINT];
355d95a1
AC
700 /* what is flushc anyway? */
701 tmp.t_flushc = tty->termios->c_cc[VEOL2];
1da177e4
LT
702 tmp.t_werasc = tty->termios->c_cc[VWERASE];
703 tmp.t_lnextc = tty->termios->c_cc[VLNEXT];
704 return copy_to_user(ltchars, &tmp, sizeof(tmp)) ? -EFAULT : 0;
705}
706
355d95a1 707static int set_ltchars(struct tty_struct *tty, struct ltchars __user *ltchars)
1da177e4
LT
708{
709 struct ltchars tmp;
710
711 if (copy_from_user(&tmp, ltchars, sizeof(tmp)))
712 return -EFAULT;
713
714 tty->termios->c_cc[VSUSP] = tmp.t_suspc;
355d95a1
AC
715 /* what is dsuspc anyway? */
716 tty->termios->c_cc[VEOL2] = tmp.t_dsuspc;
1da177e4 717 tty->termios->c_cc[VREPRINT] = tmp.t_rprntc;
355d95a1
AC
718 /* what is flushc anyway? */
719 tty->termios->c_cc[VEOL2] = tmp.t_flushc;
1da177e4
LT
720 tty->termios->c_cc[VWERASE] = tmp.t_werasc;
721 tty->termios->c_cc[VLNEXT] = tmp.t_lnextc;
722 return 0;
723}
724#endif
725
af9b897e
AC
726/**
727 * send_prio_char - send priority character
728 *
729 * Send a high priority character to the tty even if stopped
730 *
5f412b24 731 * Locking: none for xchar method, write ordering for write method.
1da177e4 732 */
af9b897e 733
5f412b24 734static int send_prio_char(struct tty_struct *tty, char ch)
1da177e4
LT
735{
736 int was_stopped = tty->stopped;
737
738 if (tty->driver->send_xchar) {
739 tty->driver->send_xchar(tty, ch);
5f412b24 740 return 0;
1da177e4 741 }
5f412b24 742
9c1729db 743 if (tty_write_lock(tty, 0) < 0)
5f412b24
AC
744 return -ERESTARTSYS;
745
1da177e4
LT
746 if (was_stopped)
747 start_tty(tty);
748 tty->driver->write(tty, &ch, 1);
749 if (was_stopped)
750 stop_tty(tty);
9c1729db 751 tty_write_unlock(tty);
5f412b24 752 return 0;
1da177e4
LT
753}
754
0fc00e24
AC
755/**
756 * tty_mode_ioctl - mode related ioctls
757 * @tty: tty for the ioctl
758 * @file: file pointer for the tty
759 * @cmd: command
760 * @arg: ioctl argument
761 *
762 * Perform non line discipline specific mode control ioctls. This
763 * is designed to be called by line disciplines to ensure they provide
764 * consistent mode setting.
765 */
766
355d95a1 767int tty_mode_ioctl(struct tty_struct *tty, struct file *file,
0fc00e24 768 unsigned int cmd, unsigned long arg)
1da177e4 769{
355d95a1 770 struct tty_struct *real_tty;
1da177e4 771 void __user *p = (void __user *)arg;
1da177e4
LT
772
773 if (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
774 tty->driver->subtype == PTY_TYPE_MASTER)
775 real_tty = tty->link;
776 else
777 real_tty = tty;
778
779 switch (cmd) {
780#ifdef TIOCGETP
355d95a1
AC
781 case TIOCGETP:
782 return get_sgttyb(real_tty, (struct sgttyb __user *) arg);
783 case TIOCSETP:
784 case TIOCSETN:
785 return set_sgttyb(real_tty, (struct sgttyb __user *) arg);
1da177e4
LT
786#endif
787#ifdef TIOCGETC
355d95a1
AC
788 case TIOCGETC:
789 return get_tchars(real_tty, p);
790 case TIOCSETC:
791 return set_tchars(real_tty, p);
1da177e4
LT
792#endif
793#ifdef TIOCGLTC
355d95a1
AC
794 case TIOCGLTC:
795 return get_ltchars(real_tty, p);
796 case TIOCSLTC:
797 return set_ltchars(real_tty, p);
1da177e4 798#endif
355d95a1
AC
799 case TCSETSF:
800 return set_termios(real_tty, p, TERMIOS_FLUSH | TERMIOS_WAIT | TERMIOS_OLD);
801 case TCSETSW:
802 return set_termios(real_tty, p, TERMIOS_WAIT | TERMIOS_OLD);
803 case TCSETS:
804 return set_termios(real_tty, p, TERMIOS_OLD);
edc6afc5 805#ifndef TCGETS2
355d95a1
AC
806 case TCGETS:
807 if (kernel_termios_to_user_termios((struct termios __user *)arg, real_tty->termios))
808 return -EFAULT;
809 return 0;
edc6afc5 810#else
355d95a1
AC
811 case TCGETS:
812 if (kernel_termios_to_user_termios_1((struct termios __user *)arg, real_tty->termios))
813 return -EFAULT;
814 return 0;
815 case TCGETS2:
816 if (kernel_termios_to_user_termios((struct termios2 __user *)arg, real_tty->termios))
817 return -EFAULT;
818 return 0;
819 case TCSETSF2:
820 return set_termios(real_tty, p, TERMIOS_FLUSH | TERMIOS_WAIT);
821 case TCSETSW2:
822 return set_termios(real_tty, p, TERMIOS_WAIT);
823 case TCSETS2:
824 return set_termios(real_tty, p, 0);
edc6afc5 825#endif
355d95a1
AC
826 case TCGETA:
827 return get_termio(real_tty, p);
828 case TCSETAF:
829 return set_termios(real_tty, p, TERMIOS_FLUSH | TERMIOS_WAIT | TERMIOS_TERMIO);
830 case TCSETAW:
831 return set_termios(real_tty, p, TERMIOS_WAIT | TERMIOS_TERMIO);
832 case TCSETA:
833 return set_termios(real_tty, p, TERMIOS_TERMIO);
0fc00e24 834#ifndef TCGETS2
355d95a1
AC
835 case TIOCGLCKTRMIOS:
836 if (kernel_termios_to_user_termios((struct termios __user *)arg, real_tty->termios_locked))
837 return -EFAULT;
838 return 0;
839 case TIOCSLCKTRMIOS:
840 if (!capable(CAP_SYS_ADMIN))
841 return -EPERM;
842 if (user_termios_to_kernel_termios(real_tty->termios_locked,
843 (struct termios __user *) arg))
844 return -EFAULT;
845 return 0;
0fc00e24 846#else
355d95a1
AC
847 case TIOCGLCKTRMIOS:
848 if (kernel_termios_to_user_termios_1((struct termios __user *)arg, real_tty->termios_locked))
849 return -EFAULT;
850 return 0;
851 case TIOCSLCKTRMIOS:
852 if (!capable(CAP_SYS_ADMIN))
853 return -EPERM;
854 if (user_termios_to_kernel_termios_1(real_tty->termios_locked,
855 (struct termios __user *) arg))
856 return -EFAULT;
0fc00e24
AC
857 return 0;
858#endif
355d95a1
AC
859 case TIOCGSOFTCAR:
860 return put_user(C_CLOCAL(tty) ? 1 : 0,
861 (int __user *)arg);
862 case TIOCSSOFTCAR:
863 if (get_user(arg, (unsigned int __user *) arg))
864 return -EFAULT;
865 mutex_lock(&tty->termios_mutex);
866 tty->termios->c_cflag =
867 ((tty->termios->c_cflag & ~CLOCAL) |
868 (arg ? CLOCAL : 0));
869 mutex_unlock(&tty->termios_mutex);
870 return 0;
871 default:
872 return -ENOIOCTLCMD;
0fc00e24
AC
873 }
874}
0fc00e24
AC
875EXPORT_SYMBOL_GPL(tty_mode_ioctl);
876
877int tty_perform_flush(struct tty_struct *tty, unsigned long arg)
878{
879 struct tty_ldisc *ld;
880 int retval = tty_check_change(tty);
881 if (retval)
882 return retval;
883
884 ld = tty_ldisc_ref(tty);
885 switch (arg) {
886 case TCIFLUSH:
887 if (ld && ld->flush_buffer)
888 ld->flush_buffer(tty);
889 break;
890 case TCIOFLUSH:
891 if (ld && ld->flush_buffer)
892 ld->flush_buffer(tty);
893 /* fall through */
894 case TCOFLUSH:
895 if (tty->driver->flush_buffer)
896 tty->driver->flush_buffer(tty);
897 break;
898 default:
899 tty_ldisc_deref(ld);
900 return -EINVAL;
901 }
902 tty_ldisc_deref(ld);
903 return 0;
904}
0fc00e24
AC
905EXPORT_SYMBOL_GPL(tty_perform_flush);
906
355d95a1 907int n_tty_ioctl(struct tty_struct *tty, struct file *file,
0fc00e24
AC
908 unsigned int cmd, unsigned long arg)
909{
355d95a1 910 struct tty_struct *real_tty;
04f378b1 911 unsigned long flags;
0fc00e24
AC
912 int retval;
913
914 if (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
915 tty->driver->subtype == PTY_TYPE_MASTER)
916 real_tty = tty->link;
917 else
918 real_tty = tty;
919
920 switch (cmd) {
355d95a1
AC
921 case TCXONC:
922 retval = tty_check_change(tty);
923 if (retval)
924 return retval;
925 switch (arg) {
926 case TCOOFF:
927 if (!tty->flow_stopped) {
928 tty->flow_stopped = 1;
929 stop_tty(tty);
1da177e4 930 }
355d95a1
AC
931 break;
932 case TCOON:
933 if (tty->flow_stopped) {
934 tty->flow_stopped = 0;
935 start_tty(tty);
936 }
937 break;
938 case TCIOFF:
939 if (STOP_CHAR(tty) != __DISABLED_CHAR)
940 return send_prio_char(tty, STOP_CHAR(tty));
941 break;
942 case TCION:
943 if (START_CHAR(tty) != __DISABLED_CHAR)
944 return send_prio_char(tty, START_CHAR(tty));
945 break;
1da177e4 946 default:
355d95a1 947 return -EINVAL;
1da177e4 948 }
355d95a1
AC
949 return 0;
950 case TCFLSH:
951 return tty_perform_flush(tty, arg);
952 case TIOCOUTQ:
953 return put_user(tty->driver->chars_in_buffer ?
954 tty->driver->chars_in_buffer(tty) : 0,
955 (int __user *) arg);
956 case TIOCINQ:
957 retval = tty->read_cnt;
958 if (L_ICANON(tty))
959 retval = inq_canon(tty);
960 return put_user(retval, (unsigned int __user *) arg);
961 case TIOCPKT:
962 {
963 int pktmode;
964
965 if (tty->driver->type != TTY_DRIVER_TYPE_PTY ||
966 tty->driver->subtype != PTY_TYPE_MASTER)
967 return -ENOTTY;
968 if (get_user(pktmode, (int __user *) arg))
969 return -EFAULT;
04f378b1 970 spin_lock_irqsave(&tty->ctrl_lock, flags);
355d95a1
AC
971 if (pktmode) {
972 if (!tty->packet) {
973 tty->packet = 1;
974 tty->link->ctrl_status = 0;
975 }
976 } else
977 tty->packet = 0;
04f378b1 978 spin_unlock_irqrestore(&tty->ctrl_lock, flags);
355d95a1
AC
979 return 0;
980 }
981 default:
982 /* Try the mode commands */
983 return tty_mode_ioctl(tty, file, cmd, arg);
984 }
1da177e4 985}
1da177e4 986EXPORT_SYMBOL(n_tty_ioctl);