Android的電話功能介紹——整個(gè)RIL文件夾的分析_第1頁(yè)
Android的電話功能介紹——整個(gè)RIL文件夾的分析_第2頁(yè)
Android的電話功能介紹——整個(gè)RIL文件夾的分析_第3頁(yè)
Android的電話功能介紹——整個(gè)RIL文件夾的分析_第4頁(yè)
Android的電話功能介紹——整個(gè)RIL文件夾的分析_第5頁(yè)
已閱讀5頁(yè),還剩66頁(yè)未讀 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

1、 Android 的電話功能介紹整個(gè) RIL 文件夾的分析 介紹 本文檔對(duì) Android RIL 部分的內(nèi)容進(jìn)行了介紹,其重點(diǎn)放在了Android RIL 的原生代碼 部分。包括四個(gè)主題: 1. Android RIL 框架介紹 2. Android RIL 與 WindowsMobile RIL 3. Android RIL porting 4. Android RIL 的 java 框架 在本文檔中將 Android 代碼中的重要模塊列出進(jìn)行分析, 并給出了相關(guān)的程序執(zhí)行流程 介紹,以加深對(duì)模塊間交互方式的理解。 對(duì)于 java 代碼部分,這里僅進(jìn)行簡(jiǎn)單的介紹。如果需要深入了解,可以查看

2、相關(guān)參考 資料。 本文檔中還對(duì) Android RIL 的 Porting 部分內(nèi)容進(jìn)行了描述和分析。 針對(duì)對(duì) Linux 操作系統(tǒng)環(huán)境并不熟悉的讀者,本文檔中所涉及到的相關(guān)知識(shí)包括: Linux file system Linux socket Linux thread Linux 下 I/O 多路轉(zhuǎn)接 以上信息可以在任意一份描述 Linux 系統(tǒng)調(diào)用的文檔中找到。 1.Android RIL 框架介紹 術(shù)語(yǔ): fd pipe cond tty unsolicited response event loop init.rc HAL Linux 文件描述符 Linux 管道 一般是 condi

3、tion variable 的縮寫(xiě) 通常使用 tty 來(lái)簡(jiǎn)稱各種類型的終端設(shè)備 被動(dòng)請(qǐng)求命令來(lái)自 baseband android 的消息隊(duì)列機(jī)制,由 Linux 的系統(tǒng)調(diào)用 select() 實(shí)現(xiàn) init 守護(hù)進(jìn)程啟動(dòng)后被執(zhí)行的啟動(dòng)腳本。 硬件抽象層( Hardware Abstraction Layer , HAL ) 1.1 Android RIL 概況: RIL 在 Android Android RIL 提供了無(wú)線硬件設(shè)備與電話服務(wù)之間的抽象層。下圖展示了 體系中的位置。 android 的 ril 位于應(yīng)用程序框架與內(nèi)核之間,分成了兩個(gè)部分,一個(gè)部分是rild, 它負(fù)責(zé) sock

4、et 與應(yīng)用程序框架進(jìn)行通信。另外一個(gè)部分是Vendor RIL,這個(gè)部分負(fù)責(zé)向下是通過(guò)兩 種方式與 radio 進(jìn)行通信,它們是直接與 radio 通信的 AT 指令通道和用于傳輸包數(shù)據(jù)的通道, 數(shù)據(jù)通道用于手機(jī)的上網(wǎng)功能。 對(duì)于 RIL的 java 框架部分,也被分成了兩個(gè)部分,一個(gè)是RIL模塊,這個(gè)模塊主要用于 與下層的 rild 進(jìn)行通信, 另外一個(gè)是 Phone 模塊, 這個(gè)模塊直接暴露電話功能接口給應(yīng)用開(kāi) 發(fā)用戶,供他們調(diào)用以進(jìn)行電話功能的實(shí)現(xiàn)。 1.2 Android RIL 目錄結(jié)構(gòu) : Android 的 RIL 模塊位于 Android/hardware/ril 文件夾,有

5、三個(gè)子模塊: rild , libril reference-ril 所在目錄結(jié)構(gòu): /hardware/ril/ |- ril (無(wú)線電抽象層) | |- include (頭文件) | |- libril (庫(kù)) | |- reference-cdma-sms ( cdma 短信參考) | |- reference-ril ( ril 參考) | |- rild ( ril 后臺(tái)服務(wù)程序) hardware/ril$ ls include libril reference-cdma-sms reference-ril rild 1. hardware/ril/rild$ ls Androi

6、d.mk MODULE_LICENSE_APACHE2 NOTICE radiooptions.c rild.c 2. hardware/ril/include/telephony$ ls ril_cdma_sms.h ril.h 3. hardware/ril/libril$ ls Android.mk NOTICE ril_event.h ril.cpp ril_event.cpp ril_commands.h ril_unsol_commands.h MODULE_LICENSE_APACHE2 4. hardware/ril/reference-cdma-sms$ ls Android

7、.mk reference-cdma-sms.c reference-cdma-sms.h 5. hardware/ril/reference-ril$ ls Android.mk atchannel.h at_tok.h misc.h NOTICE atchannel.c at_tok.c ril_event.h reference-ril.c misc.c MODULE_LICENSE_APACHE2 Android 的 Radio Interface Layer (RIL)提供了電話服務(wù)和的 radio 硬件之間的抽象層。 Radio Interface Layer RIL(Radio

8、Interface Layer)負(fù)責(zé)數(shù)據(jù)的可靠傳輸、 AT 命令的發(fā)送以及 response 的解析。應(yīng)用處理器通過(guò) AT 命令集與帶 GPRS功能的無(wú)線通訊模塊通信。 AT command由 Hayes公司發(fā)明, 是一個(gè)調(diào)制解調(diào)器制造商采用的一個(gè)調(diào)制解調(diào)器命令 語(yǔ)言,每條命令以字母 AT開(kāi)頭。 JAVA Framework 代碼的路徑為: frameworks/base/telephony/java/android/telephony android.telephony 以及 android.telephony.gsm Core native: 在 hardware/ril 目錄中,提供了對(duì)

9、 RIL 支持的本地代碼,包括 4 個(gè)文件夾: hardware/ril/include hardware/ril/libril hardware/ril/reference-ril hardware/ril/rild kernel Driver 在 Linux 內(nèi)核的驅(qū)動(dòng)中,提供了相關(guān)的驅(qū)動(dòng)程序的支持,可以建立在UART 或者 SDIO, USB等高速的串行總線上。 電話功能各個(gè)部分: hardware/ril/include/telephony/ 目錄中的 ril.h 文件是 ril 部分的基礎(chǔ)頭文件。 其中定義的結(jié)構(gòu)體 RIL_RadioFunctions 如下所示: typedef s

10、truct int version; RIL_RequestFunc onRequest; RIL_RadioStateRequest onStateRequest; RIL_Supports supports; RIL_Cancel onCancel; RIL_GetVersion getVersion; RIL_RadioFunctions; RIL_RadioFunctions 中包含了幾個(gè)函數(shù)指針的結(jié)構(gòu)體,這實(shí)際上是一個(gè)移植層的接口,下 層的庫(kù)實(shí)現(xiàn)后,由 rild 守護(hù)進(jìn)程得到這些函數(shù)指針,執(zhí)行對(duì)應(yīng)的函數(shù)。 幾個(gè)函數(shù)指針的原型為: typedef void (*RIL_RequestF

11、unc) (int request, void *data, size_t datalen, RIL_Token t); typedef RIL_RadioState (*RIL_RadioStateRequest)(); typedef int (*RIL_Supports)(int requestCode); typedef void (*RIL_Cancel)(RIL_Token t); typedef const char * (*RIL_GetVersion) (void); 其中最為重要的函數(shù)是 onRequest() ,它是一個(gè)請(qǐng)求執(zhí)行的函數(shù)。 2.1 rild 守護(hù)進(jìn)程 ril

12、d 守護(hù)進(jìn)程的文件包含在 hardware/ril/rild 目錄中,其中包含了 rild.c 和 radiooptions.c 兩個(gè)文件, 這個(gè)目錄中的文件經(jīng)過(guò)編譯后生成一個(gè)可執(zhí)行程序, 這個(gè)程序在系統(tǒng)的安裝路徑 在: /system/bin/rild rild.c 是這個(gè)守護(hù)進(jìn)程的入口,它具有一個(gè)主函數(shù)的入口main ,執(zhí)行的過(guò)程是將上層來(lái) 的請(qǐng)求都由這個(gè)函數(shù) RIL_RadioFunctionsonReques() 的方法進(jìn)行映射后轉(zhuǎn)換成對(duì)應(yīng)的AT 命令的字符串,發(fā)給下層的硬件執(zhí)行。在運(yùn)行過(guò)程中,使用dlopen 打開(kāi)路徑為 /system/lib/ 中名稱為 libreference-

13、ril.so 的動(dòng)態(tài)庫(kù),然后從中取出 RIL_Init 符號(hào)來(lái)運(yùn)行。 ril_register() 注冊(cè): RIL_Init 符號(hào)是一個(gè)函數(shù)指針,執(zhí)行這個(gè)函數(shù)后,返回的是一個(gè) RIL_RadioFunctions 類型的指針。得到這個(gè)指針后, 調(diào)用 RIL_register()函數(shù),將這個(gè)指針注冊(cè) 到 libril 庫(kù)之中,然后進(jìn)入循環(huán) ril_event_loop() 。 事實(shí)上,這個(gè)守護(hù)進(jìn)程提供了一個(gè)申請(qǐng)?zhí)幚淼目蚣埽唧w的功能都是在 libril.so 和 libreference-ril.so 中完成的。 附: RIL守護(hù)進(jìn)程,開(kāi)機(jī)時(shí)被 init 守護(hù)進(jìn)程調(diào)用啟動(dòng),里面僅有 main

14、函數(shù)作為入口點(diǎn),負(fù)責(zé) 完成 RIL 初始化工作。 在 rild.c 文件中,將完成 ril 的加載過(guò)程,它會(huì)執(zhí)行如下操作: 動(dòng)態(tài)加載 Vendor RIL的.so 文件 執(zhí)行 RIL_startEventLoop() 開(kāi)啟消息隊(duì)列以進(jìn)行事件監(jiān)聽(tīng) 通過(guò)執(zhí)行 Vendor RIL的 rilInit() 方法來(lái)進(jìn)行 Vendor RIL 與 libril 的關(guān)系建立。 在 rild 文件夾中還包括一個(gè) radiooptions.c 文件 , 它的作用是通過(guò)串口將一些 radio 相關(guān)的 參數(shù)直接傳給 rild 來(lái)對(duì) radio 進(jìn)行配置。 2.2 libreference-ril.so 動(dòng)態(tài)庫(kù) li

15、breference-ril.so 動(dòng)態(tài)庫(kù)的路徑是: hardware/ril/reference-ril 其中主要的文件是 reference-ril.c 和 atchannel.c 。這個(gè)庫(kù)必須實(shí)現(xiàn)的是一個(gè)名稱為 RIL_Init 的函數(shù),這個(gè)函數(shù)執(zhí)行的結(jié)果是返回一個(gè) RIL_RadioFunctions 結(jié)構(gòu)體的指針,指針指向函數(shù) 指針。 這個(gè)庫(kù)在執(zhí)行的過(guò)程中需要?jiǎng)?chuàng)建一個(gè)線程來(lái)執(zhí)行實(shí)際的功能。 在執(zhí)行的過(guò)程中, 這個(gè)庫(kù) 將打開(kāi)一個(gè) /dev/ttySXXX 的終端(終端的名字是從上層傳入的) ,然后利用這個(gè)終端控制硬 件執(zhí)行。 附: 在編譯時(shí) libril 被鏈入 rild, 它為 ri

16、ld 提供了 event 處理功能,還提供了在 rild 與 Vendor RIL 之間傳遞請(qǐng)求和響應(yīng)消息的能力。 Libril 提供的主要功能分布在兩個(gè)主要方法內(nèi), 一個(gè)是 RIL_startEventLoop()方法, 另一個(gè) 是 RIL_register()方法 RIL_startEventLoop()方法所提供的功能就是啟用 eventLoop 線程,開(kāi)始執(zhí)行 RIL消息隊(duì)列。 RIL_register()方法的主要功能是啟動(dòng)名為 rild 的監(jiān)聽(tīng)端口,等待 java 端通過(guò) socket 進(jìn)行 連接。 2.3 libril.so 動(dòng)態(tài)庫(kù) libril.so 庫(kù)的目 錄是: hardw

17、are/ril/libril 其中主要的文件為 ril.cpp ,這個(gè)庫(kù)主要需要實(shí)現(xiàn)的以下幾個(gè)接口為: RIL_startEventLoop(void); void RIL_setcallbacks (const RIL_RadioFunctions *callbacks); RIL_register (const RIL_RadioFunctions *callbacks); RIL_onRequestComplete(RIL_Token t, RIL_Errno e, void *response, size_t responselen); void RIL_onUnsolicitedRe

