Commit 16c7cc30 authored by Ahmon Dancy's avatar Ahmon Dancy Committed by Greg Kroah-Hartman

[PATCH] USB: add TIOCMIWAIT support to pl2303 driver

parent d0d2d872
...@@ -169,6 +169,7 @@ static struct usb_serial_device_type pl2303_device = { ...@@ -169,6 +169,7 @@ static struct usb_serial_device_type pl2303_device = {
struct pl2303_private { struct pl2303_private {
spinlock_t lock; spinlock_t lock;
wait_queue_head_t delta_msr_wait;
u8 line_control; u8 line_control;
u8 line_status; u8 line_status;
u8 termios_initialized; u8 termios_initialized;
...@@ -186,6 +187,7 @@ static int pl2303_startup (struct usb_serial *serial) ...@@ -186,6 +187,7 @@ static int pl2303_startup (struct usb_serial *serial)
return -ENOMEM; return -ENOMEM;
memset (priv, 0x00, sizeof (struct pl2303_private)); memset (priv, 0x00, sizeof (struct pl2303_private));
spin_lock_init(&priv->lock); spin_lock_init(&priv->lock);
init_waitqueue_head(&priv->delta_msr_wait);
usb_set_serial_port_data(serial->port[i], priv); usb_set_serial_port_data(serial->port[i], priv);
} }
return 0; return 0;
...@@ -556,11 +558,51 @@ static int pl2303_tiocmget (struct usb_serial_port *port, struct file *file) ...@@ -556,11 +558,51 @@ static int pl2303_tiocmget (struct usb_serial_port *port, struct file *file)
return result; 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) 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); dbg("%s (%d) cmd = 0x%04x", __FUNCTION__, port->number, cmd);
switch (cmd) { switch (cmd) {
case TIOCMIWAIT:
dbg("%s (%d) TIOCMIWAIT", __FUNCTION__, port->number);
return wait_modem_info(port, arg);
default: default:
dbg("%s not supported = 0x%04x", __FUNCTION__, cmd); dbg("%s not supported = 0x%04x", __FUNCTION__, cmd);
break; break;
...@@ -703,6 +745,7 @@ static void pl2303_read_bulk_callback (struct urb *urb, struct pt_regs *regs) ...@@ -703,6 +745,7 @@ static void pl2303_read_bulk_callback (struct urb *urb, struct pt_regs *regs)
spin_lock_irqsave(&priv->lock, flags); spin_lock_irqsave(&priv->lock, flags);
status = priv->line_status; status = priv->line_status;
spin_unlock_irqrestore(&priv->lock, flags); spin_unlock_irqrestore(&priv->lock, flags);
wake_up_interruptible (&priv->delta_msr_wait);
/* break takes precedence over parity, */ /* break takes precedence over parity, */
/* which takes precedence over framing errors */ /* which takes precedence over framing errors */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment