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 */