18、sponse(int unsolResponse, void *data, size_t datalen); RIL_requestTimedCallback (RIL_TimedCallback callback, void *param, const struct timeval *relativeTime); 這些函數(shù)也是被 rild 守護(hù)進(jìn)程調(diào)用的, 不同的 vendor 可以通過(guò)自己的方式實(shí)現(xiàn)這幾個(gè)接 口,這樣可以保證 RIL 可以在 不同系統(tǒng)的移植。其中 RIL_register()函數(shù)把外部的 RIL_RadioFunctions 結(jié)構(gòu)體注冊(cè)到這個(gè)庫(kù)之中,在恰當(dāng)?shù)臅r(shí)候調(diào)用相應(yīng)的函

19、數(shù)。在執(zhí)行的過(guò) 程中,這個(gè)庫(kù)處理了一些將請(qǐng)求轉(zhuǎn)換成字符串的功能。 附: Android 自帶的 VendorRIL 的參考實(shí)現(xiàn)。被編譯成 .so 文件,由于本部分是廠商定制的重 點(diǎn)所在。所以被設(shè)計(jì)為松散耦合,且可靈活配置的。在 rild 中通過(guò) opendl() 的方式加載。 librefrence.so 負(fù)責(zé)直接與 radio 通信,這包括將來(lái)自 libril 的指令轉(zhuǎn)換為 AT 指令,并且 將 AT 指令寫(xiě)入 radio 中。 reference-ril 會(huì)接收調(diào)用者傳來(lái)的參數(shù), 參數(shù)內(nèi)容為與 radio 的通信方式。 如通過(guò)串口連 接 radio, 那么參數(shù)為這種形式: -d /dev/

20、ttySx 2.4 ril 層的所有代碼分析 2.4.1 ril/rild 下的文件 rild.c-mian() 為函數(shù)入口 int main(int argc, char *argv) / / OpenLib: #endif switchUser(); / 打開(kāi) dlopen() 加載 vendor RIL 獲取由 RIL_register(funcs); 注冊(cè)進(jìn)來(lái)的參數(shù),并解析 dlHandle = dlopen(rilLibPath, RTLD_NOW); if (dlHandle = NULL) fprintf(stderr, dlopen failed: %sn, dlerror()

21、; exit(-1); /1:消息隊(duì)列的入口 1.到 select 阻塞/每當(dāng)看到打印信息,不按順序打下來(lái)說(shuō)明阻塞 RIL_startEventLoop(); / 通過(guò) dlsym 函數(shù)得到 rilInit 函數(shù)指針的引用 rilInit = (const RIL_RadioFunctions *(*)(const struct RIL_Env *, int, char *)dlsym(dlHandle, RIL_Init); if (rilInit = NULL) fprintf(stderr, RIL_Init not defined or exported in %sn, rilLibP

22、ath); exit(-1); if (hasLibArgs) rilArgv = argv + i - 1; argc = argc -i + 1; else static char * newArgvMAX_LIB_ARGS; static char argsPROPERTY_VALUE_MAX; rilArgv = newArgv; property_get(LIB_ARGS_PROPERT, Yargs, ); argc = make_argv(args, rilArgv); / Make sure theres a reasonable argv0 rilArgv0 = argv0;

23、 / 2:利用得到的 rilInit 函數(shù)指針,調(diào)用真正的 RIL_Init funcs = rilInit( RIL_register(funcs); done: while(1) / sleep(UINT32_MAX) seems to return immediately on bionic sleep(0 x00ffffff); 2.4.2 ril/libril-ril.cpp 中 RIL_startEventLoop() 函數(shù)分析 RIL_startEventLoop(void) int ret; pthread_attr_t attr; LOGD(-2-ril.cpp-RIL_st

24、artEventLoop-); /* spin up eventLoop thread and wait for it to get started */ s_started = 0; pthread_mutex_lock( pthread_attr_init ( pthread_attr_setdetachstate( LOGD(-1-ril.cpp-kai-kou-pthread_create(); ret = pthread_create(/ 創(chuàng)建線程,為入口函數(shù) LOGD(-2-ril.cpp-tiao-chu-rpthread_create(); while (s_started =

25、 0) pthread_cond_wait( pthread_mutex_unlock( if (ret fd = fd; ev-index = -1; ev-persist = persist; ev-func = func; ev-param = param; fcntl(fd, F_SETFL, O_NONBLOCK); 3.1processWakeupCallback static void processWakeupCallback(int fd, short flags, void *param) char buff16; int ret; -); LOGV(processWake

26、upCallback); /* empty our wakeup socket out */ do ret = read(s_fdWakeupRead, while (ret 0 | (ret 0 4. -rilEventAddWakeup ( static void rilEventAddWakeup(struct ril_event *ev) LOGD(-2.7-rilEventAddWakeup-write-tiao-ru- ril_event_add(ev);-); ril_event_add(ev); LOGD(-2.8-ril_event_add(ev);-tiao-chu-);

27、triggerEvLoop(); 在 ril/libril/ril_event.cpp 實(shí)現(xiàn) 4.1-void ril_event_add(struct ril_event * ev) LOGD(-RIL_evnent.cpp-shi-xian-void ril_event_add(struct ril_event * ev); dlog( +ril_event_add ); MUTEX_ACQUIRE(); for (int i = 0; i index = i; dlog( added at %d , i); dump_event(ev); /2: FD_SET(ev-fd, if (ev

28、-fd = nfds) nfds = ev-fd+1; dlog( nfds = %d , nfds); break;ENTS; i+) if (watch_tablei = NU MUTEX_RELEASE(); dlog( -ril_event_add ); 4.2-static void triggerEvLoop() int ret; LOGD(- ret = write (s_fdWakeupWrite, , 1);-); if (!pthread_equal(pthread_self(), s_tid_dispatch) /* trigger event loop to wakeu

29、p. No reason to do this, * if were in the event loop thread */ do ret = write (s_fdWakeupWrite, , 1); while (ret 0 5. ril_event_loop(); -RIL 層代碼分析 -RIL_RadioFunctions *RIL_Init(funcs =rilInit()-mainloop() ril/rild/rild.c-main() 為函數(shù)入口 1. 消息隊(duì)列 select 為非阻塞的去輪詢事件 2. read 的阻塞的去讀取上層發(fā)下來(lái)的命令 ,并響應(yīng) int main(in

30、t argc, char *argv) const char * rilLibPath = NULL; char *rilArgv; void *dlHandle; const RIL_RadioFunctions *(*rilInit)(const struct RIL_Env *, int, char *); const RIL_RadioFunctions *funcs; char libPathPROPERTY_VALUE_MAX; unsigned char hasLibArgs = 0; OpenLib: #endif switchUser(); /* 打開(kāi) dlopen() 函數(shù)

31、,就會(huì)動(dòng)態(tài)去加載動(dòng)態(tài)庫(kù) vendor RIL 獲取由 RIL_register(funcs); 注冊(cè)進(jìn)來(lái)的參數(shù),并解析 */ dlHandle = dlopen(rilLibPath, RTLD_NOW); if (dlHandle = NULL) fprintf(stderr, dlopen failed: %sn, dlerror(); exit(-1); /*消息隊(duì)列的入口 ,添加到 select ,用阻塞方式去讀取那些 ril_event_set() 的數(shù)據(jù) #每當(dāng)看到打印信息,不按順序打下來(lái) 說(shuō)明阻塞 #*/ RIL_startEventLoop(); /* 通過(guò) dlsym 函數(shù)得

32、到 rilInit 函數(shù)指針的引用 */ rilInit = (const RIL_RadioFunctions *(*)(const struct RIL_Env *, int, char *)dlsym(dlHandle, RIL_Init); if (rilInit = NULL) fprintf(stderr, RIL_Init not defined or exported in %sn, rilLibPath); exit(-1); if (hasLibArgs) rilArgv = argv + i - 1; argc = argc -i + 1; else static cha

33、r * newArgvMAX_LIB_ARGS; static char argsPROPERTY_VALUE_MAX; rilArgv = newArgv; property_get(LIB_ARGS_PROPERTY, args, ); argc = make_argv(args, rilArgv); / Make sure theres a reasonable argv0 rilArgv0 = argv0; /*利用得到的 rilInit 函數(shù)指針,調(diào)用真正的 RIL_Init ,實(shí)際是動(dòng)態(tài)加載動(dòng)態(tài)庫(kù)去鏈接 reference-ril.c ,由 dlopen()函數(shù)加載 */ func

34、s = rilInit( /*RIL_register 作用一:把 vendor RIL( 即 RIL_init) 注冊(cè)到 reference-ril 庫(kù)去等待, dopen() 函數(shù)加載鏈接 附:RIL_init 通過(guò)是 onRequest() 方法,將上層來(lái)的請(qǐng)求進(jìn)行映射后轉(zhuǎn)換成對(duì)應(yīng)的 AT 命令發(fā)給硬件,rild 通過(guò) RIL_register 注冊(cè)這一指針。 RIL_register 作用二:創(chuàng)建 rild socket 主要是等待 java 層得數(shù)據(jù)通過(guò),傳到下一層,還創(chuàng)建 debug socket*/ RIL_register(funcs); done: while(1) / sl

35、eep(UINT32_MAX) seems to return immediately on bionic sleep(0 x00ffffff); 所有文件: hardware/ril/reference-ril$ ls Android.mk atchannel.h at_tok.h misc.h NOTICE atchannel.c at_tok.c ril_event.h reference-ril.c misc.c MODULE_LICENSE_APACHE2 在編譯時(shí) libril 被鏈入 rild, 它為 rild 提供了 event 處理功能,還提供了在 rild 與 Vendor

36、 RIL 之間傳遞請(qǐng)求和響應(yīng)消息的能力。 libril.so 駐留在 rild 這一守護(hù)進(jìn)程中,主要完成同上層通信的工作,接受 ril 請(qǐng)求并傳遞給 librefrence_ril.so , 同 時(shí)把來(lái)自 librefrence_ril.so 的反饋回傳給調(diào)用進(jìn)程。 librefrence.so 負(fù)責(zé)直接與 modem通信,這包括將來(lái)自 libril 的指令轉(zhuǎn)換為 AT 指令,并且將 AT 指令寫(xiě)入 modem中。 reference-ril 會(huì)接收調(diào)用者傳來(lái)的參數(shù),參數(shù)內(nèi)容為與 radio 的通信方式。 如通過(guò)串口連接 modem那, 么參數(shù)為這種形式: -d /dev/ttySx func

37、s =rilInit(/ 實(shí)際是通過(guò)動(dòng)態(tài)加載動(dòng)態(tài)庫(kù)的方式執(zhí)行 reference-ril.c 中的 RIL_Init reference-ril/reference-ril.c -RIL_RadioFunctions *RIL_Init() 函數(shù) const RIL_RadioFunctions *RIL_Init(const struct RIL_Env *env, int argc, char *argv) int ret; int fd = -1; int opt; pthread_attr_t attr; s_rilenv = env; LOGD(-referencen_ril.c-

38、RIL_RadioFunctions -shi-xian-*RIL_Init); while ( -1 != (opt = getopt(argc, argv, p:d:s:) switch (opt) case p: s_port = atoi(optarg); if (s_port = 0) usage(argv0); return NULL; LOGI(Opening loopback port %dn, s_port); break; /獲取 dev/ttyUSB ,只是打開(kāi)而已,是否獲取,由線程 mainLoop 執(zhí)行完才知道 case d: s_device_path = opta

39、rg; LOGI(Opening tty device %sn, s_device_path); break; case s: s_device_path = optarg; s_device_socket = 1; LOGI(Opening socket %sn, s_device_path); break; default: usage(argv0); return NULL; if (s_port readloop ()-line() 方法阻塞等待是否又?jǐn)?shù)據(jù) 過(guò)來(lái),并向硬件主動(dòng)上報(bào)或響應(yīng)( OK )。 發(fā)命令的是由 initializeCallback ()發(fā)過(guò)來(lái)的 ATE0Q0V1 等

40、 1.打開(kāi) rild socket (init.rc 傳過(guò)來(lái)的)是用于等待 read()后 java 層傳來(lái)的數(shù)據(jù) (再去調(diào) nitializeCallback 發(fā) at 命令 ) 2. 就是調(diào)用 RIL_requestTimedCallback( initializeCallback , NULL, 函數(shù),用來(lái)向 modem 發(fā)生 AT 命令 static void * mainLoop(void *param) LOGD(shi-xian-mainLoop); LOGI(in mainLoopn); int fd; int ret; static struct timeval TIMEVA

41、L_DELAYINIT = 0,0;/ 延時(shí)函數(shù) AT_DUMP(= , entering mainLoop(), -1 ); at_set_on_reader_closed(onATReaderClosed); at_set_on_timeout(onATTimeout); for (;) fd = -1; while (fd 0) fd = socket_loopback_client(s_port, SOCK_STREAM); else if (s_device_socket) if (!strcmp(s_device_path, /dev/socket/qemud) /* Qemu-s

42、pecific control socket */ /1: LOGD(-1socket_local_client-after-qian-yi-ge-); fd = socket_local_client( qemud,ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_STREAM ); if (fd = 0 ) char answer2; if ( write(fd, gsm, 3) != 3 | read(fd, answer, 2) != 2 | memcmp(answer, OK, 2) != 0) close(fd); fd = -1; else /1:

43、LOGD(-2-socket_local_client-after-hou-yi-ge-); fd = socket_local_client( s_device_path, ANDROID_SOCKET_NAMESPACE_FILESYSTEM, SOCK_S TREAM ); else if (s_device_path != NULL) fd = open (s device path, O RDWR); if ( fd = 0 ) /* disable echo on serial ports */ struct termios ios; tcgetattr( fd, ios.c_lf

44、lag = 0; /* disable ECHO, ICANON, etc. */ tcsetattr( fd, TCSANOW, LOGI(-open() sucessn); else LOGI(-open() failedn); if (fd 0) perror (opening AT interface. retrying.); sleep(10); /* never returns */ s_closed = 0; /2: LOGD(-jin-ru-at_open-); ret = at_open(fd, onUnsolicited); if (ret ATE0Q0V1 / Give

45、initializeCallback a chance to dispatched, since / we dont presently have a cancellation mechanism sleep(1); waitForClose(); LOGI(Re-opening after close); at_open() 的作用: 1.可以添加自己想要的 modem 2. 函數(shù)建立起這一設(shè)備文件上的 reader 等待循環(huán) * Starts AT handler on stream fd * returns 0 on success, -1 on error */ int at_open

46、(int fd, ATUnsolHandler h) int ret; pthread_t tid; pthread_attr_t attr; LOGD(-shi-xian -at_open); s_fd = fd; s_unsolHandler = h; s_readerClosed = 0; s_responsePrefix = NULL; s_smsPDU = NULL; sp_response = NULL; /* Android power control ioctl */ #ifdef HAVE_ANDROID_OS #ifdef OMAP_CSMI_POWER_CONTROL r

47、et = ioctl(fd, OMAP_CSMI_TTY_ENABLE_ACK); if(ret = 0) int ack_count; int read_count; int old_flags; char sync_buf256; old_flags = fcntl(fd, F_GETFL, 0); fcntl(fd, F_SETFL, old_flags | O_NONBLOCK); do ioctl(fd, OMAP_CSMI_TTY_READ_UNACKED, read_count = 0; do ret = read(fd, sync_buf, sizeof(sync_buf);

48、if(ret 0) read_count += ret; while(ret 0 | (ret 0 | read_count 0); fcntl(fd, F_SETFL, old_flags); s_readCount = 0; s_ackPowerIoctl = 1; else s_ackPowerIoctl = 0; #else / OMAP_CSMI_POWER_CONTROL s_ackPowerIoctl = 0; #endif / OMAP_CSMI_POWER_CONTROL #endif /*HAVE_ANDROID_OS*/ pthread_attr_init ( pthre

49、ad_attr_setdetachstate( #ifdef HUAWEI_EM770W /新增的 modem ,在創(chuàng)建一個(gè)線程去實(shí)現(xiàn)它的功能 int fd2 = -1; while(fd2 0) fd2 = open (/dev/ttyUSB2, O_RDWR); if (fd2 0) urc_fd = fd2; struct termios ios; tcgetattr( fd2, ios.c_lflag = 0; tcsetattr( fd2, TCSANOW, ret = pthread_create( if (ret 0) perror (pthread_create); retur

50、n -1; #else LOGD(-at_openru-kou-ret = pthread_create(); ret = pthread create( if (ret 0) /* acknowledge that bytes have been read and processed */ ioctl(s_fd, OMAP_CSMI_TTY_ACK, s_readCount = 0; #endif /*HAVE_ANDROID_OS*/ onReaderClosed(); return NULL; * Reads a line from the AT channel, returns NUL

51、L on timeout. * Assumes it has exclusive read access to the FD * This line is valid only until the next call to readline * This function exists because as of writing, android libc does not * have buffered stdio. */ static const char *readline() ssize_t count; char *p_read = NULL; char *p_eol = NULL;

52、 char *ret; LOGD(shi-xian-readline); /* this is a little odd. I use *s_ATBufferCur = 0 to * mean buffer consumed completely. If it points to a character, than * the buffer continues until a 0 */ if (*s_ATBufferCur = 0) /* empty buffer */ s_ATBufferCur = s_ATBuffer; *s_ATBufferCur = 0; p_read = s_ATB

53、uffer; else /* *s_ATBufferCur != 0 */ /* theres data in the buffer from the last read */ / skip over leading newlines while (*s_ATBufferCur = r | *s_ATBufferCur = n) s_ATBufferCur+; p_eol = findNextEOL(s_ATBufferCur); if (p_eol = NULL) /* a partial line. move it up and prepare to read more */ size_t

54、 len; len = strlen(s_ATBufferCur); memmove(s_ATBuffer, s_ATBufferCur, len + 1); p_read = s_ATBuffer + len; s_ATBufferCur = s_ATBuffer; /* Otherwise, (p_eol !- NULL) there is a complete line*/ /* that will be returned the while () loop below*/ while (p_eol = NULL) if (0 = MAX_AT_RESPONSE - (p_read -

55、s_ATBuffer) LOGE(ERROR: Input line exceeded buffern); /* ditch buffer and start over again */ s_ATBufferCur = s_ATBuffer; *s_ATBufferCur = 0; p_read = s_ATBuffer; do count = read(s_fd, p_read, MAX_AT_RESPONSE - (p_read - s_ATBuffer); while (count 0) AT_DUMP( , p_read, count ); s_readCount += count;

56、p_readcount = 0; / skip over leading newlines while (*s_ATBufferCur = r | *s_ATBufferCur = n) s_ATBufferCur+; p_eol = findNextEOL(s_ATBufferCur); p_read += count; else if (count = 0) /* read error encountered or EOF reached */ if(count = 0) LOGD(atchannel: EOF reached); else LOGD(atchannel: read err

57、or %s, strerror(errno); return NULL; /* a full line in the buffer. Place a 0 over the r and return */ ret = s_ATBufferCur; *p_eol = 0; s_ATBufferCur = p_eol + 1; /* this will always be = p_read,*/ /* and there will be a 0 at *p_read */ /在這打印 Modem 回應(yīng)的 OK 信息 LOGD(AT %sn, ret); return ret;/ 返回,讀取好的上面信

58、息 -RIL 層代碼分析 -RIL_startEventLoop()-eventLoop()-ril_event_ loop() ril/rild/rild.c-main() 為函數(shù)入口 1. 消息隊(duì)列 select 為非阻塞的去輪詢事件 2.read 的阻塞的去讀取上層發(fā)下來(lái)的命令 ,并響應(yīng) int main(int argc, char *argv) const char * rilLibPath = NULL; char *rilArgv; void *dlHandle; const RIL_RadioFunctions *(*rilInit)(const struct RIL_Env

59、*, int, char *); const RIL_RadioFunctions *funcs; char libPathPROPERTY_VALUE_MAX; unsigned char hasLibArgs = 0; OpenLib: #endif switchUser(); /* 打開(kāi) dlopen() 函數(shù),就會(huì)動(dòng)態(tài)去加載動(dòng)態(tài)庫(kù) vendor RIL 獲取由 RIL_register(funcs); 注冊(cè)進(jìn)來(lái)的參數(shù),并解析 */ dlHandle = dlopen(rilLibPath, RTLD_NOW); if (dlHandle = NULL) fprintf(stderr,

60、dlopen failed: %sn, dlerror(); exit(-1); /*消息隊(duì)列的入口 ,添加到 select ,用阻塞方式去讀取那些 ril_event_set() 的數(shù)據(jù) #每當(dāng)看到打印信息,不按順序打下來(lái) 說(shuō)明阻塞 #*/ RIL_startEventLoop(); /* 通過(guò) dlsym 函數(shù)得到 rilInit 函數(shù)指針的引用 */ rilInit = (const RIL_RadioFunctions *(*)(const struct RIL_Env *, int, char *)dlsym(dlHandle, RIL_Init); if (rilInit = NU

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論