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

📄 rilhand.cpp

📁 Xcale270Bsp包,wince平台
💻 CPP
📖 第 1 页 / 共 4 页
字号:
/*++
THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
PARTICULAR PURPOSE.
Copyright (c) 1995-1999  Microsoft Corporation

Module Name:

handle.cpp

Abstract:


Notes:


--*/


#include "precomp.h"
#include "simmgr.h"
#include "bvd1.h"
#include "bvd1bd.h"
#include "xllp_bcr.h"

#ifdef BSP_MAINSTONE
    volatile XLLP_BCR_T  *v_pBCRRegs = NULL;
    // Mainstone SW10 is bit 13 of the General-Purpose Switch Register GPSWR
#define  BCR_GPSWR_SW10_MSK  XLLP_BCR_GPSR_GPSWT5  // Note: Bit set if no-dot position

#endif

HRESULT ParseGetPhoneLockedState(LPCSTR szRsp, void*& pBlob, UINT& cbBlob);

// RIL registry key
const LPCTSTR g_tszRegKeyRIL = TEXT("Software\\Microsoft\\RIL");

// RIL API info registry key
const LPCTSTR g_tszRegKeyAPIInfo = TEXT("Software\\Microsoft\\RIL\\APIInfo\\");

// RIL opertor names registry key
const LPCTSTR g_tszRegKeyOperNames = TEXT("Software\\Microsoft\\RIL\\OperatorNames");

const HRESULT INITIAL_COMMAND_ID = 1;

DWORD g_TimeoutCmdInit;
DWORD g_TimeoutCmdNoOp;
DWORD g_TimeoutCmdOnline;
DWORD g_TimeoutAPIDefault;
DWORD g_TimeoutDTRDrop;
DWORD g_TimeoutWaitForInit;

// It's safe to put these params in globals since the SIM PW prompt thread is only launched from the command thread,
// and no more than one SIM PW prompt thread at a time is launched.
BOOL g_PromptingForSim=FALSE;
DWORD g_dwLockFacility;
CQueue<CCommand, 10>* g_pSimLockedQueue;



// HW-SPECIFIC: The following init commands are hardware-specific
// NOTES: Z                 resets the AT interface
//        +CPIN?            initializes the SIM (OEM1 only)
//        S0=0              disables auto-answer
//        E0                disables command echo
//        Q0                enable result codes
//        V0                enable non-verbose responses
//        X3                enable busy signal detection and additional info in CONNECT response (OEM1 only)
//        X4                enable busy signal detection and additional info in CONNECT response
//        &C1               enables DCD to be used for carrier detection
//        &D1               enables DTR to be used for dropping out of data mode
//        &S1               enables DSR off ==> cmd mode, DSR on ==> data mode (WaveCom only)
//        %C0               disables dat compression (WaveCom series 2 only)
//        +WIND=8           enables +WIND notifications (WaveCom only)
//        +CMEE=1           enables +CME ERROR and +CMS ERROR responses
//        +CRC=1            enables +CRING notifications
//        +CR=1             enables +CR notifications
//        +CMOD=0           enables single call mode
//        +CREG=1           enables short +CREG notifications
//        +FCLASS=0         enables data mode
//        +CSSN=0,1         enables +CSSU notifications
//        +CHSR=1           enables +CHSR notifications
//        +CLIP=1           enables +CLIP notifications
//        +CLIR=2           enables CallerID presentatin on outgoing calls
//        +COLP=1           enables +COLP notifications
//        +CCWA=1           enables +CCWA notifications
//        %SATC=1           enables %SATI, %SATN, and %SATA notifications (OEM1 only)
//        +CMGF=0           enables SMS PDU mode
//        +CNMI=2,2,2,1,0   enables +CMT, +CBM, and +CDS notifications
//        +CSCS="8859-1"    sets default alphabet to ISO 8859-1
//        +CSCS="PCCP437"   sets default alphabet to PC CodePage 437 (WaveCom only)

const INITSTRING_DATA g_rgisdModuleInit[] =
{
    // WaveCom init commands
#if defined(WAVECOM_DRIVER)
    { "ZS0=0E0Q0V0X4&C1&D1&S1", CMDOPT_INIT | CMDOPT_GENERALINIT},
    { "ZS0=0E0Q0V0X4&C1&D1&S1|+WIND=8;+CMEE=1;+CRC=1;+CR=1;+CMOD=0;+CREG=1|+FCLASS=0|+CSSN=0,1|", CMDOPT_INIT | CMDOPT_GENERALINIT},
    { "+CLIP=1;+COLP=0;+CCWA=1,2;+CAOC=2;+CMGF=0;+CNMI=2,2,2,1,0;+CSCS=\"GSM\";+CSAS|&W",    CMDOPT_INIT | CMDOPT_SMSINIT},

    // OEM1 devboard init command
#elif defined(OEM1_DRIVER)
    { "Z;S0=0;E0;Q0;V0|X3;&C1;&D1;+CMEE=1;+CRC=1;+CR=1;+CMOD=0;+CREG=1;+FCLASS=0;+CSSN=0,1;+CLIP=1;+COLP=0;+CCWA=1;+CSCS=\"HEX\";+CMGF=0|+CGREG=1|+CUSD=1|"
#if defined(RIL_ENABLE_SIMTK)
    "%SATC=1|"
#endif
    "+CNMI=2,2,2,1,0\\24,5000\\|", CMDOPT_INIT | CMDOPT_GENERALINIT},
    // temporarily remove pending support for these cmds
    // they're failure is causing RIL_E_RADIOFAILEDINIT failures
#if defined(TPC) && !defined(OEMW_DRIVER)
    { "$AS=100|$AU=200|$AD=200|", CMDOPT_INIT | CMDOPT_GENERALINIT},
#else
    { "E0", CMDOPT_INIT | CMDOPT_GENERALINIT},
#endif

    // Generic init command used by default GSM hardware
#else  // defined(WAVECOM_DRIVER) || defined(OEM1_DRIVER)
    { "ZS0=0E0Q0V0X4&C1&D1;+CMEE=1;+CRC=1;+CR=1;+CMOD=0;+CREG=1;+FCLASS=0;+CSSN=0,1;+CHSR=1;+CLIP=1;+COLP=0;+CCWA=1;+CMGF=0;+CNMI=2,2,2,1,0;+CSCS=\"GSM\";&W", CMDOPT_INIT | CMDOPT_GENERALINIT | CMDOPT_SMSINIT},
#endif // defined(WAVECOM_DRIVER) || defined(OEM1_DRIVER)
};

//
// RIL handle ctor
//
CRilHandle::CRilHandle()
: m_hInitEvent(NULL),
m_hCancelEvent(NULL),
m_hDataEvent(NULL),
m_hSimReadyEvent(NULL),
m_hCmdThread(NULL),
m_hReadThread(NULL),
m_fQuitReadyStateThread(FALSE),
m_dwCmdThreadID(0),
m_dwReadThreadID(0),
m_pCheckPoint(NULL),
m_pMonitor(NULL),
m_pInstances(NULL),
m_hrNextCmdID(INITIAL_COMMAND_ID),
m_pComDevice(NULL),
m_pReadBytes(NULL),
m_dwDataModeCmdDelay(3000),
m_dwMaxDataModeTimeWithoutCmd(30000),
m_fInited(FALSE),
m_fFailedInit(FALSE),
m_fInitedForSMS(FALSE),
m_fWaitingForRsp(FALSE),
m_fEmergencyMode(FALSE),
m_fSimReady(FALSE),
m_fLastCommandTimedOut(FALSE)
{
    // // TBD_FUNCTION(CRilHandle::CRilHandle);
    // Intialize critical sections
    InitializeCriticalSection(&m_cs);
    InitializeCriticalSection(&m_csInstances);
    InitializeCriticalSection(&m_csCmdID);
    InitializeCriticalSection(&m_csEmergency);

    memset(m_rgpAPIInfo, 0x00, APIID_TOTAL * sizeof(APIINFO*));
}


