Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1070179
  • 博文数量: 403
  • 博客积分: 10272
  • 博客等级: 上将
  • 技术积分: 4407
  • 用 户 组: 普通用户
  • 注册时间: 2012-02-24 14:22
文章分类

全部博文(403)

文章存档

2012年(403)

分类: 嵌入式

2012-03-25 19:33:21

1. RIL(RadioInterface Layer) Architecture

RIL is short name for Radio Layer Interface. The rilis divided into three rild, libril, reference-ril. Rild is a executable file,it can be run in linux, and call by init.rc script to run the rild. RIL sourcecode is under the directory as following:root/hardril/ril. The followingpicture show the position of RIL and function for other application.

 

Picture 1 RIL Architecture

 

In the picture, there is some information need to show. Vendor ril may be implementedby MODEM manufactory.They may use thefollowing method to implement.

a) Using AT command, this means that the commandshould be sent via COM or UART. So the command may sent by tty device. Thisimplementation recommend by GOOGLE, so in the Android source code, the ril isimplemented by this way.

b) Using message queue, this depending on themanufactory, they will develop their own method to handle the message. Butanyway, they may use the process communication, such as share memory(MemoryMapping), IO pipe(A pipe connect the AP and MODEM). This method need moredeveloping time due to we can not use the modem supporting AT command.(Themodem are supported the AT commands in 3GPP 27.007, the protocols is standardizedby 3GPP). The following, we will descript the ril boot using AT command method.

2. RILProgress of Booting up

The rildis executed by script init.rc. You can find the script in the directory/system/core/rootdir/init.rc. When you open the script and search the key words“rild”, you can findthe following code.

 

[plain] view plaincopy
  1. service ril-daemon /system/bin/rild  
  2.     class main  
  3.     socket rild stream 660 root radio  
  4.     socket rild-debug stream 660 radio system  
  5.     user root  
  6.     group radio cache inet misc audio sdcard_rw log  

So the rildwill be compile as an executable program and run by linux system. Now we wantto descript the RILD work.

a)   Parameters work.

In this work, itwant to check the parameters assigned by running the command rild. It may usetty mode or other method progress communication. For example, when we use ATcommand, we may use the –d parameters to inform the system using which device.

b)   OpenLib work.

This workis want to gainthe directory of the reference ril. This step is preparing for work four(Get function RIL_Init by opendl and dlsym). Only when we get the path of reference ril, wecan open itdynamically. This method will reduce the opportunity of coincidence(相一致的,相投的).So the modem manufactory can match the AP code easily.

c)   RIL_startEventLoop work.

This work is want to get theril event loop for ap request. In the source code, you can see this ret = pthread_create(&s_tid_dispatch,&attr, eventLoop, NULL);In linux, this is want to create a new thread to runfunction eventloop. In function event loop, it want to open multi AT channel, ril_event_initfunction is initialize three list(readFds, timer_list, pending_list).

  1. static void *  
  2. eventLoop(void *param) {  
  3.     int ret;  
  4.     int filedes[2];  
  5.     ril_event_init();  
  6.     pthread_mutex_lock(&s_startupMutex);  
  7.     s_started = 1;  
  8.     pthread_cond_broadcast(&s_startupCond);  
  9.     pthread_mutex_unlock(&s_startupMutex);  
  10.     ret = pipe(filedes);  
  11.     if (ret < 0) {  
  12.         ALOGE("Error in pipe() errno:%d", errno);  
  13.         return NULL;  
  14.     }  
  15.     s_fdWakeupRead = filedes[0];  
  16.     s_fdWakeupWrite = filedes[1];  
  17.     fcntl(s_fdWakeupRead, F_SETFL, O_NONBLOCK);  
  18.     ril_event_set (&s_wakeupfd_event, s_fdWakeupRead, true,  
  19.                 processWakeupCallback, NULL);  
  20.     rilEventAddWakeup (&s_wakeupfd_event);  
  21.     // Only returns on error  
  22.     ril_event_loop();  
  23.     ALOGE ("error in event_loop_base errno:%d", errno);  
  24.     // kill self to restart on error  
  25.     kill(0, SIGKILL);  
  26.     return NULL;  
  27. }  

You can see that the code has open two file(readand write), so the simple code is only support single channel, however, in ourdevice, there are more then five channels to support multi operation, forexample, you want to data service to access the website, at meanwhile, you wantto get a ring call or send MMS. Single channel is only a simple code, not inreal time.

d)  Get function RIL_Init byopendl and dlsym


This work is only to gain the function RIL_Init address and call it. The function RIL_Init is inthe reference ril. After entering this work, we will use the first work result(Parameters),and then run the mainloop function.

  1. const RIL_RadioFunctions *RIL_Init(const struct RIL_Env *env, int argc, char **argv)  
  2. {  
  3.     int ret;  
  4.     int fd = -1;  
  5.     int opt;  
  6.     pthread_attr_t attr;  
  7.     s_rilenv = env;  
  8.     while ( -1 != (opt = getopt(argc, argv, "p:d:s:"))) {  
  9.         switch (opt) {  
  10.             case 'p':  
  11.                 s_port = atoi(optarg);  
  12.                 if (s_port == 0) {  
  13.                     usage(argv[0]);  
  14.                     return NULL;  
  15.                 }  
  16.                 ALOGI("Opening loopback port %d\n", s_port);  
  17.             break;  
  18.             case 'd':  
  19.                 s_device_path = optarg;  
  20.                 ALOGI("Opening tty device %s\n", s_device_path);  
  21.             break;  
  22.             case 's':  
  23.                 s_device_path   = optarg;  
  24.                 s_device_socket = 1;  
  25.                 ALOGI("Opening socket %s\n", s_device_path);  
  26.             break;  
  27.             default:  
  28.                 usage(argv[0]);  
  29.                 return NULL;  
  30.         }  
  31.     }  
  32.     if (s_port < 0 && s_device_path == NULL) {  
  33.         usage(argv[0]);  
  34.         return NULL;  
  35.     }  
  36.     pthread_attr_init (&attr);  
  37.     pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);  
  38.     ret = pthread_create(&s_tid_mainloop, &attr, mainLoop, NULL);  
  39.     return &s_callbacks;  
  40. }  

In function mainloop, you can know that it is a dead loop. The code willcheck the socket port and connect to ril.java. if the device is simulator, itwill connect to qemud, otherwise it will connect to ril.java. After all is bedone, will open AT channel and give the callback function onUnsolicited, whenthere are some unsolicited messages from modem.

  1. static void *  
  2. mainLoop(void *param)  
  3. {  
  4. int fd;  
  5. int ret;  
  6.     AT_DUMP("== ""entering mainLoop()", -1 );  
  7.     at_set_on_reader_closed(onATReaderClosed);  
  8.     at_set_on_timeout(onATTimeout);  
  9.     for (;;) {  
  10.         fd = -1;  
  11.         while  (fd < 0) {  
  12.             if (s_port > 0) {  
  13.                 fd = socket_loopback_client(s_port, SOCK_STREAM);  
  14.             } else if (s_device_socket) {  
  15.                 if (!strcmp(s_device_path, "/dev/socket/qemud")) {  
  16.                     /* Before trying to connect to /dev/socket/qemud (which is 
  17.                      * now another "legacy" way of communicating with the 
  18.                      * emulator), we will try to connecto to gsm service via 
  19.                      * qemu pipe. */  
  20.                     fd = qemu_pipe_open("qemud:gsm");  
  21.                     if (fd < 0) {  
  22.                         /* Qemu-specific control socket */  
  23.                         fd = socket_local_client( "qemud",  
  24.                                                   ANDROID_SOCKET_NAMESPACE_RESERVED,  
  25.                                                   SOCK_STREAM );  
  26.                         if (fd >= 0 ) {  
  27.                             char  answer[2];  
  28.                             if ( write(fd, "gsm", 3) != 3 ||  
  29.                                  read(fd, answer, 2) != 2 ||  
  30.                                  memcmp(answer, "OK", 2) != 0)  
  31.                             {  
  32.                                 close(fd);  
  33.                                 fd = -1;  
  34.                             }  
  35.                        }  
  36.                     }  
  37.                 }  
  38.                 else  
  39.                     fd = socket_local_client( s_device_path,  
  40.                                             ANDROID_SOCKET_NAMESPACE_FILESYSTEM,  
  41.                                             SOCK_STREAM );  
  42.             } else if (s_device_path != NULL) {  
  43.                 fd = open (s_device_path, O_RDWR);  
  44.                 if ( fd >= 0 && !memcmp( s_device_path, "/dev/ttyS", 9 ) ) {  
  45.                     /* disable echo on serial ports */  
  46.                     struct termios  ios;  
  47.                     tcgetattr( fd, &ios );  
  48.                     ios.c_lflag = 0;  /* disable ECHO, ICANON, etc... */  
  49.                     tcsetattr( fd, TCSANOW, &ios );  
  50.                 }  
  51.             }  
  52.   
  53.             if (fd < 0) {  
  54.                 perror ("opening AT interface. retrying...");  
  55.                 sleep(10);  
  56.                 /* never returns */  
  57.             }  
  58.         }  
  59.   
  60.         s_closed = 0;  
  61.         ret = at_open(fd, onUnsolicited);  
  62.   
  63.         if (ret < 0) {  
  64.             ALOGE ("AT error %d on at_open\n", ret);  
  65.             return 0;  
  66.         }  
  67.         RIL_requestTimedCallback(initializeCallback, NULL, &TIMEVAL_0);  
  68.         // Give initializeCallback a chance to dispatched, since  
  69.         // we don't presently have a cancellation mechanism  
  70.         sleep(1);  
  71.         waitForClose();  
  72.         ALOGI("Re-opening after close");  
  73.     }  
  74. }  
e)   RIL_register

This work isto register all the AP request and callback, so when the function has been finished,we can return to ril.java. The event includes solicited and unsolicitedrequest.

  1. extern "C" void  
  2. RIL_register (const RIL_RadioFunctions *callbacks) {  
  3.     int ret;  
  4.     int flags;  
  5.   
  6.     if (callbacks == NULL) {  
  7.         ALOGE("RIL_register: RIL_RadioFunctions * null");  
  8.         return;  
  9.     }  
  10.     if (callbacks->version < RIL_VERSION_MIN) {  
  11.         ALOGE("RIL_register: version %d is to old, min version is %d",  
  12.              callbacks->version, RIL_VERSION_MIN);  
  13.         return;  
  14.     }  
  15.     if (callbacks->version > RIL_VERSION) {  
  16.         ALOGE("RIL_register: version %d is too new, max version is %d",  
  17.              callbacks->version, RIL_VERSION);  
  18.         return;  
  19.     }  
  20.     ALOGE("RIL_register: RIL version %d", callbacks->version);  
  21.   
  22.     if (s_registerCalled > 0) {  
  23.         ALOGE("RIL_register has been called more than once. "  
  24.                 "Subsequent call ignored");  
  25.         return;  
  26.     }  
  27.   
  28.     memcpy(&s_callbacks, callbacks, sizeof (RIL_RadioFunctions));  
  29.   
  30.     s_registerCalled = 1;  
  31.   
  32.     // Little self-check  
  33.   
  34.     for (int i = 0; i < (int)NUM_ELEMS(s_commands); i++) {  
  35.         assert(i == s_commands[i].requestNumber);  
  36.     }  
  37.   
  38.     for (int i = 0; i < (int)NUM_ELEMS(s_unsolResponses); i++) {  
  39.         assert(i + RIL_UNSOL_RESPONSE_BASE  
  40.                 == s_unsolResponses[i].requestNumber);  
  41.     }  
  42.   
  43.     // New rild impl calls RIL_startEventLoop() first  
  44.     // old standalone impl wants it here.  
  45.   
  46.     if (s_started == 0) {  
  47.         RIL_startEventLoop();  
  48.     }  
  49.   
  50.     // start listen socket  
  51.   
  52. #if 0  
  53.     ret = socket_local_server (SOCKET_NAME_RIL,  
  54.             ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM);  
  55.   
  56.     if (ret < 0) {  
  57.         ALOGE("Unable to bind socket errno:%d", errno);  
  58.         exit (-1);  
  59.     }  
  60.     s_fdListen = ret;  
  61.   
  62. #else  
  63.     s_fdListen = android_get_control_socket(SOCKET_NAME_RIL);  
  64.     if (s_fdListen < 0) {  
  65.         ALOGE("Failed to get socket '" SOCKET_NAME_RIL "'");  
  66.         exit(-1);  
  67.     }  
  68.   
  69.     ret = listen(s_fdListen, 4);  
  70.   
  71.     if (ret < 0) {  
  72.         ALOGE("Failed to listen on control socket '%d': %s",  
  73.              s_fdListen, strerror(errno));  
  74.         exit(-1);  
  75.     }  
  76. #endif  
  77.   
  78.   
  79.     /* note: non-persistent so we can accept only one connection at a time */  
  80.     ril_event_set (&s_listen_event, s_fdListen, false,  
  81.                 listenCallback, NULL);  
  82.   
  83.     rilEventAddWakeup (&s_listen_event);  
  84.   
  85. #if 1  
  86.     // start debug interface socket  
  87.   
  88.     s_fdDebug = android_get_control_socket(SOCKET_NAME_RIL_DEBUG);  
  89.     if (s_fdDebug < 0) {  
  90.         ALOGE("Failed to get socket '" SOCKET_NAME_RIL_DEBUG "' errno:%d", errno);  
  91.         exit(-1);  
  92.     }  
  93.   
  94.     ret = listen(s_fdDebug, 4);  
  95.   
  96.     if (ret < 0) {  
  97.         ALOGE("Failed to listen on ril debug socket '%d': %s",  
  98.              s_fdDebug, strerror(errno));  
  99.         exit(-1);  
  100.     }  
  101.   
  102.     ril_event_set (&s_debug_event, s_fdDebug, true,  
  103.                 debugCallback, NULL);  
  104.   
  105.     rilEventAddWakeup (&s_debug_event);  
  106. #endif  
  107.   
  108. }  
阅读(2921) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~