ChangeSet 1.1504.2.4, 2003/12/05 10:58:30-08:00, dancy@dancysoft.com [PATCH] USB: add TIOCMIWAIT support to pl2303 driver drivers/usb/serial/pl2303.c | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 43 insertions(+) diff -Nru a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c --- a/drivers/usb/serial/pl2303.c Mon Dec 29 14:26:47 2003 +++ b/drivers/usb/serial/pl2303.c Mon Dec 29 14:26:47 2003 @@ -169,6 +169,7 @@ struct pl2303_private { spinlock_t lock; + wait_queue_head_t delta_msr_wait; u8 line_control; u8 line_status; u8 termios_initialized; @@ -186,6 +187,7 @@ return -ENOMEM; memset (priv, 0x00, sizeof (struct pl2303_private)); spin_lock_init(&priv->lock); + init_waitqueue_head(&priv->delta_msr_wait); usb_set_serial_port_data(serial->port[i], priv); } return 0; @@ -556,11 +558,51 @@ return result; } +static int wait_modem_info(struct usb_serial_port *port, unsigned int arg) +{ + struct pl2303_private *priv = usb_get_serial_port_data(port); + unsigned long flags; + unsigned int prevstatus; + unsigned int status; + unsigned int changed; + + spin_lock_irqsave (&priv->lock, flags); + prevstatus = priv->line_status; + spin_unlock_irqrestore (&priv->lock, flags); + + while (1) { + interruptible_sleep_on(&priv->delta_msr_wait); + /* see if a signal did it */ + if (signal_pending(current)) + return -ERESTARTSYS; + + spin_lock_irqsave (&priv->lock, flags); + status = priv->line_status; + spin_unlock_irqrestore (&priv->lock, flags); + + changed=prevstatus^status; + + if (((arg & TIOCM_RNG) && (changed & UART_RING)) || + ((arg & TIOCM_DSR) && (changed & UART_DSR)) || + ((arg & TIOCM_CD) && (changed & UART_DCD)) || + ((arg & TIOCM_CTS) && (changed & UART_CTS)) ) { + return 0; + } + prevstatus = status; + } + /* NOTREACHED */ + return 0; +} + static int pl2303_ioctl (struct usb_serial_port *port, struct file *file, unsigned int cmd, unsigned long arg) { dbg("%s (%d) cmd = 0x%04x", __FUNCTION__, port->number, cmd); switch (cmd) { + case TIOCMIWAIT: + dbg("%s (%d) TIOCMIWAIT", __FUNCTION__, port->number); + return wait_modem_info(port, arg); + default: dbg("%s not supported = 0x%04x", __FUNCTION__, cmd); break; @@ -703,6 +745,7 @@ spin_lock_irqsave(&priv->lock, flags); status = priv->line_status; spin_unlock_irqrestore(&priv->lock, flags); + wake_up_interruptible (&priv->delta_msr_wait); /* break takes precedence over parity, */ /* which takes precedence over framing errors */