OpenHarmony3.1适配移远EC20模组4G上网功能
OpenHarmony3.1适配移远EC20模组4G上网功能
一、概述
通过阅读本篇文档,您将学习到如何适配移远EC20模组到OpenHarmony3.1(以下简称OHOS),并添加4G上网功能。
本篇文档,使用硬件为大禹RK3568开发板。
开发板资料:https://gitee.com/openharmony/device_board_hihope/blob/master/rk3568/README_zh.md
软件方案分为PPP和QMI两种,请读者自行选择。
二、PPP方案
2.1.内核添加对应配置
CONFIG_PPP=yCONFIG_PPP_ASYNC=yCONFIG_PPP_SYNC_TTY=yCONFIG_PPP_DEFLATE=y
2.2.修改内核驱动源码
2.2.1修改drivers/usb/serial/option.c
diff --git a/v5.10.11/drivers/usb/serial/option.c b/v5.10.11/drivers/usb/serial/option.cindex 3fe9591..2a3e20e 100644--- a/v5.10.11/drivers/usb/serial/option.c+++ b/v5.10.11/drivers/usb/serial/option.c@@ -580,6 +580,32 @@ 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(0x05C6, 0x9215) }, /* Quectel EC20(MDM9215) */+{ USB_DEVICE(0x2C7C, 0x0125) }, /* Quectel EC20(MDM9x07)/EC25/EG25 */+{ USB_DEVICE(0x2C7C, 0x0121) }, /* Quectel EC21 */+{ USB_DEVICE(0x2C7C, 0x0191) }, /* Quectel EG91 */+{ USB_DEVICE(0x2C7C, 0x0195) }, /* Quectel EG95 */+{ USB_DEVICE(0x2C7C, 0x0306) }, /* Quectel EG06/EP06/EM06 */+{ USB_DEVICE(0x2C7C, 0x030B) }, /* Quectel EG065K/EG060K */+{ USB_DEVICE(0x2C7C, 0x0514) }, /* Quectel BL EG060K RNDIS Only */+{ USB_DEVICE(0x2C7C, 0x0512) }, /* Quectel EG12/EP12/EM12/EG16/EG18 */+{ USB_DEVICE(0x2C7C, 0x0296) }, /* Quectel BG96 */+{ USB_DEVICE(0x2C7C, 0x0700) }, /* Quectel BG95/BG77/BG600L-M3/BC69 */+{ USB_DEVICE(0x2C7C, 0x0435) }, /* Quectel AG35 */+{ USB_DEVICE(0x2C7C, 0x0415) }, /* Quectel AG15 */+{ USB_DEVICE(0x2C7C, 0x0452) }, /* Quectel AG520 */+{ USB_DEVICE(0x2C7C, 0x0455) }, /* Quectel AG550 */+{ USB_DEVICE(0x2C7C, 0x0620) }, /* Quectel EG20 */+{ USB_DEVICE(0x2C7C, 0x0800) }, /* Quectel RG500/RM500/RG510/RM510 */+{ USB_DEVICE(0x2C7C, 0x0801) }, /* Quectel RG520/RM520/SG520 */+{ USB_DEVICE(0x2C7C, 0x6026) }, /* Quectel EC200 */+{ USB_DEVICE(0x2C7C, 0x6120) }, /* Quectel UC200 */+{ USB_DEVICE(0x2C7C, 0x6000) }, /* Quectel EC200/UC200 */+{ .match_flags = USB_DEVICE_ID_MATCH_VENDOR, .idVendor = 0x2C7C }, /* Match All Quectel Modules */+#endif { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COLT) }, { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA) }, { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA_LIGHT) },@@ -2071,7 +2097,26 @@ MODULE_DEVICE_TABLE(usb, option_ids); * recognizes separately, thus num_port=1. */ +#if 1 //Added by Quectel+static void cfmakeraw(struct ktermios *t)+{+t->c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON);+t->c_oflag &= ~OPOST;+t->c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);+t->c_cflag &= ~(CSIZE|PARENB);+t->c_cflag |= CS8;+t->c_cc[VMIN] = 1;+t->c_cc[VTIME] = 0;+}++static void option_init_termios(struct tty_struct *tty)+{+cfmakeraw(&tty->termios);+}+#endif+ static struct usb_serial_driver option_1port_device = {+.init_termios = option_init_termios, .driver = { .owner =THIS_MODULE, .name ="option1",@@ -2098,6 +2143,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 }; @@ -2122,6 +2170,35 @@ 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(MDM9215)'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);+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+ /* Never bind to the CD-Rom emulation interface*/ if (iface_desc->bInterfaceClass == USB_CLASS_MASS_STORAGE) return -ENODEV;@@ -2235,7 +2312,7 @@ static void option_instat_callback(struct urb *urb) dev_dbg(dev, "%s: error %d\n", __func__, status); /* Resubmit urb so we continue receiving IRQ data */-if (status != -ESHUTDOWN && status != -ENOENT) {+if (status != -ESHUTDOWN && status != -ENOENT && status != -EPROTO) { usb_mark_last_busy(port->serial->dev); err = usb_submit_urb(urb, GFP_ATOMIC); if (err)
2.2.2修改drivers/usb/serial/qcserial.c
diff --git a/v5.10.11/drivers/usb/serial/qcserial.c b/v5.10.11/drivers/usb/serial/qcserial.cindex 83da823..469b202 100644--- a/v5.10.11/drivers/usb/serial/qcserial.c+++ b/v5.10.11/drivers/usb/serial/qcserial.c@@ -63,7 +63,7 @@ static const struct usb_device_id id_table[] = { {DEVICE_G1K(0x05c6, 0x9202)},/* Generic Gobi Modem device */ {DEVICE_G1K(0x05c6, 0x9203)},/* Generic Gobi Modem device */ {DEVICE_G1K(0x05c6, 0x9222)},/* Generic Gobi Modem device */-{DEVICE_G1K(0x05c6, 0x9008)},/* Generic Gobi QDL device */+//{DEVICE_G1K(0x05c6, 0x9008)},/* Generic Gobi QDL device */ {DEVICE_G1K(0x05c6, 0x9009)},/* Generic Gobi Modem device */ {DEVICE_G1K(0x05c6, 0x9201)},/* Generic Gobi QDL device */ {DEVICE_G1K(0x05c6, 0x9221)},/* Generic Gobi QDL device */
2.2.3修改drivers/usb/serial/usb_wwan.c
diff --git a/v5.10.11/drivers/usb/serial/usb_wwan.c b/v5.10.11/drivers/usb/serial/usb_wwan.cindex 4b98458..236102b 100644--- a/v5.10.11/drivers/usb/serial/usb_wwan.c+++ b/v5.10.11/drivers/usb/serial/usb_wwan.c@@ -272,7 +272,7 @@ static void usb_wwan_indat_callback(struct urb *urb) __func__, status, endpoint); /* don't resubmit on fatal errors */-if (status == -ESHUTDOWN || status == -ENOENT)+if (status == -ESHUTDOWN || status == -ENOENT || status == -EPROTO) return; } else { if (urb->actual_length) {@@ -476,6 +476,19 @@ static struct urb *usb_wwan_setup_urb(struct usb_serial_port *port, usb_sndbulkpipe(serial->dev, endpoint) | dir, buf, len, callback, ctx); +#if 1 //Added by Quectel for Zero Packet+if (dir == USB_DIR_OUT) {+if (serial->dev->descriptor.idVendor == cpu_to_le16(0x05C6) && serial->dev->descriptor.idProduct == cpu_to_le16(0x9090))+urb->transfer_flags |= URB_ZERO_PACKET;+if (serial->dev->descriptor.idVendor == cpu_to_le16(0x05C6) && serial->dev->descriptor.idProduct == cpu_to_le16(0x9003))+urb->transfer_flags |= URB_ZERO_PACKET;+if (serial->dev->descriptor.idVendor == cpu_to_le16(0x05C6) && serial->dev->descriptor.idProduct == cpu_to_le16(0x9215))+urb->transfer_flags |= URB_ZERO_PACKET;+if (serial->dev->descriptor.idVendor == cpu_to_le16(0x2C7C))+urb->transfer_flags |= URB_ZERO_PACKET;+}+#endif+ if (intfdata->use_zlp && dir == USB_DIR_OUT) urb->transfer_flags |= URB_ZERO_PACKET;
2.3添加ppp拨号软件
2.3.1pcap移植
主页:https://www.tcpdump.org/index.html
https://www.tcpdump.org/release/libpcap-1.10.1.tar.gz
解压到目录third_party/libpcap
原生编译:
./configure --host=arm-linux-gnueabi#修改Makefile#CC = arm-linux-gnueabi-gcc#AR = arm-linux-gnueabi-armake
import("//build/ohos.gni")ohos_static_library("libpcap") { sources = [ "pcap-linux.c", "fad-getad.c", "pcap-usb-linux.c", "pcap-netfilter-linux.c", "pcap.c", "gencode.c", "optimize.c", "nametoaddr.c", "etherent.c", "fmtutils.c", "savefile.c", "sf-pcap.c", "sf-pcapng.c", "pcap-common.c", "bpf_image.c", "bpf_filter.c", "bpf_dump.c", "scanner.c", "grammar.c", "missing/strlcat.c", "missing/strlcpy.c" ] include_dirs = [ "//third_party/libpcap" ] cflags = [ "-O2", "-g", "-fvisibility=hidden", "-fpic", "-DBUILDING_PCAP", "-Dpcap_EXPORTS", "-DHAVE_CONFIG_H", "-Wno-int-conversion", ] part_name = "libpcap" subsystem_name = "ppp"}
修改ftmacros.h,宏_GNU_SOURCE重复定义:
#ifndef _GNU_SOURCE #define _GNU_SOURCE #endif
修改config.h文件,屏蔽以下两行:
/* define if we have the Linux getnetbyname_r() */// #define HAVE_LINUX_GETNETBYNAME_R 1/* define if we have the Linux getprotobyname_r() */// #define HAVE_LINUX_GETPROTOBYNAME_R 1
2.3.2.ppp移植
主页:https://download.samba.org/pub/ppp/
下载地址:https://download.samba.org/pub/ppp/ppp-2.4.9.tar.gz
代码解压到目录third_party/ppp
原生编译:
./configure --cross_compile=arm-linux-gnueabi-gmake
新建文件bundle.json,内容如下:
{ "name": "@ohos/ppp", "description": "the Point-to-Point Protocol (PPP) to provide Internet connections over serial lines", "version": "3.1", "license": "Public Domain", "publishAs": "code-segment", "segment": { "destPath": "third_party/ppp" }, "dirs": {}, "scripts": {}, "licensePath": "", "readmePath": { "en": "" }, "component": { "name": "ppp", "subsystem": "ppp", "syscap": [], "features": [], "adapted_system_type": [], "rom": "", "ram": "", "deps": { "components": [], "third_party": [] }, "build": { "sub_component": [ "//third_party/ppp:ppp_group" ], "inner_kits": [], "test": [] } }}
新建文件ohos.build,内容如下:
{ "subsystem": "ppp", "parts": { "ppp": { "module_list": [ "//third_party/ppp:ppp_group" ] } }}
新建文件BUILD.gn,内容如下:
import("//build/ohos.gni")group("ppp_group") { deps =[ "pppd:pppd_group", "chat:chat", "etc:ppp_copy" ]}
2.3.2.1pppd移植
原生交叉编译:
./configure --host=arm-linux-gnueabimake CC=arm-linux-gnueabi-gcc AR=arm-linux-gnueabi-ar
新建gn,并编译:
import("//build/ohos.gni")group("pppd_group") { deps =[ ":pppd", # "plugins:pppd_plugins", ]}ohos_executable("pppd") { sources = [ "main.c", "magic.c", "fsm.c", "lcp.c", "ipcp.c", "upap.c", "chap-new.c", # "md5.c", "ccp.c", "ecp.c", "ipxcp.c", "auth.c", "options.c", "sys-linux.c", "md4.c", "chap_ms.c", "demand.c", "utils.c", "tty.c", "eap.c", "chap-md5.c", "session.c", # "sha1.c", "multilink.c", "tdb.c", "spinlock.c", "ipv6cp.c", "eui64.c", "pppcrypt.c", "eap-tls.c" ] include_dirs = [ "//third_party/ppp/include", "//third_party/ppp/pppd", "//third_party/openssl/include", "//third_party/libpcap", ] defines = [ "HAVE_PATHS_H", "IPX_CHANGE", "HAVE_MMAP", "DESTDIR=\"/usr/local\"", "CHAPMS=1", "MPPE=1", "USE_EAPTLS=1", "HAS_SHADOW", "HAVE_CRYPT_H=1", # "HAVE_LOGWTMP=1", "HAVE_MULTILINK", "USE_TDB=1", "PLUGIN", "PPP_FILTER", "INET6=1", "MAXOCTETS", "USE_CRYPT=1", "_PATH_VARRUN=\"/data/ppp/var/run/\"" ] cflags = [ "-Wno-implicit-function-declaration", "-O2", "-g", "-pipe", ] deps = [ "//third_party/openssl:libcrypto_static", "//third_party/openssl:ssl_source", "//third_party/libpcap:libpcap", ] install_enable = true part_name = "ppp" subsystem_name = "ppp" install_images = [ "system", "updater", ]}
2.3.2.2chat移植
import("//build/ohos.gni")ohos_executable("chat") { sources = [ "chat.c", ] cflags = [ "-O2", "-g", "-pipe", "-fPIC", "-UNO_SLEEP" ] defines = [ "TERMIOS", "SIGTYPE=void", "FNDELAY=O_NDELAY" ] include_dirs = [ "//third_party/ppp/include", "//third_party/ppp/chat", "//third_party/ppp", ] deps = [ "//third_party/openssl:libcrypto_static", "//third_party/openssl:ssl_source", "//third_party/libpcap:libpcap", ] part_name = "ppp" subsystem_name = "ppp" install_enable = true install_images = [ "system", "updater", ]}
2.3.2.3etc配置
新建etc目录,用于拷贝ppp配置到/data目录。
注:因为OHOS的/system分区为只读,所以需要修改部分源码将ppp配置文件路径修改到/data下,这部分请读者自行修改。
新建文件BUILD.gn,内容如下:
import("//build/ohos.gni")group("ppp_copy") { deps =[ ":ip-up", ":ip-down", ":ipv6-up", ":ipv6-down", ":options", ":options.pptp", ":chap-secrets", ":pap-secrets", ":resolv.conf", ":peers_provider", ":peers_quectel-ppp", ":peers_quectel-chat-connect", ":peers_quectel-chat-disconnect", ":ip-up.d_0000usepeerdns", ":ip-down.d_0000usepeerdns" ]}ohos_prebuilt_etc("ip-up") { source = "ppp/ip-up" relative_install_dir = "ppp" part_name = "ppp"}ohos_prebuilt_etc("ipv6-up") { relative_install_dir = "ppp" source = "ppp/ipv6-up" part_name = "ppp"}ohos_prebuilt_etc("ip-down") { relative_install_dir = "ppp" source = "ppp/ip-down" part_name = "ppp"}ohos_prebuilt_etc("ipv6-down") { relative_install_dir = "ppp" source = "ppp/ipv6-down" part_name = "ppp"}ohos_prebuilt_etc("options") { relative_install_dir = "ppp" source = "ppp/options" part_name = "ppp"}ohos_prebuilt_etc("options.pptp") { relative_install_dir = "ppp" source = "ppp/options.pptp" part_name = "ppp"}ohos_prebuilt_etc("chap-secrets") { relative_install_dir = "ppp" source = "ppp/chap-secrets" part_name = "ppp"}ohos_prebuilt_etc("pap-secrets") { relative_install_dir = "ppp" source = "ppp/pap-secrets" part_name = "ppp"}ohos_prebuilt_etc("resolv.conf") { relative_install_dir = "ppp" source = "ppp/resolv.conf" part_name = "ppp"}ohos_prebuilt_etc("peers_provider") { relative_install_dir = "ppp/peers" source = "ppp/peers/provider" part_name = "ppp"}ohos_prebuilt_etc("peers_quectel-ppp") { relative_install_dir = "ppp/peers" source = "ppp/peers/quectel-ppp" part_name = "ppp"}ohos_prebuilt_etc("peers_quectel-chat-connect") { relative_install_dir = "ppp/peers" source = "ppp/peers/quectel-chat-connect" part_name = "ppp"}ohos_prebuilt_etc("peers_quectel-chat-disconnect") { relative_install_dir = "ppp/peers" source = "ppp/peers/quectel-chat-disconnect" part_name = "ppp"}ohos_prebuilt_etc("ip-up.d_0000usepeerdns") { relative_install_dir = "ppp/ip-up.d" source = "ppp/ip-up.d/0000usepeerdns" part_name = "ppp"}ohos_prebuilt_etc("ip-down.d_0000usepeerdns") { relative_install_dir = "ppp/ip-down.d" source = "ppp/ip-down.d/0000usepeerdns" part_name = "ppp"}
2.4添加route
原始OHOS3.1中没有route程序,造成ppp拨号成功后无法设置路由。
需要添加route软件到toybox中,修改文件third_party/toybox/generated/config.h,内容如下:
#ifdef WITH_SELINUX# define CFG_ROUTE 1# define USE_ROUTE(...) __VA_ARGS__#else# define CFG_ROUTE 1# define USE_ROUTE(...) __VA_ARGS__
2.5编译配置
修改productdefine/common/products/rk3568.json,新增ppp:
"ppp:ppp":{}
修改build/subsystem_config.json,新增ppp:
"ppp":{ "path": "third_party/ppp", "name": "ppp" },
修改文件build/config/compiler/BUILD.gn:
treat_warnings_as_errors = false
注:这里因为无需遵守编码规范,故取消该设置。
2.6启动配置
修改文件base/startup/init_lite/services/etc/init.cfg。
新增jobs:
{ "name" : "services:pppd_service", "cmds" : [ "mkdir /data/ppp", "mkdir /data/ppp/var", "mkdir /data/ppp/var/lock", "mkdir /data/ppp/var/run", "mkdir /data/ppp/var/log", "mkdir /data/ppp/etc", "mkdir /data/ppp/etc/ppp", "copy /etc/ppp/ip-up /data/ppp/etc/ppp/ip-up", "copy /etc/ppp/ip-down /data/ppp/etc/ppp/ip-down", "chmod 0775 /data/ppp/etc/ppp/ip-up", "chmod 0775 /data/ppp/etc/ppp/ip-down", "copy /etc/ppp/ipv6-up /data/ppp/etc/ppp/ipv6-up", "copy /etc/ppp/ipv6-down /data/ppp/etc/ppp/ipv6-down", "chmod 0775 /data/ppp/etc/ppp/ipv6-up", "chmod 0775 /data/ppp/etc/ppp/ipv6-down", "copy /etc/ppp/options /data/ppp/etc/ppp/options", "copy /etc/ppp/options.pptp /data/ppp/etc/ppp/options.pptp", "copy /etc/ppp/chap-secrets /data/ppp/etc/ppp/chap-secrets", "copy /etc/ppp/pap-secrets /data/ppp/etc/ppp/pap-secrets", "copy /etc/ppp/resolv.conf /data/ppp/etc/ppp/resolv.conf", "mkdir /data/ppp/etc/ppp/ip-up.d", "copy /etc/ppp/ip-up.d/0000usepeerdns /data/ppp/etc/ppp/ip-up.d/0000usepeerdns", "mkdir /data/ppp/etc/ppp/ip-down.d", "copy /etc/ppp/ip-down.d/0000usepeerdns /data/ppp/etc/ppp/ip-down.d/0000usepeerdns", "mkdir /data/ppp/etc/ppp/peers", "copy /etc/ppp/peers/provider /data/ppp/etc/ppp/peers/provider", "copy /etc/ppp/peers/quectel-ppp /data/ppp/etc/ppp/peers/quectel-ppp", "copy /etc/ppp/peers/quectel-chat-connect /data/ppp/etc/ppp/peers/quectel-chat-connect", "copy /etc/ppp/peers/quectel-chat-disconnect /data/ppp/etc/ppp/peers/quectel-chat-disconnect" ] }
新增services:
{ "name" : "pppd_service", "start-mode" : "condition", "path" : ["/system/bin/pppd", "call", "quectel-ppp"], "once" : 1, "disabled" : 1, "console" : 1, "uid" : "root", "gid" : ["shell", "log", "readproc"], "jobs" : { "on-start" : "services:pppd_service" } }
在init的最后新增:
"name" : "init", "cmds" : [# ...... "start pppd_service" ]
2.7最终效果
系统启动后,自动启动pppd进行拨号,成功效果如下:
三、QMI方案
3.1内核添加对应配置
CONFIG_USB_NET_QMI_WWAN=yCONFIG_USB_WDM=y
3.2修改内核代码
拷贝移远提供的qmi_wwan_q.c源码到drivers/net/usb/目录。
修改drivers/net/usb/Makefile,内容如下:
obj-${CONFIG_USB_NET_QMI_WWAN} += qmi_wwan_q.oobj-${CONFIG_USB_NET_QMI_WWAN} += qmi_wwan.o
3.3添加quectel-cm软件
该软件源码由移远提供。
新建BUILD.gn,内容如下:
import("//build/ohos.gni")group("quectel-cm-group") { deps = [ ":quectel-CM",# ":quectel-qmi-proxy",# ":quectel-mbim-proxy",# ":quectel-atc-proxy", ":quectel-script" ]}ohos_prebuilt_etc("quectel-script") { # relative_install_dir = "quectel" source = "default.script" part_name = "quectel" module_install_dir = "quectel" subsystem_name = "quectel"}ohos_executable("quectel-CM") { sources = [ "QmiWwanCM.c", "GobiNetCM.c", "main.c", "MPQMUX.c", "QMIThread.c", "util.c", "qmap_bridge_mode.c", "mbim-cm.c", "device.c", "atc.c", "atchannel.c", "at_tok.c", "udhcpc.c" ] defines = [ "USE_OHOS" ] include_dirs = [ "//third_party/quectel/quectel-cm", ] install_enable = true part_name = "quectel" subsystem_name = "quectel" install_images = [ "system", "updater", ]}
3.4启动配置
修改文件base/startup/init_lite/services/etc/init.cfg。
添加trigger,用以启动软件:
----------------- base/startup/init_lite/services/etc/init.cfg -----------------index 3a1e0b1f3d..b093e0fb6c 100755@@ -166,7 +166,8 @@ "trigger post-fs-data", "trigger firmware_mounts_complete", "trigger early-boot",- "trigger boot"+ "trigger boot",+ "trigger quectel-cm" ] }, { "name" : "early-fs",@@ -431,6 +432,11 @@ "chmod 0773 /data/misc/trace", "chmod 0775 /data/misc/wmtrace" ]+ }, {+ "name" : "quectel-cm",+ "cmds" : [+ "exec /system/bin/quectel-CM &"+ ] } ], "services" : [{
3.5最终效果