]> bbs.cooldavid.org Git - net-next-2.6.git/blame - drivers/char/tty_ioctl.c
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/penberg...
[net-next-2.6.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>
0ee9cbb3 24#include <linux/smp_lock.h>
1da177e4
LT
25
26#include <asm/io.h>
27#include <asm/uaccess.h>
28#include <asm/system.h>
29
30#undef TTY_DEBUG_WAIT_UNTIL_SENT
31
32#undef DEBUG
33
34/*
35 * Internal flag options for termios setting behavior
36 */
37#define TERMIOS_FLUSH 1
38#define TERMIOS_WAIT 2
39#define TERMIOS_TERMIO 4
edc6afc5 40#define TERMIOS_OLD 8
1da177e4 41
af9b897e 42
d81ed103
AC
43/**
44 * tty_chars_in_buffer - characters pending
45 * @tty: terminal
46 *
47 * Return the number of bytes of data in the device private
48 * output queue. If no private method is supplied there is assumed
49 * to be no queue on the device.
50 */
51
f34d7a5b
AC
52int tty_chars_in_buffer(struct tty_struct *tty)
53{
54 if (tty->ops->chars_in_buffer)
55 return tty->ops->chars_in_buffer(tty);
56 else
57 return 0;
58}
f34d7a5b
AC
59EXPORT_SYMBOL(tty_chars_in_buffer);
60
d81ed103
AC
61/**
62 * tty_write_room - write queue space
63 * @tty: terminal
64 *
65 * Return the number of bytes that can be queued to this device
66 * at the present time. The result should be treated as a guarantee
67 * and the driver cannot offer a value it later shrinks by more than
68 * the number of bytes written. If no method is provided 2K is always
69 * returned and data may be lost as there will be no flow control.
70 */
71
f34d7a5b
AC
72int tty_write_room(struct tty_struct *tty)
73{
74 if (tty->ops->write_room)
75 return tty->ops->write_room(tty);
76 return 2048;
77}
f34d7a5b
AC
78EXPORT_SYMBOL(tty_write_room);
79
d81ed103
AC
80/**
81 * tty_driver_flush_buffer - discard internal buffer
82 * @tty: terminal
83 *
84 * Discard the internal output buffer for this device. If no method
85 * is provided then either the buffer cannot be hardware flushed or
86 * there is no buffer driver side.
87 */
f34d7a5b
AC
88void tty_driver_flush_buffer(struct tty_struct *tty)
89{
90 if (tty->ops->flush_buffer)
91 tty->ops->flush_buffer(tty);
92}
f34d7a5b
AC
93EXPORT_SYMBOL(tty_driver_flush_buffer);
94
d81ed103
AC
95/**
96 * tty_throttle - flow control
97 * @tty: terminal
98 *
99 * Indicate that a tty should stop transmitting data down the stack.
100 */
101
39c2e60f
AC
102void tty_throttle(struct tty_struct *tty)
103{
104 /* check TTY_THROTTLED first so it indicates our state */
105 if (!test_and_set_bit(TTY_THROTTLED, &tty->flags) &&
106 tty->ops->throttle)
107 tty->ops->throttle(tty);
108}
109EXPORT_SYMBOL(tty_throttle);
110
d81ed103
AC
111/**
112 * tty_unthrottle - flow control
113 * @tty: terminal
114 *
115 * Indicate that a tty may continue transmitting data down the stack.
116 */
117
39c2e60f
AC
118void tty_unthrottle(struct tty_struct *tty)
119{
120 if (test_and_clear_bit(TTY_THROTTLED, &tty->flags) &&
121 tty->ops->unthrottle)
122 tty->ops->unthrottle(tty);
123}
124EXPORT_SYMBOL(tty_unthrottle);
f34d7a5b 125
af9b897e
AC
126/**
127 * tty_wait_until_sent - wait for I/O to finish
128 * @tty: tty we are waiting for
129 * @timeout: how long we will wait
130 *
131 * Wait for characters pending in a tty driver to hit the wire, or
132 * for a timeout to occur (eg due to flow control)
133 *
134 * Locking: none
135 */
136
355d95a1 137void tty_wait_until_sent(struct tty_struct *tty, long timeout)
1da177e4 138{
1da177e4
LT
139#ifdef TTY_DEBUG_WAIT_UNTIL_SENT
140 char buf[64];
355d95a1 141
1da177e4
LT
142 printk(KERN_DEBUG "%s wait until sent...\n", tty_name(tty, buf));
143#endif
1da177e4
LT
144 if (!timeout)
145 timeout = MAX_SCHEDULE_TIMEOUT;
5a52bd4a 146 if (wait_event_interruptible_timeout(tty->write_wait,
f34d7a5b
AC
147 !tty_chars_in_buffer(tty), timeout) >= 0) {
148 if (tty->ops->wait_until_sent)
149 tty->ops->wait_until_sent(tty, timeout);
0ee9cbb3 150 }
1da177e4 151}
1da177e4
LT
152EXPORT_SYMBOL(tty_wait_until_sent);
153
d81ed103
AC
154
155/*
156 * Termios Helper Methods
157 */
158
edc6afc5
AC
159static void unset_locked_termios(struct ktermios *termios,
160 struct ktermios *old,
161 struct ktermios *locked)
1da177e4
LT
162{
163 int i;
355d95a1
AC
164
165#define NOSET_MASK(x, y, z) (x = ((x) & ~(z)) | ((y) & (z)))
1da177e4
LT
166
167 if (!locked) {
168 printk(KERN_WARNING "Warning?!? termios_locked is NULL.\n");
169 return;
170 }
171
172 NOSET_MASK(termios->c_iflag, old->c_iflag, locked->c_iflag);
173 NOSET_MASK(termios->c_oflag, old->c_oflag, locked->c_oflag);
174 NOSET_MASK(termios->c_cflag, old->c_cflag, locked->c_cflag);
175 NOSET_MASK(termios->c_lflag, old->c_lflag, locked->c_lflag);
176 termios->c_line = locked->c_line ? old->c_line : termios->c_line;
355d95a1 177 for (i = 0; i < NCCS; i++)
1da177e4
LT
178 termios->c_cc[i] = locked->c_cc[i] ?
179 old->c_cc[i] : termios->c_cc[i];
edc6afc5 180 /* FIXME: What should we do for i/ospeed */
1da177e4
LT
181}
182
edc6afc5
AC
183/*
184 * Routine which returns the baud rate of the tty
185 *
186 * Note that the baud_table needs to be kept in sync with the
187 * include/asm/termbits.h file.
188 */
189static const speed_t baud_table[] = {
190 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
191 9600, 19200, 38400, 57600, 115200, 230400, 460800,
192#ifdef __sparc__
193 76800, 153600, 307200, 614400, 921600
194#else
195 500000, 576000, 921600, 1000000, 1152000, 1500000, 2000000,
196 2500000, 3000000, 3500000, 4000000
197#endif
198};
199
200#ifndef __sparc__
201static const tcflag_t baud_bits[] = {
202 B0, B50, B75, B110, B134, B150, B200, B300, B600,
203 B1200, B1800, B2400, B4800, B9600, B19200, B38400,
204 B57600, B115200, B230400, B460800, B500000, B576000,
205 B921600, B1000000, B1152000, B1500000, B2000000, B2500000,
206 B3000000, B3500000, B4000000
207};
208#else
209static const tcflag_t baud_bits[] = {
210 B0, B50, B75, B110, B134, B150, B200, B300, B600,
211 B1200, B1800, B2400, B4800, B9600, B19200, B38400,
212 B57600, B115200, B230400, B460800, B76800, B153600,
213 B307200, B614400, B921600
214};
215#endif
216
217static int n_baud_table = ARRAY_SIZE(baud_table);
218
219/**
220 * tty_termios_baud_rate
221 * @termios: termios structure
222 *
223 * Convert termios baud rate data into a speed. This should be called
224 * with the termios lock held if this termios is a terminal termios
225 * structure. May change the termios data. Device drivers can call this
226 * function but should use ->c_[io]speed directly as they are updated.
227 *
228 * Locking: none
229 */
230
231speed_t tty_termios_baud_rate(struct ktermios *termios)
232{
233 unsigned int cbaud;
234
235 cbaud = termios->c_cflag & CBAUD;
236
237#ifdef BOTHER
238 /* Magic token for arbitary speed via c_ispeed/c_ospeed */
239 if (cbaud == BOTHER)
240 return termios->c_ospeed;
241#endif
242 if (cbaud & CBAUDEX) {
243 cbaud &= ~CBAUDEX;
244
245 if (cbaud < 1 || cbaud + 15 > n_baud_table)
246 termios->c_cflag &= ~CBAUDEX;
247 else
248 cbaud += 15;
249 }
250 return baud_table[cbaud];
251}
edc6afc5
AC
252EXPORT_SYMBOL(tty_termios_baud_rate);
253
254/**
255 * tty_termios_input_baud_rate
256 * @termios: termios structure
257 *
258 * Convert termios baud rate data into a speed. This should be called
259 * with the termios lock held if this termios is a terminal termios
260 * structure. May change the termios data. Device drivers can call this
261 * function but should use ->c_[io]speed directly as they are updated.
262 *
263 * Locking: none
264 */
265
266speed_t tty_termios_input_baud_rate(struct ktermios *termios)
267{
268#ifdef IBSHIFT
269 unsigned int cbaud = (termios->c_cflag >> IBSHIFT) & CBAUD;
270
271 if (cbaud == B0)
272 return tty_termios_baud_rate(termios);
273
274 /* Magic token for arbitary speed via c_ispeed*/
275 if (cbaud == BOTHER)
276 return termios->c_ispeed;
277
278 if (cbaud & CBAUDEX) {
279 cbaud &= ~CBAUDEX;
280
281 if (cbaud < 1 || cbaud + 15 > n_baud_table)
282 termios->c_cflag &= ~(CBAUDEX << IBSHIFT);
283 else
284 cbaud += 15;
285 }
286 return baud_table[cbaud];
287#else
288 return tty_termios_baud_rate(termios);
289#endif
290}
edc6afc5
AC
291EXPORT_SYMBOL(tty_termios_input_baud_rate);
292
edc6afc5
AC
293/**
294 * tty_termios_encode_baud_rate
78137e3b 295 * @termios: ktermios structure holding user requested state
edc6afc5
AC
296 * @ispeed: input speed
297 * @ospeed: output speed
298 *
299 * Encode the speeds set into the passed termios structure. This is
300 * used as a library helper for drivers os that they can report back
301 * the actual speed selected when it differs from the speed requested
302 *
78137e3b
AC
303 * For maximal back compatibility with legacy SYS5/POSIX *nix behaviour
304 * we need to carefully set the bits when the user does not get the
305 * desired speed. We allow small margins and preserve as much of possible
306 * of the input intent to keep compatiblity.
edc6afc5
AC
307 *
308 * Locking: Caller should hold termios lock. This is already held
309 * when calling this function from the driver termios handler.
5f519d72
AC
310 *
311 * The ifdefs deal with platforms whose owners have yet to update them
312 * and will all go away once this is done.
edc6afc5
AC
313 */
314
75e8b71d
MR
315void tty_termios_encode_baud_rate(struct ktermios *termios,
316 speed_t ibaud, speed_t obaud)
edc6afc5
AC
317{
318 int i = 0;
78137e3b
AC
319 int ifound = -1, ofound = -1;
320 int iclose = ibaud/50, oclose = obaud/50;
321 int ibinput = 0;
edc6afc5 322
5f519d72
AC
323 if (obaud == 0) /* CD dropped */
324 ibaud = 0; /* Clear ibaud to be sure */
325
edc6afc5
AC
326 termios->c_ispeed = ibaud;
327 termios->c_ospeed = obaud;
328
5f519d72 329#ifdef BOTHER
78137e3b
AC
330 /* If the user asked for a precise weird speed give a precise weird
331 answer. If they asked for a Bfoo speed they many have problems
332 digesting non-exact replies so fuzz a bit */
333
334 if ((termios->c_cflag & CBAUD) == BOTHER)
335 oclose = 0;
336 if (((termios->c_cflag >> IBSHIFT) & CBAUD) == BOTHER)
337 iclose = 0;
338 if ((termios->c_cflag >> IBSHIFT) & CBAUD)
339 ibinput = 1; /* An input speed was specified */
5f519d72 340#endif
edc6afc5 341 termios->c_cflag &= ~CBAUD;
edc6afc5 342
5f519d72
AC
343 /*
344 * Our goal is to find a close match to the standard baud rate
345 * returned. Walk the baud rate table and if we get a very close
346 * match then report back the speed as a POSIX Bxxxx value by
347 * preference
348 */
349
edc6afc5 350 do {
75e8b71d
MR
351 if (obaud - oclose <= baud_table[i] &&
352 obaud + oclose >= baud_table[i]) {
edc6afc5 353 termios->c_cflag |= baud_bits[i];
78137e3b 354 ofound = i;
edc6afc5 355 }
75e8b71d
MR
356 if (ibaud - iclose <= baud_table[i] &&
357 ibaud + iclose >= baud_table[i]) {
358 /* For the case input == output don't set IBAUD bits
359 if the user didn't do so */
5f519d72
AC
360 if (ofound == i && !ibinput)
361 ifound = i;
362#ifdef IBSHIFT
363 else {
364 ifound = i;
78137e3b 365 termios->c_cflag |= (baud_bits[i] << IBSHIFT);
5f519d72
AC
366 }
367#endif
edc6afc5 368 }
6804396f 369 } while (++i < n_baud_table);
5f519d72
AC
370
371 /*
372 * If we found no match then use BOTHER if provided or warn
373 * the user their platform maintainer needs to wake up if not.
374 */
375#ifdef BOTHER
78137e3b 376 if (ofound == -1)
edc6afc5 377 termios->c_cflag |= BOTHER;
78137e3b
AC
378 /* Set exact input bits only if the input and output differ or the
379 user already did */
6804396f 380 if (ifound == -1 && (ibaud != obaud || ibinput))
edc6afc5 381 termios->c_cflag |= (BOTHER << IBSHIFT);
5f519d72
AC
382#else
383 if (ifound == -1 || ofound == -1) {
384 static int warned;
385 if (!warned++)
386 printk(KERN_WARNING "tty: Unable to return correct "
387 "speed data as your architecture needs updating.\n");
388 }
389#endif
edc6afc5 390}
edc6afc5
AC
391EXPORT_SYMBOL_GPL(tty_termios_encode_baud_rate);
392
d81ed103
AC
393/**
394 * tty_encode_baud_rate - set baud rate of the tty
395 * @ibaud: input baud rate
396 * @obad: output baud rate
397 *
398 * Update the current termios data for the tty with the new speed
399 * settings. The caller must hold the termios_mutex for the tty in
400 * question.
401 */
402
5f519d72
AC
403void tty_encode_baud_rate(struct tty_struct *tty, speed_t ibaud, speed_t obaud)
404{
405 tty_termios_encode_baud_rate(tty->termios, ibaud, obaud);
406}
407EXPORT_SYMBOL_GPL(tty_encode_baud_rate);
edc6afc5
AC
408
409/**
410 * tty_get_baud_rate - get tty bit rates
411 * @tty: tty to query
412 *
413 * Returns the baud rate as an integer for this terminal. The
414 * termios lock must be held by the caller and the terminal bit
415 * flags may be updated.
416 *
417 * Locking: none
418 */
419
420speed_t tty_get_baud_rate(struct tty_struct *tty)
421{
422 speed_t baud = tty_termios_baud_rate(tty->termios);
423
424 if (baud == 38400 && tty->alt_speed) {
425 if (!tty->warned) {
426 printk(KERN_WARNING "Use of setserial/setrocket to "
427 "set SPD_* flags is deprecated\n");
428 tty->warned = 1;
429 }
430 baud = tty->alt_speed;
431 }
432
433 return baud;
434}
edc6afc5
AC
435EXPORT_SYMBOL(tty_get_baud_rate);
436
5f519d72
AC
437/**
438 * tty_termios_copy_hw - copy hardware settings
439 * @new: New termios
440 * @old: Old termios
441 *
442 * Propogate the hardware specific terminal setting bits from
443 * the old termios structure to the new one. This is used in cases
444 * where the hardware does not support reconfiguration or as a helper
445 * in some cases where only minimal reconfiguration is supported
446 */
447
448void tty_termios_copy_hw(struct ktermios *new, struct ktermios *old)
449{
450 /* The bits a dumb device handles in software. Smart devices need
451 to always provide a set_termios method */
452 new->c_cflag &= HUPCL | CREAD | CLOCAL;
453 new->c_cflag |= old->c_cflag & ~(HUPCL | CREAD | CLOCAL);
454 new->c_ispeed = old->c_ispeed;
455 new->c_ospeed = old->c_ospeed;
456}
5f519d72
AC
457EXPORT_SYMBOL(tty_termios_copy_hw);
458
bf5e5834
AC
459/**
460 * tty_termios_hw_change - check for setting change
461 * @a: termios
462 * @b: termios to compare
463 *
464 * Check if any of the bits that affect a dumb device have changed
465 * between the two termios structures, or a speed change is needed.
466 */
467
468int tty_termios_hw_change(struct ktermios *a, struct ktermios *b)
469{
470 if (a->c_ispeed != b->c_ispeed || a->c_ospeed != b->c_ospeed)
471 return 1;
472 if ((a->c_cflag ^ b->c_cflag) & ~(HUPCL | CREAD | CLOCAL))
473 return 1;
474 return 0;
475}
476EXPORT_SYMBOL(tty_termios_hw_change);
477
af9b897e
AC
478/**
479 * change_termios - update termios values
480 * @tty: tty to update
481 * @new_termios: desired new value
482 *
483 * Perform updates to the termios values set on this terminal. There
484 * is a bit of layering violation here with n_tty in terms of the
485 * internal knowledge of this function.
486 *
d81ed103 487 * Locking: termios_mutex
af9b897e
AC
488 */
489
355d95a1 490static void change_termios(struct tty_struct *tty, struct ktermios *new_termios)
1da177e4 491{
978e595f 492 struct ktermios old_termios;
1da177e4 493 struct tty_ldisc *ld;
04f378b1 494 unsigned long flags;
355d95a1 495
1da177e4
LT
496 /*
497 * Perform the actual termios internal changes under lock.
498 */
355d95a1 499
1da177e4
LT
500
501 /* FIXME: we need to decide on some locking/ordering semantics
502 for the set_termios notification eventually */
5785c95b 503 mutex_lock(&tty->termios_mutex);
978e595f 504 old_termios = *tty->termios;
1da177e4
LT
505 *tty->termios = *new_termios;
506 unset_locked_termios(tty->termios, &old_termios, tty->termios_locked);
1da177e4
LT
507
508 /* See if packet mode change of state. */
1da177e4
LT
509 if (tty->link && tty->link->packet) {
510 int old_flow = ((old_termios.c_iflag & IXON) &&
511 (old_termios.c_cc[VSTOP] == '\023') &&
512 (old_termios.c_cc[VSTART] == '\021'));
513 int new_flow = (I_IXON(tty) &&
514 STOP_CHAR(tty) == '\023' &&
515 START_CHAR(tty) == '\021');
516 if (old_flow != new_flow) {
04f378b1 517 spin_lock_irqsave(&tty->ctrl_lock, flags);
1da177e4
LT
518 tty->ctrl_status &= ~(TIOCPKT_DOSTOP | TIOCPKT_NOSTOP);
519 if (new_flow)
520 tty->ctrl_status |= TIOCPKT_DOSTOP;
521 else
522 tty->ctrl_status |= TIOCPKT_NOSTOP;
04f378b1 523 spin_unlock_irqrestore(&tty->ctrl_lock, flags);
1da177e4
LT
524 wake_up_interruptible(&tty->link->read_wait);
525 }
526 }
355d95a1 527
f34d7a5b
AC
528 if (tty->ops->set_termios)
529 (*tty->ops->set_termios)(tty, &old_termios);
5f519d72
AC
530 else
531 tty_termios_copy_hw(tty->termios, &old_termios);
1da177e4
LT
532
533 ld = tty_ldisc_ref(tty);
534 if (ld != NULL) {
a352def2
AC
535 if (ld->ops->set_termios)
536 (ld->ops->set_termios)(tty, &old_termios);
1da177e4
LT
537 tty_ldisc_deref(ld);
538 }
5785c95b 539 mutex_unlock(&tty->termios_mutex);
1da177e4
LT
540}
541
af9b897e
AC
542/**
543 * set_termios - set termios values for a tty
544 * @tty: terminal device
545 * @arg: user data
546 * @opt: option information
547 *
3a4fa0a2 548 * Helper function to prepare termios data and run necessary other
af9b897e
AC
549 * functions before using change_termios to do the actual changes.
550 *
551 * Locking:
d81ed103 552 * Called functions take ldisc and termios_mutex locks
af9b897e
AC
553 */
554
355d95a1 555static int set_termios(struct tty_struct *tty, void __user *arg, int opt)
1da177e4 556{
edc6afc5 557 struct ktermios tmp_termios;
1da177e4
LT
558 struct tty_ldisc *ld;
559 int retval = tty_check_change(tty);
560
561 if (retval)
562 return retval;
563
978e595f 564 mutex_lock(&tty->termios_mutex);
64bb6c5e 565 memcpy(&tmp_termios, tty->termios, sizeof(struct ktermios));
978e595f 566 mutex_unlock(&tty->termios_mutex);
64bb6c5e 567
1da177e4 568 if (opt & TERMIOS_TERMIO) {
1da177e4
LT
569 if (user_termio_to_kernel_termios(&tmp_termios,
570 (struct termio __user *)arg))
571 return -EFAULT;
edc6afc5
AC
572#ifdef TCGETS2
573 } else if (opt & TERMIOS_OLD) {
edc6afc5 574 if (user_termios_to_kernel_termios_1(&tmp_termios,
64bb6c5e 575 (struct termios __user *)arg))
edc6afc5 576 return -EFAULT;
1da177e4
LT
577 } else {
578 if (user_termios_to_kernel_termios(&tmp_termios,
64bb6c5e 579 (struct termios2 __user *)arg))
1da177e4
LT
580 return -EFAULT;
581 }
64bb6c5e
AC
582#else
583 } else if (user_termios_to_kernel_termios(&tmp_termios,
584 (struct termios __user *)arg))
585 return -EFAULT;
586#endif
1da177e4 587
355d95a1
AC
588 /* If old style Bfoo values are used then load c_ispeed/c_ospeed
589 * with the real speed so its unconditionally usable */
edc6afc5
AC
590 tmp_termios.c_ispeed = tty_termios_input_baud_rate(&tmp_termios);
591 tmp_termios.c_ospeed = tty_termios_baud_rate(&tmp_termios);
592
1da177e4 593 ld = tty_ldisc_ref(tty);
355d95a1 594
1da177e4 595 if (ld != NULL) {
a352def2
AC
596 if ((opt & TERMIOS_FLUSH) && ld->ops->flush_buffer)
597 ld->ops->flush_buffer(tty);
1da177e4
LT
598 tty_ldisc_deref(ld);
599 }
355d95a1 600
1da177e4
LT
601 if (opt & TERMIOS_WAIT) {
602 tty_wait_until_sent(tty, 0);
603 if (signal_pending(current))
604 return -EINTR;
605 }
606
607 change_termios(tty, &tmp_termios);
5f519d72
AC
608
609 /* FIXME: Arguably if tmp_termios == tty->termios AND the
610 actual requested termios was not tmp_termios then we may
611 want to return an error as no user requested change has
612 succeeded */
1da177e4
LT
613 return 0;
614}
615
355d95a1 616static int get_termio(struct tty_struct *tty, struct termio __user *termio)
1da177e4
LT
617{
618 if (kernel_termios_to_user_termio(termio, tty->termios))
619 return -EFAULT;
620 return 0;
621}
622
1d65b4a0
AC
623
624#ifdef TCGETX
625
626/**
627 * set_termiox - set termiox fields if possible
628 * @tty: terminal
629 * @arg: termiox structure from user
630 * @opt: option flags for ioctl type
631 *
632 * Implement the device calling points for the SYS5 termiox ioctl
633 * interface in Linux
634 */
635
636static int set_termiox(struct tty_struct *tty, void __user *arg, int opt)
637{
638 struct termiox tnew;
639 struct tty_ldisc *ld;
640
641 if (tty->termiox == NULL)
642 return -EINVAL;
643 if (copy_from_user(&tnew, arg, sizeof(struct termiox)))
644 return -EFAULT;
645
646 ld = tty_ldisc_ref(tty);
647 if (ld != NULL) {
648 if ((opt & TERMIOS_FLUSH) && ld->ops->flush_buffer)
649 ld->ops->flush_buffer(tty);
650 tty_ldisc_deref(ld);
651 }
652 if (opt & TERMIOS_WAIT) {
653 tty_wait_until_sent(tty, 0);
654 if (signal_pending(current))
655 return -EINTR;
656 }
657
658 mutex_lock(&tty->termios_mutex);
659 if (tty->ops->set_termiox)
660 tty->ops->set_termiox(tty, &tnew);
661 mutex_unlock(&tty->termios_mutex);
662 return 0;
663}
664
665#endif
666
1da177e4
LT
667
668#ifdef TIOCGETP
669/*
670 * These are deprecated, but there is limited support..
671 *
672 * The "sg_flags" translation is a joke..
673 */
355d95a1 674static int get_sgflags(struct tty_struct *tty)
1da177e4
LT
675{
676 int flags = 0;
677
678 if (!(tty->termios->c_lflag & ICANON)) {
679 if (tty->termios->c_lflag & ISIG)
680 flags |= 0x02; /* cbreak */
681 else
682 flags |= 0x20; /* raw */
683 }
684 if (tty->termios->c_lflag & ECHO)
685 flags |= 0x08; /* echo */
686 if (tty->termios->c_oflag & OPOST)
687 if (tty->termios->c_oflag & ONLCR)
688 flags |= 0x10; /* crmod */
689 return flags;
690}
691
355d95a1 692static int get_sgttyb(struct tty_struct *tty, struct sgttyb __user *sgttyb)
1da177e4
LT
693{
694 struct sgttyb tmp;
695
5785c95b 696 mutex_lock(&tty->termios_mutex);
606d099c
AC
697 tmp.sg_ispeed = tty->termios->c_ispeed;
698 tmp.sg_ospeed = tty->termios->c_ospeed;
1da177e4
LT
699 tmp.sg_erase = tty->termios->c_cc[VERASE];
700 tmp.sg_kill = tty->termios->c_cc[VKILL];
701 tmp.sg_flags = get_sgflags(tty);
5785c95b 702 mutex_unlock(&tty->termios_mutex);
355d95a1 703
1da177e4
LT
704 return copy_to_user(sgttyb, &tmp, sizeof(tmp)) ? -EFAULT : 0;
705}
706
355d95a1 707static void set_sgflags(struct ktermios *termios, int flags)
1da177e4
LT
708{
709 termios->c_iflag = ICRNL | IXON;
710 termios->c_oflag = 0;
711 termios->c_lflag = ISIG | ICANON;
712 if (flags & 0x02) { /* cbreak */
713 termios->c_iflag = 0;
714 termios->c_lflag &= ~ICANON;
715 }
716 if (flags & 0x08) { /* echo */
717 termios->c_lflag |= ECHO | ECHOE | ECHOK |
718 ECHOCTL | ECHOKE | IEXTEN;
719 }
720 if (flags & 0x10) { /* crmod */
721 termios->c_oflag |= OPOST | ONLCR;
722 }
723 if (flags & 0x20) { /* raw */
724 termios->c_iflag = 0;
725 termios->c_lflag &= ~(ISIG | ICANON);
726 }
727 if (!(termios->c_lflag & ICANON)) {
728 termios->c_cc[VMIN] = 1;
729 termios->c_cc[VTIME] = 0;
730 }
731}
732
af9b897e
AC
733/**
734 * set_sgttyb - set legacy terminal values
735 * @tty: tty structure
736 * @sgttyb: pointer to old style terminal structure
737 *
738 * Updates a terminal from the legacy BSD style terminal information
739 * structure.
740 *
d81ed103 741 * Locking: termios_mutex
af9b897e
AC
742 */
743
355d95a1 744static int set_sgttyb(struct tty_struct *tty, struct sgttyb __user *sgttyb)
1da177e4
LT
745{
746 int retval;
747 struct sgttyb tmp;
edc6afc5 748 struct ktermios termios;
1da177e4
LT
749
750 retval = tty_check_change(tty);
751 if (retval)
752 return retval;
355d95a1 753
1da177e4
LT
754 if (copy_from_user(&tmp, sgttyb, sizeof(tmp)))
755 return -EFAULT;
756
5785c95b 757 mutex_lock(&tty->termios_mutex);
6804396f 758 termios = *tty->termios;
1da177e4
LT
759 termios.c_cc[VERASE] = tmp.sg_erase;
760 termios.c_cc[VKILL] = tmp.sg_kill;
761 set_sgflags(&termios, tmp.sg_flags);
edc6afc5
AC
762 /* Try and encode into Bfoo format */
763#ifdef BOTHER
355d95a1
AC
764 tty_termios_encode_baud_rate(&termios, termios.c_ispeed,
765 termios.c_ospeed);
edc6afc5 766#endif
5785c95b 767 mutex_unlock(&tty->termios_mutex);
1da177e4
LT
768 change_termios(tty, &termios);
769 return 0;
770}
771#endif
772
773#ifdef TIOCGETC
355d95a1 774static int get_tchars(struct tty_struct *tty, struct tchars __user *tchars)
1da177e4
LT
775{
776 struct tchars tmp;
777
978e595f 778 mutex_lock(&tty->termios_mutex);
1da177e4
LT
779 tmp.t_intrc = tty->termios->c_cc[VINTR];
780 tmp.t_quitc = tty->termios->c_cc[VQUIT];
781 tmp.t_startc = tty->termios->c_cc[VSTART];
782 tmp.t_stopc = tty->termios->c_cc[VSTOP];
783 tmp.t_eofc = tty->termios->c_cc[VEOF];
784 tmp.t_brkc = tty->termios->c_cc[VEOL2]; /* what is brkc anyway? */
978e595f 785 mutex_unlock(&tty->termios_mutex);
1da177e4
LT
786 return copy_to_user(tchars, &tmp, sizeof(tmp)) ? -EFAULT : 0;
787}
788
355d95a1 789static int set_tchars(struct tty_struct *tty, struct tchars __user *tchars)
1da177e4
LT
790{
791 struct tchars tmp;
792
793 if (copy_from_user(&tmp, tchars, sizeof(tmp)))
794 return -EFAULT;
978e595f 795 mutex_lock(&tty->termios_mutex);
1da177e4
LT
796 tty->termios->c_cc[VINTR] = tmp.t_intrc;
797 tty->termios->c_cc[VQUIT] = tmp.t_quitc;
798 tty->termios->c_cc[VSTART] = tmp.t_startc;
799 tty->termios->c_cc[VSTOP] = tmp.t_stopc;
800 tty->termios->c_cc[VEOF] = tmp.t_eofc;
801 tty->termios->c_cc[VEOL2] = tmp.t_brkc; /* what is brkc anyway? */
978e595f 802 mutex_unlock(&tty->termios_mutex);
1da177e4
LT
803 return 0;
804}
805#endif
806
807#ifdef TIOCGLTC
355d95a1 808static int get_ltchars(struct tty_struct *tty, struct ltchars __user *ltchars)
1da177e4
LT
809{
810 struct ltchars tmp;
811
978e595f 812 mutex_lock(&tty->termios_mutex);
1da177e4 813 tmp.t_suspc = tty->termios->c_cc[VSUSP];
355d95a1
AC
814 /* what is dsuspc anyway? */
815 tmp.t_dsuspc = tty->termios->c_cc[VSUSP];
1da177e4 816 tmp.t_rprntc = tty->termios->c_cc[VREPRINT];
355d95a1
AC
817 /* what is flushc anyway? */
818 tmp.t_flushc = tty->termios->c_cc[VEOL2];
1da177e4
LT
819 tmp.t_werasc = tty->termios->c_cc[VWERASE];
820 tmp.t_lnextc = tty->termios->c_cc[VLNEXT];
978e595f 821 mutex_unlock(&tty->termios_mutex);
1da177e4
LT
822 return copy_to_user(ltchars, &tmp, sizeof(tmp)) ? -EFAULT : 0;
823}
824
355d95a1 825static int set_ltchars(struct tty_struct *tty, struct ltchars __user *ltchars)
1da177e4
LT
826{
827 struct ltchars tmp;
828
829 if (copy_from_user(&tmp, ltchars, sizeof(tmp)))
830 return -EFAULT;
831
978e595f 832 mutex_lock(&tty->termios_mutex);
1da177e4 833 tty->termios->c_cc[VSUSP] = tmp.t_suspc;
355d95a1
AC
834 /* what is dsuspc anyway? */
835 tty->termios->c_cc[VEOL2] = tmp.t_dsuspc;
1da177e4 836 tty->termios->c_cc[VREPRINT] = tmp.t_rprntc;
355d95a1
AC
837 /* what is flushc anyway? */
838 tty->termios->c_cc[VEOL2] = tmp.t_flushc;
1da177e4
LT
839 tty->termios->c_cc[VWERASE] = tmp.t_werasc;
840 tty->termios->c_cc[VLNEXT] = tmp.t_lnextc;
978e595f 841 mutex_unlock(&tty->termios_mutex);
1da177e4
LT
842 return 0;
843}
844#endif
845
af9b897e
AC
846/**
847 * send_prio_char - send priority character
848 *
849 * Send a high priority character to the tty even if stopped
850 *
5f412b24 851 * Locking: none for xchar method, write ordering for write method.
1da177e4 852 */
af9b897e 853
5f412b24 854static int send_prio_char(struct tty_struct *tty, char ch)
1da177e4
LT
855{
856 int was_stopped = tty->stopped;
857
f34d7a5b
AC
858 if (tty->ops->send_xchar) {
859 tty->ops->send_xchar(tty, ch);
5f412b24 860 return 0;
1da177e4 861 }
5f412b24 862
9c1729db 863 if (tty_write_lock(tty, 0) < 0)
5f412b24
AC
864 return -ERESTARTSYS;
865
1da177e4
LT
866 if (was_stopped)
867 start_tty(tty);
f34d7a5b 868 tty->ops->write(tty, &ch, 1);
1da177e4
LT
869 if (was_stopped)
870 stop_tty(tty);
9c1729db 871 tty_write_unlock(tty);
5f412b24 872 return 0;
1da177e4
LT
873}
874
1c2630cc
AC
875/**
876 * tty_change_softcar - carrier change ioctl helper
877 * @tty: tty to update
878 * @arg: enable/disable CLOCAL
879 *
880 * Perform a change to the CLOCAL state and call into the driver
881 * layer to make it visible. All done with the termios mutex
882 */
883
884static int tty_change_softcar(struct tty_struct *tty, int arg)
885{
886 int ret = 0;
887 int bit = arg ? CLOCAL : 0;
f34d7a5b 888 struct ktermios old;
1c2630cc
AC
889
890 mutex_lock(&tty->termios_mutex);
f34d7a5b 891 old = *tty->termios;
1c2630cc
AC
892 tty->termios->c_cflag &= ~CLOCAL;
893 tty->termios->c_cflag |= bit;
f34d7a5b
AC
894 if (tty->ops->set_termios)
895 tty->ops->set_termios(tty, &old);
1c2630cc
AC
896 if ((tty->termios->c_cflag & CLOCAL) != bit)
897 ret = -EINVAL;
898 mutex_unlock(&tty->termios_mutex);
899 return ret;
900}
901
0fc00e24
AC
902/**
903 * tty_mode_ioctl - mode related ioctls
904 * @tty: tty for the ioctl
905 * @file: file pointer for the tty
906 * @cmd: command
907 * @arg: ioctl argument
908 *
909 * Perform non line discipline specific mode control ioctls. This
910 * is designed to be called by line disciplines to ensure they provide
911 * consistent mode setting.
912 */
913
355d95a1 914int tty_mode_ioctl(struct tty_struct *tty, struct file *file,
0fc00e24 915 unsigned int cmd, unsigned long arg)
1da177e4 916{
355d95a1 917 struct tty_struct *real_tty;
1da177e4 918 void __user *p = (void __user *)arg;
8f520021 919 int ret = 0;
1da177e4
LT
920
921 if (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
922 tty->driver->subtype == PTY_TYPE_MASTER)
923 real_tty = tty->link;
924 else
925 real_tty = tty;
926
927 switch (cmd) {
928#ifdef TIOCGETP
355d95a1
AC
929 case TIOCGETP:
930 return get_sgttyb(real_tty, (struct sgttyb __user *) arg);
931 case TIOCSETP:
932 case TIOCSETN:
933 return set_sgttyb(real_tty, (struct sgttyb __user *) arg);
1da177e4
LT
934#endif
935#ifdef TIOCGETC
355d95a1
AC
936 case TIOCGETC:
937 return get_tchars(real_tty, p);
938 case TIOCSETC:
939 return set_tchars(real_tty, p);
1da177e4
LT
940#endif
941#ifdef TIOCGLTC
355d95a1
AC
942 case TIOCGLTC:
943 return get_ltchars(real_tty, p);
944 case TIOCSLTC:
945 return set_ltchars(real_tty, p);
1da177e4 946#endif
355d95a1
AC
947 case TCSETSF:
948 return set_termios(real_tty, p, TERMIOS_FLUSH | TERMIOS_WAIT | TERMIOS_OLD);
949 case TCSETSW:
950 return set_termios(real_tty, p, TERMIOS_WAIT | TERMIOS_OLD);
951 case TCSETS:
952 return set_termios(real_tty, p, TERMIOS_OLD);
edc6afc5 953#ifndef TCGETS2
355d95a1 954 case TCGETS:
8f520021 955 mutex_lock(&real_tty->termios_mutex);
355d95a1 956 if (kernel_termios_to_user_termios((struct termios __user *)arg, real_tty->termios))
8f520021
AC
957 ret = -EFAULT;
958 mutex_unlock(&real_tty->termios_mutex);
959 return ret;
edc6afc5 960#else
355d95a1 961 case TCGETS:
8f520021 962 mutex_lock(&real_tty->termios_mutex);
355d95a1 963 if (kernel_termios_to_user_termios_1((struct termios __user *)arg, real_tty->termios))
8f520021
AC
964 ret = -EFAULT;
965 mutex_unlock(&real_tty->termios_mutex);
966 return ret;
355d95a1 967 case TCGETS2:
8f520021 968 mutex_lock(&real_tty->termios_mutex);
355d95a1 969 if (kernel_termios_to_user_termios((struct termios2 __user *)arg, real_tty->termios))
8f520021
AC
970 ret = -EFAULT;
971 mutex_unlock(&real_tty->termios_mutex);
972 return ret;
355d95a1
AC
973 case TCSETSF2:
974 return set_termios(real_tty, p, TERMIOS_FLUSH | TERMIOS_WAIT);
975 case TCSETSW2:
976 return set_termios(real_tty, p, TERMIOS_WAIT);
977 case TCSETS2:
978 return set_termios(real_tty, p, 0);
edc6afc5 979#endif
355d95a1
AC
980 case TCGETA:
981 return get_termio(real_tty, p);
982 case TCSETAF:
983 return set_termios(real_tty, p, TERMIOS_FLUSH | TERMIOS_WAIT | TERMIOS_TERMIO);
984 case TCSETAW:
985 return set_termios(real_tty, p, TERMIOS_WAIT | TERMIOS_TERMIO);
986 case TCSETA:
987 return set_termios(real_tty, p, TERMIOS_TERMIO);
0fc00e24 988#ifndef TCGETS2
355d95a1 989 case TIOCGLCKTRMIOS:
8f520021 990 mutex_lock(&real_tty->termios_mutex);
355d95a1 991 if (kernel_termios_to_user_termios((struct termios __user *)arg, real_tty->termios_locked))
8f520021
AC
992 ret = -EFAULT;
993 mutex_unlock(&real_tty->termios_mutex);
994 return ret;
355d95a1
AC
995 case TIOCSLCKTRMIOS:
996 if (!capable(CAP_SYS_ADMIN))
997 return -EPERM;
8f520021 998 mutex_lock(&real_tty->termios_mutex);
355d95a1
AC
999 if (user_termios_to_kernel_termios(real_tty->termios_locked,
1000 (struct termios __user *) arg))
8f520021
AC
1001 ret = -EFAULT;
1002 mutex_unlock(&real_tty->termios_mutex);
1003 return ret;
0fc00e24 1004#else
355d95a1 1005 case TIOCGLCKTRMIOS:
8f520021 1006 mutex_lock(&real_tty->termios_mutex);
355d95a1 1007 if (kernel_termios_to_user_termios_1((struct termios __user *)arg, real_tty->termios_locked))
8f520021
AC
1008 ret = -EFAULT;
1009 mutex_unlock(&real_tty->termios_mutex);
1010 return ret;
355d95a1
AC
1011 case TIOCSLCKTRMIOS:
1012 if (!capable(CAP_SYS_ADMIN))
8f520021
AC
1013 ret = -EPERM;
1014 mutex_lock(&real_tty->termios_mutex);
355d95a1
AC
1015 if (user_termios_to_kernel_termios_1(real_tty->termios_locked,
1016 (struct termios __user *) arg))
8f520021
AC
1017 ret = -EFAULT;
1018 mutex_unlock(&real_tty->termios_mutex);
1019 return ret;
0fc00e24 1020#endif
1d65b4a0
AC
1021#ifdef TCGETX
1022 case TCGETX:
1023 if (real_tty->termiox == NULL)
1024 return -EINVAL;
8f520021 1025 mutex_lock(&real_tty->termios_mutex);
1d65b4a0 1026 if (copy_to_user(p, real_tty->termiox, sizeof(struct termiox)))
8f520021
AC
1027 ret = -EFAULT;
1028 mutex_unlock(&real_tty->termios_mutex);
1029 return ret;
1d65b4a0
AC
1030 case TCSETX:
1031 return set_termiox(real_tty, p, 0);
1032 case TCSETXW:
1033 return set_termiox(real_tty, p, TERMIOS_WAIT);
1034 case TCSETXF:
1035 return set_termiox(real_tty, p, TERMIOS_FLUSH);
1036#endif
355d95a1 1037 case TIOCGSOFTCAR:
8f520021
AC
1038 mutex_lock(&real_tty->termios_mutex);
1039 ret = put_user(C_CLOCAL(real_tty) ? 1 : 0,
355d95a1 1040 (int __user *)arg);
8f520021
AC
1041 mutex_unlock(&real_tty->termios_mutex);
1042 return ret;
355d95a1
AC
1043 case TIOCSSOFTCAR:
1044 if (get_user(arg, (unsigned int __user *) arg))
1045 return -EFAULT;
f753f327 1046 return tty_change_softcar(real_tty, arg);
355d95a1
AC
1047 default:
1048 return -ENOIOCTLCMD;
0fc00e24
AC
1049 }
1050}
0fc00e24
AC
1051EXPORT_SYMBOL_GPL(tty_mode_ioctl);
1052
1053int tty_perform_flush(struct tty_struct *tty, unsigned long arg)
1054{
1055 struct tty_ldisc *ld;
1056 int retval = tty_check_change(tty);
1057 if (retval)
1058 return retval;
1059
c0253eec 1060 ld = tty_ldisc_ref_wait(tty);
0fc00e24
AC
1061 switch (arg) {
1062 case TCIFLUSH:
a352def2
AC
1063 if (ld && ld->ops->flush_buffer)
1064 ld->ops->flush_buffer(tty);
0fc00e24
AC
1065 break;
1066 case TCIOFLUSH:
a352def2
AC
1067 if (ld && ld->ops->flush_buffer)
1068 ld->ops->flush_buffer(tty);
0fc00e24
AC
1069 /* fall through */
1070 case TCOFLUSH:
f34d7a5b 1071 tty_driver_flush_buffer(tty);
0fc00e24
AC
1072 break;
1073 default:
1074 tty_ldisc_deref(ld);
1075 return -EINVAL;
1076 }
1077 tty_ldisc_deref(ld);
1078 return 0;
1079}
0fc00e24
AC
1080EXPORT_SYMBOL_GPL(tty_perform_flush);
1081
47afa7a5 1082int n_tty_ioctl_helper(struct tty_struct *tty, struct file *file,
0fc00e24
AC
1083 unsigned int cmd, unsigned long arg)
1084{
04f378b1 1085 unsigned long flags;
0fc00e24
AC
1086 int retval;
1087
0fc00e24 1088 switch (cmd) {
355d95a1
AC
1089 case TCXONC:
1090 retval = tty_check_change(tty);
1091 if (retval)
1092 return retval;
1093 switch (arg) {
1094 case TCOOFF:
1095 if (!tty->flow_stopped) {
1096 tty->flow_stopped = 1;
1097 stop_tty(tty);
1da177e4 1098 }
355d95a1
AC
1099 break;
1100 case TCOON:
1101 if (tty->flow_stopped) {
1102 tty->flow_stopped = 0;
1103 start_tty(tty);
1104 }
1105 break;
1106 case TCIOFF:
1107 if (STOP_CHAR(tty) != __DISABLED_CHAR)
1108 return send_prio_char(tty, STOP_CHAR(tty));
1109 break;
1110 case TCION:
1111 if (START_CHAR(tty) != __DISABLED_CHAR)
1112 return send_prio_char(tty, START_CHAR(tty));
1113 break;
1da177e4 1114 default:
355d95a1 1115 return -EINVAL;
1da177e4 1116 }
355d95a1
AC
1117 return 0;
1118 case TCFLSH:
1119 return tty_perform_flush(tty, arg);
355d95a1
AC
1120 case TIOCPKT:
1121 {
1122 int pktmode;
1123
1124 if (tty->driver->type != TTY_DRIVER_TYPE_PTY ||
1125 tty->driver->subtype != PTY_TYPE_MASTER)
1126 return -ENOTTY;
1127 if (get_user(pktmode, (int __user *) arg))
1128 return -EFAULT;
04f378b1 1129 spin_lock_irqsave(&tty->ctrl_lock, flags);
355d95a1
AC
1130 if (pktmode) {
1131 if (!tty->packet) {
1132 tty->packet = 1;
1133 tty->link->ctrl_status = 0;
1134 }
1135 } else
1136 tty->packet = 0;
04f378b1 1137 spin_unlock_irqrestore(&tty->ctrl_lock, flags);
355d95a1
AC
1138 return 0;
1139 }
1140 default:
1141 /* Try the mode commands */
1142 return tty_mode_ioctl(tty, file, cmd, arg);
1143 }
1da177e4 1144}
47afa7a5 1145EXPORT_SYMBOL(n_tty_ioctl_helper);