]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
USB: serial: kobil_sct: fix TIOCMBIS and TIOCMBIC
authorJohan Hovold <johan@kernel.org>
Wed, 22 Oct 2025 15:26:34 +0000 (17:26 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 12 Dec 2025 17:40:19 +0000 (18:40 +0100)
commit d432df758f92c4c28aac409bc807fd1716167577 upstream.

Asserting or deasserting a modem control line using TIOCMBIS or TIOCMBIC
should not deassert any lines that are not in the mask.

Fix this long-standing issue dating back to 2003 when the support for
these ioctls was added with the introduction of the tiocmset() callback.

Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Cc: stable@vger.kernel.org
Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Johan Hovold <johan@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/usb/serial/kobil_sct.c

index 464433be2034437876fdb3567275eed0e481728c..96ea571c436a7135b28bcd65fd2c8f3f3bc5ecc1 100644 (file)
@@ -418,7 +418,7 @@ static int kobil_tiocmset(struct tty_struct *tty,
        struct usb_serial_port *port = tty->driver_data;
        struct device *dev = &port->dev;
        struct kobil_private *priv;
-       int result;
+       int result = 0;
        int dtr = 0;
        int rts = 0;
 
@@ -435,12 +435,12 @@ static int kobil_tiocmset(struct tty_struct *tty,
        if (set & TIOCM_DTR)
                dtr = 1;
        if (clear & TIOCM_RTS)
-               rts = 0;
+               rts = 1;
        if (clear & TIOCM_DTR)
-               dtr = 0;
+               dtr = 1;
 
-       if (priv->device_type == KOBIL_ADAPTER_B_PRODUCT_ID) {
-               if (dtr != 0)
+       if (dtr && priv->device_type == KOBIL_ADAPTER_B_PRODUCT_ID) {
+               if (set & TIOCM_DTR)
                        dev_dbg(dev, "%s - Setting DTR\n", __func__);
                else
                        dev_dbg(dev, "%s - Clearing DTR\n", __func__);
@@ -448,13 +448,13 @@ static int kobil_tiocmset(struct tty_struct *tty,
                          usb_sndctrlpipe(port->serial->dev, 0),
                          SUSBCRequest_SetStatusLinesOrQueues,
                          USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_OUT,
-                         ((dtr != 0) ? SUSBCR_SSL_SETDTR : SUSBCR_SSL_CLRDTR),
+                         ((set & TIOCM_DTR) ? SUSBCR_SSL_SETDTR : SUSBCR_SSL_CLRDTR),
                          0,
                          NULL,
                          0,
                          KOBIL_TIMEOUT);
-       } else {
-               if (rts != 0)
+       } else if (rts) {
+               if (set & TIOCM_RTS)
                        dev_dbg(dev, "%s - Setting RTS\n", __func__);
                else
                        dev_dbg(dev, "%s - Clearing RTS\n", __func__);
@@ -462,7 +462,7 @@ static int kobil_tiocmset(struct tty_struct *tty,
                        usb_sndctrlpipe(port->serial->dev, 0),
                        SUSBCRequest_SetStatusLinesOrQueues,
                        USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_OUT,
-                       ((rts != 0) ? SUSBCR_SSL_SETRTS : SUSBCR_SSL_CLRRTS),
+                       ((set & TIOCM_RTS) ? SUSBCR_SSL_SETRTS : SUSBCR_SSL_CLRRTS),
                        0,
                        NULL,
                        0,