在AM3715上调试gprs模块时遇到了一些问题,在这里记录一下,以免日后忘记。
下面按照遇到的问题先后来做记录:
使用的是广和通的G510模块,使用的是他们提供的RIL和MUX驱动,根据他们的指导文档,很快就实现了电话、短信功能。
手动调用pppd call ppp-dial 是可以拨号成功,ifconfig ppp0 可获取IP地址,但是通过勾选“设置”->“无线和网络”->“移动网络”->“已启用网络”
并不能实现拨号。
此时发现进入“接入点名称”并没看到任何APN显示出来,新建APN时MCC、MNC为空,将所有信息填完也无法保存,保存时ril log(logcat -b radio)显示:
"Failed setting numeric 'null' for the current operator."
numeric是由MCC、MNC组成的,这个说明系统没有读到SIM卡的MCC和MNC,但是在ril log中可看到
D/GSM ( 1103): IMSI: 460028xxxxxxx
说明已经读到了MCC=460,MNC=02,查看/system/etc/apns-conf.xml,发现里面已经含了
<apn carrier="China Mobile" mcc="460" mnc="02" apn="cmnet" type="default,supl" />
但是这个APN为什么还是没有显示出来呢?这些情况说明MCC、MNC虽然得到了,但是却没有成功上报给上一层,所以numeric是null。
还是要从源代码入手:
D/GSM ( 1103): IMSI: 460028xxxxxxx
这句来自于frameworks/base/telephony/java/com/android/internal/telephony/gsm/SIMRecords.java, 位于其中的
public void handleMessage(Message msg)->case EVENT_GET_IMSI_DONE 分句,获取IMSI后,应该就会去更新mncLength,
if (mncLength == UNKNOWN) {
// the SIM has told us all it knows, but it didn't know the mnc length.
// guess using the mcc
try {
int mcc = Integer.parseInt(imsi.substring(0,3));
mncLength = MccTable.smallestDigitsMccForMnc(mcc);
} catch (NumberFormatException e) {
mncLength = UNKNOWN;
Log.e(LOG_TAG, "SIMRecords: Corrupt IMSI!");
}
}
通过添加log语句,可知mncLength在这个if之前是mncLength=UNINITIALIZED (-1), 所以就跳过了这个if里的语句,没有更新
mncLength,故将条件判断改为
if ((mncLength == UNKNOWN || mncLength == UNINITIALIZED) && (imsi != null))
这样就能正确更新mncLength为2。
从case EVENT_GET_IMSI_DONE break出来后,就会调用onRecordLoaded():
protected void onRecordLoaded() {
// One record loaded successfully or failed, In either case
// we need to update the recordsToLoad count
recordsToLoad -= 1;
if (recordsToLoad == 0 && recordsRequested == true) {
onAllRecordsLoaded();
} else if (recordsToLoad < 0) {
Log.e(LOG_TAG, "SIMRecords: recordsToLoad <0, programmer error suspected");
recordsToLoad = 0;
}
}
其中的onAllRecordsLoaded()函数会调用getSIMOperatorNumeric()去获取numeric,然后设置PROPERTY_ICC_OPERATOR_NUMERIC,
但是通过在getSIMOperatorNumeric里添加log语句,发现getSIMOperatorNumeric根本就没有被执行过,说明onAllRecordsLoaded也没有
被执行过,估计是onRecordLoaded里的判断条件没有符合,所以将判断条件去掉,重新编译更新系统,果然能够正常显示已有的APN,新建APN
也能保存了。
此时再次勾选“已启用网络”,可见可以开始pppd拨号了,ifconfig ppp0 也返回了IP,但是android屏幕上端的标题仍然没有出现数据连接的图标,
这个说明pppd拨号虽然通了,但是没有上报给android系统,android系统仍不知有这个连接存在,这是ril的工作,勾选“已启用网络”后,会调用
hardware/ril/reference-ril/reference-ril.c 里的 requestSetupDataCall()来进行pppd拨号:
static void requestSetupDataCall(void *data, size_t datalen, RIL_Token t)
{
const char *apn;
const char *user = NULL;
const char *password = NULL;
char *cmd;
int err;
int res;
ATResponse *p_response = NULL;
apn = ((const char **)data)[2];
user = ((const char **)data)[3];
password = ((const char **)data)[4];
const char *pdp_type;
/*set data call state in RIL process*/ //by trento
LOGD("requesting data connection to APN '%s'", apn);
if (datalen > 6 * sizeof(char *)) {
pdp_type = ((const char **)data)[6];
} else {
pdp_type = "IP";
}
asprintf(&cmd, "AT+CGDCONT=1,\"%s\",\"%s\"",pdp_type, apn);//,,0,0", pdp_type, apn);
//FIXME check for error here
err = at_send_command(cmd, NULL);
free(cmd);
err = dial_at_modem("ATD*99***1#\r");
if(err != 0)
{
LOGE("dial failed");
}
err=runPPPD(user, password);//system("pppd call ppp-dial &"); //mod by trento
if(err !=0){
goto error;
}
at_response_free(p_response);
return;
error:
RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
at_response_free(p_response);
}
发现这里面只进行了pppd拨号,并没有上报的动作,所以在函数里定义
char *response[3] = { "1", PPP_TTY_PATH, "0.0.0.0"};
并在runPPPD后添加:
sleep(5); //wait for establish the connection
RIL_onRequestComplete(t, RIL_E_SUCCESS, response, sizeof(response));
这样就改动以后,建立连接后就可在android屏幕上看到建立连接的图标了,不过在浏览器里输入www.baidu.com还是打不开,
后来发现ping IP是成功的,但是ping域名就不行,心想在浏览器里直接输入百度IP是不是可以呢,一试,果然可以!这样应该是
dns设置的问题了,在网上搜到了解决办法:在init.rc中
setprop net.tcp.buffersize.gprs 4092,8760,11680,4096,8760,11680
下面加上:
setprop net.dns1 202.96.128.166
setprop net.dns2 202.96.134.133
setprop net.dnschange 2
就可以了。
至此拨号上网功能已经调通,但是发现无法关闭拨号功能,在网上搜到这篇博文:
参考它的做法就可以实现关闭功能了。