reference库的加载
reference库需要完成两个任务:
1、将eventLoop中的命令通过AT发送给Modem;
2、构建一个readerLoop循环,接受Modem消息,并根据消息的不同(URC和非URC)将消息返回给eventLoop(非URC消息)或者直接发送给RILJ(URC消息)。
RIL_Init方法是在RILD初始化的时候(rild.c)调用的,其作用是连接libril与reference,libril的Env地址指针作为变量传入到该方法中,后续底层上报URC消息会用到
@reference-ril.c
const RIL_RadioFunctions *RIL_Init(const struct RIL_Env *env, int argc, char **argv)
{
//开启ril的线程,入口函数是mainLoop
ret = pthread_create(&s_tid_mainloop, &attr, mainLoop, NULL);
//把ril的回调函数返回出来
return &s_callbacks;
}
//指令通过reference发往modem
static void * mainLoop(void *param)
{
//初始化AT通道的关闭方法和超时方法
at_set_on_reader_closed(onATReaderClosed);
at_set_on_timeout(onATTimeout);
for (;;) {
//打开AT并把处理URC消息的方法onUnsolicited传进去
ret = at_open(fd, onUnsolicited);
RIL_requestTimedCallback(initializeCallback, NULL, &TIMEVAL_0);
waitForClose();
}
}
/hardware/ril/reference-ril/atchannel.c
int at_open(int fd, ATUnsolHandler h)
{
int ret;
pthread_t tid;
pthread_attr_t attr;
s_fd = fd;
s_unsolHandler = h;
s_readerClosed = 0;
s_responsePrefix = NULL;
s_smsPDU = NULL;
sp_response = NULL;
pthread_attr_init (&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
//创建线程,执行readerLoop循环,读取AT命令并处理Modem发过来的信息
ret = pthread_create(&s_tid_reader, &attr, readerLoop, &attr);
return 0;
}
整个RILD主要是由两个循环组成,一个是EventLoop,一个是readerLoop。EventLoop主要与上层打交道,而readerLoop主要与modem交互。
//readerLoop接收从modem上传的数据,分为URC和非URC两种方式进行处理
static void *readerLoop(void *arg)
{
for (;;) {
//读取命令
line = readline();
if(isSMSUnsolicited(line)) {
if (s_unsolHandler != NULL) {
//URC消息可以直接发送给RILJ
s_unsolHandler (line1, line2);
}
} else {
//非URC的处理方式的判断
processLine(line);
}
}
//关闭read
onReaderClosed();
return NULL;
}
processLine会通过标志位对URC和非URC进行判断,分别调用不同的处理方法,当为URC的时候,调用handleUnsolicited,当为非URC的时候,会去唤醒下发非URC请求的时候阻塞的线程,然后把响应继续往上发送
//sp_response是主动下发请求的回调,如果该值不为空,那么表示请求是自己主动下发到modem的,如果为空,则表示是modem自己主动上报的
static void processLine(const char *line)
{
pthread_mutex_lock(&s_commandmutex);
if (sp_response == NULL) {
/* no command pending */
handleUnsolicited(line);
} else if (isFinalResponseSuccess(line)) {
//设置非URC请求的标志位
sp_response->success = 1;
handleFinalResponse(line);
} else if (isFinalResponseError(line)) {
sp_response->success = 0;
handleFinalResponse(line);
} else if (s_smsPDU != NULL && 0 == strcmp(line, "> ")) {
// See eg. TS 27.005 4.3
// Commands like AT+CMGS have a "> " prompt
writeCtrlZ(s_smsPDU);
s_smsPDU = NULL;
} else switch (s_type) {
case NO_RESULT:
handleUnsolicited(line);
break;
case NUMERIC:
if (sp_response->p_intermediates == NULL
&& isdigit(line[0])
) {
addIntermediate(line);
} else {
/* either we already have an intermediate response or
the line doesn't begin with a digit */
handleUnsolicited(line);
}
break;
case SINGLELINE:
if (sp_response->p_intermediates == NULL
&& strStartsWith (line, s_responsePrefix)
) {
addIntermediate(line);
} else {
/* we already have an intermediate response */
handleUnsolicited(line);
}
break;
case MULTILINE:
if (strStartsWith (line, s_responsePrefix)) {
addIntermediate(line);
} else {
handleUnsolicited(line);
}
break;
default: /* this should never be reached */
RLOGE("Unsupported AT command type %d\n", s_type);
handleUnsolicited(line);
break;
}
pthread_mutex_unlock(&s_commandmutex);
}
static void handleUnsolicited(const char *line)
{
//at_open传入的参数
if (s_unsolHandler != NULL) {
s_unsolHandler(line, NULL);
}
}
@reference-ril.c
//s_rilenv是在rild.c的main函数
#define RIL_onUnsolicitedResponse(a,b,c) s_rilenv->OnUnsolicitedResponse(a,b,c)
static void onUnsolicited (const char *s, const char *sms_pdu)
RIL_onUnsolicitedResponse (
RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED,
NULL, 0);
@rild.c
static struct RIL_Env s_rilEnv = {
RIL_onRequestComplete,
RIL_onUnsolicitedResponse,
RIL_requestTimedCallback,
RIL_onRequestAck
};
/hardware/ril/libril/ril.cpp
OnUnsolicitedResponse-->sendResponse(p,socket_id)-->sendResponseRaw(p.data(),p.dataSize(),socket_id)--> blockingWrite(fd, data, dataSize) -->RILJ socket
因为非URC消息从上层下发到modem的时候会阻塞住,等到modem响应了之后会重新唤醒,这个也就是非URC消息的上报与URC的不同之处