blob: 14cc19c344cc69c10800c85d57e098e853b516a0 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
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>
Arjan van de Ven5785c952006-09-29 02:00:43 -070023#include <linux/mutex.h>
Alan Cox0ee9cbb2008-04-30 00:53:32 -070024#include <linux/smp_lock.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070025
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
Alan Coxedc6afc2006-12-08 02:38:44 -080040#define TERMIOS_OLD 8
Linus Torvalds1da177e2005-04-16 15:20:36 -070041
Alan Coxaf9b8972006-08-27 01:24:01 -070042
Alan Coxd81ed102008-10-13 10:41:42 +010043/**
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
Alan Coxf34d7a52008-04-30 00:54:13 -070052int 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}
Alan Coxf34d7a52008-04-30 00:54:13 -070059EXPORT_SYMBOL(tty_chars_in_buffer);
60
Alan Coxd81ed102008-10-13 10:41:42 +010061/**
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
Alan Coxf34d7a52008-04-30 00:54:13 -070072int 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}
Alan Coxf34d7a52008-04-30 00:54:13 -070078EXPORT_SYMBOL(tty_write_room);
79
Alan Coxd81ed102008-10-13 10:41:42 +010080/**
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 */
Alan Coxf34d7a52008-04-30 00:54:13 -070088void tty_driver_flush_buffer(struct tty_struct *tty)
89{
90 if (tty->ops->flush_buffer)
91 tty->ops->flush_buffer(tty);
92}
Alan Coxf34d7a52008-04-30 00:54:13 -070093EXPORT_SYMBOL(tty_driver_flush_buffer);
94
Alan Coxd81ed102008-10-13 10:41:42 +010095/**
96 * tty_throttle - flow control
97 * @tty: terminal
98 *
99 * Indicate that a tty should stop transmitting data down the stack.
100 */
101
Alan Cox39c2e602008-04-30 00:54:18 -0700102void 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
Alan Coxd81ed102008-10-13 10:41:42 +0100111/**
112 * tty_unthrottle - flow control
113 * @tty: terminal
114 *
115 * Indicate that a tty may continue transmitting data down the stack.
116 */
117
Alan Cox39c2e602008-04-30 00:54:18 -0700118void 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);
Alan Coxf34d7a52008-04-30 00:54:13 -0700125
Alan Coxaf9b8972006-08-27 01:24:01 -0700126/**
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
Alan Cox355d95a2008-02-08 04:18:48 -0800137void tty_wait_until_sent(struct tty_struct *tty, long timeout)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700138{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700139#ifdef TTY_DEBUG_WAIT_UNTIL_SENT
140 char buf[64];
Alan Cox355d95a2008-02-08 04:18:48 -0800141
Linus Torvalds1da177e2005-04-16 15:20:36 -0700142 printk(KERN_DEBUG "%s wait until sent...\n", tty_name(tty, buf));
143#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700144 if (!timeout)
145 timeout = MAX_SCHEDULE_TIMEOUT;
Jiri Slaby5a52bd42007-07-15 23:40:18 -0700146 if (wait_event_interruptible_timeout(tty->write_wait,
Alan Coxf34d7a52008-04-30 00:54:13 -0700147 !tty_chars_in_buffer(tty), timeout) >= 0) {
148 if (tty->ops->wait_until_sent)
149 tty->ops->wait_until_sent(tty, timeout);
Alan Cox0ee9cbb2008-04-30 00:53:32 -0700150 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700151}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700152EXPORT_SYMBOL(tty_wait_until_sent);
153
Alan Coxd81ed102008-10-13 10:41:42 +0100154
155/*
156 * Termios Helper Methods
157 */
158
Alan Coxedc6afc2006-12-08 02:38:44 -0800159static void unset_locked_termios(struct ktermios *termios,
160 struct ktermios *old,
161 struct ktermios *locked)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700162{
163 int i;
Alan Cox355d95a2008-02-08 04:18:48 -0800164
165#define NOSET_MASK(x, y, z) (x = ((x) & ~(z)) | ((y) & (z)))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700166
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;
Alan Cox355d95a2008-02-08 04:18:48 -0800177 for (i = 0; i < NCCS; i++)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700178 termios->c_cc[i] = locked->c_cc[i] ?
179 old->c_cc[i] : termios->c_cc[i];
Alan Coxedc6afc2006-12-08 02:38:44 -0800180 /* FIXME: What should we do for i/ospeed */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700181}
182
Alan Coxedc6afc2006-12-08 02:38:44 -0800183/*
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}
Alan Coxedc6afc2006-12-08 02:38:44 -0800252EXPORT_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}
Alan Coxedc6afc2006-12-08 02:38:44 -0800291EXPORT_SYMBOL(tty_termios_input_baud_rate);
292
Alan Coxedc6afc2006-12-08 02:38:44 -0800293/**
294 * tty_termios_encode_baud_rate
Alan Cox78137e32007-02-10 01:45:57 -0800295 * @termios: ktermios structure holding user requested state
Alan Coxedc6afc2006-12-08 02:38:44 -0800296 * @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 *
Alan Cox78137e32007-02-10 01:45:57 -0800303 * 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.
Alan Coxedc6afc2006-12-08 02:38:44 -0800307 *
308 * Locking: Caller should hold termios lock. This is already held
309 * when calling this function from the driver termios handler.
Alan Cox5f519d72007-10-16 23:30:07 -0700310 *
311 * The ifdefs deal with platforms whose owners have yet to update them
312 * and will all go away once this is done.
Alan Coxedc6afc2006-12-08 02:38:44 -0800313 */
314
Maciej W. Rozycki75e8b712007-10-18 03:04:35 -0700315void tty_termios_encode_baud_rate(struct ktermios *termios,
316 speed_t ibaud, speed_t obaud)
Alan Coxedc6afc2006-12-08 02:38:44 -0800317{
318 int i = 0;
Alan Cox78137e32007-02-10 01:45:57 -0800319 int ifound = -1, ofound = -1;
320 int iclose = ibaud/50, oclose = obaud/50;
321 int ibinput = 0;
Alan Coxedc6afc2006-12-08 02:38:44 -0800322
Alan Cox5f519d72007-10-16 23:30:07 -0700323 if (obaud == 0) /* CD dropped */
324 ibaud = 0; /* Clear ibaud to be sure */
325
Alan Coxedc6afc2006-12-08 02:38:44 -0800326 termios->c_ispeed = ibaud;
327 termios->c_ospeed = obaud;
328
Alan Cox5f519d72007-10-16 23:30:07 -0700329#ifdef BOTHER
Alan Cox78137e32007-02-10 01:45:57 -0800330 /* 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 */
Alan Cox5f519d72007-10-16 23:30:07 -0700340#endif
Alan Coxedc6afc2006-12-08 02:38:44 -0800341 termios->c_cflag &= ~CBAUD;
Alan Coxedc6afc2006-12-08 02:38:44 -0800342
Alan Cox5f519d72007-10-16 23:30:07 -0700343 /*
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
Alan Coxedc6afc2006-12-08 02:38:44 -0800350 do {
Maciej W. Rozycki75e8b712007-10-18 03:04:35 -0700351 if (obaud - oclose <= baud_table[i] &&
352 obaud + oclose >= baud_table[i]) {
Alan Coxedc6afc2006-12-08 02:38:44 -0800353 termios->c_cflag |= baud_bits[i];
Alan Cox78137e32007-02-10 01:45:57 -0800354 ofound = i;
Alan Coxedc6afc2006-12-08 02:38:44 -0800355 }
Maciej W. Rozycki75e8b712007-10-18 03:04:35 -0700356 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 */
Alan Cox5f519d72007-10-16 23:30:07 -0700360 if (ofound == i && !ibinput)
361 ifound = i;
362#ifdef IBSHIFT
363 else {
364 ifound = i;
Alan Cox78137e32007-02-10 01:45:57 -0800365 termios->c_cflag |= (baud_bits[i] << IBSHIFT);
Alan Cox5f519d72007-10-16 23:30:07 -0700366 }
367#endif
Alan Coxedc6afc2006-12-08 02:38:44 -0800368 }
Jiri Slaby68043962007-07-15 23:40:18 -0700369 } while (++i < n_baud_table);
Alan Cox5f519d72007-10-16 23:30:07 -0700370
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
Alan Cox78137e32007-02-10 01:45:57 -0800376 if (ofound == -1)
Alan Coxedc6afc2006-12-08 02:38:44 -0800377 termios->c_cflag |= BOTHER;
Alan Cox78137e32007-02-10 01:45:57 -0800378 /* Set exact input bits only if the input and output differ or the
379 user already did */
Jiri Slaby68043962007-07-15 23:40:18 -0700380 if (ifound == -1 && (ibaud != obaud || ibinput))
Alan Coxedc6afc2006-12-08 02:38:44 -0800381 termios->c_cflag |= (BOTHER << IBSHIFT);
Alan Cox5f519d72007-10-16 23:30:07 -0700382#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
Alan Coxedc6afc2006-12-08 02:38:44 -0800390}
Alan Coxedc6afc2006-12-08 02:38:44 -0800391EXPORT_SYMBOL_GPL(tty_termios_encode_baud_rate);
392
Alan Coxd81ed102008-10-13 10:41:42 +0100393/**
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
Alan Cox5f519d72007-10-16 23:30:07 -0700403void 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);
Alan Coxedc6afc2006-12-08 02:38:44 -0800408
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}
Alan Coxedc6afc2006-12-08 02:38:44 -0800435EXPORT_SYMBOL(tty_get_baud_rate);
436
Alan Coxaf9b8972006-08-27 01:24:01 -0700437/**
Alan Cox5f519d72007-10-16 23:30:07 -0700438 * 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}
Alan Cox5f519d72007-10-16 23:30:07 -0700457EXPORT_SYMBOL(tty_termios_copy_hw);
458
459/**
Alan Coxbf5e5832008-01-08 14:55:51 +0000460 * 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
478/**
Alan Coxaf9b8972006-08-27 01:24:01 -0700479 * 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 *
Alan Coxd81ed102008-10-13 10:41:42 +0100487 * Locking: termios_mutex
Alan Coxaf9b8972006-08-27 01:24:01 -0700488 */
489
Alan Cox355d95a2008-02-08 04:18:48 -0800490static void change_termios(struct tty_struct *tty, struct ktermios *new_termios)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700491{
492 int canon_change;
Alan Cox978e5952008-04-30 00:53:59 -0700493 struct ktermios old_termios;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700494 struct tty_ldisc *ld;
Alan Cox04f378b2008-04-30 00:53:29 -0700495 unsigned long flags;
Alan Cox355d95a2008-02-08 04:18:48 -0800496
Linus Torvalds1da177e2005-04-16 15:20:36 -0700497 /*
498 * Perform the actual termios internal changes under lock.
499 */
Alan Cox355d95a2008-02-08 04:18:48 -0800500
Linus Torvalds1da177e2005-04-16 15:20:36 -0700501
502 /* FIXME: we need to decide on some locking/ordering semantics
503 for the set_termios notification eventually */
Arjan van de Ven5785c952006-09-29 02:00:43 -0700504 mutex_lock(&tty->termios_mutex);
Alan Cox978e5952008-04-30 00:53:59 -0700505 old_termios = *tty->termios;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700506 *tty->termios = *new_termios;
507 unset_locked_termios(tty->termios, &old_termios, tty->termios_locked);
508 canon_change = (old_termios.c_lflag ^ tty->termios->c_lflag) & ICANON;
509 if (canon_change) {
510 memset(&tty->read_flags, 0, sizeof tty->read_flags);
511 tty->canon_head = tty->read_tail;
512 tty->canon_data = 0;
513 tty->erasing = 0;
514 }
Alan Cox355d95a2008-02-08 04:18:48 -0800515
Alan Cox5f519d72007-10-16 23:30:07 -0700516 /* This bit should be in the ldisc code */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700517 if (canon_change && !L_ICANON(tty) && tty->read_cnt)
518 /* Get characters left over from canonical mode. */
519 wake_up_interruptible(&tty->read_wait);
520
521 /* See if packet mode change of state. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700522 if (tty->link && tty->link->packet) {
523 int old_flow = ((old_termios.c_iflag & IXON) &&
524 (old_termios.c_cc[VSTOP] == '\023') &&
525 (old_termios.c_cc[VSTART] == '\021'));
526 int new_flow = (I_IXON(tty) &&
527 STOP_CHAR(tty) == '\023' &&
528 START_CHAR(tty) == '\021');
529 if (old_flow != new_flow) {
Alan Cox04f378b2008-04-30 00:53:29 -0700530 spin_lock_irqsave(&tty->ctrl_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700531 tty->ctrl_status &= ~(TIOCPKT_DOSTOP | TIOCPKT_NOSTOP);
532 if (new_flow)
533 tty->ctrl_status |= TIOCPKT_DOSTOP;
534 else
535 tty->ctrl_status |= TIOCPKT_NOSTOP;
Alan Cox04f378b2008-04-30 00:53:29 -0700536 spin_unlock_irqrestore(&tty->ctrl_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700537 wake_up_interruptible(&tty->link->read_wait);
538 }
539 }
Alan Cox355d95a2008-02-08 04:18:48 -0800540
Alan Coxf34d7a52008-04-30 00:54:13 -0700541 if (tty->ops->set_termios)
542 (*tty->ops->set_termios)(tty, &old_termios);
Alan Cox5f519d72007-10-16 23:30:07 -0700543 else
544 tty_termios_copy_hw(tty->termios, &old_termios);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700545
546 ld = tty_ldisc_ref(tty);
547 if (ld != NULL) {
Alan Coxa352def2008-07-16 21:53:12 +0100548 if (ld->ops->set_termios)
549 (ld->ops->set_termios)(tty, &old_termios);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700550 tty_ldisc_deref(ld);
551 }
Arjan van de Ven5785c952006-09-29 02:00:43 -0700552 mutex_unlock(&tty->termios_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700553}
554
Alan Coxaf9b8972006-08-27 01:24:01 -0700555/**
556 * set_termios - set termios values for a tty
557 * @tty: terminal device
558 * @arg: user data
559 * @opt: option information
560 *
Robert P. J. Day3a4fa0a2007-10-19 23:10:43 +0200561 * Helper function to prepare termios data and run necessary other
Alan Coxaf9b8972006-08-27 01:24:01 -0700562 * functions before using change_termios to do the actual changes.
563 *
564 * Locking:
Alan Coxd81ed102008-10-13 10:41:42 +0100565 * Called functions take ldisc and termios_mutex locks
Alan Coxaf9b8972006-08-27 01:24:01 -0700566 */
567
Alan Cox355d95a2008-02-08 04:18:48 -0800568static int set_termios(struct tty_struct *tty, void __user *arg, int opt)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700569{
Alan Coxedc6afc2006-12-08 02:38:44 -0800570 struct ktermios tmp_termios;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700571 struct tty_ldisc *ld;
572 int retval = tty_check_change(tty);
573
574 if (retval)
575 return retval;
576
Alan Cox978e5952008-04-30 00:53:59 -0700577 mutex_lock(&tty->termios_mutex);
Alan Cox64bb6c52006-12-08 02:38:47 -0800578 memcpy(&tmp_termios, tty->termios, sizeof(struct ktermios));
Alan Cox978e5952008-04-30 00:53:59 -0700579 mutex_unlock(&tty->termios_mutex);
Alan Cox64bb6c52006-12-08 02:38:47 -0800580
Linus Torvalds1da177e2005-04-16 15:20:36 -0700581 if (opt & TERMIOS_TERMIO) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700582 if (user_termio_to_kernel_termios(&tmp_termios,
583 (struct termio __user *)arg))
584 return -EFAULT;
Alan Coxedc6afc2006-12-08 02:38:44 -0800585#ifdef TCGETS2
586 } else if (opt & TERMIOS_OLD) {
Alan Coxedc6afc2006-12-08 02:38:44 -0800587 if (user_termios_to_kernel_termios_1(&tmp_termios,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700588 (struct termios __user *)arg))
589 return -EFAULT;
Alan Cox64bb6c52006-12-08 02:38:47 -0800590 } else {
591 if (user_termios_to_kernel_termios(&tmp_termios,
592 (struct termios2 __user *)arg))
593 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700594 }
Alan Cox64bb6c52006-12-08 02:38:47 -0800595#else
596 } else if (user_termios_to_kernel_termios(&tmp_termios,
597 (struct termios __user *)arg))
598 return -EFAULT;
599#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700600
Alan Cox355d95a2008-02-08 04:18:48 -0800601 /* If old style Bfoo values are used then load c_ispeed/c_ospeed
602 * with the real speed so its unconditionally usable */
Alan Coxedc6afc2006-12-08 02:38:44 -0800603 tmp_termios.c_ispeed = tty_termios_input_baud_rate(&tmp_termios);
604 tmp_termios.c_ospeed = tty_termios_baud_rate(&tmp_termios);
605
Linus Torvalds1da177e2005-04-16 15:20:36 -0700606 ld = tty_ldisc_ref(tty);
Alan Cox355d95a2008-02-08 04:18:48 -0800607
Linus Torvalds1da177e2005-04-16 15:20:36 -0700608 if (ld != NULL) {
Alan Coxa352def2008-07-16 21:53:12 +0100609 if ((opt & TERMIOS_FLUSH) && ld->ops->flush_buffer)
610 ld->ops->flush_buffer(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700611 tty_ldisc_deref(ld);
612 }
Alan Cox355d95a2008-02-08 04:18:48 -0800613
Linus Torvalds1da177e2005-04-16 15:20:36 -0700614 if (opt & TERMIOS_WAIT) {
615 tty_wait_until_sent(tty, 0);
616 if (signal_pending(current))
617 return -EINTR;
618 }
619
620 change_termios(tty, &tmp_termios);
Alan Cox5f519d72007-10-16 23:30:07 -0700621
622 /* FIXME: Arguably if tmp_termios == tty->termios AND the
623 actual requested termios was not tmp_termios then we may
624 want to return an error as no user requested change has
625 succeeded */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700626 return 0;
627}
628
Alan Cox355d95a2008-02-08 04:18:48 -0800629static int get_termio(struct tty_struct *tty, struct termio __user *termio)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700630{
631 if (kernel_termios_to_user_termio(termio, tty->termios))
632 return -EFAULT;
633 return 0;
634}
635
Alan Cox1d65b4a2008-10-13 10:38:18 +0100636
637#ifdef TCGETX
638
639/**
640 * set_termiox - set termiox fields if possible
641 * @tty: terminal
642 * @arg: termiox structure from user
643 * @opt: option flags for ioctl type
644 *
645 * Implement the device calling points for the SYS5 termiox ioctl
646 * interface in Linux
647 */
648
649static int set_termiox(struct tty_struct *tty, void __user *arg, int opt)
650{
651 struct termiox tnew;
652 struct tty_ldisc *ld;
653
654 if (tty->termiox == NULL)
655 return -EINVAL;
656 if (copy_from_user(&tnew, arg, sizeof(struct termiox)))
657 return -EFAULT;
658
659 ld = tty_ldisc_ref(tty);
660 if (ld != NULL) {
661 if ((opt & TERMIOS_FLUSH) && ld->ops->flush_buffer)
662 ld->ops->flush_buffer(tty);
663 tty_ldisc_deref(ld);
664 }
665 if (opt & TERMIOS_WAIT) {
666 tty_wait_until_sent(tty, 0);
667 if (signal_pending(current))
668 return -EINTR;
669 }
670
671 mutex_lock(&tty->termios_mutex);
672 if (tty->ops->set_termiox)
673 tty->ops->set_termiox(tty, &tnew);
674 mutex_unlock(&tty->termios_mutex);
675 return 0;
676}
677
678#endif
679
Alan Cox355d95a2008-02-08 04:18:48 -0800680static unsigned long inq_canon(struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700681{
682 int nr, head, tail;
683
684 if (!tty->canon_data || !tty->read_buf)
685 return 0;
686 head = tty->canon_head;
687 tail = tty->read_tail;
688 nr = (head - tail) & (N_TTY_BUF_SIZE-1);
689 /* Skip EOF-chars.. */
690 while (head != tail) {
691 if (test_bit(tail, tty->read_flags) &&
692 tty->read_buf[tail] == __DISABLED_CHAR)
693 nr--;
694 tail = (tail+1) & (N_TTY_BUF_SIZE-1);
695 }
696 return nr;
697}
698
699#ifdef TIOCGETP
700/*
701 * These are deprecated, but there is limited support..
702 *
703 * The "sg_flags" translation is a joke..
704 */
Alan Cox355d95a2008-02-08 04:18:48 -0800705static int get_sgflags(struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700706{
707 int flags = 0;
708
709 if (!(tty->termios->c_lflag & ICANON)) {
710 if (tty->termios->c_lflag & ISIG)
711 flags |= 0x02; /* cbreak */
712 else
713 flags |= 0x20; /* raw */
714 }
715 if (tty->termios->c_lflag & ECHO)
716 flags |= 0x08; /* echo */
717 if (tty->termios->c_oflag & OPOST)
718 if (tty->termios->c_oflag & ONLCR)
719 flags |= 0x10; /* crmod */
720 return flags;
721}
722
Alan Cox355d95a2008-02-08 04:18:48 -0800723static int get_sgttyb(struct tty_struct *tty, struct sgttyb __user *sgttyb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700724{
725 struct sgttyb tmp;
726
Arjan van de Ven5785c952006-09-29 02:00:43 -0700727 mutex_lock(&tty->termios_mutex);
Alan Cox606d0992006-12-08 02:38:45 -0800728 tmp.sg_ispeed = tty->termios->c_ispeed;
729 tmp.sg_ospeed = tty->termios->c_ospeed;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700730 tmp.sg_erase = tty->termios->c_cc[VERASE];
731 tmp.sg_kill = tty->termios->c_cc[VKILL];
732 tmp.sg_flags = get_sgflags(tty);
Arjan van de Ven5785c952006-09-29 02:00:43 -0700733 mutex_unlock(&tty->termios_mutex);
Alan Cox355d95a2008-02-08 04:18:48 -0800734
Linus Torvalds1da177e2005-04-16 15:20:36 -0700735 return copy_to_user(sgttyb, &tmp, sizeof(tmp)) ? -EFAULT : 0;
736}
737
Alan Cox355d95a2008-02-08 04:18:48 -0800738static void set_sgflags(struct ktermios *termios, int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700739{
740 termios->c_iflag = ICRNL | IXON;
741 termios->c_oflag = 0;
742 termios->c_lflag = ISIG | ICANON;
743 if (flags & 0x02) { /* cbreak */
744 termios->c_iflag = 0;
745 termios->c_lflag &= ~ICANON;
746 }
747 if (flags & 0x08) { /* echo */
748 termios->c_lflag |= ECHO | ECHOE | ECHOK |
749 ECHOCTL | ECHOKE | IEXTEN;
750 }
751 if (flags & 0x10) { /* crmod */
752 termios->c_oflag |= OPOST | ONLCR;
753 }
754 if (flags & 0x20) { /* raw */
755 termios->c_iflag = 0;
756 termios->c_lflag &= ~(ISIG | ICANON);
757 }
758 if (!(termios->c_lflag & ICANON)) {
759 termios->c_cc[VMIN] = 1;
760 termios->c_cc[VTIME] = 0;
761 }
762}
763
Alan Coxaf9b8972006-08-27 01:24:01 -0700764/**
765 * set_sgttyb - set legacy terminal values
766 * @tty: tty structure
767 * @sgttyb: pointer to old style terminal structure
768 *
769 * Updates a terminal from the legacy BSD style terminal information
770 * structure.
771 *
Alan Coxd81ed102008-10-13 10:41:42 +0100772 * Locking: termios_mutex
Alan Coxaf9b8972006-08-27 01:24:01 -0700773 */
774
Alan Cox355d95a2008-02-08 04:18:48 -0800775static int set_sgttyb(struct tty_struct *tty, struct sgttyb __user *sgttyb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700776{
777 int retval;
778 struct sgttyb tmp;
Alan Coxedc6afc2006-12-08 02:38:44 -0800779 struct ktermios termios;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700780
781 retval = tty_check_change(tty);
782 if (retval)
783 return retval;
Alan Cox355d95a2008-02-08 04:18:48 -0800784
Linus Torvalds1da177e2005-04-16 15:20:36 -0700785 if (copy_from_user(&tmp, sgttyb, sizeof(tmp)))
786 return -EFAULT;
787
Arjan van de Ven5785c952006-09-29 02:00:43 -0700788 mutex_lock(&tty->termios_mutex);
Jiri Slaby68043962007-07-15 23:40:18 -0700789 termios = *tty->termios;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700790 termios.c_cc[VERASE] = tmp.sg_erase;
791 termios.c_cc[VKILL] = tmp.sg_kill;
792 set_sgflags(&termios, tmp.sg_flags);
Alan Coxedc6afc2006-12-08 02:38:44 -0800793 /* Try and encode into Bfoo format */
794#ifdef BOTHER
Alan Cox355d95a2008-02-08 04:18:48 -0800795 tty_termios_encode_baud_rate(&termios, termios.c_ispeed,
796 termios.c_ospeed);
Alan Coxedc6afc2006-12-08 02:38:44 -0800797#endif
Arjan van de Ven5785c952006-09-29 02:00:43 -0700798 mutex_unlock(&tty->termios_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700799 change_termios(tty, &termios);
800 return 0;
801}
802#endif
803
804#ifdef TIOCGETC
Alan Cox355d95a2008-02-08 04:18:48 -0800805static int get_tchars(struct tty_struct *tty, struct tchars __user *tchars)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700806{
807 struct tchars tmp;
808
Alan Cox978e5952008-04-30 00:53:59 -0700809 mutex_lock(&tty->termios_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700810 tmp.t_intrc = tty->termios->c_cc[VINTR];
811 tmp.t_quitc = tty->termios->c_cc[VQUIT];
812 tmp.t_startc = tty->termios->c_cc[VSTART];
813 tmp.t_stopc = tty->termios->c_cc[VSTOP];
814 tmp.t_eofc = tty->termios->c_cc[VEOF];
815 tmp.t_brkc = tty->termios->c_cc[VEOL2]; /* what is brkc anyway? */
Alan Cox978e5952008-04-30 00:53:59 -0700816 mutex_unlock(&tty->termios_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700817 return copy_to_user(tchars, &tmp, sizeof(tmp)) ? -EFAULT : 0;
818}
819
Alan Cox355d95a2008-02-08 04:18:48 -0800820static int set_tchars(struct tty_struct *tty, struct tchars __user *tchars)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700821{
822 struct tchars tmp;
823
824 if (copy_from_user(&tmp, tchars, sizeof(tmp)))
825 return -EFAULT;
Alan Cox978e5952008-04-30 00:53:59 -0700826 mutex_lock(&tty->termios_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700827 tty->termios->c_cc[VINTR] = tmp.t_intrc;
828 tty->termios->c_cc[VQUIT] = tmp.t_quitc;
829 tty->termios->c_cc[VSTART] = tmp.t_startc;
830 tty->termios->c_cc[VSTOP] = tmp.t_stopc;
831 tty->termios->c_cc[VEOF] = tmp.t_eofc;
832 tty->termios->c_cc[VEOL2] = tmp.t_brkc; /* what is brkc anyway? */
Alan Cox978e5952008-04-30 00:53:59 -0700833 mutex_unlock(&tty->termios_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700834 return 0;
835}
836#endif
837
838#ifdef TIOCGLTC
Alan Cox355d95a2008-02-08 04:18:48 -0800839static int get_ltchars(struct tty_struct *tty, struct ltchars __user *ltchars)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700840{
841 struct ltchars tmp;
842
Alan Cox978e5952008-04-30 00:53:59 -0700843 mutex_lock(&tty->termios_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700844 tmp.t_suspc = tty->termios->c_cc[VSUSP];
Alan Cox355d95a2008-02-08 04:18:48 -0800845 /* what is dsuspc anyway? */
846 tmp.t_dsuspc = tty->termios->c_cc[VSUSP];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700847 tmp.t_rprntc = tty->termios->c_cc[VREPRINT];
Alan Cox355d95a2008-02-08 04:18:48 -0800848 /* what is flushc anyway? */
849 tmp.t_flushc = tty->termios->c_cc[VEOL2];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700850 tmp.t_werasc = tty->termios->c_cc[VWERASE];
851 tmp.t_lnextc = tty->termios->c_cc[VLNEXT];
Alan Cox978e5952008-04-30 00:53:59 -0700852 mutex_unlock(&tty->termios_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700853 return copy_to_user(ltchars, &tmp, sizeof(tmp)) ? -EFAULT : 0;
854}
855
Alan Cox355d95a2008-02-08 04:18:48 -0800856static int set_ltchars(struct tty_struct *tty, struct ltchars __user *ltchars)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700857{
858 struct ltchars tmp;
859
860 if (copy_from_user(&tmp, ltchars, sizeof(tmp)))
861 return -EFAULT;
862
Alan Cox978e5952008-04-30 00:53:59 -0700863 mutex_lock(&tty->termios_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700864 tty->termios->c_cc[VSUSP] = tmp.t_suspc;
Alan Cox355d95a2008-02-08 04:18:48 -0800865 /* what is dsuspc anyway? */
866 tty->termios->c_cc[VEOL2] = tmp.t_dsuspc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700867 tty->termios->c_cc[VREPRINT] = tmp.t_rprntc;
Alan Cox355d95a2008-02-08 04:18:48 -0800868 /* what is flushc anyway? */
869 tty->termios->c_cc[VEOL2] = tmp.t_flushc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700870 tty->termios->c_cc[VWERASE] = tmp.t_werasc;
871 tty->termios->c_cc[VLNEXT] = tmp.t_lnextc;
Alan Cox978e5952008-04-30 00:53:59 -0700872 mutex_unlock(&tty->termios_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700873 return 0;
874}
875#endif
876
Alan Coxaf9b8972006-08-27 01:24:01 -0700877/**
878 * send_prio_char - send priority character
879 *
880 * Send a high priority character to the tty even if stopped
881 *
Alan Cox5f412b22006-09-29 02:01:40 -0700882 * Locking: none for xchar method, write ordering for write method.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700883 */
Alan Coxaf9b8972006-08-27 01:24:01 -0700884
Alan Cox5f412b22006-09-29 02:01:40 -0700885static int send_prio_char(struct tty_struct *tty, char ch)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700886{
887 int was_stopped = tty->stopped;
888
Alan Coxf34d7a52008-04-30 00:54:13 -0700889 if (tty->ops->send_xchar) {
890 tty->ops->send_xchar(tty, ch);
Alan Cox5f412b22006-09-29 02:01:40 -0700891 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700892 }
Alan Cox5f412b22006-09-29 02:01:40 -0700893
Alan Cox9c1729d2007-07-15 23:39:43 -0700894 if (tty_write_lock(tty, 0) < 0)
Alan Cox5f412b22006-09-29 02:01:40 -0700895 return -ERESTARTSYS;
896
Linus Torvalds1da177e2005-04-16 15:20:36 -0700897 if (was_stopped)
898 start_tty(tty);
Alan Coxf34d7a52008-04-30 00:54:13 -0700899 tty->ops->write(tty, &ch, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700900 if (was_stopped)
901 stop_tty(tty);
Alan Cox9c1729d2007-07-15 23:39:43 -0700902 tty_write_unlock(tty);
Alan Cox5f412b22006-09-29 02:01:40 -0700903 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700904}
905
Alan Cox0fc00e22007-11-07 01:24:56 -0800906/**
Alan Cox1c2630c2008-04-30 00:53:34 -0700907 * tty_change_softcar - carrier change ioctl helper
908 * @tty: tty to update
909 * @arg: enable/disable CLOCAL
910 *
911 * Perform a change to the CLOCAL state and call into the driver
912 * layer to make it visible. All done with the termios mutex
913 */
914
915static int tty_change_softcar(struct tty_struct *tty, int arg)
916{
917 int ret = 0;
918 int bit = arg ? CLOCAL : 0;
Alan Coxf34d7a52008-04-30 00:54:13 -0700919 struct ktermios old;
Alan Cox1c2630c2008-04-30 00:53:34 -0700920
921 mutex_lock(&tty->termios_mutex);
Alan Coxf34d7a52008-04-30 00:54:13 -0700922 old = *tty->termios;
Alan Cox1c2630c2008-04-30 00:53:34 -0700923 tty->termios->c_cflag &= ~CLOCAL;
924 tty->termios->c_cflag |= bit;
Alan Coxf34d7a52008-04-30 00:54:13 -0700925 if (tty->ops->set_termios)
926 tty->ops->set_termios(tty, &old);
Alan Cox1c2630c2008-04-30 00:53:34 -0700927 if ((tty->termios->c_cflag & CLOCAL) != bit)
928 ret = -EINVAL;
929 mutex_unlock(&tty->termios_mutex);
930 return ret;
931}
932
933/**
Alan Cox0fc00e22007-11-07 01:24:56 -0800934 * tty_mode_ioctl - mode related ioctls
935 * @tty: tty for the ioctl
936 * @file: file pointer for the tty
937 * @cmd: command
938 * @arg: ioctl argument
939 *
940 * Perform non line discipline specific mode control ioctls. This
941 * is designed to be called by line disciplines to ensure they provide
942 * consistent mode setting.
943 */
944
Alan Cox355d95a2008-02-08 04:18:48 -0800945int tty_mode_ioctl(struct tty_struct *tty, struct file *file,
Alan Cox0fc00e22007-11-07 01:24:56 -0800946 unsigned int cmd, unsigned long arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700947{
Alan Cox355d95a2008-02-08 04:18:48 -0800948 struct tty_struct *real_tty;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700949 void __user *p = (void __user *)arg;
Alan Cox8f520022008-10-13 10:38:46 +0100950 int ret = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700951
952 if (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
953 tty->driver->subtype == PTY_TYPE_MASTER)
954 real_tty = tty->link;
955 else
956 real_tty = tty;
957
958 switch (cmd) {
959#ifdef TIOCGETP
Alan Cox355d95a2008-02-08 04:18:48 -0800960 case TIOCGETP:
961 return get_sgttyb(real_tty, (struct sgttyb __user *) arg);
962 case TIOCSETP:
963 case TIOCSETN:
964 return set_sgttyb(real_tty, (struct sgttyb __user *) arg);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700965#endif
966#ifdef TIOCGETC
Alan Cox355d95a2008-02-08 04:18:48 -0800967 case TIOCGETC:
968 return get_tchars(real_tty, p);
969 case TIOCSETC:
970 return set_tchars(real_tty, p);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700971#endif
972#ifdef TIOCGLTC
Alan Cox355d95a2008-02-08 04:18:48 -0800973 case TIOCGLTC:
974 return get_ltchars(real_tty, p);
975 case TIOCSLTC:
976 return set_ltchars(real_tty, p);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700977#endif
Alan Cox355d95a2008-02-08 04:18:48 -0800978 case TCSETSF:
979 return set_termios(real_tty, p, TERMIOS_FLUSH | TERMIOS_WAIT | TERMIOS_OLD);
980 case TCSETSW:
981 return set_termios(real_tty, p, TERMIOS_WAIT | TERMIOS_OLD);
982 case TCSETS:
983 return set_termios(real_tty, p, TERMIOS_OLD);
Alan Coxedc6afc2006-12-08 02:38:44 -0800984#ifndef TCGETS2
Alan Cox355d95a2008-02-08 04:18:48 -0800985 case TCGETS:
Alan Cox8f520022008-10-13 10:38:46 +0100986 mutex_lock(&real_tty->termios_mutex);
Alan Cox355d95a2008-02-08 04:18:48 -0800987 if (kernel_termios_to_user_termios((struct termios __user *)arg, real_tty->termios))
Alan Cox8f520022008-10-13 10:38:46 +0100988 ret = -EFAULT;
989 mutex_unlock(&real_tty->termios_mutex);
990 return ret;
Alan Coxedc6afc2006-12-08 02:38:44 -0800991#else
Alan Cox355d95a2008-02-08 04:18:48 -0800992 case TCGETS:
Alan Cox8f520022008-10-13 10:38:46 +0100993 mutex_lock(&real_tty->termios_mutex);
Alan Cox355d95a2008-02-08 04:18:48 -0800994 if (kernel_termios_to_user_termios_1((struct termios __user *)arg, real_tty->termios))
Alan Cox8f520022008-10-13 10:38:46 +0100995 ret = -EFAULT;
996 mutex_unlock(&real_tty->termios_mutex);
997 return ret;
Alan Cox355d95a2008-02-08 04:18:48 -0800998 case TCGETS2:
Alan Cox8f520022008-10-13 10:38:46 +0100999 mutex_lock(&real_tty->termios_mutex);
Alan Cox355d95a2008-02-08 04:18:48 -08001000 if (kernel_termios_to_user_termios((struct termios2 __user *)arg, real_tty->termios))
Alan Cox8f520022008-10-13 10:38:46 +01001001 ret = -EFAULT;
1002 mutex_unlock(&real_tty->termios_mutex);
1003 return ret;
Alan Cox355d95a2008-02-08 04:18:48 -08001004 case TCSETSF2:
1005 return set_termios(real_tty, p, TERMIOS_FLUSH | TERMIOS_WAIT);
1006 case TCSETSW2:
1007 return set_termios(real_tty, p, TERMIOS_WAIT);
1008 case TCSETS2:
1009 return set_termios(real_tty, p, 0);
Alan Coxedc6afc2006-12-08 02:38:44 -08001010#endif
Alan Cox355d95a2008-02-08 04:18:48 -08001011 case TCGETA:
1012 return get_termio(real_tty, p);
1013 case TCSETAF:
1014 return set_termios(real_tty, p, TERMIOS_FLUSH | TERMIOS_WAIT | TERMIOS_TERMIO);
1015 case TCSETAW:
1016 return set_termios(real_tty, p, TERMIOS_WAIT | TERMIOS_TERMIO);
1017 case TCSETA:
1018 return set_termios(real_tty, p, TERMIOS_TERMIO);
Alan Cox0fc00e22007-11-07 01:24:56 -08001019#ifndef TCGETS2
Alan Cox355d95a2008-02-08 04:18:48 -08001020 case TIOCGLCKTRMIOS:
Alan Cox8f520022008-10-13 10:38:46 +01001021 mutex_lock(&real_tty->termios_mutex);
Alan Cox355d95a2008-02-08 04:18:48 -08001022 if (kernel_termios_to_user_termios((struct termios __user *)arg, real_tty->termios_locked))
Alan Cox8f520022008-10-13 10:38:46 +01001023 ret = -EFAULT;
1024 mutex_unlock(&real_tty->termios_mutex);
1025 return ret;
Alan Cox355d95a2008-02-08 04:18:48 -08001026 case TIOCSLCKTRMIOS:
1027 if (!capable(CAP_SYS_ADMIN))
1028 return -EPERM;
Alan Cox8f520022008-10-13 10:38:46 +01001029 mutex_lock(&real_tty->termios_mutex);
Alan Cox355d95a2008-02-08 04:18:48 -08001030 if (user_termios_to_kernel_termios(real_tty->termios_locked,
1031 (struct termios __user *) arg))
Alan Cox8f520022008-10-13 10:38:46 +01001032 ret = -EFAULT;
1033 mutex_unlock(&real_tty->termios_mutex);
1034 return ret;
Alan Cox0fc00e22007-11-07 01:24:56 -08001035#else
Alan Cox355d95a2008-02-08 04:18:48 -08001036 case TIOCGLCKTRMIOS:
Alan Cox8f520022008-10-13 10:38:46 +01001037 mutex_lock(&real_tty->termios_mutex);
Alan Cox355d95a2008-02-08 04:18:48 -08001038 if (kernel_termios_to_user_termios_1((struct termios __user *)arg, real_tty->termios_locked))
Alan Cox8f520022008-10-13 10:38:46 +01001039 ret = -EFAULT;
1040 mutex_unlock(&real_tty->termios_mutex);
1041 return ret;
Alan Cox355d95a2008-02-08 04:18:48 -08001042 case TIOCSLCKTRMIOS:
1043 if (!capable(CAP_SYS_ADMIN))
Alan Cox8f520022008-10-13 10:38:46 +01001044 ret = -EPERM;
1045 mutex_lock(&real_tty->termios_mutex);
Alan Cox355d95a2008-02-08 04:18:48 -08001046 if (user_termios_to_kernel_termios_1(real_tty->termios_locked,
1047 (struct termios __user *) arg))
Alan Cox8f520022008-10-13 10:38:46 +01001048 ret = -EFAULT;
1049 mutex_unlock(&real_tty->termios_mutex);
1050 return ret;
Alan Cox0fc00e22007-11-07 01:24:56 -08001051#endif
Alan Cox1d65b4a2008-10-13 10:38:18 +01001052#ifdef TCGETX
1053 case TCGETX:
1054 if (real_tty->termiox == NULL)
1055 return -EINVAL;
Alan Cox8f520022008-10-13 10:38:46 +01001056 mutex_lock(&real_tty->termios_mutex);
Alan Cox1d65b4a2008-10-13 10:38:18 +01001057 if (copy_to_user(p, real_tty->termiox, sizeof(struct termiox)))
Alan Cox8f520022008-10-13 10:38:46 +01001058 ret = -EFAULT;
1059 mutex_unlock(&real_tty->termios_mutex);
1060 return ret;
Alan Cox1d65b4a2008-10-13 10:38:18 +01001061 case TCSETX:
1062 return set_termiox(real_tty, p, 0);
1063 case TCSETXW:
1064 return set_termiox(real_tty, p, TERMIOS_WAIT);
1065 case TCSETXF:
1066 return set_termiox(real_tty, p, TERMIOS_FLUSH);
1067#endif
Alan Cox355d95a2008-02-08 04:18:48 -08001068 case TIOCGSOFTCAR:
Alan Cox8f520022008-10-13 10:38:46 +01001069 mutex_lock(&real_tty->termios_mutex);
1070 ret = put_user(C_CLOCAL(real_tty) ? 1 : 0,
Alan Cox355d95a2008-02-08 04:18:48 -08001071 (int __user *)arg);
Alan Cox8f520022008-10-13 10:38:46 +01001072 mutex_unlock(&real_tty->termios_mutex);
1073 return ret;
Alan Cox355d95a2008-02-08 04:18:48 -08001074 case TIOCSSOFTCAR:
1075 if (get_user(arg, (unsigned int __user *) arg))
1076 return -EFAULT;
Alan Coxf753f322008-08-26 19:52:47 +01001077 return tty_change_softcar(real_tty, arg);
Alan Cox355d95a2008-02-08 04:18:48 -08001078 default:
1079 return -ENOIOCTLCMD;
Alan Cox0fc00e22007-11-07 01:24:56 -08001080 }
1081}
Alan Cox0fc00e22007-11-07 01:24:56 -08001082EXPORT_SYMBOL_GPL(tty_mode_ioctl);
1083
1084int tty_perform_flush(struct tty_struct *tty, unsigned long arg)
1085{
1086 struct tty_ldisc *ld;
1087 int retval = tty_check_change(tty);
1088 if (retval)
1089 return retval;
1090
1091 ld = tty_ldisc_ref(tty);
1092 switch (arg) {
1093 case TCIFLUSH:
Alan Coxa352def2008-07-16 21:53:12 +01001094 if (ld && ld->ops->flush_buffer)
1095 ld->ops->flush_buffer(tty);
Alan Cox0fc00e22007-11-07 01:24:56 -08001096 break;
1097 case TCIOFLUSH:
Alan Coxa352def2008-07-16 21:53:12 +01001098 if (ld && ld->ops->flush_buffer)
1099 ld->ops->flush_buffer(tty);
Alan Cox0fc00e22007-11-07 01:24:56 -08001100 /* fall through */
1101 case TCOFLUSH:
Alan Coxf34d7a52008-04-30 00:54:13 -07001102 tty_driver_flush_buffer(tty);
Alan Cox0fc00e22007-11-07 01:24:56 -08001103 break;
1104 default:
1105 tty_ldisc_deref(ld);
1106 return -EINVAL;
1107 }
1108 tty_ldisc_deref(ld);
1109 return 0;
1110}
Alan Cox0fc00e22007-11-07 01:24:56 -08001111EXPORT_SYMBOL_GPL(tty_perform_flush);
1112
Alan Cox355d95a2008-02-08 04:18:48 -08001113int n_tty_ioctl(struct tty_struct *tty, struct file *file,
Alan Cox0fc00e22007-11-07 01:24:56 -08001114 unsigned int cmd, unsigned long arg)
1115{
Alan Cox04f378b2008-04-30 00:53:29 -07001116 unsigned long flags;
Alan Cox0fc00e22007-11-07 01:24:56 -08001117 int retval;
1118
Alan Cox0fc00e22007-11-07 01:24:56 -08001119 switch (cmd) {
Alan Cox355d95a2008-02-08 04:18:48 -08001120 case TCXONC:
1121 retval = tty_check_change(tty);
1122 if (retval)
1123 return retval;
1124 switch (arg) {
1125 case TCOOFF:
1126 if (!tty->flow_stopped) {
1127 tty->flow_stopped = 1;
1128 stop_tty(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001129 }
Alan Cox355d95a2008-02-08 04:18:48 -08001130 break;
1131 case TCOON:
1132 if (tty->flow_stopped) {
1133 tty->flow_stopped = 0;
1134 start_tty(tty);
1135 }
1136 break;
1137 case TCIOFF:
1138 if (STOP_CHAR(tty) != __DISABLED_CHAR)
1139 return send_prio_char(tty, STOP_CHAR(tty));
1140 break;
1141 case TCION:
1142 if (START_CHAR(tty) != __DISABLED_CHAR)
1143 return send_prio_char(tty, START_CHAR(tty));
1144 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001145 default:
Alan Cox355d95a2008-02-08 04:18:48 -08001146 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001147 }
Alan Cox355d95a2008-02-08 04:18:48 -08001148 return 0;
1149 case TCFLSH:
1150 return tty_perform_flush(tty, arg);
1151 case TIOCOUTQ:
Alan Coxf34d7a52008-04-30 00:54:13 -07001152 return put_user(tty_chars_in_buffer(tty), (int __user *) arg);
Alan Cox355d95a2008-02-08 04:18:48 -08001153 case TIOCINQ:
1154 retval = tty->read_cnt;
1155 if (L_ICANON(tty))
1156 retval = inq_canon(tty);
1157 return put_user(retval, (unsigned int __user *) arg);
1158 case TIOCPKT:
1159 {
1160 int pktmode;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001161
Alan Cox355d95a2008-02-08 04:18:48 -08001162 if (tty->driver->type != TTY_DRIVER_TYPE_PTY ||
1163 tty->driver->subtype != PTY_TYPE_MASTER)
1164 return -ENOTTY;
1165 if (get_user(pktmode, (int __user *) arg))
1166 return -EFAULT;
Alan Cox04f378b2008-04-30 00:53:29 -07001167 spin_lock_irqsave(&tty->ctrl_lock, flags);
Alan Cox355d95a2008-02-08 04:18:48 -08001168 if (pktmode) {
1169 if (!tty->packet) {
1170 tty->packet = 1;
1171 tty->link->ctrl_status = 0;
1172 }
1173 } else
1174 tty->packet = 0;
Alan Cox04f378b2008-04-30 00:53:29 -07001175 spin_unlock_irqrestore(&tty->ctrl_lock, flags);
Alan Cox355d95a2008-02-08 04:18:48 -08001176 return 0;
1177 }
1178 default:
1179 /* Try the mode commands */
1180 return tty_mode_ioctl(tty, file, cmd, arg);
1181 }
1182}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001183EXPORT_SYMBOL(n_tty_ioctl);