📄 response.cpp
字号:
{
RIL_REMOTEPARTYINFO_VALID, // 0
RIL_REMOTEPARTYINFO_WITHHELD, // 1
RIL_REMOTEPARTYINFO_UNAVAILABLE, // 2
};
#define NUM_VALIDITIES (sizeof(g_rgdwValidities) / sizeof(DWORD))
//
// Supplementary service data status values
//
static const DWORD g_rgdwSupSvcDataStats[] =
{
RIL_SUPSVCDATASTATUS_NOINFOREQUIRED, // 0
RIL_SUPSVCDATASTATUS_FURTHERINFOREQUIRED, // 1
RIL_SUPSVCDATASTATUS_TERMINATED, // 2
RIL_SUPSVCDATASTATUS_OTHERCLIENTRESPONDED, // 3
RIL_SUPSVCDATASTATUS_UNSUPPORTED, // 4
RIL_SUPSVCDATASTATUS_TIMEOUT, // 5
};
#define NUM_SUPSVCDATASTATS (sizeof(g_rgdwSupSvcDataStats) / sizeof(DWORD))
#ifdef RIL_LAST_ERROR
extern DWORD g_dwLastError;
#endif
CResponse* g_CachedToolKitNotifs[MAX_TOOLKITNOTIFS];
RILSIGNALQUALITY g_rsq;
BOOL g_fSignalQualityReceived = FALSE;
RILLOCATIONINFO g_rliLocationInfo;
BOOL g_fInitialLocationInfoReceived = FALSE;
BOOL g_fLocationInfoReceived = FALSE;
BOOL g_fSuppressRegStatusNotification = FALSE;
BOOL g_fSuppressGPRSRegStatusNotification = FALSE;
//
// Response ctor
//
CResponse::CResponse()
: m_dwCode(0),
m_fUnsolicited(FALSE),
m_fUnrecognized(FALSE),
m_fPotentialBogusResponse(FALSE),
m_pBlob(NULL),
m_cbBlob(0),
m_nOffset(0)
{
// FUNCTION_TRACE(CResponse::CResponse);
}
//
// copy Response ctor
//
CResponse::CResponse(const CResponse &Rsp)
: m_dwCode(Rsp.m_dwCode),
m_fUnsolicited(Rsp.m_fUnsolicited),
m_fUnrecognized(Rsp.m_fUnrecognized),
m_fPotentialBogusResponse(Rsp.m_fPotentialBogusResponse),
m_pBlob(NULL),
m_cbBlob(0),
m_nOffset(0)
// CBuffer initialized null.
{
}
//
// Response dtor
//
CResponse::~CResponse()
{
// FUNCTION_TRACE(CResponse::~CResponse);
FreeBlob(m_pBlob);
m_pBlob = NULL;
m_cbBlob = 0;
}
//
// Append data to the response
//
BOOL CResponse::AppendString(const LPCSTR szString, const UINT cbString, LPCSTR& rszRemainder, UINT& rcbRemainder, BOOL fDataOnNotificationPort)
{
FUNCTION_TRACE(CResponse::AppendString);
UINT cbNewLength = 0;
UINT cbOldLength = m_cbLength;
BOOL fRet = FALSE;
// Append the new data to the buffer
if (!Append(szString, cbString))
{
goto Error;
}
// Parse the data
if (Parse(cbNewLength, fDataOnNotificationPort))
{
DEBUGCHK(cbNewLength != 0);
DEBUGCHK(cbNewLength <= m_cbLength);
m_cbLength = cbNewLength;
rszRemainder = szString + cbNewLength - cbOldLength;
rcbRemainder = cbString - (rszRemainder - szString);
}
else
{
rszRemainder = NULL;
rcbRemainder = 0;
}
fRet = TRUE;
Error:
return fRet;
}
//
//
//
BOOL CResponse::SetBlob(const void* const pBlob, const UINT cbBlob)
{
FUNCTION_TRACE(CResponse::SetBlob);
BOOL fRet = FALSE;
DEBUGCHK(NULL == m_pBlob && 0 == m_cbBlob);
FreeBlob(m_pBlob);
m_cbBlob = 0;
if (cbBlob)
{
DEBUGCHK(NULL != pBlob);
m_pBlob = AllocBlob(cbBlob);
if (!m_pBlob)
{
// Critically low on memory
SignalCriticalError(RILLOG_EVENT_LOWMEMORY, __LINE__, __FILE__);
goto Error;
}
memcpy(m_pBlob, pBlob, cbBlob);
}
m_cbBlob = cbBlob;
fRet = TRUE;
Error:
return fRet;
}
//
//
//
BOOL CResponse::OKToError(HRESULT hr)
{
FUNCTION_TRACE(CResponse::OKToError);
DEBUGCHK(RIL_RESULT_OK == m_dwCode);
DEBUGCHK(FALSE == m_fUnsolicited);
return MakeError(hr);
}
//
//
//
BOOL CResponse::MakeError(const HRESULT hrError)
{
FUNCTION_TRACE(CResponse::MakeError);
// Get rid of the old blob
FreeBlob(m_pBlob);
m_pBlob = NULL;
m_cbBlob = 0;
m_fUnsolicited = FALSE;
m_dwCode = RIL_RESULT_ERROR;
return SetBlob((void*)&hrError, sizeof(HRESULT));
}
//
// Parse a response
//
BOOL CResponse::Parse(UINT& rcbNewLength, BOOL fDataOnNotificationPort)
{
FUNCTION_TRACE(CResponse::Parse);
// NULL-terminate the response string temporarily
m_szData[m_cbLength] = '\0';
#ifdef DEBUG
DEBUGMSG(ZONE_ATCMD, (TEXT("RILDrv : i : Accumulated response: %s\r\n"), TString(PrintableString(m_szData, m_cbLength))));
#else
#ifdef WANT_RETAIL_RILDRV_OUTPUT
{
char szPrint[256];
const char szCR[] = "<cr>";
const char szLF[] = "<lf>";
UINT iPrint = 0;
UINT iChars = 0;
// convert \r, \n to visible chars.
while (iChars < m_cbLength && iPrint < (sizeof(szPrint) - sizeof(szLF)))
{
if (m_szData[iChars] == '\r')
{
strcpy(&szPrint[iPrint], szCR);
iPrint += (sizeof(szCR) - 1);
}
else if (m_szData[iChars] == '\n')
{
strcpy(&szPrint[iPrint], szLF);
iPrint += (sizeof(szLF) - 1);
}
else
{
szPrint[iPrint] = m_szData[iChars];
iPrint++;
}
iChars++;
}
szPrint[iPrint] = '\0';
NKDbgPrintfW(TEXT("RilDrv: Accumulated response: %a\r\n"), szPrint);
}
#endif //WANT_RETAIL_RILDRV_OUTPUT
#endif // DEBUG
return (ParseNotification(rcbNewLength, fDataOnNotificationPort) ||
ParseOKOrError(TRUE, rcbNewLength) ||
ParseOKOrError(FALSE, rcbNewLength));
// Remove attempts to parse partial responses. Can't be done safely with the current architecture,
// since we can't safely verify at this point that this isn't a valid partial response.
// || ParsePartialResponse(rcbNewLength));
}
// 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);
LPCSTR szPointer = m_szData;
LPCSTR szResponse1;
LPCSTR 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);
LPCSTR szPointer = m_szData;
LPCSTR szCode = (fOK ? "0\r" : "4\r");
HRESULT hrError;
BOOL fRet;
Pre_ParseOKOrErrorOEM(szPointer);
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);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -