?? comhand.cpp
字號:
// We want the response that follows the command we are about to send.
// Discard any responses that have accidentally queued up.
while (!g_pRspQ->FEmpty())
{
hr = g_pRspQ->Get(pRsp, 0);
if (SUCCEEDED(hr))
{
#ifdef DEBUG
DEBUGMSG(ZONE_INFO, (TEXT("RILDrv : i : CComHandle::SendRILCmdHandleRsp : Discarding extra queued response: %s\r\n"),
VerboseString(TString(pRsp->GetData()))));
#endif // DEBUG
delete pRsp;
pRsp = NULL;
}
}
if (rpCmd->CmdOptIsSet(CMDOPT_SETRADIOON))
{
hr = PDD_BeginRadioPowerOn();
if ( FAILED( hr ) && E_NOTIMPL != hr )
{
DEBUGMSG(ZONE_ERROR, (TEXT("RILDrv : E : CComHandle::SendRILCmdHandleRsp : Error returned by PDD_BeginRadioPowerOn [0x%08x]\r\n"), hr));
goto Error;
}
}
if (rpCmd->CmdOptIsSet(CMDOPT_DEACT))
{
hr = PDD_BeginGPRSContextDeactivation();
if ( FAILED( hr ) && E_NOTIMPL != hr )
{
DEBUGMSG(ZONE_ERROR, (TEXT("RILDrv : E : CComHandle::SendRILCmdHandleRsp : Error returned by PDD_BeginGPRSContextDeactivation [0x%08x]\r\n"), hr));
goto Error;
}
}
bool fSendingSecondPart = false;
// Write the command out to the com port
UINT iCmdLen = strlen(szCmd);
if (!WriteCmdsToComPort(pRilDevice, szCmd, iCmdLen))
{
#ifdef DEBUG
DEBUGMSG(ZONE_ERROR, (TEXT("RILDrv : E : CComHandle::SendRILCmdHandleRsp : Error writing command: %s\r\n"), VerboseString(TString(szCmd))));
#endif // DEBUG
// Ignore the error. Even if we know that there was a problem writing to the com port,
// we don't know what exactly was written nor whether we should expect a response.
// It's best at this point to wait normally for a response. If no response is generated
// due to the error, then we'll time out and continue as usual.
}
else
{
if (!rpCmd->CmdOptIsSet(CMDOPT_SUPPRESSLOGGING))
{
RIL_EVENTLOG_MSG((RILLOG_EVENT_SENDINGCMD, PrintableString(szCmd, iCmdLen)));
}
else
{
RIL_EVENTLOG_MSG((RILLOG_EVENT_SENDINGCMDSUPPRESSED, rpCmd->GetAPIID()));
}
#ifdef RIL_WATSON_REPORT
// Store last command in info cache.
EnterCriticalSection(&g_csRilInfoCache);
strncpy(g_RilInfoCache.szLastCmd, szCmd, MAXLENGTH_CMD);
g_RilInfoCache.fLastCmdSuppress = rpCmd->CmdOptIsSet(CMDOPT_SUPPRESSLOGGING);
LeaveCriticalSection(&g_csRilInfoCache);
#endif //RIL_WATSON_REPORT
}
// If we've just sent a dial or answer command, prepare to handle a hangup command before getting a response
if (rpCmd->FDial() || rpCmd->FAnswer())
{
// Launch a thread to wait for a hangup
HANDLE hThread = NULL;
hQuitEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (hQuitEvent)
{
HANGUP_THREAD_DATA* phtd = new HANGUP_THREAD_DATA;
if (phtd)
{
(void)memset(phtd, 0x00, sizeof(HANGUP_THREAD_DATA));
phtd->hQuitEvent = hQuitEvent;
phtd->pComDevice = this;
phtd->pRilDevice = pRilDevice;
hThread = CreateThread(NULL, 0, HangupThreadProc, (LPVOID)phtd, 0, NULL);
}
if (hThread)
{
// We created the thread
// Don't need a handle to the thread...
CloseHandle(hThread);
// The thread takes care of freeing pthd and closing the event handle
// Therefore, don't touch phtd after this point
}
else
{
// If we didn't create the thread, clean up and soldier on...
delete phtd;
phtd=NULL;
CloseHandle(hQuitEvent);
hQuitEvent=NULL;
}
}
}
// Get the response out of the Response Queue
hr = g_pRspQ->Get(pRsp, rpCmd->GetTimeout());
if (SUCCEEDED(hr) && (rpCmd->CmdOptIsSet(CMDOPT_INTERMEDIATERESPONSE)) && (RIL_RESULT_OK == pRsp->GetNotifyCode()))
{
szCmd = rpCmd->GetCmdPart2();
if (NULL != szCmd)
{
// if there is a secondary command, send it out now. This is primarily to handle SMS send commands
// that need an intermediary prompt.
pRilDevice->StopWaitingForRsp();
pRilDevice->StartWaitingForRsp(rpCmd);
fSendingSecondPart = true;
iCmdLen = strlen(szCmd);
if (!WriteCmdsToComPort(pRilDevice, szCmd, iCmdLen))
{
#ifdef DEBUG
DEBUGMSG(ZONE_ERROR, (TEXT("RILDrv : E : CComHandle::SendRILCmdHandleRsp : Error writing command: %s\r\n"), VerboseString(TString(szCmd))));
#endif // DEBUG
// Ignore the error. Even if we know that there was a problem writing to the com port,
// we don't know what exactly was written nor whether we should expect a response.
// It's best at this point to wait normally for a response. If no response is generated
// due to the error, then we'll time out and continue as usual.
}
else
{
if (!rpCmd->CmdOptIsSet(CMDOPT_SUPPRESSLOGGING))
{
RIL_EVENTLOG_MSG((RILLOG_EVENT_SENDINGCMD, PrintableString(szCmd, iCmdLen)));
}
else
{
RIL_EVENTLOG_MSG((RILLOG_EVENT_SENDINGCMDSUPPRESSED, rpCmd->GetAPIID()));
}
#ifdef RIL_WATSON_REPORT
// Store last command in info cache.
EnterCriticalSection(&g_csRilInfoCache);
strncpy(g_RilInfoCache.szLastCmd, szCmd, MAXLENGTH_CMD);
g_RilInfoCache.fLastCmdSuppress = rpCmd->CmdOptIsSet(CMDOPT_SUPPRESSLOGGING);
LeaveCriticalSection(&g_csRilInfoCache);
#endif //RIL_WATSON_REPORT
}
}
// Now wait for the secondary response which will be the real deal.
delete pRsp;
hr = g_pRspQ->Get(pRsp, rpCmd->GetTimeout());
}
if (RIL_E_TIMEDOUT == hr)
{
// If we timed out, just print out a warning and (maybe) try again
DEBUGMSG(ZONE_ERROR, (TEXT("RILDrv : E : CComHandle::SendRILCmdHandleRsp : Cmd timed out? (Before StopWaitingForRsp)\r\n")));
#ifdef RIL_LAST_ERROR
g_dwLastError = MAKELONG(0, RADIO_TIMEOUTERROR);
#endif
if (rpCmd->CmdOptIsSet(CMDOPT_SUPPRESSLOGGING))
{
RIL_EVENTLOG_MSG((RILLOG_EVENT_CMDTIMEDOUTSUPPRESSED, rpCmd->GetAPIID()));
}
else
{
RIL_EVENTLOG_MSG((RILLOG_EVENT_CMDTIMEDOUT, PrintableString(szCmd, iCmdLen)));
}
// Bug 29018 Send an extra AT\r to try to kick the modem out of its stupor!
if (fSendingSecondPart)
{
WriteCharsToComPort(pRilDevice, "\x1b\r", 2);
RIL_EVENTLOG_MSG((RILLOG_EVENT_SENDINGCMD, PrintableString("<esc>\r", 6)));
}
else
{
WriteCharsToComPort(pRilDevice, "AT\r", 3);
RIL_EVENTLOG_MSG((RILLOG_EVENT_SENDINGCMD, PrintableString("AT\r", 3)));
}
HRESULT hrTmp;
CResponse* pRspTmp = NULL;
hrTmp = g_pRspQ->Get(pRspTmp, 500); // Wait 1/2 second for a response
delete pRspTmp;
}
// Let RIL know we're not waiting for AT response anymore
pRilDevice->StopWaitingForRsp();
// If we lauched a thread to wait for hangup, kill it
if (hQuitEvent)
{
(void)SetEvent(hQuitEvent);
hQuitEvent = NULL;
}
if (SUCCEEDED(hr))
{
// There is a remote chance that while waiting for a connect code
// to go back into data mode, that we pick up some other rogue
// response. We don't want RIL to go into data mode until we're
// sure there is a connect. So, if we don't get a connect result,
// try the command again.
// If the command generates its own error response, then we will be
// repeating this command/error for NUM_TIMEOUT_INIT_ATTEMPTS.
// The last error response will be returned to the caller.
if (rpCmd->FRequireConnectRsp() &&
RIL_NOTIFY_CONNECT != pRsp->GetNotifyCode())
{
continue;
}
// If we cancelled the last dial command, turn the OK response into a NOCARRIER
if (m_fCancelledDial)
{
if (rpCmd->FDial() || rpCmd->FAnswer())
{
pRsp->SetCallAborted();
}
m_fCancelledDial = FALSE;
}
else if (rpCmd->FDial() && RIL_RESULT_ERROR == pRsp->GetNotifyCode() &&
rpCmd->CmdOptIsSet(CMDOPT_LONGDIALSTRING))
{
pRsp->MakeError(RIL_E_DIALSTRINGTOOLONG);
}
break;
}
// See if we couldn't get the response for some reason
else if (RIL_E_TIMEDOUT == hr)
{
// If we timed out, just print out a warning and (maybe) try again
DEBUGMSG(ZONE_ERROR, (TEXT("RILDrv : E : CComHandle::SendRILCmdHandleRsp : Cmd timed out?\r\n")));
// Send a hint to the response thread that we could have
// bad data in the response buffer.
pRilDevice->SetLastCommandTimedOut();
}
else
{
DEBUGCHK(RIL_E_CANCELLED == hr);
goto Error;
}
} // for (i = 0; i < MaxRetries; i++)
// Did we time out??
if (RIL_E_TIMEDOUT == hr)
{
#ifdef DEBUG
DEBUGMSG(ZONE_ERROR, (TEXT("RILDrv : E : CComHandle::SendRILCmdHandleRsp : Command has timed out: %s\r\n"), VerboseString(TString(szCmd))));
#endif
DEBUGCHK(NULL == pRsp);
rfTimedOut = TRUE;
// Additional operations may be requred to cancel timed out dial commands, so we need to return a different error
if (rpCmd->FDial())
{
hr = RIL_E_NORESPONSETODIAL;
}
// We fail timed out commands
if (FAILED(PDD_GetResponseObject(pRsp)) || !pRsp || !pRsp->MakeError(hr))
{
goto Error;
}
}
else if (RIL_E_TIMEDOUT == pRsp->GetError())
{
#ifdef DEBUG
DEBUGMSG(ZONE_ERROR, (TEXT("RILDrv : E : CComHandle::SendRILCmdHandleRsp : Radio indicated timeout for command: %s\r\n"), VerboseString(TString(szCmd))));
#endif
rfTimedOut = TRUE;
}
SetTimeoutStatus(rfTimedOut);
} // else
// If we issued a successful hangup command, exit out of the data mode
if (rpCmd->FHangup() &&
(RIL_RESULT_NOCARRIER == pRsp->GetNotifyCode() || RIL_RESULT_OK == pRsp->GetNotifyCode()))
{
(void)ExitDataMode();
}
// If we tried to get a connect response but failed,
// then we've timed out.
if (rpCmd->FRequireConnectRsp() &&
(RIL_NOTIFY_CONNECT != pRsp->GetNotifyCode() &&
RIL_RESULT_NOCARRIER != pRsp->GetNotifyCode()))
{
rfTimedOut = TRUE;
}
if (APIID_SETEQUIPMENTSTATE == rpCmd->GetAPIID() &&
RIL_RESULT_ERROR == pRsp->GetNotifyCode() &&
(RIL_E_SIMPINREQUIRED == pRsp->GetError() || RIL_E_SIMPUKREQUIRED == pRsp->GetError() || RIL_E_SIMWRONG == pRsp->GetError()
|| RIL_E_SIMNOTINSERTED == pRsp->GetError() || RIL_E_SIMBUSY == pRsp->GetError() || RIL_E_SIMFAILURE == pRsp->GetError() ))
{
UpdateSIMState(pRsp->GetError());
pRsp->MakeOK();
}
// If the last command set the equipment state (+CFUN),
// then update the global on/off state.
if (APIID_SETEQUIPMENTSTATE == rpCmd->GetAPIID() &&
RIL_RESULT_OK == pRsp->GetNotifyCode())
{
g_bRadioOff = rpCmd->CmdOptIsSet(CMDOPT_SETRADIOON) ? FALSE : TRUE;
// Make sure that we turn off the audio path both starting up and shutting down.
// Indicate call is inactive to audio driver
IndicateCallActivityToAudioSubsystem ( FALSE, FALSE );
// The radio is now on, so we'd better check to see if the SIM is ready
if (!g_bRadioOff)
{
// On some radios we really can't allow any other commands to go down after a CFUN=1 until we get a +CPINN notification.
// Note that this restriction doesn't apply if the previous equipment state is RIL_EQSTATE_DISABLETX,
// RIL_EQSTATE_DISABLERX, or RIL_EQSTATE_DISABLETXANDRX.
if (!rpCmd->CmdOptIsSet(CMDOPT_NOOP))
{
hr = PDD_WaitForSIMReady();
if ( FAILED( hr ) && E_NOTIMPL != hr )
{
DEBUGMSG(ZONE_ERROR, (TEXT("RILDrv : E : SendRILCmdHandleRsp : PDD_WaitForSIMReady failed , hr = [0x%08x]\r\n"), hr));
goto Error;
}
}
pRilDevice->StartReadyStateQuery();
}
else
{
// Radio's off -- reset g_dwReadyState
pRilDevice->StopReadyStateQuery();
pRilDevice->SendReadyStateNotification(RIL_READYSTATE_NONE);
UpdateSIMState(RIL_E_RADIOOFF);
}
}
#ifdef GPRS_CONTEXT_CACHING
if ((APIID_SETGPRSCONTEXT == rpCmd->GetAPIID()) &&
(!rpCmd->FNoOp()) &&
(RIL_RESULT_OK == pRsp->GetNotifyCode()))
{
// We just set the GPRS context. Don't set the same context again
// unless the radio reboots.
UpdateGPRSContextCommandCache(szCmd);
}
#endif // GPRS_CONTEXT_CACHING
// If the last command resulted in error, then attempt
// to retry the command. If no retry is necessary, then
// RetryCommandOnError will just return without doing anything.
if (RIL_RESULT_ERROR == pRsp->GetNotifyCode())
{
(void)rpCmd->RetryCommandOnError();
}
// Handle the response
if (!pRilDevice->HandleRsp(rpCmd, pRsp, rfHungUp, g_bRadioOff))
{
goto Error;
}
DEBUGCHK(NULL == rpCmd);
DEBUGCHK(NULL == pRsp);
fRet = TRUE;
Error:
if (!fRet)
{
delete pRsp;
}
if (hQuitEvent)
{
(void)CloseHandle(hQuitEvent);
}
return fRet;
}
BOOL CComHandle::WriteCmdsToComPort(CRilHandle* const pRilDevice, LPCSTR szChars, UINT cbToWrite)
{
LPCSTR szEnd = szChars+cbToWrite;
for (;;)
{
// Look for a <cr>
LPCSTR szEndCurr = strchr(szChars,'\r');
// Write up to the <cr>, or up to end if no <cr> found
cbToWrite = (szEndCurr) ? (szEndCurr - szChars + 1) : (szEnd - szChars);
// Write command to com port
if(!WriteCharsToComPort(pRilDevice,szChars,cbToWrite))
{
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -