]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blob - releases/4.18.14/usb-serial-option-improve-quectel-ep06-detection.patch
4.9-stable patches
[thirdparty/kernel/stable-queue.git] / releases / 4.18.14 / usb-serial-option-improve-quectel-ep06-detection.patch
1 From 36cae568404a298a19a6e8a3f18641075d4cab04 Mon Sep 17 00:00:00 2001
2 From: Kristian Evensen <kristian.evensen@gmail.com>
3 Date: Thu, 13 Sep 2018 11:21:49 +0200
4 Subject: USB: serial: option: improve Quectel EP06 detection
5
6 From: Kristian Evensen <kristian.evensen@gmail.com>
7
8 commit 36cae568404a298a19a6e8a3f18641075d4cab04 upstream.
9
10 The Quectel EP06 (and EM06/EG06) LTE modem supports updating the USB
11 configuration, without the VID/PID or configuration number changing.
12 When the configuration is updated and interfaces are added/removed, the
13 interface numbers are updated. This causes our current code for matching
14 EP06 not to work as intended, as the assumption about reserved
15 interfaces no longer holds. If for example the diagnostic (first)
16 interface is removed, option will (try to) bind to the QMI interface.
17
18 This patch improves EP06 detection by replacing the current match with
19 two matches, and those matches check class, subclass and protocol as
20 well as VID and PID. The diag interface exports class, subclass and
21 protocol as 0xff. For the other serial interfaces, class is 0xff and
22 subclass and protocol are both 0x0.
23
24 The modem can export the following devices and always in this order:
25 diag, nmea, at, ppp. qmi and adb. This means that diag can only ever be
26 interface 0, and interface numbers 1-5 should be marked as reserved. The
27 three other serial devices can have interface numbers 0-3, but I have
28 not marked any interfaces as reserved. The reason is that the serial
29 devices are the only interfaces exported by the device where subclass
30 and protocol is 0x0.
31
32 QMI exports the same class, subclass and protocol values as the diag
33 interface. However, the two interfaces have different number of
34 endpoints, QMI has three and diag two. I have added a check for number
35 of interfaces if VID/PID matches the EP06, and we ignore the device if
36 number of interfaces equals three (and subclass is set).
37
38 Signed-off-by: Kristian Evensen <kristian.evensen@gmail.com>
39 Acked-by: Dan Williams <dcbw@redhat.com>
40 [ johan: drop uneeded RSVD(5) for ADB ]
41 Cc: stable <stable@vger.kernel.org>
42 Signed-off-by: Johan Hovold <johan@kernel.org>
43 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
44
45 ---
46 drivers/usb/serial/option.c | 18 ++++++++++++++++--
47 1 file changed, 16 insertions(+), 2 deletions(-)
48
49 --- a/drivers/usb/serial/option.c
50 +++ b/drivers/usb/serial/option.c
51 @@ -1081,8 +1081,9 @@ static const struct usb_device_id option
52 .driver_info = RSVD(4) },
53 { USB_DEVICE(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_BG96),
54 .driver_info = RSVD(4) },
55 - { USB_DEVICE(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EP06),
56 - .driver_info = RSVD(4) | RSVD(5) },
57 + { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EP06, 0xff, 0xff, 0xff),
58 + .driver_info = RSVD(1) | RSVD(2) | RSVD(3) | RSVD(4) },
59 + { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EP06, 0xff, 0, 0) },
60 { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_6001) },
61 { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_CMU_300) },
62 { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_6003),
63 @@ -1985,6 +1986,7 @@ static int option_probe(struct usb_seria
64 {
65 struct usb_interface_descriptor *iface_desc =
66 &serial->interface->cur_altsetting->desc;
67 + struct usb_device_descriptor *dev_desc = &serial->dev->descriptor;
68 unsigned long device_flags = id->driver_info;
69
70 /* Never bind to the CD-Rom emulation interface */
71 @@ -1999,6 +2001,18 @@ static int option_probe(struct usb_seria
72 if (device_flags & RSVD(iface_desc->bInterfaceNumber))
73 return -ENODEV;
74
75 + /*
76 + * Don't bind to the QMI device of the Quectel EP06/EG06/EM06. Class,
77 + * subclass and protocol is 0xff for both the diagnostic port and the
78 + * QMI interface, but the diagnostic port only has two endpoints (QMI
79 + * has three).
80 + */
81 + if (dev_desc->idVendor == cpu_to_le16(QUECTEL_VENDOR_ID) &&
82 + dev_desc->idProduct == cpu_to_le16(QUECTEL_PRODUCT_EP06) &&
83 + iface_desc->bInterfaceSubClass && iface_desc->bNumEndpoints == 3) {
84 + return -ENODEV;
85 + }
86 +
87 /* Store the device flags so we can use them during attach. */
88 usb_set_serial_data(serial, (void *)device_flags);
89