Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753168AbYC3MYH (ORCPT ); Sun, 30 Mar 2008 08:24:07 -0400 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1751474AbYC3MXz (ORCPT ); Sun, 30 Mar 2008 08:23:55 -0400 Received: from mail2.hosting.nl ([62.129.139.44]:38874 "HELO mail2.hosting.nl" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with SMTP id S1751419AbYC3MXy convert rfc822-to-8bit (ORCPT ); Sun, 30 Mar 2008 08:23:54 -0400 X-Greylist: delayed 399 seconds by postgrey-1.27 at vger.kernel.org; Sun, 30 Mar 2008 08:23:53 EDT Message-ID: <20080330140948.0cqmtqb9us880cw8@62.129.139.44> Date: Sun, 30 Mar 2008 14:09:48 +0200 From: postmaster@van-ginkel.eu To: linux-kernel@vger.kernel.org Subject: Re: [PATCH] ptmx: adding handshake support References: <20080311212830.5f4apfr4uqs884cc@62.129.139.44> In-Reply-To: <20080311212830.5f4apfr4uqs884cc@62.129.139.44> MIME-Version: 1.0 Content-Type: text/plain; charset=US-ASCII; DelSp=Yes format=flowed Content-Disposition: inline Content-Transfer-Encoding: 7BIT User-Agent: Internet Messaging Program (IMP) H3 (4.1.3) Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 11153 Lines: 413 This weekend I upgraded my kernel to 2.6.22.5 and tried my patch. Unfortunately pty.c seems to be a slightly different, so generated a new patch: Signed-off-by: Sander van Ginkel =================================================================== --- linux-2.6.22.5.orig/drivers/char/pty.c 2007-08-23 01:23:54.000000000 +0200 +++ linux-2.6.22.5.new/drivers/char/pty.c 2008-03-23 15:25:24.000000000 +0100 @@ -7,6 +7,8 @@ * -- C. Scott Ananian , 14-Jan-1998 * Added TTY_DO_WRITE_WAKEUP to enable n_tty to send POLL_OUT to * waiting writers -- Sapan Bhatia + * Added support for MCR/MSR, used for serial over ethernet + * -- Sander van Ginkel * * */ @@ -29,6 +31,16 @@ #include #include +struct pty_mcrmsr { + + struct semaphore sem; /* locks this structure */ + + /* for tiocmget and tiocmset functions */ + + int msr; /* MSR shadow */ + int mcr; /* MCR shadow */ +}; + /* These are global because they are accessed in tty_io.c */ #ifdef CONFIG_UNIX98_PTYS struct tty_driver *ptm_driver; @@ -196,6 +208,7 @@ static int pty_open(struct tty_struct *tty, struct file * filp) { + struct pty_mcrmsr *mcrmsr; int retval = -ENODEV; if (!tty || !tty->link) @@ -213,10 +226,90 @@ set_bit(TTY_THROTTLED, &tty->flags); set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags); retval = 0; + + /* initialize the pointer in case something fails */ + + tty->driver_data = NULL; + tty->link->driver_data = NULL; + + /* first time accessing this device, let's create it */ + + mcrmsr = kmalloc(sizeof(*mcrmsr), GFP_KERNEL); + + init_MUTEX(&mcrmsr->sem); + + if (mcrmsr != NULL) { + down(&mcrmsr->sem); + + /* save our structure within the tty structure */ + + mcrmsr->mcr=0; + mcrmsr->msr=0; + + tty->driver_data = mcrmsr; + tty->link->driver_data = mcrmsr; + + up(&mcrmsr->sem); + + } + out: return retval; } +static int pty_tiocmget(struct tty_struct *tty, struct file *file) +{ + struct pty_mcrmsr *mcrmsr = tty->driver_data; + unsigned int result = 0; + unsigned int msr=0; + unsigned int mcr=0; + + if (tty->driver_data != NULL) { + msr = mcrmsr->msr; + mcr = mcrmsr->mcr; + } + + result = ((mcr & 0x01) ? TIOCM_DTR : 0) | /* DTR is set */ + ((mcr & 0x02) ? TIOCM_RTS : 0) | /* RTS is set */ + ((mcr & 0x04) ? TIOCM_LOOP : 0) | /* LOOP is set */ + ((msr & 0x08) ? TIOCM_CTS : 0) | /* CTS is set */ + ((msr & 0x10) ? TIOCM_CAR : 0) | /* Carrier detect is set*/ + ((msr & 0x20) ? TIOCM_RI : 0) | /* Ring Indicator is set */ + ((msr & 0x40) ? TIOCM_DSR : 0); /* DSR is set */ + + return result; +} + +static int pty_tiocmset(struct tty_struct *tty, struct file *file,unsigned int set, unsigned int clear) +{ + struct pty_mcrmsr *mcrmsr = tty->driver_data; + unsigned int mcr=0; + + if (tty->driver_data != NULL) + mcr = mcrmsr->mcr; + + if (set & TIOCM_DTR) + mcr |= 0x01; + if (set & TIOCM_RTS) + mcr |= 0x02; + if (set & TIOCM_LOOP) + mcr |= 0x04; + + if (clear & TIOCM_DTR) + mcr &= ~0x01; + if (clear & TIOCM_RTS) + mcr &= ~0x02; + if (clear & TIOCM_LOOP) + mcr &= ~0x04; + + /* set the new MCR value in the device */ + + if (tty->driver_data != NULL) + mcrmsr->mcr=mcr; + + return 0; +} + static void pty_set_termios(struct tty_struct *tty, struct ktermios *old_termios) { tty->termios->c_cflag &= ~(CSIZE | PARENB); @@ -232,6 +325,8 @@ .chars_in_buffer = pty_chars_in_buffer, .unthrottle = pty_unthrottle, .set_termios = pty_set_termios, + .tiocmget = pty_tiocmget, + .tiocmset = pty_tiocmset, }; /* Traditional BSD devices */ @@ -338,11 +433,44 @@ static int pty_unix98_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg) { + unsigned int value; + struct pty_mcrmsr *mcrmsr = tty->driver_data; + unsigned int msr=0; + unsigned int mcr=0; + switch (cmd) { case TIOCSPTLCK: /* Set PT Lock (disallow slave open) */ return pty_set_lock(tty, (int __user *)arg); case TIOCGPTN: /* Get PT Number */ return put_user(tty->index, (unsigned int __user *)arg); + + case 0x5426: /* Set all of the handshake line, even the normally read only */ + { + if (copy_from_user(&value,(unsigned int *)arg,sizeof(unsigned int))) + return -EFAULT; + + if (value & 0x0002) /* DTR set */ + mcr|=0x01; + if (value & 0x0004) /* RTS set */ + mcr|=0x02; + if (value & 0x8000) /* LOOP set */ + mcr|=0x04; + if (value & 0x0020) /* CTS set */ + msr|=0x08; + if (value & 0x0040) /* DCD set */ + msr|=0x10; + if (value & 0x0080) /* RI set */ + msr|=0x20; + if (value & 0x0100) /* DSR set */ + msr|=0x40; + + if (tty->driver_data != NULL) + { + mcrmsr->msr=msr; + mcrmsr->mcr=mcr; + } + return 0; + } } return -ENOIOCTLCMD; Quoting sander van ginkel : > For serial over ethernet communication, /dev/ptmx will be used to > create a virtual device. > Due to the lack of a modem status register and a modem control register > in the ptmx driver, > it won't be possible to transfer handshake signaling. > > I wrote this patch to add these registers to the ptmx driver. > The modem status register, which controls CD,CTS,DSR,RI is normally > read-only. To be able to > pass these signals from the remote port to the local ptmx device, I've > added an IOCTL routine. > The result of a remote TIOCMGET IOCTL call , can be passed directly > through this IOCTL routine. > The IOCTL value I used for this is, 0x5426 which was formerly known as > TIOCTTYGSTRUCT. > > I've tested this patch at an 2.6.16.27 kernel. > > Suggestions and/or other test results are welcome. > > Sander > > > Signed-off-by: Sander van Ginkel > > =================================================================== > --- drivers/char/pty.c 2008-03-03 20:02:09.000000000 +0100 > +++ drivers/char/pty-new.c 2008-03-02 21:55:53.000000000 +0100 > @@ -7,6 +7,8 @@ > * -- C. Scott Ananian , 14-Jan-1998 > * Added TTY_DO_WRITE_WAKEUP to enable n_tty to send POLL_OUT to > * waiting writers -- Sapan Bhatia > + * Added support for MCR/MSR, used for serial over ethernet > + * -- Sander van Ginkel > * > * > */ > @@ -32,6 +34,16 @@ > #include > #include > > +struct pty_mcrmsr { > + > + struct semaphore sem; /* locks this structure */ > + > + /* for tiocmget and tiocmset functions */ > + > + int msr; /* MSR shadow */ > + int mcr; /* MCR shadow */ > +}; > + > /* These are global because they are accessed in tty_io.c */ > #ifdef CONFIG_UNIX98_PTYS > struct tty_driver *ptm_driver; > @@ -199,6 +211,7 @@ > > static int pty_open(struct tty_struct *tty, struct file * filp) > { > + struct pty_mcrmsr *mcrmsr; > int retval = -ENODEV; > > if (!tty || !tty->link) > @@ -216,10 +229,90 @@ > set_bit(TTY_THROTTLED, &tty->flags); > set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags); > retval = 0; > + > + /* initialize the pointer in case something fails */ > + > + tty->driver_data = NULL; > + tty->link->driver_data = NULL; > + > + /* first time accessing this device, let's create it */ > + > + mcrmsr = kmalloc(sizeof(*mcrmsr), GFP_KERNEL); > + > + init_MUTEX(&mcrmsr->sem); > + > + if (mcrmsr != NULL) { > + down(&mcrmsr->sem); > + > + /* save our structure within the tty structure */ > + > + mcrmsr->mcr=0; > + mcrmsr->msr=0; > + > + tty->driver_data = mcrmsr; > + tty->link->driver_data = mcrmsr; > + > + up(&mcrmsr->sem); > + > + } > + > out: > return retval; > } > > +static int pty_tiocmget(struct tty_struct *tty, struct file *file) > +{ > + struct pty_mcrmsr *mcrmsr = tty->driver_data; > + unsigned int result = 0; > + unsigned int msr=0; > + unsigned int mcr=0; > + > + if (tty->driver_data != NULL) { > + msr = mcrmsr->msr; > + mcr = mcrmsr->mcr; > + } > + > + result = ((mcr & 0x01) ? TIOCM_DTR : 0) | /* DTR is set */ > + ((mcr & 0x02) ? TIOCM_RTS : 0) | /* RTS is set */ > + ((mcr & 0x04) ? TIOCM_LOOP : 0) | /* LOOP is set */ > + ((msr & 0x08) ? TIOCM_CTS : 0) | /* CTS is set */ > + ((msr & 0x10) ? TIOCM_CAR : 0) | /* Carrier detect is set*/ > + ((msr & 0x20) ? TIOCM_RI : 0) | /* Ring Indicator is set */ > + ((msr & 0x40) ? TIOCM_DSR : 0); /* DSR is set */ > + > + return result; > +} > + > +static int pty_tiocmset(struct tty_struct *tty, struct file > *file,unsigned int set, unsigned int clear) > +{ > + struct pty_mcrmsr *mcrmsr = tty->driver_data; > + unsigned int mcr=0; > + > + if (tty->driver_data != NULL) > + mcr = mcrmsr->mcr; > + > + if (set & TIOCM_DTR) > + mcr |= 0x01; > + if (set & TIOCM_RTS) > + mcr |= 0x02; > + if (set & TIOCM_LOOP) > + mcr |= 0x04; > + > + if (clear & TIOCM_DTR) > + mcr &= ~0x01; > + if (clear & TIOCM_RTS) > + mcr &= ~0x02; > + if (clear & TIOCM_LOOP) > + mcr &= ~0x04; > + > + /* set the new MCR value in the device */ > + > + if (tty->driver_data != NULL) > + mcrmsr->mcr=mcr; > + > + return 0; > +} > + > static void pty_set_termios(struct tty_struct *tty, struct termios > *old_termios) > { > tty->termios->c_cflag &= ~(CSIZE | PARENB); > @@ -235,6 +328,8 @@ > .chars_in_buffer = pty_chars_in_buffer, > .unthrottle = pty_unthrottle, > .set_termios = pty_set_termios, > + .tiocmget = pty_tiocmget, > + .tiocmset = pty_tiocmset, > }; > > /* Traditional BSD devices */ > @@ -339,11 +434,44 @@ > static int pty_unix98_ioctl(struct tty_struct *tty, struct file *file, > unsigned int cmd, unsigned long arg) > { > + unsigned int value; > + struct pty_mcrmsr *mcrmsr = tty->driver_data; > + unsigned int msr=0; > + unsigned int mcr=0; > + > switch (cmd) { > case TIOCSPTLCK: /* Set PT Lock (disallow slave open) */ > return pty_set_lock(tty, (int __user *)arg); > case TIOCGPTN: /* Get PT Number */ > return put_user(tty->index, (unsigned int __user *)arg); > + > + case 0x5426: /* Set all of the handshake line, even the normally read > only */ > + { > + if (copy_from_user(&value,(unsigned int *)arg,sizeof(unsigned int))) > + return -EFAULT; > + > + if (value & 0x0002) /* DTR set */ > + mcr|=0x01; > + if (value & 0x0004) /* RTS set */ > + mcr|=0x02; > + if (value & 0x8000) /* LOOP set */ > + mcr|=0x04; > + if (value & 0x0020) /* CTS set */ > + msr|=0x08; > + if (value & 0x0040) /* DCD set */ > + msr|=0x10; > + if (value & 0x0080) /* RI set */ > + msr|=0x20; > + if (value & 0x0100) /* DSR set */ > + msr|=0x40; > + > + if (tty->driver_data != NULL) > + { > + mcrmsr->msr=msr; > + mcrmsr->mcr=mcr; > + } > + return 0; > + } > } > > return -ENOIOCTLCMD; -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/