📄 comhand.cpp
字号:
// NKDbgPrintfW(TEXT("SendRILCmdHandleRsp\r\n"));
// NKDbgPrintfW(TEXT("RILDrv : t : Executing command with ID: 0x%08x\r\n"), rpCmd->GetID());
#ifdef GPRS_CONTEXT_CACHING
if (APIID_SETGPRSCONTEXT == rpCmd->GetAPIID())
{
szCmd = rpCmd->GetCmd();
if (IsGPRSContextCommandCached(szCmd))
{
// This exact set GPRS context command has already been sent down.
// some radios don't like this to be sent down again, and anyway, there's
// no point, so just NOOP
rpCmd->SetCmdOpt(CMDOPT_NOOP);
}
}
#endif // GPRS_CONTEXT_CACHING
// If this is a deactivate command and a CRING has been detected just before this
// we are likely in the scenario where a ATCI or non-S/R data call is being deactivated
// before processing the incoming voice call (Connection Manager functionality). Class
// B GPRS radios cannot process a GPRS deactivate request when a incoming call is
// not processed yet, so we fake a response to this deactivate request without sending
// it to the radio. Note that we depend on celltsp to deactivate the GPRS context after
// the voice call is hung up because there is a mismatch between celltsp's picture (deactivated)
// and the radio's picture of the context (activated) and celltsp forces its state on the radio.
if (rpCmd->CmdOptIsSet(CMDOPT_DEACT)) {
EnterCriticalSection(&g_csDeactCringLock);
if (TRUE == IncomingCallInProgress()) {
rpCmd->SetCmdOpt(CMDOPT_NOOP);
}
LeaveCriticalSection(&g_csDeactCringLock);
}
if (rpCmd->FNoOp())
{
// This command is a no-op, so we can avoid sending it
// Allocate a new response
pRsp = new CResponse(pRilDevice);
if (!pRsp)
{
// Critically low on memory
SignalCriticalError(RILLOG_EVENT_LOWMEMORY, __LINE__, __FILE__);
goto Error;
}
// Create an OK response (since the command was a no-op, it can't fail)
pRsp->MakeOK();
// We can't possibly fail a no-op
hr = S_OK;
}
else if (g_bRadioOff && !rpCmd->FInit() && !rpCmd->CmdOptIsSet(CMDOPT_IGNORERADIOOFF))
{
// The radio is off and the current command is not acceptable
// while the radio is in this state.
//
// Note: These conditions should really be handled in the radio with
// a CME error, but the radio corresponding to the OEM1_DRIVER does
// not behave well when some commands are sent when the radio is in
// the minimum power mode. We keep this logic for the Wavecom driver
// for consistency and testing purposes.
//
// Allocate a new response
pRsp = new CResponse(pRilDevice);
if (!pRsp)
{
// Critically low on memory
SignalCriticalError(RILLOG_EVENT_LOWMEMORY, __LINE__, __FILE__);
goto Error;
}
// Create an error response to indicate that the radio is off.
if (!pRsp->MakeError(RIL_E_RADIOOFF))
goto Error;
}
else
{
int NumRetries = rpCmd->GetRetries();
while (NumRetries-->=0)
{
delete pRsp;
pRsp = NULL;
// This command wasn't a no-op, so we need to send it
szCmd = rpCmd->GetCmd();
DEBUGCHK(NULL != szCmd);
// Let RIL know we're waiting for AT response
pRilDevice->StartWaitingForRsp(rpCmd);
// 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;
}
}
#ifdef OEM2_DRIVER
// On OEM2 we need to reset the CPINN event in case one has happened previously.
if (rpCmd->CmdOptIsSet(CMDOPT_SETRADIOON) && (NULL != g_hCPINNEvent))
{
ResetEvent(g_hCPINNEvent);
}
#endif
#if defined(OEM1_GPRS_DEACT) || defined(EMP_DRIVER)
if (rpCmd->CmdOptIsSet(CMDOPT_DEACT)) {
EnterCriticalSection(&g_csGPRSDeactLock);
// In case the previous deactivation attempt did not result in a expected ME DEACT notification
// after a response was received, we want to be sure to not confuse the response for that
// transaction with that for this new transaction, so we clear it
g_fDeactResponseRcvd = FALSE;
LeaveCriticalSection(&g_csGPRSDeactLock);
}
#endif
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
{
DWORD dwZone = rpCmd->CmdOptIsSet(CMDOPT_POLLING) ?
RILLOG_ZONE_CMD_POLLING : RILLOG_ZONE_CMD;
if (!rpCmd->CmdOptIsSet(CMDOPT_SUPPRESSLOGGING))
{
g_RilLog.LogEvent(dwZone, RILLOG_EVENT_SENDINGCMD, PrintableString(szCmd, iCmdLen));
}
else
{
g_RilLog.LogEvent(dwZone, 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());
DEBUGMSG(ZONE_ERROR, (TEXT("RILDrv : E : CComHandle::SendRILCmdHandleRsp : Got the response(Timeout=%d)\r\n"),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
{
DWORD dwZone = rpCmd->CmdOptIsSet(CMDOPT_POLLING) ?
RILLOG_ZONE_CMD_POLLING : RILLOG_ZONE_CMD;
if (!rpCmd->CmdOptIsSet(CMDOPT_SUPPRESSLOGGING))
{
g_RilLog.LogEvent(dwZone, RILLOG_EVENT_SENDINGCMD, PrintableString(szCmd, iCmdLen));
}
else
{
g_RilLog.LogEvent(dwZone, 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))
{
g_RilLog.LogEvent(RILLOG_ZONE_CMD, RILLOG_EVENT_CMDTIMEDOUTSUPPRESSED, rpCmd->GetAPIID());
}
else
{
g_RilLog.LogEvent(RILLOG_ZONE_CMD, RILLOG_EVENT_CMDTIMEDOUT, PrintableString(szCmd, iCmdLen));
}
#ifndef OEM2_DRIVER
// Bug 29018 Send an extra AT\r to try to kick the modem out of its stupor!
if (fSendingSecondPart)
{
WriteCharsToComPort(pRilDevice, "\x1b\r", 2);
g_RilLog.LogEvent(RILLOG_ZONE_CMD, RILLOG_EVENT_SENDINGCMD, PrintableString("<esc>\r", 6));
}
else
{
WriteCharsToComPort(pRilDevice, "AT\r", 3);
g_RilLog.LogEvent(RILLOG_ZONE_CMD, 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;
#endif // ! OEM2_DRIVER
}
// 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
pRsp = new CResponse(pRilDevice);
if (!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 defined (OEM1_DRIVER) || defined(OEM2_DRIVER) || defined(PHILIP_DRIVER)
if (APIID_SETEQUIPMENTSTATE == rpCmd->GetAPIID() &&
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -