android下调试3G之自动拨号

本文介绍如何在Android系统中实现3G网络的自动拨号功能,包括修改rild源码、编写拨号脚本及配置系统文件等内容。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

android下调试3G之自动拨号
2014-11-13 11:20:14       0 个评论      
收藏    我要投稿

本章简单讲述下android实现自动拨号的功能,该功能利用了系统启动的rild的服务来实现,因为rild的服务是杀不死的,所以利用这一点,可以使拨号失败或网络断掉后自动重拨,来增强上网的可靠性。这里只实现拨号功能,把ril库实现的一些功能都去掉了。

一、修改rild程序源码

把 .../hardware/ril里面的文件全部删掉,创建rild文件夹,把以下面代码放到新建的文件夹下。

1、rild.c

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#define LOG_TAG "RILD"
#include <unistd.h>
#include <pthread.h>
#include <utils log.h= "" >
#include <sys types.h= "" >
#include <sys stat.h= "" >
#include "ril_fun.h"
int main( int argc, char *argv[])
{
     int opt;
     int err;
     pthread_t tid;
     char buf[PROPERTY_VALUE_MAX];
     static int device_fd;
     static char * device_path = NULL;
     umask(S_IRGRP | S_IWGRP | S_IXGRP | S_IROTH | S_IWOTH | S_IXOTH);
     while ( - 1 != (opt = getopt(argc, argv, "d:" ))) { //用来分析main函数传递的命令行参数
         switch (opt) {
             case 'd' :
                 device_path = optarg;
                 ALOGD( "Opening tty device %s\n" , device_path);
             break ;
             default :
                 ALOGD( "Not tty device" );
                 goto done;
         }
     }
     device_fd = device_open(device_path); //打开设备节点
     device_init(device_fd); //初始化设备节点
     property_set( "ctl.stop" , PPPD_SERVICE_NAME); //设置pppd_gprs属性为停止
     request_setup_datacall(device_fd); //继续执行拨号
         
     pthread_create(&tid,NULL,ip_detection,( void *)device_fd); //创建查询IP线程,使断网后重新拨号
done:
     while ( 1 ){
         sleep( 0x00ffffff );
     }
     return 0 ;
}</sys></sys></utils></pthread.h></unistd.h>

2、ril_fun.c

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
#define LOG_TAG "RIL"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys types.h= "" >
#include <sys stat.h= "" >
#include <fcntl.h>
#include <termios.h>
#include <sys select.h= "" >
#include "ril_fun.h"
 
#define PPPD_EXIT_CODE      "net.gprs.ppp-exit"
#define PPP_NET_LOCAL_IP    "net.ppp0.local-ip"
#define PPP_SYSFS_RETRY     5
#define PPP_OPERSTATE_PATH  "/sys/class/net/ppp0/operstate"
 
static int pppd_started = 0 ;
 
