欢迎来到冰豆网! | 帮助中心 分享价值,成长自我!
冰豆网
全部分类
  • IT计算机>
  • 经管营销>
  • 医药卫生>
  • 自然科学>
  • 农林牧渔>
  • 人文社科>
  • 工程科技>
  • PPT模板>
  • 求职职场>
  • 解决方案>
  • 总结汇报>
  • 党团工作>
  • ImageVerifierCode 换一换
    首页 冰豆网 > 资源分类 > DOCX文档下载
    分享到微信 分享到微博 分享到QQ空间

    rilmulticard.docx

    • 资源ID:9090696       资源大小:66.81KB        全文页数:13页
    • 资源格式: DOCX        下载积分:12金币
    快捷下载 游客一键下载
    账号登录下载
    微信登录下载
    三方登录下载: 微信开放平台登录 QQ登录
    二维码
    微信扫一扫登录
    下载资源需要12金币
    邮箱/手机:
    温馨提示:
    快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。
    如填写123,账号就是123,密码也是123。
    支付方式: 支付宝    微信支付   
    验证码:   换一换

    加入VIP,免费下载
     
    账号:
    密码:
    验证码:   换一换
      忘记密码?
        
    友情提示
    2、PDF文件下载后,可能会被浏览器默认打开,此种情况可以点击浏览器菜单,保存网页到桌面,就可以正常下载了。
    3、本站不支持迅雷下载,请使用电脑自带的IE浏览器,或者360浏览器、谷歌浏览器下载即可。
    4、本站资源下载后的文档和图纸-无水印,预览文档经过压缩,下载后原文更清晰。
    5、试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。

    rilmulticard.docx

    1、rilmulticardAndroid hardware RIL层多卡功能的具体实现修改记录作者日期修改内容黄理洪2010-5-20加入智能识别卡槽、逻辑卡号到真实卡号的映射、自动关闭未插卡的modem等说明。黄理洪2010-5-15增加“修改上报radio state的方法”黄理洪2010-4-11初稿一、 原有RIL层简介android的hardware RIL(radio interface layer)是手机modem和android framework层的接口,代码位于hardware/ril/,文件类型包含c和c+,共约6千多行。整个ril编译出来得到三个文件:libreferen

    2、ce-ril.so (负责直接和modem交互)libril.so (负责通过socket和framework层交互)rild(作为守护进程的可执行程序,是上面两个库的入口)上面两个.so库实现了三个的线程:Mainloop thread,只是起初始化串口和modem的作用,后期处于idle状态;request dispatch thread,负责分发framework层对modem的AT command;response reader thread,负责从modem读取response。下图是RIL层的总体框图:绿色箭头指示response reader threadAT command是发

    3、送给modem的AT指令,如自动注册网络用AT+COPS=0, 拨打移动客服用ATD10086; 挂电话用ATH。Response是由modem返回的响应信息,包括请求响应(指对AT command的响应)和主动响应(英文称为unsolicited response,包括短信和手机网络主动上报信息)。二、 改造需求 现在的ril只支持一个modem带一张手机卡,我们要实现多模多卡多待手机就需要让它同时支持多个modem,多张手机卡。需要支持的modem按照网络模式分,有下列四类:1、GSM modem a. 单卡GSM modem b. 双卡GSM modem2、TDS-CDMA modem

    4、(属于中国移动的3G标准)3、CDMA2000 EVDO modem(属于中国电信的3G标准)4、WCDMA modem (属于中国联通的3G标准)目前尚未发现支持双卡的3G modem,所以一个多模手机的极限情况是同时具有上面四种modem,带5张手机卡(2张2G的sim卡,3张3G卡)。我们的ril层改造目标就是支持这种极限连接方式。如同其他对android的改造一样,在达到目的的前提下,我们希望对android的修改越少越好。目前我们只有智源单卡GSM modem IW368,和联芯TDS-CDMA modem LC6311,这两个模块可以用于多卡功能的前期调试。三、 具体实现1. ri

    5、l层对modem和framework层的信息接口的重新约定Modem主要有uart接口和usb接口(3G比2G有更高的数据传输速度,一般用usb接口;华为海思正在研发的4G LTE modem加上了1Gbit/s的以太网接口实现更高的速度),从ril角度来看,它是几个虚拟的串口设备。比如展讯的双卡GSM modem,接在物理的uart2上,那么uart2对应的/dev/ttyS2将虚拟出/dev/pts/0、/dev/pts/1和/dev/pts/2 三个虚拟串口设备分别对应sim1和sim2的AT指令通道和上网的gprs通道;又如大唐的3G modem LC6311,接在我们cpu的usb

    6、host接口上,通过usb serial驱动虚拟出/dev/ttyUSB05, 共6个ttyUSB串口设备,我们只用其中的ttyUSB3作为AT指令通道,ttyUSB5作为上网数据通道。对于ril层多卡的改造,我们主要考虑AT指令通道的串口设备(下面简称为AT串口设备),暂时不考虑上网数据通道的串口设备,因为ril层三个线程Mainloop thread,request dispatch thread,AT reader thread操作的都是AT指令通道。上网数据通道仅被一个data call request调用,很单纯。一张手机卡(下面有时称其为card)对应一个AT串口设备,所以要建一个

    7、card id 和AT串口设备的描述符fd 的对应表:Modem 网络模式fd(AT串口设备描述符)Card id(十进制)GSMfd_G011fd_G112WCDMAfd_W021TDS-CDMAfd_T031CDMA2000(EVDO)fd_C041其中,双卡GSM modem的fd_G0 和fd_G1是通过open /dev/pts/0和/dev/pts/1得到的设备描述符,分别对应两张sim卡。fd_T0是open ttyUSB3得到的设备描述符,对应一张中国移动手机卡。严格地说,card id其实应该称为卡槽id,因为对于多卡手机来说,卡槽常有而卡不常有。每次开机,ril层首先自己探

    8、测哪些卡槽插了卡,当与framework的socket通信建立时,就把所有已插入卡的id传给framework。framework层通过card id的十位数就可以得知该手机卡的网络模式。 在reference-ril/misc.h中,定义下面表示真实卡号的宏,和表示卡槽信息的结构体:#define CARDID_GSM_0 11#define CARDID_GSM_1 12#define CARDID_TDSCDMA_0 21#define CARDID_EVDO_0 31#define CARDID_WCDMA_0 41struct card_slot_t int id; char *mo

    9、dem_name; char *tty_name; int fd;在reference-ril/misc.c中定义具体的卡槽信息:struct card_slot_t card_slot_info = CARDID_TDSCDMA_0, LC6311, /dev/ttyUSB3, -1,CARDID_GSM_0, IW368, /dev/pts/2, -1,0;其中card_slot_info.fd是在open /dev/ ttyUSB3或/dev/pts/2成功后,用open的返回值来赋值。在framework层,GSM、WCDMA和TDS-CDMA三种网络模式都使用GSMPhone类,EV

    10、DO使用CDMAPhone类。为了方便处理,framework使用逻辑卡号,逻辑卡号的十位数表示该卡使用GSMPhone类还是CDMAPhone类,分别对应于1和2;个位数表示某类的第几张卡。举个例子,如果实际插入卡槽的卡的真实卡号有11、31和41,那么它们对应的逻辑卡号分别是11、12和21。真实卡号比逻辑卡号带有更多的网络类型信息,也需要保留。理论上逻辑卡号和真实卡号的转换工作可以放在framework中做,但在实践中遇到了一些困难,所以还是放在hardware ril中来做。这样framework和ril之间就采用逻辑卡号来通信。也就是说framework把“逻辑卡号+request”

    11、发给ril,ril把“逻辑卡号+response”发给framework。 清楚了ril层对modem和framework层的信息接口,下面就可以展开具体的ril层的修改工作了。修改ril主要有三部分工作,分别对应ril的三个线程。首先需要增加两个全局变量:request_card_id(表示正分发的AT command request发向哪张卡,会被mainloop和request dispatch两个线程使用)和response_card_id(表示正从哪张卡读取response信息,只被response reader thread使用)。 2. 修改mainloop thread上面提到

    12、,该线程只是起初始化串口和modem的作用,原有程序只初始化了一个串口设备和一个modem,现在要根据card_slot_info的内容来初始化多个串口设备和modem。下图为修改之后的mainloop相关的流程图,蓝色为修改部分。013. 修改request dispatch thread framework层通过socket把request card id传递给ril,ril在processCommandBuffer() 中把request card id从socket data中取出,最后在writeline() 和writectrlz()中通过request card id判断往哪个m

    13、odem发送指令。下图为修改之后的request dispatch thread相关的流程图,蓝色为修改部分。024. 修改AT reader thread修改readloop函数,使其用select方法阻塞式地同时监视所有手机卡的fd是否可读,某个fd可读就解除阻塞,根据fd设置response_card_id,然后调用readline读取response。在程序中response被分为三种:1、 短信息;2、 主动上报(unsolicited response),如网络状态、信号强度等;3、 AT command request的response。如果是短信息或主动上报,那么就在 RIL_

    14、onUnsolicitedResponse()里把response_card_id和response一起封到parcel里,通过socket传给framework层。如果是AT command response,并且此时response card id = request card id,那么释放信号量解除AT command request thread的阻塞。会不会出现读到的是AT response但response card id != request card id的情况?如果不考虑主动上报被误认为AT response的情况(这种情况在后面的技术要点备忘里讨论),那么不会发生这种情况

    15、,因为某卡读到了AT response说明之前该卡发过AT command request,它发AT command的时候,就会阻塞住,一直等AT response,不会让其他卡有发AT command的机会。所以,当收到AT response时,不用判断response_card_id和 request_card_id是否相等,就可以直接解除AT command的阻塞了。接触阻塞之后的request dispatch thread在RIL_onRequestComplete()里把request_card_id 和经过解析的response一起封到parcel里,通过socket传给fram

    16、ework层。下图是AT reader thread的程序流程图,其中蓝色部分是针对多卡功能的修改。035. 修改上报radio state的方法原始的android RIL代码只用一个变量sState来表示卡的radio state,要支持多卡,就必须用一个数组sState MAX_CARD_NUM来表示所有卡的radio state。除了与framework层的socket通信刚建立时的radio state是非请求的主动上报外,其余的radio state都是framework通过request radio power获取的。下图是RIL处理request radio power的程序流

    17、程图,其中蓝色部分是针对多卡功能的修改。04下图是android原始的framework收到RIL上报的radio state后的相应动作的程序流程图:四、 技术要点备忘1. 表示多卡中哪一张卡的信息,用全局变量表示还是使用参数传递的选择使用参数传递的方法对代码的改动量很大,需要给很多相关函数增加相应的表示哪张卡的参数。使用两个全局变量 request_card_id和response_card_id,大大简化改造工作,因为rild是守护进程,只会运行一个,request_card_id和response_card_id只会被一个线程使用,不存在多线程安全问题。 2. 读取多卡时使用多线程还是

    18、select的选择 如果不使用select同时检测多张卡,那么就要对每张卡开一个线程来读取信息,这将使改造工作很复杂。 3. 多卡功能使atchannel.c中的readerLoop()的情况变复杂,要针对各种情景进行修改。情景1:一张卡一次主动上报了大量信息,里面包含了若干行信息,都缓存到read buffer里了,readline()只能一次返回一行数据进行处理,如果在处理完所有信息行之前,另一张卡产生response了,select检测到它的fd可读,于是response card id改为这张的id了,之前缓存在read buffer里的数据就都被误认为是这张卡的了。要避免这种情况产生

    19、,就需要在一张卡可读时,把该卡缓存在read buffer中的response全都处理完。情景2:比如发送下面查询网络注册状态的AT指令:AT+CREG?response返回下面两行:+CREG: 1, 1, 0408, 5C15OKresponse的每一行都是以rn结尾的,readline()根据行尾的r或n得知读取到一行,对于上面的两行response,line = readline()将被调用两次,line是指向所读到的当前行的指针。第一行不是final response,程序会调用addIntermediate(line)把它们保存起来,等到作为final response的“OK”返

    20、回时,因发送查询网络状态请求“AT+CREG?”而阻塞的AT command thread才解除阻塞。如果在读取到 +CREG: 1, 1, 0408, 5C15 时,其它卡突然主动上报了一个网络状态的信息,主动上报的前缀+CREG与上一张卡AT+CREG? 的response的前缀一样,AT command thread会误以为这是上一张卡的response的信息而错误地用addIntermediate(line)来保存信息。有两种解决方法:一是,在addIntermediate(line)之前判断response card id与request card id是否相等,相等才add,不相等

    21、就认为是主动上报或短信;二是,一旦某张卡开始接收AT command response,就一直针对这张卡循环调用readline()和processline(),直到该AT command response完全被处理完毕。我们采用第二种方法,因为这种方法代码修改起来相对简单。情景3:当读到下面的response:OKreadline()会返回指向”OK”的指针,同时s_ATBufferCur跳过,指向了。再次调用readline()时,readline()首先判断s_ATBufferCur是否为NULL,如果非NULL就认为s_ATBuffer里有未处理完的数据,但其实只有一个,这种情况下会再

    22、去阻塞地read,会一直阻塞住直到下次该卡可读为止,这期间,就算其他卡可读也没有机会去读了。这对于单卡可以容忍,但对于多卡显然是不合理的。综合解决方法:综合考虑上面三种情景,对atchannel.c的readerLoop()做了下面蓝色部分所示的修改。static void *readerLoop(void *arg) for (;) const char * line; memcpy(&rfds, &s_readFds, sizeof(fd_set); n = select(nfds, &rfds, NULL, NULL, NULL); for(i = 0; i card_slot_num(

    23、); i+) if (FD_ISSET(card_slot_infoi.fd, &rfds) s_read_fd = card_slot_infoi.fd; break; response_card_id = fd_to_card_id(s_read_fd); card_response_final = 1; / addIntermediate(line) can make it 0 for (;) line = readline(); if(isSMSUnsolicited(line) s_unsolHandler (line1, line2); else processLine(line)

    24、; if (card_response_final = 1) & ( *s_ATBufferCur = 0) | (*s_ATBufferCur = n) & (strlen(s_ATBufferCur) = 1) break; 当一张卡被select认为可读时,会循环调用readline()进行读取,退出循环的条件是(card_response_final = 1) & ( *s_ATBufferCur = 0) | (*s_ATBufferCur = n) & (strlen(s_ATBufferCur) = 1), 其中条件( *s_ATBufferCur = 0) | (*s_ATBu

    25、fferCur = n) & (strlen(s_ATBufferCur) = 1)避免了第一个和第三个情景的问题,条件(card_response_final = 1)避免了第二个情景的问题。4. 如果有多个modem,可以把没插卡的modem关闭,以节省功耗但如果所有的modem都没插卡,那么不能都把它们都关闭,要留一个开着,否则不能打紧急电话。这种情况下是默认把card_slot_info0对应的modem打开。对于没有插卡的卡槽,不必让select监视它是否可读,最好从fd set中把它的fd删除,因为内核对select实现是轮询方式,监听的fd越多,越费时间,但考虑多监听一两个空卡槽

    26、对效率影响可以忽略不计,所以这个改进目前还没实现。一般需要考虑select效率的是网络服务器,它可能需要监听几千个fd,而有些fd很不活跃,这时就要考虑用epoll来替代select,epoll可以根据fd的活跃度调整监听策略。5. 智能识别卡槽如果手机modem支持的卡槽个数大于手机实际拥有的卡槽个数,那么就要使用卡槽的智能识别。比如某手机里有一个支持双卡的GSM modem和一个支持单卡的EVDO modem,理论上需要安装三个卡槽,但受到手机内部空间的限制,只能存在两个卡槽,插入这两个卡槽的卡的组合可能是:G卡+G卡,G卡+C卡和C卡+G卡。C卡必须接在EVDO modem上,G卡必须连

    27、在GSM modem上,所以卡槽和modem连接需要智能调节。本文以这种情况为例,说明一下智能识别卡槽的方法。初始状态让卡槽1和卡槽2都默认连接在GSM modem上(如上图所示),这种初始状态可以让探测卡槽过程中切换卡槽次数最少。为了让程序健壮,考虑了插卡的各种组合情况:G+G,G+C,C+G,C+C,错卡+G或C。具体实现的程序流程图如下:056. linux内核中和modem相关的驱动drivers/misc/jz_modem.c :hardware ril通过该文件实现的ioctl来控制各modem底层行为,如上电、复位、切换卡槽、切换音频连接等。在hardware ril中,ioct

    28、l的case相关的宏定义位于reference-ril/misc.h,这些定义要和jz_modem.c中的定义一致。drivers/input/misc/jz_ringin.c :处理在cpu休眠时,modem的ring in中断把cpu唤醒。五、 针对RIL多卡的具体代码在android源码根目录下,cd hardware/rilsvn diff -r673:HEAD 六、 参考资料1. Advanced Programming in the UNIX Environment(关于socket、select和pthread的相关知识)2. 各modem的AT指令集文中程序流程图采用Microsoft Office Visio 2003绘制。


    注意事项

    本文(rilmulticard.docx)为本站会员主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(点击联系客服),我们立即给予删除!

    温馨提示:如果因为网速或其他原因下载失败请重新下载,重复下载不扣分。




    关于我们 - 网站声明 - 网站地图 - 资源地图 - 友情链接 - 网站客服 - 联系我们

    copyright@ 2008-2022 冰点文档网站版权所有

    经营许可证编号:鄂ICP备2022015515号-1

    收起
    展开