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>
22 #include <linux/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
);
167 if (opt
& TERMIOS_TERMIO
) {
168 memcpy(&tmp_termios
, tty
->termios
, sizeof(struct termios
));
169 if (user_termio_to_kernel_termios(&tmp_termios
,
170 (struct termio __user
*)arg
))
173 if (user_termios_to_kernel_termios(&tmp_termios
,
174 (struct termios __user
*)arg
))
178 ld
= tty_ldisc_ref(tty
);
181 if ((opt
& TERMIOS_FLUSH
) && ld
->flush_buffer
)
182 ld
->flush_buffer(tty
);
186 if (opt
& TERMIOS_WAIT
) {
187 tty_wait_until_sent(tty
, 0);
188 if (signal_pending(current
))
192 change_termios(tty
, &tmp_termios
);
196 static int get_termio(struct tty_struct
* tty
, struct termio __user
* termio
)
198 if (kernel_termios_to_user_termio(termio
, tty
->termios
))
203 static unsigned long inq_canon(struct tty_struct
* tty
)
207 if (!tty
->canon_data
|| !tty
->read_buf
)
209 head
= tty
->canon_head
;
210 tail
= tty
->read_tail
;
211 nr
= (head
- tail
) & (N_TTY_BUF_SIZE
-1);
212 /* Skip EOF-chars.. */
213 while (head
!= tail
) {
214 if (test_bit(tail
, tty
->read_flags
) &&
215 tty
->read_buf
[tail
] == __DISABLED_CHAR
)
217 tail
= (tail
+1) & (N_TTY_BUF_SIZE
-1);
224 * These are deprecated, but there is limited support..
226 * The "sg_flags" translation is a joke..
228 static int get_sgflags(struct tty_struct
* tty
)
232 if (!(tty
->termios
->c_lflag
& ICANON
)) {
233 if (tty
->termios
->c_lflag
& ISIG
)
234 flags
|= 0x02; /* cbreak */
236 flags
|= 0x20; /* raw */
238 if (tty
->termios
->c_lflag
& ECHO
)
239 flags
|= 0x08; /* echo */
240 if (tty
->termios
->c_oflag
& OPOST
)
241 if (tty
->termios
->c_oflag
& ONLCR
)
242 flags
|= 0x10; /* crmod */
246 static int get_sgttyb(struct tty_struct
* tty
, struct sgttyb __user
* sgttyb
)
250 down(&tty
->termios_sem
);
253 tmp
.sg_erase
= tty
->termios
->c_cc
[VERASE
];
254 tmp
.sg_kill
= tty
->termios
->c_cc
[VKILL
];
255 tmp
.sg_flags
= get_sgflags(tty
);
256 up(&tty
->termios_sem
);
258 return copy_to_user(sgttyb
, &tmp
, sizeof(tmp
)) ? -EFAULT
: 0;
261 static void set_sgflags(struct termios
* termios
, int flags
)
263 termios
->c_iflag
= ICRNL
| IXON
;
264 termios
->c_oflag
= 0;
265 termios
->c_lflag
= ISIG
| ICANON
;
266 if (flags
& 0x02) { /* cbreak */
267 termios
->c_iflag
= 0;
268 termios
->c_lflag
&= ~ICANON
;
270 if (flags
& 0x08) { /* echo */
271 termios
->c_lflag
|= ECHO
| ECHOE
| ECHOK
|
272 ECHOCTL
| ECHOKE
| IEXTEN
;
274 if (flags
& 0x10) { /* crmod */
275 termios
->c_oflag
|= OPOST
| ONLCR
;
277 if (flags
& 0x20) { /* raw */
278 termios
->c_iflag
= 0;
279 termios
->c_lflag
&= ~(ISIG
| ICANON
);
281 if (!(termios
->c_lflag
& ICANON
)) {
282 termios
->c_cc
[VMIN
] = 1;
283 termios
->c_cc
[VTIME
] = 0;
287 static int set_sgttyb(struct tty_struct
* tty
, struct sgttyb __user
* sgttyb
)
291 struct termios termios
;
293 retval
= tty_check_change(tty
);
297 if (copy_from_user(&tmp
, sgttyb
, sizeof(tmp
)))
300 down(&tty
->termios_sem
);
301 termios
= *tty
->termios
;
302 termios
.c_cc
[VERASE
] = tmp
.sg_erase
;
303 termios
.c_cc
[VKILL
] = tmp
.sg_kill
;
304 set_sgflags(&termios
, tmp
.sg_flags
);
305 up(&tty
->termios_sem
);
306 change_termios(tty
, &termios
);
312 static int get_tchars(struct tty_struct
* tty
, struct tchars __user
* tchars
)
316 tmp
.t_intrc
= tty
->termios
->c_cc
[VINTR
];
317 tmp
.t_quitc
= tty
->termios
->c_cc
[VQUIT
];
318 tmp
.t_startc
= tty
->termios
->c_cc
[VSTART
];
319 tmp
.t_stopc
= tty
->termios
->c_cc
[VSTOP
];
320 tmp
.t_eofc
= tty
->termios
->c_cc
[VEOF
];
321 tmp
.t_brkc
= tty
->termios
->c_cc
[VEOL2
]; /* what is brkc anyway? */
322 return copy_to_user(tchars
, &tmp
, sizeof(tmp
)) ? -EFAULT
: 0;
325 static int set_tchars(struct tty_struct
* tty
, struct tchars __user
* tchars
)
329 if (copy_from_user(&tmp
, tchars
, sizeof(tmp
)))
331 tty
->termios
->c_cc
[VINTR
] = tmp
.t_intrc
;
332 tty
->termios
->c_cc
[VQUIT
] = tmp
.t_quitc
;
333 tty
->termios
->c_cc
[VSTART
] = tmp
.t_startc
;
334 tty
->termios
->c_cc
[VSTOP
] = tmp
.t_stopc
;
335 tty
->termios
->c_cc
[VEOF
] = tmp
.t_eofc
;
336 tty
->termios
->c_cc
[VEOL2
] = tmp
.t_brkc
; /* what is brkc anyway? */
342 static int get_ltchars(struct tty_struct
* tty
, struct ltchars __user
* ltchars
)
346 tmp
.t_suspc
= tty
->termios
->c_cc
[VSUSP
];
347 tmp
.t_dsuspc
= tty
->termios
->c_cc
[VSUSP
]; /* what is dsuspc anyway? */
348 tmp
.t_rprntc
= tty
->termios
->c_cc
[VREPRINT
];
349 tmp
.t_flushc
= tty
->termios
->c_cc
[VEOL2
]; /* what is flushc anyway? */
350 tmp
.t_werasc
= tty
->termios
->c_cc
[VWERASE
];
351 tmp
.t_lnextc
= tty
->termios
->c_cc
[VLNEXT
];
352 return copy_to_user(ltchars
, &tmp
, sizeof(tmp
)) ? -EFAULT
: 0;
355 static int set_ltchars(struct tty_struct
* tty
, struct ltchars __user
* ltchars
)
359 if (copy_from_user(&tmp
, ltchars
, sizeof(tmp
)))
362 tty
->termios
->c_cc
[VSUSP
] = tmp
.t_suspc
;
363 tty
->termios
->c_cc
[VEOL2
] = tmp
.t_dsuspc
; /* what is dsuspc anyway? */
364 tty
->termios
->c_cc
[VREPRINT
] = tmp
.t_rprntc
;
365 tty
->termios
->c_cc
[VEOL2
] = tmp
.t_flushc
; /* what is flushc anyway? */
366 tty
->termios
->c_cc
[VWERASE
] = tmp
.t_werasc
;
367 tty
->termios
->c_cc
[VLNEXT
] = tmp
.t_lnextc
;
373 * Send a high priority character to the tty.
375 static void send_prio_char(struct tty_struct
*tty
, char ch
)
377 int was_stopped
= tty
->stopped
;
379 if (tty
->driver
->send_xchar
) {
380 tty
->driver
->send_xchar(tty
, ch
);
385 tty
->driver
->write(tty
, &ch
, 1);
390 int n_tty_ioctl(struct tty_struct
* tty
, struct file
* file
,
391 unsigned int cmd
, unsigned long arg
)
393 struct tty_struct
* real_tty
;
394 void __user
*p
= (void __user
*)arg
;
396 struct tty_ldisc
*ld
;
398 if (tty
->driver
->type
== TTY_DRIVER_TYPE_PTY
&&
399 tty
->driver
->subtype
== PTY_TYPE_MASTER
)
400 real_tty
= tty
->link
;
407 return get_sgttyb(real_tty
, (struct sgttyb __user
*) arg
);
410 return set_sgttyb(real_tty
, (struct sgttyb __user
*) arg
);
414 return get_tchars(real_tty
, p
);
416 return set_tchars(real_tty
, p
);
420 return get_ltchars(real_tty
, p
);
422 return set_ltchars(real_tty
, p
);
425 if (kernel_termios_to_user_termios((struct termios __user
*)arg
, real_tty
->termios
))
429 return set_termios(real_tty
, p
, TERMIOS_FLUSH
| TERMIOS_WAIT
);
431 return set_termios(real_tty
, p
, TERMIOS_WAIT
);
433 return set_termios(real_tty
, p
, 0);
435 return get_termio(real_tty
, p
);
437 return set_termios(real_tty
, p
, TERMIOS_FLUSH
| TERMIOS_WAIT
| TERMIOS_TERMIO
);
439 return set_termios(real_tty
, p
, TERMIOS_WAIT
| TERMIOS_TERMIO
);
441 return set_termios(real_tty
, p
, TERMIOS_TERMIO
);
443 retval
= tty_check_change(tty
);
448 if (!tty
->flow_stopped
) {
449 tty
->flow_stopped
= 1;
454 if (tty
->flow_stopped
) {
455 tty
->flow_stopped
= 0;
460 if (STOP_CHAR(tty
) != __DISABLED_CHAR
)
461 send_prio_char(tty
, STOP_CHAR(tty
));
464 if (START_CHAR(tty
) != __DISABLED_CHAR
)
465 send_prio_char(tty
, START_CHAR(tty
));
472 retval
= tty_check_change(tty
);
476 ld
= tty_ldisc_ref(tty
);
479 if (ld
->flush_buffer
)
480 ld
->flush_buffer(tty
);
483 if (ld
->flush_buffer
)
484 ld
->flush_buffer(tty
);
487 if (tty
->driver
->flush_buffer
)
488 tty
->driver
->flush_buffer(tty
);
497 return put_user(tty
->driver
->chars_in_buffer
?
498 tty
->driver
->chars_in_buffer(tty
) : 0,
501 retval
= tty
->read_cnt
;
503 retval
= inq_canon(tty
);
504 return put_user(retval
, (unsigned int __user
*) arg
);
506 if (kernel_termios_to_user_termios((struct termios __user
*)arg
, real_tty
->termios_locked
))
511 if (!capable(CAP_SYS_ADMIN
))
513 if (user_termios_to_kernel_termios(real_tty
->termios_locked
, (struct termios __user
*) arg
))
521 if (tty
->driver
->type
!= TTY_DRIVER_TYPE_PTY
||
522 tty
->driver
->subtype
!= PTY_TYPE_MASTER
)
524 if (get_user(pktmode
, (int __user
*) arg
))
529 tty
->link
->ctrl_status
= 0;
536 return put_user(C_CLOCAL(tty
) ? 1 : 0, (int __user
*)arg
);
538 if (get_user(arg
, (unsigned int __user
*) arg
))
540 down(&tty
->termios_sem
);
541 tty
->termios
->c_cflag
=
542 ((tty
->termios
->c_cflag
& ~CLOCAL
) |
544 up(&tty
->termios_sem
);
551 EXPORT_SYMBOL(n_tty_ioctl
);