]> www.infradead.org Git - users/dwmw2/linux.git/commitdiff
USB: serial: option: support dynamic Quectel USB compositions
authorBjørn Mork <bjorn@mork.no>
Sat, 29 Aug 2020 13:42:50 +0000 (15:42 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 17 Sep 2020 11:47:55 +0000 (13:47 +0200)
commit 2bb70f0a4b238323e4e2f392fc3ddeb5b7208c9e upstream.

The USB composition, defining the set of exported functions, is dynamic
in newer Quectel modems.  Default functions can be disabled and
alternative functions can be enabled instead.  The alternatives
includes class functions using interface pairs, which should be
handled by the respective class drivers.

Active interfaces are numbered consecutively, so static
blacklisting based on interface numbers will fail when the
composition changes.  An example of such an error, where the
option driver has bound to the CDC ECM data interface,
preventing cdc_ether from handling this function:

 T: Bus=01 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#= 2 Spd=480 MxCh= 0
 D: Ver= 2.00 Cls=ef(misc ) Sub=02 Prot=01 MxPS=64 #Cfgs= 1
 P: Vendor=2c7c ProdID=0125 Rev= 3.18
 S: Manufacturer=Quectel
 S: Product=EC25-AF
 C:* #Ifs= 6 Cfg#= 1 Atr=a0 MxPwr=500mA
 A: FirstIf#= 4 IfCount= 2 Cls=02(comm.) Sub=06 Prot=00
 I:* If#= 0 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=ff Driver=option
 E: Ad=81(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
 E: Ad=01(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms
 I:* If#= 1 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=00 Prot=00 Driver=option
 E: Ad=83(I) Atr=03(Int.) MxPS= 10 Ivl=32ms
 E: Ad=82(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
 E: Ad=02(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms
 I:* If#= 2 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=00 Prot=00 Driver=option
 E: Ad=85(I) Atr=03(Int.) MxPS= 10 Ivl=32ms
 E: Ad=84(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
 E: Ad=03(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms
 I:* If#= 3 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=00 Prot=00 Driver=option
 E: Ad=87(I) Atr=03(Int.) MxPS= 10 Ivl=32ms
 E: Ad=86(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
 E: Ad=04(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms
 I:* If#= 4 Alt= 0 #EPs= 1 Cls=02(comm.) Sub=06 Prot=00 Driver=(none)
 E: Ad=89(I) Atr=03(Int.) MxPS= 16 Ivl=32ms
 I:* If#= 5 Alt= 0 #EPs= 0 Cls=0a(data ) Sub=00 Prot=00 Driver=option
 I: If#= 5 Alt= 1 #EPs= 2 Cls=0a(data ) Sub=00 Prot=00 Driver=option
 E: Ad=88(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
 E: Ad=05(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms

Another device with the same id gets correct drivers, since the
interface of the network function happens to be blacklisted by option:

 T: Bus=01 Lev=02 Prnt=02 Port=01 Cnt=01 Dev#= 3 Spd=480 MxCh= 0
 D: Ver= 2.00 Cls=ef(misc ) Sub=02 Prot=01 MxPS=64 #Cfgs= 1
 P: Vendor=2c7c ProdID=0125 Rev= 3.18
 S: Manufacturer=Android
 S: Product=Android
 C:* #Ifs= 5 Cfg#= 1 Atr=a0 MxPwr=500mA
 I:* If#= 0 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=ff Driver=option
 E: Ad=81(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
 E: Ad=01(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms
 I:* If#= 1 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=00 Prot=00 Driver=option
 E: Ad=83(I) Atr=03(Int.) MxPS= 10 Ivl=32ms
 E: Ad=82(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
 E: Ad=02(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms
 I:* If#= 2 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=00 Prot=00 Driver=option
 E: Ad=85(I) Atr=03(Int.) MxPS= 10 Ivl=32ms
 E: Ad=84(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
 E: Ad=03(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms
 I:* If#= 3 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=00 Prot=00 Driver=option
 E: Ad=87(I) Atr=03(Int.) MxPS= 10 Ivl=32ms
 E: Ad=86(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
 E: Ad=04(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms
 I:* If#= 4 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=ff Driver=qmi_wwan
 E: Ad=89(I) Atr=03(Int.) MxPS= 8 Ivl=32ms
 E: Ad=88(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
 E: Ad=05(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms

Change rules for EC21, EC25, BG96 and EG95 to match vendor specific
serial functions only, to prevent binding to class functions. Require
2 endpoints on ff/ff/ff functions, avoiding the 3 endpoint QMI/RMNET
network functions.

Cc: AceLan Kao <acelan.kao@canonical.com>
Cc: Sebastian Sjoholm <ssjoholm@mac.com>
Cc: Dan Williams <dcbw@redhat.com>
Cc: stable@vger.kernel.org
Signed-off-by: Bjørn Mork <bjorn@mork.no>
Signed-off-by: Johan Hovold <johan@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/usb/serial/option.c

index 9b7cee98ea6072f3006cf54f2700be3dfb363b02..955bb7a2d81ee43fd76aa3cc259824e7f5295bb1 100644 (file)
@@ -1094,14 +1094,18 @@ static const struct usb_device_id option_ids[] = {
        { USB_DEVICE(QUALCOMM_VENDOR_ID, UBLOX_PRODUCT_R410M),
          .driver_info = RSVD(1) | RSVD(3) },
        /* Quectel products using Quectel vendor ID */
-       { USB_DEVICE(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EC21),
-         .driver_info = RSVD(4) },
-       { USB_DEVICE(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EC25),
-         .driver_info = RSVD(4) },
-       { USB_DEVICE(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EG95),
-         .driver_info = RSVD(4) },
-       { USB_DEVICE(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_BG96),
-         .driver_info = RSVD(4) },
+       { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EC21, 0xff, 0xff, 0xff),
+         .driver_info = NUMEP2 },
+       { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EC21, 0xff, 0, 0) },
+       { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EC25, 0xff, 0xff, 0xff),
+         .driver_info = NUMEP2 },
+       { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EC25, 0xff, 0, 0) },
+       { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EG95, 0xff, 0xff, 0xff),
+         .driver_info = NUMEP2 },
+       { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EG95, 0xff, 0, 0) },
+       { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_BG96, 0xff, 0xff, 0xff),
+         .driver_info = NUMEP2 },
+       { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_BG96, 0xff, 0, 0) },
        { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EP06, 0xff, 0xff, 0xff),
          .driver_info = RSVD(1) | RSVD(2) | RSVD(3) | RSVD(4) | NUMEP2 },
        { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EP06, 0xff, 0, 0) },