//
// Function passed to CDlbList::Enum() below
//
BOOL DeleteInstanceHandle(void* pItem, DWORD dwData)
{
    TBD_ASSERT(pItem != NULL);

    CRilInstanceHandle* pHandle = (CRilInstanceHandle*)pItem;
    delete pHandle;

    // Continue enumeration
    return FALSE;
}

//
// RIL handle dtor
//
CRilHandle::~CRilHandle()
{
    // // TBD_FUNCTION(CRilHandle::~CRilHandle);

    UINT i;

    {
        SYNCBLOCK(m_cs);

        HANDLE rghThreads[2] = { m_hCmdThread, m_hReadThread};

        // Signal the cancel event to kill the thread
        if (m_hCancelEvent)
        {
            (void)SetEvent(m_hCancelEvent);
        }

        // Reset the COM port
        if (m_pComDevice)
        {
            (void)DeinitComPort(m_pComDevice);
        }

        StopReadyStateQuery();

        // Wait for auxiliary threads to terminate
        (void)WaitForSingleObject(m_hCmdThread, 10000);
        (void)WaitForSingleObject(m_hReadThread, 10000);

        // Get rid of the threads
        if (m_hCmdThread)
        {
            (void)CloseHandle(m_hCmdThread);
            m_hCmdThread = NULL;
            m_dwCmdThreadID = 0;
        }

        if (m_hReadThread)
        {
            (void)CloseHandle(m_hReadThread);
            m_hReadThread = NULL;
            m_dwReadThreadID = 0;
        }

        // Get rid of the event
        if (m_hCancelEvent)
        {
            (void)CloseHandle(m_hCancelEvent);
            m_hCancelEvent = NULL;
        }

        // Get rid of the checkpoint
        delete m_pCheckPoint;
        m_pCheckPoint = NULL;

        // Get rid of the monitor
        delete m_pMonitor;
        m_pMonitor = NULL;

        // Get rid of the queues
        delete g_pCmdQ;
        delete g_pRspQ;
        delete g_pSimLockedQueue;
        g_pCmdQ = NULL;
        g_pRspQ = NULL;
        g_pSimLockedQueue = NULL;

        // Close the serial port
        if (m_pComDevice)
        {
            COM_CloseInternal(m_pComDevice);
            m_pComDevice = NULL;
        }

        // All of the instance handles should be closed
        // before the driver handle is destroyed.
        m_pInstances->Enum(DeleteInstanceHandle, 0);

        // Delete the instance handle list
        delete m_pInstances;
        m_pInstances = NULL;

        // Delete the Read Bytes buffer
        delete m_pReadBytes;
        m_pReadBytes = NULL;

        // Get rid of init event
        if (m_hInitEvent)
        {
            (void)CloseHandle(m_hInitEvent);
            m_hInitEvent = NULL;
        }

        // Get rid of data event
        if (m_hDataEvent)
        {
            (void)CloseHandle(m_hDataEvent);
            m_hDataEvent = NULL;
        }

        // Delete the API information structures
        for (i = 0; i < APIID_TOTAL; i++)
        {
            delete m_rgpAPIInfo[i];
            m_rgpAPIInfo[i] = NULL;
        }

        DeleteCriticalSection(&m_csInstances);
        DeleteCriticalSection(&m_csCmdID);
        DeleteCriticalSection(&m_csEmergency);
        m_fInited = FALSE;
        m_fFailedInit=FALSE;
        m_fInitedForSMS = FALSE;
    }

    DeleteCriticalSection(&m_cs);
}

//
// Broadcasts a change in the radio ready state
//
void CRilHandle::SendReadyStateNotification(DWORD dwReadyState, BOOL fBroadcast)
{
    RILEQUIPMENTSTATE res;
    CNotificationData *pnd = NULL;

#if defined(OEM1_DRIVER)
    if ((dwReadyState & RIL_READYSTATE_UNLOCKED) && !(g_dwReadyState & RIL_READYSTATE_UNLOCKED))
    {
        // certain commands like COPS need to wait for the module to
        // "settle" after it's been unlocked.
        g_dwUnlocked = GetTickCount();
    }
#endif

    // Set this in our global
    if (dwReadyState)
    {
        g_dwReadyState |= dwReadyState;
    }
    else
    {
        g_dwReadyState = 0;
    }

    if (fBroadcast)
    {
        // Broadcast the notification
        memset(&res, 0x00, sizeof(RILEQUIPMENTSTATE));
        res.cbSize = sizeof(RILEQUIPMENTSTATE);
        res.dwParams = RIL_PARAM_EQUIPMENTSTATE_READYSTATE;
        res.dwReadyState = g_dwReadyState;
        pnd = new CNotificationData;
        if (pnd && pnd->InitFromRealBlob(RIL_NOTIFY_RADIOEQUIPMENTSTATECHANGED, (void *) &res, res.cbSize))
        {
            // Note that BroadcastNotification frees pnd
            BroadcastNotification(pnd);
            pnd = NULL;
        }

        delete pnd;
    }

    // Now, update StatStor
    UpdateStatStore();
}

//
// Thread responsible for sending commands from the Command Queue to COM port
//
DWORD WINAPI SimReadyThreadProc(LPVOID lpParameter)
{
    TBD_FUNCTION(SimReadyThreadProc);
    TBD_ASSERT(lpParameter != NULL);
    CRilHandle* pRilDevice = (CRilHandle*)lpParameter;
    TBD_OUTPUT(TBDCT_INFO, TBDOL_TRACE, TEXT("SimReadyThreadProc : Entering, pRilDevice=0x%x"),pRilDevice);
    const DWORD dwReturn = pRilDevice->SimReadyThread();
    TBD_OUTPUT(TBDCT_INFO, TBDOL_ERROR, TEXT("SimReadyThreadProc : THREAD IS EXITING, dwReturn=0x%x"),dwReturn);
    return dwReturn;
}

//
// Loop until RIL is ready to process SIM commands
//
DWORD CRilHandle::SimReadyThread()
{
    CCommand *pCmd = NULL;
    APIINFO apiiInfo;
    const APIID apiid = APIID_GETPHONELOCKEDSTATE;

    // Create an event
    m_fSimReady = FALSE;
    m_hSimReadyEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
    if (!m_hSimReadyEvent)
    {
        goto Error;
    }

    // Get the info about this API
    memset(&apiiInfo,0,sizeof(apiiInfo));
    GetAPIInfo(apiid, apiiInfo);

    // Query for the PIN until we don't get back 515 as an error
    do
    {
        TBD_OUTPUT(TBDCT_INFO, TBDOL_TRACE, TEXT("SimReadyThread : Sending SIM Query Command..."));

        // Set up a CPIN command to be sent
        // Note that we don't care what the return value is, so long as it's not that the radio isn't ready
        pCmd = new CCommand;
#ifdef WAVECOM_DRIVER
        if (!pCmd || !pCmd->Init(NULL, "AT+CPIN?\r", CMDOPT_SIMQUERY, apiiInfo.dwExecTime, apiiInfo.dwTimeout, NULL, NULL, 0, 0, 0, apiid))
 #else
        if (!pCmd || !pCmd->Init(NULL, "AT+CPIN?\r", CMDOPT_SIMQUERY, apiiInfo.dwExecTime, apiiInfo.dwTimeout, NULL, ParseGetPhoneLockedState, 0, 0, 0, apiid))
 #endif
        {
            TBD_OUTPUT(TBDCT_INFO, TBDOL_ERROR, TEXT("SimReadyThread : Unable to construct or Init CCommand"));
            goto Error;
        }

        // Place the command into the command queue
        //    (this may block if the queue is full)
        if (!g_pCmdQ->Put(pCmd, INFINITE))
        {
            goto Error;
        }

        // Now, block until we get a response back
        WaitForSingleObject(m_hSimReadyEvent, apiiInfo.dwTimeout);

        // Sleep a bit before the next try
        if (!m_fSimReady && !m_fQuitReadyStateThread)
        {
            Sleep(2000);
        }
    }
    while (!m_fSimReady && !m_fQuitReadyStateThread);

    if (m_fQuitReadyStateThread)
    {
        goto Error;
    }

#ifndef WAVECOM_DRIVER
    // We don't have a way to say SMS is ready, so we'll just sleep 30 seconds and hope that's enough
    Sleep(30000);
    SendReadyStateNotification(RIL_READYSTATE_SMS, TRUE);
#endif

Error:
    if (m_hSimReadyEvent)
    {
        CloseHandle(m_hSimReadyEvent);
        m_hSimReadyEvent = NULL;
    }

    return 0;
}

