adroid通信模块ril_第1页
adroid通信模块ril_第2页
adroid通信模块ril_第3页
adroid通信模块ril_第4页
adroid通信模块ril_第5页
已阅读5页,还剩15页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、 第一部分 简介简单介绍性部分:Android电话系统围绕底层使用Modem硬件来搭建,提供呼叫、短信和网络连接功能,其中modem也称为基带。Modem驱动程序包含在Linux内核层中,所以3G/4G模块的搭建其实就是电话系统的搭建 主流3G/4G模块:主要分有 内置(集成在处理器中如高通等,高通拥有相关基带的专利,内置模块主要通过共享内存与处理器通信), 外置(较常见,大多通过usb转串口接口并利用AT命令与处理器通信,usb串口一般使用标准的驱动,AT命令由Hayes公司发明,一种是调制解调器命令语言每条命令以AT(也有一些笔记本专用的接口类型如PCIE和NGFF,手机上的LGA,工业用

2、B2B等等)对与目前的通信模块来说,都已经非常成熟,有有着接口简单和统一的软件接口一般大多数模块装上SIM卡直接上电即可完成初始找网、网络注册等工作。框架部分主要是Android:1 电话系统大体框架(图1):分三大层,硬件(连接modem设备),Android系统(主要包括了Linux内核层,运行库层和Framework层),平台API(即再往上为应用层) 图(1)电话系统大体框架2.电话系统部分结构图(2):具体实现自下到上:Modem驱动,RIL库 、RIL守护进程,电话JAVA框架和电话应用(其中电话系统部分无JNI) Kernel Space 属于驱动层在内核中实现,一般分为AT命令

3、通道和数据通道两路接口。 RIL层:贯穿Android的内核层至应用层,由三部分组成:RIL守护进程(本质是rild可执行程序,开机通过init启动,与framework层主要通过socket来进行)、 libril库和ril实现库(电话层硬件抽象层)。主要负责负责数据的可靠传输、AT命令的发送以及response(来自modem)的解析 图(2)电话系统部分结构图 3.RIL接口下层结构(图3)(更细化的下层) ril实现库的接口非常复杂,需要处理的命令,相关结构体比较多,其接口主要定义在 hardware/ril/include/telephony 目录的ri.h中。 rild socke

4、t:与框架层进行通信 RIL_Env: 主要用于请求完成函数、上报消息响应函数和周期行处理函数三个功能。 RIL_RadioFunctions: RIL_REQUEST: RequestCompete: UnsolicitedResponse: RIL_UNSOL: (ril硬件抽象层主要实现 ril命令与AT命令的转换。) (电话功能移植的两大部分:Modem驱动和ril硬件抽象层,移植需要注意的问题是省电,因为Modem省电策略复杂,低功耗模式下还要处理来电或短信等唤醒操作。) 图(3)RIL接口下层结构Linux部分(具体实现部分):Linux部分(部分与Android相同):1.dri

5、vers/usb/serial/option.c #define XXXX_OPTION_VENDOR_ID XXX (添加PID和VID) #define XXXX_OPTION_PRODUCT_COLT XXX2.(外置插在usb上的话)usb_modeswitch 插入的3G/4G模块被识别成存储设备,用usb_modeswitch转成串口 3.在static struct usb_device_id option_ids = ; (结构结构体中加入加入ID)USB_DEVICE(OPTION_VENDOR_ID,OPTION_PRODUCT_COLT) ,USB_DEVICE(XXXX

6、_OPTION_VENDOR_ID ,XXXX_ OPTION_PRODUCT_COLT) ,(插上3G/4G模块上电后会出现两个端口:/dev/ttyusb0 和/dev/ttyusb1 一个用于数据一个用于命令.)(以上Linux和Android相同部分) 第二部分 RIL源码分析不同设备厂商使用的AT命令不完全相同,为了保密,AP(上层)与BP(板层)之间通过各厂商自己的相关动态库来通信。RIL模块由rild守护进程、libril.so、librefrence.so三部分组成:1. rild模块被编译为一个可执行文件,实现一个main函数作为整个ril模块的入口点。2. libril.s

7、o是共享库,主要负责同上层的通信工作,接收ril的请求,并传递给librefrence_ril.so,同时将librefrence_ril.so返回的消息送给调用进程。3. librefrence_ril.so是由各手机厂商自己实现,在rild进程运行中通过dlopen方式加载,主要负责跟modem硬件通信,转换来自libril.so的请求为AT命令,同时监听Modem的反馈信息给libril.so 源代码的图谱如下流程框图如下:RILD源码分析在kernel启动完成后,将启动第一个应用进程Init进程,在android之Init进程启动过程源码分析一文中对init进程的启动流程进行了详细的介

8、绍。init进程在启动过程中将读取init.rc文件来启动一些重量级的native服务,rild进程就是通过配置在init.rc中来启动的。在代码中的流程图如下在main函数中主要完成以下工作: 1. 解析命令行参数,通过判断是否为模拟器采取不同的方式来读取libreference-ril.so库的存放路径; 2.使用dlopen手动装载libreference-ril.so库; 3.启动事件循环处理;(这里启动另一线程) 4.从libreference-ril.so库中取得RIL_Init函数地址,并使用该函数将libril.so库中的RIL_Env接口注册到libreference-ril

9、.so库,同时将libreference-ril.so库中的RIL_RadioFunctions接口注册到到libril.so库中,建立起libril.so库与libreference-ril.so库通信桥梁;启动事件循环处理eventLoop工作线程 建立多路I/O驱动机制的消息队列,用来接收上层发出的命令以及往Modem发送AT指令的工作,是整个RIL系统的核心部分。创建一个事件分发线程s_tid_dispatch,线程中主要执行eventLoop (ril_event_loop).ventLoop流程图1. 定时事件:根据事件的执行时间来启动执行,通过ril_timer_add添加到ti

10、me_list队列中2. Wakeup事件:这些事件的句柄fd将加入的select IO多路复用的句柄池readFDs中,当对应的fd可读时将触发这些事件。对于处于listen端的socket,fd可读表示有个客户端连接,此时需要调用accept接受连接。 在eventLoop工作线程中,循环处理到来的事件及定时结束事件,整个处理流程如下图所示:首先通过Linux中的select多路I/O复用对句柄池中的所有句柄进行监控,当有事件到来时select返回,否则阻塞。当select返回时,表示有事件的到来,通过调用processTimeouts函数来处理超时事件,处理方式是遍历time_list链

11、表以查询超时事件,并将超时事件移入到pending_list链表中,接着调用processReadReadies函数来处理触发的事件,处理方式为遍历watch_table列表以查询触发的事件,并将触发的事件移入到pending_list链表中,如果该事件不是持久事件,还需要从watch_table列表中移除,当查询完两种待处理的事件并放入到pending_list链表中后,调用firePending函数对待处理的事件进行集中处理,处理方式为遍历链表,调用每一个事件的回调函数。部分主要代码如下1 /使用select 函数等待在FDS 上,只要FDS 中记录的设备有数据到来,select 就会设置

12、相应的标志位并返回。readFDS 记录了所有的事件相关设备句柄。readFDS 中句柄是在在AddEvent 加入的。 2 printReadies(&rfds); 3 n = select(nfds, &rfds, NULL, NULL, ptv); 4 printReadies(&rfds); 5 dlog(" %d events fired ", n); 6 if (n < 0) 7 if (errno = EINTR) continue; 8 LOGE("ril_event: select error (%d)",

13、 errno); 9 return; 10 11 processTimeouts(); /从timer_list中查询执行时间已到的事件,并添加到pending_list中 12 processReadReadies(&rfds, n); /从watch_table中查询数据可读的事件,并添加到pending_list中去处理,如果该事件不是持久事件,则同时从watch_table中删除 13 /遍历pending_list,调用事件处理回调函数处理所有事件 14 firePending(); RIL接口移植Hardware/ril/include/telephony/ril.hRIL

14、_ENC定义Struct RIL_ENV /动态库完成请求后通知处理结果的接口 void (*OnRequestComplete)(RIL_Token t, RIL_Errno e,void *response, size_t responselen); /动态库unSolicited Response通知接口 void (*OnUnsolicitedResponse)(int unsolResponse, const void *data,size_t datalen); /向Rild提交一个超时任务的接口 void (*RequestTimedCallback) (RIL_TimedCal

15、lback callback,void *param, const struct timeval *relativeTime); 在hardwarerillibrilril.cpp中实现了RIL_Env的各个接口函数RIL_onRequestComplete通过调用responseXXX将底层响应传给客户进程RIL_onUnsolicitedResponse函数处理modem从网络端接收到的各种事件,如网络信号变化,拨入的电话,收到短信等。然后传给客户进程。RIL_requestTimedCallback 回调对应的内部处理函数,将回调添加到event循环。RIL_RadioFunctions

