summaryrefslogtreecommitdiff
path: root/drivers/usb
diff options
context:
space:
mode:
authorJohan Hovold <johan@kernel.org>2022-11-29 15:15:39 +0100
committerJohan Hovold <johan@kernel.org>2022-11-30 07:37:12 +0100
commitd03a6d4e2beaa358b6c4e16fe106e813a57e927a (patch)
tree0e8710507caa4e927753e02de0f9c527a93c9928 /drivers/usb
parente88906b169ebcb8046e8f0ad76edd09ab41cfdfe (diff)
USB: serial: cp210x: add support for B0 hangup
A request to set the line speed to B0 is used to hang up a modem connection by deasserting the modem control lines. Note that there is no need reconfigure the line speed in hardware when B0 is requested (even if some drivers do set it to an arbitrary value for implementation or protocol reasons). Reviewed-by: Alex Henrie <alexh@vpitech.com> Signed-off-by: Johan Hovold <johan@kernel.org>
Diffstat (limited to 'drivers/usb')
-rw-r--r--drivers/usb/serial/cp210x.c19
1 files changed, 15 insertions, 4 deletions
diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c
index f6fb23620e87..67372acc2352 100644
--- a/drivers/usb/serial/cp210x.c
+++ b/drivers/usb/serial/cp210x.c
@@ -1049,11 +1049,12 @@ static void cp210x_change_speed(struct tty_struct *tty,
struct cp210x_serial_private *priv = usb_get_serial_data(serial);
u32 baud;
+ if (tty->termios.c_ospeed == 0)
+ return;
+
/*
* This maps the requested rate to the actual rate, a valid rate on
* cp2102 or cp2103, or to an arbitrary rate in [1M, max_speed].
- *
- * NOTE: B0 is not implemented.
*/
baud = clamp(tty->termios.c_ospeed, priv->min_speed, priv->max_speed);
@@ -1146,7 +1147,8 @@ static void cp210x_set_flow_control(struct tty_struct *tty,
tty->termios.c_iflag &= ~(IXON | IXOFF);
}
- if (old_termios &&
+ if (tty->termios.c_ospeed != 0 &&
+ old_termios && old_termios->c_ospeed != 0 &&
C_CRTSCTS(tty) == (old_termios->c_cflag & CRTSCTS) &&
I_IXON(tty) == (old_termios->c_iflag & IXON) &&
I_IXOFF(tty) == (old_termios->c_iflag & IXOFF) &&
@@ -1171,6 +1173,14 @@ static void cp210x_set_flow_control(struct tty_struct *tty,
mutex_lock(&port_priv->mutex);
+ if (tty->termios.c_ospeed == 0) {
+ port_priv->dtr = false;
+ port_priv->rts = false;
+ } else if (old_termios && old_termios->c_ospeed == 0) {
+ port_priv->dtr = true;
+ port_priv->rts = true;
+ }
+
ret = cp210x_read_reg_block(port, CP210X_GET_FLOW, &flow_ctl,
sizeof(flow_ctl));
if (ret)
@@ -1243,7 +1253,8 @@ static void cp210x_set_termios(struct tty_struct *tty,
u16 bits;
int ret;
- if (old_termios && !cp210x_termios_change(&tty->termios, old_termios))
+ if (old_termios && !cp210x_termios_change(&tty->termios, old_termios) &&
+ tty->termios.c_ospeed != 0)
return;
if (!old_termios || tty->termios.c_ospeed != old_termios->c_ospeed)