摘要:
本文主要针对MTK MT8317 Android6.0 代码进行4G模块移植,使用pppd拨号的方式实现上网,并没有按照移远提供的文档GobiNet方式上网。
1、内核部分的移植
1.1 内核驱动修改
添加USB串口驱动,如下:
kernel\kernel-3.18\drivers\usb\serial\option.c
static const struct usb_device_id option_ids[] = {
.....................................................................
{ USB_DEVICE(QUALCOMM_VENDOR_ID, 0x9003), /* Quectel UC20 */
.driver_info = (kernel_ulong_t)&net_intf4_blacklist },
#if 1//Added by Quectel
//{ USB_DEVICE(0x05C6, 0x9090) }, //For Quectel UC15
//{ USB_DEVICE(0x05C6, 0x9003) }, //For Quectel UC20
//{ USB_DEVICE(0x05C6, 0x9215) }, //For Quectel EC20
{ USB_DEVICE(0x2C7C, 0x0125) }, /* Quectel EC25 */
#endif
{ USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_6001) },
........................................
}
因系统使用pppd拨号,不用GobiNet,所以其它部分就不需要在进行配置
1.2 内核配置
修改kernel\kernel-3.18\arch\arm\configs\ac83xx_androidm_defconfig 添加如下配置:
CONFIG_USB_SERIAL=y
CONFIG_USB_SERIAL_GENERIC=y
CONFIG_USB_SERIAL_WWAN=y
CONFIG_USB_SERIAL_OPTION=y
2、hardware层的修改
这个部分主要针对MTK平台dongle的选择以及相应的PID和VID配置,同时在针对Dongle模块的libpath的配置等。
因为EC20模组不需要进行USB模式切换,需要修改USB模式选择,对EC20模式不进行USB模式切换。具体修改如下:
2.1 模块配置
修改:vendor\atc\proprietary\hardware\dongle-ril\configs\dongleselect.conf 添加
VID=1e89,PID=2916,ATPort=/dev/ttyUSB3,ModemPort=/dev/ttyUSB4,LIBPATH=libmtk-ril.so
VID=2c7c,PID=0125,ATPort=/dev/ttyUSB2,ModemPort=/dev/ttyUSB0,LIBPATH=libmtk-ril-ec20.so
修改:device\atc\ac83xx\device.mk
ifeq ($(strip $(MTK_EXTERNAL_DONGLE_SUPPORT)), yes)
PRODUCT_PACKAGES += dongled
PRODUCT_PACKAGES += usb_modeswitch
PRODUCT_PACKAGES += chat
PRODUCT_PACKAGES += rild_dongle
PRODUCT_PACKAGES += libril_dongle
PRODUCT_PACKAGES += libmtk-ril
PRODUCT_PACKAGES += libmtk-ril-e1750
PRODUCT_PACKAGES += libmtk-ril-mf626
PRODUCT_PACKAGES += libmtk-ril-e3131
PRODUCT_PACKAGES += libmtk-ril-ec20
.....................................................................
$(call inherit-product-if-exists, vendor/atc/proprietary/hardware/dongle-ril/configs/dongled.mk)
Endif
2.2 USB Dongle不进行USB模式切换
具体修改如下:
vendor\atc\proprietary\hardware\dongle-ril\dongled\UsbSelect.cpp
int UsbSelect::handleUsbAutoSelect(NetlinkEvent *evt)
{
.........................................................................
if (strtoul(lastDevice.VID, NULL, 16) == strtoul(vid, NULL, 16) &&
strtoul(lastDevice.PID, NULL, 16) == strtoul(pid, NULL, 16)) {
SLOGD("handleUsbAutoSelect: NetlinkEvent is the same of last one");
} else {
//if(doUsbModeSwitch(vid ,pid))
//{
// SLOGD("doUsbModeSwitch:device vid:%s,pid:%s, success!", vid, pid);
// return 0;
// }
/*Quectel's EC20 do not need to modeswitch*/
if (tmpvid == 0x2c7c && tmppid == 0x0125) {
SLOGD("Quectel EC20 is no need to do modeswitch");
} else {
bool modeSwitch = false;
modeSwitch = doUsbModeSwitch(vid ,pid);
if (modeSwitch){
SLOGD("doUsbModeSwitch:device vid:%s,pid:%s, success!", vid, pid)
return 0;
}
}
found = findDevice(vid, pid, &device);
..........................................................
}
2.3 EC20 R2.1 4G模块的reference-ril模块的移植
将移远提供reference-ril代码目录拷贝到
vendor\atc\proprietary\hardware\dongle-ril\mtk-ril\目录下,重命名为mtk-ril-ec20,如下:
vendor\atc\proprietary\hardware\dongle-ril\mtk-ril\mtk-ril-ec20\
修改
vendor\atc\proprietary\hardware\dongle-ril\mtk-ril\Android.mk文件,添加对针对mtk-ril-ec20模块的编译,如下:
ifeq ($(MTK_EXTERNAL_DONGLE_SUPPORT),yes)
.................................................................................
LOCAL_MODULE:= libmtk-ril-e3131
include $(BUILD_SHARED_LIBRARY)
#for Quectel EC20
include $(CLEAR_VARS)
USE_MUXD=1
LOCAL_SRC_FILES:= \
mtk-ril-ec20/mtk-ril-ec20.c \
mtk-ril-ec20/atchannel.c \
mtk-ril-ec20/misc.c \
mtk-ril-ec20/at_tok.c \
mtk-ril-ec20/ql-pppd.c \
mtk-ril-ec20/ql-gps.c \
mtk-ril-ec20/ql-datafwd.c \
mtk-ril-ec20/ql-dtmf.c \
mtk-ril-ec20/ql-tty2tcp.c
ifeq ($(USE_NDK),1)
LOCAL_CFLAGS += -DUSE_NDK
LOCAL_LDLIBS += -llog
LOCAL_SRC_FILES += mtk-ril-ec20/ql-ndk.c
else
LOCAL_SHARED_LIBRARIES := \
libcutils libutils libril libnetutils
endif
# for asprinf
LOCAL_CFLAGS += -D_GNU_SOURCE
LOCAL_C_INCLUDES := $(KERNEL_HEADERS)
ifeq ($(USE_MUXD),1)
LOCAL_CFLAGS += -DMUX_ANDROID -DUSE_MUXD
$(shell touch $(LOCAL_PATH)/mtk-ril-ec20/CMUX/*)
LOCAL_SRC_FILES += mtk-ril-ec20/CMUX/gsm0710muxd_bp.c
endif
#build shared library
LOCAL_SHARED_LIBRARIES += \
libcutils libutils
LOCAL_CFLAGS += -DRIL_SHLIB
LOCAL_MODULE:= libmtk-ril-ec20
include $(BUILD_SHARED_LIBRARY)
endif #(($(MTK_EXTERNAL_DONGLE_SUPPORT),yes)
2.3.1 去掉不必要的文件
因MTK平台已经自带chat、ip-up、ip-down,所以去掉移远提供的ril代码中的chat.c、ip-up.c、ip-down.c文件,将reference-ril.c重命名为mtk-ril-ec20.c
2.3.2 修改Android.mk去掉Gobinet相关的文件编译、以及chat.c、ip-up.c、ip-down.c三个文件编译,如下:
USE_MUXD=1 ------->使用改选项
USE_NDIS=0 -------->使用pppd上网,不使用NDIS
LOCAL_PATH:= $(call my-dir)
$(shell touch $(LOCAL_PATH)/*)
include $(CLEAR_VARS)
LOCAL_SRC_FILES:= \
mtk-ril-ec20.c \
atchannel.c \
misc.c \
at_tok.c \
ql-pppd.c \
ql-gps.c \
ql-datafwd.c \
ql-dtmf.c \
ql-tty2tcp.c
ifeq ($(USE_NDK),1)
LOCAL_CFLAGS += -DUSE_NDK
LOCAL_LDLIBS += -llog
LOCAL_SRC_FILES += ql-ndk.c
else
LOCAL_SHARED_LIBRARIES := \
libcutils libutils libril libnetutils
endif
# for asprinf
LOCAL_CFLAGS += -D_GNU_SOURCE
LOCAL_C_INCLUDES := $(KERNEL_HEADERS)
ifeq ($(USE_MUXD),1)
LOCAL_CFLAGS += -DMUX_ANDROID -DUSE_MUXD
$(shell touch $(LOCAL_PATH)/CMUX/*)
LOCAL_SRC_FILES += CMUX/gsm0710muxd_bp.c
endif
#build shared library
LOCAL_SHARED_LIBRARIES += \
libcutils libutils
LOCAL_CFLAGS += -DRIL_SHLIB
LOCAL_MODULE:= libmtk-ril-ec20 ------>EC20 lib库模块编译
include $(BUILD_SHARED_LIBRARY)
2.3.3 不使用quectel-CM的时候,将影响的相关代码移除
修改:vendor\atc\proprietary\hardware\dongle-ril\mtk-ril\mtk-ril-ec20\atchannel.c
#define LOG_NDEBUG 0
#define LOG_TAG "ATC"
#include <utils/Log.h>
#include "ql-log.h"
....................................................
#ifdef USE_NP
static void setTimespecRelative(struct timespec *p_ts, long long msec)
{
struct timeval tv;
gettimeofday(&tv, (struct timezone *) NULL);
/* what's really funny about this is that I know
pthread_cond_timedwait just turns around and makes this
a relative time again */
p_ts->tv_sec = tv.tv_sec + (msec / 1000);
p_ts->tv_nsec = (tv.tv_usec + (msec % 1000) * 1000L ) * 1000L;
}
#endif /*USE_NP*/
.......................................
2.3.4 mtk-ril-ec20.c文件的修改
2.3.4.1 打开ril层库的pppd模式开关,如下:
#define USB_HOST_USE_Autochips_ac83xx
#ifdef USB_HOST_USE_Autochips_ac83xx
/*only use pppd,not NDIS*/
#define USE_MUXD
static int s_ppp_fd = -1;
#endif
2.3.4.2 针对上层请求SIM卡时,移动远ril层返回空的问题,需要将其修改成自定义,如下:
#ifdef USE_NDIS
................................................
#else
static int ql_get_ndisname(char **pp_usbnet_adapter) { return -ENODEV; }
static int ql_ndis_start(const char *apn, const char *user, const char *password, const char *auth_type) { return 0; }
static int ql_ndis_stop(int signo) { return 0; }
#endif
修改成:
#ifdef USE_NDIS
.................................................
#else
static int ql_get_ndisname(char **pp_usbnet_adapter) { return -ENODEV; }
static int ql_ndis_start(const char *apn, const char *user, const char *password, const char *auth_type,int default_pdp) { return 0; }
static int ql_ndis_stop(int signo) { return 0; }
#endif
static void requestSIM_IO(void *data, size_t datalen, RIL_Token t)
{
...........................................................
#ifdef QUECTEL_REPORT_SIGNAL_STRENGTH
if ((p_args->fileid == EF_ICCID) && (p_args->command == COMMAND_READ_BINARY)) {
requestSignalStrength(NULL, 0, NULL);
}
#endif
//if (p_args->fileid == EF_ICCID && sr.simResponse == NULL)
// goto error;
if (p_args->fileid == EF_ICCID && *(sr.simResponse) == NULL ){
LOGD("[%s]EF_ICCID=%d,p_args->fileid is %d,sr.simResponse=%p",__func__,EF_ICCID,p_args->fileid,sr.simResponse);
LOGD("deal with SIMIO error");
goto error;
}
LOGD("[%s]EF_ICCID=%d,p_args->fileid is %d,sr.simResponse=%p",__func__,EF_ICCID,p_args->fileid,sr.simResponse);
LOGD("[%s]SIMIO REQUEST COMPLETE------NO ERROR",__func__);
RIL_onRequestComplete(t, RIL_E_SUCCESS, &sr, sizeof(sr));
at_response_free(p_response);
free(cmd);
return;
error:
.............................................
.......................................................
}
2.3.4.3 去掉ril调试开关
static void *
mainLoop(void *param)
{
int fd;
int ret;
//#if 1
#if 0
//pay attention:
//these codes means will result catch log every time your device boot up.
//so make sure these codes are commented in your release software
if (access(QL_DEBUG_LOG_PATH, W_OK) && errno == ENOENT) {
system("/system/bin/mkdir "QL_DEBUG_LOG_PATH);
}
#endif
..........................................................................
}
2.3.4.4 RIL版本号跟Android6.0版本不一致导致上层获取不到网络数据包的问题
将RIL的版本号修改成Android6.0的版本号为9,修改如下:
const RIL_RadioFunctions *RIL_Init(const struct RIL_Env *env, int argc, char **argv)
{
int ret;
int fd = -1;
int opt;
pthread_attr_t attr;
struct passwd *pwd;
.........................................
if (anroid_version <= 40) QL_RIL_VERSION = 6;
else if (anroid_version == 41) QL_RIL_VERSION = 6;
else if (anroid_version == 42) QL_RIL_VERSION = 7;
else if (anroid_version == 43) QL_RIL_VERSION = 8; //maybe should be 7
else if (anroid_version == 44) QL_RIL_VERSION = 9;
//else if (anroid_version == 50) QL_RIL_VERSION = 10;
//else if (anroid_version == 51) QL_RIL_VERSION = 11;
//else if (anroid_version == 60) QL_RIL_VERSION = 11;
else if (anroid_version == 50) QL_RIL_VERSION = 9;
else if (anroid_version == 51) QL_RIL_VERSION = 9;
else if (anroid_version == 60) QL_RIL_VERSION = 9;
else LOGE("Unsupport Android Version %d by Quectel Now!!!!", anroid_version);
LOGD("Android Version: %d, RIL_VERSION: %d / %d", anroid_version, QL_RIL_VERSION, RIL_VERSION);
#ifndef USE_NDK
if (QL_RIL_VERSION != RIL_VERSION) //maybe get error when dynamic detect ril version
QL_RIL_VERSION = RIL_VERSION;
#endif
......................................................
}
修改ril.h,将版本号修改成9,并添加对应版本的结构体参数,如下:
//#define RIL_VERSION 11 /* Current version */
#define RIL_VERSION 9 /* Current version */
.....................................................................................
} RIL_Data_Call_Response_v9; // FIXME: Change to v10
typedef struct {
int status; /* A RIL_DataCallFailCause, 0 which is PDP_FAIL_NONE if no error */
int suggestedRetryTime; /* If status != 0, this fields indicates the suggested retry
back-off timer value RIL wants to override the one
pre-configured in FW.
The unit is miliseconds.
The value < 0 means no value is suggested.
The value 0 means retry should be done ASAP.
he value of INT_MAX(0x7fffffff) means no retry. */
int cid; /* Context ID, uniquely identifies this call */
int active; /* 0=inactive, 1=active/physical link down, 2=active/physical link up */
char * type; /* One of the PDP_type values in TS 27.007 section 10.1.1.
For example, "IP", "IPV6", "IPV4V6", or "PPP". If status is
PDP_FAIL_ONLY_SINGLE_BEARER_ALLOWED this is the type supported
such as "IP" or "IPV6" */
char * ifname; /* The network interface name */
char * addresses; /* A space-delimited list of addresses with optional "/" prefix length,
e.g., "192.0.1.3" or "192.0.1.11/16 2001:db8::1/64".
May not be empty, typically 1 IPv4 or 1 IPv6 or
one of each. If the prefix length is absent the addresses
are assumed to be point to point with IPv4 having a prefix
length of 32 and IPv6 128. */
char * dnses; /* A space-delimited list of DNS server addresses,
e.g., "192.0.1.3" or "192.0.1.11 2001:db8::1".
May be empty. */
char * gateways; /* A space-delimited list of default gateway addresses,
e.g., "192.0.1.3" or "192.0.1.11 2001:db8::1".
May be empty in which case the addresses represent point
to point connections. */
char * pcscf; /* the Proxy Call State Control Function address
via PCO(Protocol Configuration Option) for IMS client. */
int mtu; /* MTU received from network
Value <= 0 means network has either not sent a value or
sent an invalid value */
} RIL_Data_Call_Response_v11;
typedef enum {
RADIO_TECH_3GPP = 1, /* 3GPP Technologies - GSM, WCDMA */
RADIO_TECH_3GPP2 = 2 /* 3GPP2 Technologies - CDMA */
} RIL_RadioTechnologyFamily;
添加ril.h头文件的路径:
//#include "../include/telephony/ril.h"
#include "../../include/telephony/ril.h"
2.3.4.5 修改ril主循环调用libril库的路径
const RIL_RadioFunctions *RIL_Init(const struct RIL_Env *env, int argc, char **argv)
{
int ret;
int fd = -1;
int opt;
pthread_attr_t attr;
struct passwd *pwd;
....................................................
s_callbacks.version = QL_RIL_VERSION;
//if (property_get("rild.libpath", prop_value, NULL) > 0) {
if (property_get("ro.build.description", prop_value, NULL) > 0) {
LOGD("[ro.build.description]: [%s]", prop_value);
}
//if (property_get("rild.libargs", prop_value, NULL) > 0) {
if (property_get("tedongle.rild.libpath", prop_value, NULL) > 0) {
LOGD("[rild.libpath]: [%s]", prop_value);
}
if (property_get("tedongle.rild.libargs", prop_value, NULL) > 0) {
LOGD("[rild.libargs]: [%s]", prop_value);
}
if ((QL_RIL_VERSION > 9) && access("/sys/fs/selinux", F_OK) == 0) {
3测试
合并好代码之后,全部编译系统,用SD卡烧录系统到机器,在4G模块插入之前只用
Adb root
Adb shell
#logcat >/sdcard/4G_logacta.log
如果log信息中有:
D Dongled : handleUsbAutoSelect: The PRODUCT is: 2c7c/125/318
01-01 08:08:57.337 843 848 D Dongled : Quectel EC20 is no need to do modeswitch
01-01 08:08:57.337 843 848 E Dongled : not found the value of ModemPort
01-01 08:08:57.337 843 848 E Dongled : It's not ModemPort
01-01 08:08:57.337 843 848 E Dongled : The 3Gdongle(vid = 2c7c,pid = 0125) is not found
说明vendor\atc\proprietary\hardware\dongle-ril\configs\dongleselect.conf文件中模组的PID、VID、AT口相关没配置正确,如果全部OK,一般情况状态栏就会显示4G信号图标了。
注意模组的SIM卡,要保证能够上4G网络,首先在手机上使用,确认OK之后在到机器上使用。
其它请看代码上传部分,ATC_AndroidM-8317代码库的Development分支commit ID:
f6b819c78d9708b73a2f889f9c70c82969d1b251
或者ATC_AndroidM-8317代码库的GS1_AndroidM分支commit ID:
cc1e31c4d401fb0f6d4107b91235582dd9656799
经过GS1_AndroidM分支上是OK的,模组支持热插拔。