RIL层源码分析w(6)

2019-09-01 20:03

}

我们再分析上面的第一个步骤,也就是把消息发送到Eventloop中的过程。当发送到Eventloop后,Eventloop就会调用当前Event的回调函数,现在的回调函数是processCommandsCallback: static void processCommandsCallback(int fd, short flags, void *param) { for (;;) {

ret = record_stream_get_next(p_rs, &p_record, &recordlen);

if (ret == 0 && p_record == NULL) { break; } else if (ret < 0) { break;

} else if (ret == 0) { /* && p_record != NULL */ //把RILJ层数据通过AT发送到Modem processCommandBuffer(p_record, recordlen); } }

if (ret == 0 || !(errno == EAGAIN || errno == EINTR)) { //命令已经发送完成,关闭当前命令的流套接字 close(s_fdCommand); s_fdCommand = -1; //删掉当前Event

ril_event_del(&s_commands_event); record_stream_free(p_rs);

//重新添加RILJ与RILC之间的Socket Event rilEventAddWakeup(&s_listen_event); onCommandsSocketClosed();

} }

上面看到,发送命令给Modem是通过processCommandBuffer实现的: static int processCommandBuffer(void *buffer, size_t buflen) { Parcel p; int32_t request; int32_t token; RequestInfo *pRI;

p.setData((uint8_t *) buffer, buflen); //得到请求码和令牌

status = p.readInt32(&request); status = p.readInt32 (&token);

pRI = (RequestInfo *)calloc(1, sizeof(RequestInfo)); //设置当前请求的令牌 pRI->token = token;

//s_commands中针对不同的命令对应不同的处理函数 pRI->pCI = &(s_commands[request]);

//链表结构

pRI->p_next = s_pendingRequests; s_pendingRequests = pRI;

//调用reference 中的

pRI->pCI->dispatchFunction(p, pRI);

return 0; }

首先说明一个很重要的标志位:token令牌;这个令牌可以看作当前请求的ID,当我们从Modem得到数据后需要根据不同的令牌找到当初的请求命令,然后做出相应的答复。

这里还涉及到一个特殊的数组s_commands。他的作用和s_unsolResponses类似,详细说明在本文的最后一章,这里还是简单介绍一下他的作用:

s_commands是一个数组,每个RILJ发送过来的命令在s_commands中都对应一个元素,而每个元素包含3个数据:

typedef struct { int requestNumber;

void (*dispatchFunction) (Parcel &p, struct RequestInfo *pRI); int(*responseFunction) (Parcel &p, void *response, size_t responselen); } CommandInfo;

其中requestNumber表示当前命令的编号;dispatchFunction的作用是,当前命令可以通过这个接口把数据发送到reference库;responseFunction的作用是:当Modem返回数据后reference侧可以用这个函数把数据进行打包,然后传递给Event侧。

而在processCommandBuffer中要做的就是通过当前的命令号,找到对应的发送函数(dispatchFunction)和打包函数(responseFunction)。然后把这三个数据连同当前命令的令牌(当前命令的ID)构建一个在Event和reference侧通用的数据类型(RequestInfo)并把它发送给reference侧。

假如我们从RILJ得到的命令号为RIL_REQUEST_GET_SIM_STATUS(得到当前SIM卡的状态),那么对应的,就需要调用当前命令的发送函数,而在s_commands中对于这条命令的描述为: {RIL_REQUEST_GET_SIM_STATUS, dispatchVoid, responseSimStatus}, 因此,它对应的发送函数就是dispatchVoid: @ril.cpp

static void dispatchVoid (Parcel& p, RequestInfo *pRI) { //发送数据到Modem clearPrintBuf;

//打印Log信息RLOGD(\ printRequest(pRI->token, pRI->pCI->requestNumber);

//s_callbacks是从reference注册过来的

s_callbacks.onRequest(pRI->pCI->requestNumber, NULL, 0, pRI); }

这里看到,将命令发送到reference库是通过s_callbacks的onRequest方法实现的,而且发送时会将命令号和ril_commands.h中对应的当前命令的信息一同发送。

而关于s_callbacks这个全局变量,我们在这一节的最初就讲到,当我们调用reference中的RIL_Init完成初始化时,就会得到reference返回当前链接库提供的接口函数,而s_callbacks正是来自于这些接口: @reference-ril.c

static const RIL_RadioFunctions s_callbacks = { RIL_VERSION, onRequest, currentState, onSupports, onCancel, getVersion };

因此,当上面的Eventloop将数据通过s_callbacks.onRequest发送给reference的过程就是调用reference-ril.c中的onRequest的过程。

之后,Eventloop就完成了下发命令的任务,接下来需要reference完成把命令发送给Modem的任务。

3.2、reference将Eventloop的数据发送到Modem

上面说道,s_callbacks.onRequest其实就是reference-ril.c中的onRequest,经过这次调用,就将数据由Eventloop侧传到了reference侧。 @reference-ril.c

static void onRequest (int request, void *data, size_t datalen, RIL_Token t) {

ATResponse *p_response;

RLOGD(\

//我们重点看RIL_REQUEST_GET_SIM_STATUS switch (request) {

case RIL_REQUEST_GET_SIM_STATUS: { RIL_CardStatus_v6 *p_card_status; char *p_buffer; int buffer_size;

//与Modem交互,发送命令并得到回应 int result = getCardStatus(&p_card_status); //把回应传回给Eventloop

RIL_onRequestComplete(t, result, p_buffer, buffer_size); freeCardStatus(p_card_status); break; }

case RIL_REQUEST_GET_CURRENT_CALLS: //得到当前通话

requestGetCurrentCalls(data, datalen, t); break;

case RIL_REQUEST_DIAL: //拨号

requestDial(data, datalen, t); break;

case RIL_REQUEST_HANGUP: //挂起

requestHangup(data, datalen, t); } }


RIL层源码分析w(6).doc 将本文的Word文档下载到电脑 下载失败或者文档不完整,请联系客服人员解决!

下一篇:2018年湖南省政府采购评审专家库培训测评-多选题部分答案

相关阅读
本类排行
× 注册会员免费下载(下载后可以自由复制和排版)

马上注册会员

注:下载文档有可能“只有目录或者内容不全”等情况,请下载之前注意辨别,如果您已付费且无法下载或内容有问题,请联系我们协助你处理。
微信: QQ: