aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/serial/pl2303.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/serial/pl2303.c')
-rw-r--r--drivers/usb/serial/pl2303.c89
1 files changed, 37 insertions, 52 deletions
diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c
index 751a533a4347..ec6c132a25b5 100644
--- a/drivers/usb/serial/pl2303.c
+++ b/drivers/usb/serial/pl2303.c
@@ -652,69 +652,41 @@ static void pl2303_set_termios(struct tty_struct *tty,
kfree(buf);
}
-static void pl2303_close(struct tty_struct *tty,
- struct usb_serial_port *port, struct file *filp)
+static void pl2303_dtr_rts(struct usb_serial_port *port, int on)
+{
+ struct pl2303_private *priv = usb_get_serial_port_data(port);
+ unsigned long flags;
+ u8 control;
+
+ spin_lock_irqsave(&priv->lock, flags);
+ /* Change DTR and RTS */
+ if (on)
+ priv->line_control |= (CONTROL_DTR | CONTROL_RTS);
+ else
+ priv->line_control &= ~(CONTROL_DTR | CONTROL_RTS);
+ control = priv->line_control;
+ spin_unlock_irqrestore(&priv->lock, flags);
+ set_control_lines(port->serial->dev, control);
+}
+
+static void pl2303_close(struct usb_serial_port *port)
{
struct pl2303_private *priv = usb_get_serial_port_data(port);
unsigned long flags;
- unsigned int c_cflag;
- int bps;
- long timeout;
- wait_queue_t wait;
dbg("%s - port %d", __func__, port->number);
- /* wait for data to drain from the buffer */
spin_lock_irqsave(&priv->lock, flags);
- timeout = PL2303_CLOSING_WAIT;
- init_waitqueue_entry(&wait, current);
- add_wait_queue(&tty->write_wait, &wait);
- for (;;) {
- set_current_state(TASK_INTERRUPTIBLE);
- if (pl2303_buf_data_avail(priv->buf) == 0 ||
- timeout == 0 || signal_pending(current) ||
- port->serial->disconnected)
- break;
- spin_unlock_irqrestore(&priv->lock, flags);
- timeout = schedule_timeout(timeout);
- spin_lock_irqsave(&priv->lock, flags);
- }
- set_current_state(TASK_RUNNING);
- remove_wait_queue(&tty->write_wait, &wait);
/* clear out any remaining data in the buffer */
pl2303_buf_clear(priv->buf);
spin_unlock_irqrestore(&priv->lock, flags);
- /* wait for characters to drain from the device */
- /* (this is long enough for the entire 256 byte */
- /* pl2303 hardware buffer to drain with no flow */
- /* control for data rates of 1200 bps or more, */
- /* for lower rates we should really know how much */
- /* data is in the buffer to compute a delay */
- /* that is not unnecessarily long) */
- bps = tty_get_baud_rate(tty);
- if (bps > 1200)
- timeout = max((HZ*2560)/bps, HZ/10);
- else
- timeout = 2*HZ;
- schedule_timeout_interruptible(timeout);
-
/* shutdown our urbs */
dbg("%s - shutting down urbs", __func__);
usb_kill_urb(port->write_urb);
usb_kill_urb(port->read_urb);
usb_kill_urb(port->interrupt_in_urb);
- if (tty) {
- c_cflag = tty->termios->c_cflag;
- if (c_cflag & HUPCL) {
- /* drop DTR and RTS */
- spin_lock_irqsave(&priv->lock, flags);
- priv->line_control = 0;
- spin_unlock_irqrestore(&priv->lock, flags);
- set_control_lines(port->serial->dev, 0);
- }
- }
}
static int pl2303_open(struct tty_struct *tty,
@@ -748,7 +720,7 @@ static int pl2303_open(struct tty_struct *tty,
if (result) {
dev_err(&port->dev, "%s - failed submitting read urb,"
" error %d\n", __func__, result);
- pl2303_close(tty, port, NULL);
+ pl2303_close(port);
return -EPROTO;
}
@@ -758,9 +730,10 @@ static int pl2303_open(struct tty_struct *tty,
if (result) {
dev_err(&port->dev, "%s - failed submitting interrupt urb,"
" error %d\n", __func__, result);
- pl2303_close(tty, port, NULL);
+ pl2303_close(port);
return -EPROTO;
}
+ port->port.drain_delay = 256;
return 0;
}
@@ -821,6 +794,14 @@ static int pl2303_tiocmget(struct tty_struct *tty, struct file *file)
return result;
}
+static int pl2303_carrier_raised(struct usb_serial_port *port)
+{
+ struct pl2303_private *priv = usb_get_serial_port_data(port);
+ if (priv->line_status & UART_DCD)
+ return 1;
+ 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);
@@ -897,7 +878,7 @@ static void pl2303_break_ctl(struct tty_struct *tty, int break_state)
dbg("%s - error sending break = %d", __func__, result);
}
-static void pl2303_shutdown(struct usb_serial *serial)
+static void pl2303_release(struct usb_serial *serial)
{
int i;
struct pl2303_private *priv;
@@ -909,7 +890,6 @@ static void pl2303_shutdown(struct usb_serial *serial)
if (priv) {
pl2303_buf_free(priv->buf);
kfree(priv);
- usb_set_serial_port_data(serial->port[i], NULL);
}
}
}
@@ -946,6 +926,8 @@ static void pl2303_update_line_status(struct usb_serial_port *port,
spin_lock_irqsave(&priv->lock, flags);
priv->line_status = data[status_idx];
spin_unlock_irqrestore(&priv->lock, flags);
+ if (priv->line_status & UART_BREAK_ERROR)
+ usb_serial_handle_break(port);
wake_up_interruptible(&priv->delta_msr_wait);
}
@@ -1056,7 +1038,8 @@ static void pl2303_read_bulk_callback(struct urb *urb)
if (line_status & UART_OVERRUN_ERROR)
tty_insert_flip_char(tty, 0, TTY_OVERRUN);
for (i = 0; i < urb->actual_length; ++i)
- tty_insert_flip_char(tty, data[i], tty_flag);
+ if (!usb_serial_handle_sysrq_char(port, data[i]))
+ tty_insert_flip_char(tty, data[i], tty_flag);
tty_flip_buffer_push(tty);
}
tty_kref_put(tty);
@@ -1125,6 +1108,8 @@ static struct usb_serial_driver pl2303_device = {
.num_ports = 1,
.open = pl2303_open,
.close = pl2303_close,
+ .dtr_rts = pl2303_dtr_rts,
+ .carrier_raised = pl2303_carrier_raised,
.write = pl2303_write,
.ioctl = pl2303_ioctl,
.break_ctl = pl2303_break_ctl,
@@ -1137,7 +1122,7 @@ static struct usb_serial_driver pl2303_device = {
.write_room = pl2303_write_room,
.chars_in_buffer = pl2303_chars_in_buffer,
.attach = pl2303_startup,
- .shutdown = pl2303_shutdown,
+ .release = pl2303_release,
};
static int __init pl2303_init(void)