Commit 1d65b4a0 authored by Alan Cox's avatar Alan Cox Committed by Linus Torvalds

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: default avatarAlan Cox <alan@redhat.com>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 5aaa70a8
...@@ -579,6 +579,50 @@ static int get_termio(struct tty_struct *tty, struct termio __user *termio) ...@@ -579,6 +579,50 @@ static int get_termio(struct tty_struct *tty, struct termio __user *termio)
return 0; 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) static unsigned long inq_canon(struct tty_struct *tty)
{ {
int nr, head, tail; int nr, head, tail;
...@@ -935,6 +979,20 @@ int tty_mode_ioctl(struct tty_struct *tty, struct file *file, ...@@ -935,6 +979,20 @@ int tty_mode_ioctl(struct tty_struct *tty, struct file *file,
(struct termios __user *) arg)) (struct termios __user *) arg))
return -EFAULT; return -EFAULT;
return 0; 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 #endif
case TIOCGSOFTCAR: case TIOCGSOFTCAR:
/* FIXME: for correctness we may need to take the termios /* FIXME: for correctness we may need to take the termios
......
...@@ -56,6 +56,10 @@ ...@@ -56,6 +56,10 @@
#define TIOCGPTN _IOR('T', 0x30, unsigned int) #define TIOCGPTN _IOR('T', 0x30, unsigned int)
/* Get Pty Number (of pty-mux device) */ /* Get Pty Number (of pty-mux device) */
#define TIOCSPTLCK _IOW('T', 0x31, int) /* Lock/unlock Pty */ #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 FIONCLEX 0x5450
#define FIOCLEX 0x5451 #define FIOCLEX 0x5451
......
...@@ -4,4 +4,19 @@ ...@@ -4,4 +4,19 @@
#include <linux/types.h> #include <linux/types.h>
#include <asm/termios.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 #endif
...@@ -219,6 +219,7 @@ struct tty_struct { ...@@ -219,6 +219,7 @@ struct tty_struct {
spinlock_t ctrl_lock; spinlock_t ctrl_lock;
/* Termios values are protected by the termios mutex */ /* Termios values are protected by the termios mutex */
struct ktermios *termios, *termios_locked; struct ktermios *termios, *termios_locked;
struct termiox *termiox; /* May be NULL for unsupported */
char name[64]; char name[64];
struct pid *pgrp; /* Protected by ctrl lock */ struct pid *pgrp; /* Protected by ctrl lock */
struct pid *session; struct pid *session;
......
...@@ -180,6 +180,14 @@ ...@@ -180,6 +180,14 @@
* not force errors here if they are not resizable objects (eg a serial * 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 * line). See tty_do_resize() if you need to wrap the standard method
* in your own logic - the usual case. * 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> #include <linux/fs.h>
...@@ -220,6 +228,7 @@ struct tty_operations { ...@@ -220,6 +228,7 @@ struct tty_operations {
unsigned int set, unsigned int clear); unsigned int set, unsigned int clear);
int (*resize)(struct tty_struct *tty, struct tty_struct *real_tty, int (*resize)(struct tty_struct *tty, struct tty_struct *real_tty,
struct winsize *ws); struct winsize *ws);
int (*set_termiox)(struct tty_struct *tty, struct termiox *tnew);
#ifdef CONFIG_CONSOLE_POLL #ifdef CONFIG_CONSOLE_POLL
int (*poll_init)(struct tty_driver *driver, int line, char *options); int (*poll_init)(struct tty_driver *driver, int line, char *options);
int (*poll_get_char)(struct tty_driver *driver, int line); int (*poll_get_char)(struct tty_driver *driver, int line);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment