上层发送下来的指令通过RILJ传递给RILC,在s_command数组中会根据不同的请求调用不同的dispatch方法,dispatch方法再往下就需要调用不同的AT指令进行处理。
@ril.cpp
static void dispatchVoid (Parcel& p, RequestInfo *pRI) {
//发送数据到Modem
clearPrintBuf;
//打印Log信息RLOGD("[%04d]> %s %s", token, requestToString(req), printBuf)
printRequest(pRI->token, pRI->pCI->requestNumber);
//s_callbacks是从reference注册过来的
s_callbacks.onRequest(pRI->pCI->requestNumber, NULL, 0, pRI);
}
@reference-ril.c
#define RIL_onRequestComplete(t, e, response, responselen) s_rilenv->OnRequestComplete(t,e, response, responselen)
static void onRequest (int request, void *data, size_t datalen, RIL_Token t)
{
ATResponse *p_response;
int err;
RLOGD("onRequest: %s", requestToString(request));
switch (request) {
case RIL_REQUEST_GET_SIM_STATUS: {
RIL_CardStatus_v6 *p_card_status;
char *p_buffer;
int buffer_size;
//获取SIMCard的状态
int result = getCardStatus(&p_card_status);
if (result == RIL_E_SUCCESS) {
p_buffer = (char *)p_card_status;
buffer_size = sizeof(*p_card_status);
} else {
p_buffer = NULL;
buffer_size = 0;
}
//调用了Event的OnRequestComplete方法,reference与lib-ril的相互调用
RIL_onRequestComplete(t, result, p_buffer, buffer_size);
freeCardStatus(p_card_status);
break;
}
......
}
RIL_onRequestComplete(t, result, p_buffer, buffer_size)的调用reference与lib-ril的相互调用的一个体现,在rild.c的RILD入口就对reference的方法和lib-ril中的Env进行相互的绑定,掌握着彼此的句柄
@rild.c
//rilEnv内定义的所有方法都是在ril.c中实现
static struct RIL_Env s_rilEnv = {
RIL_onRequestComplete,
RIL_onUnsolicitedResponse,
RIL_requestTimedCallback,
RIL_onRequestAck
};
@reference-ril.c
static int getCardStatus(RIL_CardStatus_v6 **pp_card_status) {
//定义SIM卡状态的数组
static RIL_AppStatus app_status_array[] = {
// SIM_ABSENT = 0
{ RIL_APPTYPE_UNKNOWN, RIL_APPSTATE_UNKNOWN, RIL_PERSOSUBSTATE_UNKNOWN,
NULL, NULL, 0, RIL_PINSTATE_UNKNOWN, RIL_PINSTATE_UNKNOWN },
// SIM_NOT_READY = 1
{ RIL_APPTYPE_SIM, RIL_APPSTATE_DETECTED, RIL_PERSOSUBSTATE_UNKNOWN,
NULL, NULL, 0, RIL_PINSTATE_UNKNOWN, RIL_PINSTATE_UNKNOWN }
......
};
RIL_CardState card_state;
int num_apps;
//获取SIM卡的状态
int sim_status = getSIMStatus();
if (sim_status == SIM_ABSENT) {
card_state = RIL_CARDSTATE_ABSENT;
num_apps = 0;
} else {
card_state = RIL_CARDSTATE_PRESENT;
num_apps = 2;
}
......
// Pickup the appropriate application status
// that reflects sim_status for gsm.
if (num_apps != 0) {
// Only support one app, gsm
p_card_status->num_applications = 2;
p_card_status->gsm_umts_subscription_app_index = 0;
p_card_status->cdma_subscription_app_index = 1;
// Get the correct app status
//根据getSIMStatus方法返回的状态码获取到SIM卡的状态
p_card_status->applications[0] = app_status_array[sim_status];
p_card_status->applications[1] = app_status_array[sim_status + RUIM_ABSENT];
}
*pp_card_status = p_card_status;
//将状态返回给reference
return RIL_E_SUCCESS;
}
/** Returns SIM_NOT_READY on error */
static SIM_Status
getSIMStatus()
{
ATResponse *p_response = NULL;
int err;
int ret;
char *cpinLine;
char *cpinResult;
RLOGD("getSIMStatus(). sState: %d",sState);
if (sState == RADIO_STATE_OFF || sState == RADIO_STATE_UNAVAILABLE) {
ret = SIM_NOT_READY;
goto done;
}
//通过AT指令进行查询,返回错误码
err = at_send_command_singleline("AT+CPIN?", "+CPIN:", &p_response);
//根据返回码判断SIM卡状态
if (err != 0) {
ret = SIM_NOT_READY;
goto done;
}
......
}
at_send_command_singleline ->at_send_command_full_nolock
AT指令的发送使用writeline就可以了,这里注意的是当AT指令发送完毕之后,线程会阻塞,因为主动下发请求的都是非URC请求,需要等待modem的返回,而modem的返回会在另外一个方法processLine中进行判断(关于processline的判断可参考另外一篇博客RIJD--Reference(URC消息上报)),当返回的信息中含有非URC的标志的时候就会使s_commandcond条件成立,然后释放sp_response
@atchannel.c
static int at_send_command_full_nolock (const char *command, ATCommandType type,
const char *responsePrefix, const char *smspdu,
long long timeoutMsec, ATResponse **pp_outResponse)
{
int err = 0;
struct timespec ts;
if(sp_response != NULL) {
err = AT_ERROR_COMMAND_PENDING;
goto error;
}
//发送AT指令
err = writeline (command);
if (err < 0) {
goto error;
}
s_type = type;
s_responsePrefix = responsePrefix;
s_smsPDU = smspdu;
sp_response = at_response_new();
if (timeoutMsec != 0) {
setTimespecRelative(&ts, timeoutMsec);
}
//阻塞线程,条件满足时退出。s_commandcond是线程间共享的条件变量
//在processLine处理函数中有对URC和非URC的不同回调的处理,当modem返回的消息属于非URC下发的响应的时候,就会唤醒这个阻塞线程,释放sp_response
while (sp_response->finalResponse == NULL && s_readerClosed == 0) {
if (timeoutMsec != 0) {
err = pthread_cond_timedwait(&s_commandcond, &s_commandmutex, &ts);
} else {
err = pthread_cond_wait(&s_commandcond, &s_commandmutex);
}
if (err == ETIMEDOUT) {
err = AT_ERROR_TIMEOUT;
goto error;
}
}
if (pp_outResponse == NULL) {
//释放sp_response
at_response_free(sp_response);
} else {
/* line reader stores intermediate responses in reverse order */
reverseIntermediates(sp_response);
*pp_outResponse = sp_response;
}
......
}
当modem返回,sp_response释放,那么RILD往modem下发的流程就走完了。