📄 rilhand.cpp
字号:
/*++
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 + -