📄 rilhand.cpp
字号:
//
//
BOOL CRilHandle::RegisterWithCPM()
{
// TBD_FUNCTION(CRilHandle::RegisterWithCPM);
BOOL fRet = FALSE;
m_pMonitor = new CMonitor;
if (!m_pMonitor || !m_pMonitor->Init(m_hCancelEvent, m_dwCmdThreadID, m_dwReadThreadID))
{
goto Error;
}
fRet = TRUE;
Error:
if (!fRet)
{
delete m_pMonitor;
m_pMonitor = NULL;
}
return fRet;
}
//
//
//
void CRilHandle::GetAPIInfo(APIID apiid, APIINFO& rapii)
{
// TBD_FUNCTION(CRilHandle::GetAPIInfo);
TCHAR tszRegKey[MAX_PATH];
char szID[40];
APIINFO* pNewAPIInfo = NULL;
// Intialize the output struct with defaults
rapii.dwExecTime = EXECTIME_API_DEFAULT;
rapii.dwTimeout = g_TimeoutAPIDefault;
// See if already loaded info for this API
if (!m_rgpAPIInfo[apiid])
{
// Allocate new API info
pNewAPIInfo = new APIINFO;
if (!pNewAPIInfo)
{
goto Error;
}
// Compose the registry key
(void)_itoa((int)apiid, szID, 10);
(void)_tcsncpyz(tszRegKey, g_tszRegKeyAPIInfo, MAX_PATH);
(void)_tcsncatz(tszRegKey, TString(szID), MAX_PATH);
// Read the execution time and the timeout
if (!GetRegistryDWORD(HKEY_LOCAL_MACHINE, tszRegKey, TEXT("ExecutionTime"), &pNewAPIInfo->dwExecTime))
{
// Just use the default
pNewAPIInfo->dwExecTime = EXECTIME_API_DEFAULT;
}
if (!GetRegistryDWORD(HKEY_LOCAL_MACHINE, tszRegKey, TEXT("Timeout"), &pNewAPIInfo->dwTimeout))
{
// Just use the default
pNewAPIInfo->dwTimeout = g_TimeoutAPIDefault;
}
// If the timeout is specified as 0 milliseconds, assume INFINITE timeout
if (!pNewAPIInfo->dwTimeout)
{
pNewAPIInfo->dwTimeout = INFINITE;
}
// Cache the data we just read
m_rgpAPIInfo[apiid] = pNewAPIInfo;
pNewAPIInfo = NULL;
}
TBD_ASSERT(NULL != m_rgpAPIInfo[apiid]);
rapii = *m_rgpAPIInfo[apiid];
Error:
delete pNewAPIInfo;
TBD_OUTPUT(TBDCT_INFO, TBDOL_TRACE, TEXT("CRilHandle::GetAPIInfo : Info for API %d: exec time: %d msec, timeout: %d msec"),
apiid, rapii.dwExecTime, rapii.dwTimeout);
}
//
// Send an intialization command string to the COM port
//
BOOL SendComInitString(UINT iString)
{
TBD_FUNCTION(SendComInitString);
TBD_ASSERT(iString < sizeof(g_rgisdModuleInit) / sizeof(INITSTRING_DATA));
char szInit[1024];
BOOL fRet = FALSE;
szInit[0]=TEXT('\0');
#if !defined(OEMW_DRIVER)
if (SENDREGINIT(iString))
{
TCHAR tszRegInit[MAX_PATH];
const TCHAR cszPreInitString[] = TEXT("PreInitString");
tszRegInit[0]=TEXT('\0');
GetRegistrySZ(HKEY_LOCAL_MACHINE, g_tszRegKeyRIL, cszPreInitString, tszRegInit, MAX_PATH);
if (tszRegInit[0])
{
strncatz(szInit,AnsiString(tszRegInit),sizeof(szInit));
}
const TCHAR cszTmpInitString[] = TEXT("TmpInitString");
tszRegInit[0]=TEXT('\0');
GetRegistrySZ(HKEY_LOCAL_MACHINE, g_tszRegKeyRIL, cszTmpInitString, tszRegInit, MAX_PATH);
if (tszRegInit[0])
{
strncatz(szInit,AnsiString(tszRegInit),sizeof(szInit));
HKEY hKey;
long lResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE,g_tszRegKeyRIL,0,0,&hKey);
if (lResult == ERROR_SUCCESS)
{
RegDeleteValue(hKey,cszTmpInitString);
RegCloseKey(hKey);
}
}
}
#endif
if (g_rgisdModuleInit[iString].szCmd[0])
{
strncatz(szInit,g_rgisdModuleInit[iString].szCmd,sizeof(szInit));
}
#if !defined(OEMW_DRIVER)
if (SENDREGINIT(iString))
{
TCHAR tszRegInit[MAX_PATH];
const TCHAR cszInitString[] = TEXT("ComInitString");
tszRegInit[0]=TEXT('\0');
GetRegistrySZ(HKEY_LOCAL_MACHINE, g_tszRegKeyRIL, cszInitString, tszRegInit, MAX_PATH);
if (tszRegInit[0])
{
strncatz(szInit,AnsiString(tszRegInit),sizeof(szInit));
}
}
#endif
// Now go through the string and break it up into individual commands separated by a '|'
char szCmd[MAX_PATH];
char *pszStart, *pszEnd;
DWORD dwCmdOption = g_rgisdModuleInit[iString].dwCmdOption;
pszStart = szInit;
for (;;)
{
// Look for the end of the current command
pszEnd = strchr(pszStart, '|');
if (pszEnd)
{
// If we found a termination char, terminate the command there
*pszEnd = '\0';
}
else
{
// This must be the last init command of the initial init phase
dwCmdOption|=CMDOPT_FINALINIT;
}
UINT nRetriesOnError = 0;
UINT nRetryOnErrorDelay = 0;
char * pszRetry = strchr(pszStart, '\\');
if (pszRetry)
{
char *pszOpt = pszRetry++;
if (! ParseUInt(pszRetry, FALSE, nRetriesOnError, pszRetry) ||
! MatchStringBeginning(pszRetry, ",", pszRetry) ||
! ParseUInt(pszRetry, FALSE, nRetryOnErrorDelay, pszRetry) ||
! MatchStringBeginning(pszRetry, "\\", pszRetry))
{
nRetriesOnError = 0;
nRetryOnErrorDelay = 0;
}
else
{
*pszOpt = '\0';
}
}
// Send the command
(void)_snprintfz(szCmd, MAX_PATH, "AT%s\r", pszStart);
if (!QueueCmdIgnoreRsp(szCmd, dwCmdOption, g_TimeoutCmdInit, 2, nRetriesOnError, nRetryOnErrorDelay))
{
goto Error;
}
// If this was the last command, get out now
if (!pszEnd)
{
break;
}
// Get the next command
pszStart = pszEnd+1;
}
#if defined(OEM1_DRIVER)
// This driver doesn't have a way to query current
// uplink and downlink volume, so we have to cache them.
if (COM_REINIT_INDEX == iString) {
extern DWORD g_dwCacheUplinkVolume;
extern DWORD g_dwCacheDownlinkVolume;
// These numbers are set according to the
// values in the reinit string.
g_dwCacheUplinkVolume = 200;
g_dwCacheDownlinkVolume = 200;
}
#endif
fRet = TRUE;
Error:
if (!fRet)
{
// Couldn't send an init string -- signal critical error
SignalCriticalError(RILLOG_EVENT_COULDNTSENDINIT);
}
return fRet;
}
//
// Used for cleaning up notification items
// when the notification queue is destroyed.
//
void NotificationItemDtor(void *pItem)
{
LocalFree(pItem);
}
//
// Instance handle ctor
//
CRilInstanceHandle::CRilInstanceHandle()
: CListElem(),
m_pDevice(NULL),
m_pCmdList(NULL),
m_hNotifyCancelEvent(NULL),
m_notificationQ(NotificationItemDtor),
m_fInited(FALSE),
m_fPreferred(FALSE)
{
TBD_FUNCTION(CRilInstanceHandle::CRilInstanceHandle);
}
//
// Instance handle dtor
//
CRilInstanceHandle::~CRilInstanceHandle()
{
TBD_FUNCTION(CRilInstanceHandle::~CRilInstanceHandle);
if (m_fPreferred)
{
// Switch RIL out of emergency mode
(void)m_pDevice->SetEmergencyMode(FALSE);
// This handle is not preferred anymore
m_fPreferred = FALSE;
}
CancelNotifications();
delete m_pCmdList;
m_pCmdList = NULL;
if (m_hNotifyCancelEvent)
{
(void)CloseHandle(m_hNotifyCancelEvent);
m_hNotifyCancelEvent = NULL;
}
m_fInited = FALSE;
}
//
// Initalization
//
BOOL CRilInstanceHandle::Init(CRilHandle* const pDevice)
{
TBD_FUNCTION(CRilInstanceHandle::Init);
BOOL fRet = FALSE;
if (pDevice->FInEmergencyMode())
{
// We can't create any additional RIL instances in emergency mode
TBD_ASSERT(FALSE == m_fPreferred);
goto Error;
}
// Create command list
m_pCmdList = new CDblList<CCommand>;
if (!m_pCmdList)
{
goto Error;
}
m_pDevice = pDevice;
m_fInited = TRUE;
fRet = TRUE;
Error:
return fRet;
}
//
//
//
void CRilInstanceHandle::Notify(const DWORD dwCode, const HRESULT hrCmdID, const void* const pBlob,
const UINT cbBlob)
{
TBD_FUNCTION(CRilInstanceHandle::Notify);
TBD_ASSERT(FALSE != m_fInited);
RILDRVNOTIFICATION* prdn = NULL;
UINT cbTotal;
// Alocate a notification data structure
// NOTE: LocalAlloc() is used to prevent allocated memory from being tracked
// (since it may be freed by a thread coming from RIL proxy)
cbTotal = sizeof(RILDRVNOTIFICATION) + cbBlob;
prdn = (RILDRVNOTIFICATION*)LocalAlloc(0, cbTotal);
if (!prdn)
{
goto Error;
}
// Fill in the structure fields
prdn->cbSize = cbTotal;
prdn->cbSizeNeeded = cbTotal;
prdn->dwCode = dwCode;
prdn->hrCmdID = hrCmdID;
if (cbBlob)
{
memcpy(prdn->pbData, pBlob, cbBlob);
}
// Try to queue the structure into the Notification Queue
// (NOTE: this will fail if the queue is already full -- this guarantees that this RIL thread can't
// be blocked by a hanging RIL client)
if (!m_notificationQ.Put(prdn))
{
TBD_OUTPUT(TBDCT_INFO, TBDOL_ERROR, TEXT("CRilInstanceHandle::Notify : Dropped RIL notification - out of memory? (0x%x)"), this);
goto Error;
}
#ifdef TBD_DEBUG
if (m_notificationQ.GetSize() > 10)
{
TBD_OUTPUT(TBDCT_INFO, TBDOL_ERROR, TEXT("CRilInstanceHandle::Notify : Notify queue for handle 0x%x has size %d"), this, m_notificationQ.GetSize());
}
#endif
// The queue took ownership of the notification data
//prdn = NULL;
return;
Error:
// NOTE: Since we allocated this structure using LocalAlloc(), we need to use LocalFree() to delete it
// (or else the memory tracker will assert)
LocalFree(prdn);
}
//
// Function passed to CQueue::ConditionalGet() below
//
BOOL FEnoughStorage(void* pItem, DWORD dwData)
{
TBD_FUNCTION(FEnoughStorage);
TBD_ASSERT(NULL != pItem);
RILDRVNOTIFICATION* prdnNextNotification = (RILDRVNOTIFICATION*)pItem;
RILDRVNOTIFICATION* prdnSuppliedStruct = (RILDRVNOTIFICATION*)dwData;
prdnSuppliedStruct->cbSizeNeeded = prdnNextNotification->cbSizeNeeded;
return (prdnSuppliedStruct->cbSize >= prdnSuppliedStruct->cbSizeNeeded);
}
//
//
//
BOOL CRilInstanceHandle::GetNextNotification(RILDRVNOTIFICATION& rrdnSuppliedStruct)
{
TBD_FUNCTION(CRilInstanceHandle::GetNextNotification);
TBD_ASSERT(FALSE != m_fInited);
RILDRVNOTIFICATION* prdnNextNotification = NULL;
UINT cbBlob;
HRESULT hr;
BOOL fRet = FALSE;
// Initialize cbSizeNeeded field
rrdnSuppliedStruct.cbSizeNeeded = rrdnSuppliedStruct.cbSize;
// Get the next notification from the queue, if the provided size is sufficient
hr = m_notificationQ.ConditionalGet(FEnoughStorage, (DWORD)&rrdnSuppliedStruct, &prdnNextNotification);
if (E_FAIL == hr)
{
// The supplied size wasn't enough - return TRUE
fRet = TRUE;
goto Error;
}
else if (S_FALSE == hr)
{
goto Error;
}
// We shouldn't have to worry about any error result other than E_FAIL.
TBD_ASSERT(SUCCEEDED(hr));
// The supplied size is enough, so we retrieved the next notification
TBD_ASSERT(NULL != prdnNextNotification);
TBD_ASSERT(prdnNextNotification->cbSize == prdnNextNotification->cbSizeNeeded);
rrdnSuppliedStruct.dwCode = prdnNextNotification->dwCode;
rrdnSuppliedStruct.hrCmdID = prdnNextNotification->hrCmdID;
cbBlob = prdnNextNotification->cbSize - sizeof(RILDRVNOTIFICATION);
if (cbBlob)
{
memcpy(rrdnSuppliedStruct.pbData, prdnNextNotification->pbData, cbBlob);
}
fRet = TRUE;
Error:
(void)LocalFree(prdnNextNotification);
return fRet;
}
//
//
//
BOOL CRilInstanceHandle::MakePreferred()
{
TBD_FUNCTION(CRilInstanceHandle::MakePreferred);
TBD_ASSERT(NULL != m_pDevice);
BOOL fRet = FALSE;
// Switch RIL into emergency mode
if (!m_pDevice->SetEmergencyMode(TRUE))
{
goto Error;
}
// Mark this handle as preferred
m_fPreferred = TRUE;
fRet = TRUE;
Error:
return fRet;
}
//
//
//
BOOL CRilInstanceHandle::CreateNotificationQueue(LPCTSTR tszCancelEventName,
PBYTE pBufOut, DWORD dwLenOut, PDWORD pdwActualOut)
{
TBD_FUNCTION(CRilInstanceHandle::CreateNotificationQueue);
TBD_ASSERT(FALSE != m_fInited);
BOOL fRet = FALSE;
DWORD dwOut = 0;
if (!pBufOut || !dwLenOut || !pdwActualOut)
{
goto Error;
}
// Initialize Notification Q
if (!m_notificationQ.Init(5))
{
goto Error;
}
// Create the cancel event
m_hNotifyCancelEvent = CreateEvent(NULL, TRUE, FALSE, tszCancelEventName);
if (!m_hNotifyCancelEvent)
{
goto Error;
}
TBD_ASSERT(ERROR_ALREADY_EXISTS == GetLastError());
dwOut = _tcslen(m_notificationQ.GetItemsEventName()) * sizeof(TCHAR) + sizeof(TCHAR);
if (dwOut > dwLenOut)
{
goto Error;
}
_tcscpy((TCHAR*)pBufOut, m_notificationQ.GetItemsEventName());
*pdwActualOut = dwOut;
fRet = TRUE;
Error:
return fRet;
}
//
// Wrap up the serial port operations
//
BOOL DeinitComPort(const CComHandle* const pComDevice)
{
TBD_FUNCTION(DeinitComPort);
/*
DWORD dwWritten;
return pComDevice->Write("ATZ\r", 4, dwWritten);
*/
return pComDevice->VirtSetCommMask(0);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -