Openwrt支持移远4G模块过程记录 您所在的位置:网站首页 移远ec25改gpd Openwrt支持移远4G模块过程记录

Openwrt支持移远4G模块过程记录

2024-01-22 18:29| 来源: 网络整理| 查看: 265

参考了不少教程,也做了不少尝试,最后记录下整个过程以便自己和坛友们参考

我所用的4G模块是Quectel EC20 R2.0,对于这个型号以下的操作前半部分修改USB Serial驱动应该是不需要的,但是我也都修改了并且记录下来,对于其他品牌型号的模块应该是原理相通的。 Quectel EC20R2.0

1、修改内核增加USB Serial驱动支持 增加PID&VID,教程中所用内核4.4.79尚没有支持,我用的4.19.122已经支持,而且两者之间的定义方式稍有不同教程里需要添加的代码为: build_dir/target-mips_24kc_musl/linux-ar71xx_generic/linux-4.4.79/drivers/usb/serial/option.c 【注】只添加#if 1 到 #endif的内容 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_id option_ids[]里添加了移远各型号的PID和VID 而新内核的此结构体是通过在前面define然后后面通过VENDOR_ID和PRODUCT来定义

#define QUECTEL_VENDOR_ID 0x2c7c /* These Quectel products use Quectel's vendor ID */ #define QUECTEL_PRODUCT_EC21 0x0121 #define QUECTEL_PRODUCT_EC25 0x0125 #define QUECTEL_PRODUCT_BG96 0x0296 #define QUECTEL_PRODUCT_EP06 0x0306 #define QUECTEL_PRODUCT_EM12 0x0512 #define QUECTEL_PRODUCT_RM500Q 0x0800

后面则是 { USB_DEVICE(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EC25), .driver_info = RSVD(4) }, 总之就是此处不需要额外修改了

2.添加零包处理

文件位于build_dir/target-mips_24kc_musl/linux-ar71xx_generic/linux-4.4.79/drivers/usb/serial/usb_wwan.c添加在函数urb中

static struct urb *usb_wwan_setup_urb(struct usb_serial_port *port, int endpoint, int dir, void *ctx, char *buf, int len, void (*callback) (struct urb *)) { struct usb_serial *serial = port->serial; struct usb_wwan_intf_private *intfdata = usb_get_serial_data(serial); struct urb *urb; urb = usb_alloc_urb(0, GFP_KERNEL); /* No ISO */ if (!urb) return NULL; usb_fill_bulk_urb(urb, serial->dev, usb_sndbulkpipe(serial->dev, endpoint) | dir, buf, len, callback, ctx); if (intfdata->use_zlp && dir == USB_DIR_OUT) urb->transfer_flags |= URB_ZERO_PACKET; #if 1 //Added by Quectelfor 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; if (desc->idVendor == cpu_to_le16(0x1286) && desc->idProduct == cpu_to_le16(0x4e3d)) { urb->transfer_flags |= URB_ZERO_PACKET; } } #endif return urb; } 3.增加休眠后唤醒接口

文件位于build_dir/target-mips_24kc_musl/linux-ar71xx_generic/linux-4.4.79/drivers/usb/serial/option.c添加在option_1port_device结构体中

static struct usb_serial_driver option_1port_device = { .driver = { .owner = THIS_MODULE, .name = "option1", }, .description = "GSM modem (1-port)", .id_table = option_ids, .num_ports = 1, .probe = option_probe, .open = usb_wwan_open, .close = usb_wwan_close, .dtr_rts = usb_wwan_dtr_rts, .write = usb_wwan_write, .write_room = usb_wwan_write_room, .chars_in_buffer = usb_wwan_chars_in_buffer, .tiocmget = usb_wwan_tiocmget, .tiocmset = usb_wwan_tiocmset, .ioctl = usb_wwan_ioctl, .attach = option_attach, .release = option_release, .port_probe = usb_wwan_port_probe, .port_remove = usb_wwan_port_remove, .read_int_callback = option_instat_callback, #ifdef CONFIG_PM .suspend = usb_wwan_suspend, .resume = usb_wwan_resume, #if 1 //Added by Quectel .reset_resume = usb_wwan_resume, #endif #endif }; 4.使用 GobiNet or QMI WWAN

如果使用ucxx/ec2x/egxx/EP06/EM06/BG96/AG35,并要求GobiNet或QMI WWAN,请添加以下语句,以防止这些模块接口4被用作USB串行设备文件位于build_dir/target-mips_24kc_musl/linux-ar71xx_generic/linux-4.4.79/drivers/usb/serial/option.c添加在函数option_probe中

static int option_probe(struct usb_serial *serial, const struct usb_device_id *id) { struct usb_interface_descriptor *iface_desc = &serial->interface->cur_altsetting->desc; unsigned long device_flags = id->driver_info; /* Never bind to the CD-Rom emulation interface */ if (iface_desc->bInterfaceClass == USB_CLASS_MASS_STORAGE) return -ENODEV; /* * Don't bind reserved interfaces (like network ones) which often have * the same class/subclass/protocol as the serial interfaces. Look at * the Windows driver .INF files for reserved interface numbers. */ if (device_flags & RSVD(iface_desc->bInterfaceNumber)) return -ENODEV; /* * Allow matching on bNumEndpoints for devices whose interface numbers * can change (e.g. Quectel EP06). */ if (device_flags & NUMEP2 && iface_desc->bNumEndpoints != 2) return -ENODEV; #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 /* Store the device flags so we can use them during attach. */ usb_set_serial_data(serial, (void *)device_flags); return 0; }

以下部分则是必须的了,不然即便设备和接口都能正常识别,但是却没法获取ip,此处参考https://www.right.com.cn/forum/thread-480555-1-1.html

修改内核增加QMI WWAN驱动支持

1.增加VID和PID

文件位于build_dir/target-mips_24kc_musl/linux-ar71xx_generic/linux-4.4.79/drivers/net/usb/qmi_wwan.c在结构体usb_device_id products[]中

static const struct usb_device_id products[] = { #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(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

但是我注意到源文件里有

#define QMI_MATCH_FF_FF_FF(vend, prod) \ USB_DEVICE_AND_INTERFACE_INFO(vend, prod, USB_CLASS_VENDOR_SPEC, \ USB_SUBCLASS_VENDOR_SPEC, 0xff), \ .driver_info = (unsigned long)&qmi_wwan_info_quirk_dtr ... ... {QMI_MATCH_FF_FF_FF(0x2c7c, 0x0125)}, /* Quectel EC25, EC20 R2.0 Mini PCIe */ {QMI_MATCH_FF_FF_FF(0x2c7c, 0x0306)}, /* Quectel EP06/EG06/EM06 */ {QMI_MATCH_FF_FF_FF(0x2c7c, 0x0512)}, /* Quectel EG12/EM12 */ {QMI_MATCH_FF_FF_FF(0x2c7c, 0x0800)}, /* Quectel RM500Q-GL */

不知道此处应该怎么理解

2.增加对Raw IP Mode的支持

文件位于build_dir/target-mips_24kc_musl/linux-ar71xx_generic/linux-4.4.79/drivers/net/usb/qmi_wwan.c增加一个函数

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; };

本来教程还要添加一部分LINUX_VERSION_CODE < KERNEL_VERSION( 3,9,1 )也就是处理内核版本低于3.9.1的,因为已知肯定是高于这个版本了,我就没有添加了下来是修改qmi_wwan_bind函数

static int qmi_wwan_bind(struct usbnet *dev, struct usb_interface *intf) { int status = -1; u8 *buf = intf->cur_altsetting->extra; int len = intf->cur_altsetting->extralen; ... ... /* make MAC addr easily distinguishable from an IP header */ if (possibly_iphdr(dev->net->dev_addr)) { dev->net->dev_addr[0] |= 0x02; /* set local assignment bit */ dev->net->dev_addr[0] &= 0xbf; /* clear "IP" bit */ } 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 EC25&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; }

教程里还有一个要修改的函数qmi_wwan_bind_shared,但是在此处不存在,所以不修改然后是两个结构体qmi_wwan_info和qmi_wwan_info_quirk_dtr里需要添加

static const struct driver_info qmi_wwan_info = { .description = "WWAN/QMI device", .flags = FLAG_WWAN | FLAG_SEND_ZLP, .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, #endif }; static const struct driver_info qmi_wwan_info_quirk_dtr = { .description = "WWAN/QMI device", .flags = FLAG_WWAN | FLAG_SEND_ZLP, .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, #endif .data = QMI_WWAN_QUIRK_DTR, }; 3、编译设置

内核

Device Drivers -> USB Support -> USB Serial Converter support -> USB driver for GSM and CMDA modems Device Drivers → -*- Network device support → USB Network Adapters → {*} Multi-purpose USB Networking Framework QMI WWAN driver for Qualcomm MSM based 3G and LTE modems

常规

Kernel modules >> USB Support >> Kmod -usb-core -*- Kmod -usb-net -*- Kmod-usb-net-cdc-ether Kmod-usb-net-cdc-mbim -*- Kmod-usb-net-cdc-ncm Kmod-usb-net-cdc-subset Kmod-usb-net-qmi-wwan Kmod-usb-ohci Kmod-usb-serial Kmod-usb-serial-option Kmod-usb-uhci Kmod-usb2 NetWork >> wwan chat ppp umbim Utilities quectel_cm usb-modeswitch ``` **Luci** ```makefile 1. Collections luci 3. Applications luci-app-multiwan (optional to support multiple 3g dongles) luci-app-qos (optional to provide QOS support) 6. Protocols luci-proto-3g -*- luci-proto-ppp luci-proto-qmi

其中quectel_cm也是来自https://download.csdn.net/download/jianzhizuo/10749215因为Quectel对于资料方面的管控比较严格,这方面我就不私自放出了,不过我查了github上有哈哈哈

在这里插入图片描述 编译好刷入后,在ssh执行quectel_cm &就会开始拨号,并且四海众联何锦明发布的源码是会自动设置dns的,不然还要自己手动设置 拨号成功后ifconfig会看到wwan0这个接口已经有了ip 在这里插入图片描述 在这里插入图片描述 在这里插入图片描述 其他相关内容,也是在学习过程中发现的: 采用的模块型号为移远EC20 R2.0等同于EC25,两者PID和VID一致,所以在lsusb时识别为EC25 插上后/dev会出现五个设备,分别是cdc-wdm0,ttyUSB0,ttyUSB1,ttyUSB2,ttyUSB3 其中cdc-wdm0是进行qmi拨号的设备 ttyUSB0是DM接口 ttyUSB1是GPS NMEA信息输出接口 ttyUSB2是AT指令的接口 ttyUSB3是建立ppp连接或者AT指令的接口

因为ttyUSB2是用来交互AT指令的,所以可以通过cat /dev/ttyUSB2 & 指令来保持这个接口的输出反馈,然后输入AT指令来控制模块 echo -e “AT+QCCID\r\n” >/dev/ttyUSB2 //查询SIM卡 echo -e “AT+CFUN=1,1\r\n” >/dev/ttyUSB2 //重启模块 echo -e “AT+QSIMDET=1\r\n” >/dev/ttyUSB2 //开启SIM卡热插拔状态报告 echo -e “AT+QSIMDET=1,1\r\n” >/dev/ttyUSB2 //开启SIM卡检测功能 echo -e “AT+CSQ\r\n” >/dev/ttyUSB2 //查询信号强度 echo -e “AT+QNWINFO\r\n” >/dev/ttyUSB2 //查询网络状态 echo -e “AT+CGMM\r\n” >/dev/ttyUSB2 //输出模块型号 echo -e “AT+CGMI\r\n” >/dev/ttyUSB2 //输出厂商 echo -e “AT+QCFG=“NWSCANMODE”,3,1\r\n” >/dev/ttyUSB2 //设置4G LTE only echo -e “AT+QCFG=“NWSCANMODE”,2,1\r\n” >/dev/ttyUSB2 //设置3G WCDMA only echo -e “AT+QCFG=“NWSCANMODE”,1,1\r\n” >/dev/ttyUSB2 //设置2G GSM only echo -e “AT+QCFG=“NWSCANMODE”,0,1\r\n” >/dev/ttyUSB2 //设置自动搜索网络



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有