ril - 3

前文對request的分析, 終止在了at_send_command_full_nolock裏的writeline操作,因爲這裏完成命令寫出到硬件設備的操作,接下來就是等待硬件響應,也就是response的過程了。我們的分析也是從這裏開始。
response信息的獲取,是在第一篇初始化分析中,提到的readerLoop中。由readline函數以‘行’爲單位接收上來。
AT的response有兩種,一是主動上報的,比如網絡狀態,短信,來電等都不需要經過請求,有一unsolicited詞語專門描述。另一種纔是真正意義上的response,也就是命令的響應。

  這裏我們可以看到,所有的行,首先經過sms的自動上報篩選,因爲短信的AT處理通常比較麻煩,無論收發都單獨列出。這裏是因爲要即時處理這條短信消息(兩行,標誌+pdu),而不能拆開處理。處理函數爲onUnsolicited(由s_unsolHandler指向),我們等下介紹。

  除開sms的特例,所有的line都要經過processLine,我們來看看這個流程:

processLine
|----no cmd--->handleUnsolicited //主動上報
|----isFinalResponseSuccess--->handleFinalResponse //成功,標準響應
|----isFinalResponseError--->handleFinalResponse //失敗,標準響應
|----get '>'--->send sms pdu //收到>符號,發送sms數據再繼續等待響應
|----switch s_type--->具體響應 //命令有具體的響應信息需要對應分析

  我們這裏主要關注handleUnsolicited自動上報(會調用到前面smsUnsolicite也調用的onUnsolicite),以及switch s_type具體響應信息,另外具體響應需要handleFinalResponse這樣的標準響應來最終完成。

1. onUnsolicite(主動上報響應)
static void onUnsolicited (const char *s, const char *sms_pdu);

  短信的AT設計真是麻煩的主,以致這個函數的第二個參數完全就是爲它準備的。response的主要的解析過程,由at_tok.c中的函數完成,其實就是字符串按塊解析,具體的解析方式由每條命令或上報信息自行決定。這裏不再詳述,onUnsolicited只解析出頭部(一般是+XXXX的形式),然後按類型決定下一步操作,操作爲RIL_onUnsolicitedResponse和RIL_requestTimedCallback兩種。

a)RIL_onUnsolicitedResponse:

  將unsolicited的信息直接返回給上層。通過Parcel傳遞,將RESPONSE_UNSOLICITED,unsolResponse(request號)寫入Parcel先,然後通過s_unsolResponses數組,查找到對應的responseFunction完成進一步的的解析,存入Parcel中。最終通過sendResponse將其傳遞迴原進程。流程:
sendResponse-->sendResponseRaw-->blockingWrite-->write to s_fdCommand(前面建立起來的和上層框架的socket連接)
這些步驟之後有一些喚醒系統等其他操作。不再詳述。

  b)RIL_requestTimedCallback:

  通過event機制(參考文章二)實現的timer機制,回調對應的內部處理函數。通過internalRequestTimedCallback將回調添加到event循環,最終完成callback上掛的函數的回調。比如pollSIMState,onPDPContextListChanged等回調, 不用返回上層, 內部處理就可以。

  2. switch s_type(命令的具體響應)及handleFinalResponse(標準響應):

  命令的類型(s_type)在send command的時候設置(參考文章二),有NO_RESULT,NUMERIC,SINGLELINE,MULTILINE幾種,供不同的AT使用。比如AT+CSQ是singleline, 返回at+csq=xx,xx,再加一行OK,比如一些設置命令,就是no_result, 只有一行OK或ERROR。

  這幾個類型的解析都很相仿,通過一定的判斷(比較AT頭標記等),如果是對應的響應,就通過addIntermediate掛到一個臨時結果sp_response->p_intermediates隊列裏。如果不是對應響應,那它其實應該是穿插其中的自動上報,用onUnsolicite來處理。

  具體響應,只起一個獲取響應信息到臨時結果,等待具體分析的作用。無論有無具體響應,最終都得以標準響應handleFinalResponse來完成,也就是接受到OK,ERROR等標準response來結束,這是大多數AT命令的規範。 

  handleFinalResponse會設置s_commandcond這一object,也就是at_send_command_full_nolock等待的對象。到這裏,響應的完整信息已經完全獲得,send command可以進一步處理返回的信息了(臨時結果,以及標準返回的成功或失敗,都在sp_response中)。

  pp_outResponse參數將sp_response返回給調用at_send_command_full_nolock的函數。
繼續我們在文章二的分析的話,這個函數其實是requestDial,不過requestDial忽略了響應,所以我們另外看個例子,如requestSignalStrength,命令其實就是前面提到的at+csq:可以看到確實是通過at_send_command_singleline來進行的操作,response在p_response中。p_response如果返回失敗(也就是標準響應的ERROR等造成),則通過RIL_onRequestComplete發送返回數據給上層,結束命令。

  如果成功,則進一步分析p_response->p_intermediates, 同樣是通過at_tok.c裏的函數進行分析。並同樣將結果通過RIL_onRequestComplete返回。

RIL_onRequestComplete:
RIL_onRequestComplete和RIL_onUnsolicitedResponse很相仿,功能也一致。

  通過Parcel來傳遞迴上層,同樣是先寫入RESPONSE_SOLICITED(區別於RESPONSE_UNSOLICITED),pRI->token(上層傳下的request號),錯誤碼(send command的錯誤,不是AT響應)。如果有AT響應,通過訪問pRI->pCI->responseFunction來完成具體response的解析,並寫入Parcel。

  然後通過同樣的途徑:
sendResponse-->sendResponseRaw-->blockingWrite-->write to s_fdCommand

完成最終的響應傳遞。

  到這裏,我們分析了自動上報與命令響應,其實response部分,也就告一段落了,三篇分析RIL的文章也到此結束。

發佈了0 篇原創文章 · 獲贊 16 · 訪問量 16萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章