⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 comhand.cpp

📁 手机RILGSM实现的源代码
💻 CPP
📖 第 1 页 / 共 5 页
字号:
    {
        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;
        }
    } 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;
        (void)pRilDevice->BroadcastRealBlobNotification(RIL_NOTIFY_CALLSTATECHANGED, NULL, 0);
    }

    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();
    BOOL fRet = FALSE;

    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);
            g_RilLog.LogEvent(RILLOG_ZONE_CMD, RILLOG_EVENT_SENDINGCMD, PrintableString("AT\r", 3));
        }
    }

    (void)CloseHandle(hQuitEvent);
    return 0;
}

#ifdef OEM1_DRIVER
//
// 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;
}
#endif // OEM1_DRIVER

//
// 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);

    LPSTR szCmd = NULL;
    CResponse* pRsp = NULL;
    HANDLE hQuitEvent=NULL;
    HRESULT hr = S_OK;
    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);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -