Qualcomm平台qcril初始化及消息处理流程
2016-09-05 13:51
1191 查看
本节主要来介绍Qcril的初始化流程以及消息在Qcril中如何传递。
Android平台不同厂商的AP侧可以相同,但是Modem侧肯定会有很大的差异,RIL层要解决一个问题就是适配不同厂商的Modem,为了达到兼容性要求,Android在AP与Modem之间搭建了RILC的框架,由不同的Modem厂商将自己的协议连接到AP侧。对于高通平台来说,他的RILC就是QCRIL。
在Qcril中保存一个静态表单,里面保存了所有RILC中下发请求的ID以及相应的处理函数,表单内容简要如下:
[cpp] view
plain copy
![](https://oscdn.geek-share.com/Uploads/Images/Content/201611/a7c8e286f463007e2a900848b93dd72c.png)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201611/9e12f1d3e499fc949c886e7c9e0484f9)
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 ) },
}
里面每一项都包含两个元素:事件ID和处理函数,在处理这些消息时将会根据事件的ID查找并执行相应的处理函数。
比如,对于得到当前SIM卡状态这个请求,对应的ID为RIL_REQUEST_GET_SIM_STATUS,而其处理函数为:qcril_uim_request_get_sim_status()。
[cpp] view
plain copy
![](https://oscdn.geek-share.com/Uploads/Images/Content/201611/a7c8e286f463007e2a900848b93dd72c.png)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201611/9e12f1d3e499fc949c886e7c9e0484f9)
@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 *(*)(const struct RIL_Env *, int, char **))dlsym(dlHandle, "RIL_Init");
funcs = rilInit(&s_rilEnv, argc, rilArgv);
RIL_register(funcs);
}
在RILD中会通过dlsym查找ril库中的RIL_Init函数地址,然后通过rilInit调用,对高通来说,该函数在qcril.c中:
[cpp] view
plain copy
![](https://oscdn.geek-share.com/Uploads/Images/Content/201611/a7c8e286f463007e2a900848b93dd72c.png)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201611/9e12f1d3e499fc949c886e7c9e0484f9)
@qcril.c
const RIL_RadioFunctions *RIL_Init ( const struct 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 ];
}
下面我们分别来分析上面的过程。
[cpp] view
plain copy
![](https://oscdn.geek-share.com/Uploads/Images/Content/201611/a7c8e286f463007e2a900848b93dd72c.png)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201611/9e12f1d3e499fc949c886e7c9e0484f9)
@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);
}
}
在初始化过程中,通过pthread_create()函数创建了EventLoop线程,并且指出该线程的入口函数为qcril_event_main(),我们从线程的入口开始分析:
[cpp] view
plain copy
![](https://oscdn.geek-share.com/Uploads/Images/Content/201611/a7c8e286f463007e2a900848b93dd72c.png)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201611/9e12f1d3e499fc949c886e7c9e0484f9)
static void *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
{
if ( ( NULL != ( ev = qcril_event.list.next ) && ( ev != &qcril_event.list ) ) )
{
qcril_event_remove_from_list( ev );
QCRIL_MUTEX_UNLOCK( &qcril_event.list_mutex, "[Event Thread] qcril_event.list_mutex" );
//处理Modem发送的请求
err_no = qcril_process_event( ev->instance_id, ev->modem_id, ev->event_id, ev->data, ev->datalen, ev->t );
QCRIL_MUTEX_LOCK( &qcril_event.list_mutex, "[Event Thread] qcril_event.list_mutex" );
if ( ev->data_must_be_freed && ev->data )
{
qcril_free( ev->data );
}
qcril_free( ev );
}
go_on = ( ( NULL != ( ev = qcril_event.list.next ) && ( ev != &qcril_event.list ) ) );
} while ( go_on );
}
qmi_ril_clear_thread_name(pthread_self());
return NULL;
}
在以上过程中,完成qcril_event.list链表的初始化,然后通过pthread_cond_wait进入阻塞状态,当被解锁后以及进入EventLoop循环,检测到事件后,通过qcril_process_event处理。
[cpp] view
plain copy
![](https://oscdn.geek-share.com/Uploads/Images/Content/201611/a7c8e286f463007e2a900848b93dd72c.png)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201611/9e12f1d3e499fc949c886e7c9e0484f9)
void qcril_init ( void) {
qcril_arb_init();
qcril_init_state();
qmi_ril_oem_hook_init();
qcril_db_init();
//初始化Event table
qcril_init_hash_table();
qcril_reqlist_init();
#ifdef FEATURE_QCRIL_PLMN_LIST
qcril_qmi_nas2_init();
#endif
qcril_request_suppress_list_init();
qmi_ril_qmi_client_pre_initialization_init();
qmi_ril_qmi_client_pre_initialization_acquire();
qcril_qmi_nas_dms_commmon_pre_init();
qcril_qmi_voice_pre_init();
#ifndef QMI_RIL_UTF
qcril_am_pre_init();
#else
qmi_ril_rat_enable_option = QMI_RIL_FTR_RAT_UNKNOWN;
qmi_ril_baseband_ftr_info = QMI_RIL_FTR_BASEBAND_UNKNOWN;
#endif
qcril_qmi_imsa_pre_init();
qcril_qmi_sms_pre_init();
QCRIL_LOG_FUNC_RETURN();
}
在这里对qcril的各个模块进行初始化。其中完成了很重要的一步就是将qcril_event_table表拷贝给qcril_hash_table,用于onRequest时对各种请求进行处理,我们来看具体操作:
[cpp] view
plain copy
![](https://oscdn.geek-share.com/Uploads/Images/Content/201611/a7c8e286f463007e2a900848b93dd72c.png)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201611/9e12f1d3e499fc949c886e7c9e0484f9)
static void qcril_init_hash_table( void ) {
uint32 reg_index, hash_index; /*!< index into hash table */
qcril_dispatch_table_entry_type *temp_entry_ptr;
for (reg_index = 0; reg_index < QCRIL_ARR_SIZE( qcril_event_table ); reg_index++)
{
hash_index = qcril_hash( qcril_event_table[reg_index].event_id, QCRIL_HT_ENTRIES_MAX, 0 );
if(hash_index < QCRIL_HT_ENTRIES_MAX)
{
if (qcril_hash_table[hash_index] == NULL)
{
//将qcril_event_table拷贝给qcril_hash_table
qcril_hash_table[hash_index] = &qcril_event_table[reg_index];
}
else
{
temp_entry_ptr = qcril_hash_table[hash_index];
while (temp_entry_ptr->next_ptr != NULL)
{
temp_entry_ptr = temp_entry_ptr->next_ptr;
}
temp_entry_ptr->next_ptr = &qcril_event_table[reg_index];
}
}
}
}
经过上面的拷贝,qcril_event_table中就保存了所有Request的id和处理方法。
这是在qcril_event_start()中完成的:
[cpp] view
plain copy
![](https://oscdn.geek-share.com/Uploads/Images/Content/201611/a7c8e286f463007e2a900848b93dd72c.png)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201611/9e12f1d3e499fc949c886e7c9e0484f9)
void qcril_event_start( void )
{
QCRIL_MUTEX_LOCK( &qcril_event.startup_mutex, "[Main Thread] qcril_event.startup_mutex" );
//更新状态
qcril_event.started = 2;
//释放EventLoop锁
pthread_cond_broadcast(&qcril_event_startupCond);
QCRIL_MUTEX_UNLOCK( &qcril_event.startup_mutex, "[Main Thread] qcril_event.startup_mutex" );
}
由于EventLoop被初始化后一直处于阻塞状态,所以在这里将started状态置为2后,对qcril_event_startupCond进行解锁,从而使EventLoop进入循环。
[cpp] view
plain copy
![](https://oscdn.geek-share.com/Uploads/Images/Content/201611/a7c8e286f463007e2a900848b93dd72c.png)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201611/9e12f1d3e499fc949c886e7c9e0484f9)
void qmi_ril_initiate_bootup(void)
{
qcril_setup_timed_callback( QCRIL_DEFAULT_INSTANCE_ID, QCRIL_DEFAULT_MODEM_ID, qmi_ril_bootup_perform_core_or_start_polling, NULL, NULL );
}
继续看qmi_ril_bootup_perform_core_or_start_polling()过程:
[cpp] view
plain copy
![](https://oscdn.geek-share.com/Uploads/Images/Content/201611/a7c8e286f463007e2a900848b93dd72c.png)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201611/9e12f1d3e499fc949c886e7c9e0484f9)
void qmi_ril_bootup_perform_core_or_start_polling(void * params)
{
RIL_Errno init_res;
int ril_version;
qcril_unsol_resp_params_type unsol_resp;
qmi_ril_main_thread_id = pthread_self();
qmi_ril_set_thread_name( qmi_ril_fw_get_main_thread_id(), QMI_RIL_QMI_MAIN_THREAD_NAME);
qmi_ril_wave_modem_status(); // this should result in "modem unavailble" report
qmi_ril_set_operational_status( QMI_RIL_GEN_OPERATIONAL_STATUS_INIT_PENDING ); // for consistency
qmi_ril_set_operational_status( QMI_RIL_GEN_OPERATIONAL_STATUS_INIT_ONGOING );
//qmi初始化
init_res = qmi_ril_core_init();
}
上面通过qmi_ril_core_init()完成了qmi的初始化:
[cpp] view
plain copy
![](https://oscdn.geek-share.com/Uploads/Images/Content/201611/a7c8e286f463007e2a900848b93dd72c.png)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201611/9e12f1d3e499fc949c886e7c9e0484f9)
RIL_Errno qmi_ril_core_init(void)
{
RIL_Errno res = RIL_E_GENERIC_FAILURE;
QCRIL_LOG_FUNC_ENTRY();
qcril_event_suspend(); // to ensure atomic init flow cross sub domains
do
{
//qcril client的初始化
res = qcril_qmi_client_init();
if ( RIL_E_SUCCESS != res )
break;
qcril_other_init();
qcril_uim_init();
qcril_gstk_qmi_init();
#ifndef QMI_RIL_UTF
qcril_data_init();
#endif
qcril_qmi_nas_dms_commmon_post_init();
if (qmi_ril_is_feature_supported(QMI_RIL_FEATURE_OEM_SOCKET))
{
QCRIL_LOG_INFO( "%s Init OEM socket thread", __FUNCTION__ );
qcril_qmi_oem_socket_init();
}
} while (FALSE);
qcril_event_resume();
QCRIL_LOG_FUNC_RETURN_WITH_RET(res);
return res;
}
在上面完成了qcril客户端的初始化过程:
[cpp] view
plain copy
![](https://oscdn.geek-share.com/Uploads/Images/Content/201611/a7c8e286f463007e2a900848b93dd72c.png)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201611/9e12f1d3e499fc949c886e7c9e0484f9)
RIL_Errno qcril_qmi_client_init( void )
{
qmi_client_error_type client_err = 0;
RIL_Errno res = RIL_E_GENERIC_FAILURE;
QCRIL_LOG_FUNC_ENTRY();
/* Start modem or vote for start modem */
qcril_qmi_modem_power_process_bootup();
memset(&client_info, 0, sizeof(client_info));
do
{
// QMI VOICE command callback
client_info.client_cbs[QCRIL_QMI_CLIENT_VOICE] = qcril_qmi_voice_command_cb;
// Get IDL service objects
client_info.service_objects[QCRIL_QMI_CLIENT_VOICE] = voice_get_service_object_v02();
client_info.service_objects[QCRIL_QMI_CLIENT_NAS] = nas_get_service_object_v01();
client_info.service_objects[QCRIL_QMI_CLIENT_WMS] = wms_get_service_object_v01();
client_info.service_objects[QCRIL_QMI_CLIENT_WDS] = wds_get_service_object_v01();
client_info.service_objects[QCRIL_QMI_CLIENT_DMS] = dms_get_service_object_v01();
/*client_info.service_objects[QCRIL_QMI_CLIENT_UIM] = uim_get_service_object_v01();*/
client_info.service_objects[QCRIL_QMI_CLIENT_PBM] = pbm_get_service_object_v01();
client_info.service_objects[QCRIL_QMI_CLIENT_RF_SAR] = sar_get_service_object_v01();
client_info.service_objects[QCRIL_QMI_CLIENT_IMS_VT] = ims_qmi_get_service_object_v01();
client_info.service_objects[QCRIL_QMI_CLIENT_IMS_PRESENCE] = imsp_get_service_object_v01();
client_info.service_objects[QCRIL_QMI_CLIENT_IMSA] = imsa_get_service_object_v01();
client_info.service_objects[QCRIL_QMI_CLIENT_RFPE] = rfrpe_get_service_object_v01();
client_info.service_objects[QCRIL_QMI_CLIENT_IMS_SETTING] = imss_get_service_object_v01();
if ( qmi_ril_get_process_instance_id() == QCRIL_DEFAULT_INSTANCE_ID )
{
client_info.service_objects[QCRIL_QMI_CLIENT_PDC] = pdc_get_service_object_v01();
}
pthread_mutexattr_init(&client_info.cache_lock_mtx_atr);
pthread_mutex_init(&client_info.cache_lock_mutex, &client_info.cache_lock_mtx_atr);
res = qcril_qmi_init_core_client_handles();
if (RIL_E_SUCCESS != res)
break;
} while (FALSE);
return res;
}
[cpp] view
plain copy
![](https://oscdn.geek-share.com/Uploads/Images/Content/201611/a7c8e286f463007e2a900848b93dd72c.png)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201611/9e12f1d3e499fc949c886e7c9e0484f9)
static const RIL_RadioFunctions qcril_request_api[] = {
{ RIL_VERSION, onRequest_rid, currentState_rid, onSupports_rid, onCancel_rid, getVersion_rid }
};
这样的话,在RIL中调用的接口就会进入该函数列表中进行处理。
以上就是qcril的初始化流程。
[cpp] view
plain copy
![](https://oscdn.geek-share.com/Uploads/Images/Content/201611/a7c8e286f463007e2a900848b93dd72c.png)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201611/9e12f1d3e499fc949c886e7c9e0484f9)
@qcril.c
static void onRequest_rid ( int request, void *data, size_t datalen, RIL_Token t)
{
onRequest( qmi_ril_process_instance_id, request, data, datalen, t );
}
然后进入onRequest()中继续处理:
[cpp] view
plain copy
![](https://oscdn.geek-share.com/Uploads/Images/Content/201611/a7c8e286f463007e2a900848b93dd72c.png)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201611/9e12f1d3e499fc949c886e7c9e0484f9)
static void onRequest ( qcril_instance_id_e_type instance_id, int request, void *data, size_t datalen, RIL_Token t) {
udit_result = qmi_ril_fw_android_request_render_execution( param.t,
param.event_id,
param.data,
param.datalen,
param.instance_id,
&log_dispatch_dedicated_thrd );
}
继续:
[cpp] view
plain copy
![](https://oscdn.geek-share.com/Uploads/Images/Content/201611/a7c8e286f463007e2a900848b93dd72c.png)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201611/9e12f1d3e499fc949c886e7c9e0484f9)
RIL_Errno qmi_ril_fw_android_request_render_execution( RIL_Token token, int android_request_id, void * android_request_data, int android_request_data_len, qcril_instance_id_e_type instance_id, int * is_dedicated_thread ) {
do
{
entry_ptr = NULL;
//从hash表中查找当前的Event
if ( qcril_hash_table_lookup( (uint32) param.event_id, &entry_ptr ) != E_SUCCESS || NULL == entry_ptr )
{
audit_result = RIL_E_REQUEST_NOT_SUPPORTED;
break;
}
if ( dedicated_thrd_req_lookup_val == param.event_id )
{ // deferred thread exec
}
else
{
//派发该Event
if ( qcril_dispatch_event( entry_ptr, ¶m ) == E_NOT_ALLOWED )
{
audit_result = RIL_E_RADIO_NOT_AVAILABLE;
break;
}
}
} while (FALSE);
return audit_result;
}
在上面的过程中,要先通过qcril_hash_table_lookup()函数查找当前的Event,如果没有找到当前的Request,就认为非法,找到之后,进入qcril_dispatch_event()中派发该Event:
[cpp] view
plain copy
![](https://oscdn.geek-share.com/Uploads/Images/Content/201611/a7c8e286f463007e2a900848b93dd72c.png)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201611/9e12f1d3e499fc949c886e7c9e0484f9)
IxErrnoType qcril_dispatch_event ( qcril_dispatch_table_entry_type *entry_ptr, qcril_request_params_type *params_ptr) {
if(params_ptr != NULL && (params_ptr->instance_id < QCRIL_MAX_INSTANCE_ID) )
{
// print the recieved date byte stream
qcril_qmi_print_hex(params_ptr->data, params_ptr->datalen);
instance_id = params_ptr->instance_id;
s_ptr = &qcril_state->info[ instance_id ];
modem_id = params_ptr->modem_id;
if (E_SUCCESS == res)
{
//处理当前Request
(entry_ptr->handler)(params_ptr, &ret);
if ( ret.pri_gw_sim_state_changed || ret.pri_cdma_sim_state_changed ||
ret.sec_gw_sim_state_changed || ret.sec_cdma_sim_state_changed ||
ret.ter_gw_sim_state_changed || ret.ter_cdma_sim_state_changed
)
{
qcril_state_transition( instance_id, modem_id, params_ptr->event_id, &ret );
}
}
}
else
{
}
return res;
}
上面的过程通过entry_ptr->handler调用当前Event的处理函数。这里的handler对应qcril_hash_table中的某一项。从上面1.2步骤中我们将qcril_event_table表中的数据拷贝给了qcril_hash_table,所以这里的handler可以理解为qcril_event_table中的某一项。
之后的流程就会进入到某个具体请求的处理函数中,比如对于得到当前SIM卡状态这个请求,其处理函数为:qcril_uim_request_get_sim_status()。
Android平台不同厂商的AP侧可以相同,但是Modem侧肯定会有很大的差异,RIL层要解决一个问题就是适配不同厂商的Modem,为了达到兼容性要求,Android在AP与Modem之间搭建了RILC的框架,由不同的Modem厂商将自己的协议连接到AP侧。对于高通平台来说,他的RILC就是QCRIL。
在Qcril中保存一个静态表单,里面保存了所有RILC中下发请求的ID以及相应的处理函数,表单内容简要如下:
[cpp] view
plain copy
![](https://oscdn.geek-share.com/Uploads/Images/Content/201611/a7c8e286f463007e2a900848b93dd72c.png)
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 ) },
}
里面每一项都包含两个元素:事件ID和处理函数,在处理这些消息时将会根据事件的ID查找并执行相应的处理函数。
比如,对于得到当前SIM卡状态这个请求,对应的ID为RIL_REQUEST_GET_SIM_STATUS,而其处理函数为:qcril_uim_request_get_sim_status()。
一、Qcril初始化流程
初始化流程需要完成EventLoop消息循环的建立、各个模块的初始化等工作。先看RILD部分。[cpp] view
plain copy
![](https://oscdn.geek-share.com/Uploads/Images/Content/201611/a7c8e286f463007e2a900848b93dd72c.png)
@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 *(*)(const struct RIL_Env *, int, char **))dlsym(dlHandle, "RIL_Init");
funcs = rilInit(&s_rilEnv, argc, rilArgv);
RIL_register(funcs);
}
在RILD中会通过dlsym查找ril库中的RIL_Init函数地址,然后通过rilInit调用,对高通来说,该函数在qcril.c中:
[cpp] view
plain copy
![](https://oscdn.geek-share.com/Uploads/Images/Content/201611/a7c8e286f463007e2a900848b93dd72c.png)
@qcril.c
const RIL_RadioFunctions *RIL_Init ( const struct 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()中完成的。[cpp] view
plain copy
![](https://oscdn.geek-share.com/Uploads/Images/Content/201611/a7c8e286f463007e2a900848b93dd72c.png)
@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);
}
}
在初始化过程中,通过pthread_create()函数创建了EventLoop线程,并且指出该线程的入口函数为qcril_event_main(),我们从线程的入口开始分析:
[cpp] view
plain copy
![](https://oscdn.geek-share.com/Uploads/Images/Content/201611/a7c8e286f463007e2a900848b93dd72c.png)
static void *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
{
if ( ( NULL != ( ev = qcril_event.list.next ) && ( ev != &qcril_event.list ) ) )
{
qcril_event_remove_from_list( ev );
QCRIL_MUTEX_UNLOCK( &qcril_event.list_mutex, "[Event Thread] qcril_event.list_mutex" );
//处理Modem发送的请求
err_no = qcril_process_event( ev->instance_id, ev->modem_id, ev->event_id, ev->data, ev->datalen, ev->t );
QCRIL_MUTEX_LOCK( &qcril_event.list_mutex, "[Event Thread] qcril_event.list_mutex" );
if ( ev->data_must_be_freed && ev->data )
{
qcril_free( ev->data );
}
qcril_free( ev );
}
go_on = ( ( NULL != ( ev = qcril_event.list.next ) && ( ev != &qcril_event.list ) ) );
} while ( go_on );
}
qmi_ril_clear_thread_name(pthread_self());
return NULL;
}
在以上过程中,完成qcril_event.list链表的初始化,然后通过pthread_cond_wait进入阻塞状态,当被解锁后以及进入EventLoop循环,检测到事件后,通过qcril_process_event处理。
1.2、初始化qcril各个模块
Qcril在接到RILC的请求后,需要根据请求的类型将消息派发给不同的负责模块,而qcril_init()就是完成各个模块的初始化工作。[cpp] view
plain copy
![](https://oscdn.geek-share.com/Uploads/Images/Content/201611/a7c8e286f463007e2a900848b93dd72c.png)
void qcril_init ( void) {
qcril_arb_init();
qcril_init_state();
qmi_ril_oem_hook_init();
qcril_db_init();
//初始化Event table
qcril_init_hash_table();
qcril_reqlist_init();
#ifdef FEATURE_QCRIL_PLMN_LIST
qcril_qmi_nas2_init();
#endif
qcril_request_suppress_list_init();
qmi_ril_qmi_client_pre_initialization_init();
qmi_ril_qmi_client_pre_initialization_acquire();
qcril_qmi_nas_dms_commmon_pre_init();
qcril_qmi_voice_pre_init();
#ifndef QMI_RIL_UTF
qcril_am_pre_init();
#else
qmi_ril_rat_enable_option = QMI_RIL_FTR_RAT_UNKNOWN;
qmi_ril_baseband_ftr_info = QMI_RIL_FTR_BASEBAND_UNKNOWN;
#endif
qcril_qmi_imsa_pre_init();
qcril_qmi_sms_pre_init();
QCRIL_LOG_FUNC_RETURN();
}
在这里对qcril的各个模块进行初始化。其中完成了很重要的一步就是将qcril_event_table表拷贝给qcril_hash_table,用于onRequest时对各种请求进行处理,我们来看具体操作:
[cpp] view
plain copy
![](https://oscdn.geek-share.com/Uploads/Images/Content/201611/a7c8e286f463007e2a900848b93dd72c.png)
static void qcril_init_hash_table( void ) {
uint32 reg_index, hash_index; /*!< index into hash table */
qcril_dispatch_table_entry_type *temp_entry_ptr;
for (reg_index = 0; reg_index < QCRIL_ARR_SIZE( qcril_event_table ); reg_index++)
{
hash_index = qcril_hash( qcril_event_table[reg_index].event_id, QCRIL_HT_ENTRIES_MAX, 0 );
if(hash_index < QCRIL_HT_ENTRIES_MAX)
{
if (qcril_hash_table[hash_index] == NULL)
{
//将qcril_event_table拷贝给qcril_hash_table
qcril_hash_table[hash_index] = &qcril_event_table[reg_index];
}
else
{
temp_entry_ptr = qcril_hash_table[hash_index];
while (temp_entry_ptr->next_ptr != NULL)
{
temp_entry_ptr = temp_entry_ptr->next_ptr;
}
temp_entry_ptr->next_ptr = &qcril_event_table[reg_index];
}
}
}
}
经过上面的拷贝,qcril_event_table中就保存了所有Request的id和处理方法。
1.3、开启EventLoop
在1.1中介绍过,初始化EventLoop时,在完成其链表的初始化过程后,通过pthread_cond_wait()将其阻塞,而现在要做的就是取消其阻塞状态,使其进入消息检测循环。这是在qcril_event_start()中完成的:
[cpp] view
plain copy
![](https://oscdn.geek-share.com/Uploads/Images/Content/201611/a7c8e286f463007e2a900848b93dd72c.png)
void qcril_event_start( void )
{
QCRIL_MUTEX_LOCK( &qcril_event.startup_mutex, "[Main Thread] qcril_event.startup_mutex" );
//更新状态
qcril_event.started = 2;
//释放EventLoop锁
pthread_cond_broadcast(&qcril_event_startupCond);
QCRIL_MUTEX_UNLOCK( &qcril_event.startup_mutex, "[Main Thread] qcril_event.startup_mutex" );
}
由于EventLoop被初始化后一直处于阻塞状态,所以在这里将started状态置为2后,对qcril_event_startupCond进行解锁,从而使EventLoop进入循环。
1.4、其他初始化过程
在qmi_ril_initiate_bootup()中完成了一些其他的初始化流程。[cpp] view
plain copy
![](https://oscdn.geek-share.com/Uploads/Images/Content/201611/a7c8e286f463007e2a900848b93dd72c.png)
void qmi_ril_initiate_bootup(void)
{
qcril_setup_timed_callback( QCRIL_DEFAULT_INSTANCE_ID, QCRIL_DEFAULT_MODEM_ID, qmi_ril_bootup_perform_core_or_start_polling, NULL, NULL );
}
继续看qmi_ril_bootup_perform_core_or_start_polling()过程:
[cpp] view
plain copy
![](https://oscdn.geek-share.com/Uploads/Images/Content/201611/a7c8e286f463007e2a900848b93dd72c.png)
void qmi_ril_bootup_perform_core_or_start_polling(void * params)
{
RIL_Errno init_res;
int ril_version;
qcril_unsol_resp_params_type unsol_resp;
qmi_ril_main_thread_id = pthread_self();
qmi_ril_set_thread_name( qmi_ril_fw_get_main_thread_id(), QMI_RIL_QMI_MAIN_THREAD_NAME);
qmi_ril_wave_modem_status(); // this should result in "modem unavailble" report
qmi_ril_set_operational_status( QMI_RIL_GEN_OPERATIONAL_STATUS_INIT_PENDING ); // for consistency
qmi_ril_set_operational_status( QMI_RIL_GEN_OPERATIONAL_STATUS_INIT_ONGOING );
//qmi初始化
init_res = qmi_ril_core_init();
}
上面通过qmi_ril_core_init()完成了qmi的初始化:
[cpp] view
plain copy
![](https://oscdn.geek-share.com/Uploads/Images/Content/201611/a7c8e286f463007e2a900848b93dd72c.png)
RIL_Errno qmi_ril_core_init(void)
{
RIL_Errno res = RIL_E_GENERIC_FAILURE;
QCRIL_LOG_FUNC_ENTRY();
qcril_event_suspend(); // to ensure atomic init flow cross sub domains
do
{
//qcril client的初始化
res = qcril_qmi_client_init();
if ( RIL_E_SUCCESS != res )
break;
qcril_other_init();
qcril_uim_init();
qcril_gstk_qmi_init();
#ifndef QMI_RIL_UTF
qcril_data_init();
#endif
qcril_qmi_nas_dms_commmon_post_init();
if (qmi_ril_is_feature_supported(QMI_RIL_FEATURE_OEM_SOCKET))
{
QCRIL_LOG_INFO( "%s Init OEM socket thread", __FUNCTION__ );
qcril_qmi_oem_socket_init();
}
} while (FALSE);
qcril_event_resume();
QCRIL_LOG_FUNC_RETURN_WITH_RET(res);
return res;
}
在上面完成了qcril客户端的初始化过程:
[cpp] view
plain copy
![](https://oscdn.geek-share.com/Uploads/Images/Content/201611/a7c8e286f463007e2a900848b93dd72c.png)
RIL_Errno qcril_qmi_client_init( void )
{
qmi_client_error_type client_err = 0;
RIL_Errno res = RIL_E_GENERIC_FAILURE;
QCRIL_LOG_FUNC_ENTRY();
/* Start modem or vote for start modem */
qcril_qmi_modem_power_process_bootup();
memset(&client_info, 0, sizeof(client_info));
do
{
// QMI VOICE command callback
client_info.client_cbs[QCRIL_QMI_CLIENT_VOICE] = qcril_qmi_voice_command_cb;
// Get IDL service objects
client_info.service_objects[QCRIL_QMI_CLIENT_VOICE] = voice_get_service_object_v02();
client_info.service_objects[QCRIL_QMI_CLIENT_NAS] = nas_get_service_object_v01();
client_info.service_objects[QCRIL_QMI_CLIENT_WMS] = wms_get_service_object_v01();
client_info.service_objects[QCRIL_QMI_CLIENT_WDS] = wds_get_service_object_v01();
client_info.service_objects[QCRIL_QMI_CLIENT_DMS] = dms_get_service_object_v01();
/*client_info.service_objects[QCRIL_QMI_CLIENT_UIM] = uim_get_service_object_v01();*/
client_info.service_objects[QCRIL_QMI_CLIENT_PBM] = pbm_get_service_object_v01();
client_info.service_objects[QCRIL_QMI_CLIENT_RF_SAR] = sar_get_service_object_v01();
client_info.service_objects[QCRIL_QMI_CLIENT_IMS_VT] = ims_qmi_get_service_object_v01();
client_info.service_objects[QCRIL_QMI_CLIENT_IMS_PRESENCE] = imsp_get_service_object_v01();
client_info.service_objects[QCRIL_QMI_CLIENT_IMSA] = imsa_get_service_object_v01();
client_info.service_objects[QCRIL_QMI_CLIENT_RFPE] = rfrpe_get_service_object_v01();
client_info.service_objects[QCRIL_QMI_CLIENT_IMS_SETTING] = imss_get_service_object_v01();
if ( qmi_ril_get_process_instance_id() == QCRIL_DEFAULT_INSTANCE_ID )
{
client_info.service_objects[QCRIL_QMI_CLIENT_PDC] = pdc_get_service_object_v01();
}
pthread_mutexattr_init(&client_info.cache_lock_mtx_atr);
pthread_mutex_init(&client_info.cache_lock_mutex, &client_info.cache_lock_mtx_atr);
res = qcril_qmi_init_core_client_handles();
if (RIL_E_SUCCESS != res)
break;
} while (FALSE);
return res;
}
1.5、将回调函数注册给RILC
在Qcril的初始化完毕后,将自己的函数列表返回给RilC,也就是qcril_request_api:[cpp] view
plain copy
![](https://oscdn.geek-share.com/Uploads/Images/Content/201611/a7c8e286f463007e2a900848b93dd72c.png)
static const RIL_RadioFunctions qcril_request_api[] = {
{ RIL_VERSION, onRequest_rid, currentState_rid, onSupports_rid, onCancel_rid, getVersion_rid }
};
这样的话,在RIL中调用的接口就会进入该函数列表中进行处理。
以上就是qcril的初始化流程。
二、QCRIL对请求的处理过程
当ril有请求过来时,就会调用ril库的onRequest()方法,此时就会根据当前Qcril注册的函数列表进入到qcril_request_api的onRequest_rid()函数中:[cpp] view
plain copy
![](https://oscdn.geek-share.com/Uploads/Images/Content/201611/a7c8e286f463007e2a900848b93dd72c.png)
@qcril.c
static void onRequest_rid ( int request, void *data, size_t datalen, RIL_Token t)
{
onRequest( qmi_ril_process_instance_id, request, data, datalen, t );
}
然后进入onRequest()中继续处理:
[cpp] view
plain copy
![](https://oscdn.geek-share.com/Uploads/Images/Content/201611/a7c8e286f463007e2a900848b93dd72c.png)
static void onRequest ( qcril_instance_id_e_type instance_id, int request, void *data, size_t datalen, RIL_Token t) {
udit_result = qmi_ril_fw_android_request_render_execution( param.t,
param.event_id,
param.data,
param.datalen,
param.instance_id,
&log_dispatch_dedicated_thrd );
}
继续:
[cpp] view
plain copy
![](https://oscdn.geek-share.com/Uploads/Images/Content/201611/a7c8e286f463007e2a900848b93dd72c.png)
RIL_Errno qmi_ril_fw_android_request_render_execution( RIL_Token token, int android_request_id, void * android_request_data, int android_request_data_len, qcril_instance_id_e_type instance_id, int * is_dedicated_thread ) {
do
{
entry_ptr = NULL;
//从hash表中查找当前的Event
if ( qcril_hash_table_lookup( (uint32) param.event_id, &entry_ptr ) != E_SUCCESS || NULL == entry_ptr )
{
audit_result = RIL_E_REQUEST_NOT_SUPPORTED;
break;
}
if ( dedicated_thrd_req_lookup_val == param.event_id )
{ // deferred thread exec
}
else
{
//派发该Event
if ( qcril_dispatch_event( entry_ptr, ¶m ) == E_NOT_ALLOWED )
{
audit_result = RIL_E_RADIO_NOT_AVAILABLE;
break;
}
}
} while (FALSE);
return audit_result;
}
在上面的过程中,要先通过qcril_hash_table_lookup()函数查找当前的Event,如果没有找到当前的Request,就认为非法,找到之后,进入qcril_dispatch_event()中派发该Event:
[cpp] view
plain copy
![](https://oscdn.geek-share.com/Uploads/Images/Content/201611/a7c8e286f463007e2a900848b93dd72c.png)
IxErrnoType qcril_dispatch_event ( qcril_dispatch_table_entry_type *entry_ptr, qcril_request_params_type *params_ptr) {
if(params_ptr != NULL && (params_ptr->instance_id < QCRIL_MAX_INSTANCE_ID) )
{
// print the recieved date byte stream
qcril_qmi_print_hex(params_ptr->data, params_ptr->datalen);
instance_id = params_ptr->instance_id;
s_ptr = &qcril_state->info[ instance_id ];
modem_id = params_ptr->modem_id;
if (E_SUCCESS == res)
{
//处理当前Request
(entry_ptr->handler)(params_ptr, &ret);
if ( ret.pri_gw_sim_state_changed || ret.pri_cdma_sim_state_changed ||
ret.sec_gw_sim_state_changed || ret.sec_cdma_sim_state_changed ||
ret.ter_gw_sim_state_changed || ret.ter_cdma_sim_state_changed
)
{
qcril_state_transition( instance_id, modem_id, params_ptr->event_id, &ret );
}
}
}
else
{
}
return res;
}
上面的过程通过entry_ptr->handler调用当前Event的处理函数。这里的handler对应qcril_hash_table中的某一项。从上面1.2步骤中我们将qcril_event_table表中的数据拷贝给了qcril_hash_table,所以这里的handler可以理解为qcril_event_table中的某一项。
之后的流程就会进入到某个具体请求的处理函数中,比如对于得到当前SIM卡状态这个请求,其处理函数为:qcril_uim_request_get_sim_status()。
相关文章推荐
- framework学习之Qualcomm平台qcril初始化及消息处理流程
- Qualcomm平台qcril初始化及消息处理流程
- Qualcomm平台qcril初始化及消息处理流程(原)
- 微信平台下两种消息处理流程
- windows 鼠标消息触发及处理流程
- Openfire Server presence(在线状态)消息处理流程
- windows控制面板消息处理流程
- DELPHI消息处理的流程
- 第二人生的源码分析(三十七)消息处理的完整流程
- DELPHI消息处理的流程
- 贸易时代的消息处理流程
- 高通平台AT命令处理流程详解--从sio到ds
- XMPP协议学习笔记五(Openfire消息处理流程)
- Android 4.0 消息处理的流程之我见
- live555 RTSP服务器建立及消息处理流程 .
- live555 RTSP服务器建立及消息处理流程
- 第二人生的源码分析(三十七)消息处理的完整流程
- windows平台消息处理函数(C++版)
- 浅析达芬奇DM644x平台ARM中断处理流程
- 开机流程简介--init 处理系统初始化流程 (/etc/rc.d/rc.sysinit)