OpenWrt – Rev 4

Subversion Repositories:
Rev:
--- a/drivers/net/usb/qmi_wwan.c
+++ b/drivers/net/usb/qmi_wwan.c
@@ -155,6 +155,24 @@ static const u8 default_modem_addr[ETH_A
 
 static const u8 buggy_fw_addr[ETH_ALEN] = {0x00, 0xa0, 0xc6, 0x00, 0x00, 0x00};
 
+#if 1 //Added by Quectel
+#include <linux/etherdevice.h>
+struct sk_buff *qmi_wwan_tx_fixup(struct usbnet *dev, struct sk_buff *skb, gfp_t flags)
+{
+       if (dev->udev->descriptor.idVendor != cpu_to_le16(0x2C7C))
+               return skb;
+       // Skip Ethernet header from message
+       if (skb_pull(skb, ETH_HLEN)) {
+               return skb;
+       } else {
+               dev_err(&dev->intf->dev, "Packet Dropped ");
+       }
+       // Filter the packet out, release it
+       dev_kfree_skb_any(skb);
+       return NULL;
+}
+#endif
+
 /* Make up an ethernet header if the packet doesn't have one.
  *
  * A firmware bug common among several devices cause them to send raw
@@ -445,6 +463,20 @@ static int qmi_wwan_bind(struct usbnet *
        }
        dev->net->netdev_ops = &qmi_wwan_netdev_ops;
        dev->net->sysfs_groups[0] = &qmi_wwan_sysfs_attr_group;
+#if 1 //Added by Quectel
+       if (dev->udev->descriptor.idVendor == cpu_to_le16(0x2C7C)) {
+               dev_info(&intf->dev, "QuectelEC25&EC21&EG91&EG95&EG06&EP06&EM06&BG96&AG35 work on RawIP mode\n");
+               dev->net->flags |= IFF_NOARP;
+               usb_control_msg(
+               interface_to_usbdev(intf),
+               usb_sndctrlpipe(interface_to_usbdev(intf), 0),
+               0x22, //USB_CDC_REQ_SET_CONTROL_LINE_STATE
+               0x21, //USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE
+               1, //active CDC DTR
+               intf->cur_altsetting->desc.bInterfaceNumber,
+               NULL, 0, 100);
+               }
+#endif
 err:
        return status;
 }
@@ -535,7 +567,10 @@ static const struct driver_info    qmi_wwan
        .bind           = qmi_wwan_bind,
        .unbind         = qmi_wwan_unbind,
        .manage_power   = qmi_wwan_manage_power,
-       .rx_fixup       = qmi_wwan_rx_fixup,
+       #if 1 //Added by Quectel
+       .tx_fixup = qmi_wwan_tx_fixup,
+       .rx_fixup = qmi_wwan_rx_fixup,
+       #endif
 };
 
 static const struct driver_info        qmi_wwan_info_quirk_dtr = {
@@ -569,6 +604,17 @@ static const struct driver_info    qmi_wwan
        QMI_FIXED_INTF(vend, prod, 0)
 
 static const struct usb_device_id products[] = {
+#if 1 //Added by Quectel
+       { QMI_FIXED_INTF(0x05C6, 0x9003, 4) }, /* Quectel UC20 */
+       { QMI_FIXED_INTF(0x2C7C, 0x0125, 4) }, /* Quectel EC25 */
+       { QMI_FIXED_INTF(0x2C7C, 0x0121, 4) }, /* Quectel EC21 */
+       { QMI_FIXED_INTF(0x05C6, 0x9215, 4) }, /* Quectel EC20 */
+       { QMI_FIXED_INTF(0x2C7C, 0x0191, 4) }, /* Quectel EG91 */
+       { QMI_FIXED_INTF(0x2C7C, 0x0195, 4) }, /* Quectel EG95 */
+       { QMI_FIXED_INTF(0x2C7C, 0x0306, 4) }, /* Quectel EG06/EP06/EM06 */
+       { QMI_FIXED_INTF(0x2C7C, 0x0296, 4) }, /* Quectel BG96 */
+       { QMI_FIXED_INTF(0x2C7C, 0x0435, 4) }, /* Quectel AG35 */
+#endif
        /* 1. CDC ECM like devices match on the control interface */
        {       /* Huawei E392, E398 and possibly others sharing both device id and more... */
                USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, USB_CLASS_VENDOR_SPEC, 1, 9),
@@ -985,7 +1031,6 @@ static const struct usb_device_id produc
        {QMI_GOBI_DEVICE(0x05c6, 0x9225)},      /* Sony Gobi 2000 Modem device (N0279, VU730) */
        {QMI_GOBI_DEVICE(0x05c6, 0x9245)},      /* Samsung Gobi 2000 Modem device (VL176) */
        {QMI_GOBI_DEVICE(0x03f0, 0x251d)},      /* HP Gobi 2000 Modem device (VP412) */
-       {QMI_GOBI_DEVICE(0x05c6, 0x9215)},      /* Acer Gobi 2000 Modem device (VP413) */
        {QMI_FIXED_INTF(0x05c6, 0x9215, 4)},    /* Quectel EC20 Mini PCIe */
        {QMI_GOBI_DEVICE(0x05c6, 0x9265)},      /* Asus Gobi 2000 Modem device (VR305) */
        {QMI_GOBI_DEVICE(0x05c6, 0x9235)},      /* Top Global Gobi 2000 Modem device (VR306) */
--- a/drivers/usb/serial/option.c
+++ b/drivers/usb/serial/option.c
@@ -553,6 +553,22 @@ static void option_instat_callback(struc
 #define WETELECOM_PRODUCT_6802                 0x6802
 #define WETELECOM_PRODUCT_WMD300               0x6803
 
+#define LONGSUNG_PRODUCT_U9300C                 0x9b3c
+
+/* FORGE PRODUCT */
+#define FORGE_VENDOR_ID                         0x05c6
+
+#define FORGE_PRODUCT_SLM750                    0xf601
+
+/* NODECOM PRODUCT */
+#define NODECOM_VENDOR_ID                       0x1508
+
+#define NODECOM_PRODUCT_NL660                   0x1001
+
+/* NEOWAY PRODUCT */
+#define NEOWAY_VENDOR_ID                        0x2949
+
+#define NEOWAY_PRODUCT_N720                     0x8243
 
 /* Device flags */
 
@@ -564,6 +580,24 @@ static void option_instat_callback(struc
 
 
 static const struct usb_device_id option_ids[] = {
+#if 1 //Added by Quectel
+       { USB_DEVICE(0x05C6, 0x9090) }, /* Quectel UC15 */
+       { USB_DEVICE(0x05C6, 0x9003) }, /* Quectel UC20 */
+       { USB_DEVICE(0x2C7C, 0x0125) }, /* Quectel EC25 */
+       { USB_DEVICE(0x2C7C, 0x0121) }, /* Quectel EC21 */
+       { USB_DEVICE(0x05C6, 0x9215) }, /* Quectel EC20 */
+       { USB_DEVICE(0x2C7C, 0x0191) }, /* Quectel EG91 */
+       { USB_DEVICE(0x2C7C, 0x0195) }, /* Quectel EG95 */
+       { USB_DEVICE(0x2C7C, 0x0306) }, /* Quectel EG06/EP06/EM06 */
+       { USB_DEVICE(0x2C7C, 0x0296) }, /* Quectel BG96 */
+       { USB_DEVICE(0x2C7C, 0x0435) }, /* Quectel AG35 */
+#endif
+       { USB_DEVICE(0x19d2, 0x0536) },/* MZ386 */
+       { USB_DEVICE(LONGCHEER_VENDOR_ID, LONGSUNG_PRODUCT_U9300C) },
+       { USB_DEVICE(FORGE_VENDOR_ID, FORGE_PRODUCT_SLM750) },
+       { USB_DEVICE(NODECOM_VENDOR_ID, NODECOM_PRODUCT_NL660) },
+       { USB_DEVICE(NEOWAY_VENDOR_ID, NEOWAY_PRODUCT_N720) },
+
        { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COLT) },
        { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA) },
        { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA_LIGHT) },
@@ -1972,6 +2006,9 @@ static struct usb_serial_driver option_1
 #ifdef CONFIG_PM
        .suspend           = usb_wwan_suspend,
        .resume            = usb_wwan_resume,
+#if 1 //Added by Quectel
+       .reset_resume = usb_wwan_resume,
+#endif
 #endif
 };
 
