Ril分析三——客户端请求和响应处理与modem交互


    Ril与modem的交互

一 客户端的请求处理

客户端请求从EventLoop通过dispatch传递到reference-ril.c中调用onRequest接口。
  

    


处理客户端请求:

static void onRequest (int request, void *data, size_t datalen, RIL_Token t) { switch (request) { case RIL_REQUEST_DIAL: requestDial(data, datalen, t); break; …… } }

 

二 AT Command发送

将客户端请求转化成AT命令:

 

static void requestDial(void *data, size_t datalen, RIL_Token t) { RIL_Dial *p_dial; char *cmd;
//转化成AT命令 p_dial = (RIL_Dial *)data; asprintf(&cmd, "ATD%s%s;", p_dial->address, clir);
//发送AT命令 ret = at_send_command(cmd, NULL); //请求处理完成回调 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0); }

发送AT Command:

static int at_send_command_full_nolock (const char *command,                       ATCommandType type,……) { //将数据写入到mdoem设备文件节点中
  err = writeline (command); //休眠等待写入的数据被读取
    while (sp_response->finalResponse == NULL && s_readerClosed == 0) { err = pthread_cond_wait(&s_commandcond, &s_commandmutex); } return err; }

将数据写入modem设备节点中:

static int writeline (const char *s) { //写入数据到设备文件描述符s_fd
    while (cur < len) { do { written = write (s_fd, s + cur, len - cur); } while (written < 0 && errno == EINTR); cur += written; }
//返回行首 do { written = write (s_fd, "\r" , 1); } while ((written < 0 && errno == EINTR) || (written == 0)); return 0; }

 

  这样就将数据写入到设备文件描述符s_fd,将AT Command传递给Modem了;

  在数据被读取之前处于休眠状态。数据写入被读取之后,方才返回。

  那么s_fd代表的的设备是如何设置的,读数据又是怎么进行的呢。


三 Modem响应请求处理


  通过AT Command将命令发给了Modem,等待Modem处理此请求,然后将结果返回来,

读取之后进行处理,然后表示此请求Complete,并且通知 Client。

过程如下:

    

 

  这个Serial Prot是什么,Reader Loop是什么呢。回到rild进程main函数中看看。

在rild进程的main函数中:

int main(int argc, char **argv) { //处理客户端请求的模块reference-ril.c 调用RIL_Init
    funcs_inst[0] = rilInit(&s_rilEnv, argc, s_argv); …… }

reference-ril初始化函数:

RIL_RadioFunctions *RIL_Init(const struct RIL_Env *env, int argc, char **argv) { //交互的接口
    s_rilenv = env; //提取modem设备端口或者路径   //此处是d 根据前面属性系统获取参数:rild.libargs=-d /dev/ttyS0   // getopt的使用 提取选项
    while ( -1 != (opt = getopt(argc, argv, "p:d:s:c:"))) { switch (opt) { case 'd': s_device_path = optarg; break; } } //创建线程s_tid_mainloop
  ret = pthread_create(&s_tid_mainloop, &attr, mainLoop, NULL); //返回请求交互的接口
    return &s_callbacks; }

s_tid_mainloop线程的执行体:

static void *mainLoop(void *param) { at_set_on_reader_closed(onATReaderClosed); at_set_on_timeout(onATTimeout); for (;;) { fd = open (s_device_path, O_RDWR); s_closed = 0; ret = at_open(fd, onUnsolicited); RIL_requestTimedCallback(initializeCallback, NULL, &TIMEVAL_0); // Give initializeCallback a chance to dispatched, since // we don't presently have a cancellation mechanism
        sleep(1); waitForClose(); } }

这里打开了modem的设备文件描述符fd,传递给了at_open():

int at_open(int fd, ATUnsolHandler h) { //与modem设备通信文件描述符
    s_fd = fd;
//网络端传来事件请求处理onUnsolicited s_unsolHandler = h; s_readerClosed = 0;
//创建线程s_tid_reader ret = pthread_create(&s_tid_reader, &attr, readerLoop, &attr); return 0; }

线程执行体readerLoop():

static void *readerLoop(void *arg) { for (;;) { //从与modem通信设备端口读取数据
        line = readline(); if (line == NULL) { break; } //处理数据
 processLine(line); } onReaderClosed(); return NULL; }

来自Modem端数据处理:

static void processLine(const char *line) { if (sp_response == NULL) { //来自网络端事件
 handleUnsolicited(line); } else if (isFinalResponseSuccess(line)) { //客户端请求处理返回
        sp_response->success = 1; handleFinalResponse(line);   }   …… }


来自网络端事件:

static void handleUnsolicited(const char *line) { // 回调接口onUnsolicited
    if (s_unsolHandler != NULL) { s_unsolHandler(line, NULL); } }

客户端请求处理返回:

static void handleFinalResponse(const char *line) { //保存modem端响应请求所传递的数据
    sp_response->finalResponse = strdup(line);
//发送signal 唤醒等待s_commandcond的线程——Event Loop pthread_cond_signal(&s_commandcond); }

 

整个数据流程图如下:

图片来自:http://blog.csdn.net/maxleng/article/details/5576637


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM