📄 rilhand.cpp
字号:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// Use of this sample source code is subject to the terms of the Microsoft
// license agreement under which you licensed this sample source code. If
// you did not accept the terms of the license agreement, you are not
// authorized to use this sample source code. For the terms of the license,
// please see the license agreement between you and Microsoft or, if applicable,
// see the LICENSE.RTF on your install media or the root of your tools installation.
// THE SAMPLE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES.
//
/*++
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.
Module Name:
rilhand.cpp
Abstract:
Notes:
--*/
#include "precomp.h"
#include "simmgr.h"
extern HANDLE g_mtxSetEquipmentState;
HRESULT ParseGetPhoneLockedState(LPCSTR szRsp, void*& pBlob, UINT& cbBlob);
#ifdef RIL_WATSON_REPORT
HRESULT ParseGetEquipmentInfo(LPCSTR szRsp, void*& pBlob, UINT& cbBlob);
#endif // RIL_WATSON_REPORT
HRESULT ParseGetPhonebookOptions(LPCSTR szRsp, void*& pBlob, UINT& cbBlob);
// RIL OEM independent registry key
const LPCTSTR g_tszRegKeyRILMS = 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");
// RIL Remote Calltype Determination registry key
const LPCTSTR g_tszRegKeyRemoteCalltype = TEXT("Comm\\Cellular\\RIL\\RemoteCalltype");
const HRESULT INITIAL_COMMAND_ID = 1;
DWORD g_TimeoutCmdInit;
DWORD g_TimeoutCmdNoOp;
DWORD g_TimeoutCmdOnline;
DWORD g_TimeoutAPIDefault;
DWORD g_TimeoutDTRDrop;
DWORD g_TimeoutWaitForInit;
DWORD g_dwLastCLIP = 1;
DWORD g_dwLastCLIR = 0;
// 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;
//
// RIL handle ctor
//
CRilHandle::CRilHandle()
: m_hInitEvent(NULL),
m_hCancelEvent(NULL),
m_hDataEvent(NULL),
m_hSimReadyEvent(NULL),
m_hInitedForSMSEvent(NULL),
m_hATCommandLogOwner(NULL),
m_hInitedForSIMPBEvent(NULL),
m_hCmdThread(NULL),
m_hReadThread(NULL),
m_fQuitReadyStateThread(FALSE),
m_dwCmdThreadID(0),
m_dwReadThreadID(0),
m_pCheckPoint(NULL),
#ifndef RIL_RADIO_RESILIENCE
m_pMonitor(NULL),
#endif // ! RIL_RADIO_RESILIENCE
m_pInstances(NULL),
m_hrNextCmdID(INITIAL_COMMAND_ID),
m_pComDevice(NULL),
m_pReadBytes(NULL),
m_pReadBytes2(NULL),
m_dwDataModeCmdDelay(3000),
m_dwMaxDataModeTimeWithoutCmd(30000),
m_fInited(FALSE),
m_fFailedInit(FALSE),
m_fInitedForSMS(FALSE),
m_fInitedForSIMPB(FALSE),
m_fWaitingForRsp(FALSE),
m_fEmergencyMode(FALSE),
m_fSimReady(FALSE),
m_dwSIMPBLastSize((DWORD)-1),
m_fLastCommandTimedOut(FALSE),
m_pCurrCommand(NULL)
{
// // FUNCTION_TRACE(CRilHandle::CRilHandle);
// Intialize critical sections
InitializeCriticalSection(&m_cs);
InitializeCriticalSection(&m_csInstances);
InitializeCriticalSection(&m_csCmdID);
InitializeCriticalSection(&m_csEmergency);
if ( TRUE == GetRegistryPacketSupport())
{
// This object owns the pointer returned by PDD_GetRilNdisObject
// PDD_GetRilNdisObject is not expected to return E_NOTIMPL here since the above check succeeds
HRESULT hr = PDD_GetRilNdisObject(this, m_pCRilNdis);
if ( FAILED( hr ) )
{
DEBUGMSG(ZONE_ERROR, (TEXT("RILDrv : E : CRilHandle ctor : PDD_GetRilNdisObject failed , hr = [0x%08x]\r\n"), hr));
}
}
else
{
m_pCRilNdis = NULL;
}
memset(m_rgpAPIInfo, 0x00, APIID_TOTAL * sizeof(APIINFO*));
}
//
// Function passed to CDlbList::Enum() below
//
BOOL DeleteInstanceHandle(void* pItem, DWORD dwData)
{
DEBUGCHK(pItem != NULL);
CRilInstanceHandle* pHandle = (CRilInstanceHandle*)pItem;
delete pHandle;
// Continue enumeration
return FALSE;
}
//
// RIL handle dtor
//
CRilHandle::~CRilHandle()
{
// // FUNCTION_TRACE(CRilHandle::~CRilHandle);
UINT i;
{
SYNCBLOCK(m_cs);
// 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);
// Kill NDIS Thread
if (m_pCRilNdis) {
m_pCRilNdis->NdisStop();
delete m_pCRilNdis;
m_pCRilNdis = NULL;
}
// 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;
#ifndef RIL_RADIO_RESILIENCE
// Get rid of the monitor
delete m_pMonitor;
m_pMonitor = NULL;
#endif // RIL_RADIO_RESILIENCE
// 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 equipment state mutex
if ( g_mtxSetEquipmentState )
{
BOOL fMutex = CloseHandle(g_mtxSetEquipmentState);
ASSERT ( fMutex );
}
// 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;
// Delete the Read Bytes buffer
delete m_pReadBytes2;
m_pReadBytes2 = 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;
m_fInitedForSIMPB = FALSE;
m_dwSIMPBLastSize = (DWORD)-1;
}
DeleteCriticalSection(&m_cs);
}
//
// Broadcasts a change in the radio ready state
//
void CRilHandle::SendReadyStateNotification(DWORD dwReadyState)
{
RILEQUIPMENTSTATE res;
CNotificationData *pnd = NULL;
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();
}
// Set this in our global
if (dwReadyState)
{
g_dwReadyState |= dwReadyState;
}
else
{
g_dwReadyState = 0;
}
// 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;
if (g_rppPDDParams->fSendRegStatusChangedAfterEveryReadyStateNotification)
{
pnd = new CNotificationData;
if (pnd && pnd->InitFromRealBlob(RIL_NOTIFY_REGSTATUSCHANGED, (void *) &g_dwRegStatus, sizeof(g_dwRegStatus)))
{
// Note that BroadcastNotification frees pnd
BroadcastNotification(pnd);
pnd = NULL;
}
delete pnd;
}
}
//
// Thread responsible for sending commands from the Command Queue to COM port
//
DWORD WINAPI SimReadyThreadProc(LPVOID lpParameter)
{
FUNCTION_TRACE(SimReadyThreadProc);
DEBUGCHK(lpParameter != NULL);
CRilHandle* pRilDevice = (CRilHandle*)lpParameter;
DEBUGMSG(ZONE_TRACE, (TEXT("RILDrv : t : SimReadyThreadProc : Entering, pRilDevice=0x%x\r\n"),pRilDevice));
const DWORD dwReturn = pRilDevice->SimReadyThread();
DEBUGMSG(ZONE_TRACE, (TEXT("RILDrv : t : SimReadyThreadProc : THREAD IS EXITING, dwReturn=0x%x\r\n"),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
{
DEBUGMSG(ZONE_TRACE, (TEXT("RILDrv : t : SimReadyThread : Sending SIM Query Command...\r\n")));
// 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;
if (!pCmd || !pCmd->Init(NULL, "AT+CPIN?\r", NULL, CMDOPT_SIMQUERY, apiiInfo.dwExecTime, apiiInfo.dwTimeout, NULL, ParseGetPhoneLockedState, 0, 0, 0, apiid, NULL, NULL))
{
DEBUGMSG(ZONE_ERROR, (TEXT("RILDrv : E : SimReadyThread : Unable to construct or Init CCommand\r\n")));
goto SMSReady;
}
// Place the command into the command queue
// (this may block if the queue is full)
if (!g_pCmdQ->Put(pCmd, INFINITE))
{
goto SMSReady;
}
// 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;
}
SMSReady:
if (g_rppPDDParams->fRequireWaitingForSMSReady) {
// Phase 1 - Wait for SMS to be ready
// Create the needed event
m_fInitedForSMS = FALSE;
m_hInitedForSMSEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
if (!m_hInitedForSMSEvent)
{
goto Error;
}
// for some platforms the measure of SMS readiness is a successful CNMI initialization
do
{
Sleep(10000); //retry every 10s
if (g_dwReadyState & RIL_READYSTATE_UNLOCKED)
{
DEBUGMSG(ZONE_TRACE, (TEXT("RILDrv : t : SMSReadyThread : Sending CNMI Init Command...\r\n")));
pCmd = new CCommand;
#ifdef RIL_CELL_BROADCAST
if (!pCmd || !pCmd->Init(NULL, "AT+CNMI=2,2,2,1,0\r", NULL, CMDOPT_SMSINIT | CMDOPT_IGNORERSP, EXECTIME_API_DEFAULT, g_TimeoutCmdInit, NULL, NULL, 0, 0, 0, APIID_NONE, NULL, NULL))
#else
if (!pCmd || !pCmd->Init(NULL, "AT+CNMI=2,2,0,1,0\r", NULL, CMDOPT_SMSINIT | CMDOPT_IGNORERSP, EXECTIME_API_DEFAULT, g_TimeoutCmdInit, NULL, NULL, 0, 0, 0, APIID_NONE, NULL, NULL))
#endif
{
DEBUGMSG(ZONE_ERROR, (TEXT("RILDrv : E : SMSReadyThread : Unable to construct or Init CCommand\r\n")));
goto SimPhoneBookReady;
}
// Place the command into the command queue
// (this may block if the queue is full)
if (!g_pCmdQ->Put(pCmd, INFINITE))
{
goto SimPhoneBookReady;
}
// Now, block until we get a response back
WaitForSingleObject(m_hInitedForSMSEvent, g_TimeoutCmdInit);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -