All of lore.kernel.org
 help / color / mirror / Atom feed
From: Dominique Larchey-Wendling <Dominique.Larchey-Wendling@loria.fr>
To: linux-serial@vger.kernel.org
Subject: New IOCTL for Modem Control Lines monitoring
Date: Thu, 25 Jan 2007 18:09:33 +0100	[thread overview]
Message-ID: <45B8E44D.5050005@loria.fr> (raw)

In kernel 2.6 (file drivers/serial/serial_core.c), there exists 2 IOCTL
for receiving signals over the modem control lines

TIOCMIWAIT  (function uart_wait_modem_status) for waiting for a change
             on the modem status lines.

TIOCGICOUNT (uart_get_count) to get the current state of the modem
              status lines.

While these IOCTL may be helpful to use the serial port as a general
serial communication device over modem control lines like in
the following (and quite old) discussion

http://www.mail-archive.com/linux-serial@vger.rutgers.edu/msg00407.html

I find a kind of "design" flaw with the 2 IOCTL for such a goal.

Indeed, it is possible that a modem status change occurs in between
ioctl(TIOCGICOUNT) and ioctl(TIOCMIWAIT) possibly locking a
communication because the last call would miss the status change
necessary to trigger a response. Indeed ioctl(TIOCMIWAIT) cannot
detect a change occurring before its call.

Even tough such an event would have a low probability to occur
if the 2 ioctl are close enough, it is still possible. This is
a race condition (outside the kernel but possibly locking some
process).

I propose the introduction of a new ioctl to solve this race,
implemented through the NEW function uart_wait_new_status associated
to a NEW ioctl.

The idea is that this new call would detect a change not compared
to the status at the beginning of the call but compared to some
previously recorded state. This way, the new ioctl would not
miss a status change, even if it occurs before the call to the
ioctl.

Could it be considered for inclusion in the kernel ?
It does not change any existing behavior. However it
does need a new ioctl name/number.

Thanks in advance for any comment

Dominique Larchey-Wendling
CNRS, France

-------------------------------------------------
Code to include in drivers/serial/serial_core.c
-------------------------------------------------

/*
  * Wait until any NEW signal is received on some selected
  * modem inputs lines (DCD,RI,DSR,CTS), compared to some
  * previously considered state.
  * If asked to wait on none, simply returns the current
  * status
  */

static int
uart_wait_new_status(struct uart_state *state, struct 
serial_icounter_struct __user *icnt)
{
	struct uart_port *port = state->port;
	DECLARE_WAITQUEUE(wait, current);
         struct serial_icounter_struct icount;
	struct uart_icount cstart, cnow;
         unsigned int mask, mctrl;
	int ret;

         if (copy_from_user(&icount, icnt, sizeof(icount)))
                 return -EFAULT;

         cstart.cts         = icount.cts;
         cstart.dsr         = icount.dsr;
         cstart.rng         = icount.rng;
         cstart.dcd         = icount.dcd;
         cstart.rx          = icount.rx;
         cstart.tx          = icount.tx;
         cstart.frame       = icount.frame;
         cstart.overrun     = icount.overrun;
         cstart.parity      = icount.parity;
         cstart.buf_overrun = icount.buf_overrun;

         /* if mask == 0 just simulate behavior of TIOCGICOUNT
          */

         mask = (unsigned) icount.reserved[0];

         /* enable Modem Status Interrupts in case not already done
          */

	spin_lock_irq(&port->lock);
	port->ops->enable_ms(port);
	spin_unlock_irq(&port->lock);

	add_wait_queue(&state->info->delta_msr_wait, &wait);

	for (;;) {
		spin_lock_irq(&port->lock);
                 mctrl = port->ops->get_mctrl(port);
		memcpy(&cnow, &port->icount, sizeof(struct uart_icount));
		spin_unlock_irq(&port->lock);

		set_current_state(TASK_INTERRUPTIBLE);

		if (((mask & TIOCM_RNG) && (cnow.rng != cstart.rng)) ||
		    ((mask & TIOCM_DSR) && (cnow.dsr != cstart.dsr)) ||
		    ((mask & TIOCM_CAR) && (cnow.dcd != cstart.dcd)) ||
		    ((mask & TIOCM_CTS) && (cnow.cts != cstart.cts)) ||
                      (mask == 0))
                 {
		    	ret = 0;
		    	break;
		}

		schedule();

		/* see if a signal did it */
		if (signal_pending(current)) {
			ret = -ERESTARTSYS;
			break;
		}

	}

	current->state = TASK_RUNNING;
	remove_wait_queue(&state->info->delta_msr_wait, &wait);

         if (ret < 0) return ret;

         /* we got our (new) state, transfer to user space
          */

         icount.cts         = cnow.cts;
	icount.dsr         = cnow.dsr;
	icount.rng         = cnow.rng;
	icount.dcd         = cnow.dcd;
	icount.rx          = cnow.rx;
	icount.tx          = cnow.tx;
	icount.frame       = cnow.frame;
	icount.overrun     = cnow.overrun;
	icount.parity      = cnow.parity;
	icount.brk         = cnow.brk;
	icount.buf_overrun = cnow.buf_overrun;
         icount.reserved[0] = mctrl;

         return copy_to_user(icnt, &icount, sizeof(icount)) ? -EFAULT : 0;
}

             reply	other threads:[~2007-01-25 17:19 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2007-01-25 17:09 Dominique Larchey-Wendling [this message]
2007-01-25 18:34 ` New IOCTL for Modem Control Lines monitoring Tosoni
2007-01-25 19:00   ` Dominique Larchey
2007-01-30  2:39 ` Theodore Tso
2007-01-30 17:19   ` Dominique Larchey-Wendling

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=45B8E44D.5050005@loria.fr \
    --to=dominique.larchey-wendling@loria.fr \
    --cc=linux-serial@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.