Chinaunix首页 | 论坛 | 博客
  • 博客访问: 3037369
  • 博文数量: 674
  • 博客积分: 17881
  • 博客等级: 上将
  • 技术积分: 4849
  • 用 户 组: 普通用户
  • 注册时间: 2010-03-17 10:15
文章分类

全部博文(674)

文章存档

2013年(34)

2012年(146)

2011年(197)

2010年(297)

分类: LINUX

2012-03-20 21:12:13

曾几何时在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中增加的代码
  1. #include <termios.h>

  2. static int urc_fd = -1; /* fd of the URC channel */
  3. static char s_URCBuffer[MAX_AT_RESPONSE+1];
  4. static char *s_URCBufferCur = s_URCBuffer;
  5. static pthread_t s_tid_reader_urc;
  1. static const char *urc_readline()
  2. {
  3.     ssize_t count;
  4.     char *p_read = NULL;
  5.     char *p_eol = NULL;
  6.     char *ret;
  7.     if (*s_URCBufferCur == '\0') {
  8.         s_URCBufferCur = s_URCBuffer;
  9.         *s_URCBufferCur = '\0';
  10.         p_read = s_URCBuffer;
  11.     } else {
  12.         while (*s_URCBufferCur == '\r' || *s_URCBufferCur == '\n')
  13.             s_URCBufferCur++;
  14.         p_eol = findNextEOL(s_URCBufferCur);
  15.         if (p_eol == NULL) {
  16.             size_t len;
  17.             len = strlen(s_URCBufferCur);
  18.             memmove(s_URCBuffer, s_URCBufferCur, len + 1);
  19.             p_read = s_URCBuffer + len;
  20.             s_URCBufferCur = s_URCBuffer;
  21.         }
  22.     }
  23.     while (p_eol == NULL) {
  24.         if (0 == MAX_AT_RESPONSE - (p_read - s_URCBuffer)) {
  25.             LOGE("ERROR: Input line exceeded buffer\n");
  26.             s_URCBufferCur = s_URCBuffer;
  27.             *s_URCBufferCur = '\0';
  28.             p_read = s_URCBuffer;
  29.         }
  30.         do {
  31.             count = read(urc_fd, p_read, MAX_AT_RESPONSE - (p_read - s_URCBuffer));
  32.         } while (count < 0 && errno == EINTR);
  33.         if (count > 0) {
  34.             AT_DUMP( "<< ", p_read, count );
  35.             s_readCount += count;
  36.             p_read[count] = '\0';
  37.             while (*s_URCBufferCur == '\r' || *s_URCBufferCur == '\n')
  38.                 s_URCBufferCur++;
  39.             p_eol = findNextEOL(s_URCBufferCur);
  40.             p_read += count;
  41.         } else if (count <= 0) {
  42.             if(count == 0) {
  43.                 LOGD("atchannel: EOF reached");
  44.             } else {
  45.                 LOGD("atchannel: read error %s", strerror(errno));
  46.             }
  47.             return NULL;
  48.         }
  49.     }
  50.     ret = s_URCBufferCur;
  51.     *p_eol = '\0';
  52.     s_URCBufferCur = p_eol + 1; 
  53.     LOGD("AT< %s\n", ret);
  54.     return ret;
  55. }

  56. static void *urc_readerLoop(void *arg)
  57. {
  58.     for (;;) {
  59.         const char * line;
  60.         line = urc_readline();
  61.         if (line == NULL) {
  62.             break;
  63.         }
  64.         if(isSMSUnsolicited(line)) {
  65.             char *line1;
  66.             const char *line2;
  67.             line1 = strdup(line);
  68.             line2 = readline();
  69.             if (line2 == NULL) {
  70.                 break;
  71.             }
  72.             if (s_unsolHandler != NULL) {
  73.                 s_unsolHandler (line1, line2);
  74.             }
  75.             free(line1);
  76.         } else {
  77.             processLine(line);
  78.         }
  79.     }
  80.     onReaderClosed();
  81.     return NULL;
  82. }
(3)修改ril/reference-ril/atchannel.c中的at_open函数,增加HUAWEI_EM770W宏控制的代码
  1.     pthread_attr_init (&attr);
  2.     pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);

  3. #ifdef HUAWEI_EM770W
  4.     int fd2 = -1;
  5.     while(fd2 < 0) {
  6.         fd2 = open ("/dev/ttyUSB2", O_RDWR);
  7.         if (fd2 < 0) {
  8.             perror ("opening URC interface. retrying...");
  9.             sleep(10);
  10.         }
  11.     }
  12.     if(fd2 > 0) {
  13.         urc_fd = fd2;
  14.         struct termios ios;
  15.         tcgetattr( fd2, &ios );
  16.         ios.c_lflag = 0;
  17.         tcsetattr( fd2, TCSANOW, &ios );
  18.     }
  19.     ret = pthread_create(&s_tid_reader_urc, &attr, urc_readerLoop, &attr);
  20.     if (ret < 0) {
  21.         perror ("pthread_create");
  22.         return -1;
  23.     }
  24. #endif

  25.     ret = pthread_create(&s_tid_reader, &attr, readerLoop, &attr);

(4)在ril/reference-ril/reference-ril.c中修改的代码

  1. +#include <cutils/properties.h>

  2. -#define PPP_TTY_PATH "/dev/omap_csmi_tty1"
  3. +#define PPP_TTY_PATH "/dev/ppp0"

  4. - /* Not muted */
  5. - at_send_command("AT+CMUT=0", NULL);
  6. + /* Set muted */
  7. + at_send_command("AT+CMUT=1", NULL);

  8. - if ( fd >= 0 && !memcmp( s_device_path, "/dev/ttyS", 9 ) ) {
  9. + if ( fd >= 0) {

  10.      /*    
  11.      asprintf(&cmd, "AT+CGDCONT=1,\"IP\",\"%s\",,0,0", apn);
  12.      //FIXME check for error here
  13.      err = at_send_command(cmd, NULL);
  14.      free(cmd);
  15.      // Set required QoS params to default
  16.      err = at_send_command("AT+CGQREQ=1", NULL);
  17.      // Set minimum QoS params to default
  18.      err = at_send_command("AT+CGQMIN=1", NULL);
  19.      // packet-domain event reporting
  20.      err = at_send_command("AT+CGEREP=1,0", NULL);
  21.      // Hangup anything that's happening there now
  22.      err = at_send_command("AT+CGACT=1,0", NULL);
  23.      // Start data on PDP context 1
  24.      err = at_send_command("ATD*99***1#", &p_response);
  25.      if (err < 0 || p_response->success == 0) {
  26.          goto error;
  27.      }
  28.      */
  29.    + property_set("ctl.start","pppd_gprs");
  30.    RIL_onRequestComplete(t, RIL_E_SUCCESS, response, sizeof(response));
  31.    at_response_free(p_response);
(5)在ril/rild/rild.c中修改的代码
  1. +#if 0
  2.      /* special override when in the emulator */
  3. -#if 1
  4.      {
  5.          static char* arg_overrides[3];
  6.          static char arg_device[32];

  7.  //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
  1. #!/system/bin/sh
  2. # An unforunate wrapper script
  3. PPPD_PID=
  4. /system/bin/setprop "net.gprs.ppp-exit" ""
  5. /system/bin/log -t pppd "Starting pppd"
  6. /system/bin/pppd call gprs $*
  7. PPPD_EXIT=$?
  8. PPPD_PID=$!
  9. /system/bin/log -t pppd "pppd exited with $PPPD_EXIT"
  10. /system/bin/setprop "net.gprs.ppp-exit" "$PPPD_EXIT"
  11. exit $PPPD_EXIT

2.gprs-connect-chat

  1. ABORT 'BUSY'
  2. ABORT 'NO CARRIER'
  3. ABORT 'ERROR'
  4. ABORT '+CME ERROR: 100'
  5. "" AT
  6. OK AT+CGDCONT=1,"IP","CMNET"
  7. OK AT+CGEQREQ=1,2,128,384,0,0,0,0,"0E0","0E0",,0,0
  8. OK AT
  9. OK AT
  10. OK ATS0=0
  11. OK AT
  12. OK AT
  13. OK ATDT*98*1#
  14. CONNECT
3.gprs-disconnect-chat
  1. ABORT OK
  2. ABORT BUSY
  3. ABORT DELAYED
  4. ABORT "NO ANSWER"
  5. ABORT "NO CARRIER"
  6. ABORT "NO DIALTONE"
  7. ABORT VOICE
  8. ABORT ERROR
  9. ABORT RINGING
  10. TIMEOUT 12
  11. "" \\k\\k\\k\\d+++ATH
  12. "NO CARRIER-AT-OK" ""
4.ip-up
  1. #!/system/bin/sh
  2. /system/bin/setprop "net.interfaces.defaultroute" "gprs"
  3. /system/bin/setprop "net.gprs.dns1" "$DNS1"
  4. /system/bin/setprop "net.gprs.dns2" "$DNS2"
  5. /system/bin/setprop "net.gprs.local-ip" "$IPLOCAL"
  6. /system/bin/setprop "net.gprs.remote-ip" "$IPREMOTE"
  7. exit 0
5.ip-down
  1. #!/system/bin/sh
  2. case $1 in
  3.     ppp1)
  4.   echo 0 > /proc/sys/net/ipv4/ip_forward;
  5.   ;;
  6. esac
  7. rm /etc/ppp/ppp*.pid
  8. # Use interface name if linkname is not available
  9. NAME=${LINKNAME:-"$1"}
  10. #/system/bin/setprop "net.dns1" ""
  11. #/system/bin/setprop "net.dns2" ""
  12. /system/bin/setprop "net.$NAME.local-ip" ""
  13. /system/bin/setprop "net.$NAME.remote-ip" ""

6.peers/gprs

  1. # This is pppd script, used Huawei EM770W3G Module
  2. # Usage: root>pppd call gprs
  3. /dev/ttyUSB0
  4. 115200
  5. crtscts
  6. modem
  7. debug
  8. nodetach
  9. usepeerdns
  10. noipdefault
  11. defaultroute
  12. user "cmnet"
  13. 0.0.0.0:0.0.0.0
  14. connect '/system/bin/chat -s -v -f /etc/ppp/gprs-connect-chat'
  15. #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

阅读(1516) | 评论(0) | 转发(1) |
给主人留下些什么吧!~~