ChangeSet 1.1136.78.2, 2003/12/05 10:42:16-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 Fri Dec 12 15:08:06 2003 +++ b/drivers/usb/serial/pl2303.c Fri Dec 12 15:08:06 2003 @@ -156,6 +156,7 @@ struct pl2303_private { spinlock_t lock; + wait_queue_head_t delta_msr_wait; u8 line_control; u8 line_status; u8 termios_initialized; @@ -173,6 +174,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; @@ -563,6 +565,42 @@ return 0; } +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); @@ -579,6 +617,10 @@ dbg("%s (%d) TIOCMSET/TIOCMBIC/TIOCMSET", __FUNCTION__, port->number); return set_modem_info(port, cmd, (unsigned int *) arg); + 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; @@ -662,6 +704,7 @@ spin_lock_irqsave(&priv->lock, flags); priv->line_status = data[UART_STATE]; spin_unlock_irqrestore(&priv->lock, flags); + wake_up_interruptible (&priv->delta_msr_wait); return; }