oFono是一个开源免费的电话协议栈软件,它遵循3GPP27.007等通信标准,通过AT命令与modem进行交互,以实现各种电话功能(Voicecall, GPRS, SMS, Stk等等)。由于在oFono之中没有完全实现TS 27.007的AT指令,所以在开发之中我们会遇到将一些功能加入到oFono系统之中。
一、在oFono中增加消息监听(以SRVCC为例说明):
关于oFono中的消息传递可分为两类:一类是AP侧将请求传递给modem,即主动请求;另一类是modem有事件变化后将消息主动上报到AP侧,即主动上报。我们先来看一下后者。
这里以Srvcc为例说明如何在oFono中添加modem主动上报的逻辑。所谓Srvcc指的是当Volte通话由于网络变化等原因从PS域回落到CS域了,这种情况下modem会上报通知到应用层。关于Srvcc的AT Command是CIREPH,关于该指令的具体描述请参考TS 27.007的8.64 IMS network reporting +CIREP章节。
+CIREPH: <srvcch> Provides PS to CS SRVCC, PS to CS vSRVCC and CS to PS SRVCC handover information.
在增加Code之前,我们先看一下oFono系统的层次结构,主要包含接口层与驱动层(PS:应用层与Modem属于oFono的外围模块,oFono起到沟通上下层的作用),具体参考下图:
- Application Layer(应用层) : 负责与oFono通过DBus进行通信,是用户层代码。oFono源码中ofono/test目录下使用Python语言编写了很多Demo程序,这一部分就属于应用层。
- Interface Layer(接口层) : 负责与应用层沟通,接收应用层下发的请求与上报消息到应用层。该层主要是为了屏蔽驱动层的差异,为应用层提供统一的接口(DBus)。
- Driver Layer(驱动层) : 在驱动层中包含了很多类型的modem目录,比如有atmodem、rilmodem、huaweimodem和ztemodem等,目的是区分不同厂商底层的差异。这里需要提到的是不同类型的modem是可以配置的。
- Modem : 对于Driver层配置不同的modem类型,这一层的属性是不同的,比如如果Driver配置成atmodem,则这一层为CP侧,oFono通过串口发送at指令与CP直接通信;如果Dirver层配置成为rilmodem,则这一层是与rild直接通信的,使用的是Ril的相关事件进行通信的(下面的文章都会以rilmodem来进行讲解)。该层的代码不在oFono之中。
基于以上的信息,我们可以发现如果在oFono中增加无论主动上报还是主动下发,需要扩展接口和驱动层的代码,当然用户层的代码也需要增加,并且Modem需要支持该主动上报和主动下发的相关事件。
下面我们从接口层和驱动层分别叙述如何扩展Modem主动上报的消息通知应用层:
1. 修改驱动层的Code
首先,在Android的telephony/ril.h之中,定义了关于SRVCC的相关事件ID。
/**
* RIL_UNSOL_SRVCC_STATE_NOTIFY
*
* Called when Single Radio Voice Call Continuity(SRVCC)
* progress state has changed
*
* "data" is int *
* ((int *)data)[0] is of type const RIL_SrvccState
*
*/
#define RIL_UNSOL_SRVCC_STATE_NOTIFY 1039
oFono为了接收RIL的该时间,我们需要在gril/ril_constants.h中定义与RIL相同的消息,且Message ID( 1039 )必须与RIL保持一致。其次,因为Srvcc属于通话模块的范畴,所以需要将监听放到voicecall模块之中,在voicecall之中,监听底层的消息都在ril_delayed_register之中发起注册的。
static gboolean ril_delayed_register(gpointer user_data) {
/* Unsol