另外我们可以看到,
在进入 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 域,上层来的请求都由这个函数进行映射后转换成对应的