16、定义客户端向Rild发送请求的接口,由各设备厂商实现。15 typedef struct 16 int version; /Rild版本 17 RIL_RequestFunc onRequest; /AP请求接口 18 RIL_RadioStateRequest onStateRequest;/BP状态查询 19 RIL_Supports supports; 20 RIL_Cancel onCancel; 21 RIL_GetVersion getVersion;/动态库版本 22 RIL_RadioFunctions; 在hardwarerilreference-rilreference-r

17、il.c中实现了RIL_RadioFunctions的各个接口函数 (其中最重要的是onRequest函数)onRequest函数对每一个RIL_REQUEST_XXX请求转化成相应的ATcommand,发送给modem,然后睡眠等待,当收到ATcommand的最终响应后,线程被唤醒,将响应传给客户端进程。注册RIL_Env接口主要步骤如下由于各设备厂商的AT指令差异,因此与modem交互层需要各厂商实现,以动态库的形式提供。作为介于modem与上层的中间层,即要与底层交互也要与上层通信,因此就需要定义一个接口来衔接RILD与动态库,RIL_Env和RIL_RadioFunctions接口就是

18、libril.so与librefrence.so通信的桥梁。是Rild架构中用于隔离通用代码和厂商代码的接口,RIL_Env由通用代码实现,而RIL_RadioFunctions则是由厂商代码实现。RIL_Init的主要任务:1. 向librefrence.so注册libril.so提供的接口RIL_Env;2. 创建一个mainLoop工作线程,用于初始化AT模块,并监控AT模块的状态,一旦AT被关闭,则重新打开并初始化AT;3. 当AT被打开后,mainLoop工作线程将向Rild提交一个定时事件,并触发eventLoop来完成对modem的初始化;4. 创建一个readLoop工作线程,

19、用于从AT串口中读取数据;5.返回librefrence.so提供的接口RIL_RadioFunctions;路径在hardwarerilreference-rilreference-ril.creadLoop工作线程Read loop 解析从Modem 发过来的回应。如果遇到URC 则通过handleUnsolicited 上报的RIL_JAVA。如果是命令的应答,则通过handleFinalResponse 通知send_at_command 有应答结果。注册RIL_RadioFunctions接口代码主要在hardwarerillibrilril.cppvoid RIL_register

20、 (const RIL_RadioFunctions *callbacks) .23 / 得到名为rild的socket句柄 24 s_fdListen = android_get_control_socket(SOCKET_NAME_RIL); 25 if (s_fdListen < 0) 26 LOGE("Failed to get socket '" SOCKET_NAME_RIL "'"); 27 exit(-1); 28 29 / 监听该socket 30 ret = listen(s_fdListen, 4); 31 i

21、f (ret < 0) 32 LOGE("Failed to listen on control socket '%d': %s",s_fdListen, strerror(errno); 33 exit(-1); 34 35 /* 设置s_listen_event事件,一旦有客户端连接,即s_fdListen可读就会导致eventLoop工作线程中的select返回,因为该事件不是持久的,因此调用为listenCallback处理完后,将从watch_table移除该事件,所以Rild只支持一个客户端连接*/ 36 ril_event_set (&a

22、mp;s_listen_event, s_fdListen, false,listenCallback, NULL); 37 /* 添加s_listen_event事件,并触发eventLoop工作线程 */ 38 rilEventAddWakeup (&s_listen_event); 39 #if 1 40 / 得到调试socket的句柄rild-debug 41 s_fdDebug = android_get_control_socket(SOCKET_NAME_RIL_DEBUG); 42 if (s_fdDebug < 0) 43 LOGE("Failed to get socket '" SOCKET_NAME_RIL_DEBUG "' errno:%d", errno); 44 exit(-1); 45 46 /监听该socket 47 ret = listen(s_fdDebug, 4); 48 if (ret < 0) 49 LOGE("Failed to listen on ril debug socket '%d': %s",s_fdDebug,

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论