?? comhand.cpp
字號:
{
// Break is detected on the downstream port
if (ClearCommBreak(m_hDownstream))
{
DEBUGMSG(ZONE_ERROR, (TEXT("RILDrv : E : CComHandle::GetDTRDropResponse : Detected comm break\r\n")));
}
}
if (dwMask & EV_RXCHAR)
{
while (1)
{
// Get up to 1K of data
if (!DOWNST_READFILE(m_hDownstream, szData, 1024, &dwRead))
{
goto Error;
}
if (!dwRead)
{
break;
}
#ifdef DEBUG
DEBUGMSG(ZONE_TRACE, (TEXT("RILDrv : t : CComHandle::GetDTRDropResponse : Read bytes(3): %s\r\n"), TString(PrintableString(szData, dwRead))));
#endif
// Append what we got to the temporary buffer
if (!bufTemp.Append(szData, dwRead))
{
// Critically low on memory
SignalCriticalError(RILLOG_EVENT_LOWMEMORY, __LINE__, __FILE__);
goto Error;
}
// Get the accumulated string
szTotal = bufTemp.GetData();
cbTotal = bufTemp.GetLength();
#ifdef DEBUG
DEBUGMSG(ZONE_TRACE, (TEXT("RILDrv : t : CComHandle::GetDTRDropResponse : Accumulated DTR response has %d chars: %s\r\n"), cbTotal,
TString(PrintableString(szTotal, cbTotal))));
#endif
// Look for the indication of successful DTR drop
if (MatchBytesAnywhere((BYTE*)szTotal, cbTotal, (BYTE*)"0\r\r\n", 4, const_cast<const BYTE*&>(pbRemainder)))
{
// We found "0\r\r\n", i.e. OK<CR> followed by <CR><LF> (starting an unsolicited notification)
DEBUGCHK(NULL != pbRemainder);
// Include the terminating <CR><LF> in the remainder
pbRemainder -= 2;
}
else if (MatchBytesEnd((BYTE*)szTotal, cbTotal, (BYTE*)"0\r", 2, const_cast<const BYTE*&>(pbRemainder)))
{
// We found '0\r" at the very end of the data
DEBUGCHK(NULL != pbRemainder);
}
if (pbRemainder)
{
szRemainder = (LPCSTR)pbRemainder;
// Store any data before OK into the backup buffer
cbDataBeforeOK = szRemainder - szTotal - 2;
if (cbDataBeforeOK && !m_pBuffer->Append(szTotal, cbDataBeforeOK))
{
// Critically low on memory
SignalCriticalError(RILLOG_EVENT_LOWMEMORY, __LINE__, __FILE__);
goto Error;
}
// Store any data after OK in the response buffer of the read thread
cbDataAfterOK = cbTotal - (szRemainder - szTotal);
if (cbDataAfterOK && !pRilDevice->AppendReadBytes(szRemainder, cbDataAfterOK, false))
{
goto Error;
}
#ifdef DEBUG
DEBUGMSG(ZONE_INFO, (TEXT("RILDrv : i : CComHandle::GetDTRDropResponse : DTR successfuly dropped: %d bytes before, %d bytes after: %s\r\n"),
cbDataBeforeOK, cbDataAfterOK, TString(PrintableString(szRemainder,cbDataAfterOK))));
#endif
fRet = TRUE;
goto Error;
}
}
}
}
Error:
if (!fRet && bufTemp.GetLength())
{
// Append any data we've accumulated
(void)m_pBuffer->Append(bufTemp.GetData(), bufTemp.GetLength());
DEBUGMSG(ZONE_TRACE, (TEXT("RILDrv : t : CComHandle::GetDTRDropResponse : Stored %d bytes in the buffer\r\n"), bufTemp.GetLength()));
}
return fRet;
}
//
// A custom action callback passed to EnterExclusiveUse() below
//
void CComHandle::ResetCommMask(DWORD dwParam)
{
FUNCTION_TRACE(ResetCommMask);
DEBUGCHK(NULL != dwParam);
HANDLE hCom = (HANDLE)dwParam;
// Release any threads waiting on comm events
(void)SetCommMask(hCom, 0);
}
HRESULT ParseGetSignalQuality(LPCSTR szRsp, void*& pBlob, UINT& cbBlob);
HRESULT ParseBatteryInfo(LPCSTR szRsp, void*& pBlob, UINT& cbBlob);
#ifdef SUPPRESS_ONLINE_SIGNAL_STRENGTH
extern char gszGetSignalQualityLast[128];
#endif
#ifdef SUPPRESS_ONLINE_BATTERY_INFO
extern char gszGetBatteryInfoLast[128];
#endif
//
// Interrupt other serial operations on the downstream port and send an RIL command
// WARNING: this routine enters Exclusive Use mode, effectively blocking any other virtual
// serial port operation, so MAKE SURE not to block inside this routine.
//
BOOL CComHandle::SendRILCmdsInDataMode(CRilHandle* const pRilDevice, BOOL& rfBackToCmdMode)
{
// FUNCTION_TRACE(CComHandle::SendRILCmdsInDataMode);
DEBUGCHK(FALSE != m_fInited);
DEBUGCHK(FALSE != m_fPortOpened);
DEBUGCHK(FALSE != m_fDataMode);
DEBUGCHK(m_hDownstream != INVALID_HANDLE_VALUE);
DCB dcbOld; memset(&dcbOld,0,sizeof(dcbOld)); // zero struct
COMMTIMEOUTS ctOld; memset(&ctOld,0,sizeof(ctOld)); // zero struct
CCommand* pCmd = NULL;
CCommand* pCmdPeeked = NULL;
DWORD dwStartTime;
UINT nAttempts;
BOOL fInCmdMode = FALSE;
HRESULT hr;
DWORD dwMask=0;
DWORD dwTimeAllowedInCmdMode;
BOOL fEnteredExclusiveUse = FALSE;
BOOL fPortInitSucceded = FALSE;
BOOL fATOTimedOut;
BOOL fDummy;
BOOL fRet = FALSE;
DWORD dwStatus;
rfBackToCmdMode = FALSE;
if (GetCommModemStatus(m_hDownstream, &dwStatus))
{
#ifndef NO_RLSD_SUPPORT
if (!(dwStatus & MS_RLSD_ON))
{
// RLSD is off, which means that data connections has been dropped
DEBUGMSG(ZONE_INFO, (TEXT("RILDrv : i : CComHandle::SendRILCmdsInDataMode : Detected remote disconnect due to loss of RLSD\r\n")));
fInCmdMode = TRUE;
}
#endif
}
// Send out all the no-op commands at the front of the queue without dropping out of data mode
while (!fInCmdMode && g_pCmdQ->Peek(pCmdPeeked))
{
if (pCmdPeeked->FNoOp())
{
// Delete whatever was in the command structure
delete pCmd;
pCmd = NULL;
// Get the next command
hr = g_pCmdQ->Get(pCmd, 0);
if (FAILED(hr))
{
goto Error;
}
// Send the command
if (!SendRILCmdHandleRsp(pRilDevice, pCmd, rfBackToCmdMode, fDummy))
{
goto Error;
}
DEBUGCHK(NULL == pCmd);
}
#ifdef SUPPRESS_ONLINE_SIGNAL_STRENGTH
// Option to avoid getting signal strength while connected (avoids dropping DTR during data calls)
else if (pCmdPeeked->GetParseFunc()==ParseGetSignalQuality)
{
DEBUGMSG(ZONE_INFO, (TEXT("RILDrv : i : CComHandle::SendRILCmdsInDataMode : Faking signal quality\r\n")));
// Delete whatever was in the command structure
delete pCmd;
pCmd = NULL;
// Get the next command
hr = g_pCmdQ->Get(pCmd, 0);
if (FAILED(hr))
{
goto Error;
}
// Allocate a new response
CResponse *pRsp = NULL;
if (FAILED(PDD_GetResponseObject(pRsp)) || !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)
char *szRemainder;
UINT cbRemainder;
if (!pRsp->AppendString(gszGetSignalQualityLast, strlen(gszGetSignalQualityLast), const_cast<LPCSTR&>(szRemainder), cbRemainder, FALSE))
{
goto Error;
}
BOOL fHungUp;
if (!pRilDevice->HandleRsp(pCmd, pRsp, fHungUp, g_bRadioOff))
{
goto Error;
}
DEBUGCHK(NULL == pCmd);
}
#endif // SUPPRESS_ONLINE_SIGNAL_STRENGTH
#ifdef SUPPRESS_ONLINE_BATTERY_INFO
// Option to avoid getting battery strength while connected (avoids dropping DTR during data calls)
else if (pCmdPeeked->GetParseFunc()==ParseBatteryInfo)
{
DEBUGMSG(ZONE_INFO, (TEXT("RILDrv : i : CComHandle::SendRILCmdsInDataMode : Faking battery info\r\n")));
// Delete whatever was in the command structure
delete pCmd;
pCmd = NULL;
// Get the next command
hr = g_pCmdQ->Get(pCmd, 0);
if (FAILED(hr))
{
goto Error;
}
// Allocate a new response
CResponse *pRsp = NULL;
if (FAILED(PDD_GetResponseObject(pRsp)) || !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)
char *szRemainder;
UINT cbRemainder;
if (!pRsp->AppendString(gszGetBatteryInfoLast, strlen(gszGetBatteryInfoLast), szRemainder, cbRemainder, FALSE))
{
goto Error;
}
BOOL fHungUp;
if (!pRilDevice->HandleRsp(pCmd, pRsp, fHungUp, g_bRadioOff))
{
goto Error;
}
DEBUGCHK(NULL == pCmd);
}
#endif // SUPPRESS_ONLINE_BATTERY_INFO
else
{
break;
}
}
pCmdPeeked = NULL;
// See how much of the next quantum we can spend in the command mode
dwTimeAllowedInCmdMode = CalculateCmdModeTime();
DEBUGMSG(ZONE_TRACE, (TEXT("RILDrv : t : CComHandle::SendRILCmdsInDataMode : Time allowed in cmd mode: %d msec\r\n"), dwTimeAllowedInCmdMode));
// See if there are any commands in the queue
if (!g_pCmdQ->Peek(pCmdPeeked))
{
goto Error;
}
// See if the first command in the queue will take too long
if (!FEnoughTimeToSendCmd(pCmdPeeked, dwTimeAllowedInCmdMode))
{
goto Error;
}
pCmdPeeked = NULL;
// Get the comm mask used now
(void)GetCommMask(m_hDownstream, &dwMask);
#ifndef DEDICATED_DATA_PORT
SetEvent(m_hDataModeInterrupted);
#endif
// Enter exclusive use mode
if (!EnterExclusiveUse())
{
goto Error;
}
fEnteredExclusiveUse = TRUE;
dwStartTime = GetTickCount();
// Intialize downstream port for RIL use
if (!InitComPortForRIL(&dcbOld, &ctOld))
{
goto Error;
}
fPortInitSucceded = TRUE;
nAttempts = 0;
while (!fInCmdMode && nAttempts < MAX_DTR_ATTEMPTS)
{
#ifdef NO_DTR_SUPPORT
WriteCharsToComPort(pRilDevice, "+++", 3);
#else
// Drop the DTR
(void)EscapeCommFunction(m_hDownstream, CLRDTR);
DEBUGMSG(ZONE_INFO, (TEXT("RILDrv : i : CComHandle::SendRILCmdsInDataMode : Dropping DTR\r\n")));
#endif
// Verify that we got an "OK" response
fInCmdMode = GetDTRDropResponse(pRilDevice);
(void)EscapeCommFunction(m_hDownstream, SETDTR);
++nAttempts;
}
SetTimeoutStatus(!fInCmdMode);
// If we couldn't drop the DTR for some reason, bail for now
if (!fInCmdMode)
{
DEBUGMSG(ZONE_ERROR, (TEXT("RILDrv : E : CComHandle::SendRILCmdsInDataMode : Could not drop DTR\r\n")));
goto Error;
}
// Temporarily release threads waiting for command mode to operate
if (!SetEvent(m_hCommandModeEvent))
{
goto Error;
}
// Send as many commands as we can in the time we have (make sure to send at least one command)
while (!g_pCmdQ->FEmpty())
{
// Delete whatever was in the command structure
delete pCmd;
pCmd = NULL;
// Get the next command
hr = g_pCmdQ->Get(pCmd, 0);
if (FAILED(hr))
{
goto Error;
}
// Send the command
if (!SendRILCmdHandleRsp(pRilDevice, pCmd, rfBackToCmdMode, fDummy))
{
goto Error;
}
DEBUGCHK(NULL == pCmd);
// If this command forced us to hangup the data connection, bail out
if (rfBackToCmdMode)
{
fRet = TRUE;
goto Error;
}
// See if we can send another command
if (!g_pCmdQ->Peek(pCmdPeeked) ||
!FEnoughTimeToSendCmd(pCmdPeeked, dwTimeAllowedInCmdMode - (GetTickCount() - dwStartTime)))
{
break;
}
}
pCmdPeeked = NULL;
// Return to the data mode
nAttempts = 0;
do
{
pCmd = new CCommand;
if (!pCmd ||
!pCmd->Init(NULL, "ATO\r", NULL,
CMDOPT_IGNORERSP | CMDOPT_REQUIRECONNECTRSP,
EXECTIME_API_DEFAULT,
g_TimeoutCmdOnline,
NULL, NULL, 0, 0, 0, APIID_NONE, NULL, NULL))
{
goto Error;
}
if (!SendRILCmdHandleRsp(pRilDevice, pCmd, rfBackToCmdMode, fATOTimedOut))
{
goto Error;
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -