diff options
-rw-r--r-- | drivers/char/tty_ioctl.c | 58 | ||||
-rw-r--r-- | include/asm-x86/ioctls.h | 4 | ||||
-rw-r--r-- | include/linux/termios.h | 15 | ||||
-rw-r--r-- | include/linux/tty.h | 1 | ||||
-rw-r--r-- | include/linux/tty_driver.h | 9 |
5 files changed, 87 insertions, 0 deletions
diff --git a/drivers/char/tty_ioctl.c b/drivers/char/tty_ioctl.c index bf34e459742..93bfa1d6cc9 100644 --- a/drivers/char/tty_ioctl.c +++ b/drivers/char/tty_ioctl.c @@ -579,6 +579,50 @@ static int get_termio(struct tty_struct *tty, struct termio __user *termio) return 0; } + +#ifdef TCGETX + +/** + * set_termiox - set termiox fields if possible + * @tty: terminal + * @arg: termiox structure from user + * @opt: option flags for ioctl type + * + * Implement the device calling points for the SYS5 termiox ioctl + * interface in Linux + */ + +static int set_termiox(struct tty_struct *tty, void __user *arg, int opt) +{ + struct termiox tnew; + struct tty_ldisc *ld; + + if (tty->termiox == NULL) + return -EINVAL; + if (copy_from_user(&tnew, arg, sizeof(struct termiox))) + return -EFAULT; + + ld = tty_ldisc_ref(tty); + if (ld != NULL) { + if ((opt & TERMIOS_FLUSH) && ld->ops->flush_buffer) + ld->ops->flush_buffer(tty); + tty_ldisc_deref(ld); + } + if (opt & TERMIOS_WAIT) { + tty_wait_until_sent(tty, 0); + if (signal_pending(current)) + return -EINTR; + } + + mutex_lock(&tty->termios_mutex); + if (tty->ops->set_termiox) + tty->ops->set_termiox(tty, &tnew); + mutex_unlock(&tty->termios_mutex); + return 0; +} + +#endif + static unsigned long inq_canon(struct tty_struct *tty) { int nr, head, tail; @@ -936,6 +980,20 @@ int tty_mode_ioctl(struct tty_struct *tty, struct file *file, return -EFAULT; return 0; #endif +#ifdef TCGETX + case TCGETX: + if (real_tty->termiox == NULL) + return -EINVAL; + if (copy_to_user(p, real_tty->termiox, sizeof(struct termiox))) + return -EFAULT; + return 0; + case TCSETX: + return set_termiox(real_tty, p, 0); + case TCSETXW: + return set_termiox(real_tty, p, TERMIOS_WAIT); + case TCSETXF: + return set_termiox(real_tty, p, TERMIOS_FLUSH); +#endif case TIOCGSOFTCAR: /* FIXME: for correctness we may need to take the termios lock here - review */ diff --git a/include/asm-x86/ioctls.h b/include/asm-x86/ioctls.h index 1a8ac45b28b..06752a64904 100644 --- a/include/asm-x86/ioctls.h +++ b/include/asm-x86/ioctls.h @@ -56,6 +56,10 @@ #define TIOCGPTN _IOR('T', 0x30, unsigned int) /* Get Pty Number (of pty-mux device) */ #define TIOCSPTLCK _IOW('T', 0x31, int) /* Lock/unlock Pty */ +#define TCGETX 0x5432 /* SYS5 TCGETX compatibility */ +#define TCSETX 0x5433 +#define TCSETXF 0x5434 +#define TCSETXW 0x5435 #define FIONCLEX 0x5450 #define FIOCLEX 0x5451 diff --git a/include/linux/termios.h b/include/linux/termios.h index 478662889f4..2acd0c1f8a2 100644 --- a/include/linux/termios.h +++ b/include/linux/termios.h @@ -4,4 +4,19 @@ #include <linux/types.h> #include <asm/termios.h> +#define NFF 5 + +struct termiox +{ + __u16 x_hflag; + __u16 x_cflag; + __u16 x_rflag[NFF]; + __u16 x_sflag; +}; + +#define RTSXOFF 0x0001 /* RTS flow control on input */ +#define CTSXON 0x0002 /* CTS flow control on output */ +#define DTRXOFF 0x0004 /* DTR flow control on input */ +#define DSRXON 0x0008 /* DCD flow control on output */ + #endif diff --git a/include/linux/tty.h b/include/linux/tty.h index b6e6c26883e..b64d10b6654 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h @@ -219,6 +219,7 @@ struct tty_struct { spinlock_t ctrl_lock; /* Termios values are protected by the termios mutex */ struct ktermios *termios, *termios_locked; + struct termiox *termiox; /* May be NULL for unsupported */ char name[64]; struct pid *pgrp; /* Protected by ctrl lock */ struct pid *session; diff --git a/include/linux/tty_driver.h b/include/linux/tty_driver.h index 16d27944c32..ac6e58e26b7 100644 --- a/include/linux/tty_driver.h +++ b/include/linux/tty_driver.h @@ -180,6 +180,14 @@ * not force errors here if they are not resizable objects (eg a serial * line). See tty_do_resize() if you need to wrap the standard method * in your own logic - the usual case. + * + * void (*set_termiox)(struct tty_struct *tty, struct termiox *new); + * + * Called when the device receives a termiox based ioctl. Passes down + * the requested data from user space. This method will not be invoked + * unless the tty also has a valid tty->termiox pointer. + * + * Optional: Called under the termios lock */ #include <linux/fs.h> @@ -220,6 +228,7 @@ struct tty_operations { unsigned int set, unsigned int clear); int (*resize)(struct tty_struct *tty, struct tty_struct *real_tty, struct winsize *ws); + int (*set_termiox)(struct tty_struct *tty, struct termiox *tnew); #ifdef CONFIG_CONSOLE_POLL int (*poll_init)(struct tty_driver *driver, int line, char *options); int (*poll_get_char)(struct tty_driver *driver, int line); |