summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/char/tty_ioctl.c58
-rw-r--r--include/asm-x86/ioctls.h4
-rw-r--r--include/linux/termios.h15
-rw-r--r--include/linux/tty.h1
-rw-r--r--include/linux/tty_driver.h9
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);