【Android架构Telephony篇】数据业务(3)RILC 【转】

转自 https://blog.csdn.net/u013686019/article/details/53580878

三、Telephony数据业务的RILC层

现在,建立移动数据业务的任务通过socket传递给C/C++的RIL进行处理了:

  1. hardware\ril\rild\rild.c:

  2. int main(int argc, char **argv)

  3. {

  4. char libPath[PROPERTY_VALUE_MAX];

  5.  
  6. /**启动rild并解析/init.rc传进来的参数:

  7. * rild -l /system/lib/libreference-ril.so -- -d /dev/mux2

  8. */

  9. for (i = 1; i < argc ;) {

  10. if (0 == strcmp(argv[i], "-l") && (argc - i > 1)) {

  11. rilLibPath = argv[i + 1]; // ril库的路径,即"/system/lib/libreference-ril.so"

  12. i += 2;

  13. } else if (0 == strcmp(argv[i], "--")) {

  14. i++;

  15. hasLibArgs = 1;

  16. break;

  17. } else {

  18. usage(argv[0]);

  19. }

  20. }

  21.  
  22. /** 启动/system/bin/muxd,生成/dev/mux2节点 */

  23. startmux(bpID);

  24.  
  25. /** 加载传进来的/system/lib/libreference-ril.so库*/

  26. dlHandle = dlopen(rilLibPath, RTLD_NOW);

  27.  
  28. if (dlHandle == NULL) {

  29. RLOGE("dlopen failed: %s", dlerror());

  30. exit(-1);

  31. }

  32.  
  33. /** 事件监听 */

  34. RIL_startEventLoop();

  35.  
  36. rilInit = (const RIL_RadioFunctions *(*)(const struct RIL_Env *, int, char **))dlsym(dlHandle, "RIL_Init");

  37.  
  38. if (rilInit == NULL) {

  39. RLOGE("RIL_Init not defined or exported in %s\n", rilLibPath);

  40. exit(-1);

  41. }

  42.  
  43. /**注册事件回调函数

  44. *static struct RIL_Env s_rilEnv = {

  45. * RIL_onRequestComplete,

  46. * RIL_onUnsolicitedResponse,

  47. * RIL_requestTimedCallback

  48. *};

  49. */

  50. funcs = rilInit(&s_rilEnv, argc, rilArgv);

  51.  
  52. RIL_register(funcs);

  53. done:

  54. while(1) {

  55. sleep(0x00ffffff);

  56. }

  57. }


rild用来对RIL进行管理。对于不同的Modem,尤其不同无线通信技术(GSM、CDMA)之间,其差别是很大的;就算是同种技术的Modem,不同厂商也有区别。所以管理部分处理它们共通的业务逻辑,而把具体的实现交给xxxril.so。管理部分涉及文件:hardware\ril\libril\ril.cpp、hardware\ril\libril\ril_event.cpp,本文不对该部分进行分析。

 

 

/system/lib/libreference-ril.so库处理AT指令相关操作,/dev/mux2用作数据通道。我们知道,Modem和CPU之间是通过串口连接的,为了使AT指令和数据分开管理,系统对串口进行了复用。原理和实现参见:hardware/ril/gsm0710muxd/src/gsm0710muxd.c。

回到数据业务建立上面。在RIL的具体实现上,每一个操作,比如短信、电话、查询信号强度等都有独有的Request,且RILC/C++和RILJava定义一致。建立数据连接的Request是RIL_REQUEST_SETUP_DATA_CALL:

 
  1. frameworks\opt\telephony\src\java\com\android\internal\telephony\RIL.java

  2. RILRequest rr = RILRequest.obtain(RIL_REQUEST_SETUP_DATA_CALL, result);


响应该request的地方是:

 

 
  1. hardware\ril\reference-ril\reference-ril.c

  2. /**

  3. * Call from RIL to us to make a RIL_REQUEST

  4. */

  5. static void onRequest (int request, void *data, size_t datalen, RIL_Token t)

  6. {

  7. switch (request) {

  8. case RIL_REQUEST_SETUP_DATA_CALL:

  9. requestSetupDataCall(data, datalen, t);

  10. break;

  11. }

  12. }

  13.  
  14. static void requestSetupDataCall(void *data, size_t datalen, RIL_Token t)

  15. {

  16. char value[PROPERTY_VALUE_MAX] = "";

  17. char dns1[64]="";

  18. char dns2[64]="";

  19. char *cmd;

  20. int err,i,fd;

  21.  
  22. char *response[3] = { "ppp0", "IP", ip_address };

  23. RIL_Data_Call_Response_v6 response_v6;

  24. int mypppstatus;

  25. char strTemp[32];

  26. ATResponse *p_response = NULL;

  27. char *dialup = NULL;

  28. int cid = 1;

  29. int channel = 0;

  30. char dev_path[32];

  31. char gateway[PROPERTY_VALUE_MAX] = "";

  32.  
  33. const char* radioTechnology = ((const char**)data)[0];

  34. const char* profile = ((const char**)data)[1];

  35. const char* apn = ((const char**)data)[2];

  36. const char* user = ((const char**)data)[3];

  37. const char* password = ((const char**)data)[4];

  38. const char* authType = ((const char**)data)[5];

  39. char *auth_option;

  40. memset(ip_address,0,32);

  41. LOGD("radioTechnology:%s", radioTechnology);

  42. LOGD("profile:%s", profile);

  43. LOGD("apn:%s", apn);

  44. LOGD("user:%s", user);

  45. LOGD("password:%s", password);

  46. LOGD("authType:%s", authType);

  47.  
  48. /**

  49. * 数据业务建立的方式,依据不同Modem而有所不同

  50. */

  51. asprintf(&cmd, "/etc/ppp/call-pppd "

  52. "\"%s 115200\" " // $1

  53. "\"novj novjccomp noccp ipcp-accept-local ipcp-accept-remote\" " // $2

  54. "\"%s\" \"%s\" " // $3 $4

  55. "\"%s\" \"%s\" &", // $5 $6

  56. s_pppChannel, user, password, conn_script, disconn_script);

  57. ret = system(cmd);

  58. RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);

  59. at_response_free(p_response);

  60. }


据业务建立的方式,依据不同Modem而有所不同,对于PPP方式,Android下的一个实现是通过/etc/ppp/call-pppd脚本进行:

 

 
  1. /etc/ppp/call-pppd

  2. #!/system/bin/sh

  3. # An unforunate wrapper script

  4. # so that the exit code of pppd may be retrieved

  5.  
  6. #PPPD_PID=""

  7. PPPD_EXIT=""

  8.  
  9. /system/bin/setprop "net.gprs.ppp-exit" ""

  10.  
  11. /system/bin/pppd $1 debug defaultroute noauth nodetach nocrtscts $2 noipdefault usepeerdns user "$3" password "$4" connect "$5" disconnect "$6"

  12.  
  13. PPPD_EXIT=$?

  14. #PPPD_PID=$!

  15.  
  16. /system/bin/setprop "net.gprs.ppp-exit" "$PPPD_EXIT"


call-pppd脚本需要我们传进来6个参数,比如:

 
  1. asprintf(&cmd, "/etc/ppp/call-pppd "

  2. "\"%s 115200\" " // $1

  3. "\"novj novjccomp noccp ipcp-accept-local ipcp-accept-remote\" " // $2

  4. "\"%s\" \"%s\" " // $3 $4

  5. "\"%s\" \"%s\" &", // $5 $6

  6. s_pppChannel, user, password, conn_script, disconn_script);

  7. ret = system(cmd);


system(const char *command)函数用来执行call-pppd脚本,log:



至此,数据业务建立完成,通过ifconfig命令查看,生成由ppp设备节点。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值