Android 2.1下调试3G模块

来源:互联网 发布:在线编程 编辑:程序博客网 时间:2024/05/08 14:00
采用的是华为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拨号上网功能。

本篇文章来源于 Linux公社网站(www.linuxidc.com)  原文链接:http://www.linuxidc.com/Linux/2011-08/40117p2.htm

现在开始介绍如何实现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上网了。

0 0