libqmi-qmuxd/gobi-api/GobiAPI_1.0.40/Shared/GobiQMICoreNAS.cpp

1987 lines
56 KiB
C++
Executable File

/*===========================================================================
FILE:
GobiQMICoreNAS.cpp
DESCRIPTION:
QUALCOMM Gobi QMI Based API Core (NAS Service)
PUBLIC CLASSES AND FUNCTIONS:
cGobiQMICore
Copyright (c) 2011, Code Aurora Forum. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of Code Aurora Forum nor
the names of its contributors may be used to endorse or promote
products derived from this software without specific prior written
permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
==========================================================================*/
//---------------------------------------------------------------------------
// Include Files
//---------------------------------------------------------------------------
#include "StdAfx.h"
#include "GobiQMICore.h"
#include "QMIBuffers.h"
//---------------------------------------------------------------------------
// Definitions
//---------------------------------------------------------------------------
// Maximum length for a scanned network description
const ULONG MAX_SNI_DESCRIPTION_LEN = 255;
//---------------------------------------------------------------------------
// Pragmas (pack structs)
//---------------------------------------------------------------------------
#pragma pack( push, 1 )
/*=========================================================================*/
// Struct sEVDOCustomSCPConfig
// Struct to represent CDMA 1xEV-DO custom SCP config
/*=========================================================================*/
struct sEVDOCustomSCPConfig
{
public:
BYTE mbActive;
ULONG mProtocolMask;
ULONG mBroadcastMask;
ULONG mApplicationMask;
};
/*=========================================================================*/
// Struct sScannedNetworkInfo
// Struct to represent scanned network information
/*=========================================================================*/
struct sScannedNetworkInfo
{
public:
USHORT mMCC;
USHORT mMNC;
ULONG mInUse;
ULONG mRoaming;
ULONG mForbidden;
ULONG mPreferred;
CHAR mDescription[MAX_SNI_DESCRIPTION_LEN];
};
/*=========================================================================*/
// Struct sScannedNetworkRATInfo
// Struct to represent scanned network RAT information
/*=========================================================================*/
struct sScannedNetworkRATInfo
{
public:
USHORT mMCC;
USHORT mMNC;
ULONG mRAT;
};
//---------------------------------------------------------------------------
// Pragmas
//---------------------------------------------------------------------------
#pragma pack( pop )
/*=========================================================================*/
// cGobiQMICore Methods
/*=========================================================================*/
/*===========================================================================
METHOD:
GetANAAAAuthenticationStatus (Public Method)
DESCRIPTION:
This function gets the AN-AAA authentication status
PARAMETERS:
pStatus [ O ] - AN-AAA authentication status
RETURN VALUE:
eGobiError - Return code
===========================================================================*/
eGobiError cGobiQMICore::GetANAAAAuthenticationStatus( ULONG * pStatus )
{
// Validate arguments
if (pStatus == 0)
{
return eGOBI_ERR_INVALID_ARG;
}
// Generate and send the QMI request
WORD msgID = (WORD)eQMI_NAS_GET_AAA_AUTH_STATUS;
sProtocolBuffer rsp = SendSimple( eQMI_SVC_NAS, msgID );
if (rsp.IsValid() == false)
{
return GetCorrectedLastError();
}
// Did we receive a valid QMI response?
sQMIServiceBuffer qmiRsp( rsp.GetSharedBuffer() );
if (qmiRsp.IsValid() == false)
{
return eGOBI_ERR_MALFORMED_RSP;
}
// Check the mandatory QMI result TLV for success
ULONG rc = 0;
ULONG ec = 0;
bool bResult = qmiRsp.GetResult( rc, ec );
if (bResult == false)
{
return eGOBI_ERR_MALFORMED_RSP;
}
else if (rc != 0)
{
return GetCorrectedQMIError( ec );
}
// Prepare TLVs for parsing
std::vector <sDB2NavInput> tlvs = DB2ReduceQMIBuffer( qmiRsp );
const cCoreDatabase & db = GetDatabase();
// Parse the TLV we want (by DB key)
sProtocolEntityKey tlvKey( eDB2_ET_QMI_NAS_RSP, msgID, 1 );
cDataParser::tParsedFields pf = ParseTLV( db, rsp, tlvs, tlvKey );
if (pf.size() < 1)
{
return eGOBI_ERR_INVALID_RSP;
}
// Populate the index
*pStatus = (ULONG)pf[0].mValue.mU32;
return eGOBI_ERR_NONE;
}
/*===========================================================================
METHOD:
GetSignalStrengths (Public Method)
DESCRIPTION:
This function gets the current available signal strengths (in dBm)
as measured by the device
PARAMETERS:
pArraySizes [I/O] - Upon input the maximum number of elements
that each array can contain can contain.
Upon successful output the actual number
of elements in each array
pSignalStrengths [ O ] - Received signal strength array (dBm)
pRadioInterfaces [ O ] - Radio interface technology array
RETURN VALUE:
eGobiError - Return code
===========================================================================*/
eGobiError cGobiQMICore::GetSignalStrengths(
ULONG * pArraySizes,
INT8 * pSignalStrengths,
ULONG * pRadioInterfaces )
{
// Validate arguments
if ( (pArraySizes == 0)
|| (*pArraySizes == 0)
|| (pSignalStrengths == 0)
|| (pRadioInterfaces == 0) )
{
return eGOBI_ERR_INVALID_ARG;
}
ULONG maxSignals = (ULONG)*pArraySizes;
// Assume failure
*pArraySizes = 0;
// Generate and send the QMI request
WORD msgID = (WORD)eQMI_NAS_GET_RSSI;
sProtocolBuffer rsp = SendSimple( eQMI_SVC_NAS, msgID );
if (rsp.IsValid() == false)
{
return GetCorrectedLastError();
}
// Did we receive a valid QMI response?
sQMIServiceBuffer qmiRsp( rsp.GetSharedBuffer() );
if (qmiRsp.IsValid() == false)
{
return eGOBI_ERR_MALFORMED_RSP;
}
// Check the mandatory QMI result TLV for success
ULONG rc = 0;
ULONG ec = 0;
bool bResult = qmiRsp.GetResult( rc, ec );
if (bResult == false)
{
return eGOBI_ERR_MALFORMED_RSP;
}
else if (rc != 0)
{
return GetCorrectedQMIError( ec );
}
// Prepare TLVs for parsing
std::vector <sDB2NavInput> tlvs = DB2ReduceQMIBuffer( qmiRsp );
const cCoreDatabase & db = GetDatabase();
// Parse the TLV we want (by DB key)
sProtocolEntityKey tlvKey( eDB2_ET_QMI_NAS_RSP, msgID, 1 );
cDataParser::tParsedFields pf = ParseTLV( db, rsp, tlvs, tlvKey );
if (pf.size() < 2)
{
return eGOBI_ERR_INVALID_RSP;
}
// Remove any values outside the legal range
std::map <ULONG, INT8> sigMap;
INT8 sigVal = pf[0].mValue.mS8;
ULONG radioVal = pf[1].mValue.mU32;
if (sigVal <= -30 && sigVal > -125 && radioVal != 0)
{
sigMap[radioVal] = sigVal;
}
// Parse the TLV we want (by DB key)
tlvKey = sProtocolEntityKey( eDB2_ET_QMI_NAS_RSP, msgID, 16 );
pf = ParseTLV( db, rsp, tlvs, tlvKey );
if (pf.size() > 2)
{
ULONG fi = 0;
ULONG auxSigs = (ULONG)pf[fi++].mValue.mU16;
if (pf.size() >= 1 + 2 * auxSigs)
{
for (ULONG s = 0; s < auxSigs; s++, fi += 2)
{
sigVal = pf[fi].mValue.mS8;
radioVal = pf[fi + 1].mValue.mU32;
if (sigVal <= -30 && sigVal > -125 && radioVal != 0)
{
sigMap[radioVal] = sigVal;
}
}
}
}
ULONG sigCount = 0;
std::map <ULONG, INT8>::const_iterator pIter;
for (pIter = sigMap.begin(); pIter != sigMap.end(); pIter++, sigCount++)
{
if (sigCount < maxSignals)
{
pSignalStrengths[sigCount] = pIter->second;
pRadioInterfaces[sigCount] = pIter->first;
*pArraySizes = sigCount + 1;
}
}
// No valid signals?
if (sigCount == 0)
{
return eGOBI_ERR_NO_SIGNAL;
}
return eGOBI_ERR_NONE;
}
/*===========================================================================
METHOD:
GetRFInfo (Public Method)
DESCRIPTION:
This function gets the current RF information
PARAMETERS:
pInstanceSize [I/O] - Upon input the maximum number of elements that the
RF info instance array can contain. Upon success
the actual number of elements in the RF info
instance array
pInstances [ O ] - The RF info instance array
RETURN VALUE:
eGobiError - Return code
===========================================================================*/
eGobiError cGobiQMICore::GetRFInfo(
BYTE * pInstanceSize,
BYTE * pInstances )
{
// Validate arguments
if (pInstanceSize == 0 || *pInstanceSize == 0 || pInstances == 0)
{
return eGOBI_ERR_INVALID_ARG;
}
// Assume failure
BYTE maxInstances = *pInstanceSize;
*pInstanceSize = 0;
// Generate and send the QMI request
WORD msgID = (WORD)eQMI_NAS_GET_RF_INFO;
sProtocolBuffer rsp = SendSimple( eQMI_SVC_NAS, msgID );
if (rsp.IsValid() == false)
{
return GetCorrectedLastError();
}
// Did we receive a valid QMI response?
sQMIServiceBuffer qmiRsp( rsp.GetSharedBuffer() );
if (qmiRsp.IsValid() == false)
{
return eGOBI_ERR_MALFORMED_RSP;
}
// Check the mandatory QMI result TLV for success
ULONG rc = 0;
ULONG ec = 0;
bool bResult = qmiRsp.GetResult( rc, ec );
if (bResult == false)
{
return eGOBI_ERR_MALFORMED_RSP;
}
else if (rc != 0)
{
return GetCorrectedQMIError( ec );
}
// Prepare TLVs for parsing
std::vector <sDB2NavInput> tlvs = DB2ReduceQMIBuffer( qmiRsp );
const cCoreDatabase & db = GetDatabase();
// Parse the TLV we want (by DB key)
sProtocolEntityKey tlvKey( eDB2_ET_QMI_NAS_RSP, msgID, 1 );
cDataParser::tParsedFields pf = ParseTLV( db, rsp, tlvs, tlvKey );
ULONG fieldCount = (ULONG)pf.size();
if (fieldCount < 1)
{
return eGOBI_ERR_INVALID_RSP;
}
BYTE ifaceCount = pf[0].mValue.mU8;
if (fieldCount < 1 + ((ULONG)ifaceCount * 3))
{
return eGOBI_ERR_INVALID_RSP;
}
if (ifaceCount > maxInstances)
{
ifaceCount = maxInstances;
}
ULONG * pOutput = (ULONG *)pInstances;
for (BYTE i = 0; i < ifaceCount; i++)
{
ULONG offset = 3 * (ULONG)i;
*pOutput++ = pf[offset + 1].mValue.mU32;
*pOutput++ = pf[offset + 2].mValue.mU32;
*pOutput++ = (ULONG)pf[offset + 3].mValue.mU16;
}
*pInstanceSize = ifaceCount;
return eGOBI_ERR_NONE;
}
/*===========================================================================
METHOD:
PerformNetworkScan (Public Method)
DESCRIPTION:
This function performs a scan for available networks
PARAMETERS:
pInstanceSize [I/O] - Upon input the maximum number of elements that the
network info instance array can contain. Upon
success the actual number of elements in the
network info instance array
pInstances [ O ] - The network info instance array
RETURN VALUE:
eGobiError - Return code
===========================================================================*/
eGobiError cGobiQMICore::PerformNetworkScan(
BYTE * pInstanceSize,
BYTE * pInstances )
{
// Validate arguments
if ( (pInstanceSize == 0)
|| (*pInstanceSize == 0)
|| (pInstances == 0) )
{
return eGOBI_ERR_INVALID_ARG;
}
BYTE maxInstances = *pInstanceSize;
// Assume failure
*pInstanceSize = 0;
// This can take a really long time
ULONG to = MAX_REQ_TIMEOUT;
// Generate and send the QMI request
WORD msgID = (WORD)eQMI_NAS_SCAN_NETS;
sProtocolBuffer rsp = SendSimple( eQMI_SVC_NAS, msgID, to );
if (rsp.IsValid() == false)
{
return GetCorrectedLastError();
}
// Did we receive a valid QMI response?
sQMIServiceBuffer qmiRsp( rsp.GetSharedBuffer() );
if (qmiRsp.IsValid() == false)
{
return eGOBI_ERR_MALFORMED_RSP;
}
// Check the mandatory QMI result TLV for success
ULONG rc = 0;
ULONG ec = 0;
bool bResult = qmiRsp.GetResult( rc, ec );
if (bResult == false)
{
return eGOBI_ERR_MALFORMED_RSP;
}
else if (rc != 0)
{
return GetCorrectedQMIError( ec );
}
// Prepare TLVs for parsing
std::vector <sDB2NavInput> tlvs = DB2ReduceQMIBuffer( qmiRsp );
const cCoreDatabase & db = GetDatabase();
// Parse the TLV we want (by DB key)
sProtocolEntityKey tlvKey( eDB2_ET_QMI_NAS_RSP, msgID, 16 );
cDataParser::tParsedFields pf = ParseTLV( db, rsp, tlvs, tlvKey );
ULONG maxIdx = (ULONG)pf.size();
if (maxIdx-- < 1)
{
return eGOBI_ERR_INVALID_RSP;
}
ULONG idx = 0;
BYTE netCount = pf[idx++].mValue.mU8;
if (netCount > maxInstances)
{
netCount = maxInstances;
}
sScannedNetworkInfo * pNet = (sScannedNetworkInfo *)pInstances;
for (BYTE i = 0; i < netCount; i++)
{
// Validate field count
if (idx + 6 > maxIdx)
{
return eGOBI_ERR_INVALID_RSP;
}
pNet->mMCC = pf[idx++].mValue.mU16;
pNet->mMNC = pf[idx++].mValue.mU16;
pNet->mInUse = pf[idx++].mValue.mU32;
pNet->mRoaming = pf[idx++].mValue.mU32;
pNet->mForbidden = pf[idx++].mValue.mU32;
pNet->mPreferred = pf[idx++].mValue.mU32;
memset( &pNet->mDescription[0], 0, (SIZE_T)MAX_SNI_DESCRIPTION_LEN );
BYTE descLen = pf[idx++].mValue.mU8;
if (descLen > 0)
{
std::string netDesc( pf[idx++].mValueString );
ULONG actualLen = netDesc.size();
if (actualLen >= MAX_SNI_DESCRIPTION_LEN)
{
actualLen = MAX_SNI_DESCRIPTION_LEN - 1;
}
memcpy( (LPVOID)&pNet->mDescription[0],
(LPCSTR)netDesc.c_str(),
(SIZE_T)actualLen );
}
pNet++;
}
*pInstanceSize = netCount;
return eGOBI_ERR_NONE;
}
/*===========================================================================
METHOD:
PerformNetworkRATScan (Public Method)
DESCRIPTION:
This function performs a scan for available networks (includes RAT)
PARAMETERS:
pInstanceSize [I/O] - Upon input the maximum number of elements that the
network info instance array can contain. Upon
success the actual number of elements in the
network info instance array
pInstances [ O ] - The network info instance array
pRATSize [I/O] - Upon input the maximum number of elements that the
RAT info instance array can contain. Upon success
the actual number of elements in the RAT info
instance array
pRATInstances [ O ] - The RAT info instance array
RETURN VALUE:
eGobiError - Return code
===========================================================================*/
eGobiError cGobiQMICore::PerformNetworkRATScan(
BYTE * pInstanceSize,
BYTE * pInstances,
BYTE * pRATSize,
BYTE * pRATInstances )
{
// Validate arguments
if ( (pInstanceSize == 0)
|| (*pInstanceSize == 0)
|| (pInstances == 0)
|| (pRATSize == 0)
|| (*pRATSize == 0)
|| (pRATInstances == 0) )
{
return eGOBI_ERR_INVALID_ARG;
}
BYTE maxInstances = *pInstanceSize;
BYTE maxRATInstances = *pRATSize;
// Assume failure
*pInstanceSize = 0;
*pRATSize = 0;
// This can take a really long time
ULONG to = MAX_REQ_TIMEOUT;
// Generate and send the QMI request
WORD msgID = (WORD)eQMI_NAS_SCAN_NETS;
sProtocolBuffer rsp = SendSimple( eQMI_SVC_NAS, msgID, to );
if (rsp.IsValid() == false)
{
return GetCorrectedLastError();
}
// Did we receive a valid QMI response?
sQMIServiceBuffer qmiRsp( rsp.GetSharedBuffer() );
if (qmiRsp.IsValid() == false)
{
return eGOBI_ERR_MALFORMED_RSP;
}
// Check the mandatory QMI result TLV for success
ULONG rc = 0;
ULONG ec = 0;
bool bResult = qmiRsp.GetResult( rc, ec );
if (bResult == false)
{
return eGOBI_ERR_MALFORMED_RSP;
}
else if (rc != 0)
{
return GetCorrectedQMIError( ec );
}
// Prepare TLVs for parsing
std::vector <sDB2NavInput> tlvs = DB2ReduceQMIBuffer( qmiRsp );
const cCoreDatabase & db = GetDatabase();
// Parse the TLV we want (by DB key)
sProtocolEntityKey tlvKey( eDB2_ET_QMI_NAS_RSP, msgID, 16 );
cDataParser::tParsedFields pf = ParseTLV( db, rsp, tlvs, tlvKey );
ULONG maxIdx = (ULONG)pf.size();
if (maxIdx-- < 1)
{
return eGOBI_ERR_INVALID_RSP;
}
ULONG idx = 0;
BYTE netCount = pf[idx++].mValue.mU8;
if (netCount > maxInstances)
{
netCount = maxInstances;
}
sScannedNetworkInfo * pNet = (sScannedNetworkInfo *)pInstances;
for (BYTE i = 0; i < netCount; i++)
{
// Validate field count
if (idx + 6 > maxIdx)
{
return eGOBI_ERR_INVALID_RSP;
}
pNet->mMCC = pf[idx++].mValue.mU16;
pNet->mMNC = pf[idx++].mValue.mU16;
pNet->mInUse = pf[idx++].mValue.mU32;
pNet->mRoaming = pf[idx++].mValue.mU32;
pNet->mForbidden = pf[idx++].mValue.mU32;
pNet->mPreferred = pf[idx++].mValue.mU32;
memset( &pNet->mDescription[0], 0, (SIZE_T)MAX_SNI_DESCRIPTION_LEN );
BYTE descLen = pf[idx++].mValue.mU8;
if (descLen > 0)
{
std::string netDesc( pf[idx++].mValueString );
ULONG actualLen = netDesc.size();
if (actualLen >= MAX_SNI_DESCRIPTION_LEN)
{
actualLen = MAX_SNI_DESCRIPTION_LEN - 1;
}
LPCSTR pNetDesc = netDesc.c_str();
memcpy( (LPVOID)&pNet->mDescription[0],
(LPCVOID)pNetDesc,
(SIZE_T)actualLen );
}
pNet++;
}
// Parse the TLV we want (by DB key)
tlvKey = sProtocolEntityKey( eDB2_ET_QMI_NAS_RSP, msgID, 17 );
pf = ParseTLV( db, rsp, tlvs, tlvKey );
maxIdx = (ULONG)pf.size();
if (maxIdx-- < 1)
{
return eGOBI_ERR_INVALID_RSP;
}
idx = 0;
BYTE ratCount = pf[idx++].mValue.mU8;
if (ratCount > maxRATInstances)
{
ratCount = maxRATInstances;
}
sScannedNetworkRATInfo * pRAT = (sScannedNetworkRATInfo *)pRATInstances;
for (BYTE r = 0; r < ratCount; r++)
{
// Validate field count
if (idx + 2 > maxIdx)
{
return eGOBI_ERR_INVALID_RSP;
}
pRAT->mMCC = pf[idx++].mValue.mU16;
pRAT->mMNC = pf[idx++].mValue.mU16;
pRAT->mRAT = pf[idx++].mValue.mU32;
pRAT++;
}
*pInstanceSize = netCount;
*pRATSize = ratCount;
return eGOBI_ERR_NONE;
}
/*===========================================================================
METHOD:
InitiateNetworkRegistration (Public Method)
DESCRIPTION:
This function initiates a network registration
PARAMETERS:
regType [ I ] - Registration type
mcc [ I ] - Mobile country code (ignored for auto registration)
mnc [ I ] - Mobile network code (ignored for auto registration)
rat [ I ] - Radio access type (ignored for auto registration)
RETURN VALUE:
eGobiError - Return code
===========================================================================*/
eGobiError cGobiQMICore::InitiateNetworkRegistration(
ULONG regType,
WORD mcc,
WORD mnc,
ULONG rat )
{
WORD msgID = (WORD)eQMI_NAS_REGISTER_NET;
std::vector <sDB2PackingInput> piv;
std::ostringstream tmp;
tmp << (UINT)regType;
sProtocolEntityKey pek( eDB2_ET_QMI_NAS_REQ, msgID, 1 );
sDB2PackingInput pi( pek, (LPCSTR)tmp.str().c_str() );
piv.push_back( pi );
if (regType == 2)
{
// We need to add the manual registration data
// "%hu %hu %u"
std::ostringstream tmp2;
tmp2 << (USHORT)mcc << " " << (USHORT)mnc << " "
<< (UINT)rat;
pek = sProtocolEntityKey( eDB2_ET_QMI_NAS_REQ, msgID, 16 );
pi = sDB2PackingInput( pek, (LPCSTR)tmp2.str().c_str() );
piv.push_back( pi );
}
// Pack up the QMI request
const cCoreDatabase & db = GetDatabase();
sSharedBuffer * pRequest = DB2PackQMIBuffer( db, piv );
// Send the QMI request, check result, and return
return SendAndCheckReturn( eQMI_SVC_NAS, pRequest, 30000 );
}
/*===========================================================================
METHOD:
InitiateDomainAttach (Public Method)
DESCRIPTION:
This function initiates a domain attach (or detach)
PARAMETERS:
action [ I ] - PS attach action (attach or detach)
RETURN VALUE:
eGobiError - Return code
===========================================================================*/
eGobiError cGobiQMICore::InitiateDomainAttach( ULONG action )
{
WORD msgID = (WORD)eQMI_NAS_ATTACH_DETACH;
std::vector <sDB2PackingInput> piv;
std::ostringstream tmp;
tmp << (UINT)action;
sProtocolEntityKey pek( eDB2_ET_QMI_NAS_REQ, msgID, 16 );
sDB2PackingInput pi( pek, (LPCSTR)tmp.str().c_str() );
piv.push_back( pi );
// Pack up the QMI request
const cCoreDatabase & db = GetDatabase();
sSharedBuffer * pRequest = DB2PackQMIBuffer( db, piv );
// Send the QMI request, check result, and return
return SendAndCheckReturn( eQMI_SVC_NAS, pRequest, 30000 );
}
/*===========================================================================
METHOD:
GetServingNetwork (Public Method)
DESCRIPTION:
Gets information regarding the system that currently provides service
to the device
PARAMETERS:
pRegistrationState [ O ] - Registration state
pCSDomain [ O ] - Circuit switch domain status
pPSDomain [ O ] - Packet switch domain status
pRAN [ O ] - Radio access network
pRadioIfacesSize [I/O] - Upon input the maximum number of elements
that the radio interfaces can contain. Upon
successful output the actual number of elements
in the radio interface array
pRadioIfaces [ O ] - The radio interface array
pRoaming [ O ] - Roaming indicator (0xFFFFFFFF - Unknown)
pMCC [ O ] - Mobile country code (0xFFFF - Unknown)
pMNC [ O ] - Mobile network code (0xFFFF - Unknown)
nameSize [ I ] - The maximum number of characters (including
NULL terminator) that the network name array
can contain
pName [ O ] - The network name or description represented
as a NULL terminated string (empty string
returned when unknown)
RETURN VALUE:
eGobiError - Return code
===========================================================================*/
eGobiError cGobiQMICore::GetServingNetwork(
ULONG * pRegistrationState,
ULONG * pCSDomain,
ULONG * pPSDomain,
ULONG * pRAN,
BYTE * pRadioIfacesSize,
BYTE * pRadioIfaces,
ULONG * pRoaming,
WORD * pMCC,
WORD * pMNC,
BYTE nameSize,
CHAR * pName )
{
// Validate arguments
if ( (pRegistrationState == 0)
|| (pCSDomain == 0)
|| (pPSDomain == 0)
|| (pRAN == 0)
|| (pRadioIfacesSize == 0)
|| (*pRadioIfacesSize == 0)
|| (pRadioIfaces == 0)
|| (pRoaming == 0)
|| (pMCC == 0)
|| (pMNC == 0)
|| (nameSize == 0)
|| (pName == 0) )
{
return eGOBI_ERR_INVALID_ARG;
}
BYTE maxRadioIfaces = *pRadioIfacesSize;
// Assume failure
*pRadioIfacesSize = 0;
*pRoaming = ULONG_MAX;
*pMCC = USHRT_MAX;
*pMNC = USHRT_MAX;
*pName = 0;
// Generate and send the QMI request
WORD msgID = (WORD)eQMI_NAS_GET_SS_INFO;
sProtocolBuffer rsp = SendSimple( eQMI_SVC_NAS, msgID );
if (rsp.IsValid() == false)
{
return GetCorrectedLastError();
}
// Did we receive a valid QMI response?
sQMIServiceBuffer qmiRsp( rsp.GetSharedBuffer() );
if (qmiRsp.IsValid() == false)
{
return eGOBI_ERR_MALFORMED_RSP;
}
// Check the mandatory QMI result TLV for success
ULONG rc = 0;
ULONG ec = 0;
bool bResult = qmiRsp.GetResult( rc, ec );
if (bResult == false)
{
return eGOBI_ERR_MALFORMED_RSP;
}
else if (rc != 0)
{
return GetCorrectedQMIError( ec );
}
// Prepare TLVs for parsing
std::vector <sDB2NavInput> tlvs = DB2ReduceQMIBuffer( qmiRsp );
const cCoreDatabase & db = GetDatabase();
// Parse the TLV we want (by DB key)
sProtocolEntityKey tlvKey1( eDB2_ET_QMI_NAS_RSP, msgID, 1 );
cDataParser::tParsedFields pf1 = ParseTLV( db, rsp, tlvs, tlvKey1 );
if (pf1.size() < 5)
{
return eGOBI_ERR_INVALID_RSP;
}
// Populate the variables
*pRegistrationState = pf1[0].mValue.mU32;
*pCSDomain = pf1[1].mValue.mU32;
*pPSDomain = pf1[2].mValue.mU32;
*pRAN = pf1[3].mValue.mU32;
BYTE activeRadioIfaces = pf1[4].mValue.mU8;
if (pf1.size() < 5 + (ULONG)activeRadioIfaces)
{
return eGOBI_ERR_INVALID_RSP;
}
if (activeRadioIfaces > maxRadioIfaces)
{
activeRadioIfaces = maxRadioIfaces;
}
ULONG * pOutRadioIfaces = (ULONG *)pRadioIfaces;
for (ULONG r = 0; r < activeRadioIfaces; r++)
{
*pOutRadioIfaces++ = pf1[5 + r].mValue.mU32;
}
*pRadioIfacesSize = activeRadioIfaces;
// Parse the optional TLV we want (by DB key)
sProtocolEntityKey tlvKey2( eDB2_ET_QMI_NAS_RSP, msgID, 16 );
cDataParser::tParsedFields pf2 = ParseTLV( db, rsp, tlvs, tlvKey2 );
if (pf2.size() >= 1)
{
*pRoaming = pf2[0].mValue.mU32;
}
// Parse the optional TLV we want (by DB key)
sProtocolEntityKey tlvKey3( eDB2_ET_QMI_NAS_RSP, msgID, 18 );
cDataParser::tParsedFields pf3 = ParseTLV( db, rsp, tlvs, tlvKey3 );
if (pf3.size() >= 3)
{
*pMCC = pf3[0].mValue.mU16;
*pMNC = pf3[1].mValue.mU16;
// Network name?
if (pf3[2].mValue.mU8 > 0 && pf3.size() >= 4)
{
LONG strLen = pf3[3].mValueString.size();
if (strLen > 0)
{
// Space to perform the copy?
if (nameSize < strLen + 1)
{
return eGOBI_ERR_BUFFER_SZ;
}
memcpy( (LPVOID)pName, (LPCSTR)pf3[3].mValueString.c_str(), strLen );
pName[strLen] = 0;
}
}
}
return eGOBI_ERR_NONE;
}
/*===========================================================================
METHOD:
GetServingNetworkCapabilities (Public Method)
DESCRIPTION:
Gets information regarding the data capabilities of the system that
currently provides service to the device
PARAMETERS:
pDataCapsSize [I/O] - Upon input the maximum number of elements that the
data capabilities array can contain. Upon success
the actual number of elements in the data
capabilities array
pDataCaps [ O ] - The data capabilities array
RETURN VALUE:
eGobiError - Return code
===========================================================================*/
eGobiError cGobiQMICore::GetServingNetworkCapabilities(
BYTE * pDataCapsSize,
BYTE * pDataCaps )
{
// Validate arguments
if ( (pDataCapsSize == 0)
|| (*pDataCapsSize == 0)
|| (pDataCaps == 0) )
{
return eGOBI_ERR_INVALID_ARG;
}
BYTE maxDataCaps = *pDataCapsSize;
// Assume failure
*pDataCapsSize = 0;
// Generate and send the QMI request
WORD msgID = (WORD)eQMI_NAS_GET_SS_INFO;
sProtocolBuffer rsp = SendSimple( eQMI_SVC_NAS, msgID );
if (rsp.IsValid() == false)
{
return GetCorrectedLastError();
}
// Did we receive a valid QMI response?
sQMIServiceBuffer qmiRsp( rsp.GetSharedBuffer() );
if (qmiRsp.IsValid() == false)
{
return eGOBI_ERR_MALFORMED_RSP;
}
// Check the mandatory QMI result TLV for success
ULONG rc = 0;
ULONG ec = 0;
bool bResult = qmiRsp.GetResult( rc, ec );
if (bResult == false)
{
return eGOBI_ERR_MALFORMED_RSP;
}
else if (rc != 0)
{
return GetCorrectedQMIError( ec );
}
// Prepare TLVs for parsing
std::vector <sDB2NavInput> tlvs = DB2ReduceQMIBuffer( qmiRsp );
const cCoreDatabase & db = GetDatabase();
// Parse the TLV we want (by DB key)
sProtocolEntityKey tlvKey( eDB2_ET_QMI_NAS_RSP, msgID, 17 );
cDataParser::tParsedFields pf = ParseTLV( db, rsp, tlvs, tlvKey );
if (pf.size() < 1)
{
return eGOBI_ERR_INVALID_RSP;
}
BYTE activeDataCaps = pf[0].mValue.mU8;
if (pf.size() < 1 + (ULONG)activeDataCaps)
{
return eGOBI_ERR_INVALID_RSP;
}
if (activeDataCaps > maxDataCaps)
{
activeDataCaps = maxDataCaps;
}
ULONG * pOutDataCaps = (ULONG *)pDataCaps;
for (ULONG d = 0; d < activeDataCaps; d++)
{
*pOutDataCaps++ = pf[1 + d].mValue.mU32;
}
*pDataCapsSize = activeDataCaps;
return eGOBI_ERR_NONE;
}
/*===========================================================================
METHOD:
GetDataBearerTechnology (Public Method)
DESCRIPTION:
This function retrieves the current data bearer technology (only
valid when connected)
PARAMETERS:
pDataCaps [ O ] - The data bearer technology
RETURN VALUE:
eGobiError - Return code
===========================================================================*/
eGobiError cGobiQMICore::GetDataBearerTechnology( ULONG * pDataBearer )
{
// Validate arguments
if (pDataBearer == 0)
{
return eGOBI_ERR_INVALID_ARG;
}
// Generate and send the QMI request
WORD msgID = (WORD)eQMI_WDS_GET_DATA_BEARER;
sProtocolBuffer rsp = SendSimple( eQMI_SVC_WDS, msgID );
if (rsp.IsValid() == false)
{
return GetCorrectedLastError();
}
// Did we receive a valid QMI response?
sQMIServiceBuffer qmiRsp( rsp.GetSharedBuffer() );
if (qmiRsp.IsValid() == false)
{
return eGOBI_ERR_MALFORMED_RSP;
}
// Check the mandatory QMI result TLV for success
ULONG rc = 0;
ULONG ec = 0;
bool bResult = qmiRsp.GetResult( rc, ec );
if (bResult == false)
{
return eGOBI_ERR_MALFORMED_RSP;
}
else if (rc != 0)
{
return GetCorrectedQMIError( ec );
}
// Prepare TLVs for parsing
std::vector <sDB2NavInput> tlvs = DB2ReduceQMIBuffer( qmiRsp );
const cCoreDatabase & db = GetDatabase();
// Parse the TLV we want (by DB key)
sProtocolEntityKey tlvKey( eDB2_ET_QMI_WDS_RSP, msgID, 1 );
cDataParser::tParsedFields pf = ParseTLV( db, rsp, tlvs, tlvKey );
if (pf.size() < 1)
{
return eGOBI_ERR_INVALID_RSP;
}
// Populate the state
*pDataBearer = pf[0].mValue.mU32;
return eGOBI_ERR_NONE;
}
/*===========================================================================
METHOD:
GetHomeNetwork (Public Method)
DESCRIPTION:
This function retrieves information about the home network of the device
PARAMETERS:
pMCC [ O ] - Mobile country code
pMNC [ O ] - Mobile network code
nameSize [ I ] - The maximum number of characters (including
NULL terminator) that the network name array
can contain
pName [ O ] - The network name or description represented
as a NULL terminated string (empty string
returned when unknown)
pSID [ O ] - Home network system ID (0xFFFF - Unknown)
pNID [ O ] - Home network ID (0xFFFF - Unknown)
RETURN VALUE:
eGobiError - Return code
===========================================================================*/
eGobiError cGobiQMICore::GetHomeNetwork(
WORD * pMCC,
WORD * pMNC,
BYTE nameSize,
CHAR * pName,
WORD * pSID,
WORD * pNID )
{
// Validate arguments
if ( (pMCC == 0)
|| (pMNC == 0)
|| (nameSize == 0)
|| (pName == 0)
|| (pSID == 0) )
{
return eGOBI_ERR_INVALID_ARG;
}
// Assume failure
*pName = 0;
*pSID = USHRT_MAX;
*pNID = USHRT_MAX;
// Generate and send the QMI request
WORD msgID = (WORD)eQMI_NAS_GET_HOME_INFO;
sProtocolBuffer rsp = SendSimple( eQMI_SVC_NAS, msgID );
if (rsp.IsValid() == false)
{
return GetCorrectedLastError();
}
// Did we receive a valid QMI response?
sQMIServiceBuffer qmiRsp( rsp.GetSharedBuffer() );
if (qmiRsp.IsValid() == false)
{
return eGOBI_ERR_MALFORMED_RSP;
}
// Check the mandatory QMI result TLV for success
ULONG rc = 0;
ULONG ec = 0;
bool bResult = qmiRsp.GetResult( rc, ec );
if (bResult == false)
{
return eGOBI_ERR_MALFORMED_RSP;
}
else if (rc != 0)
{
return GetCorrectedQMIError( ec );
}
// Prepare TLVs for parsing
std::vector <sDB2NavInput> tlvs = DB2ReduceQMIBuffer( qmiRsp );
const cCoreDatabase & db = GetDatabase();
// Parse the TLV we want (by DB key)
sProtocolEntityKey tlvKey1( eDB2_ET_QMI_NAS_RSP, msgID, 1 );
cDataParser::tParsedFields pf1 = ParseTLV( db, rsp, tlvs, tlvKey1 );
if (pf1.size() < 3)
{
return eGOBI_ERR_INVALID_RSP;
}
// Populate the variables
*pMCC = pf1[0].mValue.mU16;
*pMNC = pf1[1].mValue.mU16;
// Network name?
if (pf1[2].mValue.mU8 > 0 && pf1.size() >= 4)
{
LONG strLen = pf1[3].mValueString.size();
if (strLen > 0)
{
// Space to perform the copy?
if (nameSize < strLen + 1)
{
return eGOBI_ERR_BUFFER_SZ;
}
memcpy( (LPVOID)pName, (LPCSTR)pf1[3].mValueString.c_str(), strLen );
pName[strLen] = 0;
}
}
// Parse the optional TLV we want (by DB key)
sProtocolEntityKey tlvKey2( eDB2_ET_QMI_NAS_RSP, msgID, 16 );
cDataParser::tParsedFields pf2 = ParseTLV( db, rsp, tlvs, tlvKey2 );
if (pf2.size() >= 2)
{
*pSID = pf2[0].mValue.mU16;
*pNID = pf2[1].mValue.mU16;
}
return eGOBI_ERR_NONE;
}
/*===========================================================================
METHOD:
SetNetworkPreference (Public Method)
DESCRIPTION:
This function sets the network registration preference
PARAMETERS:
technologyPref [ I ] - Technology preference bitmap
duration [ I ] - Duration of active preference
RETURN VALUE:
eGobiError - Return code
===========================================================================*/
eGobiError cGobiQMICore::SetNetworkPreference(
ULONG technologyPref,
ULONG duration )
{
// Buffer to hold technology preference TLV (ID = 1)
const ULONG TLV_HDR_SZ = (ULONG)sizeof( sQMIRawContentHeader );
BYTE req[3 + TLV_HDR_SZ];
// Fill out TLV header
sQMIRawContentHeader * pTLV = (sQMIRawContentHeader *)&req[0];
pTLV->mLength = 3;
pTLV->mTypeID = 1;
// Copy packed technology preference WORD as-is
WORD * pTmp = (WORD *)&req[TLV_HDR_SZ];
*pTmp = (WORD)technologyPref;
// Fill out duration
req[TLV_HDR_SZ + 2] = (BYTE)duration;
// Pack TLV into a QMI NAS request
sSharedBuffer * pRequest = 0;
pRequest = sQMIServiceBuffer::BuildBuffer( eQMI_SVC_NAS,
eQMI_NAS_SET_TECH_PREF,
false,
false,
&req[0],
3 + TLV_HDR_SZ );
// Send the QMI request, check result, and return
return SendAndCheckReturn( eQMI_SVC_NAS, pRequest );
}
/*===========================================================================
METHOD:
GetNetworkPreference (Public Method)
DESCRIPTION:
This function returns the network registration preference
PARAMETERS:
pTechnologyPref [ O ] - Technology preference bitmap
pDuration [ O ] - Duration of active preference
pPersistentTechnologyPref [ O ] - Persistent technology preference bitmap
RETURN VALUE:
eGobiError - Return code
===========================================================================*/
eGobiError cGobiQMICore::GetNetworkPreference(
ULONG * pTechnologyPref,
ULONG * pDuration,
ULONG * pPersistentTechnologyPref )
{
// Validate arguments
if ( (pTechnologyPref == 0)
|| (pDuration == 0)
|| (pPersistentTechnologyPref == 0) )
{
return eGOBI_ERR_INVALID_ARG;
}
// Generate and send the QMI request
WORD msgID = (WORD)eQMI_NAS_GET_TECH_PREF;
sProtocolBuffer rsp = SendSimple( eQMI_SVC_NAS, msgID );
if (rsp.IsValid() == false)
{
return GetCorrectedLastError();
}
// Did we receive a valid QMI response?
sQMIServiceBuffer qmiRsp( rsp.GetSharedBuffer() );
if (qmiRsp.IsValid() == false)
{
return eGOBI_ERR_MALFORMED_RSP;
}
// Check the mandatory QMI result TLV for success
ULONG rc = 0;
ULONG ec = 0;
bool bResult = qmiRsp.GetResult( rc, ec );
if (bResult == false)
{
return eGOBI_ERR_MALFORMED_RSP;
}
else if (rc != 0)
{
return GetCorrectedQMIError( ec );
}
// Prepare TLVs for parsing
std::vector <sDB2NavInput> tlvs = DB2ReduceQMIBuffer( qmiRsp );
// Parse the TLV we want (by DB key)
sProtocolEntityKey tlvKey1( eDB2_ET_QMI_NAS_RSP, msgID, 1 );
sDB2NavInput ni1 = FindTLV( tlvs, tlvKey1 );
if (ni1.mPayloadLen < 3)
{
return eGOBI_ERR_INVALID_RSP;
}
const BYTE * pData = ni1.mpPayload;
const WORD * pTmp = (const WORD *)pData;
pData += 2;
// Populate the variables
*pTechnologyPref = (ULONG)*pTmp;
*pDuration = (ULONG)*pData;
// Until we know any better the persistent setting is the current setting
*pPersistentTechnologyPref = *pTechnologyPref;
// Parse the optional TLV we want (by DB key)
sProtocolEntityKey tlvKey2( eDB2_ET_QMI_NAS_RSP, msgID, 16 );
sDB2NavInput ni2 = FindTLV( tlvs, tlvKey2 );
if (ni2.mPayloadLen >= 2)
{
pTmp = (const WORD *)ni2.mpPayload;
*pPersistentTechnologyPref = (ULONG)*pTmp;
}
return eGOBI_ERR_NONE;
}
/*===========================================================================
METHOD:
SetCDMANetworkParameters (Public Method)
DESCRIPTION:
This function sets the desired CDMA network parameters
PARAMETERS:
pSPC [ I ] - Six digit service programming code
pForceRev0 [ I ] - (Optional) Force CDMA 1x-EV-DO Rev. 0 mode?
pCustomSCP [ I ] - (Optional) Use a custom config for CDMA 1x-EV-DO SCP?
pProtocol [ I ] - (Optional) Protocol mask for custom SCP config
pBroadcast [ I ] - (Optional) Broadcast mask for custom SCP config
pApplication [ I ] - (Optional) Application mask for custom SCP config
pRoaming [ I ] - (Optional) Roaming preference
RETURN VALUE:
eGobiError - Return code
===========================================================================*/
eGobiError cGobiQMICore::SetCDMANetworkParameters(
CHAR * pSPC,
BYTE * pForceRev0,
BYTE * pCustomSCP,
ULONG * pProtocol,
ULONG * pBroadcast,
ULONG * pApplication,
ULONG * pRoaming )
{
// If you specify one of the custom SCP config fields then you must
// specify them all
ULONG scpCount = 0;
if (pCustomSCP != 0)
{
scpCount++;
}
if (pProtocol != 0)
{
scpCount++;
}
if (pBroadcast != 0)
{
scpCount++;
}
if (pApplication != 0)
{
scpCount++;
}
if (scpCount != 0 && scpCount != 4)
{
return eGOBI_ERR_INVALID_ARG;
}
// Rev. 0 and SCP custom config are mutually exclusive
if (pForceRev0 != 0 && scpCount == 4)
{
if (*pForceRev0 != 0 && *pCustomSCP != 0)
{
return eGOBI_ERR_INVALID_ARG;
}
}
WORD msgID = (WORD)eQMI_NAS_SET_NET_PARAMS;
std::vector <sDB2PackingInput> piv;
// Need to start with SPC?
if (pForceRev0 != 0 || scpCount == 4)
{
// Validate arguments
if (pSPC == 0 || pSPC[0] == 0)
{
return eGOBI_ERR_INVALID_ARG;
}
std::string spc( pSPC );
if (spc.size() > 6)
{
return eGOBI_ERR_INVALID_ARG;
}
int nNonDigit = spc.find_first_not_of( "0123456789" );
std::string digitSPC = spc.substr( 0, nNonDigit );
if (digitSPC.size() != spc.size())
{
return eGOBI_ERR_INVALID_ARG;
}
sProtocolEntityKey pek( eDB2_ET_QMI_NAS_REQ, msgID, 16 );
sDB2PackingInput pi( pek, (LPCSTR)spc.c_str() );
piv.push_back( pi );
}
if (pForceRev0 != 0)
{
// "%u"
std::ostringstream tmp;
tmp << (UINT)(*pForceRev0 == 0 ? 0 : 1);
sProtocolEntityKey pek( eDB2_ET_QMI_NAS_REQ, msgID, 20 );
sDB2PackingInput pi( pek, (LPCSTR)tmp.str().c_str() );
piv.push_back( pi );
}
if (scpCount == 4)
{
// "%u %u %u %u %u %u %u %u %u %u %u %u"
std::ostringstream tmp;
tmp << (UINT)(*pCustomSCP == 0 ? 0 : 1)
<< (UINT)(*pProtocol & 0x00000001 ? 1 : 0)
<< (UINT)(*pProtocol & 0x00000002 ? 1 : 0)
<< (UINT)(*pProtocol & 0x00000004 ? 1 : 0)
<< (UINT)(*pProtocol & 0x00000008 ? 1 : 0)
<< (UINT)(*pProtocol & 0x00000010 ? 1 : 0)
<< (UINT)(*pProtocol & 0x00000020 ? 1 : 0)
<< (UINT)(*pProtocol & 0x00000040 ? 1 : 0)
<< (UINT)(*pProtocol & 0x00000080 ? 1 : 0)
<< (UINT)(*pBroadcast & 0x00000001 ? 1 : 0)
<< (UINT)(*pApplication & 0x00000001 ? 1 : 0)
<< (UINT)(*pApplication & 0x00000002 ? 1 : 0);
sProtocolEntityKey pek( eDB2_ET_QMI_NAS_REQ, msgID, 21 );
sDB2PackingInput pi( pek, (LPCSTR)tmp.str().c_str() );
piv.push_back( pi );
}
if (pRoaming != 0)
{
// "%u"
std::ostringstream tmp;
tmp << (UINT)*pRoaming;
sProtocolEntityKey pek( eDB2_ET_QMI_NAS_REQ, msgID, 22 );
sDB2PackingInput pi( pek, (LPCSTR)tmp.str().c_str() );
piv.push_back( pi );
}
// We require something to actually configure
if (piv.size() == 0)
{
// Much ado about nothing
return eGOBI_ERR_INVALID_ARG;
}
// Pack up the QMI request
const cCoreDatabase & db = GetDatabase();
sSharedBuffer * pRequest = DB2PackQMIBuffer( db, piv );
// Send the QMI request, check result, and return
return SendAndCheckReturn( eQMI_SVC_NAS, pRequest, 5000 );
}
/*===========================================================================
METHOD:
GetCDMANetworkParameters (Public Method)
DESCRIPTION:
This function gets the current CDMA network parameters
PARAMETERS:
pSCI [ O ] - Slot cycle index
pSCM [ O ] - Station class mark
pRegHomeSID [ O ] - Register on home SID?
pRegForeignSID [ O ] - Register on foreign SID?
pRegForeignNID [ O ] - Register on foreign NID?
pForceRev0 [ O ] - Force CDMA 1x-EV-DO Rev. 0 mode?
pCustomSCP [ O ] - Use a custom config for CDMA 1x-EV-DO SCP?
pProtocol [ O ] - Protocol mask for custom SCP config
pBroadcast [ O ] - Broadcast mask for custom SCP config
pApplication [ O ] - Application mask for custom SCP config
pRoaming [ O ] - Roaming preference
RETURN VALUE:
eGobiError - Return code
===========================================================================*/
eGobiError cGobiQMICore::GetCDMANetworkParameters(
BYTE * pSCI,
BYTE * pSCM,
BYTE * pRegHomeSID,
BYTE * pRegForeignSID,
BYTE * pRegForeignNID,
BYTE * pForceRev0,
BYTE * pCustomSCP,
ULONG * pProtocol,
ULONG * pBroadcast,
ULONG * pApplication,
ULONG * pRoaming )
{
// Validate arguments
if ( (pSCI == 0)
|| (pSCM == 0)
|| (pRegHomeSID == 0)
|| (pRegForeignSID == 0)
|| (pRegForeignNID == 0)
|| (pForceRev0 == 0)
|| (pCustomSCP == 0)
|| (pProtocol == 0)
|| (pBroadcast == 0)
|| (pApplication == 0)
|| (pRoaming == 0) )
{
return eGOBI_ERR_INVALID_ARG;
}
*pSCI = UCHAR_MAX;
*pSCM = UCHAR_MAX;
*pRegHomeSID = UCHAR_MAX;
*pRegForeignSID = UCHAR_MAX;
*pRegForeignNID = UCHAR_MAX;
*pForceRev0 = UCHAR_MAX;
*pCustomSCP = UCHAR_MAX;
*pProtocol = ULONG_MAX;
*pBroadcast = ULONG_MAX;
*pApplication = ULONG_MAX;
*pRoaming = UCHAR_MAX;
// Generate and send the QMI request
WORD msgID = (WORD)eQMI_NAS_GET_NET_PARAMS;
sProtocolBuffer rsp = SendSimple( eQMI_SVC_NAS, msgID );
if (rsp.IsValid() == false)
{
return GetCorrectedLastError();
}
// Did we receive a valid QMI response?
sQMIServiceBuffer qmiRsp( rsp.GetSharedBuffer() );
if (qmiRsp.IsValid() == false)
{
return eGOBI_ERR_MALFORMED_RSP;
}
// Check the mandatory QMI result TLV for success
ULONG rc = 0;
ULONG ec = 0;
bool bResult = qmiRsp.GetResult( rc, ec );
if (bResult == false)
{
return eGOBI_ERR_MALFORMED_RSP;
}
else if (rc != 0)
{
return GetCorrectedQMIError( ec );
}
// Prepare TLVs for parsing
std::vector <sDB2NavInput> tlvs = DB2ReduceQMIBuffer( qmiRsp );
const cCoreDatabase & db = GetDatabase();
// Parse the TLVs we want (by DB key)
sProtocolEntityKey tlvKey( eDB2_ET_QMI_NAS_RSP, msgID, 17 );
cDataParser::tParsedFields pf = ParseTLV( db, rsp, tlvs, tlvKey );
if (pf.size() >= 1)
{
*pSCI = pf[0].mValue.mU8;
}
tlvKey = sProtocolEntityKey( eDB2_ET_QMI_NAS_RSP, msgID, 18 );
pf = ParseTLV( db, rsp, tlvs, tlvKey );
if (pf.size() >= 1)
{
*pSCM = pf[0].mValue.mU8;
}
tlvKey = sProtocolEntityKey( eDB2_ET_QMI_NAS_RSP, msgID, 19 );
pf = ParseTLV( db, rsp, tlvs, tlvKey );
if (pf.size() >= 3)
{
*pRegHomeSID = pf[0].mValue.mU8;
*pRegForeignSID = pf[0].mValue.mU8;
*pRegForeignNID = pf[0].mValue.mU8;
}
tlvKey = sProtocolEntityKey( eDB2_ET_QMI_NAS_RSP, msgID, 20 );
pf = ParseTLV( db, rsp, tlvs, tlvKey );
if (pf.size() >= 1)
{
*pForceRev0 = pf[0].mValue.mU8;
}
tlvKey = sProtocolEntityKey ( eDB2_ET_QMI_NAS_RSP, msgID, 21 );
sDB2NavInput ni = FindTLV( tlvs, tlvKey );
if (ni.mPayloadLen >= (ULONG)sizeof( sEVDOCustomSCPConfig ))
{
const sEVDOCustomSCPConfig * pData = 0;
pData = (const sEVDOCustomSCPConfig *)ni.mpPayload;
*pCustomSCP = pData->mbActive;
*pProtocol = pData->mProtocolMask;
*pBroadcast = pData->mBroadcastMask;
*pApplication = pData->mApplicationMask;
}
tlvKey = sProtocolEntityKey( eDB2_ET_QMI_NAS_RSP, msgID, 22 );
pf = ParseTLV( db, rsp, tlvs, tlvKey );
if (pf.size() >= 1)
{
*pRoaming = pf[0].mValue.mU32;
}
return eGOBI_ERR_NONE;
}
/*===========================================================================
METHOD:
GetACCOLC (Public Method)
DESCRIPTION:
This function returns the Access Overload Class (ACCOLC) of the device
PARAMETERS:
pACCOLC [ O ] - The ACCOLC
RETURN VALUE:
eGobiError - Return code
===========================================================================*/
eGobiError cGobiQMICore::GetACCOLC( BYTE * pACCOLC )
{
// Validate arguments
if (pACCOLC == 0)
{
return eGOBI_ERR_INVALID_ARG;
}
// Generate and send the QMI request
WORD msgID = (WORD)eQMI_NAS_GET_ACCOLC;
sProtocolBuffer rsp = SendSimple( eQMI_SVC_NAS, msgID );
if (rsp.IsValid() == false)
{
return GetCorrectedLastError();
}
// Did we receive a valid QMI response?
sQMIServiceBuffer qmiRsp( rsp.GetSharedBuffer() );
if (qmiRsp.IsValid() == false)
{
return eGOBI_ERR_MALFORMED_RSP;
}
// Check the mandatory QMI result TLV for success
ULONG rc = 0;
ULONG ec = 0;
bool bResult = qmiRsp.GetResult( rc, ec );
if (bResult == false)
{
return eGOBI_ERR_MALFORMED_RSP;
}
else if (rc != 0)
{
return GetCorrectedQMIError( ec );
}
// Prepare TLVs for parsing
std::vector <sDB2NavInput> tlvs = DB2ReduceQMIBuffer( qmiRsp );
const cCoreDatabase & db = GetDatabase();
// Parse the TLV we want (by DB key)
sProtocolEntityKey tlvKey( eDB2_ET_QMI_NAS_RSP, msgID, 1 );
cDataParser::tParsedFields pf = ParseTLV( db, rsp, tlvs, tlvKey );
if (pf.size() < 1)
{
return eGOBI_ERR_INVALID_RSP;
}
// Populate the ACCOLC
*pACCOLC = pf[0].mValue.mU8;
return eGOBI_ERR_NONE;
}
/*===========================================================================
METHOD:
SetACCOLC (Public Method)
DESCRIPTION:
This function sets the Access Overload Class (ACCOLC) of the device
PARAMETERS:
pSPC [ I ] - NULL terminated string representing the six digit
service programming code
accolc [ I ] - The ACCOLC
RETURN VALUE:
eGobiError - Return code
===========================================================================*/
eGobiError cGobiQMICore::SetACCOLC(
CHAR * pSPC,
BYTE accolc )
{
// Validate arguments
if (pSPC == 0 || pSPC[0] == 0)
{
return eGOBI_ERR_INVALID_ARG;
}
std::string spc( pSPC );
if (spc.size() > 6)
{
return eGOBI_ERR_INVALID_ARG;
}
int nNonDigit = spc.find_first_not_of( "0123456789" );
std::string digitSPC = spc.substr( 0, nNonDigit );
if (digitSPC.size() != spc.size())
{
return eGOBI_ERR_INVALID_ARG;
}
WORD msgID = (WORD)eQMI_NAS_SET_ACCOLC;
std::vector <sDB2PackingInput> piv;
// "%s %u"
std::ostringstream tmp;
tmp << spc << " " << (UINT)accolc;
sProtocolEntityKey pek( eDB2_ET_QMI_NAS_REQ, msgID, 1 );
sDB2PackingInput pi( pek, (LPCSTR)tmp.str().c_str() );
piv.push_back( pi );
// Pack up the QMI request
const cCoreDatabase & db = GetDatabase();
sSharedBuffer * pRequest = DB2PackQMIBuffer( db, piv );
// Send the QMI request, check result, and return
return SendAndCheckReturn( eQMI_SVC_NAS, pRequest, 5000 );
}
/*===========================================================================
METHOD:
GetPLMNMode (Public Method)
DESCRIPTION:
This function returns the PLMN mode from the CSP
PARAMETERS:
pMode [ O ] - PLMN mode
RETURN VALUE:
eGobiError - Return code
===========================================================================*/
eGobiError cGobiQMICore::GetPLMNMode( ULONG * pMode )
{
// Validate arguments
if (pMode == 0)
{
return eGOBI_ERR_INVALID_ARG;
}
// Generate and send the QMI request
WORD msgID = (WORD)eQMI_NAS_GET_PLMN_MODE;
sProtocolBuffer rsp = SendSimple( eQMI_SVC_NAS, msgID );
if (rsp.IsValid() == false)
{
return GetCorrectedLastError();
}
// Did we receive a valid QMI response?
sQMIServiceBuffer qmiRsp( rsp.GetSharedBuffer() );
if (qmiRsp.IsValid() == false)
{
return eGOBI_ERR_MALFORMED_RSP;
}
// Check the mandatory QMI result TLV for success
ULONG rc = 0;
ULONG ec = 0;
bool bResult = qmiRsp.GetResult( rc, ec );
if (bResult == false)
{
return eGOBI_ERR_MALFORMED_RSP;
}
else if (rc != 0)
{
return GetCorrectedQMIError( ec );
}
// Prepare TLVs for parsing
std::vector <sDB2NavInput> tlvs = DB2ReduceQMIBuffer( qmiRsp );
const cCoreDatabase & db = GetDatabase();
// Parse the TLV we want (by DB key)
sProtocolEntityKey tlvKey( eDB2_ET_QMI_NAS_RSP, msgID, 16 );
cDataParser::tParsedFields pf = ParseTLV( db, rsp, tlvs, tlvKey );
if (pf.size() < 1)
{
return eGOBI_ERR_INVALID_RSP;
}
// Populate the PLMN mode
*pMode = (ULONG)pf[0].mValue.mU8;
return eGOBI_ERR_NONE;
}
/*===========================================================================
METHOD:
GetPLMNName (Public Method)
DESCRIPTION:
This function returns PLMN name information for the given MCC/MNC
PARAMETERS:
mcc [ I ] - Mobile country code
mnc [ I ] - Mobile network code
pNamesSize [I/O] - Upon input the size in BYTEs of the name structure
array. Upon success the actual number of BYTEs
copied to the name structure array
pNames [ O ] - The name structure array
RETURN VALUE:
eGobiError - Return code
===========================================================================*/
eGobiError cGobiQMICore::GetPLMNName(
USHORT mcc,
USHORT mnc,
ULONG * pNamesSize,
BYTE * pNames )
{
// Validate arguments
if ( (pNamesSize == 0)
|| (*pNamesSize == 0)
|| (pNames == 0) )
{
return eGOBI_ERR_INVALID_ARG;
}
ULONG maxSz = *pNamesSize;
*pNamesSize = 0;
WORD msgID = (WORD)eQMI_NAS_GET_PLMN_NAME;
std::vector <sDB2PackingInput> piv;
// "%hu %hu"
std::ostringstream tmp;
tmp << mcc << " " << mnc;
sProtocolEntityKey pek( eDB2_ET_QMI_NAS_REQ, msgID, 1 );
sDB2PackingInput pi( pek, tmp.str().c_str() );
piv.push_back( pi );
// Pack up the QMI request
const cCoreDatabase & db = GetDatabase();
sSharedBuffer * pRequest = DB2PackQMIBuffer( db, piv );
sProtocolBuffer rsp = Send( eQMI_SVC_NAS, pRequest );
if (rsp.IsValid() == false)
{
return GetCorrectedLastError();
}
// Did we receive a valid QMI response?
sQMIServiceBuffer qmiRsp( rsp.GetSharedBuffer() );
if (qmiRsp.IsValid() == false)
{
return eGOBI_ERR_MALFORMED_RSP;
}
// Check the mandatory QMI result TLV for success
ULONG rc = 0;
ULONG ec = 0;
bool bResult = qmiRsp.GetResult( rc, ec );
if (bResult == false)
{
return eGOBI_ERR_MALFORMED_RSP;
}
else if (rc != 0)
{
return GetCorrectedQMIError( ec );
}
// Try to find TLV ID 16
std::map <ULONG, const sQMIRawContentHeader *> tlvs;
tlvs = qmiRsp.GetContents();
std::map <ULONG, const sQMIRawContentHeader *>::const_iterator pIter;
pIter = tlvs.find( 16 );
if (pIter == tlvs.end())
{
return eGOBI_ERR_INVALID_RSP;
}
// Enough space to copy result?
const sQMIRawContentHeader * pHdr = pIter->second;
ULONG needSz = (ULONG)pHdr->mLength;
if (needSz == 0)
{
return eGOBI_ERR_INVALID_RSP;
}
*pNamesSize = needSz;
if (needSz > maxSz)
{
return eGOBI_ERR_BUFFER_SZ;
}
pHdr++;
const BYTE * pData = (const BYTE *)pHdr;
memcpy( (LPVOID)pNames,
(LPCVOID)pData,
(SIZE_T)needSz );
return eGOBI_ERR_NONE;
}