@@ -2005,12 +2042,67 @@ static int option_probe(struct usb_seria
         * a separate module.
         */
        if (dev_desc->idVendor == cpu_to_le16(SAMSUNG_VENDOR_ID) &&
-           dev_desc->idProduct == cpu_to_le16(SAMSUNG_PRODUCT_GT_B3730) &&
-           iface_desc->bInterfaceClass != USB_CLASS_CDC_DATA)
+                       dev_desc->idProduct == cpu_to_le16(SAMSUNG_PRODUCT_GT_B3730) &&
+                       iface_desc->bInterfaceClass != USB_CLASS_CDC_DATA)
                return -ENODEV;
 
-       /* Store the device flags so we can use them during attach. */
-       usb_set_serial_data(serial, (void *)device_flags);
+#if 1 //Added by Quectel
+       //Quectel UC20's interface 4 can be used as USB network device
+       if (serial->dev->descriptor.idVendor == cpu_to_le16(0x05C6) && \
+                       serial->dev->descriptor.idProduct == cpu_to_le16(0x9003) \
+                       && serial->interface->cur_altsetting->desc.bInterfaceNumber >= 4)
+               return -ENODEV;
+       //Quectel EC20's interface 4 can be used as USB network device
+       if (serial->dev->descriptor.idVendor == cpu_to_le16(0x05C6) && \
+                       serial->dev->descriptor.idProduct == cpu_to_le16(0x9215) \
+                       && serial->interface->cur_altsetting->desc.bInterfaceNumber >= 4)
+               return -ENODEV;
+       //Quectel EC25&EC21&EG91&EG95&EG06&EP06&EM06&BG96/AG35's interface 4 can be used as USB network device
+       if (serial->dev->descriptor.idVendor == cpu_to_le16(0x2C7C) \
+                       && serial->interface->cur_altsetting->desc.bInterfaceNumber >= 4)
+               return -ENODEV;
+#endif
+#if 1 //Added by Quectel
+       //For USB Auto Suspend
+       if (serial->dev->descriptor.idVendor == cpu_to_le16(0x05C6) &&
+                       serial->dev->descriptor.idProduct == cpu_to_le16(0x9090)) {
+               pm_runtime_set_autosuspend_delay(&serial->dev->dev, 3000);
+               usb_enable_autosuspend(serial->dev);
+       }
+       if (serial->dev->descriptor.idVendor == cpu_to_le16(0x05C6) &&
+                       serial->dev->descriptor.idProduct == cpu_to_le16(0x9003)) {
+               pm_runtime_set_autosuspend_delay(&serial->dev->dev, 3000);
+               usb_enable_autosuspend(serial->dev);
+       }
+       if (serial->dev->descriptor.idVendor == cpu_to_le16(0x05C6) &&
+                       serial->dev->descriptor.idProduct == cpu_to_le16(0x9215)) {
+               pm_runtime_set_autosuspend_delay(&serial->dev->dev, 3000);
+               usb_set_serial_data(serial, (void *)device_flags);
+               usb_enable_autosuspend(serial->dev);
+       }
+       if (serial->dev->descriptor.idVendor == cpu_to_le16(0x2C7C)) {
+               pm_runtime_set_autosuspend_delay(&serial->dev->dev, 3000);
+               usb_enable_autosuspend(serial->dev);
+       }
+#endif
+#if 1 //Added by Quectel
+       //For USB Remote Wakeup
+       if (serial->dev->descriptor.idVendor == cpu_to_le16(0x05C6) &&
+                       serial->dev->descriptor.idProduct == cpu_to_le16(0x9090)) {
+               device_init_wakeup(&serial->dev->dev, 1); //usb remote wakeup
+       }
+       if (serial->dev->descriptor.idVendor == cpu_to_le16(0x05C6) &&
+                       serial->dev->descriptor.idProduct == cpu_to_le16(0x9003)) {
+               device_init_wakeup(&serial->dev->dev, 1); //usb remote wakeup
+       }
+       if (serial->dev->descriptor.idVendor == cpu_to_le16(0x05C6) &&
+                       serial->dev->descriptor.idProduct == cpu_to_le16(0x9215)) {
+               device_init_wakeup(&serial->dev->dev, 1); //usb remote wakeup
+       }
+       if (serial->dev->descriptor.idVendor == cpu_to_le16(0x2C7C)) {
+               device_init_wakeup(&serial->dev->dev, 1); //usb remote wakeup
+       }
+#endif
 
        return 0;
 }
