response.cpp
来自「手机RILGSM实现的源代码」· C++ 代码 · 共 1,967 行 · 第 1/5 页
CPP
1,967 行
// This function searches for strings of the form "+X", where X is a set of at least 2
// uppercase characters. If found, it sets rszPointer to the beginning of the string,
// and returns the number of characters in the string.
int FindNextResponse(LPCSTR szStart, LPCSTR& rszPointer)
{
FUNCTION_TRACE(FindNextResponse);
LPCSTR szPointer = szStart;
LPCSTR szCmd;
int RespSize;
while (1)
{
// Find the first '+' character
szPointer = strchr(szPointer, '+');
if (!szPointer)
{
// Didn't find a +, abort
return 0;
}
// We found a '+', now look for some capital letters
RespSize=1;
szCmd = szPointer+1;
while (1)
{
UCHAR NextChar = *szCmd;
// If we hit a NULL in the middle of parsing, abort
if (NextChar=='\0')
{
return 0;
}
// Is it a capital letter?
else if ((NextChar >= 'A') && (NextChar <= 'Z'))
{
RespSize++;
szCmd++;
}
// Is it a ':', which ends a response?
else if (NextChar == ':')
{
RespSize++;
rszPointer=szPointer;
return RespSize;
}
// It's some other character. Keep looking.
else
{
// Remember to increment the initial pointer so we don't try to
// reparse the same + character in an infinite loop
szPointer=szCmd;
break;
}
}
}
}
// This function attempts to weed out invalid responses which were truncated due to comm errors
// Note that if this function thinks there is a partial response, it will throw away
// the partial response up to the '+' character of the next response. This means that it will
// also throw away any leading <cr><lf> prefix on the next call. This works because
// ParseRspPrefix always returns TRUE, even if the <cr><lf> prefix isn't there.
// Note that this function runs after other attempts to recognize notifications, OK, or
// ERROR responses have run. Therefore, it won't mistakenly throw away OEM notifications
// which don't begin with a '+', since they should be caught earlier. However, this code
// does run before parsing of responses to commands, so any such responses which don't
// begin with a '+' may be mistakenly thrown away. So far there are no such responses
// that I know of.
BOOL CResponse::ParsePartialResponse(UINT& rcbNewLength)
{
FUNCTION_TRACE(CResponse::ParsePartialResponse);
LPSTR szPointer = m_szData;
LPSTR szResponse1;
LPSTR szResponse2;
int cbResponse1;
int cbResponse2;
// Skip initial <cr><lf> if there
ParseRspPrefix(szPointer, szPointer);
// Look for the first response in buffer (anything of the form "+X", where X is
// one or more capital letters). Returns 0 if not found.
cbResponse1 = FindNextResponse(szPointer, szResponse1);
// If we didn't find one, abort
if (cbResponse1==0)
{
return FALSE;
}
// If the first '+' in the buffer doesn't occur immediately after the prefix (or at the
// beginning if there wasn't a prefix), treat everything before the '+' as the (junk)
// response
// This is somewhat nondeterministic, since this will strip leading data off of
// valid commands if we haven't received the trailing 0<cr> yet,
// but won't touch the leading data if we have received the trailing 0<cr> (since this
// will cause the earlier ParseOKOrError to succeed)
// The individual command response parsers should really be using MatchStringAnywhere
// to skip past any initial cruft, but most of them use MatchStringBeginning and are
// therefore somewhat finicky about the +XXX appearing at the beginning or immediately
// after the prefix. Someday I should go back and fix that. So far the only ones I've
// made sure to fix are those for parsing SMS Send & Write, which normally have an
// extra "<cr><lf>> " prepended which may or may not get thrown away by the code below.
if (szResponse1!=szPointer)
{
rcbNewLength = szResponse1 - m_szData;
m_fUnrecognized = TRUE;
return TRUE;
}
// Look for the second response in buffer.
cbResponse2 = FindNextResponse(szResponse1+cbResponse1, szResponse2);
if (cbResponse2==0)
{
// If we didn't find a second response, maybe we're still waiting
// for the rest of the first, so abort
return FALSE;
}
// If the first & second responses differ,
// assume the first is a partial response and throw it away
if ( (cbResponse1!=cbResponse2) || strncmp(szResponse1,szResponse2,cbResponse1) )
{
rcbNewLength = szResponse2 - m_szData;
m_fUnrecognized = TRUE;
return TRUE;
}
// Didn't find a partial response (or at least we're not sure it was a partial response)
return FALSE;
}
//
//
//
BOOL CResponse::ParseOKOrError(const BOOL fOK, UINT& rcbNewLength)
{
FUNCTION_TRACE(CResponse::ParseOKOrError);
LPSTR szPointer = m_szData;
LPCSTR szCode = (fOK ? "0\r" : "4\r");
HRESULT hrError;
BOOL fRet;
#ifdef OEM1_DRIVER
// Necessary change to make battery driver calls work on this hardware
if( strstr( szPointer, "ADC" ) )
{
char* pch;
pch = strstr( szPointer, "\n4\r" );
if( pch )
{
*(pch+1) = 0x30;
}
}
#endif // OEM1_DRIVER
while (1)
{
// First search in the beginning of the response
fRet = MatchStringBeginning(szPointer, szCode, szPointer);
if (fRet && '\n' != *szPointer)
{
// We found "<code><CR>" not followed by <LF> in the beginning of the response
break;
}
else
{
// Now search elsewhere in the response
fRet = MatchStringAnywhere(szPointer, szCode, szPointer);
if (!fRet)
{
// We didn't find "<code><CR>"
break;
}
else if ('\n' != *szPointer &&
('\n' == *(szPointer - 3) || '\r' == *(szPointer - 3)))
{
// We found "<code><CR>" not followed by <LF> and preceded by <LF> or <CR>
break;
}
}
}
if (!fRet)
{
// If we couldn't find the numeric OK or ERROR, try looking for verbose responses
fRet = MatchStringAnywhere(m_szData, (fOK ? "\r\nOK\r\n" : "\r\nERROR\r\n"), szPointer);
}
if (!fRet && fOK)
{
// If that didn't succeed either, see if we got an SMS intermediary prompt
// we'll treat this as an OK for now, but this will cause the command thread
// to send down the second part of the command which will be the SMS PDU
#ifdef OEM1_DRIVER
fRet = MatchStringBeginning(m_szData, "> \r", szPointer);
#else
fRet = MatchStringBeginning(m_szData, "\r\n> ", szPointer);
#endif
}
if (fRet)
{
m_fUnsolicited = FALSE;
m_dwCode = (fOK ? RIL_RESULT_OK : RIL_RESULT_ERROR);
rcbNewLength = szPointer - m_szData;
if (!fOK)
{
// For error responses, we have additional info -- error code
hrError = E_FAIL;
if (!SetBlob((void*)&hrError, sizeof(HRESULT)))
{
fRet = FALSE;
goto Error;
}
}
}
Error:
return fRet;
}
//
// This function gets a remotely determined calltype based on information in a RILREMOTEPARTYINFO
// structure
//
DWORD GetCalltypeFromRemotePartyInfo(RILREMOTEPARTYINFO*prrpi)
{
DWORD dwLocalCalltype = RIL_CALLTYPE_UNKNOWN;
if (NULL != g_rlpfExternalCalltypeFunction)
{
DEBUGMSG(ZONE_INFO, (TEXT("RILDrv : i : GetCalltypeFromRemotePartyInfo : Making Calltype Callback.\r\n")));
dwLocalCalltype = g_rlpfExternalCalltypeFunction(prrpi);
DEBUGMSG(ZONE_INFO, (TEXT("RILDrv : i : GetCalltypeFromRemotePartyInfo : Calltype Received = %d\r\n"), dwLocalCalltype));
// validate calltype
if ((dwLocalCalltype < RIL_CALLTYPE_UNKNOWN) ||
(dwLocalCalltype > RIL_CALLTYPE_LAST))
{
dwLocalCalltype = RIL_CALLTYPE_UNKNOWN;
}
DEBUGMSG(ZONE_INFO, (TEXT("RILDrv : i : GetCalltypeFromRemotePartyInfo : Calltype Returned = %d\r\n"), dwLocalCalltype));
}
else
{
DEBUGMSG(ZONE_ERROR, (TEXT("RILDrv : E : GetCalltypeFromRemotePartyInfo : g_rlpfExternalCalltypeFunction is NULL.\r\n")));
}
return dwLocalCalltype;
}
//
// This function sets a remotely determined calltype based on information in a RILCALLINFO
// structure. It first checks for previously validated data from previous calls to this function. It then
// looks for valid data from a RILDrv_Dial call. If these two fail, it calls GetCalltypeFromRemotePartyInfo.
// This data is then used to update the necessary calltype and call state structures.
//
VOID SetCalltypeFromCallInfo(RILCALLINFO *prci)
{
DWORD dwLocalCalltype = RIL_CALLTYPE_UNKNOWN;
BOOL fFoundDialedCalltype = FALSE;
DEBUGCHK((0 <= prci->dwID) && (prci->dwID < ARRAY_LENGTH(g_rgfCalltypeChecked))); // Otherwise, it may be necessary to increase MAX_TRACKED_CALLS
//
// The g_rgfCalltypeChecked for a new MO call that is assigned a previously used call ID must be revalidated or invalidated, and
// the cached MO call type rather than the possibly invalid global cached call type must be indicated up for the MO call.
//
if ( ((prci->dwParams & RIL_PARAM_CI_CPISTATUS) && (RIL_CPISTAT_NEW_OUTGOING == prci->dwStatus)) ||
((prci->dwParams & RIL_PARAM_CI_STATUS) && (RIL_CALLSTAT_DIALING == prci->dwStatus)) )
{
g_rgfCalltypeChecked[ prci->dwID ] = FALSE;
g_rcdDialedCallData.fValid = TRUE;
}
if (g_rgfCalltypeChecked[prci->dwID] != TRUE)
{
EnterCriticalSection(&g_csDialedCallData);
// need to see if the calltype has been set up through a dial command
if (TRUE == g_rcdDialedCallData.fValid)
{
// check the address
if (!wcsncmp(g_rcdDialedCallData.wszAddress,prci->raAddress.wszAddress,MAXLENGTH_ADDRESS))
{
// The address matches, so this is the call associated with the dial in progress.
dwLocalCalltype = g_rcdDialedCallData.dwCalltype;
// invalidate the cache data
g_rcdDialedCallData.fValid= FALSE;
fFoundDialedCalltype = TRUE;
DEBUGMSG(ZONE_INFO, (TEXT("RILDrv : i : SetCalltypeFromCallInfo : Using g_rcdDialedCallData.dwCalltype = %d\r\n"), dwLocalCalltype));
}
}
LeaveCriticalSection(&g_csDialedCallData);
if (FALSE == fFoundDialedCalltype)
{
// Haven't got a calltype yet, need to see if a calltype has been set up through a call waiting notification
if (TRUE == g_rcdWaitingCallData.fValid)
{
// check the address
if (!wcsncmp(g_rcdWaitingCallData.wszAddress,prci->raAddress.wszAddress,MAXLENGTH_ADDRESS))
{
// The address matches, so this is the call associated with the call waiting call
dwLocalCalltype = g_rcdWaitingCallData.dwCalltype;
// invalidate the cache data
g_rcdWaitingCallData.fValid = FALSE;
}
}
else
{
RILREMOTEPARTYINFO rrpi; memset(&rrpi, 0, sizeof(RILREMOTEPARTYINFO));
rrpi.cbSize = sizeof(RILREMOTEPARTYINFO);
rrpi.raAddress = prci->raAddress;
rrpi.dwValidity = RIL_REMOTEPARTYINFO_VALID;
// rrpi validity set correctly by memset above
rrpi.dwParams = RIL_PARAM_RPI_ADDRESS | RIL_PARAM_RPI_VALIDITY;
// Haven't got a calltype yet, so query the remote function
dwLocalCalltype = GetCalltypeFromRemotePartyInfo(&rrpi);
}
}
if (RIL_CALLTYPE_UNKNOWN != dwLocalCalltype)
{
// Only override the original calltype if the determined calltype is not unknown
prci->dwType = dwLocalCalltype;
}
g_rgctCalltype[prci->dwID] = prci->dwType;
g_rgfCalltypeChecked[prci->dwID] = TRUE;
DEBUGMSG(ZONE_INFO, (TEXT("RILDrv : i : SetCalltypeFromCallInfo : External Calltype = %d, Final Calltype = %d, Call ID = %d.\r\n"), dwLocalCalltype, g_rgctCalltype[prci->dwID], prci->dwID));
EnterCriticalSection(&g_csRingingCallData);
if (TRUE == g_rcdRingingCallData.fDelayRingNotification)
{
// call is ringing but calltype was undetermined - now it is
g_rcdRingingCallData.dwCalltype = g_rgctCalltype[prci->dwID];
g_rcdRingingCallData.fCalltypeValid = TRUE;
g_rcdRingingCallData.fDelayRingNotification = FALSE;
g_rcdRingingCallData.fForceRingNotification = TRUE;
g_rcdRingingCallData.fCallIdValid = TRUE;
g_rcdRingingCallData.dwCallId = prci->dwID;
DEBUGMSG(ZONE_INFO, (TEXT("RILDrv : i : SetCalltypeFromCallInfo : Setting g_rcdRingingCallData.fForceRingNotification.\r\n")));
}
DEBUGMSG(ZONE_INFO, (TEXT("RILDrv : i : SetCalltypeFromCallInfo : Ringing Call TypeValid = %d, type = %d, IdValid = %d, Id = %d, Delay = %d, Force = %d\r\n"),
g_rcdRingingCallData.fCalltypeValid, g_rcdRingingCallData.dwCalltype,g_rcdRingingCallData.fCallIdValid,g_rcdRingingCallData.dwCallId,g_rcdRingingCallData.fDelayRingNotification,g_rcdRingingCallData.fForceRingNotification));
LeaveCriticalSection(&g_csRingingCallData);
}
else
{
DEBUGMSG(ZONE_INFO, (TEXT("RILDrv : i : SetCalltypeFromCallInfo : Previously calculated Calltype = %d, Call ID = %d.\r\n"), g_rgctCalltype[prci->dwID], prci->dwID));
prci->dwType = g_rgctCalltype[prci->dwID];
}
}
//
//
//
BOOL CResponse::ParseNotification(UINT& rcbNewLength, BOOL fDataOnNotificationPort)
{
FUNCTION_TRACE(CResponse::ParseNotification);
UINT nCode;
LPSTR szPointer = m_szData + m_nOffset;
BOOL fExpectCRLF = TRUE;
BOOL fSuppressLogging = FALSE;
#ifdef RIL_WATSON_REPORT
BOOL fErrorNotification = false;
LPSTR szData = m_szData;
#endif // RIL_WATSON_REPORT
BOOL fRet = FALSE;
// Parse "<prefix>"
if (!ParseRspPrefix(szPointer, szPointer))
{
goto Error;
}
if (MatchStringBeginning(szPointer, "+++", szPointer) &&
ParseUInt(szPointer, FALSE, nCode, szPointer) &&
3 == nCode)
{
// Special case for "+++" followed by 3(NO CARRIER)
m_fUnsolicited = FALSE;
m_dwCode = RIL_RESULT_NOCARRIER;
fExpectCRLF = FALSE;
}
#ifdef OEM1_DRIVER
else if ((MatchStringBeginning(szPointer, "0\r", szPointer)) || (MatchStringBeginning(szPointer, "4\r", szPointer)))
{
goto Error;
}
else if (MatchStringBeginning(szPointer, "CONNECT 9600", szPointer))
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?