diff options
Diffstat (limited to 'drivers/usb/serial/ftdi_sio.c')
-rw-r--r-- | drivers/usb/serial/ftdi_sio.c | 50 |
1 files changed, 28 insertions, 22 deletions
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index d9fcdaedf389..d9d87111f9a9 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c | |||
@@ -719,8 +719,8 @@ static int ftdi_sio_port_probe(struct usb_serial_port *port); | |||
719 | static int ftdi_sio_port_remove(struct usb_serial_port *port); | 719 | static int ftdi_sio_port_remove(struct usb_serial_port *port); |
720 | static int ftdi_open(struct tty_struct *tty, | 720 | static int ftdi_open(struct tty_struct *tty, |
721 | struct usb_serial_port *port, struct file *filp); | 721 | struct usb_serial_port *port, struct file *filp); |
722 | static void ftdi_close(struct tty_struct *tty, | 722 | static void ftdi_close(struct usb_serial_port *port); |
723 | struct usb_serial_port *port, struct file *filp); | 723 | static void ftdi_dtr_rts(struct usb_serial_port *port, int on); |
724 | static int ftdi_write(struct tty_struct *tty, struct usb_serial_port *port, | 724 | static int ftdi_write(struct tty_struct *tty, struct usb_serial_port *port, |
725 | const unsigned char *buf, int count); | 725 | const unsigned char *buf, int count); |
726 | static int ftdi_write_room(struct tty_struct *tty); | 726 | static int ftdi_write_room(struct tty_struct *tty); |
@@ -758,6 +758,7 @@ static struct usb_serial_driver ftdi_sio_device = { | |||
758 | .port_remove = ftdi_sio_port_remove, | 758 | .port_remove = ftdi_sio_port_remove, |
759 | .open = ftdi_open, | 759 | .open = ftdi_open, |
760 | .close = ftdi_close, | 760 | .close = ftdi_close, |
761 | .dtr_rts = ftdi_dtr_rts, | ||
761 | .throttle = ftdi_throttle, | 762 | .throttle = ftdi_throttle, |
762 | .unthrottle = ftdi_unthrottle, | 763 | .unthrottle = ftdi_unthrottle, |
763 | .write = ftdi_write, | 764 | .write = ftdi_write, |
@@ -1558,6 +1559,30 @@ static int ftdi_open(struct tty_struct *tty, | |||
1558 | } /* ftdi_open */ | 1559 | } /* ftdi_open */ |
1559 | 1560 | ||
1560 | 1561 | ||
1562 | static void ftdi_dtr_rts(struct usb_serial_port *port, int on) | ||
1563 | { | ||
1564 | struct ftdi_private *priv = usb_get_serial_port_data(port); | ||
1565 | char buf[1]; | ||
1566 | |||
1567 | mutex_lock(&port->serial->disc_mutex); | ||
1568 | if (!port->serial->disconnected) { | ||
1569 | /* Disable flow control */ | ||
1570 | if (!on && usb_control_msg(port->serial->dev, | ||
1571 | usb_sndctrlpipe(port->serial->dev, 0), | ||
1572 | FTDI_SIO_SET_FLOW_CTRL_REQUEST, | ||
1573 | FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE, | ||
1574 | 0, priv->interface, buf, 0, | ||
1575 | WDR_TIMEOUT) < 0) { | ||
1576 | dev_err(&port->dev, "error from flowcontrol urb\n"); | ||
1577 | } | ||
1578 | /* drop RTS and DTR */ | ||
1579 | if (on) | ||
1580 | set_mctrl(port, TIOCM_DTR | TIOCM_RTS); | ||
1581 | else | ||
1582 | clear_mctrl(port, TIOCM_DTR | TIOCM_RTS); | ||
1583 | } | ||
1584 | mutex_unlock(&port->serial->disc_mutex); | ||
1585 | } | ||
1561 | 1586 | ||
1562 | /* | 1587 | /* |
1563 | * usbserial:__serial_close only calls ftdi_close if the point is open | 1588 | * usbserial:__serial_close only calls ftdi_close if the point is open |
@@ -1567,31 +1592,12 @@ static int ftdi_open(struct tty_struct *tty, | |||
1567 | * | 1592 | * |
1568 | */ | 1593 | */ |
1569 | 1594 | ||
1570 | static void ftdi_close(struct tty_struct *tty, | 1595 | static void ftdi_close(struct usb_serial_port *port) |
1571 | struct usb_serial_port *port, struct file *filp) | ||
1572 | { /* ftdi_close */ | 1596 | { /* ftdi_close */ |
1573 | unsigned int c_cflag = tty->termios->c_cflag; | ||
1574 | struct ftdi_private *priv = usb_get_serial_port_data(port); | 1597 | struct ftdi_private *priv = usb_get_serial_port_data(port); |
1575 | char buf[1]; | ||
1576 | 1598 | ||
1577 | dbg("%s", __func__); | 1599 | dbg("%s", __func__); |
1578 | 1600 | ||
1579 | mutex_lock(&port->serial->disc_mutex); | ||
1580 | if (c_cflag & HUPCL && !port->serial->disconnected) { | ||
1581 | /* Disable flow control */ | ||
1582 | if (usb_control_msg(port->serial->dev, | ||
1583 | usb_sndctrlpipe(port->serial->dev, 0), | ||
1584 | FTDI_SIO_SET_FLOW_CTRL_REQUEST, | ||
1585 | FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE, | ||
1586 | 0, priv->interface, buf, 0, | ||
1587 | WDR_TIMEOUT) < 0) { | ||
1588 | dev_err(&port->dev, "error from flowcontrol urb\n"); | ||
1589 | } | ||
1590 | |||
1591 | /* drop RTS and DTR */ | ||
1592 | clear_mctrl(port, TIOCM_DTR | TIOCM_RTS); | ||
1593 | } /* Note change no line if hupcl is off */ | ||
1594 | mutex_unlock(&port->serial->disc_mutex); | ||
1595 | 1601 | ||
1596 | /* cancel any scheduled reading */ | 1602 | /* cancel any scheduled reading */ |
1597 | cancel_delayed_work_sync(&priv->rx_work); | 1603 | cancel_delayed_work_sync(&priv->rx_work); |