cdc-acm: fix abnormal DATA RX issue for Mediatek Preloader.
authorMacpaul Lin <macpaul.lin@mediatek.com>
Wed, 19 Dec 2018 04:11:03 +0000 (12:11 +0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 9 Jan 2019 16:14:50 +0000 (17:14 +0100)
commit eafb27fa5283599ce6c5492ea18cf636a28222bb upstream.

Mediatek Preloader is a proprietary embedded boot loader for loading
Little Kernel and Linux into device DRAM.

This boot loader also handle firmware update. Mediatek Preloader will be
enumerated as a virtual COM port when the device is connected to Windows
or Linux OS via CDC-ACM class driver. When the USB enumeration has been
done, Mediatek Preloader will send out handshake command "READY" to PC
actively instead of waiting command from the download tool.

Since Linux 4.12, the commit "tty: reset termios state on device
registration" (93857edd9829e144acb6c7e72d593f6e01aead66) causes Mediatek
Preloader receiving some abnoraml command like "READYXX" as it sent.
This will be recognized as an incorrect response. The behavior change
also causes the download handshake fail. This change only affects
subsequent connects if the reconnected device happens to get the same minor
number.

By disabling the ECHO termios flag could avoid this problem. However, it
cannot be done by user space configuration when download tool open
/dev/ttyACM0. This is because the device running Mediatek Preloader will
send handshake command "READY" immediately once the CDC-ACM driver is
ready.

This patch wants to fix above problem by introducing "DISABLE_ECHO"
property in driver_info. When Mediatek Preloader is connected, the
CDC-ACM driver could disable ECHO flag in termios to avoid the problem.

Signed-off-by: Macpaul Lin <macpaul.lin@mediatek.com>
Cc: stable@vger.kernel.org
Reviewed-by: Johan Hovold <johan@kernel.org>
Acked-by: Oliver Neukum <oneukum@suse.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/usb/class/cdc-acm.c
drivers/usb/class/cdc-acm.h

index 5a8ef83a5c5cc2380832b363c9bac5032f17c169..423a339e53bc731f1fb24e2652863975ae890ca6 100644 (file)
@@ -593,6 +593,13 @@ static int acm_tty_install(struct tty_driver *driver, struct tty_struct *tty)
        if (retval)
                goto error_init_termios;
 
+       /*
+        * Suppress initial echoing for some devices which might send data
+        * immediately after acm driver has been installed.
+        */
+       if (acm->quirks & DISABLE_ECHO)
+               tty->termios.c_lflag &= ~ECHO;
+
        tty->driver_data = acm;
 
        return 0;
@@ -1685,6 +1692,9 @@ static const struct usb_device_id acm_ids[] = {
        { USB_DEVICE(0x0e8d, 0x0003), /* FIREFLY, MediaTek Inc; andrey.arapov@gmail.com */
        .driver_info = NO_UNION_NORMAL, /* has no union descriptor */
        },
+       { USB_DEVICE(0x0e8d, 0x2000), /* MediaTek Inc Preloader */
+       .driver_info = DISABLE_ECHO, /* DISABLE ECHO in termios flag */
+       },
        { USB_DEVICE(0x0e8d, 0x3329), /* MediaTek Inc GPS */
        .driver_info = NO_UNION_NORMAL, /* has no union descriptor */
        },
index ca06b20d7af9cc9567da1f243ad99935f8bc99e7..515aad0847ee84b408e7fceb503081f5d97fc78b 100644 (file)
@@ -140,3 +140,4 @@ struct acm {
 #define QUIRK_CONTROL_LINE_STATE       BIT(6)
 #define CLEAR_HALT_CONDITIONS          BIT(7)
 #define SEND_ZERO_PACKET               BIT(8)
+#define DISABLE_ECHO                   BIT(9)