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