diff --git a/kernel/kernel-4.9/drivers/net/usb/qmi_wwan.c b/kernel/kernel-4.9/drivers/net/usb/qmi_wwan.c index 2b728cc52..d332c6eba 100644 --- a/kernel/kernel-4.9/drivers/net/usb/qmi_wwan.c +++ b/kernel/kernel-4.9/drivers/net/usb/qmi_wwan.c @@ -175,6 +175,27 @@ static const u8 buggy_fw_addr[ETH_ALEN] = {0x00, 0xa0, 0xc6, 0x00, 0x00, 0x00}; * to 00:a0:c6:00:00:00 despite the host address being different. * This function will also fixup such packets. */ + +#if 1 /* Added by Quectel */ +#include +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 + static int qmi_wwan_rx_fixup(struct usbnet *dev, struct sk_buff *skb) { struct qmi_wwan_state *info = (void *)&dev->data; @@ -445,6 +466,21 @@ static int qmi_wwan_bind(struct usbnet *dev, struct usb_interface *intf) } 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, "Quectel EC21&EC25&EC20 R2.0 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; } @@ -536,6 +572,11 @@ static const struct driver_info qmi_wwan_info = { .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, + /* */ +#endif }; static const struct driver_info qmi_wwan_info_quirk_dtr = { @@ -1014,7 +1055,24 @@ static const struct usb_device_id products[] = { {QMI_GOBI_DEVICE(0x1199, 0x901b)}, /* Sierra Wireless MC7770 */ {QMI_GOBI_DEVICE(0x12d1, 0x14f1)}, /* Sony Gobi 3000 Composite */ {QMI_GOBI_DEVICE(0x1410, 0xa021)}, /* Foxconn Gobi 3000 Modem device (Novatel E396) */ - + #if 1 + /* Added by Quectel */ + #ifndef QMI_FIXED_INTF + /* map QMI/wwan function by a fixed interface number */ + #define QMI_FIXED_INTF(vend, prod, num) \ + .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO, \ + .idVendor = vend, \ + .idProduct = prod, \ + .bInterfaceClass = 0xff, \ + .bInterfaceSubClass = 0xff, \ + .bInterfaceProtocol = 0xff, \ + .driver_info= (unsigned long)&qmi_wwan_force_int##num, + #endif + { QMI_FIXED_INTF(0x05C6, 0x9003, 4) }, /* Quectel UC20 */ + { QMI_FIXED_INTF(0x05C6, 0x9215, 4) }, /* Quectel EC20 */ + { QMI_FIXED_INTF(0x2C7C, 0x0125, 4) }, /* Quectel EC25/EC20 R2.0 */ + { QMI_FIXED_INTF(0x2C7C, 0x0121, 4) }, /* Quectel EC21 */ + #endif { } /* END */ }; MODULE_DEVICE_TABLE(usb, products); diff --git a/kernel/kernel-4.9/drivers/usb/serial/option.c b/kernel/kernel-4.9/drivers/usb/serial/option.c index 1ea6d23a1..5e1e082d7 100644 --- a/kernel/kernel-4.9/drivers/usb/serial/option.c +++ b/kernel/kernel-4.9/drivers/usb/serial/option.c @@ -1942,6 +1942,13 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE_AND_INTERFACE_INFO(WETELECOM_VENDOR_ID, WETELECOM_PRODUCT_6802, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(WETELECOM_VENDOR_ID, WETELECOM_PRODUCT_WMD300, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(0x03f0, 0x421d, 0xff, 0xff, 0xff) }, /* HP lt2523 (Novatel E371) */ + #if 1 + { USB_DEVICE(0x05C6, 0x9090) }, /* Quectel UC15 */ + { USB_DEVICE(0x05C6, 0x9003) }, /* Quectel UC20 */ + { USB_DEVICE(0x05C6, 0x9215) }, /* Quectel EC20 */ + { USB_DEVICE(0x2C7C, 0x0125) }, /* Quectel EC25/EC20 R2.0 */ + { USB_DEVICE(0x2C7C, 0x0121) }, /* Quectel EC21 */ + #endif { } /* Terminating entry */ }; MODULE_DEVICE_TABLE(usb, option_ids); @@ -1976,7 +1983,9 @@ static struct usb_serial_driver option_1port_device = { #ifdef CONFIG_PM .suspend = usb_wwan_suspend, .resume = usb_wwan_resume, - .reset_resume = usb_wwan_resume, +#if 1 //Added by Quectel + .reset_resume = usb_wwan_resume, +#endif #endif }; @@ -2013,10 +2022,13 @@ static int option_probe(struct usb_serial *serial, dev_desc->idProduct == cpu_to_le16(SAMSUNG_PRODUCT_GT_B3730) && iface_desc->bInterfaceClass != USB_CLASS_CDC_DATA) return -ENODEV; - - if (serial->dev->descriptor.idVendor == cpu_to_le16(QUECTEL_VENDOR_ID) && serial->interface->cur_altsetting->desc.bInterfaceNumber >= 4) - return -ENODEV; - + + #if 1 //Added by Quectel + //Quectel EC21&EC25&EC20 R2.0'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 /* Store the device flags so we can use them during attach. */ usb_set_serial_data(serial, (void *)device_flags); diff --git a/kernel/kernel-4.9/drivers/usb/serial/usb_wwan.c b/kernel/kernel-4.9/drivers/usb/serial/usb_wwan.c index 53b24ce40..89d3e9db3 100644 --- a/kernel/kernel-4.9/drivers/usb/serial/usb_wwan.c +++ b/kernel/kernel-4.9/drivers/usb/serial/usb_wwan.c @@ -505,12 +505,19 @@ static struct urb *usb_wwan_setup_urb(struct usb_serial_port *port, usb_fill_bulk_urb(urb, serial->dev, usb_sndbulkpipe(serial->dev, endpoint) | dir, buf, len, callback, ctx); - - if (dir == USB_DIR_OUT) { - struct usb_device_descriptor *desc = &serial->dev->descriptor; - if (desc->idVendor == cpu_to_le16(QUECTEL_VENDOR_ID)) - urb->transfer_flags |= URB_ZERO_PACKET; - } + #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(QUECTEL_VENDOR_ID)) + urb->transfer_flags |= URB_ZERO_PACKET; + } + #endif return urb; }