diff options
Diffstat (limited to 'drivers/usb/serial/pl2303.c')
-rw-r--r-- | drivers/usb/serial/pl2303.c | 79 |
1 files changed, 31 insertions, 48 deletions
diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c index 751a533a4347..e02dc3d643c7 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, | |||
652 | kfree(buf); | 652 | kfree(buf); |
653 | } | 653 | } |
654 | 654 | ||
655 | static void pl2303_close(struct tty_struct *tty, | 655 | static void pl2303_dtr_rts(struct usb_serial_port *port, int on) |
656 | struct usb_serial_port *port, struct file *filp) | 656 | { |
657 | struct pl2303_private *priv = usb_get_serial_port_data(port); | ||
658 | unsigned long flags; | ||
659 | u8 control; | ||
660 | |||
661 | spin_lock_irqsave(&priv->lock, flags); | ||
662 | /* Change DTR and RTS */ | ||
663 | if (on) | ||
664 | priv->line_control |= (CONTROL_DTR | CONTROL_RTS); | ||
665 | else | ||
666 | priv->line_control &= ~(CONTROL_DTR | CONTROL_RTS); | ||
667 | control = priv->line_control; | ||
668 | spin_unlock_irqrestore(&priv->lock, flags); | ||
669 | set_control_lines(port->serial->dev, control); | ||
670 | } | ||
671 | |||
672 | static void pl2303_close(struct usb_serial_port *port) | ||
657 | { | 673 | { |
658 | struct pl2303_private *priv = usb_get_serial_port_data(port); | 674 | struct pl2303_private *priv = usb_get_serial_port_data(port); |
659 | unsigned long flags; | 675 | unsigned long flags; |
660 | unsigned int c_cflag; | ||
661 | int bps; | ||
662 | long timeout; | ||
663 | wait_queue_t wait; | ||
664 | 676 | ||
665 | dbg("%s - port %d", __func__, port->number); | 677 | dbg("%s - port %d", __func__, port->number); |
666 | 678 | ||
667 | /* wait for data to drain from the buffer */ | ||
668 | spin_lock_irqsave(&priv->lock, flags); | 679 | spin_lock_irqsave(&priv->lock, flags); |
669 | timeout = PL2303_CLOSING_WAIT; | ||
670 | init_waitqueue_entry(&wait, current); | ||
671 | add_wait_queue(&tty->write_wait, &wait); | ||
672 | for (;;) { | ||
673 | set_current_state(TASK_INTERRUPTIBLE); | ||
674 | if (pl2303_buf_data_avail(priv->buf) == 0 || | ||
675 | timeout == 0 || signal_pending(current) || | ||
676 | port->serial->disconnected) | ||
677 | break; | ||
678 | spin_unlock_irqrestore(&priv->lock, flags); | ||
679 | timeout = schedule_timeout(timeout); | ||
680 | spin_lock_irqsave(&priv->lock, flags); | ||
681 | } | ||
682 | set_current_state(TASK_RUNNING); | ||
683 | remove_wait_queue(&tty->write_wait, &wait); | ||
684 | /* clear out any remaining data in the buffer */ | 680 | /* clear out any remaining data in the buffer */ |
685 | pl2303_buf_clear(priv->buf); | 681 | pl2303_buf_clear(priv->buf); |
686 | spin_unlock_irqrestore(&priv->lock, flags); | 682 | spin_unlock_irqrestore(&priv->lock, flags); |
687 | 683 | ||
688 | /* wait for characters to drain from the device */ | ||
689 | /* (this is long enough for the entire 256 byte */ | ||
690 | /* pl2303 hardware buffer to drain with no flow */ | ||
691 | /* control for data rates of 1200 bps or more, */ | ||
692 | /* for lower rates we should really know how much */ | ||
693 | /* data is in the buffer to compute a delay */ | ||
694 | /* that is not unnecessarily long) */ | ||
695 | bps = tty_get_baud_rate(tty); | ||
696 | if (bps > 1200) | ||
697 | timeout = max((HZ*2560)/bps, HZ/10); | ||
698 | else | ||
699 | timeout = 2*HZ; | ||
700 | schedule_timeout_interruptible(timeout); | ||
701 | |||
702 | /* shutdown our urbs */ | 684 | /* shutdown our urbs */ |
703 | dbg("%s - shutting down urbs", __func__); | 685 | dbg("%s - shutting down urbs", __func__); |
704 | usb_kill_urb(port->write_urb); | 686 | usb_kill_urb(port->write_urb); |
705 | usb_kill_urb(port->read_urb); | 687 | usb_kill_urb(port->read_urb); |
706 | usb_kill_urb(port->interrupt_in_urb); | 688 | usb_kill_urb(port->interrupt_in_urb); |
707 | 689 | ||
708 | if (tty) { | ||
709 | c_cflag = tty->termios->c_cflag; | ||
710 | if (c_cflag & HUPCL) { | ||
711 | /* drop DTR and RTS */ | ||
712 | spin_lock_irqsave(&priv->lock, flags); | ||
713 | priv->line_control = 0; | ||
714 | spin_unlock_irqrestore(&priv->lock, flags); | ||
715 | set_control_lines(port->serial->dev, 0); | ||
716 | } | ||
717 | } | ||
718 | } | 690 | } |
719 | 691 | ||
720 | static int pl2303_open(struct tty_struct *tty, | 692 | static int pl2303_open(struct tty_struct *tty, |
@@ -748,7 +720,7 @@ static int pl2303_open(struct tty_struct *tty, | |||
748 | if (result) { | 720 | if (result) { |
749 | dev_err(&port->dev, "%s - failed submitting read urb," | 721 | dev_err(&port->dev, "%s - failed submitting read urb," |
750 | " error %d\n", __func__, result); | 722 | " error %d\n", __func__, result); |
751 | pl2303_close(tty, port, NULL); | 723 | pl2303_close(port); |
752 | return -EPROTO; | 724 | return -EPROTO; |
753 | } | 725 | } |
754 | 726 | ||
@@ -758,9 +730,10 @@ static int pl2303_open(struct tty_struct *tty, | |||
758 | if (result) { | 730 | if (result) { |
759 | dev_err(&port->dev, "%s - failed submitting interrupt urb," | 731 | dev_err(&port->dev, "%s - failed submitting interrupt urb," |
760 | " error %d\n", __func__, result); | 732 | " error %d\n", __func__, result); |
761 | pl2303_close(tty, port, NULL); | 733 | pl2303_close(port); |
762 | return -EPROTO; | 734 | return -EPROTO; |
763 | } | 735 | } |
736 | port->port.drain_delay = 256; | ||
764 | return 0; | 737 | return 0; |
765 | } | 738 | } |
766 | 739 | ||
@@ -821,6 +794,14 @@ static int pl2303_tiocmget(struct tty_struct *tty, struct file *file) | |||
821 | return result; | 794 | return result; |
822 | } | 795 | } |
823 | 796 | ||
797 | static int pl2303_carrier_raised(struct usb_serial_port *port) | ||
798 | { | ||
799 | struct pl2303_private *priv = usb_get_serial_port_data(port); | ||
800 | if (priv->line_status & UART_DCD) | ||
801 | return 1; | ||
802 | return 0; | ||
803 | } | ||
804 | |||
824 | static int wait_modem_info(struct usb_serial_port *port, unsigned int arg) | 805 | static int wait_modem_info(struct usb_serial_port *port, unsigned int arg) |
825 | { | 806 | { |
826 | struct pl2303_private *priv = usb_get_serial_port_data(port); | 807 | struct pl2303_private *priv = usb_get_serial_port_data(port); |
@@ -1125,6 +1106,8 @@ static struct usb_serial_driver pl2303_device = { | |||
1125 | .num_ports = 1, | 1106 | .num_ports = 1, |
1126 | .open = pl2303_open, | 1107 | .open = pl2303_open, |
1127 | .close = pl2303_close, | 1108 | .close = pl2303_close, |
1109 | .dtr_rts = pl2303_dtr_rts, | ||
1110 | .carrier_raised = pl2303_carrier_raised, | ||
1128 | .write = pl2303_write, | 1111 | .write = pl2303_write, |
1129 | .ioctl = pl2303_ioctl, | 1112 | .ioctl = pl2303_ioctl, |
1130 | .break_ctl = pl2303_break_ctl, | 1113 | .break_ctl = pl2303_break_ctl, |