All of lore.kernel.org
 help / color / mirror / Atom feed
From: sander van ginkel <sander@van-ginkel.eu>
To: linux-kernel@vger.kernel.org
Subject: [PATCH] ptmx: adding handshake support
Date: Tue, 11 Mar 2008 22:19:42 +0100	[thread overview]
Message-ID: <47D6F76E.2090706@van-ginkel.eu> (raw)

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 <sander@van-ginkel.eu>

===================================================================
--- 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 <cananian@alumni.princeton.edu>, 14-Jan-1998
  *  Added TTY_DO_WRITE_WAKEUP to enable n_tty to send POLL_OUT to
  *      waiting writers -- Sapan Bhatia <sapan@corewars.org>
+ *  Added support for MCR/MSR, used for serial over ethernet
+ *    -- Sander van Ginkel <sander@van-ginkel.eu>
  *
  *
  */
@@ -32,6 +34,16 @@
 #include <linux/bitops.h>
 #include <linux/devpts_fs.h>
 
+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;


             reply	other threads:[~2008-03-11 21:15 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-03-11 21:19 sander van ginkel [this message]
  -- strict thread matches above, loose matches on Subject: below --
2008-03-11 20:28 [PATCH] ptmx: adding handshake support sander van ginkel
2008-03-30 12:09 ` postmaster
2008-03-30 12:16   ` Alan Cox
2008-03-30 12:48     ` sander van ginkel
2008-04-13 15:42     ` sander van ginkel
2008-04-13 22:35       ` Alan Cox
2008-04-14 20:39         ` sander van ginkel
2008-04-14 20:02           ` Randy Dunlap
2008-04-29 18:01           ` Alan Cox

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=47D6F76E.2090706@van-ginkel.eu \
    --to=sander@van-ginkel.eu \
    --cc=linux-kernel@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.