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

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

0531_6.jpg (180.92 KB, 下载次数: 0)

2020-5-31 11:04 上传

修改内核增加USB Serial驱动支持

1.增加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,

};

编译设置

内核

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

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上有哈哈哈

0531_3.jpg (21.43 KB, 下载次数: 0)

2020-5-31 11:20 上传

编译好刷入后,在ssh执行quectel_cm &就会开始拨号,并且

0531_4.jpg (291.08 KB, 下载次数: 0)

2020-5-31 11:21 上传

拨号成功后ifconfig会看到wwan0这个接口已经有了ip

0531_8.jpg (283.93 KB, 下载次数: 0)

2020-5-31 11:22 上传

然后开始ping baidu.com也有结果了

0531_5.jpg (270.1 KB, 下载次数: 0)

2020-5-31 11:23 上传

到了这时候,路由器自身已经可以上网了,但是还没能把网络转发给LAN,需要额外创建一个接口,叫什么无所谓,协议选DHCP,接口选wwan0,防火墙选在wan就可以了

0531_2.jpg (88.31 KB, 下载次数: 0)

2020-5-31 11:20 上传

0531_1.jpg (72.54 KB, 下载次数: 0)

2020-5-31 11:24 上传

其他相关内容,也是在学习过程中发现的:

采用的模块型号为移远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 //设置自动搜索网络

4g模块注册上网 移远_Openwrt支持移远4G模块过程记录相关推荐

  1. 4g模块注册上网 移远_Openwrt实现4G模块上网功能

    Openwrt 实现 4G 模块上网功能 上海润欣科技股份有限公司创研社 大家都知道传统的路由器无非基于以下几种方式上网: 首先运营商会将网线拉入居室,该网络可以是传统的电话线 / 双绞线 / 光纤. ...

  2. 4g模块注册上网 移远_Openwrt如何实现4G模块上网功能

    大家都知道传统的路由器无非基于以下几种方式上网: 首先运营商会将网线拉入居室,该网络可以是传统的电话线/双绞线/光纤. 入户的信号线,需要通过调制解调器(猫)转换为数字信号,通过网线输出. 早期的电话 ...

  3. 4g模块注册上网 移远_移远EC20(4G模块)通过openwrt路由器拨号上网

    移远EC20是一个兼容性比较强的4G模块.我入手的这个是EC20 R2.1版本,pcie接口的,这个版本是增强版,支持最高150Mbps的下载速率,而普通的EC20只有100Mbps下载速率.这个是全 ...

  4. 4g模块注册上网 移远_RK3399 4G模块移远EC20移植调试

    CPU:RK3399 系统:Android 7.1 1.通过串口打印或者adb获取模块的 pid 和 vid,顺便可以看到生成 4 个虚拟串口 /dev/ttyUSB* [ 11.734379] us ...

  5. 4g模块注册上网 移远_【技术分享】Openwrt实现4G模块上网功能

    大家都知道传统的路由器无非基于以下几种方式上网:首先运营商会将网线拉入居室,该网络可以是传统的电话线/双绞线/光纤. 入户的信号线,需要通过调制解调器(猫)转换为数字信号,通过网线输出. 早期的电话上 ...

  6. 4g模块注册上网 移远_通信模组企业 移远通信amp;广和通

    无线通信模组通常长这个样,它是物联网设备中的关键部件. 1. 通信模组介绍无线模组为物联网开发者提供了便利,使开发者可以专注于特定应用领域业务的开发而不用关注通信协议的技术细节.无线通信模组厂商通常会 ...

  7. 4g模块注册上网 移远_物联网模组龙头移远通信

    本周末我们一起梳理一下最近刷策略报告通信板块见到的两只比较高频的标的移远通信和广和通,今天我们先一起梳理一下移远通信,公司主营业务是从事物联网领域无线通信模组及其解决方案的设计.生产.研发与销售服务, ...

  8. glance服务器上传的镜像支持,OpenStack Glance安装配置过程记录

    Glance是作为OpenStack的虚拟机的Image(镜像)服务, 它提供了一系列的REST API, 用来管理.查询虚拟机的镜像, 它支持多种后端存储介质, 例如用本地文件系统作为介质.Swif ...

  9. 【金猿技术展】模块注册机制——打造AI算法流水线

    上海人工智能实验室&商汤科技技术 本项目由上海人工智能实验室&商汤科技投递并参与"数据猿年度金猿策划活动--2021大数据产业创新技术突破榜榜单及奖项"评选. 数据 ...

最新文章

  1. 如何成为一名无人驾驶工程师
  2. 为了追求更快,CPU、内存、I/O都做了哪些努力?
  3. Linux非阻塞IO(八)使用epoll重新实现非阻塞的回射服务器
  4. RuntimeError: Expected object of backend CUDA but got backend CPU for argument #4 'mat1'
  5. linux编译安装wine,Ubuntu 13.10 编译安装Wine 1.7
  6. AngularJS学习笔记之directive—scope选项与绑定策略
  7. 基于.net开发chrome核心浏览器【五】
  8. 统一软件开发过程(rup)理解
  9. Java语言中的泛型
  10. TreeSet 和 TreeMap 排序
  11. SecKill学习初步框架时报错记录
  12. 360oauth token是什么意思_币圈token是什么意思?
  13. APISpace 绕口令API接口 免费好用
  14. android互动设计师,站酷(设计师互动平台)
  15. 7-3 特立独行的幸福
  16. pycharm光标变粗变宽
  17. explicit的作用
  18. 人工智能期末复习——速通知识点
  19. stm32波特率配置
  20. 实时计算Flink+Hologres

热门文章

  1. utf-8编码的字符串转成unicode(ucs-4)编码的字符串
  2. Google布隆过滤器与Redis布隆过滤器详解
  3. java设计模式--单例设计模式
  4. leetcode 1339. Maximum Product of Splitted Binary Tree | 1339. 分裂二叉树的最大乘积(树形dp)
  5. 高并发负载均衡(三):LVS的DR模型试验搭建
  6. 前端如何实现:在不刷新页面的情况下实时看到自己的评论
  7. 【Git】从Git远程存储库中删除所有.pyc编译文件;附常用gitignore配置
  8. 【Java小游戏】小球躲避游戏 图片轮播爆炸效果、边缘反弹、计时功能
  9. 牛客网_PAT乙级_1023旧键盘打字(20)【别人代码里用到的hash是啥】
  10. 看动画学算法之:排序-插入排序