Re: [PATCH] [RFC] Userspace serial drivers: PTY changes.

Rogier Wolff (R.E.Wolff@BitWizard.nl)
Wed, 12 Mar 2003 18:19:49 +0100


This is a MIME-formatted message. If you see this text it means that your
E-mail software does not support MIME-formatted messages.

--=_courier-3432-1047489662-0001-2
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit
Content-Disposition: inline

On Wed, Mar 12, 2003 at 08:22:50AM -0800, H. Peter Anvin wrote:
> Followup to: <20030312142822.A12206@bitwizard.nl>
> By author: Rogier Wolff <R.E.Wolff@BitWizard.nl>
> In newsgroup: linux.dev.kernel
> >
> > So we implemented all this. Patch attached. What do you think?
> >
>
> -ENOPATCH?

--EAGREE

-- 
** R.E.Wolff@BitWizard.nl ** http://www.BitWizard.nl/ ** +31-15-2600998 **
*-- BitWizard writes Linux device drivers for any device you may have! --*
* The Worlds Ecosystem is a stable system. Stable systems may experience *
* excursions from the stable situation. We are currently in such an      * 
* excursion: The stable situation does not include humans. ***************

--=_courier-3432-1047489662-0001-2 Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="patch-2.4.20.trueport-12-mrt"

