?? comhand.cpp
字號:
}
} while (!rfBackToCmdMode && fATOTimedOut && ++nAttempts < MAX_ATO_ATTEMPTS);
// If ATO timed out too many times, just assume we got stuck in command mode and hope for the best
// (The only other alternative is to reset the system)
if (fATOTimedOut)
{
(void)ExitDataMode();
rfBackToCmdMode=TRUE;
if (!SetupCallListEvaluation ())
{
DEBUGMSG(ZONE_ERROR, (TEXT("SendRILCmdsInDataMode : E : Error setting up Call List Evaluation\r\n")));
}
}
fRet = TRUE;
Error:
if (!rfBackToCmdMode)
{
if (fPortInitSucceded)
{
// Reset old timeouts
(void)SetCommTimeouts(m_hDownstream, &ctOld);
// Reset old state
(void)SetCommState(m_hDownstream, &dcbOld);
}
// Reset the old comm mask
if (fEnteredExclusiveUse)
{
(void)SetCommMask(m_hDownstream, dwMask);
}
}
// Exit exclusive use mode
if (fEnteredExclusiveUse)
{
(void)ExitExclusiveUse();
}
delete pCmd;
return fRet;
}
//
//
//
BOOL CComHandle::FEnoughTimeToSendCmd(CCommand* pCmd, DWORD dwTimeLeft) const
{
// FUNCTION_TRACE(CComHandle::FEnoughTimeToSendCmd);
DEBUGCHK(NULL != pCmd);
BOOL fRet = (pCmd->GetExecTime() <= dwTimeLeft);
if (!fRet)
{
// This command will take too long to execute -- age the command
pCmd->Age();
}
return fRet;
}
//
//
//
void CComHandle::UpdateComStatData(const BOOL fRead, const DWORD dwBytes)
{
// FUNCTION_TRACE(CComHandle::UpdateComStatData);
SYNCBLOCK(m_csStats);
DEBUGCHK(FALSE != m_fInited);
UINT nBucketsToShift;
DWORD* pdwBuckets = (fRead ? m_rgdwReadStatBits : m_rgdwWriteStatBits);
DWORD* pdwLastTime = (fRead ? &m_dwReadStatTimestamp : &m_dwWriteStatTimestamp);
DWORD dwCurrentTime = GetTickCount();
DEBUGCHK(NULL != pdwBuckets);
if (dwCurrentTime != *pdwLastTime)
{
// Determine which bucket the new data goes into
nBucketsToShift = (dwCurrentTime - *pdwLastTime) / m_dwStatQuantum;
if (STAT_BUCKETS < nBucketsToShift)
{
nBucketsToShift = STAT_BUCKETS;
}
if (nBucketsToShift)
{
// Shift the data in buckets, if needed
if (STAT_BUCKETS > nBucketsToShift)
{
memmove(pdwBuckets + nBucketsToShift, pdwBuckets, (STAT_BUCKETS - nBucketsToShift) * sizeof(DWORD));
}
// Clear out all the new buckets upfront
memset(pdwBuckets, 0x00, nBucketsToShift * sizeof(DWORD));
}
// Place the new data into the first bucket
*pdwBuckets += (dwBytes * 8);
// Update the timestamp
*pdwLastTime = dwCurrentTime;
}
}
//
//
//
void CComHandle::CalculateComStats(DWORD& rdwReadBitsPerSec, DWORD& rdwWrittenBitsPerSec)
{
// FUNCTION_TRACE(CComHandle::CalculateComStats);
SYNCBLOCK(m_csStats);
DEBUGCHK(FALSE != m_fInited);
UINT i;
DWORD dwReadBitsPerQuantum = 0;
DWORD dwWrittenBitsPerQuantum = 0;
HANDLE hThread = GetCurrentThread();
DWORD dwOldPri;
// Switch to the highest priority
dwOldPri = GetThreadPriority(hThread);
(void)SetThreadPriority(hThread, THREAD_PRIORITY_HIGHEST);
// Update the read and write statistics
UpdateComStatData(TRUE, 0);
UpdateComStatData(FALSE, 0);
// Calculate weighted averages of data in read and write buckets (in bits per m_dwStatQuantum msec)
for (i = 0; i < STAT_BUCKETS; i++)
{
dwReadBitsPerQuantum += m_rgdwReadStatBits[i] * (STAT_BUCKETS - i) / STAT_BUCKET_WEIGHTS;
dwWrittenBitsPerQuantum += m_rgdwWriteStatBits[i] * (STAT_BUCKETS - i) / STAT_BUCKET_WEIGHTS;
}
// Convert the averages to bits per sec
rdwReadBitsPerSec = dwReadBitsPerQuantum * 1000 / m_dwStatQuantum;
rdwWrittenBitsPerSec = dwWrittenBitsPerQuantum * 1000 / m_dwStatQuantum;
DEBUGMSG(ZONE_TRACE, (TEXT("RILDrv : t : CComHandle::CalculateComStats : Com statistics: read - %d bits/sec, write - %d bits/sec\r\n"),
rdwReadBitsPerSec, rdwWrittenBitsPerSec));
// Switch back to the old priority
(void)SetThreadPriority(hThread, dwOldPri);
}
//
//
//
DWORD CComHandle::CalculateCmdModeTime()
{
// FUNCTION_TRACE(CComHandle::CalculateCmdModeTime);
DEBUGCHK(0 != m_dwDownstreamBaudRate);
DWORD dwReadBitsPerSec;
DWORD dwWriteBitsPerSec;
DWORD dwBitsPerSecOverAir;
DWORD dwBitsPerQuantumOverAir;
DWORD dwTimeToSendBitsToRadio;
// Calculate average read and write throughput
CalculateComStats(dwReadBitsPerSec, dwWriteBitsPerSec);
dwBitsPerSecOverAir = dwReadBitsPerSec + dwWriteBitsPerSec;
// Calculate how many bits go over the air in m_dwStatQuantum msec, given the average throughput
// we just calculated
dwBitsPerQuantumOverAir = dwBitsPerSecOverAir * m_dwStatQuantum / 1000;
// Calculate the time we need to send these bits to the radio
dwTimeToSendBitsToRadio = dwBitsPerQuantumOverAir * 1000 / m_dwDownstreamBaudRate;
// Calculate the time difference (i.e. the time during which the radio is idle while the bits are sent
// over the air)
return m_dwStatQuantum - dwTimeToSendBitsToRadio;
}
//
// Function passed to CQueue::ConditionalGet() below
//
BOOL FDialAnswerCommand(void* pItem, DWORD dwData)
{
FUNCTION_TRACE(FDialAnswerCommand);
DEBUGCHK(NULL != pItem);
DEBUGCHK(NULL == dwData);
CCommand* pCmd = (CCommand*)pItem;
return (pCmd->FDial() || pCmd->FAnswer());
}
//
//
//
DWORD WINAPI HangupThreadProc(LPVOID lpParameter)
{
FUNCTION_TRACE(HangupThreadProc);
CCommand* pNextCmd = NULL;
HANDLE hQuitEvent;
CComHandle* pComDevice;
CRilHandle* pRilDevice;
{
HANGUP_THREAD_DATA* phtd = (HANGUP_THREAD_DATA*)lpParameter;
DEBUGCHK(NULL != phtd);
DEBUGCHK(NULL != phtd->hQuitEvent);
DEBUGCHK(NULL != phtd->pComDevice);
DEBUGCHK(NULL != phtd->pRilDevice);
hQuitEvent = phtd->hQuitEvent;
pComDevice = phtd->pComDevice;
pRilDevice = phtd->pRilDevice;
delete phtd;
}
HANDLE hEvents[2] = {g_hNewDialOrHangupEvent, hQuitEvent};
DWORD dwWait;
for (;;)
{
dwWait = WaitForMultipleObjects(2, hEvents, FALSE, INFINITE);
if (dwWait != WAIT_OBJECT_0)
{
break;
}
if (SUCCEEDED(g_pCmdQ->ConditionalGet(FDialAnswerCommand, 0, pNextCmd, 0)))
{
// The first command in the queue is a dial or answer
// Because it hasn't been issued yet, we can abort it easily by
// removing the command and faking a response.
DEBUGCHK(NULL != pNextCmd);
DEBUGCHK(pNextCmd->FDial() || pNextCmd->FAnswer());
// Fake a NOCARRIER response (acceptable for both failed dial and answer commands)
pNextCmd->SendResponse(RIL_RESULT_NOCARRIER, NULL, 0);
delete pNextCmd;
pNextCmd = NULL;
}
else if (g_pCmdQ->Peek(pNextCmd) && pNextCmd->FHangup())
{
// The first command in the queue is a hangup, so the dial/answer has
// already been issued. We must abort the ongoing command.
DEBUGMSG(ZONE_INFO, (TEXT("RILDrv : i : HangupThreadProc : Aborting dial/answer\r\n")));
pComDevice->SetCancelledDial();
// Send AT/r to abort the call
// Don't remove the command from the queue; the command thread will wake up later and
// send an additional ATH\r in case the far end picked up before we got a chance to abort.
(void)pComDevice->WriteCmdsToComPort(pRilDevice, "AT\r", 3);
RIL_EVENTLOG_MSG((RILLOG_EVENT_SENDINGCMD, PrintableString("AT\r", 3)));
}
}
(void)CloseHandle(hQuitEvent);
return 0;
}
//
// Wait for the radio signon message
//
BOOL CComHandle::WaitForRadioSignon(CRilHandle* const pRilDevice)
{
BOOL fRet = FALSE;
HRESULT hr = NOERROR;
CResponse* pRsp = NULL;
DEBUGMSG(ZONE_INFO, (TEXT("RILDrv : i : CComHandle::WaitForRadioSignon : Waiting for radio signon\r\n")));
// Let RIL know we're waiting for AT response
pRilDevice->StartWaitingForRsp(NULL);
// Get the response out of the Response Queue
hr = g_pRspQ->Get(pRsp, 60000);
// See if we couldn't get the response for some reason
if (SUCCEEDED(hr)) {
fRet = TRUE;
}
// Let RIL know we're not waiting for AT response anymore
pRilDevice->StopWaitingForRsp();
delete pRsp;
return fRet;
}
//
// Send an RIL command to the downstream port
//
BOOL CComHandle::SendRILCmdHandleRsp(CRilHandle* const pRilDevice, CCommand*& rpCmd, BOOL& rfHungUp, BOOL& rfTimedOut)
{
// FUNCTION_TRACE(CComHandle::SendRILCmdHandleRsp);
DEBUGCHK(NULL != pRilDevice);
DEBUGCHK(NULL != rpCmd);
LPCSTR szCmd;
CResponse* pRsp = NULL;
HANDLE hQuitEvent=NULL;
HRESULT hr = E_FAIL;
BOOL fRet = FALSE;
rfHungUp = FALSE;
rfTimedOut = FALSE;
DEBUGMSG(ZONE_TRACE, (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
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)
pRsp->MakeOK();
// We can't possibly fail a no-op
hr = S_OK;
}
else if ((g_bSettingMinimumEquipmentState || 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 some radios do
// not behave well when some commands are sent when the radio is in
// the minimum power mode.
// If we are attempting to set the radio to it's minimum equipment state, we need to disallow any
// other AT commands that could alter the device's state. This is due to the changes in the
// RILDrv_SetEquipmentState. The driver must now clean up active voice and data calls. This
// will take longer and potentially leave the driver open for more AT commands.
// Allocate a new response
if (FAILED(PDD_GetResponseObject(pRsp)) || !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);
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -