diff --git a/drivers/char/tty_ioctl.c b/drivers/char/tty_ioctl.c index bf34e45974212fc46df349416646779d2e7d78dd..93bfa1d6cc92301e38cca48dbf99086a6dce2e78 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 1a8ac45b28be69af883b602911bae29b2f9fa692..06752a649044d2029c4c555f006635ff41d6b9f5 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 478662889f487db6fb1b8f6abba1bd781831a445..2acd0c1f8a2a305c8c7fc23895a6cba3cdd35ea8 100644 --- a/include/linux/termios.h +++ b/include/linux/termios.h @@ -4,4 +4,19 @@ #include #include +#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 b6e6c26883ee789463eb04f10b6a3424dc9142c5..b64d10b66548141e05cebae006ea5e24fef0360d 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 16d27944c3211af2f954fa6fff4950d3c3591812..ac6e58e26b73f4f9d55ab5e32a188c783dd9d3c5 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 @@ -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);