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>
23 #include <asm/bitops.h>
24 #include <asm/uaccess.h>
25 #include <asm/system.h>
27 #undef TTY_DEBUG_WAIT_UNTIL_SENT
31 # define PRINTK(x) printk (x)
33 # define PRINTK(x) /**/
37 * Internal flag options for termios setting behavior
39 #define TERMIOS_FLUSH 1
40 #define TERMIOS_WAIT 2
41 #define TERMIOS_TERMIO 4
43 void tty_wait_until_sent(struct tty_struct
* tty
, long timeout
)
45 DECLARE_WAITQUEUE(wait
, current
);
47 #ifdef TTY_DEBUG_WAIT_UNTIL_SENT
50 printk("%s wait until sent...\n", tty_name(tty
, buf
));
52 if (!tty
->driver
.chars_in_buffer
)
54 add_wait_queue(&tty
->write_wait
, &wait
);
56 timeout
= MAX_SCHEDULE_TIMEOUT
;
58 #ifdef TTY_DEBUG_WAIT_UNTIL_SENT
59 printk("waiting %s...(%d)\n", tty_name(tty
, buf
),
60 tty
->driver
.chars_in_buffer(tty
));
62 set_current_state(TASK_INTERRUPTIBLE
);
63 if (signal_pending(current
))
65 if (!tty
->driver
.chars_in_buffer(tty
))
67 timeout
= schedule_timeout(timeout
);
69 if (tty
->driver
.wait_until_sent
)
70 tty
->driver
.wait_until_sent(tty
, timeout
);
72 current
->state
= TASK_RUNNING
;
73 remove_wait_queue(&tty
->write_wait
, &wait
);
76 static void unset_locked_termios(struct termios
*termios
,
78 struct termios
*locked
)
82 #define NOSET_MASK(x,y,z) (x = ((x) & ~(z)) | ((y) & (z)))
85 printk("Warning?!? termios_locked is NULL.\n");
89 NOSET_MASK(termios
->c_iflag
, old
->c_iflag
, locked
->c_iflag
);
90 NOSET_MASK(termios
->c_oflag
, old
->c_oflag
, locked
->c_oflag
);
91 NOSET_MASK(termios
->c_cflag
, old
->c_cflag
, locked
->c_cflag
);
92 NOSET_MASK(termios
->c_lflag
, old
->c_lflag
, locked
->c_lflag
);
93 termios
->c_line
= locked
->c_line
? old
->c_line
: termios
->c_line
;
94 for (i
=0; i
< NCCS
; i
++)
95 termios
->c_cc
[i
] = locked
->c_cc
[i
] ?
96 old
->c_cc
[i
] : termios
->c_cc
[i
];
99 static void change_termios(struct tty_struct
* tty
, struct termios
* new_termios
)
102 struct termios old_termios
= *tty
->termios
;
105 *tty
->termios
= *new_termios
;
106 unset_locked_termios(tty
->termios
, &old_termios
, tty
->termios_locked
);
107 canon_change
= (old_termios
.c_lflag
^ tty
->termios
->c_lflag
) & ICANON
;
109 memset(&tty
->read_flags
, 0, sizeof tty
->read_flags
);
110 tty
->canon_head
= tty
->read_tail
;
115 if (canon_change
&& !L_ICANON(tty
) && tty
->read_cnt
)
116 /* Get characters left over from canonical mode. */
117 wake_up_interruptible(&tty
->read_wait
);
119 /* see if packet mode change of state */
121 if (tty
->link
&& tty
->link
->packet
) {
122 int old_flow
= ((old_termios
.c_iflag
& IXON
) &&
123 (old_termios
.c_cc
[VSTOP
] == '\023') &&
124 (old_termios
.c_cc
[VSTART
] == '\021'));
125 int new_flow
= (I_IXON(tty
) &&
126 STOP_CHAR(tty
) == '\023' &&
127 START_CHAR(tty
) == '\021');
128 if (old_flow
!= new_flow
) {
129 tty
->ctrl_status
&= ~(TIOCPKT_DOSTOP
| TIOCPKT_NOSTOP
);
131 tty
->ctrl_status
|= TIOCPKT_DOSTOP
;
133 tty
->ctrl_status
|= TIOCPKT_NOSTOP
;
134 wake_up_interruptible(&tty
->link
->read_wait
);
138 if (tty
->driver
.set_termios
)
139 (*tty
->driver
.set_termios
)(tty
, &old_termios
);
141 if (tty
->ldisc
.set_termios
)
142 (*tty
->ldisc
.set_termios
)(tty
, &old_termios
);
145 static int set_termios(struct tty_struct
* tty
, unsigned long arg
, int opt
)
147 struct termios tmp_termios
;
150 retval
= tty_check_change(tty
);
154 if (opt
& TERMIOS_TERMIO
) {
155 memcpy(&tmp_termios
, tty
->termios
, sizeof(struct termios
));
156 if (user_termio_to_kernel_termios(&tmp_termios
, (struct termio
*) arg
))
159 if (user_termios_to_kernel_termios(&tmp_termios
, (struct termios
*) arg
))
163 if ((opt
& TERMIOS_FLUSH
) && tty
->ldisc
.flush_buffer
)
164 tty
->ldisc
.flush_buffer(tty
);
166 if (opt
& TERMIOS_WAIT
) {
167 tty_wait_until_sent(tty
, 0);
168 if (signal_pending(current
))
172 change_termios(tty
, &tmp_termios
);
176 static int get_termio(struct tty_struct
* tty
, struct termio
* termio
)
178 if (kernel_termios_to_user_termio(termio
, tty
->termios
))
183 static unsigned long inq_canon(struct tty_struct
* tty
)
187 if (!tty
->canon_data
|| !tty
->read_buf
)
189 head
= tty
->canon_head
;
190 tail
= tty
->read_tail
;
191 nr
= (head
- tail
) & (N_TTY_BUF_SIZE
-1);
192 /* Skip EOF-chars.. */
193 while (head
!= tail
) {
194 if (test_bit(tail
, &tty
->read_flags
) &&
195 tty
->read_buf
[tail
] == __DISABLED_CHAR
)
197 tail
= (tail
+1) & (N_TTY_BUF_SIZE
-1);
204 * These are deprecated, but there is limited support..
206 * The "sg_flags" translation is a joke..
208 static int get_sgflags(struct tty_struct
* tty
)
212 if (!(tty
->termios
->c_lflag
& ICANON
)) {
213 if (tty
->termios
->c_lflag
& ISIG
)
214 flags
|= 0x02; /* cbreak */
216 flags
|= 0x20; /* raw */
218 if (tty
->termios
->c_lflag
& ECHO
)
219 flags
|= 0x08; /* echo */
220 if (tty
->termios
->c_oflag
& OPOST
)
221 if (tty
->termios
->c_oflag
& ONLCR
)
222 flags
|= 0x10; /* crmod */
226 static int get_sgttyb(struct tty_struct
* tty
, struct sgttyb
* sgttyb
)
232 tmp
.sg_erase
= tty
->termios
->c_cc
[VERASE
];
233 tmp
.sg_kill
= tty
->termios
->c_cc
[VKILL
];
234 tmp
.sg_flags
= get_sgflags(tty
);
235 if (copy_to_user(sgttyb
, &tmp
, sizeof(tmp
)))
240 static void set_sgflags(struct termios
* termios
, int flags
)
242 termios
->c_iflag
= ICRNL
| IXON
;
243 termios
->c_oflag
= 0;
244 termios
->c_lflag
= ISIG
| ICANON
;
245 if (flags
& 0x02) { /* cbreak */
246 termios
->c_iflag
= 0;
247 termios
->c_lflag
&= ~ICANON
;
249 if (flags
& 0x08) { /* echo */
250 termios
->c_lflag
|= ECHO
| ECHOE
| ECHOK
| ECHOCTL
| ECHOKE
| IEXTEN
;
252 if (flags
& 0x10) { /* crmod */
253 termios
->c_oflag
|= OPOST
| ONLCR
;
255 if (flags
& 0x20) { /* raw */
256 termios
->c_iflag
= 0;
257 termios
->c_lflag
&= ~(ISIG
| ICANON
);
259 if (!(termios
->c_lflag
& ICANON
)) {
260 termios
->c_cc
[VMIN
] = 1;
261 termios
->c_cc
[VTIME
] = 0;
265 static int set_sgttyb(struct tty_struct
* tty
, struct sgttyb
* sgttyb
)
269 struct termios termios
;
271 retval
= tty_check_change(tty
);
274 termios
= *tty
->termios
;
275 if (copy_from_user(&tmp
, sgttyb
, sizeof(tmp
)))
277 termios
.c_cc
[VERASE
] = tmp
.sg_erase
;
278 termios
.c_cc
[VKILL
] = tmp
.sg_kill
;
279 set_sgflags(&termios
, tmp
.sg_flags
);
280 change_termios(tty
, &termios
);
286 static int get_tchars(struct tty_struct
* tty
, struct tchars
* tchars
)
290 tmp
.t_intrc
= tty
->termios
->c_cc
[VINTR
];
291 tmp
.t_quitc
= tty
->termios
->c_cc
[VQUIT
];
292 tmp
.t_startc
= tty
->termios
->c_cc
[VSTART
];
293 tmp
.t_stopc
= tty
->termios
->c_cc
[VSTOP
];
294 tmp
.t_eofc
= tty
->termios
->c_cc
[VEOF
];
295 tmp
.t_brkc
= tty
->termios
->c_cc
[VEOL2
]; /* what is brkc anyway? */
296 if (copy_to_user(tchars
, &tmp
, sizeof(tmp
)))
301 static int set_tchars(struct tty_struct
* tty
, struct tchars
* tchars
)
305 if (copy_from_user(&tmp
, tchars
, sizeof(tmp
)))
307 tty
->termios
->c_cc
[VINTR
] = tmp
.t_intrc
;
308 tty
->termios
->c_cc
[VQUIT
] = tmp
.t_quitc
;
309 tty
->termios
->c_cc
[VSTART
] = tmp
.t_startc
;
310 tty
->termios
->c_cc
[VSTOP
] = tmp
.t_stopc
;
311 tty
->termios
->c_cc
[VEOF
] = tmp
.t_eofc
;
312 tty
->termios
->c_cc
[VEOL2
] = tmp
.t_brkc
; /* what is brkc anyway? */
318 static int get_ltchars(struct tty_struct
* tty
, struct ltchars
* ltchars
)
322 tmp
.t_suspc
= tty
->termios
->c_cc
[VSUSP
];
323 tmp
.t_dsuspc
= tty
->termios
->c_cc
[VSUSP
]; /* what is dsuspc anyway? */
324 tmp
.t_rprntc
= tty
->termios
->c_cc
[VREPRINT
];
325 tmp
.t_flushc
= tty
->termios
->c_cc
[VEOL2
]; /* what is flushc anyway? */
326 tmp
.t_werasc
= tty
->termios
->c_cc
[VWERASE
];
327 tmp
.t_lnextc
= tty
->termios
->c_cc
[VLNEXT
];
328 if (copy_to_user(ltchars
, &tmp
, sizeof(tmp
)))
333 static int set_ltchars(struct tty_struct
* tty
, struct ltchars
* ltchars
)
337 if (copy_from_user(&tmp
, ltchars
, sizeof(tmp
)))
340 tty
->termios
->c_cc
[VSUSP
] = tmp
.t_suspc
;
341 tty
->termios
->c_cc
[VEOL2
] = tmp
.t_dsuspc
; /* what is dsuspc anyway? */
342 tty
->termios
->c_cc
[VREPRINT
] = tmp
.t_rprntc
;
343 tty
->termios
->c_cc
[VEOL2
] = tmp
.t_flushc
; /* what is flushc anyway? */
344 tty
->termios
->c_cc
[VWERASE
] = tmp
.t_werasc
;
345 tty
->termios
->c_cc
[VLNEXT
] = tmp
.t_lnextc
;
351 * Send a high priority character to the tty.
353 void send_prio_char(struct tty_struct
*tty
, char ch
)
355 int was_stopped
= tty
->stopped
;
357 if (tty
->driver
.send_xchar
) {
358 tty
->driver
.send_xchar(tty
, ch
);
363 tty
->driver
.write(tty
, 0, &ch
, 1);
368 int n_tty_ioctl(struct tty_struct
* tty
, struct file
* file
,
369 unsigned int cmd
, unsigned long arg
)
371 struct tty_struct
* real_tty
;
374 if (tty
->driver
.type
== TTY_DRIVER_TYPE_PTY
&&
375 tty
->driver
.subtype
== PTY_TYPE_MASTER
)
376 real_tty
= tty
->link
;
383 return get_sgttyb(real_tty
, (struct sgttyb
*) arg
);
386 return set_sgttyb(real_tty
, (struct sgttyb
*) arg
);
390 return get_tchars(real_tty
, (struct tchars
*) arg
);
392 return set_tchars(real_tty
, (struct tchars
*) arg
);
396 return get_ltchars(real_tty
, (struct ltchars
*) arg
);
398 return set_ltchars(real_tty
, (struct ltchars
*) arg
);
401 if (kernel_termios_to_user_termios((struct termios
*)arg
, real_tty
->termios
))
405 return set_termios(real_tty
, arg
, TERMIOS_FLUSH
);
407 return set_termios(real_tty
, arg
, TERMIOS_WAIT
);
409 return set_termios(real_tty
, arg
, 0);
411 return get_termio(real_tty
,(struct termio
*) arg
);
413 return set_termios(real_tty
, arg
, TERMIOS_FLUSH
| TERMIOS_TERMIO
);
415 return set_termios(real_tty
, arg
, TERMIOS_WAIT
| TERMIOS_TERMIO
);
417 return set_termios(real_tty
, arg
, TERMIOS_TERMIO
);
419 retval
= tty_check_change(tty
);
424 if (!tty
->flow_stopped
) {
425 tty
->flow_stopped
= 1;
430 if (tty
->flow_stopped
) {
431 tty
->flow_stopped
= 0;
436 if (STOP_CHAR(tty
) != __DISABLED_CHAR
)
437 send_prio_char(tty
, STOP_CHAR(tty
));
440 if (START_CHAR(tty
) != __DISABLED_CHAR
)
441 send_prio_char(tty
, START_CHAR(tty
));
448 retval
= tty_check_change(tty
);
453 if (tty
->ldisc
.flush_buffer
)
454 tty
->ldisc
.flush_buffer(tty
);
457 if (tty
->ldisc
.flush_buffer
)
458 tty
->ldisc
.flush_buffer(tty
);
461 if (tty
->driver
.flush_buffer
)
462 tty
->driver
.flush_buffer(tty
);
469 return put_user(tty
->driver
.chars_in_buffer
?
470 tty
->driver
.chars_in_buffer(tty
) : 0,
473 retval
= tty
->read_cnt
;
475 retval
= inq_canon(tty
);
476 return put_user(retval
, (unsigned int *) arg
);
478 if (kernel_termios_to_user_termios((struct termios
*)arg
, real_tty
->termios_locked
))
485 if (user_termios_to_kernel_termios(real_tty
->termios_locked
, (struct termios
*) arg
))
493 if (tty
->driver
.type
!= TTY_DRIVER_TYPE_PTY
||
494 tty
->driver
.subtype
!= PTY_TYPE_MASTER
)
496 retval
= get_user(pktmode
, (int *) arg
);
502 tty
->link
->ctrl_status
= 0;
509 return put_user(C_CLOCAL(tty
) ? 1 : 0, (int *) arg
);
511 retval
= get_user(arg
, (unsigned int *) arg
);
514 tty
->termios
->c_cflag
=
515 ((tty
->termios
->c_cflag
& ~CLOCAL
) |