RK3288 Android 10 系统开发[1] - 支持 EC20 4G 模块

根据业务需求,需要升级安卓系统,从 Android6.0 升级到 Android10.0, 本节介绍如何移植 EC20 4G 模块。

主要参考 Quetecl 提供的以下文档。

  • Quectel_WCDMA&LTE_Linux_USB_Driver_User_Guide_V1.8.pdf
  • Quectel_Android_RIL_Driver_User_Guide_V1.9.pdf

kernel

内核部分,需要修改两部分,EC20模块的使能和供电, 以及 EC20 联网所需的驱动移植。

EC20 供电使能

针对供电使能问题,dts 中需要添加 EC20 模块的供电接口信息, init-gpios 对应EC20 供电接口, 4g_rst_gpio 对应重置接口,这个可以参考原理图获取。

 &pinctrl {
+       //used for init some gpio
+       // GPIO0_B5 : EC20 4G module Power EN   (1)
+       // GPIO8_A0 : EEPROM Write protect              (0)
+       // GPIO5_C3 : EC20 4G module RF Disable (1)
+       init-gpios = < &gpio0 RK_PB5 GPIO_ACTIVE_LOW>;
+       4g_rst_gpio = <&gpio5 RK_PB4 GPIO_ACTIVE_HIGH>;
+
        backlight {
                bl_en: bl-en {
                        rockchip,pins = <7 2 RK_FUNC_GPIO &pcfg_pull_none>;

除了 dts 的修改外,还需要修改 pinctrl 驱动程序。

--- a/drivers/pinctrl/pinctrl-rockchip.c
+++ b/drivers/pinctrl/pinctrl-rockchip.c
@@ -41,6 +41,7 @@
 #include <linux/mfd/syscon.h>
 #include <linux/rockchip/cpu.h>
 #include <dt-bindings/pinctrl/rockchip.h>
+#include <linux/of_gpio.h>

 #include "core.h"
 #include "pinconf.h"
@@ -433,6 +434,14 @@ struct rockchip_pmx_func {
        u8                      ngroups;
 };

+/*
+ * porting from android6.0 
+ */
+struct gpio_init_config {
+       struct gpio *gpios;
+       int nr_gpios;
+};
+
 struct rockchip_pinctrl {
        struct regmap                   *regmap_base;
        int                             reg_size;
@@ -446,6 +455,8 @@ struct rockchip_pinctrl {
        unsigned int                    ngroups;
        struct rockchip_pmx_func        *functions;
        unsigned int                    nfunctions;
+       /* porting from android6.0 */
+       struct gpio_init_config         *config;
 };

 static struct regmap_config rockchip_regmap_config = {
@@ -4331,6 +4342,45 @@ static int rk3308b_soc_data_init(struct rockchip_pinctrl *info)
        return 0;
 }

+/*
+ * porting from android6.0
+ */
+static struct gpio_init_config *
+of_get_gpio_init_config(struct device *dev, struct device_node *np)
+{
+       struct gpio_init_config *config;
+       int gpio, i;
+       enum of_gpio_flags flags;
+
+       config = devm_kzalloc(dev,
+                       sizeof(struct gpio_init_config),
+                       GFP_KERNEL);
+       if (!config)
+               return ERR_PTR(-ENOMEM);
+
+       /* Fetch GPIOs. */
+       config->nr_gpios = of_gpio_named_count(np, "init-gpios");
+
+       config->gpios = devm_kzalloc(dev,
+                               sizeof(struct gpio) * config->nr_gpios,
+                               GFP_KERNEL);
+       if (!config->gpios)
+               return ERR_PTR(-ENOMEM);
+
+       for (i = 0; i < config->nr_gpios; i++) {
+               //gpio = of_get_named_gpio(np, "gpios", i);
+               gpio = of_get_named_gpio_flags(np, "init-gpios", i, &flags);
+               if (gpio < 0)
+                       break;
+               config->gpios[i].gpio = gpio;
+               config->gpios[i].flags = flags & OF_GPIO_ACTIVE_LOW;
+
+               printk("%s:gpio[%d] = %d, value = %lu\n",__func__, i, gpio, config->gpios[i].flags);
+       }
+
+       return config;
+}
+
 static int rockchip_pinctrl_probe(struct platform_device *pdev)
 {
        struct rockchip_pinctrl *info;
@@ -4339,7 +4389,9 @@ static int rockchip_pinctrl_probe(struct platform_device *pdev)
        struct device_node *np = pdev->dev.of_node, *node;
        struct resource *res;
        void __iomem *base;
-       int ret;
+       int ret, i, gpio;
+       enum of_gpio_flags flags;
+       int gpio_active = 0;

        if (!dev->of_node) {
                dev_err(dev, "device tree node not found\n");
@@ -4419,6 +4471,41 @@ static int rockchip_pinctrl_probe(struct platform_device *pdev)
                return ret;
        }

+       /* porting from android6.0 */
+       np = dev->of_node;
+       if (of_find_property(np, "init-gpios", NULL)) {
+               info->config = of_get_gpio_init_config(&pdev->dev, np);
+               if (IS_ERR(info->config))
+               return PTR_ERR(info->config);
+
+               ret = gpio_request_array(info->config->gpios, info->config->nr_gpios);
+               if (ret) {
+                       dev_err(&pdev->dev, "Could not obtain init GPIOs: %d\n", ret);
+                       return ret;
+               }
+
+               for(i = 0; i < info->config->nr_gpios; i++) {
+                       gpio_direction_output(info->config->gpios[i].gpio, info->config->gpios[i].flags);
+               }
+       }
+       // Reset 4G module
+       gpio = of_get_named_gpio_flags(np, "4g_rst_gpio", 0, &flags);
+       if (!gpio_is_valid(gpio)) {
+               dev_err(&pdev->dev, "invalid 4g rst gpio%d\n", gpio);
+       } else {
+               ret = devm_gpio_request(&pdev->dev, gpio, "4g_rst_gpio");
+               if (ret) {
+                       dev_err(&pdev->dev, "failed to request GPIO%d for 4g_rst\n", gpio);
+                       return ret;
+               }
+               gpio_active = !(flags & OF_GPIO_ACTIVE_LOW);
+               gpio_direction_output(gpio, gpio_active);
+               mdelay(350);
+               gpio_direction_output(gpio, !gpio_active);
+               printk("\n\n!!!!!!!!!!!4G reset!!!!!!!!!!!!!!!!!!!active=%d\n\n", gpio_active);
+       }
+       /* porting end */
+
        platform_set_drvdata(pdev, info);

        return 0;

以上修改主要是为了使能 EC20模块,同时在开机过程中重置 4G 模块,以保证 4G 模块正常供电。

EC20 驱动移植

EC20 驱动相关文件如下:

drivers/net/usb/qmi_wwan.c
drivers/usb/serial/option.c
drivers/usb/serial/qcserial.c
drivers/usb/serial/usb_wwan.c

EC20 包含以下4种工作模式:

  1. USB Serial
  2. GobiNet
  3. QMI WWAN
  4. CDC ACM

我们使用的是第一种, USB Serial. 根据参考文档一一修改。

添加 pid vid

首先添加 EC20 模块的 pid, vid, 否则驱动无法识别设备。

  • drivers/usb/serial/option.c
@@ -573,6 +573,18 @@ static void option_instat_callback(struct urb *urb);


 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(0x1286, 0x4e3c) },
        { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COLT) },
        { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA) },

此外,为了防止与其它设备的id冲突,需要修改以下文件,禁用部分干扰项。

  • drivers/net/usb/qmi_wwan.c
--- a/drivers/net/usb/qmi_wwan.c
+++ b/drivers/net/usb/qmi_wwan.c
@@ -1332,7 +1332,8 @@ static const struct usb_device_id products[] = {
        {QMI_GOBI_DEVICE(0x05c6, 0x9225)},      /* Sony Gobi 2000 Modem device (N0279, VU730) */
        {QMI_GOBI_DEVICE(0x05c6, 0x9245)},      /* Samsung Gobi 2000 Modem device (VL176) */
        {QMI_GOBI_DEVICE(0x03f0, 0x251d)},      /* HP Gobi 2000 Modem device (VP412) */
-       {QMI_GOBI_DEVICE(0x05c6, 0x9215)},      /* Acer Gobi 2000 Modem device (VP413) */
+       // Disabled for prevent conflict from quectel EC20 driver
+       //{QMI_GOBI_DEVICE(0x05c6, 0x9215)},    /* Acer Gobi 2000 Modem device (VP413) */
        {QMI_FIXED_INTF(0x05c6, 0x9215, 4)},    /* Quectel EC20 Mini PCIe */
        {QMI_GOBI_DEVICE(0x05c6, 0x9265)},      /* Asus Gobi 2000 Modem device (VR305) */
        {QMI_GOBI_DEVICE(0x05c6, 0x9235)},      /* Top Global Gobi 2000 Modem device (VR306) */
  • drivers/usb/serial/qcserial.c
--- a/drivers/usb/serial/qcserial.c
+++ b/drivers/usb/serial/qcserial.c
@@ -88,7 +88,8 @@ static const struct usb_device_id id_table[] = {
        {USB_DEVICE(0x03f0, 0x241d)},   /* HP Gobi 2000 QDL device (VP412) */
        {USB_DEVICE(0x03f0, 0x251d)},   /* HP Gobi 2000 Modem device (VP412) */
        {USB_DEVICE(0x05c6, 0x9214)},   /* Acer Gobi 2000 QDL device (VP413) */
-       {USB_DEVICE(0x05c6, 0x9215)},   /* Acer Gobi 2000 Modem device (VP413) */
+       // Disabled for prevent conflict from quectel EC20 driver
+       //{USB_DEVICE(0x05c6, 0x9215)}, /* Acer Gobi 2000 Modem device (VP413) */
        {USB_DEVICE(0x05c6, 0x9264)},   /* Asus Gobi 2000 QDL device (VR305) */
        {USB_DEVICE(0x05c6, 0x9265)},   /* Asus Gobi 2000 Modem device (VR305) */
        {USB_DEVICE(0x05c6, 0x9234)},   /* Top Global Gobi 2000 QDL device (VR306) */

启用 reset_resume

启用 reset_resume 是为了防止系统进入挂起或睡眠模式后无法重新唤醒USB设备。

  • drivers/usb/serial/option.c
@@ -2051,6 +2063,9 @@ 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
 };

启用 autosuspend remote wakeup

为了支持USB网络的自动挂起与远程唤醒,可以添加以下patch,当然这不是必须的。

@@ -2086,6 +2101,33 @@ static int option_probe(struct usb_serial *serial,
        if (device_flags & NUMEP2 && iface_desc->bNumEndpoints != 2)
                return -ENODEV;

+#if 1 // Added by Quectel
+       //For USB Auto Suspend and Remote Wakeup
+       if (serial->dev->descriptor.idVendor == cpu_to_le16(0x05C6) && 
+               serial->dev->descriptor.idProduct == cpu_to_le16(0x9090)) {
+               pm_runtime_set_autosuspend_delay(&serial->dev->dev, 3000);
+               usb_enable_autosuspend(serial->dev);
+               device_init_wakeup(&serial->dev->dev, 1); //usb remote wakeup
+       }
+       if (serial->dev->descriptor.idVendor == cpu_to_le16(0x05C6) &&
+               serial->dev->descriptor.idProduct == cpu_to_le16(0x9003)) {
+               pm_runtime_set_autosuspend_delay(&serial->dev->dev, 3000);
+               usb_enable_autosuspend(serial->dev);
+               device_init_wakeup(&serial->dev->dev, 1); //usb remote wakeup
+       }
+       if (serial->dev->descriptor.idVendor == cpu_to_le16(0x05C6) &&
+               serial->dev->descriptor.idProduct == cpu_to_le16(0x9215)) {
+               pm_runtime_set_autosuspend_delay(&serial->dev->dev, 3000);
+               usb_enable_autosuspend(serial->dev);
+               device_init_wakeup(&serial->dev->dev, 1); //usb remote wakeup
+       }
+       if (serial->dev->descriptor.idVendor == cpu_to_le16(0x2C7C)) {
+               pm_runtime_set_autosuspend_delay(&serial->dev->dev, 3000);
+               usb_enable_autosuspend(serial->dev);
+               device_init_wakeup(&serial->dev->dev, 1); //usb remote wakeup
+       }
+#endif
+

添加零包机制

  • drivers/usb/serial/usb_wwan.c
--- a/drivers/usb/serial/usb_wwan.c
+++ b/drivers/usb/serial/usb_wwan.c
@@ -509,6 +509,17 @@ static struct urb *usb_wwan_setup_urb(struct usb_serial_port *port,
                if ((desc->idVendor == cpu_to_le16(0x1286) &&
                     desc->idProduct == cpu_to_le16(0x4e3c)))
                        urb->transfer_flags |= URB_ZERO_PACKET;
+#if 1
+               // Added by Quectel for zero packet
+               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;
 }

支持usb网络

这一项主要是针对 EC20 的第5个usb interface,EC20 默认会生成 ttyUSB0~ttyUSB3 4个接口,还有一个 interface,可以用于支持 Gobinet 或者 qmi wwan 接口,用以生成 ethx 或者 wwanx 接口。以下patch就是为了防止 USB serial 驱动将该接口用掉。

--- a/drivers/usb/serial/option.c
+++ b/drivers/usb/serial/option.c
@@ -2082,6 +2082,29 @@ static int option_probe(struct usb_serial *serial,
                                &serial->interface->cur_altsetting->desc;
        unsigned long device_flags = id->driver_info;

+       #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;
+       if (serial->dev->descriptor.idVendor == cpu_to_le16(0x2C7C)) {
+               __u16 idProduct = le16_to_cpu(serial->dev->descriptor.idProduct);
+               //Quectel EC200&UC200's interface 0 can be used as USB Network device (ecm, rndis)
+               if (serial->interface->cur_altsetting->desc.bInterfaceClass != 0xFF)
+                       return -ENODEV;
+               //Quectel EC25&EC21&EG91&EG95&EG06&EP06&EM06&BG96&AG35&EG12&EG18's interface 4 can be used as USB network device (qmi,ecm,mbim)
+               if ((idProduct != 0x6026 && idProduct != 0x6126) &&
+                       serial->interface->cur_altsetting->desc.bInterfaceNumber >= 4)
+                       return -ENODEV;
+       }
+       #endif
+
        /* Never bind to the CD-Rom emulation interface */
        if (iface_desc->bInterfaceClass == USB_CLASS_MASS_STORAGE)
                return -ENODEV;

注意:该patch针对使用 USB Serial 模式的情况而言并不是必须的,加不加都无所谓。

kernel config

当驱动和供电都没问题后,还需要确保以下功能配置,大部分已经默认支持了

  • 启用 ppp 相关配置
  • 启用 USB serial 相关配置

需要注意的是,由于 android10 kernel版本 (v4.19.194) 比较新,所以 qmi wwan 驱动已经集成了 EC20 的 pid,vid,所以系统检测到设备会自动加载 qmi_wwan 驱动并自动生成 wwan0 接口,导致无法使用 ppp 拨号上网,为了解决这个问题,需要将 qmi_wwan 驱动禁用。

--- a/arch/arm/configs/rockchip_defconfig
+++ b/arch/arm/configs/rockchip_defconfig
@@ -327,7 +327,7 @@ CONFIG_USB_EPSON2888=y
 CONFIG_USB_KC2190=y
 CONFIG_USB_NET_CX82310_ETH=y
 CONFIG_USB_NET_KALMIA=y
-CONFIG_USB_NET_QMI_WWAN=y
+# CONFIG_USB_NET_QMI_WWAN is not set
 CONFIG_USB_HSO=y
 CONFIG_USB_NET_INT51X1=y
 CONFIG_USB_IPHETH=y

至此,kernel 部分的修改就完成了。

android

下面来看看 android 10kernel 外的其它修改。

device/rockchip/rk3288/rk3288_Android10/BoardConfig.mk
device/rockchip/rk3288/rk3288_Android10/EC20/
device/rockchip/rk3288/rk3288_Android10/rk3288_Android10.mk
device/rockchip/rk3288/device.mk
device/rockchip/rk3288/manifest_ab.xml
device/rockchip/common/device.mk
device/rockchip/common/init.rk30board.rc
hardware/ril/reference-ril/Android.mk
hardware/ril/rild/rild.rc
external/ppp/chat/Android.mk

vendor

  • vendor/rockchip/common/phone/phone.mk

这个目录的文件可改可不改,里面主要定义了 dongle 相关的配置,如果有用到就改。

device

BoardConfig.mk

  • device/rockchip/rk3288/rk3288_Android10/BoardConfig.mk

BoardConfig.mk 中添加 BOARD_HAS_RK_4G_MODEM 配置。

--- a/rk3288_Android10/BoardConfig.mk
+++ b/rk3288_Android10/BoardConfig.mk
@@ -7,6 +7,9 @@ BOARD_GYROSCOPE_SENSOR_SUPPORT := true
 BUILD_WITH_GOOGLE_GMS_EXPRESS := false
 CAMERA_SUPPORT_AUTOFOCUS:= false

+# enable 4g for ec20
+BOARD_HAS_RK_4G_MODEM := true
+
 PRODUCT_KERNEL_CONFIG := rockchip_defconfig android-10.config

 # AB image definition

BOARD_HAS_RK_4G_MODEM 相关的配置主要有两处。分别配置了需要安装的软件和依赖的 manifest.xml.

# device/rockchip/common/device.mk
ifeq ($(strip $(BOARD_HAS_RK_4G_MODEM)),true)
PRODUCT_PACKAGES += \
    CarrierDefaultApp \
    CarrierConfig \
    rild \
    librk-ril \
    dhcpcd

# device/rockchip/common/BoardConfig.mk
ifeq ($(strip $(BOARD_HAS_RK_4G_MODEM)),true)
DEVICE_MANIFEST_FILE := device/rockchip/common/4g_modem/manifest.xml
endif

这个 manifest.xml 和后面提到的 manifest_ab.xml 内容差不多,如果使用 4g_modem 目录下,那么下面关于 manifest_ab.xml 的修改就不用管了。

rk3288/device.mk

  • device/rockchip/rk3288/device.mk

device.mk 中更新 rild 参数。

--- a/device.mk
+++ b/device.mk
@@ -128,8 +128,8 @@ PRODUCT_PROPERTY_OVERRIDES += \
                 ro.ril.ecclist=112,911 \
                 ro.opengles.version=196610 \
                 wifi.interface=wlan0 \
-                rild.libpath=/system/lib/libril-rk29-dataonly.so \
-                rild.libargs=-d /dev/ttyACM0 \
+                rild.libpath=/vendor/lib/libreference-ril.so \
+                rild.libargs=-d /dev/ttyUSB2 \
                 persist.tegra.nvmmlite = 1 \
                 ro.audio.monitorOrientation=true \
                 debug.nfc.fw_download=false \

common/device.mk

  • device/rockchip/common/device.mk

修改 BOARD_HAS_RK_4G_MODEM 相关的配置,禁用默认的 librk-ril, 并修正 rild 相关参数。

--- a/device.mk
+++ b/device.mk
@@ -202,7 +202,6 @@ PRODUCT_PACKAGES += \
     CarrierDefaultApp \
     CarrierConfig \
     rild \
-    librk-ril \
     dhcpcd

 PRODUCT_PROPERTY_OVERRIDES += \
@@ -218,11 +217,12 @@ PRODUCT_COPY_FILES += \
                $(LOCAL_PATH)/4g_modem/lib64/librk-ril.so:$(TARGET_COPY_OUT_VENDOR)/lib64/librk-ril.so
 else
 PRODUCT_PROPERTY_OVERRIDES += \
-               vendor.rild.libpath=/vendor/lib/librk-ril.so
+               vendor.rild.libpath=/vendor/lib/libreference-ril.so \
+               vendor.rild.libargs=-d /dev/ttyUSB2

 PRODUCT_COPY_FILES += \
-               $(LOCAL_PATH)/4g_modem/bin32/dhcpcd:$(TARGET_COPY_OUT_VENDOR)/bin/dhcpcd \
-               $(LOCAL_PATH)/4g_modem/lib32/librk-ril.so:$(TARGET_COPY_OUT_VENDOR)/lib/librk-ril.so
+               $(LOCAL_PATH)/4g_modem/bin32/dhcpcd:$(TARGET_COPY_OUT_VENDOR)/bin/dhcpcd
+               #$(LOCAL_PATH)/4g_modem/lib32/librk-ril.so:$(TARGET_COPY_OUT_VENDOR)/lib/librk-ril.so

 endif
 endif

注意:为什么前面定义了 rild.libpath, rild.libargs, 这里还要定义 vendor.rild.libpath, vendor.rild.libargs, 这是因为 rild 有两套配置,根据配置 PRODUCT_COMPATIBLE_PROPERTY 使用这两套配置之一。

init.rk30board.rc

  • device/rockchip/common/init.rk30board.rc

init.rk30board.rc 文件中启动 ril-daemon, 而 ril-daemon 定义位于后续提及的 rild.rc.

--- a/init.rk30board.rc
+++ b/init.rk30board.rc
@@ -259,9 +259,9 @@ on property:persist.internet_adb_enable=0
     restart adbd

 # for telephony function
-on property:ro.boot.noril=true
-    setprop ro.radio.noril true
-    stop ril-daemon
+on property:ro.boot.noril=false
+    setprop ro.radio.noril false
+    start ril-daemon

manifest_ab.xml

  • device/rockchip/rk3288/manifest_ab.xml

manifest_ab.xml 或者 manifest.xml 中添加两条 hidl 记录,这是 android 8 及高版本所需的。当然,不改文件,直接使用 4g_modem 目录的也可以。

--- a/manifest_ab.xml
+++ b/manifest_ab.xml
@@ -183,5 +183,23 @@
             <instance>default</instance>
         </interface>
     </hal>
+    <hal format="hidl">
+        <name>android.hardware.radio.deprecated</name>
+        <transport>hwbinder</transport>
+        <version>1.0</version>
+        <interface>
+            <name>IOemHook</name>
+            <instance>slot1</instance>
+        </interface>
+    </hal>
+    <hal format="hidl">
+        <name>android.hardware.radio</name>
+        <transport>hwbinder</transport>
+        <version>1.0</version>
+        <interface>
+            <name>IRadio</name>
+            <instance>slot1</instance>
+        </interface>
+    </hal>
 </manifest>

EC20 files

  • device/rockchip/rk3288/rk3288_Android/EC20/

quectel 提供的文件拷贝至以下目录。

$ ls device/rockchip/rk3288/rk3288_Android10/EC20 
chat  ip-down  ip-up  libreference-ril.so
  • device/rockchip/rk3288/rk3288_Android10/rk3288_Android10.mk

rk3288_Android10.mk 文件中添加拷贝项 PRODUCT_COPY_FILES , 将前面的4个文件拷贝至指定目录。

--- a/rk3288_Android10/rk3288_Android10.mk
+++ b/rk3288_Android10/rk3288_Android10.mk
@@ -43,6 +43,10 @@ PRODUCT_PACKAGES += \
 PRODUCT_COPY_FILES += vendor/rockchip/common/phone/etc/apns-full-conf.xml:system/etc/apns-conf.xml
 PRODUCT_COPY_FILES += vendor/rockchip/common/phone/etc/spn-conf.xml:system/etc/spn-conf.xml
 PRODUCT_COPY_FILES += ${TARGET_DEVICE_DIR}/user_service.sh:system/bin/user_service.sh
+PRODUCT_COPY_FILES += ${TARGET_DEVICE_DIR}/EC20/chat:system/bin/chat
+PRODUCT_COPY_FILES += ${TARGET_DEVICE_DIR}/EC20/ip-down:system/etc/ppp/ip-down
+PRODUCT_COPY_FILES += ${TARGET_DEVICE_DIR}/EC20/ip-up:system/etc/ppp/ip-up
+PRODUCT_COPY_FILES += ${TARGET_DEVICE_DIR}/EC20/libreference-ril.so:vendor/lib/libreference-ril.so
 PRODUCT_PROPERTY_OVERRIDES += \
     ro.product.version = 1.0.0 \
     ro.product.ota.host = www.rockchip.com:2300 \

sepolicy

添加 sepolicy 权限,这里只是示例,具体情况需要根据日志进行添加。

  • device/rockchip/common/sepolicy/vendor/file_contexts
--- a/sepolicy/vendor/file_contexts
+++ b/sepolicy/vendor/file_contexts
@@ -1,5 +1,6 @@
 /dev/ttyFIQ[0-9]*    u:object_r:serial_device:s0
-/dev/ttyUSB[0-9]*    u:object_r:tty_device:s0
+/dev/ttyUSB[0-3]     u:object_r:radio_device:s0
+/dev/ttyUSB[4-9]     u:object_r:tty_device:s0
 /dev/mali[0-9]       u:object_r:gpu_device:s0
 /dev/mali            u:object_r:gpu_device:s0
 /dev/ddr_freq        u:object_r:ddr_device:s0
@@ -193,3 +194,7 @@

 #flash_img
 /system/bin/flash_img.sh u:object_r:install_recovery_exec:s0
+
+#rild
+/vendor/bin/hw/rild         u:object_r:rild_exec:s0
+/dev/socket/rildOemHook     u:object_r:rild_socket:s0

hardware

ril

  • hardware/ril/reference-ril/

由于使用 quectel 提供的 libreference-ril.so, 所以需要禁用 SDK 自带的 reference-ril, 将对应目录下的 Android.mk 重命名即可。

cd hardware/ril/reference-ril
git mv Android.mk Android.mk_bak

rild

  • hardware/ril/rild/rild.rc

rk3288 android10ril-daemon 定义于 rild.rc 文件中,为了使用 quectel 提供的 libreference-ril.so ,需要修改该文件。

--- a/rild/rild.rc
+++ b/rild/rild.rc
@@ -1,5 +1,5 @@
-service vendor.ril-daemon /vendor/bin/hw/rild
+service ril-daemon /vendor/bin/hw/rild -l /vendor/lib/libreference-ril.so
     class main                                                                                                           
     user radio                                                                                                           
-    group radio cache inet misc audio log readproc wakelock
+    group radio cache inet misc audio log readproc wakelock sdcard_rw
     capabilities BLOCK_SUSPEND NET_ADMIN NET_RAW

external

  • external/ppp/chat

由于使用 quectel 提供的 chat, 所以需要禁用SDK自带的 chat , 简单将自带 chat 目录的 Android.mk 重命名即可,这样编译时就检索不到了。

cd external/ppp/chat
git mv Android.mk Android.mk_bak

查看信息

系统配置好并烧录后,查看相关信息。

console:/ # ifconfig
ppp0      Link encap:Point-to-Point Protocol
          inet addr:10.167.182.79  P-t-P:10.64.64.64  Mask:255.255.255.255
          UP POINTOPOINT RUNNING NOARP MULTICAST  MTU:1500  Metric:1
          RX packets:20 errors:0 dropped:0 overruns:0 frame:0
          TX packets:82 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:3
          RX bytes:1989 TX bytes:5010
console:/ # ping baidu.com
PING baidu.com (220.181.38.148) 56(84) bytes of data.
64 bytes from 220.181.38.148: icmp_seq=1 ttl=45 time=111 ms
64 bytes from 220.181.38.148: icmp_seq=2 ttl=45 time=114 ms
64 bytes from 220.181.38.148: icmp_seq=3 ttl=45 time=117 ms
64 bytes from 220.181.38.148: icmp_seq=4 ttl=45 time=115 ms
console:/ # ls /dev/ttyUSB*
/dev/ttyUSB0 /dev/ttyUSB1 /dev/ttyUSB2 /dev/ttyUSB3
console:/ # dmesg |grep GSM
[    1.363745] usbserial: USB Serial support registered for GSM modem (1-port)
[   10.353990] option 3-1.2:1.0: GSM modem (1-port) converter detected
[   10.354280] usb 3-1.2: GSM modem (1-port) converter now attached to ttyUSB0
[   10.360191] option 3-1.2:1.1: GSM modem (1-port) converter detected
[   10.360825] usb 3-1.2: GSM modem (1-port) converter now attached to ttyUSB1
[   10.362188] option 3-1.2:1.2: GSM modem (1-port) converter detected
[   10.362542] usb 3-1.2: GSM modem (1-port) converter now attached to ttyUSB2
[   10.363543] option 3-1.2:1.3: GSM modem (1-port) converter detected
[   10.364808] usb 3-1.2: GSM modem (1-port) converter now attached to ttyUSB3
console:/ # microcom -s 115200 /dev/ttyUSB2
+CSQ: 23,99

OK

Quectel
EC20F
Revision: EC20CNHDLGR09A06M1G

注意事项

  1. 如果使用 USB Serial 模式,记得禁用 qmi_wwan 驱动,否则会自动生成 wwan0, 且影响 pppd 拨号上网。
  2. 记得查看 rild 中是否有 rild.rc ,如果有且定义了 ril-daemon, 则无需在 init.*.rc 中定义了
  3. rild.libpath , rild.libargs 需要与 rild 中使用的匹配,如果不确定,vendor.rild.libpath, vendor.rild.libargs 也加上。
  4. android10 中,需要将 libreference-ril.so 放置在 vendor 目录,而非 system 目录

参考