美文网首页安卓系统开发
EC20 驱动 移植 Gobinet 拨号

EC20 驱动 移植 Gobinet 拨号

作者: Wood木木 | 来源:发表于2023-04-25 16:15 被阅读0次

    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一直没有返回,导致服务被系统杀死的情况。

    相关文章

      网友评论

        本文标题:EC20 驱动 移植 Gobinet 拨号

        本文链接:https://www.haomeiwen.com/subject/aofmjdtx.html