--- a/drivers/usb/serial/qcserial.c
+++ b/drivers/usb/serial/qcserial.c
@@ -92,7 +92,6 @@ static const struct usb_device_id id_tab
        {USB_DEVICE(0x03f0, 0x241d)},   /* HP Gobi 2000 QDL device (VP412) */
        {USB_DEVICE(0x03f0, 0x251d)},   /* HP Gobi 2000 Modem device (VP412) */
        {USB_DEVICE(0x05c6, 0x9214)},   /* Acer Gobi 2000 QDL device (VP413) */
-       {USB_DEVICE(0x05c6, 0x9215)},   /* Acer Gobi 2000 Modem device (VP413) */
        {USB_DEVICE(0x05c6, 0x9264)},   /* Asus Gobi 2000 QDL device (VR305) */
        {USB_DEVICE(0x05c6, 0x9265)},   /* Asus Gobi 2000 Modem device (VR305) */
        {USB_DEVICE(0x05c6, 0x9234)},   /* Top Global Gobi 2000 QDL device (VR306) */
--- a/drivers/usb/serial/usb_wwan.c
+++ b/drivers/usb/serial/usb_wwan.c
@@ -504,6 +504,19 @@ static struct urb *usb_wwan_setup_urb(st
        usb_fill_bulk_urb(urb, serial->dev,
                          usb_sndbulkpipe(serial->dev, endpoint) | dir,
                          buf, len, callback, ctx);
+#if 1 //Added by Quectel for zero packet
+       if (dir == USB_DIR_OUT) {
+               struct usb_device_descriptor *desc = &serial->dev->descriptor;
+       if (desc->idVendor == cpu_to_le16(0x05C6) && desc->idProduct == cpu_to_le16(0x9090))
+               urb->transfer_flags |= URB_ZERO_PACKET;
+       if (desc->idVendor == cpu_to_le16(0x05C6) && desc->idProduct == cpu_to_le16(0x9003))
+               urb->transfer_flags |= URB_ZERO_PACKET;
+       if (desc->idVendor == cpu_to_le16(0x05C6) && desc->idProduct == cpu_to_le16(0x9215))
+               urb->transfer_flags |= URB_ZERO_PACKET;
+       if (desc->idVendor == cpu_to_le16(0x2C7C))
+               urb->transfer_flags |= URB_ZERO_PACKET;
+       }
+#endif
 
        return urb;
 }