blob: 9314d93c1a20ab8b057670f56ee55bca23d66e44 [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>
26#include <asm/system.h>
27
28#undef TTY_DEBUG_WAIT_UNTIL_SENT
29
30#undef DEBUG
31
32/*
33 * Internal flag options for termios setting behavior
34 */
35#define TERMIOS_FLUSH 1
36#define TERMIOS_WAIT 2
37#define TERMIOS_TERMIO 4
Alan Coxedc6afc2006-12-08 02:38:44 -080038#define TERMIOS_OLD 8
Linus Torvalds1da177e2005-04-16 15:20:36 -070039
Alan Coxaf9b8972006-08-27 01:24:01 -070040
Alan Coxd81ed102008-10-13 10:41:42 +010041/**
42 * tty_chars_in_buffer - characters pending
43 * @tty: terminal
44 *
45 * Return the number of bytes of data in the device private
46 * output queue. If no private method is supplied there is assumed
47 * to be no queue on the device.
48 */
49
Alan Coxf34d7a52008-04-30 00:54:13 -070050int tty_chars_in_buffer(struct tty_struct *tty)
51{
52 if (tty->ops->chars_in_buffer)
53 return tty->ops->chars_in_buffer(tty);
54 else
55 return 0;
56}
Alan Coxf34d7a52008-04-30 00:54:13 -070057EXPORT_SYMBOL(tty_chars_in_buffer);
58
Alan Coxd81ed102008-10-13 10:41:42 +010059/**
60 * tty_write_room - write queue space
61 * @tty: terminal
62 *
63 * Return the number of bytes that can be queued to this device
64 * at the present time. The result should be treated as a guarantee
65 * and the driver cannot offer a value it later shrinks by more than
66 * the number of bytes written. If no method is provided 2K is always
67 * returned and data may be lost as there will be no flow control.
68 */
69
Alan Coxf34d7a52008-04-30 00:54:13 -070070int tty_write_room(struct tty_struct *tty)
71{
72 if (tty->ops->write_room)
73 return tty->ops->write_room(tty);
74 return 2048;
75}
Alan Coxf34d7a52008-04-30 00:54:13 -070076EXPORT_SYMBOL(tty_write_room);
77
Alan Coxd81ed102008-10-13 10:41:42 +010078/**
79 * tty_driver_flush_buffer - discard internal buffer
80 * @tty: terminal
81 *
82 * Discard the internal output buffer for this device. If no method
83 * is provided then either the buffer cannot be hardware flushed or
84 * there is no buffer driver side.
85 */
Alan Coxf34d7a52008-04-30 00:54:13 -070086void tty_driver_flush_buffer(struct tty_struct *tty)
87{
88 if (tty->ops->flush_buffer)
89 tty->ops->flush_buffer(tty);
90}
Alan Coxf34d7a52008-04-30 00:54:13 -070091EXPORT_SYMBOL(tty_driver_flush_buffer);
92
Alan Coxd81ed102008-10-13 10:41:42 +010093/**
94 * tty_throttle - flow control
95 * @tty: terminal
96 *
97 * Indicate that a tty should stop transmitting data down the stack.
Alan Cox38db8972009-06-11 12:44:17 +010098 * Takes the termios mutex to protect against parallel throttle/unthrottle
99 * and also to ensure the driver can consistently reference its own
100 * termios data at this point when implementing software flow control.
Alan Coxd81ed102008-10-13 10:41:42 +0100101 */
102
Alan Cox39c2e602008-04-30 00:54:18 -0700103void tty_throttle(struct tty_struct *tty)
104{
Alan Cox38db8972009-06-11 12:44:17 +0100105 mutex_lock(&tty->termios_mutex);
Alan Cox39c2e602008-04-30 00:54:18 -0700106 /* check TTY_THROTTLED first so it indicates our state */
107 if (!test_and_set_bit(TTY_THROTTLED, &tty->flags) &&
108 tty->ops->throttle)
109 tty->ops->throttle(tty);
Alan Cox38db8972009-06-11 12:44:17 +0100110 mutex_unlock(&tty->termios_mutex);
Alan Cox39c2e602008-04-30 00:54:18 -0700111}
112EXPORT_SYMBOL(tty_throttle);
113
Alan Coxd81ed102008-10-13 10:41:42 +0100114/**
115 * tty_unthrottle - flow control
116 * @tty: terminal
117 *
118 * Indicate that a tty may continue transmitting data down the stack.
Alan Cox38db8972009-06-11 12:44:17 +0100119 * Takes the termios mutex to protect against parallel throttle/unthrottle
120 * and also to ensure the driver can consistently reference its own
121 * termios data at this point when implementing software flow control.
122 *
123 * Drivers should however remember that the stack can issue a throttle,
124 * then change flow control method, then unthrottle.
Alan Coxd81ed102008-10-13 10:41:42 +0100125 */
126
Alan Cox39c2e602008-04-30 00:54:18 -0700127void tty_unthrottle(struct tty_struct *tty)
128{
Alan Cox38db8972009-06-11 12:44:17 +0100129 mutex_lock(&tty->termios_mutex);
Alan Cox39c2e602008-04-30 00:54:18 -0700130 if (test_and_clear_bit(TTY_THROTTLED, &tty->flags) &&
131 tty->ops->unthrottle)
132 tty->ops->unthrottle(tty);
Alan Cox38db8972009-06-11 12:44:17 +0100133 mutex_unlock(&tty->termios_mutex);
Alan Cox39c2e602008-04-30 00:54:18 -0700134}
135EXPORT_SYMBOL(tty_unthrottle);
Alan Coxf34d7a52008-04-30 00:54:13 -0700136
Alan Coxaf9b8972006-08-27 01:24:01 -0700137/**
138 * tty_wait_until_sent - wait for I/O to finish
139 * @tty: tty we are waiting for
140 * @timeout: how long we will wait
141 *
142 * Wait for characters pending in a tty driver to hit the wire, or
143 * for a timeout to occur (eg due to flow control)
144 *
145 * Locking: none
146 */
147
Alan Cox355d95a12008-02-08 04:18:48 -0800148void tty_wait_until_sent(struct tty_struct *tty, long timeout)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700149{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700150#ifdef TTY_DEBUG_WAIT_UNTIL_SENT
151 char buf[64];
Alan Cox355d95a12008-02-08 04:18:48 -0800152
Linus Torvalds1da177e2005-04-16 15:20:36 -0700153 printk(KERN_DEBUG "%s wait until sent...\n", tty_name(tty, buf));
154#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700155 if (!timeout)
156 timeout = MAX_SCHEDULE_TIMEOUT;
Jiri Slaby5a52bd42007-07-15 23:40:18 -0700157 if (wait_event_interruptible_timeout(tty->write_wait,
Alan Coxf34d7a52008-04-30 00:54:13 -0700158 !tty_chars_in_buffer(tty), timeout) >= 0) {
159 if (tty->ops->wait_until_sent)
160 tty->ops->wait_until_sent(tty, timeout);
Alan Cox0ee9cbb2008-04-30 00:53:32 -0700161 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700162}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700163EXPORT_SYMBOL(tty_wait_until_sent);
164
Alan Coxd81ed102008-10-13 10:41:42 +0100165
166/*
167 * Termios Helper Methods
168 */
169
Alan Coxedc6afc2006-12-08 02:38:44 -0800170static void unset_locked_termios(struct ktermios *termios,
171 struct ktermios *old,
172 struct ktermios *locked)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700173{
174 int i;
Alan Cox355d95a12008-02-08 04:18:48 -0800175
176#define NOSET_MASK(x, y, z) (x = ((x) & ~(z)) | ((y) & (z)))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700177
178 if (!locked) {
179 printk(KERN_WARNING "Warning?!? termios_locked is NULL.\n");
180 return;
181 }
182
183 NOSET_MASK(termios->c_iflag, old->c_iflag, locked->c_iflag);
184 NOSET_MASK(termios->c_oflag, old->c_oflag, locked->c_oflag);
185 NOSET_MASK(termios->c_cflag, old->c_cflag, locked->c_cflag);
186 NOSET_MASK(termios->c_lflag, old->c_lflag, locked->c_lflag);
187 termios->c_line = locked->c_line ? old->c_line : termios->c_line;
Alan Cox355d95a12008-02-08 04:18:48 -0800188 for (i = 0; i < NCCS; i++)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700189 termios->c_cc[i] = locked->c_cc[i] ?
190 old->c_cc[i] : termios->c_cc[i];
Alan Coxedc6afc2006-12-08 02:38:44 -0800191 /* FIXME: What should we do for i/ospeed */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700192}
193
Alan Coxedc6afc2006-12-08 02:38:44 -0800194/*
195 * Routine which returns the baud rate of the tty
196 *
197 * Note that the baud_table needs to be kept in sync with the
198 * include/asm/termbits.h file.
199 */
200static const speed_t baud_table[] = {
201 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
202 9600, 19200, 38400, 57600, 115200, 230400, 460800,
203#ifdef __sparc__
204 76800, 153600, 307200, 614400, 921600
205#else
206 500000, 576000, 921600, 1000000, 1152000, 1500000, 2000000,
207 2500000, 3000000, 3500000, 4000000
208#endif
209};
210
211#ifndef __sparc__
212static const tcflag_t baud_bits[] = {
213 B0, B50, B75, B110, B134, B150, B200, B300, B600,
214 B1200, B1800, B2400, B4800, B9600, B19200, B38400,
215 B57600, B115200, B230400, B460800, B500000, B576000,
216 B921600, B1000000, B1152000, B1500000, B2000000, B2500000,
217 B3000000, B3500000, B4000000
218};
219#else
220static const tcflag_t baud_bits[] = {
221 B0, B50, B75, B110, B134, B150, B200, B300, B600,
222 B1200, B1800, B2400, B4800, B9600, B19200, B38400,
223 B57600, B115200, B230400, B460800, B76800, B153600,
224 B307200, B614400, B921600
225};
226#endif
227
228static int n_baud_table = ARRAY_SIZE(baud_table);
229
230/**
231 * tty_termios_baud_rate
232 * @termios: termios structure
233 *
234 * Convert termios baud rate data into a speed. This should be called
235 * with the termios lock held if this termios is a terminal termios
236 * structure. May change the termios data. Device drivers can call this
237 * function but should use ->c_[io]speed directly as they are updated.
238 *
239 * Locking: none
240 */
241
242speed_t tty_termios_baud_rate(struct ktermios *termios)
243{
244 unsigned int cbaud;
245
246 cbaud = termios->c_cflag & CBAUD;
247
248#ifdef BOTHER
Lucas De Marchi25985ed2011-03-30 22:57:33 -0300249 /* Magic token for arbitrary speed via c_ispeed/c_ospeed */
Alan Coxedc6afc2006-12-08 02:38:44 -0800250 if (cbaud == BOTHER)
251 return termios->c_ospeed;
252#endif
253 if (cbaud & CBAUDEX) {
254 cbaud &= ~CBAUDEX;
255
256 if (cbaud < 1 || cbaud + 15 > n_baud_table)
257 termios->c_cflag &= ~CBAUDEX;
258 else
259 cbaud += 15;
260 }
261 return baud_table[cbaud];
262}
Alan Coxedc6afc2006-12-08 02:38:44 -0800263EXPORT_SYMBOL(tty_termios_baud_rate);
264
265/**
266 * tty_termios_input_baud_rate
267 * @termios: termios structure
268 *
269 * Convert termios baud rate data into a speed. This should be called
270 * with the termios lock held if this termios is a terminal termios
271 * structure. May change the termios data. Device drivers can call this
272 * function but should use ->c_[io]speed directly as they are updated.
273 *
274 * Locking: none
275 */
276
277speed_t tty_termios_input_baud_rate(struct ktermios *termios)
278{
279#ifdef IBSHIFT
280 unsigned int cbaud = (termios->c_cflag >> IBSHIFT) & CBAUD;
281
282 if (cbaud == B0)
283 return tty_termios_baud_rate(termios);
284
Lucas De Marchi25985ed2011-03-30 22:57:33 -0300285 /* Magic token for arbitrary speed via c_ispeed*/
Alan Coxedc6afc2006-12-08 02:38:44 -0800286 if (cbaud == BOTHER)
287 return termios->c_ispeed;
288
289 if (cbaud & CBAUDEX) {
290 cbaud &= ~CBAUDEX;
291
292 if (cbaud < 1 || cbaud + 15 > n_baud_table)
293 termios->c_cflag &= ~(CBAUDEX << IBSHIFT);
294 else
295 cbaud += 15;
296 }
297 return baud_table[cbaud];
298#else
299 return tty_termios_baud_rate(termios);
300#endif
301}
Alan Coxedc6afc2006-12-08 02:38:44 -0800302EXPORT_SYMBOL(tty_termios_input_baud_rate);
303
Alan Coxedc6afc2006-12-08 02:38:44 -0800304/**
305 * tty_termios_encode_baud_rate
Alan Cox78137e32007-02-10 01:45:57 -0800306 * @termios: ktermios structure holding user requested state
Alan Coxedc6afc2006-12-08 02:38:44 -0800307 * @ispeed: input speed
308 * @ospeed: output speed
309 *
310 * Encode the speeds set into the passed termios structure. This is
Uwe Kleine-Königf98e5b82011-04-12 09:59:29 +0200311 * used as a library helper for drivers so that they can report back
Alan Coxedc6afc2006-12-08 02:38:44 -0800312 * the actual speed selected when it differs from the speed requested
313 *
Alan Cox78137e32007-02-10 01:45:57 -0800314 * For maximal back compatibility with legacy SYS5/POSIX *nix behaviour
315 * we need to carefully set the bits when the user does not get the
316 * desired speed. We allow small margins and preserve as much of possible
Dirk Hohndel06fe9fb2009-09-28 21:43:57 -0400317 * of the input intent to keep compatibility.
Alan Coxedc6afc2006-12-08 02:38:44 -0800318 *
319 * Locking: Caller should hold termios lock. This is already held
320 * when calling this function from the driver termios handler.
Alan Cox5f519d72007-10-16 23:30:07 -0700321 *
322 * The ifdefs deal with platforms whose owners have yet to update them
323 * and will all go away once this is done.
Alan Coxedc6afc2006-12-08 02:38:44 -0800324 */
325
Maciej W. Rozycki75e8b712007-10-18 03:04:35 -0700326void tty_termios_encode_baud_rate(struct ktermios *termios,
327 speed_t ibaud, speed_t obaud)
Alan Coxedc6afc2006-12-08 02:38:44 -0800328{
329 int i = 0;
Alan Cox78137e32007-02-10 01:45:57 -0800330 int ifound = -1, ofound = -1;
331 int iclose = ibaud/50, oclose = obaud/50;
332 int ibinput = 0;
Alan Coxedc6afc2006-12-08 02:38:44 -0800333
Alan Cox5f519d72007-10-16 23:30:07 -0700334 if (obaud == 0) /* CD dropped */
335 ibaud = 0; /* Clear ibaud to be sure */
336
Alan Coxedc6afc2006-12-08 02:38:44 -0800337 termios->c_ispeed = ibaud;
338 termios->c_ospeed = obaud;
339
Alan Cox5f519d72007-10-16 23:30:07 -0700340#ifdef BOTHER
Alan Cox78137e32007-02-10 01:45:57 -0800341 /* If the user asked for a precise weird speed give a precise weird
342 answer. If they asked for a Bfoo speed they many have problems
343 digesting non-exact replies so fuzz a bit */
344
345 if ((termios->c_cflag & CBAUD) == BOTHER)
346 oclose = 0;
347 if (((termios->c_cflag >> IBSHIFT) & CBAUD) == BOTHER)
348 iclose = 0;
349 if ((termios->c_cflag >> IBSHIFT) & CBAUD)
350 ibinput = 1; /* An input speed was specified */
Alan Cox5f519d72007-10-16 23:30:07 -0700351#endif
Alan Coxedc6afc2006-12-08 02:38:44 -0800352 termios->c_cflag &= ~CBAUD;
Alan Coxedc6afc2006-12-08 02:38:44 -0800353
Alan Cox5f519d72007-10-16 23:30:07 -0700354 /*
355 * Our goal is to find a close match to the standard baud rate
356 * returned. Walk the baud rate table and if we get a very close
357 * match then report back the speed as a POSIX Bxxxx value by
358 * preference
359 */
360
Alan Coxedc6afc2006-12-08 02:38:44 -0800361 do {
Maciej W. Rozycki75e8b712007-10-18 03:04:35 -0700362 if (obaud - oclose <= baud_table[i] &&
363 obaud + oclose >= baud_table[i]) {
Alan Coxedc6afc2006-12-08 02:38:44 -0800364 termios->c_cflag |= baud_bits[i];
Alan Cox78137e32007-02-10 01:45:57 -0800365 ofound = i;
Alan Coxedc6afc2006-12-08 02:38:44 -0800366 }
Maciej W. Rozycki75e8b712007-10-18 03:04:35 -0700367 if (ibaud - iclose <= baud_table[i] &&
368 ibaud + iclose >= baud_table[i]) {
369 /* For the case input == output don't set IBAUD bits
370 if the user didn't do so */
Alan Cox5f519d72007-10-16 23:30:07 -0700371 if (ofound == i && !ibinput)
372 ifound = i;
373#ifdef IBSHIFT
374 else {
375 ifound = i;
Alan Cox78137e32007-02-10 01:45:57 -0800376 termios->c_cflag |= (baud_bits[i] << IBSHIFT);
Alan Cox5f519d72007-10-16 23:30:07 -0700377 }
378#endif
Alan Coxedc6afc2006-12-08 02:38:44 -0800379 }
Jiri Slaby68043962007-07-15 23:40:18 -0700380 } while (++i < n_baud_table);
Alan Cox5f519d72007-10-16 23:30:07 -0700381
382 /*
383 * If we found no match then use BOTHER if provided or warn
384 * the user their platform maintainer needs to wake up if not.
385 */
386#ifdef BOTHER
Alan Cox78137e32007-02-10 01:45:57 -0800387 if (ofound == -1)
Alan Coxedc6afc2006-12-08 02:38:44 -0800388 termios->c_cflag |= BOTHER;
Alan Cox78137e32007-02-10 01:45:57 -0800389 /* Set exact input bits only if the input and output differ or the
390 user already did */
Jiri Slaby68043962007-07-15 23:40:18 -0700391 if (ifound == -1 && (ibaud != obaud || ibinput))
Alan Coxedc6afc2006-12-08 02:38:44 -0800392 termios->c_cflag |= (BOTHER << IBSHIFT);
Alan Cox5f519d72007-10-16 23:30:07 -0700393#else
394 if (ifound == -1 || ofound == -1) {
Marcin Slusarz9074d962009-08-09 21:54:03 +0200395 printk_once(KERN_WARNING "tty: Unable to return correct "
Alan Cox5f519d72007-10-16 23:30:07 -0700396 "speed data as your architecture needs updating.\n");
397 }
398#endif
Alan Coxedc6afc2006-12-08 02:38:44 -0800399}
Alan Coxedc6afc2006-12-08 02:38:44 -0800400EXPORT_SYMBOL_GPL(tty_termios_encode_baud_rate);
401
Alan Coxd81ed102008-10-13 10:41:42 +0100402/**
403 * tty_encode_baud_rate - set baud rate of the tty
404 * @ibaud: input baud rate
405 * @obad: output baud rate
406 *
407 * Update the current termios data for the tty with the new speed
408 * settings. The caller must hold the termios_mutex for the tty in
409 * question.
410 */
411
Alan Cox5f519d72007-10-16 23:30:07 -0700412void tty_encode_baud_rate(struct tty_struct *tty, speed_t ibaud, speed_t obaud)
413{
414 tty_termios_encode_baud_rate(tty->termios, ibaud, obaud);
415}
416EXPORT_SYMBOL_GPL(tty_encode_baud_rate);
Alan Coxedc6afc2006-12-08 02:38:44 -0800417
418/**
419 * tty_get_baud_rate - get tty bit rates
420 * @tty: tty to query
421 *
422 * Returns the baud rate as an integer for this terminal. The
423 * termios lock must be held by the caller and the terminal bit
424 * flags may be updated.
425 *
426 * Locking: none
427 */
428
429speed_t tty_get_baud_rate(struct tty_struct *tty)
430{
431 speed_t baud = tty_termios_baud_rate(tty->termios);
432
433 if (baud == 38400 && tty->alt_speed) {
434 if (!tty->warned) {
435 printk(KERN_WARNING "Use of setserial/setrocket to "
436 "set SPD_* flags is deprecated\n");
437 tty->warned = 1;
438 }
439 baud = tty->alt_speed;
440 }
441
442 return baud;
443}
Alan Coxedc6afc2006-12-08 02:38:44 -0800444EXPORT_SYMBOL(tty_get_baud_rate);
445
Alan Coxaf9b8972006-08-27 01:24:01 -0700446/**
Alan Cox5f519d72007-10-16 23:30:07 -0700447 * tty_termios_copy_hw - copy hardware settings
448 * @new: New termios
449 * @old: Old termios
450 *
Lucas De Marchi25985ed2011-03-30 22:57:33 -0300451 * Propagate the hardware specific terminal setting bits from
Alan Cox5f519d72007-10-16 23:30:07 -0700452 * the old termios structure to the new one. This is used in cases
453 * where the hardware does not support reconfiguration or as a helper
454 * in some cases where only minimal reconfiguration is supported
455 */
456
457void tty_termios_copy_hw(struct ktermios *new, struct ktermios *old)
458{
459 /* The bits a dumb device handles in software. Smart devices need
460 to always provide a set_termios method */
461 new->c_cflag &= HUPCL | CREAD | CLOCAL;
462 new->c_cflag |= old->c_cflag & ~(HUPCL | CREAD | CLOCAL);
463 new->c_ispeed = old->c_ispeed;
464 new->c_ospeed = old->c_ospeed;
465}
Alan Cox5f519d72007-10-16 23:30:07 -0700466EXPORT_SYMBOL(tty_termios_copy_hw);
467
468/**
Alan Coxbf5e5832008-01-08 14:55:51 +0000469 * tty_termios_hw_change - check for setting change
470 * @a: termios
471 * @b: termios to compare
472 *
473 * Check if any of the bits that affect a dumb device have changed
474 * between the two termios structures, or a speed change is needed.
475 */
476
477int tty_termios_hw_change(struct ktermios *a, struct ktermios *b)
478{
479 if (a->c_ispeed != b->c_ispeed || a->c_ospeed != b->c_ospeed)
480 return 1;
481 if ((a->c_cflag ^ b->c_cflag) & ~(HUPCL | CREAD | CLOCAL))
482 return 1;
483 return 0;
484}
485EXPORT_SYMBOL(tty_termios_hw_change);
486
487/**
Alan Cox8d075b12011-02-14 16:27:53 +0000488 * tty_set_termios - update termios values
Alan Coxaf9b8972006-08-27 01:24:01 -0700489 * @tty: tty to update
490 * @new_termios: desired new value
491 *
492 * Perform updates to the termios values set on this terminal. There
493 * is a bit of layering violation here with n_tty in terms of the
494 * internal knowledge of this function.
495 *
Alan Coxd81ed102008-10-13 10:41:42 +0100496 * Locking: termios_mutex
Alan Coxaf9b8972006-08-27 01:24:01 -0700497 */
498
Alan Cox8d075b12011-02-14 16:27:53 +0000499int tty_set_termios(struct tty_struct *tty, struct ktermios *new_termios)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700500{
Alan Cox978e5952008-04-30 00:53:59 -0700501 struct ktermios old_termios;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700502 struct tty_ldisc *ld;
Alan Cox04f378b2008-04-30 00:53:29 -0700503 unsigned long flags;
Alan Cox355d95a12008-02-08 04:18:48 -0800504
Linus Torvalds1da177e2005-04-16 15:20:36 -0700505 /*
506 * Perform the actual termios internal changes under lock.
507 */
Alan Cox355d95a12008-02-08 04:18:48 -0800508
Linus Torvalds1da177e2005-04-16 15:20:36 -0700509
510 /* FIXME: we need to decide on some locking/ordering semantics
511 for the set_termios notification eventually */
Arjan van de Ven5785c952006-09-29 02:00:43 -0700512 mutex_lock(&tty->termios_mutex);
Alan Cox978e5952008-04-30 00:53:59 -0700513 old_termios = *tty->termios;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700514 *tty->termios = *new_termios;
515 unset_locked_termios(tty->termios, &old_termios, tty->termios_locked);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700516
517 /* See if packet mode change of state. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700518 if (tty->link && tty->link->packet) {
hyc@symas.com26df6d12010-06-22 10:14:49 -0700519 int extproc = (old_termios.c_lflag & EXTPROC) |
520 (tty->termios->c_lflag & EXTPROC);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700521 int old_flow = ((old_termios.c_iflag & IXON) &&
522 (old_termios.c_cc[VSTOP] == '\023') &&
523 (old_termios.c_cc[VSTART] == '\021'));
524 int new_flow = (I_IXON(tty) &&
525 STOP_CHAR(tty) == '\023' &&
526 START_CHAR(tty) == '\021');
hyc@symas.com26df6d12010-06-22 10:14:49 -0700527 if ((old_flow != new_flow) || extproc) {
Alan Cox04f378b2008-04-30 00:53:29 -0700528 spin_lock_irqsave(&tty->ctrl_lock, flags);
hyc@symas.com26df6d12010-06-22 10:14:49 -0700529 if (old_flow != new_flow) {
530 tty->ctrl_status &= ~(TIOCPKT_DOSTOP | TIOCPKT_NOSTOP);
531 if (new_flow)
532 tty->ctrl_status |= TIOCPKT_DOSTOP;
533 else
534 tty->ctrl_status |= TIOCPKT_NOSTOP;
535 }
536 if (extproc)
537 tty->ctrl_status |= TIOCPKT_IOCTL;
Alan Cox04f378b2008-04-30 00:53:29 -0700538 spin_unlock_irqrestore(&tty->ctrl_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700539 wake_up_interruptible(&tty->link->read_wait);
540 }
541 }
Alan Cox355d95a12008-02-08 04:18:48 -0800542
Alan Coxf34d7a52008-04-30 00:54:13 -0700543 if (tty->ops->set_termios)
544 (*tty->ops->set_termios)(tty, &old_termios);
Alan Cox5f519d72007-10-16 23:30:07 -0700545 else
546 tty_termios_copy_hw(tty->termios, &old_termios);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700547
548 ld = tty_ldisc_ref(tty);
549 if (ld != NULL) {
Alan Coxa352def2008-07-16 21:53:12 +0100550 if (ld->ops->set_termios)
551 (ld->ops->set_termios)(tty, &old_termios);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700552 tty_ldisc_deref(ld);
553 }
Arjan van de Ven5785c952006-09-29 02:00:43 -0700554 mutex_unlock(&tty->termios_mutex);
Alan Cox8d075b12011-02-14 16:27:53 +0000555 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700556}
Alan Cox8d075b12011-02-14 16:27:53 +0000557EXPORT_SYMBOL_GPL(tty_set_termios);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700558
Alan Coxaf9b8972006-08-27 01:24:01 -0700559/**
560 * set_termios - set termios values for a tty
561 * @tty: terminal device
562 * @arg: user data
563 * @opt: option information
564 *
Robert P. J. Day3a4fa0a2007-10-19 23:10:43 +0200565 * Helper function to prepare termios data and run necessary other
Alan Cox8d075b12011-02-14 16:27:53 +0000566 * functions before using tty_set_termios to do the actual changes.
Alan Coxaf9b8972006-08-27 01:24:01 -0700567 *
568 * Locking:
Alan Coxd81ed102008-10-13 10:41:42 +0100569 * Called functions take ldisc and termios_mutex locks
Alan Coxaf9b8972006-08-27 01:24:01 -0700570 */
571
Alan Cox355d95a12008-02-08 04:18:48 -0800572static int set_termios(struct tty_struct *tty, void __user *arg, int opt)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700573{
Alan Coxedc6afc2006-12-08 02:38:44 -0800574 struct ktermios tmp_termios;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700575 struct tty_ldisc *ld;
576 int retval = tty_check_change(tty);
577
578 if (retval)
579 return retval;
580
Alan Cox978e5952008-04-30 00:53:59 -0700581 mutex_lock(&tty->termios_mutex);
Alan Cox64bb6c52006-12-08 02:38:47 -0800582 memcpy(&tmp_termios, tty->termios, sizeof(struct ktermios));
Alan Cox978e5952008-04-30 00:53:59 -0700583 mutex_unlock(&tty->termios_mutex);
Alan Cox64bb6c52006-12-08 02:38:47 -0800584
Linus Torvalds1da177e2005-04-16 15:20:36 -0700585 if (opt & TERMIOS_TERMIO) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700586 if (user_termio_to_kernel_termios(&tmp_termios,
587 (struct termio __user *)arg))
588 return -EFAULT;
Alan Coxedc6afc2006-12-08 02:38:44 -0800589#ifdef TCGETS2
590 } else if (opt & TERMIOS_OLD) {
Alan Coxedc6afc2006-12-08 02:38:44 -0800591 if (user_termios_to_kernel_termios_1(&tmp_termios,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700592 (struct termios __user *)arg))
593 return -EFAULT;
Alan Cox64bb6c52006-12-08 02:38:47 -0800594 } else {
595 if (user_termios_to_kernel_termios(&tmp_termios,
596 (struct termios2 __user *)arg))
597 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700598 }
Alan Cox64bb6c52006-12-08 02:38:47 -0800599#else
600 } else if (user_termios_to_kernel_termios(&tmp_termios,
601 (struct termios __user *)arg))
602 return -EFAULT;
603#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700604
Alan Cox355d95a12008-02-08 04:18:48 -0800605 /* If old style Bfoo values are used then load c_ispeed/c_ospeed
606 * with the real speed so its unconditionally usable */
Alan Coxedc6afc2006-12-08 02:38:44 -0800607 tmp_termios.c_ispeed = tty_termios_input_baud_rate(&tmp_termios);
608 tmp_termios.c_ospeed = tty_termios_baud_rate(&tmp_termios);
609
Linus Torvalds1da177e2005-04-16 15:20:36 -0700610 ld = tty_ldisc_ref(tty);
Alan Cox355d95a12008-02-08 04:18:48 -0800611
Linus Torvalds1da177e2005-04-16 15:20:36 -0700612 if (ld != NULL) {
Alan Coxa352def2008-07-16 21:53:12 +0100613 if ((opt & TERMIOS_FLUSH) && ld->ops->flush_buffer)
614 ld->ops->flush_buffer(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700615 tty_ldisc_deref(ld);
616 }
Alan Cox355d95a12008-02-08 04:18:48 -0800617
Linus Torvalds1da177e2005-04-16 15:20:36 -0700618 if (opt & TERMIOS_WAIT) {
619 tty_wait_until_sent(tty, 0);
620 if (signal_pending(current))
621 return -EINTR;
622 }
623
Alan Cox8d075b12011-02-14 16:27:53 +0000624 tty_set_termios(tty, &tmp_termios);
Alan Cox5f519d72007-10-16 23:30:07 -0700625
626 /* FIXME: Arguably if tmp_termios == tty->termios AND the
627 actual requested termios was not tmp_termios then we may
628 want to return an error as no user requested change has
629 succeeded */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700630 return 0;
631}
632
Alan Cox26a2e202009-06-11 14:03:13 +0100633static void copy_termios(struct tty_struct *tty, struct ktermios *kterm)
634{
635 mutex_lock(&tty->termios_mutex);
636 memcpy(kterm, tty->termios, sizeof(struct ktermios));
637 mutex_unlock(&tty->termios_mutex);
638}
639
640static void copy_termios_locked(struct tty_struct *tty, struct ktermios *kterm)
641{
642 mutex_lock(&tty->termios_mutex);
643 memcpy(kterm, tty->termios_locked, sizeof(struct ktermios));
644 mutex_unlock(&tty->termios_mutex);
645}
646
Alan Cox355d95a12008-02-08 04:18:48 -0800647static int get_termio(struct tty_struct *tty, struct termio __user *termio)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700648{
Alan Cox26a2e202009-06-11 14:03:13 +0100649 struct ktermios kterm;
650 copy_termios(tty, &kterm);
651 if (kernel_termios_to_user_termio(termio, &kterm))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700652 return -EFAULT;
653 return 0;
654}
655
Alan Cox1d65b4a2008-10-13 10:38:18 +0100656
657#ifdef TCGETX
658
659/**
660 * set_termiox - set termiox fields if possible
661 * @tty: terminal
662 * @arg: termiox structure from user
663 * @opt: option flags for ioctl type
664 *
665 * Implement the device calling points for the SYS5 termiox ioctl
666 * interface in Linux
667 */
668
669static int set_termiox(struct tty_struct *tty, void __user *arg, int opt)
670{
671 struct termiox tnew;
672 struct tty_ldisc *ld;
673
674 if (tty->termiox == NULL)
675 return -EINVAL;
676 if (copy_from_user(&tnew, arg, sizeof(struct termiox)))
677 return -EFAULT;
678
679 ld = tty_ldisc_ref(tty);
680 if (ld != NULL) {
681 if ((opt & TERMIOS_FLUSH) && ld->ops->flush_buffer)
682 ld->ops->flush_buffer(tty);
683 tty_ldisc_deref(ld);
684 }
685 if (opt & TERMIOS_WAIT) {
686 tty_wait_until_sent(tty, 0);
687 if (signal_pending(current))
688 return -EINTR;
689 }
690
691 mutex_lock(&tty->termios_mutex);
692 if (tty->ops->set_termiox)
693 tty->ops->set_termiox(tty, &tnew);
694 mutex_unlock(&tty->termios_mutex);
695 return 0;
696}
697
698#endif
699
Linus Torvalds1da177e2005-04-16 15:20:36 -0700700
701#ifdef TIOCGETP
702/*
703 * These are deprecated, but there is limited support..
704 *
705 * The "sg_flags" translation is a joke..
706 */
Alan Cox355d95a12008-02-08 04:18:48 -0800707static int get_sgflags(struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700708{
709 int flags = 0;
710
711 if (!(tty->termios->c_lflag & ICANON)) {
712 if (tty->termios->c_lflag & ISIG)
713 flags |= 0x02; /* cbreak */
714 else
715 flags |= 0x20; /* raw */
716 }
717 if (tty->termios->c_lflag & ECHO)
718 flags |= 0x08; /* echo */
719 if (tty->termios->c_oflag & OPOST)
720 if (tty->termios->c_oflag & ONLCR)
721 flags |= 0x10; /* crmod */
722 return flags;
723}
724
Alan Cox355d95a12008-02-08 04:18:48 -0800725static int get_sgttyb(struct tty_struct *tty, struct sgttyb __user *sgttyb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700726{
727 struct sgttyb tmp;
728
Arjan van de Ven5785c952006-09-29 02:00:43 -0700729 mutex_lock(&tty->termios_mutex);
Alan Cox606d0992006-12-08 02:38:45 -0800730 tmp.sg_ispeed = tty->termios->c_ispeed;
731 tmp.sg_ospeed = tty->termios->c_ospeed;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700732 tmp.sg_erase = tty->termios->c_cc[VERASE];
733 tmp.sg_kill = tty->termios->c_cc[VKILL];
734 tmp.sg_flags = get_sgflags(tty);
Arjan van de Ven5785c952006-09-29 02:00:43 -0700735 mutex_unlock(&tty->termios_mutex);
Alan Cox355d95a12008-02-08 04:18:48 -0800736
Linus Torvalds1da177e2005-04-16 15:20:36 -0700737 return copy_to_user(sgttyb, &tmp, sizeof(tmp)) ? -EFAULT : 0;
738}
739
Alan Cox355d95a12008-02-08 04:18:48 -0800740static void set_sgflags(struct ktermios *termios, int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700741{
742 termios->c_iflag = ICRNL | IXON;
743 termios->c_oflag = 0;
744 termios->c_lflag = ISIG | ICANON;
745 if (flags & 0x02) { /* cbreak */
746 termios->c_iflag = 0;
747 termios->c_lflag &= ~ICANON;
748 }
749 if (flags & 0x08) { /* echo */
750 termios->c_lflag |= ECHO | ECHOE | ECHOK |
751 ECHOCTL | ECHOKE | IEXTEN;
752 }
753 if (flags & 0x10) { /* crmod */
754 termios->c_oflag |= OPOST | ONLCR;
755 }
756 if (flags & 0x20) { /* raw */
757 termios->c_iflag = 0;
758 termios->c_lflag &= ~(ISIG | ICANON);
759 }
760 if (!(termios->c_lflag & ICANON)) {
761 termios->c_cc[VMIN] = 1;
762 termios->c_cc[VTIME] = 0;
763 }
764}
765
Alan Coxaf9b8972006-08-27 01:24:01 -0700766/**
767 * set_sgttyb - set legacy terminal values
768 * @tty: tty structure
769 * @sgttyb: pointer to old style terminal structure
770 *
771 * Updates a terminal from the legacy BSD style terminal information
772 * structure.
773 *
Alan Coxd81ed102008-10-13 10:41:42 +0100774 * Locking: termios_mutex
Alan Coxaf9b8972006-08-27 01:24:01 -0700775 */
776
Alan Cox355d95a12008-02-08 04:18:48 -0800777static int set_sgttyb(struct tty_struct *tty, struct sgttyb __user *sgttyb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700778{
779 int retval;
780 struct sgttyb tmp;
Alan Coxedc6afc2006-12-08 02:38:44 -0800781 struct ktermios termios;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700782
783 retval = tty_check_change(tty);
784 if (retval)
785 return retval;
Alan Cox355d95a12008-02-08 04:18:48 -0800786
Linus Torvalds1da177e2005-04-16 15:20:36 -0700787 if (copy_from_user(&tmp, sgttyb, sizeof(tmp)))
788 return -EFAULT;
789
Arjan van de Ven5785c952006-09-29 02:00:43 -0700790 mutex_lock(&tty->termios_mutex);
Jiri Slaby68043962007-07-15 23:40:18 -0700791 termios = *tty->termios;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700792 termios.c_cc[VERASE] = tmp.sg_erase;
793 termios.c_cc[VKILL] = tmp.sg_kill;
794 set_sgflags(&termios, tmp.sg_flags);
Alan Coxedc6afc2006-12-08 02:38:44 -0800795 /* Try and encode into Bfoo format */
796#ifdef BOTHER
Alan Cox355d95a12008-02-08 04:18:48 -0800797 tty_termios_encode_baud_rate(&termios, termios.c_ispeed,
798 termios.c_ospeed);
Alan Coxedc6afc2006-12-08 02:38:44 -0800799#endif
Arjan van de Ven5785c952006-09-29 02:00:43 -0700800 mutex_unlock(&tty->termios_mutex);
Alan Cox8d075b12011-02-14 16:27:53 +0000801 tty_set_termios(tty, &termios);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700802 return 0;
803}
804#endif
805
806#ifdef TIOCGETC
Alan Cox355d95a12008-02-08 04:18:48 -0800807static int get_tchars(struct tty_struct *tty, struct tchars __user *tchars)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700808{
809 struct tchars tmp;
810
Alan Cox978e5952008-04-30 00:53:59 -0700811 mutex_lock(&tty->termios_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700812 tmp.t_intrc = tty->termios->c_cc[VINTR];
813 tmp.t_quitc = tty->termios->c_cc[VQUIT];
814 tmp.t_startc = tty->termios->c_cc[VSTART];
815 tmp.t_stopc = tty->termios->c_cc[VSTOP];
816 tmp.t_eofc = tty->termios->c_cc[VEOF];
817 tmp.t_brkc = tty->termios->c_cc[VEOL2]; /* what is brkc anyway? */
Alan Cox978e5952008-04-30 00:53:59 -0700818 mutex_unlock(&tty->termios_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700819 return copy_to_user(tchars, &tmp, sizeof(tmp)) ? -EFAULT : 0;
820}
821
Alan Cox355d95a12008-02-08 04:18:48 -0800822static int set_tchars(struct tty_struct *tty, struct tchars __user *tchars)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700823{
824 struct tchars tmp;
825
826 if (copy_from_user(&tmp, tchars, sizeof(tmp)))
827 return -EFAULT;
Alan Cox978e5952008-04-30 00:53:59 -0700828 mutex_lock(&tty->termios_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700829 tty->termios->c_cc[VINTR] = tmp.t_intrc;
830 tty->termios->c_cc[VQUIT] = tmp.t_quitc;
831 tty->termios->c_cc[VSTART] = tmp.t_startc;
832 tty->termios->c_cc[VSTOP] = tmp.t_stopc;
833 tty->termios->c_cc[VEOF] = tmp.t_eofc;
834 tty->termios->c_cc[VEOL2] = tmp.t_brkc; /* what is brkc anyway? */
Alan Cox978e5952008-04-30 00:53:59 -0700835 mutex_unlock(&tty->termios_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700836 return 0;
837}
838#endif
839
840#ifdef TIOCGLTC
Alan Cox355d95a12008-02-08 04:18:48 -0800841static int get_ltchars(struct tty_struct *tty, struct ltchars __user *ltchars)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700842{
843 struct ltchars tmp;
844
Alan Cox978e5952008-04-30 00:53:59 -0700845 mutex_lock(&tty->termios_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700846 tmp.t_suspc = tty->termios->c_cc[VSUSP];
Alan Cox355d95a12008-02-08 04:18:48 -0800847 /* what is dsuspc anyway? */
848 tmp.t_dsuspc = tty->termios->c_cc[VSUSP];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700849 tmp.t_rprntc = tty->termios->c_cc[VREPRINT];
Alan Cox355d95a12008-02-08 04:18:48 -0800850 /* what is flushc anyway? */
851 tmp.t_flushc = tty->termios->c_cc[VEOL2];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700852 tmp.t_werasc = tty->termios->c_cc[VWERASE];
853 tmp.t_lnextc = tty->termios->c_cc[VLNEXT];
Alan Cox978e5952008-04-30 00:53:59 -0700854 mutex_unlock(&tty->termios_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700855 return copy_to_user(ltchars, &tmp, sizeof(tmp)) ? -EFAULT : 0;
856}
857
Alan Cox355d95a12008-02-08 04:18:48 -0800858static int set_ltchars(struct tty_struct *tty, struct ltchars __user *ltchars)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700859{
860 struct ltchars tmp;
861
862 if (copy_from_user(&tmp, ltchars, sizeof(tmp)))
863 return -EFAULT;
864
Alan Cox978e5952008-04-30 00:53:59 -0700865 mutex_lock(&tty->termios_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700866 tty->termios->c_cc[VSUSP] = tmp.t_suspc;
Alan Cox355d95a12008-02-08 04:18:48 -0800867 /* what is dsuspc anyway? */
868 tty->termios->c_cc[VEOL2] = tmp.t_dsuspc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700869 tty->termios->c_cc[VREPRINT] = tmp.t_rprntc;
Alan Cox355d95a12008-02-08 04:18:48 -0800870 /* what is flushc anyway? */
871 tty->termios->c_cc[VEOL2] = tmp.t_flushc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700872 tty->termios->c_cc[VWERASE] = tmp.t_werasc;
873 tty->termios->c_cc[VLNEXT] = tmp.t_lnextc;
Alan Cox978e5952008-04-30 00:53:59 -0700874 mutex_unlock(&tty->termios_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700875 return 0;
876}
877#endif
878
Alan Coxaf9b8972006-08-27 01:24:01 -0700879/**
880 * send_prio_char - send priority character
881 *
882 * Send a high priority character to the tty even if stopped
883 *
Alan Cox5f412b22006-09-29 02:01:40 -0700884 * Locking: none for xchar method, write ordering for write method.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700885 */
Alan Coxaf9b8972006-08-27 01:24:01 -0700886
Alan Cox5f412b22006-09-29 02:01:40 -0700887static int send_prio_char(struct tty_struct *tty, char ch)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700888{
889 int was_stopped = tty->stopped;
890
Alan Coxf34d7a52008-04-30 00:54:13 -0700891 if (tty->ops->send_xchar) {
892 tty->ops->send_xchar(tty, ch);
Alan Cox5f412b22006-09-29 02:01:40 -0700893 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700894 }
Alan Cox5f412b22006-09-29 02:01:40 -0700895
Alan Cox9c1729d2007-07-15 23:39:43 -0700896 if (tty_write_lock(tty, 0) < 0)
Alan Cox5f412b22006-09-29 02:01:40 -0700897 return -ERESTARTSYS;
898
Linus Torvalds1da177e2005-04-16 15:20:36 -0700899 if (was_stopped)
900 start_tty(tty);
Alan Coxf34d7a52008-04-30 00:54:13 -0700901 tty->ops->write(tty, &ch, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700902 if (was_stopped)
903 stop_tty(tty);
Alan Cox9c1729d2007-07-15 23:39:43 -0700904 tty_write_unlock(tty);
Alan Cox5f412b22006-09-29 02:01:40 -0700905 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700906}
907
Alan Cox0fc00e22007-11-07 01:24:56 -0800908/**
Alan Cox1c2630c2008-04-30 00:53:34 -0700909 * tty_change_softcar - carrier change ioctl helper
910 * @tty: tty to update
911 * @arg: enable/disable CLOCAL
912 *
913 * Perform a change to the CLOCAL state and call into the driver
914 * layer to make it visible. All done with the termios mutex
915 */
916
917static int tty_change_softcar(struct tty_struct *tty, int arg)
918{
919 int ret = 0;
920 int bit = arg ? CLOCAL : 0;
Alan Coxf34d7a52008-04-30 00:54:13 -0700921 struct ktermios old;
Alan Cox1c2630c2008-04-30 00:53:34 -0700922
923 mutex_lock(&tty->termios_mutex);
Alan Coxf34d7a52008-04-30 00:54:13 -0700924 old = *tty->termios;
Alan Cox1c2630c2008-04-30 00:53:34 -0700925 tty->termios->c_cflag &= ~CLOCAL;
926 tty->termios->c_cflag |= bit;
Alan Coxf34d7a52008-04-30 00:54:13 -0700927 if (tty->ops->set_termios)
928 tty->ops->set_termios(tty, &old);
Alan Cox1c2630c2008-04-30 00:53:34 -0700929 if ((tty->termios->c_cflag & CLOCAL) != bit)
930 ret = -EINVAL;
931 mutex_unlock(&tty->termios_mutex);
932 return ret;
933}
934
935/**
Alan Cox0fc00e22007-11-07 01:24:56 -0800936 * tty_mode_ioctl - mode related ioctls
937 * @tty: tty for the ioctl
938 * @file: file pointer for the tty
939 * @cmd: command
940 * @arg: ioctl argument
941 *
942 * Perform non line discipline specific mode control ioctls. This
943 * is designed to be called by line disciplines to ensure they provide
944 * consistent mode setting.
945 */
946
Alan Cox355d95a12008-02-08 04:18:48 -0800947int tty_mode_ioctl(struct tty_struct *tty, struct file *file,
Alan Cox0fc00e22007-11-07 01:24:56 -0800948 unsigned int cmd, unsigned long arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700949{
Alan Cox355d95a12008-02-08 04:18:48 -0800950 struct tty_struct *real_tty;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700951 void __user *p = (void __user *)arg;
Alan Cox8f520022008-10-13 10:38:46 +0100952 int ret = 0;
Alan Cox26a2e202009-06-11 14:03:13 +0100953 struct ktermios kterm;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700954
Alan Cox8d075b12011-02-14 16:27:53 +0000955 BUG_ON(file == NULL);
956
Linus Torvalds1da177e2005-04-16 15:20:36 -0700957 if (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
958 tty->driver->subtype == PTY_TYPE_MASTER)
959 real_tty = tty->link;
960 else
961 real_tty = tty;
962
963 switch (cmd) {
964#ifdef TIOCGETP
Alan Cox355d95a12008-02-08 04:18:48 -0800965 case TIOCGETP:
966 return get_sgttyb(real_tty, (struct sgttyb __user *) arg);
967 case TIOCSETP:
968 case TIOCSETN:
969 return set_sgttyb(real_tty, (struct sgttyb __user *) arg);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700970#endif
971#ifdef TIOCGETC
Alan Cox355d95a12008-02-08 04:18:48 -0800972 case TIOCGETC:
973 return get_tchars(real_tty, p);
974 case TIOCSETC:
975 return set_tchars(real_tty, p);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700976#endif
977#ifdef TIOCGLTC
Alan Cox355d95a12008-02-08 04:18:48 -0800978 case TIOCGLTC:
979 return get_ltchars(real_tty, p);
980 case TIOCSLTC:
981 return set_ltchars(real_tty, p);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700982#endif
Alan Cox355d95a12008-02-08 04:18:48 -0800983 case TCSETSF:
984 return set_termios(real_tty, p, TERMIOS_FLUSH | TERMIOS_WAIT | TERMIOS_OLD);
985 case TCSETSW:
986 return set_termios(real_tty, p, TERMIOS_WAIT | TERMIOS_OLD);
987 case TCSETS:
988 return set_termios(real_tty, p, TERMIOS_OLD);
Alan Coxedc6afc2006-12-08 02:38:44 -0800989#ifndef TCGETS2
Alan Cox355d95a12008-02-08 04:18:48 -0800990 case TCGETS:
Alan Cox26a2e202009-06-11 14:03:13 +0100991 copy_termios(real_tty, &kterm);
992 if (kernel_termios_to_user_termios((struct termios __user *)arg, &kterm))
Alan Cox8f520022008-10-13 10:38:46 +0100993 ret = -EFAULT;
Alan Cox8f520022008-10-13 10:38:46 +0100994 return ret;
Alan Coxedc6afc2006-12-08 02:38:44 -0800995#else
Alan Cox355d95a12008-02-08 04:18:48 -0800996 case TCGETS:
Alan Cox26a2e202009-06-11 14:03:13 +0100997 copy_termios(real_tty, &kterm);
998 if (kernel_termios_to_user_termios_1((struct termios __user *)arg, &kterm))
Alan Cox8f520022008-10-13 10:38:46 +0100999 ret = -EFAULT;
Alan Cox8f520022008-10-13 10:38:46 +01001000 return ret;
Alan Cox355d95a12008-02-08 04:18:48 -08001001 case TCGETS2:
Alan Cox26a2e202009-06-11 14:03:13 +01001002 copy_termios(real_tty, &kterm);
1003 if (kernel_termios_to_user_termios((struct termios2 __user *)arg, &kterm))
Alan Cox8f520022008-10-13 10:38:46 +01001004 ret = -EFAULT;
Alan Cox8f520022008-10-13 10:38:46 +01001005 return ret;
Alan Cox355d95a12008-02-08 04:18:48 -08001006 case TCSETSF2:
1007 return set_termios(real_tty, p, TERMIOS_FLUSH | TERMIOS_WAIT);
1008 case TCSETSW2:
1009 return set_termios(real_tty, p, TERMIOS_WAIT);
1010 case TCSETS2:
1011 return set_termios(real_tty, p, 0);
Alan Coxedc6afc2006-12-08 02:38:44 -08001012#endif
Alan Cox355d95a12008-02-08 04:18:48 -08001013 case TCGETA:
1014 return get_termio(real_tty, p);
1015 case TCSETAF:
1016 return set_termios(real_tty, p, TERMIOS_FLUSH | TERMIOS_WAIT | TERMIOS_TERMIO);
1017 case TCSETAW:
1018 return set_termios(real_tty, p, TERMIOS_WAIT | TERMIOS_TERMIO);
1019 case TCSETA:
1020 return set_termios(real_tty, p, TERMIOS_TERMIO);
Alan Cox0fc00e22007-11-07 01:24:56 -08001021#ifndef TCGETS2
Alan Cox355d95a12008-02-08 04:18:48 -08001022 case TIOCGLCKTRMIOS:
Alan Cox26a2e202009-06-11 14:03:13 +01001023 copy_termios_locked(real_tty, &kterm);
1024 if (kernel_termios_to_user_termios((struct termios __user *)arg, &kterm))
Alan Cox8f520022008-10-13 10:38:46 +01001025 ret = -EFAULT;
Alan Cox8f520022008-10-13 10:38:46 +01001026 return ret;
Alan Cox355d95a12008-02-08 04:18:48 -08001027 case TIOCSLCKTRMIOS:
1028 if (!capable(CAP_SYS_ADMIN))
1029 return -EPERM;
Alan Cox26a2e202009-06-11 14:03:13 +01001030 copy_termios_locked(real_tty, &kterm);
1031 if (user_termios_to_kernel_termios(&kterm,
Alan Cox355d95a12008-02-08 04:18:48 -08001032 (struct termios __user *) arg))
Alan Cox26a2e202009-06-11 14:03:13 +01001033 return -EFAULT;
1034 mutex_lock(&real_tty->termios_mutex);
1035 memcpy(real_tty->termios_locked, &kterm, sizeof(struct ktermios));
Alan Cox8f520022008-10-13 10:38:46 +01001036 mutex_unlock(&real_tty->termios_mutex);
Alan Cox26a2e202009-06-11 14:03:13 +01001037 return 0;
Alan Cox0fc00e22007-11-07 01:24:56 -08001038#else
Alan Cox355d95a12008-02-08 04:18:48 -08001039 case TIOCGLCKTRMIOS:
Alan Cox26a2e202009-06-11 14:03:13 +01001040 copy_termios_locked(real_tty, &kterm);
1041 if (kernel_termios_to_user_termios_1((struct termios __user *)arg, &kterm))
Alan Cox8f520022008-10-13 10:38:46 +01001042 ret = -EFAULT;
Alan Cox8f520022008-10-13 10:38:46 +01001043 return ret;
Alan Cox355d95a12008-02-08 04:18:48 -08001044 case TIOCSLCKTRMIOS:
1045 if (!capable(CAP_SYS_ADMIN))
Alan Cox26a2e202009-06-11 14:03:13 +01001046 return -EPERM;
1047 copy_termios_locked(real_tty, &kterm);
1048 if (user_termios_to_kernel_termios_1(&kterm,
Alan Cox355d95a12008-02-08 04:18:48 -08001049 (struct termios __user *) arg))
Alan Cox26a2e202009-06-11 14:03:13 +01001050 return -EFAULT;
1051 mutex_lock(&real_tty->termios_mutex);
1052 memcpy(real_tty->termios_locked, &kterm, sizeof(struct ktermios));
Alan Cox8f520022008-10-13 10:38:46 +01001053 mutex_unlock(&real_tty->termios_mutex);
1054 return ret;
Alan Cox0fc00e22007-11-07 01:24:56 -08001055#endif
Alan Cox1d65b4a2008-10-13 10:38:18 +01001056#ifdef TCGETX
Mike Frysinger5dca6072009-06-16 17:01:02 +01001057 case TCGETX: {
1058 struct termiox ktermx;
Alan Cox1d65b4a2008-10-13 10:38:18 +01001059 if (real_tty->termiox == NULL)
1060 return -EINVAL;
Alan Cox8f520022008-10-13 10:38:46 +01001061 mutex_lock(&real_tty->termios_mutex);
Alan Cox26a2e202009-06-11 14:03:13 +01001062 memcpy(&ktermx, real_tty->termiox, sizeof(struct termiox));
Alan Cox8f520022008-10-13 10:38:46 +01001063 mutex_unlock(&real_tty->termios_mutex);
Alan Cox26a2e202009-06-11 14:03:13 +01001064 if (copy_to_user(p, &ktermx, sizeof(struct termiox)))
1065 ret = -EFAULT;
Alan Cox8f520022008-10-13 10:38:46 +01001066 return ret;
Mike Frysinger5dca6072009-06-16 17:01:02 +01001067 }
Alan Cox1d65b4a2008-10-13 10:38:18 +01001068 case TCSETX:
1069 return set_termiox(real_tty, p, 0);
1070 case TCSETXW:
1071 return set_termiox(real_tty, p, TERMIOS_WAIT);
1072 case TCSETXF:
1073 return set_termiox(real_tty, p, TERMIOS_FLUSH);
1074#endif
Alan Cox355d95a12008-02-08 04:18:48 -08001075 case TIOCGSOFTCAR:
Alan Cox26a2e202009-06-11 14:03:13 +01001076 copy_termios(real_tty, &kterm);
1077 ret = put_user((kterm.c_cflag & CLOCAL) ? 1 : 0,
Alan Cox355d95a12008-02-08 04:18:48 -08001078 (int __user *)arg);
Alan Cox8f520022008-10-13 10:38:46 +01001079 return ret;
Alan Cox355d95a12008-02-08 04:18:48 -08001080 case TIOCSSOFTCAR:
1081 if (get_user(arg, (unsigned int __user *) arg))
1082 return -EFAULT;
Alan Coxf753f322008-08-26 19:52:47 +01001083 return tty_change_softcar(real_tty, arg);
Alan Cox355d95a12008-02-08 04:18:48 -08001084 default:
1085 return -ENOIOCTLCMD;
Alan Cox0fc00e22007-11-07 01:24:56 -08001086 }
1087}
Alan Cox0fc00e22007-11-07 01:24:56 -08001088EXPORT_SYMBOL_GPL(tty_mode_ioctl);
1089
1090int tty_perform_flush(struct tty_struct *tty, unsigned long arg)
1091{
1092 struct tty_ldisc *ld;
1093 int retval = tty_check_change(tty);
1094 if (retval)
1095 return retval;
1096
Alan Coxc0253ee2009-01-15 13:30:25 +00001097 ld = tty_ldisc_ref_wait(tty);
Alan Cox0fc00e22007-11-07 01:24:56 -08001098 switch (arg) {
1099 case TCIFLUSH:
Alan Coxa352def2008-07-16 21:53:12 +01001100 if (ld && ld->ops->flush_buffer)
1101 ld->ops->flush_buffer(tty);
Alan Cox0fc00e22007-11-07 01:24:56 -08001102 break;
1103 case TCIOFLUSH:
Alan Coxa352def2008-07-16 21:53:12 +01001104 if (ld && ld->ops->flush_buffer)
1105 ld->ops->flush_buffer(tty);
Alan Cox0fc00e22007-11-07 01:24:56 -08001106 /* fall through */
1107 case TCOFLUSH:
Alan Coxf34d7a52008-04-30 00:54:13 -07001108 tty_driver_flush_buffer(tty);
Alan Cox0fc00e22007-11-07 01:24:56 -08001109 break;
1110 default:
1111 tty_ldisc_deref(ld);
1112 return -EINVAL;
1113 }
1114 tty_ldisc_deref(ld);
1115 return 0;
1116}
Alan Cox0fc00e22007-11-07 01:24:56 -08001117EXPORT_SYMBOL_GPL(tty_perform_flush);
1118
Alan Cox47afa7a2008-10-13 10:44:17 +01001119int n_tty_ioctl_helper(struct tty_struct *tty, struct file *file,
Alan Cox0fc00e22007-11-07 01:24:56 -08001120 unsigned int cmd, unsigned long arg)
1121{
Alan Cox04f378b2008-04-30 00:53:29 -07001122 unsigned long flags;
Alan Cox0fc00e22007-11-07 01:24:56 -08001123 int retval;
1124
Alan Cox0fc00e22007-11-07 01:24:56 -08001125 switch (cmd) {
Alan Cox355d95a12008-02-08 04:18:48 -08001126 case TCXONC:
1127 retval = tty_check_change(tty);
1128 if (retval)
1129 return retval;
1130 switch (arg) {
1131 case TCOOFF:
1132 if (!tty->flow_stopped) {
1133 tty->flow_stopped = 1;
1134 stop_tty(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001135 }
Alan Cox355d95a12008-02-08 04:18:48 -08001136 break;
1137 case TCOON:
1138 if (tty->flow_stopped) {
1139 tty->flow_stopped = 0;
1140 start_tty(tty);
1141 }
1142 break;
1143 case TCIOFF:
1144 if (STOP_CHAR(tty) != __DISABLED_CHAR)
1145 return send_prio_char(tty, STOP_CHAR(tty));
1146 break;
1147 case TCION:
1148 if (START_CHAR(tty) != __DISABLED_CHAR)
1149 return send_prio_char(tty, START_CHAR(tty));
1150 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001151 default:
Alan Cox355d95a12008-02-08 04:18:48 -08001152 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001153 }
Alan Cox355d95a12008-02-08 04:18:48 -08001154 return 0;
1155 case TCFLSH:
1156 return tty_perform_flush(tty, arg);
Alan Cox355d95a12008-02-08 04:18:48 -08001157 case TIOCPKT:
1158 {
1159 int pktmode;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001160
Alan Cox355d95a12008-02-08 04:18:48 -08001161 if (tty->driver->type != TTY_DRIVER_TYPE_PTY ||
1162 tty->driver->subtype != PTY_TYPE_MASTER)
1163 return -ENOTTY;
1164 if (get_user(pktmode, (int __user *) arg))
1165 return -EFAULT;
Alan Cox04f378b2008-04-30 00:53:29 -07001166 spin_lock_irqsave(&tty->ctrl_lock, flags);
Alan Cox355d95a12008-02-08 04:18:48 -08001167 if (pktmode) {
1168 if (!tty->packet) {
1169 tty->packet = 1;
1170 tty->link->ctrl_status = 0;
1171 }
1172 } else
1173 tty->packet = 0;
Alan Cox04f378b2008-04-30 00:53:29 -07001174 spin_unlock_irqrestore(&tty->ctrl_lock, flags);
Alan Cox355d95a12008-02-08 04:18:48 -08001175 return 0;
1176 }
1177 default:
1178 /* Try the mode commands */
1179 return tty_mode_ioctl(tty, file, cmd, arg);
1180 }
1181}
Alan Cox47afa7a2008-10-13 10:44:17 +01001182EXPORT_SYMBOL(n_tty_ioctl_helper);
Thomas Meyer8193c422011-10-05 23:13:13 +02001183
1184#ifdef CONFIG_COMPAT
1185long n_tty_compat_ioctl_helper(struct tty_struct *tty, struct file *file,
1186 unsigned int cmd, unsigned long arg)
1187{
1188 switch (cmd) {
1189 case TIOCGLCKTRMIOS:
1190 case TIOCSLCKTRMIOS:
1191 return tty_mode_ioctl(tty, file, cmd, (unsigned long) compat_ptr(arg));
1192 default:
1193 return -ENOIOCTLCMD;
1194 }
1195}
1196EXPORT_SYMBOL(n_tty_compat_ioctl_helper);
1197#endif
1198