参照移远EC20用户指导手册移植驱动:
《Quectel_UMTS_LTE_5G_Linux_USB_Driver_用户指导_V1.0》
Linux内核版本:5.15.148
一、移植过程
jetson Orin Nano 开发板USB插拔EC20打印

USB插上EC20,生成 /dev/ttyUSB0 - /dev/ttyUSB3,功能如下:

$ lsusb #lsusb能看到 VID、PID

1、修改内核配置
Jetson Orin Nano配置文件路径:arch/arm64/configs/defconfig
1.1 配置USB转串口驱动
CONFIG_USB_SERIAL=y
CONFIG_USB_SERIAL_WWAN=y
CONFIG_USB_SERIAL_OPTION=y
1.2 配置QMI_WWAN驱动
当模块成功加载QMI_WWA驱动程序后,会创建一个网络设备和一个QMI设备节点。网络设备名称为“wwanX”,QMI设备节点名称为“/dev/cdc-wdmX”。网络设备用于数据传输,QMI设备节点用于QMI消息交互。
CONFIG_USB_NET_DRIVERS=y
CONFIG_USB_USBNET=y
CONFIG_USB_NET_QMI_WWAN=y
CONFIG_USB_WDM=y
修改后如下:


2、修改Kernel源码,支持EC20
2.1 修改USB转串口驱动
1)修改 drivers/usb/serial/option.c,添加VID和PID
static const struct usb_device_id option_ids[] = {
#if 1 // 2025-04-24 Added by Quectel
{ USB_DEVICE(0x2C7C, 0x0125) },
#endif
... ...
}
2)使用USBNet驱动
drivers/usb/serial/option.c
static int option_probe(struct usb_serial *serial,
const struct usb_device_id *id)
{
... ...
#if 1 // 2025-04-24 Added by Quectel
if (serial->dev->descriptor.idVendor == cpu_to_le16(0x2C7C)) {
__u16 idProduct = le16_to_cpu(serial->dev->descriptor.idProduct);
struct usb_interface_descriptor *intf = &serial->interface->cur_altsetting->desc;
if (intf->bInterfaceClass != 0xFF || intf->bInterfaceSubClass == 0x42) {
//ECM, RNDIS, NCM, MBIM, ACM, UAC, ADB
return -ENODEV;
}
if ((idProduct&0xF000) == 0x0000) {
//MDM interface 4 is QMI
if (intf->bInterfaceNumber == 4 && intf->bNumEndpoints == 3
&& intf->bInterfaceSubClass == 0xFF && intf->bInterfaceProtocol == 0xFF)
return -ENODEV;
}
}
#endif
/* Store the device flags so we can use them during attach. */
usb_set_serial_data(serial, (void *)device_flags);
return 0;
}
3)添加零包机制
根据USB协议的要求,通过添加如下语句在bulk-out传输过程中添加处理零包的机制:
路径:drivers/usb/serial/usb_wwan.c
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 *))
{
... ...
usb_fill_bulk_urb(urb, serial->dev,
usb_sndbulkpipe(serial->dev, endpoint) | dir,
buf, len, callback, ctx);
#if 1 //2025-04-24 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(0x2C7C))
urb->transfer_flags |= URB_ZERO_PACKET;
}
#endif
return urb;
}
4)添加Reset-resume机制(休眠唤醒)
部分USB主机控制器或USB hub在MCU进入Suspend/Sleep(挂起/睡眠)模式时会发生掉电或复位,并且在MCU退出Suspend/Sleep模式后不能使模块恢复。需要通过添加以下语句来启用reset-resume机制。
drivers/usb/serial/option.c
static struct usb_serial_driver option_1port_device = {
... ...
#ifdef CONFIG_PM
.suspend = usb_wwan_suspend,
.resume = usb_wwan_resume,
#if 1 //2025-04-24 Added by Quectel
.reset_resume = usb_wwan_resume,
#endif
#endif
};
3、添加QMI_WWAN驱动
移远提供了QMI_WWAN驱动源文件qmi_wwan_q.c,拷贝到 drivers/net/usb/ 目录下。修改drivers/net/usb/Makefile,使其能编译 qmi_wwan_q.c
# must insert qmi_wwan_q.o before qmi_wwan.o
obj-${CONFIG_USB_NET_QMI_WWAN} += qmi_wwan_q.o
obj-${CONFIG_USB_NET_QMI_WWAN} += qmi_wwan.o

二、验证EC20驱动移植结果
1、编译kernel
编译遇到问题:编译时 qmi_wwan_q.c 中报错 ,没有定义 "rmnet_nss_callbacks"

解决步骤:qmi_wwan_q.c 中搜索 "rmnet_nss_callbacks",发现与 CONFIG_QCA_NSS_DRV 配置相关,最终发现是由于 arch/arm64/configs/defconfig 中配置了 CONFIG_PINCTRL_IPQ8074 导致的
解决方法:删除 CONFIG_QCA_NSS_DRV 配置,即删除 CONFIG_PINCTRL_IPQ8074

编译OK后,刷机并启动。
2、命令测试结果
2.1 查看内核打印信息
启动后的打印:

2.2 查看 /dev/ttyUSB 0 -3 节点生成
$ ls /dev/ttyUSB*

2.3 查看 /dev/cdc-wdm0 节点生成
$ ls /dev/cdc-wdm0

2.4 查看wwan0网卡
ifconfig看不到wwan0网卡,输入命令打开网卡
$ sudo ifconfig wwan0 up

3、按照EC20文档测试
3.1 测试AT命令
$ sudo apt-get install minicom #安装minicom工具
$ minicom -v #查看版本

测试:
$ sudo busybox microcom /dev/ttyUSB2

3.2 测试QMI_WWAN驱动(4G)
quectel-CM 是移远提供的拨号工具
3.2.1 验证quectel-CM
1)编译生成测试程序
make编译结果如下

板子和电脑同时接到公司路由上(都获取同一网段的IP),UBUNTU输入命令:
$ scp ./quectel-CM nvidia@192.168.7.36:/tmp #用scp命令将quectel-CM拷贝到板子
$ scp defult.script nvidia@192.168.7.36:/usr/share/udhcpc/ #用scp命令将 defult.script 拷贝到板子 /usr/share/udhcpc/ 目录
$ scp defult.script nvidia@192.168.7.36:/etc/udhcpc/ #用scp命令将 defult.script 拷贝到板子 /etc/udhcpc/ 目录
注意设置 defult.script 的权限,开发板输入命令
$ sudo chmod 755 /usr/share/udhcpc/defult.script
$ sudo chmod 755 /etc/udhcpc/defult.script
断开网线,开发板输入命令:
$ sudo ./quectel-CM & #要加sudo,否则打开文件失败
问题记录:
问题:
sudo ./quectel-CM & 运行quectel-CM 会调用 udhcpc 获取 wwan0 网卡的IP地址,但是发现wwan0的IP并没有设置成功,因此无法 ping通 "www.baidu.com"

问题分析:
- default.script脚本最前面加打印,发现调用udhcpc命令时,default.script脚本没有调用
- 改用 dhclient wwan0 后,ip才设到wwan0,并能ping通 "www.baidu.com"。进一步确认是default.script脚本的问题
- default.script其实就是shell脚本,命令行直接执行 ./default.script,打印"-bash: ./default.script: /bin/sh^M: bad interpreter: No such file or directory",原因是default.script文件是windos格式,需转为Linux格式

解决方法:
- ubuntu下安装dos2unix:$ sudo apt-get install dos2unix
- $ dos2unix default.script 将default.script转换为 UNIX/Linux格式
- 将 default.script 重新传入开发板测试,设置 default.script 权限为 755

将 /tmp/default.script 拷贝到 /etc/udhcpc/ 和 /usr/share/udhcpc/ 下
$ sudo chmod 755 /etc/udhcpc/default.script #修改权限
$ sudo chmod 755 /usr/share/udhcpc/default.script #修改权限
2)测试成功
$ sudo quectel-CM &
$ ifconfig wwan0
$ ping www.baidu.com
测试过程如图:

EC20移植完成,所有修改的文件:
https://download.csdn.net/download/hinewcc/90911606