//
// Launch a thread to see if the SIM is ready or not
//
void CRilHandle::StartReadyStateQuery()
{
    m_fQuitReadyStateThread = FALSE;
    HANDLE hThread = CreateThread(NULL, 0, SimReadyThreadProc, (LPVOID)this, 0, NULL);
    if (NULL != hThread)
        CloseHandle(hThread);   // close handle we don't need
}

void CRilHandle::StopReadyStateQuery()
{
    m_fQuitReadyStateThread = TRUE;
    if (m_hSimReadyEvent)
    {
        SetEvent(m_hSimReadyEvent);
    }
}

//
// Start initialization
//
BOOL CRilHandle::StartInit()
{
    // // TBD_FUNCTION(CRilHandle::StartInit);

    SYNCBLOCK(m_cs);

    DWORD dwTemp;
    BOOL fRet = FALSE;

    if (m_fInited)
    {
        fRet = TRUE;
        goto Error;
    }

    // Read parameters from the registry
    if (GetRegistryDWORD(HKEY_LOCAL_MACHINE, g_tszRegKeyRIL, TEXT("DataModeCmdDelay"), &dwTemp))
    {
        m_dwDataModeCmdDelay = dwTemp;
    }
    if (GetRegistryDWORD(HKEY_LOCAL_MACHINE, g_tszRegKeyRIL, TEXT("MaxDataModeTimeWithoutCmd"), &dwTemp))
    {
        m_dwMaxDataModeTimeWithoutCmd = dwTemp;
    }

    g_TimeoutCmdInit = TIMEOUT_CMD_INIT;
    if (GetRegistryDWORD(HKEY_LOCAL_MACHINE, g_tszRegKeyRIL, TEXT("TimeoutCmdInit"), &dwTemp))
    {
        g_TimeoutCmdInit = dwTemp;
    }

    g_TimeoutCmdNoOp = TIMEOUT_CMD_NOOP;
    if (GetRegistryDWORD(HKEY_LOCAL_MACHINE, g_tszRegKeyRIL, TEXT("TimeoutCmdNoOp"), &dwTemp))
    {
        g_TimeoutCmdNoOp = dwTemp;
    }

    g_TimeoutCmdOnline = TIMEOUT_CMD_ONLINE;
    if (GetRegistryDWORD(HKEY_LOCAL_MACHINE, g_tszRegKeyRIL, TEXT("TimeoutCmdOnline"), &dwTemp))
    {
        g_TimeoutCmdOnline = dwTemp;
    }

    g_TimeoutAPIDefault = TIMEOUT_API_DEFAULT;
    if (GetRegistryDWORD(HKEY_LOCAL_MACHINE, g_tszRegKeyRIL, TEXT("TimeoutAPIDefault"), &dwTemp))
    {
        g_TimeoutAPIDefault = dwTemp;
    }

    g_TimeoutDTRDrop = TIMEOUT_DTRDROP;
    if (GetRegistryDWORD(HKEY_LOCAL_MACHINE, g_tszRegKeyRIL, TEXT("TimeoutDTRDrop"), &dwTemp))
    {
        g_TimeoutDTRDrop = dwTemp;
    }

    g_TimeoutWaitForInit = TIMEOUT_WAITFORINIT;
    if (GetRegistryDWORD(HKEY_LOCAL_MACHINE, g_tszRegKeyRIL, TEXT("TimeoutWaitForInit"), &dwTemp))
    {
        g_TimeoutWaitForInit = dwTemp;
    }

    // Create init event
    m_hInitEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
    if (!m_hInitEvent)
    {
        goto Error;
    }

    // Create data event
    m_hDataEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
    if (!m_hDataEvent)
    {
        goto Error;
    }

⌨️ 快捷键说明

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