RIL层源码分析w(5)

2019-09-01 20:03

b、判断是否已经把所有有效数据传输完毕:isFinalResponseSuccess //结束符

static const char * s_finalResponsesSuccess[] = { \ \ }; //判断

static int isFinalResponseSuccess(const char *line) {

size_t i;

for (i = 0 ; i < NUM_ELEMS(s_finalResponsesSuccess) ; i++) { if (strStartsWith(line, s_finalResponsesSuccess[i])) { return 1; } } return 0; }

c、发送数据给Event侧,取消Event侧阻塞的线程:handleFinalResponse static void handleFinalResponse(const char *line) {

//把回应消息返回给eventLoop

sp_response->finalResponse = strdup(line);

//发信号给s_commandcond线程,使其脱离阻塞状态 pthread_cond_signal(&s_commandcond); }

三、一个完整的过程

经过上面的eventLoop和readerLoop过程分析,我们分别对eventLoop的机制和readerLoop中两种消息的处理有个大致的了解,但是还有一些问题我们没有解决,比如:

1、eventLoop所构建的循环如何接收RILJ的消息?又如何通过reference将消息发送到Modem? 2、上面说道reference接收到非URC消息后需要通知eventLoop读取消息,具体怎么通知eventLoop的? 这些问题将在这一节中详细说明。我们用一个完整的数据流来把两个loop串起来。而一个完整的数据流应该包括以下四个步骤:

1、Eventloop接收RILJ的请求,并负责把请求发送给reference库:Eventloop--->reference 2、reference负责把命令转化为AT命令,然后发送给Modem:reference--->Modem

3、reference通过readerLoop得到Modem回应后把数据返回给Eventloop: Modem--->ReaderLoop 4、Eventloop再把数据返回给RILJ:ReaderLoop--->Eventloop 下面我们就分别介绍这4个步骤的详细流程。

3.1、Eventloop把RILJ命令发送给reference库

我们再次回到RILC层的入口处,前面两节介绍了Eventloop和reference,接下来就是RIL_register的入口: @rild.c

int main(int argc, char **argv) {

//搭建EventLoop循环 RIL_startEventLoop();

//对reference动态库进行初始化 funcs = rilInit(&s_rilEnv, argc, rilArgv);

//注册reference 的回调函数 RIL_register(funcs); }

上面看到,当我们调用reference的初始化函数(也就是RIL_Init)后,将会得到一个RIL_RadioFunctions类型的返回值:

@reference-ril.c

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

这个变量的类型为: typedef struct {

int version; //当前链接库的版本信息

RIL_RequestFunc onRequest; //用于Event侧向动态库发起请求 RIL_RadioStateRequest onStateRequest; //得到当前库的状态 RIL_Supports supports; //查询是否支持某个命令 RIL_Cancel onCancel; //取消一个Event的处理 RIL_GetVersion getVersion; //得到版本号 } RIL_RadioFunctions;

这些成员函数中最重要的是onRequest,当我们在Event侧向reference库发起请求时,就是用的这个入口函数。而我们将用这个对象去完成注册的过程。 @ril.cpp

//将reference中的回调函数注册给RIL的框架 void RIL_register (const RIL_RadioFunctions *callbacks) { //把返回值传给s_callbacks(全局变量)

memcpy(&s_callbacks, callbacks, sizeof (RIL_RadioFunctions));

//#define SOCKET_NAME_RIL \ 打开RILC与RILJ之间的Socket通道

s_fdListen = android_get_control_socket(SOCKET_NAME_RIL); ret = listen(s_fdListen, 4);

//用这个Socket通道句柄创建一个Event

ril_event_set (&s_listen_event, s_fdListen, false, listenCallback, NULL);

//添加到Eventloop中

rilEventAddWakeup (&s_listen_event); }

在上面的注册函数中主要完成了两个任务:1、将我们从reference得到的回调函数callbacks传递给一个全局变量s_callbacks;2、打开Socket通道并添加句柄到Eventloop中。对于第二个任务,我们看到在注册的过程中,通过android_get_control_socket的方法打开了RILJ与RILC之间的Socket通道,而且这个通道的文件句柄为s_fdListen(全局变量),并用这个通道的句柄构建一个Event,然后添加到Eventloop中。并且为这个Event注册了的回调函数listenCallback。

经过上面的过程,就在RILJ与EventLoop之间建立了沟通的渠道。

还记得我们在Eventloop中提到如果检测到句柄池中的某个句柄有新数据的话,就会调用将timer_list和watch_table中的Event放入pending_list中,然后调用当前Event的回调函数: @ril_event.cpp static void firePending() {

struct ril_event * ev = pending_list.next; while (ev != &pending_list) {

struct ril_event * next = ev->next; removeFromList(ev);

//这里的func就是listenCallback ev->func(ev->fd, 0, ev->param); ev = next; } }

对于RILJ中过来的Event,我们注册的回调函数是listenCallback: @ril.cpp

static void listenCallback (int fd, short flags, void *param) {

//从s_fdListen侦听套接字得到s_fdCommand(RILJ与RILC之间的流套接字) s_fdCommand = accept(s_fdListen, (sockaddr *) &peeraddr, &socklen);

//得到当前命令的选项值

err = getsockopt(s_fdCommand, SOL_SOCKET, SO_PEERCRED, &creds, &szCreds);

//对文件描述符s_fdCommand进行控制,当前是设置其非阻塞模式 ret = fcntl(s_fdCommand, F_SETFL, O_NONBLOCK);

//再次把当前命令放入Eventloop

ril_event_set (&s_commands_event, s_fdCommand, 1, processCommandsCallback, p_rs); rilEventAddWakeup (&s_commands_event);

//发送URC消息,通知RIL状态发生改变 onNewCommandConnect(); }

上面的过程分为2步:1、把当前消息重新发送到Eventloop;2、发送URC消息,通知RILJ(RIL状态改变了)。我们先来看一下第二个过程:

static void onNewCommandConnect() { //给RILJ发送URC消息,RIL连接成功

RIL_onUnsolicitedResponse(RIL_UNSOL_RIL_CONNECTED, &rilVer, sizeof(rilVer));

//给RILJ发送URC消息,告诉RILJ,Radio状态改变了

RIL_onUnsolicitedResponse(RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED, NULL, 0);


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

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

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

马上注册会员

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