EC20 驱动 移植 Gobinet 拨号
Ubuntu Server 18.04 中 移远EC20 驱动 移植 Gobinet 拨号
某宝买了台mini 工控机,让店家给安装了 移远EC20 的4G网卡; 拿回来装ubuntu,发现没有驱动啊,店家也只有window的驱动,无奈,只给了个移远官方的文件,照着操作吧。
《Quectel_WCDMA<E_Linux_USB_Driver_User_Guide_V1.7.pdf》
《Quectel_WCDMA<E_Linux_USB_Driver_User_Guide_V2.0.pdf》
就这两份呢文件, 折腾了好几天 终于搞好了
怕有什么奇怪的问题,我都是在root 用户下操作的 ,
一、下载 linux 内核
查看内核版本 uname -r
root@thingsbox:/# uname -r
4.15.0-106-generic
查找系统可用的 内核 apt search linux-source
root@thingsbox:/# apt search linux-source
Sorting... Done
Full Text Search... Done
linux-source/bionic-updates,bionic-security,now 4.15.0.106.94 all [installed]
Linux kernel source with Ubuntu patches
linux-source-4.15.0/bionic-updates,bionic-security,now 4.15.0-106.107 all [installed,automatic]
Linux kernel source for version 4.15.0 with Ubuntu patches
linux-source-4.18.0/bionic-updates,bionic-security 4.18.0-25.26~18.04.1 all
Linux kernel source for version 4.18.0 with Ubuntu patches
linux-source-5.0.0/bionic-updates,bionic-security 5.0.0-52.56~18.04.1 all
Linux kernel source for version 5.0.0 with Ubuntu patches
linux-source-5.3.0/bionic-updates,bionic-security 5.3.0-59.53~18.04.1 all
Linux kernel source for version 5.3.0 with Ubuntu patches
选择你和你系统相匹配的 内核版本 然后安装, 命令后面可以带上版本号
root@thingsbox:/# apt install linux-source
下载完成后, 安装的内核 一般在 /usr/src/目录下面
root@thingsbox:/usr/src# cd /usr/src/
root@thingsbox:/usr/src# ls
linux-headers-4.15.0-106 linux-headers-4.15.0-106-generic linux-source-4.15.0 linux-source-4.15.0.tar.bz2
打开 /usr/src/linux-source-4.15.0 目录 解压内核 tar -jxvf linux-source-4.15.0.tar.bz2
root@thingsbox:/usr/src/linux-source-4.15.0# ls
debian debian.master linux-source-4.15.0 linux-source-4.15.0.tar.bz2
root@thingsbox:/usr/src/linux-source-4.15.0# tar -jxvf linux-source-4.15.0.tar.bz2
最终 内核文件的位置为 /usr/src/linux-source-4.15.0/linux-source-4.15.0
root@thingsbox:/usr/src/linux-source-4.15.0/linux-source-4.15.0# pwd
/usr/src/linux-source-4.15.0/linux-source-4.15.0
root@thingsbox:/usr/src/linux-source-4.15.0/linux-source-4.15.0# ls
arch CREDITS dropped.txt init kernel mm scripts tools virt
block crypto firmware ipc lib net security ubuntu
certs Documentation fs Kbuild MAINTAINERS README snapcraft.yaml update-version-dkms
COPYING drivers include Kconfig Makefile samples sound usr
二、USB Serial Driver USB 驱动编辑
参考 《Quectel_WCDMA<E_Linux_USB_Driver_User_Guide_V1.7.pdf》 的3.2 章节,照着一步一操作 ,很easy
If you are using UC15/UC20/EC25/EC21/EC20/EC20 R2.0/EG91/EG95/EG06/EP06/EM06/BG96 and
requiring USB serial driver, please read this section for details. Otherwise, please skip this section.
When a Quectel module is attached to the USB Serial driver, the driver will create device files in directory
“/dev”, named as below:
ttyUSB0/ttyUSB1/ttyUSB2...
如果USB 驱动安装 成功 会在 /dev 目录先看见 ttyUSB0/ttyUSB1/ttyUSB2/ ttyUSB3 这几个设备
3.2.1. Add VID and PID
In order to recognize Quectel module, you should add module VID and PID information as below:
File: [KERNEL]/drivers/usb/serial/option.c
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/EC20 R2.0 */
{ 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 */
#endif
If you are using EC20 and following files and statements exist in your kernel source files, please delete
them, as they will conflict with EC20's USB Drivers
如果你的芯片是 EC20 还要删除这几个冲突的东西,我也不知道是什么
[KERNEL]/drivers/usb/serial/qcserial.c
{USB_DEVICE(0x05c6, 0x9215)}, /* Acer Gobi 2000 Modem device (VP413) */
[KERNEL]/drivers/net/usb/qmi_wwan.c
{QMI_GOBI_DEVICE(0x05c6, 0x9215)}, /* Acer Gobi 2000 Modem device (VP413) */
3.2.2. Add the Zero Packet Mechanism
As required by the USB protocol, you need to add the mechanism for processing zero packets during bulk
out transmission.
添加零包处理机制
File: [KERNEL]/drivers/usb/serial/usb_wwan.c
static struct urb *usb_wwan_setup_urb(struct usb_serial *serial, 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
//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(0x2C7C))
urb->transfer_flags |= URB_ZERO_PACKET;
}
#endif
return urb;
}
3.2.3. Add Reset Resume
Some USB host controllers/USB hubs will lost power or be reset when MCU entering into suspend/sleep mode, and they cannot resume USB devices when MCU exiting from suspend/sleep mode; instead, they will operate reset-resume. You should add the following statements:
睡眠重启
File: [KERNEL]/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 //Added by Quectel
.reset_resume
= usb_wwan_resume,
#endif
#endif
};
3.2.4. Enlarge Bulk out URBs
For Linux kernel version older than 2.6.29. You need to enlarge bulk out URBs to get faster uplink speed.
老的内核版本 还要添加这个东西 ,我的内核是 4.15 所以没有操作
3.2.5. Use GobiNet or QMI WWAN
If you are using UC20/EC25/EC21/EC20/EC20 R2.0/EG91/EG95/EG06/EP06/EM06/BG96 and requiring GobiNet or QMI WWAN, you must add the following statements to prevent these modules’ interface 4 from being used as USB serial device.
如果要使用 GobiNet 拨号, 还要配置这个
File: [KERNEL]/drivers/usb/serial/option.c
static int option_probe(struct usb_serial *serial, const struct usb_device_id *id) {
struct usb_wwan_intf_private *data;
......
#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&EC20 R2.0&EG91&EG95&EG06&EP06&EM06&BG96'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 device id so we can use it during attach. */
usb_set_serial_data(serial, (void *)id);
return 0;
}
3.2.6. Modify Kernel Configuration
There are several mandatory selected items in kernel configuration; you should follow the steps below to
configure the kernel:
修改内核配置,
这里要注意 我捣鼓了好久 , 就是捣鼓不对
Step 1: cd <your kernel directory>
这里 **your kernel directory ** 是内核的根目录,比如 我的内核根目录 就是'/usr/src/linux-source-4.15.0/linux-source-4.15.0'
Step 2: Set your environment variables, and import your board's defconfig The following is an example
for Raspeberrypi board
export ARCH=arm
export CROSS_COMPILE=arm-none-linux-gnueabi-
make bcmrpi_defconfig
关于默认的 defconfig 文件, 主要看每个平台的芯片。x86平台在[KERNEL]/arch/x86/configs。正常Arm的配置是在:[KERNEL]/arch/arm/configs
在内核 根目录下 make x86_64_defconfig
Step 3: make menuconfig
Step 4: Enable CONFIG_USB_SERIAL_OPTION
[*] Device Drivers →
[*] USB Support →
[*] USB Serial Converter support →
[*] USB driver for GSM and CDMA modems
按下 Y 键 选中 ,然后 选择 save 后 退出
最后在内核根目录下编译相关项目
3.2.7. Build and Load Driver as Kernel Module for PC in Linux
If you are using Linux on PC, you can follow the steps below to build the driver as Kernel module, and use
modprobe command to load the module.
Step 1:
cd <your kernel directory>
Step 2:
sudo make -C /lib/modules/`uname -r`/build M=`pwd`/drivers/usb/serial obj-m=option.o modules
sudo make -C /lib/modules/`uname -r`/build M=`pwd`/drivers/usb/serial obj-m=usb_wwan.o modules
sudo make -C /lib/modules/`uname -r`/build M=`pwd`/drivers/usb/serial obj-m=qcserial.o modules
Step 3:
sudo cp drivers/usb/serial/option.ko /lib/modules/`uname -r`/kernel/drivers/usb/serial
sudo cp drivers/usb/serial/usb_wwan.ko /lib/modules/`uname -r`/kernel/drivers/usb/serial
sudo cp drivers/usb/serial/qcserial.ko /lib/modules/`uname -r`/kernel/drivers/usb/serial
sudo depmod
sudo reboot
重启后 在 /dev 目录下面 看见这三个设备 就算成功了!
ttyUSB0 ttyUSB1 ttyUSB2 ttyUSB3
二、GobiNet Driver 驱动添加
参考 《Quectel_WCDMA<E_Linux_USB_Driver_User_Guide_V1.7.pdf》 的3.4 章节,照着一步一操作 ,也是很简单的
When a Quectel module is attached to GobiNet driver, the driver will create a network device and a QMI channel. The network device is named as ethX (usbX if the kernel version is 2.6.39 or older), and the QMI channel is named as /dev/qcqmiX. The network device is used for data transmission, and QMI channel is used for QMI message interaction.
如果操作成功 会在 /dev 目录下面 出现 qcqmiX 这个设备
3.4.1. Modify Driver Source Code
The GobiNet driver is provided by Quectel as a form of source file. You should copy the source files to “[KERNEL]/drivers/net/usb/” ([KERNEL]/drivers/usb/net/ if the kernel version is older than 2.6.22)
将 GobiNet 的驱动文件 放在 [KERNEL]/drivers/net/usb/ 目录下面
Step 2: Set your environment variables, and import your board’s defconfig. The following is an example for Raspeberrypi board
在 内核的根目录下面 make x86_64_defconfig
Step 3: make menuconfig
Step 4: Enable CONFIG_USB_USBNET
[*] Device Drivers →
-*- Network device support →
USB Network Adapters →
{*} Multi-purpose USB Networking Framework
按下 Y 键 选中 ,然后 选择 save 后 退出
Step 5: Please add the following statements to file "[KERNEL]/drivers/net/usb/Makefile"
([KERNEL]/drivers/usb/net/Makefile if the kernel version is older than 2.6.22).
obj-y += GobiNet.o
GobiNet-objs := GobiUSBNet.o QMIDevice.o QMI.o
注意 : 是 Makefile 不是 makefile
然后就可以编译相关配置了
3.4.3. Build and Load Driver as Kernel Module for PC in Linux
If you are using Linux on PC, you can follow the steps below to build the driver as Kernel module, and use modprobe command to load the module.
Step 1: cd <your kernel directory>
Step 2:
sudo make -C /lib/modules/`uname -r`/build M=`pwd`/drivers/net/usb obj-m=GobiNet.o modules
sudo make -C /lib/modules/`uname -r`/build M=`pwd`/drivers/usb/serial obj-m=qcserial.o modules
Step 3:
sudo cp drivers/net/usb/GobiNet.ko /lib/modules/`uname -r`/kernel/drivers/net/usb
sudo cp drivers/usb/serial/qcserial.ko /lib/modules/`uname -r`/kernel/drivers/usb/serial
sudo depmod
sudo reboot
最终
重启后 在 /dev 目录下面 看见这这个通道 就算成功了!
三、Connect Manager 编译配置
参考 《Quectel_WCDMA<E_Linux_USB_Driver_User_Guide_V1.7.pdf》 的5.3 章节,照着一步一操作 ,也能做出来
Step 1: Compile Connect Manager.
把 quectel Connect Manager 文件 quectel-quectel 放到 一个你喜欢的地方
进入文件目录 执行 make 就会出现 可执行的二进制文件 quectel-CM 这就是 最终操作的文件
Step 2: Prepare busybox udhcpc tool.
quectel-CM will call busybox udhpc to obtain IP and NDS, and busybox udhpc will call script file
/usr/share/udhcpc/default.script to set IP/DNS/Routing table for Linux board. You can download this tool's
source code from https://busybox.net/. You should enable CONFIG_UDHCPC in busybox menuconfig and copy the script file [BUSYBOX]/examples/udhcp/simple.script to your Linux board (renamed as
/usr/share/udhcpc/default.script).
从 busybox 官网 https://busybox.net/. 下载 最新的 源码文件。
把 [BUSYBOX]/examples/udhcp/simple.script 文件移动到/usr/share/udhcpc/default.script 。如果没有目录就创建一个
因为 udhcpc 需要需要用到这个 脚本
然后 这个enable CONFIG_UDHCPC in busybox menuconfig 我也没有搞明白怎么操作,
这里编译quectel-CM命令,我直接放到开发板上,直接make就能出来了。不需要busybox
Step 3: Use quectel-CM to setup data call.
最后 执行 ./quectel-CM 就链接成功了
quectel-CM成功连接
最后可以看见网卡已经启动,并设置上了ip
还有一个就是 我执行 quectel-CM 的时候 ,
执行到 Lease of 10.172.27.151 obtained, lease time 7200 就卡住不走了;
研究了好久的udhcp 也没有搞明白。
但是 最后 ip地址和dns也写到了网卡里面,
最后 莫名其妙的成功了; 我也搞不懂。
四、添加开机自启动服务
在/lib/systemd/system 创建 quectel-ec20.service 文件
vim quectel-ec20.service
文件内容 :
[Unit]
Description=quectel ec20 4g net service
[Service]
Type=simple
ExecStart=/opt/quectel-CM/quectel-CM
ExecReload=/opt/quectel-CM/reload.sh
ExecStop=/opt/quectel-CM/stop.sh
PrivateTmp=true
[Install]
WantedBy=multi-user.target
Alias=quectel-ec20.service
然后 sudo systemctl daemon-reload
然后重启一下
然后就可以使用 systemctl 了
systemctl start quectel-ec20.service
开机启动:
systemctl enable quectel-ec20.service
最后一张图
最后一张图
后记
编译quectel-CM可以直接把源码放到宿主机器上编译。systemd的服务类型要用simple。如果用forking的话,会因为quectel-CM一直没有返回,导致服务被系统杀死的情况。