summaryrefslogtreecommitdiff
path: root/drivers/char/tty_ioctl.c
diff options
context:
space:
mode:
authorAlan Cox <alan@redhat.com>2008-10-13 10:38:18 +0100
committerLinus Torvalds <torvalds@linux-foundation.org>2008-10-13 09:51:40 -0700
commit1d65b4a088de407e99714fdc27862449db04fb5c (patch)
tree89f378767b9e0fe1a902d73bf43be382c6110f72 /drivers/char/tty_ioctl.c
parent5aaa70a80f5bbfcc4d6a1f844bdd1c5d6b445b5f (diff)
tty: Add termiox
We need a way to describe the various additional modes and flow control features that random weird hardware shows up and software such as wine wants to emulate as Windows supports them. TCGETX/TCSETX and the termiox ioctl are a SYS5 extension that we might as well adopt. This patches adds the structures and the basic ioctl interfaces when the TCGETX etc defines are added for an architecture. Drivers wishing to use this stuff need to add new methods. Signed-off-by: Alan Cox <alan@redhat.com> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/char/tty_ioctl.c')
-rw-r--r--drivers/char/tty_ioctl.c58
1 files changed, 58 insertions, 0 deletions
diff --git a/drivers/char/tty_ioctl.c b/drivers/char/tty_ioctl.c
index bf34e4597421..93bfa1d6cc92 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 */