eg25-g: Add Quectel EG25-G Driver patches to Kernel

This commit is contained in:
dchvs 2021-02-16 21:06:14 -06:00
parent e7952b2f70
commit 10e21073d5
3 changed files with 89 additions and 12 deletions

View File

@ -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. * to 00:a0:c6:00:00:00 despite the host address being different.
* This function will also fixup such packets. * This function will also fixup such packets.
*/ */
#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
static int qmi_wwan_rx_fixup(struct usbnet *dev, struct sk_buff *skb) static int qmi_wwan_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
{ {
struct qmi_wwan_state *info = (void *)&dev->data; 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->netdev_ops = &qmi_wwan_netdev_ops;
dev->net->sysfs_groups[0] = &qmi_wwan_sysfs_attr_group; 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: err:
return status; return status;
} }
@ -536,6 +572,11 @@ static const struct driver_info qmi_wwan_info = {
.unbind = qmi_wwan_unbind, .unbind = qmi_wwan_unbind,
.manage_power = qmi_wwan_manage_power, .manage_power = qmi_wwan_manage_power,
.rx_fixup = qmi_wwan_rx_fixup, .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 = { 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(0x1199, 0x901b)}, /* Sierra Wireless MC7770 */
{QMI_GOBI_DEVICE(0x12d1, 0x14f1)}, /* Sony Gobi 3000 Composite */ {QMI_GOBI_DEVICE(0x12d1, 0x14f1)}, /* Sony Gobi 3000 Composite */
{QMI_GOBI_DEVICE(0x1410, 0xa021)}, /* Foxconn Gobi 3000 Modem device (Novatel E396) */ {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 */ { } /* END */
}; };
MODULE_DEVICE_TABLE(usb, products); MODULE_DEVICE_TABLE(usb, products);

View File

@ -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_6802, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(WETELECOM_VENDOR_ID, WETELECOM_PRODUCT_WMD300, 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) */ { 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 */ { } /* Terminating entry */
}; };
MODULE_DEVICE_TABLE(usb, option_ids); MODULE_DEVICE_TABLE(usb, option_ids);
@ -1976,7 +1983,9 @@ static struct usb_serial_driver option_1port_device = {
#ifdef CONFIG_PM #ifdef CONFIG_PM
.suspend = usb_wwan_suspend, .suspend = usb_wwan_suspend,
.resume = usb_wwan_resume, .resume = usb_wwan_resume,
.reset_resume = usb_wwan_resume, #if 1 //Added by Quectel
.reset_resume = usb_wwan_resume,
#endif
#endif #endif
}; };
@ -2013,10 +2022,13 @@ static int option_probe(struct usb_serial *serial,
dev_desc->idProduct == cpu_to_le16(SAMSUNG_PRODUCT_GT_B3730) && dev_desc->idProduct == cpu_to_le16(SAMSUNG_PRODUCT_GT_B3730) &&
iface_desc->bInterfaceClass != USB_CLASS_CDC_DATA) iface_desc->bInterfaceClass != USB_CLASS_CDC_DATA)
return -ENODEV; return -ENODEV;
if (serial->dev->descriptor.idVendor == cpu_to_le16(QUECTEL_VENDOR_ID) && serial->interface->cur_altsetting->desc.bInterfaceNumber >= 4) #if 1 //Added by Quectel
return -ENODEV; //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. */ /* Store the device flags so we can use them during attach. */
usb_set_serial_data(serial, (void *)device_flags); usb_set_serial_data(serial, (void *)device_flags);

View File

@ -505,12 +505,19 @@ static struct urb *usb_wwan_setup_urb(struct usb_serial_port *port,
usb_fill_bulk_urb(urb, serial->dev, usb_fill_bulk_urb(urb, serial->dev,
usb_sndbulkpipe(serial->dev, endpoint) | dir, usb_sndbulkpipe(serial->dev, endpoint) | dir,
buf, len, callback, ctx); buf, len, callback, ctx);
#if 1 //Added by Quectel for Zero Packet
if (dir == USB_DIR_OUT) { if (dir == USB_DIR_OUT) {
struct usb_device_descriptor *desc = &serial->dev->descriptor; struct usb_device_descriptor *desc = &serial->dev->descriptor;
if (desc->idVendor == cpu_to_le16(QUECTEL_VENDOR_ID)) if (desc->idVendor == cpu_to_le16(0x05C6) && desc->idProduct == cpu_to_le16(0x9090))
urb->transfer_flags |= URB_ZERO_PACKET; 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; return urb;
} }