亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Android GSM驅動模塊的示例分析

發布時間:2021-11-26 14:08:15 來源:億速云 閱讀:130 作者:柒染 欄目:移動開發

這篇文章給大家介紹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中。

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機制便能響應處理了。到這里啟動流程已經分析完畢。

關于Android GSM驅動模塊的示例分析就分享到這里了,希望以上內容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

综艺| 蒲江县| 连州市| 新邵县| 哈密市| 和政县| 海丰县| 盱眙县| 宜春市| 门源| 鲁甸县| 龙岩市| 阳原县| 德钦县| 抚远县| 客服| 上杭县| 沾益县| 敦化市| 诸城市| 岚皋县| 许昌市| 清河县| 凌云县| 安图县| 辽阳县| 临武县| 且末县| 长兴县| 林口县| 鹰潭市| 齐齐哈尔市| 咸宁市| 高安市| 嵊泗县| 灌云县| 平湖市| 托克逊县| 富源县| 鄂州市| 栾城县|