|
@@ -976,6 +976,13 @@ static const struct usb_device_id products[] = {
|
|
|
0xff),
|
|
0xff),
|
|
|
.driver_info = (unsigned long)&qmi_wwan_info_quirk_dtr,
|
|
.driver_info = (unsigned long)&qmi_wwan_info_quirk_dtr,
|
|
|
},
|
|
},
|
|
|
|
|
+ { /* Quectel EG12/EM12 */
|
|
|
|
|
+ USB_DEVICE_AND_INTERFACE_INFO(0x2c7c, 0x0512,
|
|
|
|
|
+ USB_CLASS_VENDOR_SPEC,
|
|
|
|
|
+ USB_SUBCLASS_VENDOR_SPEC,
|
|
|
|
|
+ 0xff),
|
|
|
|
|
+ .driver_info = (unsigned long)&qmi_wwan_info_quirk_dtr,
|
|
|
|
|
+ },
|
|
|
|
|
|
|
|
/* 3. Combined interface devices matching on interface number */
|
|
/* 3. Combined interface devices matching on interface number */
|
|
|
{QMI_FIXED_INTF(0x0408, 0xea42, 4)}, /* Yota / Megafon M100-1 */
|
|
{QMI_FIXED_INTF(0x0408, 0xea42, 4)}, /* Yota / Megafon M100-1 */
|
|
@@ -1343,17 +1350,20 @@ static bool quectel_ec20_detected(struct usb_interface *intf)
|
|
|
return false;
|
|
return false;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-static bool quectel_ep06_diag_detected(struct usb_interface *intf)
|
|
|
|
|
|
|
+static bool quectel_diag_detected(struct usb_interface *intf)
|
|
|
{
|
|
{
|
|
|
struct usb_device *dev = interface_to_usbdev(intf);
|
|
struct usb_device *dev = interface_to_usbdev(intf);
|
|
|
struct usb_interface_descriptor intf_desc = intf->cur_altsetting->desc;
|
|
struct usb_interface_descriptor intf_desc = intf->cur_altsetting->desc;
|
|
|
|
|
+ u16 id_vendor = le16_to_cpu(dev->descriptor.idVendor);
|
|
|
|
|
+ u16 id_product = le16_to_cpu(dev->descriptor.idProduct);
|
|
|
|
|
|
|
|
- if (le16_to_cpu(dev->descriptor.idVendor) == 0x2c7c &&
|
|
|
|
|
- le16_to_cpu(dev->descriptor.idProduct) == 0x0306 &&
|
|
|
|
|
- intf_desc.bNumEndpoints == 2)
|
|
|
|
|
- return true;
|
|
|
|
|
|
|
+ if (id_vendor != 0x2c7c || intf_desc.bNumEndpoints != 2)
|
|
|
|
|
+ return false;
|
|
|
|
|
|
|
|
- return false;
|
|
|
|
|
|
|
+ if (id_product == 0x0306 || id_product == 0x0512)
|
|
|
|
|
+ return true;
|
|
|
|
|
+ else
|
|
|
|
|
+ return false;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
static int qmi_wwan_probe(struct usb_interface *intf,
|
|
static int qmi_wwan_probe(struct usb_interface *intf,
|
|
@@ -1390,13 +1400,13 @@ static int qmi_wwan_probe(struct usb_interface *intf,
|
|
|
return -ENODEV;
|
|
return -ENODEV;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- /* Quectel EP06/EM06/EG06 supports dynamic interface configuration, so
|
|
|
|
|
|
|
+ /* Several Quectel modems supports dynamic interface configuration, so
|
|
|
* we need to match on class/subclass/protocol. These values are
|
|
* we need to match on class/subclass/protocol. These values are
|
|
|
* identical for the diagnostic- and QMI-interface, but bNumEndpoints is
|
|
* identical for the diagnostic- and QMI-interface, but bNumEndpoints is
|
|
|
* different. Ignore the current interface if the number of endpoints
|
|
* different. Ignore the current interface if the number of endpoints
|
|
|
* the number for the diag interface (two).
|
|
* the number for the diag interface (two).
|
|
|
*/
|
|
*/
|
|
|
- if (quectel_ep06_diag_detected(intf))
|
|
|
|
|
|
|
+ if (quectel_diag_detected(intf))
|
|
|
return -ENODEV;
|
|
return -ENODEV;
|
|
|
|
|
|
|
|
return usbnet_probe(intf, id);
|
|
return usbnet_probe(intf, id);
|