移远EC20 4G模块Linux驱动移植和测试

#PS:要转载请注明出处,本人版权所有

#PS:这个只是 《 我自己 》理解,如果和你的

#原则相冲突,请谅解,勿喷

EC20简介

EC20是一个全网通的4G模块,并提供了详细的驱动移植资料(源码+文档),我也仅仅是照着文档,一点点的改,并建立起来一个可用的环境。

EC20驱动移植准备

1 首先你会从厂家拿到一个资料文件,并解压(类似Quectel_GobiNetSR01A02V16.zip)

2 你会找到一个用户手册的PDF打开(类似Quectel_WCDMA&LTE_Linux_USB_Driver_User_Guide_V1.6.pdf)

3 这里还有一个Readme.txt告诉你需要阅读上文pdf的哪些内容。可能如下:

About GobiNet driver, please refer to the chapter 3.2、3.4、5.4、6
About ConnectManager,please refer to the chapter 5.4

4 按照pdf指示如下。

EC20 Linux驱动移植

1 增加PID&VID(对着两个不了解的,建议去找找资料来看看,这个的意思可以简单理解为这个设备的唯一标识)

[KERNEL]/drivers/usb/serial/option.c

static const struct usb_device_id option_ids[] = {
    #if 1 //Added by Sky  
    { USB_DEVICE(0x05C6, 0x9090) }, /* Quectel UC15 */  
    { USB_DEVICE(0x05C6, 0x9003) }, /* Quectel UC20 */  
    { USB_DEVICE(0x05C6, 0x9215) }, /* Quectel EC20 */  
    { USB_DEVICE(0x2C7C, 0x0125) }, /* Quectel EC25/EC20 R2.0 */  
    { USB_DEVICE(0x2C7C, 0x0121) }, /* Quectel EC21 */ 
    #endif 

这里其实只需要{ USB_DEVICE(0x05C6, 0x9215) }, /* Quectel EC20 */ 这一项,其他是无关紧要的,可以不放进去。option_ids[]就是一usb serial的设备pid,vid表。

2 注释掉冲突的vid以及pid设备(我猜存在相同的vid和pid是历史的原因)

[KERNEL]/drivers/usb/serial/qcserial.c

    //Comment by Sky,
    //{USB_DEVICE(0x05c6, 0x9215)}, /* Acer Gobi 2000 Modem device (VP413) */

[KERNEL]/drivers/net/usb/qmi_wwan.c

    //comment by Sky
    //{QMI_GOBI_DEVICE(0x05c6, 0x9215)},    /* Acer Gobi 2000 Modem device (VP413) */

注意这里貌似只有EC20的冲突了。

3 添加零包处理(这个和usb 协议中的批量传输有关)

For Linux Kernel Version newer than 2.6.34:

File: [KERNEL]/drivers/usb/serial/usb_wwan.c

    usb_fill_bulk_urb(urb, serial->dev,      usb_sndbulkpipe(serial->dev, endpoint) | dir,      buf, len, callback, ctx);
    #if 1 //Added by Sky 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 

注意,pdf上还有For Linux Kernel Version older than 2.6.35的内容,请自行根据内核版本查看。

4 增加休眠后唤醒接口

For Linux Kernel Version newer than 3.4:

File: [KERNEL]/drivers/usb/serial/option.c

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,
    .set_termios       = usb_wwan_set_termios,
    .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 Sky  
    .reset_resume   = usb_wwan_resume, 
    #endif 
#endif
};

5 如果要使用 GobiNet or QMI WWAN,需要阻止第四个接口注册为串口。

For Linux Kernel Version newer than 2.6.30:

File: [KERNEL]/drivers/usb/serial/option.c

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;
    struct usb_device_descriptor *dev_desc = &serial->dev->descriptor;

    /* Never bind to the CD-Rom emulation interface */
    if (iface_desc->bInterfaceClass == 0x08)
        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 (is_blacklisted(
        iface_desc->bInterfaceNumber,
        OPTION_BLACKLIST_RESERVED_IF,
        (const struct option_blacklist_info *) id->driver_info))
        return -ENODEV;
    /*
     * Don't bind network interface on Samsung GT-B3730, it is handled by
     * a separate module.
     */
    if (dev_desc->idVendor == cpu_to_le16(SAMSUNG_VENDOR_ID) &&
        dev_desc->idProduct == cpu_to_le16(SAMSUNG_PRODUCT_GT_B3730) &&
        iface_desc->bInterfaceClass != USB_CLASS_CDC_DATA)
        return -ENODEV;


        #if 1  //Added by Sky 
        //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 EC21&EC25&EC20 R2.0'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;
}

6 修改内核配置,并编译内核,刷入新内核

添加USB 串口 GSM 和 CDMA 驱动选项
这里写图片描述
启用USB网络支持
这里写图片描述
添加驱动代码

//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 

7 quectel-CM 测试

//交叉编译quectel-CM 
/*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). */
quectel-CM –s ctnet & 
[01-01_00:26:45:355] Quectel_ConnectManager_SR01A01V10 
[01-01_00:26:45:356] ./quectel-CM profile = ctnet///, pincode =  
[01-01_00:26:45:357] Find qmichannel = /dev/qcqmi2 
[01-01_00:26:45:358] Find usbnet_adapter = eth2 
[01-01_00:26:45:368] Get clientWDS = 7 
[01-01_00:26:45:400] Get clientDMS = 8 
[01-01_00:26:45:432] Get clientNAS = 9 
[01-01_00:26:45:464] Get clientWDA = 10 
[01-01_00:26:45:496] requestBaseBandVersion EC20CQAR02A03E2G_BETA0914  1  [Sep 14 2015 13:51:27] 
[01-01_00:26:45:560] requestGetSIMStatus SIMStatus: SIM_READY 
[01-01_00:26:45:624] requestGetProfile ctnet///0 
[01-01_00:26:45:656] requestRegistrationState MCC: 460, MNC: 11, PS: Attached, DataCap: LTE 
[01-01_00:26:45:688] requestQueryDataCall ConnectionStatus: DISCONNECTED 
[01-01_00:26:45:720] requestRegistrationState MCC: 460, MNC: 11, PS: Attached, DataCap: LTE 
[01-01_00:26:45:752] requestQueryDataCall ConnectionStatus: DISCONNECTED 
[01-01_00:26:45:816] requestSetupDataCall WdsConnectionIPv4Handle: 0x43cc4478 
[01-01_00:26:45:912] requestQueryDataCall ConnectionStatus: CONNECTED 
[01-01_00:26:45:937] udhcpc (v1.20.2) started 
[01-01_00:26:45:956] Sending discover... 
[01-01_00:26:45:960] Sending select for 10.172.27.151... 
[01-01_00:26:45:964] Lease of 10.172.27.151 obtained, lease time 7200 
[01-01_00:26:45:984] deleting routers 
route: SIOCDELRT: No such process 
[01-01_00:26:46:003] adding dns 61.132.163.68 
[01-01_00:26:46:003] adding dns 202.102.213.68 

注意,这里需要UDHCPC ,检测你的busybox是否有这个东西,如果不存在,你需要重新移植busybox,启用CONFIG_UDHCPC选项。还需要配置一个配置文件,注意检查。

特别提示,其中很多关于内核源码修改,以及内核配置修改,不同的版本有不同的写法,文档里面都有详细说明,请使用时,特别注意。
#PS:请尊重原创,不喜勿喷

#PS:要转载请注明出处,本人版权所有.

有问题请留言,看到后我会第一时间回复

猜你喜欢

转载自blog.csdn.net/u011728480/article/details/78588827