2 * linux/drivers/char/tty_ioctl.c
4 * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds
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).
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>
21 #include <linux/module.h>
24 #include <asm/bitops.h>
25 #include <asm/uaccess.h>
26 #include <asm/system.h>
28 #undef TTY_DEBUG_WAIT_UNTIL_SENT
33 * Internal flag options for termios setting behavior
35 #define TERMIOS_FLUSH 1
36 #define TERMIOS_WAIT 2
37 #define TERMIOS_TERMIO 4
39 void tty_wait_until_sent(struct tty_struct
* tty
, long timeout
)
41 DECLARE_WAITQUEUE(wait
, current
);
43 #ifdef TTY_DEBUG_WAIT_UNTIL_SENT
46 printk(KERN_DEBUG
"%s wait until sent...\n", tty_name(tty
, buf
));
48 if (!tty
->driver
->chars_in_buffer
)
50 add_wait_queue(&tty
->write_wait
, &wait
);
52 timeout
= MAX_SCHEDULE_TIMEOUT
;
54 #ifdef TTY_DEBUG_WAIT_UNTIL_SENT
55 printk(KERN_DEBUG
"waiting %s...(%d)\n", tty_name(tty
, buf
),
56 tty
->driver
->chars_in_buffer(tty
));
58 set_current_state(TASK_INTERRUPTIBLE
);
59 if (signal_pending(current
))
61 if (!tty
->driver
->chars_in_buffer(tty
))
63 timeout
= schedule_timeout(timeout
);
65 if (tty
->driver
->wait_until_sent
)
66 tty
->driver
->wait_until_sent(tty
, timeout
);
68 set_current_state(TASK_RUNNING
);
69 remove_wait_queue(&tty
->write_wait
, &wait
);
72 EXPORT_SYMBOL(tty_wait_until_sent
);
74 static void unset_locked_termios(struct termios
*termios
,
76 struct termios
*locked
)
80 #define NOSET_MASK(x,y,z) (x = ((x) & ~(z)) | ((y) & (z)))
83 printk(KERN_WARNING
"Warning?!? termios_locked is NULL.\n");
87 NOSET_MASK(termios
->c_iflag
, old
->c_iflag
, locked
->c_iflag
);
88 NOSET_MASK(termios
->c_oflag
, old
->c_oflag
, locked
->c_oflag
);
89 NOSET_MASK(termios
->c_cflag
, old
->c_cflag
, locked
->c_cflag
);
90 NOSET_MASK(termios
->c_lflag
, old
->c_lflag
, locked
->c_lflag
);
91 termios
->c_line
= locked
->c_line
? old
->c_line
: termios
->c_line
;
92 for (i
=0; i
< NCCS
; i
++)
93 termios
->c_cc
[i
] = locked
->c_cc
[i
] ?
94 old
->c_cc
[i
] : termios
->c_cc
[i
];
97 static void change_termios(struct tty_struct
* tty
, struct termios
* new_termios
)
100 struct termios old_termios
= *tty
->termios
;
101 struct tty_ldisc
*ld
;
104 * Perform the actual termios internal changes under lock.
108 /* FIXME: we need to decide on some locking/ordering semantics
109 for the set_termios notification eventually */
110 down(&tty
->termios_sem
);
112 *tty
->termios
= *new_termios
;
113 unset_locked_termios(tty
->termios
, &old_termios
, tty
->termios_locked
);
114 canon_change
= (old_termios
.c_lflag
^ tty
->termios
->c_lflag
) & ICANON
;
116 memset(&tty
->read_flags
, 0, sizeof tty
->read_flags
);
117 tty
->canon_head
= tty
->read_tail
;
123 if (canon_change
&& !L_ICANON(tty
) && tty
->read_cnt
)
124 /* Get characters left over from canonical mode. */
125 wake_up_interruptible(&tty
->read_wait
);
127 /* See if packet mode change of state. */
129 if (tty
->link
&& tty
->link
->packet
) {
130 int old_flow
= ((old_termios
.c_iflag
& IXON
) &&
131 (old_termios
.c_cc
[VSTOP
] == '\023') &&
132 (old_termios
.c_cc
[VSTART
] == '\021'));
133 int new_flow
= (I_IXON(tty
) &&
134 STOP_CHAR(tty
) == '\023' &&
135 START_CHAR(tty
) == '\021');
136 if (old_flow
!= new_flow
) {
137 tty
->ctrl_status
&= ~(TIOCPKT_DOSTOP
| TIOCPKT_NOSTOP
);
139 tty
->ctrl_status
|= TIOCPKT_DOSTOP
;
141 tty
->ctrl_status
|= TIOCPKT_NOSTOP
;
142 wake_up_interruptible(&tty
->link
->read_wait
);
146 if (tty
->driver
->set_termios
)
147 (*tty
->driver
->set_termios
)(tty
, &old_termios
);
149 ld
= tty_ldisc_ref(tty
);
152 (ld
->set_termios
)(tty
, &old_termios
);
155 up(&tty
->termios_sem
);
158 static int set_termios(struct tty_struct
* tty
, void __user
*arg
, int opt
)
160 struct termios tmp_termios
;
161 struct tty_ldisc
*ld
;
162 int retval
= tty_check_change(tty
);
168 if (opt
& TERMIOS_TERMIO
) {
170 memcpy(&tmp_termios
, tty
->termios
, sizeof(struct termios
));
171 if (user_termio_to_kernel_termios(&tmp_termios
,
172 (struct termio __user
*)arg
))
177 if (user_termios_to_kernel_termios(&tmp_termios
,
178 (struct termios __user
*)arg
))
182 ld
= tty_ldisc_ref(tty
);
187 if ((opt
& TERMIOS_FLUSH
) && ld
->flush_buffer
)
188 ld
->flush_buffer(tty
);
193 if (opt
& TERMIOS_WAIT
) {
194 tty_wait_until_sent(tty
, 0);
196 if (signal_pending(current
))
201 change_termios(tty
, &tmp_termios
);
205 static int get_termio(struct tty_struct
* tty
, struct termio __user
* termio
)
207 if (kernel_termios_to_user_termio(termio
, tty
->termios
))
212 static unsigned long inq_canon(struct tty_struct
* tty
)
216 if (!tty
->canon_data
|| !tty
->read_buf
)
218 head
= tty
->canon_head
;
219 tail
= tty
->read_tail
;
220 nr
= (head
- tail
) & (N_TTY_BUF_SIZE
-1);
221 /* Skip EOF-chars.. */
222 while (head
!= tail
) {
223 if (test_bit(tail
, tty
->read_flags
) &&
224 tty
->read_buf
[tail
] == __DISABLED_CHAR
)
226 tail
= (tail
+1) & (N_TTY_BUF_SIZE
-1);
233 * These are deprecated, but there is limited support..
235 * The "sg_flags" translation is a joke..
237 static int get_sgflags(struct tty_struct
* tty
)
241 if (!(tty
->termios
->c_lflag
& ICANON
)) {
242 if (tty
->termios
->c_lflag
& ISIG
)
243 flags
|= 0x02; /* cbreak */
245 flags
|= 0x20; /* raw */
247 if (tty
->termios
->c_lflag
& ECHO
)
248 flags
|= 0x08; /* echo */
249 if (tty
->termios
->c_oflag
& OPOST
)
250 if (tty
->termios
->c_oflag
& ONLCR
)
251 flags
|= 0x10; /* crmod */
255 static int get_sgttyb(struct tty_struct
* tty
, struct sgttyb __user
* sgttyb
)
259 down(&tty
->termios_sem
);
262 tmp
.sg_erase
= tty
->termios
->c_cc
[VERASE
];
263 tmp
.sg_kill
= tty
->termios
->c_cc
[VKILL
];
264 tmp
.sg_flags
= get_sgflags(tty
);
265 up(&tty
->termios_sem
);
267 return copy_to_user(sgttyb
, &tmp
, sizeof(tmp
)) ? -EFAULT
: 0;
270 static void set_sgflags(struct termios
* termios
, int flags
)
272 termios
->c_iflag
= ICRNL
| IXON
;
273 termios
->c_oflag
= 0;
274 termios
->c_lflag
= ISIG
| ICANON
;
275 if (flags
& 0x02) { /* cbreak */
276 termios
->c_iflag
= 0;
277 termios
->c_lflag
&= ~ICANON
;
279 if (flags
& 0x08) { /* echo */
280 termios
->c_lflag
|= ECHO
| ECHOE
| ECHOK
|
281 ECHOCTL
| ECHOKE
| IEXTEN
;
283 if (flags
& 0x10) { /* crmod */
284 termios
->c_oflag
|= OPOST
| ONLCR
;
286 if (flags
& 0x20) { /* raw */
287 termios
->c_iflag
= 0;
288 termios
->c_lflag
&= ~(ISIG
| ICANON
);
290 if (!(termios
->c_lflag
& ICANON
)) {
291 termios
->c_cc
[VMIN
] = 1;
292 termios
->c_cc
[VTIME
] = 0;
296 static int set_sgttyb(struct tty_struct
* tty
, struct sgttyb __user
* sgttyb
)
300 struct termios termios
;
302 retval
= tty_check_change(tty
);
306 if (copy_from_user(&tmp
, sgttyb
, sizeof(tmp
)))
309 down(&tty
->termios_sem
);
310 termios
= *tty
->termios
;
311 termios
.c_cc
[VERASE
] = tmp
.sg_erase
;
312 termios
.c_cc
[VKILL
] = tmp
.sg_kill
;
313 set_sgflags(&termios
, tmp
.sg_flags
);
314 up(&tty
->termios_sem
);
315 change_termios(tty
, &termios
);
321 static int get_tchars(struct tty_struct
* tty
, struct tchars __user
* tchars
)
325 tmp
.t_intrc
= tty
->termios
->c_cc
[VINTR
];
326 tmp
.t_quitc
= tty
->termios
->c_cc
[VQUIT
];
327 tmp
.t_startc
= tty
->termios
->c_cc
[VSTART
];
328 tmp
.t_stopc
= tty
->termios
->c_cc
[VSTOP
];
329 tmp
.t_eofc
= tty
->termios
->c_cc
[VEOF
];
330 tmp
.t_brkc
= tty
->termios
->c_cc
[VEOL2
]; /* what is brkc anyway? */
331 return copy_to_user(tchars
, &tmp
, sizeof(tmp
)) ? -EFAULT
: 0;
334 static int set_tchars(struct tty_struct
* tty
, struct tchars __user
* tchars
)
338 if (copy_from_user(&tmp
, tchars
, sizeof(tmp
)))
340 tty
->termios
->c_cc
[VINTR
] = tmp
.t_intrc
;
341 tty
->termios
->c_cc
[VQUIT
] = tmp
.t_quitc
;
342 tty
->termios
->c_cc
[VSTART
] = tmp
.t_startc
;
343 tty
->termios
->c_cc
[VSTOP
] = tmp
.t_stopc
;
344 tty
->termios
->c_cc
[VEOF
] = tmp
.t_eofc
;
345 tty
->termios
->c_cc
[VEOL2
] = tmp
.t_brkc
; /* what is brkc anyway? */
351 static int get_ltchars(struct tty_struct
* tty
, struct ltchars __user
* ltchars
)
355 tmp
.t_suspc
= tty
->termios
->c_cc
[VSUSP
];
356 tmp
.t_dsuspc
= tty
->termios
->c_cc
[VSUSP
]; /* what is dsuspc anyway? */
357 tmp
.t_rprntc
= tty
->termios
->c_cc
[VREPRINT
];
358 tmp
.t_flushc
= tty
->termios
->c_cc
[VEOL2
]; /* what is flushc anyway? */
359 tmp
.t_werasc
= tty
->termios
->c_cc
[VWERASE
];
360 tmp
.t_lnextc
= tty
->termios
->c_cc
[VLNEXT
];
361 return copy_to_user(ltchars
, &tmp
, sizeof(tmp
)) ? -EFAULT
: 0;
364 static int set_ltchars(struct tty_struct
* tty
, struct ltchars __user
* ltchars
)
368 if (copy_from_user(&tmp
, ltchars
, sizeof(tmp
)))
371 tty
->termios
->c_cc
[VSUSP
] = tmp
.t_suspc
;
372 tty
->termios
->c_cc
[VEOL2
] = tmp
.t_dsuspc
; /* what is dsuspc anyway? */
373 tty
->termios
->c_cc
[VREPRINT
] = tmp
.t_rprntc
;
374 tty
->termios
->c_cc
[VEOL2
] = tmp
.t_flushc
; /* what is flushc anyway? */
375 tty
->termios
->c_cc
[VWERASE
] = tmp
.t_werasc
;
376 tty
->termios
->c_cc
[VLNEXT
] = tmp
.t_lnextc
;
382 * Send a high priority character to the tty.
384 void send_prio_char(struct tty_struct
*tty
, char ch
)
386 int was_stopped
= tty
->stopped
;
388 if (tty
->driver
->send_xchar
) {
389 tty
->driver
->send_xchar(tty
, ch
);
394 tty
->driver
->write(tty
, 0, &ch
, 1);
399 int n_tty_ioctl(struct tty_struct
* tty
, struct file
* file
,
400 unsigned int cmd
, unsigned long arg
)
402 struct tty_struct
* real_tty
;
403 void __user
*p
= (void __user
*)arg
;
405 struct tty_ldisc
*ld
;
409 if (tty
->driver
->type
== TTY_DRIVER_TYPE_PTY
&&
410 tty
->driver
->subtype
== PTY_TYPE_MASTER
)
411 real_tty
= tty
->link
;
419 return get_sgttyb(real_tty
, (struct sgttyb __user
*) arg
);
422 return set_sgttyb(real_tty
, (struct sgttyb __user
*) arg
);
426 return get_tchars(real_tty
, p
);
428 return set_tchars(real_tty
, p
);
432 return get_ltchars(real_tty
, p
);
434 return set_ltchars(real_tty
, p
);
437 if (kernel_termios_to_user_termios((struct termios __user
*)arg
, real_tty
->termios
))
441 return set_termios(real_tty
, p
, TERMIOS_FLUSH
| TERMIOS_WAIT
);
443 return set_termios(real_tty
, p
, TERMIOS_WAIT
);
445 return set_termios(real_tty
, p
, 0);
447 return get_termio(real_tty
, p
);
449 return set_termios(real_tty
, p
, TERMIOS_FLUSH
| TERMIOS_WAIT
| TERMIOS_TERMIO
);
451 return set_termios(real_tty
, p
, TERMIOS_WAIT
| TERMIOS_TERMIO
);
453 return set_termios(real_tty
, p
, TERMIOS_TERMIO
);
455 retval
= tty_check_change(tty
);
460 if (!tty
->flow_stopped
) {
461 tty
->flow_stopped
= 1;
466 if (tty
->flow_stopped
) {
467 tty
->flow_stopped
= 0;
472 if (STOP_CHAR(tty
) != __DISABLED_CHAR
)
473 send_prio_char(tty
, STOP_CHAR(tty
));
476 if (START_CHAR(tty
) != __DISABLED_CHAR
)
477 send_prio_char(tty
, START_CHAR(tty
));
484 retval
= tty_check_change(tty
);
488 ld
= tty_ldisc_ref(tty
);
491 if (ld
->flush_buffer
)
492 ld
->flush_buffer(tty
);
495 if (ld
->flush_buffer
)
496 ld
->flush_buffer(tty
);
499 if (tty
->driver
->flush_buffer
)
500 tty
->driver
->flush_buffer(tty
);
509 return put_user(tty
->driver
->chars_in_buffer
?
510 tty
->driver
->chars_in_buffer(tty
) : 0,
513 retval
= tty
->read_cnt
;
515 retval
= inq_canon(tty
);
516 return put_user(retval
, (unsigned int __user
*) arg
);
518 if (kernel_termios_to_user_termios((struct termios __user
*)arg
, real_tty
->termios_locked
))
523 if (!capable(CAP_SYS_ADMIN
))
525 if (user_termios_to_kernel_termios(real_tty
->termios_locked
, (struct termios __user
*) arg
))
533 if (tty
->driver
->type
!= TTY_DRIVER_TYPE_PTY
||
534 tty
->driver
->subtype
!= PTY_TYPE_MASTER
)
536 if (get_user(pktmode
, (int __user
*) arg
))
541 tty
->link
->ctrl_status
= 0;
548 return put_user(C_CLOCAL(tty
) ? 1 : 0, (int __user
*)arg
);
550 if (get_user(arg
, (unsigned int __user
*) arg
))
552 down(&tty
->termios_sem
);
553 tty
->termios
->c_cflag
=
554 ((tty
->termios
->c_cflag
& ~CLOCAL
) |
556 up(&tty
->termios_sem
);
564 EXPORT_SYMBOL(n_tty_ioctl
);