int device_open( char *device_path)
{
     int device_fd = - 1 ;
     while (device_fd < 0 ) {
         if (device_path != NULL) {
             device_fd = open (device_path, O_RDWR); //打开串口AT模块的设备
         }
         if (device_fd < 0 ) {
             ALOGD ( "opening AT interface. retrying..." );
             sleep( 3 );
         }
     }
     return device_fd;
}
void device_init( int device_fd)
{
     struct termios options;
     tcgetattr(device_fd, &options); //获取串口属性
     
     cfsetispeed(&options, B115200); //设置接收波特率
     cfsetospeed(&options, B115200); //设置发送波特率
 
     options.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|IGNCR|ICRNL|IXON);
 
     options.c_cflag &= ~PARENB; //无奇偶校验位
     options.c_cflag &= ~CSTOPB; //停止位为1位
     options.c_cflag &= ~CSIZE; 
     options.c_cflag |= CS8;     //数据位为8位
     
     options.c_lflag   &=   ~(ICANON   |   ECHO   |   ECHOE   |   ISIG);
     
     tcsetattr(device_fd,TCSANOW,&options);
}
int at_send_command( int device_fd, char *cmd)
{
     int ret;   
     ret = write(device_fd, cmd, strlen(cmd));
     return ret;
}
void request_setup_datacall( int device_fd)
{
     const char *apn = "cmnet" ;
     char *cmd = NULL;
     int err;
 
     ALOGD( "requesting data connection to APN '%s'" , apn);
 
     if (pppd_started) {
         ALOGD( "Stop existing PPPd before activating PDP" );
         property_set( "ctl.stop" , PPPD_SERVICE_NAME); //设置pppd_gprs属性为停止
         pppd_started = 0 ;
     }
 
     err = at_send_command(device_fd, "at$qcpdplt=0" );
 
     asprintf(&cmd, "AT+CGDCONT=1,\"IP\",\"%s\",,0,0" , apn); //设置PDP上下文
     err = at_send_command(device_fd, cmd);
     free(cmd);
     if (err < 0 ) {
         ALOGD( "AT Send Command error!" );
     }
 
     err = property_set(PPPD_EXIT_CODE, "" ); //设置net.gprs.ppp-exit为空
     if (err < 0 ) {
         ALOGW( "Set PPPD_EXIT_CODE failed!" );
         goto ppp_error;
     }
     err = property_set(PPP_NET_LOCAL_IP, "" ); //设置net.ppp0.local-ip为空
     if (err < 0 ) {
         ALOGW( "Set PPPD_NET_LOCAL_IP failed!" );
         goto ppp_error;
     }
     err = property_set( "ctl.start" , PPPD_SERVICE_NAME); //设置pppd_gprs属性为启动
     pppd_started = 1 ;
     if (err < 0 ) {
         ALOGW( "Can not start PPPd" );
         goto ppp_error;
     }
     ALOGD( "PPPd started" );
 
     return ;
ppp_error:
     at_send_command(device_fd, "AT+CGACT=0,1" ); //PDP上下文去激活
 
     if (pppd_started) {
         property_set( "ctl.stop" , PPPD_SERVICE_NAME);
         pppd_started = 0 ;
     }
 
}
void *ip_detection( void *arg)
{
     int fd;
     int err;
     int device_fd = ( int )arg;
     char buffer[ 20 ];
     char exit_code[PROPERTY_VALUE_MAX];
     static char local_ip[PROPERTY_VALUE_MAX];
     static int pppd_started = 0 ;
 
     sleep( 2 );
     while ( 1 ){
         property_get(PPPD_EXIT_CODE, exit_code, "" ); //获取pppd的退出状态
         if (strcmp(exit_code, "" ) != 0 ) { //检测pppd是否异常退出
             ALOGW( "PPPd exit with code %s" , exit_code);
             request_setup_datacall(device_fd); //继续执行拨号
             goto done;
         }
         fd  = open(PPP_OPERSTATE_PATH, O_RDONLY); //读取/sys/class/net/ppp0/operstate来监控数据网络数据的状态
         if (fd >= 0 )  {
             buffer[ 0 ] = 0 ;
             read(fd, buffer, sizeof(buffer));
             close(fd);
             ALOGW( "buffer = %s" , buffer);
             if (!strncmp(buffer, "up" , strlen( "up" )) || !strncmp(buffer, "unknown" , strlen( "unknown" ))) {
                 memset(local_ip, '\0' ,sizeof(local_ip));
                 err = property_get(PPP_NET_LOCAL_IP, local_ip, "" ); //获取IP
                 if (err < 0 ) {
                     ALOGW( "Get PPPD_NET_LOCAL_IP failed!" );
                 }
                 if (!strcmp(local_ip, "" )) {
                     ALOGW( "PPP link is up but no local IP is assigned. Will retry times after %d seconds" ,PPP_SYSFS_RETRY);
                     property_set( "ctl.stop" , PPPD_SERVICE_NAME); //如果没有IP停止pppd
                 } else {
                     ALOGD( "PPP link is up with local IP address %s" , local_ip);
                 }
             } else {
                 ALOGW( "PPP link status in %s is %s. Will retry times after %d seconds" , \
                 PPP_OPERSTATE_PATH, buffer, PPP_SYSFS_RETRY);
                 property_set( "ctl.stop" , PPPD_SERVICE_NAME); //如果数据网络数据的状态不对停止pppd
             }
         } else {
             ALOGW( "Can not detect PPP state in %s. Will retry  times after %d seconds" , \
             PPP_OPERSTATE_PATH ,PPP_SYSFS_RETRY);
             request_setup_datacall(device_fd); //继续执行拨号
         }
done:
         sleep(PPP_SYSFS_RETRY);
     }
 
     return NULL;
}
</sys></termios.h></fcntl.h></sys></sys></stdlib.h></string.h></stdio.h>

