现在的位置: 首页 > 综合 > 正文

WinCE开发笔记 之 RIL

2013年12月13日 ⁄ 综合 ⁄ 共 3000字 ⁄ 字号 评论关闭

WinCE开发笔记 之 RIL

所有的AT指令都是异步的,CommandThread负责串行的下命令,
ResponseThread负责统一处理读上来的串口数据,包括回应和事件。

->rilmain.cpp的RIL_IOControl()
->msg.cpp的RIL_DeleteMsg()
  构造CNotificationData(pnd),设置Blob(Code,Index)
->atcmd.cpp的QueueCmd(,szCmd,,,,pnd,)
->atcmd.cpp的QueueCmdWithTimeout()
  构造CCommand(pCmd),传入szCmd和pnd
  把pCmd放入CRilInstanceHandle的m_pCmdList中
  把pCmd放入g_pCmdQ队列中,唤醒CommandThread

->atcmd.cpp的CRilHandle::CommandThread()
->comhand.cpp的CComHandle::SendRILCmdHandleRsp()
  ->rilhand.h的CRilHandle::StartWaitingForRsp()
    设置m_fWaitingForRsp=1 和 m_pCurrCommand=pCmd
  ->comhand.cpp的CComHandle::WriteCmdsToComPort()
    写串口
  读取g_pRspQ队列的回应信息(pRsp),由ResponseThread写入
  ->rilhand.h的CRilHandle::StopWaitingForRsp()
    设置m_fWaitingForRsp=0
  ->rilhand.cpp的CRilHandle::HandleRsp(rpCmd,pRsp)
    ->response.cpp的CResponse::ParseOKData()
      假如当初注册了ParseFunc()则释放原来的Blob,回调具体的处理函数
    取出最初的pnd
      ->rilhand.cpp的CRilHandle::BroadcastNotification(pnd)
    取出Blob
      ->command.cpp的CCommand::SendResponse(Code,Blob)
        假如当初没有设置CMDOPT_IGNORERSP的命令选项
          ->CRilInstanceHandle::Notify(Code,ID,Blob)
          ->把pCmd从CRilInstanceHandle的m_pCmdList中移除

->atcmd.cpp的CRilHandle::ResponseThread()
->atcmd.cpp的CRilHandle::HandleRxData()
  ->AppendReadBytes()把串口数据放入缓冲区
  ->GiveUpReadBytes()获得全部的新老串口数据
  构造CResponse
  ->response.cpp的CResponse::AppendString()
    ->response.cpp的CResponse::Parse()
      ->事件->response.cpp的CResponse::ParseNotification()
      ->结果->response.cpp的CResponse::ParseOKOrError()
    回应不完整则szRemainder和cbRemainder=0,否则等于下一个回应和长度
  假如pRsp->FUnsolicited==0,也就是Unsolicited Result Code(非请求结果码)
    假如FWaitingForRsp==1,调用atcmd.cpp的QueueRsp()唤醒CommandThread
  假如是URC,pRsp->GetBlob()然后BroadcastRealBlobNotification()
  剩下的串口数据调用AppendReadBytes(),重新开始一轮处理

最简单的AT指令,也就是只返回"OK",上面的处理过程很简单。

CRilHandle有内部缓冲区用来存放新老串口数据(例如上次没读完整),,
所以一进HandleRxData()就先AppendReadBytes()然后GiveUpReadBytes()

每个pRsp也有内部缓冲区,存放完整的回应数据。

对于有具体返回值的AT指令,例如AT+CSQ,
在misc.cpp的RILDrv_GetSignalQuality()调用QueueCmd()时,
注册ParseGetSignalQuality()作为而外的处理函数,
在CommandThread的HandleRsp()的ParseOKData()中被调用。
ParseGetSignalQuality()会分析回应数据,来构造新的Blob,
然后通过Blob通知调用者结果。

RIL应用程序一开始调用RIL_Initialize()会注册2个回调函数
pfnResult和pfnNotify,前者接收命令结果,后者接收事件(例如RING)。

有的AT指令会构造pnd传给QueueCmd,例如RILDrv_DeleteMsg(),
有的没有pnd,例如RILDrv_GetSignalQuality()。
前者在CommandThread的HandleRsp()结尾BroadcastNotification(pnd)。

"ATD"(呼出)有点麻烦,对方接起后才返回"OK",在此之前可能主叫方挂断,
也就是"ATD"在有回应之前下"ATH"指令。

因此comhand.cpp的CComHandle::SendRILCmdHandleRsp中对"ATD"和"ATA"有特殊处理,
启动专门的线程HangupThreadProc处理"ATH"。
->HangupThreadProc()
  情况1:"ATD"/"ATA"指令还没下给串口
    从g_pCmdQ中移走pCmd
    pCmd->SendResponse(RIL_RESULT_NOCARRIER,NULL,0);
  情况2:已经下给了串口
    假如g_pCmdQ的下个命令是"ATH",因为g_pCmdQ是CPriorityQueue,"ATH"会排在最前
      m_fCancelledDial=1
      写"AT"到串口

对于上述情况2
comhand.cpp的CComHandle::SendRILCmdHandleRsp()
在获得pRsp("AT"的返回值"OK")后,判断m_fCancelledDial==1
调用pRsp->SetCallAborted()把"OK"的RESULT换成"NOCARRIER",此后按原流程处理。
"ATH"的指令未被丢弃,随后会再次发出,来防止对方"ATA"发生在"ATD"被取消的同时。

假如有模块的"ATD"直接返回"OK",那就不需要线程HangupThreadProc,
把RILDrv_Dial()的pnd去掉,不然收到"OK"就会BroadcastNotification(RIL_NOTIFY_CONNECT)。
另外response.cpp的CResponse::ParseNotification()可能也得加点东西。

抱歉!评论已关闭.