说三道四技术文摘-感悟人生的经典句子
说三道四 > 文档快照

Android GSM驱动模块详细分析

HTML文档下载 WORD文档下载 PDF文档下载
本文详细介绍了Android的GSM驱动模块的基本架构与初始化工作过程。

作者:熊猫哥哥

 

Android的RIL驱动模块, 在hardware/ril目录下,一共分rild,libril.so以及librefrence_ril.so三个部分,另有一radiooptions可供自动或手动调试使用。都依赖于include目录中ril.h头文件。目前cupcake分支上带的是gsm的支持,另有一cdma分支,这里分析的是gsm驱动。
  GSM模块,由于Modem的历史原因,AP一直是通过基于串口的AT命令与BB交互。包括到了目前的一些edge或3g模块,或像omap这类ap,bp集成的芯片,已经使用了USB或其他等高速总线通信,但大多仍然使用模拟串口机制来使用AT命令。这里的RIL(Radio Interface Layer)层,主要也就是基于AT命令的操作,如发命令,response解析等。(gprs等传输会用到的MUX协议等在这里并没有包含,也暂不作介绍。)
  以下是详细分析,本文主要涉及基本架构和初始化的内容:
  首先介绍一下rild与libril.so以及librefrence_ril.so的关系:
1. rild:
仅实现一main函数作为整个ril层的入口点,负责完成初始化。
2. libril.so:
与rild结合相当紧密,是其共享库,编译时就已经建立了这一关系。组成部分为ril.cpp,ril_event.cpp。libril.so驻留在rild这一守护进程中,主要完成同上层通信的工作,接受ril请求并传递给librefrence_ril.so, 同时把来自librefrence_ril.so的反馈回传给调用进程。
3. librefrence_ril.so:
rild通过手动的dlopen方式加载,结合稍微松散,这也是因为librefrence.so主要负责跟Modem硬件通信的缘故。这样做更方便替换或修改以适配更多的Modem种类。它转换来自libril.so的请求为AT命令,同时监控Modem的反馈信息,并传递回libril.so。在初始化时, rild通过符号RIL_Init获取一组函数指针并以此与之建立联系。
4. radiooptions:
radiooptiongs通过获取启动参数, 利用socket与rild通信,可供调试时配置Modem参数。
  接下来分析初始化流程,主入口是rild.c中的main函数,主要完成三个任务:
1. 开启libril.so中的event机制, 在RIL_startEventLoop中,是最核心的由多路I/O驱动的消息循环。
2. 初始化librefrence_ril.so,也就是跟硬件或模拟硬件modem通信的部分(后面统一称硬件), 通过RIL_Init函数完成。
3. 通过RIL_Init获取一组函数指针RIL_RadioFunctions, 并通过RIL_register完成注册,并打开接受上层命令的socket通道。
  首先看第一个任务,也就是RIL_startEventLoop函数。RIL_startEventLoop在ril.cpp中实现, 它的主要目的是通过pthread_create(&s_tid_dispatch, &attr, eventLoop, NULL)建立一个dispatch线程,入口点在eventLoop. 而eventLoop中,会调ril_event.cpp中的ril_event_loop()函数,建立起消息(event)队列机制。
  我们来仔细看看这一消息队列的机制,这些代码都在ril_event.cpp中。

Android的RIL驱动模块, 在hardware/ril目录下,一共分rild,libril.so以及librefrence_ril.so三个部分,另有一radiooptions可供自动或手动调试使用。都依赖于include目录中ril.h头文件。目前cupcake分支上带的是gsm的支持,另有一cdma分支,这里分析的是gsm驱动。

  GSM模块,由于Modem的历史原因,AP一直是通过基于串口的AT命令与BB交互。包括到了目前的一些edge或3g模块,或像omap这类ap,bp集成的芯片,已经使用了USB或其他等高速总线通信,但大多仍然使用模拟串口机制来使用AT命令。这里的RIL(Radio Interface Layer)层,主要也就是基于AT命令的操作,如发命令,response解析等。(gprs等传输会用到的MUX协议等在这里并没有包含,也暂不作介绍。)

  以下是详细分析,本文主要涉及基本架构和初始化的内容:

  首先介绍一下rild与libril.so以及librefrence_ril.so的关系:

1. rild:

仅实现一main函数作为整个ril层的入口点,负责完成初始化。

2. libril.so:

与rild结合相当紧密,是其共享库,编译时就已经建立了这一关系。组成部分为ril.cpp,ril_event.cpp。libril.so驻留在rild这一守护进程中,主要完成同上层通信的工作,接受ril请求并传递给librefrence_ril.so, 同时把来自librefrence_ril.so的反馈回传给调用进程。

3. librefrence_ril.so:

rild通过手动的dlopen方式加载,结合稍微松散,这也是因为librefrence.so主要负责跟Modem硬件通信的缘故。这样做更方便替换或修改以适配更多的Modem种类。它转换来自libril.so的请求为AT命令,同时监控Modem的反馈信息,并传递回libril.so。在初始化时, rild通过符号RIL_Init获取一组函数指针并以此与之建立联系。

4. radiooptions:

radiooptiongs通过获取启动参数, 利用socket与rild通信,可供调试时配置Modem参数。

  接下来分析初始化流程,主入口是rild.c中的main函数,主要完成三个任务:

1. 开启libril.so中的event机制, 在RIL_startEventLoop中,是最核心的由多路I/O驱动的消息循环。

2. 初始化librefrence_ril.so,也就是跟硬件或模拟硬件modem通信的部分(后面统一称硬件), 通过RIL_Init函数完成。

3. 通过RIL_Init获取一组函数指针RIL_RadioFunctions, 并通过RIL_register完成注册,并打开接受上层命令的socket通道。

  首先看第一个任务,也就是RIL_startEventLoop函数。RIL_startEventLoop在ril.cpp中实现, 它的主要目的是通过pthread_create(&s_tid_dispatch, &attr, eventLoop, NULL)建立一个dispatch线程,入口点在eventLoop. 而eventLoop中,会调ril_event.cpp中的ril_event_loop()函数,建立起消息(event)队列机制。

  我们来仔细看看这一消息队列的机制,这些代码都在ril_event.cpp中。

 

 

 

void ril_event_init();void ril_event_set(struct ril_event * ev, int fd, bool persist, ril_event_cb func, void * param);void ril_event_add(struct ril_event * ev);void ril_timer_add(struct ril_event * ev, struct timeval * tv);void ril_event_del(struct ril_event * ev);void ril_event_loop();struct ril_event {   struct ril_event *next;   struct ril_event *prev;   int fd;   int index;   bool persist;   struct timeval timeout;   ril_event_cb func;   void *param;};
每个ril_event结构,与一个fd句柄绑定(可以是文件,socket,管道等),并且带一个func指针去执行指定的操作。
具体流程是: ril_event_init完成后,通过ril_event_set来配置一新ril_event,并通过ril_event_add加入队列之中(实际通常用rilEventAddWakeup来添加),add会把队列里所有ril_event的fd,放入一个fd集合readFds中。这样ril_event_loop能通过一个多路复用I/O的机制(select)来等待这些fd, 如果任何一个fd有数据写入,则进入分析流程processTimeouts(),processReadReadies(&rfds, n),firePending()。 后文会详细分析这些流程。
另外我们可以看到, 在进入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域,上层来的请求都由这个函数进行映射后转换成对应的AT命令发给硬件。
rild通过RIL_register注册这一指针。
  RIL_register中要完成的另外一个任务,就是打开前面提到的跟上层通信的socket接口(s_fdListen是主接口,s_fdDebug供调试时使用)。
  然后将这两个socket接口使用任务一中实现的机制进行注册(仅列出s_fdListen)
ril_event_set (&s_listen_event, s_fdListen, false, listenCallback, NULL);rilEventAddWakeup (&s_listen_event);
这样将两个socket加到任务一中建立起来多路复用I/O的检查句柄集合中,一旦有上层来的(调试)请求,event机制便能响应处理了。到这里启动流程已经分析完毕。

 

 

拥抱Spark,机遇无限——Spark Summit 2013精彩回顾 1月10日:改变世界的iPhone七岁了,你是传奇! 同洲电子推出首款手机操作系统960OS 免费授权使用 如何在Windows 8.1的IE11中打开同步选项卡? 25年老对手评价微软:换CEO可行,但是太迟了 【PPT集萃】十位一线专家分享Spark现状与未来(三) 万元奖品等你拿!2014创客118新年大Party! Firefox OS的2013回顾和2014展望 Strom8 CEO:搞好手游开发,合伙人很重要 2013年Q4全球PC出货量同比下滑6.9% 已连续下滑七个季度 一周消息树:2013年十大产品、图书、公司盘点 专访Wunderlist主设计师Jan Martin:永远不要盲目跟风流行趋势 研发周报:超实用的JavaScript技巧及最佳实践 2013最吃香的技能:Java称霸、Android势头正猛 移动周报:最火原型设计工具盘点 “京东电商云”起航,零售企业及品牌商是重点 教育乃立国之本:教育类开源项目大汇集 Hugo Barra首度谈离开谷歌后在中国工作的感受 对中国赞不绝口 母婴行业最早试水者 优谈宝宝借助轻应用全面布局移动产品线 腾讯云平台部总经理纪顺友:微云将彻底迈过文件传输的门槛 豌豆“荚”油!B轮融资1.2亿美元的豌豆荚 2013年终盘点:10款最精巧的硬件开发板 SquareWear:可替代Lilypad Arduino的开发板 开放数据:2014年最热门的竞争领域 IE11虚拟机免费面向广大开发者 九城搭建的一个以Hadoop为基础的大数据平台 Windows 8复杂性的代价到底有多大? 在发布前,第一代iPhone其实并不完善 市场占有率调查:iOS 7秒杀Android 4.4 AWS会赢、OpenStack会消亡、Connected Cars可防僵尸攻击 谷歌以32亿美金收购iPod之父的创业公司Nest 物联网时代来临 请问一下在哪里可以找到收购软件的公司呢? 想作一个DOS程序,实现多台电脑间通过网卡传输文件. 辞职信 application.initialize完成了什么 高手来帮忙啊~ 看看java的魅力 如何通过自制程序的编辑框向现有一般应用程序编辑框传送内容? 窗口执行顺序问题,请多帮助,谢谢 如何自动取得server的日期和时间 怎样让文件指针指到文件末尾,必须skipline一行一行跳吗? 我想在菜单前添加图标,使用Bitmap属性但是为何只能载入*.bmp文件而不能使用*.ico文件,我只有*.ico的图标,请问该如何解决。 有新建一个文本文件并给其命名的函数吗,怎么用 我还真不懂呀? 这个COLTYPE是怎么用的呀?你说它怎么得到表中字段的类型呀? 有关存储器(ram,rom)的编址问题。以及32位或更多位芯片的问题。 一些汇编问题。想来问bcb的兄弟{bcb里好象有不少汇编高手} 救命:在安装了sco openserver之后,系统不能启动,先前安装的win98和win2k也不能。 请问如何进行URL译码??? 请问怎样截取一个string中的一段? 请问delphi做的exe最小可以到多少?怎么做? 我想请问一下WINGATE的具体怎样在WIN2000服务器版中进行设置。 ASP的同志们,能不能留一下QQ号码? 请问何处有破解ACCESS2000的程序或源代码呢? 请问要在TEdit.text组件文本串中找出当前光标在第几个字符上怎么办?谢谢! 请问关于dbImage控件的使用方法? 关于HDC及双缓冲的问题? xxxbird(*说你行,你就行,不行也行*),来领“我遇到几个怪问题。。。。。。”中的分 为什么ASP没法向SQL Server中写入数据?代码什么地方错了 大家帮忙找一下,找到我给50分 exe 捆绑机怎么做? 大家谈谈JSP的设计模式怎末了?我有个题目,设计好的大大有奖! 浏览器下的那个进度条是怎么弄出来的? C中的typedef struct和C++中的 struct有何区别? C中的typedef struct和C++中的 struct有 什么区别?谢谢 lastlove(本栏位广告招商中,欢迎投放!),jjdelphi(我真的不懂),jinesc(杂牌军)-(人民军队为人民) 开利息了 一个网页的原代码可以保存到字符串里吗? 有没有各种C++编译器都支持的字符串类型或字符串类? <@> 关于 ProcessMessages 一个想不如大家想,请各位帮忙想个主页的名字吧。 女友23岁,她会选择前途还是爱情?-----一个VB程序员的痛苦 如何实现应用程序与动态库通信??? ----myxfang----偶来贷款了!!!--- myxfang(大富翁银行~业务员~~),都给你了,我可把赌注都压到你身上了 我存钱,没人受理吗?银行业务员在哪? CMainFrame主框架是用来干什么的? myxfang(大富翁银行~业务员~~),我已经结账了,到哪里去取贷款? 怎么释放它? ----myxfang---我给手续费了,我的贷款呢??http://www.csdn.net/expert/topic/203/203903.shtm--- myxfang(大富翁银行~业务员~~),来拿我的骚扰费~ 老师!! 这个动态查询为何总出错? 大富翁银行生意兴隆!恭喜恭喜…… ~~~~myxfang给我们上了生动的一课~~~~ 三个圆的半径都是5CM.三个圆两两相交于圆心.求阴影部分的面积之和?阴影面积明显要大于半个圆的面积,其实是半圆面积加上三个小的阴影面积,再加上等边三角形面积呀很多人说此题切割法 圆的周长是25.12厘米,求圆的面积 求阴影部分的面积 单位:厘米 圆的周长是25.12厘米 半径力10cm的圆的面积,是半径为5cm的圆的面积的4倍,对还是错 一个小圆的半径是6厘米,一个大圆的直径是8厘米,大圆和小圆的面积比是: 下图圆的周长是12.56厘米,圆和长方形面积相等,求长方形的场图是这样的:一个圆的4分之1是长方形的一部分 圆的半径从5cm减少到3cm,圆的面积减少了多少 小圆的半径是3厘米,大圆的直径是8厘米,大圆和小圆的面积的最简整数比是( 一个圆与一个长方形面积相等,圆的周长是18.84厘米,长方形长10厘米,宽多少厘米? 半径为5cm的圆比半径4cm的圆的面积大百分之几 在周长是48厘米的正方形内画一个圆,这个圆的周长是多少厘米,面积是多少平方厘米? 一个圆与一个长方形面积相等已知圆的周长是18.84厘米长方形的长是6厘米 长方形的宽是多少 一个半圆的周长是25.7cm,他的面积是多少平方厘米? 在周长是12厘米的正方形内画一个最大的圆,圆的周长是多少厘米? 一个圆儿的面积与一个长方形的面积相等,圆的周长是18.84厘米,长方形的长是六厘米,宽是多少? 一个半圆的周长是25.7厘米,求半圆的面积方程 如下图,圆的周长是50.24厘米,圆的面积与长方形的面积相等,求阴影部分的面积. 一个圆与一个长方形的面积相等,圆周长是18.84厘米,长方形长6厘米,宽是多少厘米? 已知半圆的周长是25.7CM,求半圆的面积. 图中圆的周长是25.12cm,BC=10cm 阴影部分的面积是( ) 见右下图,圆的周长是18.84厘米,圆与长方形的面积相等.长方形的长和宽各是多少? 一个半圆的周长是25.7厘米,它的面积是多少平方厘米 图中圆的周长是25.12cm,圆的面积正好等于长方形oabc的面积的2倍.求阴影部分的面积 一个圆与一个长方形的面积相等.圆的周长是37.68厘米.长方形的宽是9厘米,长是多少? 一个半圆的周长为15.42厘米,这个半圆的面积是( )平方厘米高手快来,一定采纳! 如图,圆的面积与长方体的面积相等,圆的周长是25.12cm,求阴影部分的周长 一个圆的周长是37.68厘米,面积是多少 一个环形零件,内圆半径是5cm,外圆半径是8cm,这个零件的阴影部分的面积是多少? 知道半圆的周长,怎样求半圆的面积.已知半圆的周长是25.7、要求详细,, 图中的4个圆的周长都是37.68厘米,求阴影部分的面积. 如图,圆A 圆B 圆C 两两不相交且半径都是0.5cm 求图中三个扇形(阴影部分)面积之和 一个半圆的周长是10.28cm,半圆的面积是多少平方厘米还没搞明白, 如图长方形与圆的面积相等,圆的周长是37.68CM,求阴影部分的面积是多少.π取3.14 如图,已知阴影部分面积是5cm平方,求圆环的面积. 大、小两个圆的周长比是5:3.已知两个圆的面积相差32平方厘米,这两个圆的面积各是多少? 如图,圆的周长是31.4厘米,求阴影部分面积.阴影部分面积是那梯形.那梯形的下底是8. 已知:如图,三个圆的半径都是5cm,求阴影部分的面积是多少平方厘米?(三个都是一样的园)求写出详细过程 为什么这样做 有大小两个圆,它们的面积差是160平方厘米,已知两圆的周长比是5:3,大圆的面积是多少平方厘米? 图中四个等圆的周长都是50.24cm,求阴影部分的面积?(6cm不是本题的条件) 下图中阴影部分的面积为5cm².求环形的面积.底下还有个图,大虾们快来ooo! 请问大、小两个圆的周长比是5:3 .已知两个圆的面积相差32平方厘米,这两个圆的面积各是多少? 已知下图中圆的周长是12.56厘米,求阴影部分的面积. 在四个半径为2厘米的圆围成的图形中,求阴影部分的面积和周长 大小两个圆的周长之比是5:3,它们的面积相差48平方厘米,两个圆的面积分别是多少平方厘米? ` 已知下图三角形的面积是16.28平方厘米.圆的周长都是12.56厘米,求阴影部分的面积?已知下图三角形的` 已知下图三角形的面积是16.28平方厘米.圆的周长都是12.56厘米,求阴影部分的面积? 已知下 图中圆的半径是1厘米求阴影部分的周长和面积, 大、小两个圆的周长比是5:3.已知两个圆的面积相差32平方厘米,这两圆的面积各是多少? 下图中,圆的周长是12.56厘米,圆的周长等于长方形的长,求阴影部分的面积 下面三个圆的半径都为5cm求阴影部分的面积和空白部分的周长 两个圆的周长之和是94.2厘米,已知大圆半径与小圆半径的比是4∶1.这两个圆的面积各是多少平方厘米? 如图,三个等圆的周长都是12.56,那么阴影部分的面积是多少平方厘米 三个圆的半径都是5cm,求阴影部分的面积和中间空白部分的周长.切记, 一个圆的周长是94.2厘米,半径增加1厘米,这个圆的面积增加了多少平方厘米? 已知三个圆的周长都是12.56分米,并且圆心都是三角形的顶点,请你求出阴影部分的面积 下面三个圆的半径都为五厘米,求阴影部分的面积和中间空白部分的周长 甲,乙两个圆的周长比是2比3,其中一个圆的面积是12平方厘米,另一个圆的面积可能是多少,也可能是多少? 三角形面积是16.28平方厘米,圆的周长12.56厘米,求阴影部分面积 三个半径都是5cm的圆两两相交于圆心,求阴影部分的面积 甲乙两圆的周长比是3:4,其中一个圆的面积是15平方厘米,另一个圆的面积可能是( ),也可能是( ) 圆的周长是25.12厘米,求正方形内阴影部分面积
备案号:鲁ICP备13029499号-2 说三道四 www.s3d4.cn