Commit df1cd63d authored by Johan Hovold's avatar Johan Hovold

USB: serial: ftdi_sio: clean up flow control management

Clean up the somewhat convoluted hardware-assisted flow control
handling.
Reviewed-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: default avatarJohan Hovold <johan@kernel.org>
parent 16410115
...@@ -2191,12 +2191,8 @@ static void ftdi_set_termios(struct tty_struct *tty, ...@@ -2191,12 +2191,8 @@ static void ftdi_set_termios(struct tty_struct *tty,
struct ftdi_private *priv = usb_get_serial_port_data(port); struct ftdi_private *priv = usb_get_serial_port_data(port);
struct ktermios *termios = &tty->termios; struct ktermios *termios = &tty->termios;
unsigned int cflag = termios->c_cflag; unsigned int cflag = termios->c_cflag;
u16 value; u16 value, index;
int ret;
/* Added for xon/xoff support */
unsigned int iflag = termios->c_iflag;
unsigned char vstop;
unsigned char vstart;
/* Force baud rate if this device requires it, unless it is set to /* Force baud rate if this device requires it, unless it is set to
B0. */ B0. */
...@@ -2325,61 +2321,30 @@ static void ftdi_set_termios(struct tty_struct *tty, ...@@ -2325,61 +2321,30 @@ static void ftdi_set_termios(struct tty_struct *tty,
set_mctrl(port, TIOCM_DTR | TIOCM_RTS); set_mctrl(port, TIOCM_DTR | TIOCM_RTS);
} }
/* Set flow control */
/* Note device also supports DTR/CD (ugh) and Xon/Xoff in hardware */
no_c_cflag_changes: no_c_cflag_changes:
if (cflag & CRTSCTS) { /* Set hardware-assisted flow control */
dev_dbg(ddev, "%s Setting to CRTSCTS flow control\n", __func__); value = 0;
if (usb_control_msg(dev,
usb_sndctrlpipe(dev, 0), if (C_CRTSCTS(tty)) {
FTDI_SIO_SET_FLOW_CTRL_REQUEST, dev_dbg(&port->dev, "enabling rts/cts flow control\n");
FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE, index = FTDI_SIO_RTS_CTS_HS;
0 , (FTDI_SIO_RTS_CTS_HS | priv->interface), } else if (I_IXON(tty)) {
NULL, 0, WDR_TIMEOUT) < 0) { dev_dbg(&port->dev, "enabling xon/xoff flow control\n");
dev_err(ddev, "urb failed to set to rts/cts flow control\n"); index = FTDI_SIO_XON_XOFF_HS;
} value = STOP_CHAR(tty) << 8 | START_CHAR(tty);
} else { } else {
/* dev_dbg(&port->dev, "disabling flow control\n");
* Xon/Xoff code index = FTDI_SIO_DISABLE_FLOW_CTRL;
*/
if (iflag & IXON) {
dev_dbg(ddev, "%s request to enable xonxoff iflag=%04x\n",
__func__, iflag);
/* Try to enable the XON/XOFF on the ftdi_sio
* Set the vstart and vstop -- could have been done up
* above where a lot of other dereferencing is done but
* that would be very inefficient as vstart and vstop
* are not always needed.
*/
vstart = termios->c_cc[VSTART];
vstop = termios->c_cc[VSTOP];
value = (vstop << 8) | (vstart);
if (usb_control_msg(dev,
usb_sndctrlpipe(dev, 0),
FTDI_SIO_SET_FLOW_CTRL_REQUEST,
FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE,
value , (FTDI_SIO_XON_XOFF_HS
| priv->interface),
NULL, 0, WDR_TIMEOUT) < 0) {
dev_err(&port->dev, "urb failed to set to "
"xon/xoff flow control\n");
}
} else {
/* else clause to only run if cflag ! CRTSCTS and iflag
* ! XON. CHECKME Assuming XON/XOFF handled by tty
* stack - not by device */
dev_dbg(ddev, "%s Turning off hardware flow control\n", __func__);
if (usb_control_msg(dev,
usb_sndctrlpipe(dev, 0),
FTDI_SIO_SET_FLOW_CTRL_REQUEST,
FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE,
0, priv->interface,
NULL, 0, WDR_TIMEOUT) < 0) {
dev_err(ddev, "urb failed to clear flow control\n");
}
}
} }
index |= priv->interface;
ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
FTDI_SIO_SET_FLOW_CTRL_REQUEST,
FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE,
value, index, NULL, 0, WDR_TIMEOUT);
if (ret < 0)
dev_err(&port->dev, "failed to set flow control: %d\n", ret);
} }
/* /*
......
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