RILD把请求发给modem

上层发送下来的指令通过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下发的流程就走完了。

猜你喜欢

转载自blog.csdn.net/binge__/article/details/81477904