RILD(四)---Reference(URC消息上报)

reference库的加载

reference库需要完成两个任务:
    1、将eventLoop中的命令通过AT发送给Modem;
    2、构建一个readerLoop循环,接受Modem消息,并根据消息的不同(URC和非URC)将消息返回给eventLoop(非URC消息)或者直接发送给RILJ(URC消息)。

RIL_Init方法是在RILD初始化的时候(rild.c)调用的,其作用是连接libril与reference,libril的Env地址指针作为变量传入到该方法中,后续底层上报URC消息会用到

@reference-ril.c
const RIL_RadioFunctions *RIL_Init(const struct RIL_Env *env, int argc, char **argv)
{
    //开启ril的线程,入口函数是mainLoop
    ret = pthread_create(&s_tid_mainloop, &attr, mainLoop, NULL);
    
    //把ril的回调函数返回出来
    return &s_callbacks;
}

//指令通过reference发往modem
static void * mainLoop(void *param)
{
    //初始化AT通道的关闭方法和超时方法
    at_set_on_reader_closed(onATReaderClosed);
    at_set_on_timeout(onATTimeout);
    for (;;) {
        //打开AT并把处理URC消息的方法onUnsolicited传进去
        ret = at_open(fd, onUnsolicited);
        RIL_requestTimedCallback(initializeCallback, NULL, &TIMEVAL_0);
        waitForClose();
    }
}
/hardware/ril/reference-ril/atchannel.c
int at_open(int fd, ATUnsolHandler h)
{
    int ret;
    pthread_t tid;
    pthread_attr_t attr;

    s_fd = fd;
    s_unsolHandler = h;
    s_readerClosed = 0;

    s_responsePrefix = NULL;
    s_smsPDU = NULL;
    sp_response = NULL;

    pthread_attr_init (&attr);
    
    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
    //创建线程,执行readerLoop循环,读取AT命令并处理Modem发过来的信息
    ret = pthread_create(&s_tid_reader, &attr, readerLoop, &attr);

    return 0;
}

整个RILD主要是由两个循环组成,一个是EventLoop,一个是readerLoop。EventLoop主要与上层打交道,而readerLoop主要与modem交互。

//readerLoop接收从modem上传的数据,分为URC和非URC两种方式进行处理
static void *readerLoop(void *arg)
{
    for (;;) {
        //读取命令
        line = readline();
        if(isSMSUnsolicited(line)) {
            if (s_unsolHandler != NULL) {
                //URC消息可以直接发送给RILJ
                s_unsolHandler (line1, line2);
            }
        } else {
            //非URC的处理方式的判断
            processLine(line);
        }
    }
    //关闭read
    onReaderClosed();
    return NULL;
}

 processLine会通过标志位对URC和非URC进行判断,分别调用不同的处理方法,当为URC的时候,调用handleUnsolicited,当为非URC的时候,会去唤醒下发非URC请求的时候阻塞的线程,然后把响应继续往上发送

//sp_response是主动下发请求的回调,如果该值不为空,那么表示请求是自己主动下发到modem的,如果为空,则表示是modem自己主动上报的
static void processLine(const char *line)
{
    pthread_mutex_lock(&s_commandmutex);
    
    if (sp_response == NULL) {
        /* no command pending */
        handleUnsolicited(line);
    } else if (isFinalResponseSuccess(line)) {
        //设置非URC请求的标志位
        sp_response->success = 1;
        handleFinalResponse(line);
    } else if (isFinalResponseError(line)) {
        sp_response->success = 0;
        handleFinalResponse(line);
    } else if (s_smsPDU != NULL && 0 == strcmp(line, "> ")) {
        // See eg. TS 27.005 4.3
        // Commands like AT+CMGS have a "> " prompt
        writeCtrlZ(s_smsPDU);
        s_smsPDU = NULL;
    } else switch (s_type) {
        case NO_RESULT:
            handleUnsolicited(line);
            break;
        case NUMERIC:
            if (sp_response->p_intermediates == NULL
                && isdigit(line[0])
            ) {
                addIntermediate(line);
            } else {
                /* either we already have an intermediate response or
                   the line doesn't begin with a digit */
                handleUnsolicited(line);
            }
            break;
        case SINGLELINE:
            if (sp_response->p_intermediates == NULL
                && strStartsWith (line, s_responsePrefix)
            ) {
                addIntermediate(line);
            } else {
                /* we already have an intermediate response */
                handleUnsolicited(line);
            }
            break;
        case MULTILINE:
            if (strStartsWith (line, s_responsePrefix)) {
                addIntermediate(line);
            } else {
                handleUnsolicited(line);
            }
        break;

        default: /* this should never be reached */
            RLOGE("Unsupported AT command type %d\n", s_type);
            handleUnsolicited(line);
        break;
    }

    pthread_mutex_unlock(&s_commandmutex);
}
static void handleUnsolicited(const char *line)
{
    //at_open传入的参数
    if (s_unsolHandler != NULL) {
        s_unsolHandler(line, NULL);
    }
}
@reference-ril.c
//s_rilenv是在rild.c的main函数
#define RIL_onUnsolicitedResponse(a,b,c) s_rilenv->OnUnsolicitedResponse(a,b,c)

static void onUnsolicited (const char *s, const char *sms_pdu)
        RIL_onUnsolicitedResponse (
          RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED,
          NULL, 0);
@rild.c
static struct RIL_Env s_rilEnv = {
    RIL_onRequestComplete,
    RIL_onUnsolicitedResponse,
    RIL_requestTimedCallback,
    RIL_onRequestAck
};

 /hardware/ril/libril/ril.cpp
OnUnsolicitedResponse-->sendResponse(p,socket_id)-->sendResponseRaw(p.data(),p.dataSize(),socket_id)--> blockingWrite(fd, data, dataSize) -->RILJ socket


 因为非URC消息从上层下发到modem的时候会阻塞住,等到modem响应了之后会重新唤醒,这个也就是非URC消息的上报与URC的不同之处

猜你喜欢

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