diff -ur linux-2.4.20.clean/drivers/char/pty.c linux-2.4.20.trueport2/drivers/char/pty.c --- linux-2.4.20.clean/drivers/char/pty.c Sat Aug 3 02:39:43 2002 +++ linux-2.4.20.trueport2/drivers/char/pty.c Wed Mar 12 10:56:08 2003 @@ -262,16 +262,109 @@ return 0; } +static int pty_slave_ioctl(struct tty_struct *tty, struct file *file, + unsigned int cmd, unsigned long arg) +{ + + struct tty_struct * real_tty; + + if (!tty) { + printk(KERN_ERR "%scalled with NULL tty!\n", __FUNCTION__); + return -EIO; + } + + if (tty->driver.type == TTY_DRIVER_TYPE_PTY && + tty->driver.subtype == PTY_TYPE_MASTER) + real_tty = tty->link; + else + real_tty = tty; + + switch(cmd) { + case TIOCSBRK: + case TCSBRK: + case TCSBRKP: + if (tty->link && tty->link->packet) { + tty->ctrl_status |= TIOCPKT_BREAK; + wake_up_interruptible(&tty->link->read_wait); + } + return 0; + case TIOCMBIC: + case TIOCMBIS: + case TIOCMSET: { + unsigned int new_val; + + get_user(arg, (unsigned int *) arg); + + new_val = real_tty->modem_status; + switch (cmd) { + case TIOCMBIC: + new_val &= ~arg; + break; + case TIOCMBIS: + new_val |= arg; + break; + case TIOCMSET: + new_val = arg; + break; + } + + if (new_val != real_tty->modem_status) { + printk ("New status: 0x%x 0x%x\n", new_val , real_tty->modem_status); + real_tty->modem_status = new_val; + real_tty->link->modem_status = new_val; + + if (real_tty->link && real_tty->link->packet) { + real_tty->ctrl_status |= TIOCPKT_SIGNALS; + wake_up_interruptible(&real_tty->link->read_wait); + } + } + + return 0; + } + case TIOCMGET: + printk ("Getting modem status: 0x%x\n", real_tty->modem_status); + if (put_user (real_tty->modem_status, (unsigned int*)arg)) + return -EFAULT; + return 0; + } + + + + return -ENOIOCTLCMD; +} + +int set_termios(struct tty_struct * tty, unsigned long arg, int opt); + + static int pty_bsd_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg) { + struct tty_struct * real_tty; + if (!tty) { printk("pty_ioctl called with NULL tty!\n"); return -EIO; } + + if (tty->driver.type == TTY_DRIVER_TYPE_PTY && + tty->driver.subtype == PTY_TYPE_MASTER) + real_tty = tty->link; + else + real_tty = tty; + + switch(cmd) { case TIOCSPTLCK: /* Set PT Lock (disallow slave open) */ return pty_set_lock(tty, (int *) arg); + case TCGETS: + if (kernel_termios_to_user_termios((struct termios *)arg, real_tty->termios)) + return -EFAULT; + return 0; + case TIOCMSET: + get_user(arg, (unsigned int *) arg); + tty->modem_status = arg; + tty->link->modem_status = arg; + return 0; } return -ENOIOCTLCMD; } @@ -352,6 +445,11 @@ { tty->termios->c_cflag &= ~(CSIZE | PARENB); tty->termios->c_cflag |= (CS8 | CREAD); + + if (tty->link && tty->link->packet) { + tty->ctrl_status |= TIOCPKT_TERMIOS; + wake_up_interruptible(&tty->link->read_wait); + } } int __init pty_init(void) @@ -420,6 +518,7 @@ pty_slave_driver.termios_locked = ttyp_termios_locked; pty_slave_driver.driver_state = pty_state; pty_slave_driver.other = &pty_driver; + pty_slave_driver.ioctl = pty_slave_ioctl; if (tty_register_driver(&pty_driver)) panic("Couldn't register pty driver"); diff -ur linux-2.4.20.clean/drivers/char/tty_ioctl.c linux-2.4.20.trueport2/drivers/char/tty_ioctl.c --- linux-2.4.20.clean/drivers/char/tty_ioctl.c Wed Dec 18 12:09:13 2002 +++ linux-2.4.20.trueport2/drivers/char/tty_ioctl.c Wed Mar 12 10:56:08 2003 @@ -138,7 +138,7 @@ (*tty->ldisc.set_termios)(tty, &old_termios); } -static int set_termios(struct tty_struct * tty, unsigned long arg, int opt) +int set_termios(struct tty_struct * tty, unsigned long arg, int opt) { struct termios tmp_termios; int retval = tty_check_change(tty); @@ -505,6 +505,44 @@ ((tty->termios->c_cflag & ~CLOCAL) | (arg ? CLOCAL : 0)); return 0; + case TIOCMGET: + if (put_user (tty->link->modem_status, (unsigned int*)arg)) + return -EFAULT; + return 0; + case TIOCMSET: { + unsigned int new_val; + get_user(new_val, (unsigned int *) arg); + real_tty->modem_status = new_val; + real_tty->link->modem_status = new_val; + return 0; + } + case TIOCMBIC: + if (get_user (arg, (unsigned int *) arg)) + return -EFAULT; + + if (arg & TIOCM_DTR) + tty->link->modem_status &= ~TIOCM_DTR; + + if (arg & TIOCM_RTS) + tty->link->modem_status &= ~ TIOCM_RTS; + + wake_up_interruptible(&tty->link->read_wait); + return 0; + + + case TIOCMBIS: + if (get_user (arg, (unsigned int *) arg)) + return -EFAULT; + + if (arg & TIOCM_DTR) + tty->link->modem_status |= TIOCM_DTR; + + if (arg & TIOCM_RTS) + tty->link->modem_status |= TIOCM_RTS; + + wake_up_interruptible(&tty->link->read_wait); + return 0; + default: return -ENOIOCTLCMD; } diff -ur linux-2.4.20.clean/include/asm-i386/ioctls.h linux-2.4.20.trueport2/include/asm-i386/ioctls.h --- linux-2.4.20.clean/include/asm-i386/ioctls.h Sat Aug 3 02:39:45 2002 +++ linux-2.4.20.trueport2/include/asm-i386/ioctls.h Wed Mar 12 11:00:37 2003 @@ -77,6 +77,16 @@ #define TIOCPKT_NOSTOP 16 #define TIOCPKT_DOSTOP 32 +/* Ugly hack. We use one bit for two purposes to prevent having to expand + the byte (API!). The deal is that you pretend that they are separate bits + when setting or reading these bits. However when you check if a bit is + set (indicating something changed), you have to be prepared that it + in fact didn't change at all..... (As you also have to be prepared to + handle the case where it changed back before you noticed it.) -- REW */ +#define TIOCPKT_SIGNALS 64 +#define TIOCPKT_TERMIOS 64 +#define TIOCPKT_BREAK 128 + #define TIOCSER_TEMT 0x01 /* Transmitter physically empty */ #endif diff -ur linux-2.4.20.clean/include/linux/tty.h linux-2.4.20.trueport2/include/linux/tty.h --- linux-2.4.20.clean/include/linux/tty.h Thu Feb 27 15:13:27 2003 +++ linux-2.4.20.trueport2/include/linux/tty.h Wed Mar 12 10:56:24 2003 @@ -270,6 +270,7 @@ unsigned char stopped:1, hw_stopped:1, flow_stopped:1, packet:1; unsigned char low_latency:1, warned:1; unsigned char ctrl_status; + unsigned int modem_status; struct tty_struct *link; struct fasync_struct *fasync;

--=_courier-3432-1047489662-0001-2--