3、ril_fun.h

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#ifndef _RIL_FUN_H_
#define _RIL_FUN_H_
 
#include <unistd.h>
#include <utils log.h= "" > //ALOG*()
#include <cutils properties.h= "" > //property_set()
 
#define PPPD_SERVICE_NAME "pppd_gprs"
 
/*************************************************************
* 功能:   打开串口设备文件
* 参数:   device_path: 串口设备文件名
* 返回值:  串口设备文件描述符
**************************************************************/
int device_open( char *device_path);
/*************************************************************
* 功能:   初始化设备节点
* 参数:   device_fd: 串口设备文件描述符         
* 返回值:  无
**************************************************************/
void device_init( int device_fd);
/*************************************************************
* 功能:   发送AT指令函数
* 参数:   device_fd: 串口设备文件描述符
*           cmd:AT命令         
* 返回值:  ret:状态
**************************************************************/
int at_send_command( int device_fd, char *cmd);
/*************************************************************
* 功能:   建立拨号函数
* 参数:   device_fd: 串口设备文件描述符         
* 返回值:  无
**************************************************************/
void request_setup_datacall( int device_fd);
/*************************************************************
* 功能:   创建查询IP线程
* 参数:   arg: void类型指针        
* 返回值:  NULL
**************************************************************/
void *ip_detection( void *arg);
 
#endif
</cutils></utils></unistd.h>

4、Android.mk

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
 
LOCAL_SRC_FILES:= \
     rild.c \
     ril_fun.c
 
 
LOCAL_SHARED_LIBRARIES := \
     libcutils \
     libdl
 
LOCAL_LDLIBS += -lpthread
LOCAL_MODULE:= rild
LOCAL_MODULE_TAGS := optional
 
include $(BUILD_EXECUTABLE)

上述文件添加好后,进行编译,在编译前如果之前编译过要进行清理,执行make clean

二、把下面的脚本放到板子的/etc/ppp下

1、init.gprs-pppd

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#!/system/bin/sh
# An unforunate wrapper script
# so that the exit code of pppd may be retrieved
 
PPPD_PID=
 
/system/bin/setprop "net.gprs.ppp-exit" "" #设置net.gprs.ppp-exit为空
/system/bin/log -t pppd "Starting pppd"
 
/system/bin/pppd connect 'chat -v -s -r "/var/log/chat.log" -f "/etc/ppp/3gdata_call.conf"' disconnect \
'chat -r "/var/log/chat.log" -t 30 -e -v "" +++ATH "NO CARRIER"' /dev/ttyUSB3 115200 mru 1280 mtu 1280 \
nodetach debug defaultroute usepeerdns crtscts user card password card noipdefault ipcp-accept-local  \
ipcp-accept-remote
 
PPPD_EXIT=$? #获得执行命令后的返回值
PPPD_PID=$!  #最后运行的后台进程的PID
 
/system/bin/log -t pppd "pppd exited with $PPPD_EXIT"
/system/bin/setprop "net.gprs.ppp-exit" "$PPPD_EXIT" #把返回值设置给net.gprs.ppp-exit

注:脚本中的/dev/ttyUSB3为模块USB串口的Modem口。

2、3gdata_call.conf

?
1
2
3
4
5
6
7
8
9
ABORT "NO CARRIER"
ABORT "NO DIALTONE"
ABORT "ERROR"
ABORT "NO ANSWER"
ABORT "BUSY"
TIMEOUT 120
"" at
OK atd* 99 *** 1 #
CONNECT

 

三、修改ini.rc脚本

再修改init.rc前一定要先编译好源码,因为修改的是编译后生成的文件,因为改源文件有点麻烦。

打开 .../ out/target/product/sabresd_6dq/root/init.rc按照如下红色框进行修改

\

添加修改新加入文件权限的语句。

\

注:/dev/ttyUSB2是模块USB串口的AT口。

到此,就可以进行打包 make snod ,烧写镜像进行测试了。

可以用命令:logcat -b radio 查看rild 输出的信息进行调试。如果一切正常会打印出IP(或用命令 necfg 查看IP),有IP后用命令 ping 202.108.22.5 (百度IP)看下网络是否能ping通。如果能ping通证明自动拨号已经成功。此时用命令 ps查看rild和pppd进程号,用命令kill -9 <进程号> 杀死随便一个进程,在5s之后看看是不是该进程又运行了。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值