background image

另外我们可以看到,

 在进入 ril_event_loop 之前, 已经挂入了一 s_wakeupfd_event,

 

通 过

pipe 的 机 制 实 现 的 ,   这 个 event 的 目 的 是 可 以 在 一 些 情 况 下 , 能 内 部 唤 醒

ril_event_loop 的多路复用阻塞,比如一些带 timeout 的命令 timeout 到期的时候。

至此第一个任务分析完毕,这样便建立起了基于

event 队列的消息循环,稍后便可以

接受上层发来的的请求了(上层请求的

event 对象建立,在第三个任务中)。

接下来看第二个任务,这个任务的入口是

RIL_Init, RIL_Init 首先通过参数获取硬件接

口的设备文件或模拟硬件接口的

socket. 接下来便新开一个线程继续初始化, 即 mainLoop。

mainLoop 的主要任务是建立起与硬件的通信,然后通过 read 方法阻塞等待硬件的主动

上报或响应。在注册一些基础回调(

timeout,readerclose)后,mainLoop 首先打开硬件设备

文件,建立起与硬件的通信,

s_device_path 和 s_port 是前面获取的设备路径参数,将其打

开(两者可以同时打开并拥有各自的

reader,这里也很容易添加双卡双待等支持)。

接下来通过

at_open 函数建立起这一设备文件上的 reader 等待循环,这也是通过新建一

个 线 程 完 成 ,

  ret  =  pthread_create(&s_tid_reader,  &attr,  readerLoop,  &attr) , 入 口 点

readerLoop。

AT 命令都是以\r\n 或\n\r 的换行符来作为分隔符的,所以 readerLoop 是 line 驱动的,除

非出错,超时等,否则会读到一行完整的响应或主动上报,才会返回。这个循环跑起来以后,
我 们 基 本 的

AT 响 应 机 制 已 经 建 立 了 起 来 。 它 的 具 体 分 析 , 包 括 at_open 中 挂 接 的

ATUnsolHandler, 我们都放到后面分析 response 的连载文章里去。

有 了 响 应 的 机 制 ( 当 然 , 能 与 硬 件 通 信 也 已 经 可 以 发 请 求 了 ) , 通 过

RIL_requestTimedCallback(initializeCallback, NULL,  &TIMEVAL_0),跑到 initializeCallback
中,执行一些

Modem 的初始化命令,主要都是 AT 命令的方式。发 AT 命令的流程,我们放

到后面分析

request 的连载文章里。这里可以看到,主要是一些参数配置,以及网络状态的

检查等。至此第二个任务分析完毕,硬件已经可以访问了。

最 后 是 第 三 个 任 务 。 第 三 个 任 务 是 由

RIL_Init 的 返 回 值 开 始 的 , 这 是 一 个

RIL_RadioFunctions 结构的指针。

typedef struct {
   int version;        /* set to RIL_VERSION */
   RIL_RequestFunc onRequest;
   RIL_RadioStateRequest onStateRequest;
   RIL_Supports supports;
   RIL_Cancel onCancel;
   RIL_GetVersion getVersion;
} RIL_RadioFunctions;

其中最重要的是

onRequest 域,上层来的请求都由这个函数进行映射后转换成对应的