Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Alan Cox and committed by
Linus Torvalds
1d65b4a0 5aaa70a8

+87
+58
drivers/char/tty_ioctl.c
··· 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; ··· 980 936 return -EFAULT; 981 937 return 0; 982 938 #endif 939 + #ifdef TCGETX 940 + case TCGETX: 941 + if (real_tty->termiox == NULL) 942 + return -EINVAL; 943 + if (copy_to_user(p, real_tty->termiox, sizeof(struct termiox))) 944 + return -EFAULT; 945 + return 0; 946 + case TCSETX: 947 + return set_termiox(real_tty, p, 0); 948 + case TCSETXW: 949 + return set_termiox(real_tty, p, TERMIOS_WAIT); 950 + case TCSETXF: 951 + return set_termiox(real_tty, p, TERMIOS_FLUSH); 952 + #endif 983 953 case TIOCGSOFTCAR: 984 954 /* FIXME: for correctness we may need to take the termios 985 955 lock here - review */
+4
include/asm-x86/ioctls.h
··· 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
+15
include/linux/termios.h
··· 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
+1
include/linux/tty.h
··· 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;
+9
include/linux/tty_driver.h
··· 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> ··· 228 220 unsigned int set, unsigned int clear); 229 221 int (*resize)(struct tty_struct *tty, struct tty_struct *real_tty, 230 222 struct winsize *ws); 223 + int (*set_termiox)(struct tty_struct *tty, struct termiox *tnew); 231 224 #ifdef CONFIG_CONSOLE_POLL 232 225 int (*poll_init)(struct tty_driver *driver, int line, char *options); 233 226 int (*poll_get_char)(struct tty_driver *driver, int line);