1. 程式人生 > >Qualcomm平臺qcril初始化及訊息處理流程

Qualcomm平臺qcril初始化及訊息處理流程

        Android平臺不同廠商的AP側可以相同,但是Modem側肯定會有很大的差異,RIL層要解決一個問題就是適配不同廠商的Modem,為了達到相容性要求,Android在AP與Modem之間搭建了RILC的框架,由不同的Modem廠商將自己的協議連線到AP側。對於高通平臺來說,他的RILC就是QCRIL

        在Qcril中儲存一個靜態表單,裡面儲存了所有RILC中下發請求的ID以及相應的處理函式,表單內容簡要如下:
  1. static qcril_dispatch_table_entry_type qcril_event_table[] = {  
  2.     /* QCRIL_EVT_UIM_QMI_COMMAND_CALLBACK */
  3.     { QCRIL_REG_ALL_STATES( QCRIL_EVT_UIM_QMI_COMMAND_CALLBACK, qcril_uim_process_qmi_callback ) },  
  4.     /* QCRIL_EVT_UIM_QMI_INDICATION */
  5.     { QCRIL_REG_ALL_STATES( QCRIL_EVT_UIM_QMI_INDICATION, qcril_uim_process_qmi_indication ) },  
  6.     /* QCRIL_EVT_INTERNAL_UIM_VERIFY_PIN_COMMAND_CALLBACK */
  7.     { QCRIL_REG_ALL_STATES( QCRIL_EVT_INTERNAL_UIM_VERIFY_PIN_COMMAND_CALLBACK, qcril_uim_process_internal_command ) },  
  8.     /* QCRIL_EVT_INTERNAL_MMGSDI_CARD_POWER_UP */
  9.     { QCRIL_REG_ALL_STATES( QCRIL_EVT_INTERNAL_MMGSDI_CARD_POWER_UP, qcril_uim_process_internal_command ) },  
  10.     /* 0x90007 - QCRIL_EVT_HOOK_OEM_ENG_MODE   */
  11.     { QCRIL_REG_ALL_ACTIVE_STATES( QCRIL_EVT_HOOK_OEM_ENG_MODE, qcril_qmi_nas_request_eng_mode_info ) },  
  12.     /* 1 - RIL_REQUEST_GET_SIM_STATUS */
  13.     { QCRIL_REG_ALL_ACTIVE_STATES( RIL_REQUEST_GET_SIM_STATUS, qcril_uim_request_get_sim_status ) },  
  14.     /* 2 - RIL_REQUEST_ENTER_SIM_PIN */
  15.     { QCRIL_REG_ALL_ACTIVE_STATES( RIL_REQUEST_ENTER_SIM_PIN, qcril_uim_request_enter_pin ) },  
  16.     /* 105 - RIL_REQUEST_ISIM_AUTHENTICATION */
  17.     { QCRIL_REG_ALL_ACTIVE_STATES( RIL_REQUEST_ISIM_AUTHENTICATION, qcril_uim_request_isim_authenticate ) },  
  18. }  
        裡面每一項都包含兩個元素:事件ID和處理函式,在處理這些訊息時將會根據事件的ID查詢並執行相應的處理函式。

        比如,對於得到當前SIM卡狀態這個請求,對應的ID為RIL_REQUEST_GET_SIM_STATUS,而其處理函式為:qcril_uim_request_get_sim_status()

一、Qcril初始化流程

        初始化流程需要完成EventLoop訊息迴圈的建立、各個模組的初始化等工作。先看RILD部分。
  1. @rild.c  
  2. int main(int argc, char **argv)  
  3. {  
  4.     //動態載入reference-ril.so或者qcril.so
  5.     dlHandle = dlopen(rilLibPath, RTLD_NOW);  
  6.     //建立Loop監聽Socket事件
  7.     RIL_startEventLoop();  
  8.     rilInit = (const RIL_RadioFunctions *(*)(conststruct RIL_Env *, intchar **))dlsym(dlHandle, "RIL_Init");  
  9.     funcs = rilInit(&s_rilEnv, argc, rilArgv);  
  10.     RIL_register(funcs);  
  11. }  
        在RILD中會通過dlsym查詢ril庫中的RIL_Init函式地址,然後通過rilInit呼叫,對高通來說,該函式在qcril.c中:
  1. @qcril.c  
  2. const RIL_RadioFunctions *RIL_Init ( conststruct RIL_Env *env, int argc, char **argv) {  
  3.     //設定執行緒名字為rild
  4.     qmi_ril_set_thread_name( pthread_self() , QMI_RIL_QMI_RILD_THREAD_NAME);  
  5.     qmi_ril_fw_android_request_flow_control_init();  
  6.     //初始化unsol的eventlist pending_unsol_resp_list,為其分配記憶體
  7.     qmi_ril_init_android_unsol_resp_pending_list();  
  8.     //初始化接收Modem訊息的EventLoop
  9.     qcril_event_init();  
  10.     //初始化qcril中的各個模組
  11.     qcril_init();  
  12.     //開啟EventLoop
  13.     qcril_event_start();  
  14.     //其他初始化
  15.     qmi_ril_initiate_bootup();  
  16.     //返回RILD對RILC的介面函式
  17.     return &qcril_request_api[ QCRIL_DEFAULT_INSTANCE_ID ];  
  18. }  

        下面我們分別來分析上面的過程。

1.1、初始化EventLoop過程

        在Qcril中搭建了EventLoop迴圈用於檢測Modem上報的訊息,而EventLoop機制的初始化工作是在qcril_event_init()中完成的。
  1. @qcril_event.c  
  2. void qcril_event_init( void ) {  
  3.     pthread_attr_t attr;  
  4.     int ret;  
  5.     qcril_event.started = 0;  
  6. MI_RIL_UTF  
  7.     pthread_attr_init (&attr);  
  8.     ret = utf_pthread_create_handler(&qcril_event.tid, &attr, qcril_event_main, NULL);  
  9.     pthread_attr_destroy( &attr );  
  10.     pthread_attr_init (&attr);  
  11.     pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);  
  12.     //建立EventLoop執行緒,執行緒入口是qcril_event_main
  13.     ret = pthread_create(&qcril_event.tid, &attr, qcril_event_main, NULL);  
  14.     pthread_attr_destroy( &attr );  
  15.     //設定執行緒名字為"event"
  16.     qmi_ril_set_thread_name(qcril_event.tid, QMI_RIL_EVENT_THREAD_NAME);  
  17.     pthread_mutexattr_init( &qcril_event.activity_lock_mutex_atr );  
  18.     pthread_mutex_init( &qcril_event.activity_lock_mutex, &qcril_event.activity_lock_mutex_atr );  
  19.     while (qcril_event.started == 0)  
  20.     {  
  21.         pthread_cond_wait(&qcril_event_startupCond, &qcril_event.startup_mutex);  
  22.     }  
  23. }  
        在初始化過程中,通過pthread_create()函式建立了EventLoop執行緒,並且指出該執行緒的入口函式為qcril_event_main(),我們從執行緒的入口開始分析:
  1. staticvoid *qcril_event_main ( void *param) {  
  2.     int ret;  
  3.     int filedes[2];  
  4.     int n;  
  5.     fd_set rfds;  
  6.     qcril_event_type *ev;  
  7.     char buff[16];  
  8.     IxErrnoType err_no;  
  9.     int go_on;  
  10.     param = param;  
  11.     pthread_mutex_init(&qcril_event.list_mutex, NULL);  
  12.     //初始化qcril_event.list連結串列
  13.     qcril_event_init_list(&qcril_event.list);  
  14.     FD_ZERO(&qcril_event.readFds); /* Needed to use select() system call */
  15.     QCRIL_MUTEX_LOCK( &qcril_event.startup_mutex, "[Event Thread] qcril_event.startup_mutex" );  
  16.     qcril_event.started = 1;  
  17.     //建立管道
  18.     ret = pipe(filedes);  
  19.     qcril_event.fdWakeupRead = filedes[0];  
  20.     qcril_event.fdWakeupWrite = filedes[1];  
  21.     fcntl(qcril_event.fdWakeupRead, F_SETFL, O_NONBLOCK);  
  22.     FD_SET(qcril_event.fdWakeupRead, &qcril_event.readFds);  
  23.     pthread_cond_broadcast(&qcril_event_startupCond);  
  24.     while (qcril_event.started < 2)  
  25.     {  
  26.         //阻塞等待qcril初始化
  27.         pthread_cond_wait(&qcril_event_startupCond, &qcril_event.startup_mutex);  
  28.     }  
  29.     for (;;)  
  30.     {  
  31.         /* Make a local copy of read fd_set;  Don't ask why. */
  32.         memcpy(&rfds, &qcril_event.readFds, sizeof(fd_set));  
  33.         //阻塞等待接收內容
  34.         n = select(qcril_event.fdWakeupRead + 1, &rfds, NULL, NULL, NULL);  
  35.         if (n < 0)  
  36.         {  
  37.             if (errno == EINTR) continue;  
  38.             QCRIL_LOG_ERROR("QCRIL event select error (%d)", errno);  
  39.             qmi_ril_clear_thread_name(pthread_self());  
  40.             return NULL;  
  41.         }  
  42.         /* Empty the socket */
  43.         do
  44.         {  
  45.             //讀取內容
  46.             ret = read(qcril_event.fdWakeupRead, &buff, sizeof(buff));  
  47.         } while (ret > 0 || (ret < 0 && errno == EINTR));  
  48.         do
  49.         {  
  50.             i