📄 enfora.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.
//
#include <enfora.h>
CRITICAL_SECTION g_csGPRSDeactLock;
bool g_fDeactNotificationRcvd = FALSE;
bool g_fDeactResponseRcvd = FALSE;
DWORD g_LastDeactNotificationRcvd = 0;
// Phonebook storage locations - NEEDS to be SORTED
static const LISTSTRINGMAP g_rglsmCapsPBLocations[] =
{
{ "EN", RIL_CAPS_PBLOC_SIMEMERGENCY },
{ "FD", RIL_CAPS_PBLOC_SIMFIXDIALING },
{ "LD", RIL_CAPS_PBLOC_SIMLASTDIALING },
{ "MT", RIL_CAPS_PBLOC_SIMPHONEBOOK }, // RIL_PBLOC_SIMPHONEBOOK (MT is used for TI phonebook)
{ "ON", RIL_CAPS_PBLOC_OWNNUMBERS },
};
// Phonebook storage locations - does NOT NEED to be SORTED
static const LPCSTR g_rgszPBLocations[] =
{
"", // RIL_PBLOC_UNKNOWN
"EN", // RIL_PBLOC_SIMEMERGENCY
"FD", // RIL_PBLOC_SIMFIXDIALING
"LD", // RIL_PBLOC_SIMLASTDIALING
"ON", // RIL_PBLOC_OWNNUMBERS
"MT", // RIL_PBLOC_SIMPHONEBOOK (MT is used for TI phonebook)
};
#ifdef SUPPRESS_ONLINE_BATTERY_INFO
char gszGetBatteryInfoLast[128];
#endif // SUPPRESS_ONLINE_BATTERY_INFO
// OEM1-specific error results must be in left hand sorted order
static const ERRORMAP g_rgemCMEErrors[] =
{
{ RIL_E_TIMEDOUT, 512},
};
// OEM1-specific error results must be in left hand sorted order
static const ERRORMAP g_rgemEXTErrors[] =
{
{ RIL_E_OPNOTALLOWED, 0},
{ RIL_E_OPNOTALLOWED, 1},
{ RIL_E_OPNOTALLOWED, 2},
{ RIL_E_OPNOTALLOWED, 3},
{ RIL_E_OPNOTALLOWED, 4},
{ RIL_E_INVALIDDIALSTRING, 5},
{ RIL_E_INVALIDDIALSTRING, 6},
{ RIL_E_INVALIDDIALSTRING, 7},
{ RIL_E_INVALIDDIALSTRING, 8},
{ RIL_E_INVALIDDIALSTRING, 9},
{ RIL_E_INVALIDDIALSTRING, 10},
{ RIL_E_INVALIDDIALSTRING, 11},
{ RIL_E_OPNOTALLOWED, 12},
{ RIL_E_OPNOTALLOWED, 13},
{ RIL_E_OPNOTALLOWED, 14},
{ RIL_E_OPNOTALLOWED, -1}, // unsigned value is highest for binary search
};
// %CPI is TI and Enfora specific: define TI and Enfora specific notification codes here
#define TI_CPISTAT_SETUP 0
#define TI_CPISTAT_DISCONNECTED 1
#define TI_CPISTAT_ALERT 2
#define TI_CPISTAT_CALLPROCEED 3
#define TI_CPISTAT_SYNCH 4
#define TI_CPISTAT_PROGRESS 5
#define TI_CPISTAT_CONNECTED 6
#define TI_CPISTAT_MOSETUP 7
#define TI_CPISTAT_RELEASE 9
#define TI_CPISTAT_REJECT 10
// above are the only ones we care about, the others are
// 0 = setup message
// 2 = alert message
// 3 = call proceeding message
// 5 = progress message
#define LAST_CPI_ID 11
// RIL registry key
const LPCTSTR g_tszRegKeyRIL = TEXT("Drivers\\BuiltIn\\RIL");
// 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
// +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
// +CREG=2 enables extended +CREG notifications (w/ <lac> and <ci>)
// +FCLASS=0 enables data mode
// +CSSN=0,1 enables +CSSU notifications
// +CHSR=1 enables +CHSR notifications
// +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
// %CSQ=1 enables signal quality notifications (OEM1)
// supports init levels below:
// COM_INIT_INDEX - index 0
// COM_REINIT_INDEX - index 1
// COM_SMSINIT_INDEX - index 2
const INITSTRING_DATA g_rgisdModuleInit[] =
{
// OEM1 init commands
{ "V0|E0|S0=0|Q0|X3|&C1|&D1|%DATA=2,\"UART\",0,2,\"SER\",\"UART\",0,1|+CMEE=1;+CRC=1;+CR=1;+CMOD=0;+CMUT=0|$VSELECT=1|%CGAATT=0,1|%CTZV=1|"
#ifndef RIL_NO_CREG_LOCATION_UPDATES
"+CREG=2;"
#else
"+CREG=1;"
#endif // RIL_NO_CREG_LOCATION_UPDATES
"+CSSN=0,1;+COLP=0;+CCWA=1;+CSCS=\"HEX\";+CMGF=0|+CGREG=1|+CUSD=1|"
"%SATC=1|"
"%CSQ=1|%CPI=3|+CGEREP=1,0|%CSTAT=1|"
#ifdef RIL_CELL_BROADCAST
"+CNMI=2,2,2,1,0|",
#else
"+CNMI=2,2,0,1,0|",
#endif
CMDOPT_INIT | CMDOPT_GENERALINIT}, // OEM1 Init index
{"E0|+CMUT=0|", CMDOPT_INIT | CMDOPT_GENERALINIT},
#ifdef RIL_CELL_BROADCAST
// OEM1 Re-init index
{ "+CNMI=2,2,2,1,0|", CMDOPT_INIT | CMDOPT_SMSINIT}, // OEM1 SMS-init index
#else
{ "+CNMI=2,2,0,1,0|", CMDOPT_INIT | CMDOPT_SMSINIT}, // OEM1 SMS-init index
#endif
};
// This driver doesn't have a way to query current
// uplink and downlink volume, so we have to cache them.
DWORD g_dwCacheUplinkVolume;
DWORD g_dwCacheDownlinkVolume;
// Forward declarations
static HRESULT ParseGetCurrentAddressId(LPCSTR szRsp, void*& pBlob, UINT& cbBlob);
static HRESULT ParseATRInfo(LPCSTR szRsp, void*& pBlob, UINT& cbBlob);
static HRESULT ParseGetSimToolkitProfile(LPCSTR szRsp, void*& pBlob, UINT& cbBlob);
static HRESULT ParseSendSimToolkitEnvelopeCmd(LPCSTR szRsp, void*& pBlob, UINT& cbBlob);
static HRESULT ParseBuildInfo(LPCSTR szRsp, void*& pBlob, UINT& cbBlob);
static HRESULT ParseBatteryInfo(LPCSTR szRsp, void*& pBlob, UINT& cbBlob);
static HRESULT ParseDAR(LPCSTR szRsp, void*& pBlob, UINT& cbBlob);
static HRESULT ParseGetNITZSupported( __in LPCSTR szRsp, __out void*& pBlob, __out UINT& cbBlob );
// PDD parameter table
const RILPDDParams rppTIPDDParams = {
sizeof(rppTIPDDParams), // cbSize
true, // fRadioSignonRequired
true, // fIgnoreUnsolicitedNoCarrier
ParseGetCurrentAddressId, // pfnParseGetCurrentAddressId
ParseATRInfo, // pfnParseATRInfo
g_rglsmCapsPBLocations, // plsmPhoneBookLocationCapsTable
sizeof(g_rglsmCapsPBLocations) / sizeof(LISTSTRINGMAP), // uiPhoneBookLocationCapsTableSize
RIL_SIMTKN_RADIOIMPLEMENTS_REQUESTMEINPUT, // dwDevCapsSIMTKN_SetUpCall
RIL_SIMTKN_RADIOIMPLEMENTS_NOTIFICATION, // dwDevCapsSIMTKN_SendDTMF
false, // fNotificationPortSupported
RIL_SIMCMD_GETRESPONSE, // dwCRSMStatusCommandId
15, // RestrictedSimAccessSetCmdParam3 (3GPP TS 27.007 V6.8.0 (2005-03) sec. 8.18 Restricted SIM access +CRSM)
true, // fGPRSQoSEmptyParameterListAllowed
g_rgszPBLocations, // pstrPhoneBookLocationTable
sizeof(g_rgszPBLocations) / sizeof(LPCSTR), // uiPhoneBookLocationTableSize
false, // fIsRadioOffInMinimumPowerState
false, // fDontTurnRadioOnIfAlreadyOn
true, // fSendSimCmdSupported
false, // fCRSMResponseQuoted
ParseGetSimToolkitProfile, // pfnParseGetSimToolkitProfile
ParseSendSimToolkitEnvelopeCmd, // pfnParseSendSimToolkitEnvelopeCmd
false, // fPowerManagementSupported
ParseBuildInfo, // pfnParseBuildInfo
ParseBatteryInfo, // pfnParseBatteryInfo
ENCODING_GSMDEFAULT_HEX, // etMessageEncodingType
ParseDAR, // pfnParsePostRebootDiagnostics
0, // dwPostRebootInitDelay
g_rgemCMEErrors, // pemCMEErrorTable
sizeof(g_rgemCMEErrors) / sizeof(ERRORMAP), // uiCMEErrorTableSize
NULL, // pemCMSErrorTable
0, // uiCMSErrorTableSize
g_rgemEXTErrors, // pemEXTErrorTable
sizeof(g_rgemEXTErrors) / sizeof(ERRORMAP), // uiEXTErrorTableSize
"> \r", // pchSMSIntermediaryPrompt
true, // fIgnoreDeniedNotificationsUntilUnlock
false, // fRequireWaitingForSMSReady
false, // fRequireWaitingForSIMPhoneBookReady
true, // fExplicitRadioReadyNotification
false, // fSIMToolkit_SupportsTextNotifications
false, // fSIMToolkit_SupportsTextFormat
false, // fByteArrayIsQuoted
true, // fSetAudioDevicesSupported
DEFAULT_COM_MASK, // dwDefaultCOMMask
ENCODING_TECHARSET, // etEncodingTECharset
false, // fSendRegStatusChangedAfterEveryReadyStateNotification
true, // fSignalQualityActualLevelSupported
g_rgisdModuleInit, // pisdInitStringDataTable
sizeof(g_rgisdModuleInit) / sizeof(INITSTRING_DATA), // uiInitStringDataTableSize
ParseGetNITZSupported, // pfnParseGetNITZSupported
};
HRESULT PDD_IsSIMPINNotification(__in const void* rpBlob, __in const UINT rcbBlob, __in const DWORD dwCode, __out bool& fIsSIMPIN)
{
//OEM1 does not support notification port, so no possibility of a notification on the response port
return E_NOTIMPL;
}
HRESULT PDD_QueueResponse(__in CCommand* pCurrCommand, __inout CResponse* pRsp, __out bool& fQueueResponse)
{
fQueueResponse = TRUE;
// The current command is a GPRS deactivation command
if (pCurrCommand && pCurrCommand->CmdOptIsSet(CMDOPT_DEACT)) {
// This is a ME DEACT notification (note that only a ME DEACT notification maps to a solicited
// response with a dwCode of RIL_NOTIFY_GPRSCONNECTIONSTATUS)
EnterCriticalSection(&g_csGPRSDeactLock);
if (RIL_NOTIFY_GPRSCONNECTIONSTATUS == pRsp->GetNotifyCode()) {
// The command response has already been received, convert the dwCode to look like a result
// and make this as the command response, reset all the flags as we are done
if (g_fDeactResponseRcvd) {
// AT+CGACT, 0, ME case - COMPLETE HERE
pRsp->MakeOK();
g_fDeactNotificationRcvd = g_fDeactResponseRcvd = FALSE;
}
// Otherwise, do not queue this response as we have to wait for the actual command response
else {
// AT+CGACT, ME, 0 case - INCOMPLETE HERE
fQueueResponse = FALSE;
(VOID) pRsp->UpdateDataPointer((UINT)strlen("4\r"));
}
}
// This is the response for the deactivation command
else {
g_fDeactResponseRcvd = TRUE;
// The ME DEACT notification has already been received
if (g_fDeactNotificationRcvd) {
// The ME DEACT notification is stale, wait for a new one, do not queue this response
// Note the calculation below is rollover safe but it will not work if the MEDEACT is as stale
// as 49 days - the assumption is we will not have such a stale ME DEACT under normal
// usage
if ((GetTickCount() - g_LastDeactNotificationRcvd) > STALE_MEDEACT_THRESHOLD) {
// Stale ME, AT+CGACT, 0 case (becomes AT+CGACT, 0, ME case) - INCOMPLETE HERE
g_fDeactNotificationRcvd = FALSE;
fQueueResponse = FALSE;
}
// The ME DEACT notification is not stale, this response becomes the real response
else {
// Fresh ME, AT+CGACT, 0 case - COMPLETE HERE
g_fDeactNotificationRcvd = g_fDeactResponseRcvd = FALSE;
}
}
// Otherwise, wait for a ME DEACT, do not queue this response
else {
// AT+CGACT, 0, ME case - INCOMPLETE HERE
fQueueResponse = FALSE;
(VOID) pRsp->UpdateDataPointer((UINT)strlen("0\r"));
}
}
LeaveCriticalSection(&g_csGPRSDeactLock);
}
return S_OK;
}
HRESULT PDD_CreateCommand_SendDTMF(__out_ecount(cchCmd) LPSTR szCmd, __in const size_t cchCmd, __in LPCSTR lpszChars, __out DWORD& dwDuration, __out UINT& uiNumVals)
{
HRESULT hr = StringCchCopyA( szCmd, cchCmd, "AT" );
if ( FAILED( hr ) )
{
goto Error;
}
// Because we're not setting the duration, the radio is using the default
// duration. Make sure we use the default value so the timeout calculation
// below is correct.
dwDuration = 300;
LPSTR szWalk = szCmd;
szWalk = strchr(szWalk, '\0'); // NO_TYPO: 27
DEBUGCHK(NULL != szWalk);
for (LPCSTR pchChars = lpszChars; *pchChars; pchChars++) {
uiNumVals++;
hr = StringCchPrintfA( szWalk, cchCmd - (szWalk - szCmd), "+VTS=%c;", *pchChars );
if ( FAILED( hr ) )
{
goto Error;
}
szWalk = strchr(szWalk, '\0'); // NO_TYPO: 27
DEBUGCHK(NULL != szWalk);
}
// remove the trailing ";"
*(--szWalk) = '\0';
hr = StringCchCopyA( szWalk, cchCmd - (szWalk - szCmd), "\r" );
if ( FAILED( hr ) )
{
goto Error;
}
Error:
return hr;
}
HRESULT PDD_CreateCommand_StartDTMF(__out_ecount(cchCmd) LPSTR szCmd, __in const size_t cchCmd, __in const char ch)
{
return StringCchPrintfA( szCmd, cchCmd, "AT%%VTS=%c,1\r", ch );
}
HRESULT PDD_CreateCommand_StopDTMF(__out_ecount(cchCmd) LPSTR szCmd, __in const size_t cchCmd, __in const char ch)
{
return StringCchPrintfA( szCmd, cchCmd, "AT%%VTS=%c,0\r", ch );
}
HRESULT PDD_IndicateCallActivityToAudioSubsystem(__in const bool fCallIsActive)
{
//Not supported
return E_NOTIMPL;
}
HRESULT PDD_CreateCommand_ReleaseHeld(__out_ecount(cchCmd) LPSTR szCmd, __in const size_t cchCmd)
{
return StringCchCopyA( szCmd, cchCmd, "AT+CHLD=0\r" );
}
HRESULT PDD_CreateCommand_ReleaseCall(__out_ecount(cchCmd) LPSTR szCmd, __in const size_t cchCmd, __in const DWORD dwID)
{
return StringCchPrintfA( szCmd, cchCmd, "AT%%CHLD=7%u\r", dwID );
}
HRESULT PDD_CreateCommand_HoldActiveAcceptHeld(__out_ecount(cchCmd) LPSTR szCmd, __in const size_t cchCmd)
{
return StringCchCopyA( szCmd, cchCmd, "AT+CHLD=2\r" );
}
HRESULT PDD_CreateCommand_SetCurrentAddressId(__out_ecount(cchCmd) LPSTR szCmd, __in const size_t cchCmd, __in const DWORD dwAddressId)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -