Qualcomm平臺qcril初始化及訊息處理流程
阿新 • • 發佈:2019-02-14
Android平臺不同廠商的AP側可以相同,但是Modem側肯定會有很大的差異,RIL層要解決一個問題就是適配不同廠商的Modem,為了達到相容性要求,Android在AP與Modem之間搭建了RILC的框架,由不同的Modem廠商將自己的協議連線到AP側。對於高通平臺來說,他的RILC就是QCRIL。
在Qcril中儲存一個靜態表單,裡面儲存了所有RILC中下發請求的ID以及相應的處理函式,表單內容簡要如下:- static qcril_dispatch_table_entry_type qcril_event_table[] = {
-
/* QCRIL_EVT_UIM_QMI_COMMAND_CALLBACK */
- { QCRIL_REG_ALL_STATES( QCRIL_EVT_UIM_QMI_COMMAND_CALLBACK, qcril_uim_process_qmi_callback ) },
- /* QCRIL_EVT_UIM_QMI_INDICATION */
- { QCRIL_REG_ALL_STATES( QCRIL_EVT_UIM_QMI_INDICATION, qcril_uim_process_qmi_indication ) },
-
/* QCRIL_EVT_INTERNAL_UIM_VERIFY_PIN_COMMAND_CALLBACK */
- { QCRIL_REG_ALL_STATES( QCRIL_EVT_INTERNAL_UIM_VERIFY_PIN_COMMAND_CALLBACK, qcril_uim_process_internal_command ) },
- /* QCRIL_EVT_INTERNAL_MMGSDI_CARD_POWER_UP */
- { QCRIL_REG_ALL_STATES( QCRIL_EVT_INTERNAL_MMGSDI_CARD_POWER_UP, qcril_uim_process_internal_command ) },
-
/* 0x90007 - QCRIL_EVT_HOOK_OEM_ENG_MODE */
- { QCRIL_REG_ALL_ACTIVE_STATES( QCRIL_EVT_HOOK_OEM_ENG_MODE, qcril_qmi_nas_request_eng_mode_info ) },
- /* 1 - RIL_REQUEST_GET_SIM_STATUS */
- { QCRIL_REG_ALL_ACTIVE_STATES( RIL_REQUEST_GET_SIM_STATUS, qcril_uim_request_get_sim_status ) },
- /* 2 - RIL_REQUEST_ENTER_SIM_PIN */
- { QCRIL_REG_ALL_ACTIVE_STATES( RIL_REQUEST_ENTER_SIM_PIN, qcril_uim_request_enter_pin ) },
- /* 105 - RIL_REQUEST_ISIM_AUTHENTICATION */
- { QCRIL_REG_ALL_ACTIVE_STATES( RIL_REQUEST_ISIM_AUTHENTICATION, qcril_uim_request_isim_authenticate ) },
- }
比如,對於得到當前SIM卡狀態這個請求,對應的ID為RIL_REQUEST_GET_SIM_STATUS,而其處理函式為:qcril_uim_request_get_sim_status()。
一、Qcril初始化流程
初始化流程需要完成EventLoop訊息迴圈的建立、各個模組的初始化等工作。先看RILD部分。- @rild.c
- int main(int argc, char **argv)
- {
- //動態載入reference-ril.so或者qcril.so
- dlHandle = dlopen(rilLibPath, RTLD_NOW);
- //建立Loop監聽Socket事件
- RIL_startEventLoop();
- rilInit = (const RIL_RadioFunctions *(*)(conststruct RIL_Env *, int, char **))dlsym(dlHandle, "RIL_Init");
- funcs = rilInit(&s_rilEnv, argc, rilArgv);
- RIL_register(funcs);
- }
- @qcril.c
- const RIL_RadioFunctions *RIL_Init ( conststruct RIL_Env *env, int argc, char **argv) {
- //設定執行緒名字為rild
- qmi_ril_set_thread_name( pthread_self() , QMI_RIL_QMI_RILD_THREAD_NAME);
- qmi_ril_fw_android_request_flow_control_init();
- //初始化unsol的eventlist pending_unsol_resp_list,為其分配記憶體
- qmi_ril_init_android_unsol_resp_pending_list();
- //初始化接收Modem訊息的EventLoop
- qcril_event_init();
- //初始化qcril中的各個模組
- qcril_init();
- //開啟EventLoop
- qcril_event_start();
- //其他初始化
- qmi_ril_initiate_bootup();
- //返回RILD對RILC的介面函式
- return &qcril_request_api[ QCRIL_DEFAULT_INSTANCE_ID ];
- }
下面我們分別來分析上面的過程。
1.1、初始化EventLoop過程
在Qcril中搭建了EventLoop迴圈用於檢測Modem上報的訊息,而EventLoop機制的初始化工作是在qcril_event_init()中完成的。- @qcril_event.c
- void qcril_event_init( void ) {
- pthread_attr_t attr;
- int ret;
- qcril_event.started = 0;
- MI_RIL_UTF
- pthread_attr_init (&attr);
- ret = utf_pthread_create_handler(&qcril_event.tid, &attr, qcril_event_main, NULL);
- pthread_attr_destroy( &attr );
- pthread_attr_init (&attr);
- pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
- //建立EventLoop執行緒,執行緒入口是qcril_event_main
- ret = pthread_create(&qcril_event.tid, &attr, qcril_event_main, NULL);
- pthread_attr_destroy( &attr );
- //設定執行緒名字為"event"
- qmi_ril_set_thread_name(qcril_event.tid, QMI_RIL_EVENT_THREAD_NAME);
- pthread_mutexattr_init( &qcril_event.activity_lock_mutex_atr );
- pthread_mutex_init( &qcril_event.activity_lock_mutex, &qcril_event.activity_lock_mutex_atr );
- while (qcril_event.started == 0)
- {
- pthread_cond_wait(&qcril_event_startupCond, &qcril_event.startup_mutex);
- }
- }
- staticvoid *qcril_event_main ( void *param) {
- int ret;
- int filedes[2];
- int n;
- fd_set rfds;
- qcril_event_type *ev;
- char buff[16];
- IxErrnoType err_no;
- int go_on;
- param = param;
- pthread_mutex_init(&qcril_event.list_mutex, NULL);
- //初始化qcril_event.list連結串列
- qcril_event_init_list(&qcril_event.list);
- FD_ZERO(&qcril_event.readFds); /* Needed to use select() system call */
- QCRIL_MUTEX_LOCK( &qcril_event.startup_mutex, "[Event Thread] qcril_event.startup_mutex" );
- qcril_event.started = 1;
- //建立管道
- ret = pipe(filedes);
- qcril_event.fdWakeupRead = filedes[0];
- qcril_event.fdWakeupWrite = filedes[1];
- fcntl(qcril_event.fdWakeupRead, F_SETFL, O_NONBLOCK);
- FD_SET(qcril_event.fdWakeupRead, &qcril_event.readFds);
- pthread_cond_broadcast(&qcril_event_startupCond);
- while (qcril_event.started < 2)
- {
- //阻塞等待qcril初始化
- pthread_cond_wait(&qcril_event_startupCond, &qcril_event.startup_mutex);
- }
- for (;;)
- {
- /* Make a local copy of read fd_set; Don't ask why. */
- memcpy(&rfds, &qcril_event.readFds, sizeof(fd_set));
- //阻塞等待接收內容
- n = select(qcril_event.fdWakeupRead + 1, &rfds, NULL, NULL, NULL);
- if (n < 0)
- {
- if (errno == EINTR) continue;
- QCRIL_LOG_ERROR("QCRIL event select error (%d)", errno);
- qmi_ril_clear_thread_name(pthread_self());
- return NULL;
- }
- /* Empty the socket */
- do
- {
- //讀取內容
- ret = read(qcril_event.fdWakeupRead, &buff, sizeof(buff));
- } while (ret > 0 || (ret < 0 && errno == EINTR));
- do
- {
- i