Commit 1d65b4a088de407e99714fdc27862449db04fb5c

Authored by Alan Cox
Committed by Linus Torvalds
1 parent 5aaa70a80f

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>

Showing 5 changed files with 87 additions and 0 deletions Side-by-side Diff

drivers/char/tty_ioctl.c
... ... @@ -579,6 +579,50 @@
579 579 return 0;
580 580 }
581 581  
  582 +
  583 +#ifdef TCGETX
  584 +
  585 +/**
  586 + * set_termiox - set termiox fields if possible
  587 + * @tty: terminal
  588 + * @arg: termiox structure from user
  589 + * @opt: option flags for ioctl type
  590 + *
  591 + * Implement the device calling points for the SYS5 termiox ioctl
  592 + * interface in Linux
  593 + */
  594 +
  595 +static int set_termiox(struct tty_struct *tty, void __user *arg, int opt)
  596 +{
  597 + struct termiox tnew;
  598 + struct tty_ldisc *ld;
  599 +
  600 + if (tty->termiox == NULL)
  601 + return -EINVAL;
  602 + if (copy_from_user(&tnew, arg, sizeof(struct termiox)))
  603 + return -EFAULT;
  604 +
  605 + ld = tty_ldisc_ref(tty);
  606 + if (ld != NULL) {
  607 + if ((opt & TERMIOS_FLUSH) && ld->ops->flush_buffer)
  608 + ld->ops->flush_buffer(tty);
  609 + tty_ldisc_deref(ld);
  610 + }
  611 + if (opt & TERMIOS_WAIT) {
  612 + tty_wait_until_sent(tty, 0);
  613 + if (signal_pending(current))
  614 + return -EINTR;
  615 + }
  616 +
  617 + mutex_lock(&tty->termios_mutex);
  618 + if (tty->ops->set_termiox)
  619 + tty->ops->set_termiox(tty, &tnew);
  620 + mutex_unlock(&tty->termios_mutex);
  621 + return 0;
  622 +}
  623 +
  624 +#endif
  625 +
582 626 static unsigned long inq_canon(struct tty_struct *tty)
583 627 {
584 628 int nr, head, tail;
... ... @@ -936,6 +980,20 @@
936 980 return -EFAULT;
937 981 return 0;
938 982 #endif
  983 +#ifdef TCGETX
  984 + case TCGETX:
  985 + if (real_tty->termiox == NULL)
  986 + return -EINVAL;
  987 + if (copy_to_user(p, real_tty->termiox, sizeof(struct termiox)))
  988 + return -EFAULT;
  989 + return 0;
  990 + case TCSETX:
  991 + return set_termiox(real_tty, p, 0);
  992 + case TCSETXW:
  993 + return set_termiox(real_tty, p, TERMIOS_WAIT);
  994 + case TCSETXF:
  995 + return set_termiox(real_tty, p, TERMIOS_FLUSH);
  996 +#endif
939 997 case TIOCGSOFTCAR:
940 998 /* FIXME: for correctness we may need to take the termios
941 999 lock here - review */
include/asm-x86/ioctls.h
... ... @@ -56,6 +56,10 @@
56 56 #define TIOCGPTN _IOR('T', 0x30, unsigned int)
57 57 /* Get Pty Number (of pty-mux device) */
58 58 #define TIOCSPTLCK _IOW('T', 0x31, int) /* Lock/unlock Pty */
  59 +#define TCGETX 0x5432 /* SYS5 TCGETX compatibility */
  60 +#define TCSETX 0x5433
  61 +#define TCSETXF 0x5434
  62 +#define TCSETXW 0x5435
59 63  
60 64 #define FIONCLEX 0x5450
61 65 #define FIOCLEX 0x5451
include/linux/termios.h
... ... @@ -4,5 +4,20 @@
4 4 #include <linux/types.h>
5 5 #include <asm/termios.h>
6 6  
  7 +#define NFF 5
  8 +
  9 +struct termiox
  10 +{
  11 + __u16 x_hflag;
  12 + __u16 x_cflag;
  13 + __u16 x_rflag[NFF];
  14 + __u16 x_sflag;
  15 +};
  16 +
  17 +#define RTSXOFF 0x0001 /* RTS flow control on input */
  18 +#define CTSXON 0x0002 /* CTS flow control on output */
  19 +#define DTRXOFF 0x0004 /* DTR flow control on input */
  20 +#define DSRXON 0x0008 /* DCD flow control on output */
  21 +
7 22 #endif
... ... @@ -219,6 +219,7 @@
219 219 spinlock_t ctrl_lock;
220 220 /* Termios values are protected by the termios mutex */
221 221 struct ktermios *termios, *termios_locked;
  222 + struct termiox *termiox; /* May be NULL for unsupported */
222 223 char name[64];
223 224 struct pid *pgrp; /* Protected by ctrl lock */
224 225 struct pid *session;
include/linux/tty_driver.h
... ... @@ -180,6 +180,14 @@
180 180 * not force errors here if they are not resizable objects (eg a serial
181 181 * line). See tty_do_resize() if you need to wrap the standard method
182 182 * in your own logic - the usual case.
  183 + *
  184 + * void (*set_termiox)(struct tty_struct *tty, struct termiox *new);
  185 + *
  186 + * Called when the device receives a termiox based ioctl. Passes down
  187 + * the requested data from user space. This method will not be invoked
  188 + * unless the tty also has a valid tty->termiox pointer.
  189 + *
  190 + * Optional: Called under the termios lock
183 191 */
184 192  
185 193 #include <linux/fs.h>
... ... @@ -220,6 +228,7 @@
220 228 unsigned int set, unsigned int clear);
221 229 int (*resize)(struct tty_struct *tty, struct tty_struct *real_tty,
222 230 struct winsize *ws);
  231 + int (*set_termiox)(struct tty_struct *tty, struct termiox *tnew);
223 232 #ifdef CONFIG_CONSOLE_POLL
224 233 int (*poll_init)(struct tty_driver *driver, int line, char *options);
225 234 int (*poll_get_char)(struct tty_driver *driver, int line);