曾几何时在Android2.1下调试3G模块,曾几何时模块厂商提供的库不能用,曾几何时只能用自己的库痛苦地调试...这一切的一切都已成往事,昔日的成功在毫无保留下成为浮云,该忘了忘记了,该记得也跟着忘记了。现如今再次调3G模块,却不知道以前如何调试,看来还是要记下来。
我采用的是华为EM770W模块,支持WCDMA网络,由于华为提供的库只支持Android2.2,所以用Android2.1就需要自己修改库源码。
1.修改linux内核
(1)make menuconfig:
Device Drivers --->
<*> OHCI HCD support
[*] Network device support --->
<*> PPP (point-to-point protocol) support
[*] PPP multilink support (EXPERIMENTAL)
[*] PPP filtering
<*> PPP support for async serial ports
<*> PPP support for sync tty ports
<*> PPP Deflate compression
<*> PPP BSD-Compress compression
<*> PPP MPPE compression (encryption) (EXPERIMENTAL)
<*> PPP over Ethernet (EXPERIMENTAL)
<*> PPP over L2TP (EXPERIMENTAL)
[*] USB support --->
<*> USB Serial Converter support --->
<*> USB driver for GSM and CDMA modems
(2)增加EM770W的VID和PID
修改驱动文件drivers/usb/serial/option.c,增加以下代码
#define EM770W_OPTION_VENDOR_ID 0x12d1
#define EM770W_OPTION_PRODUCT_COLT 0x1001
static struct usb_device_id option_ids[] = {
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COLT) },
…
{ USB_DEVICE(EM770W_OPTION_VENDOR_ID , EM770W_ OPTION_PRODUCT_COLT) },
}
驱动修改后插上3G模块,kernel运行后可在/dev下出现ttyUSB0、ttyUSB1 、ttyUSB2、ttyUSB3、ttyUSB4、ttyUSB5和ppp设备文件
2.修改RIL代码
(1)在ril/reference-ril/Android.mk添加一行:
LOCAL_CFLAGS += -DHUAWEI_EM770W
(2)在ril/reference-ril/atchannel.c中增加的代码
- #include <termios.h>
- static int urc_fd = -1; /* fd of the URC channel */
- static char s_URCBuffer[MAX_AT_RESPONSE+1];
- static char *s_URCBufferCur = s_URCBuffer;
- static pthread_t s_tid_reader_urc;
- static const char *urc_readline()
- {
- ssize_t count;
- char *p_read = NULL;
- char *p_eol = NULL;
- char *ret;
-
- if (*s_URCBufferCur == '\0') {
- s_URCBufferCur = s_URCBuffer;
- *s_URCBufferCur = '\0';
- p_read = s_URCBuffer;
- } else {
- while (*s_URCBufferCur == '\r' || *s_URCBufferCur == '\n')
- s_URCBufferCur++;
- p_eol = findNextEOL(s_URCBufferCur);
- if (p_eol == NULL) {
- size_t len;
- len = strlen(s_URCBufferCur);
- memmove(s_URCBuffer, s_URCBufferCur, len + 1);
- p_read = s_URCBuffer + len;
- s_URCBufferCur = s_URCBuffer;
- }
- }
- while (p_eol == NULL) {
- if (0 == MAX_AT_RESPONSE - (p_read - s_URCBuffer)) {
- LOGE("ERROR: Input line exceeded buffer\n");
- s_URCBufferCur = s_URCBuffer;
- *s_URCBufferCur = '\0';
- p_read = s_URCBuffer;
- }
- do {
- count = read(urc_fd, p_read, MAX_AT_RESPONSE - (p_read - s_URCBuffer));
- } while (count < 0 && errno == EINTR);
- if (count > 0) {
- AT_DUMP( "<< ", p_read, count );
- s_readCount += count;
- p_read[count] = '\0';
- while (*s_URCBufferCur == '\r' || *s_URCBufferCur == '\n')
- s_URCBufferCur++;
- p_eol = findNextEOL(s_URCBufferCur);
- p_read += count;
- } else if (count <= 0) {
- if(count == 0) {
- LOGD("atchannel: EOF reached");
- } else {
- LOGD("atchannel: read error %s", strerror(errno));
- }
- return NULL;
- }
- }
- ret = s_URCBufferCur;
- *p_eol = '\0';
- s_URCBufferCur = p_eol + 1;
- LOGD("AT< %s\n", ret);
- return ret;
- }
- static void *urc_readerLoop(void *arg)
- {
- for (;;) {
- const char * line;
- line = urc_readline();
- if (line == NULL) {
- break;
- }
- if(isSMSUnsolicited(line)) {
- char *line1;
- const char *line2;
- line1 = strdup(line);
- line2 = readline();
- if (line2 == NULL) {
- break;
- }
- if (s_unsolHandler != NULL) {
- s_unsolHandler (line1, line2);
- }
- free(line1);
- } else {
- processLine(line);
- }
- }
- onReaderClosed();
- return NULL;
- }
(3)修改ril/reference-ril/atchannel.c中的at_open函数,增加HUAWEI_EM770W宏控制的代码
- pthread_attr_init (&attr);
- pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
- #ifdef HUAWEI_EM770W
- int fd2 = -1;
- while(fd2 < 0) {
- fd2 = open ("/dev/ttyUSB2", O_RDWR);
- if (fd2 < 0) {
- perror ("opening URC interface. retrying...");
- sleep(10);
- }
- }
- if(fd2 > 0) {
- urc_fd = fd2;
- struct termios ios;
- tcgetattr( fd2, &ios );
- ios.c_lflag = 0;
- tcsetattr( fd2, TCSANOW, &ios );
- }
- ret = pthread_create(&s_tid_reader_urc, &attr, urc_readerLoop, &attr);
- if (ret < 0) {
- perror ("pthread_create");
- return -1;
- }
- #endif
- ret = pthread_create(&s_tid_reader, &attr, readerLoop, &attr);
(4)在ril/reference-ril/reference-ril.c中修改的代码
- +#include <cutils/properties.h>
- -#define PPP_TTY_PATH "/dev/omap_csmi_tty1"
- +#define PPP_TTY_PATH "/dev/ppp0"
- - /* Not muted */
- - at_send_command("AT+CMUT=0", NULL);
- + /* Set muted */
- + at_send_command("AT+CMUT=1", NULL);
- - if ( fd >= 0 && !memcmp( s_device_path, "/dev/ttyS", 9 ) ) {
- + if ( fd >= 0) {
- /*
- asprintf(&cmd, "AT+CGDCONT=1,\"IP\",\"%s\",,0,0", apn);
- //FIXME check for error here
- err = at_send_command(cmd, NULL);
- free(cmd);
- // Set required QoS params to default
- err = at_send_command("AT+CGQREQ=1", NULL);
- // Set minimum QoS params to default
- err = at_send_command("AT+CGQMIN=1", NULL);
- // packet-domain event reporting
- err = at_send_command("AT+CGEREP=1,0", NULL);
- // Hangup anything that's happening there now
- err = at_send_command("AT+CGACT=1,0", NULL);
- // Start data on PDP context 1
- err = at_send_command("ATD*99***1#", &p_response);
- if (err < 0 || p_response->success == 0) {
- goto error;
- }
- */
- + property_set("ctl.start","pppd_gprs");
- RIL_onRequestComplete(t, RIL_E_SUCCESS, response, sizeof(response));
- at_response_free(p_response);
(5)在ril/rild/rild.c中修改的代码
- +#if 0
- /* special override when in the emulator */
- -#if 1
- {
- static char* arg_overrides[3];
- static char arg_device[32];
- //switchUser();
前面讲到了如何让修改kernel驱动和ril层代码,接下来还需要增加ppp拨号以及设备文件和服务属性。
1.修改init.gprs-pppd属性
对应文件:system/core/include/private/android_filesystem_config.h
在static struct fs_path_config android_files[]中增加:
+ { 00777, AID_ROOT, AID_SHELL, "system/etc/init.gprs-pppd" },
2.修改ttyUSB设备属性
对应文件:system/core/init/devices.c
在static struct perms_ devperms[]中增加:
+ { "/dev/ttyUSB0", 0777, AID_RADIO, AID_RADIO, 0 },
+ { "/dev/ttyUSB1", 0777, AID_RADIO, AID_RADIO, 0 },
+ { "/dev/ttyUSB2", 0777, AID_RADIO, AID_RADIO, 0 },
+ { "/dev/ttyUSB3", 0777, AID_RADIO, AID_RADIO, 0 },
+ { "/dev/ttyUSB4", 0777, AID_RADIO, AID_RADIO, 0 },
+ { "/dev/ttyUSB5", 0777, AID_RADIO, AID_RADIO, 0 },
3.修改pppd_gprs服务属性
对应文件:system/core/init/property_service.c
在property_perms[]中增加:
+ { "net.ppp0.", AID_RADIO, 0 },
在control_perms[]中增加:
+ { "pppd_gprs",AID_RADIO, AID_LOG },
4.修改init.rc文件
service ril-daemon /system/bin/rild -l libreference-ril.so -- -d /dev/ttyUSB2
socket rild stream 660 root radio
socket rild-debug stream 660 radio system
user root
group radio cache inet misc
service pppd_gprs /etc/ppp/init.gprs-pppd /dev/ttyUSB0
user root
group radio cache inet misc
disabled
现在3G模块上电后就可以注册上网络,并能实现电话功能,接下来还要实现gprs拨号上网功能。
现在开始介绍如何实现ppp拨号上网。在/system/etc下创建ppp目录,并在ppp目录下创建以下文件:
1.init.gprs-pppd
- #!/system/bin/sh
- # An unforunate wrapper script
- PPPD_PID=
- /system/bin/setprop "net.gprs.ppp-exit" ""
- /system/bin/log -t pppd "Starting pppd"
- /system/bin/pppd call gprs $*
- PPPD_EXIT=$?
- PPPD_PID=$!
- /system/bin/log -t pppd "pppd exited with $PPPD_EXIT"
- /system/bin/setprop "net.gprs.ppp-exit" "$PPPD_EXIT"
- exit $PPPD_EXIT
2.gprs-connect-chat
- ABORT 'BUSY'
- ABORT 'NO CARRIER'
- ABORT 'ERROR'
- ABORT '+CME ERROR: 100'
- "" AT
- OK AT+CGDCONT=1,"IP","CMNET"
- OK AT+CGEQREQ=1,2,128,384,0,0,0,0,"0E0","0E0",,0,0
- OK AT
- OK AT
- OK ATS0=0
- OK AT
- OK AT
- OK ATDT*98*1#
- CONNECT
3.gprs-disconnect-chat
- ABORT OK
- ABORT BUSY
- ABORT DELAYED
- ABORT "NO ANSWER"
- ABORT "NO CARRIER"
- ABORT "NO DIALTONE"
- ABORT VOICE
- ABORT ERROR
- ABORT RINGING
- TIMEOUT 12
- "" \\k\\k\\k\\d+++ATH
- "NO CARRIER-AT-OK" ""
4.ip-up
- #!/system/bin/sh
- /system/bin/setprop "net.interfaces.defaultroute" "gprs"
- /system/bin/setprop "net.gprs.dns1" "$DNS1"
- /system/bin/setprop "net.gprs.dns2" "$DNS2"
- /system/bin/setprop "net.gprs.local-ip" "$IPLOCAL"
- /system/bin/setprop "net.gprs.remote-ip" "$IPREMOTE"
- exit 0
5.ip-down
- #!/system/bin/sh
- case $1 in
- ppp1)
- echo 0 > /proc/sys/net/ipv4/ip_forward;
- ;;
- esac
- rm /etc/ppp/ppp*.pid
- # Use interface name if linkname is not available
- NAME=${LINKNAME:-"$1"}
- #/system/bin/setprop "net.dns1" ""
- #/system/bin/setprop "net.dns2" ""
- /system/bin/setprop "net.$NAME.local-ip" ""
- /system/bin/setprop "net.$NAME.remote-ip" ""
6.peers/gprs
- # This is pppd script, used Huawei EM770W3G Module
- # Usage: root>pppd call gprs
- /dev/ttyUSB0
- 115200
- crtscts
- modem
- debug
- nodetach
- usepeerdns
- noipdefault
- defaultroute
- user "cmnet"
- 0.0.0.0:0.0.0.0
- connect '/system/bin/chat -s -v -f /etc/ppp/gprs-connect-chat'
- #disconnect '/bin/chat -v -f /etc/ppp/gprs-disconnect-chat'
文件创建好后只要在Android启动后进入"Settings(设置)"->"Wireless controls(无线网络)"->"Mobile networks(移动网络)"->"Access Points Name(接入点)",按Menu键弹出界面选择"New APN(新接入点)",一般情况下只要填写"Name(名称)"和"APN"两项即可,"MCC"和"MNC"会随着运行商网络注册成功后自动生成,最后保存。现在就可以通过gprs上网了。
http://blog.chinaunix.net/uid-25369701-id-203378.html