Remove CONFIG_VT_UNICODE
[linux-2.6-block.git] / drivers / char / tty_ioctl.c
... / ...
CommitLineData
1/*
2 * linux/drivers/char/tty_ioctl.c
3 *
4 * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds
5 *
6 * Modified by Fred N. van Kempen, 01/29/93, to add line disciplines
7 * which can be dynamically activated and de-activated by the line
8 * discipline handling modules (like SLIP).
9 */
10
11#include <linux/types.h>
12#include <linux/termios.h>
13#include <linux/errno.h>
14#include <linux/sched.h>
15#include <linux/kernel.h>
16#include <linux/major.h>
17#include <linux/tty.h>
18#include <linux/fcntl.h>
19#include <linux/string.h>
20#include <linux/mm.h>
21#include <linux/module.h>
22#include <linux/bitops.h>
23#include <linux/mutex.h>
24
25#include <asm/io.h>
26#include <asm/uaccess.h>
27#include <asm/system.h>
28
29#undef TTY_DEBUG_WAIT_UNTIL_SENT
30
31#undef DEBUG
32
33/*
34 * Internal flag options for termios setting behavior
35 */
36#define TERMIOS_FLUSH 1
37#define TERMIOS_WAIT 2
38#define TERMIOS_TERMIO 4
39#define TERMIOS_OLD 8
40
41
42/**
43 * tty_wait_until_sent - wait for I/O to finish
44 * @tty: tty we are waiting for
45 * @timeout: how long we will wait
46 *
47 * Wait for characters pending in a tty driver to hit the wire, or
48 * for a timeout to occur (eg due to flow control)
49 *
50 * Locking: none
51 */
52
53void tty_wait_until_sent(struct tty_struct * tty, long timeout)
54{
55#ifdef TTY_DEBUG_WAIT_UNTIL_SENT
56 char buf[64];
57
58 printk(KERN_DEBUG "%s wait until sent...\n", tty_name(tty, buf));
59#endif
60 if (!tty->driver->chars_in_buffer)
61 return;
62 if (!timeout)
63 timeout = MAX_SCHEDULE_TIMEOUT;
64 if (wait_event_interruptible_timeout(tty->write_wait,
65 !tty->driver->chars_in_buffer(tty), timeout))
66 return;
67 if (tty->driver->wait_until_sent)
68 tty->driver->wait_until_sent(tty, timeout);
69}
70
71EXPORT_SYMBOL(tty_wait_until_sent);
72
73static void unset_locked_termios(struct ktermios *termios,
74 struct ktermios *old,
75 struct ktermios *locked)
76{
77 int i;
78
79#define NOSET_MASK(x,y,z) (x = ((x) & ~(z)) | ((y) & (z)))
80
81 if (!locked) {
82 printk(KERN_WARNING "Warning?!? termios_locked is NULL.\n");
83 return;
84 }
85
86 NOSET_MASK(termios->c_iflag, old->c_iflag, locked->c_iflag);
87 NOSET_MASK(termios->c_oflag, old->c_oflag, locked->c_oflag);
88 NOSET_MASK(termios->c_cflag, old->c_cflag, locked->c_cflag);
89 NOSET_MASK(termios->c_lflag, old->c_lflag, locked->c_lflag);
90 termios->c_line = locked->c_line ? old->c_line : termios->c_line;
91 for (i=0; i < NCCS; i++)
92 termios->c_cc[i] = locked->c_cc[i] ?
93 old->c_cc[i] : termios->c_cc[i];
94 /* FIXME: What should we do for i/ospeed */
95}
96
97/*
98 * Routine which returns the baud rate of the tty
99 *
100 * Note that the baud_table needs to be kept in sync with the
101 * include/asm/termbits.h file.
102 */
103static const speed_t baud_table[] = {
104 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
105 9600, 19200, 38400, 57600, 115200, 230400, 460800,
106#ifdef __sparc__
107 76800, 153600, 307200, 614400, 921600
108#else
109 500000, 576000, 921600, 1000000, 1152000, 1500000, 2000000,
110 2500000, 3000000, 3500000, 4000000
111#endif
112};
113
114#ifndef __sparc__
115static const tcflag_t baud_bits[] = {
116 B0, B50, B75, B110, B134, B150, B200, B300, B600,
117 B1200, B1800, B2400, B4800, B9600, B19200, B38400,
118 B57600, B115200, B230400, B460800, B500000, B576000,
119 B921600, B1000000, B1152000, B1500000, B2000000, B2500000,
120 B3000000, B3500000, B4000000
121};
122#else
123static const tcflag_t baud_bits[] = {
124 B0, B50, B75, B110, B134, B150, B200, B300, B600,
125 B1200, B1800, B2400, B4800, B9600, B19200, B38400,
126 B57600, B115200, B230400, B460800, B76800, B153600,
127 B307200, B614400, B921600
128};
129#endif
130
131static int n_baud_table = ARRAY_SIZE(baud_table);
132
133/**
134 * tty_termios_baud_rate
135 * @termios: termios structure
136 *
137 * Convert termios baud rate data into a speed. This should be called
138 * with the termios lock held if this termios is a terminal termios
139 * structure. May change the termios data. Device drivers can call this
140 * function but should use ->c_[io]speed directly as they are updated.
141 *
142 * Locking: none
143 */
144
145speed_t tty_termios_baud_rate(struct ktermios *termios)
146{
147 unsigned int cbaud;
148
149 cbaud = termios->c_cflag & CBAUD;
150
151#ifdef BOTHER
152 /* Magic token for arbitary speed via c_ispeed/c_ospeed */
153 if (cbaud == BOTHER)
154 return termios->c_ospeed;
155#endif
156 if (cbaud & CBAUDEX) {
157 cbaud &= ~CBAUDEX;
158
159 if (cbaud < 1 || cbaud + 15 > n_baud_table)
160 termios->c_cflag &= ~CBAUDEX;
161 else
162 cbaud += 15;
163 }
164 return baud_table[cbaud];
165}
166
167EXPORT_SYMBOL(tty_termios_baud_rate);
168
169/**
170 * tty_termios_input_baud_rate
171 * @termios: termios structure
172 *
173 * Convert termios baud rate data into a speed. This should be called
174 * with the termios lock held if this termios is a terminal termios
175 * structure. May change the termios data. Device drivers can call this
176 * function but should use ->c_[io]speed directly as they are updated.
177 *
178 * Locking: none
179 */
180
181speed_t tty_termios_input_baud_rate(struct ktermios *termios)
182{
183#ifdef IBSHIFT
184 unsigned int cbaud = (termios->c_cflag >> IBSHIFT) & CBAUD;
185
186 if (cbaud == B0)
187 return tty_termios_baud_rate(termios);
188
189 /* Magic token for arbitary speed via c_ispeed*/
190 if (cbaud == BOTHER)
191 return termios->c_ispeed;
192
193 if (cbaud & CBAUDEX) {
194 cbaud &= ~CBAUDEX;
195
196 if (cbaud < 1 || cbaud + 15 > n_baud_table)
197 termios->c_cflag &= ~(CBAUDEX << IBSHIFT);
198 else
199 cbaud += 15;
200 }
201 return baud_table[cbaud];
202#else
203 return tty_termios_baud_rate(termios);
204#endif
205}
206
207EXPORT_SYMBOL(tty_termios_input_baud_rate);
208
209/**
210 * tty_termios_encode_baud_rate
211 * @termios: ktermios structure holding user requested state
212 * @ispeed: input speed
213 * @ospeed: output speed
214 *
215 * Encode the speeds set into the passed termios structure. This is
216 * used as a library helper for drivers os that they can report back
217 * the actual speed selected when it differs from the speed requested
218 *
219 * For maximal back compatibility with legacy SYS5/POSIX *nix behaviour
220 * we need to carefully set the bits when the user does not get the
221 * desired speed. We allow small margins and preserve as much of possible
222 * of the input intent to keep compatiblity.
223 *
224 * Locking: Caller should hold termios lock. This is already held
225 * when calling this function from the driver termios handler.
226 *
227 * The ifdefs deal with platforms whose owners have yet to update them
228 * and will all go away once this is done.
229 */
230
231void tty_termios_encode_baud_rate(struct ktermios *termios, speed_t ibaud, speed_t obaud)
232{
233 int i = 0;
234 int ifound = -1, ofound = -1;
235 int iclose = ibaud/50, oclose = obaud/50;
236 int ibinput = 0;
237
238 if (obaud == 0) /* CD dropped */
239 ibaud = 0; /* Clear ibaud to be sure */
240
241 termios->c_ispeed = ibaud;
242 termios->c_ospeed = obaud;
243
244#ifdef BOTHER
245 /* If the user asked for a precise weird speed give a precise weird
246 answer. If they asked for a Bfoo speed they many have problems
247 digesting non-exact replies so fuzz a bit */
248
249 if ((termios->c_cflag & CBAUD) == BOTHER)
250 oclose = 0;
251 if (((termios->c_cflag >> IBSHIFT) & CBAUD) == BOTHER)
252 iclose = 0;
253 if ((termios->c_cflag >> IBSHIFT) & CBAUD)
254 ibinput = 1; /* An input speed was specified */
255#endif
256 termios->c_cflag &= ~CBAUD;
257
258 /*
259 * Our goal is to find a close match to the standard baud rate
260 * returned. Walk the baud rate table and if we get a very close
261 * match then report back the speed as a POSIX Bxxxx value by
262 * preference
263 */
264
265 do {
266 if (obaud - oclose >= baud_table[i] && obaud + oclose <= baud_table[i]) {
267 termios->c_cflag |= baud_bits[i];
268 ofound = i;
269 }
270 if (ibaud - iclose >= baud_table[i] && ibaud + iclose <= baud_table[i]) {
271 if (ofound == i && !ibinput)
272 ifound = i;
273#ifdef IBSHIFT
274 else {
275 ifound = i;
276 termios->c_cflag |= (baud_bits[i] << IBSHIFT);
277 }
278#endif
279 }
280 } while (++i < n_baud_table);
281
282 /*
283 * If we found no match then use BOTHER if provided or warn
284 * the user their platform maintainer needs to wake up if not.
285 */
286#ifdef BOTHER
287 if (ofound == -1)
288 termios->c_cflag |= BOTHER;
289 /* Set exact input bits only if the input and output differ or the
290 user already did */
291 if (ifound == -1 && (ibaud != obaud || ibinput))
292 termios->c_cflag |= (BOTHER << IBSHIFT);
293#else
294 if (ifound == -1 || ofound == -1) {
295 static int warned;
296 if (!warned++)
297 printk(KERN_WARNING "tty: Unable to return correct "
298 "speed data as your architecture needs updating.\n");
299 }
300#endif
301}
302EXPORT_SYMBOL_GPL(tty_termios_encode_baud_rate);
303
304void tty_encode_baud_rate(struct tty_struct *tty, speed_t ibaud, speed_t obaud)
305{
306 tty_termios_encode_baud_rate(tty->termios, ibaud, obaud);
307}
308EXPORT_SYMBOL_GPL(tty_encode_baud_rate);
309
310/**
311 * tty_get_baud_rate - get tty bit rates
312 * @tty: tty to query
313 *
314 * Returns the baud rate as an integer for this terminal. The
315 * termios lock must be held by the caller and the terminal bit
316 * flags may be updated.
317 *
318 * Locking: none
319 */
320
321speed_t tty_get_baud_rate(struct tty_struct *tty)
322{
323 speed_t baud = tty_termios_baud_rate(tty->termios);
324
325 if (baud == 38400 && tty->alt_speed) {
326 if (!tty->warned) {
327 printk(KERN_WARNING "Use of setserial/setrocket to "
328 "set SPD_* flags is deprecated\n");
329 tty->warned = 1;
330 }
331 baud = tty->alt_speed;
332 }
333
334 return baud;
335}
336
337EXPORT_SYMBOL(tty_get_baud_rate);
338
339/**
340 * tty_termios_copy_hw - copy hardware settings
341 * @new: New termios
342 * @old: Old termios
343 *
344 * Propogate the hardware specific terminal setting bits from
345 * the old termios structure to the new one. This is used in cases
346 * where the hardware does not support reconfiguration or as a helper
347 * in some cases where only minimal reconfiguration is supported
348 */
349
350void tty_termios_copy_hw(struct ktermios *new, struct ktermios *old)
351{
352 /* The bits a dumb device handles in software. Smart devices need
353 to always provide a set_termios method */
354 new->c_cflag &= HUPCL | CREAD | CLOCAL;
355 new->c_cflag |= old->c_cflag & ~(HUPCL | CREAD | CLOCAL);
356 new->c_ispeed = old->c_ispeed;
357 new->c_ospeed = old->c_ospeed;
358}
359
360EXPORT_SYMBOL(tty_termios_copy_hw);
361
362/**
363 * change_termios - update termios values
364 * @tty: tty to update
365 * @new_termios: desired new value
366 *
367 * Perform updates to the termios values set on this terminal. There
368 * is a bit of layering violation here with n_tty in terms of the
369 * internal knowledge of this function.
370 *
371 * Locking: termios_sem
372 */
373
374static void change_termios(struct tty_struct * tty, struct ktermios * new_termios)
375{
376 int canon_change;
377 struct ktermios old_termios = *tty->termios;
378 struct tty_ldisc *ld;
379
380 /*
381 * Perform the actual termios internal changes under lock.
382 */
383
384
385 /* FIXME: we need to decide on some locking/ordering semantics
386 for the set_termios notification eventually */
387 mutex_lock(&tty->termios_mutex);
388
389 *tty->termios = *new_termios;
390 unset_locked_termios(tty->termios, &old_termios, tty->termios_locked);
391 canon_change = (old_termios.c_lflag ^ tty->termios->c_lflag) & ICANON;
392 if (canon_change) {
393 memset(&tty->read_flags, 0, sizeof tty->read_flags);
394 tty->canon_head = tty->read_tail;
395 tty->canon_data = 0;
396 tty->erasing = 0;
397 }
398
399 /* This bit should be in the ldisc code */
400 if (canon_change && !L_ICANON(tty) && tty->read_cnt)
401 /* Get characters left over from canonical mode. */
402 wake_up_interruptible(&tty->read_wait);
403
404 /* See if packet mode change of state. */
405 if (tty->link && tty->link->packet) {
406 int old_flow = ((old_termios.c_iflag & IXON) &&
407 (old_termios.c_cc[VSTOP] == '\023') &&
408 (old_termios.c_cc[VSTART] == '\021'));
409 int new_flow = (I_IXON(tty) &&
410 STOP_CHAR(tty) == '\023' &&
411 START_CHAR(tty) == '\021');
412 if (old_flow != new_flow) {
413 tty->ctrl_status &= ~(TIOCPKT_DOSTOP | TIOCPKT_NOSTOP);
414 if (new_flow)
415 tty->ctrl_status |= TIOCPKT_DOSTOP;
416 else
417 tty->ctrl_status |= TIOCPKT_NOSTOP;
418 wake_up_interruptible(&tty->link->read_wait);
419 }
420 }
421
422 if (tty->driver->set_termios)
423 (*tty->driver->set_termios)(tty, &old_termios);
424 else
425 tty_termios_copy_hw(tty->termios, &old_termios);
426
427 ld = tty_ldisc_ref(tty);
428 if (ld != NULL) {
429 if (ld->set_termios)
430 (ld->set_termios)(tty, &old_termios);
431 tty_ldisc_deref(ld);
432 }
433 mutex_unlock(&tty->termios_mutex);
434}
435
436/**
437 * set_termios - set termios values for a tty
438 * @tty: terminal device
439 * @arg: user data
440 * @opt: option information
441 *
442 * Helper function to prepare termios data and run neccessary other
443 * functions before using change_termios to do the actual changes.
444 *
445 * Locking:
446 * Called functions take ldisc and termios_sem locks
447 */
448
449static int set_termios(struct tty_struct * tty, void __user *arg, int opt)
450{
451 struct ktermios tmp_termios;
452 struct tty_ldisc *ld;
453 int retval = tty_check_change(tty);
454
455 if (retval)
456 return retval;
457
458 memcpy(&tmp_termios, tty->termios, sizeof(struct ktermios));
459
460 if (opt & TERMIOS_TERMIO) {
461 if (user_termio_to_kernel_termios(&tmp_termios,
462 (struct termio __user *)arg))
463 return -EFAULT;
464#ifdef TCGETS2
465 } else if (opt & TERMIOS_OLD) {
466 if (user_termios_to_kernel_termios_1(&tmp_termios,
467 (struct termios __user *)arg))
468 return -EFAULT;
469 } else {
470 if (user_termios_to_kernel_termios(&tmp_termios,
471 (struct termios2 __user *)arg))
472 return -EFAULT;
473 }
474#else
475 } else if (user_termios_to_kernel_termios(&tmp_termios,
476 (struct termios __user *)arg))
477 return -EFAULT;
478#endif
479
480 /* If old style Bfoo values are used then load c_ispeed/c_ospeed with the real speed
481 so its unconditionally usable */
482 tmp_termios.c_ispeed = tty_termios_input_baud_rate(&tmp_termios);
483 tmp_termios.c_ospeed = tty_termios_baud_rate(&tmp_termios);
484
485 ld = tty_ldisc_ref(tty);
486
487 if (ld != NULL) {
488 if ((opt & TERMIOS_FLUSH) && ld->flush_buffer)
489 ld->flush_buffer(tty);
490 tty_ldisc_deref(ld);
491 }
492
493 if (opt & TERMIOS_WAIT) {
494 tty_wait_until_sent(tty, 0);
495 if (signal_pending(current))
496 return -EINTR;
497 }
498
499 change_termios(tty, &tmp_termios);
500
501 /* FIXME: Arguably if tmp_termios == tty->termios AND the
502 actual requested termios was not tmp_termios then we may
503 want to return an error as no user requested change has
504 succeeded */
505 return 0;
506}
507
508static int get_termio(struct tty_struct * tty, struct termio __user * termio)
509{
510 if (kernel_termios_to_user_termio(termio, tty->termios))
511 return -EFAULT;
512 return 0;
513}
514
515static unsigned long inq_canon(struct tty_struct * tty)
516{
517 int nr, head, tail;
518
519 if (!tty->canon_data || !tty->read_buf)
520 return 0;
521 head = tty->canon_head;
522 tail = tty->read_tail;
523 nr = (head - tail) & (N_TTY_BUF_SIZE-1);
524 /* Skip EOF-chars.. */
525 while (head != tail) {
526 if (test_bit(tail, tty->read_flags) &&
527 tty->read_buf[tail] == __DISABLED_CHAR)
528 nr--;
529 tail = (tail+1) & (N_TTY_BUF_SIZE-1);
530 }
531 return nr;
532}
533
534#ifdef TIOCGETP
535/*
536 * These are deprecated, but there is limited support..
537 *
538 * The "sg_flags" translation is a joke..
539 */
540static int get_sgflags(struct tty_struct * tty)
541{
542 int flags = 0;
543
544 if (!(tty->termios->c_lflag & ICANON)) {
545 if (tty->termios->c_lflag & ISIG)
546 flags |= 0x02; /* cbreak */
547 else
548 flags |= 0x20; /* raw */
549 }
550 if (tty->termios->c_lflag & ECHO)
551 flags |= 0x08; /* echo */
552 if (tty->termios->c_oflag & OPOST)
553 if (tty->termios->c_oflag & ONLCR)
554 flags |= 0x10; /* crmod */
555 return flags;
556}
557
558static int get_sgttyb(struct tty_struct * tty, struct sgttyb __user * sgttyb)
559{
560 struct sgttyb tmp;
561
562 mutex_lock(&tty->termios_mutex);
563 tmp.sg_ispeed = tty->termios->c_ispeed;
564 tmp.sg_ospeed = tty->termios->c_ospeed;
565 tmp.sg_erase = tty->termios->c_cc[VERASE];
566 tmp.sg_kill = tty->termios->c_cc[VKILL];
567 tmp.sg_flags = get_sgflags(tty);
568 mutex_unlock(&tty->termios_mutex);
569
570 return copy_to_user(sgttyb, &tmp, sizeof(tmp)) ? -EFAULT : 0;
571}
572
573static void set_sgflags(struct ktermios * termios, int flags)
574{
575 termios->c_iflag = ICRNL | IXON;
576 termios->c_oflag = 0;
577 termios->c_lflag = ISIG | ICANON;
578 if (flags & 0x02) { /* cbreak */
579 termios->c_iflag = 0;
580 termios->c_lflag &= ~ICANON;
581 }
582 if (flags & 0x08) { /* echo */
583 termios->c_lflag |= ECHO | ECHOE | ECHOK |
584 ECHOCTL | ECHOKE | IEXTEN;
585 }
586 if (flags & 0x10) { /* crmod */
587 termios->c_oflag |= OPOST | ONLCR;
588 }
589 if (flags & 0x20) { /* raw */
590 termios->c_iflag = 0;
591 termios->c_lflag &= ~(ISIG | ICANON);
592 }
593 if (!(termios->c_lflag & ICANON)) {
594 termios->c_cc[VMIN] = 1;
595 termios->c_cc[VTIME] = 0;
596 }
597}
598
599/**
600 * set_sgttyb - set legacy terminal values
601 * @tty: tty structure
602 * @sgttyb: pointer to old style terminal structure
603 *
604 * Updates a terminal from the legacy BSD style terminal information
605 * structure.
606 *
607 * Locking: termios_sem
608 */
609
610static int set_sgttyb(struct tty_struct * tty, struct sgttyb __user * sgttyb)
611{
612 int retval;
613 struct sgttyb tmp;
614 struct ktermios termios;
615
616 retval = tty_check_change(tty);
617 if (retval)
618 return retval;
619
620 if (copy_from_user(&tmp, sgttyb, sizeof(tmp)))
621 return -EFAULT;
622
623 mutex_lock(&tty->termios_mutex);
624 termios = *tty->termios;
625 termios.c_cc[VERASE] = tmp.sg_erase;
626 termios.c_cc[VKILL] = tmp.sg_kill;
627 set_sgflags(&termios, tmp.sg_flags);
628 /* Try and encode into Bfoo format */
629#ifdef BOTHER
630 tty_termios_encode_baud_rate(&termios, termios.c_ispeed, termios.c_ospeed);
631#endif
632 mutex_unlock(&tty->termios_mutex);
633 change_termios(tty, &termios);
634 return 0;
635}
636#endif
637
638#ifdef TIOCGETC
639static int get_tchars(struct tty_struct * tty, struct tchars __user * tchars)
640{
641 struct tchars tmp;
642
643 tmp.t_intrc = tty->termios->c_cc[VINTR];
644 tmp.t_quitc = tty->termios->c_cc[VQUIT];
645 tmp.t_startc = tty->termios->c_cc[VSTART];
646 tmp.t_stopc = tty->termios->c_cc[VSTOP];
647 tmp.t_eofc = tty->termios->c_cc[VEOF];
648 tmp.t_brkc = tty->termios->c_cc[VEOL2]; /* what is brkc anyway? */
649 return copy_to_user(tchars, &tmp, sizeof(tmp)) ? -EFAULT : 0;
650}
651
652static int set_tchars(struct tty_struct * tty, struct tchars __user * tchars)
653{
654 struct tchars tmp;
655
656 if (copy_from_user(&tmp, tchars, sizeof(tmp)))
657 return -EFAULT;
658 tty->termios->c_cc[VINTR] = tmp.t_intrc;
659 tty->termios->c_cc[VQUIT] = tmp.t_quitc;
660 tty->termios->c_cc[VSTART] = tmp.t_startc;
661 tty->termios->c_cc[VSTOP] = tmp.t_stopc;
662 tty->termios->c_cc[VEOF] = tmp.t_eofc;
663 tty->termios->c_cc[VEOL2] = tmp.t_brkc; /* what is brkc anyway? */
664 return 0;
665}
666#endif
667
668#ifdef TIOCGLTC
669static int get_ltchars(struct tty_struct * tty, struct ltchars __user * ltchars)
670{
671 struct ltchars tmp;
672
673 tmp.t_suspc = tty->termios->c_cc[VSUSP];
674 tmp.t_dsuspc = tty->termios->c_cc[VSUSP]; /* what is dsuspc anyway? */
675 tmp.t_rprntc = tty->termios->c_cc[VREPRINT];
676 tmp.t_flushc = tty->termios->c_cc[VEOL2]; /* what is flushc anyway? */
677 tmp.t_werasc = tty->termios->c_cc[VWERASE];
678 tmp.t_lnextc = tty->termios->c_cc[VLNEXT];
679 return copy_to_user(ltchars, &tmp, sizeof(tmp)) ? -EFAULT : 0;
680}
681
682static int set_ltchars(struct tty_struct * tty, struct ltchars __user * ltchars)
683{
684 struct ltchars tmp;
685
686 if (copy_from_user(&tmp, ltchars, sizeof(tmp)))
687 return -EFAULT;
688
689 tty->termios->c_cc[VSUSP] = tmp.t_suspc;
690 tty->termios->c_cc[VEOL2] = tmp.t_dsuspc; /* what is dsuspc anyway? */
691 tty->termios->c_cc[VREPRINT] = tmp.t_rprntc;
692 tty->termios->c_cc[VEOL2] = tmp.t_flushc; /* what is flushc anyway? */
693 tty->termios->c_cc[VWERASE] = tmp.t_werasc;
694 tty->termios->c_cc[VLNEXT] = tmp.t_lnextc;
695 return 0;
696}
697#endif
698
699/**
700 * send_prio_char - send priority character
701 *
702 * Send a high priority character to the tty even if stopped
703 *
704 * Locking: none for xchar method, write ordering for write method.
705 */
706
707static int send_prio_char(struct tty_struct *tty, char ch)
708{
709 int was_stopped = tty->stopped;
710
711 if (tty->driver->send_xchar) {
712 tty->driver->send_xchar(tty, ch);
713 return 0;
714 }
715
716 if (tty_write_lock(tty, 0) < 0)
717 return -ERESTARTSYS;
718
719 if (was_stopped)
720 start_tty(tty);
721 tty->driver->write(tty, &ch, 1);
722 if (was_stopped)
723 stop_tty(tty);
724 tty_write_unlock(tty);
725 return 0;
726}
727
728int n_tty_ioctl(struct tty_struct * tty, struct file * file,
729 unsigned int cmd, unsigned long arg)
730{
731 struct tty_struct * real_tty;
732 void __user *p = (void __user *)arg;
733 int retval;
734 struct tty_ldisc *ld;
735
736 if (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
737 tty->driver->subtype == PTY_TYPE_MASTER)
738 real_tty = tty->link;
739 else
740 real_tty = tty;
741
742 switch (cmd) {
743#ifdef TIOCGETP
744 case TIOCGETP:
745 return get_sgttyb(real_tty, (struct sgttyb __user *) arg);
746 case TIOCSETP:
747 case TIOCSETN:
748 return set_sgttyb(real_tty, (struct sgttyb __user *) arg);
749#endif
750#ifdef TIOCGETC
751 case TIOCGETC:
752 return get_tchars(real_tty, p);
753 case TIOCSETC:
754 return set_tchars(real_tty, p);
755#endif
756#ifdef TIOCGLTC
757 case TIOCGLTC:
758 return get_ltchars(real_tty, p);
759 case TIOCSLTC:
760 return set_ltchars(real_tty, p);
761#endif
762 case TCSETSF:
763 return set_termios(real_tty, p, TERMIOS_FLUSH | TERMIOS_WAIT | TERMIOS_OLD);
764 case TCSETSW:
765 return set_termios(real_tty, p, TERMIOS_WAIT | TERMIOS_OLD);
766 case TCSETS:
767 return set_termios(real_tty, p, TERMIOS_OLD);
768#ifndef TCGETS2
769 case TCGETS:
770 if (kernel_termios_to_user_termios((struct termios __user *)arg, real_tty->termios))
771 return -EFAULT;
772 return 0;
773#else
774 case TCGETS:
775 if (kernel_termios_to_user_termios_1((struct termios __user *)arg, real_tty->termios))
776 return -EFAULT;
777 return 0;
778 case TCGETS2:
779 if (kernel_termios_to_user_termios((struct termios2 __user *)arg, real_tty->termios))
780 return -EFAULT;
781 return 0;
782 case TCSETSF2:
783 return set_termios(real_tty, p, TERMIOS_FLUSH | TERMIOS_WAIT);
784 case TCSETSW2:
785 return set_termios(real_tty, p, TERMIOS_WAIT);
786 case TCSETS2:
787 return set_termios(real_tty, p, 0);
788#endif
789 case TCGETA:
790 return get_termio(real_tty, p);
791 case TCSETAF:
792 return set_termios(real_tty, p, TERMIOS_FLUSH | TERMIOS_WAIT | TERMIOS_TERMIO);
793 case TCSETAW:
794 return set_termios(real_tty, p, TERMIOS_WAIT | TERMIOS_TERMIO);
795 case TCSETA:
796 return set_termios(real_tty, p, TERMIOS_TERMIO);
797 case TCXONC:
798 retval = tty_check_change(tty);
799 if (retval)
800 return retval;
801 switch (arg) {
802 case TCOOFF:
803 if (!tty->flow_stopped) {
804 tty->flow_stopped = 1;
805 stop_tty(tty);
806 }
807 break;
808 case TCOON:
809 if (tty->flow_stopped) {
810 tty->flow_stopped = 0;
811 start_tty(tty);
812 }
813 break;
814 case TCIOFF:
815 if (STOP_CHAR(tty) != __DISABLED_CHAR)
816 return send_prio_char(tty, STOP_CHAR(tty));
817 break;
818 case TCION:
819 if (START_CHAR(tty) != __DISABLED_CHAR)
820 return send_prio_char(tty, START_CHAR(tty));
821 break;
822 default:
823 return -EINVAL;
824 }
825 return 0;
826 case TCFLSH:
827 retval = tty_check_change(tty);
828 if (retval)
829 return retval;
830
831 ld = tty_ldisc_ref(tty);
832 switch (arg) {
833 case TCIFLUSH:
834 if (ld && ld->flush_buffer)
835 ld->flush_buffer(tty);
836 break;
837 case TCIOFLUSH:
838 if (ld && ld->flush_buffer)
839 ld->flush_buffer(tty);
840 /* fall through */
841 case TCOFLUSH:
842 if (tty->driver->flush_buffer)
843 tty->driver->flush_buffer(tty);
844 break;
845 default:
846 tty_ldisc_deref(ld);
847 return -EINVAL;
848 }
849 tty_ldisc_deref(ld);
850 return 0;
851 case TIOCOUTQ:
852 return put_user(tty->driver->chars_in_buffer ?
853 tty->driver->chars_in_buffer(tty) : 0,
854 (int __user *) arg);
855 case TIOCINQ:
856 retval = tty->read_cnt;
857 if (L_ICANON(tty))
858 retval = inq_canon(tty);
859 return put_user(retval, (unsigned int __user *) arg);
860#ifndef TCGETS2
861 case TIOCGLCKTRMIOS:
862 if (kernel_termios_to_user_termios((struct termios __user *)arg, real_tty->termios_locked))
863 return -EFAULT;
864 return 0;
865
866 case TIOCSLCKTRMIOS:
867 if (!capable(CAP_SYS_ADMIN))
868 return -EPERM;
869 if (user_termios_to_kernel_termios(real_tty->termios_locked, (struct termios __user *) arg))
870 return -EFAULT;
871 return 0;
872#else
873 case TIOCGLCKTRMIOS:
874 if (kernel_termios_to_user_termios_1((struct termios __user *)arg, real_tty->termios_locked))
875 return -EFAULT;
876 return 0;
877
878 case TIOCSLCKTRMIOS:
879 if (!capable(CAP_SYS_ADMIN))
880 return -EPERM;
881 if (user_termios_to_kernel_termios_1(real_tty->termios_locked, (struct termios __user *) arg))
882 return -EFAULT;
883 return 0;
884#endif
885
886 case TIOCPKT:
887 {
888 int pktmode;
889
890 if (tty->driver->type != TTY_DRIVER_TYPE_PTY ||
891 tty->driver->subtype != PTY_TYPE_MASTER)
892 return -ENOTTY;
893 if (get_user(pktmode, (int __user *) arg))
894 return -EFAULT;
895 if (pktmode) {
896 if (!tty->packet) {
897 tty->packet = 1;
898 tty->link->ctrl_status = 0;
899 }
900 } else
901 tty->packet = 0;
902 return 0;
903 }
904 case TIOCGSOFTCAR:
905 return put_user(C_CLOCAL(tty) ? 1 : 0, (int __user *)arg);
906 case TIOCSSOFTCAR:
907 if (get_user(arg, (unsigned int __user *) arg))
908 return -EFAULT;
909 mutex_lock(&tty->termios_mutex);
910 tty->termios->c_cflag =
911 ((tty->termios->c_cflag & ~CLOCAL) |
912 (arg ? CLOCAL : 0));
913 mutex_unlock(&tty->termios_mutex);
914 return 0;
915 default:
916 return -ENOIOCTLCMD;
917 }
918}
919
920EXPORT_SYMBOL(n_tty_ioctl);