blob: 9c5aebfe7053cbcae1fd65a95f3312509525e8e6 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002 * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds
3 *
4 * Modified by Fred N. van Kempen, 01/29/93, to add line disciplines
5 * which can be dynamically activated and de-activated by the line
6 * discipline handling modules (like SLIP).
7 */
8
9#include <linux/types.h>
10#include <linux/termios.h>
11#include <linux/errno.h>
12#include <linux/sched.h>
13#include <linux/kernel.h>
14#include <linux/major.h>
15#include <linux/tty.h>
16#include <linux/fcntl.h>
17#include <linux/string.h>
18#include <linux/mm.h>
19#include <linux/module.h>
20#include <linux/bitops.h>
Arjan van de Ven5785c952006-09-29 02:00:43 -070021#include <linux/mutex.h>
Thomas Meyer8193c422011-10-05 23:13:13 +020022#include <linux/compat.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070023
24#include <asm/io.h>
25#include <asm/uaccess.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070026
27#undef TTY_DEBUG_WAIT_UNTIL_SENT
28
Peter Hurleyff8339d2015-07-12 22:49:11 -040029#ifdef TTY_DEBUG_WAIT_UNTIL_SENT
30# define tty_debug_wait_until_sent(tty, f, args...) tty_debug(tty, f, ##args)
31#else
32# define tty_debug_wait_until_sent(tty, f, args...) do {} while (0)
33#endif
34
Linus Torvalds1da177e2005-04-16 15:20:36 -070035#undef DEBUG
36
37/*
38 * Internal flag options for termios setting behavior
39 */
40#define TERMIOS_FLUSH 1
41#define TERMIOS_WAIT 2
42#define TERMIOS_TERMIO 4
Alan Coxedc6afc2006-12-08 02:38:44 -080043#define TERMIOS_OLD 8
Linus Torvalds1da177e2005-04-16 15:20:36 -070044
Alan Coxaf9b8972006-08-27 01:24:01 -070045
Alan Coxd81ed102008-10-13 10:41:42 +010046/**
47 * tty_chars_in_buffer - characters pending
48 * @tty: terminal
49 *
50 * Return the number of bytes of data in the device private
51 * output queue. If no private method is supplied there is assumed
52 * to be no queue on the device.
53 */
54
Alan Coxf34d7a52008-04-30 00:54:13 -070055int tty_chars_in_buffer(struct tty_struct *tty)
56{
57 if (tty->ops->chars_in_buffer)
58 return tty->ops->chars_in_buffer(tty);
59 else
60 return 0;
61}
Alan Coxf34d7a52008-04-30 00:54:13 -070062EXPORT_SYMBOL(tty_chars_in_buffer);
63
Alan Coxd81ed102008-10-13 10:41:42 +010064/**
65 * tty_write_room - write queue space
66 * @tty: terminal
67 *
68 * Return the number of bytes that can be queued to this device
69 * at the present time. The result should be treated as a guarantee
70 * and the driver cannot offer a value it later shrinks by more than
71 * the number of bytes written. If no method is provided 2K is always
72 * returned and data may be lost as there will be no flow control.
73 */
74
Alan Coxf34d7a52008-04-30 00:54:13 -070075int tty_write_room(struct tty_struct *tty)
76{
77 if (tty->ops->write_room)
78 return tty->ops->write_room(tty);
79 return 2048;
80}
Alan Coxf34d7a52008-04-30 00:54:13 -070081EXPORT_SYMBOL(tty_write_room);
82
Alan Coxd81ed102008-10-13 10:41:42 +010083/**
84 * tty_driver_flush_buffer - discard internal buffer
85 * @tty: terminal
86 *
87 * Discard the internal output buffer for this device. If no method
88 * is provided then either the buffer cannot be hardware flushed or
89 * there is no buffer driver side.
90 */
Alan Coxf34d7a52008-04-30 00:54:13 -070091void tty_driver_flush_buffer(struct tty_struct *tty)
92{
93 if (tty->ops->flush_buffer)
94 tty->ops->flush_buffer(tty);
95}
Alan Coxf34d7a52008-04-30 00:54:13 -070096EXPORT_SYMBOL(tty_driver_flush_buffer);
97
Alan Coxd81ed102008-10-13 10:41:42 +010098/**
99 * tty_throttle - flow control
100 * @tty: terminal
101 *
102 * Indicate that a tty should stop transmitting data down the stack.
Peter Hurley6a1c0682013-06-15 09:14:23 -0400103 * Takes the termios rwsem to protect against parallel throttle/unthrottle
Alan Cox38db8972009-06-11 12:44:17 +0100104 * and also to ensure the driver can consistently reference its own
105 * termios data at this point when implementing software flow control.
Alan Coxd81ed102008-10-13 10:41:42 +0100106 */
107
Alan Cox39c2e602008-04-30 00:54:18 -0700108void tty_throttle(struct tty_struct *tty)
109{
Peter Hurley6a1c0682013-06-15 09:14:23 -0400110 down_write(&tty->termios_rwsem);
Alan Cox39c2e602008-04-30 00:54:18 -0700111 /* check TTY_THROTTLED first so it indicates our state */
112 if (!test_and_set_bit(TTY_THROTTLED, &tty->flags) &&
113 tty->ops->throttle)
114 tty->ops->throttle(tty);
Peter Hurley70bc1262013-03-06 08:20:52 -0500115 tty->flow_change = 0;
Peter Hurley6a1c0682013-06-15 09:14:23 -0400116 up_write(&tty->termios_rwsem);
Alan Cox39c2e602008-04-30 00:54:18 -0700117}
118EXPORT_SYMBOL(tty_throttle);
119
Alan Coxd81ed102008-10-13 10:41:42 +0100120/**
121 * tty_unthrottle - flow control
122 * @tty: terminal
123 *
124 * Indicate that a tty may continue transmitting data down the stack.
Peter Hurley6a1c0682013-06-15 09:14:23 -0400125 * Takes the termios rwsem to protect against parallel throttle/unthrottle
Alan Cox38db8972009-06-11 12:44:17 +0100126 * and also to ensure the driver can consistently reference its own
127 * termios data at this point when implementing software flow control.
128 *
129 * Drivers should however remember that the stack can issue a throttle,
130 * then change flow control method, then unthrottle.
Alan Coxd81ed102008-10-13 10:41:42 +0100131 */
132
Alan Cox39c2e602008-04-30 00:54:18 -0700133void tty_unthrottle(struct tty_struct *tty)
134{
Peter Hurley6a1c0682013-06-15 09:14:23 -0400135 down_write(&tty->termios_rwsem);
Alan Cox39c2e602008-04-30 00:54:18 -0700136 if (test_and_clear_bit(TTY_THROTTLED, &tty->flags) &&
137 tty->ops->unthrottle)
138 tty->ops->unthrottle(tty);
Peter Hurley70bc1262013-03-06 08:20:52 -0500139 tty->flow_change = 0;
Peter Hurley6a1c0682013-06-15 09:14:23 -0400140 up_write(&tty->termios_rwsem);
Alan Cox39c2e602008-04-30 00:54:18 -0700141}
142EXPORT_SYMBOL(tty_unthrottle);
Alan Coxf34d7a52008-04-30 00:54:13 -0700143
Alan Coxaf9b8972006-08-27 01:24:01 -0700144/**
Peter Hurley70bc1262013-03-06 08:20:52 -0500145 * tty_throttle_safe - flow control
146 * @tty: terminal
147 *
148 * Similar to tty_throttle() but will only attempt throttle
149 * if tty->flow_change is TTY_THROTTLE_SAFE. Prevents an accidental
150 * throttle due to race conditions when throttling is conditional
151 * on factors evaluated prior to throttling.
152 *
153 * Returns 0 if tty is throttled (or was already throttled)
154 */
155
156int tty_throttle_safe(struct tty_struct *tty)
157{
158 int ret = 0;
159
Peter Hurleyd8c1f922013-06-15 09:14:31 -0400160 mutex_lock(&tty->throttle_mutex);
Peter Hurley70bc1262013-03-06 08:20:52 -0500161 if (!test_bit(TTY_THROTTLED, &tty->flags)) {
162 if (tty->flow_change != TTY_THROTTLE_SAFE)
163 ret = 1;
164 else {
Peter Hurley579a00a2013-04-15 11:06:06 -0400165 set_bit(TTY_THROTTLED, &tty->flags);
Peter Hurley70bc1262013-03-06 08:20:52 -0500166 if (tty->ops->throttle)
167 tty->ops->throttle(tty);
168 }
169 }
Peter Hurleyd8c1f922013-06-15 09:14:31 -0400170 mutex_unlock(&tty->throttle_mutex);
Peter Hurley70bc1262013-03-06 08:20:52 -0500171
172 return ret;
173}
174
175/**
176 * tty_unthrottle_safe - flow control
177 * @tty: terminal
178 *
179 * Similar to tty_unthrottle() but will only attempt unthrottle
180 * if tty->flow_change is TTY_UNTHROTTLE_SAFE. Prevents an accidental
181 * unthrottle due to race conditions when unthrottling is conditional
182 * on factors evaluated prior to unthrottling.
183 *
184 * Returns 0 if tty is unthrottled (or was already unthrottled)
185 */
186
187int tty_unthrottle_safe(struct tty_struct *tty)
188{
189 int ret = 0;
190
Peter Hurleyd8c1f922013-06-15 09:14:31 -0400191 mutex_lock(&tty->throttle_mutex);
Peter Hurley70bc1262013-03-06 08:20:52 -0500192 if (test_bit(TTY_THROTTLED, &tty->flags)) {
193 if (tty->flow_change != TTY_UNTHROTTLE_SAFE)
194 ret = 1;
195 else {
Peter Hurley579a00a2013-04-15 11:06:06 -0400196 clear_bit(TTY_THROTTLED, &tty->flags);
Peter Hurley70bc1262013-03-06 08:20:52 -0500197 if (tty->ops->unthrottle)
198 tty->ops->unthrottle(tty);
199 }
200 }
Peter Hurleyd8c1f922013-06-15 09:14:31 -0400201 mutex_unlock(&tty->throttle_mutex);
Peter Hurley70bc1262013-03-06 08:20:52 -0500202
203 return ret;
204}
205
206/**
Alan Coxaf9b8972006-08-27 01:24:01 -0700207 * tty_wait_until_sent - wait for I/O to finish
208 * @tty: tty we are waiting for
209 * @timeout: how long we will wait
210 *
211 * Wait for characters pending in a tty driver to hit the wire, or
212 * for a timeout to occur (eg due to flow control)
213 *
214 * Locking: none
215 */
216
Alan Cox355d95a12008-02-08 04:18:48 -0800217void tty_wait_until_sent(struct tty_struct *tty, long timeout)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700218{
Peter Hurleyff8339d2015-07-12 22:49:11 -0400219 tty_debug_wait_until_sent(tty, "\n");
220
Linus Torvalds1da177e2005-04-16 15:20:36 -0700221 if (!timeout)
222 timeout = MAX_SCHEDULE_TIMEOUT;
Johan Hovold79fbf4a2015-03-04 10:39:06 +0100223
Johan Hovoldc37bc682015-03-04 10:39:07 +0100224 timeout = wait_event_interruptible_timeout(tty->write_wait,
225 !tty_chars_in_buffer(tty), timeout);
226 if (timeout <= 0)
Johan Hovold79fbf4a2015-03-04 10:39:06 +0100227 return;
Johan Hovold79fbf4a2015-03-04 10:39:06 +0100228
229 if (timeout == MAX_SCHEDULE_TIMEOUT)
230 timeout = 0;
231
232 if (tty->ops->wait_until_sent)
233 tty->ops->wait_until_sent(tty, timeout);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700234}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700235EXPORT_SYMBOL(tty_wait_until_sent);
236
Alan Coxd81ed102008-10-13 10:41:42 +0100237
238/*
239 * Termios Helper Methods
240 */
241
Alan Coxedc6afc2006-12-08 02:38:44 -0800242static void unset_locked_termios(struct ktermios *termios,
243 struct ktermios *old,
244 struct ktermios *locked)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700245{
246 int i;
Alan Cox355d95a12008-02-08 04:18:48 -0800247
248#define NOSET_MASK(x, y, z) (x = ((x) & ~(z)) | ((y) & (z)))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700249
250 if (!locked) {
251 printk(KERN_WARNING "Warning?!? termios_locked is NULL.\n");
252 return;
253 }
254
255 NOSET_MASK(termios->c_iflag, old->c_iflag, locked->c_iflag);
256 NOSET_MASK(termios->c_oflag, old->c_oflag, locked->c_oflag);
257 NOSET_MASK(termios->c_cflag, old->c_cflag, locked->c_cflag);
258 NOSET_MASK(termios->c_lflag, old->c_lflag, locked->c_lflag);
259 termios->c_line = locked->c_line ? old->c_line : termios->c_line;
Alan Cox355d95a12008-02-08 04:18:48 -0800260 for (i = 0; i < NCCS; i++)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700261 termios->c_cc[i] = locked->c_cc[i] ?
262 old->c_cc[i] : termios->c_cc[i];
Alan Coxedc6afc2006-12-08 02:38:44 -0800263 /* FIXME: What should we do for i/ospeed */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700264}
265
Alan Coxedc6afc2006-12-08 02:38:44 -0800266/*
267 * Routine which returns the baud rate of the tty
268 *
269 * Note that the baud_table needs to be kept in sync with the
270 * include/asm/termbits.h file.
271 */
272static const speed_t baud_table[] = {
273 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
274 9600, 19200, 38400, 57600, 115200, 230400, 460800,
275#ifdef __sparc__
276 76800, 153600, 307200, 614400, 921600
277#else
278 500000, 576000, 921600, 1000000, 1152000, 1500000, 2000000,
279 2500000, 3000000, 3500000, 4000000
280#endif
281};
282
283#ifndef __sparc__
284static const tcflag_t baud_bits[] = {
285 B0, B50, B75, B110, B134, B150, B200, B300, B600,
286 B1200, B1800, B2400, B4800, B9600, B19200, B38400,
287 B57600, B115200, B230400, B460800, B500000, B576000,
288 B921600, B1000000, B1152000, B1500000, B2000000, B2500000,
289 B3000000, B3500000, B4000000
290};
291#else
292static const tcflag_t baud_bits[] = {
293 B0, B50, B75, B110, B134, B150, B200, B300, B600,
294 B1200, B1800, B2400, B4800, B9600, B19200, B38400,
295 B57600, B115200, B230400, B460800, B76800, B153600,
296 B307200, B614400, B921600
297};
298#endif
299
300static int n_baud_table = ARRAY_SIZE(baud_table);
301
302/**
303 * tty_termios_baud_rate
304 * @termios: termios structure
305 *
306 * Convert termios baud rate data into a speed. This should be called
307 * with the termios lock held if this termios is a terminal termios
308 * structure. May change the termios data. Device drivers can call this
309 * function but should use ->c_[io]speed directly as they are updated.
310 *
311 * Locking: none
312 */
313
314speed_t tty_termios_baud_rate(struct ktermios *termios)
315{
316 unsigned int cbaud;
317
318 cbaud = termios->c_cflag & CBAUD;
319
320#ifdef BOTHER
Lucas De Marchi25985ed2011-03-30 22:57:33 -0300321 /* Magic token for arbitrary speed via c_ispeed/c_ospeed */
Alan Coxedc6afc2006-12-08 02:38:44 -0800322 if (cbaud == BOTHER)
323 return termios->c_ospeed;
324#endif
325 if (cbaud & CBAUDEX) {
326 cbaud &= ~CBAUDEX;
327
328 if (cbaud < 1 || cbaud + 15 > n_baud_table)
329 termios->c_cflag &= ~CBAUDEX;
330 else
331 cbaud += 15;
332 }
333 return baud_table[cbaud];
334}
Alan Coxedc6afc2006-12-08 02:38:44 -0800335EXPORT_SYMBOL(tty_termios_baud_rate);
336
337/**
338 * tty_termios_input_baud_rate
339 * @termios: termios structure
340 *
341 * Convert termios baud rate data into a speed. This should be called
342 * with the termios lock held if this termios is a terminal termios
343 * structure. May change the termios data. Device drivers can call this
344 * function but should use ->c_[io]speed directly as they are updated.
345 *
346 * Locking: none
347 */
348
349speed_t tty_termios_input_baud_rate(struct ktermios *termios)
350{
351#ifdef IBSHIFT
352 unsigned int cbaud = (termios->c_cflag >> IBSHIFT) & CBAUD;
353
354 if (cbaud == B0)
355 return tty_termios_baud_rate(termios);
356
Lucas De Marchi25985ed2011-03-30 22:57:33 -0300357 /* Magic token for arbitrary speed via c_ispeed*/
Alan Coxedc6afc2006-12-08 02:38:44 -0800358 if (cbaud == BOTHER)
359 return termios->c_ispeed;
360
361 if (cbaud & CBAUDEX) {
362 cbaud &= ~CBAUDEX;
363
364 if (cbaud < 1 || cbaud + 15 > n_baud_table)
365 termios->c_cflag &= ~(CBAUDEX << IBSHIFT);
366 else
367 cbaud += 15;
368 }
369 return baud_table[cbaud];
370#else
371 return tty_termios_baud_rate(termios);
372#endif
373}
Alan Coxedc6afc2006-12-08 02:38:44 -0800374EXPORT_SYMBOL(tty_termios_input_baud_rate);
375
Alan Coxedc6afc2006-12-08 02:38:44 -0800376/**
377 * tty_termios_encode_baud_rate
Alan Cox78137e32007-02-10 01:45:57 -0800378 * @termios: ktermios structure holding user requested state
Alan Coxedc6afc2006-12-08 02:38:44 -0800379 * @ispeed: input speed
380 * @ospeed: output speed
381 *
382 * Encode the speeds set into the passed termios structure. This is
Uwe Kleine-Königf98e5b82011-04-12 09:59:29 +0200383 * used as a library helper for drivers so that they can report back
Alan Coxedc6afc2006-12-08 02:38:44 -0800384 * the actual speed selected when it differs from the speed requested
385 *
Alan Cox78137e32007-02-10 01:45:57 -0800386 * For maximal back compatibility with legacy SYS5/POSIX *nix behaviour
387 * we need to carefully set the bits when the user does not get the
388 * desired speed. We allow small margins and preserve as much of possible
Dirk Hohndel06fe9fb2009-09-28 21:43:57 -0400389 * of the input intent to keep compatibility.
Alan Coxedc6afc2006-12-08 02:38:44 -0800390 *
391 * Locking: Caller should hold termios lock. This is already held
392 * when calling this function from the driver termios handler.
Alan Cox5f519d72007-10-16 23:30:07 -0700393 *
394 * The ifdefs deal with platforms whose owners have yet to update them
395 * and will all go away once this is done.
Alan Coxedc6afc2006-12-08 02:38:44 -0800396 */
397
Maciej W. Rozycki75e8b712007-10-18 03:04:35 -0700398void tty_termios_encode_baud_rate(struct ktermios *termios,
399 speed_t ibaud, speed_t obaud)
Alan Coxedc6afc2006-12-08 02:38:44 -0800400{
401 int i = 0;
Alan Cox78137e32007-02-10 01:45:57 -0800402 int ifound = -1, ofound = -1;
403 int iclose = ibaud/50, oclose = obaud/50;
404 int ibinput = 0;
Alan Coxedc6afc2006-12-08 02:38:44 -0800405
Alan Cox5f519d72007-10-16 23:30:07 -0700406 if (obaud == 0) /* CD dropped */
407 ibaud = 0; /* Clear ibaud to be sure */
408
Alan Coxedc6afc2006-12-08 02:38:44 -0800409 termios->c_ispeed = ibaud;
410 termios->c_ospeed = obaud;
411
Alan Cox5f519d72007-10-16 23:30:07 -0700412#ifdef BOTHER
Alan Cox78137e32007-02-10 01:45:57 -0800413 /* If the user asked for a precise weird speed give a precise weird
Matthias Bruggera1d51aa22014-08-08 13:01:21 +0200414 answer. If they asked for a Bfoo speed they may have problems
Alan Cox78137e32007-02-10 01:45:57 -0800415 digesting non-exact replies so fuzz a bit */
416
417 if ((termios->c_cflag & CBAUD) == BOTHER)
418 oclose = 0;
419 if (((termios->c_cflag >> IBSHIFT) & CBAUD) == BOTHER)
420 iclose = 0;
421 if ((termios->c_cflag >> IBSHIFT) & CBAUD)
422 ibinput = 1; /* An input speed was specified */
Alan Cox5f519d72007-10-16 23:30:07 -0700423#endif
Alan Coxedc6afc2006-12-08 02:38:44 -0800424 termios->c_cflag &= ~CBAUD;
Alan Coxedc6afc2006-12-08 02:38:44 -0800425
Alan Cox5f519d72007-10-16 23:30:07 -0700426 /*
427 * Our goal is to find a close match to the standard baud rate
428 * returned. Walk the baud rate table and if we get a very close
429 * match then report back the speed as a POSIX Bxxxx value by
430 * preference
431 */
432
Alan Coxedc6afc2006-12-08 02:38:44 -0800433 do {
Maciej W. Rozycki75e8b712007-10-18 03:04:35 -0700434 if (obaud - oclose <= baud_table[i] &&
435 obaud + oclose >= baud_table[i]) {
Alan Coxedc6afc2006-12-08 02:38:44 -0800436 termios->c_cflag |= baud_bits[i];
Alan Cox78137e32007-02-10 01:45:57 -0800437 ofound = i;
Alan Coxedc6afc2006-12-08 02:38:44 -0800438 }
Maciej W. Rozycki75e8b712007-10-18 03:04:35 -0700439 if (ibaud - iclose <= baud_table[i] &&
440 ibaud + iclose >= baud_table[i]) {
441 /* For the case input == output don't set IBAUD bits
442 if the user didn't do so */
Alan Cox5f519d72007-10-16 23:30:07 -0700443 if (ofound == i && !ibinput)
444 ifound = i;
445#ifdef IBSHIFT
446 else {
447 ifound = i;
Alan Cox78137e32007-02-10 01:45:57 -0800448 termios->c_cflag |= (baud_bits[i] << IBSHIFT);
Alan Cox5f519d72007-10-16 23:30:07 -0700449 }
450#endif
Alan Coxedc6afc2006-12-08 02:38:44 -0800451 }
Jiri Slaby68043962007-07-15 23:40:18 -0700452 } while (++i < n_baud_table);
Alan Cox5f519d72007-10-16 23:30:07 -0700453
454 /*
455 * If we found no match then use BOTHER if provided or warn
456 * the user their platform maintainer needs to wake up if not.
457 */
458#ifdef BOTHER
Alan Cox78137e32007-02-10 01:45:57 -0800459 if (ofound == -1)
Alan Coxedc6afc2006-12-08 02:38:44 -0800460 termios->c_cflag |= BOTHER;
Alan Cox78137e32007-02-10 01:45:57 -0800461 /* Set exact input bits only if the input and output differ or the
462 user already did */
Jiri Slaby68043962007-07-15 23:40:18 -0700463 if (ifound == -1 && (ibaud != obaud || ibinput))
Alan Coxedc6afc2006-12-08 02:38:44 -0800464 termios->c_cflag |= (BOTHER << IBSHIFT);
Alan Cox5f519d72007-10-16 23:30:07 -0700465#else
466 if (ifound == -1 || ofound == -1) {
Marcin Slusarz9074d962009-08-09 21:54:03 +0200467 printk_once(KERN_WARNING "tty: Unable to return correct "
Alan Cox5f519d72007-10-16 23:30:07 -0700468 "speed data as your architecture needs updating.\n");
469 }
470#endif
Alan Coxedc6afc2006-12-08 02:38:44 -0800471}
Alan Coxedc6afc2006-12-08 02:38:44 -0800472EXPORT_SYMBOL_GPL(tty_termios_encode_baud_rate);
473
Alan Coxd81ed102008-10-13 10:41:42 +0100474/**
475 * tty_encode_baud_rate - set baud rate of the tty
476 * @ibaud: input baud rate
477 * @obad: output baud rate
478 *
479 * Update the current termios data for the tty with the new speed
Peter Hurley6a1c0682013-06-15 09:14:23 -0400480 * settings. The caller must hold the termios_rwsem for the tty in
Alan Coxd81ed102008-10-13 10:41:42 +0100481 * question.
482 */
483
Alan Cox5f519d72007-10-16 23:30:07 -0700484void tty_encode_baud_rate(struct tty_struct *tty, speed_t ibaud, speed_t obaud)
485{
Alan Coxadc8d742012-07-14 15:31:47 +0100486 tty_termios_encode_baud_rate(&tty->termios, ibaud, obaud);
Alan Cox5f519d72007-10-16 23:30:07 -0700487}
488EXPORT_SYMBOL_GPL(tty_encode_baud_rate);
Alan Coxedc6afc2006-12-08 02:38:44 -0800489
490/**
Alan Cox5f519d72007-10-16 23:30:07 -0700491 * tty_termios_copy_hw - copy hardware settings
492 * @new: New termios
493 * @old: Old termios
494 *
Lucas De Marchi25985ed2011-03-30 22:57:33 -0300495 * Propagate the hardware specific terminal setting bits from
Alan Cox5f519d72007-10-16 23:30:07 -0700496 * the old termios structure to the new one. This is used in cases
497 * where the hardware does not support reconfiguration or as a helper
498 * in some cases where only minimal reconfiguration is supported
499 */
500
501void tty_termios_copy_hw(struct ktermios *new, struct ktermios *old)
502{
503 /* The bits a dumb device handles in software. Smart devices need
504 to always provide a set_termios method */
505 new->c_cflag &= HUPCL | CREAD | CLOCAL;
506 new->c_cflag |= old->c_cflag & ~(HUPCL | CREAD | CLOCAL);
507 new->c_ispeed = old->c_ispeed;
508 new->c_ospeed = old->c_ospeed;
509}
Alan Cox5f519d72007-10-16 23:30:07 -0700510EXPORT_SYMBOL(tty_termios_copy_hw);
511
512/**
Alan Coxbf5e5832008-01-08 14:55:51 +0000513 * tty_termios_hw_change - check for setting change
514 * @a: termios
515 * @b: termios to compare
516 *
517 * Check if any of the bits that affect a dumb device have changed
518 * between the two termios structures, or a speed change is needed.
519 */
520
521int tty_termios_hw_change(struct ktermios *a, struct ktermios *b)
522{
523 if (a->c_ispeed != b->c_ispeed || a->c_ospeed != b->c_ospeed)
524 return 1;
525 if ((a->c_cflag ^ b->c_cflag) & ~(HUPCL | CREAD | CLOCAL))
526 return 1;
527 return 0;
528}
529EXPORT_SYMBOL(tty_termios_hw_change);
530
531/**
Alan Cox8d075b12011-02-14 16:27:53 +0000532 * tty_set_termios - update termios values
Alan Coxaf9b8972006-08-27 01:24:01 -0700533 * @tty: tty to update
534 * @new_termios: desired new value
535 *
Peter Hurleydbfcd852014-10-16 15:33:23 -0400536 * Perform updates to the termios values set on this terminal.
Peter Hurley6460fbb2014-10-16 15:33:22 -0400537 * A master pty's termios should never be set.
538 *
Peter Hurley6a1c0682013-06-15 09:14:23 -0400539 * Locking: termios_rwsem
Alan Coxaf9b8972006-08-27 01:24:01 -0700540 */
541
Frederic Danisb00f5c22015-04-10 15:13:05 +0200542int tty_set_termios(struct tty_struct *tty, struct ktermios *new_termios)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700543{
Alan Cox978e5952008-04-30 00:53:59 -0700544 struct ktermios old_termios;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700545 struct tty_ldisc *ld;
Alan Cox355d95a12008-02-08 04:18:48 -0800546
Peter Hurley6460fbb2014-10-16 15:33:22 -0400547 WARN_ON(tty->driver->type == TTY_DRIVER_TYPE_PTY &&
548 tty->driver->subtype == PTY_TYPE_MASTER);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700549 /*
550 * Perform the actual termios internal changes under lock.
551 */
Alan Cox355d95a12008-02-08 04:18:48 -0800552
Linus Torvalds1da177e2005-04-16 15:20:36 -0700553
554 /* FIXME: we need to decide on some locking/ordering semantics
555 for the set_termios notification eventually */
Peter Hurley6a1c0682013-06-15 09:14:23 -0400556 down_write(&tty->termios_rwsem);
Alan Coxadc8d742012-07-14 15:31:47 +0100557 old_termios = tty->termios;
558 tty->termios = *new_termios;
559 unset_locked_termios(&tty->termios, &old_termios, &tty->termios_locked);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700560
Alan Coxf34d7a52008-04-30 00:54:13 -0700561 if (tty->ops->set_termios)
Peter Hurleyc961bfb2014-11-05 12:26:25 -0500562 tty->ops->set_termios(tty, &old_termios);
Alan Cox5f519d72007-10-16 23:30:07 -0700563 else
Alan Coxadc8d742012-07-14 15:31:47 +0100564 tty_termios_copy_hw(&tty->termios, &old_termios);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700565
566 ld = tty_ldisc_ref(tty);
567 if (ld != NULL) {
Alan Coxa352def2008-07-16 21:53:12 +0100568 if (ld->ops->set_termios)
Peter Hurleyc961bfb2014-11-05 12:26:25 -0500569 ld->ops->set_termios(tty, &old_termios);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700570 tty_ldisc_deref(ld);
571 }
Peter Hurley6a1c0682013-06-15 09:14:23 -0400572 up_write(&tty->termios_rwsem);
Alan Cox8d075b12011-02-14 16:27:53 +0000573 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700574}
Frederic Danisb00f5c22015-04-10 15:13:05 +0200575EXPORT_SYMBOL_GPL(tty_set_termios);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700576
Alan Coxaf9b8972006-08-27 01:24:01 -0700577/**
578 * set_termios - set termios values for a tty
579 * @tty: terminal device
580 * @arg: user data
581 * @opt: option information
582 *
Robert P. J. Day3a4fa0a2007-10-19 23:10:43 +0200583 * Helper function to prepare termios data and run necessary other
Alan Cox8d075b12011-02-14 16:27:53 +0000584 * functions before using tty_set_termios to do the actual changes.
Alan Coxaf9b8972006-08-27 01:24:01 -0700585 *
586 * Locking:
Peter Hurley6a1c0682013-06-15 09:14:23 -0400587 * Called functions take ldisc and termios_rwsem locks
Alan Coxaf9b8972006-08-27 01:24:01 -0700588 */
589
Alan Cox355d95a12008-02-08 04:18:48 -0800590static int set_termios(struct tty_struct *tty, void __user *arg, int opt)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700591{
Alan Coxedc6afc2006-12-08 02:38:44 -0800592 struct ktermios tmp_termios;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700593 struct tty_ldisc *ld;
594 int retval = tty_check_change(tty);
595
596 if (retval)
597 return retval;
598
Peter Hurley6a1c0682013-06-15 09:14:23 -0400599 down_read(&tty->termios_rwsem);
Alan Coxadc8d742012-07-14 15:31:47 +0100600 tmp_termios = tty->termios;
Peter Hurley6a1c0682013-06-15 09:14:23 -0400601 up_read(&tty->termios_rwsem);
Alan Cox64bb6c52006-12-08 02:38:47 -0800602
Linus Torvalds1da177e2005-04-16 15:20:36 -0700603 if (opt & TERMIOS_TERMIO) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700604 if (user_termio_to_kernel_termios(&tmp_termios,
605 (struct termio __user *)arg))
606 return -EFAULT;
Alan Coxedc6afc2006-12-08 02:38:44 -0800607#ifdef TCGETS2
608 } else if (opt & TERMIOS_OLD) {
Alan Coxedc6afc2006-12-08 02:38:44 -0800609 if (user_termios_to_kernel_termios_1(&tmp_termios,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700610 (struct termios __user *)arg))
611 return -EFAULT;
Alan Cox64bb6c52006-12-08 02:38:47 -0800612 } else {
613 if (user_termios_to_kernel_termios(&tmp_termios,
614 (struct termios2 __user *)arg))
615 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700616 }
Alan Cox64bb6c52006-12-08 02:38:47 -0800617#else
618 } else if (user_termios_to_kernel_termios(&tmp_termios,
619 (struct termios __user *)arg))
620 return -EFAULT;
621#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700622
Alan Cox355d95a12008-02-08 04:18:48 -0800623 /* If old style Bfoo values are used then load c_ispeed/c_ospeed
624 * with the real speed so its unconditionally usable */
Alan Coxedc6afc2006-12-08 02:38:44 -0800625 tmp_termios.c_ispeed = tty_termios_input_baud_rate(&tmp_termios);
626 tmp_termios.c_ospeed = tty_termios_baud_rate(&tmp_termios);
627
Linus Torvalds1da177e2005-04-16 15:20:36 -0700628 ld = tty_ldisc_ref(tty);
Alan Cox355d95a12008-02-08 04:18:48 -0800629
Linus Torvalds1da177e2005-04-16 15:20:36 -0700630 if (ld != NULL) {
Alan Coxa352def2008-07-16 21:53:12 +0100631 if ((opt & TERMIOS_FLUSH) && ld->ops->flush_buffer)
632 ld->ops->flush_buffer(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700633 tty_ldisc_deref(ld);
634 }
Alan Cox355d95a12008-02-08 04:18:48 -0800635
Linus Torvalds1da177e2005-04-16 15:20:36 -0700636 if (opt & TERMIOS_WAIT) {
637 tty_wait_until_sent(tty, 0);
638 if (signal_pending(current))
Oleg Nesterov183d95c2013-01-29 20:07:41 +0100639 return -ERESTARTSYS;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700640 }
641
Alan Cox8d075b12011-02-14 16:27:53 +0000642 tty_set_termios(tty, &tmp_termios);
Alan Cox5f519d72007-10-16 23:30:07 -0700643
644 /* FIXME: Arguably if tmp_termios == tty->termios AND the
645 actual requested termios was not tmp_termios then we may
646 want to return an error as no user requested change has
647 succeeded */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700648 return 0;
649}
650
Alan Cox26a2e202009-06-11 14:03:13 +0100651static void copy_termios(struct tty_struct *tty, struct ktermios *kterm)
652{
Peter Hurley6a1c0682013-06-15 09:14:23 -0400653 down_read(&tty->termios_rwsem);
Alan Coxadc8d742012-07-14 15:31:47 +0100654 *kterm = tty->termios;
Peter Hurley6a1c0682013-06-15 09:14:23 -0400655 up_read(&tty->termios_rwsem);
Alan Cox26a2e202009-06-11 14:03:13 +0100656}
657
658static void copy_termios_locked(struct tty_struct *tty, struct ktermios *kterm)
659{
Peter Hurley6a1c0682013-06-15 09:14:23 -0400660 down_read(&tty->termios_rwsem);
Alan Coxadc8d742012-07-14 15:31:47 +0100661 *kterm = tty->termios_locked;
Peter Hurley6a1c0682013-06-15 09:14:23 -0400662 up_read(&tty->termios_rwsem);
Alan Cox26a2e202009-06-11 14:03:13 +0100663}
664
Alan Cox355d95a12008-02-08 04:18:48 -0800665static int get_termio(struct tty_struct *tty, struct termio __user *termio)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700666{
Alan Cox26a2e202009-06-11 14:03:13 +0100667 struct ktermios kterm;
668 copy_termios(tty, &kterm);
669 if (kernel_termios_to_user_termio(termio, &kterm))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700670 return -EFAULT;
671 return 0;
672}
673
Alan Cox1d65b4a2008-10-13 10:38:18 +0100674
675#ifdef TCGETX
676
677/**
678 * set_termiox - set termiox fields if possible
679 * @tty: terminal
680 * @arg: termiox structure from user
681 * @opt: option flags for ioctl type
682 *
683 * Implement the device calling points for the SYS5 termiox ioctl
684 * interface in Linux
685 */
686
687static int set_termiox(struct tty_struct *tty, void __user *arg, int opt)
688{
689 struct termiox tnew;
690 struct tty_ldisc *ld;
691
692 if (tty->termiox == NULL)
693 return -EINVAL;
694 if (copy_from_user(&tnew, arg, sizeof(struct termiox)))
695 return -EFAULT;
696
697 ld = tty_ldisc_ref(tty);
698 if (ld != NULL) {
699 if ((opt & TERMIOS_FLUSH) && ld->ops->flush_buffer)
700 ld->ops->flush_buffer(tty);
701 tty_ldisc_deref(ld);
702 }
703 if (opt & TERMIOS_WAIT) {
704 tty_wait_until_sent(tty, 0);
705 if (signal_pending(current))
Oleg Nesterov183d95c2013-01-29 20:07:41 +0100706 return -ERESTARTSYS;
Alan Cox1d65b4a2008-10-13 10:38:18 +0100707 }
708
Peter Hurley6a1c0682013-06-15 09:14:23 -0400709 down_write(&tty->termios_rwsem);
Alan Cox1d65b4a2008-10-13 10:38:18 +0100710 if (tty->ops->set_termiox)
711 tty->ops->set_termiox(tty, &tnew);
Peter Hurley6a1c0682013-06-15 09:14:23 -0400712 up_write(&tty->termios_rwsem);
Alan Cox1d65b4a2008-10-13 10:38:18 +0100713 return 0;
714}
715
716#endif
717
Linus Torvalds1da177e2005-04-16 15:20:36 -0700718
719#ifdef TIOCGETP
720/*
721 * These are deprecated, but there is limited support..
722 *
723 * The "sg_flags" translation is a joke..
724 */
Alan Cox355d95a12008-02-08 04:18:48 -0800725static int get_sgflags(struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700726{
727 int flags = 0;
728
Alan Coxadc8d742012-07-14 15:31:47 +0100729 if (!(tty->termios.c_lflag & ICANON)) {
730 if (tty->termios.c_lflag & ISIG)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700731 flags |= 0x02; /* cbreak */
732 else
733 flags |= 0x20; /* raw */
734 }
Alan Coxadc8d742012-07-14 15:31:47 +0100735 if (tty->termios.c_lflag & ECHO)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700736 flags |= 0x08; /* echo */
Alan Coxadc8d742012-07-14 15:31:47 +0100737 if (tty->termios.c_oflag & OPOST)
738 if (tty->termios.c_oflag & ONLCR)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700739 flags |= 0x10; /* crmod */
740 return flags;
741}
742
Alan Cox355d95a12008-02-08 04:18:48 -0800743static int get_sgttyb(struct tty_struct *tty, struct sgttyb __user *sgttyb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700744{
745 struct sgttyb tmp;
746
Peter Hurley6a1c0682013-06-15 09:14:23 -0400747 down_read(&tty->termios_rwsem);
Alan Coxadc8d742012-07-14 15:31:47 +0100748 tmp.sg_ispeed = tty->termios.c_ispeed;
749 tmp.sg_ospeed = tty->termios.c_ospeed;
750 tmp.sg_erase = tty->termios.c_cc[VERASE];
751 tmp.sg_kill = tty->termios.c_cc[VKILL];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700752 tmp.sg_flags = get_sgflags(tty);
Peter Hurley6a1c0682013-06-15 09:14:23 -0400753 up_read(&tty->termios_rwsem);
Alan Cox355d95a12008-02-08 04:18:48 -0800754
Linus Torvalds1da177e2005-04-16 15:20:36 -0700755 return copy_to_user(sgttyb, &tmp, sizeof(tmp)) ? -EFAULT : 0;
756}
757
Alan Cox355d95a12008-02-08 04:18:48 -0800758static void set_sgflags(struct ktermios *termios, int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700759{
Alan Cox9833fac2012-07-17 17:05:40 +0100760 termios->c_iflag = ICRNL | IXON;
761 termios->c_oflag = 0;
762 termios->c_lflag = ISIG | ICANON;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700763 if (flags & 0x02) { /* cbreak */
Alan Cox9833fac2012-07-17 17:05:40 +0100764 termios->c_iflag = 0;
765 termios->c_lflag &= ~ICANON;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700766 }
767 if (flags & 0x08) { /* echo */
Alan Cox9833fac2012-07-17 17:05:40 +0100768 termios->c_lflag |= ECHO | ECHOE | ECHOK |
Linus Torvalds1da177e2005-04-16 15:20:36 -0700769 ECHOCTL | ECHOKE | IEXTEN;
770 }
771 if (flags & 0x10) { /* crmod */
Alan Cox9833fac2012-07-17 17:05:40 +0100772 termios->c_oflag |= OPOST | ONLCR;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700773 }
774 if (flags & 0x20) { /* raw */
Alan Cox9833fac2012-07-17 17:05:40 +0100775 termios->c_iflag = 0;
776 termios->c_lflag &= ~(ISIG | ICANON);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700777 }
Alan Cox9833fac2012-07-17 17:05:40 +0100778 if (!(termios->c_lflag & ICANON)) {
779 termios->c_cc[VMIN] = 1;
780 termios->c_cc[VTIME] = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700781 }
782}
783
Alan Coxaf9b8972006-08-27 01:24:01 -0700784/**
785 * set_sgttyb - set legacy terminal values
786 * @tty: tty structure
787 * @sgttyb: pointer to old style terminal structure
788 *
789 * Updates a terminal from the legacy BSD style terminal information
790 * structure.
791 *
Peter Hurley6a1c0682013-06-15 09:14:23 -0400792 * Locking: termios_rwsem
Alan Coxaf9b8972006-08-27 01:24:01 -0700793 */
794
Alan Cox355d95a12008-02-08 04:18:48 -0800795static int set_sgttyb(struct tty_struct *tty, struct sgttyb __user *sgttyb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700796{
797 int retval;
798 struct sgttyb tmp;
Alan Coxedc6afc2006-12-08 02:38:44 -0800799 struct ktermios termios;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700800
801 retval = tty_check_change(tty);
802 if (retval)
803 return retval;
Alan Cox355d95a12008-02-08 04:18:48 -0800804
Linus Torvalds1da177e2005-04-16 15:20:36 -0700805 if (copy_from_user(&tmp, sgttyb, sizeof(tmp)))
806 return -EFAULT;
807
Peter Hurley6a1c0682013-06-15 09:14:23 -0400808 down_write(&tty->termios_rwsem);
Alan Coxadc8d742012-07-14 15:31:47 +0100809 termios = tty->termios;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700810 termios.c_cc[VERASE] = tmp.sg_erase;
811 termios.c_cc[VKILL] = tmp.sg_kill;
812 set_sgflags(&termios, tmp.sg_flags);
Alan Coxedc6afc2006-12-08 02:38:44 -0800813 /* Try and encode into Bfoo format */
814#ifdef BOTHER
Alan Cox355d95a12008-02-08 04:18:48 -0800815 tty_termios_encode_baud_rate(&termios, termios.c_ispeed,
816 termios.c_ospeed);
Alan Coxedc6afc2006-12-08 02:38:44 -0800817#endif
Peter Hurley6a1c0682013-06-15 09:14:23 -0400818 up_write(&tty->termios_rwsem);
Alan Cox8d075b12011-02-14 16:27:53 +0000819 tty_set_termios(tty, &termios);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700820 return 0;
821}
822#endif
823
824#ifdef TIOCGETC
Alan Cox355d95a12008-02-08 04:18:48 -0800825static int get_tchars(struct tty_struct *tty, struct tchars __user *tchars)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700826{
827 struct tchars tmp;
828
Peter Hurley6a1c0682013-06-15 09:14:23 -0400829 down_read(&tty->termios_rwsem);
Alan Coxadc8d742012-07-14 15:31:47 +0100830 tmp.t_intrc = tty->termios.c_cc[VINTR];
831 tmp.t_quitc = tty->termios.c_cc[VQUIT];
832 tmp.t_startc = tty->termios.c_cc[VSTART];
833 tmp.t_stopc = tty->termios.c_cc[VSTOP];
834 tmp.t_eofc = tty->termios.c_cc[VEOF];
835 tmp.t_brkc = tty->termios.c_cc[VEOL2]; /* what is brkc anyway? */
Peter Hurley6a1c0682013-06-15 09:14:23 -0400836 up_read(&tty->termios_rwsem);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700837 return copy_to_user(tchars, &tmp, sizeof(tmp)) ? -EFAULT : 0;
838}
839
Alan Cox355d95a12008-02-08 04:18:48 -0800840static int set_tchars(struct tty_struct *tty, struct tchars __user *tchars)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700841{
842 struct tchars tmp;
843
844 if (copy_from_user(&tmp, tchars, sizeof(tmp)))
845 return -EFAULT;
Peter Hurley6a1c0682013-06-15 09:14:23 -0400846 down_write(&tty->termios_rwsem);
Alan Coxadc8d742012-07-14 15:31:47 +0100847 tty->termios.c_cc[VINTR] = tmp.t_intrc;
848 tty->termios.c_cc[VQUIT] = tmp.t_quitc;
849 tty->termios.c_cc[VSTART] = tmp.t_startc;
850 tty->termios.c_cc[VSTOP] = tmp.t_stopc;
851 tty->termios.c_cc[VEOF] = tmp.t_eofc;
852 tty->termios.c_cc[VEOL2] = tmp.t_brkc; /* what is brkc anyway? */
Peter Hurley6a1c0682013-06-15 09:14:23 -0400853 up_write(&tty->termios_rwsem);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700854 return 0;
855}
856#endif
857
858#ifdef TIOCGLTC
Alan Cox355d95a12008-02-08 04:18:48 -0800859static int get_ltchars(struct tty_struct *tty, struct ltchars __user *ltchars)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700860{
861 struct ltchars tmp;
862
Peter Hurley6a1c0682013-06-15 09:14:23 -0400863 down_read(&tty->termios_rwsem);
Alan Coxadc8d742012-07-14 15:31:47 +0100864 tmp.t_suspc = tty->termios.c_cc[VSUSP];
Alan Cox355d95a12008-02-08 04:18:48 -0800865 /* what is dsuspc anyway? */
Alan Coxadc8d742012-07-14 15:31:47 +0100866 tmp.t_dsuspc = tty->termios.c_cc[VSUSP];
867 tmp.t_rprntc = tty->termios.c_cc[VREPRINT];
Alan Cox355d95a12008-02-08 04:18:48 -0800868 /* what is flushc anyway? */
Alan Coxadc8d742012-07-14 15:31:47 +0100869 tmp.t_flushc = tty->termios.c_cc[VEOL2];
870 tmp.t_werasc = tty->termios.c_cc[VWERASE];
871 tmp.t_lnextc = tty->termios.c_cc[VLNEXT];
Peter Hurley6a1c0682013-06-15 09:14:23 -0400872 up_read(&tty->termios_rwsem);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700873 return copy_to_user(ltchars, &tmp, sizeof(tmp)) ? -EFAULT : 0;
874}
875
Alan Cox355d95a12008-02-08 04:18:48 -0800876static int set_ltchars(struct tty_struct *tty, struct ltchars __user *ltchars)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700877{
878 struct ltchars tmp;
879
880 if (copy_from_user(&tmp, ltchars, sizeof(tmp)))
881 return -EFAULT;
882
Peter Hurley6a1c0682013-06-15 09:14:23 -0400883 down_write(&tty->termios_rwsem);
Alan Coxadc8d742012-07-14 15:31:47 +0100884 tty->termios.c_cc[VSUSP] = tmp.t_suspc;
Alan Cox355d95a12008-02-08 04:18:48 -0800885 /* what is dsuspc anyway? */
Alan Coxadc8d742012-07-14 15:31:47 +0100886 tty->termios.c_cc[VEOL2] = tmp.t_dsuspc;
887 tty->termios.c_cc[VREPRINT] = tmp.t_rprntc;
Alan Cox355d95a12008-02-08 04:18:48 -0800888 /* what is flushc anyway? */
Alan Coxadc8d742012-07-14 15:31:47 +0100889 tty->termios.c_cc[VEOL2] = tmp.t_flushc;
890 tty->termios.c_cc[VWERASE] = tmp.t_werasc;
891 tty->termios.c_cc[VLNEXT] = tmp.t_lnextc;
Peter Hurley6a1c0682013-06-15 09:14:23 -0400892 up_write(&tty->termios_rwsem);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700893 return 0;
894}
895#endif
896
Alan Coxaf9b8972006-08-27 01:24:01 -0700897/**
Alan Cox1c2630c2008-04-30 00:53:34 -0700898 * tty_change_softcar - carrier change ioctl helper
899 * @tty: tty to update
900 * @arg: enable/disable CLOCAL
901 *
902 * Perform a change to the CLOCAL state and call into the driver
Peter Hurley6a1c0682013-06-15 09:14:23 -0400903 * layer to make it visible. All done with the termios rwsem
Alan Cox1c2630c2008-04-30 00:53:34 -0700904 */
905
906static int tty_change_softcar(struct tty_struct *tty, int arg)
907{
908 int ret = 0;
909 int bit = arg ? CLOCAL : 0;
Alan Coxf34d7a52008-04-30 00:54:13 -0700910 struct ktermios old;
Alan Cox1c2630c2008-04-30 00:53:34 -0700911
Peter Hurley6a1c0682013-06-15 09:14:23 -0400912 down_write(&tty->termios_rwsem);
Alan Coxadc8d742012-07-14 15:31:47 +0100913 old = tty->termios;
914 tty->termios.c_cflag &= ~CLOCAL;
915 tty->termios.c_cflag |= bit;
Alan Coxf34d7a52008-04-30 00:54:13 -0700916 if (tty->ops->set_termios)
917 tty->ops->set_termios(tty, &old);
Alan Coxadc8d742012-07-14 15:31:47 +0100918 if ((tty->termios.c_cflag & CLOCAL) != bit)
Alan Cox1c2630c2008-04-30 00:53:34 -0700919 ret = -EINVAL;
Peter Hurley6a1c0682013-06-15 09:14:23 -0400920 up_write(&tty->termios_rwsem);
Alan Cox1c2630c2008-04-30 00:53:34 -0700921 return ret;
922}
923
924/**
Alan Cox0fc00e22007-11-07 01:24:56 -0800925 * tty_mode_ioctl - mode related ioctls
926 * @tty: tty for the ioctl
927 * @file: file pointer for the tty
928 * @cmd: command
929 * @arg: ioctl argument
930 *
931 * Perform non line discipline specific mode control ioctls. This
932 * is designed to be called by line disciplines to ensure they provide
933 * consistent mode setting.
934 */
935
Alan Cox355d95a12008-02-08 04:18:48 -0800936int tty_mode_ioctl(struct tty_struct *tty, struct file *file,
Alan Cox0fc00e22007-11-07 01:24:56 -0800937 unsigned int cmd, unsigned long arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700938{
Alan Cox355d95a12008-02-08 04:18:48 -0800939 struct tty_struct *real_tty;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700940 void __user *p = (void __user *)arg;
Alan Cox8f520022008-10-13 10:38:46 +0100941 int ret = 0;
Alan Cox26a2e202009-06-11 14:03:13 +0100942 struct ktermios kterm;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700943
Alan Cox8d075b12011-02-14 16:27:53 +0000944 BUG_ON(file == NULL);
945
Linus Torvalds1da177e2005-04-16 15:20:36 -0700946 if (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
947 tty->driver->subtype == PTY_TYPE_MASTER)
948 real_tty = tty->link;
949 else
950 real_tty = tty;
951
952 switch (cmd) {
953#ifdef TIOCGETP
Alan Cox355d95a12008-02-08 04:18:48 -0800954 case TIOCGETP:
955 return get_sgttyb(real_tty, (struct sgttyb __user *) arg);
956 case TIOCSETP:
957 case TIOCSETN:
958 return set_sgttyb(real_tty, (struct sgttyb __user *) arg);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700959#endif
960#ifdef TIOCGETC
Alan Cox355d95a12008-02-08 04:18:48 -0800961 case TIOCGETC:
962 return get_tchars(real_tty, p);
963 case TIOCSETC:
964 return set_tchars(real_tty, p);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700965#endif
966#ifdef TIOCGLTC
Alan Cox355d95a12008-02-08 04:18:48 -0800967 case TIOCGLTC:
968 return get_ltchars(real_tty, p);
969 case TIOCSLTC:
970 return set_ltchars(real_tty, p);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700971#endif
Alan Cox355d95a12008-02-08 04:18:48 -0800972 case TCSETSF:
973 return set_termios(real_tty, p, TERMIOS_FLUSH | TERMIOS_WAIT | TERMIOS_OLD);
974 case TCSETSW:
975 return set_termios(real_tty, p, TERMIOS_WAIT | TERMIOS_OLD);
976 case TCSETS:
977 return set_termios(real_tty, p, TERMIOS_OLD);
Alan Coxedc6afc2006-12-08 02:38:44 -0800978#ifndef TCGETS2
Alan Cox355d95a12008-02-08 04:18:48 -0800979 case TCGETS:
Alan Cox26a2e202009-06-11 14:03:13 +0100980 copy_termios(real_tty, &kterm);
981 if (kernel_termios_to_user_termios((struct termios __user *)arg, &kterm))
Alan Cox8f520022008-10-13 10:38:46 +0100982 ret = -EFAULT;
Alan Cox8f520022008-10-13 10:38:46 +0100983 return ret;
Alan Coxedc6afc2006-12-08 02:38:44 -0800984#else
Alan Cox355d95a12008-02-08 04:18:48 -0800985 case TCGETS:
Alan Cox26a2e202009-06-11 14:03:13 +0100986 copy_termios(real_tty, &kterm);
987 if (kernel_termios_to_user_termios_1((struct termios __user *)arg, &kterm))
Alan Cox8f520022008-10-13 10:38:46 +0100988 ret = -EFAULT;
Alan Cox8f520022008-10-13 10:38:46 +0100989 return ret;
Alan Cox355d95a12008-02-08 04:18:48 -0800990 case TCGETS2:
Alan Cox26a2e202009-06-11 14:03:13 +0100991 copy_termios(real_tty, &kterm);
992 if (kernel_termios_to_user_termios((struct termios2 __user *)arg, &kterm))
Alan Cox8f520022008-10-13 10:38:46 +0100993 ret = -EFAULT;
Alan Cox8f520022008-10-13 10:38:46 +0100994 return ret;
Alan Cox355d95a12008-02-08 04:18:48 -0800995 case TCSETSF2:
996 return set_termios(real_tty, p, TERMIOS_FLUSH | TERMIOS_WAIT);
997 case TCSETSW2:
998 return set_termios(real_tty, p, TERMIOS_WAIT);
999 case TCSETS2:
1000 return set_termios(real_tty, p, 0);
Alan Coxedc6afc2006-12-08 02:38:44 -08001001#endif
Alan Cox355d95a12008-02-08 04:18:48 -08001002 case TCGETA:
1003 return get_termio(real_tty, p);
1004 case TCSETAF:
1005 return set_termios(real_tty, p, TERMIOS_FLUSH | TERMIOS_WAIT | TERMIOS_TERMIO);
1006 case TCSETAW:
1007 return set_termios(real_tty, p, TERMIOS_WAIT | TERMIOS_TERMIO);
1008 case TCSETA:
1009 return set_termios(real_tty, p, TERMIOS_TERMIO);
Alan Cox0fc00e22007-11-07 01:24:56 -08001010#ifndef TCGETS2
Alan Cox355d95a12008-02-08 04:18:48 -08001011 case TIOCGLCKTRMIOS:
Alan Cox26a2e202009-06-11 14:03:13 +01001012 copy_termios_locked(real_tty, &kterm);
1013 if (kernel_termios_to_user_termios((struct termios __user *)arg, &kterm))
Alan Cox8f520022008-10-13 10:38:46 +01001014 ret = -EFAULT;
Alan Cox8f520022008-10-13 10:38:46 +01001015 return ret;
Alan Cox355d95a12008-02-08 04:18:48 -08001016 case TIOCSLCKTRMIOS:
1017 if (!capable(CAP_SYS_ADMIN))
1018 return -EPERM;
Alan Cox26a2e202009-06-11 14:03:13 +01001019 copy_termios_locked(real_tty, &kterm);
1020 if (user_termios_to_kernel_termios(&kterm,
Alan Cox355d95a12008-02-08 04:18:48 -08001021 (struct termios __user *) arg))
Alan Cox26a2e202009-06-11 14:03:13 +01001022 return -EFAULT;
Peter Hurley6a1c0682013-06-15 09:14:23 -04001023 down_write(&real_tty->termios_rwsem);
Alan Coxadc8d742012-07-14 15:31:47 +01001024 real_tty->termios_locked = kterm;
Peter Hurley6a1c0682013-06-15 09:14:23 -04001025 up_write(&real_tty->termios_rwsem);
Alan Cox26a2e202009-06-11 14:03:13 +01001026 return 0;
Alan Cox0fc00e22007-11-07 01:24:56 -08001027#else
Alan Cox355d95a12008-02-08 04:18:48 -08001028 case TIOCGLCKTRMIOS:
Alan Cox26a2e202009-06-11 14:03:13 +01001029 copy_termios_locked(real_tty, &kterm);
1030 if (kernel_termios_to_user_termios_1((struct termios __user *)arg, &kterm))
Alan Cox8f520022008-10-13 10:38:46 +01001031 ret = -EFAULT;
Alan Cox8f520022008-10-13 10:38:46 +01001032 return ret;
Alan Cox355d95a12008-02-08 04:18:48 -08001033 case TIOCSLCKTRMIOS:
1034 if (!capable(CAP_SYS_ADMIN))
Alan Cox26a2e202009-06-11 14:03:13 +01001035 return -EPERM;
1036 copy_termios_locked(real_tty, &kterm);
1037 if (user_termios_to_kernel_termios_1(&kterm,
Alan Cox355d95a12008-02-08 04:18:48 -08001038 (struct termios __user *) arg))
Alan Cox26a2e202009-06-11 14:03:13 +01001039 return -EFAULT;
Peter Hurley6a1c0682013-06-15 09:14:23 -04001040 down_write(&real_tty->termios_rwsem);
Alan Coxadc8d742012-07-14 15:31:47 +01001041 real_tty->termios_locked = kterm;
Peter Hurley6a1c0682013-06-15 09:14:23 -04001042 up_write(&real_tty->termios_rwsem);
Alan Cox8f520022008-10-13 10:38:46 +01001043 return ret;
Alan Cox0fc00e22007-11-07 01:24:56 -08001044#endif
Alan Cox1d65b4a2008-10-13 10:38:18 +01001045#ifdef TCGETX
Mike Frysinger5dca6072009-06-16 17:01:02 +01001046 case TCGETX: {
1047 struct termiox ktermx;
Alan Cox1d65b4a2008-10-13 10:38:18 +01001048 if (real_tty->termiox == NULL)
1049 return -EINVAL;
Peter Hurley6a1c0682013-06-15 09:14:23 -04001050 down_read(&real_tty->termios_rwsem);
Alan Cox26a2e202009-06-11 14:03:13 +01001051 memcpy(&ktermx, real_tty->termiox, sizeof(struct termiox));
Peter Hurley6a1c0682013-06-15 09:14:23 -04001052 up_read(&real_tty->termios_rwsem);
Alan Cox26a2e202009-06-11 14:03:13 +01001053 if (copy_to_user(p, &ktermx, sizeof(struct termiox)))
1054 ret = -EFAULT;
Alan Cox8f520022008-10-13 10:38:46 +01001055 return ret;
Mike Frysinger5dca6072009-06-16 17:01:02 +01001056 }
Alan Cox1d65b4a2008-10-13 10:38:18 +01001057 case TCSETX:
1058 return set_termiox(real_tty, p, 0);
1059 case TCSETXW:
1060 return set_termiox(real_tty, p, TERMIOS_WAIT);
1061 case TCSETXF:
1062 return set_termiox(real_tty, p, TERMIOS_FLUSH);
1063#endif
Alan Cox355d95a12008-02-08 04:18:48 -08001064 case TIOCGSOFTCAR:
Alan Cox26a2e202009-06-11 14:03:13 +01001065 copy_termios(real_tty, &kterm);
1066 ret = put_user((kterm.c_cflag & CLOCAL) ? 1 : 0,
Alan Cox355d95a12008-02-08 04:18:48 -08001067 (int __user *)arg);
Alan Cox8f520022008-10-13 10:38:46 +01001068 return ret;
Alan Cox355d95a12008-02-08 04:18:48 -08001069 case TIOCSSOFTCAR:
1070 if (get_user(arg, (unsigned int __user *) arg))
1071 return -EFAULT;
Alan Coxf753f322008-08-26 19:52:47 +01001072 return tty_change_softcar(real_tty, arg);
Alan Cox355d95a12008-02-08 04:18:48 -08001073 default:
1074 return -ENOIOCTLCMD;
Alan Cox0fc00e22007-11-07 01:24:56 -08001075 }
1076}
Alan Cox0fc00e22007-11-07 01:24:56 -08001077EXPORT_SYMBOL_GPL(tty_mode_ioctl);
1078
Alan Cox0fc00e22007-11-07 01:24:56 -08001079
Peter Hurleye7f38802013-03-11 16:44:45 -04001080/* Caller guarantees ldisc reference is held */
1081static int __tty_perform_flush(struct tty_struct *tty, unsigned long arg)
1082{
1083 struct tty_ldisc *ld = tty->ldisc;
1084
Alan Cox0fc00e22007-11-07 01:24:56 -08001085 switch (arg) {
1086 case TCIFLUSH:
Ilya Zykova1bf9582013-01-16 13:07:50 +04001087 if (ld && ld->ops->flush_buffer) {
Alan Coxa352def2008-07-16 21:53:12 +01001088 ld->ops->flush_buffer(tty);
Ilya Zykova1bf9582013-01-16 13:07:50 +04001089 tty_unthrottle(tty);
1090 }
Alan Cox0fc00e22007-11-07 01:24:56 -08001091 break;
1092 case TCIOFLUSH:
Ilya Zykova1bf9582013-01-16 13:07:50 +04001093 if (ld && ld->ops->flush_buffer) {
Alan Coxa352def2008-07-16 21:53:12 +01001094 ld->ops->flush_buffer(tty);
Ilya Zykova1bf9582013-01-16 13:07:50 +04001095 tty_unthrottle(tty);
1096 }
Alan Cox0fc00e22007-11-07 01:24:56 -08001097 /* fall through */
1098 case TCOFLUSH:
Alan Coxf34d7a52008-04-30 00:54:13 -07001099 tty_driver_flush_buffer(tty);
Alan Cox0fc00e22007-11-07 01:24:56 -08001100 break;
1101 default:
Alan Cox0fc00e22007-11-07 01:24:56 -08001102 return -EINVAL;
1103 }
Alan Cox0fc00e22007-11-07 01:24:56 -08001104 return 0;
1105}
Peter Hurleye7f38802013-03-11 16:44:45 -04001106
1107int tty_perform_flush(struct tty_struct *tty, unsigned long arg)
1108{
1109 struct tty_ldisc *ld;
1110 int retval = tty_check_change(tty);
1111 if (retval)
1112 return retval;
1113
1114 ld = tty_ldisc_ref_wait(tty);
1115 retval = __tty_perform_flush(tty, arg);
1116 if (ld)
1117 tty_ldisc_deref(ld);
1118 return retval;
1119}
Alan Cox0fc00e22007-11-07 01:24:56 -08001120EXPORT_SYMBOL_GPL(tty_perform_flush);
1121
Alan Cox47afa7a2008-10-13 10:44:17 +01001122int n_tty_ioctl_helper(struct tty_struct *tty, struct file *file,
Alan Cox0fc00e22007-11-07 01:24:56 -08001123 unsigned int cmd, unsigned long arg)
1124{
Alan Cox0fc00e22007-11-07 01:24:56 -08001125 int retval;
1126
Alan Cox0fc00e22007-11-07 01:24:56 -08001127 switch (cmd) {
Alan Cox355d95a12008-02-08 04:18:48 -08001128 case TCXONC:
1129 retval = tty_check_change(tty);
1130 if (retval)
1131 return retval;
1132 switch (arg) {
1133 case TCOOFF:
Peter Hurleyc545b662014-09-10 15:06:33 -04001134 spin_lock_irq(&tty->flow_lock);
Alan Cox355d95a12008-02-08 04:18:48 -08001135 if (!tty->flow_stopped) {
1136 tty->flow_stopped = 1;
Peter Hurleyc545b662014-09-10 15:06:33 -04001137 __stop_tty(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001138 }
Peter Hurleyc545b662014-09-10 15:06:33 -04001139 spin_unlock_irq(&tty->flow_lock);
Alan Cox355d95a12008-02-08 04:18:48 -08001140 break;
1141 case TCOON:
Peter Hurleyc545b662014-09-10 15:06:33 -04001142 spin_lock_irq(&tty->flow_lock);
Alan Cox355d95a12008-02-08 04:18:48 -08001143 if (tty->flow_stopped) {
1144 tty->flow_stopped = 0;
Peter Hurleyc545b662014-09-10 15:06:33 -04001145 __start_tty(tty);
Alan Cox355d95a12008-02-08 04:18:48 -08001146 }
Peter Hurleyc545b662014-09-10 15:06:33 -04001147 spin_unlock_irq(&tty->flow_lock);
Alan Cox355d95a12008-02-08 04:18:48 -08001148 break;
1149 case TCIOFF:
Peter Hurleyc274f6e2014-09-10 15:06:35 -04001150 down_read(&tty->termios_rwsem);
Alan Cox355d95a12008-02-08 04:18:48 -08001151 if (STOP_CHAR(tty) != __DISABLED_CHAR)
Peter Hurleyc274f6e2014-09-10 15:06:35 -04001152 retval = tty_send_xchar(tty, STOP_CHAR(tty));
1153 up_read(&tty->termios_rwsem);
Alan Cox355d95a12008-02-08 04:18:48 -08001154 break;
1155 case TCION:
Peter Hurleyc274f6e2014-09-10 15:06:35 -04001156 down_read(&tty->termios_rwsem);
Alan Cox355d95a12008-02-08 04:18:48 -08001157 if (START_CHAR(tty) != __DISABLED_CHAR)
Peter Hurleyc274f6e2014-09-10 15:06:35 -04001158 retval = tty_send_xchar(tty, START_CHAR(tty));
1159 up_read(&tty->termios_rwsem);
Alan Cox355d95a12008-02-08 04:18:48 -08001160 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001161 default:
Alan Cox355d95a12008-02-08 04:18:48 -08001162 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001163 }
Peter Hurleyc274f6e2014-09-10 15:06:35 -04001164 return retval;
Alan Cox355d95a12008-02-08 04:18:48 -08001165 case TCFLSH:
Peter Hurley5cec7bf2013-09-25 20:13:04 -04001166 retval = tty_check_change(tty);
1167 if (retval)
1168 return retval;
Peter Hurleye7f38802013-03-11 16:44:45 -04001169 return __tty_perform_flush(tty, arg);
Alan Cox355d95a12008-02-08 04:18:48 -08001170 default:
1171 /* Try the mode commands */
1172 return tty_mode_ioctl(tty, file, cmd, arg);
1173 }
1174}
Alan Cox47afa7a2008-10-13 10:44:17 +01001175EXPORT_SYMBOL(n_tty_ioctl_helper);
Thomas Meyer8193c422011-10-05 23:13:13 +02001176
1177#ifdef CONFIG_COMPAT
1178long n_tty_compat_ioctl_helper(struct tty_struct *tty, struct file *file,
1179 unsigned int cmd, unsigned long arg)
1180{
1181 switch (cmd) {
1182 case TIOCGLCKTRMIOS:
1183 case TIOCSLCKTRMIOS:
1184 return tty_mode_ioctl(tty, file, cmd, (unsigned long) compat_ptr(arg));
1185 default:
1186 return -ENOIOCTLCMD;
1187 }
1188}
1189EXPORT_SYMBOL(n_tty_compat_ioctl_helper);
1190#endif
1191